1 --- ../lighttpd-1.4.11/NEWS 2006-03-09 19:34:33.000000000 +0200
2 +++ lighttpd-1.4.12/NEWS 2006-07-16 00:26:05.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-19 20:02:55.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 - gethostbyname poll sigtimedwait epoll_ctl getrlimit chroot \
110 + strdup strerror strstr strtol sendfile getopt socket lstat \
111 + gethostbyname poll sigtimedwait epoll_ctl getrlimit chroot strptime \
112 getuid select signal pathconf madvise posix_fadvise posix_madvise \
113 writev sigaction sendfile64 send_file kqueue port_create localtime_r])
118 if test "${GCC}" = "yes"; then
119 - CFLAGS="${CFLAGS} -Wall -W -Wshadow -pedantic"
120 + CFLAGS="${CFLAGS} -Wall -W -Wshadow -pedantic -std=gnu99"
128 -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"
129 +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"
131 plugins="mod_rewrite mod_redirect mod_ssi mod_trigger_b4_dl"
132 features="regex-conditionals"
134 disable_feature="$disable_feature $features"
137 +features="webdav-locks"
138 +if test "x$UUID_LIB" \!= x; then
139 + enable_feature="$enable_feature $features"
141 + disable_feature="$disable_feature $features"
148 --- ../lighttpd-1.4.11/cygwin/lighttpd.README 2006-03-07 14:22:19.000000000 +0200
149 +++ lighttpd-1.4.12/cygwin/lighttpd.README 2006-07-19 20:09:00.000000000 +0300
152 -------------------------------------------
\r
153 -A fast, secure and flexible webserver
\r
155 -Runtime requirements:
\r
156 - cygwin-1.5.10 or newer
\r
157 - crypt-1.1 or newer
\r
158 - libbz2_1-1.0.2 or newer
\r
159 - libpcre0-4.5 or newer
\r
160 - openssl-0.9.7d or newer
\r
161 - zlib-1.2.1 or newer
\r
163 -Build requirements:
\r
164 - cygwin-1.5.10 or newer
\r
165 - gcc-3.3.1-3 or newer
\r
166 - binutils-20030901-1 or newer
\r
175 -Canonical homepage:
\r
176 - http://jan.kneschke.de/projects/lighttpd/
\r
178 -Canonical download:
\r
179 - http://jan.kneschke.de/projects/lighttpd/download
\r
181 -------------------------------------
\r
183 -Build instructions:
\r
184 - unpack lighttpd-1.4.11-<REL>-src.tar.bz2
\r
185 - if you use setup to install this src package, it will be
\r
186 - unpacked under /usr/src automatically
\r
188 - ./lighttpd-1.4.11-<REL>.sh all
\r
191 - /usr/src/lighttpd-1.4.11-<REL>.tar.bz2
\r
192 - /usr/src/lighttpd-1.4.11-<REL>-src.tar.bz2
\r
194 -Or use './lighttpd-1.4.11-<REL>.sh prep' to get a patched source directory
\r
196 --------------------------------------------
\r
198 -Files included in the binary distribution:
\r
200 - /etc/lighttpd/lighttpd.conf.default
\r
201 - /usr/lib/cyglightcomp.dll
\r
202 - /usr/lib/lighttpd/mod_access.dll
\r
203 - /usr/lib/lighttpd/mod_accesslog.dll
\r
204 - /usr/lib/lighttpd/mod_auth.dll
\r
205 - /usr/lib/lighttpd/mod_cgi.dll
\r
206 - /usr/lib/lighttpd/mod_compress.dll
\r
207 - /usr/lib/lighttpd/mod_evhost.dll
\r
208 - /usr/lib/lighttpd/mod_expire.dll
\r
209 - /usr/lib/lighttpd/mod_fastcgi.dll
\r
210 - /usr/lib/lighttpd/mod_httptls.dll
\r
211 - /usr/lib/lighttpd/mod_maps.dll
\r
212 - /usr/lib/lighttpd/mod_proxy.dll
\r
213 - /usr/lib/lighttpd/mod_redirect.dll
\r
214 - /usr/lib/lighttpd/mod_rewrite.dll
\r
215 - /usr/lib/lighttpd/mod_rrdtool.dll
\r
216 - /usr/lib/lighttpd/mod_secdownload.dll
\r
217 - /usr/lib/lighttpd/mod_simple_vhost.dll
\r
218 - /usr/lib/lighttpd/mod_ssi.dll
\r
219 - /usr/lib/lighttpd/mod_status.dll
\r
220 - /usr/lib/lighttpd/mod_usertrack.dll
\r
221 - /usr/sbin/lighttpd.exe
\r
222 - /usr/share/doc/Cygwin/lighttpd-1.3.0.README
\r
223 - /usr/share/doc/lighttpd-1.3.0/accesslog.txt
\r
224 - /usr/share/doc/lighttpd-1.3.0/authentification.txt
\r
225 - /usr/share/doc/lighttpd-1.3.0/AUTHORS
\r
226 - /usr/share/doc/lighttpd-1.3.0/cgi.txt
\r
227 - /usr/share/doc/lighttpd-1.3.0/ChangeLog
\r
228 - /usr/share/doc/lighttpd-1.3.0/compress.txt
\r
229 - /usr/share/doc/lighttpd-1.3.0/configuration.txt
\r
230 - /usr/share/doc/lighttpd-1.3.0/COPYING
\r
231 - /usr/share/doc/lighttpd-1.3.0/fastcgi-state.txt
\r
232 - /usr/share/doc/lighttpd-1.3.0/fastcgi.txt
\r
233 - /usr/share/doc/lighttpd-1.3.0/features.txt
\r
234 - /usr/share/doc/lighttpd-1.3.0/INSTALL
\r
235 - /usr/share/doc/lighttpd-1.3.0/NEWS
\r
236 - /usr/share/doc/lighttpd-1.3.0/performance.txt
\r
237 - /usr/share/doc/lighttpd-1.3.0/plugins.txt
\r
238 - /usr/share/doc/lighttpd-1.3.0/proxy.txt
\r
239 - /usr/share/doc/lighttpd-1.3.0/README
\r
240 - /usr/share/doc/lighttpd-1.3.0/redirect.txt
\r
241 - /usr/share/doc/lighttpd-1.3.0/rewrite.txt
\r
242 - /usr/share/doc/lighttpd-1.3.0/rrdtool.txt
\r
243 - /usr/share/doc/lighttpd-1.3.0/secdownload.txt
\r
244 - /usr/share/doc/lighttpd-1.3.0/security.txt
\r
245 - /usr/share/doc/lighttpd-1.3.0/simple-vhost.txt
\r
246 - /usr/share/doc/lighttpd-1.3.0/skeleton.txt
\r
247 - /usr/share/doc/lighttpd-1.3.0/ssi.txt
\r
248 - /usr/share/doc/lighttpd-1.3.0/state.txt
\r
249 - /usr/share/man/man1/lighttpd.1.gz
\r
251 -------------------
\r
255 ----------- lighttpd-1.3.1-1 -----------
\r
259 ----------- lighttpd-1.3.0-1 -----------
\r
262 -Cygwin port maintained by: Jan Kneschke <jan@kneschke.de>
\r
263 -Please address all questions to the Cygwin mailing list at <cygwin@cygwin.com>
\r
266 +------------------------------------------
267 +A fast, secure and flexible webserver
269 +Runtime requirements:
270 + cygwin-1.5.10 or newer
272 + libbz2_1-1.0.2 or newer
273 + libpcre0-4.5 or newer
274 + openssl-0.9.7d or newer
275 + zlib-1.2.1 or newer
278 + cygwin-1.5.10 or newer
279 + gcc-3.3.1-3 or newer
280 + binutils-20030901-1 or newer
290 + http://jan.kneschke.de/projects/lighttpd/
293 + http://jan.kneschke.de/projects/lighttpd/download
295 +------------------------------------
298 + unpack lighttpd-1.4.12-<REL>-src.tar.bz2
299 + if you use setup to install this src package, it will be
300 + unpacked under /usr/src automatically
302 + ./lighttpd-1.4.12-<REL>.sh all
305 + /usr/src/lighttpd-1.4.12-<REL>.tar.bz2
306 + /usr/src/lighttpd-1.4.12-<REL>-src.tar.bz2
308 +Or use './lighttpd-1.4.12-<REL>.sh prep' to get a patched source directory
310 +-------------------------------------------
312 +Files included in the binary distribution:
314 + /etc/lighttpd/lighttpd.conf.default
315 + /usr/lib/cyglightcomp.dll
316 + /usr/lib/lighttpd/mod_access.dll
317 + /usr/lib/lighttpd/mod_accesslog.dll
318 + /usr/lib/lighttpd/mod_auth.dll
319 + /usr/lib/lighttpd/mod_cgi.dll
320 + /usr/lib/lighttpd/mod_compress.dll
321 + /usr/lib/lighttpd/mod_evhost.dll
322 + /usr/lib/lighttpd/mod_expire.dll
323 + /usr/lib/lighttpd/mod_fastcgi.dll
324 + /usr/lib/lighttpd/mod_httptls.dll
325 + /usr/lib/lighttpd/mod_maps.dll
326 + /usr/lib/lighttpd/mod_proxy.dll
327 + /usr/lib/lighttpd/mod_redirect.dll
328 + /usr/lib/lighttpd/mod_rewrite.dll
329 + /usr/lib/lighttpd/mod_rrdtool.dll
330 + /usr/lib/lighttpd/mod_secdownload.dll
331 + /usr/lib/lighttpd/mod_simple_vhost.dll
332 + /usr/lib/lighttpd/mod_ssi.dll
333 + /usr/lib/lighttpd/mod_status.dll
334 + /usr/lib/lighttpd/mod_usertrack.dll
335 + /usr/sbin/lighttpd.exe
336 + /usr/share/doc/Cygwin/lighttpd-1.3.0.README
337 + /usr/share/doc/lighttpd-1.3.0/accesslog.txt
338 + /usr/share/doc/lighttpd-1.3.0/authentification.txt
339 + /usr/share/doc/lighttpd-1.3.0/AUTHORS
340 + /usr/share/doc/lighttpd-1.3.0/cgi.txt
341 + /usr/share/doc/lighttpd-1.3.0/ChangeLog
342 + /usr/share/doc/lighttpd-1.3.0/compress.txt
343 + /usr/share/doc/lighttpd-1.3.0/configuration.txt
344 + /usr/share/doc/lighttpd-1.3.0/COPYING
345 + /usr/share/doc/lighttpd-1.3.0/fastcgi-state.txt
346 + /usr/share/doc/lighttpd-1.3.0/fastcgi.txt
347 + /usr/share/doc/lighttpd-1.3.0/features.txt
348 + /usr/share/doc/lighttpd-1.3.0/INSTALL
349 + /usr/share/doc/lighttpd-1.3.0/NEWS
350 + /usr/share/doc/lighttpd-1.3.0/performance.txt
351 + /usr/share/doc/lighttpd-1.3.0/plugins.txt
352 + /usr/share/doc/lighttpd-1.3.0/proxy.txt
353 + /usr/share/doc/lighttpd-1.3.0/README
354 + /usr/share/doc/lighttpd-1.3.0/redirect.txt
355 + /usr/share/doc/lighttpd-1.3.0/rewrite.txt
356 + /usr/share/doc/lighttpd-1.3.0/rrdtool.txt
357 + /usr/share/doc/lighttpd-1.3.0/secdownload.txt
358 + /usr/share/doc/lighttpd-1.3.0/security.txt
359 + /usr/share/doc/lighttpd-1.3.0/simple-vhost.txt
360 + /usr/share/doc/lighttpd-1.3.0/skeleton.txt
361 + /usr/share/doc/lighttpd-1.3.0/ssi.txt
362 + /usr/share/doc/lighttpd-1.3.0/state.txt
363 + /usr/share/man/man1/lighttpd.1.gz
369 +---------- lighttpd-1.3.1-1 -----------
373 +---------- lighttpd-1.3.0-1 -----------
376 +Cygwin port maintained by: Jan Kneschke <jan@kneschke.de>
377 +Please address all questions to the Cygwin mailing list at <cygwin@cygwin.com>
379 --- ../lighttpd-1.4.11/cygwin/lighttpd.README.in 2005-08-11 01:26:59.000000000 +0300
380 +++ lighttpd-1.4.12/cygwin/lighttpd.README.in 2006-07-16 00:26:04.000000000 +0300
383 -------------------------------------------
\r
384 -A fast, secure and flexible webserver
\r
386 -Runtime requirements:
\r
387 - cygwin-1.5.10 or newer
\r
388 - crypt-1.1 or newer
\r
389 - libbz2_1-1.0.2 or newer
\r
390 - libpcre0-4.5 or newer
\r
391 - openssl-0.9.7d or newer
\r
392 - zlib-1.2.1 or newer
\r
394 -Build requirements:
\r
395 - cygwin-1.5.10 or newer
\r
396 - gcc-3.3.1-3 or newer
\r
397 - binutils-20030901-1 or newer
\r
406 -Canonical homepage:
\r
407 - http://jan.kneschke.de/projects/lighttpd/
\r
409 -Canonical download:
\r
410 - http://jan.kneschke.de/projects/lighttpd/download
\r
412 -------------------------------------
\r
414 -Build instructions:
\r
415 - unpack lighttpd-@VERSION@-<REL>-src.tar.bz2
\r
416 - if you use setup to install this src package, it will be
\r
417 - unpacked under /usr/src automatically
\r
419 - ./lighttpd-@VERSION@-<REL>.sh all
\r
422 - /usr/src/lighttpd-@VERSION@-<REL>.tar.bz2
\r
423 - /usr/src/lighttpd-@VERSION@-<REL>-src.tar.bz2
\r
425 -Or use './lighttpd-@VERSION@-<REL>.sh prep' to get a patched source directory
\r
427 --------------------------------------------
\r
429 -Files included in the binary distribution:
\r
431 - /etc/lighttpd/lighttpd.conf.default
\r
432 - /usr/lib/cyglightcomp.dll
\r
433 - /usr/lib/lighttpd/mod_access.dll
\r
434 - /usr/lib/lighttpd/mod_accesslog.dll
\r
435 - /usr/lib/lighttpd/mod_auth.dll
\r
436 - /usr/lib/lighttpd/mod_cgi.dll
\r
437 - /usr/lib/lighttpd/mod_compress.dll
\r
438 - /usr/lib/lighttpd/mod_evhost.dll
\r
439 - /usr/lib/lighttpd/mod_expire.dll
\r
440 - /usr/lib/lighttpd/mod_fastcgi.dll
\r
441 - /usr/lib/lighttpd/mod_httptls.dll
\r
442 - /usr/lib/lighttpd/mod_maps.dll
\r
443 - /usr/lib/lighttpd/mod_proxy.dll
\r
444 - /usr/lib/lighttpd/mod_redirect.dll
\r
445 - /usr/lib/lighttpd/mod_rewrite.dll
\r
446 - /usr/lib/lighttpd/mod_rrdtool.dll
\r
447 - /usr/lib/lighttpd/mod_secdownload.dll
\r
448 - /usr/lib/lighttpd/mod_simple_vhost.dll
\r
449 - /usr/lib/lighttpd/mod_ssi.dll
\r
450 - /usr/lib/lighttpd/mod_status.dll
\r
451 - /usr/lib/lighttpd/mod_usertrack.dll
\r
452 - /usr/sbin/lighttpd.exe
\r
453 - /usr/share/doc/Cygwin/lighttpd-1.3.0.README
\r
454 - /usr/share/doc/lighttpd-1.3.0/accesslog.txt
\r
455 - /usr/share/doc/lighttpd-1.3.0/authentification.txt
\r
456 - /usr/share/doc/lighttpd-1.3.0/AUTHORS
\r
457 - /usr/share/doc/lighttpd-1.3.0/cgi.txt
\r
458 - /usr/share/doc/lighttpd-1.3.0/ChangeLog
\r
459 - /usr/share/doc/lighttpd-1.3.0/compress.txt
\r
460 - /usr/share/doc/lighttpd-1.3.0/configuration.txt
\r
461 - /usr/share/doc/lighttpd-1.3.0/COPYING
\r
462 - /usr/share/doc/lighttpd-1.3.0/fastcgi-state.txt
\r
463 - /usr/share/doc/lighttpd-1.3.0/fastcgi.txt
\r
464 - /usr/share/doc/lighttpd-1.3.0/features.txt
\r
465 - /usr/share/doc/lighttpd-1.3.0/INSTALL
\r
466 - /usr/share/doc/lighttpd-1.3.0/NEWS
\r
467 - /usr/share/doc/lighttpd-1.3.0/performance.txt
\r
468 - /usr/share/doc/lighttpd-1.3.0/plugins.txt
\r
469 - /usr/share/doc/lighttpd-1.3.0/proxy.txt
\r
470 - /usr/share/doc/lighttpd-1.3.0/README
\r
471 - /usr/share/doc/lighttpd-1.3.0/redirect.txt
\r
472 - /usr/share/doc/lighttpd-1.3.0/rewrite.txt
\r
473 - /usr/share/doc/lighttpd-1.3.0/rrdtool.txt
\r
474 - /usr/share/doc/lighttpd-1.3.0/secdownload.txt
\r
475 - /usr/share/doc/lighttpd-1.3.0/security.txt
\r
476 - /usr/share/doc/lighttpd-1.3.0/simple-vhost.txt
\r
477 - /usr/share/doc/lighttpd-1.3.0/skeleton.txt
\r
478 - /usr/share/doc/lighttpd-1.3.0/ssi.txt
\r
479 - /usr/share/doc/lighttpd-1.3.0/state.txt
\r
480 - /usr/share/man/man1/lighttpd.1.gz
\r
482 -------------------
\r
486 ----------- lighttpd-1.3.1-1 -----------
\r
490 ----------- lighttpd-1.3.0-1 -----------
\r
493 -Cygwin port maintained by: Jan Kneschke <jan@kneschke.de>
\r
494 -Please address all questions to the Cygwin mailing list at <cygwin@cygwin.com>
\r
497 +------------------------------------------
498 +A fast, secure and flexible webserver
500 +Runtime requirements:
501 + cygwin-1.5.10 or newer
503 + libbz2_1-1.0.2 or newer
504 + libpcre0-4.5 or newer
505 + openssl-0.9.7d or newer
506 + zlib-1.2.1 or newer
509 + cygwin-1.5.10 or newer
510 + gcc-3.3.1-3 or newer
511 + binutils-20030901-1 or newer
521 + http://jan.kneschke.de/projects/lighttpd/
524 + http://jan.kneschke.de/projects/lighttpd/download
526 +------------------------------------
529 + unpack lighttpd-@VERSION@-<REL>-src.tar.bz2
530 + if you use setup to install this src package, it will be
531 + unpacked under /usr/src automatically
533 + ./lighttpd-@VERSION@-<REL>.sh all
536 + /usr/src/lighttpd-@VERSION@-<REL>.tar.bz2
537 + /usr/src/lighttpd-@VERSION@-<REL>-src.tar.bz2
539 +Or use './lighttpd-@VERSION@-<REL>.sh prep' to get a patched source directory
541 +-------------------------------------------
543 +Files included in the binary distribution:
545 + /etc/lighttpd/lighttpd.conf.default
546 + /usr/lib/cyglightcomp.dll
547 + /usr/lib/lighttpd/mod_access.dll
548 + /usr/lib/lighttpd/mod_accesslog.dll
549 + /usr/lib/lighttpd/mod_auth.dll
550 + /usr/lib/lighttpd/mod_cgi.dll
551 + /usr/lib/lighttpd/mod_compress.dll
552 + /usr/lib/lighttpd/mod_evhost.dll
553 + /usr/lib/lighttpd/mod_expire.dll
554 + /usr/lib/lighttpd/mod_fastcgi.dll
555 + /usr/lib/lighttpd/mod_httptls.dll
556 + /usr/lib/lighttpd/mod_maps.dll
557 + /usr/lib/lighttpd/mod_proxy.dll
558 + /usr/lib/lighttpd/mod_redirect.dll
559 + /usr/lib/lighttpd/mod_rewrite.dll
560 + /usr/lib/lighttpd/mod_rrdtool.dll
561 + /usr/lib/lighttpd/mod_secdownload.dll
562 + /usr/lib/lighttpd/mod_simple_vhost.dll
563 + /usr/lib/lighttpd/mod_ssi.dll
564 + /usr/lib/lighttpd/mod_status.dll
565 + /usr/lib/lighttpd/mod_usertrack.dll
566 + /usr/sbin/lighttpd.exe
567 + /usr/share/doc/Cygwin/lighttpd-1.3.0.README
568 + /usr/share/doc/lighttpd-1.3.0/accesslog.txt
569 + /usr/share/doc/lighttpd-1.3.0/authentification.txt
570 + /usr/share/doc/lighttpd-1.3.0/AUTHORS
571 + /usr/share/doc/lighttpd-1.3.0/cgi.txt
572 + /usr/share/doc/lighttpd-1.3.0/ChangeLog
573 + /usr/share/doc/lighttpd-1.3.0/compress.txt
574 + /usr/share/doc/lighttpd-1.3.0/configuration.txt
575 + /usr/share/doc/lighttpd-1.3.0/COPYING
576 + /usr/share/doc/lighttpd-1.3.0/fastcgi-state.txt
577 + /usr/share/doc/lighttpd-1.3.0/fastcgi.txt
578 + /usr/share/doc/lighttpd-1.3.0/features.txt
579 + /usr/share/doc/lighttpd-1.3.0/INSTALL
580 + /usr/share/doc/lighttpd-1.3.0/NEWS
581 + /usr/share/doc/lighttpd-1.3.0/performance.txt
582 + /usr/share/doc/lighttpd-1.3.0/plugins.txt
583 + /usr/share/doc/lighttpd-1.3.0/proxy.txt
584 + /usr/share/doc/lighttpd-1.3.0/README
585 + /usr/share/doc/lighttpd-1.3.0/redirect.txt
586 + /usr/share/doc/lighttpd-1.3.0/rewrite.txt
587 + /usr/share/doc/lighttpd-1.3.0/rrdtool.txt
588 + /usr/share/doc/lighttpd-1.3.0/secdownload.txt
589 + /usr/share/doc/lighttpd-1.3.0/security.txt
590 + /usr/share/doc/lighttpd-1.3.0/simple-vhost.txt
591 + /usr/share/doc/lighttpd-1.3.0/skeleton.txt
592 + /usr/share/doc/lighttpd-1.3.0/ssi.txt
593 + /usr/share/doc/lighttpd-1.3.0/state.txt
594 + /usr/share/man/man1/lighttpd.1.gz
600 +---------- lighttpd-1.3.1-1 -----------
604 +---------- lighttpd-1.3.0-1 -----------
607 +Cygwin port maintained by: Jan Kneschke <jan@kneschke.de>
608 +Please address all questions to the Cygwin mailing list at <cygwin@cygwin.com>
610 --- ../lighttpd-1.4.11/doc/authentication.txt 2006-01-12 20:34:26.000000000 +0200
611 +++ lighttpd-1.4.12/doc/authentication.txt 2006-07-16 00:26:05.000000000 +0300
615 :Author: Jan Kneschke
617 -:Revision: $Revision$
619 +:Revision: $Revision$
622 The auth module provides ...
623 --- ../lighttpd-1.4.11/doc/compress.txt 2005-08-11 01:26:16.000000000 +0300
624 +++ lighttpd-1.4.12/doc/compress.txt 2006-07-16 00:26:05.000000000 +0300
628 Output compression reduces the network load and can improve the overall
629 -throughput of the webserver.
630 +throughput of the webserver. All major http-clients support compression by
631 +announcing it in the Accept-Encoding header. This is used to negotiate the
632 +most suitable compression method. We support deflate, gzip and bzip2.
634 -Only static content is supported up to now.
635 +deflate (RFC1950, RFC1951) and gzip (RFC1952) depend on zlib while bzip2
636 +depends on libbzip2. bzip2 is only supported by lynx and some other console
639 -The server negotiates automaticly which compression method is used.
640 -Supported are gzip, deflate, bzip.
641 +Currently we limit to compression support to static files.
646 +mod_compress can stored compressed files on disk to optimized the compression
647 +on a second request away. As soon as compress.cache-dir is set the files are
650 +The names of the cache files are made of the filename, the compression method
651 +and the etag associated to the file.
653 +Cleaning the cache is left to the user. A cron job deleting files older than
654 +10 days should do fine.
659 +The module limits the compression of files to files larger than 128 Byte and
660 +smaller than 128 MByte.
662 +The lower limit is set as small files tend to become larger by compressing due
663 +to the compression headers, the upper limit is set to work sensable with
664 +memory and cpu-time.
669 Default: not set, compress the file for every request
672 - mimetypes where might get compressed
673 + mimetypes which might get compressed
677 compress.filetype = ("text/plain", "text/html")
679 + Keep in mind that compressed JavaScript and CSS files are broken in some
684 +compress.max-file-size
685 + maximum size of the original file to be compressed kBytes.
687 + This is meant to protect the server against DoSing as compressing large
688 + (let's say 1Gbyte) takes a lot of time and would delay the whole operation
691 + There is a hard upper limit of 128Mbyte.
693 + Default: unlimited (== hard-limit of 128MByte)
695 Compressing Dynamic Content
696 ===========================
698 --- ../lighttpd-1.4.11/doc/configuration.txt 2006-03-09 02:10:40.000000000 +0200
699 +++ lighttpd-1.4.12/doc/configuration.txt 2006-07-16 00:26:05.000000000 +0300
703 :Author: Jan Kneschke
705 -:Revision: $Revision$
707 +:Revision: $Revision$
710 the layout of the configuration file
713 debug.log-request-handling
716 +debug.log-condition-handling
719 +debug.log-condition-cache-handling
720 + for developers only
722 --- ../lighttpd-1.4.11/doc/fastcgi.txt 2006-02-16 17:03:52.000000000 +0200
723 +++ lighttpd-1.4.12/doc/fastcgi.txt 2006-07-16 00:26:05.000000000 +0300
725 PHP can extract PATH_INFO from it (default: disabled)
726 :"disable-time": time to wait before a disabled backend is checked
728 - :"allow-x-send-file": controls if X-LIGHTTPD-send-file headers
730 + :"allow-x-send-file": controls if X-LIGHTTPD-send-file and X-Sendfile
731 + headers are allowed
735 --- ../lighttpd-1.4.11/doc/lighttpd.conf 2006-03-04 14:41:12.000000000 +0200
736 +++ lighttpd-1.4.12/doc/lighttpd.conf 2006-07-16 00:26:05.000000000 +0300
737 @@ -172,10 +172,11 @@
738 #dir-listing.activate = "enable"
741 -#debug.log-request-header = "enable"
742 -#debug.log-response-header = "enable"
743 -#debug.log-request-handling = "enable"
744 -#debug.log-file-not-found = "enable"
745 +#debug.log-request-header = "enable"
746 +#debug.log-response-header = "enable"
747 +#debug.log-request-handling = "enable"
748 +#debug.log-file-not-found = "enable"
749 +#debug.log-condition-handling = "enable"
751 ### only root can use these options
753 --- ../lighttpd-1.4.11/doc/performance.txt 2006-02-02 13:01:08.000000000 +0200
754 +++ lighttpd-1.4.12/doc/performance.txt 2006-07-16 00:26:05.000000000 +0300
757 server.stat-cache-engine = "fam" # either fam, simple or disabled
759 +See http://oss.sgi.com/projects/fam/faq.html for information about FAM.
760 +See http://www.gnome.org/~veillard/gamin/overview.html for information about gamin.
762 Platform-Specific Notes
763 =======================
764 --- ../lighttpd-1.4.11/doc/secdownload.txt 2005-12-20 15:58:58.000000000 +0200
765 +++ lighttpd-1.4.12/doc/secdownload.txt 2006-07-16 00:26:05.000000000 +0300
767 $secret = "verysecret";
768 $uri_prefix = "/dl/";
771 + # filename, make sure it's started with a "/" or you'll get 404 in the browser
772 $f = "/secret-file.txt";
775 --- ../lighttpd-1.4.11/lighttpd.spec 2006-03-07 14:22:18.000000000 +0200
776 +++ lighttpd-1.4.12/lighttpd.spec 2006-07-19 20:09:00.000000000 +0300
778 Summary: A fast webserver with minimal memory-footprint (lighttpd)
783 Source: http://jan.kneschke.de/projects/lighttpd/download/lighttpd-%version.tar.gz
784 Packager: Jan Kneschke <jan@kneschke.de>
785 --- ../lighttpd-1.4.11/openwrt/control 2006-03-07 14:22:19.000000000 +0200
786 +++ lighttpd-1.4.12/openwrt/control 2006-07-19 20:09:00.000000000 +0300
792 Maintainer: Jan Kneschke <jan@kneschke.de>
793 -Source: http://jan.kneschke.de/projects/lighttpd/download/lighttpd-1.4.11.tar.gz
794 +Source: http://jan.kneschke.de/projects/lighttpd/download/lighttpd-1.4.12.tar.gz
798 --- ../lighttpd-1.4.11/openwrt/lighttpd.mk 2006-03-07 14:22:19.000000000 +0200
799 +++ lighttpd-1.4.12/openwrt/lighttpd.mk 2006-07-19 20:09:00.000000000 +0300
802 # For this example we'll use a fairly simple package that compiles easily
803 # and has sources available for download at sourceforge
804 -LIGHTTPD=lighttpd-1.4.11
805 +LIGHTTPD=lighttpd-1.4.12
806 LIGHTTPD_TARGET=.built
807 LIGHTTPD_DIR=$(BUILD_DIR)/$(LIGHTTPD)
808 LIGHTTPD_IPK=$(BUILD_DIR)/$(LIGHTTPD)_mipsel.ipk
809 --- ../lighttpd-1.4.11/src/Makefile.am 2006-03-07 14:20:20.000000000 +0200
810 +++ lighttpd-1.4.12/src/Makefile.am 2006-07-19 20:02:55.000000000 +0300
813 configparser.y: lemon
814 mod_ssi_exprparser.y: lemon
815 +http_resp_parser.y: lemon
817 configparser.c configparser.h: configparser.y
819 - $(LEMON) -q $(srcdir)/configparser.y $(srcdir)/lempar.c
820 + $(LEMON) -q $(srcdir)/$< $(srcdir)/lempar.c
822 +http_resp_parser.c http_resp_parser.h: http_resp_parser.y
823 + rm -f http_resp_parser.h
824 + $(LEMON) -q $(srcdir)/$< $(srcdir)/lempar.c
826 mod_ssi_exprparser.c mod_ssi_exprparser.h: mod_ssi_exprparser.y
827 rm -f mod_ssi_exprparser.h
828 - $(LEMON) -q $(srcdir)/mod_ssi_exprparser.y $(srcdir)/lempar.c
829 + $(LEMON) -q $(srcdir)/$< $(srcdir)/lempar.c
832 configfile.c: configparser.h
833 mod_ssi_expr.c: mod_ssi_exprparser.h
834 +http_resp.c: http_resp_parser.h
836 common_src=buffer.c log.c \
839 fdevent_solaris_devpoll.c fdevent_freebsd_kqueue.c \
840 data_config.c bitset.c \
841 inet_ntop_cache.c crc32.c \
842 - connections-glue.c \
843 - configfile-glue.c \
844 + connections-glue.c iosocket.c \
845 + configfile-glue.c status_counter.c \
847 network_write.c network_linux_sendfile.c \
848 network_freebsd_sendfile.c network_writev.c \
849 network_solaris_sendfilev.c network_openssl.c \
851 + splaytree.c http_resp.c http_resp_parser.c
853 src = server.c response.c connections.c network.c \
854 configfile.c configparser.c request.c proc_open.c
857 lib_LTLIBRARIES += mod_webdav.la
858 mod_webdav_la_SOURCES = mod_webdav.c
859 -mod_webdav_la_CFLAGS = $(AM_CFLAGS) $(XML_CFLAGS) $(SQLITE_CFLAGS)
860 +mod_webdav_la_CFLAGS = $(AM_CFLAGS) $(XML_CFLAGS) $(SQLITE_CFLAGS)
861 mod_webdav_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
862 -mod_webdav_la_LIBADD = $(common_libadd) $(XML_LIBS) $(SQLITE_LIBS)
863 +mod_webdav_la_LIBADD = $(common_libadd) $(XML_LIBS) $(SQLITE_LIBS) $(UUID_LIB)
865 lib_LTLIBRARIES += mod_cml.la
866 mod_cml_la_SOURCES = mod_cml.c mod_cml_lua.c mod_cml_funcs.c
868 mod_mysql_vhost_la_LIBADD = $(MYSQL_LIBS) $(common_libadd)
869 mod_mysql_vhost_la_CPPFLAGS = $(MYSQL_INCLUDE)
871 +lib_LTLIBRARIES += mod_sql_vhost_core.la
872 +mod_sql_vhost_core_la_SOURCES = mod_sql_vhost_core.c
873 +mod_sql_vhost_core_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
874 +mod_sql_vhost_core_la_LIBADD = $(common_libadd)
876 lib_LTLIBRARIES += mod_cgi.la
877 mod_cgi_la_SOURCES = mod_cgi.c
878 mod_cgi_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
880 mod_proxy_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
881 mod_proxy_la_LIBADD = $(common_libadd)
883 +lib_LTLIBRARIES += mod_proxy_core.la
884 +mod_proxy_core_la_SOURCES = mod_proxy_core.c mod_proxy_core_pool.c \
885 + mod_proxy_core_backend.c mod_proxy_core_address.c \
886 + mod_proxy_core_backlog.c mod_proxy_core_rewrites.c
887 +mod_proxy_core_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
888 +mod_proxy_core_la_LIBADD = $(common_libadd) $(PCRE_LIB)
891 lib_LTLIBRARIES += mod_ssi.la
892 mod_ssi_la_SOURCES = mod_ssi_exprparser.c mod_ssi_expr.c mod_ssi.c
893 mod_ssi_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
895 mod_ssi.h mod_ssi_expr.h inet_ntop_cache.h \
896 configparser.h mod_ssi_exprparser.h \
897 sys-mmap.h sys-socket.h mod_cml.h mod_cml_funcs.h \
898 - splaytree.h proc_open.h
899 + splaytree.h proc_open.h http_resp.h mod_sql_vhost_core.h \
900 + sys-files.h sys-process.h sys-strings.h http_resp_parser.h \
901 + iosocket.h array-static.h \
902 + mod_proxy_core_address.h mod_proxy_core_backend.h \
903 + mod_proxy_core_backlog.h mod_proxy_core.h \
904 + mod_proxy_core_pool.h mod_proxy_core_rewrites.h \
907 DEFS= @DEFS@ -DLIBRARY_DIR="\"$(libdir)\""
912 noinst_HEADERS = $(hdr)
913 -EXTRA_DIST = mod_skeleton.c configparser.y mod_ssi_exprparser.y lempar.c
914 +EXTRA_DIST = mod_skeleton.c configparser.y mod_ssi_exprparser.y lempar.c http_resp_parser.y
915 --- ../lighttpd-1.4.11/src/array-static.h 1970-01-01 03:00:00.000000000 +0300
916 +++ lighttpd-1.4.12/src/array-static.h 2006-07-18 13:03:40.000000000 +0300
918 +#ifndef _ARRAY_STATIC_H_
919 +#define _ARRAY_STATIC_H_
921 +/* define a generic array of <type>
924 +#define ARRAY_STATIC_DEF(name, type, extra) \
932 +/* all append operations need a 'resize' for the +1 */
934 +#define ARRAY_STATIC_PREPARE_APPEND(a) \
935 + if (a->size == 0) { \
937 + a->ptr = malloc(a->size * sizeof(*(a->ptr))); \
938 + } else if (a->size == a->used) { \
940 + a->ptr = realloc(a->ptr, a->size * sizeof(*(a->ptr))); \
943 +#define FOREACH(array, element, func) \
944 +do { size_t _i; for (_i = 0; _i < array->used; _i++) { void *element = array->ptr[_i]; func; } } while(0);
946 +#define STRUCT_INIT(type, var) \
948 + var = calloc(1, sizeof(*var))
951 --- ../lighttpd-1.4.11/src/array.c 2005-11-18 13:58:32.000000000 +0200
952 +++ lighttpd-1.4.12/src/array.c 2006-07-16 00:26:03.000000000 +0300
955 array *array_init(void) {
959 a = calloc(1, sizeof(*a));
963 a->next_power_of_2 = 1;
970 void array_free(array *a) {
975 if (!a->is_weakref) {
976 for (i = 0; i < a->size; i++) {
977 if (a->data[i]) a->data[i]->free(a->data[i]);
982 if (a->data) free(a->data);
983 if (a->sorted) free(a->sorted);
989 void array_reset(array *a) {
994 if (!a->is_weakref) {
995 for (i = 0; i < a->used; i++) {
996 a->data[i]->reset(a->data[i]);
1005 static int array_get_index(array *a, const char *key, size_t keylen, int *rndx) {
1010 if (key == NULL) return -1;
1013 /* try to find the string */
1014 for (i = pos = a->next_power_of_2 / 2; ; i >>= 1) {
1020 } else if (pos >= (int)a->used) {
1023 cmp = buffer_caseless_compare(key, keylen, a->data[a->sorted[pos]]->key->ptr, a->data[a->sorted[pos]]->key->used);
1028 ndx = a->sorted[pos];
1029 @@ -110,46 +110,46 @@
1035 if (rndx) *rndx = pos;
1041 data_unset *array_get_element(array *a, const char *key) {
1045 if (-1 != (ndx = array_get_index(a, key, strlen(key) + 1, NULL))) {
1046 /* found, leave here */
1049 return a->data[ndx];
1057 data_unset *array_get_unused_element(array *a, data_type_t t) {
1058 data_unset *ds = NULL;
1063 if (a->size == 0) return NULL;
1066 if (a->used == a->size) return NULL;
1068 if (a->data[a->used]) {
1069 ds = a->data[a->used];
1072 a->data[a->used] = NULL;
1079 /* replace or insert data, return the old one with the same key */
1080 data_unset *array_replace(array *a, data_unset *du) {
1084 if (-1 == (ndx = array_get_index(a, du->key->ptr, du->key->used, NULL))) {
1085 array_insert_unique(a, du);
1087 @@ -164,13 +164,13 @@
1092 - /* generate unique index if neccesary */
1094 + /* generate unique index if necessary */
1095 if (str->key->used == 0 || str->is_index_key) {
1096 buffer_copy_long(str->key, a->unique_ndx++);
1097 str->is_index_key = 1;
1101 /* try to find the string */
1102 if (-1 != (ndx = array_get_index(a, str->key->ptr, str->key->used, &pos))) {
1103 /* found, leave here */
1104 @@ -181,14 +181,14 @@
1113 if (a->used+1 > INT_MAX) {
1114 /* we can't handle more then INT_MAX entries: see array_get_index() */
1121 a->data = malloc(sizeof(*a->data) * a->size);
1122 @@ -204,27 +204,27 @@
1124 for (j = a->used; j < a->size; j++) a->data[j] = NULL;
1128 ndx = (int) a->used;
1131 a->data[a->used++] = str;
1137 buffer_caseless_compare(str->key->ptr, str->key->used, a->data[a->sorted[pos]]->key->ptr, a->data[a->sorted[pos]]->key->used) > 0)) {
1141 - /* move everything on step to the right */
1144 + /* move everything one step to the right */
1146 memmove(a->sorted + (pos + 1), a->sorted + (pos), (ndx - pos) * sizeof(*a->sorted));
1151 a->sorted[pos] = ndx;
1154 if (a->next_power_of_2 == (size_t)ndx) a->next_power_of_2 <<= 1;
1171 array_print_indent(depth);
1172 fprintf(stderr, ")");
1178 @@ -323,47 +323,47 @@
1190 ds = data_string_init();
1191 buffer_copy_string(ds->key, "abc");
1192 buffer_copy_string(ds->value, "alfrag");
1195 array_insert_unique(a, (data_unset *)ds);
1198 ds = data_string_init();
1199 buffer_copy_string(ds->key, "abc");
1200 buffer_copy_string(ds->value, "hameplman");
1203 array_insert_unique(a, (data_unset *)ds);
1206 ds = data_string_init();
1207 buffer_copy_string(ds->key, "123");
1208 buffer_copy_string(ds->value, "alfrag");
1211 array_insert_unique(a, (data_unset *)ds);
1214 dc = data_count_init();
1215 buffer_copy_string(dc->key, "def");
1218 array_insert_unique(a, (data_unset *)dc);
1221 dc = data_count_init();
1222 buffer_copy_string(dc->key, "def");
1225 array_insert_unique(a, (data_unset *)dc);
1234 fprintf(stderr, "%d\n",
1235 buffer_caseless_compare(CONST_STR_LEN("Content-Type"), CONST_STR_LEN("Content-type")));
1241 --- ../lighttpd-1.4.11/src/array.h 2005-09-23 21:24:18.000000000 +0300
1242 +++ lighttpd-1.4.12/src/array.h 2006-07-16 00:26:03.000000000 +0300
1244 #define DATA_UNSET \
1247 - int is_index_key; /* 1 if key is a array index (autogenerated keys) */ \
1248 + int is_index_key; /* 1 if key is an array index (auto-generated keys) */ \
1249 struct data_unset *(*copy)(const struct data_unset *src); \
1250 void (* free)(struct data_unset *p); \
1251 void (* reset)(struct data_unset *p); \
1268 size_t next_power_of_2;
1269 int is_weakref; /* data is weakref, don't bother the data */
1298 COMP_SERVER_SOCKET, COMP_HTTP_URL, COMP_HTTP_HOST, COMP_HTTP_REFERER, COMP_HTTP_USERAGENT, COMP_HTTP_COOKIE, COMP_HTTP_REMOTEIP
1301 -/* $HTTP["host"] == "incremental.home.kneschke.de" { ... }
1302 +/* $HTTP["host"] == "incremental.home.kneschke.de" { ... }
1303 * for print: comp_key op string
1304 * for compare: comp cond string/regex
1307 typedef struct _data_config data_config;
1308 struct _data_config {
1323 int context_ndx; /* more or less like an id */
1327 /* for chaining only */
1344 @@ -120,13 +120,13 @@
1350 unsigned short port;
1357 int usage; /* fair-balancing needs the no. of connections active on this host */
1358 int last_used_ndx; /* round robin */
1360 --- ../lighttpd-1.4.11/src/base.h 2006-01-11 16:51:04.000000000 +0200
1361 +++ lighttpd-1.4.12/src/base.h 2006-07-19 20:02:55.000000000 +0300
1365 #include <sys/types.h>
1366 -#include <sys/time.h>
1367 #include <sys/stat.h>
1369 #ifdef HAVE_CONFIG_H
1371 #include "sys-socket.h"
1372 #include "splaytree.h"
1375 #if defined HAVE_LIBSSL && defined HAVE_OPENSSL_SSL_H
1376 # define USE_OPENSSL
1377 -# include <openssl/ssl.h>
1378 +# include <openssl/ssl.h>
1386 -#ifndef O_LARGEFILE
1387 -# define O_LARGEFILE 0
1392 # define SIZE_MAX SIZE_T_MAX
1395 /* solaris and NetBSD 1.3.x again */
1396 #if (!defined(HAVE_STDINT_H)) && (!defined(HAVE_INTTYPES_H)) && (!defined(uint32_t))
1397 -# define uint32_t u_int32_t
1398 +/* # define uint32_t u_int32_t */
1399 +typedef unsigned __int32 uint32_t;
1405 #include "settings.h"
1407 -typedef enum { T_CONFIG_UNSET,
1413 +typedef enum { T_CONFIG_UNSET,
1420 } config_values_type_t;
1422 -typedef enum { T_CONFIG_SCOPE_UNSET,
1423 - T_CONFIG_SCOPE_SERVER,
1424 +typedef enum { T_CONFIG_SCOPE_UNSET,
1425 + T_CONFIG_SCOPE_SERVER,
1426 T_CONFIG_SCOPE_CONNECTION
1427 } config_scope_type_t;
1434 config_values_type_t type;
1435 config_scope_type_t scope;
1437 @@ -118,18 +113,6 @@
1444 - struct sockaddr_in6 ipv6;
1446 - struct sockaddr_in ipv4;
1447 -#ifdef HAVE_SYS_UN_H
1448 - struct sockaddr_un un;
1450 - struct sockaddr plain;
1453 /* fcgi_response_header contains ... */
1454 #define HTTP_STATUS BV(0)
1455 #define HTTP_CONNECTION BV(1)
1456 @@ -142,40 +125,40 @@
1457 /* the request-line */
1465 http_method_t http_method;
1466 http_version_t http_version;
1469 buffer *request_line;
1472 /* strings to the header */
1473 buffer *http_host; /* not alloced */
1474 const char *http_range;
1475 const char *http_content_type;
1476 const char *http_if_modified_since;
1477 const char *http_if_none_match;
1484 size_t content_length; /* returned by strtoul() */
1487 /* internal representation */
1488 int accept_encoding;
1496 off_t content_length;
1497 - int keep_alive; /* used by the subrequests in proxy, cgi and fcgi to say the subrequest was keep-alive or not */
1499 + int keep_alive; /* used by the subrequests in proxy, cgi and fcgi to say whether the subrequest was keep-alive or not */
1506 HTTP_TRANSFER_ENCODING_IDENTITY, HTTP_TRANSFER_ENCODING_CHUNKED
1507 } transfer_encoding;
1509 @@ -191,21 +174,21 @@
1512 buffer *basedir; /* path = "(basedir)(.*)" */
1515 buffer *doc_root; /* path = doc_root + rel_path */
1536 @@ -215,20 +198,20 @@
1540 - splay_tree *files; /* the nodes of the tree are stat_cache_entry's */
1542 + splay_tree *files; /* the nodes of the tree are stat_cache_entries */
1544 buffer *dir_name; /* for building the dirname from the filename */
1546 splay_tree *dirs; /* the nodes of the tree are fam_dir_entry */
1558 /* virtual-servers */
1559 buffer *document_root;
1560 buffer *server_name;
1563 buffer *dirlist_encoding;
1564 buffer *errorfile_prefix;
1567 unsigned short max_keep_alive_requests;
1568 unsigned short max_keep_alive_idle;
1569 unsigned short max_read_idle;
1570 @@ -244,16 +227,17 @@
1571 unsigned short use_xattr;
1572 unsigned short follow_symlink;
1573 unsigned short range_requests;
1579 unsigned short log_file_not_found;
1580 unsigned short log_request_header;
1581 unsigned short log_request_handling;
1582 unsigned short log_response_header;
1583 unsigned short log_condition_handling;
1586 + unsigned short log_condition_cache_handling;
1590 buffer *ssl_pemfile;
1591 buffer *ssl_ca_file;
1592 @@ -268,22 +252,22 @@
1594 unsigned short global_kbytes_per_second; /* */
1596 - off_t global_bytes_per_second_cnt;
1597 + off_t global_bytes_per_second_cnt;
1598 /* server-wide traffic-shaper
1601 * each context has the counter which is inited once
1602 - * a second by the global_kbytes_per_second config-var
1603 + * per second by the global_kbytes_per_second config-var
1605 * as soon as global_kbytes_per_second gets below 0
1606 * the connected conns are "offline" a little bit
1609 - * we somehow have to loose our "we are writable" signal
1610 + * we somehow have to lose our "we are writable" signal
1615 off_t *global_bytes_per_second_cnt_ptr; /* */
1621 @@ -291,18 +275,18 @@
1623 /* the order of the items should be the same as they are processed
1624 * read before write as we use this later */
1626 - CON_STATE_CONNECT,
1627 - CON_STATE_REQUEST_START,
1629 - CON_STATE_REQUEST_END,
1630 - CON_STATE_READ_POST,
1631 - CON_STATE_HANDLE_REQUEST,
1632 - CON_STATE_RESPONSE_START,
1634 - CON_STATE_RESPONSE_END,
1638 + CON_STATE_CONNECT,
1639 + CON_STATE_REQUEST_START,
1641 + CON_STATE_REQUEST_END,
1642 + CON_STATE_READ_POST,
1643 + CON_STATE_HANDLE_REQUEST,
1644 + CON_STATE_RESPONSE_START,
1646 + CON_STATE_RESPONSE_END,
1649 } connection_state_t;
1651 typedef enum { COND_RESULT_UNSET, COND_RESULT_FALSE, COND_RESULT_TRUE } cond_result_t;
1652 @@ -315,91 +299,86 @@
1655 connection_state_t state;
1659 time_t read_idle_ts;
1660 time_t close_timeout_ts;
1661 time_t write_request_ts;
1664 time_t connection_start;
1665 time_t request_start;
1668 struct timeval start_tv;
1671 size_t request_count; /* number of requests handled in this connection */
1672 size_t loops_per_request; /* to catch endless loops in a single request
1675 * used by mod_rewrite, mod_fastcgi, ... and others
1676 * this is self-protection
1679 - int fd; /* the FD for this connection */
1680 - int fde_ndx; /* index for the fdevent-handler */
1683 int ndx; /* reverse mapping to server->connection[ndx] */
1690 - int keep_alive; /* only request.c can enable it, all other just disable */
1693 + int keep_alive; /* only request.c can enable it, all others just disable */
1699 chunkqueue *write_queue; /* a large queue for low-level write ( HTTP response ) [ file, mem ] */
1700 chunkqueue *read_queue; /* a small queue for low-level read ( HTTP request ) [ mem ] */
1701 chunkqueue *request_content_queue; /* takes request-content into tempfile if necessary [ tempfile, mem ]*/
1704 int traffic_limit_reached;
1707 off_t bytes_written; /* used by mod_accesslog, mod_rrd */
1708 off_t bytes_written_cur_second; /* used by mod_accesslog, mod_rrd */
1709 off_t bytes_read; /* used by mod_accesslog, mod_rrd */
1717 buffer *dst_addr_buf;
1720 buffer *parse_request;
1721 unsigned int parsed_response; /* bitfield which contains the important header-fields of the parsed response header */
1726 - physical physical;
1727 + physical physical;
1734 buffer *authed_user;
1735 array *environment; /* used to pass lighttpd internal stuff to the FastCGI/CGI apps, setenv does that */
1745 connection_type mode;
1748 void **plugin_ctx; /* plugin connection specific config */
1751 specific_config conf; /* global connection specific config */
1752 cond_cache_t *cond_cache;
1755 buffer *server_name;
1759 buffer *error_handler;
1760 int error_handler_saved_status;
1761 int in_error_handler;
1764 void *srv_socket; /* reference to the server-socket (typecast to server_socket) */
1772 @@ -439,55 +418,63 @@
1777 + NETWORK_STATUS_UNSET,
1778 + NETWORK_STATUS_SUCCESS,
1779 + NETWORK_STATUS_FATAL_ERROR,
1780 + NETWORK_STATUS_CONNECTION_CLOSE,
1781 + NETWORK_STATUS_WAIT_FOR_EVENT,
1782 + NETWORK_STATUS_INTERRUPTED
1783 +} network_status_t;
1786 unsigned short port;
1789 - buffer *errorlog_file;
1790 - unsigned short errorlog_use_syslog;
1793 unsigned short dont_daemonize;
1802 buffer *event_handler;
1805 buffer *modules_dir;
1806 buffer *network_backend;
1808 array *upload_tempdirs;
1811 unsigned short max_worker;
1812 unsigned short max_fds;
1813 unsigned short max_conns;
1814 unsigned short max_request_size;
1817 unsigned short log_request_header_on_error;
1818 unsigned short log_state_handling;
1820 - enum { STAT_CACHE_ENGINE_UNSET,
1821 - STAT_CACHE_ENGINE_NONE,
1822 - STAT_CACHE_ENGINE_SIMPLE,
1823 - STAT_CACHE_ENGINE_FAM
1825 + enum { STAT_CACHE_ENGINE_UNSET,
1826 + STAT_CACHE_ENGINE_NONE,
1827 + STAT_CACHE_ENGINE_SIMPLE,
1828 + STAT_CACHE_ENGINE_FAM
1829 } stat_cache_engine;
1830 unsigned short enable_cores;
1832 + buffer *errorlog_file;
1833 + unsigned short errorlog_use_syslog;
1843 buffer *ssl_pemfile;
1844 buffer *ssl_ca_file;
1845 unsigned short use_ipv6;
1846 unsigned short is_ssl;
1855 @@ -495,37 +482,32 @@
1858 server_socket **ptr;
1863 } server_socket_array;
1865 typedef struct server {
1866 server_socket_array srv_sockets;
1868 - /* the errorlog */
1870 - enum { ERRORLOG_STDERR, ERRORLOG_FILE, ERRORLOG_SYSLOG } errorlog_mode;
1871 - buffer *errorlog_buf;
1874 fdevents *ev, *ev_ins;
1877 buffer_plugin plugins;
1891 int max_fds; /* max possible fds */
1892 int cur_fds; /* currently used fds */
1893 int want_fds; /* waiting fds */
1894 int sockets_disabled;
1900 @@ -533,13 +515,13 @@
1901 buffer *response_header;
1902 buffer *response_range;
1906 buffer *tmp_chunk_len;
1909 buffer *empty_string; /* is necessary for cond_match */
1911 buffer *cond_check_buf;
1916 inet_ntop_cache_type inet_ntop_cache[INET_NTOP_CACHE_MAX];
1917 @@ -547,59 +529,46 @@
1918 mtime_cache_type mtime_cache[FILE_CACHE_MAX];
1925 time_t last_generated_date_ts;
1926 time_t last_generated_debug_ts;
1930 buffer *ts_debug_str;
1931 buffer *ts_date_str;
1936 array *config_touched;
1939 array *config_context;
1940 specific_config **config_storage;
1943 server_config srvconf;
1946 int config_deprecated;
1950 connections *joblist;
1951 connections *fdwaitqueue;
1954 stat_cache *stat_cache;
1957 - * The status array can carry all the status information you want
1958 - * the key to the array is <module-prefix>.<name>
1959 - * and the values are counters
1962 - * fastcgi.backends = 10
1963 - * fastcgi.active-backends = 6
1964 - * fastcgi.backend.<key>.load = 24
1965 - * fastcgi.backend.<key>....
1967 - * fastcgi.backend.<key>.disconnects = ...
1971 fdevent_handler_t event_handler;
1973 - int (* network_backend_write)(struct server *srv, connection *con, int fd, chunkqueue *cq);
1974 - int (* network_backend_read)(struct server *srv, connection *con, int fd, chunkqueue *cq);
1975 + network_status_t (* network_backend_write)(struct server *srv, connection *con, iosocket *sock, chunkqueue *cq);
1976 + network_status_t (* network_backend_read)(struct server *srv, connection *con, iosocket *sock, chunkqueue *cq);
1978 - int (* network_ssl_backend_write)(struct server *srv, connection *con, SSL *ssl, chunkqueue *cq);
1979 - int (* network_ssl_backend_read)(struct server *srv, connection *con, SSL *ssl, chunkqueue *cq);
1980 + network_status_t (* network_ssl_backend_write)(struct server *srv, connection *con, iosocket *sock, chunkqueue *cq);
1981 + network_status_t (* network_ssl_backend_read)(struct server *srv, connection *con, iosocket *sock, chunkqueue *cq);
1991 --- ../lighttpd-1.4.11/src/bitset.c 2005-08-22 01:54:12.000000000 +0300
1992 +++ lighttpd-1.4.12/src/bitset.c 2006-07-18 13:03:40.000000000 +0300
1999 #define BITSET_BITS \
2000 ( CHAR_BIT * sizeof(size_t) )
2001 --- ../lighttpd-1.4.11/src/buffer.c 2006-01-13 00:00:45.000000000 +0200
2002 +++ lighttpd-1.4.12/src/buffer.c 2006-07-18 13:03:40.000000000 +0300
2013 buffer* buffer_init(void) {
2017 b = malloc(sizeof(*b));
2039 void buffer_free(buffer *b) {
2042 void buffer_reset(buffer *b) {
2046 /* limit don't reuse buffer larger than ... bytes */
2047 if (b->size > BUFFER_MAX_REUSE_SIZE) {
2060 - * allocate (if neccessary) enough space for 'size' bytes and
2062 + * allocate (if necessary) enough space for 'size' bytes and
2063 * set the 'used' counter to 0
2068 #define BUFFER_PIECE_SIZE 64
2070 int buffer_prepare_copy(buffer *b, size_t size) {
2073 - if ((0 == b->size) ||
2075 + if ((0 == b->size) ||
2077 if (b->size) free(b->ptr);
2082 - /* always allocate a multiply of BUFFER_PIECE_SIZE */
2084 + /* always allocate a multiple of BUFFER_PIECE_SIZE */
2085 b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE);
2088 b->ptr = malloc(b->size);
2096 - * increase the internal buffer (if neccessary) to append another 'size' byte
2098 + * increase the internal buffer (if necessary) to append another 'size' byte
2099 * ->used isn't changed
2104 int buffer_prepare_append(buffer *b, size_t size) {
2111 - /* always allocate a multiply of BUFFER_PIECE_SIZE */
2113 + /* always allocate a multiple of BUFFER_PIECE_SIZE */
2114 b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE);
2117 b->ptr = malloc(b->size);
2120 } else if (b->used + size > b->size) {
2123 - /* always allocate a multiply of BUFFER_PIECE_SIZE */
2125 + /* always allocate a multiple of BUFFER_PIECE_SIZE */
2126 b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE);
2129 b->ptr = realloc(b->ptr, b->size);
2134 int buffer_copy_string(buffer *b, const char *s) {
2138 if (!s || !b) return -1;
2140 s_len = strlen(s) + 1;
2141 @@ -136,26 +136,26 @@
2143 int buffer_copy_string_len(buffer *b, const char *s, size_t s_len) {
2144 if (!s || !b) return -1;
2146 - /* removed optimization as we have to keep the empty string
2148 + /* removed optimization as we have to keep the empty string
2149 * in some cases for the config handling
2152 * url.access-deny = ( "" )
2154 if (s_len == 0) return 0;
2157 buffer_prepare_copy(b, s_len + 1);
2160 memcpy(b->ptr, s, s_len);
2161 b->ptr[s_len] = '\0';
2162 b->used = s_len + 1;
2168 int buffer_copy_string_buffer(buffer *b, const buffer *src) {
2169 if (!src) return -1;
2172 if (src->used == 0) {
2175 @@ -201,10 +201,10 @@
2178 * append a string to the end of the buffer
2180 - * the resulting buffer is terminated with a '\0'
2181 - * s is treated as a un-terminated string (a \0 is handled a normal character)
2184 + * the resulting buffer is terminated with a '\0'
2185 + * s is treated as an un-terminated string (a \0 is handled as a normal character)
2188 * @param s the string
2189 * @param s_len size of the string (without the terminating \0)
2191 int buffer_append_string_buffer(buffer *b, const buffer *src) {
2192 if (!src) return -1;
2193 if (src->used == 0) return 0;
2196 return buffer_append_string_len(b, src->ptr, src->used - 1);
2201 int buffer_copy_memory(buffer *b, const char *s, size_t s_len) {
2202 if (!s || !b) return -1;
2208 return buffer_append_memory(b, s, s_len);
2211 @@ -402,46 +402,115 @@
2217 + * init the ptr buffer
2220 +buffer_ptr *buffer_ptr_init(buffer_ptr_free_t freer)
2222 + buffer_ptr *l = calloc(1, sizeof(buffer_ptr));
2229 + * free the buffer_array
2232 +void buffer_ptr_free(buffer_ptr *l)
2235 + buffer_ptr_clear(l);
2240 +void buffer_ptr_clear(buffer_ptr *l)
2242 + assert(NULL != l);
2244 + if (l->free && l->used) {
2246 + for (i = 0; i < l->used; i ++) {
2247 + l->free(l->ptr[i]);
2259 +void buffer_ptr_append(buffer_ptr* l, void *item)
2261 + assert(NULL != l);
2262 + if (l->ptr == NULL) {
2264 + l->ptr = (void **)malloc(sizeof(void *) * l->size);
2266 + else if (l->used == l->size) {
2268 + l->ptr = realloc(l->ptr, sizeof(void *) * l->size);
2270 + l->ptr[l->used++] = item;
2273 +void *buffer_ptr_pop(buffer_ptr* l)
2275 + assert(NULL != l && l->used > 0);
2276 + return l->ptr[--l->used];
2279 +void *buffer_ptr_top(buffer_ptr* l)
2281 + assert(NULL != l && l->used > 0);
2282 + return l->ptr[l->used-1];
2290 buffer_array* buffer_array_init(void) {
2294 b = malloc(sizeof(*b));
2306 void buffer_array_reset(buffer_array *b) {
2313 /* if they are too large, reduce them */
2314 for (i = 0; i < b->used; i++) {
2315 buffer_reset(b->ptr[i]);
2324 - * free the buffer_array
2326 + * free the buffer_array
2330 void buffer_array_free(buffer_array *b) {
2335 for (i = 0; i < b->size; i++) {
2336 if (b->ptr[i]) buffer_free(b->ptr[i]);
2340 buffer *buffer_array_append_get_buffer(buffer_array *b) {
2346 b->ptr = malloc(sizeof(*b->ptr) * b->size);
2347 @@ -467,13 +536,13 @@
2353 if (b->ptr[b->used] == NULL) {
2354 b->ptr[b->used] = buffer_init();
2358 b->ptr[b->used]->used = 0;
2361 return b->ptr[b->used++];
2364 @@ -482,23 +551,23 @@
2366 if (len == 0) return NULL;
2367 if (needle == NULL) return NULL;
2370 if (b->used < len) return NULL;
2373 for(i = 0; i < b->used - len; i++) {
2374 if (0 == memcmp(b->ptr + i, needle, len)) {
2383 buffer *buffer_init_string(const char *str) {
2384 buffer *b = buffer_init();
2387 buffer_copy_string(b, str);
2397 - * check if two buffer contain the same data
2399 + * check if two buffers contain the same data
2401 * HISTORY: this function was pretty much optimized, but didn't handled
2402 * alignment properly.
2404 @@ -517,105 +586,105 @@
2405 if (a->used != b->used) return 0;
2406 if (a->used == 0) return 1;
2408 - return (0 == strcmp(a->ptr, b->ptr));
2409 + return (0 == strncmp(a->ptr, b->ptr, a->used - 1));
2412 int buffer_is_equal_string(buffer *a, const char *s, size_t b_len) {
2420 return buffer_is_equal(a, &b);
2423 /* simple-assumption:
2425 - * most parts are equal and doing a case conversion needs time
2428 + * most parts are equal and doing a case conversion takes time
2431 int buffer_caseless_compare(const char *a, size_t a_len, const char *b, size_t b_len) {
2432 size_t ndx = 0, max_ndx;
2434 size_t mask = sizeof(*al) - 1;
2440 - /* is the alignment correct ? */
2442 + /* is the alignment correct? */
2443 if ( ((size_t)al & mask) == 0 &&
2444 ((size_t)bl & mask) == 0 ) {
2447 max_ndx = ((a_len < b_len) ? a_len : b_len) & ~mask;
2450 for (; ndx < max_ndx; ndx += sizeof(*al)) {
2451 if (*al != *bl) break;
2465 max_ndx = ((a_len < b_len) ? a_len : b_len);
2468 for (; ndx < max_ndx; ndx++) {
2469 char a1 = *a++, b1 = *b++;
2473 if ((a1 >= 'A' && a1 <= 'Z') && (b1 >= 'a' && b1 <= 'z'))
2475 else if ((a1 >= 'a' && a1 <= 'z') && (b1 >= 'A' && b1 <= 'Z'))
2477 if ((a1 - b1) != 0) return (a1 - b1);
2489 * check if the rightmost bytes of the string are equal.
2496 int buffer_is_equal_right_len(buffer *b1, buffer *b2, size_t len) {
2497 /* no, len -> equal */
2498 if (len == 0) return 1;
2501 /* len > 0, but empty buffers -> not equal */
2502 if (b1->used == 0 || b2->used == 0) return 0;
2505 /* buffers too small -> not equal */
2506 - if (b1->used - 1 < len || b1->used - 1 < len) return 0;
2508 - if (0 == strncmp(b1->ptr + b1->used - 1 - len,
2509 + if (b1->used - 1 < len || b2->used - 1 < len) return 0;
2511 + if (0 == strncmp(b1->ptr + b1->used - 1 - len,
2512 b2->ptr + b2->used - 1 - len, len)) {
2520 int buffer_copy_string_hex(buffer *b, const char *in, size_t in_len) {
2525 if (in_len * 2 < in_len) return -1;
2528 buffer_prepare_copy(b, in_len * 2 + 1);
2531 for (i = 0; i < in_len; i++) {
2532 b->ptr[b->used++] = hex_chars[(in[i] >> 4) & 0x0F];
2533 b->ptr[b->used++] = hex_chars[in[i] & 0x0F];
2535 b->ptr[b->used++] = '\0';
2542 0 1 2 3 4 5 6 7 8 9 A B C D E F
2544 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */
2545 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
2546 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
2547 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, /* 20 - 2F space " # $ % & ' + , / */
2548 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 30 - 3F : ; = ? @ < > */
2549 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 - 4F */
2551 0 1 2 3 4 5 6 7 8 9 A B C D E F
2553 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */
2554 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
2555 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
2556 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, /* 20 - 2F space " # $ % & ' + , / */
2557 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 30 - 3F : ; = ? @ < > */
2558 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 - 4F */
2560 0 1 2 3 4 5 6 7 8 9 A B C D E F
2562 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */
2563 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
2564 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
2565 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 20 - 2F & */
2566 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, /* 30 - 3F < > */
2567 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 - 4F */
2569 0 1 2 3 4 5 6 7 8 9 A B C D E F
2571 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */
2572 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
2573 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
2574 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 20 - 2F & */
2575 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, /* 30 - 3F < > */
2576 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 - 4F */
2577 @@ -712,12 +781,12 @@
2578 0 1 2 3 4 5 6 7 8 9 A B C D E F
2580 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */
2581 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
2582 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */
2583 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 30 - 3F */
2584 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */
2585 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 50 - 5F */
2586 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */
2587 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
2588 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */
2589 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 30 - 3F */
2590 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */
2591 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 50 - 5F */
2592 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */
2593 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 70 - 7F */
2594 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 80 - 8F */
2595 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 90 - 9F */
2596 @@ -734,13 +803,12 @@
2597 unsigned char *ds, *d;
2599 const char *map = NULL;
2602 if (!s || !b) return -1;
2604 - if (b->ptr[b->used - 1] != '\0') {
2608 + if (b->used == 0) return -1;
2610 + if (b->ptr[b->used - 1] != '\0') return -1;
2612 if (s_len == 0) return 0;
2615 @@ -760,12 +828,12 @@
2616 map = encoded_chars_hex;
2618 case ENCODING_UNSET:
2620 + return buffer_append_string_len(b, s, s_len);
2623 assert(map != NULL);
2625 - /* count to-be-encoded-characters */
2627 + /* count to-be-encoded characters */
2628 for (ds = (unsigned char *)s, d_len = 0, ndx = 0; ndx < s_len; ds++, ndx++) {
2637 buffer_prepare_append(b, d_len);
2640 for (ds = (unsigned char *)s, d = (unsigned char *)b->ptr + b->used - 1, d_len = 0, ndx = 0; ndx < s_len; ds++, ndx++) {
2643 @@ -820,16 +888,16 @@
2647 - /* terminate buffer and calculate new length */
2648 + /* terminate buffer and calculate new length */
2649 b->ptr[b->used + d_len - 1] = '\0';
2658 -/* decodes url-special-chars inplace.
2659 +/* decodes url-special chars in-place.
2660 * replaces non-printable characters with '_'
2663 @@ -854,10 +922,10 @@
2664 low = hex2int(*(src + 2));
2666 high = (high << 4) | low;
2668 - /* map control-characters out */
2670 + /* map out control characters */
2671 if (high < 32 || high == 127) high = '_';
2678 * /abc/./xyz gets /abc/xyz
2679 * /abc//xyz gets /abc/xyz
2681 - * NOTE: src and dest can point to the same buffer, in which case,
2682 + * NOTE: src and dest can point to the same buffer, in which case
2683 * the operation is performed in-place.
2686 @@ -979,7 +1047,7 @@
2688 int light_isxdigit(int c) {
2689 if (light_isdigit(c)) return 1;
2693 return (c >= 'a' && c <= 'f');
2695 @@ -993,31 +1061,56 @@
2696 return light_isdigit(c) || light_isalpha(c);
2699 +#undef BUFFER_CTYPE_FUNC
2700 +#define BUFFER_CTYPE_FUNC(type) \
2701 + int buffer_is##type(buffer *b) { \
2703 + if (b->used < 2) return 0; \
2705 + len = b->used - 1; \
2706 + /* c-string only */ \
2707 + if (b->ptr[len] != '\0') { \
2710 + /* check on the whole string */ \
2711 + for (i = 0; i < len; i ++) { \
2712 + if (!light_is##type(b->ptr[i])) { \
2719 +BUFFER_CTYPE_FUNC(digit)
2720 +BUFFER_CTYPE_FUNC(xdigit)
2721 +BUFFER_CTYPE_FUNC(alpha)
2722 +BUFFER_CTYPE_FUNC(alnum)
2724 int buffer_to_lower(buffer *b) {
2728 if (b->used == 0) return 0;
2731 for (c = b->ptr; *c; c++) {
2732 if (*c >= 'A' && *c <= 'Z') {
2742 int buffer_to_upper(buffer *b) {
2746 if (b->used == 0) return 0;
2749 for (c = b->ptr; *c; c++) {
2750 if (*c >= 'a' && *c <= 'z') {
2758 --- ../lighttpd-1.4.11/src/buffer.h 2006-01-13 00:00:45.000000000 +0200
2759 +++ lighttpd-1.4.12/src/buffer.h 2006-07-18 13:03:40.000000000 +0300
2770 +typedef void (*buffer_ptr_free_t)(void *p);
2776 + buffer_ptr_free_t free;
2790 - size_t offset; /* input-pointer */
2792 - size_t used; /* output-pointer */
2794 + size_t offset; /* input pointer */
2796 + size_t used; /* output pointer */
2800 +buffer_ptr *buffer_ptr_init(buffer_ptr_free_t freer);
2801 +void buffer_ptr_free(buffer_ptr *b);
2802 +void buffer_ptr_clear(buffer_ptr *b);
2803 +void buffer_ptr_append(buffer_ptr *b, void *item);
2804 +void *buffer_ptr_pop(buffer_ptr *b);
2805 +void *buffer_ptr_top(buffer_ptr *b);
2807 buffer_array* buffer_array_init(void);
2808 void buffer_array_free(buffer_array *b);
2809 void buffer_array_reset(buffer_array *b);
2811 buffer* buffer_init_string(const char *str);
2812 void buffer_free(buffer *b);
2813 void buffer_reset(buffer *b);
2816 int buffer_prepare_copy(buffer *b, size_t size);
2817 int buffer_prepare_append(buffer *b, size_t size);
2823 - ENCODING_REL_URI, /* for coding a rel-uri (/with space/and%percent) nicely as part of a href */
2824 - ENCODING_REL_URI_PART, /* same as ENC_REL_URL plus coding / too as %2F */
2825 - ENCODING_HTML, /* & becomes & and so on */
2826 + ENCODING_REL_URI, /* for coding a rel-uri (/with space/and%percent) nicely as part of an href */
2827 + ENCODING_REL_URI_PART, /* same as ENC_REL_URL plus encoding "/" as "%2F" */
2828 + ENCODING_HTML, /* "&" becomes "&" and so on */
2829 ENCODING_MINIMAL_XML, /* minimal encoding for xml */
2830 ENCODING_HEX /* encode string as hex */
2831 } buffer_encoding_t;
2832 @@ -111,20 +127,23 @@
2833 int light_isalpha(int c);
2834 int light_isalnum(int c);
2836 +#define BUFFER_CTYPE_FUNC(type) int buffer_is##type(buffer *b);
2837 +BUFFER_CTYPE_FUNC(digit)
2838 +BUFFER_CTYPE_FUNC(xdigit)
2839 +BUFFER_CTYPE_FUNC(alpha)
2840 +BUFFER_CTYPE_FUNC(alnum)
2842 +#define BUF_STR(x) x->ptr
2843 #define BUFFER_APPEND_STRING_CONST(x, y) \
2844 buffer_append_string_len(x, y, sizeof(y) - 1)
2846 #define BUFFER_COPY_STRING_CONST(x, y) \
2847 buffer_copy_string_len(x, y, sizeof(y) - 1)
2849 -#define BUFFER_APPEND_SLASH(x) \
2850 - if (x->used > 1 && x->ptr[x->used - 2] != '/') { BUFFER_APPEND_STRING_CONST(x, "/"); }
2852 #define CONST_STR_LEN(x) x, x ? sizeof(x) - 1 : 0
2853 -#define CONST_BUF_LEN(x) x->ptr, x->used ? x->used - 1 : 0
2854 +#define CONST_BUF_LEN(x) BUF_STR(x), x->used ? x->used - 1 : 0
2857 -#define SEGFAULT() do { fprintf(stderr, "%s.%d: aborted\n", __FILE__, __LINE__); abort(); } while(0)
2859 #define UNUSED(x) ( (void)(x) )
2862 --- ../lighttpd-1.4.11/src/chunk.c 2005-11-18 15:18:19.000000000 +0200
2863 +++ lighttpd-1.4.12/src/chunk.c 2006-07-18 13:03:40.000000000 +0300
2866 * the network chunk-API
2873 #include <sys/types.h>
2874 #include <sys/stat.h>
2875 -#include <sys/mman.h>
2879 -#include <unistd.h>
2887 +#include "sys-mmap.h"
2888 +#include "sys-files.h"
2890 chunkqueue *chunkqueue_init(void) {
2894 cq = calloc(1, sizeof(*cq));
2907 static chunk *chunk_init(void) {
2911 c = calloc(1, sizeof(*c));
2914 c->mem = buffer_init();
2915 c->file.name = buffer_init();
2917 c->file.mmap.start = MAP_FAILED;
2924 static void chunk_free(chunk *c) {
2928 buffer_free(c->mem);
2929 buffer_free(c->file.name);
2933 static void chunk_reset(chunk *c) {
2937 buffer_reset(c->mem);
2939 if (c->file.is_temp && !buffer_is_empty(c->file.name)) {
2940 unlink(c->file.name->ptr);
2944 buffer_reset(c->file.name);
2946 if (c->file.fd != -1) {
2949 void chunkqueue_free(chunkqueue *cq) {
2956 for (c = cq->first; c; ) {
2963 for (c = cq->unused; c; ) {
2973 static chunk *chunkqueue_get_unused_chunk(chunkqueue *cq) {
2976 - /* check if we have a unused chunk */
2978 + /* check if we have an unused chunk */
2982 @@ -109,18 +110,18 @@
2984 cq->unused_chunks--;
2991 static int chunkqueue_prepend_chunk(chunkqueue *cq, chunk *c) {
2992 c->next = cq->first;
2996 if (cq->last == NULL) {
3004 @@ -129,19 +130,19 @@
3010 if (cq->first == NULL) {
3018 void chunkqueue_reset(chunkqueue *cq) {
3020 /* move everything to the unused queue */
3022 - /* mark all read written */
3024 + /* mark all read written */
3025 for (c = cq->first; c; c = c->next) {
3030 c->offset = c->file.length;
3037 @@ -162,93 +163,93 @@
3039 int chunkqueue_append_file(chunkqueue *cq, buffer *fn, off_t offset, off_t len) {
3043 if (len == 0) return 0;
3046 c = chunkqueue_get_unused_chunk(cq);
3049 c->type = FILE_CHUNK;
3052 buffer_copy_string_buffer(c->file.name, fn);
3053 c->file.start = offset;
3054 c->file.length = len;
3058 chunkqueue_append_chunk(cq, c);
3064 int chunkqueue_append_buffer(chunkqueue *cq, buffer *mem) {
3068 if (mem->used == 0) return 0;
3071 c = chunkqueue_get_unused_chunk(cq);
3072 c->type = MEM_CHUNK;
3074 buffer_copy_string_buffer(c->mem, mem);
3077 chunkqueue_append_chunk(cq, c);
3083 int chunkqueue_prepend_buffer(chunkqueue *cq, buffer *mem) {
3087 if (mem->used == 0) return 0;
3090 c = chunkqueue_get_unused_chunk(cq);
3091 c->type = MEM_CHUNK;
3093 buffer_copy_string_buffer(c->mem, mem);
3096 chunkqueue_prepend_chunk(cq, c);
3102 int chunkqueue_append_mem(chunkqueue *cq, const char * mem, size_t len) {
3106 if (len == 0) return 0;
3109 c = chunkqueue_get_unused_chunk(cq);
3110 c->type = MEM_CHUNK;
3112 buffer_copy_string_len(c->mem, mem, len - 1);
3115 chunkqueue_append_chunk(cq, c);
3121 buffer * chunkqueue_get_prepend_buffer(chunkqueue *cq) {
3125 c = chunkqueue_get_unused_chunk(cq);
3128 c->type = MEM_CHUNK;
3130 buffer_reset(c->mem);
3133 chunkqueue_prepend_chunk(cq, c);
3139 buffer *chunkqueue_get_append_buffer(chunkqueue *cq) {
3143 c = chunkqueue_get_unused_chunk(cq);
3146 c->type = MEM_CHUNK;
3148 buffer_reset(c->mem);
3151 chunkqueue_append_chunk(cq, c);
3158 chunk *chunkqueue_get_append_tempfile(chunkqueue *cq) {
3160 buffer *template = buffer_init_string("/var/tmp/lighttpd-upload-XXXXXX");
3163 c = chunkqueue_get_unused_chunk(cq);
3165 c->type = FILE_CHUNK;
3166 @@ -273,12 +274,12 @@
3169 /* we have several tempdirs, only if all of them fail we jump out */
3172 for (i = 0; i < cq->tempdirs->used; i++) {
3173 data_string *ds = (data_string *)cq->tempdirs->data[i];
3175 buffer_copy_string_buffer(template, ds->value);
3176 - BUFFER_APPEND_SLASH(template);
3177 + PATHNAME_APPEND_SLASH(template);
3178 BUFFER_APPEND_STRING_CONST(template, "lighttpd-upload-XXXXXX");
3180 if (-1 != (c->file.fd = mkstemp(template->ptr))) {
3182 chunkqueue_append_chunk(cq, c);
3184 buffer_free(template);
3191 off_t chunkqueue_length(chunkqueue *cq) {
3196 for (c = cq->first; c; c = c->next) {
3199 @@ -321,14 +322,14 @@
3208 off_t chunkqueue_written(chunkqueue *cq) {
3213 for (c = cq->first; c; c = c->next) {
3225 @@ -355,12 +356,13 @@
3229 + if (c->mem->used == 0) is_finished = 1;
3230 if (c->offset == (off_t)c->mem->used - 1) is_finished = 1;
3233 - if (c->offset == c->file.length) is_finished = 1;
3234 + if (c->offset == c->file.length) is_finished = 1;
3241 @@ -383,3 +385,50 @@
3246 +void chunkqueue_print(chunkqueue *cq) {
3249 + for (c = cq->first; c; c = c->next) {
3250 + fprintf(stderr, "(mem) %s", c->mem->ptr + c->offset);
3252 + fprintf(stderr, "\r\n");
3257 + * remove the last chunk if it is empty
3260 +void chunkqueue_remove_empty_last_chunk(chunkqueue *cq) {
3262 + if (!cq->last) return;
3263 + if (!cq->first) return;
3265 + if (cq->first == cq->last) {
3268 + if (c->type != MEM_CHUNK) return;
3269 + if (c->mem->used == 0) {
3271 + cq->first = cq->last = NULL;
3276 + for (c = cq->first; c->next; c = c->next) {
3277 + if (c->type != MEM_CHUNK) continue;
3278 + if (c->mem->used != 0) continue;
3280 + if (c->next == cq->last) {
3283 + chunk_free(c->next);
3292 --- ../lighttpd-1.4.11/src/chunk.h 2005-11-01 09:32:21.000000000 +0200
3293 +++ lighttpd-1.4.12/src/chunk.h 2006-07-18 13:03:40.000000000 +0300
3296 typedef struct chunk {
3297 enum { UNUSED_CHUNK, MEM_CHUNK, FILE_CHUNK } type;
3300 buffer *mem; /* either the storage of the mem-chunk or the read-ahead buffer */
3304 off_t length; /* octets to send from the starting offset */
3309 char *start; /* the start pointer of the mmap'ed area */
3310 size_t length; /* size of the mmap'ed area */
3311 - off_t offset; /* start is <n> octet away from the start of the file */
3312 + off_t offset; /* start is <n> octets away from the start of the file */
3315 - int is_temp; /* file is temporary and will be deleted if on cleanup */
3316 + int is_temp; /* file is temporary and will be deleted on cleanup */
3319 - off_t offset; /* octets sent from this chunk
3320 - the size of the chunk is either
3322 + off_t offset; /* octets sent from this chunk
3323 + the size of the chunk is either
3324 - mem-chunk: mem->used - 1
3325 - file-chunk: file.length
3338 size_t unused_chunks;
3341 buffer * chunkqueue_get_append_buffer(chunkqueue *c);
3342 buffer * chunkqueue_get_prepend_buffer(chunkqueue *c);
3343 chunk * chunkqueue_get_append_tempfile(chunkqueue *cq);
3344 +void chunkqueue_remove_empty_last_chunk(chunkqueue *cq);
3346 int chunkqueue_remove_finished_chunks(chunkqueue *cq);
3350 int chunkqueue_is_empty(chunkqueue *c);
3352 +void chunkqueue_print(chunkqueue *cq);
3355 --- ../lighttpd-1.4.11/src/configfile-glue.c 2006-03-03 20:14:56.000000000 +0200
3356 +++ lighttpd-1.4.12/src/configfile-glue.c 2006-07-16 00:26:03.000000000 +0300
3364 * are the external interface of lighttpd. The functions
3365 * are used by the server itself and the plugins.
3367 - * The main-goal is to have a small library in the end
3368 - * which is linked against both and which will define
3369 + * The main-goal is to have a small library in the end
3370 + * which is linked against both and which will define
3371 * the interface itself in the end.
3378 int config_insert_values_internal(server *srv, array *ca, const config_values_t cv[]) {
3383 for (i = 0; cv[i].key; i++) {
3386 if (NULL == (du = array_get_element(ca, cv[i].key))) {
3394 switch (cv[i].type) {
3395 case T_CONFIG_ARRAY:
3396 if (du->type == TYPE_ARRAY) {
3398 data_array *da = (data_array *)du;
3401 for (j = 0; j < da->value->used; j++) {
3402 if (da->value->data[j]->type == TYPE_STRING) {
3403 data_string *ds = data_string_init();
3406 buffer_copy_string_buffer(ds->value, ((data_string *)(da->value->data[j]))->value);
3407 if (!da->is_index_key) {
3408 /* the id's were generated automaticly, as we copy now we might have to renumber them
3409 - * this is used to prepend server.modules by mod_indexfiles as it has to be loaded
3410 + * this is used to prepend server.modules by mod_indexfiles as it has to be loaded
3411 * before mod_fastcgi and friends */
3412 buffer_copy_string_buffer(ds->key, ((data_string *)(da->value->data[j]))->key);
3416 array_insert_unique(cv[i].destination, (data_unset *)ds);
3418 - log_error_write(srv, __FILE__, __LINE__, "sssd",
3419 - "the key of and array can only be a string or a integer, variable:",
3420 - cv[i].key, "type:", da->value->data[j]->type);
3422 + log_error_write(srv, __FILE__, __LINE__, "sssd",
3423 + "the key of and array can only be a string or a integer, variable:",
3424 + cv[i].key, "type:", da->value->data[j]->type);
3430 log_error_write(srv, __FILE__, __LINE__, "sss", "unexpected type for key: ", cv[i].key, "array of strings");
3436 case T_CONFIG_STRING:
3437 if (du->type == TYPE_STRING) {
3438 data_string *ds = (data_string *)du;
3441 buffer_copy_string_buffer(cv[i].destination, ds->value);
3442 + } else if (du->type == TYPE_INTEGER) {
3443 + data_integer *di = (data_integer *)du;
3445 + buffer_copy_long(cv[i].destination, di->value);
3447 log_error_write(srv, __FILE__, __LINE__, "ssss", "unexpected type for key: ", cv[i].key, "(string)", "\"...\"");
3455 case TYPE_INTEGER: {
3456 data_integer *di = (data_integer *)du;
3459 *((unsigned short *)(cv[i].destination)) = di->value;
3463 data_string *ds = (data_string *)du;
3466 + if (buffer_isdigit(ds->value)) {
3467 + *((unsigned short *)(cv[i].destination)) = strtol(ds->value->ptr, NULL, 10);
3471 log_error_write(srv, __FILE__, __LINE__, "ssb", "get a string but expected a short:", cv[i].key, ds->value);
3477 @@ -100,19 +110,19 @@
3478 case T_CONFIG_BOOLEAN:
3479 if (du->type == TYPE_STRING) {
3480 data_string *ds = (data_string *)du;
3483 if (buffer_is_equal_string(ds->value, CONST_STR_LEN("enable"))) {
3484 *((unsigned short *)(cv[i].destination)) = 1;
3485 } else if (buffer_is_equal_string(ds->value, CONST_STR_LEN("disable"))) {
3486 *((unsigned short *)(cv[i].destination)) = 0;
3488 log_error_write(srv, __FILE__, __LINE__, "ssbs", "ERROR: unexpected value for key:", cv[i].key, ds->value, "(enable|disable)");
3494 log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: unexpected type for key:", cv[i].key, "(string)", "\"(enable|disable)\"");
3502 case T_CONFIG_DEPRECATED:
3503 log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: found deprecated key:", cv[i].key, "-", (char *)(cv[i].destination));
3506 srv->config_deprecated = 1;
3512 @@ -133,25 +143,25 @@
3513 int config_insert_values_global(server *srv, array *ca, const config_values_t cv[]) {
3518 for (i = 0; cv[i].key; i++) {
3519 data_string *touched;
3522 if (NULL == (du = array_get_element(ca, cv[i].key))) {
3531 touched = data_string_init();
3534 buffer_copy_string(touched->value, "");
3535 buffer_copy_string_buffer(touched->key, du->key);
3538 array_insert_unique(srv->config_touched, (data_unset *)touched);
3542 return config_insert_values_internal(srv, ca, cv);
3545 @@ -191,25 +201,25 @@
3548 /* pass the rules */
3552 case COMP_HTTP_HOST: {
3553 char *ck_colon = NULL, *val_colon = NULL;
3556 if (!buffer_is_empty(con->uri.authority)) {
3561 * append server-port to the HTTP_POST if necessary
3565 l = con->uri.authority;
3569 case CONFIG_COND_NE:
3570 case CONFIG_COND_EQ:
3571 ck_colon = strchr(dc->string->ptr, ':');
3572 val_colon = strchr(l->ptr, ':');
3575 if (ck_colon == val_colon) {
3576 /* nothing to do with it */
3578 @@ -230,21 +240,21 @@
3583 + l = srv->empty_string;
3587 case COMP_HTTP_REMOTEIP: {
3589 - /* handle remoteip limitations
3591 + /* handle remoteip limitations
3593 * "10.0.0.1" is provided for all comparisions
3596 * only for == and != we support
3603 if ((dc->cond == CONFIG_COND_EQ ||
3604 dc->cond == CONFIG_COND_NE) &&
3605 (con->dst_addr.plain.sa_family == AF_INET) &&
3606 @@ -253,41 +263,48 @@
3609 struct in_addr val_inp;
3612 + if (con->conf.log_condition_handling) {
3613 + l = srv->empty_string;
3615 + log_error_write(srv, __FILE__, __LINE__, "bsbsb", dc->comp_key,
3616 + "(", l, ") compare to", dc->string);
3619 if (*(nm_slash+1) == '\0') {
3620 log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: no number after / ", dc->string);
3623 return COND_RESULT_FALSE;
3627 nm_bits = strtol(nm_slash + 1, &err, 10);
3631 log_error_write(srv, __FILE__, __LINE__, "sbs", "ERROR: non-digit found in netmask:", dc->string, *err);
3634 return COND_RESULT_FALSE;
3638 /* take IP convert to the native */
3639 buffer_copy_string_len(srv->cond_check_buf, dc->string->ptr, nm_slash - dc->string->ptr);
3642 if (INADDR_NONE == (val_inp.s_addr = inet_addr(srv->cond_check_buf->ptr))) {
3643 log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: ip addr is invalid:", srv->cond_check_buf);
3646 return COND_RESULT_FALSE;
3650 if (0 == inet_aton(srv->cond_check_buf->ptr, &val_inp)) {
3651 log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: ip addr is invalid:", srv->cond_check_buf);
3654 return COND_RESULT_FALSE;
3660 nm = htonl(~((1 << (32 - nm_bits)) - 1));
3663 if ((val_inp.s_addr & nm) == (con->dst_addr.ipv4.sin_addr.s_addr & nm)) {
3664 return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_TRUE : COND_RESULT_FALSE;
3668 case COMP_HTTP_REFERER: {
3672 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Referer"))) {
3677 return COND_RESULT_FALSE;
3682 if (con->conf.log_condition_handling) {
3683 log_error_write(srv, __FILE__, __LINE__, "bsbs", dc->comp_key,
3684 @@ -346,10 +363,10 @@
3686 return COND_RESULT_FALSE;
3690 if (con->conf.log_condition_handling) {
3691 log_error_write(srv, __FILE__, __LINE__, "bsbsb", dc->comp_key,
3692 - "(", l, ") compare to ", dc->string);
3693 + "(", l, ") compare to", dc->string);
3696 case CONFIG_COND_NE:
3697 @@ -365,13 +382,13 @@
3698 case CONFIG_COND_MATCH: {
3699 cond_cache_t *cache = &con->cond_cache[dc->context_ndx];
3704 #define elementsof(x) (sizeof(x) / sizeof(x[0]))
3706 n = pcre_exec(dc->regex, dc->regex_study, l->ptr, l->used - 1, 0, 0,
3707 cache->matches, elementsof(cache->matches));
3710 cache->patterncount = n;
3712 cache->comp_value = l;
3719 return COND_RESULT_FALSE;
3723 cond_cache_t *caches = con->cond_cache;
3725 if (COND_RESULT_UNSET == caches[dc->context_ndx].result) {
3726 + if (con->conf.log_condition_handling) {
3727 + log_error_write(srv, __FILE__, __LINE__, "sds", "=== start of", dc->context_ndx, "condition block ===");
3729 if (COND_RESULT_TRUE == (caches[dc->context_ndx].result = config_check_cond_nocache(srv, con, dc))) {
3732 @@ -409,11 +429,11 @@
3734 if (con->conf.log_condition_handling) {
3735 log_error_write(srv, __FILE__, __LINE__, "dss", dc->context_ndx,
3736 - "(uncached) result:",
3738 caches[dc->context_ndx].result == COND_RESULT_TRUE ? "true" : "false");
3741 - if (con->conf.log_condition_handling) {
3742 + if (con->conf.log_condition_cache_handling) {
3743 log_error_write(srv, __FILE__, __LINE__, "dss", dc->context_ndx,
3745 caches[dc->context_ndx].result == COND_RESULT_TRUE ? "true" : "false");
3749 int config_check_cond(server *srv, connection *con, data_config *dc) {
3750 - if (con->conf.log_condition_handling) {
3751 - log_error_write(srv, __FILE__, __LINE__, "s", "=== start of condition block ===");
3753 return (config_check_cond_cached(srv, con, dc) == COND_RESULT_TRUE);
3756 @@ -443,3 +460,85 @@
3760 +/* return <0 on error
3761 + * return 0-x if matched (and replaced)
3763 +int config_exec_pcre_keyvalue_buffer(connection *con, pcre_keyvalue_buffer *kvb, data_config *context, buffer *match_buf, buffer *result)
3767 + pcre_extra *extra;
3768 + const char *pattern;
3769 + size_t pattern_len;
3772 + pcre_keyvalue *kv;
3776 + for (i = 0; i < kvb->used; i++) {
3780 + extra = kv->key_extra;
3781 + pattern = kv->value->ptr;
3782 + pattern_len = kv->value->used - 1;
3784 + if ((n = pcre_exec(match, extra, match_buf->ptr, match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) {
3785 + if (n != PCRE_ERROR_NOMATCH) {
3789 + const char **list;
3790 + size_t start, end;
3794 + pcre_get_substring_list(match_buf->ptr, ovec, n, &list);
3796 + /* search for $[0-9] */
3798 + buffer_reset(result);
3800 + start = 0; end = pattern_len;
3801 + for (k = 0; k < pattern_len; k++) {
3802 + if ((pattern[k] == '$' || pattern[k] == '%') &&
3803 + isdigit((unsigned char)pattern[k + 1])) {
3806 + size_t num = pattern[k + 1] - '0';
3810 + buffer_append_string_len(result, pattern + start, end - start);
3812 + if (pattern[k] == '$') {
3813 + /* n is always > 0 */
3814 + if (num < (size_t)n) {
3815 + buffer_append_string(result, list[num]);
3818 + config_append_cond_match_buffer(con, context, result, num);
3826 + buffer_append_string_len(result, pattern + start, pattern_len - start);
3834 + return PCRE_ERROR_NOMATCH;
3842 --- ../lighttpd-1.4.11/src/configfile.c 2006-02-15 14:26:42.000000000 +0200
3843 +++ lighttpd-1.4.12/src/configfile.c 2006-07-18 13:03:40.000000000 +0300
3848 -#include <unistd.h>
3857 -#include "license.h"
3860 #include "configparser.h"
3861 #include "configfile.h"
3862 #include "proc_open.h"
3864 +#include "sys-files.h"
3865 +#include "sys-process.h"
3869 +#define PATH_MAX 64
3872 static int config_insert(server *srv) {
3875 buffer *stat_cache_string;
3877 - config_values_t cv[] = {
3879 + config_values_t cv[] = {
3880 { "server.bind", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 0 */
3881 { "server.errorlog", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 1 */
3882 { "server.errorfile-prefix", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 2 */
3884 { "server.tag", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 7 */
3885 { "server.use-ipv6", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 8 */
3886 { "server.modules", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_SERVER }, /* 9 */
3889 { "server.event-handler", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 10 */
3890 { "server.pid-file", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 11 */
3891 { "server.max-request-size", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 12 */
3893 { "server.max-keep-alive-requests", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 17 */
3894 { "server.name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 18 */
3895 { "server.max-keep-alive-idle", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 19 */
3898 { "server.max-read-idle", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 20 */
3899 { "server.max-write-idle", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 21 */
3900 { "server.error-handler-404", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 22 */
3902 { "mimetype.use-xattr", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 27 */
3903 { "mimetype.assign", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 28 */
3904 { "ssl.pemfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 29 */
3907 { "ssl.engine", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 30 */
3910 { "debug.log-file-not-found", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 31 */
3911 { "debug.log-request-handling", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 32 */
3912 { "debug.log-response-header", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 33 */
3913 { "debug.log-request-header", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 34 */
3916 { "server.protocol-http11", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 35 */
3917 { "debug.log-request-header-on-error", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 36 */
3918 { "debug.log-state-handling", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 37 */
3919 { "ssl.ca-file", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 38 */
3922 { "server.errorlog-use-syslog", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 39 */
3923 { "server.range-requests", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 40 */
3924 { "server.stat-cache-engine", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 41 */
3926 { "server.network-backend", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 43 */
3927 { "server.upload-dirs", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 44 */
3928 { "server.core-files", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 45 */
3930 + { "debug.log-condition-cache-handling", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 46 */
3932 { "server.host", "use server.bind instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
3933 { "server.docroot", "use server.document-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
3934 { "server.virtual-root", "load mod_simple_vhost and use simple-vhost.server-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
3936 { "server.groupid", "use server.groupname instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
3937 { "server.use-keep-alive", "use server.max-keep-alive-requests = 0 instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
3938 { "server.force-lower-case-files", "use server.force-lowercase-filenames instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
3941 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
3947 cv[0].destination = srv->srvconf.bindhost;
3948 cv[1].destination = srv->srvconf.errorlog_file;
3949 @@ -102,33 +105,33 @@
3950 cv[4].destination = srv->srvconf.username;
3951 cv[5].destination = srv->srvconf.groupname;
3952 cv[6].destination = &(srv->srvconf.port);
3955 cv[9].destination = srv->srvconf.modules;
3956 cv[10].destination = srv->srvconf.event_handler;
3957 cv[11].destination = srv->srvconf.pid_file;
3960 cv[13].destination = &(srv->srvconf.max_worker);
3961 cv[23].destination = &(srv->srvconf.max_fds);
3962 cv[36].destination = &(srv->srvconf.log_request_header_on_error);
3963 cv[37].destination = &(srv->srvconf.log_state_handling);
3966 cv[39].destination = &(srv->srvconf.errorlog_use_syslog);
3969 stat_cache_string = buffer_init();
3970 cv[41].destination = stat_cache_string;
3971 cv[43].destination = srv->srvconf.network_backend;
3972 cv[44].destination = srv->srvconf.upload_tempdirs;
3973 cv[45].destination = &(srv->srvconf.enable_cores);
3976 cv[42].destination = &(srv->srvconf.max_conns);
3977 cv[12].destination = &(srv->srvconf.max_request_size);
3978 srv->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
3980 assert(srv->config_storage);
3983 for (i = 0; i < srv->config_context->used; i++) {
3987 s = calloc(1, sizeof(specific_config));
3989 s->document_root = buffer_init();
3990 @@ -154,17 +157,18 @@
3991 s->global_kbytes_per_second = 0;
3992 s->global_bytes_per_second_cnt = 0;
3993 s->global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt;
3996 cv[2].destination = s->errorfile_prefix;
3999 cv[7].destination = s->server_tag;
4000 cv[8].destination = &(s->use_ipv6);
4006 cv[14].destination = s->document_root;
4007 cv[15].destination = &(s->force_lowercase_filenames);
4008 cv[16].destination = &(s->log_condition_handling);
4009 + cv[46].destination = &(s->log_condition_cache_handling);
4010 cv[17].destination = &(s->max_keep_alive_requests);
4011 cv[18].destination = s->server_name;
4012 cv[19].destination = &(s->max_keep_alive_idle);
4013 @@ -179,23 +183,23 @@
4014 cv[28].destination = s->mimetypes;
4015 cv[29].destination = s->ssl_pemfile;
4016 cv[30].destination = &(s->is_ssl);
4019 cv[31].destination = &(s->log_file_not_found);
4020 cv[32].destination = &(s->log_request_handling);
4021 cv[33].destination = &(s->log_response_header);
4022 cv[34].destination = &(s->log_request_header);
4025 cv[35].destination = &(s->allow_http11);
4026 cv[38].destination = s->ssl_ca_file;
4027 cv[40].destination = &(s->range_requests);
4030 srv->config_storage[i] = s;
4033 if (0 != (ret = config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv))) {
4039 if (buffer_is_empty(stat_cache_string)) {
4040 srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_SIMPLE;
4041 } else if (buffer_is_equal_string(stat_cache_string, CONST_STR_LEN("simple"))) {
4042 @@ -205,22 +209,22 @@
4043 } else if (buffer_is_equal_string(stat_cache_string, CONST_STR_LEN("disable"))) {
4044 srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_NONE;
4046 - log_error_write(srv, __FILE__, __LINE__, "sb",
4047 + log_error_write(srv, __FILE__, __LINE__, "sb",
4048 "server.stat-cache-engine can be one of \"disable\", \"simple\", \"fam\", but not:", stat_cache_string);
4049 ret = HANDLER_ERROR;
4053 buffer_free(stat_cache_string);
4062 -#define PATCH(x) con->conf.x = s->x
4064 + con->conf.x = s->x
4065 int config_setup_connection(server *srv, connection *con) {
4066 specific_config *s = srv->config_storage[0];
4069 PATCH(allow_http11);
4071 PATCH(document_root);
4072 @@ -236,20 +240,21 @@
4073 PATCH(kbytes_per_second);
4074 PATCH(global_kbytes_per_second);
4075 PATCH(global_bytes_per_second_cnt);
4078 con->conf.global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt;
4079 buffer_copy_string_buffer(con->server_name, s->server_name);
4082 PATCH(log_request_header);
4083 PATCH(log_response_header);
4084 PATCH(log_request_handling);
4085 PATCH(log_condition_handling);
4086 + PATCH(log_condition_cache_handling);
4087 PATCH(log_file_not_found);
4090 PATCH(range_requests);
4091 PATCH(force_lowercase_filenames);
4098 @@ -257,22 +262,22 @@
4100 int config_patch_connection(server *srv, connection *con, comp_key_t comp) {
4104 /* skip the first, the global context */
4105 for (i = 1; i < srv->config_context->used; i++) {
4106 data_config *dc = (data_config *)srv->config_context->data[i];
4107 specific_config *s = srv->config_storage[i];
4111 if (comp != dc->comp) continue;
4114 /* condition didn't match */
4115 if (!config_check_cond(srv, con, dc)) continue;
4119 for (j = 0; j < dc->value->used; j++) {
4120 data_unset *du = dc->value->data[j];
4123 if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.document-root"))) {
4124 PATCH(document_root);
4125 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.range-requests"))) {
4126 @@ -315,11 +320,13 @@
4127 PATCH(log_response_header);
4128 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-condition-handling"))) {
4129 PATCH(log_condition_handling);
4130 + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-condition-cache-handling"))) {
4131 + PATCH(log_condition_cache_handling);
4132 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-file-not-found"))) {
4133 PATCH(log_file_not_found);
4134 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.protocol-http11"))) {
4135 PATCH(allow_http11);
4136 - } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.force-lowercase-filenames"))) {
4137 + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.force-lowercase-filenames"))) {
4138 PATCH(force_lowercase_filenames);
4139 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.kbytes-per-second"))) {
4140 PATCH(global_kbytes_per_second);
4150 @@ -336,15 +343,15 @@
4156 const buffer *source;
4172 if (0 != stream_open(&(t->s), t->file)) {
4173 - log_error_write(srv, __FILE__, __LINE__, "sbss",
4174 + log_error_write(srv, __FILE__, __LINE__, "sbss",
4175 "opening configfile ", t->file, "failed:", strerror(errno));
4176 buffer_free(t->file);
4179 t->size = t->s.size;
4188 static int config_skip_comment(tokenizer_t *t) {
4190 assert(t->input[t->offset] == '#');
4191 - for (i = 1; t->input[t->offset + i] &&
4192 + for (i = 1; t->input[t->offset + i] &&
4193 (t->input[t->offset + i] != '\n' && t->input[t->offset + i] != '\r');
4196 @@ -411,44 +418,44 @@
4197 static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *token) {
4202 for (tid = 0; tid == 0 && t->offset < t->size && t->input[t->offset] ; ) {
4203 char c = t->input[t->offset];
4204 const char *start = NULL;
4211 if (t->input[t->offset + 1] == '>') {
4215 buffer_copy_string(token, "=>");
4218 tid = TK_ARRAY_ASSIGN;
4220 - log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4221 + log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4222 "source:", t->source,
4223 - "line:", t->line, "pos:", t->line_pos,
4224 + "line:", t->line, "pos:", t->line_pos,
4225 "use => for assignments in arrays");
4228 } else if (t->in_cond) {
4229 if (t->input[t->offset + 1] == '=') {
4233 buffer_copy_string(token, "==");
4237 } else if (t->input[t->offset + 1] == '~') {
4241 buffer_copy_string(token, "=~");
4246 - log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4247 + log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4248 "source:", t->source,
4249 - "line:", t->line, "pos:", t->line_pos,
4250 + "line:", t->line, "pos:", t->line_pos,
4251 "only =~ and == are allowed in the condition");
4254 @@ -456,51 +463,51 @@
4256 } else if (t->in_key) {
4260 buffer_copy_string_len(token, t->input + t->offset, 1);
4266 - log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4267 + log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4268 "source:", t->source,
4269 - "line:", t->line, "pos:", t->line_pos,
4270 + "line:", t->line, "pos:", t->line_pos,
4271 "unexpected equal-sign: =");
4280 if (t->input[t->offset + 1] == '=') {
4284 buffer_copy_string(token, "!=");
4288 } else if (t->input[t->offset + 1] == '~') {
4292 buffer_copy_string(token, "!~");
4297 - log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4298 + log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4299 "source:", t->source,
4300 - "line:", t->line, "pos:", t->line_pos,
4301 + "line:", t->line, "pos:", t->line_pos,
4302 "only !~ and != are allowed in the condition");
4308 - log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4309 + log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4310 "source:", t->source,
4311 - "line:", t->line, "pos:", t->line_pos,
4312 + "line:", t->line, "pos:", t->line_pos,
4313 "unexpected exclamation-marks: !");
4321 @@ -546,10 +553,10 @@
4323 if (t->in_brace > 0) {
4327 buffer_copy_string(token, "(COMMA)");
4334 @@ -557,70 +564,70 @@
4335 /* search for the terminating " */
4336 start = t->input + t->offset + 1;
4337 buffer_copy_string(token, "");
4340 for (i = 1; t->input[t->offset + i]; i++) {
4341 if (t->input[t->offset + i] == '\\' &&
4342 t->input[t->offset + i + 1] == '"') {
4345 buffer_append_string_len(token, start, t->input + t->offset + i - start);
4348 start = t->input + t->offset + i + 1;
4359 if (t->input[t->offset + i] == '"') {
4363 buffer_append_string_len(token, start, t->input + t->offset + i - start);
4370 if (t->input[t->offset + i] == '\0') {
4373 - log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4375 + log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4376 "source:", t->source,
4377 - "line:", t->line, "pos:", t->line_pos,
4378 + "line:", t->line, "pos:", t->line_pos,
4379 "missing closing quote");
4387 t->line_pos += i + 1;
4399 buffer_copy_string(token, "(");
4409 buffer_copy_string(token, ")");
4420 buffer_copy_string(token, "$");
4426 @@ -637,115 +644,107 @@
4435 buffer_copy_string(token, "{");
4448 buffer_copy_string(token, "}");
4460 buffer_copy_string(token, "[");
4473 buffer_copy_string(token, "]");
4478 t->line_pos += config_skip_comment(t);
4484 - for (i = 0; t->input[t->offset + i] &&
4485 + for (i = 0; t->input[t->offset + i] &&
4486 (isalpha((unsigned char)t->input[t->offset + i])
4490 if (i && t->input[t->offset + i]) {
4491 tid = TK_SRVVARNAME;
4492 buffer_copy_string_len(token, t->input + t->offset, i);
4499 - log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4500 + log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4501 "source:", t->source,
4502 - "line:", t->line, "pos:", t->line_pos,
4503 + "line:", t->line, "pos:", t->line_pos,
4504 "invalid character in condition");
4507 } else if (isdigit((unsigned char)c)) {
4508 /* take all digits */
4509 for (i = 0; t->input[t->offset + i] && isdigit((unsigned char)t->input[t->offset + i]); i++);
4512 /* was there it least a digit ? */
4513 - if (i && t->input[t->offset + i]) {
4518 buffer_copy_string_len(token, t->input + t->offset, i);
4525 - log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4526 - "source:", t->source,
4527 - "line:", t->line, "pos:", t->line_pos,
4528 - "unexpected EOF");
4533 /* the key might consist of [-.0-9a-z] */
4534 - for (i = 0; t->input[t->offset + i] &&
4535 - (isalnum((unsigned char)t->input[t->offset + i]) ||
4536 + for (i = 0; t->input[t->offset + i] &&
4537 + (isalnum((unsigned char)t->input[t->offset + i]) ||
4538 t->input[t->offset + i] == '.' ||
4539 t->input[t->offset + i] == '_' || /* for env.* */
4540 t->input[t->offset + i] == '-'
4544 if (i && t->input[t->offset + i]) {
4545 buffer_copy_string_len(token, t->input + t->offset, i);
4547 - if (strcmp(token->ptr, "include") == 0) {
4549 + if (buffer_is_equal_string(token, CONST_STR_LEN("include"))) {
4551 - } else if (strcmp(token->ptr, "include_shell") == 0) {
4552 + } else if (buffer_is_equal_string(token, CONST_STR_LEN("include_shell"))) {
4553 tid = TK_INCLUDE_SHELL;
4554 - } else if (strcmp(token->ptr, "global") == 0) {
4555 + } else if (buffer_is_equal_string(token, CONST_STR_LEN("global"))) {
4557 - } else if (strcmp(token->ptr, "else") == 0) {
4558 + } else if (buffer_is_equal_string(token, CONST_STR_LEN("else"))) {
4569 - log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4570 + log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
4571 "source:", t->source,
4572 - "line:", t->line, "pos:", t->line_pos,
4573 + "line:", t->line, "pos:", t->line_pos,
4574 "invalid character in variable name");
4577 @@ -753,16 +752,16 @@
4586 - log_error_write(srv, __FILE__, __LINE__, "sbsdsdbdd",
4587 + log_error_write(srv, __FILE__, __LINE__, "sbsdsdbdd",
4588 "source:", t->source,
4589 "line:", t->line, "pos:", t->line_pos,
4590 token, token->used - 1, tid);
4595 } else if (t->offset < t->size) {
4596 fprintf(stderr, "%s.%d: %d, %s\n",
4597 @@ -781,10 +780,11 @@
4598 pParser = configparserAlloc( malloc );
4599 lasttoken = buffer_init();
4600 token = buffer_init();
4602 while((1 == (ret = config_tokenizer(srv, t, &token_id, token))) && context->ok) {
4603 buffer_copy_string_buffer(lasttoken, token);
4604 configparser(pParser, token_id, token, context);
4607 token = buffer_init();
4610 @@ -797,14 +797,14 @@
4613 configparserFree(pParser, free);
4617 - log_error_write(srv, __FILE__, __LINE__, "sb",
4618 + log_error_write(srv, __FILE__, __LINE__, "sb",
4619 "configfile parser failed:", lasttoken);
4620 } else if (context->ok == 0) {
4621 - log_error_write(srv, __FILE__, __LINE__, "sbsdsdsb",
4622 + log_error_write(srv, __FILE__, __LINE__, "sbsdsdsb",
4623 "source:", t->source,
4624 - "line:", t->line, "pos:", t->line_pos,
4625 + "line:", t->line, "pos:", t->line_pos,
4626 "parser failed somehow near here:", lasttoken);
4641 if (0 != stream_open(&s, filename)) {
4642 - log_error_write(srv, __FILE__, __LINE__, "sbss",
4643 + log_error_write(srv, __FILE__, __LINE__, "sbss",
4644 "opening configfile ", filename, "failed:", strerror(errno));
4648 char oldpwd[PATH_MAX];
4650 if (NULL == getcwd(oldpwd, sizeof(oldpwd))) {
4651 - log_error_write(srv, __FILE__, __LINE__, "s",
4652 + log_error_write(srv, __FILE__, __LINE__, "s",
4653 "cannot get cwd", strerror(errno));
4659 if (0 != proc_open_buffer(&proc, cmd, NULL, out, NULL)) {
4660 - log_error_write(srv, __FILE__, __LINE__, "sbss",
4661 + log_error_write(srv, __FILE__, __LINE__, "sbss",
4662 "opening", source, "failed:", strerror(errno));
4665 @@ -896,13 +896,12 @@
4666 static void context_init(server *srv, config_t *context) {
4669 - context->configs_stack = array_init();
4670 - context->configs_stack->is_weakref = 1;
4671 + context->configs_stack = buffer_ptr_init(NULL);
4672 context->basedir = buffer_init();
4675 static void context_free(config_t *context) {
4676 - array_free(context->configs_stack);
4677 + buffer_ptr_free(context->configs_stack);
4678 buffer_free(context->basedir);
4681 @@ -918,18 +917,15 @@
4682 context_init(srv, &context);
4683 context.all_configs = srv->config_context;
4692 + /* use the current dir as basedir for all other includes
4694 + pos = strrchr(fn, DIR_SEPERATOR);
4697 buffer_copy_string_len(context.basedir, fn, pos - fn + 1);
4702 dc = data_config_init();
4703 buffer_copy_string(dc->key, "global");
4706 dpid->value = getpid();
4707 buffer_copy_string(dpid->key, "var.PID");
4708 array_insert_unique(srv->config, (data_unset *)dpid);
4711 dcwd = data_string_init();
4712 buffer_prepare_copy(dcwd->value, 1024);
4713 if (NULL != getcwd(dcwd->value->ptr, dcwd->value->size - 1)) {
4720 if (NULL != (modules = (data_array *)array_get_element(srv->config, "server.modules"))) {
4722 data_array *prepends;
4723 @@ -1026,22 +1022,23 @@
4724 buffer_copy_string(modules->key, "server.modules");
4725 array_insert_unique(srv->config, (data_unset *)modules);
4730 if (0 != config_insert(srv)) {
4739 int config_set_defaults(server *srv) {
4741 specific_config *s = srv->config_storage[0];
4742 struct stat st1, st2;
4744 - struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
4747 + struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
4749 /* - poll is most reliable
4750 * - select works everywhere
4751 * - linux-* are experimental
4752 @@ -1067,20 +1064,21 @@
4754 { FDEVENT_HANDLER_UNSET, NULL }
4758 - if (buffer_is_empty(s->document_root)) {
4759 - log_error_write(srv, __FILE__, __LINE__, "s",
4760 - "a default document-root has to be set");
4766 + if (buffer_is_empty(s->document_root)) {
4767 + log_error_write(srv, __FILE__, __LINE__, "s",
4768 + "a default document-root has to be set");
4773 if (buffer_is_empty(srv->srvconf.changeroot)) {
4774 - if (-1 == stat(s->document_root->ptr, &st1)) {
4775 - log_error_write(srv, __FILE__, __LINE__, "sb",
4776 + pathname_unix2local(s->document_root);
4777 + if (-1 == stat(s->document_root->ptr, &st1)) {
4778 + log_error_write(srv, __FILE__, __LINE__, "sbs",
4779 "base-docroot doesn't exist:",
4780 - s->document_root);
4781 + s->document_root, strerror(errno));
4785 @@ -1088,18 +1086,18 @@
4786 buffer_copy_string_buffer(srv->tmp_buf, srv->srvconf.changeroot);
4787 buffer_append_string_buffer(srv->tmp_buf, s->document_root);
4789 - if (-1 == stat(srv->tmp_buf->ptr, &st1)) {
4790 - log_error_write(srv, __FILE__, __LINE__, "sb",
4791 + if (-1 == stat(srv->tmp_buf->ptr, &st1)) {
4792 + log_error_write(srv, __FILE__, __LINE__, "sb",
4793 "base-docroot doesn't exist:",
4802 - buffer_copy_string_buffer(srv->tmp_buf, s->document_root);
4804 - buffer_to_lower(srv->tmp_buf);
4805 + buffer_copy_string_buffer(srv->tmp_buf, s->document_root);
4807 + buffer_to_lower(srv->tmp_buf);
4809 if (0 == stat(srv->tmp_buf->ptr, &st1)) {
4811 @@ -1107,68 +1105,68 @@
4812 is_lower = buffer_is_equal(srv->tmp_buf, s->document_root);
4814 /* lower-case existed, check upper-case */
4815 - buffer_copy_string_buffer(srv->tmp_buf, s->document_root);
4816 + buffer_copy_string_buffer(srv->tmp_buf, s->document_root);
4818 - buffer_to_upper(srv->tmp_buf);
4819 + buffer_to_upper(srv->tmp_buf);
4821 /* we have to handle the special case that upper and lower-casing results in the same filename
4822 * as in server.document-root = "/" or "/12345/" */
4824 if (is_lower && buffer_is_equal(srv->tmp_buf, s->document_root)) {
4825 - /* lower-casing and upper-casing didn't result in
4826 - * an other filename, no need to stat(),
4827 + /* lower-casing and upper-casing didn't result in
4828 + * an other filename, no need to stat(),
4829 * just assume it is case-sensitive. */
4831 s->force_lowercase_filenames = 0;
4832 - } else if (0 == stat(srv->tmp_buf->ptr, &st2)) {
4833 + } else if (0 == stat(srv->tmp_buf->ptr, &st2)) {
4835 + /* upper case exists too, doesn't the FS handle this ? */
4837 + /* upper and lower have the same inode -> case-insensitve FS */
4839 + if (st1.st_ino == st2.st_ino) {
4840 + /* upper and lower have the same inode -> case-insensitve FS */
4842 + s->force_lowercase_filenames = 1;
4847 - /* upper case exists too, doesn't the FS handle this ? */
4849 - /* upper and lower have the same inode -> case-insensitve FS */
4851 - if (st1.st_ino == st2.st_ino) {
4852 - /* upper and lower have the same inode -> case-insensitve FS */
4854 - s->force_lowercase_filenames = 1;
4859 if (srv->srvconf.port == 0) {
4860 srv->srvconf.port = s->is_ssl ? 443 : 80;
4864 if (srv->srvconf.event_handler->used == 0) {
4865 /* choose a good default
4867 - * the event_handler list is sorted by 'goodness'
4869 + * the event_handler list is sorted by 'goodness'
4870 * taking the first available should be the best solution
4872 srv->event_handler = event_handlers[0].et;
4875 if (FDEVENT_HANDLER_UNSET == srv->event_handler) {
4876 - log_error_write(srv, __FILE__, __LINE__, "s",
4877 + log_error_write(srv, __FILE__, __LINE__, "s",
4878 "sorry, there is no event handler for this system");
4889 for (i = 0; event_handlers[i].name; i++) {
4890 if (0 == strcmp(event_handlers[i].name, srv->srvconf.event_handler->ptr)) {
4891 srv->event_handler = event_handlers[i].et;
4897 if (FDEVENT_HANDLER_UNSET == srv->event_handler) {
4898 - log_error_write(srv, __FILE__, __LINE__, "sb",
4899 - "the selected event-handler in unknown or not supported:",
4900 + log_error_write(srv, __FILE__, __LINE__, "sb",
4901 + "the selected event-handler in unknown or not supported:",
4902 srv->srvconf.event_handler );
4908 @@ -1176,19 +1174,19 @@
4910 if (buffer_is_empty(s->ssl_pemfile)) {
4911 /* PEM file is require */
4913 - log_error_write(srv, __FILE__, __LINE__, "s",
4915 + log_error_write(srv, __FILE__, __LINE__, "s",
4916 "ssl.pemfile has to be set");
4922 - log_error_write(srv, __FILE__, __LINE__, "s",
4923 + log_error_write(srv, __FILE__, __LINE__, "s",
4924 "ssl support is missing, recompile with --with-openssl");
4934 --- ../lighttpd-1.4.11/src/configfile.h 2005-08-23 17:36:12.000000000 +0300
4935 +++ lighttpd-1.4.12/src/configfile.h 2006-07-16 00:26:03.000000000 +0300
4940 - array *configs_stack; /* to parse nested block */
4941 + buffer_ptr *configs_stack; /* to parse nested block */
4942 data_config *current; /* current started with { */
4945 --- ../lighttpd-1.4.11/src/configparser.c 2006-02-01 19:51:15.000000000 +0200
4946 +++ lighttpd-1.4.12/src/configparser.c 2006-07-17 22:02:23.000000000 +0300
4948 dc->parent = ctx->current;
4949 array_insert_unique(dc->parent->childs, (data_unset *)dc);
4951 - array_insert_unique(ctx->configs_stack, (data_unset *)ctx->current);
4952 + buffer_ptr_append(ctx->configs_stack, (void *)ctx->current);
4956 static data_config *configparser_pop(config_t *ctx) {
4957 data_config *old = ctx->current;
4958 - ctx->current = (data_config *) array_pop(ctx->configs_stack);
4959 + ctx->current = (data_config *) buffer_ptr_pop(ctx->configs_stack);
4963 /* return a copied variable */
4964 static data_unset *configparser_get_variable(config_t *ctx, const buffer *key) {
4965 - if (strncmp(key->ptr, "env.", sizeof("env.") - 1) == 0) {
4968 - if (NULL != (env = getenv(key->ptr + 4))) {
4970 - ds = data_string_init();
4971 - buffer_append_string(ds->value, env);
4972 - return (data_unset *)ds;
4975 - fprintf(stderr, "Undefined env variable: %s\n", key->ptr + 4);
4986 - fprintf(stderr, "get var %s\n", key->ptr);
4987 + fprintf(stderr, "get var %s\n", key->ptr);
4989 - for (dc = ctx->current; dc; dc = dc->parent) {
4990 + for (dc = ctx->current; dc; dc = dc->parent) {
4992 - fprintf(stderr, "get var on block: %s\n", dc->key->ptr);
4993 - array_print(dc->value, 0);
4994 + fprintf(stderr, "get var on block: %s\n", dc->key->ptr);
4995 + array_print(dc->value, 0);
4997 - if (NULL != (du = array_get_element(dc->value, key->ptr))) {
4998 - return du->copy(du);
5000 + if (NULL != (du = array_get_element(dc->value, key->ptr))) {
5001 + return du->copy(du);
5003 - fprintf(stderr, "Undefined config variable: %s\n", key->ptr);
5010 /* op1 is to be eat/return by this function, op1->key is not cared
5011 @@ -124,14 +106,14 @@
5015 -#line 128 "configparser.c"
5016 +#line 110 "configparser.c"
5017 /* Next is all token values, in a form suitable for use by makeheaders.
5018 ** This section will be null unless lemon is run with the -m switch.
5022 ** These constants (all generated automatically by the parser generator)
5023 ** specify the various kinds of tokens (terminals) that the parser
5027 ** Each symbol here is a terminal symbol in the grammar.
5030 ** and nonterminals. "int" is used otherwise.
5031 ** YYNOCODE is a number of type YYCODETYPE which corresponds
5032 ** to no legal terminal or nonterminal number. This
5033 -** number is used to fill in empty slots of the hash
5034 +** number is used to fill in empty slots of the hash
5036 ** YYFALLBACK If defined, this indicates that one or more tokens
5037 ** have fall-back values which should be used if the
5039 ** and nonterminal numbers. "unsigned char" is
5040 ** used if there are fewer than 250 rules and
5041 ** states combined. "int" is used otherwise.
5042 -** configparserTOKENTYPE is the data type used for minor tokens given
5043 +** configparserTOKENTYPE is the data type used for minor tokens given
5044 ** directly to the parser from the tokenizer.
5045 ** YYMINORTYPE is the data type used for all minor tokens.
5046 ** This is typically a union of many types, one of
5048 #define configparserARG_PDECL ,config_t *ctx
5049 #define configparserARG_FETCH config_t *ctx = yypParser->ctx
5050 #define configparserARG_STORE yypParser->ctx = ctx
5051 -#define YYNSTATE 62
5053 +#define YYNSTATE 63
5055 #define YYERRORSYMBOL 26
5056 #define YYERRSYMDT yy95
5057 #define YY_NO_ACTION (YYNSTATE+YYNRULE+2)
5059 /* Next are that tables used to determine what action to take based on the
5060 ** current state and lookahead token. These tables are used to implement
5061 ** functions that take a state number and lookahead value and return an
5065 ** Suppose the action integer is N. Then the action is determined as
5068 ** If the index value yy_shift_ofst[S]+X is out of range or if the value
5069 ** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
5070 ** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
5071 -** and that yy_default[S] should be used instead.
5072 +** and that yy_default[S] should be used instead.
5074 ** The formula above is for computing the action when the lookahead is
5075 ** a terminal symbol. If the lookahead is a non-terminal (as occurs after
5076 @@ -248,67 +230,69 @@
5077 ** yy_default[] Default action for each state.
5079 static YYACTIONTYPE yy_action[] = {
5080 - /* 0 */ 2, 3, 4, 5, 13, 14, 62, 15, 7, 44,
5081 - /* 10 */ 20, 86, 16, 45, 28, 48, 40, 10, 39, 25,
5082 - /* 20 */ 22, 49, 45, 8, 15, 102, 1, 20, 28, 18,
5083 - /* 30 */ 57, 59, 19, 25, 22, 39, 19, 61, 98, 45,
5084 - /* 40 */ 20, 6, 23, 24, 26, 28, 35, 57, 59, 12,
5085 - /* 50 */ 25, 22, 28, 27, 36, 87, 29, 25, 22, 33,
5086 - /* 60 */ 15, 30, 31, 20, 28, 38, 9, 17, 37, 25,
5087 - /* 70 */ 22, 39, 42, 43, 10, 45, 11, 53, 54, 55,
5088 - /* 80 */ 56, 28, 52, 57, 59, 34, 25, 22, 28, 27,
5089 - /* 90 */ 32, 88, 41, 25, 22, 33, 28, 48, 46, 28,
5090 - /* 100 */ 48, 25, 22, 58, 25, 22, 60, 21, 19, 47,
5091 - /* 110 */ 51, 50, 25, 22, 88, 88, 93,
5092 + /* 0 */ 2, 3, 4, 5, 13, 14, 63, 15, 7, 45,
5093 + /* 10 */ 20, 88, 16, 46, 28, 49, 41, 10, 40, 25,
5094 + /* 20 */ 22, 50, 46, 8, 15, 104, 1, 20, 28, 18,
5095 + /* 30 */ 58, 60, 6, 25, 22, 40, 47, 62, 11, 46,
5096 + /* 40 */ 20, 9, 23, 24, 26, 29, 89, 58, 60, 10,
5097 + /* 50 */ 17, 38, 28, 27, 37, 19, 30, 25, 22, 34,
5098 + /* 60 */ 15, 100, 20, 20, 23, 24, 26, 12, 19, 31,
5099 + /* 70 */ 32, 40, 19, 44, 43, 46, 95, 35, 90, 89,
5100 + /* 80 */ 28, 49, 42, 58, 60, 25, 22, 59, 28, 27,
5101 + /* 90 */ 33, 48, 52, 25, 22, 34, 28, 49, 51, 28,
5102 + /* 100 */ 36, 25, 22, 61, 25, 22, 89, 28, 39, 89,
5103 + /* 110 */ 89, 89, 25, 22, 54, 55, 56, 57, 89, 28,
5104 + /* 120 */ 53, 21, 89, 89, 25, 22, 25, 22,
5106 static YYCODETYPE yy_lookahead[] = {
5107 /* 0 */ 29, 30, 31, 32, 33, 34, 0, 1, 44, 38,
5108 /* 10 */ 4, 15, 41, 16, 35, 36, 45, 46, 12, 40,
5109 /* 20 */ 41, 42, 16, 15, 1, 27, 28, 4, 35, 36,
5110 - /* 30 */ 24, 25, 5, 40, 41, 12, 5, 14, 11, 16,
5111 - /* 40 */ 4, 1, 6, 7, 8, 35, 36, 24, 25, 28,
5112 - /* 50 */ 40, 41, 35, 36, 37, 15, 39, 40, 41, 42,
5113 - /* 60 */ 1, 9, 10, 4, 35, 36, 38, 2, 3, 40,
5114 - /* 70 */ 41, 12, 28, 14, 46, 16, 13, 20, 21, 22,
5115 - /* 80 */ 23, 35, 36, 24, 25, 11, 40, 41, 35, 36,
5116 - /* 90 */ 37, 13, 13, 40, 41, 42, 35, 36, 17, 35,
5117 - /* 100 */ 36, 40, 41, 42, 40, 41, 42, 35, 5, 18,
5118 - /* 110 */ 43, 19, 40, 41, 47, 47, 13,
5119 + /* 30 */ 24, 25, 1, 40, 41, 12, 17, 14, 13, 16,
5120 + /* 40 */ 4, 38, 6, 7, 8, 9, 15, 24, 25, 46,
5121 + /* 50 */ 2, 3, 35, 36, 37, 5, 39, 40, 41, 42,
5122 + /* 60 */ 1, 11, 4, 4, 6, 7, 8, 28, 5, 9,
5123 + /* 70 */ 10, 12, 5, 14, 28, 16, 13, 11, 13, 47,
5124 + /* 80 */ 35, 36, 13, 24, 25, 40, 41, 42, 35, 36,
5125 + /* 90 */ 37, 18, 43, 40, 41, 42, 35, 36, 19, 35,
5126 + /* 100 */ 36, 40, 41, 42, 40, 41, 47, 35, 36, 47,
5127 + /* 110 */ 47, 47, 40, 41, 20, 21, 22, 23, 47, 35,
5128 + /* 120 */ 36, 35, 47, 47, 40, 41, 40, 41,
5130 #define YY_SHIFT_USE_DFLT (-5)
5131 static signed char yy_shift_ofst[] = {
5132 - /* 0 */ -5, 6, -5, -5, -5, 40, -4, 8, -3, -5,
5133 - /* 10 */ 63, -5, 23, -5, -5, -5, 65, 36, 31, 36,
5134 - /* 20 */ -5, -5, -5, -5, -5, -5, 36, 27, -5, 52,
5135 - /* 30 */ -5, 36, -5, 74, 36, 31, -5, 36, 31, 78,
5136 - /* 40 */ 79, -5, 59, -5, -5, 81, 91, 36, 31, 92,
5137 - /* 50 */ 57, 36, 103, -5, -5, -5, -5, 36, -5, 36,
5139 + /* 0 */ -5, 6, -5, -5, -5, 31, -4, 8, -3, -5,
5140 + /* 10 */ 25, -5, 23, -5, -5, -5, 48, 58, 67, 58,
5141 + /* 20 */ -5, -5, -5, -5, -5, -5, 36, 50, -5, -5,
5142 + /* 30 */ 60, -5, 58, -5, 66, 58, 67, -5, 58, 67,
5143 + /* 40 */ 65, 69, -5, 59, -5, -5, 19, 73, 58, 67,
5144 + /* 50 */ 79, 94, 58, 63, -5, -5, -5, -5, 58, -5,
5145 + /* 60 */ 58, -5, -5,
5147 #define YY_REDUCE_USE_DFLT (-37)
5148 static signed char yy_reduce_ofst[] = {
5149 - /* 0 */ -2, -29, -37, -37, -37, -36, -37, -37, 28, -37,
5150 - /* 10 */ -37, 21, -29, -37, -37, -37, -37, -7, -37, 72,
5151 + /* 0 */ -2, -29, -37, -37, -37, -36, -37, -37, 3, -37,
5152 + /* 10 */ -37, 39, -29, -37, -37, -37, -37, -7, -37, 86,
5153 /* 20 */ -37, -37, -37, -37, -37, -37, 17, -37, -37, -37,
5154 - /* 30 */ -37, 53, -37, -37, 10, -37, -37, 29, -37, -37,
5155 - /* 40 */ -37, 44, -29, -37, -37, -37, -37, -21, -37, -37,
5156 - /* 50 */ 67, 46, -37, -37, -37, -37, -37, 61, -37, 64,
5157 - /* 60 */ -37, -37,
5158 + /* 30 */ -37, -37, 53, -37, -37, 64, -37, -37, 72, -37,
5159 + /* 40 */ -37, -37, 46, -29, -37, -37, -37, -37, -21, -37,
5160 + /* 50 */ -37, 49, 84, -37, -37, -37, -37, -37, 45, -37,
5161 + /* 60 */ 61, -37, -37,
5163 static YYACTIONTYPE yy_default[] = {
5164 - /* 0 */ 64, 101, 63, 65, 66, 101, 67, 101, 101, 90,
5165 - /* 10 */ 101, 64, 101, 68, 69, 70, 101, 101, 71, 101,
5166 - /* 20 */ 73, 74, 76, 77, 78, 79, 101, 84, 75, 101,
5167 - /* 30 */ 80, 82, 81, 101, 101, 85, 83, 101, 72, 101,
5168 - /* 40 */ 101, 64, 101, 89, 91, 101, 101, 101, 98, 101,
5169 - /* 50 */ 101, 101, 101, 94, 95, 96, 97, 101, 99, 101,
5171 + /* 0 */ 65, 103, 64, 66, 67, 103, 68, 103, 103, 92,
5172 + /* 10 */ 103, 65, 103, 69, 70, 71, 103, 103, 72, 103,
5173 + /* 20 */ 74, 75, 77, 78, 79, 80, 103, 86, 76, 81,
5174 + /* 30 */ 103, 82, 84, 83, 103, 103, 87, 85, 103, 73,
5175 + /* 40 */ 103, 103, 65, 103, 91, 93, 103, 103, 103, 100,
5176 + /* 50 */ 103, 103, 103, 103, 96, 97, 98, 99, 103, 101,
5177 + /* 60 */ 103, 102, 94,
5179 #define YY_SZ_ACTTAB (sizeof(yy_action)/sizeof(yy_action[0]))
5181 /* The next table maps tokens into fallback tokens. If a construct
5182 ** like the following:
5185 ** %fallback ID X Y Z.
5187 ** appears in the grammer, then ID becomes a fallback token for X, Y,
5188 @@ -359,10 +343,10 @@
5194 ** Turn parser tracing on by giving a stream to which to write the trace
5195 ** and a prompt to preface each trace message. Tracing is turned off
5196 -** by making either argument NULL
5197 +** by making either argument NULL
5203 /* For tracing shifts, the names of all terminals and nonterminals
5204 ** are required. The following table supplies these names */
5205 -static const char *yyTokenName[] = {
5206 +static const char *yyTokenName[] = {
5207 "$", "EOL", "ASSIGN", "APPEND",
5208 "LKEY", "PLUS", "STRING", "INTEGER",
5209 "LPARAN", "RPARAN", "COMMA", "ARRAY_ASSIGN",
5210 @@ -425,27 +409,28 @@
5211 /* 15 */ "value ::= STRING",
5212 /* 16 */ "value ::= INTEGER",
5213 /* 17 */ "value ::= array",
5214 - /* 18 */ "array ::= LPARAN aelements RPARAN",
5215 - /* 19 */ "aelements ::= aelements COMMA aelement",
5216 - /* 20 */ "aelements ::= aelements COMMA",
5217 - /* 21 */ "aelements ::= aelement",
5218 - /* 22 */ "aelement ::= expression",
5219 - /* 23 */ "aelement ::= stringop ARRAY_ASSIGN expression",
5220 - /* 24 */ "eols ::= EOL",
5221 - /* 25 */ "eols ::=",
5222 - /* 26 */ "globalstart ::= GLOBAL",
5223 - /* 27 */ "global ::= globalstart LCURLY metalines RCURLY",
5224 - /* 28 */ "condlines ::= condlines eols ELSE condline",
5225 - /* 29 */ "condlines ::= condline",
5226 - /* 30 */ "condline ::= context LCURLY metalines RCURLY",
5227 - /* 31 */ "context ::= DOLLAR SRVVARNAME LBRACKET stringop RBRACKET cond expression",
5228 - /* 32 */ "cond ::= EQ",
5229 - /* 33 */ "cond ::= MATCH",
5230 - /* 34 */ "cond ::= NE",
5231 - /* 35 */ "cond ::= NOMATCH",
5232 - /* 36 */ "stringop ::= expression",
5233 - /* 37 */ "include ::= INCLUDE stringop",
5234 - /* 38 */ "include_shell ::= INCLUDE_SHELL stringop",
5235 + /* 18 */ "array ::= LPARAN RPARAN",
5236 + /* 19 */ "array ::= LPARAN aelements RPARAN",
5237 + /* 20 */ "aelements ::= aelements COMMA aelement",
5238 + /* 21 */ "aelements ::= aelements COMMA",
5239 + /* 22 */ "aelements ::= aelement",
5240 + /* 23 */ "aelement ::= expression",
5241 + /* 24 */ "aelement ::= stringop ARRAY_ASSIGN expression",
5242 + /* 25 */ "eols ::= EOL",
5243 + /* 26 */ "eols ::=",
5244 + /* 27 */ "globalstart ::= GLOBAL",
5245 + /* 28 */ "global ::= globalstart LCURLY metalines RCURLY",
5246 + /* 29 */ "condlines ::= condlines eols ELSE condline",
5247 + /* 30 */ "condlines ::= condline",
5248 + /* 31 */ "condline ::= context LCURLY metalines RCURLY",
5249 + /* 32 */ "context ::= DOLLAR SRVVARNAME LBRACKET stringop RBRACKET cond expression",
5250 + /* 33 */ "cond ::= EQ",
5251 + /* 34 */ "cond ::= MATCH",
5252 + /* 35 */ "cond ::= NE",
5253 + /* 36 */ "cond ::= NOMATCH",
5254 + /* 37 */ "stringop ::= expression",
5255 + /* 38 */ "include ::= INCLUDE stringop",
5256 + /* 39 */ "include_shell ::= INCLUDE_SHELL stringop",
5266 ** This function allocates a new parser.
5267 ** The only argument is a pointer to a function which works like
5270 /* Here is inserted the actions which take place when a
5271 ** terminal or non-terminal is destroyed. This can happen
5272 ** when the symbol is popped from the stack during a
5273 - ** reduce or during error processing or when a parser is
5274 + ** reduce or during error processing or when a parser is
5275 ** being destroyed before it is finished parsing.
5277 ** Note: during a reduce, the only symbols destroyed are those
5278 @@ -528,44 +513,44 @@
5282 -#line 160 "./configparser.y"
5283 +#line 143 "./configparser.y"
5284 { buffer_free((yypminor->yy0)); }
5285 -#line 533 "configparser.c"
5286 +#line 518 "configparser.c"
5289 -#line 151 "./configparser.y"
5290 +#line 134 "./configparser.y"
5291 { (yypminor->yy41)->free((yypminor->yy41)); }
5292 -#line 538 "configparser.c"
5293 +#line 523 "configparser.c"
5296 -#line 152 "./configparser.y"
5297 +#line 135 "./configparser.y"
5298 { (yypminor->yy41)->free((yypminor->yy41)); }
5299 -#line 543 "configparser.c"
5300 +#line 528 "configparser.c"
5303 -#line 153 "./configparser.y"
5304 +#line 136 "./configparser.y"
5305 { (yypminor->yy41)->free((yypminor->yy41)); }
5306 -#line 548 "configparser.c"
5307 +#line 533 "configparser.c"
5310 -#line 154 "./configparser.y"
5311 +#line 137 "./configparser.y"
5312 { array_free((yypminor->yy40)); }
5313 -#line 553 "configparser.c"
5314 +#line 538 "configparser.c"
5317 -#line 155 "./configparser.y"
5318 +#line 138 "./configparser.y"
5319 { array_free((yypminor->yy40)); }
5320 -#line 558 "configparser.c"
5321 +#line 543 "configparser.c"
5324 -#line 156 "./configparser.y"
5325 +#line 139 "./configparser.y"
5326 { buffer_free((yypminor->yy43)); }
5327 -#line 563 "configparser.c"
5328 +#line 548 "configparser.c"
5331 -#line 157 "./configparser.y"
5332 +#line 140 "./configparser.y"
5333 { buffer_free((yypminor->yy43)); }
5334 -#line 568 "configparser.c"
5335 +#line 553 "configparser.c"
5337 default: break; /* If no destructor action specified: do nothing */
5345 ** Deallocate and destroy a parser. Destructors are all called for
5346 ** all stack elements before shutting the parser down.
5351 int stateno = pParser->yystack[pParser->yyidx].stateno;
5354 /* if( pParser->yyidx<0 ) return YY_NO_ACTION; */
5355 i = yy_shift_ofst[stateno];
5356 if( i==YY_SHIFT_USE_DFLT ){
5360 int stateno = pParser->yystack[pParser->yyidx].stateno;
5363 i = yy_reduce_ofst[stateno];
5364 if( i==YY_REDUCE_USE_DFLT ){
5365 return yy_default[stateno];
5375 configparserARG_FETCH;
5376 yymsp = &yypParser->yystack[yypParser->yyidx];
5378 - if( yyTraceFILE && yyruleno>=0
5379 + if( yyTraceFILE && yyruleno>=0
5380 && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){
5381 fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
5382 yyRuleName[yyruleno]);
5384 /* No destructor defined for global */
5387 -#line 134 "./configparser.y"
5388 +#line 116 "./configparser.y"
5389 { yymsp[-1].minor.yy78 = NULL; }
5390 -#line 837 "configparser.c"
5391 +#line 823 "configparser.c"
5392 yy_destructor(1,&yymsp[0].minor);
5395 @@ -847,10 +833,15 @@
5396 yy_destructor(1,&yymsp[0].minor);
5399 -#line 162 "./configparser.y"
5400 +#line 145 "./configparser.y"
5402 buffer_copy_string_buffer(yymsp[0].minor.yy41->key, yymsp[-2].minor.yy43);
5403 - if (NULL == array_get_element(ctx->current->value, yymsp[0].minor.yy41->key->ptr)) {
5404 + if (strncmp(yymsp[-2].minor.yy43->ptr, "env.", sizeof("env.") - 1) == 0) {
5405 + fprintf(stderr, "Setting env variable is not supported in conditional %d %s: %s\n",
5406 + ctx->current->context_ndx,
5407 + ctx->current->key->ptr, yymsp[-2].minor.yy43->ptr);
5409 + } else if (NULL == array_get_element(ctx->current->value, yymsp[0].minor.yy41->key->ptr)) {
5410 array_insert_unique(ctx->current->value, yymsp[0].minor.yy41);
5411 yymsp[0].minor.yy41 = NULL;
5413 @@ -864,16 +855,21 @@
5414 buffer_free(yymsp[-2].minor.yy43);
5415 yymsp[-2].minor.yy43 = NULL;
5417 -#line 867 "configparser.c"
5418 +#line 858 "configparser.c"
5419 yy_destructor(2,&yymsp[-1].minor);
5422 -#line 179 "./configparser.y"
5423 +#line 167 "./configparser.y"
5425 array *vars = ctx->current->value;
5428 - if (NULL != (du = array_get_element(vars, yymsp[-2].minor.yy43->ptr))) {
5429 + if (strncmp(yymsp[-2].minor.yy43->ptr, "env.", sizeof("env.") - 1) == 0) {
5430 + fprintf(stderr, "Appending env variable is not supported in conditional %d %s: %s\n",
5431 + ctx->current->context_ndx,
5432 + ctx->current->key->ptr, yymsp[-2].minor.yy43->ptr);
5434 + } else if (NULL != (du = array_get_element(vars, yymsp[-2].minor.yy43->ptr))) {
5435 /* exists in current block */
5436 du = configparser_merge_data(du, yymsp[0].minor.yy41);
5439 buffer_copy_string_buffer(du->key, yymsp[-2].minor.yy43);
5440 array_replace(vars, du);
5442 + yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
5443 } else if (NULL != (du = configparser_get_variable(ctx, yymsp[-2].minor.yy43))) {
5444 du = configparser_merge_data(du, yymsp[0].minor.yy41);
5446 @@ -892,22 +889,20 @@
5447 buffer_copy_string_buffer(du->key, yymsp[-2].minor.yy43);
5448 array_insert_unique(ctx->current->value, du);
5450 + yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
5452 - fprintf(stderr, "Undefined config variable in conditional %d %s: %s\n",
5453 - ctx->current->context_ndx,
5454 - ctx->current->key->ptr, yymsp[-2].minor.yy43->ptr);
5456 + buffer_copy_string_buffer(yymsp[0].minor.yy41->key, yymsp[-2].minor.yy43);
5457 + array_insert_unique(ctx->current->value, yymsp[0].minor.yy41);
5459 buffer_free(yymsp[-2].minor.yy43);
5460 yymsp[-2].minor.yy43 = NULL;
5461 - yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
5462 yymsp[0].minor.yy41 = NULL;
5464 -#line 906 "configparser.c"
5465 +#line 901 "configparser.c"
5466 yy_destructor(3,&yymsp[-1].minor);
5469 -#line 214 "./configparser.y"
5470 +#line 206 "./configparser.y"
5472 if (strchr(yymsp[0].minor.yy0->ptr, '.') == NULL) {
5473 yygotominor.yy43 = buffer_init_string("var.");
5474 @@ -919,10 +914,10 @@
5475 yymsp[0].minor.yy0 = NULL;
5478 -#line 922 "configparser.c"
5479 +#line 917 "configparser.c"
5482 -#line 226 "./configparser.y"
5483 +#line 218 "./configparser.y"
5485 yygotominor.yy41 = configparser_merge_data(yymsp[-2].minor.yy41, yymsp[0].minor.yy41);
5486 if (NULL == yygotominor.yy41) {
5487 @@ -932,21 +927,38 @@
5488 yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
5489 yymsp[0].minor.yy41 = NULL;
5491 -#line 935 "configparser.c"
5492 +#line 930 "configparser.c"
5493 yy_destructor(5,&yymsp[-1].minor);
5496 -#line 236 "./configparser.y"
5497 +#line 228 "./configparser.y"
5499 yygotominor.yy41 = yymsp[0].minor.yy41;
5500 yymsp[0].minor.yy41 = NULL;
5502 -#line 944 "configparser.c"
5503 +#line 939 "configparser.c"
5506 -#line 241 "./configparser.y"
5507 +#line 233 "./configparser.y"
5509 - yygotominor.yy41 = configparser_get_variable(ctx, yymsp[0].minor.yy43);
5510 + if (strncmp(yymsp[0].minor.yy43->ptr, "env.", sizeof("env.") - 1) == 0) {
5513 + if (NULL != (env = getenv(yymsp[0].minor.yy43->ptr + 4))) {
5515 + ds = data_string_init();
5516 + buffer_append_string(ds->value, env);
5517 + yygotominor.yy41 = (data_unset *)ds;
5520 + yygotominor.yy41 = NULL;
5521 + fprintf(stderr, "Undefined env variable: %s\n", yymsp[0].minor.yy43->ptr + 4);
5524 + } else if (NULL == (yygotominor.yy41 = configparser_get_variable(ctx, yymsp[0].minor.yy43))) {
5525 + fprintf(stderr, "Undefined config variable: %s\n", yymsp[0].minor.yy43->ptr);
5528 if (!yygotominor.yy41) {
5529 /* make a dummy so it won't crash */
5530 yygotominor.yy41 = (data_unset *)data_string_init();
5531 @@ -954,50 +966,59 @@
5532 buffer_free(yymsp[0].minor.yy43);
5533 yymsp[0].minor.yy43 = NULL;
5535 -#line 957 "configparser.c"
5536 +#line 969 "configparser.c"
5539 -#line 251 "./configparser.y"
5540 +#line 260 "./configparser.y"
5542 yygotominor.yy41 = (data_unset *)data_string_init();
5543 buffer_copy_string_buffer(((data_string *)(yygotominor.yy41))->value, yymsp[0].minor.yy0);
5544 buffer_free(yymsp[0].minor.yy0);
5545 yymsp[0].minor.yy0 = NULL;
5547 -#line 967 "configparser.c"
5548 +#line 979 "configparser.c"
5551 -#line 258 "./configparser.y"
5552 +#line 267 "./configparser.y"
5554 yygotominor.yy41 = (data_unset *)data_integer_init();
5555 ((data_integer *)(yygotominor.yy41))->value = strtol(yymsp[0].minor.yy0->ptr, NULL, 10);
5556 buffer_free(yymsp[0].minor.yy0);
5557 yymsp[0].minor.yy0 = NULL;
5559 -#line 977 "configparser.c"
5560 +#line 989 "configparser.c"
5563 -#line 264 "./configparser.y"
5564 +#line 273 "./configparser.y"
5566 yygotominor.yy41 = (data_unset *)data_array_init();
5567 array_free(((data_array *)(yygotominor.yy41))->value);
5568 ((data_array *)(yygotominor.yy41))->value = yymsp[0].minor.yy40;
5569 yymsp[0].minor.yy40 = NULL;
5571 -#line 987 "configparser.c"
5572 +#line 999 "configparser.c"
5575 -#line 270 "./configparser.y"
5576 +#line 279 "./configparser.y"
5578 + yygotominor.yy40 = array_init();
5580 +#line 1006 "configparser.c"
5581 + yy_destructor(8,&yymsp[-1].minor);
5582 + yy_destructor(9,&yymsp[0].minor);
5585 +#line 282 "./configparser.y"
5587 yygotominor.yy40 = yymsp[-1].minor.yy40;
5588 yymsp[-1].minor.yy40 = NULL;
5590 -#line 995 "configparser.c"
5591 +#line 1016 "configparser.c"
5592 yy_destructor(8,&yymsp[-2].minor);
5593 yy_destructor(9,&yymsp[0].minor);
5596 -#line 275 "./configparser.y"
5598 +#line 287 "./configparser.y"
5600 if (buffer_is_empty(yymsp[0].minor.yy41->key) ||
5601 NULL == array_get_element(yymsp[-2].minor.yy40, yymsp[0].minor.yy41->key->ptr)) {
5602 @@ -1014,37 +1035,37 @@
5603 yygotominor.yy40 = yymsp[-2].minor.yy40;
5604 yymsp[-2].minor.yy40 = NULL;
5606 -#line 1017 "configparser.c"
5607 +#line 1038 "configparser.c"
5608 yy_destructor(10,&yymsp[-1].minor);
5611 -#line 292 "./configparser.y"
5613 +#line 304 "./configparser.y"
5615 yygotominor.yy40 = yymsp[-1].minor.yy40;
5616 yymsp[-1].minor.yy40 = NULL;
5618 -#line 1026 "configparser.c"
5619 +#line 1047 "configparser.c"
5620 yy_destructor(10,&yymsp[0].minor);
5623 -#line 297 "./configparser.y"
5625 +#line 309 "./configparser.y"
5627 yygotominor.yy40 = array_init();
5628 array_insert_unique(yygotominor.yy40, yymsp[0].minor.yy41);
5629 yymsp[0].minor.yy41 = NULL;
5631 -#line 1036 "configparser.c"
5632 +#line 1057 "configparser.c"
5635 -#line 303 "./configparser.y"
5637 +#line 315 "./configparser.y"
5639 yygotominor.yy41 = yymsp[0].minor.yy41;
5640 yymsp[0].minor.yy41 = NULL;
5642 -#line 1044 "configparser.c"
5643 +#line 1065 "configparser.c"
5646 -#line 307 "./configparser.y"
5648 +#line 319 "./configparser.y"
5650 buffer_copy_string_buffer(yymsp[0].minor.yy41->key, yymsp[-2].minor.yy43);
5651 buffer_free(yymsp[-2].minor.yy43);
5652 @@ -1053,27 +1074,27 @@
5653 yygotominor.yy41 = yymsp[0].minor.yy41;
5654 yymsp[0].minor.yy41 = NULL;
5656 -#line 1056 "configparser.c"
5657 +#line 1077 "configparser.c"
5658 yy_destructor(11,&yymsp[-1].minor);
5661 - yy_destructor(1,&yymsp[0].minor);
5664 + yy_destructor(1,&yymsp[0].minor);
5667 -#line 319 "./configparser.y"
5670 +#line 331 "./configparser.y"
5673 dc = (data_config *)array_get_element(ctx->srv->config_context, "global");
5675 configparser_push(ctx, dc, 0);
5677 -#line 1072 "configparser.c"
5678 +#line 1093 "configparser.c"
5679 yy_destructor(12,&yymsp[0].minor);
5682 -#line 326 "./configparser.y"
5684 +#line 338 "./configparser.y"
5688 @@ -1082,16 +1103,16 @@
5690 assert(cur && ctx->current);
5692 - yygotominor.yy0 = cur;
5693 + yygotominor.yy78 = cur;
5695 -#line 1087 "configparser.c"
5696 +#line 1108 "configparser.c"
5697 /* No destructor defined for globalstart */
5698 yy_destructor(13,&yymsp[-2].minor);
5699 /* No destructor defined for metalines */
5700 yy_destructor(14,&yymsp[0].minor);
5703 -#line 337 "./configparser.y"
5705 +#line 349 "./configparser.y"
5707 assert(yymsp[-3].minor.yy78->context_ndx < yymsp[0].minor.yy78->context_ndx);
5708 yymsp[0].minor.yy78->prev = yymsp[-3].minor.yy78;
5709 @@ -1100,20 +1121,20 @@
5710 yymsp[-3].minor.yy78 = NULL;
5711 yymsp[0].minor.yy78 = NULL;
5713 -#line 1103 "configparser.c"
5714 +#line 1124 "configparser.c"
5715 /* No destructor defined for eols */
5716 yy_destructor(15,&yymsp[-1].minor);
5719 -#line 346 "./configparser.y"
5721 +#line 358 "./configparser.y"
5723 yygotominor.yy78 = yymsp[0].minor.yy78;
5724 yymsp[0].minor.yy78 = NULL;
5726 -#line 1113 "configparser.c"
5727 +#line 1134 "configparser.c"
5730 -#line 351 "./configparser.y"
5732 +#line 363 "./configparser.y"
5736 @@ -1124,14 +1145,14 @@
5738 yygotominor.yy78 = cur;
5740 -#line 1127 "configparser.c"
5741 +#line 1148 "configparser.c"
5742 /* No destructor defined for context */
5743 yy_destructor(13,&yymsp[-2].minor);
5744 /* No destructor defined for metalines */
5745 yy_destructor(14,&yymsp[0].minor);
5748 -#line 362 "./configparser.y"
5750 +#line 374 "./configparser.y"
5753 buffer *b, *rvalue, *op;
5754 @@ -1266,45 +1287,45 @@
5755 yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
5756 yymsp[0].minor.yy41 = NULL;
5758 -#line 1269 "configparser.c"
5759 +#line 1290 "configparser.c"
5760 yy_destructor(16,&yymsp[-6].minor);
5761 yy_destructor(18,&yymsp[-4].minor);
5762 yy_destructor(19,&yymsp[-2].minor);
5765 -#line 496 "./configparser.y"
5767 +#line 508 "./configparser.y"
5769 yygotominor.yy27 = CONFIG_COND_EQ;
5771 -#line 1279 "configparser.c"
5772 +#line 1300 "configparser.c"
5773 yy_destructor(20,&yymsp[0].minor);
5776 -#line 499 "./configparser.y"
5778 +#line 511 "./configparser.y"
5780 yygotominor.yy27 = CONFIG_COND_MATCH;
5782 -#line 1287 "configparser.c"
5783 +#line 1308 "configparser.c"
5784 yy_destructor(21,&yymsp[0].minor);
5787 -#line 502 "./configparser.y"
5789 +#line 514 "./configparser.y"
5791 yygotominor.yy27 = CONFIG_COND_NE;
5793 -#line 1295 "configparser.c"
5794 +#line 1316 "configparser.c"
5795 yy_destructor(22,&yymsp[0].minor);
5798 -#line 505 "./configparser.y"
5800 +#line 517 "./configparser.y"
5802 yygotominor.yy27 = CONFIG_COND_NOMATCH;
5804 -#line 1303 "configparser.c"
5805 +#line 1324 "configparser.c"
5806 yy_destructor(23,&yymsp[0].minor);
5809 -#line 509 "./configparser.y"
5811 +#line 521 "./configparser.y"
5813 yygotominor.yy43 = NULL;
5815 @@ -1321,10 +1342,10 @@
5816 yymsp[0].minor.yy41->free(yymsp[0].minor.yy41);
5817 yymsp[0].minor.yy41 = NULL;
5819 -#line 1324 "configparser.c"
5820 +#line 1345 "configparser.c"
5823 -#line 526 "./configparser.y"
5825 +#line 538 "./configparser.y"
5828 if (0 != config_parse_file(ctx->srv, ctx, yymsp[0].minor.yy43->ptr)) {
5829 @@ -1334,11 +1355,11 @@
5830 yymsp[0].minor.yy43 = NULL;
5833 -#line 1337 "configparser.c"
5834 +#line 1358 "configparser.c"
5835 yy_destructor(24,&yymsp[-1].minor);
5838 -#line 536 "./configparser.y"
5840 +#line 548 "./configparser.y"
5843 if (0 != config_parse_cmd(ctx->srv, ctx, yymsp[0].minor.yy43->ptr)) {
5844 @@ -1348,7 +1369,7 @@
5845 yymsp[0].minor.yy43 = NULL;
5848 -#line 1351 "configparser.c"
5849 +#line 1372 "configparser.c"
5850 yy_destructor(25,&yymsp[-1].minor);
5853 @@ -1378,11 +1399,11 @@
5854 while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
5855 /* Here code is inserted which will be executed whenever the
5857 -#line 125 "./configparser.y"
5858 +#line 107 "./configparser.y"
5862 -#line 1385 "configparser.c"
5863 +#line 1406 "configparser.c"
5864 configparserARG_STORE; /* Suppress warning about unused %extra_argument variable */
5867 @@ -1489,7 +1510,7 @@
5868 #ifdef YYERRORSYMBOL
5869 /* A syntax error has occurred.
5870 ** The response to an error depends upon whether or not the
5871 - ** grammar defines an error token "ERROR".
5872 + ** grammar defines an error token "ERROR".
5874 ** This is what we do if the grammar does define ERROR:
5876 --- ../lighttpd-1.4.11/src/configparser.y 2006-01-26 18:46:25.000000000 +0200
5877 +++ lighttpd-1.4.12/src/configparser.y 2006-07-16 00:26:04.000000000 +0300
5879 dc->parent = ctx->current;
5880 array_insert_unique(dc->parent->childs, (data_unset *)dc);
5882 - array_insert_unique(ctx->configs_stack, (data_unset *)ctx->current);
5883 + buffer_ptr_append(ctx->configs_stack, (void *)ctx->current);
5887 static data_config *configparser_pop(config_t *ctx) {
5888 data_config *old = ctx->current;
5889 - ctx->current = (data_config *) array_pop(ctx->configs_stack);
5890 + ctx->current = (data_config *) buffer_ptr_pop(ctx->configs_stack);
5894 /* return a copied variable */
5895 static data_unset *configparser_get_variable(config_t *ctx, const buffer *key) {
5896 - if (strncmp(key->ptr, "env.", sizeof("env.") - 1) == 0) {
5899 - if (NULL != (env = getenv(key->ptr + 4))) {
5901 - ds = data_string_init();
5902 - buffer_append_string(ds->value, env);
5903 - return (data_unset *)ds;
5906 - fprintf(stderr, "Undefined env variable: %s\n", key->ptr + 4);
5917 - fprintf(stderr, "get var %s\n", key->ptr);
5918 + fprintf(stderr, "get var %s\n", key->ptr);
5920 - for (dc = ctx->current; dc; dc = dc->parent) {
5921 + for (dc = ctx->current; dc; dc = dc->parent) {
5923 - fprintf(stderr, "get var on block: %s\n", dc->key->ptr);
5924 - array_print(dc->value, 0);
5925 + fprintf(stderr, "get var on block: %s\n", dc->key->ptr);
5926 + array_print(dc->value, 0);
5928 - if (NULL != (du = array_get_element(dc->value, key->ptr))) {
5929 - return du->copy(du);
5931 + if (NULL != (du = array_get_element(dc->value, key->ptr))) {
5932 + return du->copy(du);
5934 - fprintf(stderr, "Undefined config variable: %s\n", key->ptr);
5941 /* op1 is to be eat/return by this function, op1->key is not cared
5943 %type aelement {data_unset *}
5944 %type condline {data_config *}
5945 %type condlines {data_config *}
5946 +%type global {data_config *}
5947 %type aelements {array *}
5948 %type array {array *}
5949 %type key {buffer *}
5950 @@ -161,7 +144,12 @@
5952 varline ::= key(A) ASSIGN expression(B). {
5953 buffer_copy_string_buffer(B->key, A);
5954 - if (NULL == array_get_element(ctx->current->value, B->key->ptr)) {
5955 + if (strncmp(A->ptr, "env.", sizeof("env.") - 1) == 0) {
5956 + fprintf(stderr, "Setting env variable is not supported in conditional %d %s: %s\n",
5957 + ctx->current->context_ndx,
5958 + ctx->current->key->ptr, A->ptr);
5960 + } else if (NULL == array_get_element(ctx->current->value, B->key->ptr)) {
5961 array_insert_unique(ctx->current->value, B);
5964 @@ -180,7 +168,12 @@
5965 array *vars = ctx->current->value;
5968 - if (NULL != (du = array_get_element(vars, A->ptr))) {
5969 + if (strncmp(A->ptr, "env.", sizeof("env.") - 1) == 0) {
5970 + fprintf(stderr, "Appending env variable is not supported in conditional %d %s: %s\n",
5971 + ctx->current->context_ndx,
5972 + ctx->current->key->ptr, A->ptr);
5974 + } else if (NULL != (du = array_get_element(vars, A->ptr))) {
5975 /* exists in current block */
5976 du = configparser_merge_data(du, B);
5979 buffer_copy_string_buffer(du->key, A);
5980 array_replace(vars, du);
5983 } else if (NULL != (du = configparser_get_variable(ctx, A))) {
5984 du = configparser_merge_data(du, B);
5986 @@ -199,15 +193,13 @@
5987 buffer_copy_string_buffer(du->key, A);
5988 array_insert_unique(ctx->current->value, du);
5992 - fprintf(stderr, "Undefined config variable in conditional %d %s: %s\n",
5993 - ctx->current->context_ndx,
5994 - ctx->current->key->ptr, A->ptr);
5996 + buffer_copy_string_buffer(B->key, A);
5997 + array_insert_unique(ctx->current->value, B);
6005 @@ -239,7 +231,24 @@
6008 value(A) ::= key(B). {
6009 - A = configparser_get_variable(ctx, B);
6010 + if (strncmp(B->ptr, "env.", sizeof("env.") - 1) == 0) {
6013 + if (NULL != (env = getenv(B->ptr + 4))) {
6015 + ds = data_string_init();
6016 + buffer_append_string(ds->value, env);
6017 + A = (data_unset *)ds;
6021 + fprintf(stderr, "Undefined env variable: %s\n", B->ptr + 4);
6024 + } else if (NULL == (A = configparser_get_variable(ctx, B))) {
6025 + fprintf(stderr, "Undefined config variable: %s\n", B->ptr);
6029 /* make a dummy so it won't crash */
6030 A = (data_unset *)data_string_init();
6032 ((data_array *)(A))->value = B;
6035 +array(A) ::= LPARAN RPARAN. {
6038 array(A) ::= LPARAN aelements(B) RPARAN. {
6041 --- ../lighttpd-1.4.11/src/connections-glue.c 2005-09-12 10:04:23.000000000 +0300
6042 +++ lighttpd-1.4.12/src/connections-glue.c 2006-07-16 00:26:03.000000000 +0300
6044 case CON_STATE_REQUEST_END: return "req-end";
6045 case CON_STATE_RESPONSE_START: return "resp-start";
6046 case CON_STATE_RESPONSE_END: return "resp-end";
6047 - default: return "(unknown)";
6048 + default: return "(unknown)";
6053 case CON_STATE_REQUEST_END: return "Q";
6054 case CON_STATE_RESPONSE_START: return "s";
6055 case CON_STATE_RESPONSE_END: return "S";
6056 - default: return "x";
6057 + default: return "x";
6061 int connection_set_state(server *srv, connection *con, connection_state_t state) {
6071 --- ../lighttpd-1.4.11/src/connections.c 2006-03-05 22:14:53.000000000 +0200
6072 +++ lighttpd-1.4.12/src/connections.c 2006-07-18 13:03:40.000000000 +0300
6077 -#include <unistd.h>
6082 #include "inet_ntop_cache.h"
6085 -# include <openssl/ssl.h>
6086 -# include <openssl/err.h>
6087 +# include <openssl/ssl.h>
6088 +# include <openssl/err.h>
6091 #ifdef HAVE_SYS_FILIO_H
6095 #include "sys-socket.h"
6096 +#include "sys-files.h"
6103 static connection *connections_get_new_connection(server *srv) {
6104 connections *conns = srv->conns;
6108 if (conns->size == 0) {
6112 } else if (conns->size == conns->used) {
6114 conns->ptr = realloc(conns->ptr, sizeof(*conns->ptr) * conns->size);
6117 for (i = conns->used; i < conns->size; i++) {
6118 conns->ptr[i] = connection_init(srv);
6122 connection_reset(srv, conns->ptr[conns->used]);
6124 - fprintf(stderr, "%s.%d: add: ", __FILE__, __LINE__);
6125 - for (i = 0; i < conns->used + 1; i++) {
6126 - fprintf(stderr, "%d ", conns->ptr[i]->fd);
6128 - fprintf(stderr, "\n");
6132 conns->ptr[conns->used]->ndx = conns->used;
6133 return conns->ptr[conns->used++];
6135 @@ -77,263 +70,134 @@
6137 connections *conns = srv->conns;
6141 if (con == NULL) return -1;
6144 if (-1 == con->ndx) return -1;
6150 /* not last element */
6153 if (i != conns->used - 1) {
6154 temp = conns->ptr[i];
6155 conns->ptr[i] = conns->ptr[conns->used - 1];
6156 conns->ptr[conns->used - 1] = temp;
6159 conns->ptr[i]->ndx = i;
6160 conns->ptr[conns->used - 1]->ndx = -1;
6169 - fprintf(stderr, "%s.%d: del: (%d)", __FILE__, __LINE__, conns->used);
6170 - for (i = 0; i < conns->used; i++) {
6171 - fprintf(stderr, "%d ", conns->ptr[i]->fd);
6173 - fprintf(stderr, "\n");
6179 int connection_close(server *srv, connection *con) {
6181 server_socket *srv_sock = con->srv_socket;
6186 if (srv_sock->is_ssl) {
6187 - if (con->ssl) SSL_free(con->ssl);
6189 + if (con->sock->ssl) SSL_free(con->sock->ssl);
6190 + con->sock->ssl = NULL;
6194 - fdevent_event_del(srv->ev, &(con->fde_ndx), con->fd);
6195 - fdevent_unregister(srv->ev, con->fd);
6197 - if (closesocket(con->fd)) {
6198 - log_error_write(srv, __FILE__, __LINE__, "sds",
6199 - "(warning) close:", con->fd, strerror(errno));
6202 - if (close(con->fd)) {
6204 + fdevent_event_del(srv->ev, con->sock);
6205 + fdevent_unregister(srv->ev, con->sock);
6207 + if (closesocket(con->sock->fd)) {
6208 log_error_write(srv, __FILE__, __LINE__, "sds",
6209 - "(warning) close:", con->fd, strerror(errno));
6210 + "(warning) close:", con->sock->fd, strerror(errno));
6217 - log_error_write(srv, __FILE__, __LINE__, "sd",
6218 - "closed()", con->fd);
6222 connection_del(srv, con);
6223 connection_set_state(srv, con, CON_STATE_CONNECT);
6230 static void dump_packet(const unsigned char *data, size_t len) {
6234 if (len == 0) return;
6237 for (i = 0; i < len; i++) {
6238 if (i % 16 == 0) fprintf(stderr, " ");
6241 fprintf(stderr, "%02x ", data[i]);
6244 if ((i + 1) % 16 == 0) {
6245 fprintf(stderr, " ");
6246 for (j = 0; j <= i % 16; j++) {
6250 if (i-15+j >= len) break;
6256 fprintf(stderr, "%c", c > 32 && c < 128 ? c : '.');
6260 fprintf(stderr, "\n");
6265 if (len % 16 != 0) {
6266 for (j = i % 16; j < 16; j++) {
6267 fprintf(stderr, " ");
6271 fprintf(stderr, " ");
6272 for (j = i & ~0xf; j < len; j++) {
6277 fprintf(stderr, "%c", c > 32 && c < 128 ? c : '.');
6279 fprintf(stderr, "\n");
6284 -static int connection_handle_read(server *srv, connection *con) {
6289 - server_socket *srv_sock = con->srv_socket;
6292 - b = chunkqueue_get_append_buffer(con->read_queue);
6293 - buffer_prepare_copy(b, 4096);
6296 - if (srv_sock->is_ssl) {
6297 - len = SSL_read(con->ssl, b->ptr, b->size - 1);
6299 - if (ioctl(con->fd, FIONREAD, &toread)) {
6300 - log_error_write(srv, __FILE__, __LINE__, "sd",
6301 - "unexpected end-of-file:",
6305 - buffer_prepare_copy(b, toread);
6306 +static network_status_t connection_handle_read(server *srv, connection *con) {
6307 + off_t oldlen, newlen;
6309 - len = read(con->fd, b->ptr, b->size - 1);
6311 -#elif defined(__WIN32)
6312 - len = recv(con->fd, b->ptr, b->size - 1, 0);
6314 - if (ioctl(con->fd, FIONREAD, &toread)) {
6315 - log_error_write(srv, __FILE__, __LINE__, "sd",
6316 - "unexpected end-of-file:",
6320 - buffer_prepare_copy(b, toread);
6321 + oldlen = chunkqueue_length(con->read_queue);
6323 - len = read(con->fd, b->ptr, b->size - 1);
6327 + switch(network_read_chunkqueue(srv, con, con->read_queue)) {
6328 + case NETWORK_STATUS_SUCCESS:
6330 + case NETWORK_STATUS_WAIT_FOR_EVENT:
6331 + con->is_readable = 0;
6332 + return NETWORK_STATUS_WAIT_FOR_EVENT;
6333 + case NETWORK_STATUS_INTERRUPTED:
6334 + con->is_readable = 1;
6335 + return NETWORK_STATUS_WAIT_FOR_EVENT;
6336 + case NETWORK_STATUS_CONNECTION_CLOSE:
6338 + con->is_readable = 0;
6339 + return NETWORK_STATUS_CONNECTION_CLOSE;
6340 + case NETWORK_STATUS_FATAL_ERROR:
6341 con->is_readable = 0;
6344 - if (srv_sock->is_ssl) {
6347 - switch ((r = SSL_get_error(con->ssl, len))) {
6348 - case SSL_ERROR_WANT_READ:
6350 - case SSL_ERROR_SYSCALL:
6352 - * man SSL_get_error()
6354 - * SSL_ERROR_SYSCALL
6355 - * Some I/O error occurred. The OpenSSL error queue may contain more
6356 - * information on the error. If the error queue is empty (i.e.
6357 - * ERR_get_error() returns 0), ret can be used to find out more about
6358 - * the error: If ret == 0, an EOF was observed that violates the
6359 - * protocol. If ret == -1, the underlying BIO reported an I/O error
6360 - * (for socket I/O on Unix systems, consult errno for details).
6363 - while((ssl_err = ERR_get_error())) {
6364 - /* get all errors from the error-queue */
6365 - log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
6366 - r, ERR_error_string(ssl_err, NULL));
6371 - log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
6378 - case SSL_ERROR_ZERO_RETURN:
6379 - /* clean shutdown on the remote side */
6382 - /* FIXME: later */
6385 - /* fall thourgh */
6387 - while((ssl_err = ERR_get_error())) {
6388 - /* get all errors from the error-queue */
6389 - log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
6390 - r, ERR_error_string(ssl_err, NULL));
6395 - if (errno == EAGAIN) return 0;
6396 - if (errno == EINTR) {
6397 - /* we have been interrupted before we could read */
6398 - con->is_readable = 1;
6402 - if (errno != ECONNRESET) {
6403 - /* expected for keep-alive */
6404 - log_error_write(srv, __FILE__, __LINE__, "ssd", "connection closed - read failed: ", strerror(errno), errno);
6408 - if (errno == EAGAIN) return 0;
6409 - if (errno == EINTR) {
6410 - /* we have been interrupted before we could read */
6411 - con->is_readable = 1;
6415 - if (errno != ECONNRESET) {
6416 - /* expected for keep-alive */
6417 - log_error_write(srv, __FILE__, __LINE__, "ssd", "connection closed - read failed: ", strerror(errno), errno);
6420 connection_set_state(srv, con, CON_STATE_ERROR);
6423 - } else if (len == 0) {
6424 - con->is_readable = 0;
6425 - /* the other end close the connection -> KEEP-ALIVE */
6426 + return NETWORK_STATUS_FATAL_ERROR;
6433 + newlen = chunkqueue_length(con->read_queue);
6436 - } else if ((size_t)len < b->size - 1) {
6437 - /* we got less then expected, wait for the next fd-event */
6439 - con->is_readable = 0;
6443 - b->ptr[b->used++] = '\0';
6445 - con->bytes_read += len;
6447 - dump_packet(b->ptr, len);
6451 + con->bytes_read += (newlen - oldlen);
6453 + return NETWORK_STATUS_SUCCESS;
6456 static int connection_handle_write_prepare(server *srv, connection *con) {
6458 case HTTP_METHOD_GET:
6459 case HTTP_METHOD_POST:
6460 case HTTP_METHOD_HEAD:
6462 case HTTP_METHOD_PUT:
6463 case HTTP_METHOD_MKCOL:
6464 case HTTP_METHOD_DELETE:
6465 @@ -350,12 +215,14 @@
6466 case HTTP_METHOD_MOVE:
6467 case HTTP_METHOD_PROPFIND:
6468 case HTTP_METHOD_PROPPATCH:
6469 + case HTTP_METHOD_LOCK:
6470 + case HTTP_METHOD_UNLOCK:
6472 case HTTP_METHOD_OPTIONS:
6474 * 400 is coming from the request-parser BEFORE uri.path is set
6475 - * 403 is from the response handler when noone else catched it
6477 + * 403 is from the response handler when noone else catched it
6480 if (con->uri.path->used &&
6481 con->uri.path->ptr[0] != '*') {
6482 @@ -381,55 +248,60 @@
6488 if (con->http_status == 0) {
6489 con->http_status = 403;
6493 switch(con->http_status) {
6494 case 400: /* class: header + custom body */
6512 if (con->mode != DIRECT) break;
6515 con->file_finished = 0;
6518 buffer_reset(con->physical.path);
6521 /* try to send static errorfile */
6522 if (!buffer_is_empty(con->conf.errorfile_prefix)) {
6523 stat_cache_entry *sce = NULL;
6526 buffer_copy_string_buffer(con->physical.path, con->conf.errorfile_prefix);
6527 buffer_append_string(con->physical.path, get_http_status_body_name(con->http_status));
6530 if (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
6531 con->file_finished = 1;
6534 http_chunk_append_file(srv, con, con->physical.path, 0, sce->st.st_size);
6535 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
6539 - if (!con->file_finished) {
6541 + if (!con->file_finished) {
6545 buffer_reset(con->physical.path);
6548 con->file_finished = 1;
6549 b = chunkqueue_get_append_buffer(con->write_queue);
6552 /* build default error-page */
6553 - buffer_copy_string(b,
6554 + buffer_copy_string(b,
6555 "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
6556 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
6557 " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
6559 buffer_append_long(b, con->http_status);
6560 buffer_append_string(b, " - ");
6561 buffer_append_string(b, get_http_status_name(con->http_status));
6564 buffer_append_string(b,
6567 @@ -448,12 +320,12 @@
6568 buffer_append_long(b, con->http_status);
6569 buffer_append_string(b, " - ");
6570 buffer_append_string(b, get_http_status_name(con->http_status));
6572 - buffer_append_string(b,"</h1>\n"
6574 + buffer_append_string(b,"</h1>\n"
6580 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
6583 @@ -463,10 +335,10 @@
6589 case 206: /* write_queue is already prepared */
6590 con->file_finished = 1;
6594 case 205: /* class: header only */
6596 @@ -474,19 +346,19 @@
6597 /* disable chunked encoding again as we have no body */
6598 con->response.transfer_encoding &= ~HTTP_TRANSFER_ENCODING_CHUNKED;
6599 chunkqueue_reset(con->write_queue);
6602 con->file_finished = 1;
6608 if (con->file_finished) {
6609 - /* we have all the content and chunked encoding is not used, set a content-length */
6611 - if ((!(con->parsed_response & HTTP_CONTENT_LENGTH)) &&
6612 + /* we have all the content and chunked encoding is not used, set a content-length */
6614 + if ((!(con->parsed_response & HTTP_CONTENT_LENGTH)) &&
6615 (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) == 0) {
6616 buffer_copy_off_t(srv->tmp_buf, chunkqueue_length(con->write_queue));
6619 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Length"), CONST_BUF_LEN(srv->tmp_buf));
6622 @@ -495,77 +367,79 @@
6623 ((con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) == 0)) {
6624 con->keep_alive = 0;
6628 if (0 == (con->parsed_response & HTTP_CONNECTION)) {
6629 /* (f)cgi did'nt send Connection: header
6634 if (((con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) == 0) &&
6635 (con->parsed_response & HTTP_CONTENT_LENGTH) == 0) {
6636 /* without content_length, no keep-alive */
6639 con->keep_alive = 0;
6642 /* a subrequest disable keep-alive although the client wanted it */
6643 if (con->keep_alive && !con->response.keep_alive) {
6644 con->keep_alive = 0;
6647 /* FIXME: we have to drop the Connection: Header from the subrequest */
6653 if (con->request.http_method == HTTP_METHOD_HEAD) {
6654 chunkqueue_reset(con->write_queue);
6657 http_response_write_header(srv, con);
6663 static int connection_handle_write(server *srv, connection *con) {
6664 switch(network_write_chunkqueue(srv, con, con->write_queue)) {
6666 + case NETWORK_STATUS_SUCCESS:
6667 if (con->file_finished) {
6668 connection_set_state(srv, con, CON_STATE_RESPONSE_END);
6669 joblist_append(srv, con);
6672 - case -1: /* error on our side */
6673 + case NETWORK_STATUS_FATAL_ERROR: /* error on our side */
6674 log_error_write(srv, __FILE__, __LINE__, "sd",
6675 - "connection closed: write failed on fd", con->fd);
6676 + "connection closed: write failed on fd", con->sock->fd);
6677 connection_set_state(srv, con, CON_STATE_ERROR);
6678 joblist_append(srv, con);
6680 - case -2: /* remote close */
6681 + case NETWORK_STATUS_CONNECTION_CLOSE: /* remote close */
6682 connection_set_state(srv, con, CON_STATE_ERROR);
6683 joblist_append(srv, con);
6686 + case NETWORK_STATUS_WAIT_FOR_EVENT:
6687 con->is_writable = 0;
6690 /* not finished yet -> WRITE */
6692 + case NETWORK_STATUS_INTERRUPTED:
6693 + con->is_writable = 1;
6695 + case NETWORK_STATUS_UNSET:
6705 connection *connection_init(server *srv) {
6711 con = calloc(1, sizeof(*con));
6715 + con->sock = iosocket_init();
6717 - con->fde_ndx = -1;
6718 con->bytes_written = 0;
6719 con->bytes_read = 0;
6720 con->bytes_header = 0;
6721 @@ -573,32 +447,32 @@
6724 con->x = buffer_init();
6728 CLEAN(request.request_line);
6729 CLEAN(request.request);
6730 CLEAN(request.pathinfo);
6733 CLEAN(request.orig_uri);
6737 CLEAN(uri.authority);
6739 CLEAN(uri.path_raw);
6743 CLEAN(physical.doc_root);
6744 CLEAN(physical.path);
6745 CLEAN(physical.basedir);
6746 CLEAN(physical.rel_path);
6747 CLEAN(physical.etag);
6748 CLEAN(parse_request);
6753 CLEAN(error_handler);
6754 CLEAN(dst_addr_buf);
6758 con->write_queue = chunkqueue_init();
6759 con->read_queue = chunkqueue_init();
6760 @@ -608,26 +482,27 @@
6761 con->request.headers = array_init();
6762 con->response.headers = array_init();
6763 con->environment = array_init();
6766 /* init plugin specific connection structures */
6769 con->plugin_ctx = calloc(1, (srv->plugins.used + 1) * sizeof(void *));
6772 con->cond_cache = calloc(srv->config_context->used, sizeof(cond_cache_t));
6773 config_setup_connection(srv, con);
6779 void connections_free(server *srv) {
6780 connections *conns = srv->conns;
6785 for (i = 0; i < conns->size; i++) {
6786 connection *con = conns->ptr[i];
6789 connection_reset(srv, con);
6791 + iosocket_free(con->sock);
6793 chunkqueue_free(con->write_queue);
6794 chunkqueue_free(con->read_queue);
6795 chunkqueue_free(con->request_content_queue);
6796 @@ -637,27 +512,27 @@
6799 buffer_free(con->x);
6803 CLEAN(request.request_line);
6804 CLEAN(request.request);
6805 CLEAN(request.pathinfo);
6808 CLEAN(request.orig_uri);
6812 CLEAN(uri.authority);
6814 CLEAN(uri.path_raw);
6818 CLEAN(physical.doc_root);
6819 CLEAN(physical.path);
6820 CLEAN(physical.basedir);
6821 CLEAN(physical.etag);
6822 CLEAN(physical.rel_path);
6823 CLEAN(parse_request);
6828 CLEAN(error_handler);
6829 @@ -665,97 +540,97 @@
6831 free(con->plugin_ctx);
6832 free(con->cond_cache);
6843 int connection_reset(server *srv, connection *con) {
6847 plugins_call_connection_reset(srv, con);
6850 con->is_readable = 1;
6851 con->is_writable = 1;
6852 con->http_status = 0;
6853 con->file_finished = 0;
6854 con->file_started = 0;
6855 con->got_response = 0;
6858 con->parsed_response = 0;
6861 con->bytes_written = 0;
6862 con->bytes_written_cur_second = 0;
6863 con->bytes_read = 0;
6864 con->bytes_header = 0;
6865 con->loops_per_request = 0;
6868 con->request.http_method = HTTP_METHOD_UNSET;
6869 con->request.http_version = HTTP_VERSION_UNSET;
6872 con->request.http_if_modified_since = NULL;
6873 con->request.http_if_none_match = NULL;
6876 con->response.keep_alive = 0;
6877 con->response.content_length = -1;
6878 con->response.transfer_encoding = 0;
6885 if (con->x) buffer_reset(con->x);
6889 CLEAN(request.request_line);
6890 CLEAN(request.pathinfo);
6891 CLEAN(request.request);
6894 CLEAN(request.orig_uri);
6898 CLEAN(uri.authority);
6900 CLEAN(uri.path_raw);
6904 CLEAN(physical.doc_root);
6905 CLEAN(physical.path);
6906 CLEAN(physical.basedir);
6907 CLEAN(physical.rel_path);
6908 CLEAN(physical.etag);
6911 CLEAN(parse_request);
6916 CLEAN(error_handler);
6922 - if (con->x) con->x->used = 0;
6924 + if (con->x) con->x->used = 0;
6930 con->request.x = NULL;
6935 CLEAN(http_content_type);
6937 con->request.content_length = 0;
6940 array_reset(con->request.headers);
6941 array_reset(con->response.headers);
6942 array_reset(con->environment);
6945 chunkqueue_reset(con->write_queue);
6946 chunkqueue_reset(con->request_content_queue);
6948 - /* the plugins should cleanup themself */
6949 + /* the plugins should cleanup themself */
6950 for (i = 0; i < srv->plugins.used; i++) {
6951 plugin *p = ((plugin **)(srv->plugins.ptr))[i];
6952 plugin_data *pd = p->data;
6955 con->plugin_ctx[pd->id] = NULL;
6959 #if COND_RESULT_UNSET
6960 for (i = srv->config_context->used - 1; i >= 0; i --) {
6961 con->cond_cache[i].result = COND_RESULT_UNSET;
6962 @@ -777,56 +652,56 @@
6964 memset(con->cond_cache, 0, sizeof(cond_cache_t) * srv->config_context->used);
6968 con->header_len = 0;
6969 con->in_error_handler = 0;
6972 config_setup_connection(srv, con);
6980 - * search for \r\n\r\n
6983 + * search for \r\n\r\n
6985 * this is a special 32bit version which is using a sliding window for
6986 - * the comparisions
6988 + * the comparisions
6997 * cmpbuf: abcd != cdef
6998 * cmpbuf: bcde != cdef
6999 * cmpbuf: cdef == cdef -> return &c
7001 - * cmpbuf and rnrn are treated as 32bit uint and bit-ops are used to
7003 + * cmpbuf and rnrn are treated as 32bit uint and bit-ops are used to
7004 * maintain cmpbuf and rnrn
7009 char *buffer_search_rnrn(buffer *b) {
7010 uint32_t cmpbuf, rnrn;
7015 if (b->used < 4) return NULL;
7018 rnrn = ('\r' << 24) | ('\n' << 16) |
7019 ('\r' << 8) | ('\n' << 0);
7022 cmpbuf = (b->ptr[0] << 24) | (b->ptr[1] << 16) |
7023 (b->ptr[2] << 8) | (b->ptr[3] << 0);
7027 for (i = 0; i < b->used - 4; i++) {
7028 if (cmpbuf == rnrn) return cp - 4;
7031 cmpbuf = (cmpbuf << 8 | *(cp++)) & 0xffffffff;
7038 @@ -840,22 +715,25 @@
7040 chunkqueue *cq = con->read_queue;
7041 chunkqueue *dst_cq = con->request_content_queue;
7044 if (con->is_readable) {
7045 con->read_idle_ts = srv->cur_ts;
7048 switch(connection_handle_read(srv, con)) {
7050 + case NETWORK_STATUS_FATAL_ERROR:
7053 + case NETWORK_STATUS_CONNECTION_CLOSE:
7054 /* remote side closed the connection
7055 * if we still have content, handle it, if not leave here */
7057 if (cq->first == cq->last &&
7058 - cq->first->mem->used == 0) {
7059 + (NULL == cq->first ||
7060 + cq->first->mem->used == 0)) {
7062 /* conn-closed, leave here */
7063 connection_set_state(srv, con, CON_STATE_ERROR);
7069 @@ -891,14 +769,14 @@
7070 /* the last node was empty */
7071 if (c->next == NULL) {
7083 /* nothing to handle */
7084 if (cq->first == NULL) return 0;
7086 @@ -906,25 +784,26 @@
7087 case CON_STATE_READ:
7088 /* prepare con->request.request */
7092 /* check if we need the full package */
7093 if (con->request.request->used == 0) {
7097 b.ptr = c->mem->ptr + c->offset;
7098 b.used = c->mem->used - c->offset;
7101 if (NULL != (h_term = buffer_search_rnrn(&b))) {
7103 * - copy everything incl. the terminator to request.request
7106 - buffer_copy_string_len(con->request.request,
7109 + buffer_copy_string_len(con->request.request,
7111 h_term - b.ptr + 4);
7114 /* the buffer has been read up to the terminator */
7115 c->offset += h_term - b.ptr + 4;
7118 /* not found, copy everything */
7119 buffer_copy_string_len(con->request.request, c->mem->ptr + c->offset, c->mem->used - c->offset - 1);
7120 @@ -932,14 +811,14 @@
7123 /* have to take care of overlapping header terminators */
7126 size_t l = con->request.request->used - 2;
7127 char *s = con->request.request->ptr;
7131 b.ptr = c->mem->ptr + c->offset;
7132 b.used = c->mem->used - c->offset;
7135 if (con->request.request->used - 1 > 3 &&
7139 c->mem->ptr[0] == '\n') {
7140 buffer_append_string_len(con->request.request, c->mem->ptr + c->offset, 1);
7144 h_term = con->request.request->ptr;
7145 } else if (con->request.request->used - 1 > 2 &&
7148 c->mem->ptr[1] == '\n') {
7149 buffer_append_string_len(con->request.request, c->mem->ptr + c->offset, 2);
7153 h_term = con->request.request->ptr;
7154 } else if (con->request.request->used - 1 > 1 &&
7156 @@ -968,17 +847,17 @@
7157 c->mem->ptr[2] == '\n') {
7158 buffer_append_string_len(con->request.request, c->mem->ptr + c->offset, 3);
7162 h_term = con->request.request->ptr;
7163 } else if (NULL != (h_term = buffer_search_string_len(&b, "\r\n\r\n", 4))) {
7165 * - copy everything incl. the terminator to request.request
7168 - buffer_append_string_len(con->request.request,
7169 - c->mem->ptr + c->offset,
7171 + buffer_append_string_len(con->request.request,
7172 + c->mem->ptr + c->offset,
7173 c->offset + h_term - b.ptr + 4);
7176 /* the buffer has been read up to the terminator */
7177 c->offset += h_term - b.ptr + 4;
7179 @@ -999,16 +878,16 @@
7180 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7183 - case CON_STATE_READ_POST:
7184 + case CON_STATE_READ_POST:
7185 for (c = cq->first; c && (dst_cq->bytes_in != (off_t)con->request.content_length); c = c->next) {
7186 off_t weWant, weHave, toRead;
7189 weWant = con->request.content_length - dst_cq->bytes_in;
7192 assert(c->mem->used);
7195 weHave = c->mem->used - c->offset - 1;
7198 toRead = weHave > weWant ? weWant : weHave;
7200 /* the new way, copy everything into a chunkqueue whcih might use tempfiles */
7201 @@ -1017,13 +896,13 @@
7202 /* copy everything to max 1Mb sized tempfiles */
7205 - * if the last chunk is
7206 + * if the last chunk is
7207 * - smaller than 1Mb (size < 1Mb)
7208 * - not read yet (offset == 0)
7211 - * -> create a new chunk
7213 + * -> create a new chunk
7218 @@ -1056,14 +935,14 @@
7219 /* we have a chunk, let's write to it */
7221 if (dst_c->file.fd == -1) {
7222 - /* we don't have file to write to,
7223 + /* we don't have file to write to,
7224 * EACCES might be one reason.
7226 * Instead of sending 500 we send 413 and say the request is too large
7229 log_error_write(srv, __FILE__, __LINE__, "sbs",
7230 - "denying upload as opening to temp-file for upload failed:",
7231 + "denying upload as opening to temp-file for upload failed:",
7232 dst_c->file.name, strerror(errno));
7234 con->http_status = 413; /* Request-Entity too large */
7235 @@ -1074,15 +953,15 @@
7238 if (toRead != write(dst_c->file.fd, c->mem->ptr + c->offset, toRead)) {
7239 - /* write failed for some reason ... disk full ? */
7240 + /* write failed for some reason ... disk full ? */
7241 log_error_write(srv, __FILE__, __LINE__, "sbs",
7242 - "denying upload as writing to file failed:",
7243 + "denying upload as writing to file failed:",
7244 dst_c->file.name, strerror(errno));
7247 con->http_status = 413; /* Request-Entity too large */
7248 con->keep_alive = 0;
7249 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7252 close(dst_c->file.fd);
7253 dst_c->file.fd = -1;
7255 @@ -1090,7 +969,7 @@
7258 dst_c->file.length += toRead;
7261 if (dst_cq->bytes_in + toRead == (off_t)con->request.content_length) {
7262 /* we read everything, close the chunk */
7263 close(dst_c->file.fd);
7264 @@ -1102,7 +981,7 @@
7265 b = chunkqueue_get_append_buffer(dst_cq);
7266 buffer_copy_string_len(b, c->mem->ptr + c->offset, toRead);
7270 c->offset += toRead;
7271 dst_cq->bytes_in += toRead;
7273 @@ -1111,7 +990,7 @@
7274 if (dst_cq->bytes_in == (off_t)con->request.content_length) {
7275 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7282 @@ -1123,100 +1002,104 @@
7283 handler_t connection_handle_fdevent(void *s, void *context, int revents) {
7284 server *srv = (server *)s;
7285 connection *con = context;
7288 joblist_append(srv, con);
7291 if (revents & FDEVENT_IN) {
7292 con->is_readable = 1;
7294 - log_error_write(srv, __FILE__, __LINE__, "sd", "read-wait - done", con->fd);
7297 if (revents & FDEVENT_OUT) {
7298 con->is_writable = 1;
7299 /* we don't need the event twice */
7305 if (revents & ~(FDEVENT_IN | FDEVENT_OUT)) {
7306 /* looks like an error */
7309 /* FIXME: revents = 0x19 still means that we should read from the queue */
7310 if (revents & FDEVENT_HUP) {
7311 if (con->state == CON_STATE_CLOSE) {
7312 con->close_timeout_ts = 0;
7314 /* sigio reports the wrong event here
7316 - * there was no HUP at all
7318 + * there was no HUP at all
7320 #ifdef USE_LINUX_SIGIO
7321 if (srv->ev->in_sigio == 1) {
7322 log_error_write(srv, __FILE__, __LINE__, "sd",
7323 - "connection closed: poll() -> HUP", con->fd);
7324 + "connection closed: poll() -> HUP", con->sock->fd);
7326 connection_set_state(srv, con, CON_STATE_ERROR);
7329 connection_set_state(srv, con, CON_STATE_ERROR);
7334 } else if (revents & FDEVENT_ERR) {
7335 #ifndef USE_LINUX_SIGIO
7336 log_error_write(srv, __FILE__, __LINE__, "sd",
7337 - "connection closed: poll() -> ERR", con->fd);
7339 + "connection closed: poll() -> ERR", con->sock->fd);
7341 connection_set_state(srv, con, CON_STATE_ERROR);
7343 log_error_write(srv, __FILE__, __LINE__, "sd",
7344 "connection closed: poll() -> ???", revents);
7350 if (con->state == CON_STATE_READ ||
7351 con->state == CON_STATE_READ_POST) {
7352 connection_handle_read_state(srv, con);
7354 + * if SSL_read() is not readin in the full packet we won't get
7355 + * a fdevent as the low-level has already fetched everything.
7357 + * we have to call the state-engine to read the rest of the packet
7359 + if (con->is_readable) joblist_append(srv, con);
7363 if (con->state == CON_STATE_WRITE &&
7364 !chunkqueue_is_empty(con->write_queue) &&
7368 if (-1 == connection_handle_write(srv, con)) {
7369 connection_set_state(srv, con, CON_STATE_ERROR);
7372 log_error_write(srv, __FILE__, __LINE__, "ds",
7375 "handle write failed.");
7376 } else if (con->state == CON_STATE_WRITE) {
7377 con->write_request_ts = srv->cur_ts;
7382 if (con->state == CON_STATE_CLOSE) {
7383 /* flush the read buffers */
7386 - if (ioctl(con->fd, FIONREAD, &b)) {
7388 + if (ioctl(con->sock->fd, FIONREAD, &b)) {
7389 log_error_write(srv, __FILE__, __LINE__, "ss",
7390 "ioctl() failed", strerror(errno));
7396 log_error_write(srv, __FILE__, __LINE__, "sdd",
7397 - "CLOSE-read()", con->fd, b);
7399 + "CLOSE-read()", con->sock->fd, b);
7402 - read(con->fd, buf, sizeof(buf));
7403 + read(con->sock->fd, buf, sizeof(buf));
7405 /* nothing to read */
7408 con->close_timeout_ts = 0;
7413 return HANDLER_FINISHED;
7416 @@ -1229,63 +1112,68 @@
7419 /* accept it and register the fd */
7422 cnt_len = sizeof(cnt_addr);
7424 - if (-1 == (cnt = accept(srv_socket->fd, (struct sockaddr *) &cnt_addr, &cnt_len))) {
7425 + if (-1 == (cnt = accept(srv_socket->sock->fd, (struct sockaddr *) &cnt_addr, &cnt_len))) {
7427 + errno = WSAGetLastError();
7429 if ((errno != EAGAIN) &&
7430 + (errno != EWOULDBLOCK) &&
7432 - log_error_write(srv, __FILE__, __LINE__, "ssd", "accept failed:", strerror(errno), errno);
7433 + log_error_write(srv, __FILE__, __LINE__, "ssd", "accept failed:", strerror(errno), srv_socket->sock->fd);
7443 /* ok, we have the connection, register it */
7445 log_error_write(srv, __FILE__, __LINE__, "sd",
7451 con = connections_get_new_connection(srv);
7454 - con->fde_ndx = -1;
7456 + con->sock->fd = cnt;
7457 + con->sock->fde_ndx = -1;
7459 gettimeofday(&(con->start_tv), NULL);
7461 - fdevent_register(srv->ev, con->fd, connection_handle_fdevent, con);
7464 + fdevent_register(srv->ev, con->sock, connection_handle_fdevent, con);
7466 connection_set_state(srv, con, CON_STATE_REQUEST_START);
7469 con->connection_start = srv->cur_ts;
7470 con->dst_addr = cnt_addr;
7471 buffer_copy_string(con->dst_addr_buf, inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
7472 con->srv_socket = srv_socket;
7474 - if (-1 == (fdevent_fcntl_set(srv->ev, con->fd))) {
7476 + if (-1 == (fdevent_fcntl_set(srv->ev, con->sock))) {
7477 log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
7478 + connection_close(srv, con);
7482 /* connect FD to SSL */
7483 if (srv_socket->is_ssl) {
7484 - if (NULL == (con->ssl = SSL_new(srv_socket->ssl_ctx))) {
7485 - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
7486 + if (NULL == (con->sock->ssl = SSL_new(srv_socket->ssl_ctx))) {
7487 + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
7488 ERR_error_string(ERR_get_error(), NULL));
7490 + connection_close(srv, con);
7494 - SSL_set_accept_state(con->ssl);
7496 + SSL_set_accept_state(con->sock->ssl);
7499 - if (1 != (SSL_set_fd(con->ssl, cnt))) {
7500 - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
7502 + if (1 != (SSL_set_fd(con->sock->ssl, cnt))) {
7503 + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
7504 ERR_error_string(ERR_get_error(), NULL));
7505 + connection_close(srv, con);
7509 @@ -1300,102 +1188,102 @@
7511 server_socket *srv_sock = con->srv_socket;
7515 if (srv->srvconf.log_state_handling) {
7516 - log_error_write(srv, __FILE__, __LINE__, "sds",
7519 + log_error_write(srv, __FILE__, __LINE__, "sds",
7522 connection_get_state(con->state));
7526 size_t ostate = con->state;
7530 switch (con->state) {
7531 case CON_STATE_REQUEST_START: /* transient */
7532 if (srv->srvconf.log_state_handling) {
7533 - log_error_write(srv, __FILE__, __LINE__, "sds",
7534 - "state for fd", con->fd, connection_get_state(con->state));
7535 + log_error_write(srv, __FILE__, __LINE__, "sds",
7536 + "state for fd", con->sock->fd, connection_get_state(con->state));
7540 con->request_start = srv->cur_ts;
7541 con->read_idle_ts = srv->cur_ts;
7544 con->request_count++;
7545 con->loops_per_request = 0;
7548 connection_set_state(srv, con, CON_STATE_READ);
7552 case CON_STATE_REQUEST_END: /* transient */
7553 if (srv->srvconf.log_state_handling) {
7554 - log_error_write(srv, __FILE__, __LINE__, "sds",
7555 - "state for fd", con->fd, connection_get_state(con->state));
7556 + log_error_write(srv, __FILE__, __LINE__, "sds",
7557 + "state for fd", con->sock->fd, connection_get_state(con->state));
7561 if (http_request_parse(srv, con)) {
7562 /* we have to read some data from the POST request */
7565 connection_set_state(srv, con, CON_STATE_READ_POST);
7571 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7575 case CON_STATE_HANDLE_REQUEST:
7578 * the request is parsed
7581 * decided what to do with the request
7591 if (srv->srvconf.log_state_handling) {
7592 - log_error_write(srv, __FILE__, __LINE__, "sds",
7593 - "state for fd", con->fd, connection_get_state(con->state));
7594 + log_error_write(srv, __FILE__, __LINE__, "sds",
7595 + "state for fd", con->sock->fd, connection_get_state(con->state));
7599 switch (r = http_response_prepare(srv, con)) {
7600 case HANDLER_FINISHED:
7601 if (con->http_status == 404 ||
7602 con->http_status == 403) {
7603 /* 404 error-handler */
7605 - if (con->in_error_handler == 0 &&
7607 + if (con->in_error_handler == 0 &&
7608 (!buffer_is_empty(con->conf.error_handler) ||
7609 !buffer_is_empty(con->error_handler))) {
7610 /* call error-handler */
7613 con->error_handler_saved_status = con->http_status;
7614 con->http_status = 0;
7617 if (buffer_is_empty(con->error_handler)) {
7618 buffer_copy_string_buffer(con->request.uri, con->conf.error_handler);
7620 buffer_copy_string_buffer(con->request.uri, con->error_handler);
7622 buffer_reset(con->physical.path);
7625 con->in_error_handler = 1;
7628 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7633 } else if (con->in_error_handler) {
7634 /* error-handler is a 404 */
7637 /* continue as normal, status is the same */
7638 - log_error_write(srv, __FILE__, __LINE__, "sb",
7639 + log_error_write(srv, __FILE__, __LINE__, "sb",
7640 "Warning: Either the error-handler returned status 404 or the error-handler itself was not found:", con->request.uri);
7641 - log_error_write(srv, __FILE__, __LINE__, "sd",
7642 + log_error_write(srv, __FILE__, __LINE__, "sd",
7643 "returning the original status", con->error_handler_saved_status);
7644 - log_error_write(srv, __FILE__, __LINE__, "s",
7645 + log_error_write(srv, __FILE__, __LINE__, "s",
7646 "If this is a rails app: check your production.log");
7647 con->http_status = con->error_handler_saved_status;
7649 @@ -1403,73 +1291,73 @@
7650 /* error-handler is back and has generated content */
7651 /* if Status: was set, take it otherwise use 200 */
7655 if (con->http_status == 0) con->http_status = 200;
7658 /* we have something to send, go on */
7659 connection_set_state(srv, con, CON_STATE_RESPONSE_START);
7661 case HANDLER_WAIT_FOR_FD:
7665 fdwaitqueue_append(srv, con);
7668 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7672 case HANDLER_COMEBACK:
7674 case HANDLER_WAIT_FOR_EVENT:
7675 /* come back here */
7676 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
7681 /* something went wrong */
7682 connection_set_state(srv, con, CON_STATE_ERROR);
7685 - log_error_write(srv, __FILE__, __LINE__, "sdd", "unknown ret-value: ", con->fd, r);
7686 + log_error_write(srv, __FILE__, __LINE__, "sdd", "unknown ret-value: ", con->sock->fd, r);
7692 case CON_STATE_RESPONSE_START:
7695 * the decision is done
7696 * - create the HTTP-Response-Header
7702 if (srv->srvconf.log_state_handling) {
7703 - log_error_write(srv, __FILE__, __LINE__, "sds",
7704 - "state for fd", con->fd, connection_get_state(con->state));
7705 + log_error_write(srv, __FILE__, __LINE__, "sds",
7706 + "state for fd", con->sock->fd, connection_get_state(con->state));
7710 if (-1 == connection_handle_write_prepare(srv, con)) {
7711 connection_set_state(srv, con, CON_STATE_ERROR);
7718 connection_set_state(srv, con, CON_STATE_WRITE);
7720 case CON_STATE_RESPONSE_END: /* transient */
7721 /* log the request */
7724 if (srv->srvconf.log_state_handling) {
7725 - log_error_write(srv, __FILE__, __LINE__, "sds",
7726 - "state for fd", con->fd, connection_get_state(con->state));
7727 + log_error_write(srv, __FILE__, __LINE__, "sds",
7728 + "state for fd", con->sock->fd, connection_get_state(con->state));
7732 plugins_call_handle_request_done(srv, con);
7738 if (con->keep_alive) {
7739 connection_set_state(srv, con, CON_STATE_REQUEST_START);
7744 con->request_start = srv->cur_ts;
7745 con->read_idle_ts = srv->cur_ts;
7747 @@ -1482,103 +1370,103 @@
7748 log_error_write(srv, __FILE__, __LINE__, "sd", "unhandling return value", r);
7754 if (srv_sock->is_ssl) {
7755 - switch (SSL_shutdown(con->ssl)) {
7756 + switch (SSL_shutdown(con->sock->ssl)) {
7761 - /* wait for fd-event
7763 + /* wait for fd-event
7765 * FIXME: wait for fdevent and call SSL_shutdown again
7773 - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
7774 + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
7775 ERR_error_string(ERR_get_error(), NULL));
7779 connection_close(srv, con);
7786 connection_reset(srv, con);
7790 case CON_STATE_CONNECT:
7791 if (srv->srvconf.log_state_handling) {
7792 - log_error_write(srv, __FILE__, __LINE__, "sds",
7793 - "state for fd", con->fd, connection_get_state(con->state));
7794 + log_error_write(srv, __FILE__, __LINE__, "sds",
7795 + "state for fd", con->sock->fd, connection_get_state(con->state));
7799 chunkqueue_reset(con->read_queue);
7802 con->request_count = 0;
7806 case CON_STATE_CLOSE:
7807 if (srv->srvconf.log_state_handling) {
7808 - log_error_write(srv, __FILE__, __LINE__, "sds",
7809 - "state for fd", con->fd, connection_get_state(con->state));
7810 + log_error_write(srv, __FILE__, __LINE__, "sds",
7811 + "state for fd", con->sock->fd, connection_get_state(con->state));
7815 if (con->keep_alive) {
7816 - if (ioctl(con->fd, FIONREAD, &b)) {
7817 + if (ioctl(con->sock->fd, FIONREAD, &b)) {
7818 log_error_write(srv, __FILE__, __LINE__, "ss",
7819 "ioctl() failed", strerror(errno));
7823 log_error_write(srv, __FILE__, __LINE__, "sdd",
7824 - "CLOSE-read()", con->fd, b);
7826 + "CLOSE-read()", con->sock->fd, b);
7829 - read(con->fd, buf, sizeof(buf));
7830 + read(con->sock->fd, buf, sizeof(buf));
7832 /* nothing to read */
7835 con->close_timeout_ts = 0;
7838 con->close_timeout_ts = 0;
7842 if (srv->cur_ts - con->close_timeout_ts > 1) {
7843 connection_close(srv, con);
7846 if (srv->srvconf.log_state_handling) {
7847 - log_error_write(srv, __FILE__, __LINE__, "sd",
7848 - "connection closed for fd", con->fd);
7849 + log_error_write(srv, __FILE__, __LINE__, "sd",
7850 + "connection closed for fd", con->sock->fd);
7856 case CON_STATE_READ_POST:
7857 case CON_STATE_READ:
7858 if (srv->srvconf.log_state_handling) {
7859 - log_error_write(srv, __FILE__, __LINE__, "sds",
7860 - "state for fd", con->fd, connection_get_state(con->state));
7861 + log_error_write(srv, __FILE__, __LINE__, "sds",
7862 + "state for fd", con->sock->fd, connection_get_state(con->state));
7866 connection_handle_read_state(srv, con);
7868 case CON_STATE_WRITE:
7869 if (srv->srvconf.log_state_handling) {
7870 - log_error_write(srv, __FILE__, __LINE__, "sds",
7871 - "state for fd", con->fd, connection_get_state(con->state));
7872 + log_error_write(srv, __FILE__, __LINE__, "sds",
7873 + "state for fd", con->sock->fd, connection_get_state(con->state));
7877 /* only try to write if we have something in the queue */
7878 if (!chunkqueue_is_empty(con->write_queue)) {
7880 log_error_write(srv, __FILE__, __LINE__, "dsd",
7883 "packets to write:",
7884 con->write_queue->used);
7886 @@ -1586,17 +1474,17 @@
7887 if (!chunkqueue_is_empty(con->write_queue) && con->is_writable) {
7888 if (-1 == connection_handle_write(srv, con)) {
7889 log_error_write(srv, __FILE__, __LINE__, "ds",
7892 "handle write failed.");
7893 connection_set_state(srv, con, CON_STATE_ERROR);
7894 } else if (con->state == CON_STATE_WRITE) {
7895 con->write_request_ts = srv->cur_ts;
7901 case CON_STATE_ERROR: /* transient */
7904 /* even if the connection was drop we still have to write it to the access log */
7905 if (con->http_status) {
7906 plugins_call_handle_request_done(srv, con);
7907 @@ -1604,28 +1492,28 @@
7909 if (srv_sock->is_ssl) {
7911 - switch ((ret = SSL_shutdown(con->ssl))) {
7912 + switch ((ret = SSL_shutdown(con->sock->ssl))) {
7917 - SSL_shutdown(con->ssl);
7918 + SSL_shutdown(con->sock->ssl);
7921 - log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
7922 - SSL_get_error(con->ssl, ret),
7923 + log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
7924 + SSL_get_error(con->sock->ssl, ret),
7925 ERR_error_string(ERR_get_error(), NULL));
7935 - log_error_write(srv, __FILE__, __LINE__, "sd",
7936 - "emergency exit: direct",
7938 + log_error_write(srv, __FILE__, __LINE__, "sd",
7939 + "emergency exit: direct",
7944 @@ -1639,35 +1527,35 @@
7950 connection_reset(srv, con);
7953 /* close the connection */
7954 if ((con->keep_alive == 1) &&
7955 - (0 == shutdown(con->fd, SHUT_WR))) {
7956 + (0 == shutdown(con->sock->fd, SHUT_WR))) {
7957 con->close_timeout_ts = srv->cur_ts;
7958 connection_set_state(srv, con, CON_STATE_CLOSE);
7961 if (srv->srvconf.log_state_handling) {
7962 - log_error_write(srv, __FILE__, __LINE__, "sd",
7963 - "shutdown for fd", con->fd);
7964 + log_error_write(srv, __FILE__, __LINE__, "sd",
7965 + "shutdown for fd", con->sock->fd);
7968 connection_close(srv, con);
7972 con->keep_alive = 0;
7980 - log_error_write(srv, __FILE__, __LINE__, "sdd",
7981 - "unknown state:", con->fd, con->state);
7983 + log_error_write(srv, __FILE__, __LINE__, "sdd",
7984 + "unknown state:", con->sock->fd, con->state);
7992 } else if (ostate == con->state) {
7993 @@ -1676,33 +1564,33 @@
7996 if (srv->srvconf.log_state_handling) {
7997 - log_error_write(srv, __FILE__, __LINE__, "sds",
8000 + log_error_write(srv, __FILE__, __LINE__, "sds",
8003 connection_get_state(con->state));
8007 switch(con->state) {
8008 case CON_STATE_READ_POST:
8009 case CON_STATE_READ:
8010 case CON_STATE_CLOSE:
8011 - fdevent_event_add(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_IN);
8012 + fdevent_event_add(srv->ev, con->sock, FDEVENT_IN);
8014 case CON_STATE_WRITE:
8015 - /* request write-fdevent only if we really need it
8016 + /* request write-fdevent only if we really need it
8017 * - if we have data to write
8018 - * - if the socket is not writable yet
8019 + * - if the socket is not writable yet
8021 - if (!chunkqueue_is_empty(con->write_queue) &&
8022 + if (!chunkqueue_is_empty(con->write_queue) &&
8023 (con->is_writable == 0) &&
8024 (con->traffic_limit_reached == 0)) {
8025 - fdevent_event_add(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_OUT);
8026 + fdevent_event_add(srv->ev, con->sock, FDEVENT_OUT);
8028 - fdevent_event_del(srv->ev, &(con->fde_ndx), con->fd);
8029 + fdevent_event_del(srv->ev, con->sock);
8033 - fdevent_event_del(srv->ev, &(con->fde_ndx), con->fd);
8034 + fdevent_event_del(srv->ev, con->sock);
8038 --- ../lighttpd-1.4.11/src/crc32.h 2005-09-30 20:18:59.000000000 +0300
8039 +++ lighttpd-1.4.12/src/crc32.h 2006-07-16 00:26:04.000000000 +0300
8043 #include <sys/types.h>
8044 +#include <stdlib.h>
8046 #if defined HAVE_STDINT_H
8049 #include <inttypes.h>
8053 +#define uint32_t unsigned __int32
8056 uint32_t generate_crc32c(char *string, size_t length);
8059 --- ../lighttpd-1.4.11/src/data_array.c 2005-08-23 17:36:12.000000000 +0300
8060 +++ lighttpd-1.4.12/src/data_array.c 2006-07-16 00:26:04.000000000 +0300
8063 static void data_array_free(data_unset *d) {
8064 data_array *ds = (data_array *)d;
8067 buffer_free(ds->key);
8068 array_free(ds->value);
8074 static void data_array_reset(data_unset *d) {
8075 data_array *ds = (data_array *)d;
8078 /* reused array elements */
8079 buffer_reset(ds->key);
8080 array_reset(ds->value);
8092 data_array *data_array_init(void) {
8096 ds = calloc(1, sizeof(*ds));
8099 ds->key = buffer_init();
8100 ds->value = array_init();
8103 ds->copy = data_array_copy;
8104 ds->free = data_array_free;
8105 ds->reset = data_array_reset;
8106 ds->insert_dup = data_array_insert_dup;
8107 ds->print = data_array_print;
8108 ds->type = TYPE_ARRAY;
8113 --- ../lighttpd-1.4.11/src/data_config.c 2005-08-17 12:53:19.000000000 +0300
8114 +++ lighttpd-1.4.12/src/data_config.c 2006-07-16 00:26:03.000000000 +0300
8117 static void data_config_free(data_unset *d) {
8118 data_config *ds = (data_config *)d;
8121 buffer_free(ds->key);
8122 buffer_free(ds->op);
8123 buffer_free(ds->comp_key);
8126 array_free(ds->value);
8127 array_free(ds->childs);
8130 if (ds->string) buffer_free(ds->string);
8132 if (ds->regex) pcre_free(ds->regex);
8133 if (ds->regex_study) pcre_free(ds->regex_study);
8140 static void data_config_reset(data_unset *d) {
8141 data_config *ds = (data_config *)d;
8144 /* reused array elements */
8145 buffer_reset(ds->key);
8146 buffer_reset(ds->comp_key);
8149 static int data_config_insert_dup(data_unset *dst, data_unset *src) {
8160 array *a = (array *)ds->value;
8165 if (0 == ds->context_ndx) {
8166 fprintf(stderr, "config {\n");
8168 @@ -117,22 +117,22 @@
8170 data_config *data_config_init(void) {
8174 ds = calloc(1, sizeof(*ds));
8177 ds->key = buffer_init();
8178 ds->op = buffer_init();
8179 ds->comp_key = buffer_init();
8180 ds->value = array_init();
8181 ds->childs = array_init();
8182 ds->childs->is_weakref = 1;
8185 ds->copy = data_config_copy;
8186 ds->free = data_config_free;
8187 ds->reset = data_config_reset;
8188 ds->insert_dup = data_config_insert_dup;
8189 ds->print = data_config_print;
8190 ds->type = TYPE_CONFIG;
8195 --- ../lighttpd-1.4.11/src/data_count.c 2005-08-23 17:36:12.000000000 +0300
8196 +++ lighttpd-1.4.12/src/data_count.c 2006-07-16 00:26:03.000000000 +0300
8199 static void data_count_free(data_unset *d) {
8200 data_count *ds = (data_count *)d;
8203 buffer_free(ds->key);
8209 static void data_count_reset(data_unset *d) {
8210 data_count *ds = (data_count *)d;
8213 buffer_reset(ds->key);
8219 static int data_count_insert_dup(data_unset *dst, data_unset *src) {
8220 data_count *ds_dst = (data_count *)dst;
8221 data_count *ds_src = (data_count *)src;
8224 ds_dst->count += ds_src->count;
8233 static void data_count_print(const data_unset *d, int depth) {
8234 data_count *ds = (data_count *)d;
8238 fprintf(stderr, "count(%d)", ds->count);
8242 data_count *data_count_init(void) {
8246 ds = calloc(1, sizeof(*ds));
8249 ds->key = buffer_init();
8253 ds->copy = data_count_copy;
8254 ds->free = data_count_free;
8255 ds->reset = data_count_reset;
8256 ds->insert_dup = data_count_insert_dup;
8257 ds->print = data_count_print;
8258 ds->type = TYPE_COUNT;
8263 --- ../lighttpd-1.4.11/src/data_fastcgi.c 2005-08-23 17:36:12.000000000 +0300
8264 +++ lighttpd-1.4.12/src/data_fastcgi.c 2006-07-16 00:26:04.000000000 +0300
8267 static void data_fastcgi_free(data_unset *d) {
8268 data_fastcgi *ds = (data_fastcgi *)d;
8271 buffer_free(ds->key);
8272 buffer_free(ds->host);
8278 static void data_fastcgi_reset(data_unset *d) {
8279 data_fastcgi *ds = (data_fastcgi *)d;
8282 buffer_reset(ds->key);
8283 buffer_reset(ds->host);
8288 static int data_fastcgi_insert_dup(data_unset *dst, data_unset *src) {
8297 static void data_fastcgi_print(const data_unset *d, int depth) {
8298 data_fastcgi *ds = (data_fastcgi *)d;
8302 fprintf(stderr, "fastcgi(%s)", ds->host->ptr);
8306 data_fastcgi *data_fastcgi_init(void) {
8310 ds = calloc(1, sizeof(*ds));
8313 ds->key = buffer_init();
8314 ds->host = buffer_init();
8316 ds->is_disabled = 0;
8319 ds->copy = data_fastcgi_copy;
8320 ds->free = data_fastcgi_free;
8321 ds->reset = data_fastcgi_reset;
8322 ds->insert_dup = data_fastcgi_insert_dup;
8323 ds->print = data_fastcgi_print;
8324 ds->type = TYPE_FASTCGI;
8329 --- ../lighttpd-1.4.11/src/data_integer.c 2005-08-23 17:36:12.000000000 +0300
8330 +++ lighttpd-1.4.12/src/data_integer.c 2006-07-16 00:26:03.000000000 +0300
8333 static void data_integer_free(data_unset *d) {
8334 data_integer *ds = (data_integer *)d;
8337 buffer_free(ds->key);
8343 static void data_integer_reset(data_unset *d) {
8344 data_integer *ds = (data_integer *)d;
8347 /* reused integer elements */
8348 buffer_reset(ds->key);
8352 static int data_integer_insert_dup(data_unset *dst, data_unset *src) {
8364 data_integer *data_integer_init(void) {
8368 ds = calloc(1, sizeof(*ds));
8371 ds->key = buffer_init();
8375 ds->copy = data_integer_copy;
8376 ds->free = data_integer_free;
8377 ds->reset = data_integer_reset;
8378 ds->insert_dup = data_integer_insert_dup;
8379 ds->print = data_integer_print;
8380 ds->type = TYPE_INTEGER;
8385 --- ../lighttpd-1.4.11/src/data_string.c 2005-08-23 17:36:12.000000000 +0300
8386 +++ lighttpd-1.4.12/src/data_string.c 2006-07-16 00:26:04.000000000 +0300
8389 static void data_string_free(data_unset *d) {
8390 data_string *ds = (data_string *)d;
8393 buffer_free(ds->key);
8394 buffer_free(ds->value);
8400 static void data_string_reset(data_unset *d) {
8401 data_string *ds = (data_string *)d;
8404 /* reused array elements */
8405 buffer_reset(ds->key);
8406 buffer_reset(ds->value);
8408 static int data_string_insert_dup(data_unset *dst, data_unset *src) {
8409 data_string *ds_dst = (data_string *)dst;
8410 data_string *ds_src = (data_string *)src;
8413 if (ds_dst->value->used) {
8414 buffer_append_string(ds_dst->value, ", ");
8415 buffer_append_string_buffer(ds_dst->value, ds_src->value);
8417 buffer_copy_string_buffer(ds_dst->value, ds_src->value);
8427 static int data_response_insert_dup(data_unset *dst, data_unset *src) {
8428 data_string *ds_dst = (data_string *)dst;
8429 data_string *ds_src = (data_string *)src;
8432 if (ds_dst->value->used) {
8433 buffer_append_string(ds_dst->value, "\r\n");
8434 buffer_append_string_buffer(ds_dst->value, ds_dst->key);
8437 buffer_copy_string_buffer(ds_dst->value, ds_src->value);
8449 data_string *data_string_init(void) {
8453 ds = calloc(1, sizeof(*ds));
8457 ds->key = buffer_init();
8458 ds->value = buffer_init();
8461 ds->copy = data_string_copy;
8462 ds->free = data_string_free;
8463 ds->reset = data_string_reset;
8464 ds->insert_dup = data_string_insert_dup;
8465 ds->print = data_string_print;
8466 ds->type = TYPE_STRING;
8472 data_string *data_response_init(void) {
8476 ds = data_string_init();
8477 ds->insert_dup = data_response_insert_dup;
8482 --- ../lighttpd-1.4.11/src/etag.c 2005-08-11 01:26:40.000000000 +0300
8483 +++ lighttpd-1.4.12/src/etag.c 2006-07-18 13:03:40.000000000 +0300
8487 int etag_is_equal(buffer *etag, const char *matches) {
8488 - if (0 == strcmp(etag->ptr, matches)) return 1;
8489 + if (buffer_is_equal_string(etag, matches, strlen(matches))) return 1;
8494 buffer_append_off_t(etag, st->st_size);
8495 buffer_append_string_len(etag, CONST_STR_LEN("-"));
8496 buffer_append_long(etag, st->st_mtime);
8502 int etag_mutate(buffer *mut, buffer *etag) {
8506 for (h=0, i=0; i < etag->used; ++i) h = (h<<5)^(h>>27)^(etag->ptr[i]);
8510 buffer_copy_string_len(mut, CONST_STR_LEN("\""));
8511 buffer_append_long(mut, h);
8512 buffer_append_string_len(mut, CONST_STR_LEN("\""));
8517 --- ../lighttpd-1.4.11/src/etag.h 2005-08-11 01:26:40.000000000 +0300
8518 +++ lighttpd-1.4.12/src/etag.h 2006-07-16 00:26:03.000000000 +0300
8521 #include <sys/types.h>
8522 #include <sys/stat.h>
8523 -#include <unistd.h>
8527 int etag_is_equal(buffer *etag, const char *matches);
8528 int etag_create(buffer *etag, struct stat *st);
8529 int etag_mutate(buffer *mut, buffer *etag);
8534 --- ../lighttpd-1.4.11/src/fastcgi.h 2005-08-11 01:26:40.000000000 +0300
8535 +++ lighttpd-1.4.12/src/fastcgi.h 2006-07-16 00:26:03.000000000 +0300
8541 * Defines for the FastCGI protocol.
8546 - unsigned char type;
8547 + unsigned char type;
8548 unsigned char reserved[7];
8549 } FCGI_UnknownTypeBody;
8551 --- ../lighttpd-1.4.11/src/fdevent.c 2005-11-15 10:51:05.000000000 +0200
8552 +++ lighttpd-1.4.12/src/fdevent.c 2006-07-18 13:03:40.000000000 +0300
8555 #include "settings.h"
8557 -#include <unistd.h>
8561 @@ -11,60 +10,116 @@
8563 #include "fdevent.h"
8567 +#include "sys-socket.h"
8569 +fdevent_revent *fdevent_revent_init(void) {
8570 + STRUCT_INIT(fdevent_revent, revent);
8575 +void fdevent_revent_free(fdevent_revent *revent) {
8576 + if (!revent) return;
8581 +fdevent_revents *fdevent_revents_init(void) {
8582 + STRUCT_INIT(fdevent_revents, revents);
8587 +void fdevent_revents_reset(fdevent_revents *revents) {
8588 + if (!revents) return;
8590 + revents->used = 0;
8593 +void fdevent_revents_add(fdevent_revents *revents, int fd, int events) {
8594 + fdevent_revent *revent;
8596 + if (revents->used == revents->size) {
8597 + /* resize the events-array */
8598 + revents->ptr = realloc(revents->ptr, (revents->size + 1) * sizeof(*(revents->ptr)));
8599 + revents->ptr[revents->size++] = fdevent_revent_init();
8602 + revent = revents->ptr[revents->used++];
8604 + revent->revents = events;
8607 +void fdevent_revents_free(fdevent_revents *revents) {
8610 + if (!revents) return;
8612 + if (revents->size) {
8613 + for (i = 0; i < revents->size; i++) {
8614 + fdevent_revent_free(revents->ptr[i]);
8617 + free(revents->ptr);
8622 fdevents *fdevent_init(size_t maxfds, fdevent_handler_t type) {
8626 ev = calloc(1, sizeof(*ev));
8627 ev->fdarray = calloc(maxfds, sizeof(*ev->fdarray));
8628 ev->maxfds = maxfds;
8632 case FDEVENT_HANDLER_POLL:
8633 if (0 != fdevent_poll_init(ev)) {
8634 - fprintf(stderr, "%s.%d: event-handler poll failed\n",
8635 + fprintf(stderr, "%s.%d: event-handler poll failed\n",
8636 __FILE__, __LINE__);
8642 case FDEVENT_HANDLER_SELECT:
8643 if (0 != fdevent_select_init(ev)) {
8644 - fprintf(stderr, "%s.%d: event-handler select failed\n",
8645 + fprintf(stderr, "%s.%d: event-handler select failed\n",
8646 __FILE__, __LINE__);
8650 case FDEVENT_HANDLER_LINUX_RTSIG:
8651 if (0 != fdevent_linux_rtsig_init(ev)) {
8652 - fprintf(stderr, "%s.%d: event-handler linux-rtsig failed, try to set server.event-handler = \"poll\" or \"select\"\n",
8653 + fprintf(stderr, "%s.%d: event-handler linux-rtsig failed, try to set server.event-handler = \"poll\" or \"select\"\n",
8654 __FILE__, __LINE__);
8658 case FDEVENT_HANDLER_LINUX_SYSEPOLL:
8659 if (0 != fdevent_linux_sysepoll_init(ev)) {
8660 - fprintf(stderr, "%s.%d: event-handler linux-sysepoll failed, try to set server.event-handler = \"poll\" or \"select\"\n",
8661 + fprintf(stderr, "%s.%d: event-handler linux-sysepoll failed, try to set server.event-handler = \"poll\" or \"select\"\n",
8662 __FILE__, __LINE__);
8666 case FDEVENT_HANDLER_SOLARIS_DEVPOLL:
8667 if (0 != fdevent_solaris_devpoll_init(ev)) {
8668 - fprintf(stderr, "%s.%d: event-handler solaris-devpoll failed, try to set server.event-handler = \"poll\" or \"select\"\n",
8669 + fprintf(stderr, "%s.%d: event-handler solaris-devpoll failed, try to set server.event-handler = \"poll\" or \"select\"\n",
8670 __FILE__, __LINE__);
8674 case FDEVENT_HANDLER_FREEBSD_KQUEUE:
8675 if (0 != fdevent_freebsd_kqueue_init(ev)) {
8676 - fprintf(stderr, "%s.%d: event-handler freebsd-kqueue failed, try to set server.event-handler = \"poll\" or \"select\"\n",
8677 + fprintf(stderr, "%s.%d: event-handler freebsd-kqueue failed, try to set server.event-handler = \"poll\" or \"select\"\n",
8678 __FILE__, __LINE__);
8683 - fprintf(stderr, "%s.%d: event-handler is unknown, try to set server.event-handler = \"poll\" or \"select\"\n",
8684 + fprintf(stderr, "%s.%d: event-handler is unknown, try to set server.event-handler = \"poll\" or \"select\"\n",
8685 __FILE__, __LINE__);
8688 @@ -75,28 +130,29 @@
8689 void fdevent_free(fdevents *ev) {
8694 if (ev->free) ev->free(ev);
8697 for (i = 0; i < ev->maxfds; i++) {
8698 if (ev->fdarray[i]) free(ev->fdarray[i]);
8706 int fdevent_reset(fdevents *ev) {
8707 if (ev->reset) return ev->reset(ev);
8713 fdnode *fdnode_init() {
8717 fdn = calloc(1, sizeof(*fdn));
8723 @@ -104,48 +160,40 @@
8727 -int fdevent_register(fdevents *ev, int fd, fdevent_handler handler, void *ctx) {
8728 +int fdevent_register(fdevents *ev, iosocket *sock, fdevent_handler handler, void *ctx) {
8732 fdn = fdnode_init();
8733 fdn->handler = handler;
8735 + fdn->fd = sock->fd;
8738 - ev->fdarray[fd] = fdn;
8740 + ev->fdarray[sock->fd] = fdn;
8745 -int fdevent_unregister(fdevents *ev, int fd) {
8746 +int fdevent_unregister(fdevents *ev, iosocket *sock) {
8749 - fdn = ev->fdarray[fd];
8751 + fdn = ev->fdarray[sock->fd];
8755 - ev->fdarray[fd] = NULL;
8758 + ev->fdarray[sock->fd] = NULL;
8763 -int fdevent_event_del(fdevents *ev, int *fde_ndx, int fd) {
8764 - int fde = fde_ndx ? *fde_ndx : -1;
8766 - if (ev->event_del) fde = ev->event_del(ev, fde, fd);
8768 - if (fde_ndx) *fde_ndx = fde;
8770 +int fdevent_event_del(fdevents *ev, iosocket *sock) {
8771 + if (ev->event_del) ev->event_del(ev, sock);
8776 -int fdevent_event_add(fdevents *ev, int *fde_ndx, int fd, int events) {
8777 - int fde = fde_ndx ? *fde_ndx : -1;
8779 - if (ev->event_add) fde = ev->event_add(ev, fde, fd, events);
8781 - if (fde_ndx) *fde_ndx = fde;
8783 +int fdevent_event_add(fdevents *ev, iosocket *sock, int events) {
8784 + if (ev->event_add) ev->event_add(ev, sock, events);
8789 @@ -154,49 +202,41 @@
8790 return ev->poll(ev, timeout_ms);
8793 -int fdevent_event_get_revent(fdevents *ev, size_t ndx) {
8794 - if (ev->event_get_revent == NULL) SEGFAULT();
8796 - return ev->event_get_revent(ev, ndx);
8798 +int fdevent_get_revents(fdevents *ev, size_t event_count, fdevent_revents *revents) {
8801 -int fdevent_event_get_fd(fdevents *ev, size_t ndx) {
8802 - if (ev->event_get_fd == NULL) SEGFAULT();
8804 - return ev->event_get_fd(ev, ndx);
8806 + if (ev->get_revents == NULL) SEGFAULT();
8808 -fdevent_handler fdevent_get_handler(fdevents *ev, int fd) {
8809 - if (ev->fdarray[fd] == NULL) SEGFAULT();
8810 - if (ev->fdarray[fd]->fd != fd) SEGFAULT();
8812 - return ev->fdarray[fd]->handler;
8814 + fdevent_revents_reset(revents);
8816 -void * fdevent_get_context(fdevents *ev, int fd) {
8817 - if (ev->fdarray[fd] == NULL) SEGFAULT();
8818 - if (ev->fdarray[fd]->fd != fd) SEGFAULT();
8820 - return ev->fdarray[fd]->ctx;
8821 + ev->get_revents(ev, event_count, revents);
8823 + /* patch the event handlers */
8824 + for (i = 0; i < event_count; i++) {
8825 + fdevent_revent *r = revents->ptr[i];
8827 + r->handler = ev->fdarray[r->fd]->handler;
8828 + r->context = ev->fdarray[r->fd]->ctx;
8834 -int fdevent_fcntl_set(fdevents *ev, int fd) {
8835 +int fdevent_fcntl_set(fdevents *ev, iosocket *sock) {
8840 /* close fd on exec (cgi) */
8841 - fcntl(fd, F_SETFD, FD_CLOEXEC);
8842 + fcntl(sock->fd, F_SETFD, FD_CLOEXEC);
8844 - if ((ev) && (ev->fcntl_set)) return ev->fcntl_set(ev, fd);
8846 - return fcntl(fd, F_SETFL, O_NONBLOCK | O_RDWR);
8847 + if ((ev) && (ev->fcntl_set)) return ev->fcntl_set(ev, sock->fd);
8849 + return fcntl(sock->fd, F_SETFL, O_NONBLOCK | O_RDWR);
8850 +#elif defined _WIN32
8851 + return ioctlsocket(sock->fd, FIONBIO, &i);
8858 -int fdevent_event_next_fdndx(fdevents *ev, int ndx) {
8859 - if (ev->event_next_fdndx) return ev->event_next_fdndx(ev, ndx);
8864 --- ../lighttpd-1.4.11/src/fdevent.h 2005-09-27 11:26:33.000000000 +0300
8865 +++ lighttpd-1.4.12/src/fdevent.h 2006-07-18 13:03:40.000000000 +0300
8867 #include "settings.h"
8870 +#include "iosocket.h"
8871 +#include "array-static.h"
8873 /* select event-system */
8875 #if defined(HAVE_EPOLL_CTL) && defined(HAVE_SYS_EPOLL_H)
8877 # include <sys/epoll.h>
8880 -/* MacOS 10.3.x has poll.h under /usr/include/, all other unixes
8881 +/* MacOS 10.3.x has poll.h under /usr/include/, all other unixes
8882 * under /usr/include/sys/ */
8883 #if defined HAVE_POLL && (defined(HAVE_SYS_POLL_H) || defined(HAVE_POLL_H))
8889 # include <sys/poll.h>
8891 # if defined HAVE_SIGTIMEDWAIT && defined(__linux__)
8893 # include <signal.h>
8898 +# define HAVE_SELECT
8900 #if defined HAVE_SELECT
8903 # include <winsock2.h>
8907 #define FDEVENT_HUP BV(4)
8908 #define FDEVENT_NVAL BV(5)
8910 -typedef enum { FD_EVENT_TYPE_UNSET = -1,
8911 - FD_EVENT_TYPE_CONNECTION,
8912 - FD_EVENT_TYPE_FCGI_CONNECTION,
8913 - FD_EVENT_TYPE_DIRWATCH,
8914 - FD_EVENT_TYPE_CGI_CONNECTION
8915 +typedef enum { FD_EVENT_TYPE_UNSET = -1,
8916 + FD_EVENT_TYPE_CONNECTION,
8917 + FD_EVENT_TYPE_FCGI_CONNECTION,
8918 + FD_EVENT_TYPE_DIRWATCH,
8919 + FD_EVENT_TYPE_CGI_CONNECTION
8922 -typedef enum { FDEVENT_HANDLER_UNSET,
8923 +typedef enum { FDEVENT_HANDLER_UNSET,
8924 FDEVENT_HANDLER_SELECT,
8925 FDEVENT_HANDLER_POLL,
8926 FDEVENT_HANDLER_LINUX_RTSIG,
8930 * a mapping from fd to connection structure
8935 int fd; /**< the fd */
8936 @@ -96,43 +101,51 @@
8940 +ARRAY_STATIC_DEF(fd_conn_buffer, fd_conn, );
8954 + fdevent_handler handler;
8958 +ARRAY_STATIC_DEF(fdevent_revents, fdevent_revent, );
8961 * array of unused fd's
8966 typedef struct _fdnode {
8967 - fdevent_handler handler;
8971 + fdevent_handler handler; /* who handles the events for this fd */
8972 + void *ctx; /* opaque pointer which is passed as 3rd parameter to the handler */
8975 struct _fdnode *prev, *next;
8987 * fd-event handler for select(), poll() and rt-signals on Linux 2.4
8991 typedef struct fdevents {
8992 fdevent_handler_t type;
8996 + fdnode **fdarray; /* a list of fdnodes */
9000 #ifdef USE_LINUX_SIGIO
9003 @@ -146,21 +159,21 @@
9006 struct pollfd *pollfds;
9017 fd_set select_write;
9018 fd_set select_error;
9021 fd_set select_set_read;
9022 fd_set select_set_write;
9023 fd_set select_set_error;
9028 #ifdef USE_SOLARIS_DEVPOLL
9029 @@ -177,16 +190,13 @@
9031 int (*reset)(struct fdevents *ev);
9032 void (*free)(struct fdevents *ev);
9034 - int (*event_add)(struct fdevents *ev, int fde_ndx, int fd, int events);
9035 - int (*event_del)(struct fdevents *ev, int fde_ndx, int fd);
9036 - int (*event_get_revent)(struct fdevents *ev, size_t ndx);
9037 - int (*event_get_fd)(struct fdevents *ev, size_t ndx);
9039 - int (*event_next_fdndx)(struct fdevents *ev, int ndx);
9042 + int (*event_add)(struct fdevents *ev, iosocket *sock, int events);
9043 + int (*event_del)(struct fdevents *ev, iosocket *sock);
9044 + int (*get_revents)(struct fdevents *ev, size_t event_count, fdevent_revents *revents);
9046 int (*poll)(struct fdevents *ev, int timeout_ms);
9049 int (*fcntl_set)(struct fdevents *ev, int fd);
9052 @@ -194,22 +204,44 @@
9053 int fdevent_reset(fdevents *ev);
9054 void fdevent_free(fdevents *ev);
9056 -int fdevent_event_add(fdevents *ev, int *fde_ndx, int fd, int events);
9057 -int fdevent_event_del(fdevents *ev, int *fde_ndx, int fd);
9058 -int fdevent_event_get_revent(fdevents *ev, size_t ndx);
9059 -int fdevent_event_get_fd(fdevents *ev, size_t ndx);
9060 -fdevent_handler fdevent_get_handler(fdevents *ev, int fd);
9061 -void * fdevent_get_context(fdevents *ev, int fd);
9063 + * call the plugin for the number of available events
9065 +int fdevent_poll(fdevents *ev, int timeout_ms);
9067 + * get all available events
9069 +int fdevent_get_revents(fdevents *ev, size_t event_count, fdevent_revents *revents);
9071 -int fdevent_event_next_fdndx(fdevents *ev, int ndx);
9073 + * add or remove a fd to the handled-pool
9075 +int fdevent_register(fdevents *ev, iosocket *sock, fdevent_handler handler, void *ctx);
9076 +int fdevent_unregister(fdevents *ev, iosocket *sock);
9078 -int fdevent_poll(fdevents *ev, int timeout_ms);
9080 + * add a event to a registered fd
9082 +int fdevent_event_add(fdevents *ev, iosocket *sock, int events);
9083 +int fdevent_event_del(fdevents *ev, iosocket *sock);
9086 + * set non-blocking
9088 +int fdevent_fcntl_set(fdevents *ev, iosocket *sock);
9090 +fdevent_revents *fdevent_revents_init(void);
9091 +void fdevent_revents_reset(fdevent_revents *revents);
9092 +void fdevent_revents_add(fdevent_revents *revents, int fd, int events);
9093 +void fdevent_revents_free(fdevent_revents *revents);
9095 -int fdevent_register(fdevents *ev, int fd, fdevent_handler handler, void *ctx);
9096 -int fdevent_unregister(fdevents *ev, int fd);
9097 +fdevent_revent *fdevent_revent_init(void);
9098 +void fdevent_revent_free(fdevent_revent *revent);
9100 -int fdevent_fcntl_set(fdevents *ev, int fd);
9105 int fdevent_select_init(fdevents *ev);
9106 int fdevent_poll_init(fdevents *ev);
9107 int fdevent_linux_rtsig_init(fdevents *ev);
9108 --- ../lighttpd-1.4.11/src/fdevent_freebsd_kqueue.c 2005-09-01 10:46:24.000000000 +0300
9109 +++ lighttpd-1.4.12/src/fdevent_freebsd_kqueue.c 2006-07-16 00:26:03.000000000 +0300
9111 #include <sys/types.h>
9113 -#include <unistd.h>
9132 ret = kevent(ev->kq_fd,
9141 if (filter == EVFILT_READ) {
9142 bitset_set_bit(ev->kq_bevents, fd);
9145 } else if (e == EVFILT_WRITE) {
9146 events |= FDEVENT_OUT;
9150 e = ev->kq_results[ndx].flags;
9153 @@ -152,10 +151,10 @@
9154 if (-1 == (ev->kq_fd = kqueue())) {
9155 fprintf(stderr, "%s.%d: kqueue failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
9156 __FILE__, __LINE__, strerror(errno));
9167 if (-1 == (ev->kq_fd = kqueue())) {
9168 fprintf(stderr, "%s.%d: kqueue failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
9169 __FILE__, __LINE__, strerror(errno));
9175 --- ../lighttpd-1.4.11/src/fdevent_linux_rtsig.c 2005-11-21 19:56:11.000000000 +0200
9176 +++ lighttpd-1.4.12/src/fdevent_linux_rtsig.c 2006-07-18 13:03:40.000000000 +0300
9178 #include <sys/types.h>
9180 -#include <unistd.h>
9185 #include "fdevent.h"
9186 #include "settings.h"
9188 +#include "sys-process.h"
9191 #ifdef USE_LINUX_SIGIO
9192 static void fdevent_linux_rtsig_free(fdevents *ev) {
9197 -static int fdevent_linux_rtsig_event_del(fdevents *ev, int fde_ndx, int fd) {
9198 - if (fde_ndx < 0) return -1;
9200 - if ((size_t)fde_ndx >= ev->used) {
9201 - fprintf(stderr, "%s.%d: del! out of range %d %zu\n", __FILE__, __LINE__, fde_ndx, ev->used);
9202 +static int fdevent_linux_rtsig_event_del(fdevents *ev, iosocket *sock) {
9203 + if (sock->fde_ndx < 0) return -1;
9205 + if ((size_t)sock->fde_ndx >= ev->used) {
9206 + TRACE("del! out of range %d %zu\n", sock->fde_ndx, ev->used);
9210 - if (ev->pollfds[fde_ndx].fd == fd) {
9211 - size_t k = fde_ndx;
9214 + if (ev->pollfds[sock->fde_ndx].fd == sock->fd) {
9215 + size_t k = sock->fde_ndx;
9217 ev->pollfds[k].fd = -1;
9219 - bitset_clear_bit(ev->sigbset, fd);
9221 + bitset_clear_bit(ev->sigbset, sock->fd);
9223 if (ev->unused.size == 0) {
9224 ev->unused.size = 16;
9225 ev->unused.ptr = malloc(sizeof(*(ev->unused.ptr)) * ev->unused.size);
9227 ev->unused.size += 16;
9228 ev->unused.ptr = realloc(ev->unused.ptr, sizeof(*(ev->unused.ptr)) * ev->unused.size);
9232 ev->unused.ptr[ev->unused.used++] = k;
9234 - fprintf(stderr, "%s.%d: del! %d %d\n", __FILE__, __LINE__, ev->pollfds[fde_ndx].fd, fd);
9236 + fprintf(stderr, "%s.%d: del! %d %d\n", __FILE__, __LINE__, ev->pollfds[sock->fde_ndx].fd, sock->fd);
9242 + sock->fde_ndx = -1;
9248 static int fdevent_linux_rtsig_event_compress(fdevents *ev) {
9252 if (ev->used == 0) return 0;
9253 if (ev->unused.used != 0) return 0;
9256 for (j = ev->used - 1; j + 1 > 0; j--) {
9257 if (ev->pollfds[j].fd == -1) ev->used--;
9267 -static int fdevent_linux_rtsig_event_add(fdevents *ev, int fde_ndx, int fd, int events) {
9268 +static int fdevent_linux_rtsig_event_add(fdevents *ev, iosocket *sock, int events) {
9270 - if (fde_ndx != -1) {
9271 - if (ev->pollfds[fde_ndx].fd == fd) {
9272 - ev->pollfds[fde_ndx].events = events;
9275 + if (sock->fde_ndx != -1) {
9276 + if (ev->pollfds[sock->fde_ndx].fd == sock->fd) {
9277 + ev->pollfds[sock->fde_ndx].events = events;
9279 + return sock->fde_ndx;
9281 - fprintf(stderr, "%s.%d: add: (%d, %d)\n", __FILE__, __LINE__, fde_ndx, ev->pollfds[fde_ndx].fd);
9282 + fprintf(stderr, "%s.%d: add: (%d, %d)\n", __FILE__, __LINE__, sock->fde_ndx, ev->pollfds[sock->fde_ndx].fd);
9287 if (ev->unused.used > 0) {
9288 int k = ev->unused.ptr[--ev->unused.used];
9290 - ev->pollfds[k].fd = fd;
9292 + ev->pollfds[k].fd = sock->fd;
9293 ev->pollfds[k].events = events;
9295 - bitset_set_bit(ev->sigbset, fd);
9297 + bitset_set_bit(ev->sigbset, sock->fd);
9301 if (ev->size == 0) {
9302 @@ -102,12 +104,12 @@
9304 ev->pollfds = realloc(ev->pollfds, sizeof(*ev->pollfds) * ev->size);
9307 - ev->pollfds[ev->used].fd = fd;
9309 + ev->pollfds[ev->used].fd = sock->fd;
9310 ev->pollfds[ev->used].events = events;
9312 - bitset_set_bit(ev->sigbset, fd);
9314 + bitset_set_bit(ev->sigbset, sock->fd);
9319 @@ -115,20 +117,20 @@
9320 static int fdevent_linux_rtsig_poll(fdevents *ev, int timeout_ms) {
9326 fdevent_linux_rtsig_event_compress(ev);
9333 ts.tv_sec = timeout_ms / 1000;
9334 ts.tv_nsec = (timeout_ms % 1000) * 1000000;
9335 r = sigtimedwait(&(ev->sigset), &(ev->siginfo), &(ts));
9340 if (errno == EAGAIN) return 0;
9343 } else if (r == SIGIO) {
9344 struct sigaction act;
9347 /* re-enable the signal queue */
9348 act.sa_handler = SIG_DFL;
9349 sigaction(ev->signum, &act, NULL);
9353 r = poll(ev->pollfds, ev->used, timeout_ms);
9355 @@ -156,97 +158,67 @@
9359 -static int fdevent_linux_rtsig_event_get_revent(fdevents *ev, size_t ndx) {
9360 +static int fdevent_linux_rtsig_get_revents(fdevents *ev, size_t event_count, fdevent_revents *revents) {
9361 if (ev->in_sigio == 1) {
9363 - if (ev->siginfo.si_band == POLLERR) {
9364 - fprintf(stderr, "event: %d %02lx %02x %s\n", ev->siginfo.si_fd, ev->siginfo.si_band, errno, strerror(errno));
9368 - fprintf(stderr, "+\n");
9372 - return ev->siginfo.si_band & 0x3f;
9373 + /* only one event */
9375 + fdevent_revents_add(revents, ev->siginfo.si_fd, ev->siginfo.si_band & 0x3f);
9377 - if (ndx >= ev->used) {
9378 - fprintf(stderr, "%s.%d: event: %zu %zu\n", __FILE__, __LINE__, ndx, ev->used);
9382 + for (ndx = 0; ndx < ev->used; ndx++) {
9383 + if (ev->pollfds[ndx].revents) {
9384 + fdevent_revents_add(revents, ev->pollfds[ndx].fd, ev->pollfds[ndx].revents);
9387 - return ev->pollfds[ndx].revents;
9391 -static int fdevent_linux_rtsig_event_get_fd(fdevents *ev, size_t ndx) {
9392 - if (ev->in_sigio == 1) {
9393 - return ev->siginfo.si_fd;
9395 - return ev->pollfds[ndx].fd;
9400 static int fdevent_linux_rtsig_fcntl_set(fdevents *ev, int fd) {
9401 static pid_t pid = 0;
9404 if (pid == 0) pid = getpid();
9407 if (-1 == fcntl(fd, F_SETSIG, ev->signum)) return -1;
9410 if (-1 == fcntl(fd, F_SETOWN, (int) pid)) return -1;
9413 return fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK | O_RDWR);
9417 -static int fdevent_linux_rtsig_event_next_fdndx(fdevents *ev, int ndx) {
9418 - if (ev->in_sigio == 1) {
9419 - if (ndx < 0) return 0;
9424 - i = (ndx < 0) ? 0 : ndx + 1;
9425 - for (; i < ev->used; i++) {
9426 - if (ev->pollfds[i].revents) break;
9433 int fdevent_linux_rtsig_init(fdevents *ev) {
9434 ev->type = FDEVENT_HANDLER_LINUX_RTSIG;
9436 ev->x = fdevent_linux_rtsig_##x;
9446 - SET(event_next_fdndx);
9449 - SET(event_get_fd);
9450 - SET(event_get_revent);
9454 ev->signum = SIGRTMIN + 1;
9457 sigemptyset(&(ev->sigset));
9458 sigaddset(&(ev->sigset), ev->signum);
9459 sigaddset(&(ev->sigset), SIGIO);
9460 if (-1 == sigprocmask(SIG_BLOCK, &(ev->sigset), NULL)) {
9461 fprintf(stderr, "%s.%d: sigprocmask failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
9462 __FILE__, __LINE__, strerror(errno));
9471 ev->sigbset = bitset_init(ev->maxfds);
9477 --- ../lighttpd-1.4.11/src/fdevent_linux_sysepoll.c 2005-09-30 20:29:27.000000000 +0300
9478 +++ lighttpd-1.4.12/src/fdevent_linux_sysepoll.c 2006-07-18 13:03:40.000000000 +0300
9480 #include <sys/types.h>
9482 -#include <unistd.h>
9487 #include "fdevent.h"
9488 #include "settings.h"
9492 +#include "sys-files.h"
9494 #ifdef USE_LINUX_EPOLL
9495 static void fdevent_linux_sysepoll_free(fdevents *ev) {
9497 free(ev->epoll_events);
9500 -static int fdevent_linux_sysepoll_event_del(fdevents *ev, int fde_ndx, int fd) {
9501 +static int fdevent_linux_sysepoll_event_del(fdevents *ev, iosocket *sock) {
9502 struct epoll_event ep;
9504 - if (fde_ndx < 0) return -1;
9507 + if (sock->fde_ndx < 0) return -1;
9509 memset(&ep, 0, sizeof(ep));
9513 + ep.data.fd = sock->fd;
9516 - if (0 != epoll_ctl(ev->epoll_fd, EPOLL_CTL_DEL, fd, &ep)) {
9518 + if (0 != epoll_ctl(ev->epoll_fd, EPOLL_CTL_DEL, sock->fd, &ep)) {
9519 fprintf(stderr, "%s.%d: epoll_ctl failed: %s, dying\n", __FILE__, __LINE__, strerror(errno));
9531 + sock->fde_ndx = -1;
9536 -static int fdevent_linux_sysepoll_event_add(fdevents *ev, int fde_ndx, int fd, int events) {
9537 +static int fdevent_linux_sysepoll_event_add(fdevents *ev, iosocket *sock, int events) {
9538 struct epoll_event ep;
9541 - if (fde_ndx == -1) add = 1;
9545 + if (sock->fde_ndx == -1) add = 1;
9547 memset(&ep, 0, sizeof(ep));
9553 if (events & FDEVENT_IN) ep.events |= EPOLLIN;
9554 if (events & FDEVENT_OUT) ep.events |= EPOLLOUT;
9562 ep.events |= EPOLLERR | EPOLLHUP /* | EPOLLET */;
9568 - if (0 != epoll_ctl(ev->epoll_fd, add ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, fd, &ep)) {
9569 + ep.data.fd = sock->fd;
9571 + if (0 != epoll_ctl(ev->epoll_fd, add ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, sock->fd, &ep)) {
9572 fprintf(stderr, "%s.%d: epoll_ctl failed: %s, dying\n", __FILE__, __LINE__, strerror(errno));
9583 + sock->fde_ndx = sock->fd;
9588 static int fdevent_linux_sysepoll_poll(fdevents *ev, int timeout_ms) {
9589 return epoll_wait(ev->epoll_fd, ev->epoll_events, ev->maxfds, timeout_ms);
9592 -static int fdevent_linux_sysepoll_event_get_revent(fdevents *ev, size_t ndx) {
9593 - int events = 0, e;
9595 - e = ev->epoll_events[ndx].events;
9596 - if (e & EPOLLIN) events |= FDEVENT_IN;
9597 - if (e & EPOLLOUT) events |= FDEVENT_OUT;
9598 - if (e & EPOLLERR) events |= FDEVENT_ERR;
9599 - if (e & EPOLLHUP) events |= FDEVENT_HUP;
9600 - if (e & EPOLLPRI) events |= FDEVENT_PRI;
9605 -static int fdevent_linux_sysepoll_event_get_fd(fdevents *ev, size_t ndx) {
9607 - fprintf(stderr, "%s.%d: %d, %d\n", __FILE__, __LINE__, ndx, ev->epoll_events[ndx].data.fd);
9610 - return ev->epoll_events[ndx].data.fd;
9613 -static int fdevent_linux_sysepoll_event_next_fdndx(fdevents *ev, int ndx) {
9617 +static int fdevent_linux_sysepoll_get_revents(fdevents *ev, size_t event_count, fdevent_revents *revents) {
9620 + for (ndx = 0; ndx < event_count; ndx++) {
9621 + int events = 0, e;
9623 + e = ev->epoll_events[ndx].events;
9624 + if (e & EPOLLIN) events |= FDEVENT_IN;
9625 + if (e & EPOLLOUT) events |= FDEVENT_OUT;
9626 + if (e & EPOLLERR) events |= FDEVENT_ERR;
9627 + if (e & EPOLLHUP) events |= FDEVENT_HUP;
9628 + if (e & EPOLLPRI) events |= FDEVENT_PRI;
9630 - i = (ndx < 0) ? 0 : ndx + 1;
9633 + fdevent_revents_add(revents, ev->epoll_events[ndx].data.fd, e);
9639 int fdevent_linux_sysepoll_init(fdevents *ev) {
9640 ev->type = FDEVENT_HANDLER_LINUX_SYSEPOLL;
9642 ev->x = fdevent_linux_sysepoll_##x;
9652 - SET(event_next_fdndx);
9653 - SET(event_get_fd);
9654 - SET(event_get_revent);
9659 if (-1 == (ev->epoll_fd = epoll_create(ev->maxfds))) {
9660 fprintf(stderr, "%s.%d: epoll_create failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
9661 __FILE__, __LINE__, strerror(errno));
9664 fprintf(stderr, "%s.%d: linux-sysepoll not supported, try to set server.event-handler = \"poll\" or \"select\"\n",
9665 __FILE__, __LINE__);
9671 --- ../lighttpd-1.4.11/src/fdevent_poll.c 2005-11-18 13:59:16.000000000 +0200
9672 +++ lighttpd-1.4.12/src/fdevent_poll.c 2006-07-18 13:03:40.000000000 +0300
9674 #include <sys/types.h>
9676 -#include <unistd.h>
9681 #include "fdevent.h"
9682 #include "settings.h"
9687 static void fdevent_poll_free(fdevents *ev) {
9689 if (ev->unused.ptr) free(ev->unused.ptr);
9692 -static int fdevent_poll_event_del(fdevents *ev, int fde_ndx, int fd) {
9693 - if (fde_ndx < 0) return -1;
9695 - if ((size_t)fde_ndx >= ev->used) {
9696 - fprintf(stderr, "%s.%d: del! out of range %d %zd\n", __FILE__, __LINE__, fde_ndx, ev->used);
9697 +static int fdevent_poll_event_del(fdevents *ev, iosocket *sock) {
9698 + if (sock->fde_ndx < 0) return -1;
9700 + if ((size_t)sock->fde_ndx >= ev->used) {
9701 + fprintf(stderr, "%s.%d: del! out of range %d %zd\n", __FILE__, __LINE__, sock->fde_ndx, ev->used);
9705 - if (ev->pollfds[fde_ndx].fd == fd) {
9706 - size_t k = fde_ndx;
9709 + if (ev->pollfds[sock->fde_ndx].fd == sock->fd) {
9710 + size_t k = sock->fde_ndx;
9712 ev->pollfds[k].fd = -1;
9713 /* ev->pollfds[k].events = 0; */
9714 /* ev->pollfds[k].revents = 0; */
9717 if (ev->unused.size == 0) {
9718 ev->unused.size = 16;
9719 ev->unused.ptr = malloc(sizeof(*(ev->unused.ptr)) * ev->unused.size);
9721 ev->unused.size += 16;
9722 ev->unused.ptr = realloc(ev->unused.ptr, sizeof(*(ev->unused.ptr)) * ev->unused.size);
9726 ev->unused.ptr[ev->unused.used++] = k;
9733 + sock->fde_ndx = -1;
9739 static int fdevent_poll_event_compress(fdevents *ev) {
9743 if (ev->used == 0) return 0;
9744 if (ev->unused.used != 0) return 0;
9747 for (j = ev->used - 1; j + 1 > 0 && ev->pollfds[j].fd == -1; j--) ev->used--;
9754 -static int fdevent_poll_event_add(fdevents *ev, int fde_ndx, int fd, int events) {
9757 - if (fde_ndx != -1) {
9758 - if (ev->pollfds[fde_ndx].fd == fd) {
9759 - ev->pollfds[fde_ndx].events = events;
9762 +static int fdevent_poll_event_add(fdevents *ev, iosocket *sock, int events) {
9763 + if (sock->fde_ndx != -1) {
9764 + /* this fd was already added, just change the requested events */
9766 + if (ev->pollfds[sock->fde_ndx].fd == sock->fd) {
9767 + ev->pollfds[sock->fde_ndx].events = events;
9769 + return sock->fde_ndx;
9771 - fprintf(stderr, "%s.%d: add: (%d, %d)\n", __FILE__, __LINE__, fde_ndx, ev->pollfds[fde_ndx].fd);
9772 + fprintf(stderr, "%s.%d: add: (%d, %d)\n", __FILE__, __LINE__, sock->fde_ndx, ev->pollfds[sock->fde_ndx].fd);
9777 if (ev->unused.used > 0) {
9778 int k = ev->unused.ptr[--ev->unused.used];
9780 - ev->pollfds[k].fd = fd;
9782 + ev->pollfds[k].fd = sock->fd;
9783 ev->pollfds[k].events = events;
9787 + sock->fde_ndx = k;
9790 if (ev->size == 0) {
9794 ev->pollfds = realloc(ev->pollfds, sizeof(*ev->pollfds) * ev->size);
9797 - ev->pollfds[ev->used].fd = fd;
9799 + ev->pollfds[ev->used].fd = sock->fd;
9800 ev->pollfds[ev->used].events = events;
9802 - return ev->used++;
9804 + sock->fde_ndx = ev->used++;
9809 static int fdevent_poll_poll(fdevents *ev, int timeout_ms) {
9810 @@ -105,71 +109,38 @@
9811 return poll(ev->pollfds, ev->used, timeout_ms);
9814 -static int fdevent_poll_event_get_revent(fdevents *ev, size_t ndx) {
9816 - if (ndx >= ev->used) {
9817 - fprintf(stderr, "%s.%d: dying because: event: %zd >= %zd\n", __FILE__, __LINE__, ndx, ev->used);
9824 - if (ev->pollfds[ndx].revents & POLLNVAL) {
9825 - /* should never happen */
9828 +static int fdevent_poll_get_revents(fdevents *ev, size_t event_count, fdevent_revents *revents) {
9832 - poll_r = ev->pollfds[ndx].revents;
9833 + for (ndx = 0; ndx < ev->used; ndx++) {
9834 + if (ev->pollfds[ndx].revents) {
9835 + if (ev->pollfds[ndx].revents & POLLNVAL) {
9836 + /* should never happen */
9840 - /* map POLL* to FDEVEN_* */
9842 - if (poll_r & POLLIN) r |= FDEVENT_IN;
9843 - if (poll_r & POLLOUT) r |= FDEVENT_OUT;
9844 - if (poll_r & POLLERR) r |= FDEVENT_ERR;
9845 - if (poll_r & POLLHUP) r |= FDEVENT_HUP;
9846 - if (poll_r & POLLNVAL) r |= FDEVENT_NVAL;
9847 - if (poll_r & POLLPRI) r |= FDEVENT_PRI;
9849 - return ev->pollfds[ndx].revents;
9852 -static int fdevent_poll_event_get_fd(fdevents *ev, size_t ndx) {
9853 - return ev->pollfds[ndx].fd;
9856 -static int fdevent_poll_event_next_fdndx(fdevents *ev, int ndx) {
9859 - i = (ndx < 0) ? 0 : ndx + 1;
9860 - for (; i < ev->used; i++) {
9861 - if (ev->pollfds[i].revents) break;
9862 + fdevent_revents_add(revents, ev->pollfds[ndx].fd, ev->pollfds[ndx].revents);
9871 int fdevent_poll_init(fdevents *ev) {
9872 ev->type = FDEVENT_HANDLER_POLL;
9874 ev->x = fdevent_poll_##x;
9884 - SET(event_next_fdndx);
9885 - SET(event_get_fd);
9886 - SET(event_get_revent);
9898 int fdevent_poll_init(fdevents *ev) {
9899 --- ../lighttpd-1.4.11/src/fdevent_select.c 2005-08-31 11:12:46.000000000 +0300
9900 +++ lighttpd-1.4.12/src/fdevent_select.c 2006-07-18 13:03:40.000000000 +0300
9902 -#include <sys/time.h>
9903 #include <sys/types.h>
9905 -#include <unistd.h>
9914 #include "fdevent.h"
9915 #include "settings.h"
9918 +#include "sys-socket.h"
9922 static int fdevent_select_reset(fdevents *ev) {
9923 @@ -24,101 +25,98 @@
9927 -static int fdevent_select_event_del(fdevents *ev, int fde_ndx, int fd) {
9928 - if (fde_ndx < 0) return -1;
9929 +static int fdevent_select_event_del(fdevents *ev, iosocket *sock) {
9930 + if (sock->fde_ndx < 0) return -1;
9932 - FD_CLR(fd, &(ev->select_set_read));
9933 - FD_CLR(fd, &(ev->select_set_write));
9934 - FD_CLR(fd, &(ev->select_set_error));
9935 + FD_CLR(sock->fd, &(ev->select_set_read));
9936 + FD_CLR(sock->fd, &(ev->select_set_write));
9937 + FD_CLR(sock->fd, &(ev->select_set_error));
9941 + /* mark the fdevent as deleted */
9942 + sock->fde_ndx = -1;
9944 -static int fdevent_select_event_add(fdevents *ev, int fde_ndx, int fd, int events) {
9949 +static int fdevent_select_event_add(fdevents *ev, iosocket *sock, int events) {
9950 /* we should be protected by max-fds, but you never know */
9951 - assert(fd < FD_SETSIZE);
9953 + assert(sock->fd < FD_SETSIZE);
9956 if (events & FDEVENT_IN) {
9957 - FD_SET(fd, &(ev->select_set_read));
9958 - FD_CLR(fd, &(ev->select_set_write));
9959 + FD_SET(sock->fd, &(ev->select_set_read));
9960 + FD_CLR(sock->fd, &(ev->select_set_write));
9962 if (events & FDEVENT_OUT) {
9963 - FD_CLR(fd, &(ev->select_set_read));
9964 - FD_SET(fd, &(ev->select_set_write));
9965 + FD_CLR(sock->fd, &(ev->select_set_read));
9966 + FD_SET(sock->fd, &(ev->select_set_write));
9968 - FD_SET(fd, &(ev->select_set_error));
9970 - if (fd > ev->select_max_fd) ev->select_max_fd = fd;
9973 + FD_SET(sock->fd, &(ev->select_set_error));
9975 + /* we need this for the poll */
9976 + if (sock->fd > ev->select_max_fd) ev->select_max_fd = sock->fd;
9978 + /* mark fd as added */
9979 + sock->fde_ndx = sock->fd;
9984 static int fdevent_select_poll(fdevents *ev, int timeout_ms) {
9988 tv.tv_sec = timeout_ms / 1000;
9989 tv.tv_usec = (timeout_ms % 1000) * 1000;
9992 ev->select_read = ev->select_set_read;
9993 ev->select_write = ev->select_set_write;
9994 ev->select_error = ev->select_set_error;
9997 return select(ev->select_max_fd + 1, &(ev->select_read), &(ev->select_write), &(ev->select_error), &tv);
10000 -static int fdevent_select_event_get_revent(fdevents *ev, size_t ndx) {
10003 - if (FD_ISSET(ndx, &(ev->select_read))) {
10004 - revents |= FDEVENT_IN;
10006 + * scan the fdset for events
10008 +static int fdevent_select_get_revents(fdevents *ev, size_t event_count, fdevent_revents *revents) {
10012 + for (ndx = 0; ndx < ev->select_max_fd; ndx++) {
10015 + if (FD_ISSET(ndx, &(ev->select_read))) {
10016 + events |= FDEVENT_IN;
10018 + if (FD_ISSET(ndx, &(ev->select_write))) {
10019 + events |= FDEVENT_OUT;
10021 + if (FD_ISSET(ndx, &(ev->select_error))) {
10022 + events |= FDEVENT_ERR;
10026 + fdevent_revents_add(revents, ndx, events);
10029 - if (FD_ISSET(ndx, &(ev->select_write))) {
10030 - revents |= FDEVENT_OUT;
10032 - if (FD_ISSET(ndx, &(ev->select_error))) {
10033 - revents |= FDEVENT_ERR;
10039 -static int fdevent_select_event_get_fd(fdevents *ev, size_t ndx) {
10045 -static int fdevent_select_event_next_fdndx(fdevents *ev, int ndx) {
10048 - i = (ndx < 0) ? 0 : ndx + 1;
10050 - for (; i < ev->select_max_fd + 1; i++) {
10051 - if (FD_ISSET(i, &(ev->select_read))) break;
10052 - if (FD_ISSET(i, &(ev->select_write))) break;
10053 - if (FD_ISSET(i, &(ev->select_error))) break;
10060 int fdevent_select_init(fdevents *ev) {
10061 ev->type = FDEVENT_HANDLER_SELECT;
10063 ev->x = fdevent_select_##x;
10073 - SET(event_next_fdndx);
10074 - SET(event_get_fd);
10075 - SET(event_get_revent);
10078 + SET(get_revents);
10083 --- ../lighttpd-1.4.11/src/fdevent_solaris_devpoll.c 2005-09-01 10:45:26.000000000 +0300
10084 +++ lighttpd-1.4.12/src/fdevent_solaris_devpoll.c 2006-07-16 00:26:03.000000000 +0300
10086 #include <sys/types.h>
10088 -#include <unistd.h>
10089 #include <stdlib.h>
10091 #include <string.h>
10092 @@ -23,55 +22,55 @@
10094 static int fdevent_solaris_devpoll_event_del(fdevents *ev, int fde_ndx, int fd) {
10098 if (fde_ndx < 0) return -1;
10102 pfd.events = POLLREMOVE;
10106 if (-1 == write(ev->devpoll_fd, &pfd, sizeof(pfd))) {
10107 - fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n",
10108 - __FILE__, __LINE__,
10109 + fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n",
10110 + __FILE__, __LINE__,
10111 fd, strerror(errno));
10121 static int fdevent_solaris_devpoll_event_add(fdevents *ev, int fde_ndx, int fd, int events) {
10126 if (fde_ndx == -1) add = 1;
10130 pfd.events = events;
10134 if (-1 == write(ev->devpoll_fd, &pfd, sizeof(pfd))) {
10135 - fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n",
10136 - __FILE__, __LINE__,
10137 + fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n",
10138 + __FILE__, __LINE__,
10139 fd, strerror(errno));
10149 static int fdevent_solaris_devpoll_poll(fdevents *ev, int timeout_ms) {
10150 struct dvpoll dopoll;
10154 dopoll.dp_timeout = timeout_ms;
10155 dopoll.dp_nfds = ev->maxfds;
10156 dopoll.dp_fds = ev->devpollfds;
10159 ret = ioctl(ev->devpoll_fd, DP_POLL, &dopoll);
10165 @@ -85,11 +84,11 @@
10167 static int fdevent_solaris_devpoll_event_next_fdndx(fdevents *ev, int last_ndx) {
10173 i = (last_ndx < 0) ? 0 : last_ndx + 1;
10179 @@ -117,20 +116,20 @@
10180 ev->type = FDEVENT_HANDLER_SOLARIS_DEVPOLL;
10182 ev->x = fdevent_solaris_devpoll_##x;
10194 SET(event_next_fdndx);
10196 SET(event_get_revent);
10199 ev->devpollfds = malloc(sizeof(*ev->devpollfds) * ev->maxfds);
10202 if ((ev->devpoll_fd = open("/dev/poll", O_RDWR)) < 0) {
10203 fprintf(stderr, "%s.%d: opening /dev/poll failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
10204 __FILE__, __LINE__, strerror(errno));
10205 @@ -152,7 +151,7 @@
10207 fprintf(stderr, "%s.%d: solaris-devpoll not supported, try to set server.event-handler = \"poll\" or \"select\"\n",
10208 __FILE__, __LINE__);
10214 --- ../lighttpd-1.4.11/src/http-header-glue.c 2006-02-08 15:31:36.000000000 +0200
10215 +++ lighttpd-1.4.12/src/http-header-glue.c 2006-07-18 13:03:40.000000000 +0300
10216 @@ -45,20 +45,20 @@
10217 # ifdef HAVE_STRUCT_SOCKADDR_STORAGE
10218 static size_t get_sa_len(const struct sockaddr *addr) {
10219 switch (addr->sa_family) {
10224 return (sizeof (struct sockaddr_in));
10230 return (sizeof (struct sockaddr_in6));
10235 return (sizeof (struct sockaddr));
10240 # define SA_LEN(addr) (get_sa_len(addr))
10243 int response_header_insert(server *srv, connection *con, const char *key, size_t keylen, const char *value, size_t vallen) {
10249 if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
10250 @@ -82,32 +82,32 @@
10252 buffer_copy_string_len(ds->key, key, keylen);
10253 buffer_copy_string_len(ds->value, value, vallen);
10256 array_insert_unique(con->response.headers, (data_unset *)ds);
10262 int response_header_overwrite(server *srv, connection *con, const char *key, size_t keylen, const char *value, size_t vallen) {
10268 /* if there already is a key by this name overwrite the value */
10269 if (NULL != (ds = (data_string *)array_get_element(con->response.headers, key))) {
10270 buffer_copy_string(ds->value, value);
10277 return response_header_insert(srv, con, key, keylen, value, vallen);
10280 int http_response_redirect_to_directory(server *srv, connection *con) {
10287 if (con->conf.is_ssl) {
10288 buffer_copy_string(o, "https://");
10290 @@ -123,36 +123,36 @@
10292 sock_addr our_addr;
10293 socklen_t our_addr_len;
10296 our_addr_len = sizeof(our_addr);
10298 - if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) {
10300 + if (-1 == getsockname(con->sock->fd, &(our_addr.plain), &our_addr_len)) {
10301 con->http_status = 500;
10304 log_error_write(srv, __FILE__, __LINE__, "ss",
10305 "can't get sockname", strerror(errno));
10315 /* Lookup name: secondly try to get hostname for bind address */
10316 switch(our_addr.plain.sa_family) {
10319 - if (0 != getnameinfo((const struct sockaddr *)(&our_addr.ipv6),
10320 - SA_LEN((const struct sockaddr *)&our_addr.ipv6),
10321 + if (0 != getnameinfo((const struct sockaddr *)(&our_addr.ipv6),
10322 + SA_LEN((const struct sockaddr *)&our_addr.ipv6),
10323 hbuf, sizeof(hbuf), NULL, 0, 0)) {
10326 char dst[INET6_ADDRSTRLEN];
10329 log_error_write(srv, __FILE__, __LINE__,
10330 "SSSS", "NOTICE: getnameinfo failed: ",
10331 strerror(errno), ", using ip-address instead");
10333 - buffer_append_string(o,
10334 - inet_ntop(AF_INET6, (char *)&our_addr.ipv6.sin6_addr,
10336 + buffer_append_string(o,
10337 + inet_ntop(AF_INET6, (char *)&our_addr.ipv6.sin6_addr,
10338 dst, sizeof(dst)));
10340 buffer_append_string(o, hbuf);
10341 @@ -164,7 +164,7 @@
10342 log_error_write(srv, __FILE__, __LINE__,
10343 "SdSS", "NOTICE: gethostbyaddr failed: ",
10344 h_errno, ", using ip-address instead");
10347 buffer_append_string(o, inet_ntoa(our_addr.ipv4.sin_addr));
10349 buffer_append_string(o, he->h_name);
10350 @@ -173,12 +173,12 @@
10352 log_error_write(srv, __FILE__, __LINE__,
10353 "S", "ERROR: unsupported address-type");
10360 - if (!((con->conf.is_ssl == 0 && srv->srvconf.port == 80) ||
10362 + if (!((con->conf.is_ssl == 0 && srv->srvconf.port == 80) ||
10363 (con->conf.is_ssl == 1 && srv->srvconf.port == 443))) {
10364 buffer_append_string(o, ":");
10365 buffer_append_long(o, srv->srvconf.port);
10366 @@ -190,41 +190,41 @@
10367 buffer_append_string(o, "?");
10368 buffer_append_string_buffer(o, con->uri.query);
10372 response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(o));
10375 con->http_status = 301;
10376 con->file_finished = 1;
10385 buffer * strftime_cache_get(server *srv, time_t last_mod) {
10390 for (i = 0; i < FILE_CACHE_MAX; i++) {
10391 /* found cache-entry */
10392 if (srv->mtime_cache[i].mtime == last_mod) return srv->mtime_cache[i].str;
10395 /* found empty slot */
10396 if (srv->mtime_cache[i].mtime == 0) break;
10400 if (i == FILE_CACHE_MAX) {
10405 srv->mtime_cache[i].mtime = last_mod;
10406 buffer_prepare_copy(srv->mtime_cache[i].str, 1024);
10407 tm = gmtime(&(srv->mtime_cache[i].mtime));
10408 - srv->mtime_cache[i].str->used = strftime(srv->mtime_cache[i].str->ptr,
10409 + srv->mtime_cache[i].str->used = strftime(srv->mtime_cache[i].str->ptr,
10410 srv->mtime_cache[i].str->size - 1,
10411 "%a, %d %b %Y %H:%M:%S GMT", tm);
10412 srv->mtime_cache[i].str->used++;
10415 return srv->mtime_cache[i].str;
10418 @@ -239,56 +239,60 @@
10419 * request. That is, if no entity tags match, then the server MUST NOT
10420 * return a 304 (Not Modified) response.
10424 /* last-modified handling */
10425 if (con->request.http_if_none_match) {
10426 if (etag_is_equal(con->physical.etag, con->request.http_if_none_match)) {
10427 - if (con->request.http_method == HTTP_METHOD_GET ||
10428 + if (con->request.http_method == HTTP_METHOD_GET ||
10429 con->request.http_method == HTTP_METHOD_HEAD) {
10432 /* check if etag + last-modified */
10433 if (con->request.http_if_modified_since) {
10438 if (NULL == (semicolon = strchr(con->request.http_if_modified_since, ';'))) {
10439 used_len = strlen(con->request.http_if_modified_since);
10441 used_len = semicolon - con->request.http_if_modified_since;
10445 if (0 == strncmp(con->request.http_if_modified_since, mtime->ptr, used_len)) {
10446 con->http_status = 304;
10447 return HANDLER_FINISHED;
10449 +#ifdef HAVE_STRPTIME
10450 char buf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
10451 + time_t t_header, t_file;
10454 - /* convert to timestamp */
10455 - if (used_len < sizeof(buf)) {
10456 - time_t t_header, t_file;
10459 - strncpy(buf, con->request.http_if_modified_since, used_len);
10460 - buf[used_len] = '\0';
10462 - strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm);
10463 - t_header = mktime(&tm);
10465 - strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm);
10466 - t_file = mktime(&tm);
10468 - if (t_file > t_header) {
10469 - con->http_status = 304;
10470 - return HANDLER_FINISHED;
10473 - log_error_write(srv, __FILE__, __LINE__, "ssdd",
10474 - "DEBUG: Last-Modified check failed as the received timestamp was too long:",
10475 + /* check if we can safely copy the string */
10476 + if (used_len >= sizeof(buf)) {
10477 + log_error_write(srv, __FILE__, __LINE__, "ssdd",
10478 + "DEBUG: Last-Modified check failed as the received timestamp was too long:",
10479 con->request.http_if_modified_since, used_len, sizeof(buf) - 1);
10482 con->http_status = 412;
10483 return HANDLER_FINISHED;
10487 + strncpy(buf, con->request.http_if_modified_since, used_len);
10488 + buf[used_len] = '\0';
10490 + strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm);
10491 + t_header = mktime(&tm);
10493 + strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm);
10494 + t_file = mktime(&tm);
10496 + if (t_file > t_header) return HANDLER_GO_ON;
10498 + con->http_status = 304;
10499 + return HANDLER_FINISHED;
10501 + return HANDLER_GO_ON;
10505 con->http_status = 304;
10506 @@ -302,16 +306,41 @@
10507 } else if (con->request.http_if_modified_since) {
10512 if (NULL == (semicolon = strchr(con->request.http_if_modified_since, ';'))) {
10513 used_len = strlen(con->request.http_if_modified_since);
10515 used_len = semicolon - con->request.http_if_modified_since;
10519 if (0 == strncmp(con->request.http_if_modified_since, mtime->ptr, used_len)) {
10520 con->http_status = 304;
10521 return HANDLER_FINISHED;
10523 +#ifdef HAVE_STRPTIME
10524 + char buf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
10525 + time_t t_header, t_file;
10528 + /* convert to timestamp */
10529 + if (used_len >= sizeof(buf)) return HANDLER_GO_ON;
10531 + strncpy(buf, con->request.http_if_modified_since, used_len);
10532 + buf[used_len] = '\0';
10534 + strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm);
10535 + t_header = mktime(&tm);
10537 + strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm);
10538 + t_file = mktime(&tm);
10540 + if (t_file > t_header) return HANDLER_GO_ON;
10542 + con->http_status = 304;
10543 + return HANDLER_FINISHED;
10545 + return HANDLER_GO_ON;
10550 --- ../lighttpd-1.4.11/src/http_auth.c 2006-02-01 13:02:52.000000000 +0200
10551 +++ lighttpd-1.4.12/src/http_auth.c 2006-07-18 13:03:40.000000000 +0300
10553 #include <string.h>
10556 -#include <unistd.h>
10559 #include "server.h"
10560 @@ -31,23 +30,14 @@
10561 #include "http_auth_digest.h"
10562 #include "stream.h"
10564 +#include "sys-strings.h"
10567 # include <openssl/md5.h>
10574 -#include <security/pam_appl.h>
10575 -#include <security/pam_misc.h>
10577 -static struct pam_conv conv = {
10583 handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s);
10585 static const char base64_pad = '=';
10586 @@ -75,25 +65,25 @@
10587 unsigned char *result;
10592 size_t in_len = strlen(in);
10595 buffer_prepare_copy(out, in_len);
10598 result = (unsigned char *)out->ptr;
10602 /* run through the whole string, converting as we go */
10603 for (i = 0; i < in_len; i++) {
10607 if (ch == '\0') break;
10610 if (ch == base64_pad) break;
10613 ch = base64_reverse_table[ch];
10614 if (ch < 0) continue;
10619 result[j] = ch << 2;
10620 @@ -125,168 +115,168 @@
10632 static int http_auth_get_password(server *srv, mod_auth_plugin_data *p, buffer *username, buffer *realm, buffer *password) {
10636 if (!username->used|| !realm->used) return -1;
10639 if (p->conf.auth_backend == AUTH_BACKEND_HTDIGEST) {
10644 if (buffer_is_empty(p->conf.auth_htdigest_userfile)) return -1;
10647 if (0 != stream_open(&f, p->conf.auth_htdigest_userfile)) {
10648 log_error_write(srv, __FILE__, __LINE__, "sbss", "opening digest-userfile", p->conf.auth_htdigest_userfile, "failed:", strerror(errno));
10658 while (f_line - f.start != f.size) {
10659 char *f_user, *f_pwd, *e, *f_realm;
10660 size_t u_len, pwd_len, r_len;
10670 - * user:realm:md5(user:realm:password)
10672 + * user:realm:md5(user:realm:password)
10676 if (NULL == (f_realm = memchr(f_user, ':', f.size - (f_user - f.start) ))) {
10677 - log_error_write(srv, __FILE__, __LINE__, "sbs",
10678 - "parsed error in", p->conf.auth_htdigest_userfile,
10679 + log_error_write(srv, __FILE__, __LINE__, "sbs",
10680 + "parsed error in", p->conf.auth_htdigest_userfile,
10681 "expected 'username:realm:hashed password'");
10691 if (NULL == (f_pwd = memchr(f_realm + 1, ':', f.size - (f_realm + 1 - f.start)))) {
10692 - log_error_write(srv, __FILE__, __LINE__, "sbs",
10693 - "parsed error in", p->conf.auth_plain_userfile,
10694 + log_error_write(srv, __FILE__, __LINE__, "sbs",
10695 + "parsed error in", p->conf.auth_plain_userfile,
10696 "expected 'username:realm:hashed password'");
10706 /* get pointers to the fields */
10707 - u_len = f_realm - f_user;
10708 + u_len = f_realm - f_user;
10710 r_len = f_pwd - f_realm;
10714 if (NULL != (e = memchr(f_pwd, '\n', f.size - (f_pwd - f.start)))) {
10715 pwd_len = e - f_pwd;
10717 pwd_len = f.size - (f_pwd - f.start);
10721 if (username->used - 1 == u_len &&
10722 (realm->used - 1 == r_len) &&
10723 (0 == strncmp(username->ptr, f_user, u_len)) &&
10724 (0 == strncmp(realm->ptr, f_realm, r_len))) {
10728 buffer_copy_string_len(password, f_pwd, pwd_len);
10745 } else if (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD ||
10746 p->conf.auth_backend == AUTH_BACKEND_PLAIN) {
10752 auth_fn = (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD) ? p->conf.auth_htpasswd_userfile : p->conf.auth_plain_userfile;
10755 if (buffer_is_empty(auth_fn)) return -1;
10758 if (0 != stream_open(&f, auth_fn)) {
10759 - log_error_write(srv, __FILE__, __LINE__, "sbss",
10760 + log_error_write(srv, __FILE__, __LINE__, "sbss",
10761 "opening plain-userfile", auth_fn, "failed:", strerror(errno));
10771 while (f_line - f.start != f.size) {
10772 char *f_user, *f_pwd, *e;
10773 size_t u_len, pwd_len;
10784 * user:crypted passwd
10788 if (NULL == (f_pwd = memchr(f_user, ':', f.size - (f_user - f.start) ))) {
10789 - log_error_write(srv, __FILE__, __LINE__, "sbs",
10790 - "parsed error in", auth_fn,
10791 + log_error_write(srv, __FILE__, __LINE__, "sbs",
10792 + "parsed error in", auth_fn,
10793 "expected 'username:hashed password'");
10803 /* get pointers to the fields */
10804 - u_len = f_pwd - f_user;
10805 + u_len = f_pwd - f_user;
10809 if (NULL != (e = memchr(f_pwd, '\n', f.size - (f_pwd - f.start)))) {
10810 pwd_len = e - f_pwd;
10812 pwd_len = f.size - (f_pwd - f.start);
10816 if (username->used - 1 == u_len &&
10817 (0 == strncmp(username->ptr, f_user, u_len))) {
10821 buffer_copy_string_len(password, f_pwd, pwd_len);
10838 } else if (p->conf.auth_backend == AUTH_BACKEND_LDAP) {
10848 @@ -296,7 +286,7 @@
10850 data_string *require;
10857 @@ -304,12 +294,12 @@
10858 /* search auth-directives for path */
10859 for (i = 0; i < p->conf.auth_require->used; i++) {
10860 if (p->conf.auth_require->data[i]->key->used == 0) continue;
10863 if (0 == strncmp(url, p->conf.auth_require->data[i]->key->ptr, p->conf.auth_require->data[i]->key->used - 1)) {
10869 if (i == p->conf.auth_require->used) {
10872 @@ -317,72 +307,72 @@
10873 req = ((data_array *)(p->conf.auth_require->data[i]))->value;
10875 require = (data_string *)array_get_element(req, "require");
10878 /* if we get here, the user we got a authed user */
10879 - if (0 == strcmp(require->value->ptr, "valid-user")) {
10880 + if (buffer_is_equal_string(require->value, CONST_STR_LEN("valid-user"))) {
10885 /* user=name1|group=name3|host=name4 */
10888 /* seperate the string by | */
10890 log_error_write(srv, __FILE__, __LINE__, "sb", "rules", require->value);
10895 username_len = username ? strlen(username) : 0;
10898 r = rules = require->value->ptr;
10903 const char *k, *v, *e;
10904 int k_len, v_len, r_len;
10907 e = strchr(r, '|');
10913 r_len = strlen(rules) - (r - rules);
10917 /* from r to r + r_len is a rule */
10920 if (0 == strncmp(r, "valid-user", r_len)) {
10921 - log_error_write(srv, __FILE__, __LINE__, "sb",
10922 + log_error_write(srv, __FILE__, __LINE__, "sb",
10923 "parsing the 'require' section in 'auth.require' failed: valid-user cannot be combined with other require rules",
10929 /* search for = in the rules */
10930 if (NULL == (eq = strchr(r, '='))) {
10931 - log_error_write(srv, __FILE__, __LINE__, "sb",
10932 - "parsing the 'require' section in 'auth.require' failed: a = is missing",
10933 + log_error_write(srv, __FILE__, __LINE__, "sb",
10934 + "parsing the 'require' section in 'auth.require' failed: a = is missing",
10940 /* = out of range */
10941 if (eq > r + r_len) {
10942 - log_error_write(srv, __FILE__, __LINE__, "sb",
10943 + log_error_write(srv, __FILE__, __LINE__, "sb",
10944 "parsing the 'require' section in 'auth.require' failed: = out of range",
10952 /* the part before the = is user|group|host */
10958 v_len = r_len - k_len - 1;
10962 if (0 == strncmp(k, "user", k_len)) {
10965 username_len == v_len &&
10966 0 == strncmp(username, v, v_len)) {
10968 @@ -404,19 +394,19 @@
10969 log_error_write(srv, __FILE__, __LINE__, "s", "unknown key");
10979 log_error_write(srv, __FILE__, __LINE__, "s", "nothing matched");
10990 * @param password password-string from the auth-backend
10991 * @param pw password-string from the client
10993 @@ -426,16 +416,16 @@
10996 if (p->conf.auth_backend == AUTH_BACKEND_HTDIGEST) {
11001 - * user:realm:md5(user:realm:password)
11003 + * user:realm:md5(user:realm:password)
11013 MD5_Update(&Md5Ctx, (unsigned char *)username->ptr, username->used - 1);
11014 MD5_Update(&Md5Ctx, (unsigned char *)":", 1);
11015 @@ -443,24 +433,24 @@
11016 MD5_Update(&Md5Ctx, (unsigned char *)":", 1);
11017 MD5_Update(&Md5Ctx, (unsigned char *)pw, strlen(pw));
11018 MD5_Final(HA1, &Md5Ctx);
11023 - if (0 == strcmp(password->ptr, a1)) {
11025 + if (buffer_is_equal_string(password, a1, strlen(a1))) {
11028 - } else if (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD) {
11030 + } else if (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD) {
11034 size_t salt_len = 0;
11040 * user:crypted password
11046 * CRYPT_STD_DES 2-character (Default)
11047 * CRYPT_EXT_DES 9-character
11048 @@ -478,7 +468,7 @@
11050 } else if (password->ptr[0] == '$' && password->ptr[2] == '$') {
11051 char *dollar = NULL;
11054 if (NULL == (dollar = strchr(password->ptr + 3, '$'))) {
11055 fprintf(stderr, "%s.%d\n", __FILE__, __LINE__);
11057 @@ -495,48 +485,21 @@
11058 strncpy(salt, password->ptr, salt_len);
11060 salt[salt_len] = '\0';
11063 crypted = crypt(pw, salt);
11065 - if (0 == strcmp(password->ptr, crypted)) {
11066 + if (buffer_is_equal_string(password, crypted, strlen(crypted))) {
11069 fprintf(stderr, "%s.%d\n", __FILE__, __LINE__);
11073 - } else if (p->conf.auth_backend == AUTH_BACKEND_PLAIN) {
11074 - if (0 == strcmp(password->ptr, pw)) {
11077 - } else if (p->conf.auth_backend == AUTH_BACKEND_PAM) {
11079 - pam_handle_t *pamh=NULL;
11082 - retval = pam_start("lighttpd", username->ptr, &conv, &pamh);
11084 - if (retval == PAM_SUCCESS)
11085 - retval = pam_authenticate(pamh, 0); /* is user really user? */
11087 - if (retval == PAM_SUCCESS)
11088 - retval = pam_acct_mgmt(pamh, 0); /* permitted access? */
11090 - /* This is where we have been authorized or not. */
11092 - if (pam_end(pamh,retval) != PAM_SUCCESS) { /* close Linux-PAM */
11094 - log_error_write(srv, __FILE__, __LINE__, "s", "failed to release authenticator");
11097 - if (retval == PAM_SUCCESS) {
11098 - log_error_write(srv, __FILE__, __LINE__, "s", "Authenticated");
11101 + } else if (p->conf.auth_backend == AUTH_BACKEND_PLAIN) {
11102 + if (buffer_is_equal_string(password, pw, strlen(pw))) {
11105 - log_error_write(srv, __FILE__, __LINE__, "s", "Not Authenticated");
11108 - } else if (p->conf.auth_backend == AUTH_BACKEND_LDAP) {
11109 + } else if (p->conf.auth_backend == AUTH_BACKEND_LDAP) {
11112 LDAPMessage *lm, *first;
11113 @@ -544,45 +507,45 @@
11115 char *attrs[] = { LDAP_NO_ATTRS, NULL };
11119 /* for now we stay synchronous */
11124 * 1. connect anonymously (done in plugin init)
11125 * 2. get DN for uid = username
11126 * 3. auth against ldap server
11127 * 4. (optional) check a field
11137 * we have to protect us againt username which modifies out filter in
11142 for (i = 0; i < username->used - 1; i++) {
11143 char c = username->ptr[i];
11149 - log_error_write(srv, __FILE__, __LINE__, "sbd",
11151 + log_error_write(srv, __FILE__, __LINE__, "sbd",
11152 "ldap: invalid character (a-zA-Z0-9 allowed) in username:", username, i);
11165 buffer_copy_string_buffer(p->ldap_filter, p->conf.ldap_filter_pre);
11166 buffer_append_string_buffer(p->ldap_filter, username);
11167 buffer_append_string_buffer(p->ldap_filter, p->conf.ldap_filter_post);
11173 if (p->conf.ldap == NULL ||
11174 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))) {
11175 @@ -590,71 +553,71 @@
11177 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))) {
11179 - log_error_write(srv, __FILE__, __LINE__, "sssb",
11180 + log_error_write(srv, __FILE__, __LINE__, "sssb",
11181 "ldap:", ldap_err2string(ret), "filter:", p->ldap_filter);
11189 if (NULL == (first = ldap_first_entry(p->conf.ldap, lm))) {
11190 log_error_write(srv, __FILE__, __LINE__, "s", "ldap ...");
11200 if (NULL == (dn = ldap_get_dn(p->conf.ldap, first))) {
11201 log_error_write(srv, __FILE__, __LINE__, "s", "ldap ...");
11217 if (NULL == (ldap = ldap_init(p->conf.auth_ldap_hostname->ptr, LDAP_PORT))) {
11218 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap ...", strerror(errno));
11223 ret = LDAP_VERSION3;
11224 if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &ret))) {
11225 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
11228 ldap_unbind_s(ldap);
11235 if (p->conf.auth_ldap_starttls == 1) {
11236 if (LDAP_OPT_SUCCESS != (ret = ldap_start_tls_s(ldap, NULL, NULL))) {
11237 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap startTLS failed:", ldap_err2string(ret));
11240 ldap_unbind_s(ldap);
11249 if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(ldap, dn, pw))) {
11250 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
11253 ldap_unbind_s(ldap);
11261 ldap_unbind_s(ldap);
11264 /* everything worked, good, access granted */
11270 @@ -664,65 +627,65 @@
11271 int http_auth_basic_check(server *srv, connection *con, mod_auth_plugin_data *p, array *req, buffer *url, const char *realm_str) {
11272 buffer *username, *password;
11276 data_string *realm;
11279 realm = (data_string *)array_get_element(req, "realm");
11282 username = buffer_init();
11283 password = buffer_init();
11286 base64_decode(username, realm_str);
11289 /* r2 == user:password */
11290 if (NULL == (pw = strchr(username->ptr, ':'))) {
11291 buffer_free(username);
11294 log_error_write(srv, __FILE__, __LINE__, "sb", ": is missing in", username);
11304 username->used = pw - username->ptr;
11307 /* copy password to r1 */
11308 if (http_auth_get_password(srv, p, username, realm->value, password)) {
11309 buffer_free(username);
11310 buffer_free(password);
11313 log_error_write(srv, __FILE__, __LINE__, "s", "get_password failed");
11320 /* password doesn't match */
11321 if (http_auth_basic_password_compare(srv, p, req, username, realm->value, password, pw)) {
11322 log_error_write(srv, __FILE__, __LINE__, "sbb", "password doesn't match for", con->uri.path, username);
11325 buffer_free(username);
11326 buffer_free(password);
11333 /* value is our allow-rules */
11334 if (http_auth_match_rules(srv, p, url->ptr, username->ptr, NULL, NULL)) {
11335 buffer_free(username);
11336 buffer_free(password);
11339 log_error_write(srv, __FILE__, __LINE__, "s", "rules didn't match");
11346 /* remember the username */
11347 buffer_copy_string_buffer(p->auth_user, username);
11350 buffer_free(username);
11351 buffer_free(password);
11357 @@ -735,7 +698,7 @@
11358 int http_auth_digest_check(server *srv, connection *con, mod_auth_plugin_data *p, array *req, buffer *url, const char *realm_str) {
11366 @@ -745,18 +708,18 @@
11373 const char *m = NULL;
11375 buffer *password, *b, *username_buf, *realm_buf;
11386 /* init pointers */
11388 @@ -771,11 +734,11 @@
11391 { S("response=") },
11399 dkv[0].ptr = &username;
11400 dkv[1].ptr = &realm;
11401 dkv[2].ptr = &nonce;
11402 @@ -786,24 +749,24 @@
11404 dkv[8].ptr = &respons;
11411 for (i = 0; dkv[i].key; i++) {
11412 *(dkv[i].ptr) = NULL;
11418 if (p->conf.auth_backend != AUTH_BACKEND_HTDIGEST &&
11419 p->conf.auth_backend != AUTH_BACKEND_PLAIN) {
11420 - log_error_write(srv, __FILE__, __LINE__, "s",
11421 + log_error_write(srv, __FILE__, __LINE__, "s",
11422 "digest: unsupported backend (only htdigest or plain)");
11429 b = buffer_init_string(realm_str);
11432 /* parse credentials from client */
11433 for (c = b->ptr; *c; c++) {
11434 /* skip whitespaces */
11435 @@ -812,18 +775,18 @@
11437 for (i = 0; dkv[i].key; i++) {
11438 if ((0 == strncmp(c, dkv[i].key, dkv[i].key_len))) {
11439 - if ((c[dkv[i].key_len] == '"') &&
11440 + if ((c[dkv[i].key_len] == '"') &&
11441 (NULL != (e = strchr(c + dkv[i].key_len + 1, '"')))) {
11442 /* value with "..." */
11443 *(dkv[i].ptr) = c + dkv[i].key_len + 1;
11448 } else if (NULL != (e = strchr(c + dkv[i].key_len, ','))) {
11449 /* value without "...", terminated by ',' */
11450 *(dkv[i].ptr) = c + dkv[i].key_len;
11456 /* value without "...", terminated by EOL */
11457 @@ -833,7 +796,7 @@
11463 if (p->conf.auth_debug > 1) {
11464 log_error_write(srv, __FILE__, __LINE__, "ss", "username", username);
11465 log_error_write(srv, __FILE__, __LINE__, "ss", "realm", realm);
11466 @@ -845,22 +808,22 @@
11467 log_error_write(srv, __FILE__, __LINE__, "ss", "nc", nc);
11468 log_error_write(srv, __FILE__, __LINE__, "ss", "response", respons);
11472 /* check if everything is transmitted */
11478 (qop && (!nc || !cnonce)) ||
11480 /* missing field */
11482 - log_error_write(srv, __FILE__, __LINE__, "s",
11484 + log_error_write(srv, __FILE__, __LINE__, "s",
11485 "digest: missing field");
11489 - m = get_http_method_name(con->request.http_method);
11490 + m = get_http_method_name(con->request.http_method);
11492 /* password-string == HA1 */
11493 password = buffer_init();
11494 @@ -873,10 +836,10 @@
11495 buffer_free(realm_buf);
11500 buffer_free(username_buf);
11501 buffer_free(realm_buf);
11504 if (p->conf.auth_backend == AUTH_BACKEND_PLAIN) {
11505 /* generate password from plain-text */
11507 @@ -890,16 +853,16 @@
11509 /* transform the 32-byte-hex-md5 to a 16-byte-md5 */
11510 for (i = 0; i < HASHLEN; i++) {
11511 - HA1[i] = hex2int(password->ptr[i*2]) << 4;
11512 - HA1[i] |= hex2int(password->ptr[i*2+1]);
11513 + HA1[i] = hex2int(password->ptr[i*2]) << 4;
11514 + HA1[i] |= hex2int(password->ptr[i*2+1]);
11517 /* we already check that above */
11522 buffer_free(password);
11526 strcasecmp(algorithm, "md5-sess") == 0) {
11528 @@ -910,9 +873,9 @@
11529 MD5_Update(&Md5Ctx, (unsigned char *)cnonce, strlen(cnonce));
11530 MD5_Final(HA1, &Md5Ctx);
11537 /* calculate H(A2) */
11539 MD5_Update(&Md5Ctx, (unsigned char *)m, strlen(m));
11540 @@ -924,7 +887,7 @@
11542 MD5_Final(HA2, &Md5Ctx);
11543 CvtHex(HA2, HA2Hex);
11546 /* calculate response */
11548 MD5_Update(&Md5Ctx, (unsigned char *)a1, HASHHEXLEN);
11549 @@ -942,39 +905,39 @@
11550 MD5_Update(&Md5Ctx, (unsigned char *)HA2Hex, HASHHEXLEN);
11551 MD5_Final(RespHash, &Md5Ctx);
11552 CvtHex(RespHash, a2);
11555 if (0 != strcmp(a2, respons)) {
11556 /* digest not ok */
11559 if (p->conf.auth_debug) {
11560 - log_error_write(srv, __FILE__, __LINE__, "sss",
11561 + log_error_write(srv, __FILE__, __LINE__, "sss",
11562 "digest: digest mismatch", a2, respons);
11565 - log_error_write(srv, __FILE__, __LINE__, "sss",
11567 + log_error_write(srv, __FILE__, __LINE__, "sss",
11568 "digest: auth failed for", username, "wrong password");
11576 /* value is our allow-rules */
11577 if (http_auth_match_rules(srv, p, url->ptr, username, NULL, NULL)) {
11580 - log_error_write(srv, __FILE__, __LINE__, "s",
11582 + log_error_write(srv, __FILE__, __LINE__, "s",
11583 "digest: rules did match");
11590 /* remember the username */
11591 buffer_copy_string(p->auth_user, username);
11597 if (p->conf.auth_debug) {
11598 - log_error_write(srv, __FILE__, __LINE__, "s",
11599 + log_error_write(srv, __FILE__, __LINE__, "s",
11600 "digest: auth ok");
11603 @@ -985,23 +948,23 @@
11611 /* generate shared-secret */
11613 MD5_Update(&Md5Ctx, (unsigned char *)fn->ptr, fn->used - 1);
11614 MD5_Update(&Md5Ctx, (unsigned char *)"+", 1);
11617 /* we assume sizeof(time_t) == 4 here, but if not it ain't a problem at all */
11618 ltostr(hh, srv->cur_ts);
11619 MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
11620 ltostr(hh, rand());
11621 MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
11624 MD5_Final(h, &Md5Ctx);
11632 --- ../lighttpd-1.4.11/src/http_auth.h 2005-08-14 17:12:31.000000000 +0300
11633 +++ lighttpd-1.4.12/src/http_auth.h 2006-07-16 00:26:04.000000000 +0300
11638 -typedef enum { AUTH_BACKEND_UNSET, AUTH_BACKEND_PLAIN,
11639 - AUTH_BACKEND_LDAP, AUTH_BACKEND_HTPASSWD,
11640 - AUTH_BACKEND_HTDIGEST, AUTH_BACKEND_PAM } auth_backend_t;
11642 + AUTH_BACKEND_UNSET,
11643 + AUTH_BACKEND_PLAIN,
11644 + AUTH_BACKEND_LDAP,
11645 + AUTH_BACKEND_HTPASSWD,
11646 + AUTH_BACKEND_HTDIGEST
11651 array *auth_require;
11654 buffer *auth_plain_groupfile;
11655 buffer *auth_plain_userfile;
11658 buffer *auth_htdigest_userfile;
11659 buffer *auth_htpasswd_userfile;
11662 buffer *auth_backend_conf;
11665 buffer *auth_ldap_hostname;
11666 buffer *auth_ldap_basedn;
11667 buffer *auth_ldap_binddn;
11668 @@ -32,15 +36,15 @@
11669 buffer *auth_ldap_filter;
11670 buffer *auth_ldap_cafile;
11671 unsigned short auth_ldap_starttls;
11674 unsigned short auth_debug;
11678 auth_backend_t auth_backend;
11685 buffer *ldap_filter_pre;
11686 buffer *ldap_filter_post;
11688 @@ -49,15 +53,15 @@
11697 buffer *ldap_filter;
11701 mod_auth_plugin_config **config_storage;
11704 mod_auth_plugin_config conf; /* this is only used as long as no handler_ctx is setup */
11705 } mod_auth_plugin_data;
11707 --- ../lighttpd-1.4.11/src/http_auth_digest.h 2006-01-05 00:54:01.000000000 +0200
11708 +++ lighttpd-1.4.12/src/http_auth_digest.h 2006-07-16 00:26:04.000000000 +0300
11718 --- ../lighttpd-1.4.11/src/http_chunk.c 2005-08-11 01:26:50.000000000 +0300
11719 +++ lighttpd-1.4.12/src/http_chunk.c 2006-07-16 00:26:04.000000000 +0300
11722 * the HTTP chunk-API
11729 #include <sys/types.h>
11732 #include <stdlib.h>
11734 -#include <unistd.h>
11738 @@ -23,19 +22,19 @@
11739 static int http_chunk_append_len(server *srv, connection *con, size_t len) {
11740 size_t i, olen = len, j;
11744 b = srv->tmp_chunk_len;
11748 buffer_copy_string(b, "0");
11750 for (i = 0; i < 8 && len; i++) {
11755 /* i is the number of hex digits we have */
11756 buffer_prepare_copy(b, i + 1);
11759 for (j = i-1, len = olen; j+1 > 0; j--) {
11760 b->ptr[j] = (len & 0xf) + (((len & 0xf) <= 9) ? '0' : 'a' - 10);
11762 @@ -43,61 +42,61 @@
11764 b->ptr[b->used++] = '\0';
11768 buffer_append_string(b, "\r\n");
11769 chunkqueue_append_buffer(con->write_queue, b);
11776 int http_chunk_append_file(server *srv, connection *con, buffer *fn, off_t offset, off_t len) {
11780 if (!con) return -1;
11783 cq = con->write_queue;
11786 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
11787 http_chunk_append_len(srv, con, len);
11791 chunkqueue_append_file(cq, fn, offset, len);
11794 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED && len > 0) {
11795 chunkqueue_append_mem(cq, "\r\n", 2 + 1);
11802 int http_chunk_append_buffer(server *srv, connection *con, buffer *mem) {
11806 if (!con) return -1;
11809 cq = con->write_queue;
11812 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
11813 http_chunk_append_len(srv, con, mem->used - 1);
11817 chunkqueue_append_buffer(cq, mem);
11820 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED && mem->used > 0) {
11821 chunkqueue_append_mem(cq, "\r\n", 2 + 1);
11828 int http_chunk_append_mem(server *srv, connection *con, const char * mem, size_t len) {
11832 if (!con) return -1;
11835 cq = con->write_queue;
11839 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
11840 http_chunk_append_len(srv, con, 0);
11841 @@ -107,17 +106,17 @@
11847 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
11848 http_chunk_append_len(srv, con, len - 1);
11852 chunkqueue_append_mem(cq, mem, len);
11855 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
11856 chunkqueue_append_mem(cq, "\r\n", 2 + 1);
11863 @@ -125,9 +124,9 @@
11864 off_t http_chunkqueue_length(server *srv, connection *con) {
11866 log_error_write(srv, __FILE__, __LINE__, "s", "connection is NULL!!");
11873 return chunkqueue_length(con->write_queue);
11875 --- ../lighttpd-1.4.11/src/http_resp.c 1970-01-01 03:00:00.000000000 +0300
11876 +++ lighttpd-1.4.12/src/http_resp.c 2006-07-18 13:03:40.000000000 +0300
11878 +#include <string.h>
11879 +#include <stdlib.h>
11880 +#include <stdio.h>
11881 +#include <assert.h>
11884 +#include "http_resp.h"
11885 +#include "http_resp_parser.h"
11887 +/* declare prototypes for the parser */
11888 +void *http_resp_parserAlloc(void *(*mallocProc)(size_t));
11889 +void http_resp_parserFree(void *p, void (*freeProc)(void*));
11890 +void http_resp_parserTrace(FILE *TraceFILE, char *zTracePrompt);
11891 +void http_resp_parser(void *, int, buffer *, http_resp_ctx_t *);
11896 + chunk *c; /* current chunk in the chunkqueue */
11897 + size_t offset; /* current offset in current chunk */
11900 + size_t lookup_offset;
11903 + int is_statusline;
11904 +} http_resp_tokenizer_t;
11906 +http_resp *http_response_init(void) {
11907 + http_resp *resp = calloc(1, sizeof(*resp));
11909 + resp->reason = buffer_init();
11910 + resp->headers = array_init();
11915 +void http_response_reset(http_resp *resp) {
11916 + if (!resp) return;
11918 + buffer_reset(resp->reason);
11919 + array_reset(resp->headers);
11923 +void http_response_free(http_resp *resp) {
11924 + if (!resp) return;
11926 + buffer_free(resp->reason);
11927 + array_free(resp->headers);
11932 +static int http_resp_get_next_char(http_resp_tokenizer_t *t, unsigned char *c) {
11933 + if (t->offset == t->c->mem->used - 1) {
11934 + /* end of chunk, open next chunk */
11936 + if (!t->c->next) return -1;
11938 + t->c = t->c->next;
11942 + *c = t->c->mem->ptr[t->offset++];
11944 + t->lookup_offset = t->offset;
11945 + t->lookup_c = t->c;
11948 + fprintf(stderr, "%s.%d: get: %c (%d) at offset: %d\r\n", __FILE__, __LINE__, *c > 31 ? *c : ' ', *c, t->offset - 1);
11954 +static int http_resp_lookup_next_char(http_resp_tokenizer_t *t, unsigned char *c) {
11955 + if (t->lookup_offset == t->lookup_c->mem->used - 1) {
11956 + /* end of chunk, open next chunk */
11958 + if (!t->lookup_c->next) return -1;
11960 + t->lookup_c = t->lookup_c->next;
11961 + t->lookup_offset = 0;
11964 + *c = t->lookup_c->mem->ptr[t->lookup_offset++];
11966 + fprintf(stderr, "%s.%d: lookup: %c (%d) at offset: %d\r\n", __FILE__, __LINE__, *c > 31 ? *c : ' ', *c, t->lookup_offset - 1);
11973 +static int http_resp_tokenizer(
11974 + http_resp_tokenizer_t *t,
11981 + /* push the token to the parser */
11983 + while (tid == 0 && 0 == http_resp_get_next_char(t, &c)) {
11997 + if (0 != http_resp_lookup_next_char(t, &c)) return -1;
12002 + t->c = t->lookup_c;
12003 + t->offset = t->lookup_offset;
12005 + t->is_statusline = 0;
12008 + fprintf(stderr, "%s.%d: CR with out LF\r\n", __FILE__, __LINE__);
12015 + t->is_statusline = 0;
12020 + while (c >= 32 && c != 127 && c != 255) {
12021 + if (t->is_statusline) {
12022 + if (c == ':') { t->is_statusline = 0; break; } /* this is not a status line by a real header */
12023 + if (c == 32) break; /* the space is a splitter in the statusline */
12026 + if (c == ':') break; /* the : is the splitter between key and value */
12029 + if (0 != http_resp_lookup_next_char(t, &c)) return -1;
12032 + if (t->c == t->lookup_c &&
12033 + t->offset == t->lookup_offset + 1) {
12035 + fprintf(stderr, "%s.%d: invalid char in string\n", __FILE__, __LINE__);
12041 + /* the lookup points to the first invalid char */
12042 + t->lookup_offset--;
12044 + /* no overlapping string */
12045 + if (t->c == t->lookup_c) {
12046 + buffer_copy_string_len(token, t->c->mem->ptr + t->offset - 1, t->lookup_offset - t->offset + 1);
12048 + /* first chunk */
12049 + buffer_copy_string_len(token, t->c->mem->ptr + t->offset - 1, t->c->mem->used - t->offset);
12051 + /* chunks in the middle */
12052 + for (t->c = t->c->next; t->c != t->lookup_c; t->c = t->c->next) {
12053 + buffer_append_string_buffer(token, t->c->mem);
12054 + t->offset = t->c->mem->used - 1;
12058 + buffer_append_string_len(token, t->c->mem->ptr, t->lookup_offset);
12061 + t->offset = t->lookup_offset;
12076 +parse_status_t http_response_parse_cq(chunkqueue *cq, http_resp *resp) {
12077 + http_resp_tokenizer_t t;
12078 + void *pParser = NULL;
12079 + int token_id = 0;
12080 + buffer *token = NULL;
12081 + http_resp_ctx_t context;
12082 + parse_status_t ret = PARSE_UNSET;
12083 + int last_token_id = 0;
12087 + t.offset = t.c->offset;
12089 + t.is_statusline = 1;
12092 + context.errmsg = buffer_init();
12093 + context.resp = resp;
12095 + pParser = http_resp_parserAlloc( malloc );
12096 + token = buffer_init();
12098 + http_resp_parserTrace(stderr, "http-response: ");
12101 + while((1 == http_resp_tokenizer(&t, &token_id, token)) && context.ok) {
12102 + http_resp_parser(pParser, token_id, token, &context);
12104 + token = buffer_init();
12106 + /* CRLF CRLF ... the header end sequence */
12107 + if (last_token_id == TK_CRLF &&
12108 + token_id == TK_CRLF) break;
12110 + last_token_id = token_id;
12113 + /* oops, the parser failed */
12114 + if (context.ok == 0) {
12115 + ret = PARSE_ERROR;
12117 + if (!buffer_is_empty(context.errmsg)) {
12118 + TRACE("parsing failed: %s", BUF_STR(context.errmsg));
12120 + TRACE("%s", "parsing failed ...");
12124 + http_resp_parser(pParser, 0, token, &context);
12125 + http_resp_parserFree(pParser, free);
12127 + if (context.ok == 0) {
12128 + /* we are missing the some tokens */
12130 + if (!buffer_is_empty(context.errmsg)) {
12131 + TRACE("parsing failed: %s", BUF_STR(context.errmsg));
12134 + if (ret == PARSE_UNSET) {
12135 + ret = buffer_is_empty(context.errmsg) ? PARSE_NEED_MORE : PARSE_ERROR;
12140 + for (c = cq->first; c != t.c; c = c->next) {
12141 + c->offset = c->mem->used - 1;
12144 + c->offset = t.offset;
12146 + ret = PARSE_SUCCESS;
12149 + buffer_free(token);
12150 + buffer_free(context.errmsg);
12155 --- ../lighttpd-1.4.11/src/http_resp.h 1970-01-01 03:00:00.000000000 +0300
12156 +++ lighttpd-1.4.12/src/http_resp.h 2006-07-16 00:26:04.000000000 +0300
12158 +#ifndef _HTTP_RESP_H_
12159 +#define _HTTP_RESP_H_
12161 +#include "array.h"
12162 +#include "chunk.h"
12172 + int protocol; /* http/1.0, http/1.1 */
12173 + int status; /* e.g. 200 */
12174 + buffer *reason; /* e.g. Ok */
12183 +} http_resp_ctx_t;
12185 +http_resp *http_response_init(void);
12186 +void http_response_free(http_resp *resp);
12187 +void http_response_reset(http_resp *resp);
12189 +parse_status_t http_response_parse_cq(chunkqueue *cq, http_resp *http_response);
12192 --- ../lighttpd-1.4.11/src/http_resp_parser.c 1970-01-01 03:00:00.000000000 +0300
12193 +++ lighttpd-1.4.12/src/http_resp_parser.c 2006-07-18 13:03:52.000000000 +0300
12195 +/* Driver template for the LEMON parser generator.
12196 +** The author disclaims copyright to this source code.
12198 +/* First off, code is include which follows the "include" declaration
12199 +** in the input file. */
12200 +#include <stdio.h>
12201 +#line 6 "./http_resp_parser.y"
12203 +#include <assert.h>
12204 +#include <string.h>
12205 +#include "http_resp.h"
12206 +#include "keyvalue.h"
12207 +#include "array.h"
12210 +#line 17 "http_resp_parser.c"
12211 +/* Next is all token values, in a form suitable for use by makeheaders.
12212 +** This section will be null unless lemon is run with the -m switch.
12215 +** These constants (all generated automatically by the parser generator)
12216 +** specify the various kinds of tokens (terminals) that the parser
12219 +** Each symbol here is a terminal symbol in the grammar.
12221 +/* Make sure the INTERFACE macro is defined.
12224 +# define INTERFACE 1
12226 +/* The next thing included is series of defines which control
12227 +** various aspects of the generated parser.
12228 +** YYCODETYPE is the data type used for storing terminal
12229 +** and nonterminal numbers. "unsigned char" is
12230 +** used if there are fewer than 250 terminals
12231 +** and nonterminals. "int" is used otherwise.
12232 +** YYNOCODE is a number of type YYCODETYPE which corresponds
12233 +** to no legal terminal or nonterminal number. This
12234 +** number is used to fill in empty slots of the hash
12236 +** YYFALLBACK If defined, this indicates that one or more tokens
12237 +** have fall-back values which should be used if the
12238 +** original value of the token will not parse.
12239 +** YYACTIONTYPE is the data type used for storing terminal
12240 +** and nonterminal numbers. "unsigned char" is
12241 +** used if there are fewer than 250 rules and
12242 +** states combined. "int" is used otherwise.
12243 +** http_resp_parserTOKENTYPE is the data type used for minor tokens given
12244 +** directly to the parser from the tokenizer.
12245 +** YYMINORTYPE is the data type used for all minor tokens.
12246 +** This is typically a union of many types, one of
12247 +** which is http_resp_parserTOKENTYPE. The entry in the union
12248 +** for base tokens is called "yy0".
12249 +** YYSTACKDEPTH is the maximum depth of the parser's stack.
12250 +** http_resp_parserARG_SDECL A static variable declaration for the %extra_argument
12251 +** http_resp_parserARG_PDECL A parameter declaration for the %extra_argument
12252 +** http_resp_parserARG_STORE Code to store %extra_argument into yypParser
12253 +** http_resp_parserARG_FETCH Code to extract %extra_argument from yypParser
12254 +** YYNSTATE the combined number of states.
12255 +** YYNRULE the number of rules in the grammar
12256 +** YYERRORSYMBOL is the code number of the error symbol. If not
12257 +** defined, then do no error processing.
12260 +#define YYCODETYPE unsigned char
12261 +#define YYNOCODE 12
12262 +#define YYACTIONTYPE unsigned char
12263 +#define http_resp_parserTOKENTYPE buffer *
12265 + http_resp_parserTOKENTYPE yy0;
12267 + data_string * yy9;
12272 +#define YYSTACKDEPTH 100
12273 +#define http_resp_parserARG_SDECL http_resp_ctx_t *ctx;
12274 +#define http_resp_parserARG_PDECL ,http_resp_ctx_t *ctx
12275 +#define http_resp_parserARG_FETCH http_resp_ctx_t *ctx = yypParser->ctx
12276 +#define http_resp_parserARG_STORE yypParser->ctx = ctx
12277 +#define YYNSTATE 19
12279 +#define YYERRORSYMBOL 4
12280 +#define YYERRSYMDT yy23
12281 +#define YY_NO_ACTION (YYNSTATE+YYNRULE+2)
12282 +#define YY_ACCEPT_ACTION (YYNSTATE+YYNRULE+1)
12283 +#define YY_ERROR_ACTION (YYNSTATE+YYNRULE)
12285 +/* Next are that tables used to determine what action to take based on the
12286 +** current state and lookahead token. These tables are used to implement
12287 +** functions that take a state number and lookahead value and return an
12288 +** action integer.
12290 +** Suppose the action integer is N. Then the action is determined as
12293 +** 0 <= N < YYNSTATE Shift N. That is, push the lookahead
12294 +** token onto the stack and goto state N.
12296 +** YYNSTATE <= N < YYNSTATE+YYNRULE Reduce by rule N-YYNSTATE.
12298 +** N == YYNSTATE+YYNRULE A syntax error has occurred.
12300 +** N == YYNSTATE+YYNRULE+1 The parser accepts its input.
12302 +** N == YYNSTATE+YYNRULE+2 No such action. Denotes unused
12303 +** slots in the yy_action[] table.
12305 +** The action table is constructed as a single large table named yy_action[].
12306 +** Given state S and lookahead X, the action is computed as
12308 +** yy_action[ yy_shift_ofst[S] + X ]
12310 +** If the index value yy_shift_ofst[S]+X is out of range or if the value
12311 +** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
12312 +** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
12313 +** and that yy_default[S] should be used instead.
12315 +** The formula above is for computing the action when the lookahead is
12316 +** a terminal symbol. If the lookahead is a non-terminal (as occurs after
12317 +** a reduce action) then the yy_reduce_ofst[] array is used in place of
12318 +** the yy_shift_ofst[] array and YY_REDUCE_USE_DFLT is used in place of
12319 +** YY_SHIFT_USE_DFLT.
12321 +** The following are the tables generated in this section:
12323 +** yy_action[] A single table containing all actions.
12324 +** yy_lookahead[] A table containing the lookahead for each entry in
12325 +** yy_action. Used to detect hash collisions.
12326 +** yy_shift_ofst[] For each state, the offset into yy_action for
12327 +** shifting terminals.
12328 +** yy_reduce_ofst[] For each state, the offset into yy_action for
12329 +** shifting non-terminals after a reduce.
12330 +** yy_default[] Default action for each state.
12332 +static YYACTIONTYPE yy_action[] = {
12333 + /* 0 */ 8, 29, 18, 1, 14, 2, 4, 11, 15, 12,
12334 + /* 10 */ 14, 13, 4, 21, 5, 19, 3, 5, 6, 7,
12335 + /* 20 */ 9, 17, 16, 4, 20, 22, 22, 10,
12337 +static YYCODETYPE yy_lookahead[] = {
12338 + /* 0 */ 5, 6, 2, 8, 9, 1, 2, 1, 2, 8,
12339 + /* 10 */ 9, 1, 2, 2, 3, 0, 9, 3, 2, 1,
12340 + /* 20 */ 7, 2, 2, 2, 0, 2, 11, 10,
12342 +#define YY_SHIFT_USE_DFLT (-1)
12343 +static signed char yy_shift_ofst[] = {
12344 + /* 0 */ 0, 4, 15, -1, 14, 16, 18, -1, 19, 20,
12345 + /* 10 */ 6, 21, 10, 24, -1, -1, -1, 23, 11,
12347 +#define YY_REDUCE_USE_DFLT (-6)
12348 +static signed char yy_reduce_ofst[] = {
12349 + /* 0 */ -5, 7, -6, -6, -6, -6, -6, -6, 13, 17,
12350 + /* 10 */ -6, 1, 7, -6, -6, -6, -6, -6, -6,
12352 +static YYACTIONTYPE yy_default[] = {
12353 + /* 0 */ 28, 28, 28, 25, 28, 28, 28, 27, 28, 28,
12354 + /* 10 */ 28, 28, 28, 28, 26, 24, 23, 28, 28,
12356 +#define YY_SZ_ACTTAB (sizeof(yy_action)/sizeof(yy_action[0]))
12358 +/* The next table maps tokens into fallback tokens. If a construct
12359 +** like the following:
12361 +** %fallback ID X Y Z.
12363 +** appears in the grammer, then ID becomes a fallback token for X, Y,
12364 +** and Z. Whenever one of the tokens X, Y, or Z is input to the parser
12365 +** but it does not parse, the type of the token is changed to ID and
12366 +** the parse is retried before an error is thrown.
12369 +static const YYCODETYPE yyFallback[] = {
12371 +#endif /* YYFALLBACK */
12373 +/* The following structure represents a single element of the
12374 +** parser's stack. Information stored includes:
12376 +** + The state number for the parser at this level of the stack.
12378 +** + The value of the token stored at this level of the stack.
12379 +** (In other words, the "major" token.)
12381 +** + The semantic value stored at this level of the stack. This is
12382 +** the information used by the action routines in the grammar.
12383 +** It is sometimes called the "minor" token.
12385 +struct yyStackEntry {
12386 + int stateno; /* The state-number */
12387 + int major; /* The major token value. This is the code
12388 + ** number for the token at this stack level */
12389 + YYMINORTYPE minor; /* The user-supplied minor token value. This
12390 + ** is the value of the token */
12392 +typedef struct yyStackEntry yyStackEntry;
12394 +/* The state of the parser is completely contained in an instance of
12395 +** the following structure */
12397 + int yyidx; /* Index of top element in stack */
12398 + int yyerrcnt; /* Shifts left before out of the error */
12399 + http_resp_parserARG_SDECL /* A place to hold %extra_argument */
12400 + yyStackEntry yystack[YYSTACKDEPTH]; /* The parser's stack */
12402 +typedef struct yyParser yyParser;
12405 +#include <stdio.h>
12406 +static FILE *yyTraceFILE = 0;
12407 +static char *yyTracePrompt = 0;
12408 +#endif /* NDEBUG */
12412 +** Turn parser tracing on by giving a stream to which to write the trace
12413 +** and a prompt to preface each trace message. Tracing is turned off
12414 +** by making either argument NULL
12418 +** <li> A FILE* to which trace output should be written.
12419 +** If NULL, then tracing is turned off.
12420 +** <li> A prefix string written at the beginning of every
12421 +** line of trace output. If NULL, then tracing is
12428 +void http_resp_parserTrace(FILE *TraceFILE, char *zTracePrompt){
12429 + yyTraceFILE = TraceFILE;
12430 + yyTracePrompt = zTracePrompt;
12431 + if( yyTraceFILE==0 ) yyTracePrompt = 0;
12432 + else if( yyTracePrompt==0 ) yyTraceFILE = 0;
12434 +#endif /* NDEBUG */
12437 +/* For tracing shifts, the names of all terminals and nonterminals
12438 +** are required. The following table supplies these names */
12439 +static const char *yyTokenName[] = {
12440 + "$", "CRLF", "STRING", "COLON",
12441 + "error", "protocol", "response_hdr", "number",
12442 + "headers", "header", "reason",
12444 +#endif /* NDEBUG */
12447 +/* For tracing reduce actions, the names of all rules are required.
12449 +static const char *yyRuleName[] = {
12450 + /* 0 */ "response_hdr ::= headers CRLF",
12451 + /* 1 */ "response_hdr ::= protocol number reason CRLF headers CRLF",
12452 + /* 2 */ "protocol ::= STRING",
12453 + /* 3 */ "number ::= STRING",
12454 + /* 4 */ "reason ::= STRING",
12455 + /* 5 */ "reason ::= reason STRING",
12456 + /* 6 */ "headers ::= headers header",
12457 + /* 7 */ "headers ::= header",
12458 + /* 8 */ "header ::= STRING COLON STRING CRLF",
12460 +#endif /* NDEBUG */
12463 +** This function returns the symbolic name associated with a token
12466 +const char *http_resp_parserTokenName(int tokenType){
12468 + if( tokenType>0 && tokenType<(sizeof(yyTokenName)/sizeof(yyTokenName[0])) ){
12469 + return yyTokenName[tokenType];
12471 + return "Unknown";
12479 +** This function allocates a new parser.
12480 +** The only argument is a pointer to a function which works like
12484 +** A pointer to the function used to allocate memory.
12487 +** A pointer to a parser. This pointer is used in subsequent calls
12488 +** to http_resp_parser and http_resp_parserFree.
12490 +void *http_resp_parserAlloc(void *(*mallocProc)(size_t)){
12491 + yyParser *pParser;
12492 + pParser = (yyParser*)(*mallocProc)( (size_t)sizeof(yyParser) );
12494 + pParser->yyidx = -1;
12499 +/* The following function deletes the value associated with a
12500 +** symbol. The symbol can be either a terminal or nonterminal.
12501 +** "yymajor" is the symbol code, and "yypminor" is a pointer to
12504 +static void yy_destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor){
12505 + switch( yymajor ){
12506 + /* Here is inserted the actions which take place when a
12507 + ** terminal or non-terminal is destroyed. This can happen
12508 + ** when the symbol is popped from the stack during a
12509 + ** reduce or during error processing or when a parser is
12510 + ** being destroyed before it is finished parsing.
12512 + ** Note: during a reduce, the only symbols destroyed are those
12513 + ** which appear on the RHS of the rule, but which are not used
12514 + ** inside the C code.
12519 +#line 25 "./http_resp_parser.y"
12520 +{ buffer_free((yypminor->yy0)); }
12521 +#line 327 "http_resp_parser.c"
12524 +#line 24 "./http_resp_parser.y"
12525 +{ buffer_free((yypminor->yy0)); }
12526 +#line 332 "http_resp_parser.c"
12528 + default: break; /* If no destructor action specified: do nothing */
12533 +** Pop the parser's stack once.
12535 +** If there is a destructor routine associated with the token which
12536 +** is popped from the stack, then call it.
12538 +** Return the major token number for the symbol popped.
12540 +static int yy_pop_parser_stack(yyParser *pParser){
12541 + YYCODETYPE yymajor;
12542 + yyStackEntry *yytos = &pParser->yystack[pParser->yyidx];
12544 + if( pParser->yyidx<0 ) return 0;
12546 + if( yyTraceFILE && pParser->yyidx>=0 ){
12547 + fprintf(yyTraceFILE,"%sPopping %s\n",
12549 + yyTokenName[yytos->major]);
12552 + yymajor = yytos->major;
12553 + yy_destructor( yymajor, &yytos->minor);
12554 + pParser->yyidx--;
12559 +** Deallocate and destroy a parser. Destructors are all called for
12560 +** all stack elements before shutting the parser down.
12564 +** <li> A pointer to the parser. This should be a pointer
12565 +** obtained from http_resp_parserAlloc.
12566 +** <li> A pointer to a function used to reclaim memory obtained
12570 +void http_resp_parserFree(
12571 + void *p, /* The parser to be deleted */
12572 + void (*freeProc)(void*) /* Function used to reclaim memory */
12574 + yyParser *pParser = (yyParser*)p;
12575 + if( pParser==0 ) return;
12576 + while( pParser->yyidx>=0 ) yy_pop_parser_stack(pParser);
12577 + (*freeProc)((void*)pParser);
12581 +** Find the appropriate action for a parser given the terminal
12582 +** look-ahead token iLookAhead.
12584 +** If the look-ahead token is YYNOCODE, then check to see if the action is
12585 +** independent of the look-ahead. If it is, return the action, otherwise
12586 +** return YY_NO_ACTION.
12588 +static int yy_find_shift_action(
12589 + yyParser *pParser, /* The parser */
12590 + int iLookAhead /* The look-ahead token */
12593 + int stateno = pParser->yystack[pParser->yyidx].stateno;
12595 + /* if( pParser->yyidx<0 ) return YY_NO_ACTION; */
12596 + i = yy_shift_ofst[stateno];
12597 + if( i==YY_SHIFT_USE_DFLT ){
12598 + return yy_default[stateno];
12600 + if( iLookAhead==YYNOCODE ){
12601 + return YY_NO_ACTION;
12604 + if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
12606 + int iFallback; /* Fallback token */
12607 + if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
12608 + && (iFallback = yyFallback[iLookAhead])!=0 ){
12610 + if( yyTraceFILE ){
12611 + fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
12612 + yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
12615 + return yy_find_shift_action(pParser, iFallback);
12618 + return yy_default[stateno];
12620 + return yy_action[i];
12625 +** Find the appropriate action for a parser given the non-terminal
12626 +** look-ahead token iLookAhead.
12628 +** If the look-ahead token is YYNOCODE, then check to see if the action is
12629 +** independent of the look-ahead. If it is, return the action, otherwise
12630 +** return YY_NO_ACTION.
12632 +static int yy_find_reduce_action(
12633 + yyParser *pParser, /* The parser */
12634 + int iLookAhead /* The look-ahead token */
12637 + int stateno = pParser->yystack[pParser->yyidx].stateno;
12639 + i = yy_reduce_ofst[stateno];
12640 + if( i==YY_REDUCE_USE_DFLT ){
12641 + return yy_default[stateno];
12643 + if( iLookAhead==YYNOCODE ){
12644 + return YY_NO_ACTION;
12647 + if( i<0 || i>=YY_SZ_ACTTAB || yy_lookahead[i]!=iLookAhead ){
12648 + return yy_default[stateno];
12650 + return yy_action[i];
12655 +** Perform a shift action.
12657 +static void yy_shift(
12658 + yyParser *yypParser, /* The parser to be shifted */
12659 + int yyNewState, /* The new state to shift in */
12660 + int yyMajor, /* The major token to shift in */
12661 + YYMINORTYPE *yypMinor /* Pointer ot the minor token to shift in */
12663 + yyStackEntry *yytos;
12664 + yypParser->yyidx++;
12665 + if( yypParser->yyidx>=YYSTACKDEPTH ){
12666 + http_resp_parserARG_FETCH;
12667 + yypParser->yyidx--;
12669 + if( yyTraceFILE ){
12670 + fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt);
12673 + while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
12674 + /* Here code is inserted which will execute if the parser
12675 + ** stack every overflows */
12676 + http_resp_parserARG_STORE; /* Suppress warning about unused %extra_argument var */
12679 + yytos = &yypParser->yystack[yypParser->yyidx];
12680 + yytos->stateno = yyNewState;
12681 + yytos->major = yyMajor;
12682 + yytos->minor = *yypMinor;
12684 + if( yyTraceFILE && yypParser->yyidx>0 ){
12686 + fprintf(yyTraceFILE,"%sShift %d\n",yyTracePrompt,yyNewState);
12687 + fprintf(yyTraceFILE,"%sStack:",yyTracePrompt);
12688 + for(i=1; i<=yypParser->yyidx; i++)
12689 + fprintf(yyTraceFILE," %s",yyTokenName[yypParser->yystack[i].major]);
12690 + fprintf(yyTraceFILE,"\n");
12695 +/* The following table contains information about every rule that
12696 +** is used during the reduce.
12699 + YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */
12700 + unsigned char nrhs; /* Number of right-hand side symbols in the rule */
12701 +} yyRuleInfo[] = {
12713 +static void yy_accept(yyParser*); /* Forward Declaration */
12716 +** Perform a reduce action and the shift that must immediately
12717 +** follow the reduce.
12719 +static void yy_reduce(
12720 + yyParser *yypParser, /* The parser */
12721 + int yyruleno /* Number of the rule by which to reduce */
12723 + int yygoto; /* The next state */
12724 + int yyact; /* The next action */
12725 + YYMINORTYPE yygotominor; /* The LHS of the rule reduced */
12726 + yyStackEntry *yymsp; /* The top of the parser's stack */
12727 + int yysize; /* Amount to pop the stack */
12728 + http_resp_parserARG_FETCH;
12729 + yymsp = &yypParser->yystack[yypParser->yyidx];
12731 + if( yyTraceFILE && yyruleno>=0
12732 + && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){
12733 + fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
12734 + yyRuleName[yyruleno]);
12736 +#endif /* NDEBUG */
12738 + switch( yyruleno ){
12739 + /* Beginning here are the reduction cases. A typical example
12742 + ** #line <lineno> <grammarfile>
12743 + ** { ... } // User supplied code
12744 + ** #line <lineno> <thisfile>
12748 +#line 28 "./http_resp_parser.y"
12750 + http_resp *resp = ctx->resp;
12753 + resp->protocol = HTTP_VERSION_UNSET;
12755 + buffer_copy_string(resp->reason, ""); /* no reason */
12756 + array_free(resp->headers);
12757 + resp->headers = yymsp[-1].minor.yy12;
12759 + if (NULL == (ds = (data_string *)array_get_element(yymsp[-1].minor.yy12, "Status"))) {
12760 + resp->status = 0;
12763 + resp->status = strtol(ds->value->ptr, &err, 10);
12765 + if (*err != '\0' && *err != ' ') {
12766 + buffer_copy_string(ctx->errmsg, "expected a number: ");
12767 + buffer_append_string_buffer(ctx->errmsg, ds->value);
12768 + buffer_append_string(ctx->errmsg, err);
12774 + yymsp[-1].minor.yy12 = NULL;
12776 +#line 582 "http_resp_parser.c"
12777 + yy_destructor(1,&yymsp[0].minor);
12780 +#line 56 "./http_resp_parser.y"
12782 + http_resp *resp = ctx->resp;
12784 + resp->status = yymsp[-4].minor.yy20;
12785 + resp->protocol = yymsp[-5].minor.yy20;
12786 + buffer_copy_string_buffer(resp->reason, yymsp[-3].minor.yy0);
12787 + buffer_free(yymsp[-3].minor.yy0);
12789 + array_free(resp->headers);
12791 + resp->headers = yymsp[-1].minor.yy12;
12793 +#line 599 "http_resp_parser.c"
12794 + yy_destructor(1,&yymsp[-2].minor);
12795 + yy_destructor(1,&yymsp[0].minor);
12798 +#line 69 "./http_resp_parser.y"
12800 + if (buffer_is_equal_string(yymsp[0].minor.yy0, CONST_STR_LEN("HTTP/1.0"))) {
12801 + yygotominor.yy20 = HTTP_VERSION_1_0;
12802 + } else if (buffer_is_equal_string(yymsp[0].minor.yy0, CONST_STR_LEN("HTTP/1.1"))) {
12803 + yygotominor.yy20 = HTTP_VERSION_1_1;
12805 + buffer_copy_string(ctx->errmsg, "unknown protocol: ");
12806 + buffer_append_string_buffer(ctx->errmsg, yymsp[0].minor.yy0);
12810 + buffer_free(yymsp[0].minor.yy0);
12812 +#line 618 "http_resp_parser.c"
12815 +#line 83 "./http_resp_parser.y"
12818 + yygotominor.yy20 = strtol(yymsp[0].minor.yy0->ptr, &err, 10);
12820 + if (*err != '\0') {
12821 + buffer_copy_string(ctx->errmsg, "expected a number, got: ");
12822 + buffer_append_string_buffer(ctx->errmsg, yymsp[0].minor.yy0);
12826 + buffer_free(yymsp[0].minor.yy0);
12828 +#line 634 "http_resp_parser.c"
12831 +#line 96 "./http_resp_parser.y"
12833 + yygotominor.yy0 = yymsp[0].minor.yy0;
12835 +#line 641 "http_resp_parser.c"
12838 +#line 100 "./http_resp_parser.y"
12840 + yygotominor.yy0 = yymsp[-1].minor.yy0;
12842 + buffer_append_string(yygotominor.yy0, " ");
12843 + buffer_append_string_buffer(yygotominor.yy0, yymsp[0].minor.yy0);
12845 + buffer_free(yymsp[0].minor.yy0);
12847 +#line 653 "http_resp_parser.c"
12850 +#line 109 "./http_resp_parser.y"
12852 + yygotominor.yy12 = yymsp[-1].minor.yy12;
12854 + array_insert_unique(yygotominor.yy12, (data_unset *)yymsp[0].minor.yy9);
12856 +#line 662 "http_resp_parser.c"
12859 +#line 115 "./http_resp_parser.y"
12861 + yygotominor.yy12 = array_init();
12863 + array_insert_unique(yygotominor.yy12, (data_unset *)yymsp[0].minor.yy9);
12865 +#line 671 "http_resp_parser.c"
12868 +#line 120 "./http_resp_parser.y"
12870 + yygotominor.yy9 = data_string_init();
12872 + buffer_copy_string_buffer(yygotominor.yy9->key, yymsp[-3].minor.yy0);
12873 + buffer_copy_string_buffer(yygotominor.yy9->value, yymsp[-1].minor.yy0);
12874 + buffer_free(yymsp[-3].minor.yy0);
12875 + buffer_free(yymsp[-1].minor.yy0);
12877 +#line 683 "http_resp_parser.c"
12878 + yy_destructor(3,&yymsp[-2].minor);
12879 + yy_destructor(1,&yymsp[0].minor);
12882 + yygoto = yyRuleInfo[yyruleno].lhs;
12883 + yysize = yyRuleInfo[yyruleno].nrhs;
12884 + yypParser->yyidx -= yysize;
12885 + yyact = yy_find_reduce_action(yypParser,yygoto);
12886 + if( yyact < YYNSTATE ){
12887 + yy_shift(yypParser,yyact,yygoto,&yygotominor);
12888 + }else if( yyact == YYNSTATE + YYNRULE + 1 ){
12889 + yy_accept(yypParser);
12894 +** The following code executes when the parse fails
12896 +static void yy_parse_failed(
12897 + yyParser *yypParser /* The parser */
12899 + http_resp_parserARG_FETCH;
12901 + if( yyTraceFILE ){
12902 + fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt);
12905 + while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
12906 + /* Here code is inserted which will be executed whenever the
12907 + ** parser fails */
12908 +#line 15 "./http_resp_parser.y"
12912 +#line 718 "http_resp_parser.c"
12913 + http_resp_parserARG_STORE; /* Suppress warning about unused %extra_argument variable */
12917 +** The following code executes when a syntax error first occurs.
12919 +static void yy_syntax_error(
12920 + yyParser *yypParser, /* The parser */
12921 + int yymajor, /* The major type of the error token */
12922 + YYMINORTYPE yyminor /* The minor type of the error token */
12924 + http_resp_parserARG_FETCH;
12925 +#define TOKEN (yyminor.yy0)
12926 + http_resp_parserARG_STORE; /* Suppress warning about unused %extra_argument variable */
12930 +** The following is executed when the parser accepts
12932 +static void yy_accept(
12933 + yyParser *yypParser /* The parser */
12935 + http_resp_parserARG_FETCH;
12937 + if( yyTraceFILE ){
12938 + fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt);
12941 + while( yypParser->yyidx>=0 ) yy_pop_parser_stack(yypParser);
12942 + /* Here code is inserted which will be executed whenever the
12943 + ** parser accepts */
12944 + http_resp_parserARG_STORE; /* Suppress warning about unused %extra_argument variable */
12947 +/* The main parser program.
12948 +** The first argument is a pointer to a structure obtained from
12949 +** "http_resp_parserAlloc" which describes the current state of the parser.
12950 +** The second argument is the major token number. The third is
12951 +** the minor token. The fourth optional argument is whatever the
12952 +** user wants (and specified in the grammar) and is available for
12953 +** use by the action routines.
12957 +** <li> A pointer to the parser (an opaque structure.)
12958 +** <li> The major token number.
12959 +** <li> The minor token number.
12960 +** <li> An option argument of a grammar-specified type.
12966 +void http_resp_parser(
12967 + void *yyp, /* The parser */
12968 + int yymajor, /* The major token code number */
12969 + http_resp_parserTOKENTYPE yyminor /* The value for the token */
12970 + http_resp_parserARG_PDECL /* Optional %extra_argument parameter */
12972 + YYMINORTYPE yyminorunion;
12973 + int yyact; /* The parser action. */
12974 + int yyendofinput; /* True if we are at the end of input */
12975 + int yyerrorhit = 0; /* True if yymajor has invoked an error */
12976 + yyParser *yypParser; /* The parser */
12978 + /* (re)initialize the parser, if necessary */
12979 + yypParser = (yyParser*)yyp;
12980 + if( yypParser->yyidx<0 ){
12981 + if( yymajor==0 ) return;
12982 + yypParser->yyidx = 0;
12983 + yypParser->yyerrcnt = -1;
12984 + yypParser->yystack[0].stateno = 0;
12985 + yypParser->yystack[0].major = 0;
12987 + yyminorunion.yy0 = yyminor;
12988 + yyendofinput = (yymajor==0);
12989 + http_resp_parserARG_STORE;
12992 + if( yyTraceFILE ){
12993 + fprintf(yyTraceFILE,"%sInput %s\n",yyTracePrompt,yyTokenName[yymajor]);
12998 + yyact = yy_find_shift_action(yypParser,yymajor);
12999 + if( yyact<YYNSTATE ){
13000 + yy_shift(yypParser,yyact,yymajor,&yyminorunion);
13001 + yypParser->yyerrcnt--;
13002 + if( yyendofinput && yypParser->yyidx>=0 ){
13005 + yymajor = YYNOCODE;
13007 + }else if( yyact < YYNSTATE + YYNRULE ){
13008 + yy_reduce(yypParser,yyact-YYNSTATE);
13009 + }else if( yyact == YY_ERROR_ACTION ){
13012 + if( yyTraceFILE ){
13013 + fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt);
13016 +#ifdef YYERRORSYMBOL
13017 + /* A syntax error has occurred.
13018 + ** The response to an error depends upon whether or not the
13019 + ** grammar defines an error token "ERROR".
13021 + ** This is what we do if the grammar does define ERROR:
13023 + ** * Call the %syntax_error function.
13025 + ** * Begin popping the stack until we enter a state where
13026 + ** it is legal to shift the error symbol, then shift
13027 + ** the error symbol.
13029 + ** * Set the error count to three.
13031 + ** * Begin accepting and shifting new tokens. No new error
13032 + ** processing will occur until three tokens have been
13033 + ** shifted successfully.
13036 + if( yypParser->yyerrcnt<0 ){
13037 + yy_syntax_error(yypParser,yymajor,yyminorunion);
13039 + yymx = yypParser->yystack[yypParser->yyidx].major;
13040 + if( yymx==YYERRORSYMBOL || yyerrorhit ){
13042 + if( yyTraceFILE ){
13043 + fprintf(yyTraceFILE,"%sDiscard input token %s\n",
13044 + yyTracePrompt,yyTokenName[yymajor]);
13047 + yy_destructor(yymajor,&yyminorunion);
13048 + yymajor = YYNOCODE;
13051 + yypParser->yyidx >= 0 &&
13052 + yymx != YYERRORSYMBOL &&
13053 + (yyact = yy_find_shift_action(yypParser,YYERRORSYMBOL)) >= YYNSTATE
13055 + yy_pop_parser_stack(yypParser);
13057 + if( yypParser->yyidx < 0 || yymajor==0 ){
13058 + yy_destructor(yymajor,&yyminorunion);
13059 + yy_parse_failed(yypParser);
13060 + yymajor = YYNOCODE;
13061 + }else if( yymx!=YYERRORSYMBOL ){
13063 + u2.YYERRSYMDT = 0;
13064 + yy_shift(yypParser,yyact,YYERRORSYMBOL,&u2);
13067 + yypParser->yyerrcnt = 3;
13069 +#else /* YYERRORSYMBOL is not defined */
13070 + /* This is what we do if the grammar does not define ERROR:
13072 + ** * Report an error message, and throw away the input token.
13074 + ** * If the input token is $, then fail the parse.
13076 + ** As before, subsequent error messages are suppressed until
13077 + ** three input tokens have been successfully shifted.
13079 + if( yypParser->yyerrcnt<=0 ){
13080 + yy_syntax_error(yypParser,yymajor,yyminorunion);
13082 + yypParser->yyerrcnt = 3;
13083 + yy_destructor(yymajor,&yyminorunion);
13084 + if( yyendofinput ){
13085 + yy_parse_failed(yypParser);
13087 + yymajor = YYNOCODE;
13090 + yy_accept(yypParser);
13091 + yymajor = YYNOCODE;
13093 + }while( yymajor!=YYNOCODE && yypParser->yyidx>=0 );
13096 --- ../lighttpd-1.4.11/src/http_resp_parser.h 1970-01-01 03:00:00.000000000 +0300
13097 +++ lighttpd-1.4.12/src/http_resp_parser.h 2006-07-18 13:03:52.000000000 +0300
13100 +#define TK_STRING 2
13101 +#define TK_COLON 3
13102 --- ../lighttpd-1.4.11/src/http_resp_parser.y 1970-01-01 03:00:00.000000000 +0300
13103 +++ lighttpd-1.4.12/src/http_resp_parser.y 2006-07-18 13:03:40.000000000 +0300
13106 +%token_type {buffer *}
13107 +%extra_argument {http_resp_ctx_t *ctx}
13108 +%name http_resp_parser
13111 +#include <assert.h>
13112 +#include <string.h>
13113 +#include "http_resp.h"
13114 +#include "keyvalue.h"
13115 +#include "array.h"
13123 +%type protocol { int }
13124 +%type response_hdr { http_resp * }
13125 +%type number { int }
13126 +%type headers { array * }
13127 +%type header { data_string * }
13128 +%destructor reason { buffer_free($$); }
13129 +%token_destructor { buffer_free($$); }
13131 +/* just headers + Status: ... */
13132 +response_hdr ::= headers(HDR) CRLF . {
13133 + http_resp *resp = ctx->resp;
13136 + resp->protocol = HTTP_VERSION_UNSET;
13138 + buffer_copy_string(resp->reason, ""); /* no reason */
13139 + array_free(resp->headers);
13140 + resp->headers = HDR;
13142 + if (NULL == (ds = (data_string *)array_get_element(HDR, "Status"))) {
13143 + resp->status = 0;
13146 + resp->status = strtol(ds->value->ptr, &err, 10);
13148 + if (*err != '\0' && *err != ' ') {
13149 + buffer_copy_string(ctx->errmsg, "expected a number: ");
13150 + buffer_append_string_buffer(ctx->errmsg, ds->value);
13151 + buffer_append_string(ctx->errmsg, err);
13159 +/* HTTP/1.0 <status> ... */
13160 +response_hdr ::= protocol(B) number(C) reason(D) CRLF headers(HDR) CRLF . {
13161 + http_resp *resp = ctx->resp;
13163 + resp->status = C;
13164 + resp->protocol = B;
13165 + buffer_copy_string_buffer(resp->reason, D);
13168 + array_free(resp->headers);
13170 + resp->headers = HDR;
13173 +protocol(A) ::= STRING(B). {
13174 + if (buffer_is_equal_string(B, CONST_STR_LEN("HTTP/1.0"))) {
13175 + A = HTTP_VERSION_1_0;
13176 + } else if (buffer_is_equal_string(B, CONST_STR_LEN("HTTP/1.1"))) {
13177 + A = HTTP_VERSION_1_1;
13179 + buffer_copy_string(ctx->errmsg, "unknown protocol: ");
13180 + buffer_append_string_buffer(ctx->errmsg, B);
13187 +number(A) ::= STRING(B). {
13189 + A = strtol(B->ptr, &err, 10);
13191 + if (*err != '\0') {
13192 + buffer_copy_string(ctx->errmsg, "expected a number, got: ");
13193 + buffer_append_string_buffer(ctx->errmsg, B);
13200 +reason(A) ::= STRING(B). {
13204 +reason(A) ::= reason(C) STRING(B). {
13207 + buffer_append_string(A, " ");
13208 + buffer_append_string_buffer(A, B);
13213 +headers(HDRS) ::= headers(SRC) header(HDR). {
13216 + array_insert_unique(HDRS, (data_unset *)HDR);
13219 +headers(HDRS) ::= header(HDR). {
13220 + HDRS = array_init();
13222 + array_insert_unique(HDRS, (data_unset *)HDR);
13224 +header(HDR) ::= STRING(A) COLON STRING(B) CRLF. {
13225 + HDR = data_string_init();
13227 + buffer_copy_string_buffer(HDR->key, A);
13228 + buffer_copy_string_buffer(HDR->value, B);
13232 --- ../lighttpd-1.4.11/src/inet_ntop_cache.c 2005-08-11 01:26:38.000000000 +0300
13233 +++ lighttpd-1.4.12/src/inet_ntop_cache.c 2006-07-16 00:26:04.000000000 +0300
13235 #include "sys-socket.h"
13237 const char * inet_ntop_cache_get_ip(server *srv, sock_addr *addr) {
13241 for (i = 0; i < INET_NTOP_CACHE_MAX; i++) {
13242 if (srv->inet_ntop_cache[i].ts != 0) {
13243 @@ -20,31 +20,31 @@
13244 srv->inet_ntop_cache[i].addr.ipv4.s_addr == addr->ipv4.sin_addr.s_addr) {
13245 /* IPv4 found in cache */
13254 if (i == INET_NTOP_CACHE_MAX) {
13255 /* not found in cache */
13259 - inet_ntop(addr->plain.sa_family,
13260 - addr->plain.sa_family == AF_INET6 ?
13261 + inet_ntop(addr->plain.sa_family,
13262 + addr->plain.sa_family == AF_INET6 ?
13263 (const void *) &(addr->ipv6.sin6_addr) :
13264 (const void *) &(addr->ipv4.sin_addr),
13265 srv->inet_ntop_cache[i].b2, INET6_ADDRSTRLEN);
13268 srv->inet_ntop_cache[i].ts = srv->cur_ts;
13269 srv->inet_ntop_cache[i].family = addr->plain.sa_family;
13272 if (srv->inet_ntop_cache[i].family == AF_INET) {
13273 srv->inet_ntop_cache[i].addr.ipv4.s_addr = addr->ipv4.sin_addr.s_addr;
13274 } else if (srv->inet_ntop_cache[i].family == AF_INET6) {
13275 memcpy(srv->inet_ntop_cache[i].addr.ipv6.s6_addr, addr->ipv6.sin6_addr.s6_addr, 16);
13280 return srv->inet_ntop_cache[i].b2;
13283 --- ../lighttpd-1.4.11/src/iosocket.c 1970-01-01 03:00:00.000000000 +0300
13284 +++ lighttpd-1.4.12/src/iosocket.c 2006-07-18 13:03:40.000000000 +0300
13286 +#include <stdlib.h>
13288 +#include "iosocket.h"
13289 +#include "sys-socket.h"
13290 +#include "sys-files.h"
13291 +#include "array-static.h"
13293 +iosocket *iosocket_init(void) {
13294 + STRUCT_INIT(iosocket, sock);
13296 + sock->fde_ndx = -1;
13299 + sock->type = IOSOCKET_TYPE_SOCKET;
13304 +void iosocket_free(iosocket *sock) {
13305 + if (!sock) return;
13307 + if (sock->fd != -1) {
13308 + switch (sock->type) {
13309 + case IOSOCKET_TYPE_SOCKET:
13310 + closesocket(sock->fd);
13312 + case IOSOCKET_TYPE_PIPE:
13322 --- ../lighttpd-1.4.11/src/iosocket.h 1970-01-01 03:00:00.000000000 +0300
13323 +++ lighttpd-1.4.12/src/iosocket.h 2006-07-18 13:03:40.000000000 +0300
13325 +#ifndef _IOSOCKET_H_
13326 +#define _IOSOCKET_H_
13328 +#if defined HAVE_LIBSSL && defined HAVE_OPENSSL_SSL_H
13329 +# define USE_OPENSSL
13330 +# include <openssl/ssl.h>
13334 + IOSOCKET_TYPE_UNSET,
13335 + IOSOCKET_TYPE_SOCKET,
13336 + IOSOCKET_TYPE_PIPE
13340 + * a non-blocking fd
13346 +#ifdef USE_OPENSSL
13350 + iosocket_t type; /**< sendfile on solaris doesn't work on pipes */
13353 +iosocket *iosocket_init(void);
13354 +void iosocket_free(iosocket *sock);
13357 --- ../lighttpd-1.4.11/src/joblist.c 2005-08-11 01:26:41.000000000 +0300
13358 +++ lighttpd-1.4.12/src/joblist.c 2006-07-16 00:26:03.000000000 +0300
13361 int joblist_append(server *srv, connection *con) {
13362 if (con->in_joblist) return 0;
13365 if (srv->joblist->size == 0) {
13366 srv->joblist->size = 16;
13367 srv->joblist->ptr = malloc(sizeof(*srv->joblist->ptr) * srv->joblist->size);
13368 @@ -15,15 +15,15 @@
13369 srv->joblist->size += 16;
13370 srv->joblist->ptr = realloc(srv->joblist->ptr, sizeof(*srv->joblist->ptr) * srv->joblist->size);
13374 srv->joblist->ptr[srv->joblist->used++] = con;
13380 void joblist_free(server *srv, connections *joblist) {
13384 free(joblist->ptr);
13387 @@ -31,14 +31,14 @@
13388 connection *fdwaitqueue_unshift(server *srv, connections *fdwaitqueue) {
13395 if (fdwaitqueue->used == 0) return NULL;
13398 con = fdwaitqueue->ptr[0];
13401 memmove(fdwaitqueue->ptr, &(fdwaitqueue->ptr[1]), --fdwaitqueue->used * sizeof(*(fdwaitqueue->ptr)));
13408 srv->fdwaitqueue->size += 16;
13409 srv->fdwaitqueue->ptr = realloc(srv->fdwaitqueue->ptr, sizeof(*(srv->fdwaitqueue->ptr)) * srv->fdwaitqueue->size);
13413 srv->fdwaitqueue->ptr[srv->fdwaitqueue->used++] = con;
13419 --- ../lighttpd-1.4.11/src/keyvalue.c 2006-03-02 16:08:06.000000000 +0200
13420 +++ lighttpd-1.4.12/src/keyvalue.c 2006-07-16 00:26:03.000000000 +0300
13422 { 504, "Gateway Timeout" },
13423 { 505, "HTTP Version Not Supported" },
13424 { 507, "Insufficient Storage" }, /* WebDAV */
13426 + { 509, "Bandwidth Limit exceeded" },
13431 @@ -102,12 +103,12 @@
13432 { 501, "501.html" },
13433 { 503, "503.html" },
13434 { 505, "505.html" },
13441 -const char *keyvalue_get_value(keyvalue *kv, int k) {
13442 +const char *keyvalue_get_value(keyvalue *kv, int k) {
13444 for (i = 0; kv[i].value; i++) {
13445 if (kv[i].key == k) return kv[i].value;
13446 @@ -115,7 +116,7 @@
13450 -int keyvalue_get_key(keyvalue *kv, const char *s) {
13451 +int keyvalue_get_key(keyvalue *kv, const char *s) {
13453 for (i = 0; kv[i].value; i++) {
13454 if (0 == strcmp(kv[i].value, s)) return kv[i].key;
13455 @@ -125,9 +126,9 @@
13457 keyvalue_buffer *keyvalue_buffer_init(void) {
13458 keyvalue_buffer *kvb;
13461 kvb = calloc(1, sizeof(*kvb));
13467 @@ -135,49 +136,49 @@
13469 if (kvb->size == 0) {
13473 kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
13476 for(i = 0; i < kvb->size; i++) {
13477 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
13479 } else if (kvb->used == kvb->size) {
13483 kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
13486 for(i = kvb->used; i < kvb->size; i++) {
13487 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
13492 kvb->kv[kvb->used]->key = key;
13493 kvb->kv[kvb->used]->value = strdup(value);
13502 void keyvalue_buffer_free(keyvalue_buffer *kvb) {
13506 for (i = 0; i < kvb->size; i++) {
13507 if (kvb->kv[i]->value) free(kvb->kv[i]->value);
13512 if (kvb->kv) free(kvb->kv);
13519 s_keyvalue_buffer *s_keyvalue_buffer_init(void) {
13520 s_keyvalue_buffer *kvb;
13523 kvb = calloc(1, sizeof(*kvb));
13529 @@ -186,50 +187,50 @@
13530 if (kvb->size == 0) {
13535 kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
13538 for(i = 0; i < kvb->size; i++) {
13539 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
13541 } else if (kvb->used == kvb->size) {
13545 kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
13548 for(i = kvb->used; i < kvb->size; i++) {
13549 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
13554 kvb->kv[kvb->used]->key = key ? strdup(key) : NULL;
13555 kvb->kv[kvb->used]->value = strdup(value);
13564 void s_keyvalue_buffer_free(s_keyvalue_buffer *kvb) {
13568 for (i = 0; i < kvb->size; i++) {
13569 if (kvb->kv[i]->key) free(kvb->kv[i]->key);
13570 if (kvb->kv[i]->value) free(kvb->kv[i]->value);
13575 if (kvb->kv) free(kvb->kv);
13582 httpauth_keyvalue_buffer *httpauth_keyvalue_buffer_init(void) {
13583 httpauth_keyvalue_buffer *kvb;
13586 kvb = calloc(1, sizeof(*kvb));
13592 @@ -237,42 +238,42 @@
13594 if (kvb->size == 0) {
13598 kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
13601 for(i = 0; i < kvb->size; i++) {
13602 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
13604 } else if (kvb->used == kvb->size) {
13608 kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
13611 for(i = kvb->used; i < kvb->size; i++) {
13612 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
13617 kvb->kv[kvb->used]->key = strdup(key);
13618 kvb->kv[kvb->used]->realm = strdup(realm);
13619 kvb->kv[kvb->used]->type = type;
13628 void httpauth_keyvalue_buffer_free(httpauth_keyvalue_buffer *kvb) {
13632 for (i = 0; i < kvb->size; i++) {
13633 if (kvb->kv[i]->key) free(kvb->kv[i]->key);
13634 if (kvb->kv[i]->realm) free(kvb->kv[i]->realm);
13639 if (kvb->kv) free(kvb->kv);
13645 @@ -306,9 +307,9 @@
13647 pcre_keyvalue_buffer *pcre_keyvalue_buffer_init(void) {
13648 pcre_keyvalue_buffer *kvb;
13651 kvb = calloc(1, sizeof(*kvb));
13657 @@ -319,46 +320,46 @@
13663 if (!key) return -1;
13666 if (kvb->size == 0) {
13671 kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
13674 for(i = 0; i < kvb->size; i++) {
13675 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
13677 } else if (kvb->used == kvb->size) {
13681 kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
13684 for(i = kvb->used; i < kvb->size; i++) {
13685 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
13690 kv = kvb->kv[kvb->used];
13691 if (NULL == (kv->key = pcre_compile(key,
13692 0, &errptr, &erroff, NULL))) {
13695 fprintf(stderr, "%s.%d: rexexp compilation error at %s\n", __FILE__, __LINE__, errptr);
13699 - if (NULL == (kv->key_extra = pcre_study(kv->key, 0, &errptr)) &&
13700 + if (NULL == (kv->key_extra = pcre_study(kv->key, 0, &errptr)) &&
13706 kv->value = buffer_init_string(value);
13715 @@ -380,9 +381,9 @@
13716 if (kv->value) buffer_free(kv->value);
13721 if (kvb->kv) free(kvb->kv);
13727 --- ../lighttpd-1.4.11/src/keyvalue.h 2006-03-02 16:08:06.000000000 +0200
13728 +++ lighttpd-1.4.12/src/keyvalue.h 2006-07-16 00:26:04.000000000 +0300
13734 - HTTP_METHOD_UNSET = -1,
13736 - HTTP_METHOD_POST,
13737 - HTTP_METHOD_HEAD,
13738 - HTTP_METHOD_OPTIONS,
13740 + HTTP_METHOD_UNSET = -1,
13742 + HTTP_METHOD_POST,
13743 + HTTP_METHOD_HEAD,
13744 + HTTP_METHOD_OPTIONS,
13745 HTTP_METHOD_PROPFIND, /* WebDAV */
13746 - HTTP_METHOD_MKCOL,
13748 - HTTP_METHOD_DELETE,
13749 - HTTP_METHOD_COPY,
13750 - HTTP_METHOD_MOVE,
13751 - HTTP_METHOD_PROPPATCH,
13752 + HTTP_METHOD_MKCOL,
13754 + HTTP_METHOD_DELETE,
13755 + HTTP_METHOD_COPY,
13756 + HTTP_METHOD_MOVE,
13757 + HTTP_METHOD_PROPPATCH,
13758 HTTP_METHOD_REPORT, /* DeltaV */
13759 HTTP_METHOD_CHECKOUT,
13760 HTTP_METHOD_CHECKIN,
13761 @@ -39,13 +39,13 @@
13779 pcre_extra *key_extra;
13793 httpauth_type type;
13794 } httpauth_keyvalue;
13795 --- ../lighttpd-1.4.11/src/lemon.c 2005-09-01 00:21:34.000000000 +0300
13796 +++ lighttpd-1.4.12/src/lemon.c 2006-07-16 00:26:03.000000000 +0300
13797 @@ -579,7 +579,7 @@
13800 /* Find a precedence symbol of every rule in the grammar.
13803 ** Those rules which have a precedence symbol coded in the input
13804 ** grammar using the "[symbol]" construct will already have the
13805 ** rp->precsym field filled. Other rules take as their precedence
13806 @@ -869,7 +869,7 @@
13807 cfp->status = INCOMPLETE;
13814 for(i=0; i<lemp->nstate; i++){
13815 @@ -900,7 +900,7 @@
13819 - /* Add all of the reduce actions
13820 + /* Add all of the reduce actions
13821 ** A reduce action is added for each element of the followset of
13822 ** a configuration which has its dot at the extreme right.
13824 @@ -1017,7 +1017,7 @@
13825 apx->type = RD_RESOLVED;
13830 apx->type==SH_RESOLVED ||
13831 apx->type==RD_RESOLVED ||
13832 apx->type==CONFLICT ||
13833 @@ -1350,7 +1350,7 @@
13834 OptInit(argv,options,stderr);
13836 printf("Lemon version 1.0\n");
13840 if( OptNArgs() < 1 ){
13841 fprintf(stderr,"Exactly one filename argument is required.\n");
13842 @@ -2031,7 +2031,7 @@
13846 - rp = (struct rule *)malloc( sizeof(struct rule) +
13847 + rp = (struct rule *)malloc( sizeof(struct rule) +
13848 sizeof(struct symbol*)*psp->nrhs + sizeof(char*)*psp->nrhs );
13850 ErrorMsg(psp->filename,psp->tokenlineno,
13851 @@ -2546,7 +2546,7 @@
13855 -/* Duplicate the input file without comments and without actions
13856 +/* Duplicate the input file without comments and without actions
13859 struct lemon *lemp;
13860 @@ -2822,7 +2822,7 @@
13861 PRIVATE FILE *tplt_open(lemp)
13862 struct lemon *lemp;
13869 @@ -2930,7 +2930,7 @@
13875 ** Generate code which executes when the rule "rp" is reduced. Write
13876 ** the code to "out". Make sure lineno stays up-to-date.
13878 @@ -3384,7 +3384,7 @@
13880 /* Output the yy_shift_ofst[] table */
13881 fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", mnTknOfst-1); lineno++;
13882 - fprintf(out, "static %s yy_shift_ofst[] = {\n",
13883 + fprintf(out, "static %s yy_shift_ofst[] = {\n",
13884 minimum_size_type(mnTknOfst-1, mxTknOfst)); lineno++;
13886 for(i=j=0; i<n; i++){
13887 @@ -3405,7 +3405,7 @@
13889 /* Output the yy_reduce_ofst[] table */
13890 fprintf(out, "#define YY_REDUCE_USE_DFLT (%d)\n", mnNtOfst-1); lineno++;
13891 - fprintf(out, "static %s yy_reduce_ofst[] = {\n",
13892 + fprintf(out, "static %s yy_reduce_ofst[] = {\n",
13893 minimum_size_type(mnNtOfst-1, mxNtOfst)); lineno++;
13895 for(i=j=0; i<n; i++){
13896 @@ -3480,7 +3480,7 @@
13897 tplt_xfer(lemp->name,in,out,&lineno);
13899 /* Generate code which executes every time a symbol is popped from
13900 - ** the stack while processing errors or while destroying the parser.
13901 + ** the stack while processing errors or while destroying the parser.
13902 ** (In other words, generate the %destructor actions)
13904 if( lemp->tokendest ){
13905 @@ -3522,7 +3522,7 @@
13906 tplt_print(out,lemp,lemp->overflow,lemp->overflowln,&lineno);
13907 tplt_xfer(lemp->name,in,out,&lineno);
13909 - /* Generate the table of rule information
13910 + /* Generate the table of rule information
13912 ** Note: This code depends on the fact that rules are number
13913 ** sequentually beginning with 0.
13914 @@ -3589,7 +3589,7 @@
13915 for(i=1; i<lemp->nterminal; i++){
13916 fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
13923 @@ -3630,7 +3630,7 @@
13929 /* Do not make a default if the number of rules to default
13930 ** is not at least 2 */
13931 if( nbest<2 ) continue;
13932 @@ -3781,7 +3781,7 @@
13936 - x1a->tbl = (x1node*)malloc(
13937 + x1a->tbl = (x1node*)malloc(
13938 (sizeof(x1node) + sizeof(x1node*))*1024 );
13941 @@ -3943,7 +3943,7 @@
13945 - x2a->tbl = (x2node*)malloc(
13946 + x2a->tbl = (x2node*)malloc(
13947 (sizeof(x2node) + sizeof(x2node*))*128 );
13950 @@ -4149,7 +4149,7 @@
13954 - x3a->tbl = (x3node*)malloc(
13955 + x3a->tbl = (x3node*)malloc(
13956 (sizeof(x3node) + sizeof(x3node*))*128 );
13959 @@ -4295,7 +4295,7 @@
13963 - x4a->tbl = (x4node*)malloc(
13964 + x4a->tbl = (x4node*)malloc(
13965 (sizeof(x4node) + sizeof(x4node*))*64 );
13968 --- ../lighttpd-1.4.11/src/lempar.c 2005-08-11 01:26:40.000000000 +0300
13969 +++ lighttpd-1.4.12/src/lempar.c 2006-07-16 00:26:03.000000000 +0300
13971 /* Next is all token values, in a form suitable for use by makeheaders.
13972 ** This section will be null unless lemon is run with the -m switch.
13976 ** These constants (all generated automatically by the parser generator)
13977 ** specify the various kinds of tokens (terminals) that the parser
13981 ** Each symbol here is a terminal symbol in the grammar.
13984 ** and nonterminals. "int" is used otherwise.
13985 ** YYNOCODE is a number of type YYCODETYPE which corresponds
13986 ** to no legal terminal or nonterminal number. This
13987 -** number is used to fill in empty slots of the hash
13988 +** number is used to fill in empty slots of the hash
13990 ** YYFALLBACK If defined, this indicates that one or more tokens
13991 ** have fall-back values which should be used if the
13993 ** and nonterminal numbers. "unsigned char" is
13994 ** used if there are fewer than 250 rules and
13995 ** states combined. "int" is used otherwise.
13996 -** ParseTOKENTYPE is the data type used for minor tokens given
13997 +** ParseTOKENTYPE is the data type used for minor tokens given
13998 ** directly to the parser from the tokenizer.
13999 ** YYMINORTYPE is the data type used for all minor tokens.
14000 ** This is typically a union of many types, one of
14002 /* Next are that tables used to determine what action to take based on the
14003 ** current state and lookahead token. These tables are used to implement
14004 ** functions that take a state number and lookahead value and return an
14005 -** action integer.
14006 +** action integer.
14008 ** Suppose the action integer is N. Then the action is determined as
14011 ** If the index value yy_shift_ofst[S]+X is out of range or if the value
14012 ** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
14013 ** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
14014 -** and that yy_default[S] should be used instead.
14015 +** and that yy_default[S] should be used instead.
14017 ** The formula above is for computing the action when the lookahead is
14018 ** a terminal symbol. If the lookahead is a non-terminal (as occurs after
14019 @@ -111,7 +111,7 @@
14021 /* The next table maps tokens into fallback tokens. If a construct
14022 ** like the following:
14025 ** %fallback ID X Y Z.
14027 ** appears in the grammer, then ID becomes a fallback token for X, Y,
14028 @@ -163,10 +163,10 @@
14029 #endif /* NDEBUG */
14034 ** Turn parser tracing on by giving a stream to which to write the trace
14035 ** and a prompt to preface each trace message. Tracing is turned off
14036 -** by making either argument NULL
14037 +** by making either argument NULL
14041 @@ -191,7 +191,7 @@
14043 /* For tracing shifts, the names of all terminals and nonterminals
14044 ** are required. The following table supplies these names */
14045 -static const char *yyTokenName[] = {
14046 +static const char *yyTokenName[] = {
14049 #endif /* NDEBUG */
14050 @@ -220,7 +220,7 @@
14056 ** This function allocates a new parser.
14057 ** The only argument is a pointer to a function which works like
14059 @@ -251,7 +251,7 @@
14060 /* Here is inserted the actions which take place when a
14061 ** terminal or non-terminal is destroyed. This can happen
14062 ** when the symbol is popped from the stack during a
14063 - ** reduce or during error processing or when a parser is
14064 + ** reduce or during error processing or when a parser is
14065 ** being destroyed before it is finished parsing.
14067 ** Note: during a reduce, the only symbols destroyed are those
14068 @@ -289,7 +289,7 @@
14074 ** Deallocate and destroy a parser. Destructors are all called for
14075 ** all stack elements before shutting the parser down.
14077 @@ -325,7 +325,7 @@
14080 int stateno = pParser->yystack[pParser->yyidx].stateno;
14083 /* if( pParser->yyidx<0 ) return YY_NO_ACTION; */
14084 i = yy_shift_ofst[stateno];
14085 if( i==YY_SHIFT_USE_DFLT ){
14086 @@ -369,7 +369,7 @@
14089 int stateno = pParser->yystack[pParser->yyidx].stateno;
14092 i = yy_reduce_ofst[stateno];
14093 if( i==YY_REDUCE_USE_DFLT ){
14094 return yy_default[stateno];
14095 @@ -455,7 +455,7 @@
14097 yymsp = &yypParser->yystack[yypParser->yyidx];
14099 - if( yyTraceFILE && yyruleno>=0
14100 + if( yyTraceFILE && yyruleno>=0
14101 && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){
14102 fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
14103 yyRuleName[yyruleno]);
14104 @@ -608,7 +608,7 @@
14105 #ifdef YYERRORSYMBOL
14106 /* A syntax error has occurred.
14107 ** The response to an error depends upon whether or not the
14108 - ** grammar defines an error token "ERROR".
14109 + ** grammar defines an error token "ERROR".
14111 ** This is what we do if the grammar does define ERROR:
14113 --- ../lighttpd-1.4.11/src/log.c 2005-11-07 15:01:35.000000000 +0200
14114 +++ lighttpd-1.4.12/src/log.c 2006-07-18 13:03:40.000000000 +0300
14119 -#include <unistd.h>
14120 #include <string.h>
14121 #include <stdlib.h>
14124 #include "config.h"
14128 +#undef HAVE_SYSLOG_H
14131 #ifdef HAVE_SYSLOG_H
14132 #include <syslog.h>
14138 +#include "sys-files.h"
14140 #ifdef HAVE_VALGRIND_VALGRIND_H
14141 #include <valgrind/valgrind.h>
14143 @@ -31,55 +36,114 @@
14144 # define O_LARGEFILE 0
14149 * open the errorlog
14152 * we have 3 possibilities:
14153 * - stderr (default)
14159 * if the open failed, report to the user and die
14164 -int log_error_open(server *srv) {
14168 + unsigned short use_syslog;
14170 + /* the errorlog */
14172 - int close_stderr = 1;
14173 + enum { ERRORLOG_STDERR, ERRORLOG_FILE, ERRORLOG_SYSLOG } mode;
14176 + time_t cached_ts;
14177 + buffer *cached_ts_str;
14180 +errorlog *myconfig = NULL;
14182 +void log_init(void) {
14186 + err = calloc(1, sizeof(*err));
14189 + err->mode = ERRORLOG_STDERR;
14190 + err->buf = buffer_init();
14191 + err->cached_ts_str = buffer_init();
14196 +void log_free(void) {
14197 + errorlog *err = myconfig;
14199 + if (!err) return;
14201 + TRACE("%s", "server stopped");
14203 + switch(err->mode) {
14204 + case ERRORLOG_FILE:
14207 + case ERRORLOG_SYSLOG:
14208 +#ifdef HAVE_SYSLOG_H
14212 + case ERRORLOG_STDERR:
14216 + buffer_free(err->buf);
14217 + buffer_free(err->cached_ts_str);
14218 + if (err->file) buffer_free(err->file);
14225 +int log_error_open(buffer *file, int use_syslog) {
14227 + int close_stderr = 1;
14229 + errorlog *err = myconfig;
14231 #ifdef HAVE_SYSLOG_H
14232 /* perhaps someone wants to use syslog() */
14233 openlog("lighttpd", LOG_CONS | LOG_PID, LOG_DAEMON);
14235 - srv->errorlog_mode = ERRORLOG_STDERR;
14237 - if (srv->srvconf.errorlog_use_syslog) {
14238 - srv->errorlog_mode = ERRORLOG_SYSLOG;
14239 - } else if (!buffer_is_empty(srv->srvconf.errorlog_file)) {
14240 - const char *logfile = srv->srvconf.errorlog_file->ptr;
14242 - if (-1 == (srv->errorlog_fd = open(logfile, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
14243 - log_error_write(srv, __FILE__, __LINE__, "SSSS",
14244 - "opening errorlog '", logfile,
14245 + err->mode = ERRORLOG_STDERR;
14247 + if (use_syslog) {
14248 + err->mode = ERRORLOG_SYSLOG;
14249 + } else if (!buffer_is_empty(file)) {
14250 + if (-1 == (err->fd = open(file->ptr, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
14251 + log_error_write(NULL, __FILE__, __LINE__, "SBSS",
14252 + "opening errorlog '", file,
14253 "' failed: ", strerror(errno));
14259 /* close fd on exec (cgi) */
14260 - fcntl(srv->errorlog_fd, F_SETFD, FD_CLOEXEC);
14261 + fcntl(err->fd, F_SETFD, FD_CLOEXEC);
14263 - srv->errorlog_mode = ERRORLOG_FILE;
14264 + err->mode = ERRORLOG_FILE;
14267 - log_error_write(srv, __FILE__, __LINE__, "s", "server started");
14270 + TRACE("%s", "server started");
14272 #ifdef HAVE_VALGRIND_VALGRIND_H
14273 /* don't close stderr for debugging purposes if run in valgrind */
14274 if (RUNNING_ON_VALGRIND) close_stderr = 0;
14276 - if (srv->errorlog_mode == ERRORLOG_STDERR) close_stderr = 0;
14278 + if (err->mode == ERRORLOG_STDERR) close_stderr = 0;
14280 /* move stderr to /dev/null */
14281 if (close_stderr &&
14282 -1 != (fd = open("/dev/null", O_WRONLY))) {
14283 @@ -90,167 +154,202 @@
14289 * open the errorlog
14292 * if the open failed, report to the user and die
14293 * if no filename is given, use syslog instead
14298 -int log_error_cycle(server *srv) {
14299 +int log_error_cycle(void) {
14300 /* only cycle if we are not in syslog-mode */
14302 - if (srv->errorlog_mode == ERRORLOG_FILE) {
14303 - const char *logfile = srv->srvconf.errorlog_file->ptr;
14305 + errorlog *err = myconfig;
14307 + if (err->mode == ERRORLOG_FILE) {
14308 + buffer *file = err->file;
14309 /* already check of opening time */
14314 - if (-1 == (new_fd = open(logfile, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
14316 + if (-1 == (new_fd = open(file->ptr, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
14317 /* write to old log */
14318 - log_error_write(srv, __FILE__, __LINE__, "SSSSS",
14319 - "cycling errorlog '", logfile,
14320 + log_error_write(NULL, __FILE__, __LINE__, "SBSSS",
14321 + "cycling errorlog '", file,
14322 "' failed: ", strerror(errno),
14323 ", falling back to syslog()");
14325 - close(srv->errorlog_fd);
14326 - srv->errorlog_fd = -1;
14327 -#ifdef HAVE_SYSLOG_H
14328 - srv->errorlog_mode = ERRORLOG_SYSLOG;
14332 +#ifdef HAVE_SYSLOG_H
14333 + err->mode = ERRORLOG_SYSLOG;
14336 /* ok, new log is open, close the old one */
14337 - close(srv->errorlog_fd);
14338 - srv->errorlog_fd = new_fd;
14340 + err->fd = new_fd;
14344 - log_error_write(srv, __FILE__, __LINE__, "s", "logfiles cycled");
14349 -int log_error_close(server *srv) {
14350 - log_error_write(srv, __FILE__, __LINE__, "s", "server stopped");
14352 - switch(srv->errorlog_mode) {
14353 - case ERRORLOG_FILE:
14354 - close(srv->errorlog_fd);
14356 - case ERRORLOG_SYSLOG:
14357 -#ifdef HAVE_SYSLOG_H
14361 - case ERRORLOG_STDERR:
14365 + TRACE("%s", "logfiles cycled");
14370 -int log_error_write(server *srv, const char *filename, unsigned int line, const char *fmt, ...) {
14371 +int log_error_write(void *srv, const char *filename, unsigned int line, const char *fmt, ...) {
14374 - switch(srv->errorlog_mode) {
14377 + errorlog *err = myconfig;
14379 + switch(err->mode) {
14380 case ERRORLOG_FILE:
14381 case ERRORLOG_STDERR:
14382 /* cache the generated timestamp */
14383 - if (srv->cur_ts != srv->last_generated_debug_ts) {
14384 - buffer_prepare_copy(srv->ts_debug_str, 255);
14385 - strftime(srv->ts_debug_str->ptr, srv->ts_debug_str->size - 1, "%Y-%m-%d %H:%M:%S", localtime(&(srv->cur_ts)));
14386 - srv->ts_debug_str->used = strlen(srv->ts_debug_str->ptr) + 1;
14388 - srv->last_generated_debug_ts = srv->cur_ts;
14391 + if (t != err->cached_ts) {
14392 + buffer_prepare_copy(err->cached_ts_str, 255);
14393 + strftime(err->cached_ts_str->ptr, err->cached_ts_str->size - 1, "%Y-%m-%d %H:%M:%S", localtime(&(t)));
14394 + err->cached_ts_str->used = strlen(err->cached_ts_str->ptr) + 1;
14395 + err->cached_ts = t;
14398 - buffer_copy_string_buffer(srv->errorlog_buf, srv->ts_debug_str);
14399 - BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, ": (");
14400 + buffer_copy_string_buffer(err->buf, err->cached_ts_str);
14401 + BUFFER_APPEND_STRING_CONST(err->buf, ": (");
14403 case ERRORLOG_SYSLOG:
14404 /* syslog is generating its own timestamps */
14405 - BUFFER_COPY_STRING_CONST(srv->errorlog_buf, "(");
14406 + BUFFER_COPY_STRING_CONST(err->buf, "(");
14410 - buffer_append_string(srv->errorlog_buf, filename);
14411 - BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, ".");
14412 - buffer_append_long(srv->errorlog_buf, line);
14413 - BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, ") ");
14417 + buffer_append_string(err->buf, filename);
14418 + BUFFER_APPEND_STRING_CONST(err->buf, ".");
14419 + buffer_append_long(err->buf, line);
14420 + BUFFER_APPEND_STRING_CONST(err->buf, ") ");
14422 for(va_start(ap, fmt); *fmt; fmt++) {
14430 case 's': /* string */
14431 s = va_arg(ap, char *);
14432 - buffer_append_string(srv->errorlog_buf, s);
14433 - BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, " ");
14434 + buffer_append_string(err->buf, s);
14435 + BUFFER_APPEND_STRING_CONST(err->buf, " ");
14437 case 'b': /* buffer */
14438 b = va_arg(ap, buffer *);
14439 - buffer_append_string_buffer(srv->errorlog_buf, b);
14440 - BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, " ");
14441 + buffer_append_string_buffer(err->buf, b);
14442 + BUFFER_APPEND_STRING_CONST(err->buf, " ");
14444 case 'd': /* int */
14445 d = va_arg(ap, int);
14446 - buffer_append_long(srv->errorlog_buf, d);
14447 - BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, " ");
14448 + buffer_append_long(err->buf, d);
14449 + BUFFER_APPEND_STRING_CONST(err->buf, " ");
14451 case 'o': /* off_t */
14452 o = va_arg(ap, off_t);
14453 - buffer_append_off_t(srv->errorlog_buf, o);
14454 - BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, " ");
14455 + buffer_append_off_t(err->buf, o);
14456 + BUFFER_APPEND_STRING_CONST(err->buf, " ");
14458 case 'x': /* int (hex) */
14459 d = va_arg(ap, int);
14460 - BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, "0x");
14461 - buffer_append_long_hex(srv->errorlog_buf, d);
14462 - BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, " ");
14463 + BUFFER_APPEND_STRING_CONST(err->buf, "0x");
14464 + buffer_append_long_hex(err->buf, d);
14465 + BUFFER_APPEND_STRING_CONST(err->buf, " ");
14467 case 'S': /* string */
14468 s = va_arg(ap, char *);
14469 - buffer_append_string(srv->errorlog_buf, s);
14470 + buffer_append_string(err->buf, s);
14472 case 'B': /* buffer */
14473 b = va_arg(ap, buffer *);
14474 - buffer_append_string_buffer(srv->errorlog_buf, b);
14475 + buffer_append_string_buffer(err->buf, b);
14477 case 'D': /* int */
14478 d = va_arg(ap, int);
14479 - buffer_append_long(srv->errorlog_buf, d);
14480 + buffer_append_long(err->buf, d);
14489 - buffer_append_string_len(srv->errorlog_buf, fmt, 1);
14490 + buffer_append_string_len(err->buf, fmt, 1);
14496 - switch(srv->errorlog_mode) {
14498 + switch(err->mode) {
14499 case ERRORLOG_FILE:
14500 - BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, "\n");
14501 - write(srv->errorlog_fd, srv->errorlog_buf->ptr, srv->errorlog_buf->used - 1);
14502 + BUFFER_APPEND_STRING_CONST(err->buf, "\n");
14503 + write(err->fd, err->buf->ptr, err->buf->used - 1);
14505 case ERRORLOG_STDERR:
14506 - BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, "\n");
14507 - write(STDERR_FILENO, srv->errorlog_buf->ptr, srv->errorlog_buf->used - 1);
14508 + BUFFER_APPEND_STRING_CONST(err->buf, "\n");
14509 + write(STDERR_FILENO, err->buf->ptr, err->buf->used - 1);
14511 +#ifdef HAVE_SYSLOG_H
14512 + case ERRORLOG_SYSLOG:
14513 + syslog(LOG_ERR, "%s", err->buf->ptr);
14521 +static int log_trace_write(const char *fmt, va_list ap) {
14524 + errorlog *err = myconfig;
14526 + b = buffer_init();
14527 + buffer_prepare_copy(b, 1024);
14528 + l = vsnprintf(b->ptr, b->size - 1, fmt, ap);
14530 + b->used = (l > b->size - 1) ? b->size : l + 1;
14534 + switch(err->mode) {
14535 + case ERRORLOG_FILE:
14536 + buffer_append_string(b, "\r\n");
14537 + write(err->fd, b->ptr, b->used - 1);
14539 + case ERRORLOG_STDERR:
14540 + buffer_append_string(b, "\r\n");
14541 + write(STDERR_FILENO, b->ptr, b->used - 1);
14543 +#ifdef HAVE_SYSLOG_H
14544 case ERRORLOG_SYSLOG:
14545 - syslog(LOG_ERR, "%s", srv->errorlog_buf->ptr);
14546 + syslog(LOG_ERR, "%s", b->ptr);
14556 +int log_trace(const char *fmt, ...) {
14559 + va_start(ap, fmt);
14561 + log_trace_write(fmt, ap);
14569 --- ../lighttpd-1.4.11/src/log.h 2005-08-11 01:26:36.000000000 +0300
14570 +++ lighttpd-1.4.12/src/log.h 2006-07-18 13:03:40.000000000 +0300
14575 -#include "server.h"
14576 +#include "buffer.h"
14578 -#define WP() log_error_write(srv, __FILE__, __LINE__, "");
14579 +void log_init(void);
14580 +void log_free(void);
14582 -int log_error_open(server *srv);
14583 -int log_error_close(server *srv);
14584 -int log_error_write(server *srv, const char *filename, unsigned int line, const char *fmt, ...);
14585 -int log_error_cycle(server *srv);
14587 +int log_error_open(buffer *file, int use_syslog);
14588 +int log_error_close();
14589 +int log_error_write(void *srv, const char *filename, unsigned int line, const char *fmt, ...);
14590 +int log_error_cycle();
14592 +#define ERROR(fmt, ...) \
14593 + log_trace("%s.%d: (error) "fmt, __FILE__, __LINE__, __VA_ARGS__)
14595 +#define TRACE(fmt, ...) \
14596 + log_trace("%s.%d: (trace) "fmt, __FILE__, __LINE__, __VA_ARGS__)
14598 +#define SEGFAULT() do { ERROR("%s", "Ooh, Ooh, Ooh. Something is not good ... going down"); abort(); } while(0)
14599 +int log_trace(const char *fmt, ...);
14601 --- ../lighttpd-1.4.11/src/md5.h 2005-11-17 16:20:40.000000000 +0200
14602 +++ lighttpd-1.4.12/src/md5.h 2006-07-16 00:26:04.000000000 +0300
14604 # include <inttypes.h>
14608 +#define UINT4 unsigned __int32
14609 +#define UINT2 unsigned __int16
14610 +#define POINTER unsigned char *
14612 #define UINT4 uint32_t
14613 #define UINT2 uint16_t
14614 #define POINTER unsigned char *
14619 --- ../lighttpd-1.4.11/src/mod_access.c 2006-01-14 19:44:54.000000000 +0200
14620 +++ lighttpd-1.4.12/src/mod_access.c 2006-07-16 00:26:04.000000000 +0300
14621 @@ -8,126 +8,125 @@
14623 #include "plugin.h"
14625 +#include "sys-strings.h"
14628 array *access_deny;
14635 plugin_config **config_storage;
14637 - plugin_config conf;
14639 + plugin_config conf;
14642 INIT_FUNC(mod_access_init) {
14646 p = calloc(1, sizeof(*p));
14652 FREE_FUNC(mod_access_free) {
14653 plugin_data *p = p_d;
14658 if (!p) return HANDLER_GO_ON;
14661 if (p->config_storage) {
14663 for (i = 0; i < srv->config_context->used; i++) {
14664 plugin_config *s = p->config_storage[i];
14667 array_free(s->access_deny);
14672 free(p->config_storage);
14679 return HANDLER_GO_ON;
14682 SETDEFAULTS_FUNC(mod_access_set_defaults) {
14683 plugin_data *p = p_d;
14686 - config_values_t cv[] = {
14688 + config_values_t cv[] = {
14689 { "url.access-deny", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },
14690 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
14694 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
14697 for (i = 0; i < srv->config_context->used; i++) {
14701 s = calloc(1, sizeof(plugin_config));
14702 s->access_deny = array_init();
14705 cv[0].destination = s->access_deny;
14708 p->config_storage[i] = s;
14711 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
14712 return HANDLER_ERROR;
14717 return HANDLER_GO_ON;
14720 -#define PATCH(x) \
14721 - p->conf.x = s->x;
14722 static int mod_access_patch_connection(server *srv, connection *con, plugin_data *p) {
14724 plugin_config *s = p->config_storage[0];
14726 - PATCH(access_deny);
14728 + PATCH_OPTION(access_deny);
14730 /* skip the first, the global context */
14731 for (i = 1; i < srv->config_context->used; i++) {
14732 data_config *dc = (data_config *)srv->config_context->data[i];
14733 s = p->config_storage[i];
14736 /* condition didn't match */
14737 if (!config_check_cond(srv, con, dc)) continue;
14741 for (j = 0; j < dc->value->used; j++) {
14742 data_unset *du = dc->value->data[j];
14745 if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.access-deny"))) {
14746 - PATCH(access_deny);
14747 + PATCH_OPTION(access_deny);
14757 URIHANDLER_FUNC(mod_access_uri_handler) {
14758 plugin_data *p = p_d;
14763 if (con->uri.path->used == 0) return HANDLER_GO_ON;
14766 mod_access_patch_connection(srv, con, p);
14769 s_len = con->uri.path->used - 1;
14772 for (k = 0; k < p->conf.access_deny->used; k++) {
14773 data_string *ds = (data_string *)p->conf.access_deny->data[k];
14774 int ct_len = ds->value->used - 1;
14777 if (ct_len > s_len) continue;
14780 if (ds->value->used == 0) continue;
14782 /* if we have a case-insensitive FS we have to lower-case the URI here too */
14783 @@ -135,18 +134,18 @@
14784 if (con->conf.force_lowercase_filenames) {
14785 if (0 == strncasecmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
14786 con->http_status = 403;
14789 return HANDLER_FINISHED;
14792 if (0 == strncmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
14793 con->http_status = 403;
14796 return HANDLER_FINISHED;
14803 return HANDLER_GO_ON;
14805 @@ -155,13 +154,13 @@
14806 int mod_access_plugin_init(plugin *p) {
14807 p->version = LIGHTTPD_VERSION_ID;
14808 p->name = buffer_init_string("access");
14811 p->init = mod_access_init;
14812 p->set_defaults = mod_access_set_defaults;
14813 p->handle_uri_clean = mod_access_uri_handler;
14814 p->cleanup = mod_access_free;
14822 --- ../lighttpd-1.4.11/src/mod_accesslog.c 2006-01-31 14:01:43.000000000 +0200
14823 +++ lighttpd-1.4.12/src/mod_accesslog.c 2006-07-16 00:26:04.000000000 +0300
14826 #include <stdlib.h>
14827 #include <string.h>
14828 -#include <fcntl.h>
14829 -#include <unistd.h>
14830 +#include <fcntl.h> /* only the defines on windows */
14835 #include "inet_ntop_cache.h"
14837 #include "sys-socket.h"
14838 +#include "sys-files.h"
14840 #ifdef HAVE_SYSLOG_H
14841 # include <syslog.h>
14849 FORMAT_UNSUPPORTED,
14853 FORMAT_BYTES_OUT_NO_HEADER,
14857 FORMAT_REMOTE_ADDR,
14860 @@ -59,20 +59,20 @@
14861 FORMAT_CONNECTION_STATUS,
14866 FORMAT_RESPONSE_HEADER
14875 * "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\""
14880 -const format_mapping fmap[] =
14882 +const format_mapping fmap[] =
14884 { '%', FORMAT_PERCENT },
14885 { 'h', FORMAT_REMOTE_HOST },
14886 { 'l', FORMAT_REMOTE_IDENT },
14888 { 's', FORMAT_STATUS },
14889 { 'b', FORMAT_BYTES_OUT_NO_HEADER },
14890 { 'i', FORMAT_HEADER },
14893 { 'a', FORMAT_REMOTE_ADDR },
14894 { 'A', FORMAT_LOCAL_ADDR },
14895 { 'B', FORMAT_BYTES_OUT_NO_HEADER },
14896 @@ -103,23 +103,23 @@
14897 { 'X', FORMAT_CONNECTION_STATUS },
14898 { 'I', FORMAT_BYTES_IN },
14899 { 'O', FORMAT_BYTES_OUT },
14902 { 'o', FORMAT_RESPONSE_HEADER },
14905 { '\0', FORMAT_UNSET }
14910 enum { FIELD_UNSET, FIELD_STRING, FIELD_FORMAT } type;
14918 format_field **ptr;
14924 @@ -128,39 +128,39 @@
14925 buffer *access_logfile;
14927 unsigned short use_syslog;
14933 time_t last_generated_accesslog_ts;
14934 time_t *last_generated_accesslog_ts_ptr;
14939 buffer *access_logbuffer;
14940 buffer *ts_accesslog_str;
14943 format_fields *parsed_format;
14950 plugin_config **config_storage;
14951 - plugin_config conf;
14952 + plugin_config conf;
14955 INIT_FUNC(mod_accesslog_init) {
14959 p = calloc(1, sizeof(*p));
14965 int accesslog_parse_format(server *srv, format_fields *fields, buffer *format) {
14966 size_t i, j, k = 0, start = 0;
14969 for (i = 0; i < format->used - 1; i++) {
14972 switch(format->ptr[i]) {
14975 @@ -173,19 +173,19 @@
14976 fields->size += 16;
14977 fields->ptr = realloc(fields->ptr, fields->size * sizeof(format_fields * ));
14981 fields->ptr[fields->used] = malloc(sizeof(format_fields));
14982 fields->ptr[fields->used]->type = FIELD_STRING;
14983 fields->ptr[fields->used]->string = buffer_init();
14986 buffer_copy_string_len(fields->ptr[fields->used]->string, format->ptr + start, i - start);
14995 /* we need a new field */
14998 if (fields->size == 0) {
15001 @@ -194,43 +194,43 @@
15002 fields->size += 16;
15003 fields->ptr = realloc(fields->ptr, fields->size * sizeof(format_fields * ));
15007 /* search for the terminating command */
15008 switch (format->ptr[i+1]) {
15014 for (j = 0; fmap[j].key != '\0'; j++) {
15015 if (fmap[j].key != format->ptr[i+2]) continue;
15021 fields->ptr[fields->used] = malloc(sizeof(format_fields));
15022 fields->ptr[fields->used]->type = FIELD_FORMAT;
15023 fields->ptr[fields->used]->field = fmap[j].type;
15024 fields->ptr[fields->used]->string = NULL;
15034 if (fmap[j].key == '\0') {
15035 log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
15045 /* go forward to } */
15048 for (k = i+2; k < format->used - 1; k++) {
15049 if (format->ptr[k] == '}') break;
15053 if (k == format->used - 1) {
15054 log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
15056 @@ -239,62 +239,62 @@
15057 log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
15062 for (j = 0; fmap[j].key != '\0'; j++) {
15063 if (fmap[j].key != format->ptr[k+1]) continue;
15069 fields->ptr[fields->used] = malloc(sizeof(format_fields));
15070 fields->ptr[fields->used]->type = FIELD_FORMAT;
15071 fields->ptr[fields->used]->field = fmap[j].type;
15072 fields->ptr[fields->used]->string = buffer_init();
15075 buffer_copy_string_len(fields->ptr[fields->used]->string, format->ptr + i + 2, k - (i + 2));
15085 if (fmap[j].key == '\0') {
15086 log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
15096 for (j = 0; fmap[j].key != '\0'; j++) {
15097 if (fmap[j].key != format->ptr[i+1]) continue;
15103 fields->ptr[fields->used] = malloc(sizeof(format_fields));
15104 fields->ptr[fields->used]->type = FIELD_FORMAT;
15105 fields->ptr[fields->used]->field = fmap[j].type;
15106 fields->ptr[fields->used]->string = NULL;
15116 if (fmap[j].key == '\0') {
15117 log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
15135 /* copy the string */
15136 if (fields->size == 0) {
15137 @@ -305,32 +305,32 @@
15138 fields->size += 16;
15139 fields->ptr = realloc(fields->ptr, fields->size * sizeof(format_fields * ));
15143 fields->ptr[fields->used] = malloc(sizeof(format_fields));
15144 fields->ptr[fields->used]->type = FIELD_STRING;
15145 fields->ptr[fields->used]->string = buffer_init();
15148 buffer_copy_string_len(fields->ptr[fields->used]->string, format->ptr + start, i - start);
15158 FREE_FUNC(mod_accesslog_free) {
15159 plugin_data *p = p_d;
15163 if (!p) return HANDLER_GO_ON;
15166 if (p->config_storage) {
15169 for (i = 0; i < srv->config_context->used; i++) {
15170 plugin_config *s = p->config_storage[i];
15175 if (s->access_logbuffer->used) {
15176 if (s->use_syslog) {
15177 # ifdef HAVE_SYSLOG_H
15178 @@ -342,14 +342,14 @@
15179 write(s->log_access_fd, s->access_logbuffer->ptr, s->access_logbuffer->used - 1);
15184 if (s->log_access_fd != -1) close(s->log_access_fd);
15187 buffer_free(s->ts_accesslog_str);
15188 buffer_free(s->access_logbuffer);
15189 buffer_free(s->format);
15190 buffer_free(s->access_logfile);
15193 if (s->parsed_format) {
15195 for (j = 0; j < s->parsed_format->used; j++) {
15196 @@ -359,36 +359,36 @@
15197 free(s->parsed_format->ptr);
15198 free(s->parsed_format);
15206 free(p->config_storage);
15213 return HANDLER_GO_ON;
15216 SETDEFAULTS_FUNC(log_access_open) {
15217 plugin_data *p = p_d;
15220 - config_values_t cv[] = {
15222 + config_values_t cv[] = {
15223 { "accesslog.filename", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
15224 { "accesslog.use-syslog", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },
15225 { "accesslog.format", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
15226 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
15230 if (!p) return HANDLER_ERROR;
15233 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
15236 for (i = 0; i < srv->config_context->used; i++) {
15240 s = calloc(1, sizeof(plugin_config));
15241 s->access_logfile = buffer_init();
15242 s->format = buffer_init();
15243 @@ -397,44 +397,44 @@
15244 s->log_access_fd = -1;
15245 s->last_generated_accesslog_ts = 0;
15246 s->last_generated_accesslog_ts_ptr = &(s->last_generated_accesslog_ts);
15251 cv[0].destination = s->access_logfile;
15252 cv[1].destination = &(s->use_syslog);
15253 cv[2].destination = s->format;
15256 p->config_storage[i] = s;
15259 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
15260 return HANDLER_ERROR;
15264 if (i == 0 && buffer_is_empty(s->format)) {
15265 /* set a default logfile string */
15268 buffer_copy_string(s->format, "%h %V %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"");
15275 if (s->format->used) {
15276 s->parsed_format = calloc(1, sizeof(*(s->parsed_format)));
15279 if (-1 == accesslog_parse_format(srv, s->parsed_format, s->format)) {
15281 - log_error_write(srv, __FILE__, __LINE__, "sb",
15282 + log_error_write(srv, __FILE__, __LINE__, "sb",
15283 "parsing accesslog-definition failed:", s->format);
15285 return HANDLER_ERROR;
15290 for (j = 0; j < s->parsed_format->used; j++) {
15291 switch (s->parsed_format->ptr[j]->type) {
15293 - log_error_write(srv, __FILE__, __LINE__, "ssds",
15294 + log_error_write(srv, __FILE__, __LINE__, "ssds",
15295 "config:", "format", s->parsed_format->ptr[j]->field,
15296 - s->parsed_format->ptr[j]->string ?
15297 + s->parsed_format->ptr[j]->string ?
15298 s->parsed_format->ptr[j]->string->ptr : "" );
15301 @@ -446,52 +446,52 @@
15307 if (s->use_syslog) {
15308 /* ignore the next checks */
15313 if (buffer_is_empty(s->access_logfile)) continue;
15316 if (s->access_logfile->ptr[0] == '|') {
15318 /* create write pipe and spawn process */
15325 if (pipe(to_log_fds)) {
15326 log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed: ", strerror(errno));
15327 return HANDLER_ERROR;
15332 switch (pid = fork()) {
15338 close(STDIN_FILENO);
15339 dup2(to_log_fds[0], STDIN_FILENO);
15340 close(to_log_fds[0]);
15342 close(to_log_fds[1]);
15345 /* we don't need the client socket */
15346 for (i = 3; i < 256; i++) {
15350 - /* exec the log-process (skip the | )
15353 + /* exec the log-process (skip the | )
15358 execl("/bin/sh", "sh", "-c", s->access_logfile->ptr + 1, NULL);
15360 - log_error_write(srv, __FILE__, __LINE__, "sss",
15361 - "spawning log-process failed: ", strerror(errno),
15362 + log_error_write(srv, __FILE__, __LINE__, "sss",
15363 + "spawning log-process failed: ", strerror(errno),
15364 s->access_logfile->ptr + 1);
15370 @@ -500,27 +500,28 @@
15373 close(to_log_fds[0]);
15376 s->log_access_fd = to_log_fds[1];
15384 - } else if (-1 == (s->log_access_fd =
15385 + } else if (-1 == (s->log_access_fd =
15386 open(s->access_logfile->ptr, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
15388 - log_error_write(srv, __FILE__, __LINE__, "ssb",
15389 - "opening access-log failed:",
15391 + log_error_write(srv, __FILE__, __LINE__, "ssb",
15392 + "opening access-log failed:",
15393 strerror(errno), s->access_logfile);
15396 return HANDLER_ERROR;
15399 fcntl(s->log_access_fd, F_SETFD, FD_CLOEXEC);
15405 return HANDLER_GO_ON;
15408 @@ -529,7 +530,7 @@
15411 if (!p->config_storage) return HANDLER_GO_ON;
15414 for (i = 0; i < srv->config_context->used; i++) {
15415 plugin_config *s = p->config_storage[i];
15417 @@ -544,90 +545,87 @@
15418 } else if (s->log_access_fd != -1) {
15419 write(s->log_access_fd, s->access_logbuffer->ptr, s->access_logbuffer->used - 1);
15423 buffer_reset(s->access_logbuffer);
15427 if (s->use_syslog == 0 &&
15428 !buffer_is_empty(s->access_logfile) &&
15429 s->access_logfile->ptr[0] != '|') {
15432 close(s->log_access_fd);
15434 - if (-1 == (s->log_access_fd =
15436 + if (-1 == (s->log_access_fd =
15437 open(s->access_logfile->ptr, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
15440 log_error_write(srv, __FILE__, __LINE__, "ss", "cycling access-log failed:", strerror(errno));
15443 return HANDLER_ERROR;
15449 return HANDLER_GO_ON;
15452 -#define PATCH(x) \
15453 - p->conf.x = s->x;
15454 static int mod_accesslog_patch_connection(server *srv, connection *con, plugin_data *p) {
15456 plugin_config *s = p->config_storage[0];
15458 - PATCH(access_logfile);
15460 - PATCH(log_access_fd);
15461 - PATCH(last_generated_accesslog_ts_ptr);
15462 - PATCH(access_logbuffer);
15463 - PATCH(ts_accesslog_str);
15464 - PATCH(parsed_format);
15465 - PATCH(use_syslog);
15468 + PATCH_OPTION(access_logfile);
15469 + PATCH_OPTION(format);
15470 + PATCH_OPTION(log_access_fd);
15471 + PATCH_OPTION(last_generated_accesslog_ts_ptr);
15472 + PATCH_OPTION(access_logbuffer);
15473 + PATCH_OPTION(ts_accesslog_str);
15474 + PATCH_OPTION(parsed_format);
15475 + PATCH_OPTION(use_syslog);
15477 /* skip the first, the global context */
15478 for (i = 1; i < srv->config_context->used; i++) {
15479 data_config *dc = (data_config *)srv->config_context->data[i];
15480 s = p->config_storage[i];
15483 /* condition didn't match */
15484 if (!config_check_cond(srv, con, dc)) continue;
15488 for (j = 0; j < dc->value->used; j++) {
15489 data_unset *du = dc->value->data[j];
15492 if (buffer_is_equal_string(du->key, CONST_STR_LEN("accesslog.filename"))) {
15493 - PATCH(access_logfile);
15494 - PATCH(log_access_fd);
15495 - PATCH(last_generated_accesslog_ts_ptr);
15496 - PATCH(access_logbuffer);
15497 - PATCH(ts_accesslog_str);
15498 + PATCH_OPTION(access_logfile);
15499 + PATCH_OPTION(log_access_fd);
15500 + PATCH_OPTION(last_generated_accesslog_ts_ptr);
15501 + PATCH_OPTION(access_logbuffer);
15502 + PATCH_OPTION(ts_accesslog_str);
15503 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("accesslog.format"))) {
15505 - PATCH(parsed_format);
15506 + PATCH_OPTION(format);
15507 + PATCH_OPTION(parsed_format);
15508 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("accesslog.use-syslog"))) {
15509 - PATCH(use_syslog);
15510 + PATCH_OPTION(use_syslog);
15520 REQUESTDONE_FUNC(log_access_write) {
15521 plugin_data *p = p_d;
15530 mod_accesslog_patch_connection(srv, con, p);
15533 b = p->conf.access_logbuffer;
15534 if (b->used == 0) {
15535 buffer_copy_string(b, "");
15539 for (j = 0; j < p->conf.parsed_format->used; j++) {
15540 switch(p->conf.parsed_format->ptr[j]->type) {
15542 @@ -636,14 +634,14 @@
15544 switch(p->conf.parsed_format->ptr[j]->field) {
15545 case FORMAT_TIMESTAMP:
15548 /* cache the generated timestamp */
15549 if (srv->cur_ts != *(p->conf.last_generated_accesslog_ts_ptr)) {
15551 #if defined(HAVE_STRUCT_TM_GMTOFF)
15552 long scd, hrs, min;
15556 buffer_prepare_copy(p->conf.ts_accesslog_str, 255);
15557 #if defined(HAVE_STRUCT_TM_GMTOFF)
15558 # ifdef HAVE_LOCALTIME_R
15559 @@ -653,17 +651,17 @@
15560 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)));
15562 p->conf.ts_accesslog_str->used = strlen(p->conf.ts_accesslog_str->ptr) + 1;
15565 buffer_append_string(p->conf.ts_accesslog_str, tm.tm_gmtoff >= 0 ? "+" : "-");
15568 scd = abs(tm.tm_gmtoff);
15570 min = (scd % 3600) / 60;
15574 if (hrs < 10) buffer_append_string(p->conf.ts_accesslog_str, "0");
15575 buffer_append_long(p->conf.ts_accesslog_str, hrs);
15578 if (min < 10) buffer_append_string(p->conf.ts_accesslog_str, "0");
15579 buffer_append_long(p->conf.ts_accesslog_str, min);
15580 BUFFER_APPEND_STRING_CONST(p->conf.ts_accesslog_str, "]");
15581 @@ -676,20 +674,20 @@
15583 p->conf.ts_accesslog_str->used = strlen(p->conf.ts_accesslog_str->ptr) + 1;
15587 *(p->conf.last_generated_accesslog_ts_ptr) = srv->cur_ts;
15592 buffer_append_string_buffer(b, p->conf.ts_accesslog_str);
15596 case FORMAT_REMOTE_HOST:
15599 /* handle inet_ntop cache */
15602 buffer_append_string(b, inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
15606 case FORMAT_REMOTE_IDENT:
15608 @@ -710,10 +708,10 @@
15609 case FORMAT_STATUS:
15610 buffer_append_long(b, con->http_status);
15614 case FORMAT_BYTES_OUT_NO_HEADER:
15615 if (con->bytes_written > 0) {
15616 - buffer_append_off_t(b,
15617 + buffer_append_off_t(b,
15618 con->bytes_written - con->bytes_header <= 0 ? 0 : con->bytes_written - con->bytes_header);
15620 BUFFER_APPEND_STRING_CONST(b, "-");
15621 @@ -772,7 +770,7 @@
15624 case FORMAT_REQUEST_PROTOCOL:
15625 - buffer_append_string(b,
15626 + buffer_append_string(b,
15627 con->request.http_version == HTTP_VERSION_1_1 ? "HTTP/1.1" : "HTTP/1.0");
15629 case FORMAT_REQUEST_METHOD:
15630 @@ -801,7 +799,7 @@
15631 { 'D', FORMAT_TIME_USED_MS },
15632 { 'e', FORMAT_ENV },
15639 @@ -809,7 +807,7 @@
15645 BUFFER_APPEND_STRING_CONST(b, "\n");
15647 if (p->conf.use_syslog || /* syslog doesn't cache */
15648 @@ -828,7 +826,7 @@
15654 return HANDLER_GO_ON;
15657 @@ -836,15 +834,15 @@
15658 int mod_accesslog_plugin_init(plugin *p) {
15659 p->version = LIGHTTPD_VERSION_ID;
15660 p->name = buffer_init_string("accesslog");
15663 p->init = mod_accesslog_init;
15664 p->set_defaults= log_access_open;
15665 p->cleanup = mod_accesslog_free;
15668 p->handle_request_done = log_access_write;
15669 p->handle_sighup = log_access_cycle;
15677 --- ../lighttpd-1.4.11/src/mod_alias.c 2006-03-01 23:18:51.000000000 +0200
15678 +++ lighttpd-1.4.12/src/mod_alias.c 2006-07-16 00:26:03.000000000 +0300
15680 #include "buffer.h"
15682 #include "plugin.h"
15683 +#include "sys-strings.h"
15685 /* plugin config for all request/connections */
15687 @@ -16,44 +17,44 @@
15693 plugin_config **config_storage;
15695 - plugin_config conf;
15697 + plugin_config conf;
15700 /* init the plugin data */
15701 INIT_FUNC(mod_alias_init) {
15705 p = calloc(1, sizeof(*p));
15715 /* detroy the plugin data */
15716 FREE_FUNC(mod_alias_free) {
15717 plugin_data *p = p_d;
15720 if (!p) return HANDLER_GO_ON;
15723 if (p->config_storage) {
15727 for (i = 0; i < srv->config_context->used; i++) {
15728 plugin_config *s = p->config_storage[i];
15731 array_free(s->alias);
15736 free(p->config_storage);
15743 return HANDLER_GO_ON;
15746 @@ -62,25 +63,25 @@
15747 SETDEFAULTS_FUNC(mod_alias_set_defaults) {
15748 plugin_data *p = p_d;
15751 - config_values_t cv[] = {
15753 + config_values_t cv[] = {
15754 { "alias.url", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
15755 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
15759 if (!p) return HANDLER_ERROR;
15762 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
15765 for (i = 0; i < srv->config_context->used; i++) {
15769 s = calloc(1, sizeof(plugin_config));
15770 - s->alias = array_init();
15771 + s->alias = array_init();
15772 cv[0].destination = s->alias;
15775 p->config_storage[i] = s;
15778 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
15779 return HANDLER_ERROR;
15781 @@ -110,76 +111,73 @@
15787 return HANDLER_GO_ON;
15790 -#define PATCH(x) \
15791 - p->conf.x = s->x;
15792 static int mod_alias_patch_connection(server *srv, connection *con, plugin_data *p) {
15794 plugin_config *s = p->config_storage[0];
15799 + PATCH_OPTION(alias);
15801 /* skip the first, the global context */
15802 for (i = 1; i < srv->config_context->used; i++) {
15803 data_config *dc = (data_config *)srv->config_context->data[i];
15804 s = p->config_storage[i];
15807 /* condition didn't match */
15808 if (!config_check_cond(srv, con, dc)) continue;
15812 for (j = 0; j < dc->value->used; j++) {
15813 data_unset *du = dc->value->data[j];
15816 if (buffer_is_equal_string(du->key, CONST_STR_LEN("alias.url"))) {
15818 + PATCH_OPTION(alias);
15828 PHYSICALPATH_FUNC(mod_alias_physical_handler) {
15829 plugin_data *p = p_d;
15830 int uri_len, basedir_len;
15835 if (con->physical.path->used == 0) return HANDLER_GO_ON;
15838 mod_alias_patch_connection(srv, con, p);
15841 /* not to include the tailing slash */
15842 basedir_len = (con->physical.basedir->used - 1) - 1;
15843 uri_len = con->physical.path->used - 1 - basedir_len;
15844 uri_ptr = con->physical.path->ptr + basedir_len;
15847 for (k = 0; k < p->conf.alias->used; k++) {
15848 data_string *ds = (data_string *)p->conf.alias->data[k];
15849 int alias_len = ds->key->used - 1;
15852 if (alias_len > uri_len) continue;
15853 if (ds->key->used == 0) continue;
15856 if (0 == (con->conf.force_lowercase_filenames ?
15857 strncasecmp(uri_ptr, ds->key->ptr, alias_len) :
15858 strncmp(uri_ptr, ds->key->ptr, alias_len))) {
15862 buffer_copy_string_buffer(con->physical.basedir, ds->value);
15863 buffer_copy_string_buffer(srv->tmp_buf, ds->value);
15864 buffer_append_string(srv->tmp_buf, uri_ptr + alias_len);
15865 buffer_copy_string_buffer(con->physical.path, srv->tmp_buf);
15868 return HANDLER_GO_ON;
15874 return HANDLER_GO_ON;
15876 @@ -189,13 +187,13 @@
15877 int mod_alias_plugin_init(plugin *p) {
15878 p->version = LIGHTTPD_VERSION_ID;
15879 p->name = buffer_init_string("alias");
15882 p->init = mod_alias_init;
15883 p->handle_physical= mod_alias_physical_handler;
15884 p->set_defaults = mod_alias_set_defaults;
15885 p->cleanup = mod_alias_free;
15893 --- ../lighttpd-1.4.11/src/mod_auth.c 2006-02-15 20:01:31.000000000 +0200
15894 +++ lighttpd-1.4.12/src/mod_auth.c 2006-07-18 13:03:40.000000000 +0300
15895 @@ -5,168 +5,167 @@
15896 #include <string.h>
15899 -#include <unistd.h>
15901 #include "plugin.h"
15902 #include "http_auth.h"
15904 #include "response.h"
15906 +#include "sys-strings.h"
15907 +#include "sys-files.h"
15909 handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s);
15913 * the basic and digest auth framework
15916 * - config handling
15917 * - protocol handling
15920 - * http_auth_digest.c
15924 + * http_auth_digest.c
15929 INIT_FUNC(mod_auth_init) {
15930 mod_auth_plugin_data *p;
15933 p = calloc(1, sizeof(*p));
15936 p->tmp_buf = buffer_init();
15939 p->auth_user = buffer_init();
15941 p->ldap_filter = buffer_init();
15948 FREE_FUNC(mod_auth_free) {
15949 mod_auth_plugin_data *p = p_d;
15954 if (!p) return HANDLER_GO_ON;
15957 buffer_free(p->tmp_buf);
15958 buffer_free(p->auth_user);
15960 buffer_free(p->ldap_filter);
15964 if (p->config_storage) {
15966 for (i = 0; i < srv->config_context->used; i++) {
15967 mod_auth_plugin_config *s = p->config_storage[i];
15973 array_free(s->auth_require);
15974 buffer_free(s->auth_plain_groupfile);
15975 buffer_free(s->auth_plain_userfile);
15976 buffer_free(s->auth_htdigest_userfile);
15977 buffer_free(s->auth_htpasswd_userfile);
15978 buffer_free(s->auth_backend_conf);
15981 buffer_free(s->auth_ldap_hostname);
15982 buffer_free(s->auth_ldap_basedn);
15983 buffer_free(s->auth_ldap_binddn);
15984 buffer_free(s->auth_ldap_bindpw);
15985 buffer_free(s->auth_ldap_filter);
15986 buffer_free(s->auth_ldap_cafile);
15990 buffer_free(s->ldap_filter_pre);
15991 buffer_free(s->ldap_filter_post);
15994 if (s->ldap) ldap_unbind_s(s->ldap);
16000 free(p->config_storage);
16007 return HANDLER_GO_ON;
16010 -#define PATCH(x) \
16011 - p->conf.x = s->x;
16012 static int mod_auth_patch_connection(server *srv, connection *con, mod_auth_plugin_data *p) {
16014 mod_auth_plugin_config *s = p->config_storage[0];
16016 - PATCH(auth_backend);
16017 - PATCH(auth_plain_groupfile);
16018 - PATCH(auth_plain_userfile);
16019 - PATCH(auth_htdigest_userfile);
16020 - PATCH(auth_htpasswd_userfile);
16021 - PATCH(auth_require);
16022 - PATCH(auth_debug);
16023 - PATCH(auth_ldap_hostname);
16024 - PATCH(auth_ldap_basedn);
16025 - PATCH(auth_ldap_binddn);
16026 - PATCH(auth_ldap_bindpw);
16027 - PATCH(auth_ldap_filter);
16028 - PATCH(auth_ldap_cafile);
16029 - PATCH(auth_ldap_starttls);
16030 + PATCH_OPTION(auth_backend);
16031 + PATCH_OPTION(auth_plain_groupfile);
16032 + PATCH_OPTION(auth_plain_userfile);
16033 + PATCH_OPTION(auth_htdigest_userfile);
16034 + PATCH_OPTION(auth_htpasswd_userfile);
16035 + PATCH_OPTION(auth_require);
16036 + PATCH_OPTION(auth_debug);
16037 + PATCH_OPTION(auth_ldap_hostname);
16038 + PATCH_OPTION(auth_ldap_basedn);
16039 + PATCH_OPTION(auth_ldap_binddn);
16040 + PATCH_OPTION(auth_ldap_bindpw);
16041 + PATCH_OPTION(auth_ldap_filter);
16042 + PATCH_OPTION(auth_ldap_cafile);
16043 + PATCH_OPTION(auth_ldap_starttls);
16046 - PATCH(ldap_filter_pre);
16047 - PATCH(ldap_filter_post);
16048 + PATCH_OPTION(ldap);
16049 + PATCH_OPTION(ldap_filter_pre);
16050 + PATCH_OPTION(ldap_filter_post);
16054 /* skip the first, the global context */
16055 for (i = 1; i < srv->config_context->used; i++) {
16056 data_config *dc = (data_config *)srv->config_context->data[i];
16057 s = p->config_storage[i];
16060 /* condition didn't match */
16061 if (!config_check_cond(srv, con, dc)) continue;
16065 for (j = 0; j < dc->value->used; j++) {
16066 data_unset *du = dc->value->data[j];
16069 if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend"))) {
16070 - PATCH(auth_backend);
16071 + PATCH_OPTION(auth_backend);
16072 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.plain.groupfile"))) {
16073 - PATCH(auth_plain_groupfile);
16074 + PATCH_OPTION(auth_plain_groupfile);
16075 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.plain.userfile"))) {
16076 - PATCH(auth_plain_userfile);
16077 + PATCH_OPTION(auth_plain_userfile);
16078 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.htdigest.userfile"))) {
16079 - PATCH(auth_htdigest_userfile);
16080 + PATCH_OPTION(auth_htdigest_userfile);
16081 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.htpasswd.userfile"))) {
16082 - PATCH(auth_htpasswd_userfile);
16083 + PATCH_OPTION(auth_htpasswd_userfile);
16084 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.require"))) {
16085 - PATCH(auth_require);
16086 + PATCH_OPTION(auth_require);
16087 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.debug"))) {
16088 - PATCH(auth_debug);
16089 + PATCH_OPTION(auth_debug);
16090 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.hostname"))) {
16091 - PATCH(auth_ldap_hostname);
16092 + PATCH_OPTION(auth_ldap_hostname);
16095 - PATCH(ldap_filter_pre);
16096 - PATCH(ldap_filter_post);
16097 + PATCH_OPTION(ldap);
16098 + PATCH_OPTION(ldap_filter_pre);
16099 + PATCH_OPTION(ldap_filter_post);
16101 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.base-dn"))) {
16102 - PATCH(auth_ldap_basedn);
16103 + PATCH_OPTION(auth_ldap_basedn);
16104 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.filter"))) {
16105 - PATCH(auth_ldap_filter);
16106 + PATCH_OPTION(auth_ldap_filter);
16107 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.ca-file"))) {
16108 - PATCH(auth_ldap_cafile);
16109 + PATCH_OPTION(auth_ldap_cafile);
16110 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.starttls"))) {
16111 - PATCH(auth_ldap_starttls);
16112 + PATCH_OPTION(auth_ldap_starttls);
16122 static handler_t mod_auth_uri_handler(server *srv, connection *con, void *p_d) {
16124 @@ -175,22 +174,22 @@
16126 mod_auth_plugin_data *p = p_d;
16130 /* select the right config */
16131 mod_auth_patch_connection(srv, con, p);
16134 if (p->conf.auth_require == NULL) return HANDLER_GO_ON;
16144 /* do we have to ask for auth ? */
16148 auth_satisfied = 0;
16151 /* search auth-directives for path */
16152 for (k = 0; k < p->conf.auth_require->used; k++) {
16153 buffer *req = p->conf.auth_require->data[k]->key;
16154 @@ -212,76 +211,76 @@
16160 /* nothing to do for us */
16161 if (auth_required == 0) return HANDLER_GO_ON;
16164 req = ((data_array *)(p->conf.auth_require->data[k]))->value;
16167 /* try to get Authorization-header */
16170 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Authorization"))) {
16171 http_authorization = ds->value->ptr;
16175 if (ds && ds->value && ds->value->used) {
16177 data_string *method;
16180 method = (data_string *)array_get_element(req, "method");
16183 /* parse auth-header */
16184 if (NULL != (auth_realm = strchr(http_authorization, ' '))) {
16185 int auth_type_len = auth_realm - http_authorization;
16188 if ((auth_type_len == 5) &&
16189 (0 == strncmp(http_authorization, "Basic", auth_type_len))) {
16191 - if (0 == strcmp(method->value->ptr, "basic")) {
16193 + if (buffer_is_equal_string(method->value, CONST_STR_LEN("basic"))) {
16194 auth_satisfied = http_auth_basic_check(srv, con, p, req, con->uri.path, auth_realm+1);
16196 } else if ((auth_type_len == 6) &&
16197 (0 == strncmp(http_authorization, "Digest", auth_type_len))) {
16198 - if (0 == strcmp(method->value->ptr, "digest")) {
16199 + if (buffer_is_equal_string(method->value, CONST_STR_LEN("digest"))) {
16200 if (-1 == (auth_satisfied = http_auth_digest_check(srv, con, p, req, con->uri.path, auth_realm+1))) {
16201 con->http_status = 400;
16204 /* a field was missing */
16207 return HANDLER_FINISHED;
16211 - log_error_write(srv, __FILE__, __LINE__, "ss",
16212 + log_error_write(srv, __FILE__, __LINE__, "ss",
16213 "unknown authentification type:",
16214 http_authorization);
16220 if (!auth_satisfied) {
16221 data_string *method, *realm;
16222 method = (data_string *)array_get_element(req, "method");
16223 realm = (data_string *)array_get_element(req, "realm");
16226 con->http_status = 401;
16228 - if (0 == strcmp(method->value->ptr, "basic")) {
16230 + if (buffer_is_equal_string(method->value, CONST_STR_LEN("basic"))) {
16231 buffer_copy_string(p->tmp_buf, "Basic realm=\"");
16232 buffer_append_string_buffer(p->tmp_buf, realm->value);
16233 buffer_append_string(p->tmp_buf, "\"");
16236 response_header_insert(srv, con, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(p->tmp_buf));
16237 - } else if (0 == strcmp(method->value->ptr, "digest")) {
16238 + } else if (buffer_is_equal_string(method->value, CONST_STR_LEN("digest"))) {
16240 http_auth_digest_generate_nonce(srv, p, srv->tmp_buf, hh);
16243 buffer_copy_string(p->tmp_buf, "Digest realm=\"");
16244 buffer_append_string_buffer(p->tmp_buf, realm->value);
16245 buffer_append_string(p->tmp_buf, "\", nonce=\"");
16246 buffer_append_string(p->tmp_buf, hh);
16247 buffer_append_string(p->tmp_buf, "\", qop=\"auth\"");
16250 response_header_insert(srv, con, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(p->tmp_buf));
16253 @@ -289,18 +288,18 @@
16254 return HANDLER_FINISHED;
16256 /* the REMOTE_USER header */
16259 buffer_copy_string_buffer(con->authed_user, p->auth_user);
16263 return HANDLER_GO_ON;
16266 SETDEFAULTS_FUNC(mod_auth_set_defaults) {
16267 mod_auth_plugin_data *p = p_d;
16270 - config_values_t cv[] = {
16272 + config_values_t cv[] = {
16273 { "auth.backend", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
16274 { "auth.backend.plain.groupfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
16275 { "auth.backend.plain.userfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
16276 @@ -317,7 +316,7 @@
16277 { "auth.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 13 */
16278 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
16282 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
16284 for (i = 0; i < srv->config_context->used; i++) {
16285 @@ -325,14 +324,14 @@
16291 s = calloc(1, sizeof(mod_auth_plugin_config));
16292 s->auth_plain_groupfile = buffer_init();
16293 s->auth_plain_userfile = buffer_init();
16294 s->auth_htdigest_userfile = buffer_init();
16295 s->auth_htpasswd_userfile = buffer_init();
16296 s->auth_backend_conf = buffer_init();
16299 s->auth_ldap_hostname = buffer_init();
16300 s->auth_ldap_basedn = buffer_init();
16301 s->auth_ldap_binddn = buffer_init();
16302 @@ -341,15 +340,15 @@
16303 s->auth_ldap_cafile = buffer_init();
16304 s->auth_ldap_starttls = 0;
16308 s->auth_require = array_init();
16312 s->ldap_filter_pre = buffer_init();
16313 s->ldap_filter_post = buffer_init();
16318 cv[0].destination = s->auth_backend_conf;
16319 cv[1].destination = s->auth_plain_groupfile;
16320 cv[2].destination = s->auth_plain_userfile;
16321 @@ -364,146 +363,148 @@
16322 cv[11].destination = s->auth_htdigest_userfile;
16323 cv[12].destination = s->auth_htpasswd_userfile;
16324 cv[13].destination = &(s->auth_debug);
16327 p->config_storage[i] = s;
16328 ca = ((data_config *)srv->config_context->data[i])->value;
16331 if (0 != config_insert_values_global(srv, ca, cv)) {
16332 return HANDLER_ERROR;
16335 - if (s->auth_backend_conf->used) {
16336 - if (0 == strcmp(s->auth_backend_conf->ptr, "htpasswd")) {
16338 + if (!buffer_is_empty(s->auth_backend_conf)) {
16339 + if (buffer_is_equal_string(s->auth_backend_conf, CONST_STR_LEN("htpasswd"))) {
16340 s->auth_backend = AUTH_BACKEND_HTPASSWD;
16341 - } else if (0 == strcmp(s->auth_backend_conf->ptr, "htdigest")) {
16342 + } else if (buffer_is_equal_string(s->auth_backend_conf, CONST_STR_LEN("htdigest"))) {
16343 s->auth_backend = AUTH_BACKEND_HTDIGEST;
16344 - } else if (0 == strcmp(s->auth_backend_conf->ptr, "plain")) {
16345 + } else if (buffer_is_equal_string(s->auth_backend_conf, CONST_STR_LEN("plain"))) {
16346 s->auth_backend = AUTH_BACKEND_PLAIN;
16347 - } else if (0 == strcmp(s->auth_backend_conf->ptr, "ldap")) {
16348 + } else if (buffer_is_equal_string(s->auth_backend_conf, CONST_STR_LEN("ldap"))) {
16349 s->auth_backend = AUTH_BACKEND_LDAP;
16351 log_error_write(srv, __FILE__, __LINE__, "sb", "auth.backend not supported:", s->auth_backend_conf);
16354 return HANDLER_ERROR;
16358 /* no auth.require for this section */
16359 if (NULL == (da = (data_array *)array_get_element(ca, "auth.require"))) continue;
16362 if (da->type != TYPE_ARRAY) continue;
16365 for (n = 0; n < da->value->used; n++) {
16367 data_array *da_file = (data_array *)da->value->data[n];
16368 - const char *method, *realm, *require;
16370 + buffer *method, *realm, *require;
16372 if (da->value->data[n]->type != TYPE_ARRAY) {
16373 - log_error_write(srv, __FILE__, __LINE__, "ss",
16374 - "auth.require should contain an array as in:",
16375 + log_error_write(srv, __FILE__, __LINE__, "ss",
16376 + "auth.require should contain an array as in:",
16377 "auth.require = ( \"...\" => ( ..., ...) )");
16379 return HANDLER_ERROR;
16383 method = realm = require = NULL;
16386 for (m = 0; m < da_file->value->used; m++) {
16387 - if (da_file->value->data[m]->type == TYPE_STRING) {
16388 - if (0 == strcmp(da_file->value->data[m]->key->ptr, "method")) {
16389 - method = ((data_string *)(da_file->value->data[m]))->value->ptr;
16390 - } else if (0 == strcmp(da_file->value->data[m]->key->ptr, "realm")) {
16391 - realm = ((data_string *)(da_file->value->data[m]))->value->ptr;
16392 - } else if (0 == strcmp(da_file->value->data[m]->key->ptr, "require")) {
16393 - require = ((data_string *)(da_file->value->data[m]))->value->ptr;
16395 - log_error_write(srv, __FILE__, __LINE__, "ssbs",
16396 - "the field is unknown in:",
16397 + data_string *ds_auth_req = (data_string *)da_file->value->data[m];
16399 + if (ds_auth_req->type != TYPE_STRING) {
16400 + log_error_write(srv, __FILE__, __LINE__, "ssbs",
16401 + "a string was expected for:",
16402 + "auth.require = ( \"...\" => ( ..., -> \"",
16403 + ds_auth_req->key,
16404 + "\" <- => \"...\" ) )");
16406 + return HANDLER_ERROR;
16409 + if (buffer_is_equal_string(ds_auth_req->key, CONST_STR_LEN("method"))) {
16410 + method = ds_auth_req->value;
16411 + } else if (buffer_is_equal_string(ds_auth_req->key, CONST_STR_LEN("realm"))) {
16412 + realm = ds_auth_req->value;
16413 + } else if (buffer_is_equal_string(ds_auth_req->key, CONST_STR_LEN("require"))) {
16414 + require = ds_auth_req->value;
16416 + log_error_write(srv, __FILE__, __LINE__, "ssbs",
16417 + "the field is unknown in:",
16418 "auth.require = ( \"...\" => ( ..., -> \"",
16419 da_file->value->data[m]->key,
16420 "\" <- => \"...\" ) )");
16422 - return HANDLER_ERROR;
16425 - log_error_write(srv, __FILE__, __LINE__, "ssbs",
16426 - "a string was expected for:",
16427 - "auth.require = ( \"...\" => ( ..., -> \"",
16428 - da_file->value->data[m]->key,
16429 - "\" <- => \"...\" ) )");
16431 return HANDLER_ERROR;
16437 if (method == NULL) {
16438 - log_error_write(srv, __FILE__, __LINE__, "ss",
16439 - "the require field is missing in:",
16440 + log_error_write(srv, __FILE__, __LINE__, "ss",
16441 + "the require field is missing in:",
16442 "auth.require = ( \"...\" => ( ..., \"method\" => \"...\" ) )");
16443 return HANDLER_ERROR;
16445 - if (0 != strcmp(method, "basic") &&
16446 - 0 != strcmp(method, "digest")) {
16447 - log_error_write(srv, __FILE__, __LINE__, "ss",
16448 - "method has to be either \"basic\" or \"digest\" in",
16449 - "auth.require = ( \"...\" => ( ..., \"method\" => \"...\") )");
16450 - return HANDLER_ERROR;
16453 + if (!buffer_is_equal_string(method, CONST_STR_LEN("basic")) &&
16454 + !buffer_is_equal_string(method, CONST_STR_LEN("digest"))) {
16455 + log_error_write(srv, __FILE__, __LINE__, "ss",
16456 + "method has to be either \"basic\" or \"digest\" in",
16457 + "auth.require = ( \"...\" => ( ..., \"method\" => \"...\") )");
16458 + return HANDLER_ERROR;
16462 if (realm == NULL) {
16463 - log_error_write(srv, __FILE__, __LINE__, "ss",
16464 - "the require field is missing in:",
16465 + log_error_write(srv, __FILE__, __LINE__, "ss",
16466 + "the require field is missing in:",
16467 "auth.require = ( \"...\" => ( ..., \"realm\" => \"...\" ) )");
16468 return HANDLER_ERROR;
16472 if (require == NULL) {
16473 - log_error_write(srv, __FILE__, __LINE__, "ss",
16474 - "the require field is missing in:",
16475 + log_error_write(srv, __FILE__, __LINE__, "ss",
16476 + "the require field is missing in:",
16477 "auth.require = ( \"...\" => ( ..., \"require\" => \"...\" ) )");
16478 return HANDLER_ERROR;
16482 if (method && realm && require) {
16487 a = data_array_init();
16488 buffer_copy_string_buffer(a->key, da_file->key);
16491 ds = data_string_init();
16494 buffer_copy_string(ds->key, "method");
16495 - buffer_copy_string(ds->value, method);
16497 + buffer_copy_string_buffer(ds->value, method);
16499 array_insert_unique(a->value, (data_unset *)ds);
16502 ds = data_string_init();
16505 buffer_copy_string(ds->key, "realm");
16506 - buffer_copy_string(ds->value, realm);
16508 + buffer_copy_string_buffer(ds->value, realm);
16510 array_insert_unique(a->value, (data_unset *)ds);
16513 ds = data_string_init();
16516 buffer_copy_string(ds->key, "require");
16517 - buffer_copy_string(ds->value, require);
16519 + buffer_copy_string_buffer(ds->value, require);
16521 array_insert_unique(a->value, (data_unset *)ds);
16524 array_insert_unique(s->auth_require, (data_unset *)a);
16529 switch(s->auth_backend) {
16530 case AUTH_BACKEND_PLAIN:
16531 if (s->auth_plain_userfile->used) {
16534 if (-1 == (fd = open(s->auth_plain_userfile->ptr, O_RDONLY))) {
16535 - log_error_write(srv, __FILE__, __LINE__, "sbss",
16536 + log_error_write(srv, __FILE__, __LINE__, "sbss",
16537 "opening auth.backend.plain.userfile:", s->auth_plain_userfile,
16538 "failed:", strerror(errno));
16539 return HANDLER_ERROR;
16540 @@ -516,7 +517,7 @@
16543 if (-1 == (fd = open(s->auth_htpasswd_userfile->ptr, O_RDONLY))) {
16544 - log_error_write(srv, __FILE__, __LINE__, "sbss",
16545 + log_error_write(srv, __FILE__, __LINE__, "sbss",
16546 "opening auth.backend.htpasswd.userfile:", s->auth_htpasswd_userfile,
16547 "failed:", strerror(errno));
16548 return HANDLER_ERROR;
16549 @@ -529,7 +530,7 @@
16552 if (-1 == (fd = open(s->auth_htdigest_userfile->ptr, O_RDONLY))) {
16553 - log_error_write(srv, __FILE__, __LINE__, "sbss",
16554 + log_error_write(srv, __FILE__, __LINE__, "sbss",
16555 "opening auth.backend.htdigest.userfile:", s->auth_htdigest_userfile,
16556 "failed:", strerror(errno));
16557 return HANDLER_ERROR;
16558 @@ -554,75 +555,75 @@
16559 handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s) {
16564 if (s->auth_ldap_basedn->used == 0) {
16565 log_error_write(srv, __FILE__, __LINE__, "s", "ldap: auth.backend.ldap.base-dn has to be set");
16568 return HANDLER_ERROR;
16573 if (s->auth_ldap_filter->used) {
16580 if (NULL == (dollar = strchr(s->auth_ldap_filter->ptr, '$'))) {
16581 log_error_write(srv, __FILE__, __LINE__, "s", "ldap: auth.backend.ldap.filter is missing a replace-operator '$'");
16584 return HANDLER_ERROR;
16588 buffer_copy_string_len(s->ldap_filter_pre, s->auth_ldap_filter->ptr, dollar - s->auth_ldap_filter->ptr);
16589 buffer_copy_string(s->ldap_filter_post, dollar+1);
16593 if (s->auth_ldap_hostname->used) {
16594 if (NULL == (s->ldap = ldap_init(s->auth_ldap_hostname->ptr, LDAP_PORT))) {
16595 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap ...", strerror(errno));
16598 return HANDLER_ERROR;
16602 ret = LDAP_VERSION3;
16603 if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(s->ldap, LDAP_OPT_PROTOCOL_VERSION, &ret))) {
16604 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
16607 return HANDLER_ERROR;
16610 if (s->auth_ldap_starttls) {
16611 - /* if no CA file is given, it is ok, as we will use encryption
16612 + /* if no CA file is given, it is ok, as we will use encryption
16613 * if the server requires a CAfile it will tell us */
16614 if (!buffer_is_empty(s->auth_ldap_cafile)) {
16615 - if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE,
16616 + if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE,
16617 s->auth_ldap_cafile->ptr))) {
16618 - log_error_write(srv, __FILE__, __LINE__, "ss",
16619 + log_error_write(srv, __FILE__, __LINE__, "ss",
16620 "Loading CA certificate failed:", ldap_err2string(ret));
16623 return HANDLER_ERROR;
16628 if (LDAP_OPT_SUCCESS != (ret = ldap_start_tls_s(s->ldap, NULL, NULL))) {
16629 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap startTLS failed:", ldap_err2string(ret));
16632 return HANDLER_ERROR;
16640 if (s->auth_ldap_binddn->used) {
16641 if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(s->ldap, s->auth_ldap_binddn->ptr, s->auth_ldap_bindpw->ptr))) {
16642 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
16645 return HANDLER_ERROR;
16648 if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(s->ldap, NULL, NULL))) {
16649 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
16652 return HANDLER_ERROR;
16655 @@ -641,8 +642,8 @@
16656 p->set_defaults = mod_auth_set_defaults;
16657 p->handle_uri_clean = mod_auth_uri_handler;
16658 p->cleanup = mod_auth_free;
16666 --- ../lighttpd-1.4.11/src/mod_cgi.c 2006-02-22 15:15:10.000000000 +0200
16667 +++ lighttpd-1.4.12/src/mod_cgi.c 2006-07-18 17:34:32.000000000 +0300
16669 #include <sys/types.h>
16671 -#include <winsock2.h>
16673 -#include <sys/socket.h>
16674 -#include <sys/wait.h>
16675 -#include <sys/mman.h>
16677 -#include <netinet/in.h>
16679 -#include <arpa/inet.h>
16682 -#include <unistd.h>
16684 #include <stdlib.h>
16685 #include <string.h>
16686 -#include <fdevent.h>
16687 #include <signal.h>
16689 #include <assert.h>
16691 #include "connections.h"
16692 #include "joblist.h"
16693 #include "http_chunk.h"
16694 +#include "fdevent.h"
16696 #include "plugin.h"
16697 +#include "http_resp.h"
16699 +#include "sys-files.h"
16700 +#include "sys-mmap.h"
16701 +#include "sys-socket.h"
16702 +#include "sys-strings.h"
16703 +#include "sys-process.h"
16705 #ifdef HAVE_SYS_FILIO_H
16706 # include <sys/filio.h>
16707 @@ -40,11 +35,12 @@
16721 @@ -58,57 +54,68 @@
16724 buffer_pid_t cgi_pid;
16728 - buffer *parse_response;
16733 plugin_config **config_storage;
16735 - plugin_config conf;
16737 + plugin_config conf;
16742 + CGI_STATE_CONNECTING,
16743 + CGI_STATE_READ_RESPONSE_HEADER,
16744 + CGI_STATE_READ_RESPONSE_CONTENT
16750 - int fde_ndx; /* index into the fd-event buffer */
16752 - connection *remote_conn; /* dumb pointer */
16753 - plugin_data *plugin_data; /* dumb pointer */
16755 - buffer *response;
16756 - buffer *response_header;
16759 -static handler_ctx * cgi_handler_ctx_init() {
16760 - handler_ctx *hctx = calloc(1, sizeof(*hctx));
16765 - hctx->response = buffer_init();
16766 - hctx->response_header = buffer_init();
16773 -static void cgi_handler_ctx_free(handler_ctx *hctx) {
16774 - buffer_free(hctx->response);
16775 - buffer_free(hctx->response_header);
16778 + cgi_state_t state;
16780 + connection *remote_con; /* dumb pointer */
16783 +static cgi_session * cgi_session_init() {
16784 + cgi_session *sess = calloc(1, sizeof(*sess));
16787 + sess->sock = iosocket_init();
16788 + sess->wb = chunkqueue_init();
16789 + sess->rb = chunkqueue_init();
16794 -enum {FDEVENT_HANDLED_UNSET, FDEVENT_HANDLED_FINISHED, FDEVENT_HANDLED_NOT_FINISHED, FDEVENT_HANDLED_ERROR};
16795 +static void cgi_session_free(cgi_session *sess) {
16796 + if (!sess) return;
16798 + iosocket_free(sess->sock);
16800 + chunkqueue_free(sess->wb);
16801 + chunkqueue_free(sess->rb);
16806 INIT_FUNC(mod_cgi_init) {
16810 p = calloc(1, sizeof(*p));
16815 p->tmp_buf = buffer_init();
16816 - p->parse_response = buffer_init();
16818 + p->resp = http_response_init();
16823 @@ -116,62 +123,62 @@
16824 FREE_FUNC(mod_cgi_free) {
16825 plugin_data *p = p_d;
16826 buffer_pid_t *r = &(p->cgi_pid);
16832 if (p->config_storage) {
16834 for (i = 0; i < srv->config_context->used; i++) {
16835 plugin_config *s = p->config_storage[i];
16838 array_free(s->cgi);
16843 free(p->config_storage);
16848 if (r->ptr) free(r->ptr);
16851 buffer_free(p->tmp_buf);
16852 - buffer_free(p->parse_response);
16854 + http_response_free(p->resp);
16859 return HANDLER_GO_ON;
16862 SETDEFAULTS_FUNC(mod_fastcgi_set_defaults) {
16863 plugin_data *p = p_d;
16866 - config_values_t cv[] = {
16868 + config_values_t cv[] = {
16869 { "cgi.assign", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
16870 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET}
16873 if (!p) return HANDLER_ERROR;
16876 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
16879 for (i = 0; i < srv->config_context->used; i++) {
16883 s = calloc(1, sizeof(plugin_config));
16887 s->cgi = array_init();
16890 cv[0].destination = s->cgi;
16893 p->config_storage[i] = s;
16896 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
16897 return HANDLER_ERROR;
16902 return HANDLER_GO_ON;
16905 @@ -180,13 +187,13 @@
16908 buffer_pid_t *r = &(p->cgi_pid);
16913 for (i = 0; i < r->used; i++) {
16914 if (r->ptr[i] > m) m = r->ptr[i];
16918 if (r->size == 0) {
16920 r->ptr = malloc(sizeof(*r->ptr) * r->size);
16921 @@ -194,321 +201,179 @@
16923 r->ptr = realloc(r->ptr, sizeof(*r->ptr) * r->size);
16927 r->ptr[r->used++] = pid;
16933 static int cgi_pid_del(server *srv, plugin_data *p, pid_t pid) {
16935 buffer_pid_t *r = &(p->cgi_pid);
16940 for (i = 0; i < r->used; i++) {
16941 if (r->ptr[i] == pid) break;
16945 if (i != r->used) {
16949 if (i != r->used - 1) {
16950 r->ptr[i] = r->ptr[r->used - 1];
16959 -static int cgi_response_parse(server *srv, connection *con, plugin_data *p, buffer *in, int eol) {
16966 - buffer_copy_string_buffer(p->parse_response, in);
16968 - for (s = p->parse_response->ptr;
16969 - NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n')));
16970 - s = ns + (eol == EOL_RN ? 2 : 1), line++) {
16971 - const char *key, *value;
16978 - 0 == strncmp(s, "HTTP/1.", 7)) {
16979 - /* non-parsed header ... we parse them anyway */
16981 - if ((s[7] == '1' ||
16985 - /* after the space should be a status code for us */
16987 - status = strtol(s+9, NULL, 10);
16989 - if (con->http_status >= 100 &&
16990 - con->http_status < 1000) {
16991 - /* we expected 3 digits and didn't got them */
16992 - con->parsed_response |= HTTP_STATUS;
16993 - con->http_status = status;
16999 - if (NULL == (value = strchr(s, ':'))) {
17000 - /* we expect: "<key>: <value>\r\n" */
17004 - key_len = value - key;
17008 - while (*value == ' ' || *value == '\t') value++;
17010 - if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
17011 - ds = data_response_init();
17013 - buffer_copy_string_len(ds->key, key, key_len);
17014 - buffer_copy_string(ds->value, value);
17016 - array_insert_unique(con->response.headers, (data_unset *)ds);
17018 - switch(key_len) {
17020 - if (0 == strncasecmp(key, "Date", key_len)) {
17021 - con->parsed_response |= HTTP_DATE;
17025 - if (0 == strncasecmp(key, "Status", key_len)) {
17026 - con->http_status = strtol(value, NULL, 10);
17027 - con->parsed_response |= HTTP_STATUS;
17031 - if (0 == strncasecmp(key, "Location", key_len)) {
17032 - con->parsed_response |= HTTP_LOCATION;
17036 - if (0 == strncasecmp(key, "Connection", key_len)) {
17037 - con->response.keep_alive = (0 == strcasecmp(value, "Keep-Alive")) ? 1 : 0;
17038 - con->parsed_response |= HTTP_CONNECTION;
17042 - if (0 == strncasecmp(key, "Content-Length", key_len)) {
17043 - con->response.content_length = strtol(value, NULL, 10);
17044 - con->parsed_response |= HTTP_CONTENT_LENGTH;
17053 - /* CGI/1.1 rev 03 - 7.2.1.2 */
17054 - if ((con->parsed_response & HTTP_LOCATION) &&
17055 - !(con->parsed_response & HTTP_STATUS)) {
17056 - con->http_status = 302;
17057 +static int cgi_demux_response(server *srv, connection *con, plugin_data *p) {
17058 + cgi_session *sess = con->plugin_ctx[p->id];
17061 + switch(srv->network_backend_read(srv, con, sess->sock, sess->rb)) {
17062 + case NETWORK_STATUS_SUCCESS:
17063 + /* we got content */
17065 + case NETWORK_STATUS_WAIT_FOR_EVENT:
17067 + case NETWORK_STATUS_CONNECTION_CLOSE:
17068 + /* this is a bit too early */
17069 + ERROR("%s", "cgi-connection got closed before we read the response-header (CGI died ?)");
17073 + ERROR("%s", "oops, read-pipe-read failed and I don't know why");
17080 + /* looks like we got some content
17082 + * split off the header from the incoming stream
17085 -static int cgi_demux_response(server *srv, handler_ctx *hctx) {
17086 - plugin_data *p = hctx->plugin_data;
17087 - connection *con = hctx->remote_conn;
17092 - buffer_prepare_copy(hctx->response, 1024);
17093 - if (-1 == (n = read(hctx->fd, hctx->response->ptr, hctx->response->size - 1))) {
17094 - if (errno == EAGAIN || errno == EINTR) {
17095 - /* would block, wait for signal */
17096 - return FDEVENT_HANDLED_NOT_FINISHED;
17099 - log_error_write(srv, __FILE__, __LINE__, "sdd", strerror(errno), con->fd, hctx->fd);
17100 - return FDEVENT_HANDLED_ERROR;
17104 - /* read finished */
17106 - con->file_finished = 1;
17108 - /* send final chunk */
17109 - http_chunk_append_mem(srv, con, NULL, 0);
17110 - joblist_append(srv, con);
17112 - return FDEVENT_HANDLED_FINISHED;
17115 - hctx->response->ptr[n] = '\0';
17116 - hctx->response->used = n+1;
17118 - /* split header from body */
17120 - if (con->file_started == 0) {
17122 - int in_header = 0;
17123 - int header_end = 0;
17124 - int cp, eol = EOL_UNSET;
17127 - buffer_append_string_buffer(hctx->response_header, hctx->response);
17129 - /* nph (non-parsed headers) */
17130 - if (0 == strncmp(hctx->response_header->ptr, "HTTP/1.", 7)) in_header = 1;
17132 - /* search for the \r\n\r\n or \n\n in the string */
17133 - for (c = hctx->response_header->ptr, cp = 0, used = hctx->response_header->used - 1; used; c++, cp++, used--) {
17134 - if (*c == ':') in_header = 1;
17135 - else if (*c == '\n') {
17136 - if (in_header == 0) {
17137 - /* got a response without a response header */
17144 - if (eol == EOL_UNSET) eol = EOL_N;
17146 - if (*(c+1) == '\n') {
17151 - } else if (used > 1 && *c == '\r' && *(c+1) == '\n') {
17152 - if (in_header == 0) {
17153 - /* got a response without a response header */
17160 - if (eol == EOL_UNSET) eol = EOL_RN;
17163 - *(c+2) == '\r' &&
17164 - *(c+3) == '\n') {
17169 - /* skip the \n */
17173 + if (con->file_started == 0) {
17175 + int have_content_length = 0;
17177 + http_response_reset(p->resp);
17179 + /* the response header is not fully received yet,
17181 + * extract the http-response header from the rb-cq
17183 + switch (http_response_parse_cq(sess->rb, p->resp)) {
17184 + case PARSE_ERROR:
17185 + /* parsing failed */
17187 + TRACE("%s", "response parser failed");
17189 + con->http_status = 502; /* Bad Gateway */
17191 + case PARSE_NEED_MORE:
17193 + case PARSE_SUCCESS:
17194 + con->http_status = p->resp->status;
17196 + chunkqueue_remove_finished_chunks(sess->rb);
17198 + /* copy the http-headers */
17199 + for (i = 0; i < p->resp->headers->used; i++) {
17200 + const char *ign[] = { "Status", "Connection", NULL };
17204 + data_string *header = (data_string *)p->resp->headers->data[i];
17206 + /* some headers are ignored by default */
17207 + for (j = 0; ign[j]; j++) {
17208 + if (0 == strcasecmp(ign[j], header->key->ptr)) break;
17212 - if (header_end) {
17214 - /* no header, but a body */
17216 - if (con->request.http_version == HTTP_VERSION_1_1) {
17217 - con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
17220 - http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used);
17221 - joblist_append(srv, con);
17223 - size_t hlen = c - hctx->response_header->ptr + (eol == EOL_RN ? 4 : 2);
17224 - size_t blen = hctx->response_header->used - hlen - 1;
17226 - /* a small hack: terminate after at the second \r */
17227 - hctx->response_header->used = hlen + 1 - (eol == EOL_RN ? 2 : 1);
17228 - hctx->response_header->ptr[hlen - (eol == EOL_RN ? 2 : 1)] = '\0';
17230 - /* parse the response header */
17231 - cgi_response_parse(srv, con, p, hctx->response_header, eol);
17233 - /* enable chunked-transfer-encoding */
17234 - if (con->request.http_version == HTTP_VERSION_1_1 &&
17235 - !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
17236 - con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
17239 - if ((hctx->response->used != hlen) && blen > 0) {
17240 - http_chunk_append_mem(srv, con, c + (eol == EOL_RN ? 4: 2), blen + 1);
17241 - joblist_append(srv, con);
17243 + if (ign[j]) continue;
17245 + if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Location"))) {
17246 + /* CGI/1.1 rev 03 - 7.2.1.2 */
17247 + if (con->http_status == 0) con->http_status = 302;
17248 + } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Content-Length"))) {
17249 + have_content_length = 1;
17252 - con->file_started = 1;
17253 + if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
17254 + ds = data_response_init();
17256 + buffer_copy_string_buffer(ds->key, header->key);
17257 + buffer_copy_string_buffer(ds->value, header->value);
17259 + array_insert_unique(con->response.headers, (data_unset *)ds);
17262 - http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used);
17263 - joblist_append(srv, con);
17265 + con->file_started = 1;
17266 + sess->state = CGI_STATE_READ_RESPONSE_CONTENT;
17268 + if (con->request.http_version == HTTP_VERSION_1_1 &&
17269 + !have_content_length) {
17270 + con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
17277 - log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), b->ptr);
17281 - return FDEVENT_HANDLED_NOT_FINISHED;
17283 + /* FIXME: pass the response-header to the other plugins to
17284 + * setup the filter-queue
17286 + * - use next-queue instead of con->write_queue
17289 + /* copy the content to the next cq */
17290 + for (c = sess->rb->first; c; c = c->next) {
17291 + http_chunk_append_mem(srv, con, c->mem->ptr + c->offset, c->mem->used - c->offset);
17293 + c->offset = c->mem->used - 1;
17296 + chunkqueue_remove_finished_chunks(sess->rb);
17297 + joblist_append(srv, con);
17302 -static handler_t cgi_connection_close(server *srv, handler_ctx *hctx) {
17303 +static handler_t cgi_connection_close(server *srv, connection *con, plugin_data *p) {
17304 + cgi_session *sess = con->plugin_ctx[p->id];
17310 - if (NULL == hctx) return HANDLER_GO_ON;
17312 - p = hctx->plugin_data;
17313 - con = hctx->remote_conn;
17316 + if (NULL == sess) return HANDLER_GO_ON;
17317 if (con->mode != p->id) return HANDLER_GO_ON;
17323 /* the connection to the browser went away, but we still have a connection
17324 - * to the CGI script
17325 + * to the CGI script
17327 * close cgi-connection
17330 - if (hctx->fd != -1) {
17332 + if (sess->sock->fd != -1) {
17333 /* close connection to the cgi-script */
17334 - fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
17335 - fdevent_unregister(srv->ev, hctx->fd);
17337 - if (close(hctx->fd)) {
17338 - log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno));
17342 - hctx->fde_ndx = -1;
17343 + fdevent_event_del(srv->ev, sess->sock);
17344 + fdevent_unregister(srv->ev, sess->sock);
17352 con->plugin_ctx[p->id] = NULL;
17355 /* is this a good idea ? */
17356 - cgi_handler_ctx_free(hctx);
17358 + cgi_session_free(sess);
17361 /* if waitpid hasn't been called by response.c yet, do it here */
17363 /* check if the CGI-script is already gone */
17365 switch(waitpid(pid, &status, WNOHANG)) {
17367 /* not finished yet */
17368 @@ -519,35 +384,35 @@
17371 if (errno == EINTR) break;
17374 - * errno == ECHILD happens if _subrequest catches the process-status before
17377 + * errno == ECHILD happens if _subrequest catches the process-status before
17378 * we have read the response of the cgi process
17382 * -> WAIT_FOR_EVENT
17384 * -> we get here with waitpid == ECHILD
17388 if (errno == ECHILD) return HANDLER_GO_ON;
17391 log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno));
17392 return HANDLER_ERROR;
17394 /* Send an error if we haven't sent any data yet */
17395 if (0 == con->file_started) {
17396 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
17397 - con->http_status = 500;
17398 + if (con->http_status == 0) con->http_status = 500;
17399 con->mode = DIRECT;
17403 if (WIFEXITED(status)) {
17405 log_error_write(srv, __FILE__, __LINE__, "sd", "(debug) cgi exited fine, pid:", pid);
17410 return HANDLER_GO_ON;
17412 log_error_write(srv, __FILE__, __LINE__, "sd", "cgi died, pid:", pid);
17413 @@ -555,122 +420,126 @@
17414 return HANDLER_GO_ON;
17421 kill(pid, SIGTERM);
17424 /* cgi-script is still alive, queue the PID for removal */
17425 cgi_pid_add(srv, p, pid);
17429 return HANDLER_GO_ON;
17432 static handler_t cgi_connection_close_callback(server *srv, connection *con, void *p_d) {
17433 plugin_data *p = p_d;
17435 - return cgi_connection_close(srv, con->plugin_ctx[p->id]);
17437 + return cgi_connection_close(srv, con, p);
17441 static handler_t cgi_handle_fdevent(void *s, void *ctx, int revents) {
17442 server *srv = (server *)s;
17443 - handler_ctx *hctx = ctx;
17444 - connection *con = hctx->remote_conn;
17446 - joblist_append(srv, con);
17448 - if (hctx->fd == -1) {
17449 - log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), "invalid cgi-fd");
17451 - return HANDLER_ERROR;
17454 + cgi_session *sess = ctx;
17455 + connection *con = sess->remote_con;
17458 if (revents & FDEVENT_IN) {
17459 - switch (cgi_demux_response(srv, hctx)) {
17460 - case FDEVENT_HANDLED_NOT_FINISHED:
17461 + switch (sess->state) {
17462 + case CGI_STATE_READ_RESPONSE_HEADER:
17463 + /* parse the header and set file-started, the demuxer will care about it */
17464 + joblist_append(srv, con);
17467 - case FDEVENT_HANDLED_FINISHED:
17468 - /* we are done */
17470 + case CGI_STATE_READ_RESPONSE_CONTENT:
17471 + /* just forward the content to the out-going queue */
17473 + chunkqueue_remove_finished_chunks(sess->rb);
17475 + switch (srv->network_backend_read(srv, sess->remote_con, sess->sock, sess->rb)) {
17476 + case NETWORK_STATUS_CONNECTION_CLOSE:
17477 + fdevent_event_del(srv->ev, sess->sock);
17479 + /* the connection is gone
17480 + * make the connect */
17481 + sess->remote_con->file_finished = 1;
17483 - log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), "finished");
17484 + fdevent_event_del(srv->ev, sess->sock);
17486 - cgi_connection_close(srv, hctx);
17488 - /* if we get a IN|HUP and have read everything don't exec the close twice */
17489 - return HANDLER_FINISHED;
17490 - case FDEVENT_HANDLED_ERROR:
17491 - connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
17492 - con->http_status = 500;
17493 - con->mode = DIRECT;
17495 - log_error_write(srv, __FILE__, __LINE__, "s", "demuxer failed: ");
17496 + case NETWORK_STATUS_SUCCESS:
17497 + /* read even more, do we have all the content */
17499 + /* how much do we want to read ? */
17501 + /* call stream-decoder (HTTP-chunked, FastCGI, ... ) */
17503 + chunkqueue_remove_finished_chunks(sess->rb);
17505 + /* copy the content to the next cq */
17506 + for (c = sess->rb->first; c; c = c->next) {
17507 + if (c->mem->used == 0) continue;
17509 + http_chunk_append_mem(srv, sess->remote_con, c->mem->ptr + c->offset, c->mem->used - c->offset);
17511 + c->offset = c->mem->used - 1;
17514 + chunkqueue_remove_finished_chunks(sess->rb);
17516 + if (sess->remote_con->file_finished) {
17517 + /* send final HTTP-Chunk packet */
17518 + http_chunk_append_mem(srv, sess->remote_con, NULL, 0);
17523 + ERROR("%s", "oops, we failed to read");
17527 + joblist_append(srv, sess->remote_con);
17530 + TRACE("unexpected state for a FDEVENT_IN: %d", sess->state);
17536 if (revents & FDEVENT_OUT) {
17537 /* nothing to do */
17541 /* perhaps this issue is already handled */
17542 if (revents & FDEVENT_HUP) {
17543 - /* check if we still have a unfinished header package which is a body in reality */
17544 - if (con->file_started == 0 &&
17545 - hctx->response_header->used) {
17546 - con->file_started = 1;
17547 - http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used);
17548 - joblist_append(srv, con);
17551 - if (con->file_finished == 0) {
17552 - http_chunk_append_mem(srv, con, NULL, 0);
17553 - joblist_append(srv, con);
17556 con->file_finished = 1;
17558 - if (chunkqueue_is_empty(con->write_queue)) {
17559 - /* there is nothing left to write */
17560 - connection_set_state(srv, con, CON_STATE_RESPONSE_END);
17562 - /* used the write-handler to finish the request on demand */
17567 - log_error_write(srv, __FILE__, __LINE__, "sddd", "got HUP from cgi", con->fd, hctx->fd, revents);
17570 - /* rtsigs didn't liked the close */
17571 - cgi_connection_close(srv, hctx);
17573 + fdevent_event_del(srv->ev, sess->sock);
17575 + /* someone has to close this socket now :) */
17576 + http_chunk_append_mem(srv, sess->remote_con, NULL, 0);
17577 + joblist_append(srv, sess->remote_con);
17578 } else if (revents & FDEVENT_ERR) {
17579 con->file_finished = 1;
17582 /* kill all connections to the cgi process */
17583 - cgi_connection_close(srv, hctx);
17585 - log_error_write(srv, __FILE__, __LINE__, "s", "cgi-FDEVENT_ERR");
17587 - return HANDLER_ERROR;
17588 + fdevent_event_del(srv->ev, sess->sock);
17592 return HANDLER_FINISHED;
17596 static int cgi_env_add(char_array *env, const char *key, size_t key_len, const char *val, size_t val_len) {
17600 if (!key || !val) return -1;
17603 dst = malloc(key_len + val_len + 3);
17604 memcpy(dst, key, key_len);
17605 dst[key_len] = '=';
17606 /* add the \0 from the value */
17607 memcpy(dst + key_len + 1, val, val_len + 1);
17610 if (env->size == 0) {
17612 env->ptr = malloc(env->size * sizeof(*env->ptr));
17613 @@ -678,45 +547,45 @@
17615 env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
17619 env->ptr[env->used++] = dst;
17625 static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer *cgi_handler) {
17630 char b2[INET6_ADDRSTRLEN + 1];
17635 int from_cgi_fds[2];
17643 if (cgi_handler->used > 1) {
17644 /* stat the exec file */
17645 if (-1 == (stat(cgi_handler->ptr, &st))) {
17646 - log_error_write(srv, __FILE__, __LINE__, "sbss",
17647 + log_error_write(srv, __FILE__, __LINE__, "sbss",
17648 "stat for cgi-handler", cgi_handler,
17649 "failed:", strerror(errno));
17655 if (pipe(to_cgi_fds)) {
17656 log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed:", strerror(errno));
17661 if (pipe(from_cgi_fds)) {
17662 log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed:", strerror(errno));
17668 switch (pid = fork()) {
17670 @@ -730,44 +599,40 @@
17673 server_socket *srv_sock = con->srv_socket;
17676 /* move stdout to from_cgi_fd[1] */
17677 close(STDOUT_FILENO);
17678 dup2(from_cgi_fds[1], STDOUT_FILENO);
17679 close(from_cgi_fds[1]);
17681 close(from_cgi_fds[0]);
17684 /* move the stdin to to_cgi_fd[0] */
17685 close(STDIN_FILENO);
17686 dup2(to_cgi_fds[0], STDIN_FILENO);
17687 close(to_cgi_fds[0]);
17689 close(to_cgi_fds[1]);
17692 - * this is not nice, but it works
17694 - * we feed the stderr of the CGI to our errorlog, if possible
17697 + * FIXME: add a event-handler for STDERR_FILENO and let it LOG()
17699 - if (srv->errorlog_mode == ERRORLOG_FILE) {
17700 - close(STDERR_FILENO);
17701 - dup2(srv->errorlog_fd, STDERR_FILENO);
17705 + close(STDERR_FILENO);
17707 /* create environment */
17713 cgi_env_add(&env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION));
17715 if (!buffer_is_empty(con->server_name)) {
17716 cgi_env_add(&env, CONST_STR_LEN("SERVER_NAME"), CONST_BUF_LEN(con->server_name));
17719 - s = inet_ntop(srv_sock->addr.plain.sa_family,
17720 - srv_sock->addr.plain.sa_family == AF_INET6 ?
17721 + s = inet_ntop(srv_sock->addr.plain.sa_family,
17722 + srv_sock->addr.plain.sa_family == AF_INET6 ?
17723 (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
17724 (const void *) &(srv_sock->addr.ipv4.sin_addr),
17726 @@ -779,10 +644,10 @@
17727 cgi_env_add(&env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1"));
17729 s = get_http_version_name(con->request.http_version);
17732 cgi_env_add(&env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s));
17738 ntohs(srv_sock->addr.plain.sa_family == AF_INET6 ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
17740 @@ -790,10 +655,10 @@
17743 cgi_env_add(&env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf));
17747 - s = inet_ntop(srv_sock->addr.plain.sa_family,
17748 - srv_sock->addr.plain.sa_family == AF_INET6 ?
17749 + s = inet_ntop(srv_sock->addr.plain.sa_family,
17750 + srv_sock->addr.plain.sa_family == AF_INET6 ?
17751 (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
17752 (const void *) &(srv_sock->addr.ipv4.sin_addr),
17754 @@ -811,15 +676,18 @@
17755 cgi_env_add(&env, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200"));
17756 if (!buffer_is_empty(con->uri.query)) {
17757 cgi_env_add(&env, CONST_STR_LEN("QUERY_STRING"), CONST_BUF_LEN(con->uri.query));
17759 + /* set a empty QUERY_STRING */
17760 + cgi_env_add(&env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN(""));
17762 if (!buffer_is_empty(con->request.orig_uri)) {
17763 cgi_env_add(&env, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri));
17770 - s = inet_ntop(con->dst_addr.plain.sa_family,
17771 - con->dst_addr.plain.sa_family == AF_INET6 ?
17772 + s = inet_ntop(con->dst_addr.plain.sa_family,
17773 + con->dst_addr.plain.sa_family == AF_INET6 ?
17774 (const void *) &(con->dst_addr.ipv6.sin6_addr) :
17775 (const void *) &(con->dst_addr.ipv4.sin_addr),
17777 @@ -828,7 +696,7 @@
17779 cgi_env_add(&env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s));
17784 ntohs(con->dst_addr.plain.sa_family == AF_INET6 ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
17786 @@ -836,19 +704,19 @@
17789 cgi_env_add(&env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf));
17792 if (!buffer_is_empty(con->authed_user)) {
17793 cgi_env_add(&env, CONST_STR_LEN("REMOTE_USER"),
17794 CONST_BUF_LEN(con->authed_user));
17798 /* request.content_length < SSIZE_MAX, see request.c */
17799 ltostr(buf, con->request.content_length);
17800 cgi_env_add(&env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf));
17801 cgi_env_add(&env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(con->physical.path));
17802 cgi_env_add(&env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
17803 cgi_env_add(&env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root));
17807 if (NULL != (s = getenv("LD_PRELOAD"))) {
17808 cgi_env_add(&env, CONST_STR_LEN("LD_PRELOAD"), s, strlen(s));
17809 @@ -863,24 +731,24 @@
17810 cgi_env_add(&env, CONST_STR_LEN("SYSTEMROOT"), s, strlen(s));
17815 for (n = 0; n < con->request.headers->used; n++) {
17819 ds = (data_string *)con->request.headers->data[n];
17822 if (ds->value->used && ds->key->used) {
17826 buffer_reset(p->tmp_buf);
17829 if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
17830 buffer_copy_string(p->tmp_buf, "HTTP_");
17831 p->tmp_buf->used--; /* strip \0 after HTTP_ */
17835 buffer_prepare_append(p->tmp_buf, ds->key->used + 2);
17838 for (j = 0; j < ds->key->used - 1; j++) {
17840 if (light_isalpha(ds->key->ptr[j])) {
17841 @@ -893,46 +761,46 @@
17842 p->tmp_buf->ptr[p->tmp_buf->used++] = cr;
17844 p->tmp_buf->ptr[p->tmp_buf->used++] = '\0';
17847 cgi_env_add(&env, CONST_BUF_LEN(p->tmp_buf), CONST_BUF_LEN(ds->value));
17852 for (n = 0; n < con->environment->used; n++) {
17856 ds = (data_string *)con->environment->data[n];
17859 if (ds->value->used && ds->key->used) {
17863 buffer_reset(p->tmp_buf);
17866 buffer_prepare_append(p->tmp_buf, ds->key->used + 2);
17869 for (j = 0; j < ds->key->used - 1; j++) {
17870 - p->tmp_buf->ptr[p->tmp_buf->used++] =
17871 - isalpha((unsigned char)ds->key->ptr[j]) ?
17872 + p->tmp_buf->ptr[p->tmp_buf->used++] =
17873 + isalpha((unsigned char)ds->key->ptr[j]) ?
17874 toupper((unsigned char)ds->key->ptr[j]) : '_';
17876 p->tmp_buf->ptr[p->tmp_buf->used++] = '\0';
17879 cgi_env_add(&env, CONST_BUF_LEN(p->tmp_buf), CONST_BUF_LEN(ds->value));
17884 if (env.size == env.used) {
17886 env.ptr = realloc(env.ptr, env.size * sizeof(*env.ptr));
17890 env.ptr[env.used] = NULL;
17895 args = malloc(sizeof(*args) * argc);
17899 if (cgi_handler->used > 1) {
17900 args[i++] = cgi_handler->ptr;
17902 @@ -942,7 +810,7 @@
17903 /* search for the last / */
17904 if (NULL != (c = strrchr(con->physical.path->ptr, '/'))) {
17908 /* change to the physical directory */
17909 if (-1 == chdir(con->physical.path->ptr)) {
17910 log_error_write(srv, __FILE__, __LINE__, "ssb", "chdir failed:", strerror(errno), con->physical.path);
17911 @@ -952,14 +820,14 @@
17913 /* we don't need the client socket */
17914 for (i = 3; i < 256; i++) {
17915 - if (i != srv->errorlog_fd) close(i);
17921 execve(args[0], args, env.ptr);
17924 log_error_write(srv, __FILE__, __LINE__, "sss", "CGI failed:", strerror(errno), args[0]);
17930 @@ -969,16 +837,16 @@
17931 log_error_write(srv, __FILE__, __LINE__, "ss", "fork failed:", strerror(errno));
17934 - handler_ctx *hctx;
17935 + cgi_session *sess;
17938 close(from_cgi_fds[1]);
17939 close(to_cgi_fds[0]);
17942 if (con->request.content_length) {
17943 chunkqueue *cq = con->request_content_queue;
17947 assert(chunkqueue_length(cq) == (off_t)con->request.content_length);
17949 /* there is content to send */
17950 @@ -993,16 +861,16 @@
17951 if (-1 == c->file.fd && /* open the file if not already open */
17952 -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
17953 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
17956 close(from_cgi_fds[0]);
17957 close(to_cgi_fds[1]);
17961 c->file.mmap.length = c->file.length;
17964 if (MAP_FAILED == (c->file.mmap.start = mmap(0, c->file.mmap.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
17965 - log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
17966 + log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
17967 strerror(errno), c->file.name, c->file.fd);
17969 close(from_cgi_fds[0]);
17970 @@ -1012,7 +880,7 @@
17976 /* chunk_reset() or chunk_free() will cleanup for us */
17979 @@ -1020,7 +888,7 @@
17982 con->http_status = 507;
17987 con->http_status = 403;
17988 @@ -1033,7 +901,7 @@
17991 con->http_status = 507;
17996 con->http_status = 403;
17997 @@ -1056,103 +924,95 @@
18000 close(to_cgi_fds[1]);
18003 /* register PID and wait for them asyncronously */
18005 buffer_reset(con->physical.path);
18007 - hctx = cgi_handler_ctx_init();
18009 - hctx->remote_conn = con;
18010 - hctx->plugin_data = p;
18012 - hctx->fd = from_cgi_fds[0];
18013 - hctx->fde_ndx = -1;
18015 - con->plugin_ctx[p->id] = hctx;
18017 - fdevent_register(srv->ev, hctx->fd, cgi_handle_fdevent, hctx);
18018 - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
18020 - if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
18022 + sess = cgi_session_init();
18024 + sess->remote_con = con;
18027 + assert(sess->sock);
18029 + sess->sock->fd = from_cgi_fds[0];
18030 + sess->sock->type = IOSOCKET_TYPE_PIPE;
18032 + if (-1 == fdevent_fcntl_set(srv->ev, sess->sock)) {
18033 log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
18035 - fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
18036 - fdevent_unregister(srv->ev, hctx->fd);
18038 - log_error_write(srv, __FILE__, __LINE__, "sd", "cgi close:", hctx->fd);
18042 - cgi_handler_ctx_free(hctx);
18044 - con->plugin_ctx[p->id] = NULL;
18047 + cgi_session_free(sess);
18053 + con->plugin_ctx[p->id] = sess;
18055 + fdevent_register(srv->ev, sess->sock, cgi_handle_fdevent, sess);
18056 + fdevent_event_add(srv->ev, sess->sock, FDEVENT_IN);
18058 + sess->state = CGI_STATE_READ_RESPONSE_HEADER;
18071 -#define PATCH(x) \
18072 - p->conf.x = s->x;
18073 static int mod_cgi_patch_connection(server *srv, connection *con, plugin_data *p) {
18075 plugin_config *s = p->config_storage[0];
18080 + PATCH_OPTION(cgi);
18082 /* skip the first, the global context */
18083 for (i = 1; i < srv->config_context->used; i++) {
18084 data_config *dc = (data_config *)srv->config_context->data[i];
18085 s = p->config_storage[i];
18088 /* condition didn't match */
18089 if (!config_check_cond(srv, con, dc)) continue;
18093 for (j = 0; j < dc->value->used; j++) {
18094 data_unset *du = dc->value->data[j];
18097 if (buffer_is_equal_string(du->key, CONST_STR_LEN("cgi.assign"))) {
18099 + PATCH_OPTION(cgi);
18109 URIHANDLER_FUNC(cgi_is_handled) {
18111 plugin_data *p = p_d;
18112 buffer *fn = con->physical.path;
18115 if (fn->used == 0) return HANDLER_GO_ON;
18118 mod_cgi_patch_connection(srv, con, p);
18121 s_len = fn->used - 1;
18124 for (k = 0; k < p->conf.cgi->used; k++) {
18125 data_string *ds = (data_string *)p->conf.cgi->data[k];
18126 size_t ct_len = ds->key->used - 1;
18129 if (ds->key->used == 0) continue;
18130 if (s_len < ct_len) continue;
18133 if (0 == strncmp(fn->ptr + s_len - ct_len, ds->key->ptr, ct_len)) {
18134 if (cgi_create_env(srv, con, p, ds->value)) {
18135 con->http_status = 500;
18138 buffer_reset(con->physical.path);
18139 return HANDLER_FINISHED;
18141 @@ -1160,7 +1020,7 @@
18147 return HANDLER_GO_ON;
18150 @@ -1168,11 +1028,11 @@
18151 plugin_data *p = p_d;
18153 /* the trigger handle only cares about lonely PID which we have to wait for */
18157 for (ndx = 0; ndx < p->cgi_pid.used; ndx++) {
18161 switch(waitpid(p->cgi_pid.ptr[ndx], &status, WNOHANG)) {
18163 /* not finished yet */
18164 @@ -1182,7 +1042,7 @@
18167 log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno));
18170 return HANDLER_ERROR;
18173 @@ -1193,96 +1053,105 @@
18175 log_error_write(srv, __FILE__, __LINE__, "s", "cgi died ?");
18179 cgi_pid_del(srv, p, p->cgi_pid.ptr[ndx]);
18180 - /* del modified the buffer structure
18181 + /* del modified the buffer structure
18182 * and copies the last entry to the current one
18183 * -> recheck the current index
18190 return HANDLER_GO_ON;
18193 SUBREQUEST_FUNC(mod_cgi_handle_subrequest) {
18195 plugin_data *p = p_d;
18196 - handler_ctx *hctx = con->plugin_ctx[p->id];
18198 + cgi_session *sess = con->plugin_ctx[p->id];
18200 if (con->mode != p->id) return HANDLER_GO_ON;
18201 - if (NULL == hctx) return HANDLER_GO_ON;
18203 + if (NULL == sess) return HANDLER_GO_ON;
18205 + switch (cgi_demux_response(srv, con, p)) {
18209 + cgi_connection_close(srv, con, p);
18211 + /* if we get a IN|HUP and have read everything don't exec the close twice */
18212 + return HANDLER_FINISHED;
18214 + cgi_connection_close(srv, con, p);
18216 + if (0 == con->http_status) con->http_status = 500;
18217 + connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
18218 + con->mode = DIRECT;
18220 + return HANDLER_FINISHED;
18224 - log_error_write(srv, __FILE__, __LINE__, "sdd", "subrequest, pid =", hctx, hctx->pid);
18226 - if (hctx->pid == 0) return HANDLER_FINISHED;
18228 - switch(waitpid(hctx->pid, &status, WNOHANG)) {
18229 + log_error_write(srv, __FILE__, __LINE__, "sdd", "subrequest, pid =", sess, sess->pid);
18231 + if (sess->pid == 0) return HANDLER_FINISHED;
18233 + switch(waitpid(sess->pid, &status, WNOHANG)) {
18235 /* we only have for events here if we don't have the header yet,
18236 * otherwise the event-handler will send us the incoming data */
18237 - if (con->file_started) return HANDLER_FINISHED;
18239 - return HANDLER_WAIT_FOR_EVENT;
18240 + if (!con->file_started) return HANDLER_WAIT_FOR_EVENT;
18241 + if (con->file_finished) return HANDLER_FINISHED;
18243 + return HANDLER_GO_ON;
18245 if (errno == EINTR) return HANDLER_WAIT_FOR_EVENT;
18248 if (errno == ECHILD && con->file_started == 0) {
18250 - * second round but still not response
18251 + * second round but still not response
18253 - return HANDLER_WAIT_FOR_EVENT;
18254 + return HANDLER_WAIT_FOR_EVENT;
18258 log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno));
18259 con->mode = DIRECT;
18260 con->http_status = 500;
18264 - fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
18265 - fdevent_unregister(srv->ev, hctx->fd);
18267 - if (close(hctx->fd)) {
18268 - log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno));
18271 - cgi_handler_ctx_free(hctx);
18276 + fdevent_event_del(srv->ev, sess->sock);
18277 + fdevent_unregister(srv->ev, sess->sock);
18279 + cgi_session_free(sess);
18282 con->plugin_ctx[p->id] = NULL;
18285 return HANDLER_FINISHED;
18287 - /* cgi process exited cleanly
18289 - * check if we already got the response
18292 - if (!con->file_started) return HANDLER_WAIT_FOR_EVENT;
18294 + con->file_finished = 1;
18296 if (WIFEXITED(status)) {
18299 log_error_write(srv, __FILE__, __LINE__, "s", "cgi died ?");
18302 con->mode = DIRECT;
18303 con->http_status = 500;
18310 - fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
18311 - fdevent_unregister(srv->ev, hctx->fd);
18313 - if (close(hctx->fd)) {
18314 - log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno));
18317 - cgi_handler_ctx_free(hctx);
18322 + fdevent_event_del(srv->ev, sess->sock);
18323 + fdevent_unregister(srv->ev, sess->sock);
18325 + cgi_session_free(sess);
18328 con->plugin_ctx[p->id] = NULL;
18329 return HANDLER_FINISHED;
18331 @@ -1306,8 +1175,8 @@
18332 p->init = mod_cgi_init;
18333 p->cleanup = mod_cgi_free;
18334 p->set_defaults = mod_fastcgi_set_defaults;
18342 --- ../lighttpd-1.4.11/src/mod_cml.c 2006-01-30 13:51:48.000000000 +0200
18343 +++ lighttpd-1.4.12/src/mod_cml.c 2006-07-16 00:26:03.000000000 +0300
18345 #include <stdlib.h>
18346 #include <string.h>
18348 -#include <unistd.h>
18351 #include "buffer.h"
18352 @@ -20,50 +19,50 @@
18353 /* init the plugin data */
18354 INIT_FUNC(mod_cml_init) {
18358 p = calloc(1, sizeof(*p));
18361 p->basedir = buffer_init();
18362 p->baseurl = buffer_init();
18363 p->trigger_handler = buffer_init();
18369 /* detroy the plugin data */
18370 FREE_FUNC(mod_cml_free) {
18371 plugin_data *p = p_d;
18376 if (!p) return HANDLER_GO_ON;
18379 if (p->config_storage) {
18381 for (i = 0; i < srv->config_context->used; i++) {
18382 plugin_config *s = p->config_storage[i];
18385 buffer_free(s->ext);
18388 buffer_free(s->mc_namespace);
18389 buffer_free(s->power_magnet);
18390 array_free(s->mc_hosts);
18393 #if defined(HAVE_MEMCACHE_H)
18394 if (s->mc) mc_free(s->mc);
18400 free(p->config_storage);
18404 buffer_free(p->trigger_handler);
18405 buffer_free(p->basedir);
18406 buffer_free(p->baseurl);
18412 return HANDLER_GO_ON;
18415 @@ -72,22 +71,22 @@
18416 SETDEFAULTS_FUNC(mod_cml_set_defaults) {
18417 plugin_data *p = p_d;
18420 - config_values_t cv[] = {
18422 + config_values_t cv[] = {
18423 { "cml.extension", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
18424 { "cml.memcache-hosts", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
18425 { "cml.memcache-namespace", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
18426 { "cml.power-magnet", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
18427 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
18431 if (!p) return HANDLER_ERROR;
18434 p->config_storage = malloc(srv->config_context->used * sizeof(specific_config *));
18437 for (i = 0; i < srv->config_context->used; i++) {
18441 s = malloc(sizeof(plugin_config));
18442 s->ext = buffer_init();
18443 s->mc_hosts = array_init();
18444 @@ -96,87 +95,84 @@
18445 #if defined(HAVE_MEMCACHE_H)
18450 cv[0].destination = s->ext;
18451 cv[1].destination = s->mc_hosts;
18452 cv[2].destination = s->mc_namespace;
18453 cv[3].destination = s->power_magnet;
18456 p->config_storage[i] = s;
18459 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
18460 return HANDLER_ERROR;
18464 if (s->mc_hosts->used) {
18465 #if defined(HAVE_MEMCACHE_H)
18470 for (k = 0; k < s->mc_hosts->used; k++) {
18471 data_string *ds = (data_string *)s->mc_hosts->data[k];
18474 if (0 != mc_server_add4(s->mc, ds->value->ptr)) {
18475 - log_error_write(srv, __FILE__, __LINE__, "sb",
18476 - "connection to host failed:",
18477 + log_error_write(srv, __FILE__, __LINE__, "sb",
18478 + "connection to host failed:",
18482 return HANDLER_ERROR;
18486 - log_error_write(srv, __FILE__, __LINE__, "s",
18487 + log_error_write(srv, __FILE__, __LINE__, "s",
18488 "memcache support is not compiled in but cml.memcache-hosts is set, aborting");
18489 return HANDLER_ERROR;
18495 return HANDLER_GO_ON;
18498 -#define PATCH(x) \
18499 - p->conf.x = s->x;
18500 static int mod_cml_patch_connection(server *srv, connection *con, plugin_data *p) {
18502 plugin_config *s = p->config_storage[0];
18506 + PATCH_OPTION(ext);
18507 #if defined(HAVE_MEMCACHE_H)
18509 + PATCH_OPTION(mc);
18511 - PATCH(mc_namespace);
18512 - PATCH(power_magnet);
18514 + PATCH_OPTION(mc_namespace);
18515 + PATCH_OPTION(power_magnet);
18517 /* skip the first, the global context */
18518 for (i = 1; i < srv->config_context->used; i++) {
18519 data_config *dc = (data_config *)srv->config_context->data[i];
18520 s = p->config_storage[i];
18523 /* condition didn't match */
18524 if (!config_check_cond(srv, con, dc)) continue;
18528 for (j = 0; j < dc->value->used; j++) {
18529 data_unset *du = dc->value->data[j];
18532 if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.extension"))) {
18534 + PATCH_OPTION(ext);
18535 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.memcache-hosts"))) {
18536 #if defined(HAVE_MEMCACHE_H)
18538 + PATCH_OPTION(mc);
18540 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.memcache-namespace"))) {
18541 - PATCH(mc_namespace);
18542 + PATCH_OPTION(mc_namespace);
18543 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.power-magnet"))) {
18544 - PATCH(power_magnet);
18545 + PATCH_OPTION(power_magnet);
18555 int cache_call_lua(server *srv, connection *con, plugin_data *p, buffer *cml_file) {
18557 @@ -187,57 +183,57 @@
18559 buffer_copy_string_buffer(b, con->uri.path);
18560 for (c = b->ptr + b->used - 1; c > b->ptr && *c != '/'; c--);
18564 b->used = c - b->ptr + 2;
18570 buffer_copy_string_buffer(b, con->physical.path);
18571 for (c = b->ptr + b->used - 1; c > b->ptr && *c != '/'; c--);
18575 b->used = c - b->ptr + 2;
18581 /* prepare variables
18583 * - get-param-based
18587 return cache_parse_lua(srv, con, p, cml_file);
18592 URIHANDLER_FUNC(mod_cml_power_magnet) {
18593 plugin_data *p = p_d;
18596 mod_cml_patch_connection(srv, con, p);
18599 buffer_reset(p->basedir);
18600 buffer_reset(p->baseurl);
18601 buffer_reset(p->trigger_handler);
18603 if (buffer_is_empty(p->conf.power_magnet)) return HANDLER_GO_ON;
18609 * cml.power-magnet = server.docroot + "/rewrite.cml"
18611 * is called on EACH request, take the original REQUEST_URI and modifies the
18612 - * request header as neccesary.
18613 + * request header as neccesary.
18616 * if file_exists("/maintainance.html") {
18617 * output_include = ( "/maintainance.html" )
18618 - * return CACHE_HIT
18619 + * return CACHE_HIT
18622 * as we only want to rewrite HTML like requests we should cover it in a conditional
18627 switch(cache_call_lua(srv, con, p, p->conf.power_magnet)) {
18628 @@ -266,20 +262,20 @@
18630 URIHANDLER_FUNC(mod_cml_is_handled) {
18631 plugin_data *p = p_d;
18634 if (buffer_is_empty(con->physical.path)) return HANDLER_ERROR;
18637 mod_cml_patch_connection(srv, con, p);
18640 buffer_reset(p->basedir);
18641 buffer_reset(p->baseurl);
18642 buffer_reset(p->trigger_handler);
18644 if (buffer_is_empty(p->conf.ext)) return HANDLER_GO_ON;
18647 if (!buffer_is_equal_right_len(con->physical.path, p->conf.ext, p->conf.ext->used - 1)) {
18648 return HANDLER_GO_ON;
18652 switch(cache_call_lua(srv, con, p, con->physical.path)) {
18654 @@ -311,15 +307,15 @@
18655 int mod_cml_plugin_init(plugin *p) {
18656 p->version = LIGHTTPD_VERSION_ID;
18657 p->name = buffer_init_string("cache");
18660 p->init = mod_cml_init;
18661 p->cleanup = mod_cml_free;
18662 p->set_defaults = mod_cml_set_defaults;
18665 p->handle_subrequest_start = mod_cml_is_handled;
18666 p->handle_physical = mod_cml_power_magnet;
18674 --- ../lighttpd-1.4.11/src/mod_cml.h 2006-01-30 13:51:35.000000000 +0200
18675 +++ lighttpd-1.4.12/src/mod_cml.h 2006-07-16 00:26:03.000000000 +0300
18676 @@ -16,10 +16,10 @@
18683 buffer *mc_namespace;
18684 -#if defined(HAVE_MEMCACHE_H)
18685 +#if defined(HAVE_MEMCACHE_H)
18686 struct memcache *mc;
18688 buffer *power_magnet;
18689 @@ -27,15 +27,15 @@
18699 buffer *trigger_handler;
18702 plugin_config **config_storage;
18704 - plugin_config conf;
18706 + plugin_config conf;
18709 int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn);
18710 --- ../lighttpd-1.4.11/src/mod_cml_funcs.c 2005-11-17 16:15:08.000000000 +0200
18711 +++ lighttpd-1.4.12/src/mod_cml_funcs.c 2006-07-16 00:26:04.000000000 +0300
18713 #include <stdlib.h>
18714 #include <string.h>
18716 -#include <unistd.h>
18717 -#include <dirent.h>
18721 #include "buffer.h"
18724 #include "plugin.h"
18725 #include "response.h"
18726 +#include "sys-files.h"
18728 #include "mod_cml.h"
18729 #include "mod_cml_funcs.h"
18739 @@ -42,29 +42,29 @@
18742 int n = lua_gettop(L);
18747 b.size = sizeof(hex);
18751 lua_pushstring(L, "md5: expected one argument");
18756 if (!lua_isstring(L, 1)) {
18757 lua_pushstring(L, "md5: argument has to be a string");
18763 MD5_Update(&Md5Ctx, (unsigned char *)lua_tostring(L, 1), lua_strlen(L, 1));
18764 MD5_Final(HA1, &Md5Ctx);
18767 buffer_copy_string_hex(&b, (char *)HA1, 16);
18770 lua_pushstring(L, b.ptr);
18776 @@ -72,37 +72,37 @@
18777 int f_file_mtime(lua_State *L) {
18779 int n = lua_gettop(L);
18783 lua_pushstring(L, "file_mtime: expected one argument");
18788 if (!lua_isstring(L, 1)) {
18789 lua_pushstring(L, "file_mtime: argument has to be a string");
18794 if (-1 == stat(lua_tostring(L, 1), &st)) {
18800 lua_pushnumber(L, st.st_mtime);
18807 int f_dir_files_iter(lua_State *L) {
18812 d = lua_touserdata(L, lua_upvalueindex(1));
18815 if (NULL == (de = readdir(d))) {
18822 lua_pushstring(L, de->d_name);
18823 @@ -113,75 +113,75 @@
18824 int f_dir_files(lua_State *L) {
18826 int n = lua_gettop(L);
18830 lua_pushstring(L, "dir_files: expected one argument");
18835 if (!lua_isstring(L, 1)) {
18836 lua_pushstring(L, "dir_files: argument has to be a string");
18840 - /* check if there is a valid DIR handle on the stack */
18842 + /* check if there is a valid DIR handle on the stack */
18843 if (NULL == (d = opendir(lua_tostring(L, 1)))) {
18849 /* push d into registry */
18850 lua_pushlightuserdata(L, d);
18851 lua_pushcclosure(L, f_dir_files_iter, 1);
18858 int f_file_isreg(lua_State *L) {
18860 int n = lua_gettop(L);
18864 lua_pushstring(L, "file_isreg: expected one argument");
18869 if (!lua_isstring(L, 1)) {
18870 lua_pushstring(L, "file_isreg: argument has to be a string");
18875 if (-1 == stat(lua_tostring(L, 1), &st)) {
18881 lua_pushnumber(L, S_ISREG(st.st_mode));
18887 int f_file_isdir(lua_State *L) {
18889 int n = lua_gettop(L);
18893 lua_pushstring(L, "file_isreg: expected one argument");
18898 if (!lua_isstring(L, 1)) {
18899 lua_pushstring(L, "file_isreg: argument has to be a string");
18904 if (-1 == stat(lua_tostring(L, 1), &st)) {
18910 lua_pushnumber(L, S_ISDIR(st.st_mode));
18916 @@ -192,33 +192,33 @@
18918 int n = lua_gettop(L);
18919 struct memcache *mc;
18922 if (!lua_islightuserdata(L, lua_upvalueindex(1))) {
18923 lua_pushstring(L, "where is my userdata ?");
18928 mc = lua_touserdata(L, lua_upvalueindex(1));
18932 lua_pushstring(L, "expected one argument");
18937 if (!lua_isstring(L, 1)) {
18938 lua_pushstring(L, "argument has to be a string");
18942 - if (NULL == (r = mc_aget(mc,
18944 + if (NULL == (r = mc_aget(mc,
18945 lua_tostring(L, 1), lua_strlen(L, 1)))) {
18948 lua_pushboolean(L, 0);
18956 lua_pushboolean(L, 1);
18959 @@ -226,74 +226,74 @@
18960 int f_memcache_get_string(lua_State *L) {
18962 int n = lua_gettop(L);
18965 struct memcache *mc;
18968 if (!lua_islightuserdata(L, lua_upvalueindex(1))) {
18969 lua_pushstring(L, "where is my userdata ?");
18974 mc = lua_touserdata(L, lua_upvalueindex(1));
18980 lua_pushstring(L, "expected one argument");
18985 if (!lua_isstring(L, 1)) {
18986 lua_pushstring(L, "argument has to be a string");
18990 - if (NULL == (r = mc_aget(mc,
18992 + if (NULL == (r = mc_aget(mc,
18993 lua_tostring(L, 1), lua_strlen(L, 1)))) {
18999 lua_pushstring(L, r);
19008 int f_memcache_get_long(lua_State *L) {
19010 int n = lua_gettop(L);
19013 struct memcache *mc;
19016 if (!lua_islightuserdata(L, lua_upvalueindex(1))) {
19017 lua_pushstring(L, "where is my userdata ?");
19022 mc = lua_touserdata(L, lua_upvalueindex(1));
19028 lua_pushstring(L, "expected one argument");
19033 if (!lua_isstring(L, 1)) {
19034 lua_pushstring(L, "argument has to be a string");
19038 - if (NULL == (r = mc_aget(mc,
19040 + if (NULL == (r = mc_aget(mc,
19041 lua_tostring(L, 1), lua_strlen(L, 1)))) {
19047 lua_pushnumber(L, strtol(r, NULL, 10));
19056 --- ../lighttpd-1.4.11/src/mod_cml_lua.c 2006-01-30 13:56:40.000000000 +0200
19057 +++ lighttpd-1.4.12/src/mod_cml_lua.c 2006-07-16 00:26:04.000000000 +0300
19070 #include <lualib.h>
19071 +#include <lauxlib.h>
19075 @@ -39,11 +40,11 @@
19077 static const char * load_file(lua_State *L, void *data, size_t *size) {
19084 if (rm->done) return 0;
19087 *size = rm->st.size;
19089 return rm->st.start;
19090 @@ -51,47 +52,47 @@
19092 static int lua_to_c_get_string(lua_State *L, const char *varname, buffer *b) {
19096 lua_pushstring(L, varname);
19099 curelem = lua_gettop(L);
19100 lua_gettable(L, LUA_GLOBALSINDEX);
19103 /* it should be a table */
19104 if (!lua_isstring(L, curelem)) {
19105 lua_settop(L, curelem - 1);
19112 buffer_copy_string(b, lua_tostring(L, curelem));
19118 assert(curelem - 1 == lua_gettop(L));
19124 static int lua_to_c_is_table(lua_State *L, const char *varname) {
19128 lua_pushstring(L, varname);
19131 curelem = lua_gettop(L);
19132 lua_gettable(L, LUA_GLOBALSINDEX);
19135 /* it should be a table */
19136 if (!lua_istable(L, curelem)) {
19137 lua_settop(L, curelem - 1);
19144 lua_settop(L, curelem - 1);
19147 assert(curelem - 1 == lua_gettop(L));
19154 lua_pushlstring(L, key, key_len);
19155 lua_pushlstring(L, val, val_len);
19156 lua_settable(L, tbl);
19162 @@ -108,21 +109,21 @@
19165 char *key = NULL, *val = NULL;
19171 /* we need the \0 */
19172 for (i = 0; i < qrystr->used; i++) {
19173 switch(qrystr->ptr[i]) {
19176 val = qrystr->ptr + i + 1;
19179 qrystr->ptr[i] = '\0';
19188 case '\0': /* fin symbol */
19189 @@ -131,19 +132,19 @@
19191 /* terminate the value */
19192 qrystr->ptr[i] = '\0';
19194 - c_to_lua_push(L, tbl,
19196 + c_to_lua_push(L, tbl,
19202 key = qrystr->ptr + i + 1;
19213 @@ -151,21 +152,21 @@
19219 if (NULL != (d = array_get_element(con->request.headers, "Cookie"))) {
19220 data_string *ds = (data_string *)d;
19221 size_t key = 0, value = 0;
19222 size_t is_key = 1, is_sid = 0;
19227 if (!DATA_IS_STRING(d)) return -1;
19228 if (ds->value->used == 0) return -1;
19231 if (ds->value->ptr[0] == '\0' ||
19232 ds->value->ptr[0] == '=' ||
19233 ds->value->ptr[0] == ';') return -1;
19236 buffer_reset(p->session_id);
19237 for (i = 0; i < ds->value->used; i++) {
19238 switch(ds->value->ptr[i]) {
19239 @@ -176,16 +177,16 @@
19252 buffer_copy_string_len(p->session_id, ds->value->ptr + value, i - value);
19259 @@ -204,48 +205,43 @@
19269 int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn) {
19274 buffer *b = buffer_init();
19275 int header_tbl = 0;
19279 stream_open(&rm.st, fn);
19282 /* push the lua file to the interpreter and see what happends */
19286 - luaopen_table(L);
19287 - luaopen_string(L);
19291 + L = luaL_newstate();
19292 + luaL_openlibs(L);
19294 /* register functions */
19295 lua_register(L, "md5", f_crypto_md5);
19296 lua_register(L, "file_mtime", f_file_mtime);
19297 lua_register(L, "file_isreg", f_file_isreg);
19298 lua_register(L, "file_isdir", f_file_isreg);
19299 lua_register(L, "dir_files", f_dir_files);
19302 #ifdef HAVE_MEMCACHE_H
19303 lua_pushliteral(L, "memcache_get_long");
19304 lua_pushlightuserdata(L, p->conf.mc);
19305 lua_pushcclosure(L, f_memcache_get_long, 1);
19306 lua_settable(L, LUA_GLOBALSINDEX);
19309 lua_pushliteral(L, "memcache_get_string");
19310 lua_pushlightuserdata(L, p->conf.mc);
19311 lua_pushcclosure(L, f_memcache_get_string, 1);
19312 lua_settable(L, LUA_GLOBALSINDEX);
19315 lua_pushliteral(L, "memcache_exists");
19316 lua_pushlightuserdata(L, p->conf.mc);
19317 lua_pushcclosure(L, f_memcache_exists, 1);
19318 @@ -255,11 +251,11 @@
19319 lua_pushliteral(L, "request");
19321 lua_settable(L, LUA_GLOBALSINDEX);
19324 lua_pushliteral(L, "request");
19325 header_tbl = lua_gettop(L);
19326 lua_gettable(L, LUA_GLOBALSINDEX);
19329 c_to_lua_push(L, header_tbl, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri));
19330 c_to_lua_push(L, header_tbl, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
19331 c_to_lua_push(L, header_tbl, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(con->physical.path));
19332 @@ -267,84 +263,84 @@
19333 if (!buffer_is_empty(con->request.pathinfo)) {
19334 c_to_lua_push(L, header_tbl, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo));
19338 c_to_lua_push(L, header_tbl, CONST_STR_LEN("CWD"), CONST_BUF_LEN(p->basedir));
19339 c_to_lua_push(L, header_tbl, CONST_STR_LEN("BASEURL"), CONST_BUF_LEN(p->baseurl));
19342 /* register GET parameter */
19343 lua_pushliteral(L, "get");
19345 lua_settable(L, LUA_GLOBALSINDEX);
19348 lua_pushliteral(L, "get");
19349 header_tbl = lua_gettop(L);
19350 lua_gettable(L, LUA_GLOBALSINDEX);
19353 buffer_copy_string_buffer(b, con->uri.query);
19354 cache_export_get_params(L, header_tbl, b);
19357 - /* 2 default constants */
19358 + /* 2 default constants */
19359 lua_pushliteral(L, "CACHE_HIT");
19360 lua_pushboolean(L, 0);
19361 lua_settable(L, LUA_GLOBALSINDEX);
19364 lua_pushliteral(L, "CACHE_MISS");
19365 lua_pushboolean(L, 1);
19366 lua_settable(L, LUA_GLOBALSINDEX);
19369 /* load lua program */
19370 if (lua_load(L, load_file, &rm, fn->ptr) || lua_pcall(L,0,1,0)) {
19371 log_error_write(srv, __FILE__, __LINE__, "s",
19372 lua_tostring(L,-1));
19379 /* get return value */
19380 ret = (int)lua_tonumber(L, -1);
19383 - /* fetch the data from lua */
19385 + /* fetch the data from lua */
19386 lua_to_c_get_string(L, "trigger_handler", p->trigger_handler);
19389 if (0 == lua_to_c_get_string(L, "output_contenttype", b)) {
19390 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(b));
19395 /* up to now it is a cache-hit, check if all files exist */
19402 if (!lua_to_c_is_table(L, "output_include")) {
19403 log_error_write(srv, __FILE__, __LINE__, "s",
19404 "output_include is missing or not a table");
19412 lua_pushstring(L, "output_include");
19415 curelem = lua_gettop(L);
19416 lua_gettable(L, LUA_GLOBALSINDEX);
19418 /* HOW-TO build a etag ?
19419 - * as we don't just have one file we have to take the stat()
19420 + * as we don't just have one file we have to take the stat()
19421 * from all base files, merge them and build the etag from
19425 * The mtime of the content is the mtime of the freshest base file
19431 lua_pushnil(L); /* first key */
19432 while (lua_next(L, curelem) != 0) {
19433 stat_cache_entry *sce = NULL;
19434 /* key' is at index -2 and value' at index -1 */
19437 if (lua_isstring(L, -1)) {
19438 const char *s = lua_tostring(L, -1);
19440 @@ -364,18 +360,18 @@
19441 /* a file is missing, call the handler to generate it */
19442 if (!buffer_is_empty(p->trigger_handler)) {
19443 ret = 1; /* cache-miss */
19446 log_error_write(srv, __FILE__, __LINE__, "s",
19447 "a file is missing, calling handler");
19452 /* handler not set -> 500 */
19456 log_error_write(srv, __FILE__, __LINE__, "s",
19457 "a file missing and no handler set");
19463 @@ -393,12 +389,12 @@
19469 lua_pop(L, 1); /* removes value'; keeps key' for next iteration */
19473 lua_settop(L, curelem - 1);
19478 char timebuf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
19479 @@ -410,9 +406,9 @@
19481 /* no Last-Modified specified */
19482 if ((mtime) && (NULL == ds)) {
19485 strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&mtime));
19488 response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), timebuf, sizeof(timebuf) - 1);
19491 @@ -428,9 +424,9 @@
19497 if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, &tbuf)) {
19498 - /* ok, the client already has our content,
19499 + /* ok, the client already has our content,
19500 * no need to send it again */
19502 chunkqueue_reset(con->write_queue);
19503 @@ -440,24 +436,24 @@
19504 chunkqueue_reset(con->write_queue);
19509 if (ret == 1 && !buffer_is_empty(p->trigger_handler)) {
19511 buffer_copy_string_buffer(con->uri.path, p->baseurl);
19512 buffer_append_string_buffer(con->uri.path, p->trigger_handler);
19515 buffer_copy_string_buffer(con->physical.path, p->basedir);
19516 buffer_append_string_buffer(con->physical.path, p->trigger_handler);
19519 chunkqueue_reset(con->write_queue);
19527 stream_close(&rm.st);
19531 return ret /* cache-error */;
19534 --- ../lighttpd-1.4.11/src/mod_compress.c 2005-11-18 13:49:14.000000000 +0200
19535 +++ lighttpd-1.4.12/src/mod_compress.c 2006-07-16 00:26:04.000000000 +0300
19537 #include <sys/stat.h>
19540 -#include <unistd.h>
19542 #include <stdlib.h>
19543 #include <string.h>
19545 #include "buffer.h"
19546 #include "response.h"
19547 #include "stat_cache.h"
19548 +#include "http_chunk.h"
19550 #include "plugin.h"
19555 #include "sys-mmap.h"
19556 +#include "sys-files.h"
19558 /* request: accept-encoding */
19559 #define HTTP_ACCEPT_ENCODING_IDENTITY BV(0)
19560 @@ -55,97 +56,127 @@
19566 plugin_config **config_storage;
19567 - plugin_config conf;
19568 + plugin_config conf;
19571 INIT_FUNC(mod_compress_init) {
19575 p = calloc(1, sizeof(*p));
19578 p->ofn = buffer_init();
19579 p->b = buffer_init();
19585 FREE_FUNC(mod_compress_free) {
19586 plugin_data *p = p_d;
19591 if (!p) return HANDLER_GO_ON;
19594 buffer_free(p->ofn);
19598 if (p->config_storage) {
19600 for (i = 0; i < srv->config_context->used; i++) {
19601 plugin_config *s = p->config_storage[i];
19606 array_free(s->compress);
19607 buffer_free(s->compress_cache_dir);
19612 free(p->config_storage);
19621 return HANDLER_GO_ON;
19624 +void mkdir_recursive(const char *dir) {
19626 + char dir_copy[256];
19627 + char *p = dir_copy;
19629 + if (!dir || !dir[0])
19632 + strncpy(dir_copy, dir, sizeof(dir_copy) / sizeof(dir_copy[0]));
19634 + while ((p = strchr(p + 1, '/')) != NULL) {
19637 + if ((mkdir(dir_copy, 0700) != 0) && (errno != EEXIST))
19643 + mkdir(dir, 0700);
19646 SETDEFAULTS_FUNC(mod_compress_setdefaults) {
19647 plugin_data *p = p_d;
19650 - config_values_t cv[] = {
19652 + config_values_t cv[] = {
19653 { "compress.cache-dir", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
19654 { "compress.filetype", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },
19655 { "compress.max-filesize", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
19656 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
19660 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
19663 for (i = 0; i < srv->config_context->used; i++) {
19667 s = calloc(1, sizeof(plugin_config));
19668 s->compress_cache_dir = buffer_init();
19669 s->compress = array_init();
19670 s->compress_max_filesize = 0;
19673 cv[0].destination = s->compress_cache_dir;
19674 cv[1].destination = s->compress;
19675 cv[2].destination = &(s->compress_max_filesize);
19678 p->config_storage[i] = s;
19681 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
19682 return HANDLER_ERROR;
19686 if (!buffer_is_empty(s->compress_cache_dir)) {
19688 if (0 != stat(s->compress_cache_dir->ptr, &st)) {
19689 - log_error_write(srv, __FILE__, __LINE__, "sbs", "can't stat compress.cache-dir",
19691 + log_error_write(srv, __FILE__, __LINE__, "sbs", "can't stat compress.cache-dir, attempting to create",
19692 s->compress_cache_dir, strerror(errno));
19694 - return HANDLER_ERROR;
19695 + mkdir_recursive(s->compress_cache_dir->ptr);
19697 + if (0 != stat(s->compress_cache_dir->ptr, &st)) {
19699 + log_error_write(srv, __FILE__, __LINE__, "sbs", "can't stat compress.cache-dir, create failed",
19700 + s->compress_cache_dir, strerror(errno));
19702 + return HANDLER_ERROR;
19709 return HANDLER_GO_ON;
19715 @@ -153,32 +184,32 @@
19728 - if (Z_OK != deflateInit2(&z,
19730 + if (Z_OK != deflateInit2(&z,
19731 Z_DEFAULT_COMPRESSION,
19734 -MAX_WBITS, /* supress zlib-header */
19736 Z_DEFAULT_STRATEGY)) {
19741 z.next_in = (unsigned char *)start;
19742 z.avail_in = st_size;
19748 buffer_prepare_copy(p->b, (z.avail_in * 1.1) + 12 + 18);
19751 /* write gzip header */
19754 c = (unsigned char *)p->b->ptr;
19757 @@ -190,24 +221,24 @@
19758 c[7] = (mtime >> 24) & 0xff;
19759 c[8] = 0x00; /* extra flags */
19760 c[9] = 0x03; /* UNIX */
19764 z.next_out = (unsigned char *)p->b->ptr + p->b->used;
19765 z.avail_out = p->b->size - p->b->used - 8;
19769 if (Z_STREAM_END != deflate(&z, Z_FINISH)) {
19776 p->b->used += z.total_out;
19779 crc = generate_crc32c(start, st_size);
19782 c = (unsigned char *)p->b->ptr + p->b->used;
19785 c[0] = (crc >> 0) & 0xff;
19786 c[1] = (crc >> 8) & 0xff;
19787 c[2] = (crc >> 16) & 0xff;
19788 @@ -221,51 +252,51 @@
19789 if (Z_OK != deflateEnd(&z)) {
19797 static int deflate_file_to_buffer_deflate(server *srv, connection *con, plugin_data *p, unsigned char *start, off_t st_size) {
19808 - if (Z_OK != deflateInit2(&z,
19810 + if (Z_OK != deflateInit2(&z,
19811 Z_DEFAULT_COMPRESSION,
19814 -MAX_WBITS, /* supress zlib-header */
19816 Z_DEFAULT_STRATEGY)) {
19822 z.avail_in = st_size;
19826 buffer_prepare_copy(p->b, (z.avail_in * 1.1) + 12);
19829 z.next_out = (unsigned char *)p->b->ptr;
19830 z.avail_out = p->b->size;
19834 if (Z_STREAM_END != deflate(&z, Z_FINISH)) {
19841 p->b->used += z.total_out;
19844 if (Z_OK != deflateEnd(&z)) {
19852 @@ -274,48 +305,48 @@
19854 static int deflate_file_to_buffer_bzip2(server *srv, connection *con, plugin_data *p, unsigned char *start, off_t st_size) {
19865 - if (BZ_OK != BZ2_bzCompressInit(&bz,
19867 + if (BZ_OK != BZ2_bzCompressInit(&bz,
19868 9, /* blocksize = 900k */
19870 0)) { /* workFactor: default */
19875 bz.next_in = (char *)start;
19876 bz.avail_in = st_size;
19877 bz.total_in_lo32 = 0;
19878 bz.total_in_hi32 = 0;
19881 buffer_prepare_copy(p->b, (bz.avail_in * 1.1) + 12);
19884 bz.next_out = p->b->ptr;
19885 bz.avail_out = p->b->size;
19886 bz.total_out_lo32 = 0;
19887 bz.total_out_hi32 = 0;
19890 if (BZ_STREAM_END != BZ2_bzCompress(&bz, BZ_FINISH)) {
19891 BZ2_bzCompressEnd(&bz);
19896 /* file is too large for now */
19897 if (bz.total_out_hi32) return -1;
19901 p->b->used = bz.total_out_lo32;
19904 if (BZ_OK != BZ2_bzCompressEnd(&bz)) {
19912 @@ -326,47 +357,50 @@
19914 const char *filename = fn->ptr;
19917 + stat_cache_entry *compressed_sce = NULL;
19919 + if (buffer_is_empty(p->conf.compress_cache_dir)) return -1;
19922 if ((off_t)(sce->st.st_size * 1.1) < sce->st.st_size) return -1;
19924 - /* don't mmap files > 128Mb
19927 + /* don't mmap files > 128Mb
19929 * we could use a sliding window, but currently there is no need for it
19933 if (sce->st.st_size > 128 * 1024 * 1024) return -1;
19936 buffer_reset(p->ofn);
19937 buffer_copy_string_buffer(p->ofn, p->conf.compress_cache_dir);
19938 - BUFFER_APPEND_SLASH(p->ofn);
19940 + PATHNAME_APPEND_SLASH(p->ofn);
19942 if (0 == strncmp(con->physical.path->ptr, con->physical.doc_root->ptr, con->physical.doc_root->used-1)) {
19943 size_t offset = p->ofn->used - 1;
19944 char *dir, *nextdir;
19947 buffer_append_string(p->ofn, con->physical.path->ptr + con->physical.doc_root->used - 1);
19950 buffer_copy_string_buffer(p->b, p->ofn);
19954 for (dir = p->b->ptr + offset; NULL != (nextdir = strchr(dir, '/')); dir = nextdir + 1) {
19958 if (-1 == mkdir(p->b->ptr, 0700)) {
19959 if (errno != EEXIST) {
19960 log_error_write(srv, __FILE__, __LINE__, "sbss", "creating cache-directory", p->b, "failed", strerror(errno));
19971 buffer_append_string_buffer(p->ofn, con->uri.path);
19976 case HTTP_ACCEPT_ENCODING_GZIP:
19977 buffer_append_string(p->ofn, "-gzip-");
19978 @@ -381,55 +415,64 @@
19979 log_error_write(srv, __FILE__, __LINE__, "sd", "unknown compression type", type);
19984 buffer_append_string_buffer(p->ofn, sce->etag);
19988 + if (HANDLER_ERROR != stat_cache_get_entry(srv, con, p->ofn, &compressed_sce)) {
19989 + /* file exists */
19991 + http_chunk_append_file(srv, con, p->ofn, 0, compressed_sce->st.st_size);
19992 + con->file_finished = 1;
19997 if (-1 == (ofd = open(p->ofn->ptr, O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0600))) {
19998 if (errno == EEXIST) {
19999 /* cache-entry exists */
20001 - log_error_write(srv, __FILE__, __LINE__, "bs", p->ofn, "compress-cache hit");
20003 - buffer_copy_string_buffer(con->physical.path, p->ofn);
20009 - log_error_write(srv, __FILE__, __LINE__, "sbss", "creating cachefile", p->ofn, "failed", strerror(errno));
20012 + log_error_write(srv, __FILE__, __LINE__, "sbss",
20013 + "creating cachefile", p->ofn,
20014 + "failed", strerror(errno));
20019 - log_error_write(srv, __FILE__, __LINE__, "bs", p->ofn, "compress-cache miss");
20022 if (-1 == (ifd = open(filename, O_RDONLY | O_BINARY))) {
20023 - log_error_write(srv, __FILE__, __LINE__, "sbss", "opening plain-file", fn, "failed", strerror(errno));
20025 + log_error_write(srv, __FILE__, __LINE__, "sbss",
20026 + "opening plain-file", fn,
20027 + "failed", strerror(errno));
20038 if (MAP_FAILED == (start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
20039 - log_error_write(srv, __FILE__, __LINE__, "sbss", "mmaping", fn, "failed", strerror(errno));
20041 + log_error_write(srv, __FILE__, __LINE__, "sbss",
20043 + "failed", strerror(errno));
20053 - case HTTP_ACCEPT_ENCODING_GZIP:
20054 + case HTTP_ACCEPT_ENCODING_GZIP:
20055 ret = deflate_file_to_buffer_gzip(srv, con, p, start, sce->st.st_size, sce->st.st_mtime);
20057 - case HTTP_ACCEPT_ENCODING_DEFLATE:
20058 + case HTTP_ACCEPT_ENCODING_DEFLATE:
20059 ret = deflate_file_to_buffer_deflate(srv, con, p, start, sce->st.st_size);
20063 - case HTTP_ACCEPT_ENCODING_BZIP2:
20064 + case HTTP_ACCEPT_ENCODING_BZIP2:
20065 ret = deflate_file_to_buffer_bzip2(srv, con, p, start, sce->st.st_size);
20068 @@ -437,26 +480,27 @@
20074 if (-1 == (r = write(ofd, p->b->ptr, p->b->used))) {
20075 - munmap(start, sce->st.st_size);
20076 + munmap(start, sce->st.st_size);
20083 if ((size_t)r != p->b->used) {
20089 munmap(start, sce->st.st_size);
20094 if (ret != 0) return -1;
20096 - buffer_copy_string_buffer(con->physical.path, p->ofn);
20099 + http_chunk_append_file(srv, con, p->ofn, 0, r);
20100 + con->file_finished = 1;
20105 @@ -465,43 +509,44 @@
20112 if ((off_t)(sce->st.st_size * 1.1) < sce->st.st_size) return -1;
20115 /* don't mmap files > 128M
20118 * we could use a sliding window, but currently there is no need for it
20122 if (sce->st.st_size > 128 * 1024 * 1024) return -1;
20126 if (-1 == (ifd = open(fn->ptr, O_RDONLY | O_BINARY))) {
20127 log_error_write(srv, __FILE__, __LINE__, "sbss", "opening plain-file", fn, "failed", strerror(errno));
20134 - if (MAP_FAILED == (start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
20136 + start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0);
20140 + if (MAP_FAILED == start) {
20141 log_error_write(srv, __FILE__, __LINE__, "sbss", "mmaping", fn, "failed", strerror(errno));
20151 - case HTTP_ACCEPT_ENCODING_GZIP:
20152 + case HTTP_ACCEPT_ENCODING_GZIP:
20153 ret = deflate_file_to_buffer_gzip(srv, con, p, start, sce->st.st_size, sce->st.st_mtime);
20155 - case HTTP_ACCEPT_ENCODING_DEFLATE:
20156 + case HTTP_ACCEPT_ENCODING_DEFLATE:
20157 ret = deflate_file_to_buffer_deflate(srv, con, p, start, sce->st.st_size);
20161 - case HTTP_ACCEPT_ENCODING_BZIP2:
20162 + case HTTP_ACCEPT_ENCODING_BZIP2:
20163 ret = deflate_file_to_buffer_bzip2(srv, con, p, start, sce->st.st_size);
20166 @@ -509,69 +554,64 @@
20172 munmap(start, sce->st.st_size);
20176 if (ret != 0) return -1;
20179 chunkqueue_reset(con->write_queue);
20180 b = chunkqueue_get_append_buffer(con->write_queue);
20181 buffer_copy_memory(b, p->b->ptr, p->b->used + 1);
20184 buffer_reset(con->physical.path);
20187 con->file_finished = 1;
20188 con->file_started = 1;
20195 -#define PATCH(x) \
20196 - p->conf.x = s->x;
20197 static int mod_compress_patch_connection(server *srv, connection *con, plugin_data *p) {
20199 plugin_config *s = p->config_storage[0];
20201 - PATCH(compress_cache_dir);
20203 - PATCH(compress_max_filesize);
20205 + PATCH_OPTION(compress_cache_dir);
20206 + PATCH_OPTION(compress);
20207 + PATCH_OPTION(compress_max_filesize);
20209 /* skip the first, the global context */
20210 for (i = 1; i < srv->config_context->used; i++) {
20211 data_config *dc = (data_config *)srv->config_context->data[i];
20212 s = p->config_storage[i];
20215 /* condition didn't match */
20216 if (!config_check_cond(srv, con, dc)) continue;
20220 for (j = 0; j < dc->value->used; j++) {
20221 data_unset *du = dc->value->data[j];
20224 if (buffer_is_equal_string(du->key, CONST_STR_LEN("compress.cache-dir"))) {
20225 - PATCH(compress_cache_dir);
20226 + PATCH_OPTION(compress_cache_dir);
20227 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("compress.filetype"))) {
20229 + PATCH_OPTION(compress);
20230 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("compress.max-filesize"))) {
20231 - PATCH(compress_max_filesize);
20232 + PATCH_OPTION(compress_max_filesize);
20242 PHYSICALPATH_FUNC(mod_compress_physical) {
20243 plugin_data *p = p_d;
20246 stat_cache_entry *sce = NULL;
20249 /* only GET and POST can get compressed */
20250 - if (con->request.http_method != HTTP_METHOD_GET &&
20251 + if (con->request.http_method != HTTP_METHOD_GET &&
20252 con->request.http_method != HTTP_METHOD_POST) {
20253 return HANDLER_GO_ON;
20255 @@ -579,46 +619,49 @@
20256 if (buffer_is_empty(con->physical.path)) {
20257 return HANDLER_GO_ON;
20261 mod_compress_patch_connection(srv, con, p);
20264 max_fsize = p->conf.compress_max_filesize;
20266 stat_cache_get_entry(srv, con, con->physical.path, &sce);
20268 /* don't compress files that are too large as we need to much time to handle them */
20269 if (max_fsize && (sce->st.st_size >> 10) > max_fsize) return HANDLER_GO_ON;
20272 + /* compressing the file might lead to larger files instead */
20273 + if (sce->st.st_size < 128) return HANDLER_GO_ON;
20275 /* check if mimetype is in compress-config */
20276 for (m = 0; m < p->conf.compress->used; m++) {
20277 data_string *compress_ds = (data_string *)p->conf.compress->data[m];
20280 if (!compress_ds) {
20281 log_error_write(srv, __FILE__, __LINE__, "sbb", "evil", con->physical.path, con->uri.path);
20284 return HANDLER_GO_ON;
20288 if (buffer_is_equal(compress_ds->value, sce->content_type)) {
20289 /* mimetype found */
20293 /* the response might change according to Accept-Encoding */
20294 response_header_insert(srv, con, CONST_STR_LEN("Vary"), CONST_STR_LEN("Accept-Encoding"));
20297 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Accept-Encoding"))) {
20298 int accept_encoding = 0;
20299 char *value = ds->value->ptr;
20300 int srv_encodings = 0;
20301 int matched_encodings = 0;
20304 /* get client side support encodings */
20305 if (NULL != strstr(value, "gzip")) accept_encoding |= HTTP_ACCEPT_ENCODING_GZIP;
20306 if (NULL != strstr(value, "deflate")) accept_encoding |= HTTP_ACCEPT_ENCODING_DEFLATE;
20307 if (NULL != strstr(value, "compress")) accept_encoding |= HTTP_ACCEPT_ENCODING_COMPRESS;
20308 if (NULL != strstr(value, "bzip2")) accept_encoding |= HTTP_ACCEPT_ENCODING_BZIP2;
20309 if (NULL != strstr(value, "identity")) accept_encoding |= HTTP_ACCEPT_ENCODING_IDENTITY;
20312 /* get server side supported ones */
20314 srv_encodings |= HTTP_ACCEPT_ENCODING_BZIP2;
20315 @@ -627,18 +670,31 @@
20316 srv_encodings |= HTTP_ACCEPT_ENCODING_GZIP;
20317 srv_encodings |= HTTP_ACCEPT_ENCODING_DEFLATE;
20321 /* find matching entries */
20322 matched_encodings = accept_encoding & srv_encodings;
20325 if (matched_encodings) {
20326 const char *dflt_gzip = "gzip";
20327 const char *dflt_deflate = "deflate";
20328 const char *dflt_bzip2 = "bzip2";
20331 const char *compression_name = NULL;
20332 int compression_type = 0;
20336 + mtime = strftime_cache_get(srv, sce->st.st_mtime);
20337 + etag_mutate(con->physical.etag, sce->etag);
20339 + response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
20340 + response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
20342 + /* perhaps we don't even have to compress the file as the browser still has the
20343 + * current version */
20344 + if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, mtime)) {
20345 + return HANDLER_FINISHED;
20348 /* select best matching encoding */
20349 if (matched_encodings & HTTP_ACCEPT_ENCODING_BZIP2) {
20350 compression_type = HTTP_ACCEPT_ENCODING_BZIP2;
20351 @@ -650,31 +706,21 @@
20352 compression_type = HTTP_ACCEPT_ENCODING_DEFLATE;
20353 compression_name = dflt_deflate;
20357 - if (p->conf.compress_cache_dir->used) {
20358 - if (0 == deflate_file_to_file(srv, con, p,
20359 - con->physical.path, sce, compression_type)) {
20362 - response_header_overwrite(srv, con, CONST_STR_LEN("Content-Encoding"), compression_name, strlen(compression_name));
20364 - mtime = strftime_cache_get(srv, sce->st.st_mtime);
20365 - response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
20367 - etag_mutate(con->physical.etag, sce->etag);
20368 - response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
20370 - response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
20372 - return HANDLER_GO_ON;
20374 - } else if (0 == deflate_file_to_buffer(srv, con, p,
20375 - con->physical.path, sce, compression_type)) {
20377 - response_header_overwrite(srv, con, CONST_STR_LEN("Content-Encoding"), compression_name, strlen(compression_name));
20378 - response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
20381 + /* deflate it to file (cached) or to memory */
20382 + if (0 == deflate_file_to_file(srv, con, p,
20383 + con->physical.path, sce, compression_type) ||
20384 + 0 == deflate_file_to_buffer(srv, con, p,
20385 + con->physical.path, sce, compression_type)) {
20387 + response_header_overwrite(srv, con,
20388 + CONST_STR_LEN("Content-Encoding"),
20389 + compression_name, strlen(compression_name));
20391 + response_header_overwrite(srv, con,
20392 + CONST_STR_LEN("Content-Type"),
20393 + CONST_BUF_LEN(sce->content_type));
20395 return HANDLER_FINISHED;
20398 @@ -682,20 +728,20 @@
20404 return HANDLER_GO_ON;
20407 int mod_compress_plugin_init(plugin *p) {
20408 p->version = LIGHTTPD_VERSION_ID;
20409 p->name = buffer_init_string("compress");
20412 p->init = mod_compress_init;
20413 p->set_defaults = mod_compress_setdefaults;
20414 p->handle_subrequest_start = mod_compress_physical;
20415 p->cleanup = mod_compress_free;
20423 --- ../lighttpd-1.4.11/src/mod_dirlisting.c 2006-01-13 00:00:45.000000000 +0200
20424 +++ lighttpd-1.4.12/src/mod_dirlisting.c 2006-07-16 00:26:04.000000000 +0300
20427 #include <stdlib.h>
20428 #include <string.h>
20429 -#include <dirent.h>
20430 #include <assert.h>
20433 -#include <unistd.h>
20438 #include "response.h"
20439 #include "stat_cache.h"
20440 #include "stream.h"
20443 +#include "sys-strings.h"
20446 * this is a dirlisting for a lighttpd plugin
20447 @@ -27,10 +28,13 @@
20448 #include <sys/syslimits.h>
20451 -#ifdef HAVE_ATTR_ATTRIBUTES_H
20453 #include <attr/attributes.h>
20456 +#include "sys-files.h"
20457 +#include "sys-strings.h"
20459 /* plugin config for all request/connections */
20463 unsigned short hide_readme_file;
20464 unsigned short show_header;
20465 unsigned short hide_header_file;
20468 excludes_buffer *excludes;
20470 buffer *external_css;
20471 @@ -63,13 +67,14 @@
20478 buffer *content_charset;
20482 plugin_config **config_storage;
20484 - plugin_config conf;
20486 + plugin_config conf;
20489 excludes_buffer *excludes_buffer_init(void) {
20490 @@ -146,44 +151,46 @@
20491 /* init the plugin data */
20492 INIT_FUNC(mod_dirlisting_init) {
20496 p = calloc(1, sizeof(*p));
20498 p->tmp_buf = buffer_init();
20499 p->content_charset = buffer_init();
20501 + p->path = buffer_init();
20506 /* detroy the plugin data */
20507 FREE_FUNC(mod_dirlisting_free) {
20508 plugin_data *p = p_d;
20513 if (!p) return HANDLER_GO_ON;
20516 if (p->config_storage) {
20518 for (i = 0; i < srv->config_context->used; i++) {
20519 plugin_config *s = p->config_storage[i];
20525 excludes_buffer_free(s->excludes);
20526 buffer_free(s->external_css);
20527 buffer_free(s->encoding);
20532 free(p->config_storage);
20536 buffer_free(p->tmp_buf);
20537 + buffer_free(p->path);
20538 buffer_free(p->content_charset);
20544 return HANDLER_GO_ON;
20547 @@ -215,10 +222,10 @@
20548 if (0 != excludes_buffer_append(s->excludes,
20549 ((data_string *)(da->value->data[j]))->value)) {
20551 - log_error_write(srv, __FILE__, __LINE__, "sb",
20552 + log_error_write(srv, __FILE__, __LINE__, "sb",
20553 "pcre-compile failed for", ((data_string *)(da->value->data[j]))->value);
20555 - log_error_write(srv, __FILE__, __LINE__, "s",
20556 + log_error_write(srv, __FILE__, __LINE__, "s",
20557 "pcre support is missing, please install libpcre and the headers");
20560 @@ -233,8 +240,8 @@
20561 SETDEFAULTS_FUNC(mod_dirlisting_set_defaults) {
20562 plugin_data *p = p_d;
20565 - config_values_t cv[] = {
20567 + config_values_t cv[] = {
20568 { "dir-listing.exclude", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
20569 { "dir-listing.activate", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
20570 { "dir-listing.hide-dotfiles", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
20571 @@ -245,18 +252,18 @@
20572 { "dir-listing.show-header", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 7 */
20573 { "dir-listing.hide-header-file", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 8 */
20574 { "server.dir-listing", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 9 */
20577 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
20581 if (!p) return HANDLER_ERROR;
20584 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
20587 for (i = 0; i < srv->config_context->used; i++) {
20592 s = calloc(1, sizeof(plugin_config));
20593 s->excludes = excludes_buffer_init();
20594 s->dir_listing = 0;
20595 @@ -267,7 +274,7 @@
20596 s->show_header = 0;
20597 s->hide_header_file = 0;
20598 s->encoding = buffer_init();
20601 cv[0].destination = s->excludes;
20602 cv[1].destination = &(s->dir_listing);
20603 cv[2].destination = &(s->hide_dot_files);
20604 @@ -292,60 +299,57 @@
20605 return HANDLER_GO_ON;
20608 -#define PATCH(x) \
20609 - p->conf.x = s->x;
20610 static int mod_dirlisting_patch_connection(server *srv, connection *con, plugin_data *p) {
20612 plugin_config *s = p->config_storage[0];
20614 - PATCH(dir_listing);
20615 - PATCH(external_css);
20616 - PATCH(hide_dot_files);
20618 - PATCH(show_readme);
20619 - PATCH(hide_readme_file);
20620 - PATCH(show_header);
20621 - PATCH(hide_header_file);
20624 + PATCH_OPTION(dir_listing);
20625 + PATCH_OPTION(external_css);
20626 + PATCH_OPTION(hide_dot_files);
20627 + PATCH_OPTION(encoding);
20628 + PATCH_OPTION(show_readme);
20629 + PATCH_OPTION(hide_readme_file);
20630 + PATCH_OPTION(show_header);
20631 + PATCH_OPTION(hide_header_file);
20632 + PATCH_OPTION(excludes);
20634 /* skip the first, the global context */
20635 for (i = 1; i < srv->config_context->used; i++) {
20636 data_config *dc = (data_config *)srv->config_context->data[i];
20637 s = p->config_storage[i];
20640 /* condition didn't match */
20641 if (!config_check_cond(srv, con, dc)) continue;
20645 for (j = 0; j < dc->value->used; j++) {
20646 data_unset *du = dc->value->data[j];
20649 if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.activate")) ||
20650 buffer_is_equal_string(du->key, CONST_STR_LEN("server.dir-listing"))) {
20651 - PATCH(dir_listing);
20652 + PATCH_OPTION(dir_listing);
20653 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.hide-dotfiles"))) {
20654 - PATCH(hide_dot_files);
20655 + PATCH_OPTION(hide_dot_files);
20656 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.external-css"))) {
20657 - PATCH(external_css);
20658 + PATCH_OPTION(external_css);
20659 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.encoding"))) {
20661 + PATCH_OPTION(encoding);
20662 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.show-readme"))) {
20663 - PATCH(show_readme);
20664 + PATCH_OPTION(show_readme);
20665 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.hide-readme-file"))) {
20666 - PATCH(hide_readme_file);
20667 + PATCH_OPTION(hide_readme_file);
20668 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.show-header"))) {
20669 - PATCH(show_header);
20670 + PATCH_OPTION(show_header);
20671 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.hide-header-file"))) {
20672 - PATCH(hide_header_file);
20673 + PATCH_OPTION(hide_header_file);
20674 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.excludes"))) {
20676 + PATCH_OPTION(excludes);
20688 @@ -432,7 +436,7 @@
20690 static void http_list_directory_header(server *srv, connection *con, plugin_data *p, buffer *out) {
20694 BUFFER_APPEND_STRING_CONST(out,
20695 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n"
20696 "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\">\n"
20697 @@ -492,11 +496,11 @@
20698 if (p->conf.show_header) {
20700 /* if we have a HEADER file, display it in <pre class="header"></pre> */
20703 buffer_copy_string_buffer(p->tmp_buf, con->physical.path);
20704 - BUFFER_APPEND_SLASH(p->tmp_buf);
20705 + PATHNAME_APPEND_SLASH(p->tmp_buf);
20706 BUFFER_APPEND_STRING_CONST(p->tmp_buf, "HEADER.txt");
20709 if (-1 != stream_open(&s, p->tmp_buf)) {
20710 BUFFER_APPEND_STRING_CONST(out, "<pre class=\"header\">");
20711 buffer_append_string_encoded(out, s.start, s.size, ENCODING_MINIMAL_XML);
20712 @@ -531,21 +535,21 @@
20714 static void http_list_directory_footer(server *srv, connection *con, plugin_data *p, buffer *out) {
20718 BUFFER_APPEND_STRING_CONST(out,
20725 if (p->conf.show_readme) {
20727 /* if we have a README file, display it in <pre class="readme"></pre> */
20730 buffer_copy_string_buffer(p->tmp_buf, con->physical.path);
20731 - BUFFER_APPEND_SLASH(p->tmp_buf);
20732 + PATHNAME_APPEND_SLASH(p->tmp_buf);
20733 BUFFER_APPEND_STRING_CONST(p->tmp_buf, "README.txt");
20736 if (-1 != stream_open(&s, p->tmp_buf)) {
20737 BUFFER_APPEND_STRING_CONST(out, "<pre class=\"readme\">");
20738 buffer_append_string_encoded(out, s.start, s.size, ENCODING_MINIMAL_XML);
20739 @@ -553,7 +557,7 @@
20745 BUFFER_APPEND_STRING_CONST(out,
20746 "<div class=\"foot\">"
20748 @@ -576,7 +580,6 @@
20750 struct dirent *dent;
20752 - char *path, *path_file;
20754 int hide_dotfiles = p->conf.hide_dot_files;
20755 dirls_list_t dirs, files, *list;
20756 @@ -586,6 +589,7 @@
20758 const char *content_type;
20764 @@ -594,10 +598,10 @@
20768 - if (dir->used == 0) return -1;
20770 - i = dir->used - 1;
20771 + /* empty pathname, never ... */
20772 + if (buffer_is_empty(dir)) return -1;
20774 + /* max-length for the opendir */
20775 #ifdef HAVE_PATHCONF
20776 if (-1 == (name_max = pathconf(dir->ptr, _PC_NAME_MAX))) {
20778 @@ -606,22 +610,24 @@
20779 name_max = 256; /* stupid default */
20782 -#elif defined __WIN32
20783 +#elif defined _WIN32
20784 name_max = FILENAME_MAX;
20786 name_max = NAME_MAX;
20789 - path = malloc(dir->used + name_max);
20791 - strcpy(path, dir->ptr);
20792 - path_file = path + i;
20794 - if (NULL == (dp = opendir(path))) {
20795 - log_error_write(srv, __FILE__, __LINE__, "sbs",
20796 + buffer_copy_string_buffer(p->path, dir);
20797 + PATHNAME_APPEND_SLASH(p->path);
20800 + /* append *.* to the path */
20801 + buffer_append_string(path, "*.*");
20804 + if (NULL == (dp = opendir(p->path->ptr))) {
20805 + log_error_write(srv, __FILE__, __LINE__, "sbs",
20806 "opendir failed:", dir, strerror(errno));
20812 @@ -633,7 +639,7 @@
20814 files.size = DIRLIST_BLOB_SIZE;
20818 while ((dent = readdir(dp)) != NULL) {
20819 unsigned short exclude_match = 0;
20821 @@ -686,15 +692,21 @@
20824 i = strlen(dent->d_name);
20827 /* NOTE: the manual says, d_name is never more than NAME_MAX
20828 * so this should actually not be a buffer-overflow-risk
20830 if (i > (size_t)name_max) continue;
20832 - memcpy(path_file, dent->d_name, i + 1);
20833 - if (stat(path, &st) != 0)
20835 + /* build the dirname */
20836 + buffer_copy_string_buffer(p->path, dir);
20837 + PATHNAME_APPEND_SLASH(p->path);
20838 + buffer_append_string(p->path, dent->d_name);
20840 + if (stat(p->path->ptr, &st) != 0) {
20841 + fprintf(stderr, "%s.%d: %s, %s\r\n", __FILE__, __LINE__, p->path->ptr, strerror(errno));
20846 if (S_ISDIR(st.st_mode))
20847 @@ -740,7 +752,7 @@
20849 strftime(datebuf, sizeof(datebuf), "%Y-%b-%d %H:%M:%S", localtime(&(tmp->mtime)));
20853 BUFFER_APPEND_STRING_CONST(out, "<tr><td class=\"n\"><a href=\"");
20854 buffer_append_string_encoded(out, DIRLIST_ENT_NAME(tmp), tmp->namelen, ENCODING_REL_URI_PART);
20855 BUFFER_APPEND_STRING_CONST(out, "/\">");
20856 @@ -757,18 +769,22 @@
20857 tmp = files.ent[i];
20859 content_type = NULL;
20863 if (con->conf.use_xattr) {
20864 - memcpy(path_file, DIRLIST_ENT_NAME(tmp), tmp->namelen + 1);
20865 + /* build the dirname */
20866 + buffer_copy_string_buffer(p->path, dir);
20867 + PATHNAME_APPEND_SLASH(p->path);
20868 + buffer_append_string_len(p->path, DIRLIST_ENT_NAME(tmp), tmp->namelen);
20870 attrlen = sizeof(attrval) - 1;
20871 - if (attr_get(path, "Content-Type", attrval, &attrlen, 0) == 0) {
20872 + if (attr_get(p->path->ptr, "Content-Type", attrval, &attrlen, 0) == 0) {
20873 attrval[attrlen] = '\0';
20874 content_type = attrval;
20880 if (content_type == NULL) {
20881 content_type = "application/octet-stream";
20882 for (k = 0; k < con->conf.mimetypes->used; k++) {
20883 @@ -788,7 +804,7 @@
20889 #ifdef HAVE_LOCALTIME_R
20890 localtime_r(&(tmp->mtime), &tm);
20891 strftime(datebuf, sizeof(datebuf), "%Y-%b-%d %H:%M:%S", &tm);
20892 @@ -814,7 +830,6 @@
20898 http_list_directory_footer(srv, con, p, out);
20900 @@ -837,36 +852,55 @@
20901 URIHANDLER_FUNC(mod_dirlisting_subrequest) {
20902 plugin_data *p = p_d;
20903 stat_cache_entry *sce = NULL;
20907 - if (con->physical.path->used == 0) return HANDLER_GO_ON;
20908 - if (con->uri.path->used == 0) return HANDLER_GO_ON;
20912 + if (con->uri.path->used < 2) return HANDLER_GO_ON;
20913 if (con->uri.path->ptr[con->uri.path->used - 2] != '/') return HANDLER_GO_ON;
20915 + if (con->physical.path->used == 0) return HANDLER_GO_ON;
20917 mod_dirlisting_patch_connection(srv, con, p);
20919 if (!p->conf.dir_listing) return HANDLER_GO_ON;
20922 + if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
20923 + /* just a second ago the file was still there */
20924 + return HANDLER_GO_ON;
20927 + if (!S_ISDIR(sce->st.st_mode)) return HANDLER_GO_ON;
20929 if (con->conf.log_request_handling) {
20930 log_error_write(srv, __FILE__, __LINE__, "s", "-- handling the request as Dir-Listing");
20931 log_error_write(srv, __FILE__, __LINE__, "sb", "URI :", con->uri.path);
20934 - if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
20935 - fprintf(stderr, "%s.%d: %s\n", __FILE__, __LINE__, con->physical.path->ptr);
20938 + /* perhaps this a cachable request
20939 + * - we use the etag of the directory
20942 + etag_mutate(con->physical.etag, sce->etag);
20943 + response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
20945 + /* prepare header */
20946 + if (NULL == (ds = (data_string *)array_get_element(con->response.headers, "Last-Modified"))) {
20947 + mtime = strftime_cache_get(srv, sce->st.st_mtime);
20948 + response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
20950 + mtime = ds->value;
20953 - if (!S_ISDIR(sce->st.st_mode)) return HANDLER_GO_ON;
20956 + if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, mtime)) {
20957 + return HANDLER_FINISHED;
20960 if (http_list_directory(srv, con, p, con->physical.path)) {
20961 /* dirlisting failed */
20962 con->http_status = 403;
20966 buffer_reset(con->physical.path);
20970 return HANDLER_FINISHED;
20972 @@ -876,13 +910,13 @@
20973 int mod_dirlisting_plugin_init(plugin *p) {
20974 p->version = LIGHTTPD_VERSION_ID;
20975 p->name = buffer_init_string("dirlisting");
20978 p->init = mod_dirlisting_init;
20979 p->handle_subrequest_start = mod_dirlisting_subrequest;
20980 p->set_defaults = mod_dirlisting_set_defaults;
20981 p->cleanup = mod_dirlisting_free;
20989 --- ../lighttpd-1.4.11/src/mod_evasive.c 2006-01-04 15:24:51.000000000 +0200
20990 +++ lighttpd-1.4.12/src/mod_evasive.c 2006-07-16 00:26:04.000000000 +0300
20991 @@ -31,100 +31,97 @@
20997 plugin_config **config_storage;
20999 - plugin_config conf;
21001 + plugin_config conf;
21004 INIT_FUNC(mod_evasive_init) {
21008 p = calloc(1, sizeof(*p));
21014 FREE_FUNC(mod_evasive_free) {
21015 plugin_data *p = p_d;
21020 if (!p) return HANDLER_GO_ON;
21023 if (p->config_storage) {
21025 for (i = 0; i < srv->config_context->used; i++) {
21026 plugin_config *s = p->config_storage[i];
21031 free(p->config_storage);
21038 return HANDLER_GO_ON;
21041 SETDEFAULTS_FUNC(mod_evasive_set_defaults) {
21042 plugin_data *p = p_d;
21045 - config_values_t cv[] = {
21047 + config_values_t cv[] = {
21048 { "evasive.max-conns-per-ip", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
21049 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
21053 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
21056 for (i = 0; i < srv->config_context->used; i++) {
21060 s = calloc(1, sizeof(plugin_config));
21064 cv[0].destination = &(s->max_conns);
21067 p->config_storage[i] = s;
21070 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
21071 return HANDLER_ERROR;
21076 return HANDLER_GO_ON;
21079 -#define PATCH(x) \
21080 - p->conf.x = s->x;
21081 static int mod_evasive_patch_connection(server *srv, connection *con, plugin_data *p) {
21083 plugin_config *s = p->config_storage[0];
21085 - PATCH(max_conns);
21087 + PATCH_OPTION(max_conns);
21089 /* skip the first, the global context */
21090 for (i = 1; i < srv->config_context->used; i++) {
21091 data_config *dc = (data_config *)srv->config_context->data[i];
21092 s = p->config_storage[i];
21095 /* condition didn't match */
21096 if (!config_check_cond(srv, con, dc)) continue;
21100 for (j = 0; j < dc->value->used; j++) {
21101 data_unset *du = dc->value->data[j];
21104 if (buffer_is_equal_string(du->key, CONST_STR_LEN("evasive.max-conns-per-ip"))) {
21105 - PATCH(max_conns);
21106 + PATCH_OPTION(max_conns);
21116 URIHANDLER_FUNC(mod_evasive_uri_handler) {
21117 plugin_data *p = p_d;
21118 @@ -132,10 +129,10 @@
21121 if (con->uri.path->used == 0) return HANDLER_GO_ON;
21124 mod_evasive_patch_connection(srv, con, p);
21126 - /* no limit set, nothing to block */
21128 + /* no limit set, nothing to block */
21129 if (p->conf.max_conns == 0) return HANDLER_GO_ON;
21131 for (j = 0; j < srv->conns->used; j++) {
21132 @@ -147,7 +144,7 @@
21133 if (c->dst_addr.ipv4.sin_addr.s_addr == con->dst_addr.ipv4.sin_addr.s_addr &&
21134 c->state > CON_STATE_REQUEST_END) {
21138 if (conns_by_ip > p->conf.max_conns) {
21139 log_error_write(srv, __FILE__, __LINE__, "ss",
21140 inet_ntop_cache_get_ip(srv, &(con->dst_addr)),
21141 @@ -158,7 +155,7 @@
21147 return HANDLER_GO_ON;
21150 @@ -166,13 +163,13 @@
21151 int mod_evasive_plugin_init(plugin *p) {
21152 p->version = LIGHTTPD_VERSION_ID;
21153 p->name = buffer_init_string("evasive");
21156 p->init = mod_evasive_init;
21157 p->set_defaults = mod_evasive_set_defaults;
21158 p->handle_uri_clean = mod_evasive_uri_handler;
21159 p->cleanup = mod_evasive_free;
21167 --- ../lighttpd-1.4.11/src/mod_evhost.c 2005-08-17 10:42:03.000000000 +0300
21168 +++ lighttpd-1.4.12/src/mod_evhost.c 2006-07-16 00:26:03.000000000 +0300
21170 #include "response.h"
21171 #include "stat_cache.h"
21173 +#include "sys-files.h"
21176 /* unparsed pieces */
21177 buffer *path_pieces_raw;
21180 /* pieces for path creation */
21182 buffer **path_pieces;
21183 @@ -21,14 +23,14 @@
21186 plugin_config **config_storage;
21187 - plugin_config conf;
21188 + plugin_config conf;
21191 INIT_FUNC(mod_evhost_init) {
21195 p = calloc(1, sizeof(*p));
21198 p->tmp_buf = buffer_init();
21201 @@ -36,34 +38,34 @@
21203 FREE_FUNC(mod_evhost_free) {
21204 plugin_data *p = p_d;
21209 if (!p) return HANDLER_GO_ON;
21212 if (p->config_storage) {
21214 for (i = 0; i < srv->config_context->used; i++) {
21215 plugin_config *s = p->config_storage[i];
21220 if(s->path_pieces) {
21222 for (j = 0; j < s->len; j++) {
21223 buffer_free(s->path_pieces[j]);
21227 free(s->path_pieces);
21231 buffer_free(s->path_pieces_raw);
21236 free(p->config_storage);
21240 buffer_free(p->tmp_buf);
21243 @@ -73,30 +75,30 @@
21245 static void mod_evhost_parse_pattern(plugin_config *s) {
21246 char *ptr = s->path_pieces_raw->ptr,*pos;
21249 s->path_pieces = NULL;
21252 for(pos=ptr;*ptr;ptr++) {
21254 s->path_pieces = realloc(s->path_pieces,(s->len+2) * sizeof(*s->path_pieces));
21255 s->path_pieces[s->len] = buffer_init();
21256 s->path_pieces[s->len+1] = buffer_init();
21259 buffer_copy_string_len(s->path_pieces[s->len],pos,ptr-pos);
21263 buffer_copy_string_len(s->path_pieces[s->len+1],ptr++,2);
21272 s->path_pieces = realloc(s->path_pieces,(s->len+1) * sizeof(*s->path_pieces));
21273 s->path_pieces[s->len] = buffer_init();
21276 buffer_append_memory(s->path_pieces[s->len],pos,ptr-pos);
21282 @@ -104,9 +106,9 @@
21283 SETDEFAULTS_FUNC(mod_evhost_set_defaults) {
21284 plugin_data *p = p_d;
21292 * # define a pattern for the host url finding
21294 @@ -117,39 +119,39 @@
21295 * # %4 => subdomain 2 name
21297 * evhost.path-pattern = "/home/ckruse/dev/www/%3/htdocs/"
21302 - config_values_t cv[] = {
21304 + config_values_t cv[] = {
21305 { "evhost.path-pattern", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
21306 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
21310 if (!p) return HANDLER_ERROR;
21313 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
21316 for (i = 0; i < srv->config_context->used; i++) {
21320 s = calloc(1, sizeof(plugin_config));
21321 s->path_pieces_raw = buffer_init();
21322 s->path_pieces = NULL;
21326 cv[0].destination = s->path_pieces_raw;
21329 p->config_storage[i] = s;
21332 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
21333 return HANDLER_ERROR;
21337 if (s->path_pieces_raw->used != 0) {
21338 mod_evhost_parse_pattern(s);
21343 return HANDLER_GO_ON;
21346 @@ -158,7 +160,7 @@
21347 * - %0 - full hostname (authority w/o port)
21349 * - %2 - domain.tld
21354 static int mod_evhost_parse_host(connection *con,array *host) {
21355 @@ -168,7 +170,7 @@
21361 /* first, find the domain + tld */
21362 for(;ptr > con->uri.authority->ptr;ptr--) {
21364 @@ -179,18 +181,18 @@
21370 ds = data_string_init();
21371 buffer_copy_string(ds->key,"%0");
21374 /* if we stopped at a dot, skip the dot */
21375 if (*ptr == '.') ptr++;
21376 buffer_copy_string_len(ds->value, ptr, colon-ptr);
21379 array_insert_unique(host,(data_unset *)ds);
21382 /* if the : is not the start of the authority, go on parsing the hostname */
21385 if (colon != con->uri.authority->ptr) {
21386 for(ptr = colon - 1, i = 1; ptr > con->uri.authority->ptr; ptr--) {
21388 @@ -200,59 +202,55 @@
21389 buffer_copy_string(ds->key,"%");
21390 buffer_append_long(ds->key, i++);
21391 buffer_copy_string_len(ds->value,ptr+1,colon-ptr-1);
21394 array_insert_unique(host,(data_unset *)ds);
21401 /* if the . is not the first charactor of the hostname */
21402 if (colon != ptr) {
21403 ds = data_string_init();
21404 buffer_copy_string(ds->key,"%");
21405 buffer_append_long(ds->key, i++);
21406 buffer_copy_string_len(ds->value,ptr,colon-ptr);
21409 array_insert_unique(host,(data_unset *)ds);
21417 -#define PATCH(x) \
21418 - p->conf.x = s->x;
21419 static int mod_evhost_patch_connection(server *srv, connection *con, plugin_data *p) {
21421 plugin_config *s = p->config_storage[0];
21423 - PATCH(path_pieces);
21427 + PATCH_OPTION(path_pieces);
21428 + PATCH_OPTION(len);
21430 /* skip the first, the global context */
21431 for (i = 1; i < srv->config_context->used; i++) {
21432 data_config *dc = (data_config *)srv->config_context->data[i];
21433 s = p->config_storage[i];
21436 /* condition didn't match */
21437 if (!config_check_cond(srv, con, dc)) continue;
21441 for (j = 0; j < dc->value->used; j++) {
21442 data_unset *du = dc->value->data[j];
21445 if (buffer_is_equal_string(du->key, CONST_STR_LEN("evhost.path-pattern"))) {
21446 - PATCH(path_pieces);
21448 + PATCH_OPTION(path_pieces);
21449 + PATCH_OPTION(len);
21460 static handler_t mod_evhost_uri_handler(server *srv, connection *con, void *p_d) {
21461 plugin_data *p = p_d;
21462 @@ -261,29 +259,29 @@
21463 register char *ptr;
21465 stat_cache_entry *sce = NULL;
21468 /* not authority set */
21469 if (con->uri.authority->used == 0) return HANDLER_GO_ON;
21472 mod_evhost_patch_connection(srv, con, p);
21475 /* missing even default(global) conf */
21476 if (0 == p->conf.len) {
21477 return HANDLER_GO_ON;
21480 parsed_host = array_init();
21483 mod_evhost_parse_host(con, parsed_host);
21486 /* build document-root */
21487 buffer_reset(p->tmp_buf);
21490 for (i = 0; i < p->conf.len; i++) {
21491 ptr = p->conf.path_pieces[i]->ptr;
21496 if (*(ptr+1) == '%') {
21498 BUFFER_APPEND_STRING_CONST(p->tmp_buf,"%");
21499 @@ -298,11 +296,11 @@
21500 buffer_append_string_buffer(p->tmp_buf,p->conf.path_pieces[i]);
21504 - BUFFER_APPEND_SLASH(p->tmp_buf);
21507 + PATHNAME_APPEND_SLASH(p->tmp_buf);
21509 array_free(parsed_host);
21512 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->tmp_buf, &sce)) {
21513 log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), p->tmp_buf);
21515 @@ -310,11 +308,11 @@
21516 log_error_write(srv, __FILE__, __LINE__, "sb", "not a directory:", p->tmp_buf);
21522 buffer_copy_string_buffer(con->physical.doc_root, p->tmp_buf);
21526 return HANDLER_GO_ON;
21529 @@ -325,9 +323,9 @@
21530 p->set_defaults = mod_evhost_set_defaults;
21531 p->handle_docroot = mod_evhost_uri_handler;
21532 p->cleanup = mod_evhost_free;
21541 --- ../lighttpd-1.4.11/src/mod_expire.c 2005-11-03 09:52:13.000000000 +0200
21542 +++ lighttpd-1.4.12/src/mod_expire.c 2006-07-16 00:26:04.000000000 +0300
21544 #include "stat_cache.h"
21547 - * this is a expire module for a lighttpd
21549 + * this is a expire module for a lighttpd
21551 * set 'Expires:' HTTP Headers on demand
21554 @@ -27,51 +27,51 @@
21560 buffer *expire_tstmp;
21563 plugin_config **config_storage;
21565 - plugin_config conf;
21567 + plugin_config conf;
21570 /* init the plugin data */
21571 INIT_FUNC(mod_expire_init) {
21575 p = calloc(1, sizeof(*p));
21578 p->expire_tstmp = buffer_init();
21581 buffer_prepare_copy(p->expire_tstmp, 255);
21587 /* detroy the plugin data */
21588 FREE_FUNC(mod_expire_free) {
21589 plugin_data *p = p_d;
21594 if (!p) return HANDLER_GO_ON;
21597 buffer_free(p->expire_tstmp);
21600 if (p->config_storage) {
21602 for (i = 0; i < srv->config_context->used; i++) {
21603 plugin_config *s = p->config_storage[i];
21606 array_free(s->expire_url);
21611 free(p->config_storage);
21618 return HANDLER_GO_ON;
21621 @@ -79,25 +79,25 @@
21634 * '(access|modification) [plus] {<num> <type>}*'
21637 * e.g. 'access 1 years'
21641 if (expire->used == 0) {
21642 - log_error_write(srv, __FILE__, __LINE__, "s",
21643 + log_error_write(srv, __FILE__, __LINE__, "s",
21652 if (0 == strncmp(ts, "access ", 7)) {
21655 @@ -110,39 +110,39 @@
21656 "invalid <base>:", ts);
21661 if (0 == strncmp(ts, "plus ", 5)) {
21662 /* skip the optional plus */
21667 /* the rest is just <number> (years|months|days|hours|minutes|seconds) */
21673 if (NULL == (space = strchr(ts, ' '))) {
21674 - log_error_write(srv, __FILE__, __LINE__, "ss",
21675 + log_error_write(srv, __FILE__, __LINE__, "ss",
21676 "missing space after <num>:", ts);
21681 num = strtol(ts, &err, 10);
21683 - log_error_write(srv, __FILE__, __LINE__, "ss",
21684 + log_error_write(srv, __FILE__, __LINE__, "ss",
21685 "missing <type> after <num>:", ts);
21693 if (NULL != (space = strchr(ts, ' '))) {
21703 0 == strncmp(ts, "years", slen)) {
21704 num *= 60 * 60 * 24 * 30 * 12;
21705 } else if (slen == 6 &&
21706 @@ -161,13 +161,13 @@
21707 0 == strncmp(ts, "seconds", slen)) {
21710 - log_error_write(srv, __FILE__, __LINE__, "ss",
21711 + log_error_write(srv, __FILE__, __LINE__, "ss",
21712 "unknown type:", ts);
21722 if (0 == strcmp(ts, "years")) {
21723 @@ -183,19 +183,19 @@
21724 } else if (0 == strcmp(ts, "seconds")) {
21727 - log_error_write(srv, __FILE__, __LINE__, "ss",
21728 + log_error_write(srv, __FILE__, __LINE__, "ss",
21729 "unknown type:", ts);
21742 if (offset != NULL) *offset = retts;
21748 @@ -205,102 +205,99 @@
21749 SETDEFAULTS_FUNC(mod_expire_set_defaults) {
21750 plugin_data *p = p_d;
21753 - config_values_t cv[] = {
21755 + config_values_t cv[] = {
21756 { "expire.url", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
21757 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
21761 if (!p) return HANDLER_ERROR;
21764 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
21767 for (i = 0; i < srv->config_context->used; i++) {
21771 s = calloc(1, sizeof(plugin_config));
21772 s->expire_url = array_init();
21775 cv[0].destination = s->expire_url;
21778 p->config_storage[i] = s;
21781 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
21782 return HANDLER_ERROR;
21786 for (k = 0; k < s->expire_url->used; k++) {
21787 data_string *ds = (data_string *)s->expire_url->data[k];
21791 if (-1 == mod_expire_get_offset(srv, p, ds->value, NULL)) {
21792 - log_error_write(srv, __FILE__, __LINE__, "sb",
21793 + log_error_write(srv, __FILE__, __LINE__, "sb",
21794 "parsing expire.url failed:", ds->value);
21795 return HANDLER_ERROR;
21803 return HANDLER_GO_ON;
21806 -#define PATCH(x) \
21807 - p->conf.x = s->x;
21808 static int mod_expire_patch_connection(server *srv, connection *con, plugin_data *p) {
21810 plugin_config *s = p->config_storage[0];
21812 - PATCH(expire_url);
21815 + PATCH_OPTION(expire_url);
21817 /* skip the first, the global context */
21818 for (i = 1; i < srv->config_context->used; i++) {
21819 data_config *dc = (data_config *)srv->config_context->data[i];
21820 s = p->config_storage[i];
21823 /* condition didn't match */
21824 if (!config_check_cond(srv, con, dc)) continue;
21828 for (j = 0; j < dc->value->used; j++) {
21829 data_unset *du = dc->value->data[j];
21832 if (buffer_is_equal_string(du->key, CONST_STR_LEN("expire.url"))) {
21833 - PATCH(expire_url);
21834 + PATCH_OPTION(expire_url);
21844 URIHANDLER_FUNC(mod_expire_path_handler) {
21845 plugin_data *p = p_d;
21850 if (con->uri.path->used == 0) return HANDLER_GO_ON;
21853 mod_expire_patch_connection(srv, con, p);
21856 s_len = con->uri.path->used - 1;
21859 for (k = 0; k < p->conf.expire_url->used; k++) {
21860 data_string *ds = (data_string *)p->conf.expire_url->data[k];
21861 int ct_len = ds->key->used - 1;
21864 if (ct_len > s_len) continue;
21865 if (ds->key->used == 0) continue;
21868 if (0 == strncmp(con->uri.path->ptr, ds->key->ptr, ct_len)) {
21872 stat_cache_entry *sce = NULL;
21875 stat_cache_get_entry(srv, con, con->physical.path, &sce);
21878 switch(mod_expire_get_offset(srv, p, ds->value, &ts)) {
21881 @@ -308,38 +305,38 @@
21887 t = (ts + sce->st.st_mtime);
21890 /* -1 is handled at parse-time */
21895 - if (0 == (len = strftime(p->expire_tstmp->ptr, p->expire_tstmp->size - 1,
21898 + if (0 == (len = strftime(p->expire_tstmp->ptr, p->expire_tstmp->size - 1,
21899 "%a, %d %b %Y %H:%M:%S GMT", gmtime(&(t))))) {
21900 /* could not set expire header, out of mem */
21903 return HANDLER_GO_ON;
21909 p->expire_tstmp->used = len + 1;
21914 response_header_overwrite(srv, con, CONST_STR_LEN("Expires"), CONST_BUF_LEN(p->expire_tstmp));
21918 buffer_copy_string(p->expire_tstmp, "max-age=");
21919 buffer_append_long(p->expire_tstmp, ts);
21922 response_header_overwrite(srv, con, CONST_STR_LEN("Cache-Control"), CONST_BUF_LEN(p->expire_tstmp));
21925 return HANDLER_GO_ON;
21931 return HANDLER_GO_ON;
21933 @@ -349,13 +346,13 @@
21934 int mod_expire_plugin_init(plugin *p) {
21935 p->version = LIGHTTPD_VERSION_ID;
21936 p->name = buffer_init_string("expire");
21939 p->init = mod_expire_init;
21940 p->handle_subrequest_start = mod_expire_path_handler;
21941 p->set_defaults = mod_expire_set_defaults;
21942 p->cleanup = mod_expire_free;
21950 --- ../lighttpd-1.4.11/src/mod_fastcgi.c 2006-03-09 13:18:39.000000000 +0200
21951 +++ lighttpd-1.4.12/src/mod_fastcgi.c 2006-07-19 20:02:55.000000000 +0300
21953 #include <sys/types.h>
21954 -#include <unistd.h>
21957 #include <string.h>
21958 @@ -18,13 +17,14 @@
21959 #include "connections.h"
21960 #include "response.h"
21961 #include "joblist.h"
21962 +#include "status_counter.h"
21964 #include "plugin.h"
21966 #include "inet_ntop_cache.h"
21967 #include "stat_cache.h"
21969 -#include <fastcgi.h>
21970 +#include "fastcgi.h"
21973 #ifdef HAVE_SYS_FILIO_H
21977 #include "sys-socket.h"
21978 +#include "sys-files.h"
21979 +#include "sys-strings.h"
21980 +#include "sys-process.h"
21982 +#include "http_resp.h"
21984 #ifndef UNIX_PATH_MAX
21985 # define UNIX_PATH_MAX 108
21986 @@ -45,14 +49,13 @@
21987 #include <sys/wait.h>
21997 * - add timeout for a connect to a non-fastcgi process
21998 * (use state_timestamp + state)
22003 typedef struct fcgi_proc {
22005 unsigned port; /* config.port + pno */
22007 buffer *connection_name; /* either tcp:<host>:<port> or unix:<socket> for debuggin purposes */
22010 pid_t pid; /* PID of the spawned process (0 if not spawned locally) */
22013 @@ -70,20 +73,20 @@
22014 time_t last_used; /* see idle_timeout */
22015 size_t requests; /* see max_requests */
22016 struct fcgi_proc *prev, *next; /* see first */
22019 time_t disabled_until; /* this proc is disabled until, use something else until than */
22026 PROC_STATE_UNSET, /* init-phase */
22027 PROC_STATE_RUNNING, /* alive */
22028 - PROC_STATE_OVERLOADED, /* listen-queue is full,
22029 + PROC_STATE_OVERLOADED, /* listen-queue is full,
22030 don't send something to this proc for the next 2 seconds */
22031 PROC_STATE_DIED_WAIT_FOR_PID, /* */
22032 PROC_STATE_DIED, /* marked as dead, should be restarted */
22033 PROC_STATE_KILLED /* was killed as we don't have the load anymore */
22039 @@ -94,20 +97,20 @@
22040 * sorted by lowest load
22042 * whenever a job is done move it up in the list
22043 - * until it is sorted, move it down as soon as the
22044 + * until it is sorted, move it down as soon as the
22047 - fcgi_proc *first;
22048 - fcgi_proc *unused_procs;
22049 + fcgi_proc *first;
22050 + fcgi_proc *unused_procs;
22054 * spawn at least min_procs, at max_procs.
22056 - * as soon as the load of the first entry
22057 + * as soon as the load of the first entry
22058 * is max_load_per_proc we spawn a new one
22059 - * and add it to the first entry and give it
22060 + * and add it to the first entry and give it
22066 unsigned short min_procs;
22067 @@ -119,44 +122,44 @@
22070 * kick the process from the list if it was not
22071 - * used for idle_timeout until min_procs is
22072 + * used for idle_timeout until min_procs is
22073 * reached. this helps to get the processlist
22074 * small again we had a small peak load.
22079 unsigned short idle_timeout;
22083 * time after a disabled remote connection is tried to be re-enabled
22091 unsigned short disable_time;
22094 * same fastcgi processes get a little bit larger
22095 - * than wanted. max_requests_per_proc kills a
22096 + * than wanted. max_requests_per_proc kills a
22097 * process after a number of handled requests.
22100 size_t max_requests_per_proc;
22111 - * if host is one of the local IP adresses the
22112 + * if host is one of the local IP adresses the
22113 * whole connection is local
22115 * if tcp/ip should be used host AND port have
22116 - * to be specified
22120 + * to be specified
22124 unsigned short port;
22127 @@ -169,7 +172,7 @@
22129 buffer *unixsocket;
22131 - /* if socket is local we can start the fastcgi
22132 + /* if socket is local we can start the fastcgi
22135 * bin-path is the path to the binary
22136 @@ -177,19 +180,19 @@
22137 * check min_procs and max_procs for the number
22138 * of process to start-up
22140 - buffer *bin_path;
22142 - /* bin-path is set bin-environment is taken to
22143 + buffer *bin_path;
22145 + /* bin-path is set bin-environment is taken to
22146 * create the environement before starting the
22154 array *bin_env_copy;
22158 - * docroot-translation between URL->phys and the
22159 + * docroot-translation between URL->phys and the
22163 @@ -208,7 +211,7 @@
22164 unsigned short mode;
22167 - * check_local tell you if the phys file is stat()ed
22168 + * check_local tell you if the phys file is stat()ed
22169 * or not. FastCGI doesn't care if the service is
22170 * remote. If the web-server side doesn't contain
22171 * the fastcgi-files we should not stat() for them
22172 @@ -218,11 +221,11 @@
22175 * append PATH_INFO to SCRIPT_FILENAME
22178 * php needs this if cgi.fix_pathinfo is provied
22184 unsigned short break_scriptfilename_for_php;
22187 @@ -231,12 +234,12 @@
22190 unsigned short allow_xsendfile;
22193 ssize_t load; /* replace by host->load */
22195 size_t max_id; /* corresponds most of the time to
22199 only if a process is killed max_id waits for the process itself
22200 to die and decrements its afterwards */
22202 @@ -245,17 +248,17 @@
22205 * one extension can have multiple hosts assigned
22206 - * one host can spawn additional processes on the same
22207 + * one host can spawn additional processes on the same
22208 * socket (if we control it)
22210 * ext -> host -> procs
22213 - * if the fastcgi process is remote that whole goes down
22214 + * if the fastcgi process is remote that whole goes down
22217 * ext -> host -> procs
22221 * in case of PHP and FCGI_CHILDREN we have again a procs
22222 * but we don't control it directly.
22223 @@ -268,7 +271,7 @@
22226 fcgi_extension_host **hosts;
22232 @@ -282,10 +285,10 @@
22239 array *ext_mapping;
22245 @@ -297,7 +300,7 @@
22254 @@ -306,55 +309,54 @@
22257 buffer_uint fcgi_request_id;
22264 - buffer *parse_response;
22271 plugin_config **config_storage;
22274 plugin_config conf; /* this is only used as long as no handler_ctx is setup */
22277 /* connection specific data */
22282 - FCGI_STATE_CONNECT_DELAYED,
22283 - FCGI_STATE_PREPARE_WRITE,
22284 - FCGI_STATE_WRITE,
22287 + FCGI_STATE_CONNECT_DELAYED,
22288 + FCGI_STATE_PREPARE_WRITE,
22289 + FCGI_STATE_WRITE,
22291 } fcgi_connection_state_t;
22295 fcgi_extension_host *host;
22296 fcgi_extension *ext;
22299 fcgi_connection_state_t state;
22300 time_t state_timestamp;
22303 int reconnects; /* number of reconnect attempts */
22305 - chunkqueue *rb; /* read queue */
22307 + chunkqueue *rb; /* the raw fcgi read-queue */
22308 + chunkqueue *http_rb; /* the decoded read-queue for http-parsing */
22309 chunkqueue *wb; /* write queue */
22311 - buffer *response_header;
22315 - int fd; /* fd to the fastcgi process */
22316 - int fde_ndx; /* index into the fd-event buffer */
22322 int send_content_body;
22325 plugin_config conf;
22328 connection *remote_conn; /* dumb pointer */
22329 plugin_data *plugin_data; /* dumb pointer */
22331 @@ -363,49 +365,6 @@
22332 /* ok, we need a prototype */
22333 static handler_t fcgi_handle_fdevent(void *s, void *ctx, int revents);
22335 -data_integer *status_counter_get_counter(server *srv, const char *s, size_t len) {
22336 - data_integer *di;
22338 - if (NULL == (di = (data_integer *)array_get_element(srv->status, s))) {
22339 - /* not found, create it */
22341 - if (NULL == (di = (data_integer *)array_get_unused_element(srv->status, TYPE_INTEGER))) {
22342 - di = data_integer_init();
22344 - buffer_copy_string_len(di->key, s, len);
22347 - array_insert_unique(srv->status, (data_unset *)di);
22352 -/* dummies of the statistic framework functions
22353 - * they will be moved to a statistics.c later */
22354 -int status_counter_inc(server *srv, const char *s, size_t len) {
22355 - data_integer *di = status_counter_get_counter(srv, s, len);
22362 -int status_counter_dec(server *srv, const char *s, size_t len) {
22363 - data_integer *di = status_counter_get_counter(srv, s, len);
22365 - if (di->value > 0) di->value--;
22370 -int status_counter_set(server *srv, const char *s, size_t len, int val) {
22371 - data_integer *di = status_counter_get_counter(srv, s, len);
22378 int fastcgi_status_copy_procname(buffer *b, fcgi_extension_host *host, fcgi_proc *proc) {
22379 buffer_copy_string(b, "fastcgi.backend.");
22380 buffer_append_string_buffer(b, host->id);
22381 @@ -421,7 +380,7 @@
22383 fastcgi_status_copy_procname(b, host, proc); \
22384 buffer_append_string(b, x); \
22385 - status_counter_set(srv, CONST_BUF_LEN(b), 0);
22386 + status_counter_set(CONST_BUF_LEN(b), 0);
22388 CLEAN(".disabled");
22390 @@ -429,42 +388,39 @@
22391 CLEAN(".connected");
22398 fastcgi_status_copy_procname(b, host, NULL); \
22399 buffer_append_string(b, x); \
22400 - status_counter_set(srv, CONST_BUF_LEN(b), 0);
22401 + status_counter_set(CONST_BUF_LEN(b), 0);
22411 static handler_ctx * handler_ctx_init() {
22412 handler_ctx * hctx;
22415 hctx = calloc(1, sizeof(*hctx));
22418 - hctx->fde_ndx = -1;
22420 - hctx->response_header = buffer_init();
22423 hctx->request_id = 0;
22424 hctx->state = FCGI_STATE_INIT;
22430 + hctx->sock = iosocket_init();
22432 hctx->reconnects = 0;
22433 hctx->send_content_body = 1;
22435 hctx->rb = chunkqueue_init();
22436 + hctx->http_rb = chunkqueue_init();
22437 hctx->wb = chunkqueue_init();
22443 @@ -473,12 +429,13 @@
22444 hctx->host->load--;
22448 - buffer_free(hctx->response_header);
22450 chunkqueue_free(hctx->rb);
22451 + chunkqueue_free(hctx->http_rb);
22452 chunkqueue_free(hctx->wb);
22454 + iosocket_free(hctx->sock);
22459 @@ -488,21 +445,21 @@
22460 f = calloc(1, sizeof(*f));
22461 f->unixsocket = buffer_init();
22462 f->connection_name = buffer_init();
22472 void fastcgi_process_free(fcgi_proc *f) {
22476 fastcgi_process_free(f->next);
22479 buffer_free(f->unixsocket);
22480 buffer_free(f->connection_name);
22486 @@ -519,13 +476,13 @@
22487 f->bin_env = array_init();
22488 f->bin_env_copy = array_init();
22489 f->strip_request_uri = buffer_init();
22495 void fastcgi_host_free(fcgi_extension_host *h) {
22499 buffer_free(h->id);
22500 buffer_free(h->host);
22501 buffer_free(h->unixsocket);
22502 @@ -534,49 +491,49 @@
22503 buffer_free(h->strip_request_uri);
22504 array_free(h->bin_env);
22505 array_free(h->bin_env_copy);
22508 fastcgi_process_free(h->first);
22509 fastcgi_process_free(h->unused_procs);
22517 fcgi_exts *fastcgi_extensions_init() {
22520 f = calloc(1, sizeof(*f));
22526 void fastcgi_extensions_free(fcgi_exts *f) {
22533 for (i = 0; i < f->used; i++) {
22534 fcgi_extension *fe;
22541 for (j = 0; j < fe->used; j++) {
22542 fcgi_extension_host *h;
22548 fastcgi_host_free(h);
22552 buffer_free(fe->key);
22566 @@ -625,24 +582,25 @@
22570 - fe->hosts[fe->used++] = fh;
22571 + fe->hosts[fe->used++] = fh;
22578 INIT_FUNC(mod_fastcgi_init) {
22582 p = calloc(1, sizeof(*p));
22585 p->fcgi_env = buffer_init();
22588 p->path = buffer_init();
22589 - p->parse_response = buffer_init();
22591 + p->resp = http_response_init();
22593 p->statuskey = buffer_init();
22599 @@ -650,81 +608,82 @@
22600 FREE_FUNC(mod_fastcgi_free) {
22601 plugin_data *p = p_d;
22602 buffer_uint *r = &(p->fcgi_request_id);
22607 if (r->ptr) free(r->ptr);
22610 buffer_free(p->fcgi_env);
22611 buffer_free(p->path);
22612 - buffer_free(p->parse_response);
22613 buffer_free(p->statuskey);
22616 + http_response_free(p->resp);
22618 if (p->config_storage) {
22620 for (i = 0; i < srv->config_context->used; i++) {
22621 plugin_config *s = p->config_storage[i];
22630 for (j = 0; j < exts->used; j++) {
22631 fcgi_extension *ex;
22634 ex = exts->exts[j];
22637 for (n = 0; n < ex->used; n++) {
22639 fcgi_extension_host *host;
22642 host = ex->hosts[n];
22645 for (proc = host->first; proc; proc = proc->next) {
22646 if (proc->pid != 0) kill(proc->pid, SIGTERM);
22648 - if (proc->is_local &&
22650 + if (proc->is_local &&
22651 !buffer_is_empty(proc->unixsocket)) {
22652 unlink(proc->unixsocket->ptr);
22657 for (proc = host->unused_procs; proc; proc = proc->next) {
22658 if (proc->pid != 0) kill(proc->pid, SIGTERM);
22660 - if (proc->is_local &&
22662 + if (proc->is_local &&
22663 !buffer_is_empty(proc->unixsocket)) {
22664 unlink(proc->unixsocket->ptr);
22671 fastcgi_extensions_free(s->exts);
22672 array_free(s->ext_mapping);
22677 free(p->config_storage);
22684 return HANDLER_GO_ON;
22687 static int env_add(char_array *env, const char *key, size_t key_len, const char *val, size_t val_len) {
22691 if (!key || !val) return -1;
22694 dst = malloc(key_len + val_len + 3);
22695 memcpy(dst, key, key_len);
22696 dst[key_len] = '=';
22697 /* add the \0 from the value */
22698 memcpy(dst + key_len + 1, val, val_len + 1);
22701 if (env->size == 0) {
22703 env->ptr = malloc(env->size * sizeof(*env->ptr));
22704 @@ -732,9 +691,9 @@
22706 env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
22710 env->ptr[env->used++] = dst;
22716 @@ -753,15 +712,15 @@
22717 if (env->size == 0) {
22719 env->ptr = malloc(env->size * sizeof(*env->ptr));
22720 - } else if (env->size == env->used) {
22721 + } else if (env->size == env->used) {
22723 env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
22729 env->ptr[env->used++] = start;
22732 start = b->ptr + i + 1;
22735 @@ -794,7 +753,7 @@
22739 -static int fcgi_spawn_connection(server *srv,
22740 +static int fcgi_spawn_connection(server *srv,
22742 fcgi_extension_host *host,
22744 @@ -806,31 +765,27 @@
22746 struct sockaddr_in fcgi_addr_in;
22747 struct sockaddr *fcgi_addr;
22758 if (p->conf.debug) {
22759 log_error_write(srv, __FILE__, __LINE__, "sdb",
22760 "new proc, socket:", proc->port, proc->unixsocket);
22764 if (!buffer_is_empty(proc->unixsocket)) {
22765 memset(&fcgi_addr, 0, sizeof(fcgi_addr));
22768 #ifdef HAVE_SYS_UN_H
22769 fcgi_addr_un.sun_family = AF_UNIX;
22770 strcpy(fcgi_addr_un.sun_path, proc->unixsocket->ptr);
22774 servlen = SUN_LEN(&fcgi_addr_un);
22776 - /* stevens says: */
22777 - servlen = proc->unixsocket->used + sizeof(fcgi_addr_un.sun_family);
22780 socket_type = AF_UNIX;
22781 fcgi_addr = (struct sockaddr *) &fcgi_addr_un;
22783 @@ -844,108 +799,108 @@
22786 fcgi_addr_in.sin_family = AF_INET;
22789 if (buffer_is_empty(host->host)) {
22790 fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
22792 struct hostent *he;
22795 /* set a usefull default */
22796 fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
22801 if (NULL == (he = gethostbyname(host->host->ptr))) {
22802 - log_error_write(srv, __FILE__, __LINE__,
22803 - "sdb", "gethostbyname failed: ",
22804 + log_error_write(srv, __FILE__, __LINE__,
22805 + "sdb", "gethostbyname failed: ",
22806 h_errno, host->host);
22811 if (he->h_addrtype != AF_INET) {
22812 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype);
22817 if (he->h_length != sizeof(struct in_addr)) {
22818 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-length != sizeof(in_addr): ", he->h_length);
22823 memcpy(&(fcgi_addr_in.sin_addr.s_addr), he->h_addr_list[0], he->h_length);
22827 fcgi_addr_in.sin_port = htons(proc->port);
22828 servlen = sizeof(fcgi_addr_in);
22831 socket_type = AF_INET;
22832 fcgi_addr = (struct sockaddr *) &fcgi_addr_in;
22835 buffer_copy_string(proc->connection_name, "tcp:");
22836 buffer_append_string_buffer(proc->connection_name, host->host);
22837 buffer_append_string(proc->connection_name, ":");
22838 buffer_append_long(proc->connection_name, proc->port);
22842 if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
22843 - log_error_write(srv, __FILE__, __LINE__, "ss",
22844 + log_error_write(srv, __FILE__, __LINE__, "ss",
22845 "failed:", strerror(errno));
22850 if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) {
22851 /* server is not up, spawn in */
22855 - if (errno != ENOENT &&
22857 + if (errno != ENOENT &&
22858 !buffer_is_empty(proc->unixsocket)) {
22859 unlink(proc->unixsocket->ptr);
22866 /* reopen socket */
22867 if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
22868 - log_error_write(srv, __FILE__, __LINE__, "ss",
22869 + log_error_write(srv, __FILE__, __LINE__, "ss",
22870 "socket failed:", strerror(errno));
22876 if (setsockopt(fcgi_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
22877 - log_error_write(srv, __FILE__, __LINE__, "ss",
22878 + log_error_write(srv, __FILE__, __LINE__, "ss",
22879 "socketsockopt failed:", strerror(errno));
22884 /* create socket */
22885 if (-1 == bind(fcgi_fd, fcgi_addr, servlen)) {
22886 - log_error_write(srv, __FILE__, __LINE__, "sbs",
22887 - "bind failed for:",
22888 + log_error_write(srv, __FILE__, __LINE__, "sbs",
22889 + "bind failed for:",
22890 proc->connection_name,
22896 if (-1 == listen(fcgi_fd, 1024)) {
22897 - log_error_write(srv, __FILE__, __LINE__, "ss",
22898 + log_error_write(srv, __FILE__, __LINE__, "ss",
22899 "listen failed:", strerror(errno));
22906 switch ((child = fork())) {
22914 /* create environment */
22923 @@ -955,18 +910,18 @@
22924 dup2(fcgi_fd, FCGI_LISTENSOCK_FILENO);
22929 /* we don't need the client socket */
22930 for (i = 3; i < 256; i++) {
22935 /* build clean environment */
22936 if (host->bin_env_copy->used) {
22937 for (i = 0; i < host->bin_env_copy->used; i++) {
22938 data_string *ds = (data_string *)host->bin_env_copy->data[i];
22942 if (NULL != (ge = getenv(ds->value->ptr))) {
22943 env_add(&env, CONST_BUF_LEN(ds->value), ge, strlen(ge));
22945 @@ -974,39 +929,39 @@
22947 for (i = 0; environ[i]; i++) {
22951 if (NULL != (eq = strchr(environ[i], '='))) {
22952 env_add(&env, environ[i], eq - environ[i], eq+1, strlen(eq+1));
22958 /* create environment */
22959 for (i = 0; i < host->bin_env->used; i++) {
22960 data_string *ds = (data_string *)host->bin_env->data[i];
22963 env_add(&env, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
22967 for (i = 0; i < env.used; i++) {
22968 /* search for PHP_FCGI_CHILDREN */
22969 if (0 == strncmp(env.ptr[i], "PHP_FCGI_CHILDREN=", sizeof("PHP_FCGI_CHILDREN=") - 1)) break;
22973 /* not found, add a default */
22974 if (i == env.used) {
22975 env_add(&env, CONST_STR_LEN("PHP_FCGI_CHILDREN"), CONST_STR_LEN("1"));
22979 env.ptr[env.used] = NULL;
22981 parse_binpath(&arg, host->bin_path);
22984 /* chdir into the base of the bin-path,
22985 * search for the last / */
22986 if (NULL != (c = strrchr(arg.ptr[0], '/'))) {
22990 /* change to the physical directory */
22991 if (-1 == chdir(arg.ptr[0])) {
22993 @@ -1018,12 +973,12 @@
22996 execve(arg.ptr[0], arg.ptr, env.ptr);
22998 - log_error_write(srv, __FILE__, __LINE__, "sbs",
23000 + log_error_write(srv, __FILE__, __LINE__, "sbs",
23001 "execve failed for:", host->bin_path, strerror(errno));
23010 @@ -1031,17 +986,17 @@
23017 select(0, NULL, NULL, NULL, &tv);
23020 switch (waitpid(child, &status, WNOHANG)) {
23022 /* child still running after timeout, good */
23025 /* no PID found ? should never happen */
23026 - log_error_write(srv, __FILE__, __LINE__, "ss",
23027 + log_error_write(srv, __FILE__, __LINE__, "ss",
23028 "pid not found:", strerror(errno));
23031 @@ -1049,10 +1004,10 @@
23032 "the fastcgi-backend", host->bin_path, "failed to start:");
23033 /* the child should not terminate at all */
23034 if (WIFEXITED(status)) {
23035 - log_error_write(srv, __FILE__, __LINE__, "sdb",
23036 - "child exited with status",
23037 + log_error_write(srv, __FILE__, __LINE__, "sdb",
23038 + "child exited with status",
23039 WEXITSTATUS(status), host->bin_path);
23040 - log_error_write(srv, __FILE__, __LINE__, "s",
23041 + log_error_write(srv, __FILE__, __LINE__, "s",
23042 "if you try do run PHP as FastCGI backend make sure you use the FastCGI enabled version.\n"
23043 "You can find out if it is the right one by executing 'php -v' and it should display '(cgi-fcgi)' "
23044 "in the output, NOT (cgi) NOR (cli)\n"
23045 @@ -1060,8 +1015,8 @@
23046 log_error_write(srv, __FILE__, __LINE__, "s",
23047 "If this is PHP on Gentoo add fastcgi to the USE flags");
23048 } else if (WIFSIGNALED(status)) {
23049 - log_error_write(srv, __FILE__, __LINE__, "sd",
23050 - "terminated by signal:",
23051 + log_error_write(srv, __FILE__, __LINE__, "sd",
23052 + "terminated by signal:",
23055 if (WTERMSIG(status) == 11) {
23056 @@ -1071,8 +1026,8 @@
23057 "If this is PHP try to remove the byte-code caches for now and try again.");
23060 - log_error_write(srv, __FILE__, __LINE__, "sd",
23061 - "child died somehow:",
23062 + log_error_write(srv, __FILE__, __LINE__, "sd",
23063 + "child died somehow:",
23067 @@ -1082,26 +1037,26 @@
23069 proc->last_used = srv->cur_ts;
23070 proc->is_local = 1;
23077 proc->is_local = 0;
23081 if (p->conf.debug) {
23082 log_error_write(srv, __FILE__, __LINE__, "sb",
23083 "(debug) socket is already used, won't spawn:",
23084 proc->connection_name);
23089 proc->state = PROC_STATE_RUNNING;
23090 host->active_procs++;
23099 @@ -1111,93 +1066,93 @@
23102 buffer *fcgi_mode = buffer_init();
23104 - config_values_t cv[] = {
23106 + config_values_t cv[] = {
23107 { "fastcgi.server", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
23108 { "fastcgi.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
23109 { "fastcgi.map-extensions", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
23110 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
23114 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
23117 for (i = 0; i < srv->config_context->used; i++) {
23122 s = malloc(sizeof(plugin_config));
23123 s->exts = fastcgi_extensions_init();
23125 s->ext_mapping = array_init();
23128 cv[0].destination = s->exts;
23129 cv[1].destination = &(s->debug);
23130 cv[2].destination = s->ext_mapping;
23133 p->config_storage[i] = s;
23134 ca = ((data_config *)srv->config_context->data[i])->value;
23137 if (0 != config_insert_values_global(srv, ca, cv)) {
23138 return HANDLER_ERROR;
23148 if (NULL != (du = array_get_element(ca, "fastcgi.server"))) {
23150 data_array *da = (data_array *)du;
23153 if (du->type != TYPE_ARRAY) {
23154 - log_error_write(srv, __FILE__, __LINE__, "sss",
23155 + log_error_write(srv, __FILE__, __LINE__, "sss",
23156 "unexpected type for key: ", "fastcgi.server", "array of strings");
23159 return HANDLER_ERROR;
23164 - * fastcgi.server = ( "<ext>" => ( ... ),
23168 + * fastcgi.server = ( "<ext>" => ( ... ),
23169 * "<ext>" => ( ... ) )
23173 for (j = 0; j < da->value->used; j++) {
23175 data_array *da_ext = (data_array *)da->value->data[j];
23178 if (da->value->data[j]->type != TYPE_ARRAY) {
23179 - log_error_write(srv, __FILE__, __LINE__, "sssbs",
23180 - "unexpected type for key: ", "fastcgi.server",
23181 + log_error_write(srv, __FILE__, __LINE__, "sssbs",
23182 + "unexpected type for key: ", "fastcgi.server",
23183 "[", da->value->data[j]->key, "](string)");
23186 return HANDLER_ERROR;
23190 - * da_ext->key == name of the extension
23193 + * da_ext->key == name of the extension
23197 - * fastcgi.server = ( "<ext>" =>
23198 - * ( "<host>" => ( ... ),
23201 + * fastcgi.server = ( "<ext>" =>
23202 + * ( "<host>" => ( ... ),
23203 * "<host>" => ( ... )
23210 for (n = 0; n < da_ext->value->used; n++) {
23211 data_array *da_host = (data_array *)da_ext->value->data[n];
23214 fcgi_extension_host *host;
23216 - config_values_t fcv[] = {
23218 + config_values_t fcv[] = {
23219 { "host", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
23220 { "docroot", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
23221 { "mode", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
23222 { "socket", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
23223 { "bin-path", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 4 */
23226 { "check-local", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 5 */
23227 { "port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 6 */
23228 { "min-procs-not-working", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 7 this is broken for now */
23229 @@ -1205,28 +1160,28 @@
23230 { "max-load-per-proc", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 9 */
23231 { "idle-timeout", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 10 */
23232 { "disable-time", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 11 */
23235 { "bin-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 12 */
23236 { "bin-copy-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 13 */
23239 { "broken-scriptfilename", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 14 */
23240 { "allow-x-send-file", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 15 */
23241 { "strip-request-uri", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 16 */
23244 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
23248 if (da_host->type != TYPE_ARRAY) {
23249 - log_error_write(srv, __FILE__, __LINE__, "ssSBS",
23250 - "unexpected type for key:",
23251 - "fastcgi.server",
23252 + log_error_write(srv, __FILE__, __LINE__, "ssSBS",
23253 + "unexpected type for key:",
23254 + "fastcgi.server",
23255 "[", da_host->key, "](string)");
23258 return HANDLER_ERROR;
23262 host = fastcgi_host_init();
23265 buffer_copy_string_buffer(host->id, da_host->key);
23267 host->check_local = 1;
23268 @@ -1238,13 +1193,13 @@
23269 host->disable_time = 60;
23270 host->break_scriptfilename_for_php = 0;
23271 host->allow_xsendfile = 0; /* handle X-LIGHTTPD-send-file */
23274 fcv[0].destination = host->host;
23275 fcv[1].destination = host->docroot;
23276 fcv[2].destination = fcgi_mode;
23277 fcv[3].destination = host->unixsocket;
23278 fcv[4].destination = host->bin_path;
23281 fcv[5].destination = &(host->check_local);
23282 fcv[6].destination = &(host->port);
23283 fcv[7].destination = &(host->min_procs);
23284 @@ -1252,35 +1207,35 @@
23285 fcv[9].destination = &(host->max_load_per_proc);
23286 fcv[10].destination = &(host->idle_timeout);
23287 fcv[11].destination = &(host->disable_time);
23290 fcv[12].destination = host->bin_env;
23291 fcv[13].destination = host->bin_env_copy;
23292 fcv[14].destination = &(host->break_scriptfilename_for_php);
23293 fcv[15].destination = &(host->allow_xsendfile);
23294 fcv[16].destination = host->strip_request_uri;
23297 if (0 != config_insert_values_internal(srv, da_host->value, fcv)) {
23298 return HANDLER_ERROR;
23301 - if ((!buffer_is_empty(host->host) || host->port) &&
23303 + if ((!buffer_is_empty(host->host) || host->port) &&
23304 !buffer_is_empty(host->unixsocket)) {
23305 - log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
23306 + log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
23307 "either host/port or socket have to be set in:",
23310 da_ext->key, " => (",
23311 da_host->key, " ( ...");
23313 return HANDLER_ERROR;
23317 if (!buffer_is_empty(host->unixsocket)) {
23318 /* unix domain socket */
23321 if (host->unixsocket->used > UNIX_PATH_MAX - 2) {
23322 - log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
23323 + log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
23324 "unixsocket is too long in:",
23327 da_ext->key, " => (",
23328 da_host->key, " ( ...");
23330 @@ -1288,37 +1243,37 @@
23335 - if (buffer_is_empty(host->host) &&
23337 + if (buffer_is_empty(host->host) &&
23338 buffer_is_empty(host->bin_path)) {
23339 - log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
23340 + log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
23341 "host or binpath have to be set in:",
23344 da_ext->key, " => (",
23345 da_host->key, " ( ...");
23348 return HANDLER_ERROR;
23349 } else if (host->port == 0) {
23350 - log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
23351 + log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
23352 "port has to be set in:",
23355 da_ext->key, " => (",
23356 da_host->key, " ( ...");
23358 return HANDLER_ERROR;
23362 - if (!buffer_is_empty(host->bin_path)) {
23364 + if (!buffer_is_empty(host->bin_path)) {
23365 /* a local socket + self spawning */
23368 /* HACK: just to make sure the adaptive spawing is disabled */
23369 host->min_procs = host->max_procs;
23372 if (host->min_procs > host->max_procs) host->max_procs = host->min_procs;
23373 if (host->max_load_per_proc < 1) host->max_load_per_proc = 0;
23377 log_error_write(srv, __FILE__, __LINE__, "ssbsdsbsdsd",
23378 "--- fastcgi spawning local",
23379 @@ -1328,7 +1283,7 @@
23380 "\n\tmin-procs:", host->min_procs,
23381 "\n\tmax-procs:", host->max_procs);
23385 for (pno = 0; pno < host->min_procs; pno++) {
23388 @@ -1343,7 +1298,7 @@
23389 buffer_append_string(proc->unixsocket, "-");
23390 buffer_append_long(proc->unixsocket, pno);
23395 log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd",
23396 "--- fastcgi spawning",
23397 @@ -1351,7 +1306,7 @@
23398 "\n\tsocket", host->unixsocket,
23399 "\n\tcurrent:", pno, "/", host->min_procs);
23403 if (fcgi_spawn_connection(srv, p, host, proc)) {
23404 log_error_write(srv, __FILE__, __LINE__, "s",
23405 "[ERROR]: spawning fcgi failed.");
23406 @@ -1359,35 +1314,35 @@
23409 fastcgi_status_init(srv, p->statuskey, host, proc);
23412 proc->next = host->first;
23413 if (host->first) host->first->prev = proc;
23416 host->first = proc;
23422 proc = fastcgi_process_init();
23423 proc->id = host->num_procs++;
23425 host->active_procs++;
23426 proc->state = PROC_STATE_RUNNING;
23429 if (buffer_is_empty(host->unixsocket)) {
23430 proc->port = host->port;
23432 buffer_copy_string_buffer(proc->unixsocket, host->unixsocket);
23436 fastcgi_status_init(srv, p->statuskey, host, proc);
23438 host->first = proc;
23441 host->min_procs = 1;
23442 host->max_procs = 1;
23446 if (!buffer_is_empty(fcgi_mode)) {
23447 if (strcmp(fcgi_mode->ptr, "responder") == 0) {
23448 host->mode = FCGI_RESPONDER;
23449 @@ -1411,16 +1366,16 @@
23455 buffer_free(fcgi_mode);
23458 return HANDLER_GO_ON;
23461 static int fcgi_set_state(server *srv, handler_ctx *hctx, fcgi_connection_state_t state) {
23462 hctx->state = state;
23463 hctx->state_timestamp = srv->cur_ts;
23469 @@ -1429,13 +1384,13 @@
23472 buffer_uint *r = &(p->fcgi_request_id);
23477 for (i = 0; i < r->used; i++) {
23478 if (r->ptr[i] > m) m = r->ptr[i];
23482 if (r->size == 0) {
23484 r->ptr = malloc(sizeof(*r->ptr) * r->size);
23485 @@ -1443,54 +1398,55 @@
23487 r->ptr = realloc(r->ptr, sizeof(*r->ptr) * r->size);
23491 r->ptr[r->used++] = ++m;
23497 static int fcgi_requestid_del(server *srv, plugin_data *p, size_t request_id) {
23499 buffer_uint *r = &(p->fcgi_request_id);
23504 for (i = 0; i < r->used; i++) {
23505 if (r->ptr[i] == request_id) break;
23509 if (i != r->used) {
23513 if (i != r->used - 1) {
23514 r->ptr[i] = r->ptr[r->used - 1];
23522 void fcgi_connection_close(server *srv, handler_ctx *hctx) {
23527 if (NULL == hctx) return;
23530 p = hctx->plugin_data;
23531 con = hctx->remote_conn;
23534 if (con->mode != p->id) {
23539 - if (hctx->fd != -1) {
23540 - fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
23541 - fdevent_unregister(srv->ev, hctx->fd);
23544 + if (hctx->sock->fd != -1) {
23545 + fdevent_event_del(srv->ev, hctx->sock);
23546 + fdevent_unregister(srv->ev, hctx->sock);
23547 + closesocket(hctx->sock->fd);
23548 + hctx->sock->fd = -1;
23554 if (hctx->request_id != 0) {
23555 fcgi_requestid_del(srv, p, hctx->request_id);
23557 @@ -1499,111 +1455,111 @@
23558 if (hctx->got_proc) {
23559 /* after the connect the process gets a load */
23560 hctx->proc->load--;
23562 - status_counter_dec(srv, CONST_STR_LEN("fastcgi.active-requests"));
23564 + status_counter_dec(CONST_STR_LEN("fastcgi.active-requests"));
23566 fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
23567 buffer_append_string(p->statuskey, ".load");
23569 - status_counter_set(srv, CONST_BUF_LEN(p->statuskey), hctx->proc->load);
23570 + status_counter_set(CONST_BUF_LEN(p->statuskey), hctx->proc->load);
23572 if (p->conf.debug) {
23573 log_error_write(srv, __FILE__, __LINE__, "ssdsbsd",
23574 - "released proc:",
23575 - "pid:", hctx->proc->pid,
23576 - "socket:", hctx->proc->connection_name,
23577 + "released proc:",
23578 + "pid:", hctx->proc->pid,
23579 + "socket:", hctx->proc->connection_name,
23580 "load:", hctx->proc->load);
23587 handler_ctx_free(hctx);
23588 - con->plugin_ctx[p->id] = NULL;
23589 + con->plugin_ctx[p->id] = NULL;
23592 static int fcgi_reconnect(server *srv, handler_ctx *hctx) {
23593 plugin_data *p = hctx->plugin_data;
23604 * connect was ok, connection was accepted
23605 * but the php accept loop checks after the accept if it should die or not.
23607 - * if yes we can only detect it at a write()
23610 + * if yes we can only detect it at a write()
23612 * next step is resetting this attemp and setup a connection again
23615 * if we have more then 5 reconnects for the same request, die
23622 * we have a connection but the child died by some other reason
23627 - if (hctx->fd != -1) {
23628 - fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
23629 - fdevent_unregister(srv->ev, hctx->fd);
23631 + if (hctx->sock->fd != -1) {
23632 + fdevent_event_del(srv->ev, hctx->sock);
23633 + fdevent_unregister(srv->ev, hctx->sock);
23634 + close(hctx->sock->fd);
23637 + hctx->sock->fd = -1;
23641 fcgi_requestid_del(srv, p, hctx->request_id);
23644 fcgi_set_state(srv, hctx, FCGI_STATE_INIT);
23647 hctx->request_id = 0;
23648 hctx->reconnects++;
23651 if (p->conf.debug > 2) {
23653 log_error_write(srv, __FILE__, __LINE__, "sdb",
23654 - "release proc for reconnect:",
23655 + "release proc for reconnect:",
23656 hctx->proc->pid, hctx->proc->connection_name);
23658 log_error_write(srv, __FILE__, __LINE__, "sb",
23659 - "release proc for reconnect:",
23660 + "release proc for reconnect:",
23661 hctx->host->unixsocket);
23665 - if (hctx->proc && hctx->got_proc) {
23666 + if (hctx->proc && hctx->got_proc) {
23667 hctx->proc->load--;
23670 /* perhaps another host gives us more luck */
23671 hctx->host->load--;
23679 static handler_t fcgi_connection_reset(server *srv, connection *con, void *p_d) {
23680 plugin_data *p = p_d;
23683 fcgi_connection_close(srv, con->plugin_ctx[p->id]);
23686 return HANDLER_GO_ON;
23690 static int fcgi_env_add(buffer *env, const char *key, size_t key_len, const char *val, size_t val_len) {
23694 if (!key || !val) return -1;
23697 len = key_len + val_len;
23700 len += key_len > 127 ? 4 : 1;
23701 len += val_len > 127 ? 4 : 1;
23704 buffer_prepare_append(env, len);
23707 if (key_len > 127) {
23708 env->ptr[env->used++] = ((key_len >> 24) & 0xff) | 0x80;
23709 env->ptr[env->used++] = (key_len >> 16) & 0xff;
23710 @@ -1612,7 +1568,7 @@
23712 env->ptr[env->used++] = (key_len >> 0) & 0xff;
23716 if (val_len > 127) {
23717 env->ptr[env->used++] = ((val_len >> 24) & 0xff) | 0x80;
23718 env->ptr[env->used++] = (val_len >> 16) & 0xff;
23719 @@ -1621,12 +1577,12 @@
23721 env->ptr[env->used++] = (val_len >> 0) & 0xff;
23725 memcpy(env->ptr + env->used, key, key_len);
23726 env->used += key_len;
23727 memcpy(env->ptr + env->used, val, val_len);
23728 env->used += val_len;
23734 @@ -1639,11 +1595,11 @@
23735 header->contentLengthB1 = (contentLength >> 8) & 0xff;
23736 header->paddingLength = paddingLength;
23737 header->reserved = 0;
23748 @@ -1665,26 +1621,23 @@
23749 struct sockaddr_un fcgi_addr_un;
23754 fcgi_extension_host *host = hctx->host;
23755 fcgi_proc *proc = hctx->proc;
23756 - int fcgi_fd = hctx->fd;
23758 + int fcgi_fd = hctx->sock->fd;
23760 memset(&fcgi_addr, 0, sizeof(fcgi_addr));
23763 if (!buffer_is_empty(proc->unixsocket)) {
23764 #ifdef HAVE_SYS_UN_H
23765 /* use the unix domain socket */
23766 fcgi_addr_un.sun_family = AF_UNIX;
23767 strcpy(fcgi_addr_un.sun_path, proc->unixsocket->ptr);
23770 servlen = SUN_LEN(&fcgi_addr_un);
23772 - /* stevens says: */
23773 - servlen = proc->unixsocket->used + sizeof(fcgi_addr_un.sun_family);
23776 fcgi_addr = (struct sockaddr *) &fcgi_addr_un;
23779 if (buffer_is_empty(proc->connection_name)) {
23780 /* on remote spawing we have to set the connection-name now */
23781 buffer_copy_string(proc->connection_name, "unix:");
23782 @@ -1695,16 +1648,18 @@
23785 fcgi_addr_in.sin_family = AF_INET;
23787 if (0 == inet_aton(host->host->ptr, &(fcgi_addr_in.sin_addr))) {
23788 - log_error_write(srv, __FILE__, __LINE__, "sbs",
23789 - "converting IP-adress failed for", host->host,
23790 + log_error_write(srv, __FILE__, __LINE__, "sbs",
23791 + "converting IP-adress failed for", host->host,
23792 "\nBe sure to specify an IP address here");
23798 fcgi_addr_in.sin_port = htons(proc->port);
23799 servlen = sizeof(fcgi_addr_in);
23802 fcgi_addr = (struct sockaddr *) &fcgi_addr_in;
23804 if (buffer_is_empty(proc->connection_name)) {
23805 @@ -1715,20 +1670,20 @@
23806 buffer_append_long(proc->connection_name, proc->port);
23811 if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) {
23812 - if (errno == EINPROGRESS ||
23813 + if (errno == EINPROGRESS ||
23814 errno == EALREADY ||
23816 if (hctx->conf.debug > 2) {
23817 - log_error_write(srv, __FILE__, __LINE__, "sb",
23818 + log_error_write(srv, __FILE__, __LINE__, "sb",
23819 "connect delayed, will continue later:", proc->connection_name);
23823 return CONNECTION_DELAYED;
23824 } else if (errno == EAGAIN) {
23825 if (hctx->conf.debug) {
23826 - log_error_write(srv, __FILE__, __LINE__, "sbsd",
23827 + log_error_write(srv, __FILE__, __LINE__, "sbsd",
23828 "This means that the you have more incoming requests than your fastcgi-backend can handle in parallel. "
23829 "Perhaps it helps to spawn more fastcgi backend or php-children, if not decrease server.max-connections."
23830 "The load for this fastcgi backend", proc->connection_name, "is", proc->load);
23831 @@ -1736,8 +1691,8 @@
23833 return CONNECTION_OVERLOADED;
23835 - log_error_write(srv, __FILE__, __LINE__, "sssb",
23836 - "connect failed:",
23837 + log_error_write(srv, __FILE__, __LINE__, "sssb",
23838 + "connect failed:",
23839 strerror(errno), "on",
23840 proc->connection_name);
23842 @@ -1747,7 +1702,7 @@
23844 hctx->reconnects = 0;
23845 if (hctx->conf.debug > 1) {
23846 - log_error_write(srv, __FILE__, __LINE__, "sd",
23847 + log_error_write(srv, __FILE__, __LINE__, "sd",
23848 "connect succeeded: ", fcgi_fd);
23851 @@ -1756,21 +1711,21 @@
23853 static int fcgi_env_add_request_headers(server *srv, connection *con, plugin_data *p) {
23857 for (i = 0; i < con->request.headers->used; i++) {
23861 ds = (data_string *)con->request.headers->data[i];
23864 if (ds->value->used && ds->key->used) {
23866 buffer_reset(srv->tmp_buf);
23869 if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
23870 BUFFER_COPY_STRING_CONST(srv->tmp_buf, "HTTP_");
23871 srv->tmp_buf->used--;
23875 buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
23876 for (j = 0; j < ds->key->used - 1; j++) {
23878 @@ -1784,20 +1739,20 @@
23879 srv->tmp_buf->ptr[srv->tmp_buf->used++] = c;
23881 srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
23884 fcgi_env_add(p->fcgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
23889 for (i = 0; i < con->environment->used; i++) {
23893 ds = (data_string *)con->environment->data[i];
23896 if (ds->value->used && ds->key->used) {
23898 buffer_reset(srv->tmp_buf);
23901 buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
23902 for (j = 0; j < ds->key->used - 1; j++) {
23904 @@ -1811,11 +1766,11 @@
23905 srv->tmp_buf->ptr[srv->tmp_buf->used++] = c;
23907 srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
23910 fcgi_env_add(p->fcgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
23918 @@ -1824,24 +1779,24 @@
23919 FCGI_BeginRequestRecord beginRecord;
23920 FCGI_Header header;
23927 char b2[INET6_ADDRSTRLEN + 1];
23931 plugin_data *p = hctx->plugin_data;
23932 fcgi_extension_host *host= hctx->host;
23934 connection *con = hctx->remote_conn;
23935 server_socket *srv_sock = con->srv_socket;
23938 sock_addr our_addr;
23939 socklen_t our_addr_len;
23942 /* send FCGI_BEGIN_REQUEST */
23945 fcgi_header(&(beginRecord.header), FCGI_BEGIN_REQUEST, request_id, sizeof(beginRecord.body), 0);
23946 beginRecord.body.roleB0 = host->mode;
23947 beginRecord.body.roleB1 = 0;
23948 @@ -1849,21 +1804,21 @@
23949 memset(beginRecord.body.reserved, 0, sizeof(beginRecord.body.reserved));
23951 b = chunkqueue_get_append_buffer(hctx->wb);
23954 buffer_copy_memory(b, (const char *)&beginRecord, sizeof(beginRecord));
23957 /* send FCGI_PARAMS */
23958 buffer_prepare_copy(p->fcgi_env, 1024);
23961 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION));
23964 if (con->server_name->used) {
23965 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_NAME"), CONST_BUF_LEN(con->server_name));
23968 - s = inet_ntop(srv_sock->addr.plain.sa_family,
23969 - srv_sock->addr.plain.sa_family == AF_INET6 ?
23970 + s = inet_ntop(srv_sock->addr.plain.sa_family,
23971 + srv_sock->addr.plain.sa_family == AF_INET6 ?
23972 (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
23973 (const void *) &(srv_sock->addr.ipv4.sin_addr),
23975 @@ -1872,50 +1827,50 @@
23977 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_NAME"), s, strlen(s));
23981 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1"));
23987 ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
23989 ntohs(srv_sock->addr.ipv4.sin_port)
23994 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf));
23997 /* get the server-side of the connection to the client */
23998 our_addr_len = sizeof(our_addr);
24000 - if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) {
24002 + if (-1 == getsockname(con->sock->fd, &(our_addr.plain), &our_addr_len)) {
24003 s = inet_ntop_cache_get_ip(srv, &(srv_sock->addr));
24005 s = inet_ntop_cache_get_ip(srv, &(our_addr));
24007 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_ADDR"), s, strlen(s));
24013 ntohs(con->dst_addr.plain.sa_family ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
24015 ntohs(con->dst_addr.ipv4.sin_port)
24020 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf));
24023 s = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
24024 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s));
24027 if (!buffer_is_empty(con->authed_user)) {
24028 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_USER"),
24029 CONST_BUF_LEN(con->authed_user));
24033 if (con->request.content_length > 0 && host->mode != FCGI_AUTHORIZER) {
24034 /* CGI-SPEC 6.1.2 and FastCGI spec 6.3 */
24037 /* request.content_length < SSIZE_MAX, see request.c */
24038 ltostr(buf, con->request.content_length);
24039 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf));
24040 @@ -1930,12 +1885,12 @@
24043 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
24046 if (!buffer_is_empty(con->request.pathinfo)) {
24047 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo));
24050 /* PATH_TRANSLATED is only defined if PATH_INFO is set */
24053 if (!buffer_is_empty(host->docroot)) {
24054 buffer_copy_string_buffer(p->path, host->docroot);
24056 @@ -1957,27 +1912,27 @@
24059 if (!buffer_is_empty(host->docroot)) {
24061 - * rewrite SCRIPT_FILENAME
24064 + * rewrite SCRIPT_FILENAME
24069 buffer_copy_string_buffer(p->path, host->docroot);
24070 buffer_append_string_buffer(p->path, con->uri.path);
24073 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
24074 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(host->docroot));
24076 buffer_copy_string_buffer(p->path, con->physical.path);
24078 - /* cgi.fix_pathinfo need a broken SCRIPT_FILENAME to find out what PATH_INFO is itself
24081 + /* cgi.fix_pathinfo need a broken SCRIPT_FILENAME to find out what PATH_INFO is itself
24083 * see src/sapi/cgi_main.c, init_request_info()
24085 if (host->break_scriptfilename_for_php) {
24086 buffer_append_string_buffer(p->path, con->request.pathinfo);
24090 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
24091 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root));
24093 @@ -1987,7 +1942,7 @@
24097 - * stripping /app1 or /app1/ should lead to
24098 + * stripping /app1 or /app1/ should lead to
24102 @@ -2001,7 +1956,7 @@
24103 0 == strncmp(con->request.orig_uri->ptr, host->strip_request_uri->ptr, host->strip_request_uri->used - 1)) {
24104 /* the left is the same */
24106 - fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_URI"),
24107 + fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_URI"),
24108 con->request.orig_uri->ptr + (host->strip_request_uri->used - 2),
24109 con->request.orig_uri->used - (host->strip_request_uri->used - 2));
24111 @@ -2018,26 +1973,26 @@
24113 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN(""));
24117 s = get_http_method_name(con->request.http_method);
24118 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_METHOD"), s, strlen(s));
24119 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200")); /* if php is compiled with --force-redirect */
24120 s = get_http_version_name(con->request.http_version);
24121 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s));
24125 if (srv_sock->is_ssl) {
24126 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("HTTPS"), CONST_STR_LEN("on"));
24133 fcgi_env_add_request_headers(srv, con, p);
24136 fcgi_header(&(header), FCGI_PARAMS, request_id, p->fcgi_env->used, 0);
24137 buffer_append_memory(b, (const char *)&header, sizeof(header));
24138 buffer_append_memory(b, (const char *)p->fcgi_env->ptr, p->fcgi_env->used);
24141 fcgi_header(&(header), FCGI_PARAMS, request_id, 0, 0);
24142 buffer_append_memory(b, (const char *)&header, sizeof(header));
24144 @@ -2057,7 +2012,7 @@
24146 /* we announce toWrite octects
24147 * now take all the request_content chunk that we need to fill this request
24151 b = chunkqueue_get_append_buffer(hctx->wb);
24152 fcgi_header(&(header), FCGI_STDIN, request_id, weWant, 0);
24153 @@ -2080,16 +2035,16 @@
24154 if (weHave > weWant - written) weHave = weWant - written;
24156 if (p->conf.debug > 10) {
24157 - fprintf(stderr, "%s.%d: sending %lld bytes from (%lld / %lld) %s\n",
24158 - __FILE__, __LINE__,
24161 - req_c->file.length,
24162 + fprintf(stderr, "%s.%d: sending %lld bytes from (%lld / %lld) %s\n",
24163 + __FILE__, __LINE__,
24166 + req_c->file.length,
24167 req_c->file.name->ptr);
24170 assert(weHave != 0);
24173 chunkqueue_append_file(hctx->wb, req_c->file.name, req_c->offset, weHave);
24175 req_c->offset += weHave;
24176 @@ -2104,7 +2059,7 @@
24177 * - we reference the tempfile from the request-content-queue several times
24178 * if the req_c is larger than FCGI_MAX_LENGTH
24179 * - we can't simply cleanup the request-content-queue as soon as possible
24180 - * as it would remove the tempfiles
24181 + * as it would remove the tempfiles
24182 * - the idea is to 'steal' the tempfiles and attach the is_temp flag to the last
24183 * referencing chunk of the fastcgi-write-queue
24185 @@ -2141,7 +2096,7 @@
24186 req_c->offset += weHave;
24187 req_cq->bytes_out += weHave;
24191 hctx->wb->bytes_in += weHave;
24193 if (req_c->offset == req_c->mem->used - 1) {
24194 @@ -2155,12 +2110,12 @@
24200 b->used++; /* add virtual \0 */
24206 b = chunkqueue_get_append_buffer(hctx->wb);
24207 /* terminate STDIN */
24208 fcgi_header(&(header), FCGI_STDIN, request_id, 0, 0);
24209 @@ -2175,118 +2130,19 @@
24210 if ((i+1) % 16 == 0) {
24212 for (j = i-15; j <= i; j++) {
24213 - fprintf(stderr, "%c",
24214 + fprintf(stderr, "%c",
24215 isprint((unsigned char)hctx->write_buffer->ptr[j]) ? hctx->write_buffer->ptr[j] : '.');
24217 fprintf(stderr, "\n");
24225 -static int fcgi_response_parse(server *srv, connection *con, plugin_data *p, buffer *in) {
24228 - handler_ctx *hctx = con->plugin_ctx[p->id];
24229 - fcgi_extension_host *host= hctx->host;
24233 - buffer_copy_string_buffer(p->parse_response, in);
24235 - /* search for \n */
24236 - for (s = p->parse_response->ptr; NULL != (ns = strchr(s, '\n')); s = ns + 1) {
24237 - char *key, *value;
24241 - /* a good day. Someone has read the specs and is sending a \r\n to us */
24243 - if (ns > p->parse_response->ptr &&
24244 - *(ns-1) == '\r') {
24251 - if (NULL == (value = strchr(s, ':'))) {
24252 - /* we expect: "<key>: <value>\n" */
24256 - key_len = value - key;
24260 - while (*value == ' ' || *value == '\t') value++;
24262 - if (host->mode != FCGI_AUTHORIZER ||
24263 - !(con->http_status == 0 ||
24264 - con->http_status == 200)) {
24265 - /* authorizers shouldn't affect the response headers sent back to the client */
24267 - /* don't forward Status: */
24268 - if (0 != strncasecmp(key, "Status", key_len)) {
24269 - if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
24270 - ds = data_response_init();
24272 - buffer_copy_string_len(ds->key, key, key_len);
24273 - buffer_copy_string(ds->value, value);
24275 - array_insert_unique(con->response.headers, (data_unset *)ds);
24279 - switch(key_len) {
24281 - if (0 == strncasecmp(key, "Date", key_len)) {
24282 - con->parsed_response |= HTTP_DATE;
24286 - if (0 == strncasecmp(key, "Status", key_len)) {
24287 - con->http_status = strtol(value, NULL, 10);
24288 - con->parsed_response |= HTTP_STATUS;
24292 - if (0 == strncasecmp(key, "Location", key_len)) {
24293 - con->parsed_response |= HTTP_LOCATION;
24297 - if (0 == strncasecmp(key, "Connection", key_len)) {
24298 - con->response.keep_alive = (0 == strcasecmp(value, "Keep-Alive")) ? 1 : 0;
24299 - con->parsed_response |= HTTP_CONNECTION;
24303 - if (0 == strncasecmp(key, "Content-Length", key_len)) {
24304 - con->response.content_length = strtol(value, NULL, 10);
24305 - con->parsed_response |= HTTP_CONTENT_LENGTH;
24307 - if (con->response.content_length < 0) con->response.content_length = 0;
24315 - /* CGI/1.1 rev 03 - 7.2.1.2 */
24316 - if ((con->parsed_response & HTTP_LOCATION) &&
24317 - !(con->parsed_response & HTTP_STATUS)) {
24318 - con->http_status = 302;
24330 @@ -2327,9 +2183,9 @@
24334 - /* we have at least a header, now check how much me have to fetch */
24335 + /* we have at least a header, now check how much me have to fetch */
24336 header = (FCGI_Header *)(packet->b->ptr);
24339 packet->len = (header->contentLengthB0 | (header->contentLengthB1 << 8)) + header->paddingLength;
24340 packet->request_id = (header->requestIdB0 | (header->requestIdB1 << 8));
24341 packet->type = header->type;
24342 @@ -2348,7 +2204,7 @@
24343 size_t weHave = c->mem->used - c->offset - offset - 1;
24345 if (weHave > weWant) weHave = weWant;
24348 buffer_append_string_len(packet->b, c->mem->ptr + c->offset + offset, weHave);
24350 /* we only skipped the first 8 bytes as they are the fcgi header */
24351 @@ -2380,65 +2236,42 @@
24354 chunkqueue_remove_finished_chunks(hctx->rb);
24360 static int fcgi_demux_response(server *srv, handler_ctx *hctx) {
24366 plugin_data *p = hctx->plugin_data;
24367 connection *con = hctx->remote_conn;
24368 - int fcgi_fd = hctx->fd;
24369 fcgi_extension_host *host= hctx->host;
24370 fcgi_proc *proc = hctx->proc;
24373 - * check how much we have to read
24375 - if (ioctl(hctx->fd, FIONREAD, &toread)) {
24376 - log_error_write(srv, __FILE__, __LINE__, "sd",
24377 - "unexpected end-of-file (perhaps the fastcgi process died):",
24382 - /* init read-buffer */
24384 - if (toread > 0) {
24387 - b = chunkqueue_get_append_buffer(hctx->rb);
24388 - buffer_prepare_copy(b, toread + 1);
24390 - /* append to read-buffer */
24391 - if (-1 == (r = read(hctx->fd, b->ptr, toread))) {
24392 - log_error_write(srv, __FILE__, __LINE__, "sds",
24393 - "unexpected end-of-file (perhaps the fastcgi process died):",
24394 - fcgi_fd, strerror(errno));
24398 - /* this should be catched by the b > 0 above */
24402 - b->used = r + 1; /* one extra for the fake \0 */
24403 - b->ptr[b->used - 1] = '\0';
24405 - log_error_write(srv, __FILE__, __LINE__, "ssdsb",
24406 - "unexpected end-of-file (perhaps the fastcgi process died):",
24407 - "pid:", proc->pid,
24408 - "socket:", proc->connection_name);
24410 + /* in case we read nothing, check the return code
24411 + * if we got something, be happy :)
24413 + * Ok, to be honest:
24414 + * - it is fine to receive a EAGAIN on a second read() call
24415 + * - it might be fine they we get a con-close on a second read() call */
24416 + switch(srv->network_backend_read(srv, con, hctx->sock, hctx->rb)) {
24417 + case NETWORK_STATUS_WAIT_FOR_EVENT:
24418 + /* a EAGAIN after we read exactly the chunk-size */
24420 + ERROR("%s", "oops, got a EAGAIN even if we just got call for the event, wired");
24422 + case NETWORK_STATUS_SUCCESS:
24425 + ERROR("reading from fastcgi socket failed (fd=%d)", hctx->sock->fd);
24430 * parse the fastcgi packets and forward the content to the write-queue
24435 fastcgi_response_packet packet;
24437 @@ -2454,92 +2287,136 @@
24439 /* is the header already finished */
24440 if (0 == con->file_started) {
24445 - /* search for header terminator
24447 - * if we start with \r\n check if last packet terminated with \r\n
24448 - * if we start with \n check if last packet terminated with \n
24449 - * search for \r\n\r\n
24450 - * search for \n\n
24453 - if (hctx->response_header->used == 0) {
24454 - buffer_copy_string_buffer(hctx->response_header, packet.b);
24456 - buffer_append_string_buffer(hctx->response_header, packet.b);
24459 - if (NULL != (c = buffer_search_string_len(hctx->response_header, CONST_STR_LEN("\r\n\r\n")))) {
24460 - blen = hctx->response_header->used - (c - hctx->response_header->ptr) - 4;
24461 - hctx->response_header->used = (c - hctx->response_header->ptr) + 3;
24462 - c += 4; /* point the the start of the response */
24463 - } else if (NULL != (c = buffer_search_string_len(hctx->response_header, CONST_STR_LEN("\n\n")))) {
24464 - blen = hctx->response_header->used - (c - hctx->response_header->ptr) - 2;
24465 - hctx->response_header->used = c - hctx->response_header->ptr + 2;
24466 - c += 2; /* point the the start of the response */
24468 - /* no luck, no header found */
24469 + int have_content_length = 0;
24470 + int need_more = 0;
24473 + /* append the current packet to the chunk queue */
24474 + chunkqueue_append_buffer(hctx->http_rb, packet.b);
24475 + http_response_reset(p->resp);
24477 + switch(http_response_parse_cq(hctx->http_rb, p->resp)) {
24478 + case PARSE_ERROR:
24479 + /* parsing the response header failed */
24481 + con->http_status = 502; /* Bad Gateway */
24484 + case PARSE_NEED_MORE:
24486 + break; /* leave the loop */
24487 + case PARSE_SUCCESS:
24490 + /* should not happen */
24494 - /* parse the response header */
24495 - fcgi_response_parse(srv, con, p, hctx->response_header);
24496 + if (need_more) break;
24498 - con->file_started = 1;
24499 + chunkqueue_remove_finished_chunks(hctx->http_rb);
24501 + con->http_status = p->resp->status;
24502 + hctx->send_content_body = 1;
24504 - if (host->mode == FCGI_AUTHORIZER &&
24505 - (con->http_status == 0 ||
24506 - con->http_status == 200)) {
24507 - /* a authorizer with approved the static request, ignore the content here */
24508 - hctx->send_content_body = 0;
24511 - if (host->allow_xsendfile &&
24512 - NULL != (ds = (data_string *) array_get_element(con->response.headers, "X-LIGHTTPD-send-file"))) {
24513 - stat_cache_entry *sce;
24515 - if (HANDLER_ERROR != stat_cache_get_entry(srv, con, ds->value, &sce)) {
24518 - http_chunk_append_file(srv, con, ds->value, 0, sce->st.st_size);
24519 - hctx->send_content_body = 0; /* ignore the content */
24520 - joblist_append(srv, con);
24521 + /* handle the header fields */
24522 + if (host->mode == FCGI_AUTHORIZER) {
24523 + /* auth mode is a bit different */
24525 + if (con->http_status == 0 ||
24526 + con->http_status == 200) {
24527 + /* a authorizer with approved the static request, ignore the content here */
24528 + hctx->send_content_body = 0;
24532 + /* copy the http-headers */
24533 + for (i = 0; i < p->resp->headers->used; i++) {
24534 + const char *ign[] = { "Status", NULL };
24538 + data_string *header = (data_string *)p->resp->headers->data[i];
24540 + /* ignore all headers in AUTHORIZER mode */
24541 + if (host->mode == FCGI_AUTHORIZER) continue;
24543 + /* some headers are ignored by default */
24544 + for (j = 0; ign[j]; j++) {
24545 + if (0 == strcasecmp(ign[j], header->key->ptr)) break;
24547 + if (ign[j]) continue;
24549 + if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Location"))) {
24550 + /* CGI/1.1 rev 03 - 7.2.1.2 */
24551 + con->http_status = 302;
24552 + } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Content-Length"))) {
24553 + have_content_length = 1;
24554 + } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("X-Sendfile")) ||
24555 + 0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("X-LIGHTTPD-send-file"))) {
24557 + stat_cache_entry *sce;
24559 - if (hctx->send_content_body && blen > 1) {
24560 - /* enable chunked-transfer-encoding */
24561 + if (host->allow_xsendfile &&
24562 + HANDLER_ERROR != stat_cache_get_entry(srv, con, header->value, &sce)) {
24563 + http_chunk_append_file(srv, con, header->value, 0, sce->st.st_size);
24564 + hctx->send_content_body = 0; /* ignore the content */
24566 + joblist_append(srv, con);
24569 + continue; /* ignore header */
24572 + if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
24573 + ds = data_response_init();
24575 + buffer_copy_string_buffer(ds->key, header->key);
24576 + buffer_copy_string_buffer(ds->value, header->value);
24578 + array_insert_unique(con->response.headers, (data_unset *)ds);
24581 + /* header is complete ... go on with the body */
24583 + con->file_started = 1;
24585 + if (hctx->send_content_body) {
24586 + chunk *c = hctx->http_rb->first;
24588 + /* if we don't have a content-length enable chunked encoding
24591 + * TODO: move this to a later stage in the filter-queue
24593 if (con->request.http_version == HTTP_VERSION_1_1 &&
24594 - !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
24595 + !have_content_length) {
24596 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
24599 - http_chunk_append_mem(srv, con, c, blen);
24600 + /* copy the rest of the data */
24601 + for (c = hctx->http_rb->first; c; c = c->next) {
24602 + if (c->mem->used > 1) {
24603 + http_chunk_append_mem(srv, con, c->mem->ptr + c->offset, c->mem->used - c->offset);
24604 + c->offset = c->mem->used - 1;
24607 + chunkqueue_remove_finished_chunks(hctx->http_rb);
24608 joblist_append(srv, con);
24610 } else if (hctx->send_content_body && packet.b->used > 1) {
24611 - if (con->request.http_version == HTTP_VERSION_1_1 &&
24612 - !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
24613 - /* enable chunked-transfer-encoding */
24614 - con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
24617 http_chunk_append_mem(srv, con, packet.b->ptr, packet.b->used);
24618 joblist_append(srv, con);
24622 - log_error_write(srv, __FILE__, __LINE__, "sb",
24623 + log_error_write(srv, __FILE__, __LINE__, "sb",
24624 "FastCGI-stderr:", packet.b);
24628 case FCGI_END_REQUEST:
24629 con->file_finished = 1;
24632 if (host->mode != FCGI_AUTHORIZER ||
24633 !(con->http_status == 0 ||
24634 con->http_status == 200)) {
24635 @@ -2547,39 +2424,39 @@
24636 http_chunk_append_mem(srv, con, NULL, 0);
24637 joblist_append(srv, con);
24644 - log_error_write(srv, __FILE__, __LINE__, "sd",
24645 + log_error_write(srv, __FILE__, __LINE__, "sd",
24646 "FastCGI: header.type not handled: ", packet.type);
24649 buffer_free(packet.b);
24656 static int fcgi_restart_dead_procs(server *srv, plugin_data *p, fcgi_extension_host *host) {
24660 for (proc = host->first; proc; proc = proc->next) {
24663 if (p->conf.debug > 2) {
24664 - log_error_write(srv, __FILE__, __LINE__, "sbdddd",
24666 + log_error_write(srv, __FILE__, __LINE__, "sbdddd",
24668 proc->connection_name,
24678 * if the remote side is overloaded, we check back after <n> seconds
24682 switch (proc->state) {
24683 case PROC_STATE_KILLED:
24684 @@ -2592,13 +2469,13 @@
24686 case PROC_STATE_OVERLOADED:
24687 if (srv->cur_ts <= proc->disabled_until) break;
24690 proc->state = PROC_STATE_RUNNING;
24691 host->active_procs++;
24693 - log_error_write(srv, __FILE__, __LINE__, "sbdb",
24694 - "fcgi-server re-enabled:",
24695 - host->host, host->port,
24697 + log_error_write(srv, __FILE__, __LINE__, "sbdb",
24698 + "fcgi-server re-enabled:",
24699 + host->host, host->port,
24702 case PROC_STATE_DIED_WAIT_FOR_PID:
24703 @@ -2606,7 +2483,7 @@
24704 if (!proc->is_local) break;
24706 /* the child should not terminate at all */
24709 switch(waitpid(proc->pid, &status, WNOHANG)) {
24711 /* child is still alive */
24712 @@ -2616,45 +2493,45 @@
24714 if (WIFEXITED(status)) {
24716 - log_error_write(srv, __FILE__, __LINE__, "sdsd",
24717 + log_error_write(srv, __FILE__, __LINE__, "sdsd",
24718 "child exited, pid:", proc->pid,
24719 "status:", WEXITSTATUS(status));
24721 } else if (WIFSIGNALED(status)) {
24722 - log_error_write(srv, __FILE__, __LINE__, "sd",
24723 - "child signaled:",
24724 + log_error_write(srv, __FILE__, __LINE__, "sd",
24725 + "child signaled:",
24728 - log_error_write(srv, __FILE__, __LINE__, "sd",
24729 - "child died somehow:",
24730 + log_error_write(srv, __FILE__, __LINE__, "sd",
24731 + "child died somehow:",
24736 proc->state = PROC_STATE_DIED;
24741 /* fall through if we have a dead proc now */
24742 if (proc->state != PROC_STATE_DIED) break;
24744 case PROC_STATE_DIED:
24745 - /* local proc get restarted by us,
24746 + /* local proc get restarted by us,
24747 * remote ones hopefully by the admin */
24750 if (proc->is_local) {
24751 /* we still have connections bound to this proc,
24752 * let them terminate first */
24753 if (proc->load != 0) break;
24756 /* restart the child */
24759 if (p->conf.debug) {
24760 log_error_write(srv, __FILE__, __LINE__, "ssbsdsd",
24761 "--- fastcgi spawning",
24762 "\n\tsocket", proc->connection_name,
24763 "\n\tcurrent:", 1, "/", host->min_procs);
24767 if (fcgi_spawn_connection(srv, p, host, proc)) {
24768 log_error_write(srv, __FILE__, __LINE__, "s",
24769 "ERROR: spawning fcgi failed.");
24770 @@ -2662,18 +2539,18 @@
24773 if (srv->cur_ts <= proc->disabled_until) break;
24776 proc->state = PROC_STATE_RUNNING;
24777 host->active_procs++;
24779 - log_error_write(srv, __FILE__, __LINE__, "sb",
24780 - "fcgi-server re-enabled:",
24782 + log_error_write(srv, __FILE__, __LINE__, "sb",
24783 + "fcgi-server re-enabled:",
24784 proc->connection_name);
24794 @@ -2682,19 +2559,19 @@
24795 fcgi_extension_host *host= hctx->host;
24796 connection *con = hctx->remote_conn;
24802 - /* sanity check */
24803 + /* sanity check */
24805 ((!host->host->used || !host->port) && !host->unixsocket->used)) {
24806 - log_error_write(srv, __FILE__, __LINE__, "sxddd",
24807 + log_error_write(srv, __FILE__, __LINE__, "sxddd",
24808 "write-req: error",
24812 host->unixsocket->used);
24815 hctx->proc->disabled_until = srv->cur_ts + 10;
24816 hctx->proc->state = PROC_STATE_DIED;
24818 @@ -2705,12 +2582,12 @@
24819 if (hctx->state == FCGI_STATE_CONNECT_DELAYED) {
24821 socklen_t socket_error_len = sizeof(socket_error);
24824 /* try to finish the connect() */
24825 - if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
24826 - log_error_write(srv, __FILE__, __LINE__, "ss",
24827 + if (0 != getsockopt(hctx->sock->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
24828 + log_error_write(srv, __FILE__, __LINE__, "ss",
24829 "getsockopt failed:", strerror(errno));
24832 hctx->proc->disabled_until = srv->cur_ts + 10;
24833 hctx->proc->state = PROC_STATE_DIED;
24835 @@ -2719,12 +2596,12 @@
24836 if (socket_error != 0) {
24837 if (!hctx->proc->is_local || p->conf.debug) {
24838 /* local procs get restarted */
24841 log_error_write(srv, __FILE__, __LINE__, "sssb",
24842 - "establishing connection failed:", strerror(socket_error),
24843 + "establishing connection failed:", strerror(socket_error),
24844 "socket:", hctx->proc->connection_name);
24848 hctx->proc->disabled_until = srv->cur_ts + 5;
24850 if (hctx->proc->is_local) {
24851 @@ -2732,17 +2609,17 @@
24853 hctx->proc->state = PROC_STATE_DIED;
24857 hctx->proc->state = PROC_STATE_DIED;
24860 fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
24861 buffer_append_string(p->statuskey, ".died");
24863 - status_counter_inc(srv, CONST_BUF_LEN(p->statuskey));
24865 + status_counter_inc(CONST_BUF_LEN(p->statuskey));
24867 return HANDLER_ERROR;
24869 - /* go on with preparing the request */
24870 + /* go on with preparing the request */
24871 hctx->state = FCGI_STATE_PREPARE_WRITE;
24874 @@ -2755,14 +2632,14 @@
24875 /* do we have a running process for this host (max-procs) ? */
24878 - for (proc = hctx->host->first;
24879 - proc && proc->state != PROC_STATE_RUNNING;
24880 + for (proc = hctx->host->first;
24881 + proc && proc->state != PROC_STATE_RUNNING;
24882 proc = proc->next);
24885 /* all childs are dead */
24886 if (proc == NULL) {
24887 - hctx->fde_ndx = -1;
24889 + hctx->sock->fde_ndx = -1;
24891 return HANDLER_ERROR;
24894 @@ -2775,50 +2652,50 @@
24897 ret = host->unixsocket->used ? AF_UNIX : AF_INET;
24899 - if (-1 == (hctx->fd = socket(ret, SOCK_STREAM, 0))) {
24901 + if (-1 == (hctx->sock->fd = socket(ret, SOCK_STREAM, 0))) {
24902 if (errno == EMFILE ||
24904 - log_error_write(srv, __FILE__, __LINE__, "sd",
24905 - "wait for fd at connection:", con->fd);
24907 + log_error_write(srv, __FILE__, __LINE__, "sd",
24908 + "wait for fd at connection:", con->sock->fd);
24910 return HANDLER_WAIT_FOR_FD;
24913 - log_error_write(srv, __FILE__, __LINE__, "ssdd",
24915 + log_error_write(srv, __FILE__, __LINE__, "ssdd",
24916 "socket failed:", strerror(errno), srv->cur_fds, srv->max_fds);
24917 return HANDLER_ERROR;
24919 - hctx->fde_ndx = -1;
24921 + hctx->sock->fde_ndx = -1;
24925 - fdevent_register(srv->ev, hctx->fd, fcgi_handle_fdevent, hctx);
24927 - if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
24928 - log_error_write(srv, __FILE__, __LINE__, "ss",
24930 + fdevent_register(srv->ev, hctx->sock, fcgi_handle_fdevent, hctx);
24932 + if (-1 == fdevent_fcntl_set(srv->ev, hctx->sock)) {
24933 + log_error_write(srv, __FILE__, __LINE__, "ss",
24934 "fcntl failed:", strerror(errno));
24937 return HANDLER_ERROR;
24941 if (hctx->proc->is_local) {
24942 hctx->pid = hctx->proc->pid;
24946 switch (fcgi_establish_connection(srv, hctx)) {
24947 case CONNECTION_DELAYED:
24948 /* connection is in progress, wait for an event and call getsockopt() below */
24950 - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
24953 + fdevent_event_add(srv->ev, hctx->sock, FDEVENT_OUT);
24955 fcgi_set_state(srv, hctx, FCGI_STATE_CONNECT_DELAYED);
24956 return HANDLER_WAIT_FOR_EVENT;
24957 case CONNECTION_OVERLOADED:
24958 /* cool down the backend, it is overloaded
24961 - log_error_write(srv, __FILE__, __LINE__, "ssdsd",
24962 + log_error_write(srv, __FILE__, __LINE__, "ssdsd",
24963 "backend is overloaded, we disable it for a 2 seconds and send the request to another backend instead:",
24964 "reconnects:", hctx->reconnects,
24965 "load:", host->load);
24966 @@ -2830,8 +2707,8 @@
24967 fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
24968 buffer_append_string(p->statuskey, ".overloaded");
24970 - status_counter_inc(srv, CONST_BUF_LEN(p->statuskey));
24972 + status_counter_inc(CONST_BUF_LEN(p->statuskey));
24974 return HANDLER_ERROR;
24975 case CONNECTION_DEAD:
24976 /* we got a hard error from the backend like
24977 @@ -2840,67 +2717,67 @@
24979 * for check if the host is back in 5 seconds
24983 hctx->proc->disabled_until = srv->cur_ts + 5;
24984 if (hctx->proc->is_local) {
24985 hctx->proc->state = PROC_STATE_DIED_WAIT_FOR_PID;
24987 hctx->proc->state = PROC_STATE_DIED;
24990 - log_error_write(srv, __FILE__, __LINE__, "ssdsd",
24992 + log_error_write(srv, __FILE__, __LINE__, "ssdsd",
24993 "backend died, we disable it for a 5 seconds and send the request to another backend instead:",
24994 "reconnects:", hctx->reconnects,
24995 "load:", host->load);
24998 fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
24999 buffer_append_string(p->statuskey, ".died");
25001 - status_counter_inc(srv, CONST_BUF_LEN(p->statuskey));
25002 + status_counter_inc(CONST_BUF_LEN(p->statuskey));
25004 return HANDLER_ERROR;
25005 case CONNECTION_OK:
25006 /* everything is ok, go on */
25008 fcgi_set_state(srv, hctx, FCGI_STATE_PREPARE_WRITE);
25012 case CONNECTION_UNSET:
25017 case FCGI_STATE_PREPARE_WRITE:
25018 /* ok, we have the connection */
25021 hctx->proc->load++;
25022 hctx->proc->last_used = srv->cur_ts;
25023 hctx->got_proc = 1;
25025 - status_counter_inc(srv, CONST_STR_LEN("fastcgi.requests"));
25026 - status_counter_inc(srv, CONST_STR_LEN("fastcgi.active-requests"));
25028 + status_counter_inc(CONST_STR_LEN("fastcgi.requests"));
25029 + status_counter_inc(CONST_STR_LEN("fastcgi.active-requests"));
25031 fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
25032 buffer_append_string(p->statuskey, ".connected");
25034 - status_counter_inc(srv, CONST_BUF_LEN(p->statuskey));
25035 + status_counter_inc(CONST_BUF_LEN(p->statuskey));
25037 /* the proc-load */
25038 fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
25039 buffer_append_string(p->statuskey, ".load");
25041 - status_counter_set(srv, CONST_BUF_LEN(p->statuskey), hctx->proc->load);
25042 + status_counter_set(CONST_BUF_LEN(p->statuskey), hctx->proc->load);
25044 /* the host-load */
25045 fastcgi_status_copy_procname(p->statuskey, hctx->host, NULL);
25046 buffer_append_string(p->statuskey, ".load");
25048 - status_counter_set(srv, CONST_BUF_LEN(p->statuskey), hctx->host->load);
25049 + status_counter_set(CONST_BUF_LEN(p->statuskey), hctx->host->load);
25051 if (p->conf.debug) {
25052 log_error_write(srv, __FILE__, __LINE__, "ssdsbsd",
25054 - "pid:", hctx->proc->pid,
25055 - "socket:", hctx->proc->connection_name,
25057 + "pid:", hctx->proc->pid,
25058 + "socket:", hctx->proc->connection_name,
25059 "load:", hctx->proc->load);
25062 @@ -2908,74 +2785,75 @@
25063 if (hctx->request_id == 0) {
25064 hctx->request_id = fcgi_requestid_new(srv, p);
25066 - log_error_write(srv, __FILE__, __LINE__, "sd",
25067 + log_error_write(srv, __FILE__, __LINE__, "sd",
25068 "fcgi-request is already in use:", hctx->request_id);
25073 fcgi_create_env(srv, hctx, hctx->request_id);
25076 fcgi_set_state(srv, hctx, FCGI_STATE_WRITE);
25080 case FCGI_STATE_WRITE:
25081 - ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
25082 + ret = srv->network_backend_write(srv, con, hctx->sock, hctx->wb);
25084 chunkqueue_remove_finished_chunks(hctx->wb);
25090 - /* the connection got dropped after accept()
25092 - * this is most of the time a PHP which dies
25093 + /* the connection got dropped after accept()
25095 + * this is most of the time a PHP which dies
25096 * after PHP_FCGI_MAX_REQUESTS
25101 if (hctx->wb->bytes_out == 0 &&
25102 hctx->reconnects < 5) {
25103 - usleep(10000); /* take away the load of the webserver
25104 - * to let the php a chance to restart
25106 + usleep(10000); /* take away the load of the webserver
25107 + * to let the php a chance to restart
25111 fcgi_reconnect(srv, hctx);
25114 return HANDLER_WAIT_FOR_FD;
25118 /* not reconnected ... why
25121 * far@#lighttpd report this for FreeBSD
25126 - log_error_write(srv, __FILE__, __LINE__, "ssdsd",
25128 + log_error_write(srv, __FILE__, __LINE__, "ssosd",
25129 "[REPORT ME] connection was dropped after accept(). reconnect() denied:",
25130 "write-offset:", hctx->wb->bytes_out,
25131 "reconnect attempts:", hctx->reconnects);
25134 return HANDLER_ERROR;
25137 - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
25139 + fdevent_event_add(srv->ev, hctx->sock, FDEVENT_OUT);
25141 return HANDLER_WAIT_FOR_EVENT;
25143 - log_error_write(srv, __FILE__, __LINE__, "ssd",
25144 + log_error_write(srv, __FILE__, __LINE__, "ssd",
25145 "write failed:", strerror(errno), errno);
25148 return HANDLER_ERROR;
25152 if (hctx->wb->bytes_out == hctx->wb->bytes_in) {
25153 /* we don't need the out event anymore */
25154 - fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
25155 - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
25156 + fdevent_event_del(srv->ev, hctx->sock);
25157 + fdevent_event_add(srv->ev, hctx->sock, FDEVENT_IN);
25158 fcgi_set_state(srv, hctx, FCGI_STATE_READ);
25160 - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
25162 + fdevent_event_add(srv->ev, hctx->sock, FDEVENT_OUT);
25164 return HANDLER_WAIT_FOR_EVENT;
25167 @@ -2987,7 +2865,7 @@
25168 log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state");
25169 return HANDLER_ERROR;
25173 return HANDLER_WAIT_FOR_EVENT;
25176 @@ -2996,18 +2874,18 @@
25178 SUBREQUEST_FUNC(mod_fastcgi_handle_subrequest) {
25179 plugin_data *p = p_d;
25182 handler_ctx *hctx = con->plugin_ctx[p->id];
25184 fcgi_extension_host *host;
25187 if (NULL == hctx) return HANDLER_GO_ON;
25191 if (con->mode != p->id) return HANDLER_GO_ON;
25193 /* we don't have a host yet, choose one
25194 - * -> this happens in the first round
25195 + * -> this happens in the first round
25196 * and when the host died and we have to select a new one */
25197 if (hctx->host == NULL) {
25199 @@ -3016,23 +2894,23 @@
25200 /* get best server */
25201 for (k = 0, ndx = -1; k < hctx->ext->used; k++) {
25202 host = hctx->ext->hosts[k];
25205 /* we should have at least one proc that can do something */
25206 if (host->active_procs == 0) continue;
25208 if (used == -1 || host->load < used) {
25217 /* found a server */
25219 /* all hosts are down */
25221 fcgi_connection_close(srv, hctx);
25224 con->http_status = 500;
25225 con->mode = DIRECT;
25227 @@ -3040,16 +2918,16 @@
25230 host = hctx->ext->hosts[ndx];
25233 - * if check-local is disabled, use the uri.path handler
25237 + * if check-local is disabled, use the uri.path handler
25242 /* init handler-context */
25245 - /* we put a connection on this host, move the other new connections to other hosts
25246 + /* we put a connection on this host, move the other new connections to other hosts
25248 * as soon as hctx->host is unassigned, decrease the load again */
25249 hctx->host->load++;
25250 @@ -3063,7 +2941,7 @@
25251 case HANDLER_ERROR:
25256 if (hctx->state == FCGI_STATE_INIT ||
25257 hctx->state == FCGI_STATE_CONNECT_DELAYED) {
25258 if (proc) host->active_procs--;
25259 @@ -3078,7 +2956,7 @@
25260 return HANDLER_WAIT_FOR_FD;
25262 fcgi_connection_close(srv, hctx);
25265 buffer_reset(con->physical.path);
25266 con->mode = DIRECT;
25267 con->http_status = 500;
25268 @@ -3088,12 +2966,12 @@
25271 fcgi_connection_close(srv, hctx);
25274 buffer_reset(con->physical.path);
25275 con->mode = DIRECT;
25276 con->http_status = 503;
25277 joblist_append(srv, con); /* really ? */
25280 return HANDLER_FINISHED;
25282 case HANDLER_WAIT_FOR_EVENT:
25283 @@ -3115,7 +2993,7 @@
25284 handler_ctx *hctx = ctx;
25285 connection *con = hctx->remote_conn;
25286 plugin_data *p = hctx->plugin_data;
25289 fcgi_proc *proc = hctx->proc;
25290 fcgi_extension_host *host= hctx->host;
25292 @@ -3125,8 +3003,8 @@
25297 - if (host->mode == FCGI_AUTHORIZER &&
25299 + if (host->mode == FCGI_AUTHORIZER &&
25300 (con->http_status == 200 ||
25301 con->http_status == 0)) {
25303 @@ -3136,26 +3014,26 @@
25306 buffer_copy_string_buffer(con->physical.doc_root, host->docroot);
25309 buffer_copy_string_buffer(con->physical.path, host->docroot);
25310 buffer_append_string_buffer(con->physical.path, con->uri.path);
25311 fcgi_connection_close(srv, hctx);
25314 con->mode = DIRECT;
25315 con->file_started = 1; /* fcgi_extension won't touch the request afterwards */
25318 fcgi_connection_close(srv, hctx);
25322 joblist_append(srv, con);
25323 return HANDLER_FINISHED;
25325 if (proc->pid && proc->state != PROC_STATE_DIED) {
25329 /* only fetch the zombie if it is not already done */
25332 switch(waitpid(proc->pid, &status, WNOHANG)) {
25334 /* child is still alive */
25335 @@ -3165,60 +3043,61 @@
25337 /* the child should not terminate at all */
25338 if (WIFEXITED(status)) {
25339 - log_error_write(srv, __FILE__, __LINE__, "sdsd",
25340 + log_error_write(srv, __FILE__, __LINE__, "sdsd",
25341 "child exited, pid:", proc->pid,
25342 "status:", WEXITSTATUS(status));
25343 } else if (WIFSIGNALED(status)) {
25344 - log_error_write(srv, __FILE__, __LINE__, "sd",
25345 - "child signaled:",
25346 + log_error_write(srv, __FILE__, __LINE__, "sd",
25347 + "child signaled:",
25350 - log_error_write(srv, __FILE__, __LINE__, "sd",
25351 - "child died somehow:",
25352 + log_error_write(srv, __FILE__, __LINE__, "sd",
25353 + "child died somehow:",
25358 if (p->conf.debug) {
25359 log_error_write(srv, __FILE__, __LINE__, "ssbsdsd",
25360 "--- fastcgi spawning",
25361 "\n\tsocket", proc->connection_name,
25362 "\n\tcurrent:", 1, "/", host->min_procs);
25366 if (fcgi_spawn_connection(srv, p, host, proc)) {
25367 /* respawning failed, retry later */
25368 proc->state = PROC_STATE_DIED;
25370 - log_error_write(srv, __FILE__, __LINE__, "s",
25371 + log_error_write(srv, __FILE__, __LINE__, "s",
25372 "respawning failed, will retry later");
25381 if (con->file_started == 0) {
25382 /* nothing has been send out yet, try to use another child */
25385 if (hctx->wb->bytes_out == 0 &&
25386 hctx->reconnects < 5) {
25387 fcgi_reconnect(srv, hctx);
25389 - log_error_write(srv, __FILE__, __LINE__, "ssbsbs",
25391 + log_error_write(srv, __FILE__, __LINE__, "ssbsbs",
25392 "response not received, request not sent",
25393 - "on socket:", proc->connection_name,
25394 + "on socket:", proc->connection_name,
25395 "for", con->uri.path, ", reconnecting");
25398 return HANDLER_WAIT_FOR_FD;
25401 - log_error_write(srv, __FILE__, __LINE__, "sosbsbs",
25403 + log_error_write(srv, __FILE__, __LINE__, "sosbsbs",
25404 "response not received, request sent:", hctx->wb->bytes_out,
25405 - "on socket:", proc->connection_name,
25406 + "on socket:", proc->connection_name,
25407 "for", con->uri.path, ", closing connection");
25410 fcgi_connection_close(srv, hctx);
25413 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
25414 buffer_reset(con->physical.path);
25415 con->http_status = 500;
25416 @@ -3226,76 +3105,76 @@
25418 /* response might have been already started, kill the connection */
25419 fcgi_connection_close(srv, hctx);
25421 - log_error_write(srv, __FILE__, __LINE__, "ssbsbs",
25423 + log_error_write(srv, __FILE__, __LINE__, "ssbsbs",
25424 "response already sent out, but backend returned error",
25425 - "on socket:", proc->connection_name,
25426 + "on socket:", proc->connection_name,
25427 "for", con->uri.path, ", terminating connection");
25430 connection_set_state(srv, con, CON_STATE_ERROR);
25438 joblist_append(srv, con);
25439 return HANDLER_FINISHED;
25444 if (revents & FDEVENT_OUT) {
25445 if (hctx->state == FCGI_STATE_CONNECT_DELAYED ||
25446 hctx->state == FCGI_STATE_WRITE) {
25447 /* we are allowed to send something out
25450 * 1. in a unfinished connect() call
25451 * 2. in a unfinished write() call (long POST request)
25453 return mod_fastcgi_handle_subrequest(srv, con, p);
25455 - log_error_write(srv, __FILE__, __LINE__, "sd",
25456 - "got a FDEVENT_OUT and didn't know why:",
25457 + log_error_write(srv, __FILE__, __LINE__, "sd",
25458 + "got a FDEVENT_OUT and didn't know why:",
25464 /* perhaps this issue is already handled */
25465 if (revents & FDEVENT_HUP) {
25466 if (hctx->state == FCGI_STATE_CONNECT_DELAYED) {
25467 /* getoptsock will catch this one (right ?)
25469 - * if we are in connect we might get a EINPROGRESS
25470 - * in the first call and a FDEVENT_HUP in the
25472 + * if we are in connect we might get a EINPROGRESS
25473 + * in the first call and a FDEVENT_HUP in the
25477 * FIXME: as it is a bit ugly.
25481 return mod_fastcgi_handle_subrequest(srv, con, p);
25482 } else if (hctx->state == FCGI_STATE_READ &&
25483 hctx->proc->port == 0) {
25487 * ioctl says 8192 bytes to read from PHP and we receive directly a HUP for the socket
25488 * even if the FCGI_FIN packet is not received yet
25491 - log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd",
25492 - "error: unexpected close of fastcgi connection for",
25493 + log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd",
25494 + "error: unexpected close of fastcgi connection for",
25496 - "(no fastcgi process on host:",
25497 + "(no fastcgi process on host:",
25506 connection_set_state(srv, con, CON_STATE_ERROR);
25507 fcgi_connection_close(srv, hctx);
25508 joblist_append(srv, con);
25510 } else if (revents & FDEVENT_ERR) {
25511 - log_error_write(srv, __FILE__, __LINE__, "s",
25512 + log_error_write(srv, __FILE__, __LINE__, "s",
25513 "fcgi: got a FDEVENT_ERR. Don't know why.");
25514 /* kill all connections to the fastcgi process */
25516 @@ -3304,45 +3183,42 @@
25517 fcgi_connection_close(srv, hctx);
25518 joblist_append(srv, con);
25522 return HANDLER_FINISHED;
25524 -#define PATCH(x) \
25525 - p->conf.x = s->x;
25527 static int fcgi_patch_connection(server *srv, connection *con, plugin_data *p) {
25529 plugin_config *s = p->config_storage[0];
25533 - PATCH(ext_mapping);
25536 + PATCH_OPTION(exts);
25537 + PATCH_OPTION(debug);
25538 + PATCH_OPTION(ext_mapping);
25540 /* skip the first, the global context */
25541 for (i = 1; i < srv->config_context->used; i++) {
25542 data_config *dc = (data_config *)srv->config_context->data[i];
25543 s = p->config_storage[i];
25546 /* condition didn't match */
25547 if (!config_check_cond(srv, con, dc)) continue;
25551 for (j = 0; j < dc->value->used; j++) {
25552 data_unset *du = dc->value->data[j];
25555 if (buffer_is_equal_string(du->key, CONST_STR_LEN("fastcgi.server"))) {
25557 + PATCH_OPTION(exts);
25558 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("fastcgi.debug"))) {
25560 + PATCH_OPTION(debug);
25561 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("fastcgi.map-extensions"))) {
25562 - PATCH(ext_mapping);
25563 + PATCH_OPTION(ext_mapping);
25574 static handler_t fcgi_check_extension(server *srv, connection *con, void *p_d, int uri_path_handler) {
25575 plugin_data *p = p_d;
25576 @@ -3351,16 +3227,16 @@
25578 fcgi_extension *extension = NULL;
25579 fcgi_extension_host *host = NULL;
25582 /* Possibly, we processed already this request */
25583 if (con->file_started == 1) return HANDLER_GO_ON;
25585 fn = uri_path_handler ? con->uri.path : con->physical.path;
25587 if (buffer_is_empty(fn)) return HANDLER_GO_ON;
25590 s_len = fn->used - 1;
25593 fcgi_patch_connection(srv, con, p);
25595 /* fastcgi.map-extensions maps extensions to existing fastcgi.server entries
25596 @@ -3368,24 +3244,24 @@
25597 * fastcgi.map-extensions = ( ".php3" => ".php" )
25599 * fastcgi.server = ( ".php" => ... )
25604 /* check if extension-mapping matches */
25605 for (k = 0; k < p->conf.ext_mapping->used; k++) {
25606 data_string *ds = (data_string *)p->conf.ext_mapping->data[k];
25607 size_t ct_len; /* length of the config entry */
25610 if (ds->key->used == 0) continue;
25613 ct_len = ds->key->used - 1;
25616 if (s_len < ct_len) continue;
25619 /* found a mapping */
25620 if (0 == strncmp(fn->ptr + s_len - ct_len, ds->key->ptr, ct_len)) {
25621 /* check if we know the extension */
25624 /* we can reuse k here */
25625 for (k = 0; k < p->conf.exts->used; k++) {
25626 extension = p->conf.exts->exts[k];
25627 @@ -3407,15 +3283,15 @@
25628 /* check if extension matches */
25629 for (k = 0; k < p->conf.exts->used; k++) {
25630 size_t ct_len; /* length of the config entry */
25633 extension = p->conf.exts->exts[k];
25636 if (extension->key->used == 0) continue;
25639 ct_len = extension->key->used - 1;
25642 if (s_len < ct_len) continue;
25645 /* check extension in the form "/fcgi_pattern" */
25646 if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
25648 @@ -3441,10 +3317,10 @@
25652 - /* we found one host that is alive */
25653 + /* we found one host that is alive */
25659 /* sorry, we don't have a server alive for this ext */
25660 buffer_reset(con->physical.path);
25661 @@ -3459,72 +3335,72 @@
25662 "on", extension->key,
25667 return HANDLER_FINISHED;
25670 /* a note about no handler is not sent yey */
25671 extension->note_is_sent = 0;
25674 - * if check-local is disabled, use the uri.path handler
25677 + * if check-local is disabled, use the uri.path handler
25682 /* init handler-context */
25683 if (uri_path_handler) {
25684 if (host->check_local == 0) {
25689 hctx = handler_ctx_init();
25692 hctx->remote_conn = con;
25693 hctx->plugin_data = p;
25695 hctx->ext = extension;
25699 hctx->conf.exts = p->conf.exts;
25700 hctx->conf.debug = p->conf.debug;
25703 con->plugin_ctx[p->id] = hctx;
25709 if (con->conf.log_request_handling) {
25710 - log_error_write(srv, __FILE__, __LINE__, "s",
25711 + log_error_write(srv, __FILE__, __LINE__, "s",
25712 "handling it in mod_fastcgi");
25715 - /* the prefix is the SCRIPT_NAME,
25717 + /* the prefix is the SCRIPT_NAME,
25718 * everthing from start to the next slash
25719 * this is important for check-local = "disable"
25722 * if prefix = /admin.fcgi
25725 * /admin.fcgi/foo/bar
25728 * SCRIPT_NAME = /admin.fcgi
25729 * PATH_INFO = /foo/bar
25732 * if prefix = /fcgi-bin/
25735 * /fcgi-bin/foo/bar
25738 * SCRIPT_NAME = /fcgi-bin/foo
25745 /* the rewrite is only done for /prefix/? matches */
25746 if (extension->key->ptr[0] == '/' &&
25747 con->uri.path->used > extension->key->used &&
25748 NULL != (pathinfo = strchr(con->uri.path->ptr + extension->key->used - 1, '/'))) {
25749 - /* rewrite uri.path and pathinfo */
25751 + /* rewrite uri.path and pathinfo */
25753 buffer_copy_string(con->request.pathinfo, pathinfo);
25756 con->uri.path->used -= con->request.pathinfo->used - 1;
25757 con->uri.path->ptr[con->uri.path->used - 1] = '\0';
25759 @@ -3532,19 +3408,19 @@
25762 hctx = handler_ctx_init();
25765 hctx->remote_conn = con;
25766 hctx->plugin_data = p;
25768 hctx->ext = extension;
25771 hctx->conf.exts = p->conf.exts;
25772 hctx->conf.debug = p->conf.debug;
25775 con->plugin_ctx[p->id] = hctx;
25781 if (con->conf.log_request_handling) {
25782 log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_fastcgi");
25784 @@ -3566,19 +3442,19 @@
25785 JOBLIST_FUNC(mod_fastcgi_handle_joblist) {
25786 plugin_data *p = p_d;
25787 handler_ctx *hctx = con->plugin_ctx[p->id];
25790 if (hctx == NULL) return HANDLER_GO_ON;
25792 - if (hctx->fd != -1) {
25793 + if (hctx->sock->fd != -1) {
25794 switch (hctx->state) {
25795 case FCGI_STATE_READ:
25796 - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
25798 + fdevent_event_add(srv->ev, hctx->sock, FDEVENT_IN);
25801 case FCGI_STATE_CONNECT_DELAYED:
25802 case FCGI_STATE_WRITE:
25803 - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
25805 + fdevent_event_add(srv->ev, hctx->sock, FDEVENT_OUT);
25808 case FCGI_STATE_INIT:
25810 @@ -3595,7 +3471,7 @@
25812 static handler_t fcgi_connection_close_callback(server *srv, connection *con, void *p_d) {
25813 plugin_data *p = p_d;
25816 fcgi_connection_close(srv, con->plugin_ctx[p->id]);
25818 return HANDLER_GO_ON;
25819 @@ -3604,16 +3480,39 @@
25820 TRIGGER_FUNC(mod_fastcgi_handle_trigger) {
25821 plugin_data *p = p_d;
25827 /* perhaps we should kill a connect attempt after 10-15 seconds
25830 * currently we wait for the TCP timeout which is on Linux 180 seconds
25837 + for (i = 0; i < srv->conns->used; i++) {
25838 + connection *con = srv->conns->ptr[i];
25839 + handler_ctx *hctx = con->plugin_ctx[p->id];
25841 + /* if a connection is ours and is in handle-req for more than max-request-time
25842 + * kill the connection */
25844 + if (con->mode != p->id) continue;
25845 + if (con->state != CON_STATE_HANDLE_REQUEST) continue;
25846 + if (srv->cur_ts < con->request_start + 60) continue;
25848 + /* the request is waiting for a FCGI_STDOUT since 60 seconds */
25850 + /* kill the connection */
25852 + log_error_write(srv, __FILE__, __LINE__, "s", "fastcgi backend didn't responded after 60 seconds");
25854 + fcgi_connection_close(srv, hctx);
25856 + con->mode = DIRECT;
25857 + con->http_status = 500;
25859 + joblist_append(srv, con);
25862 /* check all childs if they are still up */
25864 for (i = 0; i < srv->config_context->used; i++) {
25865 @@ -3628,45 +3527,45 @@
25866 fcgi_extension *ex;
25868 ex = exts->exts[j];
25871 for (n = 0; n < ex->used; n++) {
25875 unsigned long sum_load = 0;
25876 fcgi_extension_host *host;
25879 host = ex->hosts[n];
25882 fcgi_restart_dead_procs(srv, p, host);
25885 for (proc = host->first; proc; proc = proc->next) {
25886 sum_load += proc->load;
25890 if (host->num_procs &&
25891 host->num_procs < host->max_procs &&
25892 (sum_load / host->num_procs) > host->max_load_per_proc) {
25893 /* overload, spawn new child */
25894 if (p->conf.debug) {
25895 - log_error_write(srv, __FILE__, __LINE__, "s",
25896 + log_error_write(srv, __FILE__, __LINE__, "s",
25897 "overload detected, spawning a new child");
25901 for (proc = host->unused_procs; proc && proc->pid != 0; proc = proc->next);
25905 if (proc == host->unused_procs) host->unused_procs = proc->next;
25908 if (proc->next) proc->next->prev = NULL;
25913 proc = fastcgi_process_init();
25914 proc->id = host->max_id++;
25921 if (buffer_is_empty(host->unixsocket)) {
25922 proc->port = host->port + proc->id;
25924 @@ -3674,13 +3573,13 @@
25925 buffer_append_string(proc->unixsocket, "-");
25926 buffer_append_long(proc->unixsocket, proc->id);
25930 if (fcgi_spawn_connection(srv, p, host, proc)) {
25931 log_error_write(srv, __FILE__, __LINE__, "s",
25932 "ERROR: spawning fcgi failed.");
25933 return HANDLER_ERROR;
25938 proc->next = host->first;
25940 @@ -3688,56 +3587,56 @@
25942 host->first = proc;
25946 for (proc = host->first; proc; proc = proc->next) {
25947 if (proc->load != 0) break;
25948 if (host->num_procs <= host->min_procs) break;
25949 if (proc->pid == 0) continue;
25952 if (srv->cur_ts - proc->last_used > host->idle_timeout) {
25953 /* a proc is idling for a long time now,
25957 if (p->conf.debug) {
25958 - log_error_write(srv, __FILE__, __LINE__, "ssbsd",
25959 - "idle-timeout reached, terminating child:",
25960 - "socket:", proc->connection_name,
25961 + log_error_write(srv, __FILE__, __LINE__, "ssbsd",
25962 + "idle-timeout reached, terminating child:",
25963 + "socket:", proc->connection_name,
25970 if (proc->next) proc->next->prev = proc->prev;
25971 if (proc->prev) proc->prev->next = proc->next;
25974 if (proc->prev == NULL) host->first = proc->next;
25978 proc->next = host->unused_procs;
25981 if (host->unused_procs) host->unused_procs->prev = proc;
25982 host->unused_procs = proc;
25985 kill(proc->pid, SIGTERM);
25988 proc->state = PROC_STATE_KILLED;
25990 - log_error_write(srv, __FILE__, __LINE__, "ssbsd",
25992 - "socket:", proc->connection_name,
25994 + log_error_write(srv, __FILE__, __LINE__, "ssbsd",
25996 + "socket:", proc->connection_name,
26003 /* proc is now in unused, let the next second handle the next process */
26010 for (proc = host->unused_procs; proc; proc = proc->next) {
26014 if (proc->pid == 0) continue;
26017 switch (waitpid(proc->pid, &status, WNOHANG)) {
26019 /* child still running after timeout, good */
26020 @@ -3745,10 +3644,10 @@
26022 if (errno != EINTR) {
26023 /* no PID found ? should never happen */
26024 - log_error_write(srv, __FILE__, __LINE__, "sddss",
26025 + log_error_write(srv, __FILE__, __LINE__, "sddss",
26026 "pid ", proc->pid, proc->state,
26027 "not found:", strerror(errno));
26031 if (errno == ECHILD) {
26032 /* someone else has cleaned up for us */
26033 @@ -3762,25 +3661,26 @@
26034 /* the child should not terminate at all */
26035 if (WIFEXITED(status)) {
26036 if (proc->state != PROC_STATE_KILLED) {
26037 - log_error_write(srv, __FILE__, __LINE__, "sdb",
26039 + log_error_write(srv, __FILE__, __LINE__, "sdb",
26041 WEXITSTATUS(status), proc->connection_name);
26043 } else if (WIFSIGNALED(status)) {
26044 if (WTERMSIG(status) != SIGTERM) {
26045 - log_error_write(srv, __FILE__, __LINE__, "sd",
26046 - "child signaled:",
26047 + log_error_write(srv, __FILE__, __LINE__, "sd",
26048 + "child signaled:",
26052 - log_error_write(srv, __FILE__, __LINE__, "sd",
26053 - "child died somehow:",
26054 + log_error_write(srv, __FILE__, __LINE__, "sd",
26055 + "child died somehow:",
26059 proc->state = PROC_STATE_UNSET;
26066 @@ -3804,8 +3704,8 @@
26067 p->handle_subrequest = mod_fastcgi_handle_subrequest;
26068 p->handle_joblist = mod_fastcgi_handle_joblist;
26069 p->handle_trigger = mod_fastcgi_handle_trigger;
26077 --- ../lighttpd-1.4.11/src/mod_flv_streaming.c 2006-03-07 14:06:26.000000000 +0200
26078 +++ lighttpd-1.4.12/src/mod_flv_streaming.c 2006-07-16 00:26:04.000000000 +0300
26079 @@ -23,35 +23,35 @@
26089 plugin_config **config_storage;
26091 - plugin_config conf;
26093 + plugin_config conf;
26096 /* init the plugin data */
26097 INIT_FUNC(mod_flv_streaming_init) {
26101 p = calloc(1, sizeof(*p));
26104 p->query_str = buffer_init();
26105 p->get_params = array_init();
26111 /* detroy the plugin data */
26112 FREE_FUNC(mod_flv_streaming_free) {
26113 plugin_data *p = p_d;
26118 if (!p) return HANDLER_GO_ON;
26121 if (p->config_storage) {
26124 @@ -59,19 +59,19 @@
26125 plugin_config *s = p->config_storage[i];
26130 array_free(s->extensions);
26135 free(p->config_storage);
26139 buffer_free(p->query_str);
26140 array_free(p->get_params);
26146 return HANDLER_GO_ON;
26149 @@ -80,83 +80,80 @@
26150 SETDEFAULTS_FUNC(mod_flv_streaming_set_defaults) {
26151 plugin_data *p = p_d;
26154 - config_values_t cv[] = {
26156 + config_values_t cv[] = {
26157 { "flv-streaming.extensions", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
26158 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
26162 if (!p) return HANDLER_ERROR;
26165 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
26168 for (i = 0; i < srv->config_context->used; i++) {
26172 s = calloc(1, sizeof(plugin_config));
26173 s->extensions = array_init();
26176 cv[0].destination = s->extensions;
26179 p->config_storage[i] = s;
26182 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
26183 return HANDLER_ERROR;
26188 return HANDLER_GO_ON;
26191 -#define PATCH(x) \
26192 - p->conf.x = s->x;
26193 static int mod_flv_streaming_patch_connection(server *srv, connection *con, plugin_data *p) {
26195 plugin_config *s = p->config_storage[0];
26197 - PATCH(extensions);
26200 + PATCH_OPTION(extensions);
26202 /* skip the first, the global context */
26203 for (i = 1; i < srv->config_context->used; i++) {
26204 data_config *dc = (data_config *)srv->config_context->data[i];
26205 s = p->config_storage[i];
26208 /* condition didn't match */
26209 if (!config_check_cond(srv, con, dc)) continue;
26213 for (j = 0; j < dc->value->used; j++) {
26214 data_unset *du = dc->value->data[j];
26217 if (buffer_is_equal_string(du->key, CONST_STR_LEN("flv-streaming.extensions"))) {
26218 - PATCH(extensions);
26219 + PATCH_OPTION(extensions);
26229 -static int split_get_params(server *srv, connection *con, array *get_params, buffer *qrystr) {
26230 +static int split_get_params(array *get_params, buffer *qrystr) {
26233 char *key = NULL, *val = NULL;
26239 /* we need the \0 */
26240 for (i = 0; i < qrystr->used; i++) {
26241 switch(qrystr->ptr[i]) {
26244 val = qrystr->ptr + i + 1;
26247 qrystr->ptr[i] = '\0';
26256 case '\0': /* fin symbol */
26257 @@ -167,7 +164,7 @@
26258 /* terminate the value */
26259 qrystr->ptr[i] = '\0';
26261 - if (NULL == (ds = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
26262 + if (NULL == (ds = (data_string *)array_get_unused_element(get_params, TYPE_STRING))) {
26263 ds = data_string_init();
26265 buffer_copy_string_len(ds->key, key, strlen(key));
26266 @@ -175,14 +172,14 @@
26268 array_insert_unique(get_params, (data_unset *)ds);
26272 key = qrystr->ptr + i + 1;
26283 @@ -190,34 +187,34 @@
26284 plugin_data *p = p_d;
26291 if (buffer_is_empty(con->physical.path)) return HANDLER_GO_ON;
26294 mod_flv_streaming_patch_connection(srv, con, p);
26296 s_len = con->physical.path->used - 1;
26299 for (k = 0; k < p->conf.extensions->used; k++) {
26300 data_string *ds = (data_string *)p->conf.extensions->data[k];
26301 int ct_len = ds->value->used - 1;
26304 if (ct_len > s_len) continue;
26305 if (ds->value->used == 0) continue;
26308 if (0 == strncmp(con->physical.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
26309 data_string *get_param;
26310 stat_cache_entry *sce = NULL;
26314 - /* if there is a start=[0-9]+ in the header use it as start,
26315 + /* if there is a start=[0-9]+ in the header use it as start,
26316 * otherwise send the full file */
26318 array_reset(p->get_params);
26319 buffer_copy_string_buffer(p->query_str, con->uri.query);
26320 - split_get_params(srv, con, p->get_params, p->query_str);
26321 + split_get_params(p->get_params, p->query_str);
26323 if (NULL == (get_param = (data_string *)array_get_element(p->get_params, "start"))) {
26324 return HANDLER_GO_ON;
26325 @@ -256,7 +253,7 @@
26326 return HANDLER_FINISHED;
26332 return HANDLER_GO_ON;
26334 @@ -266,13 +263,13 @@
26335 int mod_flv_streaming_plugin_init(plugin *p) {
26336 p->version = LIGHTTPD_VERSION_ID;
26337 p->name = buffer_init_string("flv_streaming");
26340 p->init = mod_flv_streaming_init;
26341 p->handle_physical = mod_flv_streaming_path_handler;
26342 p->set_defaults = mod_flv_streaming_set_defaults;
26343 p->cleanup = mod_flv_streaming_free;
26351 --- ../lighttpd-1.4.11/src/mod_indexfile.c 2005-09-30 01:08:53.000000000 +0300
26352 +++ lighttpd-1.4.12/src/mod_indexfile.c 2006-07-16 00:26:04.000000000 +0300
26355 #include "stat_cache.h"
26357 +#include "sys-strings.h"
26358 +#include "sys-files.h"
26359 /* plugin config for all request/connections */
26362 @@ -20,51 +22,51 @@
26371 plugin_config **config_storage;
26373 - plugin_config conf;
26375 + plugin_config conf;
26378 /* init the plugin data */
26379 INIT_FUNC(mod_indexfile_init) {
26383 p = calloc(1, sizeof(*p));
26386 p->tmp_buf = buffer_init();
26392 /* detroy the plugin data */
26393 FREE_FUNC(mod_indexfile_free) {
26394 plugin_data *p = p_d;
26399 if (!p) return HANDLER_GO_ON;
26402 if (p->config_storage) {
26404 for (i = 0; i < srv->config_context->used; i++) {
26405 plugin_config *s = p->config_storage[i];
26410 array_free(s->indexfiles);
26415 free(p->config_storage);
26419 buffer_free(p->tmp_buf);
26425 return HANDLER_GO_ON;
26428 @@ -73,131 +75,139 @@
26429 SETDEFAULTS_FUNC(mod_indexfile_set_defaults) {
26430 plugin_data *p = p_d;
26433 - config_values_t cv[] = {
26435 + config_values_t cv[] = {
26436 { "index-file.names", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
26437 { "server.indexfiles", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
26438 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
26442 if (!p) return HANDLER_ERROR;
26445 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
26448 for (i = 0; i < srv->config_context->used; i++) {
26452 s = calloc(1, sizeof(plugin_config));
26453 s->indexfiles = array_init();
26456 cv[0].destination = s->indexfiles;
26457 cv[1].destination = s->indexfiles; /* old name for [0] */
26460 p->config_storage[i] = s;
26463 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
26464 return HANDLER_ERROR;
26469 return HANDLER_GO_ON;
26472 -#define PATCH(x) \
26473 - p->conf.x = s->x;
26474 static int mod_indexfile_patch_connection(server *srv, connection *con, plugin_data *p) {
26476 plugin_config *s = p->config_storage[0];
26478 - PATCH(indexfiles);
26481 + PATCH_OPTION(indexfiles);
26483 /* skip the first, the global context */
26484 for (i = 1; i < srv->config_context->used; i++) {
26485 data_config *dc = (data_config *)srv->config_context->data[i];
26486 s = p->config_storage[i];
26489 /* condition didn't match */
26490 if (!config_check_cond(srv, con, dc)) continue;
26494 for (j = 0; j < dc->value->used; j++) {
26495 data_unset *du = dc->value->data[j];
26498 if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.indexfiles"))) {
26499 - PATCH(indexfiles);
26500 + PATCH_OPTION(indexfiles);
26501 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("index-file.names"))) {
26502 - PATCH(indexfiles);
26503 + PATCH_OPTION(indexfiles);
26513 URIHANDLER_FUNC(mod_indexfile_subrequest) {
26514 plugin_data *p = p_d;
26516 stat_cache_entry *sce = NULL;
26519 if (con->uri.path->used == 0) return HANDLER_GO_ON;
26520 if (con->uri.path->ptr[con->uri.path->used - 2] != '/') return HANDLER_GO_ON;
26523 mod_indexfile_patch_connection(srv, con, p);
26526 + /* is the physical-path really a dir ? */
26527 + if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
26528 + return HANDLER_GO_ON;
26531 + if (!S_ISDIR(sce->st.st_mode)) {
26532 + return HANDLER_GO_ON;
26535 if (con->conf.log_request_handling) {
26536 log_error_write(srv, __FILE__, __LINE__, "s", "-- handling the request as Indexfile");
26537 log_error_write(srv, __FILE__, __LINE__, "sb", "URI :", con->uri.path);
26543 for (k = 0; k < p->conf.indexfiles->used; k++) {
26544 data_string *ds = (data_string *)p->conf.indexfiles->data[k];
26547 if (ds->value && ds->value->ptr[0] == '/') {
26548 - /* if the index-file starts with a prefix as use this file as
26549 + /* if the index-file starts with a prefix as use this file as
26550 * index-generator */
26551 buffer_copy_string_buffer(p->tmp_buf, con->physical.doc_root);
26553 buffer_copy_string_buffer(p->tmp_buf, con->physical.path);
26554 + PATHNAME_APPEND_SLASH(p->tmp_buf);
26556 buffer_append_string_buffer(p->tmp_buf, ds->value);
26559 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->tmp_buf, &sce)) {
26560 if (errno == EACCES) {
26561 con->http_status = 403;
26562 buffer_reset(con->physical.path);
26565 return HANDLER_FINISHED;
26569 if (errno != ENOENT &&
26570 errno != ENOTDIR) {
26571 /* we have no idea what happend. let's tell the user so. */
26574 con->http_status = 500;
26577 log_error_write(srv, __FILE__, __LINE__, "ssbsb",
26578 "file not found ... or so: ", strerror(errno),
26580 "->", con->physical.path);
26583 buffer_reset(con->physical.path);
26586 return HANDLER_FINISHED;
26592 /* rewrite uri.path to the real path (/ -> /index.php) */
26593 buffer_append_string_buffer(con->uri.path, ds->value);
26594 buffer_copy_string_buffer(con->physical.path, p->tmp_buf);
26597 /* fce is already set up a few lines above */
26600 return HANDLER_GO_ON;
26605 return HANDLER_GO_ON;
26607 @@ -207,13 +217,13 @@
26608 int mod_indexfile_plugin_init(plugin *p) {
26609 p->version = LIGHTTPD_VERSION_ID;
26610 p->name = buffer_init_string("indexfile");
26613 p->init = mod_indexfile_init;
26614 p->handle_subrequest_start = mod_indexfile_subrequest;
26615 p->set_defaults = mod_indexfile_set_defaults;
26616 p->cleanup = mod_indexfile_free;
26624 --- ../lighttpd-1.4.11/src/mod_mysql_vhost.c 2006-01-14 20:35:10.000000000 +0200
26625 +++ lighttpd-1.4.12/src/mod_mysql_vhost.c 2006-07-20 00:57:19.000000000 +0300
26627 -#include <unistd.h>
26631 -#include <strings.h>
26632 +#include <string.h>
26634 #ifdef HAVE_CONFIG_H
26635 #include "config.h"
26638 +#ifdef HAVE_MYSQL_H
26639 +# ifdef HAVE_LIBMYSQL
26640 +# define HAVE_MYSQL
26647 @@ -16,61 +21,40 @@
26650 #include "stat_cache.h"
26651 -#ifdef DEBUG_MOD_MYSQL_VHOST
26654 +#include "sys-files.h"
26657 - * Plugin for lighttpd to use MySQL
26658 - * for domain to directory lookups,
26659 - * i.e virtual hosts (vhosts).
26661 - * Optionally sets fcgi_offset and fcgi_arg
26662 - * in preparation for fcgi.c to handle
26663 - * per-user fcgi chroot jails.
26665 - * /ada@riksnet.se 2004-12-06
26667 +#include "mod_sql_vhost_core.h"
26671 +#define CORE_PLUGIN "mod_sql_vhost_core"
26681 - buffer *hostname;
26682 - unsigned short port;
26686 buffer *mysql_post;
26688 + mod_sql_vhost_core_plugin_config *core;
26691 /* global plugin data */
26699 plugin_config **config_storage;
26701 - plugin_config conf;
26703 + plugin_config conf;
26706 -/* per connection plugin data */
26708 - buffer *server_name;
26709 - buffer *document_root;
26710 - buffer *fcgi_arg;
26711 - unsigned fcgi_offset;
26712 -} plugin_connection_data;
26713 +SQLVHOST_BACKEND_GETVHOST(mod_mysql_vhost_get_vhost);
26715 /* init the plugin data */
26716 INIT_FUNC(mod_mysql_vhost_init) {
26720 p = calloc(1, sizeof(*p));
26722 p->tmp_buf = buffer_init();
26723 @@ -83,144 +67,77 @@
26724 plugin_data *p = p_d;
26729 - log_error_write(srv, __FILE__, __LINE__, "ss",
26730 - "mod_mysql_vhost_cleanup", p ? "yes" : "NO");
26733 if (!p) return HANDLER_GO_ON;
26736 if (p->config_storage) {
26738 for (i = 0; i < srv->config_context->used; i++) {
26739 plugin_config *s = p->config_storage[i];
26744 mysql_close(s->mysql);
26746 - buffer_free(s->mydb);
26747 - buffer_free(s->myuser);
26748 - buffer_free(s->mypass);
26749 - buffer_free(s->mysock);
26751 buffer_free(s->mysql_pre);
26752 buffer_free(s->mysql_post);
26757 free(p->config_storage);
26759 buffer_free(p->tmp_buf);
26763 - return HANDLER_GO_ON;
26766 -/* handle the plugin per connection data */
26767 -static void* mod_mysql_vhost_connection_data(server *srv, connection *con, void *p_d)
26769 - plugin_data *p = p_d;
26770 - plugin_connection_data *c = con->plugin_ctx[p->id];
26775 - log_error_write(srv, __FILE__, __LINE__, "ss",
26776 - "mod_mysql_connection_data", c ? "old" : "NEW");
26780 - c = calloc(1, sizeof(*c));
26782 - c->server_name = buffer_init();
26783 - c->document_root = buffer_init();
26784 - c->fcgi_arg = buffer_init();
26785 - c->fcgi_offset = 0;
26787 - return con->plugin_ctx[p->id] = c;
26790 -/* destroy the plugin per connection data */
26791 -CONNECTION_FUNC(mod_mysql_vhost_handle_connection_close) {
26792 - plugin_data *p = p_d;
26793 - plugin_connection_data *c = con->plugin_ctx[p->id];
26798 - log_error_write(srv, __FILE__, __LINE__, "ss",
26799 - "mod_mysql_vhost_handle_connection_close", c ? "yes" : "NO");
26802 - if (!c) return HANDLER_GO_ON;
26804 - buffer_free(c->server_name);
26805 - buffer_free(c->document_root);
26806 - buffer_free(c->fcgi_arg);
26807 - c->fcgi_offset = 0;
26812 - con->plugin_ctx[p->id] = NULL;
26813 return HANDLER_GO_ON;
26816 /* set configuration values */
26817 SERVER_FUNC(mod_mysql_vhost_set_defaults) {
26818 plugin_data *p = p_d;
26819 + mod_sql_vhost_core_plugin_data *core_config;
26824 - config_values_t cv[] = {
26825 - { "mysql-vhost.db", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
26826 - { "mysql-vhost.user", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
26827 - { "mysql-vhost.pass", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
26828 - { "mysql-vhost.sock", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
26829 - { "mysql-vhost.sql", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
26830 - { "mysql-vhost.hostname", NULL, T_CONFIG_STRING,T_CONFIG_SCOPE_SERVER },
26831 - { "mysql-vhost.port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER },
26832 - { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
26835 + /* our very own plugin storage, one entry for each conditional
26837 + * srv->config_context->used is the number of conditionals
26839 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
26842 + /* get the config of the core-plugin */
26843 + core_config = plugin_get_config(srv, CORE_PLUGIN);
26846 + /* walk through all conditionals and check for assignments */
26847 for (i = 0; i < srv->config_context->used; i++) {
26854 + /* get the config from the core plugin for this conditional-context */
26855 s = calloc(1, sizeof(plugin_config));
26856 - s->mydb = buffer_init();
26857 - s->myuser = buffer_init();
26858 - s->mypass = buffer_init();
26859 - s->mysock = buffer_init();
26860 - s->hostname = buffer_init();
26861 - s->port = 0; /* default port for mysql */
26862 - sel = buffer_init();
26865 + s->core = core_config->config_storage[i];
26869 s->mysql_pre = buffer_init();
26870 s->mysql_post = buffer_init();
26872 - cv[0].destination = s->mydb;
26873 - cv[1].destination = s->myuser;
26874 - cv[2].destination = s->mypass;
26875 - cv[3].destination = s->mysock;
26876 - cv[4].destination = sel;
26877 - cv[5].destination = s->hostname;
26878 - cv[6].destination = &(s->port);
26881 p->config_storage[i] = s;
26883 - if (config_insert_values_global(srv,
26884 - ((data_config *)srv->config_context->data[i])->value,
26885 - cv)) return HANDLER_ERROR;
26887 - s->mysql_pre = buffer_init();
26888 - s->mysql_post = buffer_init();
26891 + /* check if we are the plugin for this backend */
26892 + if (!buffer_is_equal_string(s->core->backend, CONST_STR_LEN("mysql"))) continue;
26894 + /* attach us to the core-plugin */
26895 + s->core->backend_data = p;
26896 + s->core->get_vhost = mod_mysql_vhost_get_vhost;
26898 + sel = buffer_init();
26899 + buffer_copy_string_buffer(sel, s->core->select_vhost);
26901 if (sel->used && (qmark = index(sel->ptr, '?'))) {
26903 buffer_copy_string(s->mysql_pre, sel->ptr);
26904 @@ -228,35 +145,38 @@
26906 buffer_copy_string_buffer(s->mysql_pre, sel);
26909 + buffer_free(sel);
26918 * - password, default: empty
26919 * - socket, default: mysql default
26920 * - hostname, if set overrides socket
26921 * - port, default: 3306
26925 /* all have to be set */
26926 - if (!(buffer_is_empty(s->myuser) ||
26927 - buffer_is_empty(s->mydb))) {
26928 + if (!(buffer_is_empty(s->core->user) ||
26929 + buffer_is_empty(s->core->db))) {
26934 if (NULL == (s->mysql = mysql_init(NULL))) {
26935 log_error_write(srv, __FILE__, __LINE__, "s", "mysql_init() failed, exiting...");
26938 return HANDLER_ERROR;
26940 -#define FOO(x) (s->x->used ? s->x->ptr : NULL)
26942 - if (!mysql_real_connect(s->mysql, FOO(hostname), FOO(myuser), FOO(mypass),
26943 - FOO(mydb), s->port, FOO(mysock), 0)) {
26944 +#define FOO(x) (s->core->x->used ? s->core->x->ptr : NULL)
26946 + s->mysql->free_me = 1;
26948 + if (!mysql_real_connect(s->mysql, FOO(hostname), FOO(user), FOO(pass),
26949 + FOO(db), s->core->port, FOO(sock), 0)) {
26950 log_error_write(srv, __FILE__, __LINE__, "s", mysql_error(s->mysql));
26953 return HANDLER_ERROR;
26956 @@ -265,61 +185,47 @@
26957 /* otherwise we cannot be sure that mysql is fd i-1 */
26958 if (-1 == (fd = open("/dev/null", 0))) {
26960 - fcntl(fd-1, F_SETFD, FD_CLOEXEC);
26961 + fcntl(fd-1, F_SETFD, FD_CLOEXEC);
26970 return HANDLER_GO_ON;
26973 -#define PATCH(x) \
26974 - p->conf.x = s->x;
26975 static int mod_mysql_vhost_patch_connection(server *srv, connection *con, plugin_data *p) {
26978 plugin_config *s = p->config_storage[0];
26980 - PATCH(mysql_pre);
26981 - PATCH(mysql_post);
26987 + PATCH_OPTION(mysql_pre);
26988 + PATCH_OPTION(mysql_post);
26989 + PATCH_OPTION(mysql);
26991 /* skip the first, the global context */
26992 for (i = 1; i < srv->config_context->used; i++) {
26993 data_config *dc = (data_config *)srv->config_context->data[i];
26994 s = p->config_storage[i];
26997 /* condition didn't match */
26998 if (!config_check_cond(srv, con, dc)) continue;
27000 - /* merge config */
27001 - for (j = 0; j < dc->value->used; j++) {
27002 - data_unset *du = dc->value->data[j];
27004 - if (buffer_is_equal_string(du->key, CONST_STR_LEN("mysql-vhost.sql"))) {
27005 - PATCH(mysql_pre);
27006 - PATCH(mysql_post);
27013 + PATCH_OPTION(mysql);
27014 + PATCH_OPTION(mysql_pre);
27015 + PATCH_OPTION(mysql_post);
27025 -/* handle document root request */
27026 -CONNECTION_FUNC(mod_mysql_vhost_handle_docroot) {
27028 + * get the vhost info from the database
27030 +SQLVHOST_BACKEND_GETVHOST(mod_mysql_vhost_get_vhost) {
27031 plugin_data *p = p_d;
27032 - plugin_connection_data *c;
27033 - stat_cache_entry *sce;
27037 @@ -332,13 +238,6 @@
27039 if (!p->conf.mysql) return HANDLER_GO_ON;
27041 - /* sets up connection data if not done yet */
27042 - c = mod_mysql_vhost_connection_data(srv, con, p_d);
27044 - /* check if cached this connection */
27045 - if (c->server_name->used && /* con->uri.authority->used && */
27046 - buffer_is_equal(c->server_name, con->uri.authority)) goto GO_ON;
27048 /* build and run SQL query */
27049 buffer_copy_string_buffer(p->tmp_buf, p->conf.mysql_pre);
27050 if (p->conf.mysql_post->used) {
27051 @@ -347,77 +246,43 @@
27053 if (mysql_query(p->conf.mysql, p->tmp_buf->ptr)) {
27054 log_error_write(srv, __FILE__, __LINE__, "s", mysql_error(p->conf.mysql));
27057 + mysql_free_result(result);
27058 + return HANDLER_GO_ON;
27060 result = mysql_store_result(p->conf.mysql);
27061 cols = mysql_num_fields(result);
27062 row = mysql_fetch_row(result);
27064 if (!row || cols < 1) {
27065 /* no such virtual host */
27066 mysql_free_result(result);
27067 return HANDLER_GO_ON;
27070 - /* sanity check that really is a directory */
27071 - buffer_copy_string(p->tmp_buf, row[0]);
27072 - BUFFER_APPEND_SLASH(p->tmp_buf);
27074 - if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->tmp_buf, &sce)) {
27075 - log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), p->tmp_buf);
27078 - if (!S_ISDIR(sce->st.st_mode)) {
27079 - log_error_write(srv, __FILE__, __LINE__, "sb", "Not a directory", p->tmp_buf);
27082 + buffer_copy_string(docroot, row[0]);
27084 - /* cache the data */
27085 - buffer_copy_string_buffer(c->server_name, con->uri.authority);
27086 - buffer_copy_string_buffer(c->document_root, p->tmp_buf);
27088 - /* fcgi_offset and fcgi_arg are optional */
27089 - if (cols > 1 && row[1]) {
27090 - c->fcgi_offset = atoi(row[1]);
27092 - if (cols > 2 && row[2]) {
27093 - buffer_copy_string(c->fcgi_arg, row[2]);
27095 - c->fcgi_arg->used = 0;
27098 - c->fcgi_offset = c->fcgi_arg->used = 0;
27100 mysql_free_result(result);
27102 - /* fix virtual server and docroot */
27103 -GO_ON: buffer_copy_string_buffer(con->server_name, c->server_name);
27104 - buffer_copy_string_buffer(con->physical.doc_root, c->document_root);
27107 - log_error_write(srv, __FILE__, __LINE__, "sbbdb",
27108 - result ? "NOT CACHED" : "cached",
27109 - con->server_name, con->physical.doc_root,
27110 - c->fcgi_offset, c->fcgi_arg);
27112 - return HANDLER_GO_ON;
27114 -ERR500: if (result) mysql_free_result(result);
27115 - con->http_status = 500; /* Internal Error */
27116 - return HANDLER_FINISHED;
27117 + return HANDLER_GO_ON;
27120 /* this function is called at dlopen() time and inits the callbacks */
27121 int mod_mysql_vhost_plugin_init(plugin *p) {
27124 p->version = LIGHTTPD_VERSION_ID;
27125 p->name = buffer_init_string("mysql_vhost");
27127 p->init = mod_mysql_vhost_init;
27128 p->cleanup = mod_mysql_vhost_cleanup;
27129 - p->handle_request_done = mod_mysql_vhost_handle_connection_close;
27131 p->set_defaults = mod_mysql_vhost_set_defaults;
27132 - p->handle_docroot = mod_mysql_vhost_handle_docroot;
27134 + ds = data_string_init();
27135 + buffer_copy_string(ds->value, CORE_PLUGIN);
27136 + array_insert_unique(p->required_plugins, (data_unset *)ds);
27141 --- ../lighttpd-1.4.11/src/mod_proxy.c 2006-01-31 13:01:22.000000000 +0200
27142 +++ lighttpd-1.4.12/src/mod_proxy.c 2006-07-19 20:02:55.000000000 +0300
27144 #include <sys/types.h>
27146 -#include <unistd.h>
27149 #include <string.h>
27152 #include "inet_ntop_cache.h"
27154 +#include "network.h"
27156 +#include "http_resp.h"
27163 #include "sys-socket.h"
27164 +#include "sys-files.h"
27165 +#include "sys-strings.h"
27167 #define data_proxy data_fastcgi
27168 #define data_proxy_init data_fastcgi_init
27169 @@ -38,22 +42,25 @@
27170 #define PROXY_RETRY_TIMEOUT 60
27174 - * the proxy module is based on the fastcgi module
27177 + * the proxy module is based on the fastcgi module
27179 * 28.06.2004 Jan Kneschke The first release
27180 * 01.07.2004 Evgeny Rodichev Several bugfixes and cleanups
27181 * - co-ordinate up- and downstream flows correctly (proxy_demux_response
27182 * and proxy_handle_fdevent)
27183 * - correctly transfer upstream http_response_status;
27184 * - some unused structures removed.
27187 * TODO: - delay upstream read if write_queue is too large
27188 * (to prevent memory eating, like in apache). Shoud be
27190 * - persistent connection with upstream servers
27197 PROXY_BALANCE_UNSET,
27198 PROXY_BALANCE_FAIR,
27199 @@ -66,26 +73,33 @@
27202 proxy_balance_t balance;
27204 + array *last_used_backends; /* "extension" : last_used_backend */
27211 buffer *parse_response;
27212 buffer *balance_buf;
27217 + array *ignore_headers;
27219 plugin_config **config_storage;
27222 plugin_config conf;
27226 - PROXY_STATE_INIT,
27227 - PROXY_STATE_CONNECT,
27228 - PROXY_STATE_PREPARE_WRITE,
27229 - PROXY_STATE_WRITE,
27230 - PROXY_STATE_READ,
27231 - PROXY_STATE_ERROR
27233 + PROXY_STATE_INIT,
27234 + PROXY_STATE_CONNECT,
27235 + PROXY_STATE_PREPARE_WRITE,
27236 + PROXY_STATE_WRITE,
27237 + PROXY_STATE_RESPONSE_HEADER,
27238 + PROXY_STATE_RESPONSE_CONTENT,
27239 + PROXY_STATE_ERROR
27240 } proxy_connection_state_t;
27242 enum { PROXY_STDOUT, PROXY_END_REQUEST };
27243 @@ -93,19 +107,16 @@
27245 proxy_connection_state_t state;
27246 time_t state_timestamp;
27251 - buffer *response;
27252 - buffer *response_header;
27256 - int fd; /* fd to the proxy process */
27257 - int fde_ndx; /* index into the fd-event buffer */
27260 + iosocket *sock; /* fd to the proxy process */
27262 size_t path_info_offset; /* start of path_info in uri.path */
27265 connection *remote_conn; /* dump pointer */
27266 plugin_data *plugin_data; /* dump pointer */
27268 @@ -116,69 +127,89 @@
27270 static handler_ctx * handler_ctx_init() {
27271 handler_ctx * hctx;
27275 hctx = calloc(1, sizeof(*hctx));
27278 hctx->state = PROXY_STATE_INIT;
27281 - hctx->response = buffer_init();
27282 - hctx->response_header = buffer_init();
27284 hctx->wb = chunkqueue_init();
27285 + hctx->rb = chunkqueue_init();
27287 + hctx->sock = iosocket_init();
27290 - hctx->fde_ndx = -1;
27295 static void handler_ctx_free(handler_ctx *hctx) {
27296 - buffer_free(hctx->response);
27297 - buffer_free(hctx->response_header);
27298 chunkqueue_free(hctx->wb);
27300 + chunkqueue_free(hctx->rb);
27302 + iosocket_free(hctx->sock);
27307 INIT_FUNC(mod_proxy_init) {
27312 + char *hop2hop_headers[] = {
27319 p = calloc(1, sizeof(*p));
27321 - p->parse_response = buffer_init();
27323 p->balance_buf = buffer_init();
27325 + p->ignore_headers = array_init();
27326 + p->resp = http_response_init();
27328 + for (i = 0; hop2hop_headers[i]; i++) {
27331 + if (NULL == (ds = (data_string *)array_get_unused_element(p->ignore_headers, TYPE_STRING))) {
27332 + ds = data_string_init();
27335 + buffer_copy_string(ds->key, hop2hop_headers[i]);
27336 + buffer_copy_string(ds->value, hop2hop_headers[i]);
27337 + array_insert_unique(p->ignore_headers, (data_unset *)ds);
27344 FREE_FUNC(mod_proxy_free) {
27345 plugin_data *p = p_d;
27350 - buffer_free(p->parse_response);
27351 - buffer_free(p->balance_buf);
27353 if (p->config_storage) {
27355 for (i = 0; i < srv->config_context->used; i++) {
27356 plugin_config *s = p->config_storage[i];
27361 array_free(s->extensions);
27363 + array_free(s->last_used_backends);
27368 free(p->config_storage);
27372 + array_free(p->ignore_headers);
27373 + buffer_free(p->balance_buf);
27374 + http_response_free(p->resp);
27379 return HANDLER_GO_ON;
27382 @@ -186,37 +217,38 @@
27383 plugin_data *p = p_d;
27387 - config_values_t cv[] = {
27389 + config_values_t cv[] = {
27390 { "proxy.server", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
27391 { "proxy.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
27392 { "proxy.balance", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
27393 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
27397 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
27400 for (i = 0; i < srv->config_context->used; i++) {
27405 s = malloc(sizeof(plugin_config));
27406 - s->extensions = array_init();
27407 + s->extensions = array_init();
27408 + s->last_used_backends = array_init();
27412 cv[0].destination = s->extensions;
27413 cv[1].destination = &(s->debug);
27414 cv[2].destination = p->balance_buf;
27416 buffer_reset(p->balance_buf);
27419 p->config_storage[i] = s;
27420 ca = ((data_config *)srv->config_context->data[i])->value;
27423 if (0 != config_insert_values_global(srv, ca, cv)) {
27424 return HANDLER_ERROR;
27428 if (buffer_is_empty(p->balance_buf)) {
27429 s->balance = PROXY_BALANCE_FAIR;
27430 } else if (buffer_is_equal_string(p->balance_buf, CONST_STR_LEN("fair"))) {
27431 @@ -226,99 +258,99 @@
27432 } else if (buffer_is_equal_string(p->balance_buf, CONST_STR_LEN("hash"))) {
27433 s->balance = PROXY_BALANCE_HASH;
27435 - log_error_write(srv, __FILE__, __LINE__, "sb",
27436 - "proxy.balance has to be one of: fair, round-robin, hash, but not:", p->balance_buf);
27437 + log_error_write(srv, __FILE__, __LINE__, "sb",
27438 + "proxy.balance has to be one of: fair, round-robin, hash, but not:", p->balance_buf);
27439 return HANDLER_ERROR;
27442 if (NULL != (du = array_get_element(ca, "proxy.server"))) {
27444 data_array *da = (data_array *)du;
27447 if (du->type != TYPE_ARRAY) {
27448 - log_error_write(srv, __FILE__, __LINE__, "sss",
27449 + log_error_write(srv, __FILE__, __LINE__, "sss",
27450 "unexpected type for key: ", "proxy.server", "array of strings");
27453 return HANDLER_ERROR;
27459 * proxy.server = ( "<ext>" => ...,
27464 for (j = 0; j < da->value->used; j++) {
27465 data_array *da_ext = (data_array *)da->value->data[j];
27469 if (da_ext->type != TYPE_ARRAY) {
27470 - log_error_write(srv, __FILE__, __LINE__, "sssbs",
27471 - "unexpected type for key: ", "proxy.server",
27472 + log_error_write(srv, __FILE__, __LINE__, "sssbs",
27473 + "unexpected type for key: ", "proxy.server",
27474 "[", da->value->data[j]->key, "](string)");
27477 return HANDLER_ERROR;
27481 - * proxy.server = ( "<ext>" =>
27482 - * ( "<host>" => ( ... ),
27485 + * proxy.server = ( "<ext>" =>
27486 + * ( "<host>" => ( ... ),
27487 * "<host>" => ( ... )
27494 for (n = 0; n < da_ext->value->used; n++) {
27495 data_array *da_host = (data_array *)da_ext->value->data[n];
27501 - config_values_t pcv[] = {
27503 + config_values_t pcv[] = {
27504 { "host", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
27505 { "port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
27506 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
27510 if (da_host->type != TYPE_ARRAY) {
27511 - log_error_write(srv, __FILE__, __LINE__, "ssSBS",
27512 - "unexpected type for key:",
27514 + log_error_write(srv, __FILE__, __LINE__, "ssSBS",
27515 + "unexpected type for key:",
27517 "[", da_ext->value->data[n]->key, "](string)");
27520 return HANDLER_ERROR;
27524 df = data_proxy_init();
27530 buffer_copy_string_buffer(df->key, da_host->key);
27533 pcv[0].destination = df->host;
27534 pcv[1].destination = &(df->port);
27537 if (0 != config_insert_values_internal(srv, da_host->value, pcv)) {
27538 return HANDLER_ERROR;
27542 if (buffer_is_empty(df->host)) {
27543 - log_error_write(srv, __FILE__, __LINE__, "sbbbs",
27544 - "missing key (string):",
27545 + log_error_write(srv, __FILE__, __LINE__, "sbbbs",
27546 + "missing key (string):",
27553 return HANDLER_ERROR;
27557 /* if extension already exists, take it */
27560 if (NULL == (dfa = (data_array *)array_get_element(s->extensions, da_ext->key->ptr))) {
27561 dfa = data_array_init();
27564 buffer_copy_string_buffer(dfa->key, da_ext->key);
27567 array_insert_unique(dfa->value, (data_unset *)df);
27568 array_insert_unique(s->extensions, (data_unset *)dfa);
27570 @@ -328,67 +360,76 @@
27576 return HANDLER_GO_ON;
27579 void proxy_connection_close(server *srv, handler_ctx *hctx) {
27584 if (NULL == hctx) return;
27587 p = hctx->plugin_data;
27588 con = hctx->remote_conn;
27590 - if (hctx->fd != -1) {
27591 - fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
27592 - fdevent_unregister(srv->ev, hctx->fd);
27595 + if (hctx->sock->fd != -1) {
27596 + fdevent_event_del(srv->ev, hctx->sock);
27597 + fdevent_unregister(srv->ev, hctx->sock);
27599 + close(hctx->sock->fd);
27604 handler_ctx_free(hctx);
27605 - con->plugin_ctx[p->id] = NULL;
27606 + con->plugin_ctx[p->id] = NULL;
27609 static int proxy_establish_connection(server *srv, handler_ctx *hctx) {
27610 struct sockaddr *proxy_addr;
27611 struct sockaddr_in proxy_addr_in;
27615 plugin_data *p = hctx->plugin_data;
27616 data_proxy *host= hctx->host;
27617 - int proxy_fd = hctx->fd;
27619 + int proxy_fd = hctx->sock->fd;
27621 memset(&proxy_addr, 0, sizeof(proxy_addr));
27624 proxy_addr_in.sin_family = AF_INET;
27625 proxy_addr_in.sin_addr.s_addr = inet_addr(host->host->ptr);
27626 proxy_addr_in.sin_port = htons(host->port);
27627 servlen = sizeof(proxy_addr_in);
27630 proxy_addr = (struct sockaddr *) &proxy_addr_in;
27633 if (-1 == connect(proxy_fd, proxy_addr, servlen)) {
27634 - if (errno == EINPROGRESS || errno == EALREADY) {
27636 + errno = WSAGetLastError();
27640 + case WSAEWOULDBLOCK:
27642 + case EINPROGRESS:
27644 if (p->conf.debug) {
27645 - log_error_write(srv, __FILE__, __LINE__, "sd",
27646 + log_error_write(srv, __FILE__, __LINE__, "sd",
27647 "connect delayed:", proxy_fd);
27654 - log_error_write(srv, __FILE__, __LINE__, "sdsd",
27657 + log_error_write(srv, __FILE__, __LINE__, "sdsd",
27658 "connect failed:", proxy_fd, strerror(errno), errno);
27664 + fprintf(stderr, "%s.%d: connected fd = %d\r\n", __FILE__, __LINE__, proxy_fd);
27665 if (p->conf.debug) {
27666 - log_error_write(srv, __FILE__, __LINE__, "sd",
27667 + log_error_write(srv, __FILE__, __LINE__, "sd",
27668 "connect succeeded: ", proxy_fd);
27671 @@ -396,51 +437,52 @@
27674 void proxy_set_header(connection *con, const char *key, const char *value) {
27675 - data_string *ds_dst;
27676 + data_string *ds_dst;
27678 - if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
27679 - ds_dst = data_string_init();
27682 - buffer_copy_string(ds_dst->key, key);
27683 - buffer_copy_string(ds_dst->value, value);
27684 - array_insert_unique(con->request.headers, (data_unset *)ds_dst);
27685 + if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
27686 + ds_dst = data_string_init();
27689 + buffer_copy_string(ds_dst->key, key);
27690 + buffer_copy_string(ds_dst->value, value);
27691 + array_insert_unique(con->request.headers, (data_unset *)ds_dst);
27694 void proxy_append_header(connection *con, const char *key, const char *value) {
27695 - data_string *ds_dst;
27696 + data_string *ds_dst;
27698 - if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
27699 - ds_dst = data_string_init();
27702 - buffer_copy_string(ds_dst->key, key);
27703 - buffer_append_string(ds_dst->value, value);
27704 - array_insert_unique(con->request.headers, (data_unset *)ds_dst);
27705 + if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
27706 + ds_dst = data_string_init();
27709 + buffer_copy_string(ds_dst->key, key);
27710 + buffer_append_string(ds_dst->value, value);
27711 + array_insert_unique(con->request.headers, (data_unset *)ds_dst);
27715 static int proxy_create_env(server *srv, handler_ctx *hctx) {
27719 connection *con = hctx->remote_conn;
27720 + plugin_data *p = hctx->plugin_data;
27726 b = chunkqueue_get_append_buffer(hctx->wb);
27730 buffer_copy_string(b, get_http_method_name(con->request.http_method));
27731 BUFFER_APPEND_STRING_CONST(b, " ");
27734 buffer_append_string_buffer(b, con->request.uri);
27735 BUFFER_APPEND_STRING_CONST(b, " HTTP/1.0\r\n");
27737 proxy_append_header(con, "X-Forwarded-For", (char *)inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
27738 - /* http_host is NOT is just a pointer to a buffer
27739 + /* http_host is NOT is just a pointer to a buffer
27740 * which is NULL if it is not set */
27741 - if (con->request.http_host &&
27742 + if (con->request.http_host &&
27743 !buffer_is_empty(con->request.http_host)) {
27744 proxy_set_header(con, "X-Host", con->request.http_host->ptr);
27746 @@ -449,24 +491,25 @@
27747 /* request header */
27748 for (i = 0; i < con->request.headers->used; i++) {
27752 ds = (data_string *)con->request.headers->data[i];
27754 - if (ds->value->used && ds->key->used) {
27755 - if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Connection"))) continue;
27757 - buffer_append_string_buffer(b, ds->key);
27758 - BUFFER_APPEND_STRING_CONST(b, ": ");
27759 - buffer_append_string_buffer(b, ds->value);
27760 - BUFFER_APPEND_STRING_CONST(b, "\r\n");
27763 + if (buffer_is_empty(ds->value) || buffer_is_empty(ds->key)) continue;
27765 + if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Connection"))) continue;
27766 + if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Keep-Alive"))) continue;
27768 + buffer_append_string_buffer(b, ds->key);
27769 + BUFFER_APPEND_STRING_CONST(b, ": ");
27770 + buffer_append_string_buffer(b, ds->value);
27771 + BUFFER_APPEND_STRING_CONST(b, "\r\n");
27775 BUFFER_APPEND_STRING_CONST(b, "\r\n");
27778 hctx->wb->bytes_in += b->used - 1;
27782 if (con->request.content_length) {
27783 chunkqueue *req_cq = con->request_content_queue;
27785 @@ -479,7 +522,7 @@
27787 /* we announce toWrite octects
27788 * now take all the request_content chunk that we need to fill this request
27792 switch (req_c->type) {
27794 @@ -507,223 +550,150 @@
27796 req_c->offset += weHave;
27797 req_cq->bytes_out += weHave;
27800 hctx->wb->bytes_in += weHave;
27817 static int proxy_set_state(server *srv, handler_ctx *hctx, proxy_connection_state_t state) {
27818 hctx->state = state;
27819 hctx->state_timestamp = srv->cur_ts;
27825 -static int proxy_response_parse(server *srv, connection *con, plugin_data *p, buffer *in) {
27827 - int http_response_status = -1;
27831 - /* \r\n -> \0\0 */
27833 - buffer_copy_string_buffer(p->parse_response, in);
27835 - for (s = p->parse_response->ptr; NULL != (ns = strstr(s, "\r\n")); s = ns + 2) {
27836 - char *key, *value;
27844 - if (-1 == http_response_status) {
27845 - /* The first line of a Response message is the Status-Line */
27847 - for (key=s; *key && *key != ' '; key++);
27850 - http_response_status = (int) strtol(key, NULL, 10);
27851 - if (http_response_status <= 0) http_response_status = 502;
27853 - http_response_status = 502;
27856 - con->http_status = http_response_status;
27857 - con->parsed_response |= HTTP_STATUS;
27861 - if (NULL == (value = strchr(s, ':'))) {
27862 - /* now we expect: "<key>: <value>\n" */
27868 - key_len = value - key;
27872 - while (*value == ' ' || *value == '\t') value++;
27876 - switch(key_len) {
27878 - if (0 == strncasecmp(key, "Date", key_len)) {
27879 - con->parsed_response |= HTTP_DATE;
27883 - if (0 == strncasecmp(key, "Location", key_len)) {
27884 - con->parsed_response |= HTTP_LOCATION;
27888 - if (0 == strncasecmp(key, "Connection", key_len)) {
27893 - if (0 == strncasecmp(key, "Content-Length", key_len)) {
27894 - con->response.content_length = strtol(value, NULL, 10);
27895 - con->parsed_response |= HTTP_CONTENT_LENGTH;
27902 - if (copy_header) {
27903 - if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
27904 - ds = data_response_init();
27906 - buffer_copy_string_len(ds->key, key, key_len);
27907 - buffer_copy_string(ds->value, value);
27909 - array_insert_unique(con->response.headers, (data_unset *)ds);
27917 static int proxy_demux_response(server *srv, handler_ctx *hctx) {
27922 plugin_data *p = hctx->plugin_data;
27923 connection *con = hctx->remote_conn;
27924 - int proxy_fd = hctx->fd;
27926 - /* check how much we have to read */
27927 - if (ioctl(hctx->fd, FIONREAD, &b)) {
27928 - log_error_write(srv, __FILE__, __LINE__, "sd",
27929 - "ioctl failed: ",
27931 + chunkqueue *next_queue = NULL;
27934 + switch(srv->network_backend_read(srv, con, hctx->sock, hctx->rb)) {
27935 + case NETWORK_STATUS_SUCCESS:
27936 + /* we got content */
27938 + case NETWORK_STATUS_WAIT_FOR_EVENT:
27940 + case NETWORK_STATUS_CONNECTION_CLOSE:
27941 + /* we are done, get out of here */
27942 + con->file_finished = 1;
27944 + /* close the chunk-queue with a empty chunk */
27952 + /* looks like we got some content
27954 + * split off the header from the incoming stream
27957 - if (p->conf.debug) {
27958 - log_error_write(srv, __FILE__, __LINE__, "sd",
27959 - "proxy - have to read:", b);
27961 + if (hctx->state == PROXY_STATE_RESPONSE_HEADER) {
27963 + int have_content_length = 0;
27966 - if (hctx->response->used == 0) {
27967 - /* avoid too small buffer */
27968 - buffer_prepare_append(hctx->response, b + 1);
27969 - hctx->response->used = 1;
27971 - buffer_prepare_append(hctx->response, hctx->response->used + b);
27974 - if (-1 == (r = read(hctx->fd, hctx->response->ptr + hctx->response->used - 1, b))) {
27975 - log_error_write(srv, __FILE__, __LINE__, "sds",
27976 - "unexpected end-of-file (perhaps the proxy process died):",
27977 - proxy_fd, strerror(errno));
27981 - /* this should be catched by the b > 0 above */
27984 - hctx->response->used += r;
27985 - hctx->response->ptr[hctx->response->used - 1] = '\0';
27988 - log_error_write(srv, __FILE__, __LINE__, "sdsbs",
27989 - "demux: Response buffer len", hctx->response->used, ":", hctx->response, ":");
27991 + http_response_reset(p->resp);
27993 - if (0 == con->got_response) {
27994 - con->got_response = 1;
27995 - buffer_prepare_copy(hctx->response_header, 128);
27998 - if (0 == con->file_started) {
28001 - /* search for the \r\n\r\n in the string */
28002 - if (NULL != (c = buffer_search_string_len(hctx->response, "\r\n\r\n", 4))) {
28003 - size_t hlen = c - hctx->response->ptr + 4;
28004 - size_t blen = hctx->response->used - hlen - 1;
28007 - buffer_append_string_len(hctx->response_header, hctx->response->ptr, c - hctx->response->ptr + 4);
28009 - log_error_write(srv, __FILE__, __LINE__, "sb", "Header:", hctx->response_header);
28011 - /* parse the response header */
28012 - proxy_response_parse(srv, con, p, hctx->response_header);
28014 - /* enable chunked-transfer-encoding */
28015 - if (con->request.http_version == HTTP_VERSION_1_1 &&
28016 - !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
28017 - con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
28018 + /* the response header is not fully received yet,
28020 + * extract the http-response header from the rb-cq
28022 + switch (http_response_parse_cq(hctx->rb, p->resp)) {
28023 + case PARSE_ERROR:
28024 + /* parsing failed */
28026 + con->http_status = 502; /* Bad Gateway */
28028 + case PARSE_NEED_MORE:
28030 + case PARSE_SUCCESS:
28031 + con->http_status = p->resp->status;
28033 + chunkqueue_remove_finished_chunks(hctx->rb);
28035 + /* copy the http-headers */
28036 + for (i = 0; i < p->resp->headers->used; i++) {
28037 + const char *ign[] = { "Status", "Connection", NULL };
28041 + data_string *header = (data_string *)p->resp->headers->data[i];
28043 + /* some headers are ignored by default */
28044 + for (j = 0; ign[j]; j++) {
28045 + if (0 == strcasecmp(ign[j], header->key->ptr)) break;
28047 + if (ign[j]) continue;
28049 + if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Location"))) {
28050 + /* CGI/1.1 rev 03 - 7.2.1.2 */
28051 + if (con->http_status == 0) con->http_status = 302;
28052 + } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Content-Length"))) {
28053 + have_content_length = 1;
28056 - con->file_started = 1;
28058 - http_chunk_append_mem(srv, con, c + 4, blen + 1);
28059 - joblist_append(srv, con);
28061 + if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
28062 + ds = data_response_init();
28064 - hctx->response->used = 0;
28065 + buffer_copy_string_buffer(ds->key, header->key);
28066 + buffer_copy_string_buffer(ds->value, header->value);
28068 + array_insert_unique(con->response.headers, (data_unset *)ds);
28071 - http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used);
28072 - joblist_append(srv, con);
28073 - hctx->response->used = 0;
28075 + con->file_started = 1;
28077 + if (con->request.http_version == HTTP_VERSION_1_1 &&
28078 + !have_content_length) {
28079 + con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
28082 + hctx->state = PROXY_STATE_RESPONSE_CONTENT;
28087 - /* reading from upstream done */
28088 - con->file_finished = 1;
28090 - http_chunk_append_mem(srv, con, NULL, 0);
28091 - joblist_append(srv, con);
28098 + /* FIXME: pass the response-header to the other plugins to
28099 + * setup the filter-queue
28101 + * - use next-queue instead of con->write_queue
28104 + next_queue = con->write_queue;
28106 + assert(hctx->state == PROXY_STATE_RESPONSE_CONTENT);
28108 + /* FIXME: if we have a content-length or chunked-encoding
28111 + * for now we wait for EOF on the socket */
28113 + /* copy the content to the next cq */
28114 + for (c = hctx->rb->first; c; c = c->next) {
28115 + http_chunk_append_mem(srv, con, c->mem->ptr + c->offset, c->mem->used - c->offset);
28117 + c->offset = c->mem->used - 1;
28120 + chunkqueue_remove_finished_chunks(hctx->rb);
28121 + joblist_append(srv, con);
28127 @@ -731,32 +701,32 @@
28128 data_proxy *host= hctx->host;
28129 plugin_data *p = hctx->plugin_data;
28130 connection *con = hctx->remote_conn;
28136 - (!host->host->used || !host->port)) return -1;
28140 + (!host->host->used || !host->port)) return -1;
28142 switch(hctx->state) {
28143 case PROXY_STATE_INIT:
28144 - if (-1 == (hctx->fd = socket(AF_INET, SOCK_STREAM, 0))) {
28145 + if (-1 == (hctx->sock->fd = socket(AF_INET, SOCK_STREAM, 0))) {
28146 log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed: ", strerror(errno));
28147 return HANDLER_ERROR;
28149 - hctx->fde_ndx = -1;
28151 + hctx->sock->fde_ndx = -1;
28155 - fdevent_register(srv->ev, hctx->fd, proxy_handle_fdevent, hctx);
28157 - if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
28159 + fdevent_register(srv->ev, hctx->sock, proxy_handle_fdevent, hctx);
28161 + if (-1 == fdevent_fcntl_set(srv->ev, hctx->sock)) {
28162 log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
28165 return HANDLER_ERROR;
28172 case PROXY_STATE_CONNECT:
28173 /* try to finish the connect() */
28174 if (hctx->state == PROXY_STATE_INIT) {
28175 @@ -764,16 +734,16 @@
28176 switch (proxy_establish_connection(srv, hctx)) {
28178 proxy_set_state(srv, hctx, PROXY_STATE_CONNECT);
28181 /* connection is in progress, wait for an event and call getsockopt() below */
28183 - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
28186 + fdevent_event_add(srv->ev, hctx->sock, FDEVENT_OUT);
28188 return HANDLER_WAIT_FOR_EVENT;
28190 /* if ECONNREFUSED choose another connection -> FIXME */
28191 - hctx->fde_ndx = -1;
28193 + hctx->sock->fde_ndx = -1;
28195 return HANDLER_ERROR;
28197 /* everything is ok, go on */
28198 @@ -782,152 +752,152 @@
28201 socklen_t socket_error_len = sizeof(socket_error);
28203 - /* we don't need it anymore */
28204 - fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
28206 + /* we don't need it anymore */
28207 + fdevent_event_del(srv->ev, hctx->sock);
28209 /* try to finish the connect() */
28210 - if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
28211 - log_error_write(srv, __FILE__, __LINE__, "ss",
28212 + if (0 != getsockopt(hctx->sock->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
28213 + log_error_write(srv, __FILE__, __LINE__, "ss",
28214 "getsockopt failed:", strerror(errno));
28217 return HANDLER_ERROR;
28219 if (socket_error != 0) {
28220 log_error_write(srv, __FILE__, __LINE__, "ss",
28221 - "establishing connection failed:", strerror(socket_error),
28222 + "establishing connection failed:", strerror(socket_error),
28223 "port:", hctx->host->port);
28226 return HANDLER_ERROR;
28228 if (p->conf.debug) {
28229 - log_error_write(srv, __FILE__, __LINE__, "s", "proxy - connect - delayed success");
28230 + log_error_write(srv, __FILE__, __LINE__, "s", "proxy - connect - delayed success");
28235 proxy_set_state(srv, hctx, PROXY_STATE_PREPARE_WRITE);
28237 case PROXY_STATE_PREPARE_WRITE:
28238 proxy_create_env(srv, hctx);
28241 proxy_set_state(srv, hctx, PROXY_STATE_WRITE);
28245 case PROXY_STATE_WRITE:;
28246 - ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
28247 + ret = srv->network_backend_write(srv, con, hctx->sock, hctx->wb);
28249 chunkqueue_remove_finished_chunks(hctx->wb);
28252 - if (errno != EAGAIN &&
28253 - errno != EINTR) {
28254 - log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), errno);
28256 - return HANDLER_ERROR;
28258 - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
28260 + case NETWORK_STATUS_FATAL_ERROR:
28261 + log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), errno);
28263 - return HANDLER_WAIT_FOR_EVENT;
28265 + return HANDLER_ERROR;
28266 + case NETWORK_STATUS_WAIT_FOR_EVENT:
28268 + fdevent_event_add(srv->ev, hctx->sock, FDEVENT_OUT);
28270 + return HANDLER_WAIT_FOR_EVENT;
28273 if (hctx->wb->bytes_out == hctx->wb->bytes_in) {
28274 - proxy_set_state(srv, hctx, PROXY_STATE_READ);
28275 + proxy_set_state(srv, hctx, PROXY_STATE_RESPONSE_HEADER);
28277 - fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
28278 - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
28279 + fdevent_event_del(srv->ev, hctx->sock);
28280 + fdevent_event_add(srv->ev, hctx->sock, FDEVENT_IN);
28282 - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
28284 + fdevent_event_add(srv->ev, hctx->sock, FDEVENT_OUT);
28286 return HANDLER_WAIT_FOR_EVENT;
28290 return HANDLER_WAIT_FOR_EVENT;
28291 - case PROXY_STATE_READ:
28292 + case PROXY_STATE_RESPONSE_CONTENT:
28293 + case PROXY_STATE_RESPONSE_HEADER:
28294 /* waiting for a response */
28296 return HANDLER_WAIT_FOR_EVENT;
28298 log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state");
28299 return HANDLER_ERROR;
28303 return HANDLER_GO_ON;
28306 -#define PATCH(x) \
28307 - p->conf.x = s->x;
28308 static int mod_proxy_patch_connection(server *srv, connection *con, plugin_data *p) {
28310 plugin_config *s = p->config_storage[0];
28312 - PATCH(extensions);
28317 + PATCH_OPTION(extensions);
28318 + PATCH_OPTION(debug);
28319 + PATCH_OPTION(balance);
28320 + PATCH_OPTION(last_used_backends);
28322 /* skip the first, the global context */
28323 for (i = 1; i < srv->config_context->used; i++) {
28324 data_config *dc = (data_config *)srv->config_context->data[i];
28325 s = p->config_storage[i];
28328 /* condition didn't match */
28329 if (!config_check_cond(srv, con, dc)) continue;
28333 for (j = 0; j < dc->value->used; j++) {
28334 data_unset *du = dc->value->data[j];
28337 if (buffer_is_equal_string(du->key, CONST_STR_LEN("proxy.server"))) {
28338 - PATCH(extensions);
28339 + PATCH_OPTION(extensions);
28340 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("proxy.debug"))) {
28342 + PATCH_OPTION(debug);
28343 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("proxy.balance"))) {
28345 + PATCH_OPTION(balance);
28346 + PATCH_OPTION(last_used_backends);
28356 SUBREQUEST_FUNC(mod_proxy_handle_subrequest) {
28357 plugin_data *p = p_d;
28360 handler_ctx *hctx = con->plugin_ctx[p->id];
28364 if (NULL == hctx) return HANDLER_GO_ON;
28366 mod_proxy_patch_connection(srv, con, p);
28373 if (con->mode != p->id) return HANDLER_GO_ON;
28376 /* ok, create the request */
28377 switch(proxy_write_request(srv, hctx)) {
28378 case HANDLER_ERROR:
28379 - log_error_write(srv, __FILE__, __LINE__, "sbdd", "proxy-server disabled:",
28380 + log_error_write(srv, __FILE__, __LINE__, "sbdd", "proxy-server disabled:",
28387 /* disable this server */
28388 host->is_disabled = 1;
28389 host->disable_ts = srv->cur_ts;
28392 proxy_connection_close(srv, hctx);
28394 - /* reset the enviroment and restart the sub-request */
28396 + /* reset the enviroment and restart the sub-request */
28397 buffer_reset(con->physical.path);
28398 con->mode = DIRECT;
28400 joblist_append(srv, con);
28402 - /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
28403 - * and hope that the childs will be restarted
28405 + /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
28406 + * and hope that the childs will be restarted
28410 return HANDLER_WAIT_FOR_FD;
28411 @@ -938,7 +908,7 @@
28417 if (con->file_started == 1) {
28418 return HANDLER_FINISHED;
28420 @@ -951,13 +921,14 @@
28421 handler_ctx *hctx = ctx;
28422 connection *con = hctx->remote_conn;
28423 plugin_data *p = hctx->plugin_data;
28428 if ((revents & FDEVENT_IN) &&
28429 - hctx->state == PROXY_STATE_READ) {
28430 + (hctx->state == PROXY_STATE_RESPONSE_HEADER ||
28431 + hctx->state == PROXY_STATE_RESPONSE_CONTENT)) {
28433 if (p->conf.debug) {
28434 - log_error_write(srv, __FILE__, __LINE__, "sd",
28435 + log_error_write(srv, __FILE__, __LINE__, "sd",
28436 "proxy: fdevent-in", hctx->state);
28439 @@ -965,11 +936,15 @@
28443 + log_error_write(srv, __FILE__, __LINE__, "sd",
28444 + "proxy: request done", hctx->sock->fd);
28445 hctx->host->usage--;
28448 + http_chunk_append_mem(srv, con, NULL, 0);
28451 proxy_connection_close(srv, hctx);
28454 joblist_append(srv, con);
28455 return HANDLER_FINISHED;
28457 @@ -982,53 +957,53 @@
28458 /* response might have been already started, kill the connection */
28459 connection_set_state(srv, con, CON_STATE_ERROR);
28463 joblist_append(srv, con);
28464 return HANDLER_FINISHED;
28469 if (revents & FDEVENT_OUT) {
28470 if (p->conf.debug) {
28471 - log_error_write(srv, __FILE__, __LINE__, "sd",
28472 + log_error_write(srv, __FILE__, __LINE__, "sd",
28473 "proxy: fdevent-out", hctx->state);
28476 if (hctx->state == PROXY_STATE_CONNECT ||
28477 hctx->state == PROXY_STATE_WRITE) {
28478 /* we are allowed to send something out
28481 * 1. in a unfinished connect() call
28482 * 2. in a unfinished write() call (long POST request)
28484 return mod_proxy_handle_subrequest(srv, con, p);
28486 - log_error_write(srv, __FILE__, __LINE__, "sd",
28487 + log_error_write(srv, __FILE__, __LINE__, "sd",
28488 "proxy: out", hctx->state);
28493 /* perhaps this issue is already handled */
28494 if (revents & FDEVENT_HUP) {
28495 if (p->conf.debug) {
28496 - log_error_write(srv, __FILE__, __LINE__, "sd",
28497 + log_error_write(srv, __FILE__, __LINE__, "sd",
28498 "proxy: fdevent-hup", hctx->state);
28502 if (hctx->state == PROXY_STATE_CONNECT) {
28503 /* connect() -> EINPROGRESS -> HUP */
28507 - * what is proxy is doing if it can't reach the next hop ?
28509 + * what is proxy is doing if it can't reach the next hop ?
28514 proxy_connection_close(srv, hctx);
28515 joblist_append(srv, con);
28518 con->http_status = 503;
28519 con->mode = DIRECT;
28522 return HANDLER_FINISHED;
28525 @@ -1038,13 +1013,13 @@
28526 joblist_append(srv, con);
28527 } else if (revents & FDEVENT_ERR) {
28528 /* kill all connections to the proxy process */
28531 log_error_write(srv, __FILE__, __LINE__, "sd", "proxy-FDEVENT_ERR, but no HUP", revents);
28533 joblist_append(srv, con);
28534 proxy_connection_close(srv, hctx);
28538 return HANDLER_FINISHED;
28541 @@ -1058,44 +1033,48 @@
28543 data_array *extension = NULL;
28544 size_t path_info_offset;
28546 + data_integer *last_used_backend;
28547 + data_proxy *host = NULL;
28548 + handler_ctx *hctx = NULL;
28550 + array *backends = NULL;
28552 /* Possibly, we processed already this request */
28553 if (con->file_started == 1) return HANDLER_GO_ON;
28556 mod_proxy_patch_connection(srv, con, p);
28559 fn = con->uri.path;
28561 if (fn->used == 0) {
28562 return HANDLER_ERROR;
28566 s_len = fn->used - 1;
28570 path_info_offset = 0;
28572 - if (p->conf.debug) {
28573 + if (p->conf.debug) {
28574 log_error_write(srv, __FILE__, __LINE__, "s", "proxy - start");
28577 /* check if extension matches */
28578 for (k = 0; k < p->conf.extensions->used; k++) {
28582 extension = (data_array *)p->conf.extensions->data[k];
28585 if (extension->key->used == 0) continue;
28588 ct_len = extension->key->used - 1;
28591 if (s_len < ct_len) continue;
28594 /* check extension in the form "/proxy_pattern" */
28595 if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
28596 if (s_len > ct_len + 1) {
28600 if (0 != (pi_offset = strchr(fn->ptr + ct_len + 1, '/'))) {
28601 path_info_offset = pi_offset - fn->ptr;
28603 @@ -1106,12 +1085,14 @@
28609 if (k == p->conf.extensions->used) {
28610 return HANDLER_GO_ON;
28613 - if (p->conf.debug) {
28614 + backends = extension->value;
28616 + if (p->conf.debug) {
28617 log_error_write(srv, __FILE__, __LINE__, "s", "proxy - ext found");
28620 @@ -1120,34 +1101,34 @@
28621 /* hash balancing */
28623 if (p->conf.debug) {
28624 - log_error_write(srv, __FILE__, __LINE__, "sd",
28625 - "proxy - used hash balancing, hosts:", extension->value->used);
28626 + log_error_write(srv, __FILE__, __LINE__, "sd",
28627 + "proxy - used hash balancing, hosts:", backends->used);
28630 - for (k = 0, ndx = -1, last_max = ULONG_MAX; k < extension->value->used; k++) {
28631 - data_proxy *host = (data_proxy *)extension->value->data[k];
28632 + for (k = 0, ndx = -1, last_max = ULONG_MAX; k < backends->used; k++) {
28633 unsigned long cur_max;
28635 - if (host->is_disabled) continue;
28637 + data_proxy *cur = (data_proxy *)backends->data[k];
28639 + if (cur->is_disabled) continue;
28641 cur_max = generate_crc32c(CONST_BUF_LEN(con->uri.path)) +
28642 - generate_crc32c(CONST_BUF_LEN(host->host)) + /* we can cache this */
28643 + generate_crc32c(CONST_BUF_LEN(cur->host)) + /* we can cache this */
28644 generate_crc32c(CONST_BUF_LEN(con->uri.authority));
28647 if (p->conf.debug) {
28648 - log_error_write(srv, __FILE__, __LINE__, "sbbbd",
28649 + log_error_write(srv, __FILE__, __LINE__, "sbbbd",
28650 "proxy - election:",
28654 con->uri.authority,
28658 - if ((last_max == ULONG_MAX) || /* first round */
28659 - (cur_max > last_max)) {
28660 + if (host == NULL || (cur_max > last_max)) {
28661 last_max = cur_max;
28668 @@ -1155,19 +1136,20 @@
28669 case PROXY_BALANCE_FAIR:
28670 /* fair balancing */
28671 if (p->conf.debug) {
28672 - log_error_write(srv, __FILE__, __LINE__, "s",
28673 + log_error_write(srv, __FILE__, __LINE__, "s",
28674 "proxy - used fair balancing");
28677 - for (k = 0, ndx = -1, max_usage = INT_MAX; k < extension->value->used; k++) {
28678 - data_proxy *host = (data_proxy *)extension->value->data[k];
28680 - if (host->is_disabled) continue;
28682 - if (host->usage < max_usage) {
28683 - max_usage = host->usage;
28686 + /* try to find the host with the lowest load */
28687 + for (k = 0, max_usage = 0; k < backends->used; k++) {
28688 + data_proxy *cur = (data_proxy *)backends->data[k];
28690 + if (cur->is_disabled) continue;
28692 + if (NULL == host || cur->usage < max_usage) {
28693 + max_usage = cur->usage;
28699 @@ -1175,89 +1157,100 @@
28700 case PROXY_BALANCE_RR:
28702 if (p->conf.debug) {
28703 - log_error_write(srv, __FILE__, __LINE__, "s",
28704 + log_error_write(srv, __FILE__, __LINE__, "s",
28705 "proxy - used round-robin balancing");
28708 /* just to be sure */
28709 - assert(extension->value->used < INT_MAX);
28711 - for (k = 0, ndx = -1, max_usage = INT_MAX; k < extension->value->used; k++) {
28712 - data_proxy *host = (data_proxy *)extension->value->data[k];
28714 - if (host->is_disabled) continue;
28716 - /* first usable ndx */
28717 - if (max_usage == INT_MAX) {
28720 + assert(backends->used < INT_MAX);
28722 - /* get next ndx */
28723 - if ((int)k > host->last_used_ndx) {
28725 - host->last_used_ndx = k;
28726 + /* send each request to another host:
28730 + * if we have three hosts it is
28732 + * 1 .. 2 .. 3 .. 1 .. 2 .. 3
28738 + /* walk through the list */
28739 + last_used_backend = (data_integer *)array_get_element(p->conf.last_used_backends, extension->key->ptr);
28741 + if (NULL == last_used_backend) {
28742 + last_used_backend = data_integer_init();
28744 + buffer_copy_string_buffer(last_used_backend->key, extension->key);
28745 + last_used_backend->value = 0;
28747 + array_insert_unique(p->conf.last_used_backends, (data_unset *)last_used_backend);
28750 + /* scan all but the last host to see if they are up
28751 + * take the first running host */
28752 + for (k = last_used_backend->value + 1; (int)(k % backends->used) != last_used_backend->value; k++) {
28753 + data_proxy *cur = (data_proxy *)backends->data[k % backends->used];
28755 + if (cur->is_disabled) continue;
28759 + last_used_backend->value = k;
28764 - /* didn't found a higher id, wrap to the start */
28765 - if (ndx != -1 && max_usage != INT_MAX) {
28768 + if (NULL == host) {
28769 + /* we found nothing better, fallback to the last used backend
28770 + * and check if it is still up */
28771 + host = (data_proxy *)backends->data[last_used_backend->value];
28773 + if (host->is_disabled) host = NULL;
28781 - /* found a server */
28783 - data_proxy *host = (data_proxy *)extension->value->data[ndx];
28786 - * if check-local is disabled, use the uri.path handler
28790 - /* init handler-context */
28791 - handler_ctx *hctx;
28792 - hctx = handler_ctx_init();
28794 - hctx->path_info_offset = path_info_offset;
28795 - hctx->remote_conn = con;
28796 - hctx->plugin_data = p;
28797 - hctx->host = host;
28799 - con->plugin_ctx[p->id] = hctx;
28803 - con->mode = p->id;
28805 - if (p->conf.debug) {
28806 - log_error_write(srv, __FILE__, __LINE__, "sbd",
28807 - "proxy - found a host",
28808 - host->host, host->port);
28811 - return HANDLER_GO_ON;
28813 - /* no handler found */
28814 + /* we havn't found a host */
28815 + if (NULL == host) {
28816 con->http_status = 500;
28818 - log_error_write(srv, __FILE__, __LINE__, "sb",
28819 - "no proxy-handler found for:",
28821 + log_error_write(srv, __FILE__, __LINE__, "sb",
28822 + "no proxy-handler found for:",
28826 return HANDLER_FINISHED;
28829 + /* init handler-context */
28830 + hctx = handler_ctx_init();
28832 + hctx->path_info_offset = path_info_offset;
28833 + hctx->remote_conn = con;
28834 + hctx->plugin_data = p;
28835 + hctx->host = host;
28837 + con->plugin_ctx[p->id] = hctx;
28841 + /* we handle this request */
28842 + con->mode = p->id;
28844 + if (p->conf.debug) {
28845 + log_error_write(srv, __FILE__, __LINE__, "sbd",
28846 + "proxy - found a host",
28847 + host->host, host->port);
28850 return HANDLER_GO_ON;
28853 static handler_t mod_proxy_connection_close_callback(server *srv, connection *con, void *p_d) {
28854 plugin_data *p = p_d;
28857 proxy_connection_close(srv, con->plugin_ctx[p->id]);
28859 return HANDLER_GO_ON;
28860 @@ -1276,11 +1269,11 @@
28862 for (i = 0; i < srv->config_context->used; i++) {
28863 plugin_config *s = p->config_storage[i];
28865 - if (!s) continue;
28867 + if (!s) continue;
28869 /* get the extensions for all configs */
28872 for (k = 0; k < s->extensions->used; k++) {
28873 data_array *extension = (data_array *)s->extensions->data[k];
28875 @@ -1290,8 +1283,8 @@
28877 if (!host->is_disabled ||
28878 srv->cur_ts - host->disable_ts < 5) continue;
28880 - log_error_write(srv, __FILE__, __LINE__, "sbd",
28882 + log_error_write(srv, __FILE__, __LINE__, "sbd",
28883 "proxy - re-enabled:",
28884 host->host, host->port);
28886 @@ -1317,8 +1310,8 @@
28887 p->handle_uri_clean = mod_proxy_check_extension;
28888 p->handle_subrequest = mod_proxy_handle_subrequest;
28889 p->handle_trigger = mod_proxy_trigger;
28897 --- ../lighttpd-1.4.11/src/mod_proxy_core.c 1970-01-01 03:00:00.000000000 +0300
28898 +++ lighttpd-1.4.12/src/mod_proxy_core.c 2006-07-19 20:02:55.000000000 +0300
28900 +#include <string.h>
28901 +#include <stdlib.h>
28902 +#include <fcntl.h>
28903 +#include <errno.h>
28904 +#include <ctype.h>
28906 +#include "buffer.h"
28907 +#include "array.h"
28911 +#include "plugin.h"
28912 +#include "joblist.h"
28913 +#include "sys-files.h"
28914 +#include "inet_ntop_cache.h"
28915 +#include "http_resp.h"
28916 +#include "http_chunk.h"
28917 +#include "crc32.h"
28919 +#include "mod_proxy_core_pool.h"
28920 +#include "mod_proxy_core_backend.h"
28921 +#include "mod_proxy_core_backlog.h"
28922 +#include "mod_proxy_core_rewrites.h"
28924 +#define CONFIG_PROXY_CORE_BALANCER "proxy-core.balancer"
28925 +#define CONFIG_PROXY_CORE_PROTOCOL "proxy-core.protocol"
28926 +#define CONFIG_PROXY_CORE_DEBUG "proxy-core.debug"
28927 +#define CONFIG_PROXY_CORE_BACKENDS "proxy-core.backends"
28928 +#define CONFIG_PROXY_CORE_REWRITE_REQUEST "proxy-core.rewrite-request"
28929 +#define CONFIG_PROXY_CORE_REWRITE_RESPONSE "proxy-core.rewrite-response"
28932 + PROXY_PROTOCOL_UNSET,
28933 + PROXY_PROTOCOL_HTTP,
28934 + PROXY_PROTOCOL_HTTPS,
28935 + PROXY_PROTOCOL_FASTCGI,
28936 + PROXY_PROTOCOL_SCGI
28937 +} proxy_protocol_t;
28940 + proxy_backends *backends;
28942 + proxy_backlog *backlog;
28944 + proxy_rewrites *request_rewrites;
28945 + proxy_rewrites *response_rewrites;
28949 + proxy_balance_t balancer;
28950 + proxy_protocol_t protocol;
28958 + array *possible_balancers;
28959 + array *possible_protocols;
28961 + /* for parsing only */
28962 + array *backends_arr;
28963 + buffer *protocol_buf;
28964 + buffer *balance_buf;
28966 + buffer *replace_buf;
28968 + plugin_config **config_storage;
28970 + plugin_config conf;
28973 +int array_insert_int(array *a, const char *key, int val) {
28974 + data_integer *di;
28976 + if (NULL == (di = (data_integer *)array_get_unused_element(a, TYPE_INTEGER))) {
28977 + di = data_integer_init();
28980 + buffer_copy_string(di->key, key);
28982 + array_insert_unique(a, (data_unset *)di);
28987 +INIT_FUNC(mod_proxy_core_init) {
28990 + p = calloc(1, sizeof(*p));
28992 + /* create some backends as long as we don't have the config-parser */
28994 + p->possible_balancers = array_init();
28995 + array_insert_int(p->possible_balancers, "fair", PROXY_BALANCE_FAIR);
28996 + array_insert_int(p->possible_balancers, "hash", PROXY_BALANCE_HASH);
28997 + array_insert_int(p->possible_balancers, "round-robin", PROXY_BALANCE_RR);
28999 + p->possible_protocols = array_init();
29000 + array_insert_int(p->possible_protocols, "http", PROXY_PROTOCOL_HTTP);
29001 + array_insert_int(p->possible_protocols, "fastcgi", PROXY_PROTOCOL_FASTCGI);
29002 + array_insert_int(p->possible_protocols, "scgi", PROXY_PROTOCOL_SCGI);
29003 + array_insert_int(p->possible_protocols, "https", PROXY_PROTOCOL_HTTPS);
29005 + p->balance_buf = buffer_init();
29006 + p->protocol_buf = buffer_init();
29007 + p->replace_buf = buffer_init();
29008 + p->backends_arr = array_init();
29010 + p->resp = http_response_init();
29015 +FREE_FUNC(mod_proxy_core_free) {
29016 + plugin_data *p = p_d;
29018 + if (!p) return HANDLER_GO_ON;
29020 + if (p->config_storage) {
29022 + for (i = 0; i < srv->config_context->used; i++) {
29023 + plugin_config *s = p->config_storage[i];
29025 + if (!s) continue;
29027 + proxy_backends_free(s->backends);
29028 + proxy_backlog_free(s->backlog);
29033 + free(p->config_storage);
29036 + array_free(p->possible_protocols);
29037 + array_free(p->possible_balancers);
29038 + array_free(p->backends_arr);
29040 + buffer_free(p->balance_buf);
29041 + buffer_free(p->protocol_buf);
29042 + buffer_free(p->replace_buf);
29044 + http_response_free(p->resp);
29048 + return HANDLER_GO_ON;
29051 +static handler_t mod_proxy_core_config_parse_rewrites(proxy_rewrites *dest, array *src, const char *config_key) {
29055 + if (NULL != (du = array_get_element(src, config_key))) {
29056 + data_array *keys = (data_array *)du;
29058 + if (keys->type != TYPE_ARRAY) {
29059 + ERROR("%s = <...>",
29062 + return HANDLER_ERROR;
29066 + * proxy-core.rewrite-request = (
29067 + * "_uri" => ( ... )
29071 + for (j = 0; j < keys->value->used; j++) {
29073 + data_array *headers = (data_array *)keys->value->data[j];
29075 + /* keys->key should be "_uri" and the value a array of rewrite */
29076 + if (headers->type != TYPE_ARRAY) {
29077 + ERROR("%s = ( %s => <...> ) has to a array",
29079 + BUF_STR(headers->key));
29081 + return HANDLER_ERROR;
29084 + if (headers->value->used > 1) {
29085 + ERROR("%s = ( %s => <...> ) has to a array with only one element",
29087 + BUF_STR(headers->key));
29089 + return HANDLER_ERROR;
29093 + for (k = 0; k < headers->value->used; k++) {
29094 + data_string *rewrites = (data_string *)headers->value->data[k];
29095 + proxy_rewrite *rw;
29097 + /* keys->key should be "_uri" and the value a array of rewrite */
29098 + if (rewrites->type != TYPE_STRING) {
29099 + ERROR("%s = ( \"%s\" => ( \"%s\" => <value> ) ) has to a string",
29101 + BUF_STR(headers->key),
29102 + BUF_STR(rewrites->key));
29104 + return HANDLER_ERROR;
29107 + rw = proxy_rewrite_init();
29109 + if (0 != proxy_rewrite_set_regex(rw, rewrites->key)) {
29110 + return HANDLER_ERROR;
29112 + buffer_copy_string_buffer(rw->replace, rewrites->value);
29113 + buffer_copy_string_buffer(rw->match, rewrites->key);
29114 + buffer_copy_string_buffer(rw->header, headers->key);
29116 + proxy_rewrites_add(dest, rw);
29121 + return HANDLER_GO_ON;
29125 +SETDEFAULTS_FUNC(mod_proxy_core_set_defaults) {
29126 + plugin_data *p = p_d;
29129 + config_values_t cv[] = {
29130 + { CONFIG_PROXY_CORE_BACKENDS, NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
29131 + { CONFIG_PROXY_CORE_DEBUG, NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
29132 + { CONFIG_PROXY_CORE_BALANCER, NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
29133 + { CONFIG_PROXY_CORE_PROTOCOL, NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
29134 + { CONFIG_PROXY_CORE_REWRITE_REQUEST, NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 4 */
29135 + { CONFIG_PROXY_CORE_REWRITE_RESPONSE, NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION },/* 5 */
29136 + { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
29139 + p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
29141 + for (i = 0; i < srv->config_context->used; i++) {
29142 + plugin_config *s;
29144 + proxy_backend *backend;
29146 + array_reset(p->backends_arr);
29147 + buffer_reset(p->balance_buf);
29148 + buffer_reset(p->protocol_buf);
29150 + s = malloc(sizeof(plugin_config));
29152 + s->balancer = PROXY_BALANCE_UNSET;
29153 + s->protocol = PROXY_PROTOCOL_UNSET;
29154 + s->backends = proxy_backends_init();
29155 + s->backlog = proxy_backlog_init();
29156 + s->response_rewrites = proxy_rewrites_init();
29157 + s->request_rewrites = proxy_rewrites_init();
29159 + cv[0].destination = p->backends_arr;
29160 + cv[1].destination = &(s->debug);
29161 + cv[2].destination = p->balance_buf; /* parse into a constant */
29162 + cv[3].destination = p->protocol_buf; /* parse into a constant */
29164 + buffer_reset(p->balance_buf);
29166 + p->config_storage[i] = s;
29167 + ca = ((data_config *)srv->config_context->data[i])->value;
29169 + if (0 != config_insert_values_global(srv, ca, cv)) {
29170 + return HANDLER_ERROR;
29173 + if (!buffer_is_empty(p->balance_buf)) {
29174 + data_integer *di;
29176 + if (NULL == (di = (data_integer *)array_get_element(p->possible_balancers, BUF_STR(p->balance_buf)))) {
29177 + ERROR("proxy.balance has to be on of 'fair', 'round-robin', 'hash', got %s", BUF_STR(p->balance_buf));
29179 + return HANDLER_ERROR;
29182 + s->balancer = di->value;
29185 + if (!buffer_is_empty(p->protocol_buf)) {
29186 + data_integer *di;
29188 + if (NULL == (di = (data_integer *)array_get_element(p->possible_protocols, BUF_STR(p->protocol_buf)))) {
29189 + ERROR("proxy.balance has to be on of 'fair', 'round-robin', 'hash', got %s", BUF_STR(p->protocol_buf));
29191 + return HANDLER_ERROR;
29194 + s->protocol = di->value;
29197 + if (p->backends_arr->used) {
29198 + backend = proxy_backend_init();
29200 + /* check if the backends have a valid host-name */
29201 + for (j = 0; j < p->backends_arr->used; j++) {
29202 + data_string *ds = (data_string *)p->backends_arr->data[j];
29204 + /* the values should be ips or hostnames */
29205 + if (0 != proxy_address_pool_add_string(backend->address_pool, ds->value)) {
29206 + return HANDLER_ERROR;
29210 + proxy_backends_add(s->backends, backend);
29213 + if (HANDLER_GO_ON != mod_proxy_core_config_parse_rewrites(s->request_rewrites, ca, CONFIG_PROXY_CORE_REWRITE_REQUEST)) {
29214 + return HANDLER_ERROR;
29217 + if (HANDLER_GO_ON != mod_proxy_core_config_parse_rewrites(s->response_rewrites, ca, CONFIG_PROXY_CORE_REWRITE_RESPONSE)) {
29218 + return HANDLER_ERROR;
29222 + return HANDLER_GO_ON;
29227 + PROXY_STATE_UNSET,
29228 + PROXY_STATE_CONNECTING,
29229 + PROXY_STATE_CONNECTED,
29230 + PROXY_STATE_WRITE_REQUEST_HEADER,
29231 + PROXY_STATE_WRITE_REQUEST_BODY,
29232 + PROXY_STATE_READ_RESPONSE_HEADER,
29233 + PROXY_STATE_READ_RESPONSE_BODY
29237 + proxy_connection *proxy_con;
29238 + proxy_backend *proxy_backend;
29240 + connection *remote_con;
29242 + array *request_headers;
29248 + * - the encoded_rb is the raw network stuff
29249 + * - the rb is filtered through the stream decoder
29251 + * - wb is the normal bytes stream
29252 + * - encoded_wb is encoded for the network by the stream encoder
29254 + chunkqueue *recv;
29255 + chunkqueue *recv_raw;
29256 + chunkqueue *send_raw;
29257 + chunkqueue *send;
29259 + off_t bytes_read;
29260 + off_t content_length;
29262 + proxy_state_t state;
29265 +proxy_session *proxy_session_init(void) {
29266 + proxy_session *sess;
29268 + sess = calloc(1, sizeof(*sess));
29270 + sess->state = PROXY_STATE_UNSET;
29271 + sess->request_headers = array_init();
29273 + sess->recv = chunkqueue_init();
29274 + sess->recv_raw = chunkqueue_init();
29275 + sess->send_raw = chunkqueue_init();
29276 + sess->send = chunkqueue_init();
29278 + sess->is_chunked = 0;
29283 +void proxy_session_free(proxy_session *sess) {
29284 + if (!sess) return;
29286 + array_free(sess->request_headers);
29288 + chunkqueue_free(sess->recv);
29289 + chunkqueue_free(sess->recv_raw);
29290 + chunkqueue_free(sess->send_raw);
29291 + chunkqueue_free(sess->send);
29296 +handler_t proxy_connection_connect(proxy_connection *con) {
29299 + if (-1 == (fd = socket(con->address->addr.plain.sa_family, SOCK_STREAM, 0))) {
29302 + fcntl(fd, F_SETFL, O_NONBLOCK | O_RDWR);
29304 + con->sock->fd = fd;
29305 + con->sock->fde_ndx = -1;
29306 + con->sock->type = IOSOCKET_TYPE_SOCKET;
29308 + if (-1 == connect(fd, &(con->address->addr.plain), sizeof(con->address->addr))) {
29310 + case EINPROGRESS:
29313 + return HANDLER_WAIT_FOR_EVENT;
29316 + con->sock->fd = -1;
29318 + return HANDLER_ERROR;
29322 + return HANDLER_GO_ON;
29326 + * event-handler for idling connections
29328 + * unused (idling) keep-alive connections are not bound to a session
29329 + * and need their own event-handler
29331 + * if the connection closes (we get a FDEVENT_IN), close our side too and
29332 + * let the trigger-func handle the cleanup
29334 + * @see proxy_trigger
29338 +static handler_t proxy_handle_fdevent_idle(void *s, void *ctx, int revents) {
29339 + server *srv = (server *)s;
29340 + proxy_connection *proxy_con = ctx;
29342 + if (revents & FDEVENT_IN) {
29343 + switch (proxy_con->state) {
29344 + case PROXY_CONNECTION_STATE_IDLE:
29345 + proxy_con->state = PROXY_CONNECTION_STATE_CLOSED;
29347 + /* close + unregister have to be in the same call,
29348 + * otherwise we get a events for a re-opened fd */
29350 + fdevent_event_del(srv->ev, proxy_con->sock);
29353 + case PROXY_CONNECTION_STATE_CLOSED:
29354 + /* poll() is state-driven, we will get events as long as it isn't disabled
29355 + * the close() above should disable the events too */
29356 + ERROR("%s", "hurry up buddy, I got another event for a closed idle-connection");
29359 + ERROR("invalid connection state: %d, should be idle", proxy_con->state);
29364 + return HANDLER_GO_ON;
29367 +void chunkqueue_skip(chunkqueue *cq, off_t skip) {
29370 + for (c = cq->first; c && skip; c = c->next) {
29371 + if (skip > c->mem->used - c->offset - 1) {
29372 + skip -= c->mem->used - c->offset - 1;
29374 + c->offset += skip;
29382 +int proxy_http_stream_decoder(server *srv, proxy_session *sess, chunkqueue *raw, chunkqueue *decoded) {
29385 + if (raw->first == NULL) return 0;
29387 + if (sess->is_chunked) {
29389 + /* the start should always be a chunk-length */
29390 + off_t chunk_len = 0;
29391 + char *err = NULL;
29392 + int chunklen_strlen = 0;
29394 + off_t we_have = 0, we_need = 0;
29398 + if (c->mem->used == 0) return 0;
29400 + chunk_len = strtol(BUF_STR(c->mem) + c->offset, &err, 16);
29401 + if (!(*err == ' ' || *err == '\r' || *err == ';')) {
29402 + if (*err == '\0') {
29403 + /* we just need more data */
29409 + if (chunk_len < 0) {
29410 + ERROR("chunk_len is negative: %Ld", chunk_len);
29414 + chunklen_strlen = err - (BUF_STR(c->mem) + c->offset);
29415 + chunklen_strlen++; /* skip the err-char */
29418 + ch = BUF_STR(c->mem)[c->offset + chunklen_strlen];
29423 + /* bingo, chunk-header is finished */
29428 + chunklen_strlen++;
29429 + } while (ch != '\n' && c != '\0');
29431 + if (ch != '\n') {
29432 + ERROR("%s", "missing the CRLF");
29436 + we_need = chunk_len + chunklen_strlen + 2;
29437 + /* do we have the full chunk ? */
29438 + for (c = raw->first; c; c = c->next) {
29439 + we_have += c->mem->used - 1 - c->offset;
29441 + /* we have enough, jump out */
29442 + if (we_have > we_need) break;
29445 + /* get more data */
29446 + if (we_have < we_need) {
29450 + /* skip the chunk-header */
29451 + chunkqueue_skip(raw, chunklen_strlen);
29453 + /* final chunk */
29454 + if (chunk_len == 0) {
29455 + chunkqueue_skip(raw, 2);
29460 + /* we have enough, copy the data */
29461 + for (c = raw->first; c && chunk_len; c = c->next) {
29462 + off_t we_want = 0;
29463 + buffer *b = chunkqueue_get_append_buffer(decoded);
29465 + we_want = chunk_len > (c->mem->used - c->offset - 1) ? c->mem->used - c->offset - 1: chunk_len;
29467 + buffer_copy_string_len(b, c->mem->ptr + c->offset, we_want);
29469 + c->offset += we_want;
29470 + chunk_len -= we_want;
29473 + /* skip the \r\n */
29474 + chunkqueue_skip(raw, 2);
29476 + /* we are done, give the connection to someone else */
29477 + chunkqueue_remove_finished_chunks(raw);
29480 + /* no chunked encoding, ok, perhaps a content-length ? */
29482 + chunkqueue_remove_finished_chunks(raw);
29483 + for (c = raw->first; c; c = c->next) {
29486 + if (c->mem->used == 0) continue;
29488 + b = chunkqueue_get_append_buffer(decoded);
29490 + sess->bytes_read += c->mem->used - c->offset - 1;
29492 + buffer_copy_string_len(b, c->mem->ptr + c->offset, c->mem->used - c->offset - 1);
29494 + c->offset = c->mem->used - 1;
29496 + if (sess->bytes_read == sess->content_length) {
29501 + if (sess->bytes_read == sess->content_length) {
29502 + return 1; /* finished */
29508 +/* don't call any proxy functions directly */
29509 +static handler_t proxy_handle_fdevent(void *s, void *ctx, int revents) {
29510 + server *srv = (server *)s;
29511 + proxy_session *sess = ctx;
29513 + if (revents & FDEVENT_OUT) {
29514 + switch (sess->state) {
29515 + case PROXY_STATE_CONNECTING: /* delayed connect */
29516 + case PROXY_STATE_WRITE_REQUEST_HEADER:
29517 + case PROXY_STATE_WRITE_REQUEST_BODY:
29518 + /* we are still connection */
29520 + joblist_append(srv, sess->remote_con);
29523 + ERROR("oops, unexpected state for fdevent-out %d", sess->state);
29526 + } else if (revents & FDEVENT_IN) {
29529 + switch (sess->state) {
29530 + case PROXY_STATE_READ_RESPONSE_HEADER:
29531 + /* call our header parser */
29532 + joblist_append(srv, sess->remote_con);
29534 + case PROXY_STATE_READ_RESPONSE_BODY:
29535 + /* we should be in the WRITE state now,
29536 + * just read in the content and forward it to the outgoing connection
29539 + chunkqueue_remove_finished_chunks(sess->recv_raw);
29540 + switch (srv->network_backend_read(srv, sess->remote_con, sess->proxy_con->sock, sess->recv_raw)) {
29541 + case NETWORK_STATUS_CONNECTION_CLOSE:
29542 + fdevent_event_del(srv->ev,sess->proxy_con->sock);
29544 + /* the connection is gone
29545 + * make the connect */
29546 + sess->remote_con->file_finished = 1;
29547 + sess->proxy_con->state = PROXY_CONNECTION_STATE_CLOSED;
29549 + case NETWORK_STATUS_SUCCESS:
29550 + /* read even more, do we have all the content */
29552 + /* how much do we want to read ? */
29554 + /* call stream-decoder (HTTP-chunked, FastCGI, ... ) */
29556 + switch (proxy_http_stream_decoder(srv, sess, sess->recv_raw, sess->recv)) {
29564 + /* we are done */
29565 + sess->remote_con->file_finished = 1;
29569 + chunkqueue_remove_finished_chunks(sess->recv_raw);
29571 + /* copy the content to the next cq */
29572 + for (c = sess->recv->first; c; c = c->next) {
29573 + if (c->mem->used == 0) continue;
29575 + http_chunk_append_mem(srv, sess->remote_con, c->mem->ptr + c->offset, c->mem->used - c->offset);
29577 + c->offset = c->mem->used - 1;
29580 + chunkqueue_remove_finished_chunks(sess->recv);
29582 + if (sess->remote_con->file_finished) {
29583 + /* send final HTTP-Chunk packet */
29584 + http_chunk_append_mem(srv, sess->remote_con, NULL, 0);
29589 + ERROR("%s", "oops, we failed to read");
29593 + joblist_append(srv, sess->remote_con);
29596 + ERROR("oops, unexpected state for fdevent-in %d", sess->state);
29601 + if (revents & FDEVENT_HUP) {
29602 + /* someone closed our connection */
29603 + switch (sess->state) {
29604 + case PROXY_STATE_CONNECTING:
29605 + /* let the getsockopt() catch this */
29606 + joblist_append(srv, sess->remote_con);
29609 + ERROR("oops, unexpected state for fdevent-hup %d", sess->state);
29614 + return HANDLER_GO_ON;
29617 +int pcre_replace(pcre *match, buffer *replace, buffer *match_buf, buffer *result) {
29618 + const char *pattern = replace->ptr;
29619 + size_t pattern_len = replace->used - 1;
29625 + if ((n = pcre_exec(match, NULL, match_buf->ptr, match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) {
29626 + if (n != PCRE_ERROR_NOMATCH) {
29630 + const char **list;
29631 + size_t start, end;
29635 + pcre_get_substring_list(match_buf->ptr, ovec, n, &list);
29637 + /* search for $[0-9] */
29639 + buffer_reset(result);
29641 + start = 0; end = pattern_len;
29642 + for (k = 0; k < pattern_len; k++) {
29643 + if ((pattern[k] == '$') &&
29644 + isdigit((unsigned char)pattern[k + 1])) {
29647 + size_t num = pattern[k + 1] - '0';
29651 + buffer_append_string_len(result, pattern + start, end - start);
29653 + /* n is always > 0 */
29654 + if (num < (size_t)n) {
29655 + buffer_append_string(result, list[num]);
29663 + buffer_append_string_len(result, pattern + start, pattern_len - start);
29672 + * generate a HTTP/1.1 proxy request from the set of request-headers
29674 + * TODO: this is HTTP-proxy specific and will be moved moved into a separate backed
29677 +int proxy_get_request_chunk(server *srv, connection *con, plugin_data *p, proxy_session *sess, chunkqueue *cq) {
29681 + b = chunkqueue_get_append_buffer(cq);
29683 + /* request line */
29684 + buffer_copy_string(b, get_http_method_name(con->request.http_method));
29685 + BUFFER_APPEND_STRING_CONST(b, " ");
29687 + /* check if we want to rewrite the uri */
29689 + for (i = 0; i < p->conf.request_rewrites->used; i++) {
29690 + proxy_rewrite *rw = p->conf.request_rewrites->ptr[i];
29692 + if (buffer_is_equal_string(rw->header, CONST_STR_LEN("_uri"))) {
29695 + if ((ret = pcre_replace(rw->regex, rw->replace, con->request.uri, p->replace_buf)) < 0) {
29697 + case PCRE_ERROR_NOMATCH:
29698 + /* hmm, ok. no problem */
29699 + buffer_append_string_buffer(b, con->request.uri);
29702 + TRACE("oops, pcre_replace failed with: %d", ret);
29706 + buffer_append_string_buffer(b, p->replace_buf);
29713 + if (i == p->conf.request_rewrites->used) {
29715 + buffer_append_string_buffer(b, con->request.uri);
29718 + BUFFER_APPEND_STRING_CONST(b, " HTTP/1.1\r\n");
29720 + for (i = 0; i < sess->request_headers->used; i++) {
29723 + ds = (data_string *)sess->request_headers->data[i];
29725 + buffer_append_string_buffer(b, ds->key);
29726 + BUFFER_APPEND_STRING_CONST(b, ": ");
29727 + buffer_append_string_buffer(b, ds->value);
29728 + BUFFER_APPEND_STRING_CONST(b, "\r\n");
29731 + BUFFER_APPEND_STRING_CONST(b, "\r\n");
29736 +void proxy_set_header(array *hdrs, const char *key, size_t key_len, const char *value, size_t val_len) {
29737 + data_string *ds_dst;
29739 + if (NULL != (ds_dst = (data_string *)array_get_element(hdrs, key))) {
29740 + buffer_copy_string_len(ds_dst->value, value, val_len);
29744 + if (NULL == (ds_dst = (data_string *)array_get_unused_element(hdrs, TYPE_STRING))) {
29745 + ds_dst = data_string_init();
29748 + buffer_copy_string_len(ds_dst->key, key, key_len);
29749 + buffer_copy_string_len(ds_dst->value, value, val_len);
29750 + array_insert_unique(hdrs, (data_unset *)ds_dst);
29753 +void proxy_append_header(array *hdrs, const char *key, size_t key_len, const char *value, size_t val_len) {
29754 + data_string *ds_dst;
29756 + if (NULL == (ds_dst = (data_string *)array_get_unused_element(hdrs, TYPE_STRING))) {
29757 + ds_dst = data_string_init();
29760 + buffer_copy_string_len(ds_dst->key, key, key_len);
29761 + buffer_copy_string_len(ds_dst->value, value, val_len);
29762 + array_insert_unique(hdrs, (data_unset *)ds_dst);
29767 + * build the request-header array and call the backend specific request formater
29768 + * to fill the chunkqueue
29770 +int proxy_get_request_header(server *srv, connection *con, plugin_data *p, proxy_session *sess) {
29771 + /* request line */
29772 + const char *remote_ip;
29775 + remote_ip = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
29776 + proxy_append_header(sess->request_headers, CONST_STR_LEN("X-Forwarded-For"), remote_ip, strlen(remote_ip));
29778 + /* http_host is NOT is just a pointer to a buffer
29779 + * which is NULL if it is not set */
29780 + if (con->request.http_host &&
29781 + !buffer_is_empty(con->request.http_host)) {
29782 + proxy_set_header(sess->request_headers, CONST_STR_LEN("X-Host"), CONST_BUF_LEN(con->request.http_host));
29784 + if (con->conf.is_ssl) {
29785 + proxy_set_header(sess->request_headers, CONST_STR_LEN("X-Forwarded-Proto"), CONST_STR_LEN("https"));
29787 + proxy_set_header(sess->request_headers, CONST_STR_LEN("X-Forwarded-Proto"), CONST_STR_LEN("http"));
29790 + /* request header */
29791 + for (i = 0; i < con->request.headers->used; i++) {
29795 + ds = (data_string *)con->request.headers->data[i];
29797 + if (buffer_is_empty(ds->value) || buffer_is_empty(ds->key)) continue;
29799 + if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Connection"))) continue;
29800 + if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Keep-Alive"))) continue;
29802 + for (k = 0; k < p->conf.request_rewrites->used; k++) {
29803 + proxy_rewrite *rw = p->conf.request_rewrites->ptr[k];
29805 + if (buffer_is_equal(rw->header, ds->key)) {
29808 + if ((ret = pcre_replace(rw->regex, rw->replace, ds->value, p->replace_buf)) < 0) {
29810 + case PCRE_ERROR_NOMATCH:
29811 + /* hmm, ok. no problem */
29812 + proxy_set_header(sess->request_headers, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
29815 + TRACE("oops, pcre_replace failed with: %d", ret);
29819 + proxy_set_header(sess->request_headers, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(p->replace_buf));
29826 + if (k == p->conf.request_rewrites->used) {
29827 + proxy_set_header(sess->request_headers, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
29831 + proxy_get_request_chunk(srv, con, p, sess, sess->send_raw);
29837 + * parse the response header
29839 + * NOTE: this can be used by all backends as they all send a HTTP-Response a clean block
29840 + * - fastcgi needs some decoding for the protocol
29842 +parse_status_t proxy_parse_response_header(server *srv, connection *con, plugin_data *p, proxy_session *sess, chunkqueue *cq) {
29843 + int have_content_length = 0;
29846 + http_response_reset(p->resp);
29848 + switch (http_response_parse_cq(cq, p->resp)) {
29849 + case PARSE_ERROR:
29850 + /* parsing failed */
29852 + return PARSE_ERROR;
29853 + case PARSE_NEED_MORE:
29854 + return PARSE_NEED_MORE;
29855 + case PARSE_SUCCESS:
29856 + con->http_status = p->resp->status;
29858 + chunkqueue_remove_finished_chunks(cq);
29860 + sess->content_length = -1;
29862 + /* copy the http-headers */
29863 + for (i = 0; i < p->resp->headers->used; i++) {
29864 + const char *ign[] = { "Status", "Connection", NULL };
29868 + data_string *header = (data_string *)p->resp->headers->data[i];
29870 + /* some headers are ignored by default */
29871 + for (j = 0; ign[j]; j++) {
29872 + if (0 == strcasecmp(ign[j], header->key->ptr)) break;
29874 + if (ign[j]) continue;
29876 + if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Location"))) {
29877 + /* CGI/1.1 rev 03 - 7.2.1.2 */
29878 + if (con->http_status == 0) con->http_status = 302;
29879 + } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Content-Length"))) {
29880 + have_content_length = 1;
29882 + sess->content_length = strtol(header->value->ptr, NULL, 10);
29884 + if (sess->content_length < 0) {
29885 + return PARSE_ERROR;
29887 + } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Transfer-Encoding"))) {
29888 + if (strstr(header->value->ptr, "chunked")) {
29889 + sess->is_chunked = 1;
29891 + /* ignore the header */
29895 + if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
29896 + ds = data_response_init();
29900 + buffer_copy_string_buffer(ds->key, header->key);
29902 + for (k = 0; k < p->conf.response_rewrites->used; k++) {
29903 + proxy_rewrite *rw = p->conf.response_rewrites->ptr[k];
29905 + if (buffer_is_equal(rw->header, header->key)) {
29908 + if ((ret = pcre_replace(rw->regex, rw->replace, header->value, p->replace_buf)) < 0) {
29910 + case PCRE_ERROR_NOMATCH:
29911 + /* hmm, ok. no problem */
29912 + buffer_append_string_buffer(ds->value, header->value);
29915 + TRACE("oops, pcre_replace failed with: %d", ret);
29919 + buffer_append_string_buffer(ds->value, p->replace_buf);
29926 + if (k == p->conf.response_rewrites->used) {
29927 + buffer_copy_string_buffer(ds->value, header->value);
29930 + array_insert_unique(con->response.headers, (data_unset *)ds);
29933 + /* does the client allow us to send chunked encoding ? */
29934 + if (con->request.http_version == HTTP_VERSION_1_1 &&
29935 + !have_content_length) {
29936 + con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
29942 + return PARSE_SUCCESS; /* we have a full header */
29945 +/* we are event-driven
29947 + * the first entry is connect() call, if the doesn't need a event
29950 + * - connect (+ delayed connect)
29951 + * - write header + content
29952 + * - read header + content
29954 + * as soon as have read the response header we switch con->file_started and return HANDLER_GO_ON to
29955 + * tell the core we are ready to stream out the content.
29957 +handler_t proxy_state_engine(server *srv, connection *con, plugin_data *p, proxy_session *sess) {
29958 + /* do we have a connection ? */
29960 + if (sess->state == PROXY_STATE_UNSET) {
29961 + /* we are not started yet */
29962 + switch(proxy_connection_connect(sess->proxy_con)) {
29963 + case HANDLER_WAIT_FOR_EVENT:
29964 + /* waiting on the connect call */
29966 + fdevent_register(srv->ev, sess->proxy_con->sock, proxy_handle_fdevent, sess);
29967 + fdevent_event_add(srv->ev, sess->proxy_con->sock, FDEVENT_OUT);
29969 + sess->state = PROXY_STATE_CONNECTING;
29970 + sess->proxy_con->state = PROXY_CONNECTION_STATE_CONNECTING;
29972 + return HANDLER_WAIT_FOR_EVENT;
29973 + case HANDLER_GO_ON:
29974 + /* we are connected */
29975 + sess->state = PROXY_STATE_CONNECTED;
29976 + sess->proxy_con->state = PROXY_CONNECTION_STATE_CONNECTED;
29977 + fdevent_register(srv->ev, sess->proxy_con->sock, proxy_handle_fdevent, sess);
29980 + case HANDLER_ERROR:
29982 + /* not good, something failed */
29983 + return HANDLER_ERROR;
29986 + } else if (sess->state == PROXY_STATE_CONNECTING) {
29987 + int socket_error;
29988 + socklen_t socket_error_len = sizeof(socket_error);
29990 + fdevent_event_del(srv->ev, sess->proxy_con->sock);
29992 + if (0 != getsockopt(sess->proxy_con->sock->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
29993 + ERROR("getsockopt failed:", strerror(errno));
29995 + return HANDLER_ERROR;
29997 + if (socket_error != 0) {
29998 + switch (socket_error) {
29999 + case ECONNREFUSED:
30000 + /* there is no-one on the other side */
30001 + sess->proxy_con->address->disabled_until = srv->cur_ts + 2;
30003 + TRACE("address %s refused us, disabling for 2 sec", sess->proxy_con->address->name->ptr);
30005 + case EHOSTUNREACH:
30006 + /* there is no-one on the other side */
30007 + sess->proxy_con->address->disabled_until = srv->cur_ts + 60;
30009 + TRACE("host %s is unreachable, disabling for 60 sec", sess->proxy_con->address->name->ptr);
30012 + sess->proxy_con->address->disabled_until = srv->cur_ts + 60;
30014 + TRACE("connected finally failed: %s (%d)", strerror(socket_error), socket_error);
30016 + TRACE("connect to address %s failed and I don't know why, disabling for 10 sec", sess->proxy_con->address->name->ptr);
30021 + sess->proxy_con->address->state = PROXY_ADDRESS_STATE_DISABLED;
30023 + sess->proxy_con->state = PROXY_CONNECTION_STATE_CLOSED;
30024 + return HANDLER_COMEBACK;
30027 + sess->state = PROXY_STATE_CONNECTED;
30028 + sess->proxy_con->state = PROXY_CONNECTION_STATE_CONNECTED;
30031 + if (sess->state == PROXY_STATE_CONNECTED) {
30032 + /* build the header */
30033 + proxy_get_request_header(srv, con, p, sess);
30035 + sess->state = PROXY_STATE_WRITE_REQUEST_HEADER;
30038 + switch (sess->state) {
30039 + case PROXY_STATE_WRITE_REQUEST_HEADER:
30040 + /* create the request-packet */
30041 + fdevent_event_del(srv->ev, sess->proxy_con->sock);
30043 + switch (srv->network_backend_write(srv, con, sess->proxy_con->sock, sess->send_raw)) {
30044 + case NETWORK_STATUS_SUCCESS:
30045 + sess->state = PROXY_STATE_WRITE_REQUEST_BODY;
30047 + case NETWORK_STATUS_WAIT_FOR_EVENT:
30048 + fdevent_event_add(srv->ev, sess->proxy_con->sock, FDEVENT_OUT);
30050 + return HANDLER_WAIT_FOR_EVENT;
30051 + case NETWORK_STATUS_CONNECTION_CLOSE:
30052 + sess->proxy_con->state = PROXY_CONNECTION_STATE_CLOSED;
30054 + /* this connection is closed, restart the request with a new connection */
30056 + return HANDLER_COMEBACK;
30058 + return HANDLER_ERROR;
30060 + /* fall through */
30061 + case PROXY_STATE_WRITE_REQUEST_BODY:
30062 + fdevent_event_del(srv->ev, sess->proxy_con->sock);
30063 + sess->state = PROXY_STATE_READ_RESPONSE_HEADER;
30065 + case PROXY_STATE_READ_RESPONSE_HEADER:
30066 + fdevent_event_del(srv->ev, sess->proxy_con->sock);
30068 + chunkqueue_remove_finished_chunks(sess->recv_raw);
30070 + switch (srv->network_backend_read(srv, con, sess->proxy_con->sock, sess->recv_raw)) {
30071 + case NETWORK_STATUS_SUCCESS:
30072 + /* we read everything from the socket, do we have a full header ? */
30074 + switch (proxy_parse_response_header(srv, con, p, sess, sess->recv_raw)) {
30075 + case PARSE_ERROR:
30076 + con->http_status = 502; /* bad gateway */
30078 + return HANDLER_FINISHED;
30079 + case PARSE_NEED_MORE:
30080 + /* we need more */
30081 + fdevent_event_add(srv->ev, sess->proxy_con->sock, FDEVENT_IN);
30083 + return HANDLER_WAIT_FOR_EVENT;
30084 + case PARSE_SUCCESS:
30087 + return HANDLER_ERROR;
30090 + con->file_started = 1;
30092 + sess->state = PROXY_STATE_READ_RESPONSE_BODY;
30095 + * set the event to pass the content through to the server
30097 + * this triggers the event-handler
30098 + * @see proxy_handle_fdevent
30100 + fdevent_event_add(srv->ev, sess->proxy_con->sock, FDEVENT_IN);
30102 + return HANDLER_GO_ON; /* tell http_response_prepare that we are done with the header */
30103 + case NETWORK_STATUS_WAIT_FOR_EVENT:
30104 + fdevent_event_add(srv->ev, sess->proxy_con->sock, FDEVENT_IN);
30105 + return HANDLER_WAIT_FOR_EVENT;
30106 + case NETWORK_STATUS_CONNECTION_CLOSE:
30107 + if (chunkqueue_length(sess->recv_raw) == 0) {
30108 + /* the connection went away before we got something back */
30109 + sess->proxy_con->state = PROXY_CONNECTION_STATE_CLOSED;
30112 + * we might run into a 'race-condition'
30114 + * 1. proxy-con is keep-alive, idling and just being closed (FDEVENT_IN) [fd=27]
30115 + * 2. new connection comes in, we use the idling connection [fd=14]
30116 + * 3. we write(), successful [to fd=27]
30117 + * 3. we read() ... and finally receive the close-event for the connection
30120 + con->http_status = 500;
30122 + ERROR("++ %s", "oops, connection got closed while we were reading from it");
30123 + return HANDLER_FINISHED;
30126 + ERROR("%s", "conn-close after header-read");
30130 + ERROR("++ %s", "oops, something went wrong while reading");
30131 + return HANDLER_ERROR;
30133 + case PROXY_STATE_READ_RESPONSE_BODY:
30134 + /* if we do everything right, we won't get call for this state-anymore */
30136 + ERROR("%s", "PROXY_STATE_READ_RESPONSE_BODY");
30141 + return HANDLER_GO_ON;
30144 +proxy_backend *proxy_get_backend(server *srv, connection *con, plugin_data *p) {
30147 + for (i = 0; i < p->conf.backends->used; i++) {
30148 + proxy_backend *backend = p->conf.backends->ptr[i];
30157 + * choose a available address from the address-pool
30159 + * the backend has different balancers
30161 +proxy_address *proxy_backend_balance(server *srv, connection *con, proxy_backend *backend) {
30163 + proxy_address_pool *address_pool = backend->address_pool;
30164 + unsigned long last_max; /* for the HASH balancer */
30165 + proxy_address *address = NULL, *cur_address = NULL;
30166 + int active_addresses = 0, rand_ndx;
30168 + switch(backend->balancer) {
30169 + case PROXY_BALANCE_HASH:
30170 + /* hash balancing */
30172 + for (i = 0, last_max = ULONG_MAX; i < address_pool->used; i++) {
30173 + unsigned long cur_max;
30175 + cur_address = address_pool->ptr[i];
30177 + if (cur_address->state != PROXY_ADDRESS_STATE_ACTIVE) continue;
30179 + cur_max = generate_crc32c(CONST_BUF_LEN(con->uri.path)) +
30180 + generate_crc32c(CONST_BUF_LEN(cur_address->name)) + /* we can cache this */
30181 + generate_crc32c(CONST_BUF_LEN(con->uri.authority));
30183 + TRACE("hash-election: %s - %s - %s: %ld",
30184 + con->uri.path->ptr,
30185 + cur_address->name->ptr,
30186 + con->uri.authority->ptr,
30189 + if (address == NULL || (cur_max > last_max)) {
30190 + last_max = cur_max;
30192 + address = cur_address;
30197 + case PROXY_BALANCE_FAIR:
30198 + /* fair balancing */
30200 + for (i = 0; i < address_pool->used; i++) {
30201 + cur_address = address_pool->ptr[i];
30203 + if (cur_address->state != PROXY_ADDRESS_STATE_ACTIVE) continue;
30205 + /* the address is up, use it */
30207 + address = cur_address;
30213 + case PROXY_BALANCE_RR:
30214 + /* round robin */
30217 + * instead of real RoundRobin we just do a RandomSelect
30219 + * it is state-less and has the same distribution
30222 + active_addresses = 0;
30224 + for (i = 0; i < address_pool->used; i++) {
30225 + cur_address = address_pool->ptr[i];
30227 + if (cur_address->state != PROXY_ADDRESS_STATE_ACTIVE) continue;
30229 + active_addresses++;
30232 + rand_ndx = (int) (1.0 * active_addresses * rand()/(RAND_MAX));
30234 + active_addresses = 0;
30235 + for (i = 0; i < address_pool->used; i++) {
30236 + cur_address = address_pool->ptr[i];
30238 + if (cur_address->state != PROXY_ADDRESS_STATE_ACTIVE) continue;
30240 + address = cur_address;
30242 + if (rand_ndx == active_addresses++) break;
30253 +static int mod_proxy_core_patch_connection(server *srv, connection *con, plugin_data *p) {
30255 + plugin_config *s = p->config_storage[0];
30257 + /* global defaults */
30258 + PATCH_OPTION(balancer);
30259 + PATCH_OPTION(debug);
30260 + PATCH_OPTION(backends);
30261 + PATCH_OPTION(backlog);
30262 + PATCH_OPTION(protocol);
30263 + PATCH_OPTION(request_rewrites);
30264 + PATCH_OPTION(response_rewrites);
30266 + /* skip the first, the global context */
30267 + for (i = 1; i < srv->config_context->used; i++) {
30268 + data_config *dc = (data_config *)srv->config_context->data[i];
30269 + s = p->config_storage[i];
30271 + /* condition didn't match */
30272 + if (!config_check_cond(srv, con, dc)) continue;
30274 + /* merge config */
30275 + for (j = 0; j < dc->value->used; j++) {
30276 + data_unset *du = dc->value->data[j];
30278 + if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_PROXY_CORE_BACKENDS))) {
30279 + PATCH_OPTION(backends);
30280 + PATCH_OPTION(backlog);
30281 + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_PROXY_CORE_DEBUG))) {
30282 + PATCH_OPTION(debug);
30283 + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_PROXY_CORE_BALANCER))) {
30284 + PATCH_OPTION(balancer);
30285 + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_PROXY_CORE_PROTOCOL))) {
30286 + PATCH_OPTION(protocol);
30287 + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_PROXY_CORE_REWRITE_REQUEST))) {
30288 + PATCH_OPTION(request_rewrites);
30289 + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_PROXY_CORE_REWRITE_RESPONSE))) {
30290 + PATCH_OPTION(response_rewrites);
30299 +SUBREQUEST_FUNC(mod_proxy_core_check_extension) {
30300 + plugin_data *p = p_d;
30301 + proxy_session *sess = con->plugin_ctx[p->id]; /* if this is the second round, sess is already prepared */
30303 + /* check if we have a matching conditional for this request */
30305 + if (buffer_is_empty(con->uri.path)) return HANDLER_GO_ON;
30307 + mod_proxy_core_patch_connection(srv, con, p);
30309 + if (p->conf.backends->used == 0) return HANDLER_GO_ON;
30312 + * 0. build session
30313 + * 1. get a proxy connection
30314 + * 2. create the http-request header
30315 + * 3. stream the content to the backend
30316 + * 4. wait for http-response header
30317 + * 5. decode the response + parse the response
30318 + * 6. stream the response-content to the client
30319 + * 7. kill session
30323 + /* a session lives for a single request */
30324 + sess = proxy_session_init();
30326 + con->plugin_ctx[p->id] = sess;
30327 + con->mode = p->id;
30329 + sess->remote_con = con;
30332 + switch (sess->state) {
30333 + case PROXY_STATE_CONNECTING:
30334 + /* this connections is waited 10 seconds to connect to the backend
30335 + * and didn't got a successful connection yet, sending timeout */
30336 + if (srv->cur_ts - con->request_start > 10) {
30337 + con->http_status = 504; /* gateway timeout */
30338 + con->file_finished = 1;
30340 + if (sess->proxy_con) {
30341 + /* if we are waiting for a proxy-connection right now, close it */
30342 + proxy_connection_pool_remove_connection(sess->proxy_backend->pool, sess->proxy_con);
30344 + fdevent_event_del(srv->ev, sess->proxy_con->sock);
30345 + fdevent_unregister(srv->ev, sess->proxy_con->sock);
30347 + proxy_connection_free(sess->proxy_con);
30349 + sess->proxy_con = NULL;
30352 + return HANDLER_FINISHED;
30355 + /* handle-request-timeout, */
30356 + if (srv->cur_ts - con->request_start > 60) {
30357 + TRACE("request runs longer than 60sec: current state: %d", sess->state);
30362 + /* if the WRITE fails from the start, restart the connection */
30364 + if (sess->proxy_con == NULL) {
30365 + proxy_address *address = NULL;
30366 + if (NULL == (sess->proxy_backend = proxy_get_backend(srv, con, p))) {
30367 + /* no connection pool for this location */
30371 + sess->proxy_backend->balancer = p->conf.balancer;
30374 + * ask the balancer for the next address and
30375 + * check the connection pool if we have a connection open
30376 + * for that address
30378 + if (NULL == (address = proxy_backend_balance(srv, con, sess->proxy_backend))) {
30379 + /* we don't have any backends to connect to */
30380 + proxy_request *req;
30382 + /* connection pool is full, queue the request for now */
30383 + req = proxy_request_init();
30384 + req->added_ts = srv->cur_ts;
30387 + TRACE("backlog: all backends are down, putting %s (%d) into the backlog", BUF_STR(con->uri.path), con->sock->fd);
30388 + proxy_backlog_push(p->conf.backlog, req);
30390 + /* no, not really a event,
30391 + * we just want to block the outer loop from stepping forward
30393 + * the trigger will bring this connection back into the game
30395 + return HANDLER_WAIT_FOR_EVENT;
30398 + if (PROXY_CONNECTIONPOOL_FULL == proxy_connection_pool_get_connection(
30399 + sess->proxy_backend->pool,
30401 + &(sess->proxy_con))) {
30402 + proxy_request *req;
30404 + /* connection pool is full, queue the request for now */
30405 + req = proxy_request_init();
30406 + req->added_ts = srv->cur_ts;
30409 + TRACE("backlog: the con-pool is full, putting %s (%d) into the backlog", con->uri.path->ptr, con->sock->fd);
30410 + proxy_backlog_push(p->conf.backlog, req);
30412 + /* no, not really a event,
30413 + * we just want to block the outer loop from stepping forward
30415 + * the trigger will bring this connection back into the game
30417 + return HANDLER_WAIT_FOR_EVENT;
30420 + /* a fresh connection, we need address for it */
30421 + if (sess->proxy_con->state == PROXY_CONNECTION_STATE_CONNECTING) {
30422 + sess->state = PROXY_STATE_UNSET;
30423 + sess->bytes_read = 0;
30425 + /* we are already connected */
30426 + sess->state = PROXY_STATE_CONNECTED;
30428 + /* the connection was idling and using the fdevent_idle-handler
30429 + * switch it back to the normal proxy-event-handler */
30430 + fdevent_event_del(srv->ev, sess->proxy_con->sock);
30431 + fdevent_unregister(srv->ev, sess->proxy_con->sock);
30433 + fdevent_register(srv->ev, sess->proxy_con->sock, proxy_handle_fdevent, sess);
30434 + fdevent_event_add(srv->ev, sess->proxy_con->sock, FDEVENT_IN);
30438 + switch (proxy_state_engine(srv, con, p, sess)) {
30439 + case HANDLER_WAIT_FOR_EVENT:
30440 + return HANDLER_WAIT_FOR_EVENT;
30441 + case HANDLER_COMEBACK:
30442 + proxy_connection_pool_remove_connection(sess->proxy_backend->pool, sess->proxy_con);
30444 + fdevent_event_del(srv->ev, sess->proxy_con->sock);
30445 + fdevent_unregister(srv->ev, sess->proxy_con->sock);
30447 + proxy_connection_free(sess->proxy_con);
30449 + sess->proxy_con = NULL;
30450 + /* restart the connection to the backend */
30451 + TRACE("%s", "write failed, restarting request");
30453 + case HANDLER_GO_ON:
30454 + return HANDLER_GO_ON;
30456 + return HANDLER_ERROR;
30460 + /* should not be reached */
30461 + return HANDLER_ERROR;
30465 + * end of the connection to the client
30467 +REQUESTDONE_FUNC(mod_proxy_connection_close_callback) {
30468 + plugin_data *p = p_d;
30470 + if (con->mode != p->id) return HANDLER_GO_ON;
30472 + return HANDLER_GO_ON;
30476 + * end of a request
30478 +CONNECTION_FUNC(mod_proxy_connection_reset) {
30479 + plugin_data *p = p_d;
30480 + proxy_session *sess = con->plugin_ctx[p->id];
30482 + if (con->mode != p->id) return HANDLER_GO_ON;
30484 + if (sess->proxy_con) {
30485 + switch (sess->proxy_con->state) {
30486 + case PROXY_CONNECTION_STATE_CONNECTED:
30487 + sess->proxy_con->state = PROXY_CONNECTION_STATE_IDLE;
30489 + /* ignore events as the FD is idle, we might get a HUP as the remote connection might close */
30490 + fdevent_event_del(srv->ev, sess->proxy_con->sock);
30491 + fdevent_unregister(srv->ev, sess->proxy_con->sock);
30493 + fdevent_register(srv->ev, sess->proxy_con->sock, proxy_handle_fdevent_idle, sess->proxy_con);
30494 + fdevent_event_add(srv->ev, sess->proxy_con->sock, FDEVENT_IN);
30497 + case PROXY_CONNECTION_STATE_CLOSED:
30498 + proxy_connection_pool_remove_connection(sess->proxy_backend->pool, sess->proxy_con);
30500 + fdevent_event_del(srv->ev, sess->proxy_con->sock);
30501 + fdevent_unregister(srv->ev, sess->proxy_con->sock);
30503 + proxy_connection_free(sess->proxy_con);
30505 + case PROXY_CONNECTION_STATE_IDLE:
30506 + TRACE("%s", "... connection is already back in the pool");
30509 + ERROR("connection is in a unexpected state at close-time: %d", sess->proxy_con->state);
30513 + /* if we have the connection in the backlog, remove it */
30514 + proxy_backlog_remove_connection(p->conf.backlog, con);
30518 + proxy_session_free(sess);
30520 + con->plugin_ctx[p->id] = NULL;
30522 + return HANDLER_GO_ON;
30528 + * cleanup dead connections once a second
30530 + * the idling event-handler can't cleanup connections itself and has to wait until the
30531 + * trigger cleans up
30533 +handler_t mod_proxy_trigger_context(server *srv, plugin_config *p) {
30535 + proxy_request *req;
30537 + for (i = 0; i < p->backends->used; i++) {
30538 + proxy_backend *backend = p->backends->ptr[i];
30539 + proxy_connection_pool *pool = backend->pool;
30540 + proxy_address_pool *address_pool = backend->address_pool;
30542 + for (j = 0; j < pool->used; ) {
30543 + proxy_connection *proxy_con = pool->ptr[j];
30545 + /* remove-con is removing the current con and moves the good connections to the left
30546 + * no need to increment i */
30547 + if (proxy_con->state == PROXY_CONNECTION_STATE_CLOSED) {
30548 + proxy_connection_pool_remove_connection(backend->pool, proxy_con);
30550 + fdevent_event_del(srv->ev, proxy_con->sock);
30551 + fdevent_unregister(srv->ev, proxy_con->sock);
30553 + proxy_connection_free(proxy_con);
30559 + /* active the disabled addresses again */
30560 + for (j = 0; j < address_pool->used; j++) {
30561 + proxy_address *address = address_pool->ptr[j];
30563 + if (address->state != PROXY_ADDRESS_STATE_DISABLED) continue;
30565 + if (srv->cur_ts > address->disabled_until) {
30566 + address->disabled_until = 0;
30567 + address->state = PROXY_ADDRESS_STATE_ACTIVE;
30572 + /* wake up the connections from the backlog */
30573 + while ((req = proxy_backlog_shift(p->backlog))) {
30574 + connection *con = req->con;
30576 + joblist_append(srv, con);
30578 + proxy_request_free(req);
30581 + return HANDLER_GO_ON;
30584 +TRIGGER_FUNC(mod_proxy_trigger) {
30585 + plugin_data *p = p_d;
30588 + for (i = 0; i < srv->config_context->used; i++) {
30589 + mod_proxy_trigger_context(srv, p->config_storage[i]);
30592 + return HANDLER_GO_ON;
30595 +int mod_proxy_core_plugin_init(plugin *p) {
30596 + p->version = LIGHTTPD_VERSION_ID;
30597 + p->name = buffer_init_string("mod_proxy_core");
30599 + p->init = mod_proxy_core_init;
30600 + p->cleanup = mod_proxy_core_free;
30601 + p->set_defaults = mod_proxy_core_set_defaults;
30602 + p->handle_uri_clean = mod_proxy_core_check_extension;
30603 + p->handle_subrequest_start = mod_proxy_core_check_extension;
30604 + p->handle_subrequest = mod_proxy_core_check_extension;
30605 + p->connection_reset = mod_proxy_connection_reset;
30606 + p->handle_connection_close = mod_proxy_connection_close_callback;
30607 + p->handle_trigger = mod_proxy_trigger;
30613 --- ../lighttpd-1.4.11/src/mod_proxy_core.h 1970-01-01 03:00:00.000000000 +0300
30614 +++ lighttpd-1.4.12/src/mod_proxy_core.h 2006-07-18 13:03:40.000000000 +0300
30616 +#ifndef _MOD_PROXY_CORE_H_
30617 +#define _MOD_PROXY_CORE_H_
30619 +#include "buffer.h"
30622 +#define PROXY_BACKEND_CONNECT_PARAMS \
30623 + (server *srv, connection *con, void *p_d)
30625 +#define PROXY_BACKEND_CONNECT_RETVAL handler_t
30627 +#define PROXY_BACKEND_CONNECT(name) \
30628 + PROXY_BACKEND_CONNECT_RETVAL name PROXY_BACKEND_CONNECT_PARAMS
30630 +#define PROXY_BACKEND_CONNECT_PTR(name) \
30631 + PROXY_BACKEND_CONNECT_RETVAL (* name)PROXY_BACKEND_CONNECT_PARAMS
30634 --- ../lighttpd-1.4.11/src/mod_proxy_core_address.c 1970-01-01 03:00:00.000000000 +0300
30635 +++ lighttpd-1.4.12/src/mod_proxy_core_address.c 2006-07-20 00:57:20.000000000 +0300
30637 +#include <stdlib.h>
30638 +#include <string.h>
30641 +#include "sys-socket.h"
30642 +#include "mod_proxy_core_address.h"
30644 +proxy_address *proxy_address_init(void) {
30645 + proxy_address *address;
30647 + address = calloc(1, sizeof(*address));
30649 + address->name = buffer_init();
30654 +void proxy_address_free(proxy_address *address) {
30655 + if (!address) return;
30657 + buffer_free(address->name);
30663 +proxy_address_pool *proxy_address_pool_init(void) {
30664 + proxy_address_pool *address_pool;
30666 + address_pool = calloc(1, sizeof(*address_pool));
30668 + return address_pool;
30671 +void proxy_address_pool_free(proxy_address_pool *address_pool) {
30672 + if (!address_pool) return;
30674 + FOREACH(address_pool, element, proxy_address_free(element));
30676 + if (address_pool->ptr) free(address_pool->ptr);
30678 + free(address_pool);
30681 +void proxy_address_pool_add(proxy_address_pool *address_pool, proxy_address *address) {
30684 + /* check if this address is already known */
30686 + for (i = 0; i < address_pool->used; i++) {
30687 + proxy_address *pool_address = address_pool->ptr[i];
30689 + if (buffer_is_equal(address->name, pool_address->name)) {
30690 + TRACE("%s is already in the address-pool", BUF_STR(address->name));
30692 + proxy_address_free(address);
30698 + TRACE("adding %s to the address-pool", BUF_STR(address->name));
30700 + ARRAY_STATIC_PREPARE_APPEND(address_pool);
30702 + address_pool->ptr[address_pool->used++] = address;
30705 +int proxy_address_pool_add_string(proxy_address_pool *address_pool, buffer *name) {
30706 + struct addrinfo *res = NULL, pref, *cur;
30708 + buffer *hostname = NULL, *port = NULL;
30711 + pref.ai_flags = 0;
30712 + pref.ai_family = PF_UNSPEC;
30713 + pref.ai_socktype = SOCK_STREAM;
30714 + pref.ai_protocol = 0;
30715 + pref.ai_addrlen = 0;
30716 + pref.ai_addr = NULL;
30717 + pref.ai_canonname = NULL;
30718 + pref.ai_next = NULL;
30720 + /* check the address style
30722 + * unix:/tmp/socket
30723 + * www.example.org
30724 + * www.example.org:80
30731 + if (buffer_is_empty(name)) return -1;
30733 + if (0 == strncmp(BUF_STR(name), "unix:", 5)) {
30734 + /* a unix domain socket */
30735 + ERROR("unix: scheme is not supported for %s", BUF_STR(name));
30737 + } else if (name->ptr[0] == '[') {
30738 + if (name->ptr[name->used - 1] == ']') {
30739 + /* no port-number attached */
30741 + hostname = buffer_init();
30742 + buffer_copy_string_len(hostname, BUF_STR(name) + 1, name->used - 3);
30743 + port = buffer_init_string("80");
30744 + } else if (NULL != (colon = strrchr(BUF_STR(name), ':'))) {
30745 + /* with port number */
30747 + hostname = buffer_init();
30748 + buffer_copy_string_len(hostname, BUF_STR(name) + 1, colon - BUF_STR(name) - 2);
30749 + port = buffer_init();
30750 + buffer_copy_string(port, colon + 1);
30753 + ERROR("this is neither [<ipv6-address>] nor [<ipv6-address>]:<port>: %s", BUF_STR(name));
30757 + } else if (name->ptr[name->used - 1] != ']' &&
30758 + NULL != (colon = strrchr(BUF_STR(name), ':'))) {
30760 + hostname = buffer_init();
30761 + buffer_copy_string_len(hostname, BUF_STR(name), colon - BUF_STR(name));
30762 + port = buffer_init();
30763 + buffer_copy_string(port, colon + 1);
30765 + /* no colon, just a IPv4 address or a domain name */
30767 + hostname = buffer_init_string(BUF_STR(name));
30768 + port = buffer_init_string("80");
30771 + TRACE("resolving %s on port %s", BUF_STR(hostname), BUF_STR(port));
30773 + if (0 != (ret = getaddrinfo(BUF_STR(hostname), BUF_STR(port), &pref, &res))) {
30774 + ERROR("getaddrinfo failed: %s", gai_strerror(ret));
30776 + buffer_free(hostname);
30777 + buffer_free(port);
30782 + buffer_free(hostname);
30783 + buffer_free(port);
30785 + for (cur = res; cur; cur = cur->ai_next) {
30786 + proxy_address *a = proxy_address_init();
30788 + memcpy(&(a->addr), cur->ai_addr, cur->ai_addrlen);
30790 + a->state = PROXY_ADDRESS_STATE_ACTIVE;
30791 + buffer_prepare_copy(a->name, 128);
30793 + switch (cur->ai_family) {
30795 + a->name->ptr[0] = '[';
30796 + inet_ntop(cur->ai_family, &(a->addr.ipv6.sin6_addr), a->name->ptr + 1, a->name->size - 2);
30797 + a->name->used = strlen(a->name->ptr) + 1;
30798 + buffer_append_string(a->name, "]:");
30799 + buffer_append_long(a->name, ntohs(a->addr.ipv6.sin6_port));
30802 + inet_ntop(cur->ai_family, &(a->addr.ipv4.sin_addr), a->name->ptr, a->name->size - 1);
30803 + a->name->used = strlen(a->name->ptr) + 1;
30805 + buffer_append_string(a->name, ":");
30806 + buffer_append_long(a->name, ntohs(a->addr.ipv4.sin_port));
30809 + ERROR("unknown address-family: %d", cur->ai_family);
30814 + proxy_address_pool_add(address_pool, a);
30817 + freeaddrinfo(res);
30823 --- ../lighttpd-1.4.11/src/mod_proxy_core_address.h 1970-01-01 03:00:00.000000000 +0300
30824 +++ lighttpd-1.4.12/src/mod_proxy_core_address.h 2006-07-18 13:03:40.000000000 +0300
30826 +#ifndef _MOD_PROXY_CORE_ADDRESS_H_
30827 +#define _MOD_PROXY_CORE_ADDRESS_H_
30830 +#include "buffer.h"
30831 +#include "sys-socket.h"
30832 +#include "array-static.h"
30835 + PROXY_ADDRESS_STATE_UNSET,
30836 + PROXY_ADDRESS_STATE_ACTIVE,
30837 + PROXY_ADDRESS_STATE_DISABLED,
30838 +} proxy_address_state_t;
30843 + buffer *name; /* a inet_ntoa() prepresentation of the address */
30845 + time_t last_used;
30846 + time_t disabled_until;
30848 + proxy_address_state_t state;
30851 +ARRAY_STATIC_DEF(proxy_address_pool, proxy_address, );
30853 +proxy_address_pool *proxy_address_pool_init(void);
30854 +void proxy_address_pool_free(proxy_address_pool *address_pool);
30855 +void proxy_address_pool_add(proxy_address_pool *address_pool, proxy_address *address);
30856 +int proxy_address_pool_add_string(proxy_address_pool *address_pool, buffer *address);
30859 --- ../lighttpd-1.4.11/src/mod_proxy_core_backend.c 1970-01-01 03:00:00.000000000 +0300
30860 +++ lighttpd-1.4.12/src/mod_proxy_core_backend.c 2006-07-20 00:57:19.000000000 +0300
30862 +#include <stdlib.h>
30864 +#include "mod_proxy_core_backend.h"
30865 +#include "mod_proxy_core_pool.h"
30866 +#include "mod_proxy_core_address.h"
30868 +proxy_backend *proxy_backend_init(void) {
30869 + proxy_backend *backend;
30871 + backend = calloc(1, sizeof(*backend));
30872 + backend->pool = proxy_connection_pool_init();
30873 + backend->address_pool = proxy_address_pool_init();
30874 + backend->balancer = PROXY_BALANCE_RR;
30879 +void proxy_backend_free(proxy_backend *backend) {
30880 + if (!backend) return;
30882 + proxy_address_pool_free(backend->address_pool);
30883 + proxy_connection_pool_free(backend->pool);
30888 +proxy_backends *proxy_backends_init(void) {
30889 + proxy_backends *backends;
30891 + backends = calloc(1, sizeof(*backends));
30896 +void proxy_backends_free(proxy_backends *backends) {
30897 + FOREACH(backends, element, proxy_backend_free(element))
30899 + if (backends->ptr) free(backends->ptr);
30904 +void proxy_backends_add(proxy_backends *backends, proxy_backend *backend) {
30905 + ARRAY_STATIC_PREPARE_APPEND(backends);
30907 + backends->ptr[backends->used++] = backend;
30909 --- ../lighttpd-1.4.11/src/mod_proxy_core_backend.h 1970-01-01 03:00:00.000000000 +0300
30910 +++ lighttpd-1.4.12/src/mod_proxy_core_backend.h 2006-07-18 13:03:40.000000000 +0300
30912 +#ifndef _MOD_PROXY_CORE_BACKEND_H_
30913 +#define _MOD_PROXY_CORE_BACKEND_H_
30915 +#include "array-static.h"
30916 +#include "buffer.h"
30917 +#include "mod_proxy_core_address.h"
30918 +#include "mod_proxy_core_pool.h"
30919 +#include "sys-socket.h"
30922 + * a single DNS name might explode to several IP addresses
30925 + * - http://foo.bar/suburl/
30926 + * - https://foo.bar/suburl/
30927 + * - unix:/tmp/socket
30928 + * - tcp://foobar:1025/
30935 + * request-url-rewrite
30936 + * response-url-rewrite
30939 + PROXY_BALANCE_UNSET,
30940 + PROXY_BALANCE_FAIR,
30941 + PROXY_BALANCE_HASH,
30943 +} proxy_balance_t;
30948 + proxy_connection_pool *pool; /* pool of active connections */
30949 + int use_keepalive;
30951 + proxy_address_pool *address_pool; /* possible destination-addresses, disabling is done here */
30952 + proxy_balance_t balancer; /* how to choose a address from the address-pool */
30955 +ARRAY_STATIC_DEF(proxy_backends, proxy_backend, );
30957 +proxy_backend *proxy_backend_init(void);
30958 +void proxy_backend_free(proxy_backend *backend);
30960 +proxy_backends *proxy_backends_init(void);
30961 +void proxy_backends_free(proxy_backends *backends);
30962 +void proxy_backends_add(proxy_backends *backends, proxy_backend *backend);
30966 --- ../lighttpd-1.4.11/src/mod_proxy_core_backlog.c 1970-01-01 03:00:00.000000000 +0300
30967 +++ lighttpd-1.4.12/src/mod_proxy_core_backlog.c 2006-07-18 13:03:40.000000000 +0300
30969 +#include <stdlib.h>
30971 +#include "mod_proxy_core_backlog.h"
30972 +#include "array-static.h"
30974 +proxy_backlog *proxy_backlog_init(void) {
30975 + STRUCT_INIT(proxy_backlog, backlog);
30980 +void proxy_backlog_free(proxy_backlog *backlog) {
30981 + if (!backlog) return;
30986 +int proxy_backlog_push(proxy_backlog *backlog, proxy_request *req) {
30987 + /* first entry */
30988 + if (NULL == backlog->first) {
30989 + backlog->first = backlog->last = req;
30991 + backlog->last->next = req;
30992 + backlog->last = req;
30994 + backlog->length++;
31000 + * remove the first element from the backlog
31002 +proxy_request *proxy_backlog_shift(proxy_backlog *backlog) {
31003 + proxy_request *req = NULL;
31005 + if (!backlog->first) return req;
31007 + backlog->length--;
31009 + req = backlog->first;
31011 + backlog->first = req->next;
31013 + /* the backlog is empty */
31014 + if (backlog->first == NULL) backlog->last = NULL;
31019 +int proxy_backlog_remove_connection(proxy_backlog *backlog, void *con) {
31020 + proxy_request *req = NULL;
31022 + if (!backlog->first) return -1;
31023 + if (!con) return -1;
31025 + /* the first element is what we look for */
31026 + if (backlog->first->con == con) {
31027 + req = backlog->first;
31029 + backlog->first = req->next;
31030 + if (backlog->first == NULL) backlog->last = NULL;
31032 + backlog->length--;
31034 + proxy_request_free(req);
31040 + for (req = backlog->first; req && req->next; req = req->next) {
31041 + proxy_request *cur;
31043 + if (req->next->con != con) continue;
31045 + backlog->length--;
31046 + /* the next node is our searched connection */
31049 + req->next = cur->next;
31051 + /* the next node is the last one, make the current the new last */
31052 + if (cur == backlog->last) {
31053 + backlog->last = req;
31055 + cur->next = NULL;
31057 + proxy_request_free(req);
31065 +proxy_request *proxy_request_init(void) {
31066 + STRUCT_INIT(proxy_request, request);
31071 +void proxy_request_free(proxy_request *request) {
31072 + if (!request) return;
31078 --- ../lighttpd-1.4.11/src/mod_proxy_core_backlog.h 1970-01-01 03:00:00.000000000 +0300
31079 +++ lighttpd-1.4.12/src/mod_proxy_core_backlog.h 2006-07-18 13:03:40.000000000 +0300
31081 +#ifndef _MOD_PROXY_CORE_BACKLOG_H_
31082 +#define _MOD_PROXY_CORE_BACKLOG_H_
31084 +#include <sys/types.h>
31085 +#include <sys/time.h>
31087 +typedef struct _proxy_request {
31088 + void *con; /* a pointer to the client-connection, (type: connection) */
31090 + time_t added_ts; /* when was the entry added (for timeout handling) */
31092 + struct _proxy_request *next;
31096 + * a we can't get a connection from the pool, queue the request in the
31097 + * request queue (FIFO)
31099 + * - the queue is infinite
31100 + * - entries are removed after a timeout (status 504)
31103 + proxy_request *first; /* pull() does q->first = q->first->next */
31104 + proxy_request *last; /* push() does q->last = r */
31109 +proxy_backlog *proxy_backlog_init(void);
31110 +void proxy_backlog_free(proxy_backlog *backlog);
31113 + * append a request to the end
31115 + * @return 0 in success, -1 if full
31117 +int proxy_backlog_push(proxy_backlog *backlog, proxy_request *req);
31120 + * remove the first request from the backlog
31122 + * @return NULL if backlog is empty, the request otherwise
31124 +proxy_request *proxy_backlog_shift(proxy_backlog *backlog);
31126 + * remove the request with the connection 'con' from the backlog
31128 + * @return -1 if not found, 0 otherwise
31130 +int proxy_backlog_remove_connection(proxy_backlog *backlog, void *con);
31132 +proxy_request *proxy_request_init(void);
31133 +void proxy_request_free(proxy_request *req);
31137 --- ../lighttpd-1.4.11/src/mod_proxy_core_pool.c 1970-01-01 03:00:00.000000000 +0300
31138 +++ lighttpd-1.4.12/src/mod_proxy_core_pool.c 2006-07-18 13:03:40.000000000 +0300
31141 +#include <stdlib.h>
31143 +#include "array-static.h"
31144 +#include "sys-files.h"
31146 +#include "mod_proxy_core_pool.h"
31148 +proxy_connection * proxy_connection_init(void) {
31149 + proxy_connection *con;
31151 + con = calloc(1, sizeof(*con));
31153 + con->sock = iosocket_init();
31158 +void proxy_connection_free(proxy_connection *con) {
31159 + if (!con) return;
31161 + iosocket_free(con->sock);
31166 +proxy_connection_pool *proxy_connection_pool_init(void) {
31167 + proxy_connection_pool *pool;
31169 + pool = calloc(1, sizeof(*pool));
31171 + /* default: max parallel connections to the backend
31173 + * this should match max-procs if we manage the procs ourself
31176 + pool->max_size = 8;
31181 +void proxy_connection_pool_free(proxy_connection_pool *pool) {
31184 + if (!pool) return;
31186 + for (i = 0; i < pool->used; i++) {
31187 + proxy_connection_free(pool->ptr[i]);
31190 + if (pool->size) free(pool->ptr);
31195 +void proxy_connection_pool_add_connection(proxy_connection_pool *pool, proxy_connection *c) {
31196 + ARRAY_STATIC_PREPARE_APPEND(pool);
31198 + pool->ptr[pool->used++] = c;
31201 + * remove the connection from the pool
31203 + * usually called on conn-shutdown
31205 +int proxy_connection_pool_remove_connection(proxy_connection_pool *pool, proxy_connection *c) {
31208 + if (pool->used == 0) return -1; /* empty */
31210 + for (i = 0; i < pool->used; i++) {
31211 + if (pool->ptr[i] == c) {
31216 + if (i == pool->used) return -1; /* not found */
31219 + * move all elements one to the left
31221 + * if the last element is going to be removed, skip the loop
31223 + for (; i < pool->used - 1; i++) {
31224 + pool->ptr[i] = pool->ptr[i + 1];
31232 +proxy_connection_pool_t proxy_connection_pool_get_connection(proxy_connection_pool *pool, proxy_address *address, proxy_connection **rcon) {
31233 + proxy_connection *proxy_con = NULL;
31236 + /* search for a idling proxy connection with the given address */
31237 + for (i = 0; i < pool->used; i++) {
31238 + proxy_con = pool->ptr[i];
31240 + if (proxy_con->address == address &&
31241 + proxy_con->state == PROXY_CONNECTION_STATE_IDLE) {
31246 + if (i == pool->used) {
31247 + /* no idling connection found */
31249 + if (pool->used == pool->max_size) return PROXY_CONNECTIONPOOL_FULL;
31251 + proxy_con = proxy_connection_init();
31253 + proxy_con->state = PROXY_CONNECTION_STATE_CONNECTING;
31254 + proxy_con->address = address;
31256 + proxy_connection_pool_add_connection(pool, proxy_con);
31258 + proxy_con->state = PROXY_CONNECTION_STATE_CONNECTED;
31261 + *rcon = proxy_con;
31263 + return PROXY_CONNECTIONPOOL_GOT_CONNECTION;
31267 --- ../lighttpd-1.4.11/src/mod_proxy_core_pool.h 1970-01-01 03:00:00.000000000 +0300
31268 +++ lighttpd-1.4.12/src/mod_proxy_core_pool.h 2006-07-18 13:03:40.000000000 +0300
31270 +#ifndef _MOD_PROXY_CORE_POOL_H_
31271 +#define _MOD_PROXY_CORE_POOL_H_
31273 +#include <sys/time.h>
31275 +#include "iosocket.h"
31276 +#include "array-static.h"
31277 +#include "mod_proxy_core_address.h"
31280 + PROXY_CONNECTION_STATE_UNSET,
31281 + PROXY_CONNECTION_STATE_CONNECTING,
31282 + PROXY_CONNECTION_STATE_CONNECTED,
31283 + PROXY_CONNECTION_STATE_IDLE,
31284 + PROXY_CONNECTION_STATE_CLOSED,
31285 +} proxy_connection_state_t;
31288 + * a connection to a proxy backend
31290 + * the connection is independent of the incoming request to allow keep-alive
31295 + time_t last_read; /* timeout handling for keep-alive connections */
31296 + time_t last_write;
31298 + proxy_address *address; /* the struct sock_addr for the sock */
31300 + proxy_connection_state_t state;
31301 +} proxy_connection;
31303 +ARRAY_STATIC_DEF(proxy_connection_pool, proxy_connection, size_t max_size;);
31306 + PROXY_CONNECTIONPOOL_UNSET,
31307 + PROXY_CONNECTIONPOOL_FULL,
31308 + PROXY_CONNECTIONPOOL_GOT_CONNECTION,
31309 +} proxy_connection_pool_t;
31311 +proxy_connection_pool *proxy_connection_pool_init(void);
31312 +void proxy_connection_pool_free(proxy_connection_pool *pool);
31314 +proxy_connection_pool_t proxy_connection_pool_get_connection(proxy_connection_pool *pool, proxy_address *address, proxy_connection **rcon);
31315 +int proxy_connection_pool_remove_connection(proxy_connection_pool *pool, proxy_connection *c);
31317 +proxy_connection * proxy_connection_init(void);
31318 +void proxy_connection_free(proxy_connection *pool);
31322 --- ../lighttpd-1.4.11/src/mod_proxy_core_rewrites.c 1970-01-01 03:00:00.000000000 +0300
31323 +++ lighttpd-1.4.12/src/mod_proxy_core_rewrites.c 2006-07-18 17:34:32.000000000 +0300
31325 +#include <stdlib.h>
31326 +#include <string.h>
31328 +#include "mod_proxy_core_rewrites.h"
31331 +proxy_rewrite *proxy_rewrite_init(void) {
31332 + STRUCT_INIT(proxy_rewrite, rewrite);
31334 + rewrite->header = buffer_init();
31335 + rewrite->match = buffer_init();
31336 + rewrite->replace = buffer_init();
31341 +void proxy_rewrite_free(proxy_rewrite *rewrite) {
31342 + if (!rewrite) return;
31344 + if (rewrite->regex) pcre_free(rewrite->regex);
31346 + buffer_free(rewrite->header);
31347 + buffer_free(rewrite->match);
31348 + buffer_free(rewrite->replace);
31353 +int proxy_rewrite_set_regex(proxy_rewrite *rewrite, buffer *regex) {
31354 + const char *errptr;
31357 + if (NULL == (rewrite->regex = pcre_compile(BUF_STR(regex),
31358 + 0, &errptr, &erroff, NULL))) {
31360 + TRACE("regex compilation for %s failed at %s", BUF_STR(regex), errptr);
31369 +proxy_rewrites *proxy_rewrites_init(void) {
31370 + STRUCT_INIT(proxy_rewrites, rewrites);
31375 +void proxy_rewrites_add(proxy_rewrites *rewrites, proxy_rewrite *rewrite) {
31376 + ARRAY_STATIC_PREPARE_APPEND(rewrites);
31378 + rewrites->ptr[rewrites->used++] = rewrite;
31381 +void proxy_rewrites_free(proxy_rewrites *rewrites) {
31382 + if (!rewrites) return;
31389 --- ../lighttpd-1.4.11/src/mod_proxy_core_rewrites.h 1970-01-01 03:00:00.000000000 +0300
31390 +++ lighttpd-1.4.12/src/mod_proxy_core_rewrites.h 2006-07-18 17:34:32.000000000 +0300
31392 +#ifndef _MOD_PROXY_CORE_REWRITES_H_
31393 +#define _MOD_PROXY_CORE_REWRITES_H_
31396 +#include "array-static.h"
31397 +#include "buffer.h"
31402 + pcre *regex; /* regex compiled from the <match> */
31408 +ARRAY_STATIC_DEF(proxy_rewrites, proxy_rewrite,);
31410 +proxy_rewrite *proxy_rewrite_init(void);
31411 +void proxy_rewrite_free(proxy_rewrite *rewrite);
31412 +int proxy_rewrite_set_regex(proxy_rewrite *rewrite, buffer *regex);
31414 +proxy_rewrites *proxy_rewrites_init(void);
31415 +void proxy_rewrites_add(proxy_rewrites *rewrites, proxy_rewrite *rewrite);
31416 +void proxy_rewrites_free(proxy_rewrites *rewrites);
31420 --- ../lighttpd-1.4.11/src/mod_redirect.c 2006-02-08 15:38:06.000000000 +0200
31421 +++ lighttpd-1.4.12/src/mod_redirect.c 2006-07-16 00:26:04.000000000 +0300
31422 @@ -22,35 +22,35 @@
31428 plugin_config **config_storage;
31430 - plugin_config conf;
31432 + plugin_config conf;
31435 INIT_FUNC(mod_redirect_init) {
31439 p = calloc(1, sizeof(*p));
31442 p->match_buf = buffer_init();
31443 p->location = buffer_init();
31449 FREE_FUNC(mod_redirect_free) {
31450 plugin_data *p = p_d;
31453 if (!p) return HANDLER_GO_ON;
31455 if (p->config_storage) {
31457 for (i = 0; i < srv->config_context->used; i++) {
31458 plugin_config *s = p->config_storage[i];
31461 pcre_keyvalue_buffer_free(s->redirect);
31466 free(p->config_storage);
31469 buffer_free(p->match_buf);
31470 buffer_free(p->location);
31476 return HANDLER_GO_ON;
31479 @@ -69,195 +69,137 @@
31480 plugin_data *p = p_d;
31484 - config_values_t cv[] = {
31486 + config_values_t cv[] = {
31487 { "url.redirect", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
31488 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
31492 if (!p) return HANDLER_ERROR;
31496 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
31499 for (i = 0; i < srv->config_context->used; i++) {
31503 data_array *da = (data_array *)du;
31506 s = calloc(1, sizeof(plugin_config));
31507 s->redirect = pcre_keyvalue_buffer_init();
31510 cv[0].destination = s->redirect;
31513 p->config_storage[i] = s;
31514 ca = ((data_config *)srv->config_context->data[i])->value;
31517 if (0 != config_insert_values_global(srv, ca, cv)) {
31518 return HANDLER_ERROR;
31522 if (NULL == (du = array_get_element(ca, "url.redirect"))) {
31523 /* no url.redirect defined */
31528 if (du->type != TYPE_ARRAY) {
31529 - log_error_write(srv, __FILE__, __LINE__, "sss",
31530 + log_error_write(srv, __FILE__, __LINE__, "sss",
31531 "unexpected type for key: ", "url.redirect", "array of strings");
31534 return HANDLER_ERROR;
31538 da = (data_array *)du;
31541 for (j = 0; j < da->value->used; j++) {
31542 if (da->value->data[j]->type != TYPE_STRING) {
31543 - log_error_write(srv, __FILE__, __LINE__, "sssbs",
31544 - "unexpected type for key: ",
31546 + log_error_write(srv, __FILE__, __LINE__, "sssbs",
31547 + "unexpected type for key: ",
31549 "[", da->value->data[j]->key, "](string)");
31552 return HANDLER_ERROR;
31555 - if (0 != pcre_keyvalue_buffer_append(s->redirect,
31557 + if (0 != pcre_keyvalue_buffer_append(s->redirect,
31558 ((data_string *)(da->value->data[j]))->key->ptr,
31559 ((data_string *)(da->value->data[j]))->value->ptr)) {
31561 - log_error_write(srv, __FILE__, __LINE__, "sb",
31563 + log_error_write(srv, __FILE__, __LINE__, "sb",
31564 "pcre-compile failed for", da->value->data[j]->key);
31570 return HANDLER_GO_ON;
31573 static int mod_redirect_patch_connection(server *srv, connection *con, plugin_data *p) {
31575 plugin_config *s = p->config_storage[0];
31578 p->conf.redirect = s->redirect;
31581 /* skip the first, the global context */
31582 for (i = 1; i < srv->config_context->used; i++) {
31583 data_config *dc = (data_config *)srv->config_context->data[i];
31584 s = p->config_storage[i];
31587 /* condition didn't match */
31588 if (!config_check_cond(srv, con, dc)) continue;
31592 for (j = 0; j < dc->value->used; j++) {
31593 data_unset *du = dc->value->data[j];
31596 if (0 == strcmp(du->key->ptr, "url.redirect")) {
31597 p->conf.redirect = s->redirect;
31598 p->conf.context = dc;
31607 static handler_t mod_redirect_uri_handler(server *srv, connection *con, void *p_data) {
31609 plugin_data *p = p_data;
31618 * e.g. redirect /base/ to /index.php?section=base
31624 mod_redirect_patch_connection(srv, con, p);
31627 buffer_copy_string_buffer(p->match_buf, con->request.uri);
31629 - for (i = 0; i < p->conf.redirect->used; i++) {
31631 - pcre_extra *extra;
31632 - const char *pattern;
31633 - size_t pattern_len;
31635 - pcre_keyvalue *kv = p->conf.redirect->kv[i];
31640 - extra = kv->key_extra;
31641 - pattern = kv->value->ptr;
31642 - pattern_len = kv->value->used - 1;
31644 - if ((n = pcre_exec(match, extra, p->match_buf->ptr, p->match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) {
31645 - if (n != PCRE_ERROR_NOMATCH) {
31646 - log_error_write(srv, __FILE__, __LINE__, "sd",
31647 - "execution error while matching: ", n);
31648 - return HANDLER_ERROR;
31651 - const char **list;
31652 - size_t start, end;
31656 - pcre_get_substring_list(p->match_buf->ptr, ovec, n, &list);
31658 - /* search for $[0-9] */
31660 - buffer_reset(p->location);
31662 - start = 0; end = pattern_len;
31663 - for (k = 0; k < pattern_len; k++) {
31664 - if ((pattern[k] == '$' || pattern[k] == '%') &&
31665 - isdigit((unsigned char)pattern[k + 1])) {
31668 - size_t num = pattern[k + 1] - '0';
31672 - buffer_append_string_len(p->location, pattern + start, end - start);
31674 - if (pattern[k] == '$') {
31675 - /* n is always > 0 */
31676 - if (num < (size_t)n) {
31677 - buffer_append_string(p->location, list[num]);
31680 - config_append_cond_match_buffer(con, p->conf.context, p->location, num);
31688 - buffer_append_string_len(p->location, pattern + start, pattern_len - start);
31692 - response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->location));
31694 - con->http_status = 301;
31695 - con->file_finished = 1;
31697 - return HANDLER_FINISHED;
31699 + i = config_exec_pcre_keyvalue_buffer(con, p->conf.redirect, p->conf.context, p->match_buf, p->location);
31702 + response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->location));
31704 + con->http_status = 301;
31705 + con->file_finished = 1;
31707 + return HANDLER_FINISHED;
31709 + else if (i != PCRE_ERROR_NOMATCH) {
31710 + log_error_write(srv, __FILE__, __LINE__, "s",
31711 + "execution error while matching", i);
31723 return HANDLER_GO_ON;
31726 @@ -265,13 +207,13 @@
31727 int mod_redirect_plugin_init(plugin *p) {
31728 p->version = LIGHTTPD_VERSION_ID;
31729 p->name = buffer_init_string("redirect");
31732 p->init = mod_redirect_init;
31733 p->handle_uri_clean = mod_redirect_uri_handler;
31734 p->set_defaults = mod_redirect_set_defaults;
31735 p->cleanup = mod_redirect_free;
31743 --- ../lighttpd-1.4.11/src/mod_rewrite.c 2005-09-29 20:59:10.000000000 +0300
31744 +++ lighttpd-1.4.12/src/mod_rewrite.c 2006-07-16 00:26:03.000000000 +0300
31749 -#ifdef HAVE_PCRE_H
31759 - rewrite_rule **ptr;
31763 -} rewrite_rule_buffer;
31766 - rewrite_rule_buffer *rewrite;
31767 + pcre_keyvalue_buffer *rewrite;
31769 data_config *context; /* to which apply me */
31772 @@ -42,20 +26,20 @@
31778 plugin_config **config_storage;
31780 - plugin_config conf;
31782 + plugin_config conf;
31785 static handler_ctx * handler_ctx_init() {
31786 handler_ctx * hctx;
31789 hctx = calloc(1, sizeof(*hctx));
31792 hctx->state = REWRITE_STATE_UNSET;
31799 @@ -63,207 +47,136 @@
31803 -rewrite_rule_buffer *rewrite_rule_buffer_init(void) {
31804 - rewrite_rule_buffer *kvb;
31806 - kvb = calloc(1, sizeof(*kvb));
31811 -int rewrite_rule_buffer_append(rewrite_rule_buffer *kvb, buffer *key, buffer *value, int once) {
31812 -#ifdef HAVE_PCRE_H
31814 - const char *errptr;
31817 - if (!key) return -1;
31819 - if (kvb->size == 0) {
31823 - kvb->ptr = malloc(kvb->size * sizeof(*kvb->ptr));
31825 - for(i = 0; i < kvb->size; i++) {
31826 - kvb->ptr[i] = calloc(1, sizeof(**kvb->ptr));
31828 - } else if (kvb->used == kvb->size) {
31831 - kvb->ptr = realloc(kvb->ptr, kvb->size * sizeof(*kvb->ptr));
31833 - for(i = kvb->used; i < kvb->size; i++) {
31834 - kvb->ptr[i] = calloc(1, sizeof(**kvb->ptr));
31838 - if (NULL == (kvb->ptr[kvb->used]->key = pcre_compile(key->ptr,
31839 - 0, &errptr, &erroff, NULL))) {
31844 - kvb->ptr[kvb->used]->value = buffer_init();
31845 - buffer_copy_string_buffer(kvb->ptr[kvb->used]->value, value);
31846 - kvb->ptr[kvb->used]->once = once;
31861 -void rewrite_rule_buffer_free(rewrite_rule_buffer *kvb) {
31862 -#ifdef HAVE_PCRE_H
31865 - for (i = 0; i < kvb->size; i++) {
31866 - if (kvb->ptr[i]->key) pcre_free(kvb->ptr[i]->key);
31867 - if (kvb->ptr[i]->value) buffer_free(kvb->ptr[i]->value);
31868 - free(kvb->ptr[i]);
31871 - if (kvb->ptr) free(kvb->ptr);
31878 INIT_FUNC(mod_rewrite_init) {
31882 p = calloc(1, sizeof(*p));
31885 p->match_buf = buffer_init();
31891 FREE_FUNC(mod_rewrite_free) {
31892 plugin_data *p = p_d;
31897 if (!p) return HANDLER_GO_ON;
31900 buffer_free(p->match_buf);
31901 if (p->config_storage) {
31903 for (i = 0; i < srv->config_context->used; i++) {
31904 plugin_config *s = p->config_storage[i];
31905 - rewrite_rule_buffer_free(s->rewrite);
31907 + pcre_keyvalue_buffer_free(s->rewrite);
31908 + buffer_free(s->once);
31912 free(p->config_storage);
31919 return HANDLER_GO_ON;
31922 static int parse_config_entry(server *srv, plugin_config *s, array *ca, const char *option, int once) {
31926 if (NULL != (du = array_get_element(ca, option))) {
31927 data_array *da = (data_array *)du;
31931 if (du->type != TYPE_ARRAY) {
31932 - log_error_write(srv, __FILE__, __LINE__, "sss",
31933 + log_error_write(srv, __FILE__, __LINE__, "sss",
31934 "unexpected type for key: ", option, "array of strings");
31937 return HANDLER_ERROR;
31941 da = (data_array *)du;
31944 for (j = 0; j < da->value->used; j++) {
31945 if (da->value->data[j]->type != TYPE_STRING) {
31946 - log_error_write(srv, __FILE__, __LINE__, "sssbs",
31947 - "unexpected type for key: ",
31949 + log_error_write(srv, __FILE__, __LINE__, "sssbs",
31950 + "unexpected type for key: ",
31952 "[", da->value->data[j]->key, "](string)");
31955 return HANDLER_ERROR;
31958 - if (0 != rewrite_rule_buffer_append(s->rewrite,
31959 - ((data_string *)(da->value->data[j]))->key,
31960 - ((data_string *)(da->value->data[j]))->value,
31963 + if (0 != pcre_keyvalue_buffer_append(s->rewrite,
31964 + ((data_string *)(da->value->data[j]))->key->ptr,
31965 + ((data_string *)(da->value->data[j]))->value->ptr)) {
31967 - log_error_write(srv, __FILE__, __LINE__, "sb",
31968 + log_error_write(srv, __FILE__, __LINE__, "sb",
31969 "pcre-compile failed for", da->value->data[j]->key);
31971 - log_error_write(srv, __FILE__, __LINE__, "s",
31972 + log_error_write(srv, __FILE__, __LINE__, "s",
31973 "pcre support is missing, please install libpcre and the headers");
31978 + buffer_append_string_len(s->once, CONST_STR_LEN("1"));
31980 + buffer_append_string_len(s->once, CONST_STR_LEN("0"));
31989 SETDEFAULTS_FUNC(mod_rewrite_set_defaults) {
31990 plugin_data *p = p_d;
31993 - config_values_t cv[] = {
31995 + config_values_t cv[] = {
31996 { "url.rewrite-repeat", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
31997 { "url.rewrite-once", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
31999 - /* old names, still supported
32002 + /* old names, still supported
32004 * url.rewrite remapped to url.rewrite-once
32005 * url.rewrite-final is url.rewrite-once
32009 { "url.rewrite", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
32010 { "url.rewrite-final", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
32011 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
32015 if (!p) return HANDLER_ERROR;
32019 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
32022 for (i = 0; i < srv->config_context->used; i++) {
32027 s = calloc(1, sizeof(plugin_config));
32028 - s->rewrite = rewrite_rule_buffer_init();
32030 - cv[0].destination = s->rewrite;
32031 - cv[1].destination = s->rewrite;
32032 - cv[2].destination = s->rewrite;
32034 + s->rewrite = pcre_keyvalue_buffer_init();
32035 + s->once = buffer_init();
32037 p->config_storage[i] = s;
32038 ca = ((data_config *)srv->config_context->data[i])->value;
32041 if (0 != config_insert_values_global(srv, ca, cv)) {
32042 return HANDLER_ERROR;
32046 parse_config_entry(srv, s, ca, "url.rewrite-once", 1);
32047 parse_config_entry(srv, s, ca, "url.rewrite-final", 1);
32048 parse_config_entry(srv, s, ca, "url.rewrite", 1);
32049 parse_config_entry(srv, s, ca, "url.rewrite-repeat", 0);
32053 return HANDLER_GO_ON;
32056 @@ -271,157 +184,107 @@
32058 plugin_config *s = p->config_storage[0];
32059 p->conf.rewrite = s->rewrite;
32061 + p->conf.once = s->once;
32063 /* skip the first, the global context */
32064 for (i = 1; i < srv->config_context->used; i++) {
32065 data_config *dc = (data_config *)srv->config_context->data[i];
32066 s = p->config_storage[i];
32069 if (COMP_HTTP_URL == dc->comp) continue;
32072 /* condition didn't match */
32073 if (!config_check_cond(srv, con, dc)) continue;
32077 for (j = 0; j < dc->value->used; j++) {
32078 data_unset *du = dc->value->data[j];
32081 if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite"))) {
32082 p->conf.rewrite = s->rewrite;
32083 + p->conf.once = s->once;
32084 p->conf.context = dc;
32085 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-once"))) {
32086 p->conf.rewrite = s->rewrite;
32087 + p->conf.once = s->once;
32088 p->conf.context = dc;
32089 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-repeat"))) {
32090 p->conf.rewrite = s->rewrite;
32091 + p->conf.once = s->once;
32092 p->conf.context = dc;
32093 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-final"))) {
32094 p->conf.rewrite = s->rewrite;
32095 + p->conf.once = s->once;
32096 p->conf.context = dc;
32105 URIHANDLER_FUNC(mod_rewrite_con_reset) {
32106 plugin_data *p = p_d;
32112 if (con->plugin_ctx[p->id]) {
32113 handler_ctx_free(con->plugin_ctx[p->id]);
32114 con->plugin_ctx[p->id] = NULL;
32118 return HANDLER_GO_ON;
32121 URIHANDLER_FUNC(mod_rewrite_uri_handler) {
32123 plugin_data *p = p_d;
32133 * e.g. rewrite /base/ to /index.php?section=base
32139 if (con->plugin_ctx[p->id]) {
32140 hctx = con->plugin_ctx[p->id];
32143 if (hctx->loops++ > 100) {
32144 - log_error_write(srv, __FILE__, __LINE__, "s",
32145 + log_error_write(srv, __FILE__, __LINE__, "s",
32146 "ENDLESS LOOP IN rewrite-rule DETECTED ... aborting request, perhaps you want to use url.rewrite-once instead of url.rewrite-repeat");
32149 return HANDLER_ERROR;
32153 if (hctx->state == REWRITE_STATE_FINISHED) return HANDLER_GO_ON;
32157 mod_rewrite_patch_connection(srv, con, p);
32159 if (!p->conf.rewrite) return HANDLER_GO_ON;
32162 buffer_copy_string_buffer(p->match_buf, con->request.uri);
32164 - for (i = 0; i < p->conf.rewrite->used; i++) {
32166 - const char *pattern;
32167 - size_t pattern_len;
32169 - rewrite_rule *rule = p->conf.rewrite->ptr[i];
32173 - match = rule->key;
32174 - pattern = rule->value->ptr;
32175 - pattern_len = rule->value->used - 1;
32177 - if ((n = pcre_exec(match, NULL, p->match_buf->ptr, p->match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) {
32178 - if (n != PCRE_ERROR_NOMATCH) {
32179 - log_error_write(srv, __FILE__, __LINE__, "sd",
32180 - "execution error while matching: ", n);
32181 - return HANDLER_ERROR;
32184 - const char **list;
32185 - size_t start, end;
32189 - pcre_get_substring_list(p->match_buf->ptr, ovec, n, &list);
32191 - /* search for $[0-9] */
32193 - buffer_reset(con->request.uri);
32195 - start = 0; end = pattern_len;
32196 - for (k = 0; k < pattern_len; k++) {
32197 - if ((pattern[k] == '$' || pattern[k] == '%') &&
32198 - isdigit((unsigned char)pattern[k + 1])) {
32201 - size_t num = pattern[k + 1] - '0';
32205 - buffer_append_string_len(con->request.uri, pattern + start, end - start);
32207 - if (pattern[k] == '$') {
32208 - /* n is always > 0 */
32209 - if (num < (size_t)n) {
32210 - buffer_append_string(con->request.uri, list[num]);
32213 - config_append_cond_match_buffer(con, p->conf.context, con->request.uri, num);
32221 - buffer_append_string_len(con->request.uri, pattern + start, pattern_len - start);
32225 - hctx = handler_ctx_init();
32227 - con->plugin_ctx[p->id] = hctx;
32229 - if (rule->once) hctx->state = REWRITE_STATE_FINISHED;
32231 - return HANDLER_COMEBACK;
32233 + i = config_exec_pcre_keyvalue_buffer(con, p->conf.rewrite, p->conf.context, p->match_buf, con->request.uri);
32236 + hctx = handler_ctx_init();
32238 + con->plugin_ctx[p->id] = hctx;
32240 + if (p->conf.once->ptr[i] == '1')
32241 + hctx->state = REWRITE_STATE_FINISHED;
32243 + return HANDLER_COMEBACK;
32245 + else if (i != PCRE_ERROR_NOMATCH) {
32246 + log_error_write(srv, __FILE__, __LINE__, "s",
32247 + "execution error while matching", i);
32255 @@ -434,17 +297,17 @@
32256 int mod_rewrite_plugin_init(plugin *p) {
32257 p->version = LIGHTTPD_VERSION_ID;
32258 p->name = buffer_init_string("rewrite");
32261 p->init = mod_rewrite_init;
32262 /* it has to stay _raw as we are matching on uri + querystring
32266 p->handle_uri_raw = mod_rewrite_uri_handler;
32267 p->set_defaults = mod_rewrite_set_defaults;
32268 p->cleanup = mod_rewrite_free;
32269 p->connection_reset = mod_rewrite_con_reset;
32277 --- ../lighttpd-1.4.11/src/mod_rrdtool.c 2005-08-22 01:52:24.000000000 +0300
32278 +++ lighttpd-1.4.12/src/mod_rrdtool.c 2006-07-18 13:03:40.000000000 +0300
32280 #include <stdlib.h>
32282 #include <string.h>
32283 -#include <unistd.h>
32287 @@ -20,10 +19,14 @@
32288 /* no need for waitpid if we don't have fork */
32289 #include <sys/wait.h>
32292 +#include "sys-files.h"
32293 +#include "sys-process.h"
32296 buffer *path_rrdtool_bin;
32300 double requests, *requests_ptr;
32301 double bytes_written, *bytes_written_ptr;
32302 double bytes_read, *bytes_read_ptr;
32303 @@ -31,84 +34,84 @@
32313 int read_fd, write_fd;
32317 int rrdtool_running;
32320 plugin_config **config_storage;
32321 plugin_config conf;
32324 INIT_FUNC(mod_rrd_init) {
32328 p = calloc(1, sizeof(*p));
32331 p->resp = buffer_init();
32332 p->cmd = buffer_init();
32338 FREE_FUNC(mod_rrd_free) {
32339 plugin_data *p = p_d;
32343 if (!p) return HANDLER_GO_ON;
32346 if (p->config_storage) {
32347 for (i = 0; i < srv->config_context->used; i++) {
32348 plugin_config *s = p->config_storage[i];
32351 buffer_free(s->path_rrdtool_bin);
32352 buffer_free(s->path_rrd);
32358 buffer_free(p->cmd);
32359 buffer_free(p->resp);
32362 free(p->config_storage);
32365 if (p->rrdtool_pid) {
32368 close(p->write_fd);
32371 /* collect status */
32372 waitpid(p->rrdtool_pid, &status, 0);
32380 return HANDLER_GO_ON;
32383 int mod_rrd_create_pipe(server *srv, plugin_data *p) {
32387 int to_rrdtool_fds[2];
32388 int from_rrdtool_fds[2];
32391 if (pipe(to_rrdtool_fds)) {
32392 - log_error_write(srv, __FILE__, __LINE__, "ss",
32393 + log_error_write(srv, __FILE__, __LINE__, "ss",
32394 "pipe failed: ", strerror(errno));
32399 if (pipe(from_rrdtool_fds)) {
32400 - log_error_write(srv, __FILE__, __LINE__, "ss",
32401 + log_error_write(srv, __FILE__, __LINE__, "ss",
32402 "pipe failed: ", strerror(errno));
32408 switch (pid = fork()) {
32410 @@ -117,33 +120,28 @@
32416 /* move stdout to from_rrdtool_fd[1] */
32417 close(STDOUT_FILENO);
32418 dup2(from_rrdtool_fds[1], STDOUT_FILENO);
32419 close(from_rrdtool_fds[1]);
32421 close(from_rrdtool_fds[0]);
32424 /* move the stdin to to_rrdtool_fd[0] */
32425 close(STDIN_FILENO);
32426 dup2(to_rrdtool_fds[0], STDIN_FILENO);
32427 close(to_rrdtool_fds[0]);
32429 close(to_rrdtool_fds[1]);
32432 close(STDERR_FILENO);
32434 - if (srv->errorlog_mode == ERRORLOG_FILE) {
32435 - dup2(srv->errorlog_fd, STDERR_FILENO);
32436 - close(srv->errorlog_fd);
32442 args = malloc(sizeof(*args) * argc);
32446 args[i++] = p->conf.path_rrdtool_bin->ptr;
32449 @@ -152,12 +150,12 @@
32450 for (i = 3; i < 256; i++) {
32456 execv(args[0], args);
32459 log_error_write(srv, __FILE__, __LINE__, "sss", "spawing rrdtool failed: ", strerror(errno), args[0]);
32465 @@ -168,19 +166,19 @@
32471 close(from_rrdtool_fds[1]);
32472 close(to_rrdtool_fds[0]);
32475 /* register PID and wait for them asyncronously */
32476 p->write_fd = to_rrdtool_fds[1];
32477 p->read_fd = from_rrdtool_fds[0];
32478 p->rrdtool_pid = pid;
32489 @@ -189,19 +187,19 @@
32491 static int mod_rrdtool_create_rrd(server *srv, plugin_data *p, plugin_config *s) {
32495 /* check if DB already exists */
32496 if (0 == stat(s->path_rrd->ptr, &st)) {
32497 /* check if it is plain file */
32498 if (!S_ISREG(st.st_mode)) {
32499 - log_error_write(srv, __FILE__, __LINE__, "sb",
32500 + log_error_write(srv, __FILE__, __LINE__, "sb",
32501 "not a regular file:", s->path_rrd);
32502 return HANDLER_ERROR;
32506 /* create a new one */
32509 BUFFER_COPY_STRING_CONST(p->cmd, "create ");
32510 buffer_append_string_buffer(p->cmd, s->path_rrd);
32511 buffer_append_string(p->cmd, " --step 60 ");
32512 @@ -220,158 +218,155 @@
32513 buffer_append_string(p->cmd, "RRA:MIN:0.5:6:700 ");
32514 buffer_append_string(p->cmd, "RRA:MIN:0.5:24:775 ");
32515 buffer_append_string(p->cmd, "RRA:MIN:0.5:288:797\n");
32518 if (-1 == (r = write(p->write_fd, p->cmd->ptr, p->cmd->used - 1))) {
32519 - log_error_write(srv, __FILE__, __LINE__, "ss",
32520 + log_error_write(srv, __FILE__, __LINE__, "ss",
32521 "rrdtool-write: failed", strerror(errno));
32524 return HANDLER_ERROR;
32528 buffer_prepare_copy(p->resp, 4096);
32529 if (-1 == (r = read(p->read_fd, p->resp->ptr, p->resp->size))) {
32530 - log_error_write(srv, __FILE__, __LINE__, "ss",
32531 + log_error_write(srv, __FILE__, __LINE__, "ss",
32532 "rrdtool-read: failed", strerror(errno));
32535 return HANDLER_ERROR;
32542 if (p->resp->ptr[0] != 'O' ||
32543 p->resp->ptr[1] != 'K') {
32544 - log_error_write(srv, __FILE__, __LINE__, "sbb",
32545 + log_error_write(srv, __FILE__, __LINE__, "sbb",
32546 "rrdtool-response:", p->cmd, p->resp);
32549 return HANDLER_ERROR;
32554 return HANDLER_GO_ON;
32557 -#define PATCH(x) \
32558 - p->conf.x = s->x;
32559 static int mod_rrd_patch_connection(server *srv, connection *con, plugin_data *p) {
32561 plugin_config *s = p->config_storage[0];
32563 - PATCH(path_rrdtool_bin);
32567 + PATCH_OPTION(path_rrdtool_bin);
32568 + PATCH_OPTION(path_rrd);
32570 p->conf.bytes_written_ptr = &(s->bytes_written);
32571 p->conf.bytes_read_ptr = &(s->bytes_read);
32572 p->conf.requests_ptr = &(s->requests);
32575 /* skip the first, the global context */
32576 for (i = 1; i < srv->config_context->used; i++) {
32577 data_config *dc = (data_config *)srv->config_context->data[i];
32578 s = p->config_storage[i];
32581 /* condition didn't match */
32582 if (!config_check_cond(srv, con, dc)) continue;
32586 for (j = 0; j < dc->value->used; j++) {
32587 data_unset *du = dc->value->data[j];
32590 if (buffer_is_equal_string(du->key, CONST_STR_LEN("rrdtool.db-name"))) {
32592 + PATCH_OPTION(path_rrd);
32593 /* get pointers to double values */
32596 p->conf.bytes_written_ptr = &(s->bytes_written);
32597 p->conf.bytes_read_ptr = &(s->bytes_read);
32598 p->conf.requests_ptr = &(s->requests);
32608 SETDEFAULTS_FUNC(mod_rrd_set_defaults) {
32609 plugin_data *p = p_d;
32612 - config_values_t cv[] = {
32614 + config_values_t cv[] = {
32615 { "rrdtool.binary", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
32616 { "rrdtool.db-name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
32617 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
32621 if (!p) return HANDLER_ERROR;
32624 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
32627 for (i = 0; i < srv->config_context->used; i++) {
32631 s = calloc(1, sizeof(plugin_config));
32632 s->path_rrdtool_bin = buffer_init();
32633 s->path_rrd = buffer_init();
32635 s->bytes_written = 0;
32639 cv[0].destination = s->path_rrdtool_bin;
32640 cv[1].destination = s->path_rrd;
32643 p->config_storage[i] = s;
32646 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
32647 return HANDLER_ERROR;
32651 if (i > 0 && !buffer_is_empty(s->path_rrdtool_bin)) {
32652 /* path_rrdtool_bin is a global option */
32654 - log_error_write(srv, __FILE__, __LINE__, "s",
32656 + log_error_write(srv, __FILE__, __LINE__, "s",
32657 "rrdtool.binary can only be set as a global option.");
32660 return HANDLER_ERROR;
32667 p->conf.path_rrdtool_bin = p->config_storage[0]->path_rrdtool_bin;
32668 p->rrdtool_running = 0;
32671 /* check for dir */
32674 if (buffer_is_empty(p->conf.path_rrdtool_bin)) {
32675 - log_error_write(srv, __FILE__, __LINE__, "s",
32676 + log_error_write(srv, __FILE__, __LINE__, "s",
32677 "rrdtool.binary has to be set");
32678 return HANDLER_ERROR;
32682 /* open the pipe to rrdtool */
32683 if (mod_rrd_create_pipe(srv, p)) {
32684 return HANDLER_ERROR;
32688 p->rrdtool_running = 1;
32691 return HANDLER_GO_ON;
32694 TRIGGER_FUNC(mod_rrd_trigger) {
32695 plugin_data *p = p_d;
32699 if (!p->rrdtool_running) return HANDLER_GO_ON;
32700 if ((srv->cur_ts % 60) != 0) return HANDLER_GO_ON;
32703 for (i = 0; i < srv->config_context->used; i++) {
32704 plugin_config *s = p->config_storage[i];
32708 if (buffer_is_empty(s->path_rrd)) continue;
32711 /* write the data down every minute */
32714 if (HANDLER_GO_ON != mod_rrdtool_create_rrd(srv, p, s)) return HANDLER_ERROR;
32717 BUFFER_COPY_STRING_CONST(p->cmd, "update ");
32718 buffer_append_string_buffer(p->cmd, s->path_rrd);
32719 BUFFER_APPEND_STRING_CONST(p->cmd, " N:");
32720 @@ -381,69 +376,69 @@
32721 BUFFER_APPEND_STRING_CONST(p->cmd, ":");
32722 buffer_append_long(p->cmd, s->requests);
32723 BUFFER_APPEND_STRING_CONST(p->cmd, "\n");
32726 if (-1 == (r = write(p->write_fd, p->cmd->ptr, p->cmd->used - 1))) {
32727 p->rrdtool_running = 0;
32729 - log_error_write(srv, __FILE__, __LINE__, "ss",
32731 + log_error_write(srv, __FILE__, __LINE__, "ss",
32732 "rrdtool-write: failed", strerror(errno));
32735 return HANDLER_ERROR;
32739 buffer_prepare_copy(p->resp, 4096);
32740 if (-1 == (r = read(p->read_fd, p->resp->ptr, p->resp->size))) {
32741 p->rrdtool_running = 0;
32743 - log_error_write(srv, __FILE__, __LINE__, "ss",
32745 + log_error_write(srv, __FILE__, __LINE__, "ss",
32746 "rrdtool-read: failed", strerror(errno));
32749 return HANDLER_ERROR;
32756 if (p->resp->ptr[0] != 'O' ||
32757 p->resp->ptr[1] != 'K') {
32758 p->rrdtool_running = 0;
32760 - log_error_write(srv, __FILE__, __LINE__, "sbb",
32762 + log_error_write(srv, __FILE__, __LINE__, "sbb",
32763 "rrdtool-response:", p->cmd, p->resp);
32766 return HANDLER_ERROR;
32769 s->bytes_written = 0;
32774 return HANDLER_GO_ON;
32777 REQUESTDONE_FUNC(mod_rrd_account) {
32778 plugin_data *p = p_d;
32781 mod_rrd_patch_connection(srv, con, p);
32784 *(p->conf.requests_ptr) += 1;
32785 *(p->conf.bytes_written_ptr) += con->bytes_written;
32786 *(p->conf.bytes_read_ptr) += con->bytes_read;
32789 return HANDLER_GO_ON;
32792 int mod_rrdtool_plugin_init(plugin *p) {
32793 p->version = LIGHTTPD_VERSION_ID;
32794 p->name = buffer_init_string("rrd");
32797 p->init = mod_rrd_init;
32798 p->cleanup = mod_rrd_free;
32799 p->set_defaults= mod_rrd_set_defaults;
32802 p->handle_trigger = mod_rrd_trigger;
32803 p->handle_request_done = mod_rrd_account;
32811 --- ../lighttpd-1.4.11/src/mod_scgi.c 2006-03-04 17:15:26.000000000 +0200
32812 +++ lighttpd-1.4.12/src/mod_scgi.c 2006-07-18 13:03:40.000000000 +0300
32814 #include <sys/types.h>
32815 -#include <unistd.h>
32818 #include <string.h>
32820 #include "connections.h"
32821 #include "response.h"
32822 #include "joblist.h"
32823 +#include "http_resp.h"
32825 #include "plugin.h"
32830 #include "sys-socket.h"
32832 +#include "sys-files.h"
32833 +#include "sys-strings.h"
32834 +#include "sys-process.h"
32836 #ifndef UNIX_PATH_MAX
32837 # define UNIX_PATH_MAX 108
32838 @@ -46,30 +48,29 @@
32839 enum {EOL_UNSET, EOL_N, EOL_RN};
32847 * - add timeout for a connect to a non-scgi process
32848 * (use state_timestamp + state)
32853 typedef struct scgi_proc {
32854 size_t id; /* id will be between 1 and max_procs */
32855 buffer *socket; /* config.socket + "-" + id */
32856 unsigned port; /* config.port + pno */
32858 - pid_t pid; /* PID of the spawned process (0 if not spawned locally) */
32860 + pid_t pid; /* PID of the spawned process (0 if not spawned locally) */
32862 size_t load; /* number of requests waiting on this process */
32864 time_t last_used; /* see idle_timeout */
32865 size_t requests; /* see max_requests */
32866 struct scgi_proc *prev, *next; /* see first */
32869 time_t disable_ts; /* replace by host->something */
32874 enum { PROC_STATE_UNSET, /* init-phase */
32876 PROC_STATE_KILLED, /* was killed as we don't have the load anymore */
32877 PROC_STATE_DIED, /* marked as dead, should be restarted */
32878 PROC_STATE_DISABLED /* proc disabled as it resulted in an error */
32884 @@ -86,20 +87,20 @@
32885 * sorted by lowest load
32887 * whenever a job is done move it up in the list
32888 - * until it is sorted, move it down as soon as the
32889 + * until it is sorted, move it down as soon as the
32892 - scgi_proc *first;
32893 - scgi_proc *unused_procs;
32894 + scgi_proc *first;
32895 + scgi_proc *unused_procs;
32899 * spawn at least min_procs, at max_procs.
32901 - * as soon as the load of the first entry
32902 + * as soon as the load of the first entry
32903 * is max_load_per_proc we spawn a new one
32904 - * and add it to the first entry and give it
32905 + * and add it to the first entry and give it
32911 unsigned short min_procs;
32912 @@ -111,44 +112,44 @@
32915 * kick the process from the list if it was not
32916 - * used for idle_timeout until min_procs is
32917 + * used for idle_timeout until min_procs is
32918 * reached. this helps to get the processlist
32919 * small again we had a small peak load.
32924 unsigned short idle_timeout;
32928 * time after a disabled remote connection is tried to be re-enabled
32936 unsigned short disable_time;
32939 * same scgi processes get a little bit larger
32940 - * than wanted. max_requests_per_proc kills a
32941 + * than wanted. max_requests_per_proc kills a
32942 * process after a number of handled requests.
32945 size_t max_requests_per_proc;
32956 - * if host is one of the local IP adresses the
32957 + * if host is one of the local IP adresses the
32958 * whole connection is local
32960 * if tcp/ip should be used host AND port have
32961 - * to be specified
32965 + * to be specified
32969 unsigned short port;
32972 @@ -161,7 +162,7 @@
32974 buffer *unixsocket;
32976 - /* if socket is local we can start the scgi
32977 + /* if socket is local we can start the scgi
32980 * bin-path is the path to the binary
32981 @@ -169,19 +170,19 @@
32982 * check min_procs and max_procs for the number
32983 * of process to start-up
32985 - buffer *bin_path;
32987 - /* bin-path is set bin-environment is taken to
32988 + buffer *bin_path;
32990 + /* bin-path is set bin-environment is taken to
32991 * create the environement before starting the
32999 array *bin_env_copy;
33003 - * docroot-translation between URL->phys and the
33004 + * docroot-translation between URL->phys and the
33008 @@ -192,7 +193,7 @@
33012 - * check_local tell you if the phys file is stat()ed
33013 + * check_local tell you if the phys file is stat()ed
33014 * or not. FastCGI doesn't care if the service is
33015 * remote. If the web-server side doesn't contain
33016 * the scgi-files we should not stat() for them
33017 @@ -202,33 +203,33 @@
33020 * append PATH_INFO to SCRIPT_FILENAME
33023 * php needs this if cgi.fix_pathinfo is provied
33029 ssize_t load; /* replace by host->load */
33031 size_t max_id; /* corresponds most of the time to
33035 only if a process is killed max_id waits for the process itself
33036 to die and decrements its afterwards */
33037 } scgi_extension_host;
33040 * one extension can have multiple hosts assigned
33041 - * one host can spawn additional processes on the same
33042 + * one host can spawn additional processes on the same
33043 * socket (if we control it)
33045 * ext -> host -> procs
33048 - * if the scgi process is remote that whole goes down
33049 + * if the scgi process is remote that whole goes down
33052 * ext -> host -> procs
33056 * in case of PHP and FCGI_CHILDREN we have again a procs
33057 * but we don't control it directly.
33058 @@ -239,7 +240,7 @@
33059 buffer *key; /* like .php */
33061 scgi_extension_host **hosts;
33067 @@ -253,14 +254,14 @@
33085 @@ -268,52 +269,51 @@
33086 /* generic plugin data, shared between all connections */
33095 - buffer *parse_response;
33100 plugin_config **config_storage;
33103 plugin_config conf; /* this is only used as long as no handler_ctx is setup */
33106 /* connection specific data */
33107 -typedef enum { FCGI_STATE_INIT, FCGI_STATE_CONNECT, FCGI_STATE_PREPARE_WRITE,
33108 - FCGI_STATE_WRITE, FCGI_STATE_READ
33111 + SCGI_STATE_CONNECT,
33112 + SCGI_STATE_PREPARE_WRITE,
33113 + SCGI_STATE_WRITE,
33114 + SCGI_STATE_RESPONSE_HEADER,
33115 + SCGI_STATE_RESPONSE_CONTENT,
33117 } scgi_connection_state_t;
33120 - buffer *response;
33121 - size_t response_len;
33122 - int response_type;
33123 - int response_padding;
33126 scgi_extension_host *host;
33129 scgi_connection_state_t state;
33130 time_t state_timestamp;
33133 int reconnects; /* number of reconnect attempts */
33140 - buffer *response_header;
33143 int delayed; /* flag to mark that the connect() is delayed */
33147 - int fd; /* fd to the scgi process */
33148 - int fde_ndx; /* index into the fd-event buffer */
33149 + iosocket *sock; /* fd to the scgi process */
33155 plugin_config conf;
33158 connection *remote_conn; /* dumb pointer */
33159 plugin_data *plugin_data; /* dumb pointer */
33161 @@ -328,42 +328,30 @@
33163 static handler_ctx * handler_ctx_init() {
33164 handler_ctx * hctx;
33167 hctx = calloc(1, sizeof(*hctx));
33170 - hctx->fde_ndx = -1;
33172 - hctx->response = buffer_init();
33173 - hctx->response_header = buffer_init();
33176 + hctx->sock = iosocket_init();;
33178 hctx->request_id = 0;
33179 - hctx->state = FCGI_STATE_INIT;
33180 + hctx->state = SCGI_STATE_INIT;
33183 - hctx->response_len = 0;
33184 - hctx->response_type = 0;
33185 - hctx->response_padding = 0;
33189 hctx->reconnects = 0;
33191 hctx->wb = chunkqueue_init();
33193 + hctx->rb = chunkqueue_init();
33198 static void handler_ctx_free(handler_ctx *hctx) {
33199 - buffer_free(hctx->response);
33200 - buffer_free(hctx->response_header);
33202 chunkqueue_free(hctx->wb);
33205 - if (hctx->rb->ptr) free(hctx->rb->ptr);
33209 + chunkqueue_free(hctx->rb);
33211 + iosocket_free(hctx->sock);
33216 @@ -372,20 +360,20 @@
33218 f = calloc(1, sizeof(*f));
33219 f->socket = buffer_init();
33229 void scgi_process_free(scgi_proc *f) {
33233 scgi_process_free(f->next);
33236 buffer_free(f->socket);
33242 @@ -400,62 +388,62 @@
33243 f->bin_path = buffer_init();
33244 f->bin_env = array_init();
33245 f->bin_env_copy = array_init();
33251 void scgi_host_free(scgi_extension_host *h) {
33255 buffer_free(h->host);
33256 buffer_free(h->unixsocket);
33257 buffer_free(h->docroot);
33258 buffer_free(h->bin_path);
33259 array_free(h->bin_env);
33260 array_free(h->bin_env_copy);
33263 scgi_process_free(h->first);
33264 scgi_process_free(h->unused_procs);
33272 scgi_exts *scgi_extensions_init() {
33275 f = calloc(1, sizeof(*f));
33281 void scgi_extensions_free(scgi_exts *f) {
33288 for (i = 0; i < f->used; i++) {
33289 scgi_extension *fe;
33296 for (j = 0; j < fe->used; j++) {
33297 scgi_extension_host *h;
33307 buffer_free(fe->key);
33321 @@ -504,99 +492,103 @@
33325 - fe->hosts[fe->used++] = fh;
33326 + fe->hosts[fe->used++] = fh;
33333 INIT_FUNC(mod_scgi_init) {
33337 p = calloc(1, sizeof(*p));
33340 p->scgi_env = buffer_init();
33343 p->path = buffer_init();
33344 - p->parse_response = buffer_init();
33346 + p->resp = http_response_init();
33352 FREE_FUNC(mod_scgi_free) {
33353 plugin_data *p = p_d;
33358 buffer_free(p->scgi_env);
33359 buffer_free(p->path);
33360 - buffer_free(p->parse_response);
33362 + http_response_free(p->resp);
33364 if (p->config_storage) {
33366 for (i = 0; i < srv->config_context->used; i++) {
33367 plugin_config *s = p->config_storage[i];
33376 for (j = 0; j < exts->used; j++) {
33377 scgi_extension *ex;
33380 ex = exts->exts[j];
33383 for (n = 0; n < ex->used; n++) {
33385 scgi_extension_host *host;
33388 host = ex->hosts[n];
33391 for (proc = host->first; proc; proc = proc->next) {
33393 if (proc->pid != 0) kill(proc->pid, SIGTERM);
33395 - if (proc->is_local &&
33398 + if (proc->is_local &&
33399 !buffer_is_empty(proc->socket)) {
33400 unlink(proc->socket->ptr);
33405 for (proc = host->unused_procs; proc; proc = proc->next) {
33407 if (proc->pid != 0) kill(proc->pid, SIGTERM);
33409 - if (proc->is_local &&
33412 + if (proc->is_local &&
33413 !buffer_is_empty(proc->socket)) {
33414 unlink(proc->socket->ptr);
33421 scgi_extensions_free(s->exts);
33426 free(p->config_storage);
33433 return HANDLER_GO_ON;
33436 static int env_add(char_array *env, const char *key, size_t key_len, const char *val, size_t val_len) {
33440 if (!key || !val) return -1;
33443 dst = malloc(key_len + val_len + 3);
33444 memcpy(dst, key, key_len);
33445 dst[key_len] = '=';
33446 /* add the \0 from the value */
33447 memcpy(dst + key_len + 1, val, val_len + 1);
33450 if (env->size == 0) {
33452 env->ptr = malloc(env->size * sizeof(*env->ptr));
33453 @@ -604,13 +596,13 @@
33455 env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
33459 env->ptr[env->used++] = dst;
33465 -static int scgi_spawn_connection(server *srv,
33466 +static int scgi_spawn_connection(server *srv,
33468 scgi_extension_host *host,
33470 @@ -622,31 +614,27 @@
33472 struct sockaddr_in scgi_addr_in;
33473 struct sockaddr *scgi_addr;
33484 if (p->conf.debug) {
33485 log_error_write(srv, __FILE__, __LINE__, "sdb",
33486 "new proc, socket:", proc->port, proc->socket);
33490 if (!buffer_is_empty(proc->socket)) {
33491 memset(&scgi_addr, 0, sizeof(scgi_addr));
33494 #ifdef HAVE_SYS_UN_H
33495 scgi_addr_un.sun_family = AF_UNIX;
33496 strcpy(scgi_addr_un.sun_path, proc->socket->ptr);
33500 servlen = SUN_LEN(&scgi_addr_un);
33502 - /* stevens says: */
33503 - servlen = proc->socket->used + sizeof(scgi_addr_un.sun_family);
33506 socket_type = AF_UNIX;
33507 scgi_addr = (struct sockaddr *) &scgi_addr_un;
33509 @@ -656,115 +644,115 @@
33512 scgi_addr_in.sin_family = AF_INET;
33515 if (buffer_is_empty(host->host)) {
33516 scgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
33518 struct hostent *he;
33521 /* set a usefull default */
33522 scgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
33527 if (NULL == (he = gethostbyname(host->host->ptr))) {
33528 - log_error_write(srv, __FILE__, __LINE__,
33529 - "sdb", "gethostbyname failed: ",
33530 + log_error_write(srv, __FILE__, __LINE__,
33531 + "sdb", "gethostbyname failed: ",
33532 h_errno, host->host);
33537 if (he->h_addrtype != AF_INET) {
33538 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype);
33543 if (he->h_length != sizeof(struct in_addr)) {
33544 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-length != sizeof(in_addr): ", he->h_length);
33549 memcpy(&(scgi_addr_in.sin_addr.s_addr), he->h_addr_list[0], he->h_length);
33553 scgi_addr_in.sin_port = htons(proc->port);
33554 servlen = sizeof(scgi_addr_in);
33557 socket_type = AF_INET;
33558 scgi_addr = (struct sockaddr *) &scgi_addr_in;
33562 if (-1 == (scgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
33563 - log_error_write(srv, __FILE__, __LINE__, "ss",
33564 + log_error_write(srv, __FILE__, __LINE__, "ss",
33565 "failed:", strerror(errno));
33570 if (-1 == connect(scgi_fd, scgi_addr, servlen)) {
33571 /* server is not up, spawn in */
33576 if (!buffer_is_empty(proc->socket)) {
33577 unlink(proc->socket->ptr);
33584 /* reopen socket */
33585 if (-1 == (scgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
33586 - log_error_write(srv, __FILE__, __LINE__, "ss",
33587 + log_error_write(srv, __FILE__, __LINE__, "ss",
33588 "socket failed:", strerror(errno));
33594 if (setsockopt(scgi_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
33595 - log_error_write(srv, __FILE__, __LINE__, "ss",
33596 + log_error_write(srv, __FILE__, __LINE__, "ss",
33597 "socketsockopt failed:", strerror(errno));
33602 /* create socket */
33603 if (-1 == bind(scgi_fd, scgi_addr, servlen)) {
33604 - log_error_write(srv, __FILE__, __LINE__, "sbds",
33605 - "bind failed for:",
33608 + log_error_write(srv, __FILE__, __LINE__, "sbds",
33609 + "bind failed for:",
33617 if (-1 == listen(scgi_fd, 1024)) {
33618 - log_error_write(srv, __FILE__, __LINE__, "ss",
33619 + log_error_write(srv, __FILE__, __LINE__, "ss",
33620 "listen failed:", strerror(errno));
33627 switch ((child = fork())) {
33637 /* create environment */
33643 /* we don't need the client socket */
33644 for (fd = 3; fd < 256; fd++) {
33645 if (fd != 2 && fd != scgi_fd) close(fd);
33649 /* build clean environment */
33650 if (host->bin_env_copy->used) {
33651 for (i = 0; i < host->bin_env_copy->used; i++) {
33652 data_string *ds = (data_string *)host->bin_env_copy->data[i];
33656 if (NULL != (ge = getenv(ds->value->ptr))) {
33657 env_add(&env, CONST_BUF_LEN(ds->value), ge, strlen(ge));
33659 @@ -772,44 +760,44 @@
33661 for (i = 0; environ[i]; i++) {
33665 if (NULL != (eq = strchr(environ[i], '='))) {
33666 env_add(&env, environ[i], eq - environ[i], eq+1, strlen(eq+1));
33672 /* create environment */
33673 for (i = 0; i < host->bin_env->used; i++) {
33674 data_string *ds = (data_string *)host->bin_env->data[i];
33677 env_add(&env, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
33681 for (i = 0; i < env.used; i++) {
33682 /* search for PHP_FCGI_CHILDREN */
33683 if (0 == strncmp(env.ptr[i], "PHP_FCGI_CHILDREN=", sizeof("PHP_FCGI_CHILDREN=") - 1)) break;
33687 /* not found, add a default */
33688 if (i == env.used) {
33689 env_add(&env, CONST_STR_LEN("PHP_FCGI_CHILDREN"), CONST_STR_LEN("1"));
33693 env.ptr[env.used] = NULL;
33697 buffer_copy_string(b, "exec ");
33698 buffer_append_string_buffer(b, host->bin_path);
33702 execle("/bin/sh", "sh", "-c", b->ptr, NULL, env.ptr);
33704 - log_error_write(srv, __FILE__, __LINE__, "sbs",
33706 + log_error_write(srv, __FILE__, __LINE__, "sbs",
33707 "execl failed for:", host->bin_path, strerror(errno));
33716 @@ -817,32 +805,32 @@
33723 select(0, NULL, NULL, NULL, &tv);
33726 switch (waitpid(child, &status, WNOHANG)) {
33728 /* child still running after timeout, good */
33731 /* no PID found ? should never happen */
33732 - log_error_write(srv, __FILE__, __LINE__, "ss",
33733 + log_error_write(srv, __FILE__, __LINE__, "ss",
33734 "pid not found:", strerror(errno));
33737 /* the child should not terminate at all */
33738 if (WIFEXITED(status)) {
33739 - log_error_write(srv, __FILE__, __LINE__, "sd",
33740 - "child exited (is this a SCGI binary ?):",
33741 + log_error_write(srv, __FILE__, __LINE__, "sd",
33742 + "child exited (is this a SCGI binary ?):",
33743 WEXITSTATUS(status));
33744 } else if (WIFSIGNALED(status)) {
33745 - log_error_write(srv, __FILE__, __LINE__, "sd",
33746 - "child signaled:",
33747 + log_error_write(srv, __FILE__, __LINE__, "sd",
33748 + "child signaled:",
33751 - log_error_write(srv, __FILE__, __LINE__, "sd",
33752 - "child died somehow:",
33753 + log_error_write(srv, __FILE__, __LINE__, "sd",
33754 + "child died somehow:",
33758 @@ -852,26 +840,26 @@
33760 proc->last_used = srv->cur_ts;
33761 proc->is_local = 1;
33768 proc->is_local = 0;
33772 if (p->conf.debug) {
33773 log_error_write(srv, __FILE__, __LINE__, "sb",
33774 "(debug) socket is already used, won't spawn:",
33780 proc->state = PROC_STATE_RUNNING;
33781 host->active_procs++;
33790 @@ -880,89 +868,89 @@
33791 plugin_data *p = p_d;
33795 - config_values_t cv[] = {
33797 + config_values_t cv[] = {
33798 { "scgi.server", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
33799 { "scgi.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
33800 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
33804 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
33807 for (i = 0; i < srv->config_context->used; i++) {
33812 s = malloc(sizeof(plugin_config));
33813 s->exts = scgi_extensions_init();
33817 cv[0].destination = s->exts;
33818 cv[1].destination = &(s->debug);
33821 p->config_storage[i] = s;
33822 ca = ((data_config *)srv->config_context->data[i])->value;
33825 if (0 != config_insert_values_global(srv, ca, cv)) {
33826 return HANDLER_ERROR;
33836 if (NULL != (du = array_get_element(ca, "scgi.server"))) {
33838 data_array *da = (data_array *)du;
33841 if (du->type != TYPE_ARRAY) {
33842 - log_error_write(srv, __FILE__, __LINE__, "sss",
33843 + log_error_write(srv, __FILE__, __LINE__, "sss",
33844 "unexpected type for key: ", "scgi.server", "array of strings");
33847 return HANDLER_ERROR;
33852 - * scgi.server = ( "<ext>" => ( ... ),
33856 + * scgi.server = ( "<ext>" => ( ... ),
33857 * "<ext>" => ( ... ) )
33861 for (j = 0; j < da->value->used; j++) {
33863 data_array *da_ext = (data_array *)da->value->data[j];
33866 if (da->value->data[j]->type != TYPE_ARRAY) {
33867 - log_error_write(srv, __FILE__, __LINE__, "sssbs",
33868 - "unexpected type for key: ", "scgi.server",
33869 + log_error_write(srv, __FILE__, __LINE__, "sssbs",
33870 + "unexpected type for key: ", "scgi.server",
33871 "[", da->value->data[j]->key, "](string)");
33874 return HANDLER_ERROR;
33878 - * da_ext->key == name of the extension
33881 + * da_ext->key == name of the extension
33885 - * scgi.server = ( "<ext>" =>
33886 - * ( "<host>" => ( ... ),
33889 + * scgi.server = ( "<ext>" =>
33890 + * ( "<host>" => ( ... ),
33891 * "<host>" => ( ... )
33898 for (n = 0; n < da_ext->value->used; n++) {
33899 data_array *da_host = (data_array *)da_ext->value->data[n];
33902 scgi_extension_host *df;
33904 - config_values_t fcv[] = {
33906 + config_values_t fcv[] = {
33907 { "host", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
33908 { "docroot", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
33909 { "socket", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
33910 { "bin-path", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
33913 { "check-local", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 4 */
33914 { "port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 5 */
33915 { "min-procs-not-working", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 7 this is broken for now */
33916 @@ -970,37 +958,37 @@
33917 { "max-load-per-proc", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 8 */
33918 { "idle-timeout", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 9 */
33919 { "disable-time", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 10 */
33922 { "bin-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 11 */
33923 { "bin-copy-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 12 */
33928 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
33932 if (da_host->type != TYPE_ARRAY) {
33933 - log_error_write(srv, __FILE__, __LINE__, "ssSBS",
33934 - "unexpected type for key:",
33936 + log_error_write(srv, __FILE__, __LINE__, "ssSBS",
33937 + "unexpected type for key:",
33939 "[", da_host->key, "](string)");
33942 return HANDLER_ERROR;
33946 df = scgi_host_init();
33949 df->check_local = 1;
33952 df->max_load_per_proc = 1;
33953 df->idle_timeout = 60;
33954 df->disable_time = 60;
33957 fcv[0].destination = df->host;
33958 fcv[1].destination = df->docroot;
33959 fcv[2].destination = df->unixsocket;
33960 fcv[3].destination = df->bin_path;
33963 fcv[4].destination = &(df->check_local);
33964 fcv[5].destination = &(df->port);
33965 fcv[6].destination = &(df->min_procs);
33966 @@ -1008,47 +996,47 @@
33967 fcv[8].destination = &(df->max_load_per_proc);
33968 fcv[9].destination = &(df->idle_timeout);
33969 fcv[10].destination = &(df->disable_time);
33972 fcv[11].destination = df->bin_env;
33973 fcv[12].destination = df->bin_env_copy;
33978 if (0 != config_insert_values_internal(srv, da_host->value, fcv)) {
33979 return HANDLER_ERROR;
33982 - if ((!buffer_is_empty(df->host) || df->port) &&
33984 + if ((!buffer_is_empty(df->host) || df->port) &&
33985 !buffer_is_empty(df->unixsocket)) {
33986 - log_error_write(srv, __FILE__, __LINE__, "s",
33987 + log_error_write(srv, __FILE__, __LINE__, "s",
33988 "either host+port or socket");
33991 return HANDLER_ERROR;
33995 if (!buffer_is_empty(df->unixsocket)) {
33996 /* unix domain socket */
33999 if (df->unixsocket->used > UNIX_PATH_MAX - 2) {
34000 - log_error_write(srv, __FILE__, __LINE__, "s",
34001 + log_error_write(srv, __FILE__, __LINE__, "s",
34002 "path of the unixdomain socket is too large");
34003 return HANDLER_ERROR;
34008 - if (buffer_is_empty(df->host) &&
34010 + if (buffer_is_empty(df->host) &&
34011 buffer_is_empty(df->bin_path)) {
34012 - log_error_write(srv, __FILE__, __LINE__, "sbbbs",
34013 - "missing key (string):",
34014 + log_error_write(srv, __FILE__, __LINE__, "sbbbs",
34015 + "missing key (string):",
34022 return HANDLER_ERROR;
34023 } else if (df->port == 0) {
34024 - log_error_write(srv, __FILE__, __LINE__, "sbbbs",
34025 - "missing key (short):",
34026 + log_error_write(srv, __FILE__, __LINE__, "sbbbs",
34027 + "missing key (short):",
34031 @@ -1056,14 +1044,14 @@
34032 return HANDLER_ERROR;
34036 - if (!buffer_is_empty(df->bin_path)) {
34038 + if (!buffer_is_empty(df->bin_path)) {
34039 /* a local socket + self spawning */
34043 if (df->min_procs > df->max_procs) df->max_procs = df->min_procs;
34044 if (df->max_load_per_proc < 1) df->max_load_per_proc = 0;
34048 log_error_write(srv, __FILE__, __LINE__, "ssbsdsbsdsd",
34049 "--- scgi spawning local",
34050 @@ -1073,7 +1061,7 @@
34051 "\n\tmin-procs:", df->min_procs,
34052 "\n\tmax-procs:", df->max_procs);
34056 for (pno = 0; pno < df->min_procs; pno++) {
34059 @@ -1088,7 +1076,7 @@
34060 buffer_append_string(proc->socket, "-");
34061 buffer_append_long(proc->socket, pno);
34066 log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd",
34067 "--- scgi spawning",
34068 @@ -1096,53 +1084,53 @@
34069 "\n\tsocket", df->unixsocket,
34070 "\n\tcurrent:", pno, "/", df->min_procs);
34074 if (scgi_spawn_connection(srv, p, df, proc)) {
34075 log_error_write(srv, __FILE__, __LINE__, "s",
34076 "[ERROR]: spawning fcgi failed.");
34077 return HANDLER_ERROR;
34081 proc->next = df->first;
34082 if (df->first) df->first->prev = proc;
34091 fp = scgi_process_init();
34092 fp->id = df->num_procs++;
34094 df->active_procs++;
34095 fp->state = PROC_STATE_RUNNING;
34098 if (buffer_is_empty(df->unixsocket)) {
34099 fp->port = df->port;
34101 buffer_copy_string_buffer(fp->socket, df->unixsocket);
34113 /* if extension already exists, take it */
34114 scgi_extension_insert(s->exts, da_ext->key, df);
34121 return HANDLER_GO_ON;
34124 static int scgi_set_state(server *srv, handler_ctx *hctx, scgi_connection_state_t state) {
34125 hctx->state = state;
34126 hctx->state_timestamp = srv->cur_ts;
34132 @@ -1150,35 +1138,35 @@
34133 void scgi_connection_cleanup(server *srv, handler_ctx *hctx) {
34138 if (NULL == hctx) return;
34141 p = hctx->plugin_data;
34142 con = hctx->remote_conn;
34145 if (con->mode != p->id) {
34150 - if (hctx->fd != -1) {
34151 - fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
34152 - fdevent_unregister(srv->ev, hctx->fd);
34155 + if (hctx->sock->fd != -1) {
34156 + fdevent_event_del(srv->ev, hctx->sock);
34157 + fdevent_unregister(srv->ev, hctx->sock);
34158 + closesocket(hctx->sock->fd);
34159 + hctx->sock->fd = -1;
34164 if (hctx->host && hctx->proc) {
34165 hctx->host->load--;
34168 if (hctx->got_proc) {
34169 /* after the connect the process gets a load */
34170 hctx->proc->load--;
34173 if (p->conf.debug) {
34174 log_error_write(srv, __FILE__, __LINE__, "sddb",
34179 hctx->proc->pid, hctx->proc->socket);
34182 @@ -1186,87 +1174,87 @@
34183 scgi_proclist_sort_down(srv, hctx->host, hctx->proc);
34188 handler_ctx_free(hctx);
34189 - con->plugin_ctx[p->id] = NULL;
34190 + con->plugin_ctx[p->id] = NULL;
34193 static int scgi_reconnect(server *srv, handler_ctx *hctx) {
34194 plugin_data *p = hctx->plugin_data;
34205 * connect was ok, connection was accepted
34206 * but the php accept loop checks after the accept if it should die or not.
34208 - * if yes we can only detect it at a write()
34211 + * if yes we can only detect it at a write()
34213 * next step is resetting this attemp and setup a connection again
34216 * if we have more then 5 reconnects for the same request, die
34223 * we have a connection but the child died by some other reason
34228 - fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
34229 - fdevent_unregister(srv->ev, hctx->fd);
34232 + fdevent_event_del(srv->ev, hctx->sock);
34233 + fdevent_unregister(srv->ev, hctx->sock);
34234 + closesocket(hctx->sock->fd);
34237 - scgi_set_state(srv, hctx, FCGI_STATE_INIT);
34240 + scgi_set_state(srv, hctx, SCGI_STATE_INIT);
34242 hctx->request_id = 0;
34243 hctx->reconnects++;
34246 if (p->conf.debug) {
34247 log_error_write(srv, __FILE__, __LINE__, "sddb",
34252 hctx->proc->pid, hctx->proc->socket);
34256 hctx->proc->load--;
34257 scgi_proclist_sort_down(srv, hctx->host, hctx->proc);
34264 static handler_t scgi_connection_reset(server *srv, connection *con, void *p_d) {
34265 plugin_data *p = p_d;
34268 scgi_connection_cleanup(srv, con->plugin_ctx[p->id]);
34271 return HANDLER_GO_ON;
34275 static int scgi_env_add(buffer *env, const char *key, size_t key_len, const char *val, size_t val_len) {
34279 if (!key || !val) return -1;
34282 len = key_len + val_len + 2;
34285 buffer_prepare_append(env, len);
34287 - /* include the NUL */
34288 + /* include the NUL */
34289 memcpy(env->ptr + env->used, key, key_len + 1);
34290 env->used += key_len + 1;
34291 memcpy(env->ptr + env->used, val, val_len + 1);
34292 env->used += val_len + 1;
34305 @@ -1280,24 +1268,21 @@
34306 struct sockaddr_un scgi_addr_un;
34311 scgi_extension_host *host = hctx->host;
34312 scgi_proc *proc = hctx->proc;
34313 - int scgi_fd = hctx->fd;
34315 + int scgi_fd = hctx->sock->fd;
34317 memset(&scgi_addr, 0, sizeof(scgi_addr));
34320 if (!buffer_is_empty(proc->socket)) {
34321 #ifdef HAVE_SYS_UN_H
34322 /* use the unix domain socket */
34323 scgi_addr_un.sun_family = AF_UNIX;
34324 strcpy(scgi_addr_un.sun_path, proc->socket->ptr);
34327 servlen = SUN_LEN(&scgi_addr_un);
34329 - /* stevens says: */
34330 - servlen = proc->socket->used + sizeof(scgi_addr_un.sun_family);
34333 scgi_addr = (struct sockaddr *) &scgi_addr_un;
34336 @@ -1305,105 +1290,105 @@
34338 scgi_addr_in.sin_family = AF_INET;
34339 if (0 == inet_aton(host->host->ptr, &(scgi_addr_in.sin_addr))) {
34340 - log_error_write(srv, __FILE__, __LINE__, "sbs",
34341 - "converting IP-adress failed for", host->host,
34342 + log_error_write(srv, __FILE__, __LINE__, "sbs",
34343 + "converting IP-adress failed for", host->host,
34344 "\nBe sure to specify an IP address here");
34349 scgi_addr_in.sin_port = htons(proc->port);
34350 servlen = sizeof(scgi_addr_in);
34353 scgi_addr = (struct sockaddr *) &scgi_addr_in;
34357 if (-1 == connect(scgi_fd, scgi_addr, servlen)) {
34358 - if (errno == EINPROGRESS ||
34359 + if (errno == EINPROGRESS ||
34360 errno == EALREADY ||
34362 if (hctx->conf.debug) {
34363 - log_error_write(srv, __FILE__, __LINE__, "sd",
34364 + log_error_write(srv, __FILE__, __LINE__, "sd",
34365 "connect delayed, will continue later:", scgi_fd);
34371 - log_error_write(srv, __FILE__, __LINE__, "sdsddb",
34372 - "connect failed:", scgi_fd,
34373 + log_error_write(srv, __FILE__, __LINE__, "sdsddb",
34374 + "connect failed:", scgi_fd,
34375 strerror(errno), errno,
34376 proc->port, proc->socket);
34378 if (errno == EAGAIN) {
34379 /* this is Linux only */
34381 - log_error_write(srv, __FILE__, __LINE__, "s",
34383 + log_error_write(srv, __FILE__, __LINE__, "s",
34384 "If this happend on Linux: You have been run out of local ports. "
34385 "Check the manual, section Performance how to handle this.");
34393 if (hctx->conf.debug > 1) {
34394 - log_error_write(srv, __FILE__, __LINE__, "sd",
34395 + log_error_write(srv, __FILE__, __LINE__, "sd",
34396 "connect succeeded: ", scgi_fd);
34405 static int scgi_env_add_request_headers(server *srv, connection *con, plugin_data *p) {
34409 for (i = 0; i < con->request.headers->used; i++) {
34413 ds = (data_string *)con->request.headers->data[i];
34416 if (ds->value->used && ds->key->used) {
34418 buffer_reset(srv->tmp_buf);
34421 if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
34422 BUFFER_COPY_STRING_CONST(srv->tmp_buf, "HTTP_");
34423 srv->tmp_buf->used--;
34427 buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
34428 for (j = 0; j < ds->key->used - 1; j++) {
34429 - srv->tmp_buf->ptr[srv->tmp_buf->used++] =
34430 - light_isalpha(ds->key->ptr[j]) ?
34431 + srv->tmp_buf->ptr[srv->tmp_buf->used++] =
34432 + light_isalpha(ds->key->ptr[j]) ?
34433 ds->key->ptr[j] & ~32 : '_';
34435 srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
34438 scgi_env_add(p->scgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
34443 for (i = 0; i < con->environment->used; i++) {
34447 ds = (data_string *)con->environment->data[i];
34450 if (ds->value->used && ds->key->used) {
34452 buffer_reset(srv->tmp_buf);
34455 buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
34456 for (j = 0; j < ds->key->used - 1; j++) {
34457 - srv->tmp_buf->ptr[srv->tmp_buf->used++] =
34458 - isalpha((unsigned char)ds->key->ptr[j]) ?
34459 + srv->tmp_buf->ptr[srv->tmp_buf->used++] =
34460 + isalpha((unsigned char)ds->key->ptr[j]) ?
34461 toupper((unsigned char)ds->key->ptr[j]) : '_';
34463 srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
34466 scgi_env_add(p->scgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
34474 @@ -1415,20 +1400,20 @@
34475 char b2[INET6_ADDRSTRLEN + 1];
34480 plugin_data *p = hctx->plugin_data;
34481 scgi_extension_host *host= hctx->host;
34483 connection *con = hctx->remote_conn;
34484 server_socket *srv_sock = con->srv_socket;
34487 sock_addr our_addr;
34488 socklen_t our_addr_len;
34491 buffer_prepare_copy(p->scgi_env, 1024);
34493 /* CGI-SPEC 6.1.2, FastCGI spec 6.3 and SCGI spec */
34496 /* request.content_length < SSIZE_MAX, see request.c */
34497 ltostr(buf, con->request.content_length);
34498 scgi_env_add(p->scgi_env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf));
34499 @@ -1436,13 +1421,13 @@
34502 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION));
34505 if (con->server_name->used) {
34506 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_NAME"), CONST_BUF_LEN(con->server_name));
34509 - s = inet_ntop(srv_sock->addr.plain.sa_family,
34510 - srv_sock->addr.plain.sa_family == AF_INET6 ?
34511 + s = inet_ntop(srv_sock->addr.plain.sa_family,
34512 + srv_sock->addr.plain.sa_family == AF_INET6 ?
34513 (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
34514 (const void *) &(srv_sock->addr.ipv4.sin_addr),
34516 @@ -1451,47 +1436,47 @@
34518 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_NAME"), s, strlen(s));
34522 scgi_env_add(p->scgi_env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1"));
34528 ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
34530 ntohs(srv_sock->addr.ipv4.sin_port)
34535 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf));
34538 /* get the server-side of the connection to the client */
34539 our_addr_len = sizeof(our_addr);
34541 - if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) {
34543 + if (-1 == getsockname(con->sock->fd, &(our_addr.plain), &our_addr_len)) {
34544 s = inet_ntop_cache_get_ip(srv, &(srv_sock->addr));
34546 s = inet_ntop_cache_get_ip(srv, &(our_addr));
34548 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_ADDR"), s, strlen(s));
34554 ntohs(con->dst_addr.plain.sa_family ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
34556 ntohs(con->dst_addr.ipv4.sin_port)
34561 scgi_env_add(p->scgi_env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf));
34564 s = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
34565 scgi_env_add(p->scgi_env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s));
34568 if (!buffer_is_empty(con->authed_user)) {
34569 scgi_env_add(p->scgi_env, CONST_STR_LEN("REMOTE_USER"),
34570 CONST_BUF_LEN(con->authed_user));
34576 * SCRIPT_NAME, PATH_INFO and PATH_TRANSLATED according to
34577 @@ -1500,12 +1485,12 @@
34580 scgi_env_add(p->scgi_env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
34583 if (!buffer_is_empty(con->request.pathinfo)) {
34584 scgi_env_add(p->scgi_env, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo));
34587 /* PATH_TRANSLATED is only defined if PATH_INFO is set */
34590 if (!buffer_is_empty(host->docroot)) {
34591 buffer_copy_string_buffer(p->path, host->docroot);
34593 @@ -1526,19 +1511,19 @@
34596 if (!buffer_is_empty(host->docroot)) {
34598 - * rewrite SCRIPT_FILENAME
34601 + * rewrite SCRIPT_FILENAME
34606 buffer_copy_string_buffer(p->path, host->docroot);
34607 buffer_append_string_buffer(p->path, con->uri.path);
34610 scgi_env_add(p->scgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
34611 scgi_env_add(p->scgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(host->docroot));
34613 buffer_copy_string_buffer(p->path, con->physical.path);
34616 scgi_env_add(p->scgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
34617 scgi_env_add(p->scgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root));
34619 @@ -1551,30 +1536,30 @@
34621 scgi_env_add(p->scgi_env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN(""));
34625 s = get_http_method_name(con->request.http_method);
34626 scgi_env_add(p->scgi_env, CONST_STR_LEN("REQUEST_METHOD"), s, strlen(s));
34627 scgi_env_add(p->scgi_env, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200")); /* if php is compiled with --force-redirect */
34628 s = get_http_version_name(con->request.http_version);
34629 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s));
34633 if (srv_sock->is_ssl) {
34634 scgi_env_add(p->scgi_env, CONST_STR_LEN("HTTPS"), CONST_STR_LEN("on"));
34639 scgi_env_add_request_headers(srv, con, p);
34641 b = chunkqueue_get_append_buffer(hctx->wb);
34644 buffer_append_long(b, p->scgi_env->used);
34645 buffer_append_string_len(b, CONST_STR_LEN(":"));
34646 buffer_append_string_len(b, (const char *)p->scgi_env->ptr, p->scgi_env->used);
34647 buffer_append_string_len(b, CONST_STR_LEN(","));
34649 hctx->wb->bytes_in += b->used - 1;
34652 if (con->request.content_length) {
34653 chunkqueue *req_cq = con->request_content_queue;
34655 @@ -1587,7 +1572,7 @@
34657 /* we announce toWrite octects
34658 * now take all the request_content chunk that we need to fill this request
34662 switch (req_c->type) {
34664 @@ -1615,293 +1600,170 @@
34666 req_c->offset += weHave;
34667 req_cq->bytes_out += weHave;
34670 hctx->wb->bytes_in += weHave;
34684 for (i = 0; i < hctx->write_buffer->used; i++) {
34685 fprintf(stderr, "%02x ", hctx->write_buffer->ptr[i]);
34686 if ((i+1) % 16 == 0) {
34688 for (j = i-15; j <= i; j++) {
34689 - fprintf(stderr, "%c",
34690 + fprintf(stderr, "%c",
34691 isprint((unsigned char)hctx->write_buffer->ptr[j]) ? hctx->write_buffer->ptr[j] : '.');
34693 fprintf(stderr, "\n");
34701 -static int scgi_response_parse(server *srv, connection *con, plugin_data *p, buffer *in, int eol) {
34708 - buffer_copy_string_buffer(p->parse_response, in);
34710 - for (s = p->parse_response->ptr;
34711 - NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n')));
34712 - s = ns + (eol == EOL_RN ? 2 : 1), line++) {
34713 - const char *key, *value;
34720 - 0 == strncmp(s, "HTTP/1.", 7)) {
34721 - /* non-parsed header ... we parse them anyway */
34723 - if ((s[7] == '1' ||
34727 - /* after the space should be a status code for us */
34729 - status = strtol(s+9, NULL, 10);
34731 - if (con->http_status >= 100 &&
34732 - con->http_status < 1000) {
34733 - /* we expected 3 digits and didn't got them */
34734 - con->parsed_response |= HTTP_STATUS;
34735 - con->http_status = status;
34741 - if (NULL == (value = strchr(s, ':'))) {
34742 - /* we expect: "<key>: <value>\r\n" */
34746 - key_len = value - key;
34750 - while (*value == ' ' || *value == '\t') value++;
34752 - if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
34753 - ds = data_response_init();
34755 - buffer_copy_string_len(ds->key, key, key_len);
34756 - buffer_copy_string(ds->value, value);
34758 - array_insert_unique(con->response.headers, (data_unset *)ds);
34760 - switch(key_len) {
34762 - if (0 == strncasecmp(key, "Date", key_len)) {
34763 - con->parsed_response |= HTTP_DATE;
34767 - if (0 == strncasecmp(key, "Status", key_len)) {
34768 - con->http_status = strtol(value, NULL, 10);
34769 - con->parsed_response |= HTTP_STATUS;
34773 - if (0 == strncasecmp(key, "Location", key_len)) {
34774 - con->parsed_response |= HTTP_LOCATION;
34778 - if (0 == strncasecmp(key, "Connection", key_len)) {
34779 - con->response.keep_alive = (0 == strcasecmp(value, "Keep-Alive")) ? 1 : 0;
34780 - con->parsed_response |= HTTP_CONNECTION;
34784 - if (0 == strncasecmp(key, "Content-Length", key_len)) {
34785 - con->response.content_length = strtol(value, NULL, 10);
34786 - con->parsed_response |= HTTP_CONTENT_LENGTH;
34795 - /* CGI/1.1 rev 03 - 7.2.1.2 */
34796 - if ((con->parsed_response & HTTP_LOCATION) &&
34797 - !(con->parsed_response & HTTP_STATUS)) {
34798 - con->http_status = 302;
34805 static int scgi_demux_response(server *srv, handler_ctx *hctx) {
34806 plugin_data *p = hctx->plugin_data;
34807 connection *con = hctx->remote_conn;
34812 - buffer_prepare_copy(hctx->response, 1024);
34813 - if (-1 == (n = read(hctx->fd, hctx->response->ptr, hctx->response->size - 1))) {
34814 - if (errno == EAGAIN || errno == EINTR) {
34815 - /* would block, wait for signal */
34819 - log_error_write(srv, __FILE__, __LINE__, "sdd", strerror(errno), con->fd, hctx->fd);
34824 - /* read finished */
34826 - con->file_finished = 1;
34828 - /* send final chunk */
34829 - http_chunk_append_mem(srv, con, NULL, 0);
34830 - joblist_append(srv, con);
34834 + switch(srv->network_backend_read(srv, con, hctx->sock, hctx->rb)) {
34835 + case NETWORK_STATUS_SUCCESS:
34836 + /* we got content */
34838 + case NETWORK_STATUS_WAIT_FOR_EVENT:
34839 + /* the ioctl will return WAIT_FOR_EVENT on a read */
34840 + if (0 == con->file_started) return -1;
34841 + case NETWORK_STATUS_CONNECTION_CLOSE:
34842 + /* we are done, get out of here */
34843 + con->file_finished = 1;
34845 + /* close the chunk-queue with a empty chunk */
34853 + /* looks like we got some content
34855 + * split off the header from the incoming stream
34858 + if (hctx->state == SCGI_STATE_RESPONSE_HEADER) {
34860 + int have_content_length = 0;
34862 + http_response_reset(p->resp);
34864 + /* the response header is not fully received yet,
34866 + * extract the http-response header from the rb-cq
34868 + switch (http_response_parse_cq(hctx->rb, p->resp)) {
34869 + case PARSE_ERROR:
34870 + /* parsing failed */
34872 + con->http_status = 502; /* Bad Gateway */
34876 - hctx->response->ptr[n] = '\0';
34877 - hctx->response->used = n+1;
34879 - /* split header from body */
34881 - if (con->file_started == 0) {
34883 - int in_header = 0;
34884 - int header_end = 0;
34885 - int cp, eol = EOL_UNSET;
34888 - buffer_append_string_buffer(hctx->response_header, hctx->response);
34890 - /* nph (non-parsed headers) */
34891 - if (0 == strncmp(hctx->response_header->ptr, "HTTP/1.", 7)) in_header = 1;
34893 - /* search for the \r\n\r\n or \n\n in the string */
34894 - for (c = hctx->response_header->ptr, cp = 0, used = hctx->response_header->used - 1; used; c++, cp++, used--) {
34895 - if (*c == ':') in_header = 1;
34896 - else if (*c == '\n') {
34897 - if (in_header == 0) {
34898 - /* got a response without a response header */
34905 - if (eol == EOL_UNSET) eol = EOL_N;
34907 - if (*(c+1) == '\n') {
34912 - } else if (used > 1 && *c == '\r' && *(c+1) == '\n') {
34913 - if (in_header == 0) {
34914 - /* got a response without a response header */
34921 - if (eol == EOL_UNSET) eol = EOL_RN;
34924 - *(c+2) == '\r' &&
34925 - *(c+3) == '\n') {
34930 - /* skip the \n */
34934 + case PARSE_NEED_MORE:
34936 + case PARSE_SUCCESS:
34937 + con->http_status = p->resp->status;
34939 + chunkqueue_remove_finished_chunks(hctx->rb);
34941 + /* copy the http-headers */
34942 + for (i = 0; i < p->resp->headers->used; i++) {
34943 + const char *ign[] = { "Status", "Connection", NULL };
34947 + data_string *header = (data_string *)p->resp->headers->data[i];
34949 + /* some headers are ignored by default */
34950 + for (j = 0; ign[j]; j++) {
34951 + if (0 == strcasecmp(ign[j], header->key->ptr)) break;
34955 - if (header_end) {
34957 - /* no header, but a body */
34959 - if (con->request.http_version == HTTP_VERSION_1_1) {
34960 - con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
34963 - http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used);
34964 - joblist_append(srv, con);
34966 - size_t hlen = c - hctx->response_header->ptr + (eol == EOL_RN ? 4 : 2);
34967 - size_t blen = hctx->response_header->used - hlen - 1;
34969 - /* a small hack: terminate after at the second \r */
34970 - hctx->response_header->used = hlen + 1 - (eol == EOL_RN ? 2 : 1);
34971 - hctx->response_header->ptr[hlen - (eol == EOL_RN ? 2 : 1)] = '\0';
34973 - /* parse the response header */
34974 - scgi_response_parse(srv, con, p, hctx->response_header, eol);
34976 - /* enable chunked-transfer-encoding */
34977 - if (con->request.http_version == HTTP_VERSION_1_1 &&
34978 - !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
34979 - con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
34982 - if ((hctx->response->used != hlen) && blen > 0) {
34983 - http_chunk_append_mem(srv, con, c + (eol == EOL_RN ? 4: 2), blen + 1);
34984 - joblist_append(srv, con);
34986 + if (ign[j]) continue;
34988 + if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Location"))) {
34989 + /* CGI/1.1 rev 03 - 7.2.1.2 */
34990 + if (con->http_status == 0) con->http_status = 302;
34991 + } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Content-Length"))) {
34992 + have_content_length = 1;
34995 - con->file_started = 1;
34996 + if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
34997 + ds = data_response_init();
34999 + buffer_copy_string_buffer(ds->key, header->key);
35000 + buffer_copy_string_buffer(ds->value, header->value);
35002 + array_insert_unique(con->response.headers, (data_unset *)ds);
35005 - http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used);
35006 - joblist_append(srv, con);
35008 + con->file_started = 1;
35010 + if (con->request.http_version == HTTP_VERSION_1_1 &&
35011 + !have_content_length) {
35012 + con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
35015 + hctx->state = SCGI_STATE_RESPONSE_CONTENT;
35020 - log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), b->ptr);
35025 + /* FIXME: pass the response-header to the other plugins to
35026 + * setup the filter-queue
35028 + * - use next-queue instead of con->write_queue
35031 + assert(hctx->state == SCGI_STATE_RESPONSE_CONTENT);
35033 + /* FIXME: if we have a content-length or chunked-encoding
35036 + * for now we wait for EOF on the socket */
35038 + /* copy the content to the next cq */
35039 + for (c = hctx->rb->first; c; c = c->next) {
35040 + http_chunk_append_mem(srv, con, c->mem->ptr + c->offset, c->mem->used - c->offset);
35042 + c->offset = c->mem->used - 1;
35045 + chunkqueue_remove_finished_chunks(hctx->rb);
35046 + joblist_append(srv, con);
35052 int scgi_proclist_sort_up(server *srv, scgi_extension_host *host, scgi_proc *proc) {
35058 - /* we have been the smallest of the current list
35059 - * and we want to insert the node sorted as soon
35061 + /* we have been the smallest of the current list
35062 + * and we want to insert the node sorted as soon
35075 /* nothing to sort, only one element */
35076 @@ -1909,9 +1771,9 @@
35078 for (p = proc; p->next && p->next->load < proc->load; p = p->next);
35080 - /* no need to move something
35081 + /* no need to move something
35088 @@ -1930,16 +1792,16 @@
35090 if (proc->prev) proc->prev->next = proc->next;
35091 if (proc->next) proc->next->prev = proc->prev;
35094 /* proc should be right of p */
35097 proc->next = p->next;
35099 if (p->next) p->next->prev = proc;
35102 for(p = host->first; p; p = p->next) {
35103 - log_error_write(srv, __FILE__, __LINE__, "dd",
35104 + log_error_write(srv, __FILE__, __LINE__, "dd",
35108 @@ -1951,21 +1813,21 @@
35110 int scgi_proclist_sort_down(server *srv, scgi_extension_host *host, scgi_proc *proc) {
35116 - /* we have been the smallest of the current list
35117 - * and we want to insert the node sorted as soon
35119 + /* we have been the smallest of the current list
35120 + * and we want to insert the node sorted as soon
35130 * the basic is idea is:
35131 - * - the last active scgi process should be still
35132 + * - the last active scgi process should be still
35133 * in ram and is not swapped out yet
35134 * - processes that are not reused will be killed
35135 * after some time by the trigger-handler
35136 @@ -1975,7 +1837,7 @@
35137 * ice-cold processes are propably unused since more
35138 * than 'unused-timeout', are swaped out and won't be
35139 * reused in the next seconds anyway.
35144 /* nothing to sort, only one element */
35145 @@ -1984,16 +1846,16 @@
35146 for (p = host->first; p != proc && p->load < proc->load; p = p->next);
35149 - /* no need to move something
35150 + /* no need to move something
35159 if (p == proc) return 0;
35162 /* we have to move left. If we are already the first element
35164 if (host->first == proc) return 0;
35165 @@ -2009,9 +1871,9 @@
35168 if (proc->prev == NULL) host->first = proc;
35171 for(p = host->first; p; p = p->next) {
35172 - log_error_write(srv, __FILE__, __LINE__, "dd",
35173 + log_error_write(srv, __FILE__, __LINE__, "dd",
35177 @@ -2023,41 +1885,42 @@
35179 static int scgi_restart_dead_procs(server *srv, plugin_data *p, scgi_extension_host *host) {
35183 for (proc = host->first; proc; proc = proc->next) {
35184 if (p->conf.debug) {
35185 - log_error_write(srv, __FILE__, __LINE__, "sbdbdddd",
35187 - host->host, proc->port,
35188 + log_error_write(srv, __FILE__, __LINE__, "sbdbdddd",
35190 + host->host, proc->port,
35199 if (0 == proc->is_local) {
35201 - * external servers might get disabled
35203 - * enable the server again, perhaps it is back again
35205 + * external servers might get disabled
35207 + * enable the server again, perhaps it is back again
35211 if ((proc->state == PROC_STATE_DISABLED) &&
35212 (srv->cur_ts - proc->disable_ts > host->disable_time)) {
35213 proc->state = PROC_STATE_RUNNING;
35214 host->active_procs++;
35216 - log_error_write(srv, __FILE__, __LINE__, "sbdb",
35217 - "fcgi-server re-enabled:",
35218 - host->host, host->port,
35220 + log_error_write(srv, __FILE__, __LINE__, "sbdb",
35221 + "fcgi-server re-enabled:",
35222 + host->host, host->port,
35226 /* the child should not terminate at all */
35230 if (proc->state == PROC_STATE_DIED_WAIT_FOR_PID) {
35232 switch(waitpid(proc->pid, &status, WNOHANG)) {
35234 /* child is still alive */
35235 @@ -2067,33 +1930,34 @@
35237 if (WIFEXITED(status)) {
35239 - log_error_write(srv, __FILE__, __LINE__, "sdsd",
35240 + log_error_write(srv, __FILE__, __LINE__, "sdsd",
35241 "child exited, pid:", proc->pid,
35242 "status:", WEXITSTATUS(status));
35244 } else if (WIFSIGNALED(status)) {
35245 - log_error_write(srv, __FILE__, __LINE__, "sd",
35246 - "child signaled:",
35247 + log_error_write(srv, __FILE__, __LINE__, "sd",
35248 + "child signaled:",
35251 - log_error_write(srv, __FILE__, __LINE__, "sd",
35252 - "child died somehow:",
35253 + log_error_write(srv, __FILE__, __LINE__, "sd",
35254 + "child died somehow:",
35259 proc->state = PROC_STATE_DIED;
35268 * local servers might died, but we restart them
35272 if (proc->state == PROC_STATE_DIED &&
35274 /* restart the child */
35277 if (p->conf.debug) {
35278 log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd",
35279 "--- scgi spawning",
35280 @@ -2101,18 +1965,18 @@
35281 "\n\tsocket", host->unixsocket,
35282 "\n\tcurrent:", 1, "/", host->min_procs);
35286 if (scgi_spawn_connection(srv, p, host, proc)) {
35287 log_error_write(srv, __FILE__, __LINE__, "s",
35288 "ERROR: spawning fcgi failed.");
35289 return HANDLER_ERROR;
35293 scgi_proclist_sort_down(srv, host, proc);
35302 @@ -2121,13 +1985,13 @@
35303 plugin_data *p = hctx->plugin_data;
35304 scgi_extension_host *host= hctx->host;
35305 connection *con = hctx->remote_conn;
35310 - /* sanity check */
35311 + /* sanity check */
35313 ((!host->host->used || !host->port) && !host->unixsocket->used)) {
35314 - log_error_write(srv, __FILE__, __LINE__, "sxddd",
35315 + log_error_write(srv, __FILE__, __LINE__, "sxddd",
35316 "write-req: error",
35319 @@ -2135,259 +1999,260 @@
35320 host->unixsocket->used);
35321 return HANDLER_ERROR;
35326 switch(hctx->state) {
35327 - case FCGI_STATE_INIT:
35328 + case SCGI_STATE_INIT:
35329 ret = host->unixsocket->used ? AF_UNIX : AF_INET;
35331 - if (-1 == (hctx->fd = socket(ret, SOCK_STREAM, 0))) {
35333 + if (-1 == (hctx->sock->fd = socket(ret, SOCK_STREAM, 0))) {
35334 if (errno == EMFILE ||
35336 - log_error_write(srv, __FILE__, __LINE__, "sd",
35337 - "wait for fd at connection:", con->fd);
35339 + log_error_write(srv, __FILE__, __LINE__, "sd",
35340 + "wait for fd at connection:", con->sock->fd);
35342 return HANDLER_WAIT_FOR_FD;
35345 - log_error_write(srv, __FILE__, __LINE__, "ssdd",
35347 + log_error_write(srv, __FILE__, __LINE__, "ssdd",
35348 "socket failed:", strerror(errno), srv->cur_fds, srv->max_fds);
35349 return HANDLER_ERROR;
35351 - hctx->fde_ndx = -1;
35353 + hctx->sock->fde_ndx = -1;
35357 - fdevent_register(srv->ev, hctx->fd, scgi_handle_fdevent, hctx);
35359 - if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
35360 - log_error_write(srv, __FILE__, __LINE__, "ss",
35362 + fdevent_register(srv->ev, hctx->sock, scgi_handle_fdevent, hctx);
35364 + if (-1 == fdevent_fcntl_set(srv->ev, hctx->sock)) {
35365 + log_error_write(srv, __FILE__, __LINE__, "ss",
35366 "fcntl failed: ", strerror(errno));
35369 return HANDLER_ERROR;
35374 - case FCGI_STATE_CONNECT:
35375 - if (hctx->state == FCGI_STATE_INIT) {
35376 - for (hctx->proc = hctx->host->first;
35377 - hctx->proc && hctx->proc->state != PROC_STATE_RUNNING;
35378 + case SCGI_STATE_CONNECT:
35379 + if (hctx->state == SCGI_STATE_INIT) {
35380 + for (hctx->proc = hctx->host->first;
35381 + hctx->proc && hctx->proc->state != PROC_STATE_RUNNING;
35382 hctx->proc = hctx->proc->next);
35385 /* all childs are dead */
35386 if (hctx->proc == NULL) {
35387 - hctx->fde_ndx = -1;
35389 + hctx->sock->fde_ndx = -1;
35391 return HANDLER_ERROR;
35395 if (hctx->proc->is_local) {
35396 hctx->pid = hctx->proc->pid;
35400 switch (scgi_establish_connection(srv, hctx)) {
35402 - scgi_set_state(srv, hctx, FCGI_STATE_CONNECT);
35404 + scgi_set_state(srv, hctx, SCGI_STATE_CONNECT);
35406 /* connection is in progress, wait for an event and call getsockopt() below */
35408 - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
35411 + fdevent_event_add(srv->ev, hctx->sock, FDEVENT_OUT);
35413 return HANDLER_WAIT_FOR_EVENT;
35415 /* if ECONNREFUSED choose another connection -> FIXME */
35416 - hctx->fde_ndx = -1;
35418 + hctx->sock->fde_ndx = -1;
35420 return HANDLER_ERROR;
35422 /* everything is ok, go on */
35430 socklen_t socket_error_len = sizeof(socket_error);
35433 /* try to finish the connect() */
35434 - if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
35435 - log_error_write(srv, __FILE__, __LINE__, "ss",
35436 + if (0 != getsockopt(hctx->sock->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
35437 + log_error_write(srv, __FILE__, __LINE__, "ss",
35438 "getsockopt failed:", strerror(errno));
35441 return HANDLER_ERROR;
35443 if (socket_error != 0) {
35444 if (!hctx->proc->is_local || p->conf.debug) {
35445 /* local procs get restarted */
35448 log_error_write(srv, __FILE__, __LINE__, "ss",
35449 - "establishing connection failed:", strerror(socket_error),
35450 + "establishing connection failed:", strerror(socket_error),
35451 "port:", hctx->proc->port);
35455 return HANDLER_ERROR;
35460 /* ok, we have the connection */
35463 hctx->proc->load++;
35464 hctx->proc->last_used = srv->cur_ts;
35465 hctx->got_proc = 1;
35468 if (p->conf.debug) {
35469 log_error_write(srv, __FILE__, __LINE__, "sddbdd",
35473 - hctx->proc->socket,
35477 + hctx->proc->socket,
35482 /* move the proc-list entry down the list */
35483 scgi_proclist_sort_up(srv, hctx->host, hctx->proc);
35485 - scgi_set_state(srv, hctx, FCGI_STATE_PREPARE_WRITE);
35487 + scgi_set_state(srv, hctx, SCGI_STATE_PREPARE_WRITE);
35489 - case FCGI_STATE_PREPARE_WRITE:
35490 + case SCGI_STATE_PREPARE_WRITE:
35491 scgi_create_env(srv, hctx);
35493 - scgi_set_state(srv, hctx, FCGI_STATE_WRITE);
35496 + scgi_set_state(srv, hctx, SCGI_STATE_WRITE);
35499 - case FCGI_STATE_WRITE:
35500 - ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
35501 + case SCGI_STATE_WRITE:
35502 + ret = srv->network_backend_write(srv, con, hctx->sock, hctx->wb);
35504 chunkqueue_remove_finished_chunks(hctx->wb);
35508 if (errno == ENOTCONN) {
35509 - /* the connection got dropped after accept()
35511 - * this is most of the time a PHP which dies
35512 + /* the connection got dropped after accept()
35514 + * this is most of the time a PHP which dies
35515 * after PHP_FCGI_MAX_REQUESTS
35520 if (hctx->wb->bytes_out == 0 &&
35521 hctx->reconnects < 5) {
35522 - usleep(10000); /* take away the load of the webserver
35523 - * to let the php a chance to restart
35525 + usleep(10000); /* take away the load of the webserver
35526 + * to let the php a chance to restart
35530 scgi_reconnect(srv, hctx);
35533 return HANDLER_WAIT_FOR_FD;
35537 /* not reconnected ... why
35540 * far@#lighttpd report this for FreeBSD
35545 - log_error_write(srv, __FILE__, __LINE__, "ssdsd",
35547 + log_error_write(srv, __FILE__, __LINE__, "ssosd",
35548 "[REPORT ME] connection was dropped after accept(). reconnect() denied:",
35549 "write-offset:", hctx->wb->bytes_out,
35550 "reconnect attempts:", hctx->reconnects);
35553 return HANDLER_ERROR;
35557 if ((errno != EAGAIN) &&
35558 (errno != EINTR)) {
35560 - log_error_write(srv, __FILE__, __LINE__, "ssd",
35562 + log_error_write(srv, __FILE__, __LINE__, "ssd",
35563 "write failed:", strerror(errno), errno);
35566 return HANDLER_ERROR;
35568 - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
35570 + fdevent_event_add(srv->ev, hctx->sock, FDEVENT_OUT);
35572 return HANDLER_WAIT_FOR_EVENT;
35577 if (hctx->wb->bytes_out == hctx->wb->bytes_in) {
35578 /* we don't need the out event anymore */
35579 - fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
35580 - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
35581 - scgi_set_state(srv, hctx, FCGI_STATE_READ);
35582 + fdevent_event_del(srv->ev, hctx->sock);
35583 + fdevent_event_add(srv->ev, hctx->sock, FDEVENT_IN);
35584 + scgi_set_state(srv, hctx, SCGI_STATE_RESPONSE_HEADER);
35586 - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
35588 + fdevent_event_add(srv->ev, hctx->sock, FDEVENT_OUT);
35590 return HANDLER_WAIT_FOR_EVENT;
35595 - case FCGI_STATE_READ:
35596 + case SCGI_STATE_RESPONSE_HEADER:
35597 /* waiting for a response */
35600 log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state");
35601 return HANDLER_ERROR;
35605 return HANDLER_WAIT_FOR_EVENT;
35608 SUBREQUEST_FUNC(mod_scgi_handle_subrequest) {
35609 plugin_data *p = p_d;
35612 handler_ctx *hctx = con->plugin_ctx[p->id];
35614 scgi_extension_host *host;
35617 if (NULL == hctx) return HANDLER_GO_ON;
35621 if (con->mode != p->id) return HANDLER_GO_ON;
35624 /* ok, create the request */
35625 switch(scgi_write_request(srv, hctx)) {
35626 case HANDLER_ERROR:
35633 0 == proc->is_local &&
35634 proc->state != PROC_STATE_DISABLED) {
35635 /* only disable remote servers as we don't manage them*/
35637 - log_error_write(srv, __FILE__, __LINE__, "sbdb", "fcgi-server disabled:",
35639 + log_error_write(srv, __FILE__, __LINE__, "sbdb", "fcgi-server disabled:",
35645 /* disable this server */
35646 proc->disable_ts = srv->cur_ts;
35647 proc->state = PROC_STATE_DISABLED;
35648 host->active_procs--;
35651 - if (hctx->state == FCGI_STATE_INIT ||
35652 - hctx->state == FCGI_STATE_CONNECT) {
35653 - /* connect() or getsockopt() failed,
35654 - * restart the request-handling
35656 + if (hctx->state == SCGI_STATE_INIT ||
35657 + hctx->state == SCGI_STATE_CONNECT) {
35658 + /* connect() or getsockopt() failed,
35659 + * restart the request-handling
35661 if (proc && proc->is_local) {
35663 if (p->conf.debug) {
35664 - log_error_write(srv, __FILE__, __LINE__, "sbdb", "connect() to scgi failed, restarting the request-handling:",
35665 + log_error_write(srv, __FILE__, __LINE__, "sbdb", "connect() to scgi failed, restarting the request-handling:",
35673 * several hctx might reference the same proc
35676 * Only one of them should mark the proc as dead all the other
35677 * ones should just take a new one.
35680 * If a new proc was started with the old struct this might lead
35681 * the mark a perfect proc as dead otherwise
35685 if (proc->state == PROC_STATE_RUNNING &&
35686 hctx->pid == proc->pid) {
35687 @@ -2395,25 +2260,25 @@
35690 scgi_restart_dead_procs(srv, p, host);
35693 scgi_connection_cleanup(srv, hctx);
35696 buffer_reset(con->physical.path);
35697 con->mode = DIRECT;
35698 joblist_append(srv, con);
35700 - /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
35701 - * and hope that the childs will be restarted
35704 + /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
35705 + * and hope that the childs will be restarted
35708 return HANDLER_WAIT_FOR_FD;
35710 scgi_connection_cleanup(srv, hctx);
35713 buffer_reset(con->physical.path);
35714 con->mode = DIRECT;
35715 con->http_status = 503;
35718 return HANDLER_FINISHED;
35720 case HANDLER_WAIT_FOR_EVENT:
35721 @@ -2433,23 +2298,23 @@
35722 static handler_t scgi_connection_close(server *srv, handler_ctx *hctx) {
35727 if (NULL == hctx) return HANDLER_GO_ON;
35730 p = hctx->plugin_data;
35731 con = hctx->remote_conn;
35734 if (con->mode != p->id) return HANDLER_GO_ON;
35736 - log_error_write(srv, __FILE__, __LINE__, "ssdsd",
35737 - "emergency exit: scgi:",
35738 - "connection-fd:", con->fd,
35739 - "fcgi-fd:", hctx->fd);
35744 + log_error_write(srv, __FILE__, __LINE__, "ssdsd",
35745 + "emergency exit: scgi:",
35746 + "connection-fd:", con->sock->fd,
35747 + "fcgi-fd:", hctx->sock->fd);
35751 scgi_connection_cleanup(srv, hctx);
35754 return HANDLER_FINISHED;
35757 @@ -2459,27 +2324,28 @@
35758 handler_ctx *hctx = ctx;
35759 connection *con = hctx->remote_conn;
35760 plugin_data *p = hctx->plugin_data;
35763 scgi_proc *proc = hctx->proc;
35764 scgi_extension_host *host= hctx->host;
35766 if ((revents & FDEVENT_IN) &&
35767 - hctx->state == FCGI_STATE_READ) {
35768 + (hctx->state == SCGI_STATE_RESPONSE_HEADER ||
35769 + hctx->state == SCGI_STATE_RESPONSE_CONTENT)) {
35770 switch (scgi_demux_response(srv, hctx)) {
35775 scgi_connection_cleanup(srv, hctx);
35778 joblist_append(srv, con);
35779 return HANDLER_FINISHED;
35781 if (proc->pid && proc->state != PROC_STATE_DIED) {
35785 /* only fetch the zombie if it is not already done */
35788 switch(waitpid(proc->pid, &status, WNOHANG)) {
35790 /* child is still alive */
35791 @@ -2489,19 +2355,19 @@
35793 /* the child should not terminate at all */
35794 if (WIFEXITED(status)) {
35795 - log_error_write(srv, __FILE__, __LINE__, "sdsd",
35796 + log_error_write(srv, __FILE__, __LINE__, "sdsd",
35797 "child exited, pid:", proc->pid,
35798 "status:", WEXITSTATUS(status));
35799 } else if (WIFSIGNALED(status)) {
35800 - log_error_write(srv, __FILE__, __LINE__, "sd",
35801 - "child signaled:",
35802 + log_error_write(srv, __FILE__, __LINE__, "sd",
35803 + "child signaled:",
35806 - log_error_write(srv, __FILE__, __LINE__, "sd",
35807 - "child died somehow:",
35808 + log_error_write(srv, __FILE__, __LINE__, "sd",
35809 + "child died somehow:",
35814 if (p->conf.debug) {
35815 log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd",
35816 "--- scgi spawning",
35817 @@ -2509,40 +2375,41 @@
35818 "\n\tsocket", host->unixsocket,
35819 "\n\tcurrent:", 1, "/", host->min_procs);
35823 if (scgi_spawn_connection(srv, p, host, proc)) {
35825 proc->state = PROC_STATE_DIED;
35827 scgi_proclist_sort_down(srv, host, proc);
35836 if (con->file_started == 0) {
35837 /* nothing has been send out yet, try to use another child */
35840 if (hctx->wb->bytes_out == 0 &&
35841 hctx->reconnects < 5) {
35842 scgi_reconnect(srv, hctx);
35844 - log_error_write(srv, __FILE__, __LINE__, "sdsdsd",
35846 + log_error_write(srv, __FILE__, __LINE__, "sdsdsd",
35847 "response not sent, request not sent, reconnection.",
35848 - "connection-fd:", con->fd,
35849 - "fcgi-fd:", hctx->fd);
35851 + "connection-fd:", con->sock->fd,
35852 + "fcgi-fd:", hctx->sock->fd);
35854 return HANDLER_WAIT_FOR_FD;
35857 - log_error_write(srv, __FILE__, __LINE__, "sdsdsd",
35859 + log_error_write(srv, __FILE__, __LINE__, "sosdsd",
35860 "response not sent, request sent:", hctx->wb->bytes_out,
35861 - "connection-fd:", con->fd,
35862 - "fcgi-fd:", hctx->fd);
35864 + "connection-fd:", con->sock->fd,
35865 + "fcgi-fd:", hctx->sock->fd);
35867 scgi_connection_cleanup(srv, hctx);
35870 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
35871 buffer_reset(con->physical.path);
35872 con->http_status = 500;
35873 @@ -2550,76 +2417,77 @@
35875 /* response might have been already started, kill the connection */
35876 scgi_connection_cleanup(srv, hctx);
35878 - log_error_write(srv, __FILE__, __LINE__, "ssdsd",
35880 + log_error_write(srv, __FILE__, __LINE__, "ssdsd",
35881 "response already sent out, termination connection",
35882 - "connection-fd:", con->fd,
35883 - "fcgi-fd:", hctx->fd);
35885 + "connection-fd:", con->sock->fd,
35886 + "fcgi-fd:", hctx->sock->fd);
35888 connection_set_state(srv, con, CON_STATE_ERROR);
35896 joblist_append(srv, con);
35897 return HANDLER_FINISHED;
35902 if (revents & FDEVENT_OUT) {
35903 - if (hctx->state == FCGI_STATE_CONNECT ||
35904 - hctx->state == FCGI_STATE_WRITE) {
35905 + if (hctx->state == SCGI_STATE_CONNECT ||
35906 + hctx->state == SCGI_STATE_WRITE) {
35907 /* we are allowed to send something out
35910 * 1. in a unfinished connect() call
35911 * 2. in a unfinished write() call (long POST request)
35913 return mod_scgi_handle_subrequest(srv, con, p);
35915 - log_error_write(srv, __FILE__, __LINE__, "sd",
35916 - "got a FDEVENT_OUT and didn't know why:",
35917 + log_error_write(srv, __FILE__, __LINE__, "sd",
35918 + "got a FDEVENT_OUT and didn't know why:",
35924 /* perhaps this issue is already handled */
35925 if (revents & FDEVENT_HUP) {
35926 - if (hctx->state == FCGI_STATE_CONNECT) {
35927 + if (hctx->state == SCGI_STATE_CONNECT) {
35928 /* getoptsock will catch this one (right ?)
35930 - * if we are in connect we might get a EINPROGRESS
35931 - * in the first call and a FDEVENT_HUP in the
35933 + * if we are in connect we might get a EINPROGRESS
35934 + * in the first call and a FDEVENT_HUP in the
35938 * FIXME: as it is a bit ugly.
35942 return mod_scgi_handle_subrequest(srv, con, p);
35943 - } else if (hctx->state == FCGI_STATE_READ &&
35944 + } else if ((hctx->state == SCGI_STATE_RESPONSE_HEADER ||
35945 + hctx->state == SCGI_STATE_RESPONSE_CONTENT ) &&
35946 hctx->proc->port == 0) {
35950 * ioctl says 8192 bytes to read from PHP and we receive directly a HUP for the socket
35951 * even if the FCGI_FIN packet is not received yet
35954 - log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd",
35955 - "error: unexpected close of scgi connection for",
35956 + log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd",
35957 + "error: unexpected close of scgi connection for",
35959 - "(no scgi process on host: ",
35960 + "(no scgi process on host: ",
35969 connection_set_state(srv, con, CON_STATE_ERROR);
35970 scgi_connection_close(srv, hctx);
35971 joblist_append(srv, con);
35973 } else if (revents & FDEVENT_ERR) {
35974 - log_error_write(srv, __FILE__, __LINE__, "s",
35975 + log_error_write(srv, __FILE__, __LINE__, "s",
35976 "fcgi: got a FDEVENT_ERR. Don't know why.");
35977 /* kill all connections to the scgi process */
35979 @@ -2628,42 +2496,39 @@
35980 scgi_connection_close(srv, hctx);
35981 joblist_append(srv, con);
35985 return HANDLER_FINISHED;
35987 -#define PATCH(x) \
35988 - p->conf.x = s->x;
35990 static int scgi_patch_connection(server *srv, connection *con, plugin_data *p) {
35992 plugin_config *s = p->config_storage[0];
35998 + PATCH_OPTION(exts);
35999 + PATCH_OPTION(debug);
36001 /* skip the first, the global context */
36002 for (i = 1; i < srv->config_context->used; i++) {
36003 data_config *dc = (data_config *)srv->config_context->data[i];
36004 s = p->config_storage[i];
36007 /* condition didn't match */
36008 if (!config_check_cond(srv, con, dc)) continue;
36012 for (j = 0; j < dc->value->used; j++) {
36013 data_unset *du = dc->value->data[j];
36016 if (buffer_is_equal_string(du->key, CONST_STR_LEN("scgi.server"))) {
36018 + PATCH_OPTION(exts);
36019 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("scgi.debug"))) {
36021 + PATCH_OPTION(debug);
36032 static handler_t scgi_check_extension(server *srv, connection *con, void *p_d, int uri_path_handler) {
36033 plugin_data *p = p_d;
36034 @@ -2673,30 +2538,30 @@
36037 scgi_extension *extension = NULL;
36040 /* Possibly, we processed already this request */
36041 if (con->file_started == 1) return HANDLER_GO_ON;
36044 fn = uri_path_handler ? con->uri.path : con->physical.path;
36046 if (buffer_is_empty(fn)) return HANDLER_GO_ON;
36048 s_len = fn->used - 1;
36051 scgi_patch_connection(srv, con, p);
36053 /* check if extension matches */
36054 for (k = 0; k < p->conf.exts->used; k++) {
36058 extension = p->conf.exts->exts[k];
36061 if (extension->key->used == 0) continue;
36064 ct_len = extension->key->used - 1;
36067 if (s_len < ct_len) continue;
36070 /* check extension in the form "/scgi_pattern" */
36071 if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
36073 @@ -2710,17 +2575,17 @@
36074 if (k == p->conf.exts->used) {
36075 return HANDLER_GO_ON;
36079 /* get best server */
36080 for (k = 0, ndx = -1; k < extension->used; k++) {
36081 scgi_extension_host *host = extension->hosts[k];
36084 /* we should have at least one proc that can do somthing */
36085 if (host->active_procs == 0) continue;
36087 if (used == -1 || host->load < used) {
36094 @@ -2728,12 +2593,12 @@
36095 /* found a server */
36097 scgi_extension_host *host = extension->hosts[ndx];
36100 - * if check-local is disabled, use the uri.path handler
36104 + * if check-local is disabled, use the uri.path handler
36109 /* init handler-context */
36110 if (uri_path_handler) {
36111 if (host->check_local == 0) {
36112 @@ -2741,7 +2606,7 @@
36115 hctx = handler_ctx_init();
36118 hctx->remote_conn = con;
36119 hctx->plugin_data = p;
36121 @@ -2749,45 +2614,45 @@
36123 hctx->conf.exts = p->conf.exts;
36124 hctx->conf.debug = p->conf.debug;
36127 con->plugin_ctx[p->id] = hctx;
36135 if (con->conf.log_request_handling) {
36136 log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_scgi");
36139 - /* the prefix is the SCRIPT_NAME,
36140 + /* the prefix is the SCRIPT_NAME,
36141 * everthing from start to the next slash
36142 * this is important for check-local = "disable"
36145 * if prefix = /admin.fcgi
36148 * /admin.fcgi/foo/bar
36151 * SCRIPT_NAME = /admin.fcgi
36152 * PATH_INFO = /foo/bar
36155 * if prefix = /fcgi-bin/
36158 * /fcgi-bin/foo/bar
36161 * SCRIPT_NAME = /fcgi-bin/foo
36168 /* the rewrite is only done for /prefix/? matches */
36169 if (extension->key->ptr[0] == '/' &&
36170 con->uri.path->used > extension->key->used &&
36171 NULL != (pathinfo = strchr(con->uri.path->ptr + extension->key->used - 1, '/'))) {
36172 - /* rewrite uri.path and pathinfo */
36174 + /* rewrite uri.path and pathinfo */
36176 buffer_copy_string(con->request.pathinfo, pathinfo);
36179 con->uri.path->used -= con->request.pathinfo->used - 1;
36180 con->uri.path->ptr[con->uri.path->used - 1] = '\0';
36182 @@ -2796,21 +2661,21 @@
36185 hctx = handler_ctx_init();
36188 hctx->remote_conn = con;
36189 hctx->plugin_data = p;
36194 hctx->conf.exts = p->conf.exts;
36195 hctx->conf.debug = p->conf.debug;
36198 con->plugin_ctx[p->id] = hctx;
36207 if (con->conf.log_request_handling) {
36208 log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_fastcgi");
36210 @@ -2821,11 +2686,11 @@
36211 /* no handler found */
36212 buffer_reset(con->physical.path);
36213 con->http_status = 500;
36215 - log_error_write(srv, __FILE__, __LINE__, "sb",
36216 - "no fcgi-handler found for:",
36218 + log_error_write(srv, __FILE__, __LINE__, "sb",
36219 + "no fcgi-handler found for:",
36223 return HANDLER_FINISHED;
36225 return HANDLER_GO_ON;
36226 @@ -2844,21 +2709,22 @@
36227 JOBLIST_FUNC(mod_scgi_handle_joblist) {
36228 plugin_data *p = p_d;
36229 handler_ctx *hctx = con->plugin_ctx[p->id];
36232 if (hctx == NULL) return HANDLER_GO_ON;
36234 - if (hctx->fd != -1) {
36235 + if (hctx->sock->fd != -1) {
36236 switch (hctx->state) {
36237 - case FCGI_STATE_READ:
36238 - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
36240 + case SCGI_STATE_RESPONSE_HEADER:
36241 + case SCGI_STATE_RESPONSE_CONTENT:
36242 + fdevent_event_add(srv->ev, hctx->sock, FDEVENT_IN);
36245 - case FCGI_STATE_CONNECT:
36246 - case FCGI_STATE_WRITE:
36247 - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
36249 + case SCGI_STATE_CONNECT:
36250 + case SCGI_STATE_WRITE:
36251 + fdevent_event_add(srv->ev, hctx->sock, FDEVENT_OUT);
36254 - case FCGI_STATE_INIT:
36255 + case SCGI_STATE_INIT:
36259 @@ -2873,21 +2739,21 @@
36261 static handler_t scgi_connection_close_callback(server *srv, connection *con, void *p_d) {
36262 plugin_data *p = p_d;
36265 return scgi_connection_close(srv, con->plugin_ctx[p->id]);
36268 TRIGGER_FUNC(mod_scgi_handle_trigger) {
36269 plugin_data *p = p_d;
36275 /* perhaps we should kill a connect attempt after 10-15 seconds
36278 * currently we wait for the TCP timeout which is on Linux 180 seconds
36287 /* check all childs if they are still up */
36288 @@ -2904,47 +2770,47 @@
36289 scgi_extension *ex;
36291 ex = exts->exts[j];
36294 for (n = 0; n < ex->used; n++) {
36298 unsigned long sum_load = 0;
36299 scgi_extension_host *host;
36302 host = ex->hosts[n];
36305 scgi_restart_dead_procs(srv, p, host);
36308 for (proc = host->first; proc; proc = proc->next) {
36309 sum_load += proc->load;
36313 if (host->num_procs &&
36314 host->num_procs < host->max_procs &&
36315 (sum_load / host->num_procs) > host->max_load_per_proc) {
36316 /* overload, spawn new child */
36317 scgi_proc *fp = NULL;
36320 if (p->conf.debug) {
36321 - log_error_write(srv, __FILE__, __LINE__, "s",
36322 + log_error_write(srv, __FILE__, __LINE__, "s",
36323 "overload detected, spawning a new child");
36327 for (fp = host->unused_procs; fp && fp->pid != 0; fp = fp->next);
36331 if (fp == host->unused_procs) host->unused_procs = fp->next;
36334 if (fp->next) fp->next->prev = NULL;
36339 fp = scgi_process_init();
36340 fp->id = host->max_id++;
36347 if (buffer_is_empty(host->unixsocket)) {
36348 fp->port = host->port + fp->id;
36350 @@ -2952,13 +2818,13 @@
36351 buffer_append_string(fp->socket, "-");
36352 buffer_append_long(fp->socket, fp->id);
36356 if (scgi_spawn_connection(srv, p, host, fp)) {
36357 log_error_write(srv, __FILE__, __LINE__, "s",
36358 "ERROR: spawning fcgi failed.");
36359 return HANDLER_ERROR;
36364 fp->next = host->first;
36366 @@ -2966,56 +2832,57 @@
36372 for (proc = host->first; proc; proc = proc->next) {
36373 if (proc->load != 0) break;
36374 if (host->num_procs <= host->min_procs) break;
36375 if (proc->pid == 0) continue;
36378 if (srv->cur_ts - proc->last_used > host->idle_timeout) {
36379 /* a proc is idling for a long time now,
36383 if (p->conf.debug) {
36384 - log_error_write(srv, __FILE__, __LINE__, "ssbsd",
36385 - "idle-timeout reached, terminating child:",
36386 - "socket:", proc->socket,
36387 + log_error_write(srv, __FILE__, __LINE__, "ssbsd",
36388 + "idle-timeout reached, terminating child:",
36389 + "socket:", proc->socket,
36396 if (proc->next) proc->next->prev = proc->prev;
36397 if (proc->prev) proc->prev->next = proc->next;
36400 if (proc->prev == NULL) host->first = proc->next;
36404 proc->next = host->unused_procs;
36407 if (host->unused_procs) host->unused_procs->prev = proc;
36408 host->unused_procs = proc;
36411 kill(proc->pid, SIGTERM);
36414 proc->state = PROC_STATE_KILLED;
36416 - log_error_write(srv, __FILE__, __LINE__, "ssbsd",
36418 - "socket:", proc->socket,
36420 + log_error_write(srv, __FILE__, __LINE__, "ssbsd",
36422 + "socket:", proc->socket,
36429 /* proc is now in unused, let the next second handle the next process */
36437 for (proc = host->unused_procs; proc; proc = proc->next) {
36441 if (proc->pid == 0) continue;
36444 switch (waitpid(proc->pid, &status, WNOHANG)) {
36446 /* child still running after timeout, good */
36447 @@ -3023,10 +2890,10 @@
36449 if (errno != EINTR) {
36450 /* no PID found ? should never happen */
36451 - log_error_write(srv, __FILE__, __LINE__, "sddss",
36452 + log_error_write(srv, __FILE__, __LINE__, "sddss",
36453 "pid ", proc->pid, proc->state,
36454 "not found:", strerror(errno));
36458 if (errno == ECHILD) {
36459 /* someone else has cleaned up for us */
36460 @@ -3040,25 +2907,26 @@
36461 /* the child should not terminate at all */
36462 if (WIFEXITED(status)) {
36463 if (proc->state != PROC_STATE_KILLED) {
36464 - log_error_write(srv, __FILE__, __LINE__, "sdb",
36466 + log_error_write(srv, __FILE__, __LINE__, "sdb",
36468 WEXITSTATUS(status), proc->socket);
36470 } else if (WIFSIGNALED(status)) {
36471 if (WTERMSIG(status) != SIGTERM) {
36472 - log_error_write(srv, __FILE__, __LINE__, "sd",
36473 - "child signaled:",
36474 + log_error_write(srv, __FILE__, __LINE__, "sd",
36475 + "child signaled:",
36479 - log_error_write(srv, __FILE__, __LINE__, "sd",
36480 - "child died somehow:",
36481 + log_error_write(srv, __FILE__, __LINE__, "sd",
36482 + "child died somehow:",
36486 proc->state = PROC_STATE_UNSET;
36493 @@ -3082,8 +2950,8 @@
36494 p->handle_subrequest = mod_scgi_handle_subrequest;
36495 p->handle_joblist = mod_scgi_handle_joblist;
36496 p->handle_trigger = mod_scgi_handle_trigger;
36504 --- ../lighttpd-1.4.11/src/mod_secure_download.c 2005-12-14 14:37:29.000000000 +0200
36505 +++ lighttpd-1.4.12/src/mod_secure_download.c 2006-07-16 00:26:03.000000000 +0300
36515 @@ -36,28 +36,28 @@
36518 buffer *uri_prefix;
36521 unsigned short timeout;
36531 plugin_config **config_storage;
36533 - plugin_config conf;
36535 + plugin_config conf;
36538 /* init the plugin data */
36539 INIT_FUNC(mod_secdownload_init) {
36543 p = calloc(1, sizeof(*p));
36546 p->md5 = buffer_init();
36552 @@ -65,27 +65,27 @@
36553 FREE_FUNC(mod_secdownload_free) {
36554 plugin_data *p = p_d;
36558 if (!p) return HANDLER_GO_ON;
36561 if (p->config_storage) {
36563 for (i = 0; i < srv->config_context->used; i++) {
36564 plugin_config *s = p->config_storage[i];
36567 buffer_free(s->secret);
36568 buffer_free(s->doc_root);
36569 buffer_free(s->uri_prefix);
36574 free(p->config_storage);
36578 buffer_free(p->md5);
36584 return HANDLER_GO_ON;
36587 @@ -94,107 +94,103 @@
36588 SETDEFAULTS_FUNC(mod_secdownload_set_defaults) {
36589 plugin_data *p = p_d;
36592 - config_values_t cv[] = {
36594 + config_values_t cv[] = {
36595 { "secdownload.secret", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
36596 { "secdownload.document-root", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
36597 { "secdownload.uri-prefix", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
36598 { "secdownload.timeout", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
36599 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
36603 if (!p) return HANDLER_ERROR;
36606 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
36609 for (i = 0; i < srv->config_context->used; i++) {
36613 s = calloc(1, sizeof(plugin_config));
36614 s->secret = buffer_init();
36615 s->doc_root = buffer_init();
36616 s->uri_prefix = buffer_init();
36620 cv[0].destination = s->secret;
36621 cv[1].destination = s->doc_root;
36622 cv[2].destination = s->uri_prefix;
36623 cv[3].destination = &(s->timeout);
36626 p->config_storage[i] = s;
36629 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
36630 return HANDLER_ERROR;
36635 return HANDLER_GO_ON;
36639 * checks if the supplied string is a MD5 string
36642 * @param str a possible MD5 string
36643 * @return if the supplied string is a valid MD5 string 1 is returned otherwise 0
36646 int is_hex_len(const char *str, size_t len) {
36650 if (NULL == str) return 0;
36653 for (i = 0; i < len && *str; i++, str++) {
36654 /* illegal characters */
36655 if (!((*str >= '0' && *str <= '9') ||
36656 (*str >= 'a' && *str <= 'f') ||
36657 - (*str >= 'A' && *str <= 'F'))
36658 + (*str >= 'A' && *str <= 'F'))
36668 -#define PATCH(x) \
36669 - p->conf.x = s->x;
36670 static int mod_secdownload_patch_connection(server *srv, connection *con, plugin_data *p) {
36672 plugin_config *s = p->config_storage[0];
36676 - PATCH(uri_prefix);
36680 + PATCH_OPTION(secret);
36681 + PATCH_OPTION(doc_root);
36682 + PATCH_OPTION(uri_prefix);
36683 + PATCH_OPTION(timeout);
36685 /* skip the first, the global context */
36686 for (i = 1; i < srv->config_context->used; i++) {
36687 data_config *dc = (data_config *)srv->config_context->data[i];
36688 s = p->config_storage[i];
36691 /* condition didn't match */
36692 if (!config_check_cond(srv, con, dc)) continue;
36696 for (j = 0; j < dc->value->used; j++) {
36697 data_unset *du = dc->value->data[j];
36700 if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.secret"))) {
36702 + PATCH_OPTION(secret);
36703 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.document-root"))) {
36705 + PATCH_OPTION(doc_root);
36706 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.uri-prefix"))) {
36707 - PATCH(uri_prefix);
36708 + PATCH_OPTION(uri_prefix);
36709 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.timeout"))) {
36711 + PATCH_OPTION(timeout);
36722 URIHANDLER_FUNC(mod_secdownload_uri_handler) {
36723 plugin_data *p = p_d;
36724 @@ -203,88 +199,88 @@
36725 const char *rel_uri, *ts_str, *md5_str;
36730 if (con->uri.path->used == 0) return HANDLER_GO_ON;
36733 mod_secdownload_patch_connection(srv, con, p);
36735 if (buffer_is_empty(p->conf.uri_prefix)) return HANDLER_GO_ON;
36738 if (buffer_is_empty(p->conf.secret)) {
36739 log_error_write(srv, __FILE__, __LINE__, "s",
36740 "secdownload.secret has to be set");
36741 return HANDLER_ERROR;
36745 if (buffer_is_empty(p->conf.doc_root)) {
36746 log_error_write(srv, __FILE__, __LINE__, "s",
36747 "secdownload.document-root has to be set");
36748 return HANDLER_ERROR;
36754 * /<uri-prefix>[a-f0-9]{32}/[a-f0-9]{8}/<rel-path>
36758 if (0 != strncmp(con->uri.path->ptr, p->conf.uri_prefix->ptr, p->conf.uri_prefix->used - 1)) return HANDLER_GO_ON;
36761 md5_str = con->uri.path->ptr + p->conf.uri_prefix->used - 1;
36764 if (!is_hex_len(md5_str, 32)) return HANDLER_GO_ON;
36765 if (*(md5_str + 32) != '/') return HANDLER_GO_ON;
36768 ts_str = md5_str + 32 + 1;
36771 if (!is_hex_len(ts_str, 8)) return HANDLER_GO_ON;
36772 if (*(ts_str + 8) != '/') return HANDLER_GO_ON;
36775 for (i = 0; i < 8; i++) {
36776 ts = (ts << 4) + hex2int(*(ts_str + i));
36781 - if (srv->cur_ts - ts > p->conf.timeout ||
36782 + if (srv->cur_ts - ts > p->conf.timeout ||
36783 srv->cur_ts - ts < -p->conf.timeout) {
36784 con->http_status = 408;
36787 return HANDLER_FINISHED;
36791 rel_uri = ts_str + 8;
36798 * <secret><rel-path><timestamp-hex>
36802 buffer_copy_string_buffer(p->md5, p->conf.secret);
36803 buffer_append_string(p->md5, rel_uri);
36804 buffer_append_string_len(p->md5, ts_str, 8);
36808 MD5_Update(&Md5Ctx, (unsigned char *)p->md5->ptr, p->md5->used - 1);
36809 MD5_Final(HA1, &Md5Ctx);
36812 buffer_copy_string_hex(p->md5, (char *)HA1, 16);
36815 if (0 != strncmp(md5_str, p->md5->ptr, 32)) {
36816 con->http_status = 403;
36818 - log_error_write(srv, __FILE__, __LINE__, "sss",
36820 + log_error_write(srv, __FILE__, __LINE__, "sss",
36822 md5_str, p->md5->ptr);
36825 return HANDLER_FINISHED;
36829 /* starting with the last / we should have relative-path to the docroot
36833 buffer_copy_string_buffer(con->physical.doc_root, p->conf.doc_root);
36834 buffer_copy_string(con->physical.rel_path, rel_uri);
36835 buffer_copy_string_buffer(con->physical.path, con->physical.doc_root);
36836 buffer_append_string_buffer(con->physical.path, con->physical.rel_path);
36839 return HANDLER_GO_ON;
36842 @@ -293,13 +289,13 @@
36843 int mod_secdownload_plugin_init(plugin *p) {
36844 p->version = LIGHTTPD_VERSION_ID;
36845 p->name = buffer_init_string("secdownload");
36848 p->init = mod_secdownload_init;
36849 p->handle_physical = mod_secdownload_uri_handler;
36850 p->set_defaults = mod_secdownload_set_defaults;
36851 p->cleanup = mod_secdownload_free;
36859 --- ../lighttpd-1.4.11/src/mod_setenv.c 2006-01-14 20:33:12.000000000 +0200
36860 +++ lighttpd-1.4.12/src/mod_setenv.c 2006-07-16 00:26:04.000000000 +0300
36861 @@ -18,25 +18,25 @@
36863 array *request_header;
36864 array *response_header;
36867 array *environment;
36874 plugin_config **config_storage;
36876 - plugin_config conf;
36878 + plugin_config conf;
36881 static handler_ctx * handler_ctx_init() {
36882 handler_ctx * hctx;
36885 hctx = calloc(1, sizeof(*hctx));
36894 @@ -48,36 +48,36 @@
36895 /* init the plugin data */
36896 INIT_FUNC(mod_setenv_init) {
36900 p = calloc(1, sizeof(*p));
36906 /* detroy the plugin data */
36907 FREE_FUNC(mod_setenv_free) {
36908 plugin_data *p = p_d;
36913 if (!p) return HANDLER_GO_ON;
36916 if (p->config_storage) {
36918 for (i = 0; i < srv->config_context->used; i++) {
36919 plugin_config *s = p->config_storage[i];
36922 array_free(s->request_header);
36923 array_free(s->response_header);
36924 array_free(s->environment);
36929 free(p->config_storage);
36936 return HANDLER_GO_ON;
36939 @@ -86,86 +86,83 @@
36940 SETDEFAULTS_FUNC(mod_setenv_set_defaults) {
36941 plugin_data *p = p_d;
36944 - config_values_t cv[] = {
36946 + config_values_t cv[] = {
36947 { "setenv.add-request-header", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
36948 { "setenv.add-response-header", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
36949 { "setenv.add-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
36950 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
36954 if (!p) return HANDLER_ERROR;
36957 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
36960 for (i = 0; i < srv->config_context->used; i++) {
36964 s = calloc(1, sizeof(plugin_config));
36965 s->request_header = array_init();
36966 s->response_header = array_init();
36967 s->environment = array_init();
36970 cv[0].destination = s->request_header;
36971 cv[1].destination = s->response_header;
36972 cv[2].destination = s->environment;
36975 p->config_storage[i] = s;
36978 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
36979 return HANDLER_ERROR;
36984 return HANDLER_GO_ON;
36987 -#define PATCH(x) \
36988 - p->conf.x = s->x;
36989 static int mod_setenv_patch_connection(server *srv, connection *con, plugin_data *p) {
36991 plugin_config *s = p->config_storage[0];
36993 - PATCH(request_header);
36994 - PATCH(response_header);
36995 - PATCH(environment);
36998 + PATCH_OPTION(request_header);
36999 + PATCH_OPTION(response_header);
37000 + PATCH_OPTION(environment);
37002 /* skip the first, the global context */
37003 for (i = 1; i < srv->config_context->used; i++) {
37004 data_config *dc = (data_config *)srv->config_context->data[i];
37005 s = p->config_storage[i];
37008 /* condition didn't match */
37009 if (!config_check_cond(srv, con, dc)) continue;
37013 for (j = 0; j < dc->value->used; j++) {
37014 data_unset *du = dc->value->data[j];
37017 if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-request-header"))) {
37018 - PATCH(request_header);
37019 + PATCH_OPTION(request_header);
37020 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-response-header"))) {
37021 - PATCH(response_header);
37022 + PATCH_OPTION(response_header);
37023 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-environment"))) {
37024 - PATCH(environment);
37025 + PATCH_OPTION(environment);
37035 URIHANDLER_FUNC(mod_setenv_uri_handler) {
37036 plugin_data *p = p_d;
37041 if (con->plugin_ctx[p->id]) {
37042 hctx = con->plugin_ctx[p->id];
37044 hctx = handler_ctx_init();
37047 con->plugin_ctx[p->id] = hctx;
37050 @@ -180,52 +177,52 @@
37051 for (k = 0; k < p->conf.request_header->used; k++) {
37052 data_string *ds = (data_string *)p->conf.request_header->data[k];
37053 data_string *ds_dst;
37056 if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
37057 ds_dst = data_string_init();
37061 buffer_copy_string_buffer(ds_dst->key, ds->key);
37062 buffer_copy_string_buffer(ds_dst->value, ds->value);
37065 array_insert_unique(con->request.headers, (data_unset *)ds_dst);
37069 for (k = 0; k < p->conf.environment->used; k++) {
37070 data_string *ds = (data_string *)p->conf.environment->data[k];
37071 data_string *ds_dst;
37074 if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) {
37075 ds_dst = data_string_init();
37079 buffer_copy_string_buffer(ds_dst->key, ds->key);
37080 buffer_copy_string_buffer(ds_dst->value, ds->value);
37083 array_insert_unique(con->environment, (data_unset *)ds_dst);
37087 for (k = 0; k < p->conf.response_header->used; k++) {
37088 data_string *ds = (data_string *)p->conf.response_header->data[k];
37091 response_header_insert(srv, con, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
37096 return HANDLER_GO_ON;
37099 REQUESTDONE_FUNC(mod_setenv_reset) {
37100 plugin_data *p = p_d;
37106 if (con->plugin_ctx[p->id]) {
37107 handler_ctx_free(con->plugin_ctx[p->id]);
37108 con->plugin_ctx[p->id] = NULL;
37111 - return HANDLER_GO_ON;
37112 + return HANDLER_GO_ON;
37115 /* this function is called at dlopen() time and inits the callbacks */
37116 @@ -233,15 +230,15 @@
37117 int mod_setenv_plugin_init(plugin *p) {
37118 p->version = LIGHTTPD_VERSION_ID;
37119 p->name = buffer_init_string("setenv");
37122 p->init = mod_setenv_init;
37123 p->handle_uri_clean = mod_setenv_uri_handler;
37124 p->set_defaults = mod_setenv_set_defaults;
37125 p->cleanup = mod_setenv_free;
37128 p->handle_request_done = mod_setenv_reset;
37135 --- ../lighttpd-1.4.11/src/mod_simple_vhost.c 2005-11-18 15:16:13.000000000 +0200
37136 +++ lighttpd-1.4.12/src/mod_simple_vhost.c 2006-07-16 00:26:04.000000000 +0300
37139 #include "plugin.h"
37141 +#include "sys-files.h"
37143 #ifdef HAVE_CONFIG_H
37144 #include "config.h"
37147 buffer *server_root;
37148 buffer *default_host;
37149 buffer *document_root;
37152 buffer *docroot_cache_key;
37153 buffer *docroot_cache_value;
37154 buffer *docroot_cache_servername;
37155 @@ -28,138 +30,138 @@
37164 plugin_config **config_storage;
37165 - plugin_config conf;
37166 + plugin_config conf;
37169 INIT_FUNC(mod_simple_vhost_init) {
37173 p = calloc(1, sizeof(*p));
37176 p->doc_root = buffer_init();
37182 FREE_FUNC(mod_simple_vhost_free) {
37183 plugin_data *p = p_d;
37188 if (!p) return HANDLER_GO_ON;
37191 if (p->config_storage) {
37193 for (i = 0; i < srv->config_context->used; i++) {
37194 plugin_config *s = p->config_storage[i];
37197 buffer_free(s->document_root);
37198 buffer_free(s->default_host);
37199 buffer_free(s->server_root);
37202 buffer_free(s->docroot_cache_key);
37203 buffer_free(s->docroot_cache_value);
37204 buffer_free(s->docroot_cache_servername);
37211 free(p->config_storage);
37215 buffer_free(p->doc_root);
37221 return HANDLER_GO_ON;
37224 SETDEFAULTS_FUNC(mod_simple_vhost_set_defaults) {
37225 plugin_data *p = p_d;
37228 - config_values_t cv[] = {
37230 + config_values_t cv[] = {
37231 { "simple-vhost.server-root", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
37232 { "simple-vhost.default-host", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
37233 { "simple-vhost.document-root", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
37234 { "simple-vhost.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
37235 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
37239 if (!p) return HANDLER_ERROR;
37242 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
37245 for (i = 0; i < srv->config_context->used; i++) {
37249 s = calloc(1, sizeof(plugin_config));
37252 s->server_root = buffer_init();
37253 s->default_host = buffer_init();
37254 s->document_root = buffer_init();
37257 s->docroot_cache_key = buffer_init();
37258 s->docroot_cache_value = buffer_init();
37259 s->docroot_cache_servername = buffer_init();
37264 cv[0].destination = s->server_root;
37265 cv[1].destination = s->default_host;
37266 cv[2].destination = s->document_root;
37267 cv[3].destination = &(s->debug);
37272 p->config_storage[i] = s;
37275 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
37276 return HANDLER_ERROR;
37281 return HANDLER_GO_ON;
37284 static int build_doc_root(server *srv, connection *con, plugin_data *p, buffer *out, buffer *host) {
37285 stat_cache_entry *sce = NULL;
37288 buffer_prepare_copy(out, 128);
37290 if (p->conf.server_root->used) {
37291 buffer_copy_string_buffer(out, p->conf.server_root);
37295 /* a hostname has to start with a alpha-numerical character
37296 * and must not contain a slash "/"
37300 - BUFFER_APPEND_SLASH(out);
37303 + PATHNAME_APPEND_SLASH(out);
37305 if (NULL == (dp = strchr(host->ptr, ':'))) {
37306 buffer_append_string_buffer(out, host);
37308 buffer_append_string_len(out, host->ptr, dp - host->ptr);
37311 - BUFFER_APPEND_SLASH(out);
37313 + PATHNAME_APPEND_SLASH(out);
37315 if (p->conf.document_root->used > 2 && p->conf.document_root->ptr[0] == '/') {
37316 buffer_append_string_len(out, p->conf.document_root->ptr + 1, p->conf.document_root->used - 2);
37318 buffer_append_string_buffer(out, p->conf.document_root);
37319 - BUFFER_APPEND_SLASH(out);
37320 + PATHNAME_APPEND_SLASH(out);
37323 buffer_copy_string_buffer(out, con->conf.document_root);
37324 - BUFFER_APPEND_SLASH(out);
37325 + PATHNAME_APPEND_SLASH(out);
37329 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, out, &sce)) {
37330 if (p->conf.debug) {
37331 log_error_write(srv, __FILE__, __LINE__, "sb",
37332 @@ -169,57 +171,53 @@
37333 } else if (!S_ISDIR(sce->st.st_mode)) {
37342 -#define PATCH(x) \
37343 - p->conf.x = s->x;
37344 static int mod_simple_vhost_patch_connection(server *srv, connection *con, plugin_data *p) {
37346 plugin_config *s = p->config_storage[0];
37348 - PATCH(server_root);
37349 - PATCH(default_host);
37350 - PATCH(document_root);
37352 - PATCH(docroot_cache_key);
37353 - PATCH(docroot_cache_value);
37354 - PATCH(docroot_cache_servername);
37358 + PATCH_OPTION(server_root);
37359 + PATCH_OPTION(default_host);
37360 + PATCH_OPTION(document_root);
37362 + PATCH_OPTION(docroot_cache_key);
37363 + PATCH_OPTION(docroot_cache_value);
37364 + PATCH_OPTION(docroot_cache_servername);
37366 + PATCH_OPTION(debug);
37368 /* skip the first, the global context */
37369 for (i = 1; i < srv->config_context->used; i++) {
37370 data_config *dc = (data_config *)srv->config_context->data[i];
37371 s = p->config_storage[i];
37374 /* condition didn't match */
37375 if (!config_check_cond(srv, con, dc)) continue;
37379 for (j = 0; j < dc->value->used; j++) {
37380 data_unset *du = dc->value->data[j];
37383 if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.server-root"))) {
37384 - PATCH(server_root);
37385 - PATCH(docroot_cache_key);
37386 - PATCH(docroot_cache_value);
37387 - PATCH(docroot_cache_servername);
37388 + PATCH_OPTION(server_root);
37389 + PATCH_OPTION(docroot_cache_key);
37390 + PATCH_OPTION(docroot_cache_value);
37391 + PATCH_OPTION(docroot_cache_servername);
37392 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.default-host"))) {
37393 - PATCH(default_host);
37394 + PATCH_OPTION(default_host);
37395 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.document-root"))) {
37396 - PATCH(document_root);
37397 + PATCH_OPTION(document_root);
37398 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.debug"))) {
37400 + PATCH_OPTION(debug);
37410 static handler_t mod_simple_vhost_docroot(server *srv, connection *con, void *p_data) {
37411 plugin_data *p = p_data;
37412 @@ -227,12 +225,12 @@
37414 * cache the last successfull translation from hostname (authority) to docroot
37415 * - this saves us a stat() call
37421 mod_simple_vhost_patch_connection(srv, con, p);
37423 - if (p->conf.docroot_cache_key->used &&
37425 + if (p->conf.docroot_cache_key->used &&
37426 con->uri.authority->used &&
37427 buffer_is_equal(p->conf.docroot_cache_key, con->uri.authority)) {
37429 @@ -243,8 +241,8 @@
37430 if ((con->uri.authority->used == 0) ||
37431 build_doc_root(srv, con, p, p->doc_root, con->uri.authority)) {
37432 /* not found, fallback the default-host */
37433 - if (build_doc_root(srv, con, p,
37435 + if (build_doc_root(srv, con, p,
37437 p->conf.default_host)) {
37438 return HANDLER_GO_ON;
37440 @@ -253,15 +251,15 @@
37442 buffer_copy_string_buffer(con->server_name, con->uri.authority);
37446 /* copy to cache */
37447 buffer_copy_string_buffer(p->conf.docroot_cache_key, con->uri.authority);
37448 buffer_copy_string_buffer(p->conf.docroot_cache_value, p->doc_root);
37449 buffer_copy_string_buffer(p->conf.docroot_cache_servername, con->server_name);
37452 buffer_copy_string_buffer(con->physical.doc_root, p->doc_root);
37456 return HANDLER_GO_ON;
37459 @@ -269,13 +267,13 @@
37460 int mod_simple_vhost_plugin_init(plugin *p) {
37461 p->version = LIGHTTPD_VERSION_ID;
37462 p->name = buffer_init_string("simple_vhost");
37465 p->init = mod_simple_vhost_init;
37466 p->set_defaults = mod_simple_vhost_set_defaults;
37467 p->handle_docroot = mod_simple_vhost_docroot;
37468 p->cleanup = mod_simple_vhost_free;
37476 --- ../lighttpd-1.4.11/src/mod_skeleton.c 2005-10-02 18:30:51.000000000 +0300
37477 +++ lighttpd-1.4.12/src/mod_skeleton.c 2006-07-16 00:26:03.000000000 +0300
37478 @@ -14,13 +14,13 @@
37481 * this is a skeleton for a lighttpd plugin
37484 * just replaces every occurance of 'skeleton' by your plugin name
37490 * :%s/skeleton/myhandler/
37496 @@ -33,12 +33,12 @@
37505 plugin_config **config_storage;
37507 - plugin_config conf;
37509 + plugin_config conf;
37513 @@ -47,36 +47,36 @@
37515 static handler_ctx * handler_ctx_init() {
37516 handler_ctx * hctx;
37519 hctx = calloc(1, sizeof(*hctx));
37525 static void handler_ctx_free(handler_ctx *hctx) {
37531 /* init the plugin data */
37532 INIT_FUNC(mod_skeleton_init) {
37536 p = calloc(1, sizeof(*p));
37539 p->match_buf = buffer_init();
37545 /* detroy the plugin data */
37546 FREE_FUNC(mod_skeleton_free) {
37547 plugin_data *p = p_d;
37552 if (!p) return HANDLER_GO_ON;
37555 if (p->config_storage) {
37558 @@ -84,18 +84,18 @@
37559 plugin_config *s = p->config_storage[i];
37564 array_free(s->match);
37569 free(p->config_storage);
37573 buffer_free(p->match_buf);
37579 return HANDLER_GO_ON;
37582 @@ -104,91 +104,88 @@
37583 SETDEFAULTS_FUNC(mod_skeleton_set_defaults) {
37584 plugin_data *p = p_d;
37587 - config_values_t cv[] = {
37589 + config_values_t cv[] = {
37590 { "skeleton.array", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
37591 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
37595 if (!p) return HANDLER_ERROR;
37598 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
37601 for (i = 0; i < srv->config_context->used; i++) {
37605 s = calloc(1, sizeof(plugin_config));
37606 s->match = array_init();
37609 cv[0].destination = s->match;
37612 p->config_storage[i] = s;
37615 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
37616 return HANDLER_ERROR;
37621 return HANDLER_GO_ON;
37624 -#define PATCH(x) \
37625 - p->conf.x = s->x;
37626 static int mod_skeleton_patch_connection(server *srv, connection *con, plugin_data *p) {
37628 plugin_config *s = p->config_storage[0];
37633 + PATCH_OPTION(match);
37635 /* skip the first, the global context */
37636 for (i = 1; i < srv->config_context->used; i++) {
37637 data_config *dc = (data_config *)srv->config_context->data[i];
37638 s = p->config_storage[i];
37641 /* condition didn't match */
37642 if (!config_check_cond(srv, con, dc)) continue;
37646 for (j = 0; j < dc->value->used; j++) {
37647 data_unset *du = dc->value->data[j];
37650 if (buffer_is_equal_string(du->key, CONST_STR_LEN("skeleton.array"))) {
37652 + PATCH_OPTION(match);
37662 URIHANDLER_FUNC(mod_skeleton_uri_handler) {
37663 plugin_data *p = p_d;
37670 if (con->uri.path->used == 0) return HANDLER_GO_ON;
37673 mod_skeleton_patch_connection(srv, con, p);
37675 s_len = con->uri.path->used - 1;
37678 for (k = 0; k < p->conf.match->used; k++) {
37679 data_string *ds = (data_string *)p->conf.match->data[k];
37680 int ct_len = ds->value->used - 1;
37683 if (ct_len > s_len) continue;
37684 if (ds->value->used == 0) continue;
37687 if (0 == strncmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
37688 con->http_status = 403;
37691 return HANDLER_FINISHED;
37697 return HANDLER_GO_ON;
37699 @@ -198,13 +195,13 @@
37700 int mod_skeleton_plugin_init(plugin *p) {
37701 p->version = LIGHTTPD_VERSION_ID;
37702 p->name = buffer_init_string("skeleton");
37705 p->init = mod_skeleton_init;
37706 p->handle_uri_clean = mod_skeleton_uri_handler;
37707 p->set_defaults = mod_skeleton_set_defaults;
37708 p->cleanup = mod_skeleton_free;
37716 --- ../lighttpd-1.4.11/src/mod_sql_vhost_core.c 1970-01-01 03:00:00.000000000 +0300
37717 +++ lighttpd-1.4.12/src/mod_sql_vhost_core.c 2006-07-20 00:57:20.000000000 +0300
37719 +#include <stdio.h>
37720 +#include <errno.h>
37721 +#include <fcntl.h>
37722 +#include <string.h>
37724 +#ifdef HAVE_CONFIG_H
37725 +#include "config.h"
37728 +#include "plugin.h"
37731 +#include "stat_cache.h"
37733 +#include "mod_sql_vhost_core.h"
37735 +#define plugin_data mod_sql_vhost_core_plugin_data
37736 +#define plugin_config mod_sql_vhost_core_plugin_config
37738 +/* init the plugin data */
37739 +INIT_FUNC(mod_sql_vhost_core_init) {
37742 + p = calloc(1, sizeof(*p));
37744 + p->docroot = buffer_init();
37745 + p->host = buffer_init();
37750 +/* cleanup the plugin data */
37751 +SERVER_FUNC(mod_sql_vhost_core_cleanup) {
37752 + plugin_data *p = p_d;
37756 + if (!p) return HANDLER_GO_ON;
37758 + if (p->config_storage) {
37760 + for (i = 0; i < srv->config_context->used; i++) {
37761 + plugin_config *s = p->config_storage[i];
37763 + if (!s) continue;
37765 + buffer_free(s->db);
37766 + buffer_free(s->user);
37767 + buffer_free(s->pass);
37768 + buffer_free(s->sock);
37769 + buffer_free(s->backend);
37770 + buffer_free(s->hostname);
37771 + buffer_free(s->select_vhost);
37775 + free(p->config_storage);
37777 + buffer_free(p->docroot);
37778 + buffer_free(p->host);
37782 + return HANDLER_GO_ON;
37785 +/* set configuration values */
37786 +SERVER_FUNC(mod_sql_vhost_core_set_defaults) {
37787 + plugin_data *p = p_d;
37791 + config_values_t cv[] = {
37792 + { "sql-vhost.db", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 0 * e.g. vhost */
37793 + { "sql-vhost.user", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 1 * lighty */
37794 + { "sql-vhost.pass", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 2 * secrect */
37795 + { "sql-vhost.sock", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 3 * /tmp/mysql.sock */
37796 + { "sql-vhost.select-vhost", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 4 * SELECT ... FROM hosts WHERE hostname = ? */
37797 + { "sql-vhost.hostname", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 5 * 127.0.0.1 */
37798 + { "sql-vhost.port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, /* 6 * 3306 */
37799 + { "sql-vhost.backend", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 7 * mysql */
37801 + /* backward compat */
37802 + { "mysql-vhost.db", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 8 == 0 */
37803 + { "mysql-vhost.user", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 9 == 1 */
37804 + { "mysql-vhost.pass", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 10 == 2 */
37805 + { "mysql-vhost.sock", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 11 == 3 */
37806 + { "mysql-vhost.sql", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 12 == 4 */
37807 + { "mysql-vhost.hostname", NULL, T_CONFIG_STRING,T_CONFIG_SCOPE_SERVER }, /* 13 == 5 */
37808 + { "mysql-vhost.port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, /* 14 == 6 */
37810 + { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
37813 + p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
37815 + for (i = 0; i < srv->config_context->used; i++) {
37816 + plugin_config *s;
37818 + s = calloc(1, sizeof(plugin_config));
37819 + s->db = buffer_init();
37820 + s->user = buffer_init();
37821 + s->pass = buffer_init();
37822 + s->sock = buffer_init();
37823 + s->hostname = buffer_init();
37824 + s->backend = buffer_init();
37825 + s->port = 0; /* default port for mysql */
37826 + s->select_vhost = buffer_init();
37827 + s->backend_data = NULL;
37829 + cv[0].destination = s->db;
37830 + cv[1].destination = s->user;
37831 + cv[2].destination = s->pass;
37832 + cv[3].destination = s->sock;
37833 + cv[4].destination = s->select_vhost;
37834 + cv[5].destination = s->hostname;
37835 + cv[6].destination = &(s->port);
37836 + cv[7].destination = s->backend;
37838 + /* backend compat */
37839 + cv[8].destination = cv[0].destination;
37840 + cv[9].destination = cv[1].destination;
37841 + cv[10].destination = cv[2].destination;
37842 + cv[11].destination = cv[3].destination;
37843 + cv[12].destination = cv[4].destination;
37844 + cv[13].destination = cv[5].destination;
37845 + cv[14].destination = cv[6].destination;
37847 + p->config_storage[i] = s;
37849 + if (config_insert_values_global(srv,
37850 + ((data_config *)srv->config_context->data[i])->value,
37851 + cv)) return HANDLER_ERROR;
37853 + /* we only parse the config, the backend plugin will patch itself into the plugin-struct */
37856 + return HANDLER_GO_ON;
37859 +static int mod_sql_vhost_core_patch_connection(server *srv, connection *con, plugin_data *p) {
37861 + plugin_config *s = p->config_storage[0];
37863 + PATCH_OPTION(backend_data);
37864 + PATCH_OPTION(get_vhost);
37866 + /* skip the first, the global context */
37867 + for (i = 1; i < srv->config_context->used; i++) {
37868 + data_config *dc = (data_config *)srv->config_context->data[i];
37869 + s = p->config_storage[i];
37871 + /* condition didn't match */
37872 + if (!config_check_cond(srv, con, dc)) continue;
37874 + if (s->backend_data) {
37875 + PATCH_OPTION(backend_data);
37876 + PATCH_OPTION(get_vhost);
37883 +/* handle document root request */
37884 +CONNECTION_FUNC(mod_sql_vhost_core_handle_docroot) {
37885 + plugin_data *p = p_d;
37886 + stat_cache_entry *sce;
37888 + /* no host specified? */
37889 + if (!con->uri.authority->used) return HANDLER_GO_ON;
37891 + mod_sql_vhost_core_patch_connection(srv, con, p);
37893 + /* do we have backend ? */
37894 + if (!p->conf.get_vhost) return HANDLER_GO_ON;
37896 + /* ask the backend for the data */
37897 + if (0 != p->conf.get_vhost(srv, con, p->conf.backend_data, p->docroot, p->host)) {
37898 + return HANDLER_GO_ON;
37901 + if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->docroot, &sce)) {
37902 + log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), p->docroot);
37903 + return HANDLER_GO_ON;
37905 + if (!S_ISDIR(sce->st.st_mode)) {
37906 + log_error_write(srv, __FILE__, __LINE__, "sb", "Not a directory", p->docroot);
37907 + return HANDLER_GO_ON;
37910 + buffer_copy_string_buffer(con->server_name, p->host);
37911 + buffer_copy_string_buffer(con->physical.doc_root, p->docroot);
37913 + return HANDLER_GO_ON;
37916 +/* this function is called at dlopen() time and inits the callbacks */
37917 +int mod_sql_vhost_core_plugin_init(plugin *p) {
37918 + p->version = LIGHTTPD_VERSION_ID;
37919 + p->name = buffer_init_string("mod_sql_vhost_core");
37921 + p->init = mod_sql_vhost_core_init;
37922 + p->cleanup = mod_sql_vhost_core_cleanup;
37924 + p->set_defaults = mod_sql_vhost_core_set_defaults;
37925 + p->handle_docroot = mod_sql_vhost_core_handle_docroot;
37930 --- ../lighttpd-1.4.11/src/mod_sql_vhost_core.h 1970-01-01 03:00:00.000000000 +0300
37931 +++ lighttpd-1.4.12/src/mod_sql_vhost_core.h 2006-07-16 00:26:04.000000000 +0300
37933 +#ifndef _MOD_SQL_VHOST_CORE_H_
37934 +#define _MOD_SQL_VHOST_CORE_H_
37936 +#include "buffer.h"
37937 +#include "plugin.h"
37939 +#define SQLVHOST_BACKEND_GETVHOST_PARAMS \
37940 + (server *srv, connection *con, void *p_d, buffer *docroot, buffer *host)
37942 +#define SQLVHOST_BACKEND_GETVHOST_RETVAL handler_t
37944 +#define SQLVHOST_BACKEND_GETVHOST(name) \
37945 + SQLVHOST_BACKEND_GETVHOST_RETVAL name SQLVHOST_BACKEND_GETVHOST_PARAMS
37947 +#define SQLVHOST_BACKEND_GETVHOST_PTR(name) \
37948 + SQLVHOST_BACKEND_GETVHOST_RETVAL (* name)SQLVHOST_BACKEND_GETVHOST_PARAMS
37956 + buffer *hostname;
37957 + unsigned short port;
37960 + void *backend_data;
37962 + buffer *select_vhost;
37964 + SQLVHOST_BACKEND_GETVHOST_PTR(get_vhost);
37965 +} mod_sql_vhost_core_plugin_config;
37967 +/* global plugin data */
37974 + mod_sql_vhost_core_plugin_config **config_storage;
37976 + mod_sql_vhost_core_plugin_config conf;
37977 +} mod_sql_vhost_core_plugin_data;
37982 --- ../lighttpd-1.4.11/src/mod_ssi.c 2006-03-04 17:09:48.000000000 +0200
37983 +++ lighttpd-1.4.12/src/mod_ssi.c 2006-07-16 00:26:04.000000000 +0300
37985 #include <string.h>
37988 -#include <unistd.h>
37993 #include "inet_ntop_cache.h"
37995 #include "sys-socket.h"
37996 +#include "sys-strings.h"
37997 +#include "sys-files.h"
38001 @@ -39,15 +40,15 @@
38002 /* init the plugin data */
38003 INIT_FUNC(mod_ssi_init) {
38007 p = calloc(1, sizeof(*p));
38010 p->timefmt = buffer_init();
38011 p->stat_fn = buffer_init();
38014 p->ssi_vars = array_init();
38015 p->ssi_cgi_env = array_init();
38021 @@ -55,21 +56,21 @@
38022 FREE_FUNC(mod_ssi_free) {
38023 plugin_data *p = p_d;
38027 if (!p) return HANDLER_GO_ON;
38030 if (p->config_storage) {
38032 for (i = 0; i < srv->config_context->used; i++) {
38033 plugin_config *s = p->config_storage[i];
38036 array_free(s->ssi_extension);
38041 free(p->config_storage);
38045 array_free(p->ssi_vars);
38046 array_free(p->ssi_cgi_env);
38050 buffer_free(p->timefmt);
38051 buffer_free(p->stat_fn);
38057 return HANDLER_GO_ON;
38060 @@ -92,36 +93,36 @@
38061 const char *errptr;
38065 - config_values_t cv[] = {
38067 + config_values_t cv[] = {
38068 { "ssi.extension", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
38069 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
38073 if (!p) return HANDLER_ERROR;
38076 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
38079 for (i = 0; i < srv->config_context->used; i++) {
38083 s = calloc(1, sizeof(plugin_config));
38084 s->ssi_extension = array_init();
38087 cv[0].destination = s->ssi_extension;
38090 p->config_storage[i] = s;
38093 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
38094 return HANDLER_ERROR;
38100 /* allow 2 params */
38101 if (NULL == (p->ssi_regex = pcre_compile("<!--#([a-z]+)\\s+(?:([a-z]+)=\"(.*?)(?<!\\\\)\"\\s*)?(?:([a-z]+)=\"(.*?)(?<!\\\\)\"\\s*)?-->", 0, &errptr, &erroff, NULL))) {
38102 log_error_write(srv, __FILE__, __LINE__, "sds",
38106 return HANDLER_ERROR;
38108 @@ -130,52 +131,52 @@
38109 "mod_ssi: pcre support is missing, please recompile with pcre support or remove mod_ssi from the list of modules");
38110 return HANDLER_ERROR;
38114 return HANDLER_GO_ON;
38117 int ssi_env_add(array *env, const char *key, const char *val) {
38121 if (NULL == (ds = (data_string *)array_get_unused_element(env, TYPE_STRING))) {
38122 ds = data_string_init();
38124 buffer_copy_string(ds->key, key);
38125 buffer_copy_string(ds->value, val);
38128 array_insert_unique(env, (data_unset *)ds);
38136 * the next two functions are take from fcgi.c
38141 static int ssi_env_add_request_headers(server *srv, connection *con, plugin_data *p) {
38145 for (i = 0; i < con->request.headers->used; i++) {
38149 ds = (data_string *)con->request.headers->data[i];
38152 if (ds->value->used && ds->key->used) {
38154 buffer_reset(srv->tmp_buf);
38157 /* don't forward the Authorization: Header */
38158 if (0 == strcasecmp(ds->key->ptr, "AUTHORIZATION")) {
38163 if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
38164 buffer_copy_string(srv->tmp_buf, "HTTP_");
38165 srv->tmp_buf->used--;
38169 buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
38170 for (j = 0; j < ds->key->used - 1; j++) {
38172 @@ -189,33 +190,33 @@
38173 srv->tmp_buf->ptr[srv->tmp_buf->used++] = c;
38175 srv->tmp_buf->ptr[srv->tmp_buf->used] = '\0';
38178 ssi_env_add(p->ssi_cgi_env, srv->tmp_buf->ptr, ds->value->ptr);
38186 static int build_ssi_cgi_vars(server *srv, connection *con, plugin_data *p) {
38190 server_socket *srv_sock = con->srv_socket;
38194 char b2[INET6_ADDRSTRLEN + 1];
38197 #define CONST_STRING(x) \
38201 array_reset(p->ssi_cgi_env);
38204 ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_SOFTWARE"), PACKAGE_NAME"/"PACKAGE_VERSION);
38205 ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_NAME"),
38207 - inet_ntop(srv_sock->addr.plain.sa_family,
38208 - srv_sock->addr.plain.sa_family == AF_INET6 ?
38209 + inet_ntop(srv_sock->addr.plain.sa_family,
38210 + srv_sock->addr.plain.sa_family == AF_INET6 ?
38211 (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
38212 (const void *) &(srv_sock->addr.ipv4.sin_addr),
38214 @@ -224,28 +225,28 @@
38217 ssi_env_add(p->ssi_cgi_env, CONST_STRING("GATEWAY_INTERFACE"), "CGI/1.1");
38223 ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
38225 ntohs(srv_sock->addr.ipv4.sin_port)
38230 ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_PORT"), buf);
38233 ssi_env_add(p->ssi_cgi_env, CONST_STRING("REMOTE_ADDR"),
38234 inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
38237 if (con->authed_user->used) {
38238 ssi_env_add(p->ssi_cgi_env, CONST_STRING("REMOTE_USER"),
38239 con->authed_user->ptr);
38243 if (con->request.content_length > 0) {
38244 /* CGI-SPEC 6.1.2 and FastCGI spec 6.3 */
38247 /* request.content_length < SSIZE_MAX, see request.c */
38248 ltostr(buf, con->request.content_length);
38249 ssi_env_add(p->ssi_cgi_env, CONST_STRING("CONTENT_LENGTH"), buf);
38250 @@ -271,30 +272,30 @@
38251 if (con->request.pathinfo->used) {
38252 ssi_env_add(p->ssi_cgi_env, CONST_STRING("PATH_INFO"), con->request.pathinfo->ptr);
38256 ssi_env_add(p->ssi_cgi_env, CONST_STRING("SCRIPT_FILENAME"), con->physical.path->ptr);
38257 ssi_env_add(p->ssi_cgi_env, CONST_STRING("DOCUMENT_ROOT"), con->physical.doc_root->ptr);
38260 ssi_env_add(p->ssi_cgi_env, CONST_STRING("REQUEST_URI"), con->request.uri->ptr);
38261 ssi_env_add(p->ssi_cgi_env, CONST_STRING("QUERY_STRING"), con->uri.query->used ? con->uri.query->ptr : "");
38262 ssi_env_add(p->ssi_cgi_env, CONST_STRING("REQUEST_METHOD"), get_http_method_name(con->request.http_method));
38263 ssi_env_add(p->ssi_cgi_env, CONST_STRING("REDIRECT_STATUS"), "200");
38264 ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_PROTOCOL"), get_http_version_name(con->request.http_version));
38267 ssi_env_add_request_headers(srv, con, p);
38273 -static int process_ssi_stmt(server *srv, connection *con, plugin_data *p,
38274 +static int process_ssi_stmt(server *srv, connection *con, plugin_data *p,
38275 const char **l, size_t n) {
38276 size_t i, ssicmd = 0;
38284 - enum { SSI_UNSET, SSI_ECHO, SSI_FSIZE, SSI_INCLUDE, SSI_FLASTMOD,
38285 + enum { SSI_UNSET, SSI_ECHO, SSI_FSIZE, SSI_INCLUDE, SSI_FLASTMOD,
38286 SSI_CONFIG, SSI_PRINTENV, SSI_SET, SSI_IF, SSI_ELIF,
38287 SSI_ELSE, SSI_ENDIF, SSI_EXEC } type;
38289 @@ -310,27 +311,27 @@
38290 { "endif", SSI_ENDIF },
38291 { "else", SSI_ELSE },
38292 { "exec", SSI_EXEC },
38295 { NULL, SSI_UNSET }
38299 for (i = 0; ssicmds[i].var; i++) {
38300 if (0 == strcmp(l[1], ssicmds[i].var)) {
38301 ssicmd = ssicmds[i].type;
38310 int var = 0, enc = 0;
38311 const char *var_val = NULL;
38312 stat_cache_entry *sce = NULL;
38318 - enum { SSI_ECHO_UNSET, SSI_ECHO_DATE_GMT, SSI_ECHO_DATE_LOCAL, SSI_ECHO_DOCUMENT_NAME, SSI_ECHO_DOCUMENT_URI,
38319 + enum { SSI_ECHO_UNSET, SSI_ECHO_DATE_GMT, SSI_ECHO_DATE_LOCAL, SSI_ECHO_DOCUMENT_NAME, SSI_ECHO_DOCUMENT_URI,
38320 SSI_ECHO_LAST_MODIFIED, SSI_ECHO_USER_NAME } type;
38322 { "DATE_GMT", SSI_ECHO_DATE_GMT },
38323 @@ -339,27 +340,27 @@
38324 { "DOCUMENT_URI", SSI_ECHO_DOCUMENT_URI },
38325 { "LAST_MODIFIED", SSI_ECHO_LAST_MODIFIED },
38326 { "USER_NAME", SSI_ECHO_USER_NAME },
38329 { NULL, SSI_ECHO_UNSET }
38336 enum { SSI_ENC_UNSET, SSI_ENC_URL, SSI_ENC_NONE, SSI_ENC_ENTITY } type;
38338 { "url", SSI_ENC_URL },
38339 { "none", SSI_ENC_NONE },
38340 { "entity", SSI_ENC_ENTITY },
38343 { NULL, SSI_ENC_UNSET }
38347 for (i = 2; i < n; i += 2) {
38348 if (0 == strcmp(l[i], "var")) {
38355 for (j = 0; echovars[j].var; j++) {
38356 if (0 == strcmp(l[i+1], echovars[j].var)) {
38357 var = echovars[j].type;
38358 @@ -368,7 +369,7 @@
38360 } else if (0 == strcmp(l[i], "encoding")) {
38364 for (j = 0; encvars[j].var; j++) {
38365 if (0 == strcmp(l[i+1], encvars[j].var)) {
38366 enc = encvars[j].type;
38367 @@ -377,26 +378,26 @@
38370 log_error_write(srv, __FILE__, __LINE__, "sss",
38371 - "ssi: unknow attribute for ",
38372 + "ssi: unknow attribute for ",
38378 if (p->if_is_false) break;
38382 log_error_write(srv, __FILE__, __LINE__, "sss",
38385 l[1], "var is missing");
38389 stat_cache_get_entry(srv, con, con->physical.path, &sce);
38393 case SSI_ECHO_USER_NAME: {
38397 b = chunkqueue_get_append_buffer(con->write_queue);
38399 if (NULL == (pw = getpwuid(sce->st.st_uid))) {
38400 @@ -411,7 +412,7 @@
38402 case SSI_ECHO_LAST_MODIFIED: {
38403 time_t t = sce->st.st_mtime;
38406 b = chunkqueue_get_append_buffer(con->write_queue);
38407 if (0 == strftime(buf, sizeof(buf), p->timefmt->ptr, localtime(&t))) {
38408 buffer_copy_string(b, "(none)");
38409 @@ -422,7 +423,7 @@
38411 case SSI_ECHO_DATE_LOCAL: {
38412 time_t t = time(NULL);
38415 b = chunkqueue_get_append_buffer(con->write_queue);
38416 if (0 == strftime(buf, sizeof(buf), p->timefmt->ptr, localtime(&t))) {
38417 buffer_copy_string(b, "(none)");
38418 @@ -433,7 +434,7 @@
38420 case SSI_ECHO_DATE_GMT: {
38421 time_t t = time(NULL);
38424 b = chunkqueue_get_append_buffer(con->write_queue);
38425 if (0 == strftime(buf, sizeof(buf), p->timefmt->ptr, gmtime(&t))) {
38426 buffer_copy_string(b, "(none)");
38427 @@ -444,7 +445,7 @@
38429 case SSI_ECHO_DOCUMENT_NAME: {
38433 b = chunkqueue_get_append_buffer(con->write_queue);
38434 if (NULL == (sl = strrchr(con->physical.path->ptr, '/'))) {
38435 buffer_copy_string_buffer(b, con->physical.path);
38436 @@ -461,15 +462,15 @@
38439 /* check if it is a cgi-var */
38442 b = chunkqueue_get_append_buffer(con->write_queue);
38445 if (NULL != (ds = (data_string *)array_get_element(p->ssi_cgi_env, var_val))) {
38446 buffer_copy_string_buffer(b, ds->value);
38448 buffer_copy_string(b, "(none)");
38455 @@ -481,7 +482,7 @@
38456 const char * file_path = NULL, *virt_path = NULL;
38461 for (i = 2; i < n; i += 2) {
38462 if (0 == strcmp(l[i], "file")) {
38463 file_path = l[i+1];
38464 @@ -489,28 +490,28 @@
38465 virt_path = l[i+1];
38467 log_error_write(srv, __FILE__, __LINE__, "sss",
38468 - "ssi: unknow attribute for ",
38469 + "ssi: unknow attribute for ",
38475 if (!file_path && !virt_path) {
38476 log_error_write(srv, __FILE__, __LINE__, "sss",
38479 l[1], "file or virtual are missing");
38484 if (file_path && virt_path) {
38485 log_error_write(srv, __FILE__, __LINE__, "sss",
38488 l[1], "only one of file and virtual is allowed here");
38495 if (p->if_is_false) break;
38499 /* current doc-root */
38500 if (NULL == (sl = strrchr(con->physical.path->ptr, '/'))) {
38501 @@ -519,46 +520,46 @@
38502 buffer_copy_string_len(p->stat_fn, con->physical.path->ptr, sl - con->physical.path->ptr + 1);
38505 - buffer_copy_string(srv->tmp_buf, file_path);
38506 + buffer_copy_string(srv->tmp_buf, file_path);
38507 buffer_urldecode_path(srv->tmp_buf);
38508 - buffer_path_simplify(srv->tmp_buf, srv->tmp_buf);
38509 - buffer_append_string_buffer(p->stat_fn, srv->tmp_buf);
38510 + buffer_path_simplify(srv->tmp_buf, srv->tmp_buf);
38511 + buffer_append_string_buffer(p->stat_fn, srv->tmp_buf);
38516 if (virt_path[0] == '/') {
38517 buffer_copy_string(p->stat_fn, virt_path);
38519 /* there is always a / */
38520 sl = strrchr(con->uri.path->ptr, '/');
38523 buffer_copy_string_len(p->stat_fn, con->uri.path->ptr, sl - con->uri.path->ptr + 1);
38524 buffer_append_string(p->stat_fn, virt_path);
38528 buffer_urldecode_path(p->stat_fn);
38529 buffer_path_simplify(srv->tmp_buf, p->stat_fn);
38532 /* we have an uri */
38535 buffer_copy_string_buffer(p->stat_fn, con->physical.doc_root);
38536 buffer_append_string_buffer(p->stat_fn, srv->tmp_buf);
38540 if (0 == stat(p->stat_fn->ptr, &st)) {
38541 time_t t = st.st_mtime;
38546 b = chunkqueue_get_append_buffer(con->write_queue);
38549 const char *abr[] = { " B", " kB", " MB", " GB", " TB", NULL };
38552 off_t s = st.st_size;
38555 for (j = 0; s > 1024 && abr[j+1]; s /= 1024, j++);
38558 buffer_copy_off_t(b, s);
38559 buffer_append_string(b, abr[j]);
38561 @@ -579,7 +580,7 @@
38564 log_error_write(srv, __FILE__, __LINE__, "sbs",
38565 - "ssi: stating failed ",
38566 + "ssi: stating failed ",
38567 p->stat_fn, strerror(errno));
38570 @@ -593,33 +594,33 @@
38573 log_error_write(srv, __FILE__, __LINE__, "sss",
38574 - "ssi: unknow attribute for ",
38575 + "ssi: unknow attribute for ",
38581 if (p->if_is_false) break;
38588 if (NULL == (ds = (data_string *)array_get_unused_element(p->ssi_vars, TYPE_STRING))) {
38589 ds = data_string_init();
38591 buffer_copy_string(ds->key, key);
38592 buffer_copy_string(ds->value, val);
38595 array_insert_unique(p->ssi_vars, (data_unset *)ds);
38597 log_error_write(srv, __FILE__, __LINE__, "sss",
38598 - "ssi: var and value have to be set in",
38599 + "ssi: var and value have to be set in",
38606 if (p->if_is_false) break;
38609 for (i = 2; i < n; i += 2) {
38610 if (0 == strcmp(l[i], "timefmt")) {
38611 buffer_copy_string(p->timefmt, l[i+1]);
38612 @@ -632,63 +633,65 @@
38613 log_error_write(srv, __FILE__, __LINE__, "sssss",
38614 "ssi: unknow value for attribute '",
38621 log_error_write(srv, __FILE__, __LINE__, "sss",
38622 - "ssi: unknow attribute for ",
38623 + "ssi: unknow attribute for ",
38629 if (p->if_is_false) break;
38632 b = chunkqueue_get_append_buffer(con->write_queue);
38633 buffer_copy_string(b, "<pre>");
38634 for (i = 0; i < p->ssi_vars->used; i++) {
38635 data_string *ds = (data_string *)p->ssi_vars->data[p->ssi_vars->sorted[i]];
38638 buffer_append_string_buffer(b, ds->key);
38639 buffer_append_string(b, ": ");
38640 buffer_append_string_buffer(b, ds->value);
38641 buffer_append_string(b, "<br />");
38645 buffer_append_string(b, "</pre>");
38652 const char *cmd = NULL;
38654 int from_exec_fds[2];
38657 for (i = 2; i < n; i += 2) {
38658 if (0 == strcmp(l[i], "cmd")) {
38661 log_error_write(srv, __FILE__, __LINE__, "sss",
38662 - "ssi: unknow attribute for ",
38663 + "ssi: unknow attribute for ",
38669 if (p->if_is_false) break;
38672 /* create a return pipe and send output to the html-page
38674 - * as exec is assumed evil it is implemented synchronously
38676 + * as exec is assumed evil it is implemented synchronously
38683 if (pipe(from_exec_fds)) {
38684 - log_error_write(srv, __FILE__, __LINE__, "ss",
38685 + log_error_write(srv, __FILE__, __LINE__, "ss",
38686 "pipe failed: ", strerror(errno));
38692 switch (pid = fork()) {
38694 @@ -698,14 +701,14 @@
38695 close(from_exec_fds[1]);
38697 close(from_exec_fds[0]);
38701 close(STDIN_FILENO);
38704 execl("/bin/sh", "sh", "-c", cmd, NULL);
38707 log_error_write(srv, __FILE__, __LINE__, "sss", "spawing exec failed:", strerror(errno), cmd);
38713 @@ -718,9 +721,9 @@
38719 close(from_exec_fds[1]);
38722 /* wait for the client to end */
38723 if (-1 == waitpid(pid, &status, 0)) {
38724 log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed:", strerror(errno));
38725 @@ -730,7 +733,7 @@
38728 if (ioctl(from_exec_fds[0], FIONREAD, &toread)) {
38729 - log_error_write(srv, __FILE__, __LINE__, "s",
38730 + log_error_write(srv, __FILE__, __LINE__, "s",
38731 "unexpected end-of-file (perhaps the ssi-exec process died)");
38734 @@ -738,10 +741,10 @@
38736 b = chunkqueue_get_append_buffer(con->write_queue);
38738 - buffer_prepare_copy(b, toread + 1);
38739 + buffer_prepare_copy(b, toread + 1);
38741 if ((r = read(from_exec_fds[0], b->ptr, b->size - 1)) < 0) {
38742 - /* read failed */
38743 + /* read failed */
38747 @@ -755,59 +758,58 @@
38748 log_error_write(srv, __FILE__, __LINE__, "s", "process exited abnormally");
38750 close(from_exec_fds[0]);
38765 const char *expr = NULL;
38768 for (i = 2; i < n; i += 2) {
38769 if (0 == strcmp(l[i], "expr")) {
38772 log_error_write(srv, __FILE__, __LINE__, "sss",
38773 - "ssi: unknow attribute for ",
38774 + "ssi: unknow attribute for ",
38781 log_error_write(srv, __FILE__, __LINE__, "sss",
38784 l[1], "expr missing");
38789 if ((!p->if_is_false) &&
38790 - ((p->if_is_false_level == 0) ||
38791 + ((p->if_is_false_level == 0) ||
38792 (p->if_level < p->if_is_false_level))) {
38793 switch (ssi_eval_expr(srv, con, p, expr)) {
38796 - p->if_is_false = 1;
38798 + p->if_is_false = 1;
38799 p->if_is_false_level = p->if_level;
38802 - p->if_is_false = 0;
38804 + p->if_is_false = 0;
38819 if (p->if_is_false) {
38820 if ((p->if_level == p->if_is_false_level) &&
38821 (p->if_is_false_endif == 0)) {
38822 @@ -815,11 +817,11 @@
38825 p->if_is_false = 1;
38828 p->if_is_false_level = p->if_level;
38835 const char *expr = NULL;
38836 @@ -828,52 +830,52 @@
38839 log_error_write(srv, __FILE__, __LINE__, "sss",
38840 - "ssi: unknow attribute for ",
38841 + "ssi: unknow attribute for ",
38848 log_error_write(srv, __FILE__, __LINE__, "sss",
38851 l[1], "expr missing");
38859 if (p->if_level == p->if_is_false_level) {
38860 if ((p->if_is_false) &&
38861 (p->if_is_false_endif == 0)) {
38862 switch (ssi_eval_expr(srv, con, p, expr)) {
38865 - p->if_is_false = 1;
38867 + p->if_is_false = 1;
38868 p->if_is_false_level = p->if_level;
38871 - p->if_is_false = 0;
38873 + p->if_is_false = 0;
38877 - p->if_is_false = 1;
38878 + p->if_is_false = 1;
38879 p->if_is_false_level = p->if_level;
38880 p->if_is_false_endif = 1;
38894 if (p->if_level == p->if_is_false_level) {
38895 p->if_is_false = 0;
38896 p->if_is_false_endif = 0;
38902 log_error_write(srv, __FILE__, __LINE__, "ss",
38903 @@ -881,41 +883,41 @@
38914 static int mod_ssi_handle_request(server *srv, connection *con, plugin_data *p) {
38925 /* get a stream to the file */
38928 array_reset(p->ssi_vars);
38929 array_reset(p->ssi_cgi_env);
38930 buffer_copy_string(p->timefmt, "%a, %d %b %Y %H:%M:%S %Z");
38932 build_ssi_cgi_vars(srv, con, p);
38933 p->if_is_false = 0;
38936 if (-1 == stream_open(&s, con->physical.path)) {
38937 log_error_write(srv, __FILE__, __LINE__, "sb",
38938 "stream-open: ", con->physical.path);
38946 - * <!--#element attribute=value attribute=value ... -->
38948 + * <!--#element attribute=value attribute=value ... -->
38951 - * errmsg -- missing
38952 + * errmsg -- missing
38956 @@ -937,13 +939,13 @@
38973 @@ -951,118 +953,115 @@
38985 - * The current date in Greenwich Mean Time.
38987 - * The current date in the local time zone.
38989 - * The filename (excluding directories) of the document requested by the user.
38991 - * 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.
38993 - * The last modification date of the document requested by the user.
38996 + * The current date in Greenwich Mean Time.
38998 + * The current date in the local time zone.
39000 + * The filename (excluding directories) of the document requested by the user.
39002 + * 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.
39004 + * The last modification date of the document requested by the user.
39006 * Contains the owner of the file which included it.
39010 -#ifdef HAVE_PCRE_H
39011 +#ifdef HAVE_PCRE_H
39012 for (i = 0; (n = pcre_exec(p->ssi_regex, NULL, s.start, s.size, i, 0, ovec, N * 3)) > 0; i = ovec[1]) {
39014 /* take everything from last offset to current match pos */
39017 if (!p->if_is_false) chunkqueue_append_file(con->write_queue, con->physical.path, i, ovec[0] - i);
39020 pcre_get_substring_list(s.start, ovec, n, &l);
39021 process_ssi_stmt(srv, con, p, l, n);
39022 pcre_free_substring_list(l);
39027 case PCRE_ERROR_NOMATCH:
39028 /* copy everything/the rest */
39029 chunkqueue_append_file(con->write_queue, con->physical.path, i, s.size - i);
39034 log_error_write(srv, __FILE__, __LINE__, "sd",
39035 "execution error while matching: ", n);
39047 con->file_started = 1;
39048 con->file_finished = 1;
39051 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
39054 /* reset physical.path */
39055 buffer_reset(con->physical.path);
39061 -#define PATCH(x) \
39062 - p->conf.x = s->x;
39063 static int mod_ssi_patch_connection(server *srv, connection *con, plugin_data *p) {
39065 plugin_config *s = p->config_storage[0];
39067 - PATCH(ssi_extension);
39070 + PATCH_OPTION(ssi_extension);
39072 /* skip the first, the global context */
39073 for (i = 1; i < srv->config_context->used; i++) {
39074 data_config *dc = (data_config *)srv->config_context->data[i];
39075 s = p->config_storage[i];
39078 /* condition didn't match */
39079 if (!config_check_cond(srv, con, dc)) continue;
39083 for (j = 0; j < dc->value->used; j++) {
39084 data_unset *du = dc->value->data[j];
39087 if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssi.extension"))) {
39088 - PATCH(ssi_extension);
39089 + PATCH_OPTION(ssi_extension);
39099 URIHANDLER_FUNC(mod_ssi_physical_path) {
39100 plugin_data *p = p_d;
39104 if (con->physical.path->used == 0) return HANDLER_GO_ON;
39107 mod_ssi_patch_connection(srv, con, p);
39110 for (k = 0; k < p->conf.ssi_extension->used; k++) {
39111 data_string *ds = (data_string *)p->conf.ssi_extension->data[k];
39114 if (ds->value->used == 0) continue;
39117 if (buffer_is_equal_right_len(con->physical.path, ds->value, ds->value->used - 1)) {
39118 /* handle ssi-request */
39121 if (mod_ssi_handle_request(srv, con, p)) {
39123 con->http_status = 500;
39127 return HANDLER_FINISHED;
39133 return HANDLER_GO_ON;
39135 @@ -1072,13 +1071,13 @@
39136 int mod_ssi_plugin_init(plugin *p) {
39137 p->version = LIGHTTPD_VERSION_ID;
39138 p->name = buffer_init_string("ssi");
39141 p->init = mod_ssi_init;
39142 p->handle_subrequest_start = mod_ssi_physical_path;
39143 p->set_defaults = mod_ssi_set_defaults;
39144 p->cleanup = mod_ssi_free;
39152 --- ../lighttpd-1.4.11/src/mod_ssi.h 2005-08-11 01:26:39.000000000 +0300
39153 +++ lighttpd-1.4.12/src/mod_ssi.h 2006-07-16 00:26:04.000000000 +0300
39154 @@ -19,23 +19,23 @@
39159 -#ifdef HAVE_PCRE_H
39161 +#ifdef HAVE_PCRE_H
39173 array *ssi_cgi_env;
39176 int if_level, if_is_false_level, if_is_false, if_is_false_endif;
39179 plugin_config **config_storage;
39181 - plugin_config conf;
39183 + plugin_config conf;
39186 int ssi_eval_expr(server *srv, connection *con, plugin_data *p, const char *expr);
39187 --- ../lighttpd-1.4.11/src/mod_ssi_expr.c 2005-08-11 01:26:48.000000000 +0300
39188 +++ lighttpd-1.4.12/src/mod_ssi_expr.c 2006-07-16 00:26:04.000000000 +0300
39201 @@ -21,15 +21,15 @@
39203 ssi_val_t *ssi_val_init() {
39207 s = calloc(1, sizeof(*s));
39213 void ssi_val_free(ssi_val_t *s) {
39214 if (s->str) buffer_free(s->str);
39220 @@ -45,175 +45,175 @@
39221 ssi_tokenizer_t *t, int *token_id, buffer *token) {
39228 for (tid = 0; tid == 0 && t->offset < t->size && t->input[t->offset] ; ) {
39229 char c = t->input[t->offset];
39243 buffer_copy_string(token, "(=)");
39248 if (t->input[t->offset + 1] == '=') {
39256 buffer_copy_string(token, "(>=)");
39265 buffer_copy_string(token, "(>)");
39271 if (t->input[t->offset + 1] == '=') {
39279 buffer_copy_string(token, "(<=)");
39288 buffer_copy_string(token, "(<)");
39296 if (t->input[t->offset + 1] == '=') {
39304 buffer_copy_string(token, "(!=)");
39313 buffer_copy_string(token, "(!)");
39319 if (t->input[t->offset + 1] == '&') {
39327 buffer_copy_string(token, "(&&)");
39329 - log_error_write(srv, __FILE__, __LINE__, "sds",
39330 - "pos:", t->line_pos,
39331 + log_error_write(srv, __FILE__, __LINE__, "sds",
39332 + "pos:", t->line_pos,
39333 "missing second &");
39340 if (t->input[t->offset + 1] == '|') {
39348 buffer_copy_string(token, "(||)");
39350 - log_error_write(srv, __FILE__, __LINE__, "sds",
39351 - "pos:", t->line_pos,
39352 + log_error_write(srv, __FILE__, __LINE__, "sds",
39353 + "pos:", t->line_pos,
39354 "missing second |");
39368 /* search for the terminating " */
39369 for (i = 1; t->input[t->offset + i] && t->input[t->offset + i] != '\''; i++);
39372 if (t->input[t->offset + i]) {
39376 buffer_copy_string_len(token, t->input + t->offset + 1, i-1);
39379 t->offset += i + 1;
39380 t->line_pos += i + 1;
39384 - log_error_write(srv, __FILE__, __LINE__, "sds",
39385 - "pos:", t->line_pos,
39387 + log_error_write(srv, __FILE__, __LINE__, "sds",
39388 + "pos:", t->line_pos,
39389 "missing closing quote");
39405 buffer_copy_string(token, "(");
39415 buffer_copy_string(token, ")");
39418 if (t->input[t->offset + 1] == '{') {
39419 for (i = 2; t->input[t->offset + i] && t->input[t->offset + i] != '}'; i++);
39422 if (t->input[t->offset + i] != '}') {
39423 - log_error_write(srv, __FILE__, __LINE__, "sds",
39424 - "pos:", t->line_pos,
39425 + log_error_write(srv, __FILE__, __LINE__, "sds",
39426 + "pos:", t->line_pos,
39427 "missing closing quote");
39434 buffer_copy_string_len(token, t->input + t->offset + 2, i-3);
39436 for (i = 1; isalpha(t->input[t->offset + i]) || t->input[t->offset + i] == '_'; i++);
39439 buffer_copy_string_len(token, t->input + t->offset + 1, i-1);
39446 if (NULL != (ds = (data_string *)array_get_element(p->ssi_cgi_env, token->ptr))) {
39447 buffer_copy_string_buffer(token, ds->value);
39448 } else if (NULL != (ds = (data_string *)array_get_element(p->ssi_vars, token->ptr))) {
39449 @@ -221,16 +221,16 @@
39451 buffer_copy_string(token, "");
39461 for (i = 0; isgraph(t->input[t->offset + i]); i++) {
39462 char d = t->input[t->offset + i];
39469 @@ -244,25 +244,25 @@
39478 buffer_copy_string_len(token, t->input + t->offset, i);
39495 } else if (t->offset < t->size) {
39496 - log_error_write(srv, __FILE__, __LINE__, "sds",
39497 - "pos:", t->line_pos,
39498 + log_error_write(srv, __FILE__, __LINE__, "sds",
39499 + "pos:", t->line_pos,
39503 @@ -275,50 +275,50 @@
39511 t.size = strlen(expr);
39524 /* default context */
39527 pParser = ssiexprparserAlloc( malloc );
39528 token = buffer_init();
39529 while((1 == (ret = ssi_expr_tokenizer(srv, con, p, &t, &token_id, token))) && context.ok) {
39530 ssiexprparser(pParser, token_id, token, &context);
39533 token = buffer_init();
39535 ssiexprparser(pParser, 0, token, &context);
39536 ssiexprparserFree(pParser, free );
39539 buffer_free(token);
39543 - log_error_write(srv, __FILE__, __LINE__, "s",
39544 + log_error_write(srv, __FILE__, __LINE__, "s",
39545 "expr parser failed");
39550 if (context.ok == 0) {
39551 - log_error_write(srv, __FILE__, __LINE__, "sds",
39552 - "pos:", t.line_pos,
39553 + log_error_write(srv, __FILE__, __LINE__, "sds",
39554 + "pos:", t.line_pos,
39555 "parser failed somehow near here");
39559 - log_error_write(srv, __FILE__, __LINE__, "ssd",
39560 + log_error_write(srv, __FILE__, __LINE__, "ssd",
39566 return context.val.bo;
39568 --- ../lighttpd-1.4.11/src/mod_ssi_expr.h 2005-08-11 01:26:48.000000000 +0300
39569 +++ lighttpd-1.4.12/src/mod_ssi_expr.h 2006-07-16 00:26:04.000000000 +0300
39573 enum { SSI_TYPE_UNSET, SSI_TYPE_BOOL, SSI_TYPE_STRING } type;
39590 --- ../lighttpd-1.4.11/src/mod_ssi_exprparser.c 2005-10-03 00:40:25.000000000 +0300
39591 +++ lighttpd-1.4.12/src/mod_ssi_exprparser.c 2006-07-17 22:02:23.000000000 +0300
39592 @@ -18,10 +18,10 @@
39593 /* Next is all token values, in a form suitable for use by makeheaders.
39594 ** This section will be null unless lemon is run with the -m switch.
39598 ** These constants (all generated automatically by the parser generator)
39599 ** specify the various kinds of tokens (terminals) that the parser
39603 ** Each symbol here is a terminal symbol in the grammar.
39606 ** and nonterminals. "int" is used otherwise.
39607 ** YYNOCODE is a number of type YYCODETYPE which corresponds
39608 ** to no legal terminal or nonterminal number. This
39609 -** number is used to fill in empty slots of the hash
39610 +** number is used to fill in empty slots of the hash
39612 ** YYFALLBACK If defined, this indicates that one or more tokens
39613 ** have fall-back values which should be used if the
39615 ** and nonterminal numbers. "unsigned char" is
39616 ** used if there are fewer than 250 rules and
39617 ** states combined. "int" is used otherwise.
39618 -** ssiexprparserTOKENTYPE is the data type used for minor tokens given
39619 +** ssiexprparserTOKENTYPE is the data type used for minor tokens given
39620 ** directly to the parser from the tokenizer.
39621 ** YYMINORTYPE is the data type used for all minor tokens.
39622 ** This is typically a union of many types, one of
39624 /* Next are that tables used to determine what action to take based on the
39625 ** current state and lookahead token. These tables are used to implement
39626 ** functions that take a state number and lookahead value and return an
39627 -** action integer.
39628 +** action integer.
39630 ** Suppose the action integer is N. Then the action is determined as
39632 @@ -116,7 +116,7 @@
39633 ** If the index value yy_shift_ofst[S]+X is out of range or if the value
39634 ** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
39635 ** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
39636 -** and that yy_default[S] should be used instead.
39637 +** and that yy_default[S] should be used instead.
39639 ** The formula above is for computing the action when the lookahead is
39640 ** a terminal symbol. If the lookahead is a non-terminal (as occurs after
39641 @@ -168,7 +168,7 @@
39643 /* The next table maps tokens into fallback tokens. If a construct
39644 ** like the following:
39647 ** %fallback ID X Y Z.
39649 ** appears in the grammer, then ID becomes a fallback token for X, Y,
39650 @@ -219,10 +219,10 @@
39651 #endif /* NDEBUG */
39656 ** Turn parser tracing on by giving a stream to which to write the trace
39657 ** and a prompt to preface each trace message. Tracing is turned off
39658 -** by making either argument NULL
39659 +** by making either argument NULL
39663 @@ -247,7 +247,7 @@
39665 /* For tracing shifts, the names of all terminals and nonterminals
39666 ** are required. The following table supplies these names */
39667 -static const char *yyTokenName[] = {
39668 +static const char *yyTokenName[] = {
39669 "$", "AND", "OR", "EQ",
39670 "NE", "GT", "GE", "LT",
39671 "LE", "NOT", "LPARAN", "RPARAN",
39672 @@ -295,7 +295,7 @@
39678 ** This function allocates a new parser.
39679 ** The only argument is a pointer to a function which works like
39681 @@ -326,7 +326,7 @@
39682 /* Here is inserted the actions which take place when a
39683 ** terminal or non-terminal is destroyed. This can happen
39684 ** when the symbol is popped from the stack during a
39685 - ** reduce or during error processing or when a parser is
39686 + ** reduce or during error processing or when a parser is
39687 ** being destroyed before it is finished parsing.
39689 ** Note: during a reduce, the only symbols destroyed are those
39690 @@ -379,7 +379,7 @@
39696 ** Deallocate and destroy a parser. Destructors are all called for
39697 ** all stack elements before shutting the parser down.
39699 @@ -415,7 +415,7 @@
39702 int stateno = pParser->yystack[pParser->yyidx].stateno;
39705 /* if( pParser->yyidx<0 ) return YY_NO_ACTION; */
39706 i = yy_shift_ofst[stateno];
39707 if( i==YY_SHIFT_USE_DFLT ){
39708 @@ -459,7 +459,7 @@
39711 int stateno = pParser->yystack[pParser->yyidx].stateno;
39714 i = yy_reduce_ofst[stateno];
39715 if( i==YY_REDUCE_USE_DFLT ){
39716 return yy_default[stateno];
39717 @@ -559,7 +559,7 @@
39718 ssiexprparserARG_FETCH;
39719 yymsp = &yypParser->yystack[yypParser->yyidx];
39721 - if( yyTraceFILE && yyruleno>=0
39722 + if( yyTraceFILE && yyruleno>=0
39723 && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){
39724 fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
39725 yyRuleName[yyruleno]);
39726 @@ -872,7 +872,7 @@
39727 #ifdef YYERRORSYMBOL
39728 /* A syntax error has occurred.
39729 ** The response to an error depends upon whether or not the
39730 - ** grammar defines an error token "ERROR".
39731 + ** grammar defines an error token "ERROR".
39733 ** This is what we do if the grammar does define ERROR:
39735 --- ../lighttpd-1.4.11/src/mod_staticfile.c 2006-02-15 14:31:14.000000000 +0200
39736 +++ lighttpd-1.4.12/src/mod_staticfile.c 2006-07-16 00:26:03.000000000 +0300
39738 #include "http_chunk.h"
39739 #include "response.h"
39741 +#include "sys-files.h"
39742 +#include "sys-strings.h"
39744 * this is a staticfile for a lighttpd plugin
39750 @@ -29,48 +31,48 @@
39759 plugin_config **config_storage;
39761 - plugin_config conf;
39763 + plugin_config conf;
39766 /* init the plugin data */
39767 INIT_FUNC(mod_staticfile_init) {
39771 p = calloc(1, sizeof(*p));
39774 p->range_buf = buffer_init();
39780 -/* detroy the plugin data */
39781 +/* destroy the plugin data */
39782 FREE_FUNC(mod_staticfile_free) {
39783 plugin_data *p = p_d;
39788 if (!p) return HANDLER_GO_ON;
39791 if (p->config_storage) {
39793 for (i = 0; i < srv->config_context->used; i++) {
39794 plugin_config *s = p->config_storage[i];
39797 array_free(s->exclude_ext);
39802 free(p->config_storage);
39804 buffer_free(p->range_buf);
39810 return HANDLER_GO_ON;
39813 @@ -79,63 +81,60 @@
39814 SETDEFAULTS_FUNC(mod_staticfile_set_defaults) {
39815 plugin_data *p = p_d;
39818 - config_values_t cv[] = {
39820 + config_values_t cv[] = {
39821 { "static-file.exclude-extensions", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
39822 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
39826 if (!p) return HANDLER_ERROR;
39829 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
39832 for (i = 0; i < srv->config_context->used; i++) {
39836 s = calloc(1, sizeof(plugin_config));
39837 s->exclude_ext = array_init();
39840 cv[0].destination = s->exclude_ext;
39843 p->config_storage[i] = s;
39846 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
39847 return HANDLER_ERROR;
39852 return HANDLER_GO_ON;
39855 -#define PATCH(x) \
39856 - p->conf.x = s->x;
39857 static int mod_staticfile_patch_connection(server *srv, connection *con, plugin_data *p) {
39859 plugin_config *s = p->config_storage[0];
39861 - PATCH(exclude_ext);
39864 + PATCH_OPTION(exclude_ext);
39866 /* skip the first, the global context */
39867 for (i = 1; i < srv->config_context->used; i++) {
39868 data_config *dc = (data_config *)srv->config_context->data[i];
39869 s = p->config_storage[i];
39872 /* condition didn't match */
39873 if (!config_check_cond(srv, con, dc)) continue;
39877 for (j = 0; j < dc->value->used; j++) {
39878 data_unset *du = dc->value->data[j];
39881 if (buffer_is_equal_string(du->key, CONST_STR_LEN("static-file.exclude-extensions"))) {
39882 - PATCH(exclude_ext);
39883 + PATCH_OPTION(exclude_ext);
39893 static int http_response_parse_range(server *srv, connection *con, plugin_data *p) {
39895 @@ -146,69 +145,69 @@
39897 stat_cache_entry *sce = NULL;
39898 buffer *content_type = NULL;
39901 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
39907 end = sce->st.st_size - 1;
39910 con->response.content_length = 0;
39913 if (NULL != (ds = (data_string *)array_get_element(con->response.headers, "Content-Type"))) {
39914 content_type = ds->value;
39918 for (s = con->request.http_range, error = 0;
39919 !error && *s && NULL != (minus = strchr(s, '-')); ) {
39928 le = strtoll(s, &err, 10);
39932 /* RFC 2616 - 14.35.1 */
39935 con->http_status = 416;
39937 } else if (*err == '\0') {
39942 end = sce->st.st_size - 1;
39943 start = sce->st.st_size + le;
39944 } else if (*err == ',') {
39949 end = sce->st.st_size - 1;
39950 start = sce->st.st_size + le;
39956 } else if (*(minus+1) == '\0' || *(minus+1) == ',') {
39960 la = strtoll(s, &err, 10);
39963 if (err == minus) {
39967 if (*(err + 1) == '\0') {
39971 end = sce->st.st_size - 1;
39975 } else if (*(err + 1) == ',') {
39980 end = sce->st.st_size - 1;
39983 @@ -220,64 +219,64 @@
39986 /* <start>-<stop> */
39989 la = strtoll(s, &err, 10);
39992 if (err == minus) {
39993 le = strtoll(minus+1, &err, 10);
39996 /* RFC 2616 - 14.35.1 */
40002 if (*err == '\0') {
40009 } else if (*err == ',') {
40032 if (start < 0) start = 0;
40035 /* RFC 2616 - 14.35.1 */
40036 if (end > sce->st.st_size - 1) end = sce->st.st_size - 1;
40039 if (start > sce->st.st_size - 1) {
40043 con->http_status = 416;
40050 /* write boundary-header */
40054 b = chunkqueue_get_append_buffer(con->write_queue);
40057 buffer_copy_string(b, "\r\n--");
40058 buffer_append_string(b, boundary);
40061 /* write Content-Range */
40062 buffer_append_string(b, "\r\nContent-Range: bytes ");
40063 buffer_append_off_t(b, start);
40064 @@ -285,54 +284,54 @@
40065 buffer_append_off_t(b, end);
40066 buffer_append_string(b, "/");
40067 buffer_append_off_t(b, sce->st.st_size);
40070 buffer_append_string(b, "\r\nContent-Type: ");
40071 buffer_append_string_buffer(b, content_type);
40074 /* write END-OF-HEADER */
40075 buffer_append_string(b, "\r\n\r\n");
40078 con->response.content_length += b->used - 1;
40084 chunkqueue_append_file(con->write_queue, con->physical.path, start, end - start + 1);
40085 con->response.content_length += end - start + 1;
40090 /* something went wrong */
40091 if (error) return -1;
40095 /* add boundary end */
40099 b = chunkqueue_get_append_buffer(con->write_queue);
40102 buffer_copy_string_len(b, "\r\n--", 4);
40103 buffer_append_string(b, boundary);
40104 buffer_append_string_len(b, "--\r\n", 4);
40107 con->response.content_length += b->used - 1;
40110 /* set header-fields */
40113 buffer_copy_string(p->range_buf, "multipart/byteranges; boundary=");
40114 buffer_append_string(p->range_buf, boundary);
40117 /* overwrite content-type */
40118 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(p->range_buf));
40120 /* add Content-Range-header */
40123 buffer_copy_string(p->range_buf, "bytes ");
40124 buffer_append_off_t(p->range_buf, start);
40125 buffer_append_string(p->range_buf, "-");
40126 buffer_append_off_t(p->range_buf, end);
40127 buffer_append_string(p->range_buf, "/");
40128 buffer_append_off_t(p->range_buf, sce->st.st_size);
40131 response_header_insert(srv, con, CONST_STR_LEN("Content-Range"), CONST_BUF_LEN(p->range_buf));
40134 @@ -347,12 +346,12 @@
40135 stat_cache_entry *sce = NULL;
40140 /* someone else has done a decision for us */
40141 if (con->http_status != 0) return HANDLER_GO_ON;
40142 if (con->uri.path->used == 0) return HANDLER_GO_ON;
40143 if (con->physical.path->used == 0) return HANDLER_GO_ON;
40146 /* someone else has handled this request */
40147 if (con->mode != DIRECT) return HANDLER_GO_ON;
40149 @@ -365,52 +364,52 @@
40151 return HANDLER_GO_ON;
40155 mod_staticfile_patch_connection(srv, con, p);
40158 s_len = con->uri.path->used - 1;
40161 /* ignore certain extensions */
40162 for (k = 0; k < p->conf.exclude_ext->used; k++) {
40163 - ds = (data_string *)p->conf.exclude_ext->data[k];
40165 + ds = (data_string *)p->conf.exclude_ext->data[k];
40167 if (ds->value->used == 0) continue;
40169 if (buffer_is_equal_right_len(con->physical.path, ds->value, ds->value->used - 1)) {
40170 return HANDLER_GO_ON;
40176 if (con->conf.log_request_handling) {
40177 log_error_write(srv, __FILE__, __LINE__, "s", "-- handling file as static file");
40181 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
40182 con->http_status = 403;
40185 log_error_write(srv, __FILE__, __LINE__, "sbsb",
40186 "not a regular file:", con->uri.path,
40187 "->", con->physical.path);
40190 return HANDLER_FINISHED;
40193 - /* we only handline regular files */
40195 + /* we only handle regular files */
40196 if (!S_ISREG(sce->st.st_mode)) {
40197 con->http_status = 404;
40200 if (con->conf.log_file_not_found) {
40201 log_error_write(srv, __FILE__, __LINE__, "sbsb",
40202 "not a regular file:", con->uri.path,
40207 return HANDLER_FINISHED;
40210 - /* mod_compress might set several data directly, don't overwrite them */
40212 + /* mod_compress might set several parameters directly; don't overwrite them */
40214 /* set response content-type, if not set already */
40216 if (NULL == array_get_element(con->response.headers, "Content-Type")) {
40217 @@ -420,15 +419,15 @@
40218 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
40223 if (NULL == array_get_element(con->response.headers, "ETag")) {
40224 /* generate e-tag */
40225 etag_mutate(con->physical.etag, sce->etag);
40228 response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
40230 response_header_overwrite(srv, con, CONST_STR_LEN("Accept-Ranges"), CONST_STR_LEN("bytes"));
40233 /* prepare header */
40234 if (NULL == (ds = (data_string *)array_get_element(con->response.headers, "Last-Modified"))) {
40235 mtime = strftime_cache_get(srv, sce->st.st_mtime);
40236 @@ -444,34 +443,34 @@
40237 /* check if we have a conditional GET */
40239 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If-Range"))) {
40240 - /* if the value is the same as our ETag, we do a Range-request,
40241 + /* if the value is the same as our ETag, we do a Range-request,
40242 * otherwise a full 200 */
40244 if (!buffer_is_equal(ds->value, con->physical.etag)) {
40245 do_range_request = 0;
40250 if (do_range_request) {
40251 /* content prepared, I'm done */
40252 con->file_finished = 1;
40255 if (0 == http_response_parse_range(srv, con, p)) {
40256 con->http_status = 206;
40258 return HANDLER_FINISHED;
40263 /* if we are still here, prepare body */
40265 - /* we add it here for all requests
40266 - * the HEAD request will drop it afterwards again
40268 + /* we add it here for all requests
40269 + * the HEAD request will drop it afterwards again
40271 http_chunk_append_file(srv, con, con->physical.path, 0, sce->st.st_size);
40274 con->file_finished = 1;
40277 return HANDLER_FINISHED;
40280 @@ -480,13 +479,13 @@
40281 int mod_staticfile_plugin_init(plugin *p) {
40282 p->version = LIGHTTPD_VERSION_ID;
40283 p->name = buffer_init_string("staticfile");
40286 p->init = mod_staticfile_init;
40287 p->handle_subrequest_start = mod_staticfile_subrequest;
40288 p->set_defaults = mod_staticfile_set_defaults;
40289 p->cleanup = mod_staticfile_free;
40297 --- ../lighttpd-1.4.11/src/mod_status.c 2006-01-10 21:45:32.000000000 +0200
40298 +++ lighttpd-1.4.12/src/mod_status.c 2006-07-19 20:02:55.000000000 +0300
40301 #include <stdlib.h>
40302 #include <string.h>
40303 -#include <unistd.h>
40308 #include "response.h"
40309 #include "connections.h"
40311 +#include "status_counter.h"
40313 #include "plugin.h"
40315 @@ -29,114 +29,114 @@
40321 double traffic_out;
40325 double mod_5s_traffic_out[5];
40326 double mod_5s_requests[5];
40330 double rel_traffic_out;
40331 double rel_requests;
40334 double abs_traffic_out;
40335 double abs_requests;
40338 double bytes_written;
40341 buffer *module_list;
40344 plugin_config **config_storage;
40346 - plugin_config conf;
40348 + plugin_config conf;
40351 INIT_FUNC(mod_status_init) {
40356 p = calloc(1, sizeof(*p));
40359 p->traffic_out = p->requests = 0;
40360 p->rel_traffic_out = p->rel_requests = 0;
40361 p->abs_traffic_out = p->abs_requests = 0;
40362 p->bytes_written = 0;
40363 p->module_list = buffer_init();
40366 for (i = 0; i < 5; i++) {
40367 p->mod_5s_traffic_out[i] = p->mod_5s_requests[i] = 0;
40374 FREE_FUNC(mod_status_free) {
40375 plugin_data *p = p_d;
40380 if (!p) return HANDLER_GO_ON;
40383 buffer_free(p->module_list);
40386 if (p->config_storage) {
40388 for (i = 0; i < srv->config_context->used; i++) {
40389 plugin_config *s = p->config_storage[i];
40392 buffer_free(s->status_url);
40393 buffer_free(s->statistics_url);
40394 buffer_free(s->config_url);
40399 free(p->config_storage);
40408 return HANDLER_GO_ON;
40411 SETDEFAULTS_FUNC(mod_status_set_defaults) {
40412 plugin_data *p = p_d;
40415 - config_values_t cv[] = {
40417 + config_values_t cv[] = {
40418 { "status.status-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
40419 { "status.config-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
40420 { "status.enable-sort", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },
40421 { "status.statistics-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
40422 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
40426 if (!p) return HANDLER_ERROR;
40429 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
40432 for (i = 0; i < srv->config_context->used; i++) {
40436 s = calloc(1, sizeof(plugin_config));
40437 s->config_url = buffer_init();
40438 s->status_url = buffer_init();
40440 s->statistics_url = buffer_init();
40443 cv[0].destination = s->status_url;
40444 cv[1].destination = s->config_url;
40445 cv[2].destination = &(s->sort);
40446 cv[3].destination = s->statistics_url;
40449 p->config_storage[i] = s;
40452 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
40453 return HANDLER_ERROR;
40458 return HANDLER_GO_ON;
40461 @@ -151,7 +151,7 @@
40462 buffer_append_string(b, value);
40463 BUFFER_APPEND_STRING_CONST(b, "</td>\n");
40464 BUFFER_APPEND_STRING_CONST(b, " </tr>\n");
40470 @@ -161,13 +161,13 @@
40471 buffer_append_string(b, key);
40472 BUFFER_APPEND_STRING_CONST(b, "</th>\n");
40473 BUFFER_APPEND_STRING_CONST(b, " </tr>\n");
40479 static int mod_status_header_append_sort(buffer *b, void *p_d, const char* key) {
40480 plugin_data *p = p_d;
40483 if (p->conf.sort) {
40484 BUFFER_APPEND_STRING_CONST(b, "<th class=\"status\"><a href=\"#\" class=\"sortheader\" onclick=\"resort(this);return false;\">");
40485 buffer_append_string(b, key);
40486 @@ -177,13 +177,13 @@
40487 buffer_append_string(b, key);
40488 BUFFER_APPEND_STRING_CONST(b, "</th>\n");
40495 static int mod_status_get_multiplier(double *avg, char *multiplier, int size) {
40499 if (*avg > size) { *avg /= size; *multiplier = 'k'; }
40500 if (*avg > size) { *avg /= size; *multiplier = 'M'; }
40501 if (*avg > size) { *avg /= size; *multiplier = 'G'; }
40502 @@ -202,21 +202,21 @@
40505 char multiplier = '\0';
40511 int days, hours, mins, seconds;
40514 b = chunkqueue_get_append_buffer(con->write_queue);
40516 - BUFFER_COPY_STRING_CONST(b,
40517 + BUFFER_COPY_STRING_CONST(b,
40518 "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
40519 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
40520 " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
40521 "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"
40523 " <title>Status</title>\n");
40526 BUFFER_APPEND_STRING_CONST(b,
40527 " <style type=\"text/css\">\n"
40528 " table.status { border: black solid thin; }\n"
40529 @@ -226,14 +226,14 @@
40530 " a.sortheader { background-color: black; color: white; font-weight: bold; text-decoration: none; display: block; }\n"
40531 " span.sortarrow { color: white; text-decoration: none; }\n"
40535 if (p->conf.sort) {
40536 BUFFER_APPEND_STRING_CONST(b,
40537 "<script type=\"text/javascript\">\n"
40539 "var sort_column;\n"
40540 "var prev_span = null;\n");
40543 BUFFER_APPEND_STRING_CONST(b,
40544 "function get_inner_text(el) {\n"
40545 " if((typeof el == 'string')||(typeof el == 'undefined'))\n"
40546 @@ -251,7 +251,7 @@
40552 BUFFER_APPEND_STRING_CONST(b,
40553 "function sortfn(a,b) {\n"
40554 " var at = get_inner_text(a.cells[sort_column]);\n"
40555 @@ -266,7 +266,7 @@
40556 " else return 1;\n"
40561 BUFFER_APPEND_STRING_CONST(b,
40562 "function resort(lnk) {\n"
40563 " var span = lnk.childNodes[1];\n"
40564 @@ -276,7 +276,7 @@
40565 " rows[j-1] = table.rows[j];\n"
40566 " sort_column = lnk.parentNode.cellIndex;\n"
40567 " rows.sort(sortfn);\n");
40570 BUFFER_APPEND_STRING_CONST(b,
40571 " if (prev_span != null) prev_span.innerHTML = '';\n"
40572 " if (span.getAttribute('sortdir')=='down') {\n"
40573 @@ -294,175 +294,175 @@
40578 - BUFFER_APPEND_STRING_CONST(b,
40580 + BUFFER_APPEND_STRING_CONST(b,
40589 /* connection listing */
40590 BUFFER_APPEND_STRING_CONST(b, "<h1>Server-Status</h1>");
40592 - BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\">");
40593 - BUFFER_APPEND_STRING_CONST(b, "<tr><td>Hostname</td><td class=\"string\">");
40595 + BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\" id=\"status\" summary=\"Server Status\">");
40596 + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Hostname</td><td class=\"string\"><span id=\"host_addr\">");
40597 buffer_append_string_buffer(b, con->uri.authority);
40598 - BUFFER_APPEND_STRING_CONST(b, " (");
40599 + BUFFER_APPEND_STRING_CONST(b, "</span> (<span id=\"host_name\">");
40600 buffer_append_string_buffer(b, con->server_name);
40601 - BUFFER_APPEND_STRING_CONST(b, ")</td></tr>\n");
40602 - BUFFER_APPEND_STRING_CONST(b, "<tr><td>Uptime</td><td class=\"string\">");
40604 + BUFFER_APPEND_STRING_CONST(b, "</span>)</td></tr>\n");
40605 + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Uptime</td><td class=\"string\" id=\"uptime\">");
40607 ts = srv->cur_ts - srv->startup_ts;
40610 days = ts / (60 * 60 * 24);
40611 ts %= (60 * 60 * 24);
40614 hours = ts / (60 * 60);
40626 buffer_append_long(b, days);
40627 BUFFER_APPEND_STRING_CONST(b, " days ");
40632 buffer_append_long(b, hours);
40633 BUFFER_APPEND_STRING_CONST(b, " hours ");
40638 buffer_append_long(b, mins);
40639 BUFFER_APPEND_STRING_CONST(b, " min ");
40643 buffer_append_long(b, seconds);
40644 BUFFER_APPEND_STRING_CONST(b, " s");
40647 BUFFER_APPEND_STRING_CONST(b, "</td></tr>\n");
40648 BUFFER_APPEND_STRING_CONST(b, "<tr><td>Started at</td><td class=\"string\">");
40651 ts = srv->startup_ts;
40653 - strftime(buf, sizeof(buf) - 1, "%Y-%m-%d %H:%M:%S", localtime(&ts));
40655 + strftime(buf, sizeof(buf) - 1, "<span id=\"start_date\">%Y-%m-%d</span> <span id=\"start_time\">%H:%M:%S</span>", localtime(&ts));
40656 buffer_append_string(b, buf);
40657 BUFFER_APPEND_STRING_CONST(b, "</td></tr>\n");
40662 BUFFER_APPEND_STRING_CONST(b, "<tr><th colspan=\"2\">absolute (since start)</th></tr>\n");
40664 - BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\">");
40666 + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\" ><span id=\"requests\">");
40667 avg = p->abs_requests;
40669 mod_status_get_multiplier(&avg, &multiplier, 1000);
40672 buffer_append_long(b, avg);
40673 - BUFFER_APPEND_STRING_CONST(b, " ");
40674 + BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_mult\">");
40675 if (multiplier) buffer_append_string_len(b, &multiplier, 1);
40676 - BUFFER_APPEND_STRING_CONST(b, "req</td></tr>\n");
40678 - BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\">");
40679 + BUFFER_APPEND_STRING_CONST(b, "</span>req</td></tr>\n");
40681 + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\"><span id=\"traffic\">");
40682 avg = p->abs_traffic_out;
40684 mod_status_get_multiplier(&avg, &multiplier, 1024);
40686 sprintf(buf, "%.2f", avg);
40687 buffer_append_string(b, buf);
40688 - BUFFER_APPEND_STRING_CONST(b, " ");
40689 + BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"traffic_mult\">");
40690 if (multiplier) buffer_append_string_len(b, &multiplier, 1);
40691 - BUFFER_APPEND_STRING_CONST(b, "byte</td></tr>\n");
40692 + BUFFER_APPEND_STRING_CONST(b, "</span>byte</td></tr>\n");
40696 BUFFER_APPEND_STRING_CONST(b, "<tr><th colspan=\"2\">average (since start)</th></tr>\n");
40698 - BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\">");
40700 + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\"><span id=\"requests_avg\">");
40701 avg = p->abs_requests / (srv->cur_ts - srv->startup_ts);
40703 mod_status_get_multiplier(&avg, &multiplier, 1000);
40705 buffer_append_long(b, avg);
40706 - BUFFER_APPEND_STRING_CONST(b, " ");
40707 + BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_avg_mult\">");
40708 if (multiplier) buffer_append_string_len(b, &multiplier, 1);
40709 - BUFFER_APPEND_STRING_CONST(b, "req/s</td></tr>\n");
40711 - BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\">");
40712 + BUFFER_APPEND_STRING_CONST(b, "</span>req/s</td></tr>\n");
40714 + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\"><span id=\"traffic_avg\">");
40715 avg = p->abs_traffic_out / (srv->cur_ts - srv->startup_ts);
40717 mod_status_get_multiplier(&avg, &multiplier, 1024);
40719 sprintf(buf, "%.2f", avg);
40720 buffer_append_string(b, buf);
40721 - BUFFER_APPEND_STRING_CONST(b, " ");
40722 + BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"traffic_avg_mult\">");
40723 if (multiplier) buffer_append_string_len(b, &multiplier, 1);
40724 - BUFFER_APPEND_STRING_CONST(b, "byte/s</td></tr>\n");
40725 + BUFFER_APPEND_STRING_CONST(b, "</span>byte/s</td></tr>\n");
40731 BUFFER_APPEND_STRING_CONST(b, "<tr><th colspan=\"2\">average (5s sliding average)</th></tr>\n");
40732 for (j = 0, avg = 0; j < 5; j++) {
40733 avg += p->mod_5s_requests[j];
40739 - BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\">");
40741 + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\"><span id=\"requests_sliding_avg\">");
40743 mod_status_get_multiplier(&avg, &multiplier, 1000);
40745 buffer_append_long(b, avg);
40746 - BUFFER_APPEND_STRING_CONST(b, " ");
40747 + BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_sliding_avg_mult\">");
40748 if (multiplier) buffer_append_string_len(b, &multiplier, 1);
40750 - BUFFER_APPEND_STRING_CONST(b, "req/s</td></tr>\n");
40753 + BUFFER_APPEND_STRING_CONST(b, "</span>req/s</td></tr>\n");
40755 for (j = 0, avg = 0; j < 5; j++) {
40756 avg += p->mod_5s_traffic_out[j];
40762 - BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\">");
40764 + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\"><span id=\"requests_sliding_traffic\">");
40766 mod_status_get_multiplier(&avg, &multiplier, 1024);
40768 sprintf(buf, "%.2f", avg);
40769 buffer_append_string(b, buf);
40770 - BUFFER_APPEND_STRING_CONST(b, " ");
40771 + BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_sliding_traffic_mult\">");
40772 if (multiplier) buffer_append_string_len(b, &multiplier, 1);
40773 - BUFFER_APPEND_STRING_CONST(b, "byte/s</td></tr>\n");
40775 + BUFFER_APPEND_STRING_CONST(b, "</span>byte/s</td></tr>\n");
40777 BUFFER_APPEND_STRING_CONST(b, "</table>\n");
40782 BUFFER_APPEND_STRING_CONST(b, "<hr />\n<pre><b>legend</b>\n");
40783 BUFFER_APPEND_STRING_CONST(b, ". = connect, C = close, E = hard error\n");
40784 BUFFER_APPEND_STRING_CONST(b, "r = read, R = read-POST, W = write, h = handle-request\n");
40785 BUFFER_APPEND_STRING_CONST(b, "q = request-start, Q = request-end\n");
40786 BUFFER_APPEND_STRING_CONST(b, "s = response-start, S = response-end\n");
40788 - BUFFER_APPEND_STRING_CONST(b, "<b>");
40790 + BUFFER_APPEND_STRING_CONST(b, "<strong><span id=\"connections\">");
40791 buffer_append_long(b, srv->conns->used);
40792 - BUFFER_APPEND_STRING_CONST(b, " connections</b>\n");
40794 + BUFFER_APPEND_STRING_CONST(b, "</span> connections</strong>\n");
40796 for (j = 0; j < srv->conns->used; j++) {
40797 connection *c = srv->conns->ptr[j];
40798 const char *state = connection_get_short_state(c->state);
40801 buffer_append_string_len(b, state, 1);
40804 if (((j + 1) % 50) == 0) {
40805 BUFFER_APPEND_STRING_CONST(b, "\n");
40810 BUFFER_APPEND_STRING_CONST(b, "\n</pre><hr />\n<h2>Connections</h2>\n");
40812 - BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\">\n");
40814 + BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\" summary=\"Current connections\" id=\"clients\">\n");
40815 BUFFER_APPEND_STRING_CONST(b, "<tr>");
40816 mod_status_header_append_sort(b, p_d, "Client IP");
40817 mod_status_header_append_sort(b, p_d, "Read");
40818 @@ -473,16 +473,16 @@
40819 mod_status_header_append_sort(b, p_d, "URI");
40820 mod_status_header_append_sort(b, p_d, "File");
40821 BUFFER_APPEND_STRING_CONST(b, "</tr>\n");
40824 for (j = 0; j < srv->conns->used; j++) {
40825 connection *c = srv->conns->ptr[j];
40827 - BUFFER_APPEND_STRING_CONST(b, "<tr><td class=\"string\">");
40830 + BUFFER_APPEND_STRING_CONST(b, "<tr><td class=\"string ip\">");
40832 buffer_append_string(b, inet_ntop_cache_get_ip(srv, &(c->dst_addr)));
40834 - BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int\">");
40837 + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int bytes_read\">");
40839 if (con->request.content_length) {
40840 buffer_append_long(b, c->request_content_queue->bytes_in);
40841 BUFFER_APPEND_STRING_CONST(b, "/");
40842 @@ -490,55 +490,55 @@
40844 BUFFER_APPEND_STRING_CONST(b, "0/0");
40847 - BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int\">");
40850 + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int bytes_written\">");
40852 buffer_append_off_t(b, chunkqueue_written(c->write_queue));
40853 BUFFER_APPEND_STRING_CONST(b, "/");
40854 buffer_append_off_t(b, chunkqueue_length(c->write_queue));
40856 - BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
40859 + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string state\">");
40861 buffer_append_string(b, connection_get_state(c->state));
40863 - BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int\">");
40866 + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int time\">");
40868 buffer_append_long(b, srv->cur_ts - c->request_start);
40870 - BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
40873 + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string host\">");
40875 if (buffer_is_empty(c->server_name)) {
40876 buffer_append_string_buffer(b, c->uri.authority);
40879 buffer_append_string_buffer(b, c->server_name);
40882 - BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
40885 + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string uri\">");
40887 if (!buffer_is_empty(c->uri.path)) {
40888 buffer_append_string_encoded(b, CONST_BUF_LEN(c->uri.path), ENCODING_HTML);
40891 - BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
40894 + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string file\">");
40896 buffer_append_string_buffer(b, c->physical.path);
40899 BUFFER_APPEND_STRING_CONST(b, "</td></tr>\n");
40903 - BUFFER_APPEND_STRING_CONST(b,
40906 + BUFFER_APPEND_STRING_CONST(b,
40910 - BUFFER_APPEND_STRING_CONST(b,
40913 + BUFFER_APPEND_STRING_CONST(b,
40919 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
40925 @@ -548,7 +548,7 @@
40931 b = chunkqueue_get_append_buffer(con->write_queue);
40933 /* output total number of requests */
40934 @@ -556,19 +556,19 @@
40935 avg = p->abs_requests;
40936 buffer_append_long(b, avg);
40937 BUFFER_APPEND_STRING_CONST(b, "\n");
40940 /* output total traffic out in kbytes */
40941 BUFFER_APPEND_STRING_CONST(b, "Total kBytes: ");
40942 avg = p->abs_traffic_out / 1024;
40943 buffer_append_long(b, avg);
40944 BUFFER_APPEND_STRING_CONST(b, "\n");
40947 /* output uptime */
40948 BUFFER_APPEND_STRING_CONST(b, "Uptime: ");
40949 ts = srv->cur_ts - srv->startup_ts;
40950 buffer_append_long(b, ts);
40951 BUFFER_APPEND_STRING_CONST(b, "\n");
40954 /* output busy servers */
40955 BUFFER_APPEND_STRING_CONST(b, "BusyServers: ");
40956 buffer_append_long(b, srv->conns->used);
40957 @@ -577,7 +577,7 @@
40958 /* set text/plain output */
40960 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/plain"));
40966 @@ -585,16 +585,16 @@
40967 plugin_data *p = p_d;
40968 buffer *b, *m = p->module_list;
40970 - array *st = srv->status;
40971 + array *st = status_counter_get_array();
40973 if (0 == st->used) {
40974 /* we have nothing to send */
40975 con->http_status = 204;
40976 con->file_finished = 1;
40979 return HANDLER_FINISHED;
40983 b = chunkqueue_get_append_buffer(con->write_queue);
40985 for (i = 0; i < st->used; i++) {
40986 @@ -605,27 +605,27 @@
40987 buffer_append_long(b, ((data_integer *)(st->data[ndx]))->value);
40988 buffer_append_string(b, "\n");
40992 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/plain"));
40995 con->http_status = 200;
40996 con->file_finished = 1;
40999 return HANDLER_FINISHED;
41003 static handler_t mod_status_handle_server_status(server *srv, connection *con, void *p_d) {
41006 if (buffer_is_equal_string(con->uri.query, CONST_STR_LEN("auto"))) {
41007 mod_status_handle_server_status_text(srv, con, p_d);
41009 mod_status_handle_server_status_html(srv, con, p_d);
41013 con->http_status = 200;
41014 con->file_finished = 1;
41017 return HANDLER_FINISHED;
41020 @@ -634,9 +634,9 @@
41021 plugin_data *p = p_d;
41022 buffer *b, *m = p->module_list;
41025 - struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
41028 + struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
41030 /* - poll is most reliable
41031 * - select works everywhere
41032 * - linux-* are experimental
41033 @@ -661,10 +661,10 @@
41035 { FDEVENT_HANDLER_UNSET, NULL }
41039 b = chunkqueue_get_append_buffer(con->write_queue);
41041 - BUFFER_COPY_STRING_CONST(b,
41043 + BUFFER_COPY_STRING_CONST(b,
41044 "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
41045 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
41046 " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
41047 @@ -675,7 +675,7 @@
41049 " <h1>" PACKAGE_NAME " " PACKAGE_VERSION "</h1>\n"
41050 " <table border=\"1\">\n");
41053 mod_status_header_append(b, "Server-Features");
41055 mod_status_row_append(b, "RegEx Conditionals", "enabled");
41056 @@ -683,21 +683,21 @@
41057 mod_status_row_append(b, "RegEx Conditionals", "disabled - pcre missing");
41059 mod_status_header_append(b, "Network Engine");
41062 for (i = 0; event_handlers[i].name; i++) {
41063 if (event_handlers[i].et == srv->event_handler) {
41064 mod_status_row_append(b, "fd-Event-Handler", event_handlers[i].name);
41070 mod_status_header_append(b, "Config-File-Settings");
41073 for (i = 0; i < srv->plugins.used; i++) {
41074 plugin **ps = srv->plugins.ptr;
41077 plugin *pl = ps[i];
41081 buffer_copy_string_buffer(m, pl->name);
41083 @@ -705,137 +705,135 @@
41084 buffer_append_string_buffer(m, pl->name);
41089 mod_status_row_append(b, "Loaded Modules", m->ptr);
41092 BUFFER_APPEND_STRING_CONST(b, " </table>\n");
41094 - BUFFER_APPEND_STRING_CONST(b,
41096 + BUFFER_APPEND_STRING_CONST(b,
41102 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
41105 con->http_status = 200;
41106 con->file_finished = 1;
41109 return HANDLER_FINISHED;
41112 -#define PATCH(x) \
41113 - p->conf.x = s->x;
41114 static int mod_status_patch_connection(server *srv, connection *con, plugin_data *p) {
41116 plugin_config *s = p->config_storage[0];
41118 - PATCH(status_url);
41119 - PATCH(config_url);
41121 - PATCH(statistics_url);
41124 + PATCH_OPTION(status_url);
41125 + PATCH_OPTION(config_url);
41126 + PATCH_OPTION(sort);
41127 + PATCH_OPTION(statistics_url);
41129 /* skip the first, the global context */
41130 for (i = 1; i < srv->config_context->used; i++) {
41131 data_config *dc = (data_config *)srv->config_context->data[i];
41132 s = p->config_storage[i];
41135 /* condition didn't match */
41136 if (!config_check_cond(srv, con, dc)) continue;
41140 for (j = 0; j < dc->value->used; j++) {
41141 data_unset *du = dc->value->data[j];
41144 if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.status-url"))) {
41145 - PATCH(status_url);
41146 + PATCH_OPTION(status_url);
41147 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.config-url"))) {
41148 - PATCH(config_url);
41149 + PATCH_OPTION(config_url);
41150 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.enable-sort"))) {
41152 + PATCH_OPTION(sort);
41153 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.statistics-url"))) {
41154 - PATCH(statistics_url);
41156 + PATCH_OPTION(statistics_url);
41165 static handler_t mod_status_handler(server *srv, connection *con, void *p_d) {
41166 plugin_data *p = p_d;
41169 mod_status_patch_connection(srv, con, p);
41171 - if (!buffer_is_empty(p->conf.status_url) &&
41173 + if (!buffer_is_empty(p->conf.status_url) &&
41174 buffer_is_equal(p->conf.status_url, con->uri.path)) {
41175 return mod_status_handle_server_status(srv, con, p_d);
41176 - } else if (!buffer_is_empty(p->conf.config_url) &&
41177 + } else if (!buffer_is_empty(p->conf.config_url) &&
41178 buffer_is_equal(p->conf.config_url, con->uri.path)) {
41179 return mod_status_handle_server_config(srv, con, p_d);
41180 - } else if (!buffer_is_empty(p->conf.statistics_url) &&
41181 + } else if (!buffer_is_empty(p->conf.statistics_url) &&
41182 buffer_is_equal(p->conf.statistics_url, con->uri.path)) {
41183 return mod_status_handle_server_statistics(srv, con, p_d);
41187 return HANDLER_GO_ON;
41190 TRIGGER_FUNC(mod_status_trigger) {
41191 plugin_data *p = p_d;
41195 /* check all connections */
41196 for (i = 0; i < srv->conns->used; i++) {
41197 connection *c = srv->conns->ptr[i];
41200 p->bytes_written += c->bytes_written_cur_second;
41204 /* a sliding average */
41205 p->mod_5s_traffic_out[p->mod_5s_ndx] = p->bytes_written;
41206 p->mod_5s_requests [p->mod_5s_ndx] = p->requests;
41209 p->mod_5s_ndx = (p->mod_5s_ndx+1) % 5;
41212 p->abs_traffic_out += p->bytes_written;
41213 p->rel_traffic_out += p->bytes_written;
41216 p->bytes_written = 0;
41219 /* reset storage - second */
41220 p->traffic_out = 0;
41224 return HANDLER_GO_ON;
41227 REQUESTDONE_FUNC(mod_status_account) {
41228 plugin_data *p = p_d;
41238 p->bytes_written += con->bytes_written_cur_second;
41241 return HANDLER_GO_ON;
41244 int mod_status_plugin_init(plugin *p) {
41245 p->version = LIGHTTPD_VERSION_ID;
41246 p->name = buffer_init_string("status");
41249 p->init = mod_status_init;
41250 p->cleanup = mod_status_free;
41251 p->set_defaults= mod_status_set_defaults;
41254 p->handle_uri_clean = mod_status_handler;
41255 p->handle_trigger = mod_status_trigger;
41256 p->handle_request_done = mod_status_account;
41264 --- ../lighttpd-1.4.11/src/mod_trigger_b4_dl.c 2005-09-23 22:53:55.000000000 +0300
41265 +++ lighttpd-1.4.12/src/mod_trigger_b4_dl.c 2006-07-16 00:26:03.000000000 +0300
41266 @@ -24,18 +24,18 @@
41269 * this is a trigger_b4_dl for a lighttpd plugin
41274 /* plugin config for all request/connections */
41277 buffer *db_filename;
41280 buffer *trigger_url;
41281 buffer *download_url;
41286 buffer *mc_namespace;
41287 #if defined(HAVE_PCRE_H)
41288 @@ -46,58 +46,58 @@
41292 -#if defined(HAVE_MEMCACHE_H)
41293 +#if defined(HAVE_MEMCACHE_H)
41294 struct memcache *mc;
41298 unsigned short trigger_timeout;
41299 unsigned short debug;
41309 plugin_config **config_storage;
41311 - plugin_config conf;
41313 + plugin_config conf;
41316 /* init the plugin data */
41317 INIT_FUNC(mod_trigger_b4_dl_init) {
41321 p = calloc(1, sizeof(*p));
41324 p->tmp_buf = buffer_init();
41330 /* detroy the plugin data */
41331 FREE_FUNC(mod_trigger_b4_dl_free) {
41332 plugin_data *p = p_d;
41337 if (!p) return HANDLER_GO_ON;
41340 if (p->config_storage) {
41342 for (i = 0; i < srv->config_context->used; i++) {
41343 plugin_config *s = p->config_storage[i];
41348 buffer_free(s->db_filename);
41349 buffer_free(s->download_url);
41350 buffer_free(s->trigger_url);
41351 buffer_free(s->deny_url);
41354 buffer_free(s->mc_namespace);
41355 array_free(s->mc_hosts);
41358 #if defined(HAVE_PCRE_H)
41359 if (s->trigger_regex) pcre_free(s->trigger_regex);
41360 if (s->download_regex) pcre_free(s->download_regex);
41361 @@ -108,16 +108,16 @@
41362 #if defined(HAVE_MEMCACHE_H)
41363 if (s->mc) mc_free(s->mc);
41369 free(p->config_storage);
41373 buffer_free(p->tmp_buf);
41379 return HANDLER_GO_ON;
41382 @@ -126,9 +126,9 @@
41383 SETDEFAULTS_FUNC(mod_trigger_b4_dl_set_defaults) {
41384 plugin_data *p = p_d;
41388 - config_values_t cv[] = {
41391 + config_values_t cv[] = {
41392 { "trigger-before-download.gdbm-filename", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
41393 { "trigger-before-download.trigger-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
41394 { "trigger-before-download.download-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
41395 @@ -139,18 +139,18 @@
41396 { "trigger-before-download.debug", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 7 */
41397 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
41401 if (!p) return HANDLER_ERROR;
41404 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
41407 for (i = 0; i < srv->config_context->used; i++) {
41409 #if defined(HAVE_PCRE_H)
41410 const char *errptr;
41415 s = calloc(1, sizeof(plugin_config));
41416 s->db_filename = buffer_init();
41417 s->download_url = buffer_init();
41418 @@ -158,7 +158,7 @@
41419 s->deny_url = buffer_init();
41420 s->mc_hosts = array_init();
41421 s->mc_namespace = buffer_init();
41424 cv[0].destination = s->db_filename;
41425 cv[1].destination = s->trigger_url;
41426 cv[2].destination = s->download_url;
41427 @@ -167,41 +167,41 @@
41428 cv[5].destination = s->mc_hosts;
41429 cv[6].destination = s->mc_namespace;
41430 cv[7].destination = &(s->debug);
41433 p->config_storage[i] = s;
41436 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
41437 return HANDLER_ERROR;
41439 #if defined(HAVE_GDBM_H)
41440 if (!buffer_is_empty(s->db_filename)) {
41441 if (NULL == (s->db = gdbm_open(s->db_filename->ptr, 4096, GDBM_WRCREAT | GDBM_NOLOCK, S_IRUSR | S_IWUSR, 0))) {
41442 - log_error_write(srv, __FILE__, __LINE__, "s",
41443 + log_error_write(srv, __FILE__, __LINE__, "s",
41444 "gdbm-open failed");
41445 return HANDLER_ERROR;
41449 -#if defined(HAVE_PCRE_H)
41450 +#if defined(HAVE_PCRE_H)
41451 if (!buffer_is_empty(s->download_url)) {
41452 if (NULL == (s->download_regex = pcre_compile(s->download_url->ptr,
41453 0, &errptr, &erroff, NULL))) {
41455 - log_error_write(srv, __FILE__, __LINE__, "sbss",
41456 - "compiling regex for download-url failed:",
41458 + log_error_write(srv, __FILE__, __LINE__, "sbss",
41459 + "compiling regex for download-url failed:",
41460 s->download_url, "pos:", erroff);
41461 return HANDLER_ERROR;
41466 if (!buffer_is_empty(s->trigger_url)) {
41467 if (NULL == (s->trigger_regex = pcre_compile(s->trigger_url->ptr,
41468 0, &errptr, &erroff, NULL))) {
41470 - log_error_write(srv, __FILE__, __LINE__, "sbss",
41471 - "compiling regex for trigger-url failed:",
41473 + log_error_write(srv, __FILE__, __LINE__, "sbss",
41474 + "compiling regex for trigger-url failed:",
41475 s->trigger_url, "pos:", erroff);
41478 return HANDLER_ERROR;
41481 @@ -211,100 +211,97 @@
41482 #if defined(HAVE_MEMCACHE_H)
41487 for (k = 0; k < s->mc_hosts->used; k++) {
41488 data_string *ds = (data_string *)s->mc_hosts->data[k];
41491 if (0 != mc_server_add4(s->mc, ds->value->ptr)) {
41492 - log_error_write(srv, __FILE__, __LINE__, "sb",
41493 - "connection to host failed:",
41494 + log_error_write(srv, __FILE__, __LINE__, "sb",
41495 + "connection to host failed:",
41499 return HANDLER_ERROR;
41503 - log_error_write(srv, __FILE__, __LINE__, "s",
41504 + log_error_write(srv, __FILE__, __LINE__, "s",
41505 "memcache support is not compiled in but trigger-before-download.memcache-hosts is set, aborting");
41506 return HANDLER_ERROR;
41512 #if (!defined(HAVE_GDBM_H) && !defined(HAVE_MEMCACHE_H)) || !defined(HAVE_PCRE_H)
41513 - log_error_write(srv, __FILE__, __LINE__, "s",
41514 + log_error_write(srv, __FILE__, __LINE__, "s",
41515 "(either gdbm or libmemcache) and pcre are require, but were not found, aborting");
41516 return HANDLER_ERROR;
41521 return HANDLER_GO_ON;
41524 -#define PATCH(x) \
41525 - p->conf.x = s->x;
41526 static int mod_trigger_b4_dl_patch_connection(server *srv, connection *con, plugin_data *p) {
41528 plugin_config *s = p->config_storage[0];
41531 #if defined(HAVE_GDBM)
41534 + PATCH_OPTION(db);
41536 #if defined(HAVE_PCRE_H)
41537 - PATCH(download_regex);
41538 - PATCH(trigger_regex);
41540 - PATCH(trigger_timeout);
41542 - PATCH(mc_namespace);
41544 + PATCH_OPTION(download_regex);
41545 + PATCH_OPTION(trigger_regex);
41547 + PATCH_OPTION(trigger_timeout);
41548 + PATCH_OPTION(deny_url);
41549 + PATCH_OPTION(mc_namespace);
41550 + PATCH_OPTION(debug);
41551 #if defined(HAVE_MEMCACHE_H)
41553 + PATCH_OPTION(mc);
41557 /* skip the first, the global context */
41558 for (i = 1; i < srv->config_context->used; i++) {
41559 data_config *dc = (data_config *)srv->config_context->data[i];
41560 s = p->config_storage[i];
41563 /* condition didn't match */
41564 if (!config_check_cond(srv, con, dc)) continue;
41568 for (j = 0; j < dc->value->used; j++) {
41569 data_unset *du = dc->value->data[j];
41571 if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.download-url"))) {
41572 #if defined(HAVE_PCRE_H)
41573 - PATCH(download_regex);
41574 + PATCH_OPTION(download_regex);
41576 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.trigger-url"))) {
41577 # if defined(HAVE_PCRE_H)
41578 - PATCH(trigger_regex);
41579 + PATCH_OPTION(trigger_regex);
41581 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.gdbm-filename"))) {
41582 #if defined(HAVE_GDBM_H)
41584 + PATCH_OPTION(db);
41586 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.trigger-timeout"))) {
41587 - PATCH(trigger_timeout);
41588 + PATCH_OPTION(trigger_timeout);
41589 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.debug"))) {
41591 + PATCH_OPTION(debug);
41592 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.deny-url"))) {
41594 + PATCH_OPTION(deny_url);
41595 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.memcache-namespace"))) {
41596 - PATCH(mc_namespace);
41597 + PATCH_OPTION(mc_namespace);
41598 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.memcache-hosts"))) {
41599 #if defined(HAVE_MEMCACHE_H)
41601 + PATCH_OPTION(mc);
41612 URIHANDLER_FUNC(mod_trigger_b4_dl_uri_handler) {
41613 plugin_data *p = p_d;
41614 @@ -315,20 +312,20 @@
41620 if (con->uri.path->used == 0) return HANDLER_GO_ON;
41623 mod_trigger_b4_dl_patch_connection(srv, con, p);
41626 if (!p->conf.trigger_regex || !p->conf.download_regex) return HANDLER_GO_ON;
41629 # if !defined(HAVE_GDBM_H) && !defined(HAVE_MEMCACHE_H)
41630 return HANDLER_GO_ON;
41631 # elif defined(HAVE_GDBM_H) && defined(HAVE_MEMCACHE_H)
41632 if (!p->conf.db && !p->conf.mc) return HANDLER_GO_ON;
41633 if (p->conf.db && p->conf.mc) {
41634 /* can't decide which one */
41637 return HANDLER_GO_ON;
41639 # elif defined(HAVE_GDBM_H)
41640 @@ -336,12 +333,12 @@
41642 if (!p->conf.mc) return HANDLER_GO_ON;
41646 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "X-Forwarded-For"))) {
41647 /* X-Forwarded-For contains the ip behind the proxy */
41650 remote_ip = ds->value->ptr;
41653 /* memcache can't handle spaces */
41655 remote_ip = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
41656 @@ -350,13 +347,13 @@
41657 if (p->conf.debug) {
41658 log_error_write(srv, __FILE__, __LINE__, "ss", "(debug) remote-ip:", remote_ip);
41662 /* check if URL is a trigger -> insert IP into DB */
41663 if ((n = pcre_exec(p->conf.trigger_regex, NULL, con->uri.path->ptr, con->uri.path->used - 1, 0, 0, ovec, 3 * N)) < 0) {
41664 if (n != PCRE_ERROR_NOMATCH) {
41665 log_error_write(srv, __FILE__, __LINE__, "sd",
41666 "execution error while matching:", n);
41669 return HANDLER_ERROR;
41672 @@ -364,34 +361,34 @@
41674 /* the trigger matched */
41678 key.dptr = (char *)remote_ip;
41679 key.dsize = strlen(remote_ip);
41682 val.dptr = (char *)&(srv->cur_ts);
41683 val.dsize = sizeof(srv->cur_ts);
41686 if (0 != gdbm_store(p->conf.db, key, val, GDBM_REPLACE)) {
41687 log_error_write(srv, __FILE__, __LINE__, "s",
41692 -# if defined(HAVE_MEMCACHE_H)
41693 +# if defined(HAVE_MEMCACHE_H)
41696 buffer_copy_string_buffer(p->tmp_buf, p->conf.mc_namespace);
41697 buffer_append_string(p->tmp_buf, remote_ip);
41700 for (i = 0; i < p->tmp_buf->used - 1; i++) {
41701 if (p->tmp_buf->ptr[i] == ' ') p->tmp_buf->ptr[i] = '-';
41705 if (p->conf.debug) {
41706 log_error_write(srv, __FILE__, __LINE__, "sb", "(debug) triggered IP:", p->tmp_buf);
41709 - if (0 != mc_set(p->conf.mc,
41710 + if (0 != mc_set(p->conf.mc,
41711 CONST_BUF_LEN(p->tmp_buf),
41712 (char *)&(srv->cur_ts), sizeof(srv->cur_ts),
41713 p->conf.trigger_timeout, 0)) {
41714 @@ -401,7 +398,7 @@
41720 /* check if URL is a download -> check IP in DB, update timestamp */
41721 if ((n = pcre_exec(p->conf.download_regex, NULL, con->uri.path->ptr, con->uri.path->used - 1, 0, 0, ovec, 3 * N)) < 0) {
41722 if (n != PCRE_ERROR_NOMATCH) {
41723 @@ -411,93 +408,93 @@
41726 /* the download uri matched */
41727 -# if defined(HAVE_GDBM_H)
41728 +# if defined(HAVE_GDBM_H)
41734 key.dptr = (char *)remote_ip;
41735 key.dsize = strlen(remote_ip);
41738 val = gdbm_fetch(p->conf.db, key);
41741 if (val.dptr == NULL) {
41742 /* not found, redirect */
41745 response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->conf.deny_url));
41748 con->http_status = 307;
41751 return HANDLER_FINISHED;
41755 last_hit = *(time_t *)(val.dptr);
41761 if (srv->cur_ts - last_hit > p->conf.trigger_timeout) {
41762 /* found, but timeout, redirect */
41765 response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->conf.deny_url));
41766 con->http_status = 307;
41770 if (0 != gdbm_delete(p->conf.db, key)) {
41771 log_error_write(srv, __FILE__, __LINE__, "s",
41777 return HANDLER_FINISHED;
41781 val.dptr = (char *)&(srv->cur_ts);
41782 val.dsize = sizeof(srv->cur_ts);
41785 if (0 != gdbm_store(p->conf.db, key, val, GDBM_REPLACE)) {
41786 log_error_write(srv, __FILE__, __LINE__, "s",
41792 -# if defined(HAVE_MEMCACHE_H)
41794 +# if defined(HAVE_MEMCACHE_H)
41800 buffer_copy_string_buffer(p->tmp_buf, p->conf.mc_namespace);
41801 buffer_append_string(p->tmp_buf, remote_ip);
41804 for (i = 0; i < p->tmp_buf->used - 1; i++) {
41805 if (p->tmp_buf->ptr[i] == ' ') p->tmp_buf->ptr[i] = '-';
41809 if (p->conf.debug) {
41810 log_error_write(srv, __FILE__, __LINE__, "sb", "(debug) checking IP:", p->tmp_buf);
41816 * memcached is do expiration for us, as long as we can fetch it every thing is ok
41817 - * and the timestamp is updated
41819 + * and the timestamp is updated
41822 - if (NULL == (r = mc_aget(p->conf.mc,
41823 + if (NULL == (r = mc_aget(p->conf.mc,
41824 CONST_BUF_LEN(p->tmp_buf)
41828 response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->conf.deny_url));
41831 con->http_status = 307;
41834 return HANDLER_FINISHED;
41841 /* set a new timeout */
41842 - if (0 != mc_set(p->conf.mc,
41843 + if (0 != mc_set(p->conf.mc,
41844 CONST_BUF_LEN(p->tmp_buf),
41845 (char *)&(srv->cur_ts), sizeof(srv->cur_ts),
41846 p->conf.trigger_timeout, 0)) {
41847 @@ -507,13 +504,13 @@
41860 return HANDLER_GO_ON;
41863 @@ -521,21 +518,21 @@
41864 TRIGGER_FUNC(mod_trigger_b4_dl_handle_trigger) {
41865 plugin_data *p = p_d;
41869 /* check DB each minute */
41870 if (srv->cur_ts % 60 != 0) return HANDLER_GO_ON;
41874 for (i = 0; i < srv->config_context->used; i++) {
41875 plugin_config *s = p->config_storage[i];
41876 datum key, val, okey;
41879 if (!s->db) continue;
41884 - /* according to the manual this loop + delete does delete all entries on its way
41887 + /* according to the manual this loop + delete does delete all entries on its way
41889 * we don't care as the next round will remove them. We don't have to perfect here.
41891 for (key = gdbm_firstkey(s->db); key.dptr; key = gdbm_nextkey(s->db, okey)) {
41892 @@ -544,21 +541,21 @@
41898 val = gdbm_fetch(s->db, key);
41901 last_hit = *(time_t *)(val.dptr);
41907 if (srv->cur_ts - last_hit > s->trigger_timeout) {
41908 gdbm_delete(s->db, key);
41914 if (okey.dptr) free(okey.dptr);
41917 /* reorg once a day */
41918 if ((srv->cur_ts % (60 * 60 * 24) != 0)) gdbm_reorganize(s->db);
41920 @@ -571,7 +568,7 @@
41921 int mod_trigger_b4_dl_plugin_init(plugin *p) {
41922 p->version = LIGHTTPD_VERSION_ID;
41923 p->name = buffer_init_string("trigger_b4_dl");
41926 p->init = mod_trigger_b4_dl_init;
41927 p->handle_uri_clean = mod_trigger_b4_dl_uri_handler;
41928 p->set_defaults = mod_trigger_b4_dl_set_defaults;
41929 @@ -579,8 +576,8 @@
41930 p->handle_trigger = mod_trigger_b4_dl_handle_trigger;
41932 p->cleanup = mod_trigger_b4_dl_free;
41940 --- ../lighttpd-1.4.11/src/mod_userdir.c 2005-10-28 16:48:28.000000000 +0300
41941 +++ lighttpd-1.4.12/src/mod_userdir.c 2006-07-16 00:26:04.000000000 +0300
41943 #include "response.h"
41945 #include "plugin.h"
41946 +#include "sys-files.h"
41950 @@ -25,54 +26,54 @@
41960 plugin_config **config_storage;
41962 - plugin_config conf;
41964 + plugin_config conf;
41967 /* init the plugin data */
41968 INIT_FUNC(mod_userdir_init) {
41972 p = calloc(1, sizeof(*p));
41975 p->username = buffer_init();
41976 p->temp_path = buffer_init();
41982 /* detroy the plugin data */
41983 FREE_FUNC(mod_userdir_free) {
41984 plugin_data *p = p_d;
41987 if (!p) return HANDLER_GO_ON;
41990 if (p->config_storage) {
41994 for (i = 0; i < srv->config_context->used; i++) {
41995 plugin_config *s = p->config_storage[i];
41998 array_free(s->include_user);
41999 array_free(s->exclude_user);
42000 buffer_free(s->path);
42001 buffer_free(s->basepath);
42006 free(p->config_storage);
42010 buffer_free(p->username);
42011 buffer_free(p->temp_path);
42017 return HANDLER_GO_ON;
42020 @@ -81,81 +82,78 @@
42021 SETDEFAULTS_FUNC(mod_userdir_set_defaults) {
42022 plugin_data *p = p_d;
42025 - config_values_t cv[] = {
42027 + config_values_t cv[] = {
42028 { "userdir.path", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
42029 { "userdir.exclude-user", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
42030 { "userdir.include-user", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
42031 { "userdir.basepath", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
42032 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
42036 if (!p) return HANDLER_ERROR;
42039 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
42042 for (i = 0; i < srv->config_context->used; i++) {
42046 s = calloc(1, sizeof(plugin_config));
42047 s->exclude_user = array_init();
42048 s->include_user = array_init();
42049 s->path = buffer_init();
42050 s->basepath = buffer_init();
42053 cv[0].destination = s->path;
42054 cv[1].destination = s->exclude_user;
42055 cv[2].destination = s->include_user;
42056 cv[3].destination = s->basepath;
42059 p->config_storage[i] = s;
42062 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
42063 return HANDLER_ERROR;
42068 return HANDLER_GO_ON;
42071 -#define PATCH(x) \
42072 - p->conf.x = s->x;
42073 static int mod_userdir_patch_connection(server *srv, connection *con, plugin_data *p) {
42075 plugin_config *s = p->config_storage[0];
42078 - PATCH(exclude_user);
42079 - PATCH(include_user);
42083 + PATCH_OPTION(path);
42084 + PATCH_OPTION(exclude_user);
42085 + PATCH_OPTION(include_user);
42086 + PATCH_OPTION(basepath);
42088 /* skip the first, the global context */
42089 for (i = 1; i < srv->config_context->used; i++) {
42090 data_config *dc = (data_config *)srv->config_context->data[i];
42091 s = p->config_storage[i];
42094 /* condition didn't match */
42095 if (!config_check_cond(srv, con, dc)) continue;
42099 for (j = 0; j < dc->value->used; j++) {
42100 data_unset *du = dc->value->data[j];
42103 if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.path"))) {
42105 + PATCH_OPTION(path);
42106 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.exclude-user"))) {
42107 - PATCH(exclude_user);
42108 + PATCH_OPTION(exclude_user);
42109 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.include-user"))) {
42110 - PATCH(include_user);
42111 + PATCH_OPTION(include_user);
42112 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.basepath"))) {
42114 + PATCH_OPTION(basepath);
42124 URIHANDLER_FUNC(mod_userdir_docroot_handler) {
42125 plugin_data *p = p_d;
42126 @@ -169,18 +167,18 @@
42127 if (con->uri.path->used == 0) return HANDLER_GO_ON;
42129 mod_userdir_patch_connection(srv, con, p);
42132 uri_len = con->uri.path->used - 1;
42135 /* /~user/foo.html -> /home/user/public_html/foo.html */
42138 if (con->uri.path->ptr[0] != '/' ||
42139 con->uri.path->ptr[1] != '~') return HANDLER_GO_ON;
42142 if (NULL == (rel_url = strchr(con->uri.path->ptr + 2, '/'))) {
42143 /* / is missing -> redirect to .../ as we are a user - DIRECTORY ! :) */
42144 http_response_redirect_to_directory(srv, con);
42147 return HANDLER_FINISHED;
42150 @@ -188,10 +186,10 @@
42151 if (0 == rel_url - (con->uri.path->ptr + 2)) {
42152 return HANDLER_GO_ON;
42156 buffer_copy_string_len(p->username, con->uri.path->ptr + 2, rel_url - (con->uri.path->ptr + 2));
42158 - if (buffer_is_empty(p->conf.basepath)
42160 + if (buffer_is_empty(p->conf.basepath)
42162 && NULL == (pwd = getpwnam(p->username->ptr))
42164 @@ -200,31 +198,31 @@
42165 return HANDLER_GO_ON;
42170 for (k = 0; k < p->conf.exclude_user->used; k++) {
42171 data_string *ds = (data_string *)p->conf.exclude_user->data[k];
42174 if (buffer_is_equal(ds->value, p->username)) {
42175 /* user in exclude list */
42176 return HANDLER_GO_ON;
42181 if (p->conf.include_user->used) {
42182 int found_user = 0;
42183 for (k = 0; k < p->conf.include_user->used; k++) {
42184 data_string *ds = (data_string *)p->conf.include_user->data[k];
42187 if (buffer_is_equal(ds->value, p->username)) {
42188 /* user in include list */
42195 if (!found_user) return HANDLER_GO_ON;
42199 /* we build the physical path */
42201 if (buffer_is_empty(p->conf.basepath)) {
42202 @@ -252,23 +250,23 @@
42205 buffer_copy_string_buffer(p->temp_path, p->conf.basepath);
42206 - BUFFER_APPEND_SLASH(p->temp_path);
42207 + PATHNAME_APPEND_SLASH(p->temp_path);
42208 buffer_append_string_buffer(p->temp_path, p->username);
42210 - BUFFER_APPEND_SLASH(p->temp_path);
42211 - buffer_append_string_buffer(p->temp_path, p->conf.path);
42212 + PATHNAME_APPEND_SLASH(p->temp_path);
42213 + buffer_append_string_buffer(p->temp_path, p->conf.path);
42215 if (buffer_is_empty(p->conf.basepath)) {
42220 ret = stat(p->temp_path->ptr, &st);
42221 if (ret < 0 || S_ISDIR(st.st_mode) != 1) {
42222 return HANDLER_GO_ON;
42227 - BUFFER_APPEND_SLASH(p->temp_path);
42228 + PATHNAME_APPEND_SLASH(p->temp_path);
42229 buffer_append_string(p->temp_path, rel_url + 1); /* skip the / */
42230 buffer_copy_string_buffer(con->physical.path, p->temp_path);
42232 @@ -282,13 +280,13 @@
42233 int mod_userdir_plugin_init(plugin *p) {
42234 p->version = LIGHTTPD_VERSION_ID;
42235 p->name = buffer_init_string("userdir");
42238 p->init = mod_userdir_init;
42239 p->handle_physical = mod_userdir_docroot_handler;
42240 p->set_defaults = mod_userdir_set_defaults;
42241 p->cleanup = mod_userdir_free;
42249 --- ../lighttpd-1.4.11/src/mod_usertrack.c 2006-01-31 15:01:20.000000000 +0200
42250 +++ lighttpd-1.4.12/src/mod_usertrack.c 2006-07-16 00:26:04.000000000 +0300
42251 @@ -24,44 +24,44 @@
42257 plugin_config **config_storage;
42259 - plugin_config conf;
42261 + plugin_config conf;
42264 /* init the plugin data */
42265 INIT_FUNC(mod_usertrack_init) {
42269 p = calloc(1, sizeof(*p));
42275 /* detroy the plugin data */
42276 FREE_FUNC(mod_usertrack_free) {
42277 plugin_data *p = p_d;
42283 if (!p) return HANDLER_GO_ON;
42286 if (p->config_storage) {
42288 for (i = 0; i < srv->config_context->used; i++) {
42289 plugin_config *s = p->config_storage[i];
42292 buffer_free(s->cookie_name);
42293 buffer_free(s->cookie_domain);
42298 free(p->config_storage);
42305 return HANDLER_GO_ON;
42308 @@ -70,38 +70,38 @@
42309 SETDEFAULTS_FUNC(mod_usertrack_set_defaults) {
42310 plugin_data *p = p_d;
42313 - config_values_t cv[] = {
42315 + config_values_t cv[] = {
42316 { "usertrack.cookie-name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
42317 { "usertrack.cookie-max-age", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
42318 { "usertrack.cookie-domain", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
42320 - { "usertrack.cookiename", NULL, T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_CONNECTION },
42322 + { "usertrack.cookiename", NULL, T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_CONNECTION },
42323 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
42327 if (!p) return HANDLER_ERROR;
42330 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
42333 for (i = 0; i < srv->config_context->used; i++) {
42337 s = calloc(1, sizeof(plugin_config));
42338 s->cookie_name = buffer_init();
42339 s->cookie_domain = buffer_init();
42340 s->cookie_max_age = 0;
42343 cv[0].destination = s->cookie_name;
42344 cv[1].destination = &(s->cookie_max_age);
42345 cv[2].destination = s->cookie_domain;
42348 p->config_storage[i] = s;
42351 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
42352 return HANDLER_ERROR;
42356 if (buffer_is_empty(s->cookie_name)) {
42357 buffer_copy_string(s->cookie_name, "TRACKID");
42359 @@ -109,68 +109,65 @@
42360 for (j = 0; j < s->cookie_name->used - 1; j++) {
42361 char c = s->cookie_name->ptr[j] | 32;
42362 if (c < 'a' || c > 'z') {
42363 - log_error_write(srv, __FILE__, __LINE__, "sb",
42364 - "invalid character in usertrack.cookie-name:",
42365 + log_error_write(srv, __FILE__, __LINE__, "sb",
42366 + "invalid character in usertrack.cookie-name:",
42370 return HANDLER_ERROR;
42376 if (!buffer_is_empty(s->cookie_domain)) {
42378 for (j = 0; j < s->cookie_domain->used - 1; j++) {
42379 char c = s->cookie_domain->ptr[j];
42380 if (c <= 32 || c >= 127 || c == '"' || c == '\\') {
42381 - log_error_write(srv, __FILE__, __LINE__, "sb",
42382 - "invalid character in usertrack.cookie-domain:",
42383 + log_error_write(srv, __FILE__, __LINE__, "sb",
42384 + "invalid character in usertrack.cookie-domain:",
42388 return HANDLER_ERROR;
42395 return HANDLER_GO_ON;
42398 -#define PATCH(x) \
42399 - p->conf.x = s->x;
42400 static int mod_usertrack_patch_connection(server *srv, connection *con, plugin_data *p) {
42402 plugin_config *s = p->config_storage[0];
42404 - PATCH(cookie_name);
42405 - PATCH(cookie_domain);
42406 - PATCH(cookie_max_age);
42409 + PATCH_OPTION(cookie_name);
42410 + PATCH_OPTION(cookie_domain);
42411 + PATCH_OPTION(cookie_max_age);
42413 /* skip the first, the global context */
42414 for (i = 1; i < srv->config_context->used; i++) {
42415 data_config *dc = (data_config *)srv->config_context->data[i];
42416 s = p->config_storage[i];
42419 /* condition didn't match */
42420 if (!config_check_cond(srv, con, dc)) continue;
42424 for (j = 0; j < dc->value->used; j++) {
42425 data_unset *du = dc->value->data[j];
42428 if (buffer_is_equal_string(du->key, CONST_STR_LEN("usertrack.cookie-name"))) {
42429 - PATCH(cookie_name);
42430 + PATCH_OPTION(cookie_name);
42431 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("usertrack.cookie-max-age"))) {
42432 - PATCH(cookie_max_age);
42433 + PATCH_OPTION(cookie_max_age);
42434 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("usertrack.cookie-domain"))) {
42435 - PATCH(cookie_domain);
42436 + PATCH_OPTION(cookie_domain);
42446 URIHANDLER_FUNC(mod_usertrack_uri_handler) {
42447 plugin_data *p = p_d;
42448 @@ -178,38 +175,38 @@
42449 unsigned char h[16];
42454 if (con->uri.path->used == 0) return HANDLER_GO_ON;
42457 mod_usertrack_patch_connection(srv, con, p);
42460 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Cookie"))) {
42462 /* we have a cookie, does it contain a valid name ? */
42464 - /* parse the cookie
42467 + /* parse the cookie
42469 * check for cookiename + (WS | '=')
42475 if (NULL != (g = strstr(ds->value->ptr, p->conf.cookie_name->ptr))) {
42480 for (nc = g + p->conf.cookie_name->used-1; *nc == ' ' || *nc == '\t'; nc++);
42484 /* ok, found the key of our own cookie */
42487 if (strlen(nc) > 32) {
42489 return HANDLER_GO_ON;
42498 if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
42499 ds = data_response_init();
42500 @@ -217,39 +214,39 @@
42501 buffer_copy_string(ds->key, "Set-Cookie");
42502 buffer_copy_string_buffer(ds->value, p->conf.cookie_name);
42503 buffer_append_string(ds->value, "=");
42507 /* taken from mod_auth.c */
42510 /* generate shared-secret */
42512 MD5_Update(&Md5Ctx, (unsigned char *)con->uri.path->ptr, con->uri.path->used - 1);
42513 MD5_Update(&Md5Ctx, (unsigned char *)"+", 1);
42516 /* we assume sizeof(time_t) == 4 here, but if not it ain't a problem at all */
42517 ltostr(hh, srv->cur_ts);
42518 MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
42519 ltostr(hh, rand());
42520 MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
42523 MD5_Final(h, &Md5Ctx);
42526 buffer_append_string_encoded(ds->value, (char *)h, 16, ENCODING_HEX);
42527 buffer_append_string(ds->value, "; Path=/");
42528 buffer_append_string(ds->value, "; Version=1");
42531 if (!buffer_is_empty(p->conf.cookie_domain)) {
42532 buffer_append_string(ds->value, "; Domain=");
42533 buffer_append_string_encoded(ds->value, CONST_BUF_LEN(p->conf.cookie_domain), ENCODING_REL_URI);
42537 if (p->conf.cookie_max_age) {
42538 buffer_append_string(ds->value, "; max-age=");
42539 buffer_append_long(ds->value, p->conf.cookie_max_age);
42543 array_insert_unique(con->response.headers, (data_unset *)ds);
42546 return HANDLER_GO_ON;
42549 @@ -258,13 +255,13 @@
42550 int mod_usertrack_plugin_init(plugin *p) {
42551 p->version = LIGHTTPD_VERSION_ID;
42552 p->name = buffer_init_string("usertrack");
42555 p->init = mod_usertrack_init;
42556 p->handle_uri_clean = mod_usertrack_uri_handler;
42557 p->set_defaults = mod_usertrack_set_defaults;
42558 p->cleanup = mod_usertrack_free;
42566 --- ../lighttpd-1.4.11/src/mod_webdav.c 2006-03-03 01:28:58.000000000 +0200
42567 +++ lighttpd-1.4.12/src/mod_webdav.c 2006-07-18 13:03:40.000000000 +0300
42570 #include <stdlib.h>
42571 #include <string.h>
42572 -#include <dirent.h>
42574 -#include <unistd.h>
42577 #include <assert.h>
42578 -#include <sys/mman.h>
42580 #ifdef HAVE_CONFIG_H
42581 #include "config.h"
42583 #include <sqlite3.h>
42586 +#if defined(HAVE_LIBXML_H) && defined(HAVE_SQLITE3_H) && defined(HAVE_UUID_H)
42588 +#include <uuid/uuid.h>
42593 #include "buffer.h"
42594 @@ -33,13 +35,16 @@
42595 #include "stream.h"
42596 #include "stat_cache.h"
42598 +#include "sys-files.h"
42599 +#include "sys-mmap.h"
42600 +#include "sys-strings.h"
42603 * this is a webdav for a lighttpd plugin
42605 - * at least a very basic one.
42606 + * at least a very basic one.
42607 * - for now it is read-only and we only support PROPFIND
42613 @@ -58,64 +63,70 @@
42614 sqlite3_stmt *stmt_delete_prop;
42615 sqlite3_stmt *stmt_select_prop;
42616 sqlite3_stmt *stmt_select_propnames;
42619 sqlite3_stmt *stmt_delete_uri;
42620 sqlite3_stmt *stmt_move_uri;
42621 sqlite3_stmt *stmt_copy_uri;
42623 + sqlite3_stmt *stmt_remove_lock;
42624 + sqlite3_stmt *stmt_create_lock;
42625 + sqlite3_stmt *stmt_read_lock;
42626 + sqlite3_stmt *stmt_read_lock_by_uri;
42627 + sqlite3_stmt *stmt_refresh_lock;
42639 plugin_config **config_storage;
42641 - plugin_config conf;
42643 + plugin_config conf;
42646 /* init the plugin data */
42647 INIT_FUNC(mod_webdav_init) {
42651 p = calloc(1, sizeof(*p));
42654 p->tmp_buf = buffer_init();
42656 p->uri.scheme = buffer_init();
42657 p->uri.path_raw = buffer_init();
42658 p->uri.path = buffer_init();
42659 p->uri.authority = buffer_init();
42662 p->physical.path = buffer_init();
42663 p->physical.rel_path = buffer_init();
42664 p->physical.doc_root = buffer_init();
42665 p->physical.basedir = buffer_init();
42671 /* detroy the plugin data */
42672 FREE_FUNC(mod_webdav_free) {
42673 plugin_data *p = p_d;
42678 if (!p) return HANDLER_GO_ON;
42681 if (p->config_storage) {
42683 for (i = 0; i < srv->config_context->used; i++) {
42684 plugin_config *s = p->config_storage[i];
42689 buffer_free(s->sqlite_db_name);
42690 #ifdef USE_PROPPATCH
42693 sqlite3_finalize(s->stmt_delete_prop);
42694 sqlite3_finalize(s->stmt_delete_uri);
42695 sqlite3_finalize(s->stmt_copy_uri);
42696 @@ -123,9 +134,15 @@
42697 sqlite3_finalize(s->stmt_update_prop);
42698 sqlite3_finalize(s->stmt_select_prop);
42699 sqlite3_finalize(s->stmt_select_propnames);
42701 + sqlite3_finalize(s->stmt_read_lock);
42702 + sqlite3_finalize(s->stmt_read_lock_by_uri);
42703 + sqlite3_finalize(s->stmt_create_lock);
42704 + sqlite3_finalize(s->stmt_remove_lock);
42705 + sqlite3_finalize(s->stmt_refresh_lock);
42706 sqlite3_close(s->sql);
42712 free(p->config_storage);
42713 @@ -135,16 +152,16 @@
42714 buffer_free(p->uri.path_raw);
42715 buffer_free(p->uri.path);
42716 buffer_free(p->uri.authority);
42719 buffer_free(p->physical.path);
42720 buffer_free(p->physical.rel_path);
42721 buffer_free(p->physical.doc_root);
42722 buffer_free(p->physical.basedir);
42725 buffer_free(p->tmp_buf);
42731 return HANDLER_GO_ON;
42734 @@ -153,32 +170,32 @@
42735 SETDEFAULTS_FUNC(mod_webdav_set_defaults) {
42736 plugin_data *p = p_d;
42739 - config_values_t cv[] = {
42741 + config_values_t cv[] = {
42742 { "webdav.activate", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
42743 { "webdav.is-readonly", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
42744 { "webdav.sqlite-db-name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
42745 { "webdav.log-xml", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
42746 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
42750 if (!p) return HANDLER_ERROR;
42753 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
42756 for (i = 0; i < srv->config_context->used; i++) {
42760 s = calloc(1, sizeof(plugin_config));
42761 s->sqlite_db_name = buffer_init();
42764 cv[0].destination = &(s->enabled);
42765 cv[1].destination = &(s->is_readonly);
42766 cv[2].destination = s->sqlite_db_name;
42767 cv[3].destination = &(s->log_xml);
42770 p->config_storage[i] = s;
42773 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
42774 return HANDLER_ERROR;
42776 @@ -193,8 +210,26 @@
42777 return HANDLER_ERROR;
42780 - if (SQLITE_OK != sqlite3_prepare(s->sql,
42781 - CONST_STR_LEN("SELECT value FROM properties WHERE resource = ? AND prop = ? AND ns = ?"),
42782 + if (SQLITE_OK != sqlite3_exec(s->sql,
42783 + "CREATE TABLE properties ("
42784 + " resource TEXT NOT NULL,"
42785 + " prop TEXT NOT NULL,"
42786 + " ns TEXT NOT NULL,"
42787 + " value TEXT NOT NULL,"
42788 + " PRIMARY KEY(resource, prop, ns))",
42789 + NULL, NULL, &err)) {
42791 + if (0 != strcmp(err, "table properties already exists")) {
42792 + log_error_write(srv, __FILE__, __LINE__, "ss", "can't open transaction:", err);
42793 + sqlite3_free(err);
42795 + return HANDLER_ERROR;
42797 + sqlite3_free(err);
42800 + if (SQLITE_OK != sqlite3_prepare(s->sql,
42801 + CONST_STR_LEN("SELECT value FROM properties WHERE resource = ? AND prop = ? AND ns = ?"),
42802 &(s->stmt_select_prop), &next_stmt)) {
42803 /* prepare failed */
42805 @@ -202,8 +237,8 @@
42806 return HANDLER_ERROR;
42809 - if (SQLITE_OK != sqlite3_prepare(s->sql,
42810 - CONST_STR_LEN("SELECT ns, prop FROM properties WHERE resource = ?"),
42811 + if (SQLITE_OK != sqlite3_prepare(s->sql,
42812 + CONST_STR_LEN("SELECT ns, prop FROM properties WHERE resource = ?"),
42813 &(s->stmt_select_propnames), &next_stmt)) {
42814 /* prepare failed */
42816 @@ -211,16 +246,67 @@
42817 return HANDLER_ERROR;
42820 - if (SQLITE_OK != sqlite3_exec(s->sql,
42821 - "CREATE TABLE properties ("
42823 + if (SQLITE_OK != sqlite3_prepare(s->sql,
42824 + CONST_STR_LEN("REPLACE INTO properties (resource, prop, ns, value) VALUES (?, ?, ?, ?)"),
42825 + &(s->stmt_update_prop), &next_stmt)) {
42826 + /* prepare failed */
42828 + log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed:", sqlite3_errmsg(s->sql));
42829 + return HANDLER_ERROR;
42832 + if (SQLITE_OK != sqlite3_prepare(s->sql,
42833 + CONST_STR_LEN("DELETE FROM properties WHERE resource = ? AND prop = ? AND ns = ?"),
42834 + &(s->stmt_delete_prop), &next_stmt)) {
42835 + /* prepare failed */
42836 + log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
42838 + return HANDLER_ERROR;
42841 + if (SQLITE_OK != sqlite3_prepare(s->sql,
42842 + CONST_STR_LEN("DELETE FROM properties WHERE resource = ?"),
42843 + &(s->stmt_delete_uri), &next_stmt)) {
42844 + /* prepare failed */
42845 + log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
42847 + return HANDLER_ERROR;
42850 + if (SQLITE_OK != sqlite3_prepare(s->sql,
42851 + CONST_STR_LEN("INSERT INTO properties SELECT ?, prop, ns, value FROM properties WHERE resource = ?"),
42852 + &(s->stmt_copy_uri), &next_stmt)) {
42853 + /* prepare failed */
42854 + log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
42856 + return HANDLER_ERROR;
42859 + if (SQLITE_OK != sqlite3_prepare(s->sql,
42860 + CONST_STR_LEN("UPDATE properties SET resource = ? WHERE resource = ?"),
42861 + &(s->stmt_move_uri), &next_stmt)) {
42862 + /* prepare failed */
42863 + log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
42865 + return HANDLER_ERROR;
42870 + if (SQLITE_OK != sqlite3_exec(s->sql,
42871 + "CREATE TABLE locks ("
42872 + " locktoken TEXT NOT NULL,"
42873 " resource TEXT NOT NULL,"
42874 - " prop TEXT NOT NULL,"
42875 - " ns TEXT NOT NULL,"
42876 - " value TEXT NOT NULL,"
42877 - " PRIMARY KEY(resource, prop, ns))",
42878 + " lockscope TEXT NOT NULL,"
42879 + " locktype TEXT NOT NULL,"
42880 + " owner TEXT NOT NULL,"
42881 + " depth INT NOT NULL,"
42882 + " timeout TIMESTAMP NOT NULL,"
42883 + " PRIMARY KEY(locktoken))",
42884 NULL, NULL, &err)) {
42886 - if (0 != strcmp(err, "table properties already exists")) {
42887 + if (0 != strcmp(err, "table locks already exists")) {
42888 log_error_write(srv, __FILE__, __LINE__, "ss", "can't open transaction:", err);
42891 @@ -228,127 +314,138 @@
42896 - if (SQLITE_OK != sqlite3_prepare(s->sql,
42897 - CONST_STR_LEN("REPLACE INTO properties (resource, prop, ns, value) VALUES (?, ?, ?, ?)"),
42898 - &(s->stmt_update_prop), &next_stmt)) {
42900 + if (SQLITE_OK != sqlite3_prepare(s->sql,
42901 + CONST_STR_LEN("INSERT INTO locks (locktoken, resource, lockscope, locktype, owner, depth, timeout) VALUES (?,?,?,?,?,?, CURRENT_TIME + 600)"),
42902 + &(s->stmt_create_lock), &next_stmt)) {
42903 /* prepare failed */
42904 + log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
42906 - log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed:", sqlite3_errmsg(s->sql));
42907 return HANDLER_ERROR;
42910 - if (SQLITE_OK != sqlite3_prepare(s->sql,
42911 - CONST_STR_LEN("DELETE FROM properties WHERE resource = ? AND prop = ? AND ns = ?"),
42912 - &(s->stmt_delete_prop), &next_stmt)) {
42913 + if (SQLITE_OK != sqlite3_prepare(s->sql,
42914 + CONST_STR_LEN("DELETE FROM locks WHERE locktoken = ?"),
42915 + &(s->stmt_remove_lock), &next_stmt)) {
42916 /* prepare failed */
42917 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
42919 return HANDLER_ERROR;
42922 - if (SQLITE_OK != sqlite3_prepare(s->sql,
42923 - CONST_STR_LEN("DELETE FROM properties WHERE resource = ?"),
42924 - &(s->stmt_delete_uri), &next_stmt)) {
42925 + if (SQLITE_OK != sqlite3_prepare(s->sql,
42926 + CONST_STR_LEN("SELECT locktoken, resource, lockscope, locktype, owner, depth, timeout FROM locks WHERE locktoken = ?"),
42927 + &(s->stmt_read_lock), &next_stmt)) {
42928 /* prepare failed */
42929 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
42931 return HANDLER_ERROR;
42934 - if (SQLITE_OK != sqlite3_prepare(s->sql,
42935 - CONST_STR_LEN("INSERT INTO properties SELECT ?, prop, ns, value FROM properties WHERE resource = ?"),
42936 - &(s->stmt_copy_uri), &next_stmt)) {
42937 + if (SQLITE_OK != sqlite3_prepare(s->sql,
42938 + CONST_STR_LEN("SELECT locktoken, resource, lockscope, locktype, owner, depth, timeout FROM locks WHERE resource = ?"),
42939 + &(s->stmt_read_lock_by_uri), &next_stmt)) {
42940 /* prepare failed */
42941 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
42943 return HANDLER_ERROR;
42946 - if (SQLITE_OK != sqlite3_prepare(s->sql,
42947 - CONST_STR_LEN("UPDATE properties SET resource = ? WHERE resource = ?"),
42948 - &(s->stmt_move_uri), &next_stmt)) {
42949 + if (SQLITE_OK != sqlite3_prepare(s->sql,
42950 + CONST_STR_LEN("UPDATE locks SET timeout = CURRENT_TIME + 600 WHERE locktoken = ?"),
42951 + &(s->stmt_refresh_lock), &next_stmt)) {
42952 /* prepare failed */
42953 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
42955 return HANDLER_ERROR;
42960 log_error_write(srv, __FILE__, __LINE__, "s", "Sorry, no sqlite3 and libxml2 support include, compile with --with-webdav-props");
42961 return HANDLER_ERROR;
42967 return HANDLER_GO_ON;
42970 -#define PATCH(x) \
42971 - p->conf.x = s->x;
42972 static int mod_webdav_patch_connection(server *srv, connection *con, plugin_data *p) {
42974 plugin_config *s = p->config_storage[0];
42977 - PATCH(is_readonly);
42981 + PATCH_OPTION(enabled);
42982 + PATCH_OPTION(is_readonly);
42983 + PATCH_OPTION(log_xml);
42985 #ifdef USE_PROPPATCH
42987 - PATCH(stmt_update_prop);
42988 - PATCH(stmt_delete_prop);
42989 - PATCH(stmt_select_prop);
42990 - PATCH(stmt_select_propnames);
42992 - PATCH(stmt_delete_uri);
42993 - PATCH(stmt_move_uri);
42994 - PATCH(stmt_copy_uri);
42995 + PATCH_OPTION(sql);
42996 + PATCH_OPTION(stmt_update_prop);
42997 + PATCH_OPTION(stmt_delete_prop);
42998 + PATCH_OPTION(stmt_select_prop);
42999 + PATCH_OPTION(stmt_select_propnames);
43001 + PATCH_OPTION(stmt_delete_uri);
43002 + PATCH_OPTION(stmt_move_uri);
43003 + PATCH_OPTION(stmt_copy_uri);
43005 + PATCH_OPTION(stmt_remove_lock);
43006 + PATCH_OPTION(stmt_refresh_lock);
43007 + PATCH_OPTION(stmt_create_lock);
43008 + PATCH_OPTION(stmt_read_lock);
43009 + PATCH_OPTION(stmt_read_lock_by_uri);
43011 /* skip the first, the global context */
43012 for (i = 1; i < srv->config_context->used; i++) {
43013 data_config *dc = (data_config *)srv->config_context->data[i];
43014 s = p->config_storage[i];
43017 /* condition didn't match */
43018 if (!config_check_cond(srv, con, dc)) continue;
43022 for (j = 0; j < dc->value->used; j++) {
43023 data_unset *du = dc->value->data[j];
43026 if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.activate"))) {
43028 + PATCH_OPTION(enabled);
43029 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.is-readonly"))) {
43030 - PATCH(is_readonly);
43031 + PATCH_OPTION(is_readonly);
43032 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.log-xml"))) {
43034 + PATCH_OPTION(log_xml);
43035 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.sqlite-db-name"))) {
43036 #ifdef USE_PROPPATCH
43038 - PATCH(stmt_update_prop);
43039 - PATCH(stmt_delete_prop);
43040 - PATCH(stmt_select_prop);
43041 - PATCH(stmt_select_propnames);
43043 - PATCH(stmt_delete_uri);
43044 - PATCH(stmt_move_uri);
43045 - PATCH(stmt_copy_uri);
43046 + PATCH_OPTION(sql);
43047 + PATCH_OPTION(stmt_update_prop);
43048 + PATCH_OPTION(stmt_delete_prop);
43049 + PATCH_OPTION(stmt_select_prop);
43050 + PATCH_OPTION(stmt_select_propnames);
43052 + PATCH_OPTION(stmt_delete_uri);
43053 + PATCH_OPTION(stmt_move_uri);
43054 + PATCH_OPTION(stmt_copy_uri);
43056 + PATCH_OPTION(stmt_remove_lock);
43057 + PATCH_OPTION(stmt_refresh_lock);
43058 + PATCH_OPTION(stmt_create_lock);
43059 + PATCH_OPTION(stmt_read_lock);
43060 + PATCH_OPTION(stmt_read_lock_by_uri);
43071 URIHANDLER_FUNC(mod_webdav_uri_handler) {
43072 plugin_data *p = p_d;
43077 if (con->uri.path->used == 0) return HANDLER_GO_ON;
43080 mod_webdav_patch_connection(srv, con, p);
43082 if (!p->conf.enabled) return HANDLER_GO_ON;
43083 @@ -362,20 +459,20 @@
43084 if (p->conf.is_readonly) {
43085 response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("PROPFIND"));
43087 - response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("PROPFIND, DELETE, MKCOL, PUT, MOVE, COPY, PROPPATCH"));
43088 + response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("PROPFIND, DELETE, MKCOL, PUT, MOVE, COPY, PROPPATCH, LOCK, UNLOCK"));
43097 return HANDLER_GO_ON;
43099 -static int webdav_gen_prop_tag(server *srv, connection *con,
43103 +static int webdav_gen_prop_tag(server *srv, connection *con,
43110 @@ -414,7 +511,7 @@
43111 buffer_append_string_buffer(b, dst->rel_path);
43112 buffer_append_string(b,"</D:href>\n");
43113 buffer_append_string(b,"<D:status>\n");
43116 if (con->request.http_version == HTTP_VERSION_1_1) {
43117 BUFFER_COPY_STRING_CONST(b, "HTTP/1.1 ");
43119 @@ -458,14 +555,13 @@
43121 /* bind the values to the insert */
43123 - sqlite3_bind_text(stmt, 1,
43124 - dst->rel_path->ptr,
43125 + sqlite3_bind_text(stmt, 1,
43126 + dst->rel_path->ptr,
43127 dst->rel_path->used - 1,
43131 if (SQLITE_DONE != sqlite3_step(stmt)) {
43137 @@ -493,14 +589,14 @@
43138 (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')) {
43140 /* ignore the parent dir */
43144 buffer_copy_string_buffer(d.path, dst->path);
43145 - BUFFER_APPEND_SLASH(d.path);
43146 + PATHNAME_APPEND_SLASH(d.path);
43147 buffer_append_string(d.path, de->d_name);
43150 buffer_copy_string_buffer(d.rel_path, dst->rel_path);
43151 - BUFFER_APPEND_SLASH(d.rel_path);
43152 + PATHNAME_APPEND_SLASH(d.rel_path);
43153 buffer_append_string(d.rel_path, de->d_name);
43155 /* stat and unlink afterwards */
43156 @@ -508,7 +604,7 @@
43157 /* don't about it yet, rmdir will fail too */
43158 } else if (S_ISDIR(st.st_mode)) {
43159 have_multi_status = webdav_delete_dir(srv, con, p, &d, b);
43162 /* try to unlink it */
43163 if (-1 == rmdir(d.path->ptr)) {
43165 @@ -535,14 +631,13 @@
43167 /* bind the values to the insert */
43169 - sqlite3_bind_text(stmt, 1,
43171 + sqlite3_bind_text(stmt, 1,
43173 d.rel_path->used - 1,
43177 if (SQLITE_DONE != sqlite3_step(stmt)) {
43183 @@ -569,7 +664,7 @@
43184 if (stream_open(&s, src->path)) {
43189 if (-1 == (ofd = open(dst->path->ptr, O_WRONLY|O_TRUNC|O_CREAT|(overwrite ? 0 : O_EXCL), 0600))) {
43190 /* opening the destination failed for some reason */
43192 @@ -601,7 +696,7 @@
43201 @@ -614,19 +709,18 @@
43202 sqlite3_reset(stmt);
43204 /* bind the values to the insert */
43205 - sqlite3_bind_text(stmt, 1,
43206 - dst->rel_path->ptr,
43207 + sqlite3_bind_text(stmt, 1,
43208 + dst->rel_path->ptr,
43209 dst->rel_path->used - 1,
43212 - sqlite3_bind_text(stmt, 2,
43213 - src->rel_path->ptr,
43214 + sqlite3_bind_text(stmt, 2,
43215 + src->rel_path->ptr,
43216 src->rel_path->used - 1,
43220 if (SQLITE_DONE != sqlite3_step(stmt)) {
43226 @@ -655,21 +749,21 @@
43227 (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')) {
43232 buffer_copy_string_buffer(s.path, src->path);
43233 - BUFFER_APPEND_SLASH(s.path);
43234 + PATHNAME_APPEND_SLASH(s.path);
43235 buffer_append_string(s.path, de->d_name);
43237 buffer_copy_string_buffer(d.path, dst->path);
43238 - BUFFER_APPEND_SLASH(d.path);
43239 + PATHNAME_APPEND_SLASH(d.path);
43240 buffer_append_string(d.path, de->d_name);
43242 buffer_copy_string_buffer(s.rel_path, src->rel_path);
43243 - BUFFER_APPEND_SLASH(s.rel_path);
43244 + PATHNAME_APPEND_SLASH(s.rel_path);
43245 buffer_append_string(s.rel_path, de->d_name);
43247 buffer_copy_string_buffer(d.rel_path, dst->rel_path);
43248 - BUFFER_APPEND_SLASH(d.rel_path);
43249 + PATHNAME_APPEND_SLASH(d.rel_path);
43250 buffer_append_string(d.rel_path, de->d_name);
43252 if (-1 == stat(s.path->ptr, &st)) {
43253 @@ -692,19 +786,18 @@
43254 sqlite3_reset(stmt);
43256 /* bind the values to the insert */
43257 - sqlite3_bind_text(stmt, 1,
43258 - dst->rel_path->ptr,
43259 + sqlite3_bind_text(stmt, 1,
43260 + dst->rel_path->ptr,
43261 dst->rel_path->used - 1,
43264 - sqlite3_bind_text(stmt, 2,
43265 - src->rel_path->ptr,
43266 + sqlite3_bind_text(stmt, 2,
43267 + src->rel_path->ptr,
43268 src->rel_path->used - 1,
43272 if (SQLITE_DONE != sqlite3_step(stmt)) {
43278 @@ -721,7 +814,7 @@
43279 buffer_free(s.rel_path);
43280 buffer_free(d.path);
43281 buffer_free(d.rel_path);
43287 @@ -748,12 +841,12 @@
43288 if (S_ISDIR(sce->st.st_mode)) {
43289 buffer_append_string(b, "<D:getcontenttype>httpd/unix-directory</D:getcontenttype>");
43291 - } else if(S_ISREG(sce->st.st_mode)) {
43292 + } else if(S_ISREG(sce->st.st_mode)) {
43293 for (k = 0; k < con->conf.mimetypes->used; k++) {
43294 data_string *ds = (data_string *)con->conf.mimetypes->data[k];
43297 if (ds->key->used == 0) continue;
43300 if (buffer_is_equal_right_len(dst->path, ds->key, ds->key->used - 1)) {
43301 buffer_append_string(b,"<D:getcontenttype>");
43302 buffer_append_string_buffer(b, ds->value);
43303 @@ -807,23 +900,23 @@
43305 /* bind the values to the insert */
43307 - sqlite3_bind_text(stmt, 1,
43308 - dst->rel_path->ptr,
43309 + sqlite3_bind_text(stmt, 1,
43310 + dst->rel_path->ptr,
43311 dst->rel_path->used - 1,
43313 - sqlite3_bind_text(stmt, 2,
43314 + sqlite3_bind_text(stmt, 2,
43318 - sqlite3_bind_text(stmt, 3,
43319 + sqlite3_bind_text(stmt, 3,
43325 - while (SQLITE_ROW == sqlite3_step(p->conf.stmt_select_prop)) {
43326 + while (SQLITE_ROW == sqlite3_step(stmt)) {
43327 /* there is a row for us, we only expect a single col 'value' */
43328 - webdav_gen_prop_tag(srv, con, prop_name, prop_ns, (char *)sqlite3_column_text(p->conf.stmt_select_prop, 0), b);
43329 + webdav_gen_prop_tag(srv, con, prop_name, prop_ns, (char *)sqlite3_column_text(stmt, 0), b);
43333 @@ -840,7 +933,7 @@
43337 -webdav_property live_properties[] = {
43338 +webdav_property live_properties[] = {
43339 { "DAV:", "creationdate" },
43340 { "DAV:", "displayname" },
43341 { "DAV:", "getcontentlanguage" },
43342 @@ -871,8 +964,8 @@
43343 webdav_property *prop;
43345 prop = props->ptr[i];
43347 - if (0 != webdav_get_property(srv, con, p,
43349 + if (0 != webdav_get_property(srv, con, p,
43350 dst, prop->prop, prop->ns, b_200)) {
43351 webdav_gen_prop_tag(srv, con, prop->prop, prop->ns, NULL, b_404);
43353 @@ -916,12 +1009,12 @@
43354 if (-1 == c->file.fd && /* open the file if not already open */
43355 -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
43356 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
43363 if (MAP_FAILED == (c->file.mmap.start = mmap(0, c->file.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
43364 - log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
43365 + log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
43366 strerror(errno), c->file.name, c->file.fd);
43369 @@ -938,7 +1031,7 @@
43370 if (XML_ERR_OK != (err = xmlParseChunk(ctxt, c->file.mmap.start + c->offset, weHave, 0))) {
43371 log_error_write(srv, __FILE__, __LINE__, "sddd", "xmlParseChunk failed at:", cq->bytes_out, weHave, err);
43375 c->offset += weHave;
43376 cq->bytes_out += weHave;
43378 @@ -956,7 +1049,7 @@
43379 if (XML_ERR_OK != (err = xmlParseChunk(ctxt, c->mem->ptr + c->offset, weHave, 0))) {
43380 log_error_write(srv, __FILE__, __LINE__, "sddd", "xmlParseChunk failed at:", cq->bytes_out, weHave, err);
43384 c->offset += weHave;
43385 cq->bytes_out += weHave;
43387 @@ -991,6 +1084,113 @@
43391 +int webdav_lockdiscovery(server *srv, connection *con,
43392 + buffer *locktoken, const char *lockscope, const char *locktype, int depth) {
43396 + response_header_overwrite(srv, con, CONST_STR_LEN("Lock-Token"), CONST_BUF_LEN(locktoken));
43398 + response_header_overwrite(srv, con,
43399 + CONST_STR_LEN("Content-Type"),
43400 + CONST_STR_LEN("text/xml; charset=\"utf-8\""));
43402 + b = chunkqueue_get_append_buffer(con->write_queue);
43404 + buffer_copy_string(b, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
43406 + buffer_append_string(b,"<D:prop xmlns:D=\"DAV:\" xmlns:ns0=\"urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/\">\n");
43407 + buffer_append_string(b,"<D:lockdiscovery>\n");
43408 + buffer_append_string(b,"<D:activelock>\n");
43410 + buffer_append_string(b,"<D:lockscope>");
43411 + buffer_append_string(b,"<D:");
43412 + buffer_append_string(b, lockscope);
43413 + buffer_append_string(b, "/>");
43414 + buffer_append_string(b,"</D:lockscope>\n");
43416 + buffer_append_string(b,"<D:locktype>");
43417 + buffer_append_string(b,"<D:");
43418 + buffer_append_string(b, locktype);
43419 + buffer_append_string(b, "/>");
43420 + buffer_append_string(b,"</D:locktype>\n");
43422 + buffer_append_string(b,"<D:depth>");
43423 + buffer_append_string(b, depth == 0 ? "0" : "infinity");
43424 + buffer_append_string(b,"</D:depth>\n");
43426 + buffer_append_string(b,"<D:timeout>");
43427 + buffer_append_string(b, "Second-600");
43428 + buffer_append_string(b,"</D:timeout>\n");
43430 + buffer_append_string(b,"<D:owner>");
43431 + buffer_append_string(b,"</D:owner>\n");
43433 + buffer_append_string(b,"<D:locktoken>");
43434 + buffer_append_string(b, "<D:href>");
43435 + buffer_append_string_buffer(b, locktoken);
43436 + buffer_append_string(b, "</D:href>");
43437 + buffer_append_string(b,"</D:locktoken>\n");
43439 + buffer_append_string(b,"</D:activelock>\n");
43440 + buffer_append_string(b,"</D:lockdiscovery>\n");
43441 + buffer_append_string(b,"</D:prop>\n");
43446 + * check if resource is having the right locks to access to resource
43451 +int webdav_has_lock(server *srv, connection *con, plugin_data *p, buffer *uri) {
43452 + int has_lock = 1;
43462 + * there is NOT, AND and OR
43463 + * and a list can be tagged
43465 + * (<lock-token>) is untagged
43466 + * <tag> (<lock-token>) is tagged
43468 + * as long as we don't handle collections it is simple. :)
43470 + * X-Litmus: locks: 11 (owner_modify)
43471 + * If: <http://127.0.0.1:1025/dav/litmus/lockme> (<opaquelocktoken:2165478d-0611-49c4-be92-e790d68a38f1>)
43473 + * X-Litmus: locks: 16 (fail_cond_put)
43474 + * If: (<DAV:no-lock> ["-1622396671"])
43476 + if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If"))) {
43478 + /* we didn't provided a lock-token -> */
43479 + /* if the resource is locked -> 423 */
43481 + sqlite3_stmt *stmt = p->conf.stmt_read_lock_by_uri;
43483 + sqlite3_reset(stmt);
43485 + sqlite3_bind_text(stmt, 1,
43486 + CONST_BUF_LEN(uri),
43487 + SQLITE_TRANSIENT);
43489 + while (SQLITE_ROW == sqlite3_step(stmt)) {
43498 URIHANDLER_FUNC(mod_webdav_subrequest_handler) {
43499 plugin_data *p = p_d;
43501 @@ -1001,7 +1201,8 @@
43504 webdav_properties *req_props;
43506 + stat_cache_entry *sce = NULL;
43510 if (!p->conf.enabled) return HANDLER_GO_ON;
43511 @@ -1019,7 +1220,19 @@
43514 /* is there a content-body ? */
43517 + switch (stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
43518 + case HANDLER_ERROR:
43519 + if (errno == ENOENT) {
43520 + con->http_status = 404;
43521 + return HANDLER_FINISHED;
43529 #ifdef USE_PROPPATCH
43530 /* any special requests or just allprop ? */
43531 if (con->request.content_length) {
43532 @@ -1087,14 +1300,13 @@
43533 /* get all property names (EMPTY) */
43534 sqlite3_reset(stmt);
43535 /* bind the values to the insert */
43537 - sqlite3_bind_text(stmt, 1,
43538 - con->uri.path->ptr,
43540 + sqlite3_bind_text(stmt, 1,
43541 + con->uri.path->ptr,
43542 con->uri.path->used - 1,
43546 if (SQLITE_DONE != sqlite3_step(stmt)) {
43550 } else if (0 == xmlStrcmp(cmd->name, BAD_CAST "allprop")) {
43551 @@ -1115,13 +1327,13 @@
43552 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/xml; charset=\"utf-8\""));
43554 b = chunkqueue_get_append_buffer(con->write_queue);
43557 buffer_copy_string(b, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
43559 buffer_append_string(b,"<D:multistatus xmlns:D=\"DAV:\" xmlns:ns0=\"urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/\">\n");
43564 prop_200 = buffer_init();
43565 prop_404 = buffer_init();
43567 @@ -1129,7 +1341,7 @@
43570 webdav_get_props(srv, con, p, &(con->physical), req_props, prop_200, prop_404);
43573 buffer_append_string(b,"<D:response>\n");
43574 buffer_append_string(b,"<D:href>");
43575 buffer_append_string_buffer(b, con->uri.scheme);
43576 @@ -1145,9 +1357,9 @@
43577 buffer_append_string_buffer(b, prop_200);
43579 buffer_append_string(b,"</D:prop>\n");
43582 buffer_append_string(b,"<D:status>HTTP/1.1 200 OK</D:status>\n");
43585 buffer_append_string(b,"</D:propstat>\n");
43587 if (!buffer_is_empty(prop_404)) {
43588 @@ -1157,16 +1369,16 @@
43589 buffer_append_string_buffer(b, prop_404);
43591 buffer_append_string(b,"</D:prop>\n");
43594 buffer_append_string(b,"<D:status>HTTP/1.1 404 Not Found</D:status>\n");
43597 buffer_append_string(b,"</D:propstat>\n");
43600 buffer_append_string(b,"</D:response>\n");
43605 if (NULL != (dir = opendir(con->physical.path->ptr))) {
43608 @@ -1179,16 +1391,16 @@
43609 if (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0') {
43611 /* ignore the parent dir */
43615 buffer_copy_string_buffer(d.path, dst->path);
43616 - BUFFER_APPEND_SLASH(d.path);
43617 + PATHNAME_APPEND_SLASH(d.path);
43619 buffer_copy_string_buffer(d.rel_path, dst->rel_path);
43620 - BUFFER_APPEND_SLASH(d.rel_path);
43621 + PATHNAME_APPEND_SLASH(d.rel_path);
43623 if (de->d_name[0] == '.' && de->d_name[1] == '\0') {
43624 - /* don't append the . */
43625 + /* don't append the . */
43627 buffer_append_string(d.path, de->d_name);
43628 buffer_append_string(d.rel_path, de->d_name);
43629 @@ -1198,7 +1410,7 @@
43630 buffer_reset(prop_404);
43632 webdav_get_props(srv, con, p, &d, req_props, prop_200, prop_404);
43635 buffer_append_string(b,"<D:response>\n");
43636 buffer_append_string(b,"<D:href>");
43637 buffer_append_string_buffer(b, con->uri.scheme);
43638 @@ -1214,9 +1426,9 @@
43639 buffer_append_string_buffer(b, prop_200);
43641 buffer_append_string(b,"</D:prop>\n");
43644 buffer_append_string(b,"<D:status>HTTP/1.1 200 OK</D:status>\n");
43647 buffer_append_string(b,"</D:propstat>\n");
43649 if (!buffer_is_empty(prop_404)) {
43650 @@ -1226,9 +1438,9 @@
43651 buffer_append_string_buffer(b, prop_404);
43653 buffer_append_string(b,"</D:prop>\n");
43656 buffer_append_string(b,"<D:status>HTTP/1.1 404 Not Found</D:status>\n");
43659 buffer_append_string(b,"</D:propstat>\n");
43662 @@ -1275,7 +1487,7 @@
43664 return HANDLER_FINISHED;
43668 /* let's create the directory */
43670 if (-1 == mkdir(con->physical.path->ptr, 0700)) {
43671 @@ -1303,7 +1515,13 @@
43672 con->http_status = 403;
43673 return HANDLER_FINISHED;
43677 + /* does the client have a lock for this connection ? */
43678 + if (!webdav_has_lock(srv, con, p, con->uri.path)) {
43679 + con->http_status = 423;
43680 + return HANDLER_FINISHED;
43683 /* stat and unlink afterwards */
43684 if (-1 == stat(con->physical.path->ptr, &st)) {
43685 /* don't about it yet, unlink will fail too */
43686 @@ -1323,7 +1541,7 @@
43687 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/xml; charset=\"utf-8\""));
43689 b = chunkqueue_get_append_buffer(con->write_queue);
43692 buffer_copy_string(b, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
43694 buffer_append_string(b,"<D:multistatus xmlns:D=\"DAV:\">\n");
43695 @@ -1331,7 +1549,7 @@
43696 buffer_append_string_buffer(b, multi_status_resp);
43698 buffer_append_string(b,"</D:multistatus>\n");
43701 if (p->conf.log_xml) {
43702 log_error_write(srv, __FILE__, __LINE__, "sb", "XML-response-body:", b);
43704 @@ -1340,7 +1558,7 @@
43705 con->file_finished = 1;
43707 /* everything went fine, remove the directory */
43710 if (-1 == rmdir(con->physical.path->ptr)) {
43713 @@ -1375,97 +1593,174 @@
43714 case HTTP_METHOD_PUT: {
43716 chunkqueue *cq = con->request_content_queue;
43718 + data_string *ds_range;
43720 if (p->conf.is_readonly) {
43721 con->http_status = 403;
43722 return HANDLER_FINISHED;
43725 + /* is a exclusive lock set on the source */
43726 + if (!webdav_has_lock(srv, con, p, con->uri.path)) {
43727 + con->http_status = 423;
43728 + return HANDLER_FINISHED;
43732 assert(chunkqueue_length(cq) == (off_t)con->request.content_length);
43734 - /* taken what we have in the request-body and write it to a file */
43735 - if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_CREAT|O_TRUNC, 0600))) {
43736 - /* we can't open the file */
43737 - con->http_status = 403;
43740 + /* RFC2616 Section 9.6 PUT requires us to send 501 on all Content-* we don't support
43741 + * - most important Content-Range
43744 + * Example: Content-Range: bytes 100-1037/1038 */
43746 - con->http_status = 201; /* created */
43747 - con->file_finished = 1;
43748 + if (NULL != (ds_range = (data_string *)array_get_element(con->request.headers, "Content-Range"))) {
43749 + const char *num = ds_range->value->ptr;
43751 + char *err = NULL;
43753 - for (c = cq->first; c; c = cq->first) {
43755 + if (0 != strncmp(num, "bytes ", 6)) {
43756 + con->http_status = 501; /* not implemented */
43758 - /* copy all chunks */
43759 - switch(c->type) {
43762 - if (c->file.mmap.start == MAP_FAILED) {
43763 - if (-1 == c->file.fd && /* open the file if not already open */
43764 - -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
43765 - log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
43770 - if (MAP_FAILED == (c->file.mmap.start = mmap(0, c->file.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
43771 - log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
43772 - strerror(errno), c->file.name, c->file.fd);
43773 + return HANDLER_FINISHED;
43778 + /* we only support <num>- ... */
43780 - c->file.mmap.length = c->file.length;
43783 - close(c->file.fd);
43786 - /* chunk_reset() or chunk_free() will cleanup for us */
43789 - if ((r = write(fd, c->file.mmap.start + c->offset, c->file.length - c->offset)) < 0) {
43792 - con->http_status = 507;
43796 - con->http_status = 403;
43802 - if ((r = write(fd, c->mem->ptr + c->offset, c->mem->used - c->offset - 1)) < 0) {
43805 - con->http_status = 507;
43809 - con->http_status = 403;
43814 + while (*num == ' ' || *num == '\t') num++;
43816 + if (*num == '\0') {
43817 + con->http_status = 501; /* not implemented */
43819 + return HANDLER_FINISHED;
43822 + offset = strtoll(num, &err, 10);
43824 + if (*err != '-' || offset < 0) {
43825 + con->http_status = 501; /* not implemented */
43827 + return HANDLER_FINISHED;
43830 + if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY, 0600))) {
43833 + con->http_status = 404; /* not found */
43835 - case UNUSED_CHUNK:
43837 + con->http_status = 403; /* not found */
43840 + return HANDLER_FINISHED;
43843 + if (-1 == lseek(fd, offset, SEEK_SET)) {
43844 + con->http_status = 501; /* not implemented */
43848 + return HANDLER_FINISHED;
43850 + con->http_status = 200; /* modified */
43852 + /* take what we have in the request-body and write it to a file */
43854 + /* if the file doesn't exist, create it */
43855 + if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_TRUNC, 0600))) {
43856 + if (errno == ENOENT &&
43857 + -1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0600))) {
43858 + /* we can't open the file */
43859 + con->http_status = 403;
43863 - cq->bytes_out += r;
43864 + return HANDLER_FINISHED;
43867 + con->http_status = 201; /* created */
43870 + con->http_status = 200; /* modified */
43874 + con->file_finished = 1;
43876 + for (c = cq->first; c; c = cq->first) {
43879 + /* copy all chunks */
43880 + switch(c->type) {
43883 + if (c->file.mmap.start == MAP_FAILED) {
43884 + if (-1 == c->file.fd && /* open the file if not already open */
43885 + -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
43886 + log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
43891 + if (MAP_FAILED == (c->file.mmap.start = mmap(0, c->file.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
43892 + log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
43893 + strerror(errno), c->file.name, c->file.fd);
43898 + c->file.mmap.length = c->file.length;
43900 + close(c->file.fd);
43903 + /* chunk_reset() or chunk_free() will cleanup for us */
43906 + if ((r = write(fd, c->file.mmap.start + c->offset, c->file.length - c->offset)) < 0) {
43909 + con->http_status = 507;
43913 + con->http_status = 403;
43917 - chunkqueue_remove_finished_chunks(cq);
43920 + if ((r = write(fd, c->mem->ptr + c->offset, c->mem->used - c->offset - 1)) < 0) {
43923 + con->http_status = 507;
43927 + con->http_status = 403;
43932 + case UNUSED_CHUNK:
43939 + cq->bytes_out += r;
43943 + chunkqueue_remove_finished_chunks(cq);
43947 return HANDLER_FINISHED;
43949 - case HTTP_METHOD_MOVE:
43950 + case HTTP_METHOD_MOVE:
43951 case HTTP_METHOD_COPY: {
43952 buffer *destination = NULL;
43954 @@ -1475,7 +1770,15 @@
43955 con->http_status = 403;
43956 return HANDLER_FINISHED;
43960 + /* is a exclusive lock set on the source */
43961 + if (con->request.http_method == HTTP_METHOD_MOVE) {
43962 + if (!webdav_has_lock(srv, con, p, con->uri.path)) {
43963 + con->http_status = 423;
43964 + return HANDLER_FINISHED;
43968 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Destination"))) {
43969 destination = ds->value;
43971 @@ -1549,10 +1852,10 @@
43974 buffer_copy_string_buffer(p->physical.path, p->physical.doc_root);
43975 - BUFFER_APPEND_SLASH(p->physical.path);
43976 + PATHNAME_APPEND_SLASH(p->physical.path);
43977 buffer_copy_string_buffer(p->physical.basedir, p->physical.path);
43979 - /* don't add a second / */
43980 + /* don't add a second / */
43981 if (p->physical.rel_path->ptr[0] == '/') {
43982 buffer_append_string_len(p->physical.path, p->physical.rel_path->ptr + 1, p->physical.rel_path->used - 2);
43984 @@ -1613,6 +1916,12 @@
43985 /* it is just a file, good */
43988 + /* does the client have a lock for this connection ? */
43989 + if (!webdav_has_lock(srv, con, p, p->uri.path)) {
43990 + con->http_status = 423;
43991 + return HANDLER_FINISHED;
43994 /* destination exists */
43995 if (0 == (r = stat(p->physical.path->ptr, &st))) {
43996 if (S_ISDIR(st.st_mode)) {
43997 @@ -1636,7 +1945,7 @@
43998 return HANDLER_FINISHED;
44000 } else if (overwrite == 0) {
44001 - /* destination exists, but overwrite is not set */
44002 + /* destination exists, but overwrite is not set */
44003 con->http_status = 412;
44004 return HANDLER_FINISHED;
44006 @@ -1655,16 +1964,16 @@
44007 sqlite3_reset(stmt);
44009 /* bind the values to the insert */
44010 - sqlite3_bind_text(stmt, 1,
44011 - p->uri.path->ptr,
44012 + sqlite3_bind_text(stmt, 1,
44013 + p->uri.path->ptr,
44014 p->uri.path->used - 1,
44017 - sqlite3_bind_text(stmt, 2,
44018 - con->uri.path->ptr,
44019 + sqlite3_bind_text(stmt, 2,
44020 + con->uri.path->ptr,
44021 con->uri.path->used - 1,
44025 if (SQLITE_DONE != sqlite3_step(stmt)) {
44026 log_error_write(srv, __FILE__, __LINE__, "ss", "sql-move failed:", sqlite3_errmsg(p->conf.sql));
44028 @@ -1691,12 +2000,17 @@
44030 return HANDLER_FINISHED;
44032 - case HTTP_METHOD_PROPPATCH: {
44033 + case HTTP_METHOD_PROPPATCH:
44034 if (p->conf.is_readonly) {
44035 con->http_status = 403;
44036 return HANDLER_FINISHED;
44039 + if (!webdav_has_lock(srv, con, p, con->uri.path)) {
44040 + con->http_status = 423;
44041 + return HANDLER_FINISHED;
44044 /* check if destination exists */
44045 if (-1 == stat(con->physical.path->ptr, &st)) {
44047 @@ -1737,7 +2051,7 @@
44049 sqlite3_stmt *stmt;
44051 - stmt = (0 == xmlStrcmp(cmd->name, BAD_CAST "remove")) ?
44052 + stmt = (0 == xmlStrcmp(cmd->name, BAD_CAST "remove")) ?
44053 p->conf.stmt_delete_prop : p->conf.stmt_update_prop;
44055 for (props = cmd->children; props; props = props->next) {
44056 @@ -1762,34 +2076,35 @@
44058 /* bind the values to the insert */
44060 - sqlite3_bind_text(stmt, 1,
44061 - con->uri.path->ptr,
44062 + sqlite3_bind_text(stmt, 1,
44063 + con->uri.path->ptr,
44064 con->uri.path->used - 1,
44066 - sqlite3_bind_text(stmt, 2,
44067 + sqlite3_bind_text(stmt, 2,
44068 (char *)prop->name,
44069 strlen((char *)prop->name),
44072 - sqlite3_bind_text(stmt, 3,
44073 + sqlite3_bind_text(stmt, 3,
44074 (char *)prop->ns->href,
44075 strlen((char *)prop->ns->href),
44078 - sqlite3_bind_text(stmt, 3,
44079 + sqlite3_bind_text(stmt, 3,
44084 if (stmt == p->conf.stmt_update_prop) {
44085 - sqlite3_bind_text(stmt, 4,
44086 + sqlite3_bind_text(stmt, 4,
44087 (char *)xmlNodeGetContent(prop),
44088 strlen((char *)xmlNodeGetContent(prop)),
44093 if (SQLITE_DONE != (r = sqlite3_step(stmt))) {
44094 - log_error_write(srv, __FILE__, __LINE__, "ss", "sql-set failed:", sqlite3_errmsg(p->conf.sql));
44095 + log_error_write(srv, __FILE__, __LINE__, "ss",
44096 + "sql-set failed:", sqlite3_errmsg(p->conf.sql));
44100 @@ -1804,7 +2119,7 @@
44102 goto propmatch_cleanup;
44106 con->http_status = 400;
44108 if (SQLITE_OK != sqlite3_exec(p->conf.sql, "COMMIT", NULL, NULL, &err)) {
44109 @@ -1821,6 +2136,7 @@
44116 con->http_status = 400;
44117 @@ -1830,11 +2146,307 @@
44119 con->http_status = 501;
44120 return HANDLER_FINISHED;
44122 + case HTTP_METHOD_LOCK:
44124 + * a mac wants to write
44126 + * LOCK /dav/expire.txt HTTP/1.1\r\n
44127 + * User-Agent: WebDAVFS/1.3 (01308000) Darwin/8.1.0 (Power Macintosh)\r\n
44128 + * Accept: * / *\r\n
44130 + * Timeout: Second-600\r\n
44131 + * Content-Type: text/xml; charset=\"utf-8\"\r\n
44132 + * Content-Length: 229\r\n
44133 + * Connection: keep-alive\r\n
44134 + * Host: 192.168.178.23:1025\r\n
44136 + * <?xml version=\"1.0\" encoding=\"utf-8\"?>\n
44137 + * <D:lockinfo xmlns:D=\"DAV:\">\n
44138 + * <D:lockscope><D:exclusive/></D:lockscope>\n
44139 + * <D:locktype><D:write/></D:locktype>\n
44141 + * <D:href>http://www.apple.com/webdav_fs/</D:href>\n
44143 + * </D:lockinfo>\n
44146 + if (depth != 0 && depth != -1) {
44147 + con->http_status = 400;
44149 + return HANDLER_FINISHED;
44153 + if (con->request.content_length) {
44155 + buffer *hdr_if = NULL;
44157 + if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If"))) {
44158 + hdr_if = ds->value;
44161 + /* we don't support Depth: Infinity on locks */
44162 + if (hdr_if == NULL && depth == -1) {
44163 + con->http_status = 409; /* Conflict */
44165 + return HANDLER_FINISHED;
44168 + if (1 == webdav_parse_chunkqueue(srv, con, p, con->request_content_queue, &xml)) {
44169 + xmlNode *rootnode = xmlDocGetRootElement(xml);
44171 + assert(rootnode);
44173 + if (0 == xmlStrcmp(rootnode->name, BAD_CAST "lockinfo")) {
44174 + xmlNode *lockinfo;
44175 + const xmlChar *lockscope = NULL, *locktype = NULL, *owner = NULL;
44177 + for (lockinfo = rootnode->children; lockinfo; lockinfo = lockinfo->next) {
44178 + if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "lockscope")) {
44180 + for (value = lockinfo->children; value; value = value->next) {
44181 + if ((0 == xmlStrcmp(value->name, BAD_CAST "exclusive")) ||
44182 + (0 == xmlStrcmp(value->name, BAD_CAST "shared"))) {
44183 + lockscope = value->name;
44185 + con->http_status = 400;
44188 + return HANDLER_FINISHED;
44191 + } else if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "locktype")) {
44193 + for (value = lockinfo->children; value; value = value->next) {
44194 + if ((0 == xmlStrcmp(value->name, BAD_CAST "write"))) {
44195 + locktype = value->name;
44197 + con->http_status = 400;
44200 + return HANDLER_FINISHED;
44204 + } else if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "owner")) {
44208 + if (lockscope && locktype) {
44209 + sqlite3_stmt *stmt = p->conf.stmt_read_lock_by_uri;
44211 + /* is this resourse already locked ? */
44213 + /* SELECT locktoken, resource, lockscope, locktype, owner, depth, timeout
44215 + * WHERE resource = ? */
44219 + sqlite3_reset(stmt);
44221 + sqlite3_bind_text(stmt, 1,
44222 + p->uri.path->ptr,
44223 + p->uri.path->used - 1,
44224 + SQLITE_TRANSIENT);
44226 + /* it is the PK */
44227 + while (SQLITE_ROW == sqlite3_step(stmt)) {
44228 + /* we found a lock
44229 + * 1. is it compatible ?
44230 + * 2. is it ours */
44231 + char *sql_lockscope = (char *)sqlite3_column_text(stmt, 2);
44233 + if (strcmp(sql_lockscope, "exclusive")) {
44234 + con->http_status = 423;
44235 + } else if (0 == xmlStrcmp(lockscope, BAD_CAST "exclusive")) {
44236 + /* resourse is locked with a shared lock
44237 + * client wants exclusive */
44238 + con->http_status = 423;
44241 + if (con->http_status == 423) {
44243 + return HANDLER_FINISHED;
44247 + stmt = p->conf.stmt_create_lock;
44249 + /* create a lock-token */
44251 + char uuid[37] /* 36 + \0 */;
44253 + uuid_generate(id);
44254 + uuid_unparse(id, uuid);
44256 + buffer_copy_string(p->tmp_buf, "opaquelocktoken:");
44257 + buffer_append_string(p->tmp_buf, uuid);
44259 + /* "CREATE TABLE locks ("
44260 + * " locktoken TEXT NOT NULL,"
44261 + * " resource TEXT NOT NULL,"
44262 + * " lockscope TEXT NOT NULL,"
44263 + * " locktype TEXT NOT NULL,"
44264 + * " owner TEXT NOT NULL,"
44265 + * " depth INT NOT NULL,"
44268 + sqlite3_reset(stmt);
44270 + sqlite3_bind_text(stmt, 1,
44271 + CONST_BUF_LEN(p->tmp_buf),
44272 + SQLITE_TRANSIENT);
44274 + sqlite3_bind_text(stmt, 2,
44275 + CONST_BUF_LEN(con->uri.path),
44276 + SQLITE_TRANSIENT);
44278 + sqlite3_bind_text(stmt, 3,
44280 + xmlStrlen(lockscope),
44281 + SQLITE_TRANSIENT);
44283 + sqlite3_bind_text(stmt, 4,
44285 + xmlStrlen(locktype),
44286 + SQLITE_TRANSIENT);
44289 + sqlite3_bind_text(stmt, 5,
44292 + SQLITE_TRANSIENT);
44295 + sqlite3_bind_int(stmt, 6,
44299 + if (SQLITE_DONE != sqlite3_step(stmt)) {
44300 + log_error_write(srv, __FILE__, __LINE__, "ss",
44301 + "create lock:", sqlite3_errmsg(p->conf.sql));
44304 + /* looks like we survived */
44305 + webdav_lockdiscovery(srv, con, p->tmp_buf, lockscope, locktype, depth);
44307 + con->http_status = 201;
44308 + con->file_finished = 1;
44314 + return HANDLER_FINISHED;
44316 + con->http_status = 400;
44317 + return HANDLER_FINISHED;
44321 + if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If"))) {
44322 + buffer *locktoken = ds->value;
44323 + sqlite3_stmt *stmt = p->conf.stmt_refresh_lock;
44325 + /* remove the < > around the token */
44326 + if (locktoken->used < 6) {
44327 + con->http_status = 400;
44329 + return HANDLER_FINISHED;
44332 + buffer_copy_string_len(p->tmp_buf, locktoken->ptr + 2, locktoken->used - 5);
44334 + sqlite3_reset(stmt);
44336 + sqlite3_bind_text(stmt, 1,
44337 + CONST_BUF_LEN(p->tmp_buf),
44338 + SQLITE_TRANSIENT);
44340 + if (SQLITE_DONE != sqlite3_step(stmt)) {
44341 + log_error_write(srv, __FILE__, __LINE__, "ss",
44342 + "refresh lock:", sqlite3_errmsg(p->conf.sql));
44345 + webdav_lockdiscovery(srv, con, p->tmp_buf, "exclusive", "write", 0);
44347 + con->http_status = 200;
44348 + con->file_finished = 1;
44349 + return HANDLER_FINISHED;
44351 + /* we need a lock-token to refresh */
44352 + con->http_status = 400;
44354 + return HANDLER_FINISHED;
44359 + con->http_status = 501;
44360 + return HANDLER_FINISHED;
44362 + case HTTP_METHOD_UNLOCK:
44364 + if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Lock-Token"))) {
44365 + buffer *locktoken = ds->value;
44366 + sqlite3_stmt *stmt = p->conf.stmt_remove_lock;
44368 + /* remove the < > around the token */
44369 + if (locktoken->used < 4) {
44370 + con->http_status = 400;
44372 + return HANDLER_FINISHED;
44378 + * if the resourse is locked:
44379 + * - by us: unlock
44380 + * - by someone else: 401
44381 + * if the resource is not locked:
44385 + buffer_copy_string_len(p->tmp_buf, locktoken->ptr + 1, locktoken->used - 3);
44387 + sqlite3_reset(stmt);
44389 + sqlite3_bind_text(stmt, 1,
44390 + CONST_BUF_LEN(p->tmp_buf),
44391 + SQLITE_TRANSIENT);
44393 + sqlite3_bind_text(stmt, 2,
44394 + CONST_BUF_LEN(con->uri.path),
44395 + SQLITE_TRANSIENT);
44397 + if (SQLITE_DONE != sqlite3_step(stmt)) {
44398 + log_error_write(srv, __FILE__, __LINE__, "ss",
44399 + "remove lock:", sqlite3_errmsg(p->conf.sql));
44402 + if (0 == sqlite3_changes(p->conf.sql)) {
44403 + con->http_status = 401;
44405 + con->http_status = 204;
44407 + return HANDLER_FINISHED;
44409 + /* we need a lock-token to unlock */
44410 + con->http_status = 400;
44412 + return HANDLER_FINISHED;
44416 + con->http_status = 501;
44417 + return HANDLER_FINISHED;
44425 return HANDLER_GO_ON;
44427 @@ -1845,14 +2457,14 @@
44428 int mod_webdav_plugin_init(plugin *p) {
44429 p->version = LIGHTTPD_VERSION_ID;
44430 p->name = buffer_init_string("webdav");
44433 p->init = mod_webdav_init;
44434 p->handle_uri_clean = mod_webdav_uri_handler;
44435 p->handle_physical = mod_webdav_subrequest_handler;
44436 p->set_defaults = mod_webdav_set_defaults;
44437 p->cleanup = mod_webdav_free;
44445 --- ../lighttpd-1.4.11/src/network.c 2006-03-04 16:45:46.000000000 +0200
44446 +++ lighttpd-1.4.12/src/network.c 2006-07-18 13:03:40.000000000 +0300
44448 #include <sys/types.h>
44449 #include <sys/stat.h>
44450 -#include <sys/time.h>
44454 -#include <unistd.h>
44455 #include <string.h>
44456 #include <stdlib.h>
44457 #include <assert.h>
44459 +#include <stdio.h>
44461 #include "network.h"
44462 #include "fdevent.h"
44464 @@ -19,11 +19,12 @@
44465 #include "network_backends.h"
44466 #include "sys-mmap.h"
44467 #include "sys-socket.h"
44468 +#include "sys-files.h"
44471 -# include <openssl/ssl.h>
44472 -# include <openssl/err.h>
44473 -# include <openssl/rand.h>
44474 +# include <openssl/ssl.h>
44475 +# include <openssl/err.h>
44476 +# include <openssl/rand.h>
44479 handler_t network_server_handle_fdevent(void *s, void *context, int revents) {
44480 @@ -31,25 +32,25 @@
44481 server_socket *srv_socket = (server_socket *)context;
44489 if (revents != FDEVENT_IN) {
44490 - log_error_write(srv, __FILE__, __LINE__, "sdd",
44491 + log_error_write(srv, __FILE__, __LINE__, "sdd",
44492 "strange event for server socket",
44494 + srv_socket->sock->fd,
44496 return HANDLER_ERROR;
44499 /* accept()s at most 100 connections directly
44501 - * we jump out after 100 to give the waiting connections a chance */
44502 + * we jump out after 100 to give the waiting connections a chance */
44503 for (loops = 0; loops < 100 && NULL != (con = connection_accept(srv, srv_socket)); loops++) {
44507 connection_state_machine(srv, con);
44510 switch(r = plugins_call_handle_joblist(srv, con)) {
44511 case HANDLER_FINISHED:
44512 case HANDLER_GO_ON:
44513 @@ -72,18 +73,18 @@
44515 int is_unix_domain_socket = 0;
44519 #ifdef SO_ACCEPTFILTER
44520 struct accept_filter_arg afa;
44525 WORD wVersionRequested;
44530 wVersionRequested = MAKEWORD( 2, 2 );
44533 err = WSAStartup( wVersionRequested, &wsaData );
44535 /* Tell the user that we could not find a usable */
44536 @@ -91,37 +92,37 @@
44542 srv_socket = calloc(1, sizeof(*srv_socket));
44543 - srv_socket->fd = -1;
44545 + srv_socket->sock = iosocket_init();
44547 srv_socket->srv_token = buffer_init();
44548 buffer_copy_string_buffer(srv_socket->srv_token, host_token);
44552 buffer_copy_string_buffer(b, host_token);
44559 if (NULL == (sp = strrchr(b->ptr, ':'))) {
44560 log_error_write(srv, __FILE__, __LINE__, "sb", "value of $SERVER[\"socket\"] has to be \"ip:port\".", b);
44570 /* check for [ and ] */
44571 if (b->ptr[0] == '[' && *(sp-1) == ']') {
44583 port = strtol(sp, NULL, 10);
44585 if (host[0] == '/') {
44586 @@ -129,18 +130,18 @@
44587 is_unix_domain_socket = 1;
44588 } else if (port == 0 || port > 65535) {
44589 log_error_write(srv, __FILE__, __LINE__, "sd", "port out of range:", port);
44596 if (*host == '\0') host = NULL;
44598 if (is_unix_domain_socket) {
44599 #ifdef HAVE_SYS_UN_H
44601 srv_socket->addr.plain.sa_family = AF_UNIX;
44603 - if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, 0))) {
44605 + if (-1 == (srv_socket->sock->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, 0))) {
44606 log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno));
44609 @@ -154,32 +155,32 @@
44612 srv_socket->addr.plain.sa_family = AF_INET6;
44614 - if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) {
44616 + if (-1 == (srv_socket->sock->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) {
44617 log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno));
44620 srv_socket->use_ipv6 = 1;
44624 - if (srv_socket->fd == -1) {
44626 + if (srv_socket->sock->fd == -1) {
44627 srv_socket->addr.plain.sa_family = AF_INET;
44628 - if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) {
44629 + if (-1 == (srv_socket->sock->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) {
44630 log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno));
44637 - srv->cur_fds = srv_socket->fd;
44639 + srv->cur_fds = srv_socket->sock->fd;
44642 - if (setsockopt(srv_socket->fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
44643 + if (setsockopt(srv_socket->sock->fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
44644 log_error_write(srv, __FILE__, __LINE__, "ss", "socketsockopt failed:", strerror(errno));
44649 switch(srv_socket->addr.plain.sa_family) {
44652 @@ -190,23 +191,23 @@
44654 struct addrinfo hints, *res;
44658 memset(&hints, 0, sizeof(hints));
44661 hints.ai_family = AF_INET6;
44662 hints.ai_socktype = SOCK_STREAM;
44663 hints.ai_protocol = IPPROTO_TCP;
44666 if (0 != (r = getaddrinfo(host, NULL, &hints, &res))) {
44667 - log_error_write(srv, __FILE__, __LINE__,
44668 - "sssss", "getaddrinfo failed: ",
44669 + log_error_write(srv, __FILE__, __LINE__,
44670 + "sssss", "getaddrinfo failed: ",
44671 gai_strerror(r), "'", host, "'");
44678 memcpy(&(srv_socket->addr), res->ai_addr, res->ai_addrlen);
44683 srv_socket->addr.ipv6.sin6_port = htons(port);
44684 @@ -221,33 +222,34 @@
44686 struct hostent *he;
44687 if (NULL == (he = gethostbyname(host))) {
44688 - log_error_write(srv, __FILE__, __LINE__,
44689 - "sds", "gethostbyname failed: ",
44690 + log_error_write(srv, __FILE__, __LINE__,
44691 + "sds", "gethostbyname failed: ",
44697 if (he->h_addrtype != AF_INET) {
44698 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype);
44703 if (he->h_length != sizeof(struct in_addr)) {
44704 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-length != sizeof(in_addr): ", he->h_length);
44709 memcpy(&(srv_socket->addr.ipv4.sin_addr.s_addr), he->h_addr_list[0], he->h_length);
44711 srv_socket->addr.ipv4.sin_port = htons(port);
44714 addr_len = sizeof(struct sockaddr_in);
44720 srv_socket->addr.un.sun_family = AF_UNIX;
44721 strcpy(srv_socket->addr.un.sun_path, host);
44725 addr_len = SUN_LEN(&srv_socket->addr.un);
44727 @@ -256,11 +258,11 @@
44730 /* check if the socket exists and try to connect to it. */
44731 - if (-1 != (fd = connect(srv_socket->fd, (struct sockaddr *) &(srv_socket->addr), addr_len))) {
44732 + if (-1 != (fd = connect(srv_socket->sock->fd, (struct sockaddr *) &(srv_socket->addr), addr_len))) {
44735 - log_error_write(srv, __FILE__, __LINE__, "ss",
44736 - "server socket is still in use:",
44737 + log_error_write(srv, __FILE__, __LINE__, "ss",
44738 + "server socket is still in use:",
44742 @@ -275,88 +277,89 @@
44746 - log_error_write(srv, __FILE__, __LINE__, "sds",
44747 - "testing socket failed:",
44748 + log_error_write(srv, __FILE__, __LINE__, "sds",
44749 + "testing socket failed:",
44750 host, strerror(errno));
44764 - if (0 != bind(srv_socket->fd, (struct sockaddr *) &(srv_socket->addr), addr_len)) {
44766 + if (0 != bind(srv_socket->sock->fd, (struct sockaddr *) &(srv_socket->addr), addr_len)) {
44767 switch(srv_socket->addr.plain.sa_family) {
44769 - log_error_write(srv, __FILE__, __LINE__, "sds",
44770 - "can't bind to socket:",
44771 + log_error_write(srv, __FILE__, __LINE__, "sds",
44772 + "can't bind to socket:",
44773 host, strerror(errno));
44776 - log_error_write(srv, __FILE__, __LINE__, "ssds",
44777 - "can't bind to port:",
44778 + log_error_write(srv, __FILE__, __LINE__, "ssds",
44779 + "can't bind to port:",
44780 host, port, strerror(errno));
44786 - if (-1 == listen(srv_socket->fd, 128 * 8)) {
44788 + if (-1 == listen(srv_socket->sock->fd, 128 * 8)) {
44789 log_error_write(srv, __FILE__, __LINE__, "ss", "listen failed: ", strerror(errno));
44796 if (srv->ssl_is_init == 0) {
44797 SSL_load_error_strings();
44798 SSL_library_init();
44799 srv->ssl_is_init = 1;
44802 if (0 == RAND_status()) {
44803 - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
44804 + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
44805 "not enough entropy in the pool");
44811 if (NULL == (s->ssl_ctx = SSL_CTX_new(SSLv23_server_method()))) {
44812 - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
44813 + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
44814 ERR_error_string(ERR_get_error(), NULL));
44819 if (buffer_is_empty(s->ssl_pemfile)) {
44820 log_error_write(srv, __FILE__, __LINE__, "s", "ssl.pemfile has to be set");
44825 if (!buffer_is_empty(s->ssl_ca_file)) {
44826 if (1 != SSL_CTX_load_verify_locations(s->ssl_ctx, s->ssl_ca_file->ptr, NULL)) {
44827 - log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
44828 + log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
44829 ERR_error_string(ERR_get_error(), NULL), s->ssl_ca_file);
44835 if (SSL_CTX_use_certificate_file(s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) {
44836 - log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
44837 + log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
44838 ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
44843 if (SSL_CTX_use_PrivateKey_file (s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) {
44844 - log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
44845 + log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
44846 ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
44851 if (SSL_CTX_check_private_key(s->ssl_ctx) != 1) {
44852 - log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:",
44853 + log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:",
44854 "Private key does not match the certificate public key, reason:",
44855 ERR_error_string(ERR_get_error(), NULL),
44857 @@ -364,15 +367,15 @@
44859 srv_socket->ssl_ctx = s->ssl_ctx;
44863 buffer_free(srv_socket->srv_token);
44869 - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
44871 + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
44872 "ssl requested but openssl support is not compiled in");
44878 @@ -383,17 +386,16 @@
44880 memset(&afa, 0, sizeof(afa));
44881 strcpy(afa.af_name, "httpready");
44882 - if (setsockopt(srv_socket->fd, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(afa)) < 0) {
44883 + if (setsockopt(srv_socket->sock->fd, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(afa)) < 0) {
44884 if (errno != ENOENT) {
44885 log_error_write(srv, __FILE__, __LINE__, "ss", "can't set accept-filter 'httpready': ", strerror(errno));
44892 srv_socket->is_ssl = s->is_ssl;
44893 - srv_socket->fde_ndx = -1;
44896 if (srv->srv_sockets.size == 0) {
44897 srv->srv_sockets.size = 4;
44898 srv->srv_sockets.used = 0;
44899 @@ -402,11 +404,10 @@
44900 srv->srv_sockets.size += 4;
44901 srv->srv_sockets.ptr = realloc(srv->srv_sockets.ptr, srv->srv_sockets.size * sizeof(server_socket));
44905 srv->srv_sockets.ptr[srv->srv_sockets.used++] = srv_socket;
44913 @@ -414,45 +415,60 @@
44915 for (i = 0; i < srv->srv_sockets.used; i++) {
44916 server_socket *srv_socket = srv->srv_sockets.ptr[i];
44918 - if (srv_socket->fd != -1) {
44920 + if (srv_socket->sock->fd != -1) {
44921 /* check if server fd are already registered */
44922 - if (srv_socket->fde_ndx != -1) {
44923 - fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd);
44924 - fdevent_unregister(srv->ev, srv_socket->fd);
44925 + if (srv_socket->sock->fde_ndx != -1) {
44926 + fdevent_event_del(srv->ev, srv_socket->sock);
44927 + fdevent_unregister(srv->ev, srv_socket->sock);
44930 - close(srv_socket->fd);
44932 + closesocket(srv_socket->sock->fd);
44935 + if (srv_socket->is_ssl) {
44936 +#ifdef USE_OPENSSL
44937 + SSL_CTX_free(srv_socket->ssl_ctx);
44942 + iosocket_free(srv_socket->sock);
44944 buffer_free(srv_socket->srv_token);
44951 +#ifdef USE_OPENSSL
44952 + ERR_free_strings();
44954 free(srv->srv_sockets.ptr);
44961 NETWORK_BACKEND_UNSET,
44963 NETWORK_BACKEND_WRITE,
44964 NETWORK_BACKEND_WRITEV,
44965 NETWORK_BACKEND_LINUX_SENDFILE,
44966 NETWORK_BACKEND_FREEBSD_SENDFILE,
44967 - NETWORK_BACKEND_SOLARIS_SENDFILEV
44968 + NETWORK_BACKEND_SOLARIS_SENDFILEV,
44970 + NETWORK_BACKEND_WIN32_SEND,
44971 + NETWORK_BACKEND_WIN32_TRANSMITFILE,
44972 } network_backend_t;
44974 int network_init(server *srv) {
44977 network_backend_t backend;
44980 - network_backend_t nb;
44981 - const char *name;
44982 - } network_backends[] = {
44985 + network_backend_t nb;
44986 + const char *name;
44987 + } network_backends[] = {
44988 /* lowest id wins */
44989 #if defined USE_LINUX_SENDFILE
44990 { NETWORK_BACKEND_LINUX_SENDFILE, "linux-sendfile" },
44991 @@ -466,21 +482,30 @@
44992 #if defined USE_WRITEV
44993 { NETWORK_BACKEND_WRITEV, "writev" },
44995 +#if defined USE_WRITE
44996 { NETWORK_BACKEND_WRITE, "write" },
44998 +#if defined USE_WIN32_TRANSMITFILE
44999 + { NETWORK_BACKEND_WIN32_TRANSMITFILE, "win32-transmitfile" },
45001 +#if defined USE_WIN32_SEND
45002 + { NETWORK_BACKEND_WIN32_SEND, "win32-send" },
45005 { NETWORK_BACKEND_UNSET, NULL }
45012 buffer_copy_string_buffer(b, srv->srvconf.bindhost);
45013 buffer_append_string(b, ":");
45014 buffer_append_long(b, srv->srvconf.port);
45017 if (0 != network_server_init(srv, b, srv->config_storage[0])) {
45024 srv->network_ssl_backend_write = network_write_chunkqueue_openssl;
45026 @@ -500,54 +525,80 @@
45027 if (NULL == network_backends[i].name) {
45028 /* we don't know it */
45030 - log_error_write(srv, __FILE__, __LINE__, "sb",
45031 - "server.network-backend has a unknown value:",
45032 + log_error_write(srv, __FILE__, __LINE__, "sb",
45033 + "server.network-backend has a unknown value:",
45034 srv->srvconf.network_backend);
45040 +#define SET_NETWORK_BACKEND(read, write) \
45041 + srv->network_backend_write = network_write_chunkqueue_##write;\
45042 + srv->network_backend_read = network_read_chunkqueue_##read
45044 +#define SET_NETWORK_BACKEND_SSL(read, write) \
45045 + srv->network_ssl_backend_write = network_write_chunkqueue_##write;\
45046 + srv->network_ssl_backend_read = network_read_chunkqueue_##read
45050 +#ifdef USE_WIN32_SEND
45051 + case NETWORK_BACKEND_WIN32_SEND:
45052 + SET_NETWORK_BACKEND(win32recv, win32send);
45054 +#ifdef USE_WIN32_TRANSMITFILE
45055 + case NETWORK_BACKEND_WIN32_TRANSMITFILE:
45056 + SET_NETWORK_BACKEND(win32recv, win32transmitfile);
45062 case NETWORK_BACKEND_WRITE:
45063 - srv->network_backend_write = network_write_chunkqueue_write;
45064 + SET_NETWORK_BACKEND(read, write);
45068 case NETWORK_BACKEND_WRITEV:
45069 - srv->network_backend_write = network_write_chunkqueue_writev;
45070 + SET_NETWORK_BACKEND(read, writev);
45073 #ifdef USE_LINUX_SENDFILE
45074 case NETWORK_BACKEND_LINUX_SENDFILE:
45075 - srv->network_backend_write = network_write_chunkqueue_linuxsendfile;
45076 + SET_NETWORK_BACKEND(read, linuxsendfile);
45079 #ifdef USE_FREEBSD_SENDFILE
45080 case NETWORK_BACKEND_FREEBSD_SENDFILE:
45081 - srv->network_backend_write = network_write_chunkqueue_freebsdsendfile;
45082 + SET_NETWORK_BACKEND(read, freebsdsendfile);
45085 #ifdef USE_SOLARIS_SENDFILEV
45086 case NETWORK_BACKEND_SOLARIS_SENDFILEV:
45087 - srv->network_backend_write = network_write_chunkqueue_solarissendfilev;
45088 + SET_NETWORK_BACKEND(read, solarissendfilev);
45095 +#ifdef USE_OPENSSL
45096 + SET_NETWORK_BACKEND_SSL(openssl, openssl);
45099 /* check for $SERVER["socket"] */
45100 for (i = 1; i < srv->config_context->used; i++) {
45101 data_config *dc = (data_config *)srv->config_context->data[i];
45102 specific_config *s = srv->config_storage[i];
45106 /* not our stage */
45107 if (COMP_SERVER_SOCKET != dc->comp) continue;
45110 if (dc->cond != CONFIG_COND_EQ) {
45111 log_error_write(srv, __FILE__, __LINE__, "s", "only == is allowed for $SERVER[\"socket\"].");
45117 @@ -558,36 +609,47 @@
45123 if (j == srv->srv_sockets.used) {
45124 if (0 != network_server_init(srv, dc->string, s)) return -1;
45132 int network_register_fdevents(server *srv) {
45135 if (-1 == fdevent_reset(srv->ev)) {
45139 /* register fdevents after reset */
45140 for (i = 0; i < srv->srv_sockets.used; i++) {
45141 server_socket *srv_socket = srv->srv_sockets.ptr[i];
45143 - fdevent_register(srv->ev, srv_socket->fd, network_server_handle_fdevent, srv_socket);
45144 - fdevent_event_add(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN);
45145 + fdevent_register(srv->ev, srv_socket->sock, network_server_handle_fdevent, srv_socket);
45146 + fdevent_event_add(srv->ev, srv_socket->sock, FDEVENT_IN);
45151 -int network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq) {
45153 +network_status_t network_read_chunkqueue(server *srv, connection *con, chunkqueue *cq) {
45154 + server_socket *srv_socket = con->srv_socket;
45156 + if (srv_socket->is_ssl) {
45157 +#ifdef USE_OPENSSL
45158 + return srv->network_ssl_backend_read(srv, con, con->sock, cq);
45160 + return NETWORK_STATUS_FATAL_ERROR;
45163 + return srv->network_backend_read(srv, con, con->sock, cq);
45167 +network_status_t network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq) {
45168 + network_status_t ret = NETWORK_STATUS_UNSET;
45174 server_socket *srv_socket = con->srv_socket;
45175 @@ -600,37 +662,42 @@
45176 joblist_append(srv, con);
45182 written = cq->bytes_out;
45186 /* Linux: put a cork into the socket as we want to combine the write() calls
45187 * but only if we really have multiple chunks
45189 if (cq->first && cq->first->next) {
45191 - setsockopt(con->fd, IPPROTO_TCP, TCP_CORK, &corked, sizeof(corked));
45192 + setsockopt(con->sock->fd, IPPROTO_TCP, TCP_CORK, &corked, sizeof(corked));
45197 if (srv_socket->is_ssl) {
45199 - ret = srv->network_ssl_backend_write(srv, con, con->ssl, cq);
45200 + ret = srv->network_ssl_backend_write(srv, con, con->sock, cq);
45203 - ret = srv->network_backend_write(srv, con, con->fd, cq);
45204 + ret = srv->network_backend_write(srv, con, con->sock, cq);
45210 + case NETWORK_STATUS_WAIT_FOR_EVENT:
45211 + case NETWORK_STATUS_SUCCESS:
45212 chunkqueue_remove_finished_chunks(cq);
45213 - ret = chunkqueue_is_empty(cq) ? 0 : 1;
45224 - setsockopt(con->fd, IPPROTO_TCP, TCP_CORK, &corked, sizeof(corked));
45225 + setsockopt(con->sock->fd, IPPROTO_TCP, TCP_CORK, &corked, sizeof(corked));
45229 @@ -639,13 +706,13 @@
45230 con->bytes_written_cur_second += written;
45232 *(con->conf.global_bytes_per_second_cnt_ptr) += written;
45235 if (con->conf.kbytes_per_second &&
45236 (con->bytes_written_cur_second > con->conf.kbytes_per_second * 1024)) {
45237 /* we reached the traffic limit */
45239 con->traffic_limit_reached = 1;
45240 joblist_append(srv, con);
45245 --- ../lighttpd-1.4.11/src/network.h 2005-08-11 01:26:42.000000000 +0300
45246 +++ lighttpd-1.4.12/src/network.h 2006-07-18 13:03:40.000000000 +0300
45249 #include "server.h"
45251 -int network_write_chunkqueue(server *srv, connection *con, chunkqueue *c);
45252 +network_status_t network_write_chunkqueue(server *srv, connection *con, chunkqueue *c);
45253 +network_status_t network_read_chunkqueue(server *srv, connection *con, chunkqueue *c);
45255 int network_init(server *srv);
45256 int network_close(server *srv);
45258 int network_register_fdevents(server *srv);
45259 +handler_t network_server_handle_fdevent(void *s, void *context, int revents);
45262 --- ../lighttpd-1.4.11/src/network_backends.h 2005-10-24 15:13:51.000000000 +0300
45263 +++ lighttpd-1.4.12/src/network_backends.h 2006-07-18 13:03:40.000000000 +0300
45264 @@ -43,16 +43,47 @@
45265 # define USE_AIX_SENDFILE
45269 +* unix can use read/write or recv/send on sockets
45270 +* win32 only recv/send
45273 +# define USE_WIN32_SEND
45274 +/* wait for async-io support
45275 +# define USE_WIN32_TRANSMITFILE
45278 +# define USE_WRITE
45282 +#include "network.h"
45284 +#define NETWORK_BACKEND_WRITE_CHUNK(x) \
45285 + network_status_t network_write_chunkqueue_##x(server *srv, connection *con, iosocket *sock, chunkqueue *cq, chunk *c)
45287 +#define NETWORK_BACKEND_WRITE(x) \
45288 + network_status_t network_write_chunkqueue_##x(server *srv, connection *con, iosocket *sock, chunkqueue *cq)
45289 +#define NETWORK_BACKEND_READ(x) \
45290 + network_status_t network_read_chunkqueue_##x(server *srv, connection *con, iosocket *sock, chunkqueue *cq)
45292 +NETWORK_BACKEND_WRITE_CHUNK(writev_mem);
45294 +NETWORK_BACKEND_WRITE(write);
45295 +NETWORK_BACKEND_WRITE(writev);
45296 +NETWORK_BACKEND_WRITE(linuxsendfile);
45297 +NETWORK_BACKEND_WRITE(freebsdsendfile);
45298 +NETWORK_BACKEND_WRITE(solarissendfilev);
45300 +NETWORK_BACKEND_WRITE(win32transmitfile);
45301 +NETWORK_BACKEND_WRITE(win32send);
45303 +NETWORK_BACKEND_READ(read);
45304 +NETWORK_BACKEND_READ(win32recv);
45306 -int network_write_chunkqueue_write(server *srv, connection *con, int fd, chunkqueue *cq);
45307 -int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkqueue *cq);
45308 -int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd, chunkqueue *cq);
45309 -int network_write_chunkqueue_freebsdsendfile(server *srv, connection *con, int fd, chunkqueue *cq);
45310 -int network_write_chunkqueue_solarissendfilev(server *srv, connection *con, int fd, chunkqueue *cq);
45312 -int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chunkqueue *cq);
45313 +NETWORK_BACKEND_WRITE(openssl);
45314 +NETWORK_BACKEND_READ(openssl);
45318 --- ../lighttpd-1.4.11/src/network_freebsd_sendfile.c 2005-10-22 12:28:18.000000000 +0300
45319 +++ lighttpd-1.4.12/src/network_freebsd_sendfile.c 2006-07-16 00:26:04.000000000 +0300
45320 @@ -26,142 +26,61 @@
45323 # ifdef __FreeBSD__
45324 -/* FreeBSD 4.7, 4.9 defined it in sys/uio.h only if _KERNEL is specified */
45325 +/* FreeBSD 4.7, 4.9 defined it in sys/uio.h only if _KERNEL is specified */
45326 # define UIO_MAXIOV 1024
45330 -int network_write_chunkqueue_freebsdsendfile(server *srv, connection *con, int fd, chunkqueue *cq) {
45331 +NETWORK_BACKEND_WRITE(freebsdsendfile) {
45333 size_t chunks_written = 0;
45336 for(c = cq->first; c; c = c->next, chunks_written++) {
45337 int chunk_finished = 0;
45339 + network_status_t ret;
45342 - case MEM_CHUNK: {
45347 - size_t num_chunks, i;
45348 - struct iovec chunks[UIO_MAXIOV];
45350 - size_t num_bytes = 0;
45352 - /* we can't send more then SSIZE_MAX bytes in one chunk */
45354 - /* build writev list
45356 - * 1. limit: num_chunks < UIO_MAXIOV
45357 - * 2. limit: num_bytes < SSIZE_MAX
45359 - for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
45361 - for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
45362 - if (tc->mem->used == 0) {
45363 - chunks[i].iov_base = tc->mem->ptr;
45364 - chunks[i].iov_len = 0;
45366 - offset = tc->mem->ptr + tc->offset;
45367 - toSend = tc->mem->used - 1 - tc->offset;
45369 - chunks[i].iov_base = offset;
45371 - /* protect the return value of writev() */
45372 - if (toSend > SSIZE_MAX ||
45373 - num_bytes + toSend > SSIZE_MAX) {
45374 - chunks[i].iov_len = SSIZE_MAX - num_bytes;
45376 - num_chunks = i + 1;
45379 - chunks[i].iov_len = toSend;
45382 - num_bytes += toSend;
45386 - if ((r = writev(fd, chunks, num_chunks)) < 0) {
45396 - log_error_write(srv, __FILE__, __LINE__, "ssd",
45397 - "writev failed:", strerror(errno), fd);
45402 + ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, &c);
45407 - /* check which chunks have been written */
45408 - cq->bytes_out += r;
45410 - for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
45411 - if (r >= (ssize_t)chunks[i].iov_len) {
45413 - r -= chunks[i].iov_len;
45414 - tc->offset += chunks[i].iov_len;
45416 - if (chunk_finished) {
45417 - /* skip the chunks from further touches */
45418 - chunks_written++;
45421 - /* chunks_written + c = c->next is done in the for()*/
45422 - chunk_finished++;
45425 - /* partially written */
45428 - chunk_finished = 0;
45432 + if (ret != NETWORK_STATUS_SUCCESS) {
45437 + chunk_finished = 1;
45444 stat_cache_entry *sce = NULL;
45448 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
45449 log_error_write(srv, __FILE__, __LINE__, "sb",
45450 strerror(errno), c->file.name);
45452 + return NETWORK_STATUS_FATAL_ERROR;
45456 offset = c->file.start + c->offset;
45457 /* limit the toSend to 2^31-1 bytes in a chunk */
45458 - toSend = c->file.length - c->offset > ((1 << 30) - 1) ?
45459 + toSend = c->file.length - c->offset > ((1 << 30) - 1) ?
45460 ((1 << 30) - 1) : c->file.length - c->offset;
45463 if (offset > sce->st.st_size) {
45464 log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
45468 + return NETWORK_STATUS_FATAL_ERROR;
45472 if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
45473 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
45477 + return NETWORK_STATUS_FATAL_ERROR;
45484 /* FreeBSD sendfile() */
45485 if (-1 == sendfile(ifd, fd, offset, toSend, NULL, &r, 0)) {
45487 @@ -169,39 +88,39 @@
45492 + return NETWORK_STATUS_CONNECTION_CLOSE;
45494 log_error_write(srv, __FILE__, __LINE__, "ssd", "sendfile: ", strerror(errno), errno);
45497 + return NETWORK_STATUS_FATAL_ERROR;
45504 cq->bytes_out += r;
45507 if (c->offset == c->file.length) {
45508 chunk_finished = 1;
45517 log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
45524 if (!chunk_finished) {
45525 /* not finished yet */
45532 - return chunks_written;
45533 + return NETWORK_STATUS_SUCCESS;
45537 --- ../lighttpd-1.4.11/src/network_linux_sendfile.c 2006-02-15 20:02:36.000000000 +0200
45538 +++ lighttpd-1.4.12/src/network_linux_sendfile.c 2006-07-18 13:03:40.000000000 +0300
45539 @@ -26,122 +26,54 @@
45540 /* on linux 2.4.29 + debian/ubuntu we have crashes if this is enabled */
45541 #undef HAVE_POSIX_FADVISE
45543 -int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd, chunkqueue *cq) {
45545 +NETWORK_BACKEND_WRITE(linuxsendfile) {
45547 size_t chunks_written = 0;
45550 for(c = cq->first; c; c = c->next, chunks_written++) {
45551 int chunk_finished = 0;
45553 + network_status_t ret;
45556 - case MEM_CHUNK: {
45561 - size_t num_chunks, i;
45562 - struct iovec chunks[UIO_MAXIOV];
45564 - size_t num_bytes = 0;
45566 - /* we can't send more then SSIZE_MAX bytes in one chunk */
45568 - /* build writev list
45570 - * 1. limit: num_chunks < UIO_MAXIOV
45571 - * 2. limit: num_bytes < SSIZE_MAX
45573 - for (num_chunks = 0, tc = c;
45574 - tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV;
45575 - tc = tc->next, num_chunks++);
45577 - for (tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
45578 - if (tc->mem->used == 0) {
45579 - chunks[i].iov_base = tc->mem->ptr;
45580 - chunks[i].iov_len = 0;
45582 - offset = tc->mem->ptr + tc->offset;
45583 - toSend = tc->mem->used - 1 - tc->offset;
45585 - chunks[i].iov_base = offset;
45587 - /* protect the return value of writev() */
45588 - if (toSend > SSIZE_MAX ||
45589 - num_bytes + toSend > SSIZE_MAX) {
45590 - chunks[i].iov_len = SSIZE_MAX - num_bytes;
45592 - num_chunks = i + 1;
45595 - chunks[i].iov_len = toSend;
45598 - num_bytes += toSend;
45602 - if ((r = writev(fd, chunks, num_chunks)) < 0) {
45612 - log_error_write(srv, __FILE__, __LINE__, "ssd",
45613 - "writev failed:", strerror(errno), fd);
45619 - /* check which chunks have been written */
45620 - cq->bytes_out += r;
45622 + ret = network_write_chunkqueue_writev_mem(srv, con, sock, cq, c);
45624 - for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
45625 - if (r >= (ssize_t)chunks[i].iov_len) {
45627 - r -= chunks[i].iov_len;
45628 - tc->offset += chunks[i].iov_len;
45630 + /* check which chunks are finished now */
45631 + for (tc = c; tc; tc = tc->next) {
45632 + /* finished the chunk */
45633 + if (tc->offset == tc->mem->used - 1) {
45634 + /* skip the first c->next as that will be done by the c = c->next in the other for()-loop */
45635 if (chunk_finished) {
45636 - /* skip the chunks from further touches */
45637 - chunks_written++;
45640 - /* chunks_written + c = c->next is done in the for()*/
45641 - chunk_finished++;
45642 + chunk_finished = 1;
45645 - /* partially written */
45648 - chunk_finished = 0;
45655 + if (ret != NETWORK_STATUS_SUCCESS) {
45665 stat_cache_entry *sce = NULL;
45668 offset = c->file.start + c->offset;
45669 /* limit the toSend to 2^31-1 bytes in a chunk */
45670 - toSend = c->file.length - c->offset > ((1 << 30) - 1) ?
45671 + toSend = c->file.length - c->offset > ((1 << 30) - 1) ?
45672 ((1 << 30) - 1) : c->file.length - c->offset;
45674 - /* open file if not already opened */
45676 + /* open file if not already opened */
45677 if (-1 == c->file.fd) {
45678 if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
45679 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
45685 @@ -151,14 +83,14 @@
45686 /* tell the kernel that we want to stream the file */
45687 if (-1 == posix_fadvise(c->file.fd, 0, 0, POSIX_FADV_SEQUENTIAL)) {
45688 if (ENOSYS != errno) {
45689 - log_error_write(srv, __FILE__, __LINE__, "ssd",
45690 + log_error_write(srv, __FILE__, __LINE__, "ssd",
45691 "posix_fadvise failed:", strerror(errno), c->file.fd);
45697 - if (-1 == (r = sendfile(fd, c->file.fd, &offset, toSend))) {
45698 + if (-1 == (r = sendfile(sock->fd, c->file.fd, &offset, toSend))) {
45702 @@ -166,11 +98,11 @@
45707 + return NETWORK_STATUS_CONNECTION_CLOSE;
45709 - log_error_write(srv, __FILE__, __LINE__, "ssd",
45710 - "sendfile failed:", strerror(errno), fd);
45712 + log_error_write(srv, __FILE__, __LINE__, "ssd",
45713 + "sendfile failed:", strerror(errno), sock->fd);
45714 + return NETWORK_STATUS_FATAL_ERROR;
45718 @@ -179,39 +111,39 @@
45720 * - the file shrinked -> error
45721 * - the remote side closed inbetween -> remote-close */
45724 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
45725 /* file is gone ? */
45727 + return NETWORK_STATUS_FATAL_ERROR;
45730 if (offset > sce->st.st_size) {
45731 /* file shrinked, close the connection */
45733 + return NETWORK_STATUS_FATAL_ERROR;
45737 + return NETWORK_STATUS_CONNECTION_CLOSE;
45740 #ifdef HAVE_POSIX_FADVISE
45743 -#define M * 1024 K
45744 +#define M * 1024 K
45745 #define READ_AHEAD 4 M
45746 /* check if we need a new chunk */
45747 if ((c->offset & ~(READ_AHEAD - 1)) != ((c->offset + r) & ~(READ_AHEAD - 1))) {
45748 /* tell the kernel that we want to stream the file */
45749 if (-1 == posix_fadvise(c->file.fd, (c->offset + r) & ~(READ_AHEAD - 1), READ_AHEAD, POSIX_FADV_NOREUSE)) {
45750 - log_error_write(srv, __FILE__, __LINE__, "ssd",
45751 + log_error_write(srv, __FILE__, __LINE__, "ssd",
45752 "posix_fadvise failed:", strerror(errno), c->file.fd);
45760 cq->bytes_out += r;
45763 if (c->offset == c->file.length) {
45764 chunk_finished = 1;
45766 @@ -222,24 +154,24 @@
45777 log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
45781 + return NETWORK_STATUS_FATAL_ERROR;
45785 if (!chunk_finished) {
45786 /* not finished yet */
45790 + return NETWORK_STATUS_WAIT_FOR_EVENT;
45794 - return chunks_written;
45795 + return NETWORK_STATUS_SUCCESS;
45799 --- ../lighttpd-1.4.11/src/network_openssl.c 2005-11-17 14:53:29.000000000 +0200
45800 +++ lighttpd-1.4.12/src/network_openssl.c 2006-07-18 13:03:40.000000000 +0300
45801 @@ -23,17 +23,87 @@
45803 #include "stat_cache.h"
45805 -# include <openssl/ssl.h>
45806 -# include <openssl/err.h>
45807 +# include <openssl/ssl.h>
45808 +# include <openssl/err.h>
45810 -int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chunkqueue *cq) {
45811 +NETWORK_BACKEND_READ(openssl) {
45815 + b = chunkqueue_get_append_buffer(cq);
45816 + buffer_prepare_copy(b, 8192);
45817 + len = SSL_read(sock->ssl, b->ptr, b->size - 1);
45819 + log_error_write(srv, __FILE__, __LINE__, "so", "SSL:", len);
45824 + switch ((r = SSL_get_error(sock->ssl, len))) {
45825 + case SSL_ERROR_WANT_READ:
45826 + return NETWORK_STATUS_WAIT_FOR_EVENT;
45827 + case SSL_ERROR_SYSCALL:
45829 + * man SSL_get_error()
45831 + * SSL_ERROR_SYSCALL
45832 + * Some I/O error occurred. The OpenSSL error queue may contain more
45833 + * information on the error. If the error queue is empty (i.e.
45834 + * ERR_get_error() returns 0), ret can be used to find out more about
45835 + * the error: If ret == 0, an EOF was observed that violates the
45836 + * protocol. If ret == -1, the underlying BIO reported an I/O error
45837 + * (for socket I/O on Unix systems, consult errno for details).
45840 + while((ssl_err = ERR_get_error())) {
45841 + /* get all errors from the error-queue */
45842 + log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
45843 + r, ERR_error_string(ssl_err, NULL));
45848 + log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
45850 + strerror(errno));
45855 + case SSL_ERROR_ZERO_RETURN:
45856 + /* clean shutdown on the remote side */
45859 + /* FIXME: later */
45862 + /* fall thourgh */
45864 + while((ssl_err = ERR_get_error())) {
45865 + /* get all errors from the error-queue */
45866 + log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
45867 + r, ERR_error_string(ssl_err, NULL));
45875 + b->ptr[b->used - 1] = '\0';
45877 + return NETWORK_STATUS_SUCCESS;
45881 +NETWORK_BACKEND_WRITE(openssl) {
45884 size_t chunks_written = 0;
45886 /* this is a 64k sendbuffer
45888 - * it has to stay at the same location all the time to satisfy the needs
45889 + * it has to stay at the same location all the time to satisfy the needs
45890 * of SSL_write to pass the SAME parameter in case of a _WANT_WRITE
45892 * the buffer is allocated once, is NOT realloced and is NOT freed at shutdown
45893 @@ -43,59 +113,61 @@
45894 * In reality we would like to use mmap() but we don't have a guarantee that
45895 * we get the same mmap() address for each call. On openbsd the mmap() address
45897 - * That means either we keep the mmap() open or we do a read() into a
45898 - * constant buffer
45899 + * That means either we keep the mmap() open or we do a read() into a
45900 + * constant buffer
45902 #define LOCAL_SEND_BUFSIZE (64 * 1024)
45903 static char *local_send_buffer = NULL;
45905 /* the remote side closed the connection before without shutdown request
45909 * if keep-alive is disabled */
45911 if (con->keep_alive == 0) {
45912 - SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
45913 + SSL_set_shutdown(sock->ssl, SSL_RECEIVED_SHUTDOWN);
45916 for(c = cq->first; c; c = c->next) {
45917 int chunk_finished = 0;
45928 if (c->mem->used == 0) {
45929 chunk_finished = 1;
45934 offset = c->mem->ptr + c->offset;
45935 toSend = c->mem->used - 1 - c->offset;
45939 * SSL_write man-page
45943 * When an SSL_write() operation has to be repeated because of
45944 * SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, it must be
45945 * repeated with the same arguments.
45948 + * SSL_write(..., 0) return 0 which is handle as an error (Success)
45949 + * checking toSend and not calling SSL_write() is simpler
45952 - if ((r = SSL_write(ssl, offset, toSend)) <= 0) {
45954 + if (toSend != 0 && (r = SSL_write(sock->ssl, offset, toSend)) <= 0) {
45957 - switch ((ssl_r = SSL_get_error(ssl, r))) {
45958 + switch ((ssl_r = SSL_get_error(sock->ssl, r))) {
45959 case SSL_ERROR_WANT_WRITE:
45961 case SSL_ERROR_SYSCALL:
45962 /* perhaps we have error waiting in our error-queue */
45963 if (0 != (err = ERR_get_error())) {
45965 - log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
45966 + log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
45968 ERR_error_string(err, NULL));
45969 } while((err = ERR_get_error()));
45970 @@ -105,43 +177,43 @@
45974 - log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
45975 + log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
45981 /* neither error-queue nor errno ? */
45982 - log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
45983 + log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
45990 case SSL_ERROR_ZERO_RETURN:
45991 /* clean shutdown on the remote side */
45994 if (r == 0) return -2;
45999 while((err = ERR_get_error())) {
46000 - log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
46001 + log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
46003 ERR_error_string(err, NULL));
46011 cq->bytes_out += r;
46015 if (c->offset == (off_t)c->mem->used - 1) {
46016 chunk_finished = 1;
46023 @@ -150,7 +222,7 @@
46024 stat_cache_entry *sce = NULL;
46026 int write_wait = 0;
46029 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
46030 log_error_write(srv, __FILE__, __LINE__, "sb",
46031 strerror(errno), c->file.name);
46032 @@ -164,13 +236,13 @@
46035 off_t offset = c->file.start + c->offset;
46036 - off_t toSend = c->file.length - c->offset;
46037 + off_t toSend = c->file.length - c->offset;
46039 if (toSend > LOCAL_SEND_BUFSIZE) toSend = LOCAL_SEND_BUFSIZE;
46042 if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
46043 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed:", strerror(errno));
46049 @@ -183,13 +255,13 @@
46052 s = local_send_buffer;
46057 - if ((r = SSL_write(ssl, s, toSend)) <= 0) {
46059 + if ((r = SSL_write(sock->ssl, s, toSend)) <= 0) {
46062 - switch ((ssl_r = SSL_get_error(ssl, r))) {
46063 + switch ((ssl_r = SSL_get_error(sock->ssl, r))) {
46064 case SSL_ERROR_WANT_WRITE:
46067 @@ -197,7 +269,7 @@
46068 /* perhaps we have error waiting in our error-queue */
46069 if (0 != (err = ERR_get_error())) {
46071 - log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
46072 + log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
46074 ERR_error_string(err, NULL));
46075 } while((err = ERR_get_error()));
46076 @@ -207,62 +279,62 @@
46080 - log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
46081 + log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
46087 /* neither error-queue nor errno ? */
46088 - log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
46089 + log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
46096 case SSL_ERROR_ZERO_RETURN:
46097 /* clean shutdown on the remote side */
46100 if (r == 0) return -2;
46105 while((err = ERR_get_error())) {
46106 - log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
46107 + log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
46109 ERR_error_string(err, NULL));
46117 cq->bytes_out += r;
46121 if (c->offset == c->file.length) {
46122 chunk_finished = 1;
46124 } while(!chunk_finished && !write_wait);
46130 log_error_write(srv, __FILE__, __LINE__, "s", "type not known");
46137 if (!chunk_finished) {
46138 /* not finished yet */
46148 - return chunks_written;
46149 + return NETWORK_STATUS_SUCCESS;
46153 --- ../lighttpd-1.4.11/src/network_solaris_sendfilev.c 2005-10-22 12:28:27.000000000 +0300
46154 +++ lighttpd-1.4.12/src/network_solaris_sendfilev.c 2006-07-16 00:26:04.000000000 +0300
46155 @@ -29,114 +29,34 @@
46159 - * a very simple sendfilev() interface for solaris which can be optimised a lot more
46160 + * a very simple sendfilev() interface for solaris which can be optimised a lot more
46161 * as solaris sendfilev() supports 'sending everythin in one syscall()'
46163 - * If you want such an interface and need the performance, just give me an account on
46166 + * If you want such an interface and need the performance, just give me an account on
46168 * - jan@kneschke.de
46172 -int network_write_chunkqueue_solarissendfilev(server *srv, connection *con, int fd, chunkqueue *cq) {
46173 +NETWORK_BACKEND_WRITE(solarissendfilev) {
46175 size_t chunks_written = 0;
46178 for(c = cq->first; c; c = c->next, chunks_written++) {
46179 int chunk_finished = 0;
46181 + network_status_t ret;
46184 - case MEM_CHUNK: {
46189 - size_t num_chunks, i;
46190 - struct iovec chunks[UIO_MAXIOV];
46193 - size_t num_bytes = 0;
46195 - /* we can't send more then SSIZE_MAX bytes in one chunk */
46197 - /* build writev list
46199 - * 1. limit: num_chunks < UIO_MAXIOV
46200 - * 2. limit: num_bytes < SSIZE_MAX
46202 - for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
46204 - for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
46205 - if (tc->mem->used == 0) {
46206 - chunks[i].iov_base = tc->mem->ptr;
46207 - chunks[i].iov_len = 0;
46209 - offset = tc->mem->ptr + tc->offset;
46210 - toSend = tc->mem->used - 1 - tc->offset;
46212 - chunks[i].iov_base = offset;
46214 - /* protect the return value of writev() */
46215 - if (toSend > SSIZE_MAX ||
46216 - num_bytes + toSend > SSIZE_MAX) {
46217 - chunks[i].iov_len = SSIZE_MAX - num_bytes;
46219 - num_chunks = i + 1;
46222 - chunks[i].iov_len = toSend;
46225 - num_bytes += toSend;
46229 - if ((r = writev(fd, chunks, num_chunks)) < 0) {
46239 - log_error_write(srv, __FILE__, __LINE__, "ssd",
46240 - "writev failed:", strerror(errno), fd);
46246 - /* check which chunks have been written */
46247 - cq->bytes_out += r;
46249 - for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
46250 - if (r >= (ssize_t)chunks[i].iov_len) {
46252 - r -= chunks[i].iov_len;
46253 - tc->offset += chunks[i].iov_len;
46255 - if (chunk_finished) {
46256 - /* skip the chunks from further touches */
46257 - chunks_written++;
46260 - /* chunks_written + c = c->next is done in the for()*/
46261 - chunk_finished++;
46264 - /* partially written */
46267 - chunk_finished = 0;
46272 + ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, &c);
46274 + if (ret != NETWORK_STATUS_SUCCESS) {
46279 + chunk_finished = 1;
46286 @@ -144,25 +64,25 @@
46287 sendfilevec_t fvec;
46288 stat_cache_entry *sce = NULL;
46292 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
46293 log_error_write(srv, __FILE__, __LINE__, "sb",
46294 strerror(errno), c->file.name);
46299 offset = c->file.start + c->offset;
46300 toSend = c->file.length - c->offset;
46303 if (offset > sce->st.st_size) {
46304 log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
46310 if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
46311 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
46317 @@ -170,44 +90,43 @@
46319 fvec.sfv_off = offset;
46320 fvec.sfv_len = toSend;
46323 /* Solaris sendfilev() */
46324 if (-1 == (r = sendfilev(fd, &fvec, 1, &written))) {
46325 if (errno != EAGAIN) {
46326 log_error_write(srv, __FILE__, __LINE__, "ssd", "sendfile: ", strerror(errno), errno);
46331 + return NETWORK_STATUS_FATAL_ERROR;
46340 c->offset += written;
46341 cq->bytes_out += written;
46344 if (c->offset == c->file.length) {
46345 chunk_finished = 1;
46353 log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
46357 + return NETWORK_STATUS_FATAL_ERROR;
46361 if (!chunk_finished) {
46362 /* not finished yet */
46369 - return chunks_written;
46370 + return NETWORK_STATUS_SUCCESS;
46374 --- ../lighttpd-1.4.11/src/network_write.c 2005-10-22 12:27:56.000000000 +0300
46375 +++ lighttpd-1.4.12/src/network_write.c 2006-07-18 13:03:40.000000000 +0300
46377 #include <sys/types.h>
46378 #include <sys/stat.h>
46379 -#include <sys/time.h>
46383 -#include <unistd.h>
46384 #include <string.h>
46385 #include <stdlib.h>
46386 +#include <assert.h>
46388 #include "network.h"
46389 #include "fdevent.h"
46391 #include "stat_cache.h"
46393 #include "sys-socket.h"
46394 +#include "sys-files.h"
46396 #include "network_backends.h"
46400 #ifdef HAVE_SYS_FILIO_H
46401 # include <sys/filio.h>
46403 @@ -24,47 +27,92 @@
46404 #include <sys/resource.h>
46407 -int network_write_chunkqueue_write(server *srv, connection *con, int fd, chunkqueue *cq) {
46410 +* fill the chunkqueue will all the data that we can get
46412 +* this might be optimized into a readv() which uses the chunks
46415 +NETWORK_BACKEND_READ(read) {
46421 + * a EAGAIN is a successful read if we already read something to the chunkqueue
46423 + int read_something = 0;
46425 + /* use a chunk-size of 8k */
46429 + b = chunkqueue_get_append_buffer(cq);
46431 + buffer_prepare_copy(b, toread);
46433 + if (-1 == (r = read(sock->fd, b->ptr, toread))) {
46436 + /* remove the last chunk from the chunkqueue */
46437 + chunkqueue_remove_empty_last_chunk(cq);
46438 + return read_something ? NETWORK_STATUS_SUCCESS : NETWORK_STATUS_WAIT_FOR_EVENT;
46440 + ERROR("oops, read from fd=%d failed: %s (%d)", sock->fd, strerror(errno), errno );
46442 + return NETWORK_STATUS_FATAL_ERROR;
46447 + chunkqueue_remove_empty_last_chunk(cq);
46448 + return read_something ? NETWORK_STATUS_SUCCESS : NETWORK_STATUS_CONNECTION_CLOSE;
46451 + read_something = 1;
46454 + b->ptr[b->used++] = '\0';
46455 + } while (r == toread);
46457 + return NETWORK_STATUS_SUCCESS;
46460 +NETWORK_BACKEND_WRITE(write) {
46462 size_t chunks_written = 0;
46465 for(c = cq->first; c; c = c->next) {
46466 int chunk_finished = 0;
46476 if (c->mem->used == 0) {
46477 chunk_finished = 1;
46482 offset = c->mem->ptr + c->offset;
46483 toSend = c->mem->used - 1 - c->offset;
46485 - if ((r = send(fd, offset, toSend, 0)) < 0) {
46486 - log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed: ", strerror(errno), fd);
46491 - if ((r = write(fd, offset, toSend)) < 0) {
46492 - log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed: ", strerror(errno), fd);
46496 + if ((r = write(sock->fd, offset, toSend)) < 0) {
46497 + log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed: ", strerror(errno), sock->fd);
46499 + return NETWORK_STATUS_FATAL_ERROR;
46505 cq->bytes_out += r;
46508 if (c->offset == (off_t)c->mem->used - 1) {
46509 chunk_finished = 1;
46516 @@ -76,93 +124,89 @@
46518 stat_cache_entry *sce = NULL;
46522 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
46523 log_error_write(srv, __FILE__, __LINE__, "sb",
46524 strerror(errno), c->file.name);
46526 + return NETWORK_STATUS_FATAL_ERROR;
46530 offset = c->file.start + c->offset;
46531 toSend = c->file.length - c->offset;
46534 if (offset > sce->st.st_size) {
46535 log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
46539 + return NETWORK_STATUS_FATAL_ERROR;
46542 if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
46543 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
46547 + return NETWORK_STATUS_FATAL_ERROR;
46551 #if defined USE_MMAP
46552 if (MAP_FAILED == (p = mmap(0, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
46553 log_error_write(srv, __FILE__, __LINE__, "ss", "mmap failed: ", strerror(errno));
46559 + return NETWORK_STATUS_FATAL_ERROR;
46563 - if ((r = write(fd, p + offset, toSend)) <= 0) {
46564 + if ((r = write(sock->fd, p + offset, toSend)) <= 0) {
46565 log_error_write(srv, __FILE__, __LINE__, "ss", "write failed: ", strerror(errno));
46566 munmap(p, sce->st.st_size);
46568 + return NETWORK_STATUS_FATAL_ERROR;
46572 munmap(p, sce->st.st_size);
46574 buffer_prepare_copy(srv->tmp_buf, toSend);
46577 lseek(ifd, offset, SEEK_SET);
46578 if (-1 == (toSend = read(ifd, srv->tmp_buf->ptr, toSend))) {
46579 log_error_write(srv, __FILE__, __LINE__, "ss", "read: ", strerror(errno));
46584 + return NETWORK_STATUS_FATAL_ERROR;
46588 - if (-1 == (r = send(fd, srv->tmp_buf->ptr, toSend, 0))) {
46589 + if (-1 == (r = send(sock->fd, srv->tmp_buf->ptr, toSend, 0))) {
46590 log_error_write(srv, __FILE__, __LINE__, "ss", "write: ", strerror(errno));
46594 + return NETWORK_STATUS_FATAL_ERROR;
46598 cq->bytes_out += r;
46601 if (c->offset == c->file.length) {
46602 chunk_finished = 1;
46611 log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
46615 + return NETWORK_STATUS_FATAL_ERROR;
46619 if (!chunk_finished) {
46620 /* not finished yet */
46630 - return chunks_written;
46631 + return NETWORK_STATUS_SUCCESS;
46635 -network_write_init(void) {
46636 - p->write = network_write_write_chunkset;
46639 --- ../lighttpd-1.4.11/src/network_writev.c 2006-02-15 01:02:36.000000000 +0200
46640 +++ lighttpd-1.4.12/src/network_writev.c 2006-07-18 13:03:40.000000000 +0300
46641 @@ -28,10 +28,10 @@
46644 # if defined(__FreeBSD__) || defined(__APPLE__) || defined(__NetBSD__)
46645 -/* FreeBSD 4.7 defines it in sys/uio.h only if _KERNEL is specified */
46646 +/* FreeBSD 4.7 defines it in sys/uio.h only if _KERNEL is specified */
46647 # define UIO_MAXIOV 1024
46648 # elif defined(__sgi)
46649 -/* IRIX 6.5 has sysconf(_SC_IOV_MAX) which might return 512 or bigger */
46650 +/* IRIX 6.5 has sysconf(_SC_IOV_MAX) which might return 512 or bigger */
46651 # define UIO_MAXIOV 512
46652 # elif defined(__sun)
46653 /* Solaris (and SunOS?) defines IOV_MAX instead */
46654 @@ -51,105 +51,121 @@
46655 #define LOCAL_BUFFERING 1
46658 -int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkqueue *cq) {
46660 +NETWORK_BACKEND_WRITE_CHUNK(writev_mem) {
46665 + size_t num_chunks, i;
46666 + struct iovec chunks[UIO_MAXIOV];
46667 + chunk *tc; /* transfer chunks */
46668 + size_t num_bytes = 0;
46670 + /* we can't send more then SSIZE_MAX bytes in one chunk */
46672 + /* build writev list
46674 + * 1. limit: num_chunks < UIO_MAXIOV
46675 + * 2. limit: num_bytes < SSIZE_MAX
46677 + for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
46679 + for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
46680 + if (tc->mem->used == 0) {
46681 + chunks[i].iov_base = tc->mem->ptr;
46682 + chunks[i].iov_len = 0;
46684 + offset = tc->mem->ptr + tc->offset;
46685 + toSend = tc->mem->used - 1 - tc->offset;
46687 + chunks[i].iov_base = offset;
46689 + /* protect the return value of writev() */
46690 + if (toSend > SSIZE_MAX ||
46691 + num_bytes + toSend > SSIZE_MAX) {
46692 + chunks[i].iov_len = SSIZE_MAX - num_bytes;
46694 + num_chunks = i + 1;
46697 + chunks[i].iov_len = toSend;
46700 + num_bytes += toSend;
46704 + if ((r = writev(sock->fd, chunks, num_chunks)) < 0) {
46707 + return NETWORK_STATUS_WAIT_FOR_EVENT;
46709 + return NETWORK_STATUS_INTERRUPTED;
46712 + return NETWORK_STATUS_CONNECTION_CLOSE;
46714 + log_error_write(srv, __FILE__, __LINE__, "ssd",
46715 + "writev failed:", strerror(errno), sock->fd);
46717 + return NETWORK_STATUS_FATAL_ERROR;
46721 + cq->bytes_out += r;
46723 + /* check which chunks have been written */
46725 + for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
46726 + if (r >= (ssize_t)chunks[i].iov_len) {
46728 + r -= chunks[i].iov_len;
46729 + tc->offset += chunks[i].iov_len;
46731 + /* partially written */
46735 + return NETWORK_STATUS_WAIT_FOR_EVENT;
46739 + /* all chunks have been pushed out */
46740 + return NETWORK_STATUS_SUCCESS;
46743 +NETWORK_BACKEND_WRITE(writev) {
46745 size_t chunks_written = 0;
46748 for(c = cq->first; c; c = c->next) {
46749 int chunk_finished = 0;
46751 + network_status_t ret;
46754 - case MEM_CHUNK: {
46759 - size_t num_chunks, i;
46760 - struct iovec chunks[UIO_MAXIOV];
46762 - size_t num_bytes = 0;
46764 - /* we can't send more then SSIZE_MAX bytes in one chunk */
46766 - /* build writev list
46768 - * 1. limit: num_chunks < UIO_MAXIOV
46769 - * 2. limit: num_bytes < SSIZE_MAX
46771 - for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
46773 - for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
46774 - if (tc->mem->used == 0) {
46775 - chunks[i].iov_base = tc->mem->ptr;
46776 - chunks[i].iov_len = 0;
46778 - offset = tc->mem->ptr + tc->offset;
46779 - toSend = tc->mem->used - 1 - tc->offset;
46781 - chunks[i].iov_base = offset;
46783 - /* protect the return value of writev() */
46784 - if (toSend > SSIZE_MAX ||
46785 - num_bytes + toSend > SSIZE_MAX) {
46786 - chunks[i].iov_len = SSIZE_MAX - num_bytes;
46788 - num_chunks = i + 1;
46791 - chunks[i].iov_len = toSend;
46794 - num_bytes += toSend;
46798 - if ((r = writev(fd, chunks, num_chunks)) < 0) {
46808 - log_error_write(srv, __FILE__, __LINE__, "ssd",
46809 - "writev failed:", strerror(errno), fd);
46815 - cq->bytes_out += r;
46817 + ret = network_write_chunkqueue_writev_mem(srv, con, sock, cq, c);
46819 - /* check which chunks have been written */
46821 - for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
46822 - if (r >= (ssize_t)chunks[i].iov_len) {
46824 - r -= chunks[i].iov_len;
46825 - tc->offset += chunks[i].iov_len;
46827 + /* check which chunks are finished now */
46828 + for (tc = c; tc; tc = tc->next) {
46829 + /* finished the chunk */
46830 + if (tc->offset == tc->mem->used - 1) {
46831 + /* skip the first c->next as that will be done by the c = c->next in the other for()-loop */
46832 if (chunk_finished) {
46833 - /* skip the chunks from further touches */
46834 - chunks_written++;
46837 - /* chunks_written + c = c->next is done in the for()*/
46838 - chunk_finished++;
46839 + chunk_finished = 1;
46842 - /* partially written */
46845 - chunk_finished = 0;
46852 + if (ret != NETWORK_STATUS_SUCCESS) {
46861 @@ -159,26 +175,26 @@
46862 #define KByte * 1024
46863 #define MByte * 1024 KByte
46864 #define GByte * 1024 MByte
46865 - const off_t we_want_to_mmap = 512 KByte;
46866 + const off_t we_want_to_mmap = 512 KByte;
46867 char *start = NULL;
46869 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
46870 log_error_write(srv, __FILE__, __LINE__, "sb",
46871 strerror(errno), c->file.name);
46873 + return NETWORK_STATUS_FATAL_ERROR;
46876 abs_offset = c->file.start + c->offset;
46879 if (abs_offset > sce->st.st_size) {
46880 - log_error_write(srv, __FILE__, __LINE__, "sb",
46881 + log_error_write(srv, __FILE__, __LINE__, "sb",
46882 "file was shrinked:", c->file.name);
46886 + return NETWORK_STATUS_FATAL_ERROR;
46889 - /* mmap the buffer
46891 + /* mmap the buffer
46893 * - new mmap as the we are at the end of the last one */
46894 if (c->file.mmap.start == MAP_FAILED ||
46895 abs_offset == (off_t)(c->file.mmap.offset + c->file.mmap.length)) {
46896 @@ -188,7 +204,7 @@
46897 * adaptive mem-mapping
46899 * we mmap() the whole file. If someone has alot large files and 32bit
46900 - * machine the virtual address area will be unrun and we will have a failing
46901 + * machine the virtual address area will be unrun and we will have a failing
46904 * only mmap 16M in one chunk and move the window as soon as we have finished
46905 @@ -234,8 +250,8 @@
46906 if (-1 == c->file.fd) { /* open the file if not already open */
46907 if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
46908 log_error_write(srv, __FILE__, __LINE__, "sbs", "open failed for:", c->file.name, strerror(errno));
46912 + return NETWORK_STATUS_FATAL_ERROR;
46915 fcntl(c->file.fd, F_SETFD, FD_CLOEXEC);
46916 @@ -245,10 +261,10 @@
46917 if (MAP_FAILED == (c->file.mmap.start = mmap(0, to_mmap, PROT_READ, MAP_SHARED, c->file.fd, c->file.mmap.offset))) {
46918 /* close it here, otherwise we'd have to set FD_CLOEXEC */
46920 - log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed:",
46921 + log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed:",
46922 strerror(errno), c->file.name, c->file.fd);
46925 + return NETWORK_STATUS_FATAL_ERROR;
46928 c->file.mmap.length = to_mmap;
46929 @@ -258,7 +274,7 @@
46930 #ifdef HAVE_MADVISE
46931 /* don't advise files < 64Kb */
46932 if (c->file.mmap.length > (64 KByte)) {
46933 - /* darwin 7 is returning EINVAL all the time and I don't know how to
46934 + /* darwin 7 is returning EINVAL all the time and I don't know how to
46935 * detect this at runtime.i
46937 * ignore the return value for now */
46938 @@ -274,12 +290,12 @@
46939 toSend = (c->file.mmap.offset + c->file.mmap.length) - (abs_offset);
46942 - log_error_write(srv, __FILE__, __LINE__, "soooo",
46943 + log_error_write(srv, __FILE__, __LINE__, "soooo",
46944 "toSend is negative:",
46946 c->file.mmap.length,
46948 - c->file.mmap.offset);
46949 + c->file.mmap.offset);
46950 assert(toSend < 0);
46953 @@ -289,7 +305,7 @@
46954 start = c->file.mmap.start;
46957 - if ((r = write(fd, start + (abs_offset - c->file.mmap.offset), toSend)) < 0) {
46958 + if ((r = write(sock->fd, start + (abs_offset - c->file.mmap.offset), toSend)) < 0) {
46962 @@ -297,18 +313,18 @@
46967 + return NETWORK_STATUS_CONNECTION_CLOSE;
46969 - log_error_write(srv, __FILE__, __LINE__, "ssd",
46970 - "write failed:", strerror(errno), fd);
46973 + log_error_write(srv, __FILE__, __LINE__, "ssd",
46974 + "write failed:", strerror(errno), sock->fd);
46976 + return NETWORK_STATUS_FATAL_ERROR;
46982 cq->bytes_out += r;
46985 if (c->offset == c->file.length) {
46986 chunk_finished = 1;
46988 @@ -318,26 +334,26 @@
46989 c->file.mmap.start = MAP_FAILED;
46999 log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
47003 + return NETWORK_STATUS_FATAL_ERROR;
47007 if (!chunk_finished) {
47008 /* not finished yet */
47018 - return chunks_written;
47019 + return NETWORK_STATUS_SUCCESS;
47023 --- ../lighttpd-1.4.11/src/plugin.c 2006-02-08 14:00:54.000000000 +0200
47024 +++ lighttpd-1.4.12/src/plugin.c 2006-07-16 00:26:04.000000000 +0300
47025 @@ -13,27 +13,27 @@
47026 #include <valgrind/valgrind.h>
47036 * if you change this enum to add a new callback, be sure
47037 * - that PLUGIN_FUNC_SIZEOF is the last entry
47038 * - that you add PLUGIN_TO_SLOT twice:
47039 - * 1. as callback-dispatcher
47040 + * 1. as callback-dispatcher
47041 * 2. in plugins_call_init()
47053 - PLUGIN_FUNC_HANDLE_URI_CLEAN,
47054 - PLUGIN_FUNC_HANDLE_URI_RAW,
47055 + PLUGIN_FUNC_HANDLE_URI_CLEAN,
47056 + PLUGIN_FUNC_HANDLE_URI_RAW,
47057 PLUGIN_FUNC_HANDLE_REQUEST_DONE,
47058 PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE,
47059 PLUGIN_FUNC_HANDLE_TRIGGER,
47060 @@ -44,38 +44,42 @@
47061 PLUGIN_FUNC_HANDLE_DOCROOT,
47062 PLUGIN_FUNC_HANDLE_PHYSICAL,
47063 PLUGIN_FUNC_CONNECTION_RESET,
47064 - PLUGIN_FUNC_INIT,
47065 + PLUGIN_FUNC_INIT,
47066 PLUGIN_FUNC_CLEANUP,
47067 PLUGIN_FUNC_SET_DEFAULTS,
47073 static plugin *plugin_init(void) {
47077 p = calloc(1, sizeof(*p));
47080 + p->required_plugins = array_init();
47085 static void plugin_free(plugin *p) {
47086 int use_dlclose = 1;
47087 if (p->name) buffer_free(p->name);
47089 + array_free(p->required_plugins);
47090 #ifdef HAVE_VALGRIND_VALGRIND_H
47091 /*if (RUNNING_ON_VALGRIND) use_dlclose = 0;*/
47094 #ifndef LIGHTTPD_STATIC
47095 - if (use_dlclose && p->lib) {
47097 + if (use_dlclose && p->lib) {
47099 FreeLibrary(p->lib);
47110 @@ -89,17 +93,17 @@
47111 srv->plugins.size += 4;
47112 srv->plugins.ptr = realloc(srv->plugins.ptr, srv->plugins.size * sizeof(*ps));
47116 ps = srv->plugins.ptr;
47117 ps[srv->plugins.used++] = p;
47132 #ifdef LIGHTTPD_STATIC
47133 @@ -121,30 +125,35 @@
47135 int plugins_load(server *srv) {
47140 int (*init)(plugin *pl);
47148 for (i = 0; i < srv->srvconf.modules->used; i++) {
47149 data_string *d = (data_string *)srv->srvconf.modules->data[i];
47150 char *modules = d->value->ptr;
47153 buffer_copy_string_buffer(srv->tmp_buf, srv->srvconf.modules_dir);
47155 buffer_append_string(srv->tmp_buf, "/");
47156 buffer_append_string(srv->tmp_buf, modules);
47157 -#if defined(__WIN32) || defined(__CYGWIN__)
47158 +#if defined(_WIN32) || defined(__CYGWIN__)
47159 buffer_append_string(srv->tmp_buf, ".dll");
47161 buffer_append_string(srv->tmp_buf, ".so");
47168 if (NULL == (p->lib = LoadLibrary(srv->tmp_buf->ptr))) {
47171 - FORMAT_MESSAGE_ALLOCATE_BUFFER |
47172 + FORMAT_MESSAGE_ALLOCATE_BUFFER |
47173 FORMAT_MESSAGE_FROM_SYSTEM,
47176 @@ -152,36 +161,36 @@
47177 (LPTSTR) &lpMsgBuf,
47180 - log_error_write(srv, __FILE__, __LINE__, "ssb", "LoadLibrary() failed",
47181 + log_error_write(srv, __FILE__, __LINE__, "ssb", "LoadLibrary() failed",
47182 lpMsgBuf, srv->tmp_buf);
47193 if (NULL == (p->lib = dlopen(srv->tmp_buf->ptr, RTLD_LAZY))) {
47194 - log_error_write(srv, __FILE__, __LINE__, "sbs", "dlopen() failed for:",
47195 + log_error_write(srv, __FILE__, __LINE__, "sbs", "dlopen() failed for:",
47196 srv->tmp_buf, dlerror());
47207 buffer_reset(srv->tmp_buf);
47208 buffer_copy_string(srv->tmp_buf, modules);
47209 buffer_append_string(srv->tmp_buf, "_plugin_init");
47213 init = GetProcAddress(p->lib, srv->tmp_buf->ptr);
47215 if (init == NULL) {
47218 - FORMAT_MESSAGE_ALLOCATE_BUFFER |
47219 + FORMAT_MESSAGE_ALLOCATE_BUFFER |
47220 FORMAT_MESSAGE_FROM_SYSTEM,
47223 @@ -190,7 +199,7 @@
47226 log_error_write(srv, __FILE__, __LINE__, "sbs", "getprocaddress failed:", srv->tmp_buf, lpMsgBuf);
47232 @@ -203,24 +212,43 @@
47234 if ((error = dlerror()) != NULL) {
47235 log_error_write(srv, __FILE__, __LINE__, "s", error);
47245 log_error_write(srv, __FILE__, __LINE__, "ss", modules, "plugin init failed" );
47252 log_error_write(srv, __FILE__, __LINE__, "ss", modules, "plugin loaded" );
47254 + /* check if the required plugin is loaded */
47255 + for (k = 0; k < p->required_plugins->used; k++) {
47256 + data_string *req = (data_string *)p->required_plugins->data[k];
47258 + for (j = 0; j < i; j++) {
47259 + data_string *mod = (data_string *)srv->srvconf.modules->data[j];
47261 + if (buffer_is_equal(req->value, mod->value)) break;
47266 + log_error_write(srv, __FILE__, __LINE__, "ssbs", modules, "failed to load. required plugin", req->value, "was not loaded" );
47273 plugins_register(srv, p);
47280 @@ -253,8 +281,8 @@
47284 - * plugins that use
47286 + * plugins that use
47289 * - connection *con
47290 * - void *p_d (plugin_data *)
47291 @@ -301,12 +329,12 @@
47295 - * plugins that use
47297 + * plugins that use
47300 * - void *p_d (plugin_data *)
47304 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_TRIGGER, handle_trigger)
47305 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SIGHUP, handle_sighup)
47306 PLUGIN_TO_SLOT(PLUGIN_FUNC_CLEANUP, cleanup)
47307 @@ -314,18 +342,18 @@
47309 #undef PLUGIN_TO_SLOT
47320 handler_t plugins_call_handle_fdevent(server *srv, const fd_conn *fdc) {
47325 ps = srv->plugins.ptr;
47328 for (i = 0; i < srv->plugins.used; i++) {
47330 if (p->handle_fdevent) {
47331 @@ -344,34 +372,34 @@
47337 return HANDLER_GO_ON;
47343 * - call init function of all plugins to init the plugin-internals
47344 * - added each plugin that supports has callback to the corresponding slot
47347 * - is only called once.
47350 handler_t plugins_call_init(server *srv) {
47355 ps = srv->plugins.ptr;
47361 srv->plugin_slots = calloc(PLUGIN_FUNC_SIZEOF, sizeof(ps));
47364 for (i = 0; i < srv->plugins.used; i++) {
47366 /* check which calls are supported */
47372 #define PLUGIN_TO_SLOT(x, y) \
47374 plugin **slot = ((plugin ***)(srv->plugin_slots))[x]; \
47375 @@ -384,11 +412,11 @@
47382 - PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_CLEAN, handle_uri_clean);
47383 - PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_RAW, handle_uri_raw);
47387 + PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_CLEAN, handle_uri_clean);
47388 + PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_RAW, handle_uri_raw);
47389 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_REQUEST_DONE, handle_request_done);
47390 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE, handle_connection_close);
47391 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_TRIGGER, handle_trigger);
47392 @@ -402,19 +430,19 @@
47393 PLUGIN_TO_SLOT(PLUGIN_FUNC_CLEANUP, cleanup);
47394 PLUGIN_TO_SLOT(PLUGIN_FUNC_SET_DEFAULTS, set_defaults);
47395 #undef PLUGIN_TO_SLOT
47399 if (NULL == (p->data = p->init())) {
47400 - log_error_write(srv, __FILE__, __LINE__, "sb",
47401 + log_error_write(srv, __FILE__, __LINE__, "sb",
47402 "plugin-init failed for module", p->name);
47403 return HANDLER_ERROR;
47407 /* used for con->mode, DIRECT == 0, plugins above that */
47408 ((plugin_data *)(p->data))->id = i + 1;
47411 if (p->version != LIGHTTPD_VERSION_ID) {
47412 - log_error_write(srv, __FILE__, __LINE__, "sb",
47413 + log_error_write(srv, __FILE__, __LINE__, "sb",
47414 "plugin-version doesn't match lighttpd-version for", p->name);
47415 return HANDLER_ERROR;
47417 @@ -422,29 +450,46 @@
47423 return HANDLER_GO_ON;
47427 + * get the config-storage of the named plugin
47429 +void *plugin_get_config(server *srv, const char *name) {
47432 + for (i = 0; i < srv->plugins.used; i++) {
47433 + plugin *p = ((plugin **)srv->plugins.ptr)[i];
47435 + if (buffer_is_equal_string(p->name, name, strlen(name))) {
47443 void plugins_free(server *srv) {
47445 plugins_call_cleanup(srv);
47448 for (i = 0; i < srv->plugins.used; i++) {
47449 plugin *p = ((plugin **)srv->plugins.ptr)[i];
47456 for (i = 0; srv->plugin_slots && i < PLUGIN_FUNC_SIZEOF; i++) {
47457 plugin **slot = ((plugin ***)(srv->plugin_slots))[i];
47460 if (slot) free(slot);
47464 free(srv->plugin_slots);
47465 srv->plugin_slots = NULL;
47468 free(srv->plugins.ptr);
47469 srv->plugins.ptr = NULL;
47470 srv->plugins.used = 0;
47471 --- ../lighttpd-1.4.11/src/plugin.h 2005-08-15 12:28:56.000000000 +0300
47472 +++ lighttpd-1.4.12/src/plugin.h 2006-07-16 00:26:04.000000000 +0300
47475 #define INIT_FUNC(x) \
47478 + * The PATCH_OPTION() macro is used in the patch_connection() functions
47479 + * of the modules to update the config object for the current request.
47481 +#define PATCH_OPTION(x) \
47484 #define FREE_FUNC SERVER_FUNC
47485 #define TRIGGER_FUNC SERVER_FUNC
47486 @@ -25,19 +31,19 @@
47487 #define URIHANDLER_FUNC CONNECTION_FUNC
47489 #define PLUGIN_DATA size_t id
47496 buffer *name; /* name of the plugin */
47500 handler_t (* set_defaults) (server *srv, void *p_d);
47501 handler_t (* cleanup) (server *srv, void *p_d);
47502 /* is called ... */
47503 handler_t (* handle_trigger) (server *srv, void *p_d); /* once a second */
47504 handler_t (* handle_sighup) (server *srv, void *p_d); /* at a signup */
47507 handler_t (* handle_uri_raw) (server *srv, connection *con, void *p_d); /* after uri_raw is set */
47508 handler_t (* handle_uri_clean) (server *srv, connection *con, void *p_d); /* after uri is set */
47509 handler_t (* handle_docroot) (server *srv, connection *con, void *p_d); /* getting the document-root */
47510 @@ -45,20 +51,22 @@
47511 handler_t (* handle_request_done) (server *srv, connection *con, void *p_d); /* at the end of a request */
47512 handler_t (* handle_connection_close)(server *srv, connection *con, void *p_d); /* at the end of a connection */
47513 handler_t (* handle_joblist) (server *srv, connection *con, void *p_d); /* after all events are handled */
47517 - handler_t (* handle_subrequest_start)(server *srv, connection *con, void *p_d);
47519 - /* when a handler for the request
47523 + handler_t (* handle_subrequest_start)(server *srv, connection *con, void *p_d);
47525 + /* when a handler for the request
47528 handler_t (* handle_subrequest) (server *srv, connection *con, void *p_d); /* */
47529 handler_t (* connection_reset) (server *srv, connection *con, void *p_d); /* */
47533 /* dlopen handle */
47536 + array *required_plugins;
47539 int plugins_load(server *srv);
47541 int config_patch_connection(server *srv, connection *con, comp_key_t comp);
47542 int config_check_cond(server *srv, connection *con, data_config *dc);
47543 int config_append_cond_match_buffer(connection *con, data_config *dc, buffer *buf, int n);
47544 +int config_exec_pcre_keyvalue_buffer(connection *con, pcre_keyvalue_buffer *kvb, data_config *context, buffer *match_buf, buffer *result);
47546 +void *plugin_get_config(server *srv, const char *name);
47549 --- ../lighttpd-1.4.11/src/proc_open.c 2005-08-11 01:26:39.000000000 +0300
47550 +++ lighttpd-1.4.12/src/proc_open.c 2006-07-16 00:26:04.000000000 +0300
47551 @@ -13,13 +13,13 @@
47557 /* {{{ win32 stuff */
47558 # define SHELLENV "ComSpec"
47559 # define SECURITY_DC , SECURITY_ATTRIBUTES *security
47560 # define SECURITY_CC , security
47561 # define pipe(pair) (CreatePipe(&pair[0], &pair[1], security, 2048L) ? 0 : -1)
47562 -static inline HANDLE dup_handle(HANDLE src, BOOL inherit, BOOL closeorig)
47563 +static HANDLE dup_handle(HANDLE src, BOOL inherit, BOOL closeorig)
47565 HANDLE copy, self = GetCurrentProcess();
47567 @@ -148,11 +148,14 @@
47570 SECURITY_ATTRIBUTES security;
47571 - const char *shell;
47572 + const char *shell = NULL;
47573 + const char *windir = NULL;
47576 - if (NULL == (shell = getenv(SHELLENV))) {
47577 - fprintf(stderr, "env %s is required", SHELLENV);
47578 + if (NULL == (shell = getenv(SHELLENV)) &&
47579 + NULL == (windir = getenv("SystemRoot")) &&
47580 + NULL == (windir = getenv("windir"))) {
47581 + fprintf(stderr, "One of %s,%%SystemRoot,%%windir is required", SHELLENV);
47585 @@ -177,17 +180,23 @@
47586 memset(&pi, 0, sizeof(pi));
47588 cmdline = buffer_init();
47589 - buffer_append_string(cmdline, shell);
47591 + buffer_append_string(cmdline, shell);
47593 + buffer_append_string(cmdline, windir);
47594 + buffer_append_string(cmdline, "\\system32\\cmd.exe");
47596 buffer_append_string_len(cmdline, CONST_STR_LEN(" /c "));
47597 buffer_append_string(cmdline, command);
47598 procok = CreateProcess(NULL, cmdline->ptr, &security, &security, TRUE,
47599 NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);
47600 - buffer_free(cmdline);
47602 if (FALSE == procok) {
47603 - fprintf(stderr, "failed to CreateProcess");
47604 + fprintf(stderr, "failed to CreateProcess: %s", cmdline->ptr);
47605 + buffer_free(cmdline);
47608 + buffer_free(cmdline);
47610 proc->child = pi.hProcess;
47611 CloseHandle(pi.hThread);
47612 @@ -226,8 +235,7 @@
47615 if (NULL == (shell = getenv(SHELLENV))) {
47616 - fprintf(stderr, "env %s is required", SHELLENV);
47618 + shell = "/bin/sh";
47621 if (proc_open_pipes(proc) != 0) {
47622 @@ -262,11 +270,11 @@
47626 -#endif /* WIN32 */
47627 +#endif /* _WIN32 */
47629 /* {{{ proc_read_fd_to_buffer */
47630 static void proc_read_fd_to_buffer(int fd, buffer *b) {
47632 + int s; /* win32 has not ssize_t */
47635 buffer_prepare_append(b, 512);
47636 --- ../lighttpd-1.4.11/src/proc_open.h 2005-08-11 01:26:39.000000000 +0300
47637 +++ lighttpd-1.4.12/src/proc_open.h 2006-07-16 00:26:04.000000000 +0300
47640 #include "buffer.h"
47644 #include <windows.h>
47645 typedef HANDLE descriptor_t;
47646 typedef HANDLE proc_pid_t;
47647 --- ../lighttpd-1.4.11/src/request.c 2006-03-05 11:58:09.000000000 +0200
47648 +++ lighttpd-1.4.12/src/request.c 2006-07-18 13:03:40.000000000 +0300
47649 @@ -10,15 +10,17 @@
47650 #include "keyvalue.h"
47653 +#include "sys-strings.h"
47655 static int request_check_hostname(server *srv, connection *con, buffer *host) {
47656 enum { DOMAINLABEL, TOPLABEL } stage = TOPLABEL;
47661 - int is_ip = -1; /* -1 don't know yet, 0 no, 1 yes */
47662 + int is_ip = -1; /* -1 don't know yet, 0 no, 1 yes */
47669 @@ -32,17 +34,17 @@
47670 * IPv6address = "[" ... "]"
47676 if (!host || host->used == 0) return 0;
47679 host_len = host->used - 1;
47683 if (host->ptr[0] == '[') {
47684 char *c = host->ptr + 1;
47688 /* check portnumber */
47689 for (; *c && *c != ']'; c++) {
47691 @@ -53,12 +55,12 @@
47704 if (*(c+1) == ':') {
47705 for (c += 2; *c; c++) {
47706 @@ -69,39 +71,39 @@
47712 if (NULL != (colon = memchr(host->ptr, ':', host_len))) {
47713 char *c = colon + 1;
47716 /* check portnumber */
47718 if (!light_isdigit(*c)) return -1;
47722 /* remove the port from the host-len */
47723 host_len = colon - host->ptr;
47727 /* Host is empty */
47728 if (host_len == 0) return -1;
47731 /* scan from the right and skip the \0 */
47732 for (i = host_len - 1; i + 1 > 0; i--) {
47733 const char c = host->ptr[i];
47739 /* only switch stage, if this is not the last character */
47740 if (i != host_len - 1) {
47741 if (label_len == 0) {
47746 /* check the first character at right of the dot */
47748 if (!light_isalpha(host->ptr[i+1])) {
47752 } else if (!light_isdigit(host->ptr[i+1])) {
47754 @@ -111,9 +113,9 @@
47760 stage = DOMAINLABEL;
47765 } else if (i == 0) {
47766 @@ -135,7 +137,7 @@
47775 @@ -143,7 +145,7 @@
47776 if (label_len == 0) {
47783 } else if (!light_isdigit(c)) {
47784 @@ -156,12 +158,12 @@
47785 if (label_len == 0) {
47790 /* c is either - or alphanum here */
47791 if ('-' == host->ptr[i+1]) {
47798 } else if (i == 0) {
47799 @@ -176,20 +178,20 @@
47810 /* a IP has to consist of 4 parts */
47811 if (is_ip == 1 && level != 3) {
47816 if (label_len == 0) {
47824 @@ -201,53 +203,53 @@
47834 * val1, val2, val3, val4
47837 * into a array (more or less a explode() incl. striping of whitespaces
47841 if (b->used == 0) return 0;
47847 for (i =0; i < b->used - 1; ) {
47848 char *start = NULL, *end = NULL;
47857 for (; (*s == ' ' || *s == '\t') && i < b->used - 1; i++, s++);
47864 case 1: /* value */
47868 for (; *s != ',' && i < b->used - 1; i++, s++);
47872 for (; (*end == ' ' || *end == '\t') && end > start; end--);
47875 if (NULL == (ds = (data_string *)array_get_unused_element(vals, TYPE_STRING))) {
47876 ds = data_string_init();
47879 buffer_copy_string_len(ds->value, start, end-start+1);
47880 array_insert_unique(vals, (data_unset *)ds);
47888 /* end of string */
47894 @@ -263,7 +265,7 @@
47895 if (c <= 32) return 0;
47896 if (c == 127) return 0;
47897 if (c == 255) return 0;
47903 @@ -271,28 +273,28 @@
47904 char *uri = NULL, *proto = NULL, *method = NULL, con_length_set;
47905 int is_key = 1, key_len = 0, is_ws_after_key = 0, in_folding;
47906 char *value = NULL, *key = NULL;
47909 enum { HTTP_CONNECTION_UNSET, HTTP_CONNECTION_KEEPALIVE, HTTP_CONNECTION_CLOSE } keep_alive_set = HTTP_CONNECTION_UNSET;
47915 int request_line_stage = 0;
47922 data_string *ds = NULL;
47925 - * Request: "^(GET|POST|HEAD) ([^ ]+(\\?[^ ]+|)) (HTTP/1\\.[01])$"
47926 - * Option : "^([-a-zA-Z]+): (.+)$"
47929 + * Request: "^(GET|POST|HEAD) ([^ ]+(\\?[^ ]+|)) (HTTP/1\\.[01])$"
47930 + * Option : "^([-a-zA-Z]+): (.+)$"
47934 if (con->conf.log_request_header) {
47935 - log_error_write(srv, __FILE__, __LINE__, "sdsdSb",
47937 - "request-len:", con->request.request->used,
47938 + log_error_write(srv, __FILE__, __LINE__, "sdsdSb",
47939 + "fd:", con->sock->fd,
47940 + "request-len:", con->request.request->used,
47941 "\n", con->request.request);
47944 @@ -300,13 +302,13 @@
47945 con->request.request->ptr[0] == '\r' &&
47946 con->request.request->ptr[1] == '\n') {
47947 /* we are in keep-alive and might get \r\n after a previous POST request.*/
47950 buffer_copy_string_len(con->parse_request, con->request.request->ptr + 2, con->request.request->used - 1 - 2);
47952 /* fill the local request buffer */
47953 buffer_copy_string_buffer(con->parse_request, con->request.request);
47957 keep_alive_set = 0;
47958 con_length_set = 0;
47960 @@ -318,25 +320,25 @@
47962 for (i = 0, first = 0; i < con->parse_request->used && line == 0; i++) {
47963 char *cur = con->parse_request->ptr + i;
47969 if (con->parse_request->ptr[i+1] == '\n') {
47976 con->parse_request->ptr[i] = '\0';
47977 con->parse_request->ptr[i+1] = '\0';
47980 buffer_copy_string_len(con->request.request_line, con->parse_request->ptr, i);
47983 if (request_line_stage != 2) {
47984 con->http_status = 400;
47985 con->response.keep_alive = 0;
47986 con->keep_alive = 0;
47989 if (srv->srvconf.log_request_header_on_error) {
47990 log_error_write(srv, __FILE__, __LINE__, "s", "incomplete request line -> 400");
47991 log_error_write(srv, __FILE__, __LINE__, "Sb",
47992 @@ -345,36 +347,36 @@
47998 proto = con->parse_request->ptr + first;
48002 *(proto - 1) = '\0';
48005 /* we got the first one :) */
48006 if (-1 == (r = get_http_method_key(method))) {
48007 con->http_status = 501;
48008 con->response.keep_alive = 0;
48009 con->keep_alive = 0;
48012 if (srv->srvconf.log_request_header_on_error) {
48013 log_error_write(srv, __FILE__, __LINE__, "s", "unknown http-method -> 501");
48014 log_error_write(srv, __FILE__, __LINE__, "Sb",
48015 "request-header:\n",
48016 con->request.request);
48024 con->request.http_method = r;
48031 * HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT
48035 if (0 == strncmp(proto, "HTTP/", sizeof("HTTP/") - 1)) {
48036 char * major = proto + sizeof("HTTP/") - 1;
48037 char * minor = strchr(major, '.');
48038 @@ -413,10 +415,10 @@
48041 if (major_num == 1 && minor_num == 1) {
48042 - con->request.http_version = con->conf.allow_http11 ? HTTP_VERSION_1_1 : HTTP_VERSION_1_0;
48043 + con->request.http_version = HTTP_VERSION_1_1;
48044 } else if (major_num == 1 && minor_num == 0) {
48045 con->request.http_version = HTTP_VERSION_1_0;
48048 con->http_status = 505;
48050 if (srv->srvconf.log_request_header_on_error) {
48051 @@ -439,30 +441,30 @@
48057 if (0 == strncmp(uri, "http://", 7) &&
48058 NULL != (nuri = strchr(uri + 7, '/'))) {
48059 /* ignore the host-part */
48062 buffer_copy_string_len(con->request.uri, nuri, proto - nuri - 1);
48064 /* everything looks good so far */
48065 buffer_copy_string_len(con->request.uri, uri, proto - uri - 1);
48069 /* check uri for invalid characters */
48070 for (j = 0; j < con->request.uri->used - 1; j++) {
48071 if (!request_uri_is_valid_char(con->request.uri->ptr[j])) {
48072 unsigned char buf[2];
48073 con->http_status = 400;
48074 con->keep_alive = 0;
48077 if (srv->srvconf.log_request_header_on_error) {
48078 buf[0] = con->request.uri->ptr[j];
48082 if (con->request.uri->ptr[j] > 32 &&
48083 - con->request.uri->ptr[j] != 127) {
48084 + con->request.uri->ptr[j] != 127) {
48085 /* the character is printable -> print it */
48086 log_error_write(srv, __FILE__, __LINE__, "ss",
48087 "invalid character in URI -> 400",
48088 @@ -473,20 +475,20 @@
48089 "invalid character in URI -> 400",
48090 con->request.uri->ptr[j]);
48094 log_error_write(srv, __FILE__, __LINE__, "Sb",
48095 "request-header:\n",
48096 con->request.request);
48105 buffer_copy_string_buffer(con->request.orig_uri, con->request.uri);
48108 con->http_status = 0;
48114 @@ -494,14 +496,14 @@
48117 switch(request_line_stage) {
48121 - method = con->parse_request->ptr + first;
48122 + method = con->parse_request->ptr + first;
48127 - uri = con->parse_request->ptr + first;
48128 + uri = con->parse_request->ptr + first;
48132 @@ -509,7 +511,7 @@
48133 con->http_status = 400;
48134 con->response.keep_alive = 0;
48135 con->keep_alive = 0;
48138 if (srv->srvconf.log_request_header_on_error) {
48139 log_error_write(srv, __FILE__, __LINE__, "s", "overlong request line -> 400");
48140 log_error_write(srv, __FILE__, __LINE__, "Sb",
48141 @@ -518,12 +520,12 @@
48147 request_line_stage++;
48155 if (con->request.uri->used == 1) {
48156 @@ -540,30 +542,30 @@
48162 for (; i < con->parse_request->used && !done; i++) {
48163 char *cur = con->parse_request->ptr + i;
48172 * 1*<any CHAR except CTLs or separators>
48173 * CTLs == 0-31 + 127
48185 if (is_ws_after_key == 0) {
48186 key_len = i - first;
48188 is_ws_after_key = 0;
48194 @@ -584,8 +586,8 @@
48195 con->http_status = 400;
48196 con->keep_alive = 0;
48197 con->response.keep_alive = 0;
48199 - log_error_write(srv, __FILE__, __LINE__, "sbsds",
48201 + log_error_write(srv, __FILE__, __LINE__, "sbsds",
48202 "invalid character in key", con->request.request, cur, *cur, "-> 400");
48205 @@ -594,13 +596,13 @@
48217 key_len = i - first;
48220 /* skip every thing up to the : */
48221 for (j = 1; !got_colon; j++) {
48222 switch(con->parse_request->ptr[j + i]) {
48223 @@ -610,40 +612,40 @@
48238 if (srv->srvconf.log_request_header_on_error) {
48239 log_error_write(srv, __FILE__, __LINE__, "s", "WS character in key -> 400");
48240 log_error_write(srv, __FILE__, __LINE__, "Sb",
48241 "request-header:\n",
48242 con->request.request);
48246 con->http_status = 400;
48247 con->response.keep_alive = 0;
48248 con->keep_alive = 0;
48258 if (con->parse_request->ptr[i+1] == '\n' && i == first) {
48259 /* End of Header */
48260 con->parse_request->ptr[i] = '\0';
48261 con->parse_request->ptr[i+1] = '\0';
48272 if (srv->srvconf.log_request_header_on_error) {
48273 @@ -652,7 +654,7 @@
48274 "request-header:\n",
48275 con->request.request);
48279 con->http_status = 400;
48280 con->keep_alive = 0;
48281 con->response.keep_alive = 0;
48282 @@ -693,16 +695,16 @@
48283 con->http_status = 400;
48284 con->keep_alive = 0;
48285 con->response.keep_alive = 0;
48288 if (srv->srvconf.log_request_header_on_error) {
48289 - log_error_write(srv, __FILE__, __LINE__, "sbsds",
48290 + log_error_write(srv, __FILE__, __LINE__, "sbsds",
48291 "CTL character in key", con->request.request, cur, *cur, "-> 400");
48293 log_error_write(srv, __FILE__, __LINE__, "Sb",
48294 "request-header:\n",
48295 con->request.request);
48302 @@ -710,25 +712,25 @@
48308 if (con->parse_request->ptr[i+1] == '\n') {
48309 /* End of Headerline */
48310 con->parse_request->ptr[i] = '\0';
48311 con->parse_request->ptr[i+1] = '\0';
48319 if (srv->srvconf.log_request_header_on_error) {
48320 log_error_write(srv, __FILE__, __LINE__, "s", "WS at the start of first line -> 400");
48323 log_error_write(srv, __FILE__, __LINE__, "Sb",
48324 "request-header:\n",
48325 con->request.request);
48330 con->http_status = 400;
48331 con->keep_alive = 0;
48332 con->response.keep_alive = 0;
48333 @@ -738,9 +740,9 @@
48336 key = con->parse_request->ptr + first;
48339 s_len = cur - value;
48344 if (NULL == (ds = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
48345 @@ -748,86 +750,87 @@
48347 buffer_copy_string_len(ds->key, key, key_len);
48348 buffer_copy_string_len(ds->value, value, s_len);
48350 - /* retreive values
48354 + /* retreive values
48357 * the list of options is sorted to simplify the search
48361 if (0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Connection")))) {
48369 vals = srv->split_vals;
48374 http_request_split_value(vals, ds->value);
48377 for (vi = 0; vi < vals->used; vi++) {
48378 data_string *dsv = (data_string *)vals->data[vi];
48381 if (0 == buffer_caseless_compare(CONST_BUF_LEN(dsv->value), CONST_STR_LEN("keep-alive"))) {
48382 keep_alive_set = HTTP_CONNECTION_KEEPALIVE;
48386 } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(dsv->value), CONST_STR_LEN("close"))) {
48387 keep_alive_set = HTTP_CONNECTION_CLOSE;
48395 } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Content-Length")))) {
48397 unsigned long int r;
48401 if (con_length_set) {
48402 con->http_status = 400;
48403 con->keep_alive = 0;
48406 if (srv->srvconf.log_request_header_on_error) {
48407 - log_error_write(srv, __FILE__, __LINE__, "s",
48408 + log_error_write(srv, __FILE__, __LINE__, "s",
48409 "duplicate Content-Length-header -> 400");
48410 log_error_write(srv, __FILE__, __LINE__, "Sb",
48411 "request-header:\n",
48412 con->request.request);
48414 + ds->free((data_unset *) ds);
48419 if (ds->value->used == 0) SEGFAULT();
48422 for (j = 0; j < ds->value->used - 1; j++) {
48423 char c = ds->value->ptr[j];
48424 if (!isdigit((unsigned char)c)) {
48425 - log_error_write(srv, __FILE__, __LINE__, "sbs",
48426 + log_error_write(srv, __FILE__, __LINE__, "sbs",
48427 "content-length broken:", ds->value, "-> 400");
48430 con->http_status = 400;
48431 con->keep_alive = 0;
48434 array_insert_unique(con->request.headers, (data_unset *)ds);
48440 r = strtoul(ds->value->ptr, &err, 10);
48443 if (*err == '\0') {
48444 con_length_set = 1;
48445 con->request.content_length = r;
48447 - log_error_write(srv, __FILE__, __LINE__, "sbs",
48448 + log_error_write(srv, __FILE__, __LINE__, "sbs",
48449 "content-length broken:", ds->value, "-> 400");
48452 con->http_status = 400;
48453 con->keep_alive = 0;
48456 array_insert_unique(con->request.headers, (data_unset *)ds);
48459 @@ -838,23 +841,24 @@
48461 con->http_status = 400;
48462 con->keep_alive = 0;
48465 if (srv->srvconf.log_request_header_on_error) {
48466 - log_error_write(srv, __FILE__, __LINE__, "s",
48467 + log_error_write(srv, __FILE__, __LINE__, "s",
48468 "duplicate Content-Type-header -> 400");
48469 log_error_write(srv, __FILE__, __LINE__, "Sb",
48470 "request-header:\n",
48471 con->request.request);
48473 + ds->free((data_unset *) ds);
48476 } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Expect")))) {
48477 - /* HTTP 2616 8.2.3
48478 + /* HTTP 2616 8.2.3
48479 * Expect: 100-continue
48482 * -> (10.1.1) 100 (read content, process request, send final status-code)
48483 * -> (10.4.18) 417 (close)
48486 * (not handled at all yet, we always send 417 here)
48488 * What has to be added ?
48489 @@ -863,10 +867,10 @@
48495 con->http_status = 417;
48496 con->keep_alive = 0;
48499 array_insert_unique(con->request.headers, (data_unset *)ds);
48501 } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Host")))) {
48502 @@ -875,14 +879,15 @@
48504 con->http_status = 400;
48505 con->keep_alive = 0;
48508 if (srv->srvconf.log_request_header_on_error) {
48509 - log_error_write(srv, __FILE__, __LINE__, "s",
48510 + log_error_write(srv, __FILE__, __LINE__, "s",
48511 "duplicate Host-header -> 400");
48512 log_error_write(srv, __FILE__, __LINE__, "Sb",
48513 "request-header:\n",
48514 con->request.request);
48516 + ds->free((data_unset *) ds);
48519 } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("If-Modified-Since")))) {
48520 @@ -897,14 +902,15 @@
48522 con->http_status = 400;
48523 con->keep_alive = 0;
48526 if (srv->srvconf.log_request_header_on_error) {
48527 - log_error_write(srv, __FILE__, __LINE__, "s",
48528 + log_error_write(srv, __FILE__, __LINE__, "s",
48529 "duplicate If-Modified-Since header -> 400");
48530 log_error_write(srv, __FILE__, __LINE__, "Sb",
48531 "request-header:\n",
48532 con->request.request);
48534 + ds->free((data_unset *) ds);
48537 } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("If-None-Match")))) {
48538 @@ -914,47 +920,49 @@
48540 con->http_status = 400;
48541 con->keep_alive = 0;
48544 if (srv->srvconf.log_request_header_on_error) {
48545 - log_error_write(srv, __FILE__, __LINE__, "s",
48546 + log_error_write(srv, __FILE__, __LINE__, "s",
48547 "duplicate If-None-Match-header -> 400");
48548 log_error_write(srv, __FILE__, __LINE__, "Sb",
48549 "request-header:\n",
48550 con->request.request);
48552 + ds->free((data_unset *) ds);
48555 } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Range")))) {
48556 if (!con->request.http_range) {
48560 if (0 == strncasecmp(ds->value->ptr, "bytes=", 6) &&
48561 NULL != strchr(ds->value->ptr+6, '-')) {
48564 /* if dup, only the first one will survive */
48565 con->request.http_range = ds->value->ptr + 6;
48568 con->http_status = 400;
48569 con->keep_alive = 0;
48572 if (srv->srvconf.log_request_header_on_error) {
48573 - log_error_write(srv, __FILE__, __LINE__, "s",
48574 + log_error_write(srv, __FILE__, __LINE__, "s",
48575 "duplicate Range-header -> 400");
48576 log_error_write(srv, __FILE__, __LINE__, "Sb",
48577 "request-header:\n",
48578 con->request.request);
48580 + ds->free((data_unset *) ds);
48586 array_insert_unique(con->request.headers, (data_unset *)ds);
48588 /* empty header-fields are not allowed by HTTP-RFC, we just ignore them */
48596 @@ -963,10 +971,10 @@
48599 if (srv->srvconf.log_request_header_on_error) {
48600 - log_error_write(srv, __FILE__, __LINE__, "sbs",
48601 + log_error_write(srv, __FILE__, __LINE__, "sbs",
48602 "CR without LF", con->request.request, "-> 400");
48606 con->http_status = 400;
48607 con->keep_alive = 0;
48608 con->response.keep_alive = 0;
48609 @@ -982,28 +990,28 @@
48615 con->header_len = i;
48618 /* do some post-processing */
48620 if (con->request.http_version == HTTP_VERSION_1_1) {
48621 if (keep_alive_set != HTTP_CONNECTION_CLOSE) {
48622 /* no Connection-Header sent */
48625 /* HTTP/1.1 -> keep-alive default TRUE */
48626 con->keep_alive = 1;
48628 con->keep_alive = 0;
48632 /* RFC 2616, 14.23 */
48633 if (con->request.http_host == NULL ||
48634 buffer_is_empty(con->request.http_host)) {
48635 con->http_status = 400;
48636 con->response.keep_alive = 0;
48637 con->keep_alive = 0;
48640 if (srv->srvconf.log_request_header_on_error) {
48641 log_error_write(srv, __FILE__, __LINE__, "s", "HTTP/1.1 but Host missing -> 400");
48642 log_error_write(srv, __FILE__, __LINE__, "Sb",
48643 @@ -1015,18 +1023,18 @@
48645 if (keep_alive_set == HTTP_CONNECTION_KEEPALIVE) {
48646 /* no Connection-Header sent */
48649 /* HTTP/1.0 -> keep-alive default FALSE */
48650 con->keep_alive = 1;
48652 con->keep_alive = 0;
48657 /* check hostname field if it is set */
48658 if (NULL != con->request.http_host &&
48659 0 != request_check_hostname(srv, con, con->request.http_host)) {
48662 if (srv->srvconf.log_request_header_on_error) {
48663 log_error_write(srv, __FILE__, __LINE__, "s",
48664 "Invalid Hostname -> 400");
48665 @@ -1038,7 +1046,7 @@
48666 con->http_status = 400;
48667 con->response.keep_alive = 0;
48668 con->keep_alive = 0;
48674 @@ -1048,7 +1056,7 @@
48675 /* content-length is forbidden for those */
48676 if (con_length_set && con->request.content_length != 0) {
48677 /* content-length is missing */
48678 - log_error_write(srv, __FILE__, __LINE__, "s",
48679 + log_error_write(srv, __FILE__, __LINE__, "s",
48680 "GET/HEAD with content-length -> 400");
48682 con->keep_alive = 0;
48683 @@ -1060,7 +1068,7 @@
48684 /* content-length is required for them */
48685 if (!con_length_set) {
48686 /* content-length is missing */
48687 - log_error_write(srv, __FILE__, __LINE__, "s",
48688 + log_error_write(srv, __FILE__, __LINE__, "s",
48689 "POST-request, but content-length missing -> 411");
48691 con->keep_alive = 0;
48692 @@ -1073,16 +1081,16 @@
48693 /* the may have a content-length */
48700 /* check if we have read post data */
48701 if (con_length_set) {
48702 /* don't handle more the SSIZE_MAX bytes in content-length */
48703 if (con->request.content_length > SSIZE_MAX) {
48704 - con->http_status = 413;
48705 + con->http_status = 413;
48706 con->keep_alive = 0;
48708 - log_error_write(srv, __FILE__, __LINE__, "sds",
48709 + log_error_write(srv, __FILE__, __LINE__, "sds",
48710 "request-size too long:", con->request.content_length, "-> 413");
48713 @@ -1090,25 +1098,25 @@
48714 /* divide by 1024 as srvconf.max_request_size is in kBytes */
48715 if (srv->srvconf.max_request_size != 0 &&
48716 (con->request.content_length >> 10) > srv->srvconf.max_request_size) {
48717 - /* the request body itself is larger then
48718 + /* the request body itself is larger then
48719 * our our max_request_size
48723 con->http_status = 413;
48724 con->keep_alive = 0;
48726 - log_error_write(srv, __FILE__, __LINE__, "sds",
48728 + log_error_write(srv, __FILE__, __LINE__, "sds",
48729 "request-size too long:", con->request.content_length, "-> 413");
48736 /* we have content */
48737 if (con->request.content_length != 0) {
48746 @@ -1116,9 +1124,9 @@
48749 if (con->request.request->used < 5) return 0;
48752 if (0 == memcmp(con->request.request->ptr + con->request.request->used - 5, "\r\n\r\n", 4)) return 1;
48753 if (NULL != strstr(con->request.request->ptr, "\r\n\r\n")) return 1;
48758 --- ../lighttpd-1.4.11/src/response.c 2006-03-04 16:41:39.000000000 +0200
48759 +++ lighttpd-1.4.12/src/response.c 2006-07-16 00:26:04.000000000 +0300
48761 #include <stdlib.h>
48762 #include <string.h>
48764 -#include <unistd.h>
48766 #include <assert.h>
48768 @@ -24,15 +23,17 @@
48769 #include "plugin.h"
48771 #include "sys-socket.h"
48772 +#include "sys-files.h"
48773 +#include "sys-strings.h"
48775 int http_response_write_header(server *srv, connection *con) {
48779 int have_server = 0;
48782 b = chunkqueue_get_prepend_buffer(con->write_queue);
48785 if (con->request.http_version == HTTP_VERSION_1_1) {
48786 BUFFER_COPY_STRING_CONST(b, "HTTP/1.1 ");
48788 @@ -41,25 +42,26 @@
48789 buffer_append_long(b, con->http_status);
48790 BUFFER_APPEND_STRING_CONST(b, " ");
48791 buffer_append_string(b, get_http_status_name(con->http_status));
48794 if (con->request.http_version != HTTP_VERSION_1_1 || con->keep_alive == 0) {
48795 BUFFER_APPEND_STRING_CONST(b, "\r\nConnection: ");
48796 buffer_append_string(b, con->keep_alive ? "keep-alive" : "close");
48800 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
48801 BUFFER_APPEND_STRING_CONST(b, "\r\nTransfer-Encoding: chunked");
48807 /* add all headers */
48808 for (i = 0; i < con->response.headers->used; i++) {
48812 ds = (data_string *)con->response.headers->data[i];
48815 if (ds->value->used && ds->key->used &&
48816 - 0 != strncmp(ds->key->ptr, "X-LIGHTTPD-", sizeof("X-LIGHTTPD-") - 1)) {
48817 + 0 != strncmp(ds->key->ptr, "X-LIGHTTPD-", sizeof("X-LIGHTTPD-") - 1) &&
48818 + 0 != strcasecmp(ds->key->ptr, "X-Sendfile")) {
48819 if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Date"))) have_date = 1;
48820 if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Server"))) have_server = 1;
48822 @@ -68,28 +70,28 @@
48823 BUFFER_APPEND_STRING_CONST(b, ": ");
48824 buffer_append_string_buffer(b, ds->value);
48826 - log_error_write(srv, __FILE__, __LINE__, "bb",
48827 + log_error_write(srv, __FILE__, __LINE__, "bb",
48828 ds->key, ds->value);
48835 /* HTTP/1.1 requires a Date: header */
48836 BUFFER_APPEND_STRING_CONST(b, "\r\nDate: ");
48839 /* cache the generated timestamp */
48840 if (srv->cur_ts != srv->last_generated_date_ts) {
48841 buffer_prepare_copy(srv->ts_date_str, 255);
48843 - strftime(srv->ts_date_str->ptr, srv->ts_date_str->size - 1,
48845 + strftime(srv->ts_date_str->ptr, srv->ts_date_str->size - 1,
48846 "%a, %d %b %Y %H:%M:%S GMT", gmtime(&(srv->cur_ts)));
48849 srv->ts_date_str->used = strlen(srv->ts_date_str->ptr) + 1;
48852 srv->last_generated_date_ts = srv->cur_ts;
48856 buffer_append_string_buffer(b, srv->ts_date_str);
48859 @@ -101,16 +103,16 @@
48860 buffer_append_string_buffer(b, con->conf.server_tag);
48865 BUFFER_APPEND_STRING_CONST(b, "\r\n\r\n");
48870 con->bytes_header = b->used - 1;
48873 if (con->conf.log_response_header) {
48874 log_error_write(srv, __FILE__, __LINE__, "sSb", "Response-Header:", "\n", b);
48881 @@ -118,71 +120,71 @@
48883 handler_t http_response_prepare(server *srv, connection *con) {
48886 - /* looks like someone has already done a decision */
48887 - if (con->mode == DIRECT &&
48889 + /* looks like someone has already made a decision */
48890 + if (con->mode == DIRECT &&
48891 (con->http_status != 0 && con->http_status != 200)) {
48892 /* remove a packets in the queue */
48893 if (con->file_finished == 0) {
48894 chunkqueue_reset(con->write_queue);
48898 return HANDLER_FINISHED;
48902 /* no decision yet, build conf->filename */
48903 if (con->mode == DIRECT && con->physical.path->used == 0) {
48906 - /* we only come here when we have the parse the full request again
48908 - * a HANDLER_COMEBACK from mod_rewrite and mod_fastcgi might be a
48909 + /* we only come here when we have to parse the full request again
48911 + * a HANDLER_COMEBACK from mod_rewrite and mod_fastcgi might be a
48912 * problem here as mod_setenv might get called multiple times
48914 * fastcgi-auth might lead to a COMEBACK too
48915 * fastcgi again dead server too
48917 * mod_compress might add headers twice too
48923 if (con->conf.log_condition_handling) {
48924 log_error_write(srv, __FILE__, __LINE__, "s", "run condition");
48926 config_patch_connection(srv, con, COMP_SERVER_SOCKET); /* SERVERsocket */
48935 * - uri.path (secure)
48944 * Name according to RFC 2396
48953 * (scheme)://(authority)(path)?(query)
48961 buffer_copy_string(con->uri.scheme, con->conf.is_ssl ? "https" : "http");
48962 buffer_copy_string_buffer(con->uri.authority, con->request.http_host);
48963 buffer_to_lower(con->uri.authority);
48966 config_patch_connection(srv, con, COMP_HTTP_HOST); /* Host: */
48967 config_patch_connection(srv, con, COMP_HTTP_REMOTEIP); /* Client-IP */
48968 config_patch_connection(srv, con, COMP_HTTP_REFERER); /* Referer: */
48969 config_patch_connection(srv, con, COMP_HTTP_USERAGENT); /* User-Agent: */
48970 config_patch_connection(srv, con, COMP_HTTP_COOKIE); /* Cookie: */
48973 /** extract query string from request.uri */
48974 if (NULL != (qstr = strchr(con->request.uri->ptr, '?'))) {
48975 buffer_copy_string (con->uri.query, qstr + 1);
48976 @@ -200,22 +202,22 @@
48977 log_error_write(srv, __FILE__, __LINE__, "sb", "URI-path : ", con->uri.path_raw);
48978 log_error_write(srv, __FILE__, __LINE__, "sb", "URI-query : ", con->uri.query);
48982 /* disable keep-alive if requested */
48985 if (con->request_count > con->conf.max_keep_alive_requests) {
48986 con->keep_alive = 0;
48999 * - based on the raw URL
49005 switch(r = plugins_call_handle_uri_raw(srv, con)) {
49006 case HANDLER_GO_ON:
49008 @@ -229,14 +231,14 @@
49012 - /* build filename
49013 + /* build filename
49015 * - decode url-encodings (e.g. %20 -> ' ')
49016 * - remove path-modifiers (e.g. /../)
49024 if (con->request.http_method == HTTP_METHOD_OPTIONS &&
49025 con->uri.path_raw->ptr[0] == '*' && con->uri.path_raw->ptr[1] == '\0') {
49026 /* OPTIONS * ... */
49027 @@ -253,15 +255,20 @@
49037 * - based on the clean URL
49043 config_patch_connection(srv, con, COMP_HTTP_URL); /* HTTPurl */
49046 + /* do we have to downgrade to 1.0 ? */
49047 + if (!con->conf.allow_http11) {
49048 + con->request.http_version = HTTP_VERSION_1_0;
49051 switch(r = plugins_call_handle_uri_clean(srv, con)) {
49052 case HANDLER_GO_ON:
49054 @@ -274,11 +281,11 @@
49055 log_error_write(srv, __FILE__, __LINE__, "");
49060 if (con->request.http_method == HTTP_METHOD_OPTIONS &&
49061 con->uri.path->ptr[0] == '*' && con->uri.path_raw->ptr[1] == '\0') {
49062 - /* option requests are handled directly without checking of the path */
49064 + /* option requests are handled directly without checking the path */
49066 response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("OPTIONS, GET, HEAD, POST"));
49068 con->http_status = 200;
49069 @@ -288,46 +295,47 @@
49079 * logical filename (URI) becomes a physical filename here
49096 * ... ISREG() -> ok, go on
49097 * ... ISDIR() -> index-file -> redirect
49112 * SEARCH DOCUMENT ROOT
49116 /* set a default */
49119 buffer_copy_string_buffer(con->physical.doc_root, con->conf.document_root);
49120 buffer_copy_string_buffer(con->physical.rel_path, con->uri.path);
49122 -#if defined(__WIN32) || defined(__CYGWIN__)
49123 - /* strip dots from the end and spaces
49125 + filename_unix2local(con->physical.rel_path);
49126 +#if defined(_WIN32) || defined(__CYGWIN__)
49127 + /* strip dots and spaces from the end
49129 * windows/dos handle those filenames as the same file
49131 * foo == foo. == foo..... == "foo... " == "foo.. ./"
49133 - * This will affect in some cases PATHINFO
49134 + * This will affect PATHINFO in some cases
49136 * on native windows we could prepend the filename with \\?\ to circumvent
49137 * this behaviour. I have no idea how to push this through cygwin
49138 @@ -377,36 +385,41 @@
49139 log_error_write(srv, __FILE__, __LINE__, "");
49143 - /* MacOS X and Windows can't distiguish between upper and lower-case
49145 - * convert to lower-case
49147 + /* The default Mac OS X and Windows filesystems can't distiguish between
49148 + * upper- and lowercase, so convert to lowercase
49150 if (con->conf.force_lowercase_filenames) {
49151 buffer_to_lower(con->physical.rel_path);
49154 - /* the docroot plugins might set the servername, if they don't we take http-host */
49155 + /* the docroot plugins might set the servername; if they don't we take http-host */
49156 if (buffer_is_empty(con->server_name)) {
49157 buffer_copy_string_buffer(con->server_name, con->uri.authority);
49161 - * create physical filename
49164 + * create physical filename
49165 * -> physical.path = docroot + rel_path
49171 buffer_copy_string_buffer(con->physical.path, con->physical.doc_root);
49172 - BUFFER_APPEND_SLASH(con->physical.path);
49173 + PATHNAME_APPEND_SLASH(con->physical.path);
49174 buffer_copy_string_buffer(con->physical.basedir, con->physical.path);
49175 if (con->physical.rel_path->used &&
49176 - con->physical.rel_path->ptr[0] == '/') {
49177 + con->physical.rel_path->ptr[0] == DIR_SEPERATOR) {
49178 buffer_append_string_len(con->physical.path, con->physical.rel_path->ptr + 1, con->physical.rel_path->used - 2);
49180 buffer_append_string_buffer(con->physical.path, con->physical.rel_path);
49183 + /* win32: directories can't have a trailing slash */
49184 + if (con->physical.path->ptr[con->physical.path->used - 2] == DIR_SEPERATOR) {
49185 + con->physical.path->ptr[con->physical.path->used - 2] = '\0';
49186 + con->physical.path->used--;
49189 if (con->conf.log_request_handling) {
49190 log_error_write(srv, __FILE__, __LINE__, "s", "-- after doc_root");
49191 log_error_write(srv, __FILE__, __LINE__, "sb", "Doc-Root :", con->physical.doc_root);
49192 @@ -426,7 +439,7 @@
49193 log_error_write(srv, __FILE__, __LINE__, "");
49198 if (con->conf.log_request_handling) {
49199 log_error_write(srv, __FILE__, __LINE__, "s", "-- logical -> physical");
49200 log_error_write(srv, __FILE__, __LINE__, "sb", "Doc-Root :", con->physical.doc_root);
49201 @@ -434,38 +447,38 @@
49202 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
49207 - * Noone catched away the file from normal path of execution yet (like mod_access)
49211 + * No one took the file away from the normal path of execution yet (like mod_access)
49213 * Go on and check of the file exists at all
49217 if (con->mode == DIRECT) {
49218 char *slash = NULL;
49219 char *pathinfo = NULL;
49221 stat_cache_entry *sce = NULL;
49224 if (con->conf.log_request_handling) {
49225 log_error_write(srv, __FILE__, __LINE__, "s", "-- handling physical path");
49226 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
49230 if (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
49234 if (con->conf.log_request_handling) {
49235 log_error_write(srv, __FILE__, __LINE__, "s", "-- file found");
49236 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
49240 if (S_ISDIR(sce->st.st_mode)) {
49241 - if (con->physical.path->ptr[con->physical.path->used - 2] != '/') {
49242 + if (con->uri.path->ptr[con->uri.path->used - 2] != '/') {
49243 /* redirect to .../ */
49246 http_response_redirect_to_directory(srv, con);
49249 return HANDLER_FINISHED;
49251 } else if (!S_ISREG(sce->st.st_mode)) {
49252 @@ -477,12 +490,12 @@
49255 con->http_status = 403;
49258 if (con->conf.log_request_handling) {
49259 log_error_write(srv, __FILE__, __LINE__, "s", "-- access denied");
49260 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
49264 buffer_reset(con->physical.path);
49265 return HANDLER_FINISHED;
49267 @@ -499,77 +512,77 @@
49268 /* PATH_INFO ! :) */
49271 - /* we have no idea what happend. let's tell the user so. */
49272 + /* we have no idea what happened, so tell the user. */
49273 con->http_status = 500;
49274 buffer_reset(con->physical.path);
49277 log_error_write(srv, __FILE__, __LINE__, "ssbsb",
49278 "file not found ... or so: ", strerror(errno),
49280 "->", con->physical.path);
49283 return HANDLER_FINISHED;
49287 /* not found, perhaps PATHINFO */
49290 buffer_copy_string_buffer(srv->tmp_buf, con->physical.path);
49298 buffer_copy_string_len(con->physical.path, srv->tmp_buf->ptr, slash - srv->tmp_buf->ptr);
49300 buffer_copy_string_buffer(con->physical.path, srv->tmp_buf);
49304 if (0 == stat(con->physical.path->ptr, &(st)) &&
49305 S_ISREG(st.st_mode)) {
49311 if (pathinfo != NULL) {
49314 slash = strrchr(srv->tmp_buf->ptr, '/');
49317 if (pathinfo != NULL) {
49323 if (slash) pathinfo = slash;
49324 } while ((found == 0) && (slash != NULL) && (slash - srv->tmp_buf->ptr > con->physical.basedir->used - 2));
49328 - /* no it really doesn't exists */
49329 + /* no, it really doesn't exists */
49330 con->http_status = 404;
49333 if (con->conf.log_file_not_found) {
49334 log_error_write(srv, __FILE__, __LINE__, "sbsb",
49335 "file not found:", con->uri.path,
49336 "->", con->physical.path);
49340 buffer_reset(con->physical.path);
49343 return HANDLER_FINISHED;
49347 /* we have a PATHINFO */
49349 buffer_copy_string(con->request.pathinfo, pathinfo);
49357 con->uri.path->used -= strlen(pathinfo);
49358 con->uri.path->ptr[con->uri.path->used - 1] = '\0';
49362 if (con->conf.log_request_handling) {
49363 log_error_write(srv, __FILE__, __LINE__, "s", "-- after pathinfo check");
49364 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
49365 @@ -577,12 +590,12 @@
49366 log_error_write(srv, __FILE__, __LINE__, "sb", "Pathinfo :", con->request.pathinfo);
49371 if (con->conf.log_request_handling) {
49372 log_error_write(srv, __FILE__, __LINE__, "s", "-- handling subrequest");
49373 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
49377 /* call the handlers */
49378 switch(r = plugins_call_handle_subrequest_start(srv, con)) {
49379 case HANDLER_GO_ON:
49380 @@ -593,32 +606,32 @@
49381 if (con->conf.log_request_handling) {
49382 log_error_write(srv, __FILE__, __LINE__, "s", "-- subrequest finished");
49385 - /* something strange happend */
49387 + /* something strange happened */
49391 - /* if we are still here, no one wanted the file, status 403 is ok I think */
49394 + /* if we are still here, no one wanted the file; status 403 is ok I think */
49396 if (con->mode == DIRECT) {
49397 con->http_status = 403;
49400 return HANDLER_FINISHED;
49407 switch(r = plugins_call_handle_subrequest(srv, con)) {
49408 case HANDLER_GO_ON:
49409 - /* request was not handled, looks like we are done */
49410 + /* request was not handled; looks like we are done */
49411 return HANDLER_FINISHED;
49412 case HANDLER_FINISHED:
49413 /* request is finished */
49415 - /* something strange happend */
49416 + /* something strange happened */
49422 return HANDLER_COMEBACK;
49424 --- ../lighttpd-1.4.11/src/server.c 2006-03-04 19:12:17.000000000 +0200
49425 +++ lighttpd-1.4.12/src/server.c 2006-07-19 20:02:55.000000000 +0300
49427 #include <sys/types.h>
49428 -#include <sys/time.h>
49429 #include <sys/stat.h>
49431 #include <string.h>
49434 -#include <unistd.h>
49435 #include <stdlib.h>
49437 #include <signal.h>
49439 #include "plugin.h"
49440 #include "joblist.h"
49441 #include "network_backends.h"
49443 +#include "status_counter.h"
49445 +/* use local getopt implementation */
49446 +# undef HAVE_GETOPT_H
49448 #ifdef HAVE_GETOPT_H
49449 #include <getopt.h>
49451 +#include "getopt.h"
49454 #ifdef HAVE_VALGRIND_VALGRIND_H
49456 /* #define USE_ALARM */
49460 +#undef HAVE_SIGNAL
49463 +#include "sys-files.h"
49464 +#include "sys-process.h"
49465 +#include "sys-socket.h"
49467 static volatile sig_atomic_t srv_shutdown = 0;
49468 static volatile sig_atomic_t graceful_shutdown = 0;
49469 +static volatile sig_atomic_t graceful_restart = 0;
49470 static volatile sig_atomic_t handle_sig_alarm = 1;
49471 static volatile sig_atomic_t handle_sig_hup = 0;
49476 case SIGTERM: srv_shutdown = 1; break;
49479 if (graceful_shutdown) srv_shutdown = 1;
49480 - else graceful_shutdown = 1;
49481 + else graceful_shutdown = 1;
49484 case SIGALRM: handle_sig_alarm = 1; break;
49486 static void signal_handler(int sig) {
49488 case SIGTERM: srv_shutdown = 1; break;
49491 if (graceful_shutdown) srv_shutdown = 1;
49492 - else graceful_shutdown = 1;
49493 + else graceful_shutdown = 1;
49496 case SIGALRM: handle_sig_alarm = 1; break;
49497 @@ -110,35 +123,35 @@
49498 signal(SIGTSTP, SIG_IGN);
49500 if (0 != fork()) exit(0);
49503 if (-1 == setsid()) exit(0);
49505 signal(SIGHUP, SIG_IGN);
49507 if (0 != fork()) exit(0);
49510 if (0 != chdir("/")) exit(0);
49514 static server *server_init(void) {
49518 server *srv = calloc(1, sizeof(*srv));
49520 + srv->max_fds = 1024;
49522 srv->x = buffer_init();
49525 CLEAN(response_header);
49526 CLEAN(parse_full_path);
49527 CLEAN(ts_debug_str);
49528 CLEAN(ts_date_str);
49529 - CLEAN(errorlog_buf);
49530 CLEAN(response_range);
49532 srv->empty_string = buffer_init_string("");
49533 CLEAN(cond_check_buf);
49536 CLEAN(srvconf.errorlog_file);
49537 CLEAN(srvconf.groupname);
49538 CLEAN(srvconf.username);
49539 @@ -146,68 +159,62 @@
49540 CLEAN(srvconf.bindhost);
49541 CLEAN(srvconf.event_handler);
49542 CLEAN(srvconf.pid_file);
49545 CLEAN(tmp_chunk_len);
49550 srv->x = array_init();
49553 CLEAN(config_context);
49554 CLEAN(config_touched);
49559 for (i = 0; i < FILE_CACHE_MAX; i++) {
49560 srv->mtime_cache[i].str = buffer_init();
49564 srv->cur_ts = time(NULL);
49565 srv->startup_ts = srv->cur_ts;
49568 srv->conns = calloc(1, sizeof(*srv->conns));
49569 assert(srv->conns);
49572 srv->joblist = calloc(1, sizeof(*srv->joblist));
49573 assert(srv->joblist);
49576 srv->fdwaitqueue = calloc(1, sizeof(*srv->fdwaitqueue));
49577 assert(srv->fdwaitqueue);
49580 srv->srvconf.modules = array_init();
49581 srv->srvconf.modules_dir = buffer_init_string(LIBRARY_DIR);
49582 srv->srvconf.network_backend = buffer_init();
49583 srv->srvconf.upload_tempdirs = array_init();
49586 - srv->errorlog_fd = -1;
49587 - srv->errorlog_mode = ERRORLOG_STDERR;
49589 srv->split_vals = array_init();
49595 static void server_free(server *srv) {
49599 for (i = 0; i < FILE_CACHE_MAX; i++) {
49600 buffer_free(srv->mtime_cache[i].str);
49605 buffer_free(srv->x);
49608 CLEAN(response_header);
49609 CLEAN(parse_full_path);
49610 CLEAN(ts_debug_str);
49611 CLEAN(ts_date_str);
49612 - CLEAN(errorlog_buf);
49613 CLEAN(response_range);
49615 CLEAN(empty_string);
49616 CLEAN(cond_check_buf);
49619 CLEAN(srvconf.errorlog_file);
49620 CLEAN(srvconf.groupname);
49621 CLEAN(srvconf.username);
49622 @@ -217,7 +224,7 @@
49623 CLEAN(srvconf.pid_file);
49624 CLEAN(srvconf.modules_dir);
49625 CLEAN(srvconf.network_backend);
49628 CLEAN(tmp_chunk_len);
49631 @@ -225,15 +232,15 @@
49632 fdevent_unregister(srv->ev, srv->fd);
49634 fdevent_free(srv->ev);
49640 if (srv->config_storage) {
49641 for (i = 0; i < srv->config_context->used; i++) {
49642 specific_config *s = srv->config_storage[i];
49647 buffer_free(s->document_root);
49648 buffer_free(s->server_name);
49649 buffer_free(s->server_tag);
49650 @@ -242,32 +249,31 @@
49651 buffer_free(s->error_handler);
49652 buffer_free(s->errorfile_prefix);
49653 array_free(s->mimetypes);
49658 free(srv->config_storage);
49659 srv->config_storage = NULL;
49664 array_free(srv->x);
49667 CLEAN(config_context);
49668 CLEAN(config_touched);
49670 CLEAN(srvconf.upload_tempdirs);
49674 joblist_free(srv, srv->joblist);
49675 fdwaitqueue_free(srv, srv->fdwaitqueue);
49678 if (srv->stat_cache) {
49679 stat_cache_free(srv->stat_cache);
49682 array_free(srv->srvconf.modules);
49683 array_free(srv->split_vals);
49689 @@ -281,14 +287,12 @@
49690 " - a light and fast webserver\n" \
49691 "Build-Date: " __DATE__ " " __TIME__ "\n";
49695 write(STDOUT_FILENO, b, strlen(b));
49698 static void show_features (void) {
49700 - printf("\nEvent Handlers:\n\n%s",
49702 + const char *s = ""
49704 "\t+ select (generic)\n"
49706 @@ -355,11 +359,6 @@
49708 "\t- crypt support\n"
49711 - "\t+ PAM support\n"
49713 - "\t- PAM support\n"
49716 "\t+ SSL Support\n"
49718 @@ -371,9 +370,9 @@
49719 "\t- PCRE support\n"
49722 - "\t+ mySQL support\n"
49723 + "\t+ MySQL support\n"
49725 - "\t- mySQL support\n"
49726 + "\t- MySQL support\n"
49728 #if defined(HAVE_LDAP_H) && defined(HAVE_LBER_H) && defined(HAVE_LIBLDAP) && defined(HAVE_LIBLBER)
49729 "\t+ LDAP support\n"
49730 @@ -410,8 +409,11 @@
49732 "\t- GDBM support\n"
49740 + printf("\nEvent Handlers:\n\n%s", s);
49743 static void show_help (void) {
49744 @@ -433,197 +435,565 @@
49745 " -h show this help\n" \
49751 write(STDOUT_FILENO, b, strlen(b));
49754 -int main (int argc, char **argv) {
49755 - server *srv = NULL;
49756 - int print_config = 0;
49757 - int test_config = 0;
49760 - int num_childs = 0;
49761 - int pid_fd = -1, fd;
49763 -#ifdef HAVE_SIGACTION
49764 - struct sigaction act;
49766 -#ifdef HAVE_GETRLIMIT
49767 - struct rlimit rlim;
49771 - struct itimerval interval;
49773 - interval.it_interval.tv_sec = 1;
49774 - interval.it_interval.tv_usec = 0;
49775 - interval.it_value.tv_sec = 1;
49776 - interval.it_value.tv_usec = 0;
49780 - /* for nice %b handling in strfime() */
49781 - setlocale(LC_TIME, "C");
49783 - if (NULL == (srv = server_init())) {
49784 - fprintf(stderr, "did this really happen?\n");
49788 - /* init structs done */
49790 - srv->srvconf.port = 0;
49791 -#ifdef HAVE_GETUID
49792 - i_am_root = (getuid() == 0);
49796 - srv->srvconf.dont_daemonize = 0;
49798 - while(-1 != (o = getopt(argc, argv, "f:m:hvVDpt"))) {
49801 - if (config_read(srv, optarg)) {
49802 - server_free(srv);
49807 - buffer_copy_string(srv->srvconf.modules_dir, optarg);
49809 - case 'p': print_config = 1; break;
49810 - case 't': test_config = 1; break;
49811 - case 'D': srv->srvconf.dont_daemonize = 1; break;
49812 - case 'v': show_version(); return 0;
49813 - case 'V': show_features(); return 0;
49814 - case 'h': show_help(); return 0;
49817 - server_free(srv);
49822 - if (!srv->config_storage) {
49823 - log_error_write(srv, __FILE__, __LINE__, "s",
49824 - "No configuration available. Try using -f option.");
49826 - server_free(srv);
49830 - if (print_config) {
49831 - data_unset *dc = srv->config_context->data[0];
49833 - dc->print(dc, 0);
49834 - fprintf(stderr, "\n");
49836 - /* shouldn't happend */
49837 - fprintf(stderr, "global config not found\n");
49840 +int lighty_mainloop(server *srv) {
49841 + fdevent_revents *revents = fdevent_revents_init();
49843 - if (test_config) {
49844 - printf("Syntax OK\n");
49847 + while (!srv_shutdown) {
49852 - if (test_config || print_config) {
49853 - server_free(srv);
49857 - /* close stdin and stdout, as they are not needed */
49858 - /* move stdin to /dev/null */
49859 - if (-1 != (fd = open("/dev/null", O_RDONLY))) {
49860 - close(STDIN_FILENO);
49861 - dup2(fd, STDIN_FILENO);
49865 - /* move stdout to /dev/null */
49866 - if (-1 != (fd = open("/dev/null", O_WRONLY))) {
49867 - close(STDOUT_FILENO);
49868 - dup2(fd, STDOUT_FILENO);
49872 - if (0 != config_set_defaults(srv)) {
49873 - log_error_write(srv, __FILE__, __LINE__, "s",
49874 - "setting default values failed");
49875 - server_free(srv);
49879 - /* UID handling */
49880 -#ifdef HAVE_GETUID
49881 - if (!i_am_root && (geteuid() == 0 || getegid() == 0)) {
49882 - /* we are setuid-root */
49884 - log_error_write(srv, __FILE__, __LINE__, "s",
49885 - "Are you nuts ? Don't apply a SUID bit to this binary");
49887 - server_free(srv);
49892 - /* check document-root */
49893 - if (srv->config_storage[0]->document_root->used <= 1) {
49894 - log_error_write(srv, __FILE__, __LINE__, "s",
49895 - "document-root is not set\n");
49897 - server_free(srv);
49902 - if (plugins_load(srv)) {
49903 - log_error_write(srv, __FILE__, __LINE__, "s",
49904 - "loading plugins finally failed");
49906 - plugins_free(srv);
49907 - server_free(srv);
49912 - /* open pid file BEFORE chroot */
49913 - if (srv->srvconf.pid_file->used) {
49914 - 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))) {
49916 - if (errno != EEXIST) {
49917 - log_error_write(srv, __FILE__, __LINE__, "sbs",
49918 - "opening pid-file failed:", srv->srvconf.pid_file, strerror(errno));
49922 - if (0 != stat(srv->srvconf.pid_file->ptr, &st)) {
49923 - log_error_write(srv, __FILE__, __LINE__, "sbs",
49924 - "stating existing pid-file failed:", srv->srvconf.pid_file, strerror(errno));
49925 + if (handle_sig_hup) {
49928 + /* reset notification */
49929 + handle_sig_hup = 0;
49934 + /* send the old process into a graceful-shutdown and start a
49935 + * new process right away
49938 + * - if webserver is running on port < 1024 (e.g. 80, 433)
49939 + * we don't have the permissions to bind to that port anymore
49943 + if (0 == (pid = fork())) {
49944 + execve(argv[0], argv, envp);
49947 + } else if (pid == -1) {
49952 + graceful_shutdown = 1; /* shutdown without killing running connections */
49953 + graceful_restart = 1; /* don't delete pid file */
49956 - if (!S_ISREG(st.st_mode)) {
49957 - log_error_write(srv, __FILE__, __LINE__, "sb",
49958 - "pid-file exists and isn't regular file:", srv->srvconf.pid_file);
49961 + /* cycle logfiles */
49963 + switch(r = plugins_call_handle_sighup(srv)) {
49964 + case HANDLER_GO_ON:
49967 + log_error_write(srv, __FILE__, __LINE__, "sd", "sighup-handler return with an error", r);
49971 - if (-1 == (pid_fd = open(srv->srvconf.pid_file->ptr, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
49972 - log_error_write(srv, __FILE__, __LINE__, "sbs",
49973 - "opening pid-file failed:", srv->srvconf.pid_file, strerror(errno));
49975 + if (-1 == log_error_cycle()) {
49976 + log_error_write(srv, __FILE__, __LINE__, "s", "cycling errorlog failed, dying");
49984 - if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
49985 - /* select limits itself
49986 + if (handle_sig_alarm) {
49987 + /* a new second */
49990 + /* reset notification */
49991 + handle_sig_alarm = 0;
49994 + /* get current time */
49995 + min_ts = time(NULL);
49997 + if (min_ts != srv->cur_ts) {
49999 + connections *conns = srv->conns;
50002 + switch(r = plugins_call_handle_trigger(srv)) {
50003 + case HANDLER_GO_ON:
50005 + case HANDLER_ERROR:
50006 + log_error_write(srv, __FILE__, __LINE__, "s", "one of the triggers failed");
50009 + log_error_write(srv, __FILE__, __LINE__, "d", r);
50013 + /* trigger waitpid */
50014 + srv->cur_ts = min_ts;
50016 + /* cleanup stat-cache */
50017 + stat_cache_trigger_cleanup(srv);
50019 + * check all connections for timeouts
50022 + for (ndx = 0; ndx < conns->used; ndx++) {
50027 + con = conns->ptr[ndx];
50029 + if (con->state == CON_STATE_READ ||
50030 + con->state == CON_STATE_READ_POST) {
50031 + if (con->request_count == 1) {
50032 + if (srv->cur_ts - con->read_idle_ts > con->conf.max_read_idle) {
50035 + log_error_write(srv, __FILE__, __LINE__, "sd",
50036 + "connection closed - read-timeout:", con->fd);
50038 + connection_set_state(srv, con, CON_STATE_ERROR);
50042 + if (srv->cur_ts - con->read_idle_ts > con->conf.max_keep_alive_idle) {
50045 + log_error_write(srv, __FILE__, __LINE__, "sd",
50046 + "connection closed - read-timeout:", con->fd);
50048 + connection_set_state(srv, con, CON_STATE_ERROR);
50054 + if ((con->state == CON_STATE_WRITE) &&
50055 + (con->write_request_ts != 0)) {
50057 + if (srv->cur_ts - con->write_request_ts > 60) {
50058 + log_error_write(srv, __FILE__, __LINE__, "sdd",
50059 + "connection closed - pre-write-request-timeout:", con->fd, srv->cur_ts - con->write_request_ts);
50063 + if (srv->cur_ts - con->write_request_ts > con->conf.max_write_idle) {
50066 + log_error_write(srv, __FILE__, __LINE__, "sbsosds",
50067 + "NOTE: a request for",
50068 + con->request.uri,
50069 + "timed out after writing",
50070 + con->bytes_written,
50071 + "bytes. We waited",
50072 + (int)con->conf.max_write_idle,
50073 + "seconds. If this a problem increase server.max-write-idle");
50075 + connection_set_state(srv, con, CON_STATE_ERROR);
50079 + /* we don't like div by zero */
50080 + if (0 == (t_diff = srv->cur_ts - con->connection_start)) t_diff = 1;
50082 + if (con->traffic_limit_reached &&
50083 + (con->conf.kbytes_per_second == 0 ||
50084 + ((con->bytes_written / t_diff) < con->conf.kbytes_per_second * 1024))) {
50085 + /* enable connection again */
50086 + con->traffic_limit_reached = 0;
50092 + connection_state_machine(srv, con);
50094 + con->bytes_written_cur_second = 0;
50095 + *(con->conf.global_bytes_per_second_cnt_ptr) = 0;
50099 + fprintf(stderr, "connection-state: ");
50103 + fprintf(stderr, "c[%d,%d]: %s ",
50106 + connection_get_state(con->state));
50110 + if (cs == 1) fprintf(stderr, "\n");
50114 + if (srv->sockets_disabled) {
50115 + /* our server sockets are disabled, why ? */
50117 + if ((srv->cur_fds + srv->want_fds < srv->max_fds * 0.8) && /* we have enough unused fds */
50118 + (srv->conns->used < srv->max_conns * 0.9) &&
50119 + (0 == graceful_shutdown)) {
50122 + for (i = 0; i < srv->srv_sockets.used; i++) {
50123 + server_socket *srv_socket = srv->srv_sockets.ptr[i];
50124 + fdevent_event_add(srv->ev, srv_socket->sock, FDEVENT_IN);
50127 + log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets enabled again");
50129 + srv->sockets_disabled = 0;
50132 + if ((srv->cur_fds + srv->want_fds > srv->max_fds * 0.9) || /* out of fds */
50133 + (srv->conns->used > srv->max_conns) || /* out of connections */
50134 + (graceful_shutdown)) { /* graceful_shutdown */
50137 + /* disable server-fds */
50139 + for (i = 0; i < srv->srv_sockets.used; i++) {
50140 + server_socket *srv_socket = srv->srv_sockets.ptr[i];
50141 + fdevent_event_del(srv->ev, srv_socket->sock);
50143 + if (graceful_shutdown) {
50144 + /* we don't want this socket anymore,
50146 + * closing it right away will make it possible for
50147 + * the next lighttpd to take over (graceful restart)
50150 + fdevent_unregister(srv->ev, srv_socket->sock);
50151 + closesocket(srv_socket->sock->fd);
50152 + srv_socket->sock->fd = -1;
50154 + /* network_close() will cleanup after us */
50158 + if (graceful_shutdown) {
50159 + log_error_write(srv, __FILE__, __LINE__, "s", "[note] graceful shutdown started");
50160 + } else if (srv->conns->used > srv->max_conns) {
50161 + log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets disabled, connection limit reached");
50163 + log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets disabled, out-of-fds");
50166 + srv->sockets_disabled = 1;
50170 + if (graceful_shutdown && srv->conns->used == 0) {
50171 + /* we are in graceful shutdown phase and all connections are closed
50172 + * we are ready to terminate without harming anyone */
50173 + srv_shutdown = 1;
50176 + /* we still have some fds to share */
50177 + if (srv->want_fds) {
50178 + /* check the fdwaitqueue for waiting fds */
50179 + int free_fds = srv->max_fds - srv->cur_fds - 16;
50182 + for (; free_fds > 0 && NULL != (con = fdwaitqueue_unshift(srv, srv->fdwaitqueue)); free_fds--) {
50183 + connection_state_machine(srv, con);
50189 + if ((n = fdevent_poll(srv->ev, 1000)) > 0) {
50190 + /* n is the number of events */
50192 + fdevent_get_revents(srv->ev, n, revents);
50194 + /* handle client connections first
50196 + * this is a bit of a hack, but we have to make sure than we handle
50197 + * close-events before the connection is reused for a keep-alive
50200 + * this is mostly an issue for mod_proxy_core, but you never know
50204 + for (i = 0; i < revents->used; i++) {
50205 + fdevent_revent *revent = revents->ptr[i];
50208 + /* skip server-fds */
50209 + if (revent->handler == network_server_handle_fdevent) continue;
50211 + switch (r = (*(revent->handler))(srv, revent->context, revent->revents)) {
50212 + case HANDLER_FINISHED:
50213 + case HANDLER_GO_ON:
50214 + case HANDLER_WAIT_FOR_EVENT:
50215 + case HANDLER_WAIT_FOR_FD:
50217 + case HANDLER_ERROR:
50218 + /* should never happen */
50222 + log_error_write(srv, __FILE__, __LINE__, "d", r);
50227 + for (i = 0; i < revents->used; i++) {
50228 + fdevent_revent *revent = revents->ptr[i];
50231 + /* server fds only */
50232 + if (revent->handler != network_server_handle_fdevent) continue;
50234 + switch (r = (*(revent->handler))(srv, revent->context, revent->revents)) {
50235 + case HANDLER_FINISHED:
50236 + case HANDLER_GO_ON:
50237 + case HANDLER_WAIT_FOR_EVENT:
50238 + case HANDLER_WAIT_FOR_FD:
50240 + case HANDLER_ERROR:
50241 + /* should never happen */
50245 + log_error_write(srv, __FILE__, __LINE__, "d", r);
50250 + } else if (n < 0 && errno != EINTR) {
50251 + log_error_write(srv, __FILE__, __LINE__, "ss",
50252 + "fdevent_poll failed:",
50253 + strerror(errno));
50256 + for (ndx = 0; ndx < srv->joblist->used; ndx++) {
50257 + connection *con = srv->joblist->ptr[ndx];
50260 + connection_state_machine(srv, con);
50262 + switch(r = plugins_call_handle_joblist(srv, con)) {
50263 + case HANDLER_FINISHED:
50264 + case HANDLER_GO_ON:
50267 + log_error_write(srv, __FILE__, __LINE__, "d", r);
50271 + con->in_joblist = 0;
50274 + srv->joblist->used = 0;
50277 + fdevent_revents_free(revents);
50283 +int main (int argc, char **argv, char **envp) {
50284 + server *srv = NULL;
50285 + int print_config = 0;
50286 + int test_config = 0;
50289 + int num_childs = 0;
50290 + int pid_fd = -1, fd;
50293 + char *optarg = NULL;
50296 +#ifdef HAVE_SIGACTION
50297 + struct sigaction act;
50299 +#ifdef HAVE_GETRLIMIT
50300 + struct rlimit rlim;
50304 + struct itimerval interval;
50306 + interval.it_interval.tv_sec = 1;
50307 + interval.it_interval.tv_usec = 0;
50308 + interval.it_value.tv_sec = 1;
50309 + interval.it_value.tv_usec = 0;
50313 + status_counter_init();
50315 + /* for nice %b handling in strfime() */
50316 + setlocale(LC_TIME, "C");
50318 + if (NULL == (srv = server_init())) {
50319 + fprintf(stderr, "did this really happen?\n");
50323 + /* init structs done */
50325 + srv->srvconf.port = 0;
50326 +#ifdef HAVE_GETUID
50327 + i_am_root = (getuid() == 0);
50331 + srv->srvconf.dont_daemonize = 0;
50333 + while(-1 != (o = getopt(argc, argv, "f:m:hvVDpt"))) {
50337 + /* evil HACK for windows, optarg is not set */
50338 + optarg = argv[optind-1];
50340 + if (config_read(srv, optarg)) {
50341 + server_free(srv);
50347 + buffer_copy_string(srv->srvconf.modules_dir, optarg);
50349 + case 'p': print_config = 1; break;
50350 + case 't': test_config = 1; break;
50351 + case 'D': srv->srvconf.dont_daemonize = 1; break;
50352 + case 'v': show_version(); return 0;
50353 + case 'V': show_features(); return 0;
50354 + case 'h': show_help(); return 0;
50357 + server_free(srv);
50362 + if (!srv->config_storage) {
50363 + log_error_write(srv, __FILE__, __LINE__, "s",
50364 + "No configuration available. Try using -f option.");
50366 + server_free(srv);
50370 + if (print_config) {
50371 + data_unset *dc = srv->config_context->data[0];
50373 + dc->print(dc, 0);
50374 + fprintf(stderr, "\n");
50376 + /* shouldn't happend */
50377 + fprintf(stderr, "global config not found\n");
50381 + if (test_config) {
50382 + printf("Syntax OK\n");
50385 + if (test_config || print_config) {
50386 + server_free(srv);
50390 + /* close stdin and stdout, as they are not needed */
50391 + /* move stdin to /dev/null */
50392 + if (-1 != (fd = open("/dev/null", O_RDONLY))) {
50393 + close(STDIN_FILENO);
50394 + dup2(fd, STDIN_FILENO);
50398 + /* move stdout to /dev/null */
50399 + if (-1 != (fd = open("/dev/null", O_WRONLY))) {
50400 + close(STDOUT_FILENO);
50401 + dup2(fd, STDOUT_FILENO);
50405 + if (0 != config_set_defaults(srv)) {
50406 + log_error_write(srv, __FILE__, __LINE__, "s",
50407 + "setting default values failed");
50408 + server_free(srv);
50412 + /* UID handling */
50413 +#ifdef HAVE_GETUID
50414 + if (!i_am_root && (geteuid() == 0 || getegid() == 0)) {
50415 + /* we are setuid-root */
50417 + log_error_write(srv, __FILE__, __LINE__, "s",
50418 + "Are you nuts ? Don't apply a SUID bit to this binary");
50420 + server_free(srv);
50425 + /* check document-root */
50426 + if (srv->config_storage[0]->document_root->used <= 1) {
50427 + log_error_write(srv, __FILE__, __LINE__, "s",
50428 + "document-root is not set\n");
50430 + server_free(srv);
50435 + if (plugins_load(srv)) {
50436 + log_error_write(srv, __FILE__, __LINE__, "s",
50437 + "loading plugins finally failed");
50439 + plugins_free(srv);
50440 + server_free(srv);
50446 + /* open pid file BEFORE chroot */
50447 + if (srv->srvconf.pid_file->used) {
50448 + 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))) {
50450 + if (errno != EEXIST) {
50451 + log_error_write(srv, __FILE__, __LINE__, "sbs",
50452 + "opening pid-file failed:", srv->srvconf.pid_file, strerror(errno));
50456 + if (0 != stat(srv->srvconf.pid_file->ptr, &st)) {
50457 + log_error_write(srv, __FILE__, __LINE__, "sbs",
50458 + "stating existing pid-file failed:", srv->srvconf.pid_file, strerror(errno));
50461 + if (!S_ISREG(st.st_mode)) {
50462 + log_error_write(srv, __FILE__, __LINE__, "sb",
50463 + "pid-file exists and isn't regular file:", srv->srvconf.pid_file);
50467 + if (-1 == (pid_fd = open(srv->srvconf.pid_file->ptr, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
50468 + log_error_write(srv, __FILE__, __LINE__, "sbs",
50469 + "opening pid-file failed:", srv->srvconf.pid_file, strerror(errno));
50475 + if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
50476 + /* select limits itself
50478 * as it is a hard limit and will lead to a segfault we add some safety
50480 - srv->max_fds = FD_SETSIZE - 200;
50481 + fprintf(stderr, "%s.%d: max parallel connections: %d\r\n", __FILE__, __LINE__, FD_SETSIZE);
50482 + srv->max_fds = FD_SETSIZE - 4;
50484 srv->max_fds = 4096;
50486 @@ -636,7 +1006,7 @@
50487 #ifdef HAVE_VALGRIND_VALGRIND_H
50488 if (RUNNING_ON_VALGRIND) use_rlimit = 0;
50492 #ifdef HAVE_GETRLIMIT
50493 if (0 != getrlimit(RLIMIT_NOFILE, &rlim)) {
50494 log_error_write(srv, __FILE__, __LINE__,
50495 @@ -644,13 +1014,13 @@
50501 if (use_rlimit && srv->srvconf.max_fds) {
50505 rlim.rlim_cur = srv->srvconf.max_fds;
50506 rlim.rlim_max = srv->srvconf.max_fds;
50509 if (0 != setrlimit(RLIMIT_NOFILE, &rlim)) {
50510 log_error_write(srv, __FILE__, __LINE__,
50511 "ss", "couldn't set 'max filedescriptors'",
50512 @@ -659,7 +1029,7 @@
50516 - /* #372: solaris need some fds extra for devpoll */
50517 + /* #372: solaris need some fds extra for devpoll */
50518 if (rlim.rlim_cur > 10) rlim.rlim_cur -= 10;
50520 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
50521 @@ -677,33 +1047,33 @@
50522 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
50523 /* don't raise the limit above FD_SET_SIZE */
50524 if (srv->max_fds > FD_SETSIZE - 200) {
50525 - log_error_write(srv, __FILE__, __LINE__, "sd",
50526 + log_error_write(srv, __FILE__, __LINE__, "sd",
50527 "can't raise max filedescriptors above", FD_SETSIZE - 200,
50528 "if event-handler is 'select'. Use 'poll' or something else or reduce server.max-fds.");
50536 /* set user and group */
50537 if (srv->srvconf.username->used) {
50538 if (NULL == (pwd = getpwnam(srv->srvconf.username->ptr))) {
50539 - log_error_write(srv, __FILE__, __LINE__, "sb",
50540 + log_error_write(srv, __FILE__, __LINE__, "sb",
50541 "can't find username", srv->srvconf.username);
50546 if (pwd->pw_uid == 0) {
50547 log_error_write(srv, __FILE__, __LINE__, "s",
50548 "I will not set uid to 0\n");
50554 if (srv->srvconf.groupname->used) {
50555 if (NULL == (grp = getgrnam(srv->srvconf.groupname->ptr))) {
50556 - log_error_write(srv, __FILE__, __LINE__, "sb",
50557 + log_error_write(srv, __FILE__, __LINE__, "sb",
50558 "can't find groupname", srv->srvconf.groupname);
50561 @@ -713,15 +1083,15 @@
50567 /* we need root-perms for port < 1024 */
50568 if (0 != network_init(srv)) {
50575 -#ifdef HAVE_CHROOT
50576 +#ifdef HAVE_CHROOT
50577 if (srv->srvconf.changeroot->used) {
50580 @@ -761,7 +1131,7 @@
50583 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
50584 - srv->max_fds = rlim.rlim_cur < FD_SETSIZE - 200 ? rlim.rlim_cur : FD_SETSIZE - 200;
50585 + srv->max_fds = rlim.rlim_cur < FD_SETSIZE - 4 ? rlim.rlim_cur : FD_SETSIZE - 4;
50587 srv->max_fds = rlim.rlim_cur;
50589 @@ -775,18 +1145,18 @@
50591 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
50592 /* don't raise the limit above FD_SET_SIZE */
50593 - if (srv->max_fds > FD_SETSIZE - 200) {
50594 - log_error_write(srv, __FILE__, __LINE__, "sd",
50595 - "can't raise max filedescriptors above", FD_SETSIZE - 200,
50596 + if (srv->max_fds > FD_SETSIZE - 4) {
50597 + log_error_write(srv, __FILE__, __LINE__, "sd",
50598 + "can't raise max filedescriptors above", FD_SETSIZE - 4,
50599 "if event-handler is 'select'. Use 'poll' or something else or reduce server.max-fds.");
50605 if (0 != network_init(srv)) {
50613 @@ -802,25 +1172,27 @@
50614 /* or use the default */
50615 srv->max_conns = srv->max_fds;
50619 if (HANDLER_GO_ON != plugins_call_init(srv)) {
50620 log_error_write(srv, __FILE__, __LINE__, "s", "Initialization of plugins failed. Going down.");
50624 network_close(srv);
50633 /* network is up, let's deamonize ourself */
50634 if (srv->srvconf.dont_daemonize == 0) daemonize();
50638 srv->gid = getgid();
50639 srv->uid = getuid();
50643 /* write pid file */
50644 if (pid_fd != -1) {
50645 buffer_copy_long(srv->tmp_buf, getpid());
50646 @@ -829,17 +1201,17 @@
50652 if (HANDLER_GO_ON != plugins_call_set_defaults(srv)) {
50653 log_error_write(srv, __FILE__, __LINE__, "s", "Configuration of plugins failed. Going down.");
50657 network_close(srv);
50665 /* dump unused config-keys */
50666 for (i = 0; i < srv->config_context->used; i++) {
50667 array *config = ((data_config *)srv->config_context->data[i])->value;
50668 @@ -847,43 +1219,42 @@
50670 for (j = 0; config && j < config->used; j++) {
50671 data_unset *du = config->data[j];
50674 /* all var.* is known as user defined variable */
50675 if (strncmp(du->key->ptr, "var.", sizeof("var.") - 1) == 0) {
50679 if (NULL == array_get_element(srv->config_touched, du->key->ptr)) {
50680 - log_error_write(srv, __FILE__, __LINE__, "sbs",
50681 + log_error_write(srv, __FILE__, __LINE__, "sbs",
50682 "WARNING: unknown config-key:",
50690 if (srv->config_deprecated) {
50691 - log_error_write(srv, __FILE__, __LINE__, "s",
50692 + log_error_write(srv, __FILE__, __LINE__, "s",
50693 "Configuration contains deprecated keys. Going down.");
50697 network_close(srv);
50704 - if (-1 == log_error_open(srv)) {
50705 - log_error_write(srv, __FILE__, __LINE__, "s",
50707 + if (-1 == log_error_open(srv->srvconf.errorlog_file, srv->srvconf.errorlog_use_syslog)) {
50708 + log_error_write(srv, __FILE__, __LINE__, "s",
50709 "opening errorlog failed, dying");
50713 network_close(srv);
50720 #ifdef HAVE_SIGACTION
50721 memset(&act, 0, sizeof(act));
50722 act.sa_handler = SIG_IGN;
50723 @@ -903,7 +1274,7 @@
50724 sigaction(SIGHUP, &act, NULL);
50725 sigaction(SIGALRM, &act, NULL);
50726 sigaction(SIGCHLD, &act, NULL);
50729 #elif defined(HAVE_SIGNAL)
50730 /* ignore the SIGPIPE from sendfile() */
50731 signal(SIGPIPE, SIG_IGN);
50732 @@ -914,20 +1285,20 @@
50733 signal(SIGCHLD, signal_handler);
50734 signal(SIGINT, signal_handler);
50739 signal(SIGALRM, signal_handler);
50742 /* setup periodic timer (1 second) */
50743 if (setitimer(ITIMER_REAL, &interval, NULL)) {
50744 log_error_write(srv, __FILE__, __LINE__, "s", "setting timer failed");
50749 getitimer(ITIMER_REAL, &interval);
50754 /* start watcher and workers */
50755 num_childs = srv->srvconf.max_worker;
50756 if (num_childs > 0) {
50757 @@ -957,13 +1328,13 @@
50761 - if (NULL == (srv->ev = fdevent_init(srv->max_fds + 1, srv->event_handler))) {
50762 + if (NULL == (srv->ev = fdevent_init(/*srv->max_fds + 1*/ 4096, srv->event_handler))) {
50763 log_error_write(srv, __FILE__, __LINE__,
50764 "s", "fdevent_init failed");
50768 - * kqueue() is called here, select resets its internals,
50770 + * kqueue() is called here, select resets its internals,
50771 * all server sockets get their handlers
50774 @@ -971,7 +1342,7 @@
50776 network_close(srv);
50783 @@ -986,17 +1357,17 @@
50785 if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_FAM) {
50786 if (0 != FAMOpen2(srv->stat_cache->fam, "lighttpd")) {
50787 - log_error_write(srv, __FILE__, __LINE__, "s",
50788 + log_error_write(srv, __FILE__, __LINE__, "s",
50789 "could not open a fam connection, dieing.");
50792 #ifdef HAVE_FAMNOEXISTS
50793 FAMNoExists(srv->stat_cache->fam);
50795 + srv->stat_cache->sock->fd = FAMCONNECTION_GETFD(srv->stat_cache->fam);
50797 - srv->stat_cache->fam_fcce_ndx = -1;
50798 - fdevent_register(srv->ev, FAMCONNECTION_GETFD(srv->stat_cache->fam), stat_cache_handle_fdevent, NULL);
50799 - fdevent_event_add(srv->ev, &(srv->stat_cache->fam_fcce_ndx), FAMCONNECTION_GETFD(srv->stat_cache->fam), FDEVENT_IN);
50800 + fdevent_register(srv->ev, srv->stat_cache->sock, stat_cache_handle_fdevent, NULL);
50801 + fdevent_event_add(srv->ev, srv->stat_cache->sock, FDEVENT_IN);
50805 @@ -1007,330 +1378,36 @@
50807 for (i = 0; i < srv->srv_sockets.used; i++) {
50808 server_socket *srv_socket = srv->srv_sockets.ptr[i];
50809 - if (-1 == fdevent_fcntl_set(srv->ev, srv_socket->fd)) {
50810 + if (-1 == fdevent_fcntl_set(srv->ev, srv_socket->sock)) {
50811 log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed:", strerror(errno));
50817 - while (!srv_shutdown) {
50822 - if (handle_sig_hup) {
50825 - /* reset notification */
50826 - handle_sig_hup = 0;
50829 - /* cycle logfiles */
50831 - switch(r = plugins_call_handle_sighup(srv)) {
50832 - case HANDLER_GO_ON:
50835 - log_error_write(srv, __FILE__, __LINE__, "sd", "sighup-handler return with an error", r);
50839 - if (-1 == log_error_cycle(srv)) {
50840 - log_error_write(srv, __FILE__, __LINE__, "s", "cycling errorlog failed, dying");
50846 - if (handle_sig_alarm) {
50847 - /* a new second */
50850 - /* reset notification */
50851 - handle_sig_alarm = 0;
50854 - /* get current time */
50855 - min_ts = time(NULL);
50857 - if (min_ts != srv->cur_ts) {
50859 - connections *conns = srv->conns;
50862 - switch(r = plugins_call_handle_trigger(srv)) {
50863 - case HANDLER_GO_ON:
50865 - case HANDLER_ERROR:
50866 - log_error_write(srv, __FILE__, __LINE__, "s", "one of the triggers failed");
50869 - log_error_write(srv, __FILE__, __LINE__, "d", r);
50873 - /* trigger waitpid */
50874 - srv->cur_ts = min_ts;
50876 - /* cleanup stat-cache */
50877 - stat_cache_trigger_cleanup(srv);
50879 - * check all connections for timeouts
50882 - for (ndx = 0; ndx < conns->used; ndx++) {
50887 - con = conns->ptr[ndx];
50889 - if (con->state == CON_STATE_READ ||
50890 - con->state == CON_STATE_READ_POST) {
50891 - if (con->request_count == 1) {
50892 - if (srv->cur_ts - con->read_idle_ts > con->conf.max_read_idle) {
50895 - log_error_write(srv, __FILE__, __LINE__, "sd",
50896 - "connection closed - read-timeout:", con->fd);
50898 - connection_set_state(srv, con, CON_STATE_ERROR);
50902 - if (srv->cur_ts - con->read_idle_ts > con->conf.max_keep_alive_idle) {
50905 - log_error_write(srv, __FILE__, __LINE__, "sd",
50906 - "connection closed - read-timeout:", con->fd);
50908 - connection_set_state(srv, con, CON_STATE_ERROR);
50914 - if ((con->state == CON_STATE_WRITE) &&
50915 - (con->write_request_ts != 0)) {
50917 - if (srv->cur_ts - con->write_request_ts > 60) {
50918 - log_error_write(srv, __FILE__, __LINE__, "sdd",
50919 - "connection closed - pre-write-request-timeout:", con->fd, srv->cur_ts - con->write_request_ts);
50923 - if (srv->cur_ts - con->write_request_ts > con->conf.max_write_idle) {
50926 - log_error_write(srv, __FILE__, __LINE__, "sbsosds",
50927 - "NOTE: a request for",
50928 - con->request.uri,
50929 - "timed out after writing",
50930 - con->bytes_written,
50931 - "bytes. We waited",
50932 - (int)con->conf.max_write_idle,
50933 - "seconds. If this a problem increase server.max-write-idle");
50935 - connection_set_state(srv, con, CON_STATE_ERROR);
50939 - /* we don't like div by zero */
50940 - if (0 == (t_diff = srv->cur_ts - con->connection_start)) t_diff = 1;
50942 - if (con->traffic_limit_reached &&
50943 - (con->conf.kbytes_per_second == 0 ||
50944 - ((con->bytes_written / t_diff) < con->conf.kbytes_per_second * 1024))) {
50945 - /* enable connection again */
50946 - con->traffic_limit_reached = 0;
50952 - connection_state_machine(srv, con);
50954 - con->bytes_written_cur_second = 0;
50955 - *(con->conf.global_bytes_per_second_cnt_ptr) = 0;
50959 - fprintf(stderr, "connection-state: ");
50963 - fprintf(stderr, "c[%d,%d]: %s ",
50966 - connection_get_state(con->state));
50970 - if (cs == 1) fprintf(stderr, "\n");
50974 - if (srv->sockets_disabled) {
50975 - /* our server sockets are disabled, why ? */
50977 - if ((srv->cur_fds + srv->want_fds < srv->max_fds * 0.8) && /* we have enough unused fds */
50978 - (srv->conns->used < srv->max_conns * 0.9) &&
50979 - (0 == graceful_shutdown)) {
50980 - for (i = 0; i < srv->srv_sockets.used; i++) {
50981 - server_socket *srv_socket = srv->srv_sockets.ptr[i];
50982 - fdevent_event_add(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN);
50985 - log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets enabled again");
50987 - srv->sockets_disabled = 0;
50990 - if ((srv->cur_fds + srv->want_fds > srv->max_fds * 0.9) || /* out of fds */
50991 - (srv->conns->used > srv->max_conns) || /* out of connections */
50992 - (graceful_shutdown)) { /* graceful_shutdown */
50994 - /* disable server-fds */
50996 - for (i = 0; i < srv->srv_sockets.used; i++) {
50997 - server_socket *srv_socket = srv->srv_sockets.ptr[i];
50998 - fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd);
51000 - if (graceful_shutdown) {
51001 - /* we don't want this socket anymore,
51003 - * closing it right away will make it possible for
51004 - * the next lighttpd to take over (graceful restart)
51007 - fdevent_unregister(srv->ev, srv_socket->fd);
51008 - close(srv_socket->fd);
51009 - srv_socket->fd = -1;
51011 - /* network_close() will cleanup after us */
51015 - if (graceful_shutdown) {
51016 - log_error_write(srv, __FILE__, __LINE__, "s", "[note] graceful shutdown started");
51017 - } else if (srv->conns->used > srv->max_conns) {
51018 - log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets disabled, connection limit reached");
51020 - log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets disabled, out-of-fds");
51023 - srv->sockets_disabled = 1;
51026 + lighty_mainloop(srv);
51028 - if (graceful_shutdown && srv->conns->used == 0) {
51029 - /* we are in graceful shutdown phase and all connections are closed
51030 - * we are ready to terminate without harming anyone */
51031 - srv_shutdown = 1;
51034 - /* we still have some fds to share */
51035 - if (srv->want_fds) {
51036 - /* check the fdwaitqueue for waiting fds */
51037 - int free_fds = srv->max_fds - srv->cur_fds - 16;
51040 - for (; free_fds > 0 && NULL != (con = fdwaitqueue_unshift(srv, srv->fdwaitqueue)); free_fds--) {
51041 - connection_state_machine(srv, con);
51046 + status_counter_free();
51048 - if ((n = fdevent_poll(srv->ev, 1000)) > 0) {
51049 - /* n is the number of events */
51054 - log_error_write(srv, __FILE__, __LINE__, "sd",
51060 - fdevent_handler handler;
51064 - fd_ndx = fdevent_event_next_fdndx (srv->ev, fd_ndx);
51065 - revents = fdevent_event_get_revent (srv->ev, fd_ndx);
51066 - fd = fdevent_event_get_fd (srv->ev, fd_ndx);
51067 - handler = fdevent_get_handler(srv->ev, fd);
51068 - context = fdevent_get_context(srv->ev, fd);
51070 - /* connection_handle_fdevent needs a joblist_append */
51072 - log_error_write(srv, __FILE__, __LINE__, "sdd",
51073 - "event for", fd, revents);
51075 - switch (r = (*handler)(srv, context, revents)) {
51076 - case HANDLER_FINISHED:
51077 - case HANDLER_GO_ON:
51078 - case HANDLER_WAIT_FOR_EVENT:
51079 - case HANDLER_WAIT_FOR_FD:
51081 - case HANDLER_ERROR:
51082 - /* should never happen */
51086 - log_error_write(srv, __FILE__, __LINE__, "d", r);
51089 - } while (--n > 0);
51090 - } else if (n < 0 && errno != EINTR) {
51091 - log_error_write(srv, __FILE__, __LINE__, "ss",
51092 - "fdevent_poll failed:",
51093 - strerror(errno));
51096 - for (ndx = 0; ndx < srv->joblist->used; ndx++) {
51097 - connection *con = srv->joblist->ptr[ndx];
51100 - connection_state_machine(srv, con);
51102 - switch(r = plugins_call_handle_joblist(srv, con)) {
51103 - case HANDLER_FINISHED:
51104 - case HANDLER_GO_ON:
51107 - log_error_write(srv, __FILE__, __LINE__, "d", r);
51111 - con->in_joblist = 0;
51114 - srv->joblist->used = 0;
51117 - if (srv->srvconf.pid_file->used &&
51118 + if (0 == graceful_restart &&
51119 + srv->srvconf.pid_file->used &&
51120 srv->srvconf.changeroot->used == 0) {
51121 if (0 != unlink(srv->srvconf.pid_file->ptr)) {
51122 if (errno != EACCES && errno != EPERM) {
51123 - log_error_write(srv, __FILE__, __LINE__, "sbds",
51124 - "unlink failed for:",
51125 + log_error_write(srv, __FILE__, __LINE__, "sbds",
51126 + "unlink failed for:",
51127 srv->srvconf.pid_file,
51136 - log_error_close(srv);
51137 network_close(srv);
51138 connections_free(srv);
51146 --- ../lighttpd-1.4.11/src/settings.h 2005-08-11 01:26:41.000000000 +0300
51147 +++ lighttpd-1.4.12/src/settings.h 2006-07-16 00:26:04.000000000 +0300
51150 * max size of a buffer which will just be reset
51151 * to ->used = 0 instead of really freeing the buffer
51154 * 64kB (no real reason, just a guess)
51156 #define BUFFER_MAX_REUSE_SIZE (4 * 1024)
51159 * max size of the HTTP request header
51162 * 32k should be enough for everything (just a guess)
51166 #define MAX_HTTP_REQUEST_HEADER (32 * 1024)
51168 -typedef enum { HANDLER_UNSET,
51170 +typedef enum { HANDLER_UNSET,
51173 - HANDLER_COMEBACK,
51174 - HANDLER_WAIT_FOR_EVENT,
51175 + HANDLER_COMEBACK,
51176 + HANDLER_WAIT_FOR_EVENT,
51178 HANDLER_WAIT_FOR_FD
51180 --- ../lighttpd-1.4.11/src/spawn-fcgi.c 2006-03-07 14:18:10.000000000 +0200
51181 +++ lighttpd-1.4.12/src/spawn-fcgi.c 2006-07-16 00:26:04.000000000 +0300
51183 #include <sys/types.h>
51184 -#include <sys/time.h>
51185 #include <sys/stat.h>
51187 #include <stdlib.h>
51188 #include <string.h>
51191 -#include <unistd.h>
51195 #ifdef HAVE_CONFIG_H
51196 #include "config.h"
51206 #include "sys-socket.h"
51207 +#include "sys-files.h"
51209 #ifdef HAVE_SYS_WAIT_H
51210 #include <sys/wait.h>
51211 @@ -45,28 +43,28 @@
51213 int socket_type, status;
51214 struct timeval tv = { 0, 100 * 1000 };
51217 struct sockaddr_un fcgi_addr_un;
51218 struct sockaddr_in fcgi_addr_in;
51219 struct sockaddr *fcgi_addr;
51225 if (child_count < 2) {
51230 if (child_count > 256) {
51238 memset(&fcgi_addr, 0, sizeof(fcgi_addr));
51241 fcgi_addr_un.sun_family = AF_UNIX;
51242 strcpy(fcgi_addr_un.sun_path, unixsocket);
51246 servlen = SUN_LEN(&fcgi_addr_un);
51248 @@ -84,50 +82,50 @@
51250 fcgi_addr_in.sin_port = htons(port);
51251 servlen = sizeof(fcgi_addr_in);
51254 socket_type = AF_INET;
51255 fcgi_addr = (struct sockaddr *) &fcgi_addr_in;
51259 if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
51260 - fprintf(stderr, "%s.%d\n",
51261 + fprintf(stderr, "%s.%d\n",
51262 __FILE__, __LINE__);
51267 if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) {
51268 /* server is not up, spawn in */
51273 if (unixsocket) unlink(unixsocket);
51279 /* reopen socket */
51280 if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
51281 - fprintf(stderr, "%s.%d\n",
51282 + fprintf(stderr, "%s.%d\n",
51283 __FILE__, __LINE__);
51288 if (setsockopt(fcgi_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
51289 - fprintf(stderr, "%s.%d\n",
51290 + fprintf(stderr, "%s.%d\n",
51291 __FILE__, __LINE__);
51295 /* create socket */
51296 if (-1 == bind(fcgi_fd, fcgi_addr, servlen)) {
51297 - fprintf(stderr, "%s.%d: bind failed: %s\n",
51298 + fprintf(stderr, "%s.%d: bind failed: %s\n",
51299 __FILE__, __LINE__,
51305 if (-1 == listen(fcgi_fd, 1024)) {
51306 - fprintf(stderr, "%s.%d: fd = -1\n",
51307 + fprintf(stderr, "%s.%d: fd = -1\n",
51308 __FILE__, __LINE__);
51311 @@ -137,42 +135,45 @@
51319 char cgi_childs[64];
51326 + /* loose control terminal */
51329 /* is save as we limit to 256 childs */
51330 sprintf(cgi_childs, "PHP_FCGI_CHILDREN=%d", child_count);
51333 if(fcgi_fd != FCGI_LISTENSOCK_FILENO) {
51334 close(FCGI_LISTENSOCK_FILENO);
51335 dup2(fcgi_fd, FCGI_LISTENSOCK_FILENO);
51340 /* we don't need the client socket */
51341 for (i = 3; i < 256; i++) {
51346 /* create environment */
51349 putenv(cgi_childs);
51352 /* fork and replace shell */
51353 b = malloc(strlen("exec ") + strlen(appPath) + 1);
51354 strcpy(b, "exec ");
51355 strcat(b, appPath);
51359 execl("/bin/sh", "sh", "-c", b, NULL);
51368 @@ -180,47 +181,47 @@
51375 select(0, NULL, NULL, NULL, &tv);
51378 switch (waitpid(child, &status, WNOHANG)) {
51380 - fprintf(stderr, "%s.%d: child spawned successfully: PID: %d\n",
51381 + fprintf(stderr, "%s.%d: child spawned successfully: PID: %d\n",
51382 __FILE__, __LINE__,
51386 /* write pid file */
51387 if (pid_fd != -1) {
51388 /* assume a 32bit pid_t */
51392 snprintf(pidbuf, sizeof(pidbuf) - 1, "%d", child);
51395 write(pid_fd, pidbuf, strlen(pidbuf));
51405 if (WIFEXITED(status)) {
51406 - fprintf(stderr, "%s.%d: child exited with: %d, %s\n",
51407 + fprintf(stderr, "%s.%d: child exited with: %d, %s\n",
51408 __FILE__, __LINE__,
51409 WEXITSTATUS(status), strerror(WEXITSTATUS(status)));
51410 } else if (WIFSIGNALED(status)) {
51411 - fprintf(stderr, "%s.%d: child signaled: %d\n",
51412 + fprintf(stderr, "%s.%d: child signaled: %d\n",
51413 __FILE__, __LINE__,
51416 - fprintf(stderr, "%s.%d: child died somehow: %d\n",
51417 + fprintf(stderr, "%s.%d: child died somehow: %d\n",
51418 __FILE__, __LINE__,
51427 @@ -228,16 +229,16 @@
51428 __FILE__, __LINE__);
51440 void show_version () {
51441 char *b = "spawn-fcgi" "-" PACKAGE_VERSION \
51442 -" - spawns fastcgi processes\n"
51443 +" - spawns fastcgi processes\n"
51445 write(1, b, strlen(b));
51447 @@ -265,7 +266,7 @@
51450 int main(int argc, char **argv) {
51451 - char *fcgi_app = NULL, *changeroot = NULL, *username = NULL,
51452 + char *fcgi_app = NULL, *changeroot = NULL, *username = NULL,
51453 *groupname = NULL, *unixsocket = NULL, *pid_file = NULL,
51455 unsigned short port = 0;
51456 @@ -273,9 +274,9 @@
51462 i_am_root = (getuid() == 0);
51465 while(-1 != (o = getopt(argc, argv, "c:f:g:hna:p:u:vC:s:P:"))) {
51467 case 'f': fcgi_app = optarg; break;
51468 @@ -290,137 +291,137 @@
51469 case 'P': pid_file = optarg; /* PID file */ break;
51470 case 'v': show_version(); return 0;
51471 case 'h': show_help(); return 0;
51480 if (fcgi_app == NULL || (port == 0 && unixsocket == NULL)) {
51486 if (unixsocket && port) {
51487 - fprintf(stderr, "%s.%d: %s\n",
51488 + fprintf(stderr, "%s.%d: %s\n",
51489 __FILE__, __LINE__,
51490 "either a unix domain socket or a tcp-port, but not both\n");
51497 if (unixsocket && strlen(unixsocket) > UNIX_PATH_MAX - 1) {
51498 - fprintf(stderr, "%s.%d: %s\n",
51499 + fprintf(stderr, "%s.%d: %s\n",
51500 __FILE__, __LINE__,
51501 "path of the unix socket is too long\n");
51508 if (!i_am_root && (geteuid() == 0 || getegid() == 0)) {
51509 /* we are setuid-root */
51511 - fprintf(stderr, "%s.%d: %s\n",
51513 + fprintf(stderr, "%s.%d: %s\n",
51514 __FILE__, __LINE__,
51515 "Are you nuts ? Don't apply a SUID bit to this binary\n");
51524 (-1 == (pid_fd = open(pid_file, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)))) {
51526 if (errno != EEXIST) {
51527 - fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n",
51528 + fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n",
51529 __FILE__, __LINE__,
51530 pid_file, strerror(errno));
51537 /* ok, file exists */
51540 if (0 != stat(pid_file, &st)) {
51541 - fprintf(stderr, "%s.%d: stating pid-file '%s' failed: %s\n",
51542 + fprintf(stderr, "%s.%d: stating pid-file '%s' failed: %s\n",
51543 __FILE__, __LINE__,
51544 pid_file, strerror(errno));
51551 /* is it a regular file ? */
51554 if (!S_ISREG(st.st_mode)) {
51555 - fprintf(stderr, "%s.%d: pid-file exists and isn't regular file: '%s'\n",
51556 + fprintf(stderr, "%s.%d: pid-file exists and isn't regular file: '%s'\n",
51557 __FILE__, __LINE__,
51565 if (-1 == (pid_fd = open(pid_file, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
51566 - fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n",
51567 + fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n",
51568 __FILE__, __LINE__,
51569 pid_file, strerror(errno));
51578 struct group *grp = NULL;
51579 struct passwd *pwd = NULL;
51582 /* set user and group */
51586 if (NULL == (pwd = getpwnam(username))) {
51587 - fprintf(stderr, "%s.%d: %s, %s\n",
51588 + fprintf(stderr, "%s.%d: %s, %s\n",
51589 __FILE__, __LINE__,
51590 "can't find username", username);
51595 if (pwd->pw_uid == 0) {
51596 - fprintf(stderr, "%s.%d: %s\n",
51597 + fprintf(stderr, "%s.%d: %s\n",
51598 __FILE__, __LINE__,
51599 "I will not set uid to 0\n");
51606 if (NULL == (grp = getgrnam(groupname))) {
51607 - fprintf(stderr, "%s.%d: %s %s\n",
51608 + fprintf(stderr, "%s.%d: %s %s\n",
51609 __FILE__, __LINE__,
51610 - "can't find groupname",
51611 + "can't find groupname",
51615 if (grp->gr_gid == 0) {
51616 - fprintf(stderr, "%s.%d: %s\n",
51617 + fprintf(stderr, "%s.%d: %s\n",
51618 __FILE__, __LINE__,
51619 "I will not set gid to 0\n");
51626 if (-1 == chroot(changeroot)) {
51627 - fprintf(stderr, "%s.%d: %s %s\n",
51628 + fprintf(stderr, "%s.%d: %s %s\n",
51629 __FILE__, __LINE__,
51630 "chroot failed: ", strerror(errno));
51633 if (-1 == chdir("/")) {
51634 - fprintf(stderr, "%s.%d: %s %s\n",
51635 + fprintf(stderr, "%s.%d: %s %s\n",
51636 __FILE__, __LINE__,
51637 "chdir failed: ", strerror(errno));
51643 /* drop root privs */
51645 setgid(grp->gr_gid);
51646 @@ -428,7 +429,7 @@
51648 if (username) setuid(pwd->pw_uid);
51652 return fcgi_spawn_connection(fcgi_app, addr, port, unixsocket, child_count, pid_fd, nofork);
51655 --- ../lighttpd-1.4.11/src/splaytree.c 2005-09-12 21:51:28.000000000 +0300
51656 +++ lighttpd-1.4.12/src/splaytree.c 2006-07-16 00:26:03.000000000 +0300
51657 @@ -56,19 +56,19 @@
51659 #define node_size splaytree_size
51661 -/* Splay using the key i (which may or may not be in the tree.)
51662 - * The starting root is t, and the tree used is defined by rat
51663 +/* Splay using the key i (which may or may not be in the tree.)
51664 + * The starting root is t, and the tree used is defined by rat
51665 * size fields are maintained */
51666 splay_tree * splaytree_splay (splay_tree *t, int i) {
51667 splay_tree N, *l, *r, *y;
51668 int comp, root_size, l_size, r_size;
51671 if (t == NULL) return t;
51672 N.left = N.right = NULL;
51674 root_size = node_size(t);
51675 l_size = r_size = 0;
51679 comp = compare(i, t->key);
51681 @@ -120,7 +120,7 @@
51683 r_size -= 1+node_size(y->right);
51687 l->right = t->left; /* assemble */
51688 r->left = t->right;
51690 --- ../lighttpd-1.4.11/src/splaytree.h 2005-09-12 21:51:13.000000000 +0300
51691 +++ lighttpd-1.4.12/src/splaytree.h 2006-07-16 00:26:03.000000000 +0300
51693 /* This macro returns the size of a node. Unlike "x->size", */
51694 /* it works even if x=NULL. The test could be avoided by using */
51695 /* a special version of NULL which was a real node with size 0. */
51700 --- ../lighttpd-1.4.11/src/stat_cache.c 2005-11-22 15:23:51.000000000 +0200
51701 +++ lighttpd-1.4.12/src/stat_cache.c 2006-07-18 13:03:40.000000000 +0300
51703 #include <stdlib.h>
51704 #include <string.h>
51706 -#include <unistd.h>
51709 #include <assert.h>
51713 #include "sys-mmap.h"
51715 -/* NetBSD 1.3.x needs it */
51716 -#ifndef MAP_FAILED
51717 -# define MAP_FAILED -1
51720 -#ifndef O_LARGEFILE
51721 -# define O_LARGEFILE 0
51724 -#ifndef HAVE_LSTAT
51725 -#define lstat stat
51727 +#include "sys-files.h"
51728 +#include "sys-strings.h"
51731 /* enables debug code for testing if all nodes in the stat-cache as accessable */
51734 * if we get a change-event from FAM, we increment the version in the FAM->dir mapping
51736 - * if the stat()-cache is queried we check if the version id for the directory is the
51737 - * same and return immediatly.
51738 + * if the stat()-cache is queried we check if the version id for the directory is the
51739 + * same and return immediatly.
51743 @@ -62,17 +50,17 @@
51744 * - for each FAMRequest we have to find the version in the directory cache (index as userdata)
51746 * stat <<-> directory <-> FAMRequest
51748 - * if file is deleted, directory is dirty, file is rechecked ...
51750 + * if file is deleted, directory is dirty, file is rechecked ...
51751 * if directory is deleted, directory mapping is removed
51765 @@ -83,16 +71,16 @@
51767 * - the hash-key is used as sorting criteria for a tree
51768 * - a splay-tree is used as we can use the caching effect of it
51772 /* we want to cleanup the stat-cache every few seconds, let's say 10
51774 * - remove entries which are outdated since 30s
51775 * - remove entries which are fresh but havn't been used since 60s
51776 * - if we don't have a stat-cache entry for a directory, release it from the monitor
51780 -#ifdef DEBUG_STAT_CACHE
51781 +#ifdef DEBUG_STAT_CACHE
51785 @@ -105,15 +93,16 @@
51787 stat_cache *stat_cache_init(void) {
51788 stat_cache *fc = NULL;
51791 fc = calloc(1, sizeof(*fc));
51794 fc->dir_name = buffer_init();
51796 fc->fam = calloc(1, sizeof(*fc->fam));
51797 + fc->sock = iosocket_init();
51800 -#ifdef DEBUG_STAT_CACHE
51801 +#ifdef DEBUG_STAT_CACHE
51805 @@ -122,24 +111,24 @@
51807 static stat_cache_entry * stat_cache_entry_init(void) {
51808 stat_cache_entry *sce = NULL;
51811 sce = calloc(1, sizeof(*sce));
51814 sce->name = buffer_init();
51815 sce->etag = buffer_init();
51816 sce->content_type = buffer_init();
51822 static void stat_cache_entry_free(void *data) {
51823 stat_cache_entry *sce = data;
51827 buffer_free(sce->etag);
51828 buffer_free(sce->name);
51829 buffer_free(sce->content_type);
51835 @@ -148,22 +137,22 @@
51836 fam_dir_entry *fam_dir = NULL;
51838 fam_dir = calloc(1, sizeof(*fam_dir));
51841 fam_dir->name = buffer_init();
51847 static void fam_dir_entry_free(void *data) {
51848 fam_dir_entry *fam_dir = data;
51851 if (!fam_dir) return;
51854 FAMCancelMonitor(fam_dir->fc, fam_dir->req);
51857 buffer_free(fam_dir->name);
51858 free(fam_dir->req);
51864 @@ -174,7 +163,7 @@
51865 splay_tree *node = sc->files;
51867 osize = sc->files->size;
51870 stat_cache_entry_free(node->data);
51871 sc->files = splaytree_delete(sc->files, node->key);
51873 @@ -187,12 +176,12 @@
51876 splay_tree *node = sc->dirs;
51879 osize = sc->dirs->size;
51881 fam_dir_entry_free(node->data);
51882 sc->dirs = splaytree_delete(sc->dirs, node->key);
51886 assert(NULL == sc->dirs);
51888 @@ -202,6 +191,7 @@
51892 + iosocket_free(sc->sock);
51896 @@ -212,7 +202,7 @@
51897 static int stat_cache_attr_get(buffer *buf, char *name) {
51903 buffer_prepare_copy(buf, attrlen);
51905 @@ -251,15 +241,15 @@
51908 events = FAMPending(sc->fam);
51911 for (i = 0; i < events; i++) {
51913 fam_dir_entry *fam_dir;
51918 FAMNextEvent(sc->fam, &fe);
51924 @@ -280,7 +270,7 @@
51926 sc->dirs = splaytree_splay(sc->dirs, ndx);
51930 if (node && (node->key == ndx)) {
51931 int osize = splaytree_size(sc->dirs);
51933 @@ -298,17 +288,15 @@
51935 if (revent & FDEVENT_HUP) {
51936 /* fam closed the connection */
51937 - srv->stat_cache->fam_fcce_ndx = -1;
51939 - fdevent_event_del(srv->ev, &(sc->fam_fcce_ndx), FAMCONNECTION_GETFD(sc->fam));
51940 - fdevent_unregister(srv->ev, FAMCONNECTION_GETFD(sc->fam));
51941 + fdevent_event_del(srv->ev, sc->sock);
51942 + fdevent_unregister(srv->ev, sc->sock);
51951 return HANDLER_GO_ON;
51954 @@ -332,7 +320,7 @@
51960 * - HANDLER_FINISHED on cache-miss (don't forget to reopen the file)
51961 * - HANDLER_ERROR on stat() failed -> see errno for problem
51963 @@ -348,16 +336,16 @@
51967 -#ifdef DEBUG_STAT_CACHE
51968 +#ifdef DEBUG_STAT_CACHE
51973 splay_tree *file_node = NULL;
51980 * check if the directory for this file has changed
51983 @@ -366,23 +354,23 @@
51984 file_ndx = hashme(name);
51985 sc->files = splaytree_splay(sc->files, file_ndx);
51987 -#ifdef DEBUG_STAT_CACHE
51988 +#ifdef DEBUG_STAT_CACHE
51989 for (i = 0; i < ctrl.used; i++) {
51990 if (ctrl.ptr[i] == file_ndx) break;
51994 if (sc->files && (sc->files->key == file_ndx)) {
51995 -#ifdef DEBUG_STAT_CACHE
51996 +#ifdef DEBUG_STAT_CACHE
51997 /* it was in the cache */
51998 assert(i < ctrl.used);
52001 - /* we have seen this file already and
52003 + /* we have seen this file already and
52004 * don't stat() it again in the same second */
52006 file_node = sc->files;
52009 sce = file_node->data;
52011 /* check if the name is the same, we might have a collision */
52012 @@ -390,7 +378,7 @@
52013 if (buffer_is_equal(name, sce->name)) {
52014 if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_SIMPLE) {
52015 if (sce->stat_ts == srv->cur_ts) {
52018 return HANDLER_GO_ON;
52021 @@ -400,15 +388,15 @@
52022 * file_node is used by the FAM check below to see if we know this file
52023 * and if we can save a stat().
52025 - * BUT, the sce is not reset here as the entry into the cache is ok, we
52026 + * BUT, the sce is not reset here as the entry into the cache is ok, we
52027 * it is just not pointing to our requested file.
52035 -#ifdef DEBUG_STAT_CACHE
52036 +#ifdef DEBUG_STAT_CACHE
52037 if (i != ctrl.used) {
52038 fprintf(stderr, "%s.%d: %08x was already inserted but not found in cache, %s\n", __FILE__, __LINE__, file_ndx, name->ptr);
52040 @@ -424,23 +412,23 @@
52043 dir_ndx = hashme(sc->dir_name);
52046 sc->dirs = splaytree_splay(sc->dirs, dir_ndx);
52049 if (sc->dirs && (sc->dirs->key == dir_ndx)) {
52050 dir_node = sc->dirs;
52054 if (dir_node && file_node) {
52055 /* we found a file */
52058 sce = file_node->data;
52059 fam_dir = dir_node->data;
52062 if (fam_dir->version == sce->dir_version) {
52063 /* the stat()-cache entry is still ok */
52068 return HANDLER_GO_ON;
52071 @@ -448,7 +436,7 @@
52077 * - open() + fstat() on a named-pipe results in a (intended) hang.
52078 * - stat() if regualar file + open() to see if we can read from it is better
52080 @@ -469,16 +457,16 @@
52087 osize = sc->files->size;
52090 sce = stat_cache_entry_init();
52091 buffer_copy_string_buffer(sce->name, name);
52093 - sc->files = splaytree_insert(sc->files, file_ndx, sce);
52094 -#ifdef DEBUG_STAT_CACHE
52096 + sc->files = splaytree_insert(sc->files, file_ndx, sce);
52097 +#ifdef DEBUG_STAT_CACHE
52098 if (ctrl.size == 0) {
52101 @@ -499,29 +487,29 @@
52103 sce->stat_ts = srv->cur_ts;
52105 - /* catch the obvious symlinks
52106 + /* catch the obvious symlinks
52108 * this is not a secure check as we still have a race-condition between
52109 - * the stat() and the open. We can only solve this by
52110 + * the stat() and the open. We can only solve this by
52111 * 1. open() the file
52112 * 2. fstat() the fd
52114 * and keeping the file open for the rest of the time. But this can
52115 * only be done at network level.
52119 if (S_ISLNK(st.st_mode) && !con->conf.follow_symlink) {
52120 return HANDLER_ERROR;
52123 - if (S_ISREG(st.st_mode)) {
52124 + if (S_ISREG(st.st_mode)) {
52125 /* determine mimetype */
52126 buffer_reset(sce->content_type);
52129 for (k = 0; k < con->conf.mimetypes->used; k++) {
52130 data_string *ds = (data_string *)con->conf.mimetypes->data[k];
52131 buffer *type = ds->key;
52134 if (type->used == 0) continue;
52136 /* check if the right side is the same */
52137 @@ -538,8 +526,10 @@
52138 stat_cache_attr_get(sce->content_type, name->ptr);
52141 + } else if (S_ISDIR(st.st_mode)) {
52142 + etag_create(sce->etag, &(sce->st));
52148 (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_FAM)) {
52149 @@ -549,19 +539,19 @@
52150 fam_dir->fc = sc->fam;
52152 buffer_copy_string_buffer(fam_dir->name, sc->dir_name);
52155 fam_dir->version = 1;
52158 fam_dir->req = calloc(1, sizeof(FAMRequest));
52160 - if (0 != FAMMonitorDirectory(sc->fam, fam_dir->name->ptr,
52162 + if (0 != FAMMonitorDirectory(sc->fam, fam_dir->name->ptr,
52163 fam_dir->req, fam_dir)) {
52165 - log_error_write(srv, __FILE__, __LINE__, "sbs",
52166 - "monitoring dir failed:",
52169 + log_error_write(srv, __FILE__, __LINE__, "sbs",
52170 + "monitoring dir failed:",
52172 FamErrlist[FAMErrno]);
52175 fam_dir_entry_free(fam_dir);
52178 @@ -570,7 +560,7 @@
52179 osize = sc->dirs->size;
52182 - sc->dirs = splaytree_insert(sc->dirs, dir_ndx, fam_dir);
52183 + sc->dirs = splaytree_insert(sc->dirs, dir_ndx, fam_dir);
52185 assert(sc->dirs->data == fam_dir);
52186 assert(osize == (sc->dirs->size - 1));
52187 @@ -578,9 +568,9 @@
52189 fam_dir = dir_node->data;
52193 /* bind the fam_fc to the stat() cache entry */
52197 sce->dir_version = fam_dir->version;
52198 sce->dir_ndx = dir_ndx;
52199 @@ -594,11 +584,11 @@
52203 - * remove stat() from cache which havn't been stat()ed for
52204 + * remove stat() from cache which havn't been stat()ed for
52205 * more than 10 seconds
52208 - * walk though the stat-cache, collect the ids which are too old
52210 + * walk though the stat-cache, collect the ids which are too old
52211 * and remove them in a second loop
52214 @@ -639,9 +629,9 @@
52215 sc->files = splaytree_splay(sc->files, ndx);
52220 if (node && (node->key == ndx)) {
52221 -#ifdef DEBUG_STAT_CACHE
52222 +#ifdef DEBUG_STAT_CACHE
52224 int osize = splaytree_size(sc->files);
52225 stat_cache_entry *sce = node->data;
52226 @@ -649,7 +639,7 @@
52227 stat_cache_entry_free(node->data);
52228 sc->files = splaytree_delete(sc->files, ndx);
52230 -#ifdef DEBUG_STAT_CACHE
52231 +#ifdef DEBUG_STAT_CACHE
52232 for (j = 0; j < ctrl.used; j++) {
52233 if (ctrl.ptr[j] == ndx) {
52234 ctrl.ptr[j] = ctrl.ptr[--ctrl.used];
52235 --- ../lighttpd-1.4.11/src/status_counter.c 1970-01-01 03:00:00.000000000 +0300
52236 +++ lighttpd-1.4.12/src/status_counter.c 2006-07-19 20:02:55.000000000 +0300
52238 +#include <stdlib.h>
52240 +#include "status_counter.h"
52242 + * The status array can carry all the status information you want
52243 + * the key to the array is <module-prefix>.<name>
52244 + * and the values are counters
52247 + * fastcgi.backends = 10
52248 + * fastcgi.active-backends = 6
52249 + * fastcgi.backend.<key>.load = 24
52250 + * fastcgi.backend.<key>....
52252 + * fastcgi.backend.<key>.disconnects = ...
52255 +static array *counters = NULL;
52257 +void status_counter_init(void) {
52258 + counters = array_init();
52260 +void status_counter_free(void) {
52261 + array_free(counters);
52264 +array *status_counter_get_array(void) {
52268 +data_integer *status_counter_get_counter(const char *s, size_t len) {
52269 + data_integer *di;
52270 + array *status = status_counter_get_array();
52272 + if (NULL == (di = (data_integer *)array_get_element(status, s))) {
52273 + /* not found, create it */
52275 + if (NULL == (di = (data_integer *)array_get_unused_element(status, TYPE_INTEGER))) {
52276 + di = data_integer_init();
52278 + buffer_copy_string_len(di->key, s, len);
52281 + array_insert_unique(status, (data_unset *)di);
52286 +/* dummies of the statistic framework functions
52287 + * they will be moved to a statistics.c later */
52288 +int status_counter_inc(const char *s, size_t len) {
52289 + data_integer *di = status_counter_get_counter(s, len);
52296 +int status_counter_dec(const char *s, size_t len) {
52297 + data_integer *di = status_counter_get_counter(s, len);
52299 + if (di->value > 0) di->value--;
52304 +int status_counter_set(const char *s, size_t len, int val) {
52305 + data_integer *di = status_counter_get_counter(s, len);
52313 --- ../lighttpd-1.4.11/src/status_counter.h 1970-01-01 03:00:00.000000000 +0300
52314 +++ lighttpd-1.4.12/src/status_counter.h 2006-07-19 20:02:55.000000000 +0300
52316 +#ifndef _STATUS_COUNTER_H_
52317 +#define _STATUS_COUNTER_H_
52319 +#include <sys/types.h>
52321 +#include "array.h"
52323 +void status_counter_init(void);
52324 +void status_counter_free(void);
52325 +array *status_counter_get_array(void);
52326 +data_integer *status_counter_get_counter(const char *s, size_t len);
52327 +int status_counter_inc(const char *s, size_t len);
52328 +int status_counter_dec(const char *s, size_t len);
52329 +int status_counter_set(const char *s, size_t len, int val);
52332 --- ../lighttpd-1.4.11/src/stream.c 2005-09-23 21:50:15.000000000 +0300
52333 +++ lighttpd-1.4.12/src/stream.c 2006-07-16 00:26:04.000000000 +0300
52335 #include <sys/types.h>
52336 #include <sys/stat.h>
52338 -#include <unistd.h>
52341 #include "stream.h"
52345 #include "sys-mmap.h"
52346 +#include "sys-files.h"
52349 # define O_BINARY 0
52350 @@ -19,39 +19,39 @@
52354 -#elif defined __WIN32
52355 +#elif defined _WIN32
52363 if (-1 == stat(fn->ptr, &st)) {
52368 f->size = st.st_size;
52371 if (-1 == (fd = open(fn->ptr, O_RDONLY | O_BINARY))) {
52376 f->start = mmap(0, f->size, PROT_READ, MAP_SHARED, fd, 0);
52382 if (MAP_FAILED == f->start) {
52386 -#elif defined __WIN32
52387 - fh = CreateFile(fn->ptr,
52392 - FILE_ATTRIBUTE_READONLY,
52393 +#elif defined _WIN32
52394 + fh = CreateFile(fn->ptr,
52399 + FILE_ATTRIBUTE_READONLY,
52402 if (!fh) return -1;
52407 - FORMAT_MESSAGE_ALLOCATE_BUFFER |
52408 + FORMAT_MESSAGE_ALLOCATE_BUFFER |
52409 FORMAT_MESSAGE_FROM_SYSTEM,
52418 p = MapViewOfFile(mh,
52425 -# error no mmap found
52426 +# error no mmap found
52433 --- ../lighttpd-1.4.11/src/sys-files.h 1970-01-01 03:00:00.000000000 +0300
52434 +++ lighttpd-1.4.12/src/sys-files.h 2006-07-16 00:26:04.000000000 +0300
52436 +#ifndef _SYS_FILES_H_
52437 +#define _SYS_FILES_H_
52439 +#define DIR_SEPERATOR_UNIX '/'
52440 +#define DIR_SEPERATOR_WIN '\\'
52443 +#include <windows.h>
52444 +#include <io.h> /* open */
52445 +#include <direct.h> /* chdir */
52447 +#include "buffer.h"
52449 +#define DIR_SEPERATOR DIR_SEPERATOR_WIN
52451 +#define __S_ISTYPE(mode, mask) (((mode) & _S_IFMT) == (mask))
52453 +#define S_ISDIR(mode) __S_ISTYPE((mode), _S_IFDIR)
52454 +#define S_ISCHR(mode) __S_ISTYPE((mode), _S_IFCHR)
52455 +#define S_ISBLK(mode) __S_ISTYPE((mode), _S_IFBLK)
52456 +#define S_ISREG(mode) __S_ISTYPE((mode), _S_IFREG)
52457 +/* we don't support symlinks */
52458 +#define S_ISLNK(mode) 0
52460 +#define lstat stat
52461 +#define mkstemp mktemp
52462 +#define mkdir(x, y) mkdir(x)
52465 + const char *d_name;
52470 + WIN32_FIND_DATA finddata;
52471 + struct dirent dent;
52474 +DIR *opendir(const char *dn);
52475 +struct dirent *readdir(DIR *d);
52476 +void closedir(DIR *d);
52478 +buffer *filename_unix2local(buffer *b);
52479 +buffer *pathname_unix2local(buffer *b);
52482 +#include <unistd.h>
52483 +#include <dirent.h>
52485 +#define DIR_SEPERATOR DIR_SEPERATOR_UNIX
52487 +#define filename_unix2local(x) (x)
52488 +#define pathname_unix2local(x) (x)
52491 +#define PATHNAME_APPEND_SLASH(x) \
52492 + if (x->used > 1 && x->ptr[x->used - 2] != DIR_SEPERATOR) { \
52493 + char sl[2] = { DIR_SEPERATOR, 0 }; \
52494 + BUFFER_APPEND_STRING_CONST(x, sl); \
52497 +#ifndef O_LARGEFILE
52498 +# define O_LARGEFILE 0
52503 --- ../lighttpd-1.4.11/src/sys-mmap.h 2005-08-11 01:26:34.000000000 +0300
52504 +++ lighttpd-1.4.12/src/sys-mmap.h 2006-07-16 00:26:04.000000000 +0300
52506 #ifndef WIN32_MMAP_H
52507 #define WIN32_MMAP_H
52512 #define MAP_FAILED -1
52513 #define PROT_SHARED 0
52514 --- ../lighttpd-1.4.11/src/sys-process.h 1970-01-01 03:00:00.000000000 +0300
52515 +++ lighttpd-1.4.12/src/sys-process.h 2006-07-16 00:26:04.000000000 +0300
52517 +#ifndef _SYS_PROCESS_H_
52518 +#define _SYS_PROCESS_H_
52521 +#include <process.h>
52523 +/* win32 has no fork() */
52524 +#define kill(x, y)
52525 +#define getpid() 0
52528 +#include <sys/wait.h>
52529 +#include <unistd.h>
52534 --- ../lighttpd-1.4.11/src/sys-socket.h 2005-08-11 01:26:39.000000000 +0300
52535 +++ lighttpd-1.4.12/src/sys-socket.h 2006-07-19 20:02:55.000000000 +0300
52537 #ifndef WIN32_SOCKET_H
52538 #define WIN32_SOCKET_H
52543 #include <winsock2.h>
52545 #define ECONNRESET WSAECONNRESET
52546 #define EINPROGRESS WSAEINPROGRESS
52547 #define EALREADY WSAEALREADY
52548 +#define ENOTCONN WSAENOTCONN
52549 +#define EWOULDBLOCK WSAEWOULDBLOCK
52550 #define ioctl ioctlsocket
52551 #define hstrerror(x) ""
52552 +#define STDIN_FILENO 0
52553 +#define STDOUT_FILENO 1
52554 +#define STDERR_FILENO 2
52555 +#define ssize_t int
52557 +int inet_aton(const char *cp, struct in_addr *inp);
52558 +#define HAVE_INET_ADDR
52559 +#undef HAVE_INET_ATON
52562 #include <sys/socket.h>
52563 #include <sys/ioctl.h>
52565 #include <sys/un.h>
52566 #include <arpa/inet.h>
52569 +#define SUN_LEN(su) \
52570 + (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
52573 +#define closesocket(x) close(x)
52576 +#endif /* !_WIN32 */
52578 +#ifdef HAVE_INET_NTOP
52579 +# define HAVE_IPV6
52584 + struct sockaddr_in6 ipv6;
52586 + struct sockaddr_in ipv4;
52587 +#ifdef HAVE_SYS_UN_H
52588 + struct sockaddr_un un;
52590 + struct sockaddr plain;
52594 --- ../lighttpd-1.4.11/src/sys-strings.h 1970-01-01 03:00:00.000000000 +0300
52595 +++ lighttpd-1.4.12/src/sys-strings.h 2006-07-16 00:26:03.000000000 +0300
52597 +#ifndef _SYS_STRINGS_H_
52598 +#define _SYS_STRINGS_H_
52601 +#define strcasecmp stricmp
52602 +#define strncasecmp strnicmp
52603 +#define strtoll(p, e, b) _strtoi64(p, e, b)
52608 --- ../lighttpd-1.4.11/tests/LightyTest.pm 2006-01-14 20:32:31.000000000 +0200
52609 +++ lighttpd-1.4.12/tests/LightyTest.pm 2006-07-18 13:03:40.000000000 +0300
52610 @@ -87,14 +87,16 @@
52611 # pre-process configfile if necessary
52614 - unlink($self->{TESTDIR}."/tmp/cfg.file");
52615 - system("cat ".$self->{SRCDIR}."/".$self->{CONFIGFILE}.' | perl -pe "s#\@SRCDIR\@#'.$self->{BASEDIR}.'/tests/#" > '.$self->{TESTDIR}.'/tmp/cfg.file');
52616 + $ENV{'SRCDIR'} = $self->{BASEDIR}.'/tests';
52617 + $ENV{'PORT'} = $self->{PORT};
52619 unlink($self->{LIGHTTPD_PIDFILE});
52621 - system($self->{LIGHTTPD_PATH}." -f ".$self->{TESTDIR}."/tmp/cfg.file -m ".$self->{MODULES_PATH});
52622 + if (defined $ENV{"TRACEME"} && $ENV{"TRACEME"} eq 'strace') {
52623 + system("strace -tt -s 512 -o strace ".$self->{LIGHTTPD_PATH}." -D -f ".$self->{SRCDIR}."/".$self->{CONFIGFILE}." -m ".$self->{MODULES_PATH}." &");
52624 + } elsif (defined $ENV{"TRACEME"} && $ENV{"TRACEME"} eq 'valgrind') {
52625 + system("valgrind --tool=memcheck --show-reachable=yes --leak-check=yes --logfile=valgrind ".$self->{LIGHTTPD_PATH}." -D -f ".$self->{SRCDIR}."/".$self->{CONFIGFILE}." -m ".$self->{MODULES_PATH}." &");
52627 - 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}." &");
52628 + system($self->{LIGHTTPD_PATH}." -f ".$self->{SRCDIR}."/".$self->{CONFIGFILE}." -m ".$self->{MODULES_PATH});
52631 select(undef, undef, undef, 0.1);
52632 @@ -184,7 +186,7 @@
52633 (my $h = $1) =~ tr/[A-Z]/[a-z]/;
52635 if (defined $resp_hdr{$h}) {
52636 - diag(sprintf("header %s is duplicated: %s and %s\n",
52637 + diag(sprintf("header '%s' is duplicated: '%s' and '%s'\n",
52638 $h, $resp_hdr{$h}, $2));
52640 $resp_hdr{$h} = $2;
52641 @@ -196,6 +198,9 @@
52645 + $t->{etag} = $resp_hdr{'etag'};
52646 + $t->{date} = $resp_hdr{'date'};
52649 if (defined $resp_hdr{"content-length"}) {
52650 $resp_body = substr($lines, 0, $resp_hdr{"content-length"});
52651 --- ../lighttpd-1.4.11/tests/Makefile.am 2005-09-16 15:48:40.000000000 +0300
52652 +++ lighttpd-1.4.12/tests/Makefile.am 2006-07-16 00:26:05.000000000 +0300
52653 @@ -39,10 +39,18 @@
52668 + proxy-backend-1.conf \
52669 + proxy-backend-2.conf
52672 TESTS_ENVIRONMENT=$(srcdir)/wrapper.sh $(srcdir) $(top_builddir)
52673 --- ../lighttpd-1.4.11/tests/bug-06.conf 2005-08-27 17:44:19.000000000 +0300
52674 +++ lighttpd-1.4.12/tests/bug-06.conf 2006-07-16 00:26:04.000000000 +0300
52676 -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
52677 -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
52678 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
52679 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
52681 ## bind to port (default: 80)
52685 ## bind to localhost (default: all interfaces)
52686 server.bind = "localhost"
52687 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
52688 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
52689 server.name = "www.example.org"
52690 server.tag = "Apache 1.3.29"
52693 ######################## MODULE CONFIG ############################
52696 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
52697 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
52699 mimetype.assign = ( ".png" => "image/png",
52700 ".jpg" => "image/jpeg",
52702 ".c" => "text/plain",
52703 ".conf" => "text/plain" )
52705 -compress.cache-dir = "@SRCDIR@/tmp/lighttpd/cache/compress/"
52706 +compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
52707 compress.filetype = ("text/plain", "text/html")
52709 setenv.add-environment = ( "TRAC_ENV" => "foo")
52711 "host" => "127.0.0.1",
52713 # "mode" => "authorizer",
52714 -# "docroot" => "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/",
52715 +# "docroot" => env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/",
52719 @@ -106,7 +106,7 @@
52720 ssl.pemfile = "server.pem"
52722 auth.backend = "plain"
52723 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
52724 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
52725 auth.backend.plain.groupfile = "lighttpd.group"
52727 auth.backend.ldap.hostname = "localhost"
52728 @@ -149,15 +149,15 @@
52729 status.config-url = "/server-config"
52731 simple-vhost.document-root = "pages"
52732 -simple-vhost.server-root = "@SRCDIR@/tmp/lighttpd/servers/"
52733 +simple-vhost.server-root = env.SRCDIR + "/tmp/lighttpd/servers/"
52734 simple-vhost.default-host = "www.example.org"
52736 $HTTP["host"] == "vvv.example.org" {
52737 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
52738 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
52741 $HTTP["host"] == "zzz.example.org" {
52742 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
52743 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
52744 server.name = "zzz.example.org"
52747 --- ../lighttpd-1.4.11/tests/bug-12.conf 2005-08-27 17:44:19.000000000 +0300
52748 +++ lighttpd-1.4.12/tests/bug-12.conf 2006-07-16 00:26:04.000000000 +0300
52750 -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
52751 -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
52752 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
52753 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
52755 ## bind to port (default: 80)
52759 ## bind to localhost (default: all interfaces)
52760 server.bind = "localhost"
52761 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
52762 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
52763 server.name = "www.example.org"
52764 server.tag = "Apache 1.3.29"
52767 ######################## MODULE CONFIG ############################
52770 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
52771 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
52773 mimetype.assign = ( ".png" => "image/png",
52774 ".jpg" => "image/jpeg",
52776 ".c" => "text/plain",
52777 ".conf" => "text/plain" )
52779 -compress.cache-dir = "@SRCDIR@/tmp/lighttpd/cache/compress/"
52780 +compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
52781 compress.filetype = ("text/plain", "text/html")
52783 setenv.add-environment = ( "TRAC_ENV" => "foo")
52785 "host" => "127.0.0.1",
52787 # "mode" => "authorizer",
52788 -# "docroot" => "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/",
52789 +# "docroot" => env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/",
52793 @@ -108,7 +108,7 @@
52794 ssl.pemfile = "server.pem"
52796 auth.backend = "plain"
52797 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
52798 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
52799 auth.backend.plain.groupfile = "lighttpd.group"
52801 auth.backend.ldap.hostname = "localhost"
52802 @@ -151,15 +151,15 @@
52803 status.config-url = "/server-config"
52805 simple-vhost.document-root = "pages"
52806 -simple-vhost.server-root = "@SRCDIR@/tmp/lighttpd/servers/"
52807 +simple-vhost.server-root = env.SRCDIR + "/tmp/lighttpd/servers/"
52808 simple-vhost.default-host = "www.example.org"
52810 $HTTP["host"] == "vvv.example.org" {
52811 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
52812 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
52815 $HTTP["host"] == "zzz.example.org" {
52816 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
52817 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
52818 server.name = "zzz.example.org"
52821 --- ../lighttpd-1.4.11/tests/cachable.t 1970-01-01 03:00:00.000000000 +0300
52822 +++ lighttpd-1.4.12/tests/cachable.t 2006-07-18 13:03:40.000000000 +0300
52824 +#!/usr/bin/env perl
52826 + # add current source dir to the include-path
52827 + # we need this for make distcheck
52828 + (my $srcdir = $0) =~ s#/[^/]+$#/#;
52829 + unshift @INC, $srcdir;
52834 +use Test::More tests => 12;
52837 +my $tf = LightyTest->new();
52840 +$tf->{CONFIGFILE} = 'lighttpd.conf';
52842 +ok($tf->start_proc == 0, "Starting lighttpd") or die();
52844 +## check if If-Modified-Since, If-None-Match works
52846 +$t->{REQUEST} = ( <<EOF
52848 +If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT
52851 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
52852 +ok($tf->handle_http($t) == 0, 'Conditional GET - old If-Modified-Since');
52854 +$t->{REQUEST} = ( <<EOF
52856 +If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT; foo
52859 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, '+Last-Modified' => ''} ];
52860 +ok($tf->handle_http($t) == 0, 'Conditional GET - old If-Modified-Since, comment');
52862 +my $now = $t->{date};
52864 +$t->{REQUEST} = ( <<EOF
52866 +If-Modified-Since: $now
52869 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
52870 +ok($tf->handle_http($t) == 0, 'Conditional GET - new If-Modified-Since');
52872 +$t->{REQUEST} = ( <<EOF
52874 +If-Modified-Since: $now; foo
52877 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
52878 +ok($tf->handle_http($t) == 0, 'Conditional GET - new If-Modified-Since, comment');
52880 +$t->{REQUEST} = ( <<EOF
52882 +If-None-Match: foo
52885 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, '+ETag' => ''} ];
52886 +ok($tf->handle_http($t) == 0, 'Conditional GET - old If-None-Match');
52888 +my $etag = $t->{etag};
52890 +$t->{REQUEST} = ( <<EOF
52892 +If-None-Match: $etag
52895 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
52896 +ok($tf->handle_http($t) == 0, 'Conditional GET - old If-None-Match');
52898 +$t->{REQUEST} = ( <<EOF
52900 +If-None-Match: $etag
52901 +If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT; foo
52904 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
52905 +ok($tf->handle_http($t) == 0, 'Conditional GET - ETag + old Last-Modified');
52907 +$t->{REQUEST} = ( <<EOF
52909 +If-None-Match: $etag
52910 +If-Modified-Since: $now; foo
52913 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
52914 +ok($tf->handle_http($t) == 0, 'Conditional GET - ETag, Last-Modified + comment');
52916 +$t->{REQUEST} = ( <<EOF
52918 +If-None-Match: Foo
52919 +If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT; foo
52922 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
52923 +ok($tf->handle_http($t) == 0, 'Conditional GET - old ETAG + old Last-Modified');
52925 +$t->{REQUEST} = ( <<EOF
52927 +If-None-Match: $etag
52928 +If-Modified-Since: $now foo
52931 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 412 } ];
52932 +ok($tf->handle_http($t) == 0, 'Conditional GET - ETag + Last-Modified + overlong timestamp');
52934 +ok($tf->stop_proc == 0, "Stopping lighttpd");
52936 --- ../lighttpd-1.4.11/tests/condition.conf 2005-08-27 17:44:19.000000000 +0300
52937 +++ lighttpd-1.4.12/tests/condition.conf 2006-07-16 00:26:05.000000000 +0300
52939 debug.log-request-handling = "enable"
52940 debug.log-condition-handling = "enable"
52942 -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
52943 -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
52944 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
52945 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
52947 ## bind to port (default: 80)
52950 ## bind to localhost (default: all interfaces)
52951 server.bind = "localhost"
52952 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
52953 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
52954 server.name = "www.example.org"
52955 server.tag = "Apache 1.3.29"
52957 @@ -22,25 +22,25 @@
52958 ######################## MODULE CONFIG ############################
52961 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
52962 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
52964 mimetype.assign = ( ".html" => "text/html" )
52966 url.redirect = ("^" => "/default")
52968 $HTTP["host"] == "www.example.org" {
52969 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
52970 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
52971 server.name = "www.example.org"
52972 url.redirect = ("^" => "/match_1")
52974 else $HTTP["host"] == "test1.example.org" {
52975 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
52976 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
52977 server.name = "test1.example.org"
52978 url.redirect = ("^" => "/match_2")
52981 else $HTTP["host"] == "test2.example.org" {
52982 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
52983 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
52984 server.name = "test2.example.org"
52985 url.redirect = ("^" => "/match_3")
52990 else $HTTP["host"] == "test3.example.org" {
52991 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
52992 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
52993 server.name = "test3.example.org"
52994 url.redirect = ("^" => "/match_4")
52996 --- ../lighttpd-1.4.11/tests/core-keepalive.t 2005-11-17 15:54:19.000000000 +0200
52997 +++ lighttpd-1.4.12/tests/core-keepalive.t 2006-07-16 00:26:05.000000000 +0300
53000 GET /12345.txt HTTP/1.0
53001 Host: 123.example.org
53002 -Connection: keep-alive
53006 $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } , { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
53007 --- ../lighttpd-1.4.11/tests/default.conf 1970-01-01 03:00:00.000000000 +0300
53008 +++ lighttpd-1.4.12/tests/default.conf 2006-07-16 00:26:05.000000000 +0300
53010 +server.name = "www.example.org"
53012 +## bind to port (default: 80)
53013 +server.port = env.PORT
53016 +server.dir-listing = "enable"
53018 +#server.event-handler = "linux-sysepoll"
53019 +#server.event-handler = "linux-rtsig"
53021 +server.modules = (
53028 + "mod_simple_vhost",
53030 + "mod_secdownload",
53037 + "mod_accesslog" )
53039 +server.indexfiles = ( "index.php", "index.html",
53040 + "index.htm", "default.htm" )
53042 +ssi.extension = ( ".shtml" )
53044 +######################## MODULE CONFIG ############################
53047 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
53048 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
53050 +mimetype.assign = ( ".png" => "image/png",
53051 + ".jpg" => "image/jpeg",
53052 + ".jpeg" => "image/jpeg",
53053 + ".gif" => "image/gif",
53054 + ".html" => "text/html",
53055 + ".htm" => "text/html",
53056 + ".pdf" => "application/pdf",
53057 + ".swf" => "application/x-shockwave-flash",
53058 + ".spl" => "application/futuresplash",
53059 + ".txt" => "text/plain",
53060 + ".tar.gz" => "application/x-tgz",
53061 + ".tgz" => "application/x-tgz",
53062 + ".gz" => "application/x-gzip",
53063 + ".c" => "text/plain",
53064 + ".conf" => "text/plain" )
53066 +compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
53067 +compress.filetype = ("text/plain", "text/html")
53069 +setenv.add-environment = ( "TRAC_ENV" => "tracenv", "SETENV" => "setenv")
53071 +cgi.assign = ( ".pl" => "/usr/bin/perl",
53072 + ".cgi" => "/usr/bin/perl",
53073 + ".py" => "/usr/bin/python" )
53075 +userdir.include-user = ( "jan" )
53076 +userdir.path = "/"
53078 +ssl.engine = "disable"
53079 +ssl.pemfile = "server.pem"
53081 +auth.backend = "plain"
53082 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
53083 +auth.backend.htpasswd.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.htpasswd"
53084 +auth.backend.plain.groupfile = "lighttpd.group"
53086 +auth.backend.ldap.hostname = "localhost"
53087 +auth.backend.ldap.base-dn = "dc=my-domain,dc=com"
53088 +auth.backend.ldap.filter = "(uid=$)"
53090 +auth.require = ( "/server-status" =>
53092 + "method" => "digest",
53093 + "realm" => "download archiv",
53094 + "require" => "valid-user"
53098 + "method" => "basic",
53099 + "realm" => "download archiv",
53100 + "require" => "user=jan"
53102 + "/server-config" =>
53104 + "method" => "basic",
53105 + "realm" => "download archiv",
53106 + "require" => "valid-user"
53110 +url.access-deny = ( "~", ".inc")
53112 +url.redirect = ( "^/redirect/$" => "http://localhost:2048/" )
53114 +url.rewrite = ( "^/rewrite/foo($|\?.+)" => "/indexfile/rewrite.php$1",
53115 + "^/rewrite/bar(?:$|\?(.+))" => "/indexfile/rewrite.php?bar&$1" )
53117 +#### status module
53118 +status.status-url = "/server-status"
53119 +status.config-url = "/server-config"
53121 --- ../lighttpd-1.4.11/tests/docroot/www/dummydir/.svn/entries 2006-03-09 19:21:49.000000000 +0200
53122 +++ lighttpd-1.4.12/tests/docroot/www/dummydir/.svn/entries 2006-07-20 00:57:20.000000000 +0300
53126 uuid="152afb58-edef-0310-8abb-c4023f1b3aa9"
53127 - revision="1040"/>
53128 + repos="svn://svn.lighttpd.net/lighttpd"
53129 + revision="1210"/>
53131 --- ../lighttpd-1.4.11/tests/fastcgi-10.conf 2005-08-31 23:36:34.000000000 +0300
53132 +++ lighttpd-1.4.12/tests/fastcgi-10.conf 2006-07-16 00:26:04.000000000 +0300
53134 -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
53135 -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
53136 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
53137 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
53139 ## bind to port (default: 80)
53142 ## bind to localhost (default: all interfaces)
53143 server.bind = "localhost"
53144 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
53145 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
53146 server.name = "www.example.org"
53147 server.tag = "Apache 1.3.29"
53150 ######################## MODULE CONFIG ############################
53153 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
53154 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
53156 mimetype.assign = ( ".png" => "image/png",
53157 ".jpg" => "image/jpeg",
53159 ".c" => "text/plain",
53160 ".conf" => "text/plain" )
53162 -compress.cache-dir = "@SRCDIR@/tmp/lighttpd/cache/compress/"
53163 +compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
53164 compress.filetype = ("text/plain", "text/html")
53168 ssl.pemfile = "server.pem"
53170 auth.backend = "plain"
53171 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
53172 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
53173 auth.backend.plain.groupfile = "lighttpd.group"
53175 auth.backend.ldap.hostname = "localhost"
53176 @@ -128,11 +128,11 @@
53177 status.config-url = "/server-config"
53179 $HTTP["host"] == "vvv.example.org" {
53180 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
53181 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
53184 $HTTP["host"] == "zzz.example.org" {
53185 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
53186 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
53187 server.name = "zzz.example.org"
53190 --- ../lighttpd-1.4.11/tests/fastcgi-13.conf 2006-01-03 12:38:17.000000000 +0200
53191 +++ lighttpd-1.4.12/tests/fastcgi-13.conf 2006-07-18 13:03:40.000000000 +0300
53193 -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
53194 -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
53195 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
53196 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
53198 debug.log-request-header = "enable"
53199 debug.log-response-header = "enable"
53202 ## bind to localhost (default: all interfaces)
53203 server.bind = "localhost"
53204 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
53205 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
53206 server.name = "www.example.org"
53207 server.tag = "Apache 1.3.29"
53210 ######################## MODULE CONFIG ############################
53213 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
53214 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
53216 mimetype.assign = ( ".png" => "image/png",
53217 ".jpg" => "image/jpeg",
53219 ".c" => "text/plain",
53220 ".conf" => "text/plain" )
53222 -compress.cache-dir = "@SRCDIR@/tmp/lighttpd/cache/compress/"
53223 +compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
53224 compress.filetype = ("text/plain", "text/html")
53229 "host" => "127.0.0.1",
53231 - "bin-path" => "/home/jan/Documents/php-5.1.0/sapi/cgi/php -c /usr/local/lib/php.ini",
53232 + "bin-path" => "/home/jan/Documents/php-5.1.4/sapi/cgi/php -c /usr/local/lib/php.ini",
53233 "bin-copy-environment" => ( "PATH", "SHELL", "USER" ),
53236 @@ -102,7 +102,7 @@
53237 ssl.pemfile = "server.pem"
53239 auth.backend = "plain"
53240 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
53241 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
53242 auth.backend.plain.groupfile = "lighttpd.group"
53244 auth.backend.ldap.hostname = "localhost"
53245 @@ -145,11 +145,11 @@
53246 status.config-url = "/server-config"
53248 $HTTP["host"] == "vvv.example.org" {
53249 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
53250 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
53253 $HTTP["host"] == "zzz.example.org" {
53254 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
53255 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
53256 server.name = "zzz.example.org"
53259 --- ../lighttpd-1.4.11/tests/fastcgi-auth.conf 2005-08-27 17:44:19.000000000 +0300
53260 +++ lighttpd-1.4.12/tests/fastcgi-auth.conf 2006-07-16 00:26:05.000000000 +0300
53262 -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
53263 -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
53264 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
53265 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
53267 debug.log-request-header = "enable"
53268 debug.log-response-header = "enable"
53271 ## bind to localhost (default: all interfaces)
53272 server.bind = "localhost"
53273 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
53274 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
53275 server.name = "www.example.org"
53276 server.tag = "Apache 1.3.29"
53279 ######################## MODULE CONFIG ############################
53282 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
53283 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
53285 mimetype.assign = ( ".png" => "image/png",
53286 ".jpg" => "image/jpeg",
53288 ".c" => "text/plain",
53289 ".conf" => "text/plain" )
53291 -compress.cache-dir = "@SRCDIR@/tmp/lighttpd/cache/compress/"
53292 +compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
53293 compress.filetype = ("text/plain", "text/html")
53298 "host" => "127.0.0.1",
53300 - "bin-path" => "@SRCDIR@/fcgi-auth",
53301 + "bin-path" => env.SRCDIR + "/fcgi-auth",
53302 "mode" => "authorizer",
53303 - "docroot" => "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/",
53304 + "docroot" => env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/",
53308 @@ -106,7 +106,7 @@
53309 ssl.pemfile = "server.pem"
53311 auth.backend = "plain"
53312 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
53313 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
53314 auth.backend.plain.groupfile = "lighttpd.group"
53316 auth.backend.ldap.hostname = "localhost"
53317 @@ -149,11 +149,11 @@
53318 status.config-url = "/server-config"
53320 $HTTP["host"] == "vvv.example.org" {
53321 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
53322 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
53325 $HTTP["host"] == "zzz.example.org" {
53326 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
53327 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
53328 server.name = "zzz.example.org"
53331 --- ../lighttpd-1.4.11/tests/fastcgi-responder.conf 2005-08-27 17:44:19.000000000 +0300
53332 +++ lighttpd-1.4.12/tests/fastcgi-responder.conf 2006-07-16 00:26:05.000000000 +0300
53334 -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
53335 -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
53336 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
53337 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
53339 #debug.log-request-header = "enable"
53340 #debug.log-response-header = "enable"
53343 ## bind to localhost (default: all interfaces)
53344 server.bind = "localhost"
53345 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
53346 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
53347 server.name = "www.example.org"
53348 server.tag = "Apache 1.3.29"
53351 ######################## MODULE CONFIG ############################
53354 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
53355 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
53357 mimetype.assign = ( ".png" => "image/png",
53358 ".jpg" => "image/jpeg",
53360 ".c" => "text/plain",
53361 ".conf" => "text/plain" )
53363 -compress.cache-dir = "@SRCDIR@/tmp/lighttpd/cache/compress/"
53364 +compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
53365 compress.filetype = ("text/plain", "text/html")
53368 @@ -90,10 +90,11 @@
53370 "host" => "127.0.0.1",
53372 - "bin-path" => "@SRCDIR@/fcgi-responder",
53373 + "bin-path" => env.SRCDIR + "/fcgi-responder",
53374 "check-local" => "disable",
53377 + "min-procs" => 1,
53378 + "allow-x-send-file" => "enable",
53382 @@ -109,7 +110,7 @@
53383 ssl.pemfile = "server.pem"
53385 auth.backend = "plain"
53386 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
53387 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
53388 auth.backend.plain.groupfile = "lighttpd.group"
53390 auth.backend.ldap.hostname = "localhost"
53391 @@ -152,11 +153,11 @@
53392 status.config-url = "/server-config"
53394 $HTTP["host"] == "vvv.example.org" {
53395 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
53396 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
53399 $HTTP["host"] == "zzz.example.org" {
53400 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
53401 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
53402 server.name = "zzz.example.org"
53405 --- ../lighttpd-1.4.11/tests/fcgi-responder.c 2005-08-11 01:26:55.000000000 +0300
53406 +++ lighttpd-1.4.12/tests/fcgi-responder.c 2006-07-16 00:26:05.000000000 +0300
53409 int num_requests = 2;
53411 - while (num_requests > 0 &&
53412 - FCGI_Accept() >= 0) {
53415 - if (NULL != (p = getenv("QUERY_STRING"))) {
53416 + while (num_requests > 0 && FCGI_Accept() >= 0) {
53418 + char* doc_root = NULL;
53419 + char fname[4096];
53420 + char* pfname = (char *)fname;
53422 + doc_root = getenv("DOCUMENT_ROOT");
53423 + p = getenv("QUERY_STRING");
53425 + if (NULL != p && NULL != doc_root) {
53426 + snprintf(pfname, sizeof(fname), "%s/phpinfo.php", doc_root);
53427 if (0 == strcmp(p, "lf")) {
53428 printf("Status: 200 OK\n\n");
53429 } else if (0 == strcmp(p, "crlf")) {
53431 printf("Status: 200 OK\r\n");
53434 + } else if (0 == strcmp(p,"x-lighttpd-send-file")) {
53435 + printf("Status: 200 OK\r\n");
53436 + printf("X-LIGHTTPD-send-file: %s\r\n", pfname);
53438 + } else if (0 == strcmp(p,"xsendfile")) {
53439 + printf("Status: 200 OK\r\n");
53440 + printf("X-Sendfile: %s\r\n", pfname);
53442 + } else if (0 == strcmp(p,"xsendfile-mixed-case")) {
53443 + printf("Status: 200 OK\r\n");
53444 + printf("X-SeNdFiLe: %s\r\n", pfname);
53446 } else if (0 == strcmp(p, "die-at-end")) {
53447 printf("Status: 200 OK\r\n\r\n");
53449 --- ../lighttpd-1.4.11/tests/lighttpd.conf 2006-03-09 15:26:58.000000000 +0200
53450 +++ lighttpd-1.4.12/tests/lighttpd.conf 2006-07-16 00:26:05.000000000 +0300
53452 -debug.log-request-handling = "enable"
53453 -debug.log-condition-handling = "enable"
53454 -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
53455 -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
53456 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
53457 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
53458 +server.tag = "Apache 1.3.29"
53460 ## 64 Mbyte ... nice limit
53461 server.max-request-size = 65000
53463 -## bind to port (default: 80)
53464 -server.port = 2048
53465 +include "default.conf"
53467 -## bind to localhost (default: all interfaces)
53468 -server.bind = "localhost"
53469 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
53470 -server.name = "www.example.org"
53471 -server.tag = "Apache 1.3.29"
53473 -server.dir-listing = "enable"
53475 -#server.event-handler = "linux-sysepoll"
53476 -#server.event-handler = "linux-rtsig"
53478 -#server.modules.path = ""
53479 -server.modules = (
53482 - "mod_secdownload",
53488 - "mod_simple_vhost",
53491 -# "mod_localizer",
53497 - "mod_accesslog" )
53499 -server.indexfiles = ( "index.php", "index.html",
53500 - "index.htm", "default.htm" )
53503 -######################## MODULE CONFIG ############################
53505 -ssi.extension = ( ".shtml" )
53507 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
53509 -mimetype.assign = ( ".png" => "image/png",
53510 - ".jpg" => "image/jpeg",
53511 - ".jpeg" => "image/jpeg",
53512 - ".gif" => "image/gif",
53513 - ".html" => "text/html",
53514 - ".htm" => "text/html",
53515 - ".pdf" => "application/pdf",
53516 - ".swf" => "application/x-shockwave-flash",
53517 - ".spl" => "application/futuresplash",
53518 - ".txt" => "text/plain",
53519 - ".tar.gz" => "application/x-tgz",
53520 - ".tgz" => "application/x-tgz",
53521 - ".gz" => "application/x-gzip",
53522 - ".c" => "text/plain",
53523 - ".conf" => "text/plain" )
53524 +setenv.add-request-header = ( "FOO" => "foo")
53525 +setenv.add-response-header = ( "BAR" => "foo")
53527 $HTTP["host"] == "cache.example.org" {
53528 - compress.cache-dir = "@SRCDIR@/tmp/lighttpd/cache/compress/"
53529 + compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
53531 -compress.filetype = ("text/plain", "text/html")
53533 -setenv.add-environment = ( "TRAC_ENV" => "tracenv", "SETENV" => "setenv")
53534 -setenv.add-request-header = ( "FOO" => "foo")
53535 -setenv.add-response-header = ( "BAR" => "foo")
53537 $HTTP["url"] =~ "\.pdf$" {
53538 server.range-requests = "disable"
53539 @@ -85,76 +23,31 @@
53540 "/prefix.fcgi" => ( ( "host" => "127.0.0.1", "port" => 1026, "check-local" => "disable", "broken-scriptfilename" => "enable" ) )
53544 -cgi.assign = ( ".pl" => "/usr/bin/perl",
53545 - ".cgi" => "/usr/bin/perl",
53546 - ".py" => "/usr/bin/python" )
53548 -userdir.include-user = ( "jan" )
53549 -userdir.path = "/"
53551 -ssl.engine = "disable"
53552 -ssl.pemfile = "server.pem"
53554 $HTTP["host"] == "auth-htpasswd.example.org" {
53555 auth.backend = "htpasswd"
53558 -auth.backend = "plain"
53559 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
53561 -auth.backend.htpasswd.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.htpasswd"
53564 -auth.require = ( "/server-status" =>
53566 - "method" => "digest",
53567 - "realm" => "download archiv",
53568 - "require" => "group=www|user=jan|host=192.168.2.10"
53570 - "/server-config" =>
53572 - "method" => "basic",
53573 - "realm" => "download archiv",
53574 - "require" => "valid-user"
53578 -url.access-deny = ( "~", ".inc")
53580 -url.rewrite = ( "^/rewrite/foo($|\?.+)" => "/indexfile/rewrite.php$1",
53581 - "^/rewrite/bar(?:$|\?(.+))" => "/indexfile/rewrite.php?bar&$1" )
53583 -expire.url = ( "/expire/access" => "access 2 hours",
53584 - "/expire/modification" => "access plus 1 seconds 2 minutes")
53586 -#cache.cache-dir = "/home/weigon/wwwroot/cache/"
53588 -#### status module
53589 -status.status-url = "/server-status"
53590 -status.config-url = "/server-config"
53592 $HTTP["host"] == "vvv.example.org" {
53593 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
53594 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
53595 secdownload.secret = "verysecret"
53596 - secdownload.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
53597 + secdownload.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
53598 secdownload.uri-prefix = "/sec/"
53599 secdownload.timeout = 120
53602 $HTTP["host"] == "zzz.example.org" {
53603 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
53604 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
53605 server.name = "zzz.example.org"
53608 $HTTP["host"] == "no-simple.example.org" {
53609 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/123.example.org/pages/"
53610 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/123.example.org/pages/"
53611 server.name = "zzz.example.org"
53614 $HTTP["host"] !~ "(no-simple\.example\.org)" {
53615 simple-vhost.document-root = "pages"
53616 - simple-vhost.server-root = "@SRCDIR@/tmp/lighttpd/servers/"
53617 + simple-vhost.server-root = env.SRCDIR + "/tmp/lighttpd/servers/"
53618 simple-vhost.default-host = "www.example.org"
53621 --- ../lighttpd-1.4.11/tests/lowercase.conf 1970-01-01 03:00:00.000000000 +0300
53622 +++ lighttpd-1.4.12/tests/lowercase.conf 2006-07-16 00:26:05.000000000 +0300
53624 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
53625 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
53627 +## bind to port (default: 80)
53628 +server.port = 2048
53630 +## bind to localhost (default: all interfaces)
53631 +server.bind = "localhost"
53632 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
53634 +server.force-lowercase-filenames = "enable"
53636 +server.dir-listing = "enable"
53638 +server.modules = (
53641 + "mod_secdownload",
53650 +server.indexfiles = ( "index.php", "index.html",
53651 + "index.htm", "default.htm" )
53654 +######################## MODULE CONFIG ############################
53656 +mimetype.assign = ( ".png" => "image/png",
53657 + ".jpg" => "image/jpeg",
53658 + ".jpeg" => "image/jpeg",
53659 + ".gif" => "image/gif",
53660 + ".html" => "text/html",
53661 + ".htm" => "text/html",
53662 + ".pdf" => "application/pdf",
53663 + ".swf" => "application/x-shockwave-flash",
53664 + ".spl" => "application/futuresplash",
53665 + ".txt" => "text/plain",
53666 + ".tar.gz" => "application/x-tgz",
53667 + ".tgz" => "application/x-tgz",
53668 + ".gz" => "application/x-gzip",
53669 + ".c" => "text/plain",
53670 + ".conf" => "text/plain" )
53673 +fastcgi.server = ( ".php" => ( ( "host" => "127.0.0.1", "port" => 1026, "broken-scriptfilename" => "enable" ) ),
53674 + "/prefix.fcgi" => ( ( "host" => "127.0.0.1", "port" => 1026, "check-local" => "disable", "broken-scriptfilename" => "enable" ) )
53678 +cgi.assign = ( ".pl" => "/usr/bin/perl",
53679 + ".cgi" => "/usr/bin/perl",
53680 + ".py" => "/usr/bin/python" )
53682 +auth.backend = "plain"
53683 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
53685 +auth.backend.htpasswd.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.htpasswd"
53687 +$HTTP["host"] == "lowercase-auth" {
53688 + auth.require = ( "/image.jpg" =>
53690 + "method" => "digest",
53691 + "realm" => "download archiv",
53692 + "require" => "valid-user"
53697 +$HTTP["host"] == "lowercase-deny" {
53698 + url.access-deny = ( ".jpg")
53701 +$HTTP["host"] == "lowercase-exclude" {
53702 + static-file.exclude-extensions = ( ".jpg" )
53704 --- ../lighttpd-1.4.11/tests/lowercase.t 1970-01-01 03:00:00.000000000 +0300
53705 +++ lighttpd-1.4.12/tests/lowercase.t 2006-07-16 00:26:05.000000000 +0300
53707 +#!/usr/bin/env perl
53709 + # add current source dir to the include-path
53710 + # we need this for make distcheck
53711 + (my $srcdir = $0) =~ s#/[^/]+$#/#;
53712 + unshift @INC, $srcdir;
53717 +use Test::More tests => 10;
53720 +my $tf = LightyTest->new();
53723 +$tf->{CONFIGFILE} = 'lowercase.conf';
53725 +ok($tf->start_proc == 0, "Starting lighttpd") or die();
53727 +## check if lower-casing works
53729 +$t->{REQUEST} = ( <<EOF
53730 +GET /image.JPG HTTP/1.0
53733 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
53734 +ok($tf->handle_http($t) == 0, 'uppercase access');
53736 +$t->{REQUEST} = ( <<EOF
53737 +GET /image.jpg HTTP/1.0
53740 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
53741 +ok($tf->handle_http($t) == 0, 'lowercase access');
53743 +## check that mod-auth works
53745 +$t->{REQUEST} = ( <<EOF
53746 +GET /image.JPG HTTP/1.0
53747 +Host: lowercase-auth
53750 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
53751 +ok($tf->handle_http($t) == 0, 'uppercase access');
53753 +$t->{REQUEST} = ( <<EOF
53754 +GET /image.jpg HTTP/1.0
53755 +Host: lowercase-auth
53758 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 401 } ];
53759 +ok($tf->handle_http($t) == 0, 'lowercase access');
53762 +## check that mod-staticfile exclude works
53763 +$t->{REQUEST} = ( <<EOF
53764 +GET /image.JPG HTTP/1.0
53765 +Host: lowercase-exclude
53768 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
53769 +ok($tf->handle_http($t) == 0, 'upper case access to staticfile.exclude-extension');
53771 +$t->{REQUEST} = ( <<EOF
53772 +GET /image.jpg HTTP/1.0
53773 +Host: lowercase-exclude
53776 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
53777 +ok($tf->handle_http($t) == 0, 'lowercase access');
53780 +## check that mod-access exclude works
53781 +$t->{REQUEST} = ( <<EOF
53782 +GET /image.JPG HTTP/1.0
53783 +Host: lowercase-deny
53786 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
53787 +ok($tf->handle_http($t) == 0, 'uppercase access to url.access-deny protected location');
53789 +$t->{REQUEST} = ( <<EOF
53790 +GET /image.jpg HTTP/1.0
53791 +Host: lowercase-deny
53794 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
53795 +ok($tf->handle_http($t) == 0, 'lowercase access');
53799 +ok($tf->stop_proc == 0, "Stopping lighttpd");
53801 --- ../lighttpd-1.4.11/tests/mod-cgi.t 2005-09-01 14:43:05.000000000 +0300
53802 +++ lighttpd-1.4.12/tests/mod-cgi.t 2006-07-18 13:03:40.000000000 +0300
53804 GET /nph-status.pl HTTP/1.0
53807 -$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
53808 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 502 } ];
53809 ok($tf->handle_http($t) == 0, 'NPH + perl, Bug #14');
53811 $t->{REQUEST} = ( <<EOF
53812 --- ../lighttpd-1.4.11/tests/mod-fastcgi.t 2006-03-09 15:30:45.000000000 +0200
53813 +++ lighttpd-1.4.12/tests/mod-fastcgi.t 2006-07-18 13:03:40.000000000 +0300
53818 -use Test::More tests => 47;
53819 +use Test::More tests => 49;
53822 my $tf = LightyTest->new();
53827 - skip "no PHP running on port 1026", 30 unless $tf->listening_on(1026);
53828 + skip "no PHP running on port 1026", 29 unless $tf->listening_on(1026);
53830 ok($tf->start_proc == 0, "Starting lighttpd") or die();
53832 @@ -223,7 +223,7 @@
53836 - skip "no php found", 4 unless -x "/home/jan/Documents/php-5.1.0/sapi/cgi/php";
53837 + skip "no php found", 4 unless -x "/home/jan/Documents/php-5.1.4/sapi/cgi/php";
53838 $tf->{CONFIGFILE} = 'fastcgi-13.conf';
53839 ok($tf->start_proc == 0, "Starting lighttpd with $tf->{CONFIGFILE}") or die();
53840 $t->{REQUEST} = ( <<EOF
53841 @@ -285,6 +285,34 @@
53842 $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'test123' } ];
53843 ok($tf->handle_http($t) == 0, 'line-ending \r\n + \r\n');
53845 + # X-LIGHTTPD-send-file
53846 + $t->{REQUEST} = ( <<EOF
53847 +GET /index.fcgi?x-lighttpd-send-file HTTP/1.0
53848 +Host: www.example.org
53851 + $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '<?php phpinfo(); ?>
53853 + ok($tf->handle_http($t) == 0, 'X-LIGHTTPD-send-file');
53855 + $t->{REQUEST} = ( <<EOF
53856 +GET /index.fcgi?xsendfile HTTP/1.0
53857 +Host: www.example.org
53860 + $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '<?php phpinfo(); ?>
53862 + ok($tf->handle_http($t) == 0, 'X-Sendfile');
53864 + $t->{REQUEST} = ( <<EOF
53865 +GET /index.fcgi?xsendfile-mixed-case HTTP/1.0
53866 +Host: www.example.org
53869 + $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '<?php phpinfo(); ?>
53871 + ok($tf->handle_http($t) == 0, 'X-SeNdFiLe in mixed case');
53873 $t->{REQUEST} = ( <<EOF
53874 GET /index.fcgi?die-at-end HTTP/1.0
53875 Host: www.example.org
53876 --- ../lighttpd-1.4.11/tests/mod-proxy.t 1970-01-01 03:00:00.000000000 +0300
53877 +++ lighttpd-1.4.12/tests/mod-proxy.t 2006-07-18 13:03:40.000000000 +0300
53879 +#!/usr/bin/env perl
53881 + # add current source dir to the include-path
53882 + # we need this for make distcheck
53883 + (my $srcdir = $0) =~ s#/[^/]+$#/#;
53884 + unshift @INC, $srcdir;
53889 +use Test::More tests => 21;
53892 +my $tf_proxy = LightyTest->new();
53893 +my $tf_backend1 = LightyTest->new();
53894 +my $tf_backend2 = LightyTest->new();
53898 +## we need two procs
53899 +## 1. the real webserver
53900 +## 2. the proxy server
53903 + skip "disabled for now", 21;
53904 +$tf_proxy->{PORT} = 2048;
53905 +$tf_proxy->{CONFIGFILE} = 'proxy.conf';
53906 +$tf_proxy->{LIGHTTPD_PIDFILE} = $tf_proxy->{SRCDIR}.'/tmp/lighttpd/lighttpd-proxy.pid';
53908 +$tf_backend1->{PORT} = 2050;
53909 +$tf_backend1->{CONFIGFILE} = 'proxy-backend-1.conf';
53910 +$tf_backend1->{LIGHTTPD_PIDFILE} = $tf_backend1->{SRCDIR}.'/tmp/lighttpd/lighttpd-backend-1.pid';
53912 +$tf_backend2->{PORT} = 2051;
53913 +$tf_backend2->{CONFIGFILE} = 'proxy-backend-2.conf';
53914 +$tf_backend2->{LIGHTTPD_PIDFILE} = $tf_backend2->{SRCDIR}.'/tmp/lighttpd/lighttpd-backend-2.pid';
53917 +ok($tf_backend1->start_proc == 0, "Starting lighttpd") or die();
53919 +ok($tf_proxy->start_proc == 0, "Starting lighttpd as proxy") or die();
53923 +$t->{REQUEST} = ( <<EOF
53924 +GET /index.html HTTP/1.0
53925 +Host: www.example.org
53928 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
53929 +ok($tf_proxy->handle_http($t) == 0, 'valid request');
53931 +$t->{REQUEST} = ( <<EOF
53932 +GET /index.html HTTP/1.0
53933 +Host: www.example.org
53936 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'Server' => 'proxy-backend-1' } ];
53937 +ok($tf_proxy->handle_http($t) == 0, 'drop Server from real server');
53939 +$t->{REQUEST} = ( <<EOF
53940 +GET /balance-rr/foo HTTP/1.0
53941 +Host: www.example.org
53944 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
53945 +ok($tf_proxy->handle_http($t) == 0, 'balance rr - one backend');
53947 +$t->{REQUEST} = ( <<EOF
53948 +GET /balance-rr/foo HTTP/1.0
53949 +Host: www.example.org
53952 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
53953 +ok($tf_proxy->handle_http($t) == 0, 'balance rr - one host down, failover');
53955 +$t->{REQUEST} = ( <<EOF
53956 +GET /balance-fair/foo HTTP/1.0
53957 +Host: www.example.org
53960 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
53961 +ok($tf_proxy->handle_http($t) == 0, 'balance fair - one backend');
53963 +## backend 2 starting
53964 +ok($tf_backend2->start_proc == 0, "Starting second proxy backend") or die();
53966 +$t->{REQUEST} = ( <<EOF
53967 +GET /balance-rr/foo HTTP/1.0
53968 +Host: www.example.org
53971 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
53972 +ok($tf_proxy->handle_http($t) == 0, 'balance rr - lb, backend 1');
53974 +$t->{REQUEST} = ( <<EOF
53975 +GET /balance-rr/foo HTTP/1.0
53976 +Host: www.example.org
53979 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
53980 +ok($tf_proxy->handle_http($t) == 0, 'balance rr - lb, backend 2');
53982 +$t->{REQUEST} = ( <<EOF
53983 +GET /balance-hash/foo HTTP/1.0
53984 +Host: www.example.org
53987 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
53988 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 1');
53990 +$t->{REQUEST} = ( <<EOF
53991 +GET /balance-hash/foo HTTP/1.0
53992 +Host: www.example.org
53995 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
53996 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 1 - same URL');
53998 +$t->{REQUEST} = ( <<EOF
53999 +GET /balance-hash/bar HTTP/1.0
54000 +Host: www.example.org
54003 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
54004 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 2');
54006 +$t->{REQUEST} = ( <<EOF
54007 +GET /balance-hash/bar HTTP/1.0
54008 +Host: www.example.org
54011 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
54012 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 2 - same URL');
54014 +## backend 1 stopping, failover
54015 +ok($tf_backend1->stop_proc == 0, "Stopping backend 1");
54017 +$t->{REQUEST} = ( <<EOF
54018 +GET /balance-hash/foo HTTP/1.0
54019 +Host: www.example.org
54022 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
54023 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - failover to backend 2');
54025 +$t->{REQUEST} = ( <<EOF
54026 +GET /balance-hash/bar HTTP/1.0
54027 +Host: www.example.org
54030 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
54031 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - failover to backend 2 - same URL');
54033 +$t->{REQUEST} = ( <<EOF
54034 +GET /balance-rr/foo HTTP/1.0
54035 +Host: www.example.org
54038 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
54039 +ok($tf_proxy->handle_http($t) == 0, 'balance rr - failover to backend 2');
54041 +$t->{REQUEST} = ( <<EOF
54042 +GET /balance-fair/foo HTTP/1.0
54043 +Host: www.example.org
54046 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
54047 +ok($tf_proxy->handle_http($t) == 0, 'balance fair - failover to backend 2');
54050 +ok($tf_backend2->stop_proc == 0, "Stopping lighttpd");
54052 +ok($tf_proxy->stop_proc == 0, "Stopping lighttpd proxy");
54054 --- ../lighttpd-1.4.11/tests/proxy-backend-1.conf 1970-01-01 03:00:00.000000000 +0300
54055 +++ lighttpd-1.4.12/tests/proxy-backend-1.conf 2006-07-16 00:26:05.000000000 +0300
54057 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
54058 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd-backend-1.pid"
54060 +include "default.conf"
54063 +server.tag = "proxy-backend-1"
54064 --- ../lighttpd-1.4.11/tests/proxy-backend-2.conf 1970-01-01 03:00:00.000000000 +0300
54065 +++ lighttpd-1.4.12/tests/proxy-backend-2.conf 2006-07-16 00:26:04.000000000 +0300
54067 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
54068 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd-backend-2.pid"
54070 +include "default.conf"
54073 +server.tag = "proxy-backend-2"
54074 --- ../lighttpd-1.4.11/tests/proxy.conf 1970-01-01 03:00:00.000000000 +0300
54075 +++ lighttpd-1.4.12/tests/proxy.conf 2006-07-16 00:26:05.000000000 +0300
54077 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
54078 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd-proxy.pid"
54079 +server.tag = "proxy"
54081 +include "default.conf"
54083 +## 127.0.0.1 and 127.0.0.2 are the same host
54085 + "" => (( "host" => "127.0.0.1",
54086 + "port" => 2050 ),
54087 + ( "host" => "127.0.0.2",
54091 +$HTTP["url"] =~ "^/balance-rr/" {
54092 + proxy.balance = "round-robin"
54095 +$HTTP["url"] =~ "^/balance-hash/" {
54096 + proxy.balance = "hash"
54099 +$HTTP["url"] =~ "^/balance-fair/" {
54100 + proxy.balance = "fair"
54103 --- ../lighttpd-1.4.11/tests/var-include.conf 2005-08-27 17:44:19.000000000 +0300
54104 +++ lighttpd-1.4.12/tests/var-include.conf 2006-07-16 00:26:05.000000000 +0300
54106 debug.log-request-handling = "enable"
54107 debug.log-condition-handling = "enable"
54109 -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
54110 -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
54111 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
54112 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
54114 ## bind to port (default: 80)
54117 ## bind to localhost (default: all interfaces)
54118 server.bind = "localhost"
54119 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
54120 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
54121 server.name = "www.example.org"
54122 server.tag = "Apache 1.3.29"
54124 @@ -21,19 +21,19 @@
54125 ######################## MODULE CONFIG ############################
54128 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
54129 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
54131 mimetype.assign = ( ".html" => "text/html" )
54133 url.redirect = ("^" => "/default")
54135 $HTTP["host"] == "www.example.org" {
54136 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
54137 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
54138 server.name = "www.example.org"
54139 url.redirect = ("^" => "/redirect")
54141 $HTTP["host"] == "test.example.org" {
54142 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
54143 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
54144 server.name = "test.example.org"