2 Property changes on: debian/menu.ex
3 ___________________________________________________________________
8 Property changes on: debian/control
9 ___________________________________________________________________
14 Property changes on: debian/emacsen-remove.ex
15 ___________________________________________________________________
20 Property changes on: debian/watch.ex
21 ___________________________________________________________________
26 Property changes on: debian/manpage.1.ex
27 ___________________________________________________________________
32 Property changes on: debian/manpage.xml.ex
33 ___________________________________________________________________
38 Property changes on: debian/compat
39 ___________________________________________________________________
44 Property changes on: debian/manpage.sgml.ex
45 ___________________________________________________________________
50 Property changes on: debian/init.d
51 ___________________________________________________________________
56 Property changes on: debian/emacsen-startup.ex
57 ___________________________________________________________________
62 Property changes on: debian/changelog
63 ___________________________________________________________________
68 Property changes on: debian/docs
69 ___________________________________________________________________
74 Property changes on: debian/README.Debian.ex
75 ___________________________________________________________________
80 Property changes on: debian/emacsen-install.ex
81 ___________________________________________________________________
86 Property changes on: debian/rules
87 ___________________________________________________________________
92 Property changes on: debian/cron.d.ex
93 ___________________________________________________________________
98 Property changes on: debian/postrm.ex
99 ___________________________________________________________________
104 Property changes on: debian/preinst.ex
105 ___________________________________________________________________
110 Property changes on: debian/prerm.ex
111 ___________________________________________________________________
116 Property changes on: debian/dirs
117 ___________________________________________________________________
122 Property changes on: debian/lighttpd.postinst
123 ___________________________________________________________________
128 Property changes on: debian/lighttpd.conf
129 ___________________________________________________________________
134 Property changes on: debian/lighttpd.doc-base.EX
135 ___________________________________________________________________
140 Property changes on: debian/copyright
141 ___________________________________________________________________
146 Property changes on: debian/conffiles
147 ___________________________________________________________________
152 Property changes on: debian/Makefile.am
153 ___________________________________________________________________
158 Property changes on: debian/lighttpd-default.ex
159 ___________________________________________________________________
164 Property changes on: debian/.cvsignore
165 ___________________________________________________________________
170 Property changes on: debian/lighttpd.logrotate
171 ___________________________________________________________________
176 Property changes on: AUTHORS
177 ___________________________________________________________________
182 ===================================================================
183 --- configure.in (.../tags/lighttpd-1.4.11) (revision 1159)
184 +++ configure.in (.../branches/lighttpd-merge-1.4.x) (revision 1159)
187 # Process this file with autoconf to produce a configure script.
189 -AC_INIT(lighttpd, 1.4.11, jan@kneschke.de)
190 +AC_INIT(lighttpd, 1.4.12, jan@kneschke.de)
191 AC_CONFIG_SRCDIR([src/server.c])
198 -AC_CHECK_MEMBER(struct tm.tm_gmtoff,AC_DEFINE([HAVE_STRUCT_TM_GMTOFF],[1],[gmtoff in struct tm]),,[#include <time.h>])
199 +AC_CHECK_MEMBER(struct tm.tm_gmtoff,[AC_DEFINE([HAVE_STRUCT_TM_GMTOFF],[1],[gmtoff in struct tm])],,[#include <time.h>])
200 AC_CHECK_TYPES(struct sockaddr_storage,,,[#include <sys/socket.h>])
201 AC_CHECK_TYPES(socklen_t,,,[#include <sys/types.h>
202 #include <sys/socket.h>])
204 AC_DEFINE([HAVE_SQLITE3], [1], [libsqlite3])
205 AC_DEFINE([HAVE_SQLITE3_H], [1], [sqlite3.h])
208 + AC_MSG_CHECKING(for locks in mod_webdav)
209 + AC_ARG_WITH(webdav-locks, AC_HELP_STRING([--with-webdav-locks],[locks in mod_webdav]),
210 + [WITH_WEBDAV_LOCKS=$withval],[WITH_WEBDAV_LOCKS=no])
211 + AC_MSG_RESULT([$WITH_WEBDAV_LOCKS])
213 + if test "$WITH_WEBDAV_LOCKS" != "no"; then
214 + AC_CHECK_LIB(uuid, uuid_unparse, [
215 + AC_CHECK_HEADERS([uuid/uuid.h],[
217 + AC_DEFINE([HAVE_UUID], [1], [libuuid])
218 + AC_DEFINE([HAVE_UUID_H], [1], [uuid/uuid.h is available])
226 @@ -381,31 +397,12 @@
228 AC_MSG_RESULT($WITH_LUA)
229 if test "$WITH_LUA" != "no"; then
230 - AC_PATH_PROG(LUACONFIG, lua-config)
232 - if test x"$LUACONFIG" != x; then
233 - LUA_CFLAGS=`$LUACONFIG --include`
234 - LUA_LIBS=`$LUACONFIG --libs --extralibs`
236 + PKG_CHECK_MODULES(LUA, lua >= 5.1, [
237 AC_DEFINE([HAVE_LUA], [1], [liblua])
238 AC_DEFINE([HAVE_LUA_H], [1], [lua.h])
240 - AC_CHECK_LIB(lua, lua_open, [
241 - AC_CHECK_HEADERS([lua.h],[
242 - LUA_LIBS="-llua -llualib"
243 - AC_DEFINE([HAVE_LUA], [1], [liblua])
244 - AC_DEFINE([HAVE_LUA_H], [1], [lua.h])
250 - if test x"$LUA_LIBS" = x; then
252 - PKG_CHECK_MODULES(LUA, lua, [
253 - AC_DEFINE([HAVE_LUA], [1], [liblua])
254 - AC_DEFINE([HAVE_LUA_H], [1], [lua.h])
264 AC_CHECK_FUNCS([dup2 getcwd inet_ntoa inet_ntop memset mmap munmap strchr \
265 - strdup strerror strstr strtol sendfile getopt socket \
266 + strdup strerror strstr strtol sendfile getopt socket lstat \
267 gethostbyname poll sigtimedwait epoll_ctl getrlimit chroot \
268 getuid select signal pathconf madvise posix_fadvise posix_madvise \
269 writev sigaction sendfile64 send_file kqueue port_create localtime_r])
274 -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"
275 +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"
277 plugins="mod_rewrite mod_redirect mod_ssi mod_trigger_b4_dl"
278 features="regex-conditionals"
280 disable_feature="$disable_feature $features"
283 +features="webdav-locks"
284 +if test "x$UUID_LIB" \!= x; then
285 + enable_feature="$enable_feature $features"
287 + disable_feature="$disable_feature $features"
295 Property changes on: configure.in
296 ___________________________________________________________________
301 Property changes on: ChangeLog
302 ___________________________________________________________________
306 Index: src/data_config.c
307 ===================================================================
308 --- src/data_config.c (.../tags/lighttpd-1.4.11) (revision 1159)
309 +++ src/data_config.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
312 static void data_config_free(data_unset *d) {
313 data_config *ds = (data_config *)d;
316 buffer_free(ds->key);
318 buffer_free(ds->comp_key);
321 array_free(ds->value);
322 array_free(ds->childs);
325 if (ds->string) buffer_free(ds->string);
327 if (ds->regex) pcre_free(ds->regex);
328 if (ds->regex_study) pcre_free(ds->regex_study);
335 static void data_config_reset(data_unset *d) {
336 data_config *ds = (data_config *)d;
339 /* reused array elements */
340 buffer_reset(ds->key);
341 buffer_reset(ds->comp_key);
344 static int data_config_insert_dup(data_unset *dst, data_unset *src) {
355 array *a = (array *)ds->value;
360 if (0 == ds->context_ndx) {
361 fprintf(stderr, "config {\n");
363 @@ -117,22 +117,22 @@
365 data_config *data_config_init(void) {
369 ds = calloc(1, sizeof(*ds));
372 ds->key = buffer_init();
373 ds->op = buffer_init();
374 ds->comp_key = buffer_init();
375 ds->value = array_init();
376 ds->childs = array_init();
377 ds->childs->is_weakref = 1;
380 ds->copy = data_config_copy;
381 ds->free = data_config_free;
382 ds->reset = data_config_reset;
383 ds->insert_dup = data_config_insert_dup;
384 ds->print = data_config_print;
385 ds->type = TYPE_CONFIG;
391 Property changes on: src/data_config.c
392 ___________________________________________________________________
396 Index: src/configfile-glue.c
397 ===================================================================
398 --- src/configfile-glue.c (.../tags/lighttpd-1.4.11) (revision 1159)
399 +++ src/configfile-glue.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
407 * are the external interface of lighttpd. The functions
408 * are used by the server itself and the plugins.
410 - * The main-goal is to have a small library in the end
411 - * which is linked against both and which will define
412 + * The main-goal is to have a small library in the end
413 + * which is linked against both and which will define
414 * the interface itself in the end.
421 int config_insert_values_internal(server *srv, array *ca, const config_values_t cv[]) {
426 for (i = 0; cv[i].key; i++) {
429 if (NULL == (du = array_get_element(ca, cv[i].key))) {
437 switch (cv[i].type) {
439 if (du->type == TYPE_ARRAY) {
441 data_array *da = (data_array *)du;
444 for (j = 0; j < da->value->used; j++) {
445 if (da->value->data[j]->type == TYPE_STRING) {
446 data_string *ds = data_string_init();
449 buffer_copy_string_buffer(ds->value, ((data_string *)(da->value->data[j]))->value);
450 if (!da->is_index_key) {
451 /* the id's were generated automaticly, as we copy now we might have to renumber them
452 - * this is used to prepend server.modules by mod_indexfiles as it has to be loaded
453 + * this is used to prepend server.modules by mod_indexfiles as it has to be loaded
454 * before mod_fastcgi and friends */
455 buffer_copy_string_buffer(ds->key, ((data_string *)(da->value->data[j]))->key);
459 array_insert_unique(cv[i].destination, (data_unset *)ds);
461 - log_error_write(srv, __FILE__, __LINE__, "sssd",
462 - "the key of and array can only be a string or a integer, variable:",
463 - cv[i].key, "type:", da->value->data[j]->type);
465 + log_error_write(srv, __FILE__, __LINE__, "sssd",
466 + "the key of and array can only be a string or a integer, variable:",
467 + cv[i].key, "type:", da->value->data[j]->type);
473 log_error_write(srv, __FILE__, __LINE__, "sss", "unexpected type for key: ", cv[i].key, "array of strings");
479 case T_CONFIG_STRING:
480 if (du->type == TYPE_STRING) {
481 data_string *ds = (data_string *)du;
484 buffer_copy_string_buffer(cv[i].destination, ds->value);
485 + } else if (du->type == TYPE_INTEGER) {
486 + data_integer *di = (data_integer *)du;
488 + buffer_copy_long(cv[i].destination, di->value);
490 log_error_write(srv, __FILE__, __LINE__, "ssss", "unexpected type for key: ", cv[i].key, "(string)", "\"...\"");
499 data_integer *di = (data_integer *)du;
502 *((unsigned short *)(cv[i].destination)) = di->value;
506 data_string *ds = (data_string *)du;
509 + if (buffer_isdigit(ds->value)) {
510 + *((unsigned short *)(cv[i].destination)) = strtol(ds->value->ptr, NULL, 10);
514 log_error_write(srv, __FILE__, __LINE__, "ssb", "get a string but expected a short:", cv[i].key, ds->value);
520 @@ -100,19 +110,19 @@
521 case T_CONFIG_BOOLEAN:
522 if (du->type == TYPE_STRING) {
523 data_string *ds = (data_string *)du;
526 if (buffer_is_equal_string(ds->value, CONST_STR_LEN("enable"))) {
527 *((unsigned short *)(cv[i].destination)) = 1;
528 } else if (buffer_is_equal_string(ds->value, CONST_STR_LEN("disable"))) {
529 *((unsigned short *)(cv[i].destination)) = 0;
531 log_error_write(srv, __FILE__, __LINE__, "ssbs", "ERROR: unexpected value for key:", cv[i].key, ds->value, "(enable|disable)");
537 log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: unexpected type for key:", cv[i].key, "(string)", "\"(enable|disable)\"");
545 case T_CONFIG_DEPRECATED:
546 log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: found deprecated key:", cv[i].key, "-", (char *)(cv[i].destination));
549 srv->config_deprecated = 1;
555 @@ -133,25 +143,25 @@
556 int config_insert_values_global(server *srv, array *ca, const config_values_t cv[]) {
561 for (i = 0; cv[i].key; i++) {
562 data_string *touched;
565 if (NULL == (du = array_get_element(ca, cv[i].key))) {
574 touched = data_string_init();
577 buffer_copy_string(touched->value, "");
578 buffer_copy_string_buffer(touched->key, du->key);
581 array_insert_unique(srv->config_touched, (data_unset *)touched);
585 return config_insert_values_internal(srv, ca, cv);
588 @@ -191,25 +201,25 @@
595 case COMP_HTTP_HOST: {
596 char *ck_colon = NULL, *val_colon = NULL;
599 if (!buffer_is_empty(con->uri.authority)) {
604 * append server-port to the HTTP_POST if necessary
608 l = con->uri.authority;
614 ck_colon = strchr(dc->string->ptr, ':');
615 val_colon = strchr(l->ptr, ':');
618 if (ck_colon == val_colon) {
619 /* nothing to do with it */
621 @@ -230,21 +240,21 @@
626 + l = srv->empty_string;
630 case COMP_HTTP_REMOTEIP: {
632 - /* handle remoteip limitations
634 + /* handle remoteip limitations
636 * "10.0.0.1" is provided for all comparisions
639 * only for == and != we support
646 if ((dc->cond == CONFIG_COND_EQ ||
647 dc->cond == CONFIG_COND_NE) &&
648 (con->dst_addr.plain.sa_family == AF_INET) &&
649 @@ -253,41 +263,48 @@
652 struct in_addr val_inp;
655 + if (con->conf.log_condition_handling) {
656 + l = srv->empty_string;
658 + log_error_write(srv, __FILE__, __LINE__, "bsbsb", dc->comp_key,
659 + "(", l, ") compare to", dc->string);
662 if (*(nm_slash+1) == '\0') {
663 log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: no number after / ", dc->string);
666 return COND_RESULT_FALSE;
670 nm_bits = strtol(nm_slash + 1, &err, 10);
674 log_error_write(srv, __FILE__, __LINE__, "sbs", "ERROR: non-digit found in netmask:", dc->string, *err);
677 return COND_RESULT_FALSE;
681 /* take IP convert to the native */
682 buffer_copy_string_len(srv->cond_check_buf, dc->string->ptr, nm_slash - dc->string->ptr);
685 if (INADDR_NONE == (val_inp.s_addr = inet_addr(srv->cond_check_buf->ptr))) {
686 log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: ip addr is invalid:", srv->cond_check_buf);
689 return COND_RESULT_FALSE;
693 if (0 == inet_aton(srv->cond_check_buf->ptr, &val_inp)) {
694 log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: ip addr is invalid:", srv->cond_check_buf);
697 return COND_RESULT_FALSE;
703 nm = htonl(~((1 << (32 - nm_bits)) - 1));
706 if ((val_inp.s_addr & nm) == (con->dst_addr.ipv4.sin_addr.s_addr & nm)) {
707 return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_TRUE : COND_RESULT_FALSE;
711 case COMP_HTTP_REFERER: {
715 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Referer"))) {
720 return COND_RESULT_FALSE;
725 if (con->conf.log_condition_handling) {
726 log_error_write(srv, __FILE__, __LINE__, "bsbs", dc->comp_key,
727 @@ -346,10 +363,10 @@
729 return COND_RESULT_FALSE;
733 if (con->conf.log_condition_handling) {
734 log_error_write(srv, __FILE__, __LINE__, "bsbsb", dc->comp_key,
735 - "(", l, ") compare to ", dc->string);
736 + "(", l, ") compare to", dc->string);
740 @@ -365,13 +382,13 @@
741 case CONFIG_COND_MATCH: {
742 cond_cache_t *cache = &con->cond_cache[dc->context_ndx];
747 #define elementsof(x) (sizeof(x) / sizeof(x[0]))
749 n = pcre_exec(dc->regex, dc->regex_study, l->ptr, l->used - 1, 0, 0,
750 cache->matches, elementsof(cache->matches));
753 cache->patterncount = n;
755 cache->comp_value = l;
762 return COND_RESULT_FALSE;
766 cond_cache_t *caches = con->cond_cache;
768 if (COND_RESULT_UNSET == caches[dc->context_ndx].result) {
769 + if (con->conf.log_condition_handling) {
770 + log_error_write(srv, __FILE__, __LINE__, "sds", "=== start of", dc->context_ndx, "condition block ===");
772 if (COND_RESULT_TRUE == (caches[dc->context_ndx].result = config_check_cond_nocache(srv, con, dc))) {
775 @@ -409,11 +429,11 @@
777 if (con->conf.log_condition_handling) {
778 log_error_write(srv, __FILE__, __LINE__, "dss", dc->context_ndx,
779 - "(uncached) result:",
781 caches[dc->context_ndx].result == COND_RESULT_TRUE ? "true" : "false");
784 - if (con->conf.log_condition_handling) {
785 + if (con->conf.log_condition_cache_handling) {
786 log_error_write(srv, __FILE__, __LINE__, "dss", dc->context_ndx,
788 caches[dc->context_ndx].result == COND_RESULT_TRUE ? "true" : "false");
792 int config_check_cond(server *srv, connection *con, data_config *dc) {
793 - if (con->conf.log_condition_handling) {
794 - log_error_write(srv, __FILE__, __LINE__, "s", "=== start of condition block ===");
796 return (config_check_cond_cached(srv, con, dc) == COND_RESULT_TRUE);
803 +/* return <0 on error
804 + * return 0-x if matched (and replaced)
806 +int config_exec_pcre_keyvalue_buffer(connection *con, pcre_keyvalue_buffer *kvb, data_config *context, buffer *match_buf, buffer *result)
811 + const char *pattern;
812 + size_t pattern_len;
819 + for (i = 0; i < kvb->used; i++) {
823 + extra = kv->key_extra;
824 + pattern = kv->value->ptr;
825 + pattern_len = kv->value->used - 1;
827 + if ((n = pcre_exec(match, extra, match_buf->ptr, match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) {
828 + if (n != PCRE_ERROR_NOMATCH) {
837 + pcre_get_substring_list(match_buf->ptr, ovec, n, &list);
839 + /* search for $[0-9] */
841 + buffer_reset(result);
843 + start = 0; end = pattern_len;
844 + for (k = 0; k < pattern_len; k++) {
845 + if ((pattern[k] == '$' || pattern[k] == '%') &&
846 + isdigit((unsigned char)pattern[k + 1])) {
849 + size_t num = pattern[k + 1] - '0';
853 + buffer_append_string_len(result, pattern + start, end - start);
855 + if (pattern[k] == '$') {
856 + /* n is always > 0 */
857 + if (num < (size_t)n) {
858 + buffer_append_string(result, list[num]);
861 + config_append_cond_match_buffer(con, context, result, num);
869 + buffer_append_string_len(result, pattern + start, pattern_len - start);
877 + return PCRE_ERROR_NOMATCH;
886 Property changes on: src/configfile-glue.c
887 ___________________________________________________________________
892 ===================================================================
893 --- src/fdevent.h (.../tags/lighttpd-1.4.11) (revision 1159)
894 +++ src/fdevent.h (.../branches/lighttpd-merge-1.4.x) (revision 1159)
896 # include <sys/epoll.h>
899 -/* MacOS 10.3.x has poll.h under /usr/include/, all other unixes
900 +/* MacOS 10.3.x has poll.h under /usr/include/, all other unixes
901 * under /usr/include/sys/ */
902 #if defined HAVE_POLL && (defined(HAVE_SYS_POLL_H) || defined(HAVE_POLL_H))
908 # include <sys/poll.h>
910 # if defined HAVE_SIGTIMEDWAIT && defined(__linux__)
917 +# define HAVE_SELECT
919 #if defined HAVE_SELECT
922 # include <winsock2.h>
926 #define FDEVENT_HUP BV(4)
927 #define FDEVENT_NVAL BV(5)
929 -typedef enum { FD_EVENT_TYPE_UNSET = -1,
930 - FD_EVENT_TYPE_CONNECTION,
931 - FD_EVENT_TYPE_FCGI_CONNECTION,
932 - FD_EVENT_TYPE_DIRWATCH,
933 - FD_EVENT_TYPE_CGI_CONNECTION
934 +typedef enum { FD_EVENT_TYPE_UNSET = -1,
935 + FD_EVENT_TYPE_CONNECTION,
936 + FD_EVENT_TYPE_FCGI_CONNECTION,
937 + FD_EVENT_TYPE_DIRWATCH,
938 + FD_EVENT_TYPE_CGI_CONNECTION
941 -typedef enum { FDEVENT_HANDLER_UNSET,
942 +typedef enum { FDEVENT_HANDLER_UNSET,
943 FDEVENT_HANDLER_SELECT,
944 FDEVENT_HANDLER_POLL,
945 FDEVENT_HANDLER_LINUX_RTSIG,
949 * a mapping from fd to connection structure
954 int fd; /**< the fd */
966 * array of unused fd's
971 typedef struct _fdnode {
972 fdevent_handler handler;
977 struct _fdnode *prev, *next;
989 * fd-event handler for select(), poll() and rt-signals on Linux 2.4
993 typedef struct fdevents {
994 fdevent_handler_t type;
1001 #ifdef USE_LINUX_SIGIO
1004 @@ -146,21 +148,21 @@
1007 struct pollfd *pollfds;
1018 fd_set select_write;
1019 fd_set select_error;
1022 fd_set select_set_read;
1023 fd_set select_set_write;
1024 fd_set select_set_error;
1029 #ifdef USE_SOLARIS_DEVPOLL
1030 @@ -177,16 +179,16 @@
1032 int (*reset)(struct fdevents *ev);
1033 void (*free)(struct fdevents *ev);
1036 int (*event_add)(struct fdevents *ev, int fde_ndx, int fd, int events);
1037 int (*event_del)(struct fdevents *ev, int fde_ndx, int fd);
1038 int (*event_get_revent)(struct fdevents *ev, size_t ndx);
1039 int (*event_get_fd)(struct fdevents *ev, size_t ndx);
1042 int (*event_next_fdndx)(struct fdevents *ev, int ndx);
1045 int (*poll)(struct fdevents *ev, int timeout_ms);
1048 int (*fcntl_set)(struct fdevents *ev, int fd);
1052 Property changes on: src/fdevent.h
1053 ___________________________________________________________________
1057 Index: src/mod_cgi.c
1058 ===================================================================
1059 --- src/mod_cgi.c (.../tags/lighttpd-1.4.11) (revision 1159)
1060 +++ src/mod_cgi.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
1062 #include <sys/types.h>
1064 -#include <winsock2.h>
1066 -#include <sys/socket.h>
1067 -#include <sys/wait.h>
1068 -#include <sys/mman.h>
1070 -#include <netinet/in.h>
1072 -#include <arpa/inet.h>
1075 -#include <unistd.h>
1079 -#include <fdevent.h>
1084 #include "connections.h"
1085 #include "joblist.h"
1086 #include "http_chunk.h"
1087 +#include "fdevent.h"
1091 +#include "sys-files.h"
1092 +#include "sys-mmap.h"
1093 +#include "sys-socket.h"
1094 +#include "sys-strings.h"
1095 +#include "sys-process.h"
1097 #ifdef HAVE_SYS_FILIO_H
1098 # include <sys/filio.h>
1117 buffer_pid_t cgi_pid;
1121 buffer *parse_response;
1124 plugin_config **config_storage;
1126 - plugin_config conf;
1128 + plugin_config conf;
1134 int fde_ndx; /* index into the fd-event buffer */
1137 connection *remote_conn; /* dumb pointer */
1138 plugin_data *plugin_data; /* dumb pointer */
1142 buffer *response_header;
1145 handler_ctx *hctx = calloc(1, sizeof(*hctx));
1150 hctx->response = buffer_init();
1151 hctx->response_header = buffer_init();
1157 static void cgi_handler_ctx_free(handler_ctx *hctx) {
1158 buffer_free(hctx->response);
1159 buffer_free(hctx->response_header);
1165 @@ -101,14 +96,14 @@
1167 INIT_FUNC(mod_cgi_init) {
1171 p = calloc(1, sizeof(*p));
1176 p->tmp_buf = buffer_init();
1177 p->parse_response = buffer_init();
1183 @@ -116,62 +111,62 @@
1184 FREE_FUNC(mod_cgi_free) {
1185 plugin_data *p = p_d;
1186 buffer_pid_t *r = &(p->cgi_pid);
1192 if (p->config_storage) {
1194 for (i = 0; i < srv->config_context->used; i++) {
1195 plugin_config *s = p->config_storage[i];
1203 free(p->config_storage);
1208 if (r->ptr) free(r->ptr);
1211 buffer_free(p->tmp_buf);
1212 buffer_free(p->parse_response);
1218 return HANDLER_GO_ON;
1221 SETDEFAULTS_FUNC(mod_fastcgi_set_defaults) {
1222 plugin_data *p = p_d;
1225 - config_values_t cv[] = {
1227 + config_values_t cv[] = {
1228 { "cgi.assign", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
1229 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET}
1232 if (!p) return HANDLER_ERROR;
1235 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
1238 for (i = 0; i < srv->config_context->used; i++) {
1242 s = calloc(1, sizeof(plugin_config));
1246 s->cgi = array_init();
1249 cv[0].destination = s->cgi;
1252 p->config_storage[i] = s;
1255 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
1256 return HANDLER_ERROR;
1261 return HANDLER_GO_ON;
1264 @@ -180,13 +175,13 @@
1267 buffer_pid_t *r = &(p->cgi_pid);
1272 for (i = 0; i < r->used; i++) {
1273 if (r->ptr[i] > m) m = r->ptr[i];
1279 r->ptr = malloc(sizeof(*r->ptr) * r->size);
1280 @@ -194,31 +189,31 @@
1282 r->ptr = realloc(r->ptr, sizeof(*r->ptr) * r->size);
1286 r->ptr[r->used++] = pid;
1292 static int cgi_pid_del(server *srv, plugin_data *p, pid_t pid) {
1294 buffer_pid_t *r = &(p->cgi_pid);
1299 for (i = 0; i < r->used; i++) {
1300 if (r->ptr[i] == pid) break;
1308 if (i != r->used - 1) {
1309 r->ptr[i] = r->ptr[r->used - 1];
1318 @@ -226,32 +221,32 @@
1327 buffer_copy_string_buffer(p->parse_response, in);
1329 - for (s = p->parse_response->ptr;
1330 - NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n')));
1332 + for (s = p->parse_response->ptr;
1333 + NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n')));
1334 s = ns + (eol == EOL_RN ? 2 : 1), line++) {
1335 const char *key, *value;
1345 0 == strncmp(s, "HTTP/1.", 7)) {
1346 /* non-parsed header ... we parse them anyway */
1353 /* after the space should be a status code for us */
1356 status = strtol(s+9, NULL, 10);
1359 if (con->http_status >= 100 &&
1360 con->http_status < 1000) {
1361 /* we expected 3 digits and didn't got them */
1362 @@ -260,27 +255,27 @@
1369 if (NULL == (value = strchr(s, ':'))) {
1370 /* we expect: "<key>: <value>\r\n" */
1375 key_len = value - key;
1380 while (*value == ' ' || *value == '\t') value++;
1383 if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
1384 ds = data_response_init();
1386 buffer_copy_string_len(ds->key, key, key_len);
1387 buffer_copy_string(ds->value, value);
1390 array_insert_unique(con->response.headers, (data_unset *)ds);
1395 if (0 == strncasecmp(key, "Date", key_len)) {
1396 @@ -315,13 +310,13 @@
1402 /* CGI/1.1 rev 03 - 7.2.1.2 */
1403 if ((con->parsed_response & HTTP_LOCATION) &&
1404 !(con->parsed_response & HTTP_STATUS)) {
1405 con->http_status = 302;
1412 @@ -329,10 +324,10 @@
1413 static int cgi_demux_response(server *srv, handler_ctx *hctx) {
1414 plugin_data *p = hctx->plugin_data;
1415 connection *con = hctx->remote_conn;
1422 buffer_prepare_copy(hctx->response, 1024);
1423 if (-1 == (n = read(hctx->fd, hctx->response->ptr, hctx->response->size - 1))) {
1424 if (errno == EAGAIN || errno == EINTR) {
1425 @@ -343,125 +338,125 @@
1426 log_error_write(srv, __FILE__, __LINE__, "sdd", strerror(errno), con->fd, hctx->fd);
1427 return FDEVENT_HANDLED_ERROR;
1435 con->file_finished = 1;
1438 /* send final chunk */
1439 http_chunk_append_mem(srv, con, NULL, 0);
1440 joblist_append(srv, con);
1443 return FDEVENT_HANDLED_FINISHED;
1447 hctx->response->ptr[n] = '\0';
1448 hctx->response->used = n+1;
1451 /* split header from body */
1454 if (con->file_started == 0) {
1458 int cp, eol = EOL_UNSET;
1462 buffer_append_string_buffer(hctx->response_header, hctx->response);
1465 /* nph (non-parsed headers) */
1466 if (0 == strncmp(hctx->response_header->ptr, "HTTP/1.", 7)) in_header = 1;
1469 /* search for the \r\n\r\n or \n\n in the string */
1470 for (c = hctx->response_header->ptr, cp = 0, used = hctx->response_header->used - 1; used; c++, cp++, used--) {
1471 if (*c == ':') in_header = 1;
1472 else if (*c == '\n') {
1473 if (in_header == 0) {
1474 /* got a response without a response header */
1483 if (eol == EOL_UNSET) eol = EOL_N;
1486 if (*(c+1) == '\n') {
1492 } else if (used > 1 && *c == '\r' && *(c+1) == '\n') {
1493 if (in_header == 0) {
1494 /* got a response without a response header */
1503 if (eol == EOL_UNSET) eol = EOL_RN;
1525 /* no header, but a body */
1528 if (con->request.http_version == HTTP_VERSION_1_1) {
1529 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
1533 http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used);
1534 joblist_append(srv, con);
1536 size_t hlen = c - hctx->response_header->ptr + (eol == EOL_RN ? 4 : 2);
1537 size_t blen = hctx->response_header->used - hlen - 1;
1540 /* a small hack: terminate after at the second \r */
1541 hctx->response_header->used = hlen + 1 - (eol == EOL_RN ? 2 : 1);
1542 hctx->response_header->ptr[hlen - (eol == EOL_RN ? 2 : 1)] = '\0';
1545 /* parse the response header */
1546 cgi_response_parse(srv, con, p, hctx->response_header, eol);
1549 /* enable chunked-transfer-encoding */
1550 if (con->request.http_version == HTTP_VERSION_1_1 &&
1551 !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
1552 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
1556 if ((hctx->response->used != hlen) && blen > 0) {
1557 http_chunk_append_mem(srv, con, c + (eol == EOL_RN ? 4: 2), blen + 1);
1558 joblist_append(srv, con);
1563 con->file_started = 1;
1566 http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used);
1567 joblist_append(srv, con);
1573 log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), b->ptr);
1578 return FDEVENT_HANDLED_NOT_FINISHED;
1581 @@ -470,45 +465,46 @@
1587 if (NULL == hctx) return HANDLER_GO_ON;
1590 p = hctx->plugin_data;
1591 con = hctx->remote_conn;
1594 if (con->mode != p->id) return HANDLER_GO_ON;
1600 /* the connection to the browser went away, but we still have a connection
1601 - * to the CGI script
1602 + * to the CGI script
1604 * close cgi-connection
1608 if (hctx->fd != -1) {
1609 /* close connection to the cgi-script */
1610 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
1611 fdevent_unregister(srv->ev, hctx->fd);
1614 if (close(hctx->fd)) {
1615 log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno));
1627 con->plugin_ctx[p->id] = NULL;
1630 /* is this a good idea ? */
1631 cgi_handler_ctx_free(hctx);
1634 /* if waitpid hasn't been called by response.c yet, do it here */
1636 /* check if the CGI-script is already gone */
1638 switch(waitpid(pid, &status, WNOHANG)) {
1640 /* not finished yet */
1641 @@ -519,19 +515,19 @@
1644 if (errno == EINTR) break;
1647 - * errno == ECHILD happens if _subrequest catches the process-status before
1650 + * errno == ECHILD happens if _subrequest catches the process-status before
1651 * we have read the response of the cgi process
1657 * -> we get here with waitpid == ECHILD
1661 if (errno == ECHILD) return HANDLER_GO_ON;
1664 log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno));
1665 return HANDLER_ERROR;
1667 @@ -541,13 +537,13 @@
1668 con->http_status = 500;
1673 if (WIFEXITED(status)) {
1675 log_error_write(srv, __FILE__, __LINE__, "sd", "(debug) cgi exited fine, pid:", pid);
1680 return HANDLER_GO_ON;
1682 log_error_write(srv, __FILE__, __LINE__, "sd", "cgi died, pid:", pid);
1683 @@ -555,20 +551,20 @@
1684 return HANDLER_GO_ON;
1694 /* cgi-script is still alive, queue the PID for removal */
1695 cgi_pid_add(srv, p, pid);
1699 return HANDLER_GO_ON;
1702 static handler_t cgi_connection_close_callback(server *srv, connection *con, void *p_d) {
1703 plugin_data *p = p_d;
1706 return cgi_connection_close(srv, con->plugin_ctx[p->id]);
1709 @@ -577,43 +573,43 @@
1710 server *srv = (server *)s;
1711 handler_ctx *hctx = ctx;
1712 connection *con = hctx->remote_conn;
1715 joblist_append(srv, con);
1718 if (hctx->fd == -1) {
1719 log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), "invalid cgi-fd");
1722 return HANDLER_ERROR;
1726 if (revents & FDEVENT_IN) {
1727 switch (cgi_demux_response(srv, hctx)) {
1728 case FDEVENT_HANDLED_NOT_FINISHED:
1730 case FDEVENT_HANDLED_FINISHED:
1735 log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), "finished");
1737 cgi_connection_close(srv, hctx);
1739 - /* if we get a IN|HUP and have read everything don't exec the close twice */
1741 + /* if we get a IN|HUP and have read everything don't exec the close twice */
1742 return HANDLER_FINISHED;
1743 case FDEVENT_HANDLED_ERROR:
1744 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
1745 con->http_status = 500;
1749 log_error_write(srv, __FILE__, __LINE__, "s", "demuxer failed: ");
1755 if (revents & FDEVENT_OUT) {
1760 /* perhaps this issue is already handled */
1761 if (revents & FDEVENT_HUP) {
1762 /* check if we still have a unfinished header package which is a body in reality */
1763 @@ -623,54 +619,54 @@
1764 http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used);
1765 joblist_append(srv, con);
1769 if (con->file_finished == 0) {
1770 http_chunk_append_mem(srv, con, NULL, 0);
1771 joblist_append(srv, con);
1775 con->file_finished = 1;
1778 if (chunkqueue_is_empty(con->write_queue)) {
1779 /* there is nothing left to write */
1780 connection_set_state(srv, con, CON_STATE_RESPONSE_END);
1782 /* used the write-handler to finish the request on demand */
1789 log_error_write(srv, __FILE__, __LINE__, "sddd", "got HUP from cgi", con->fd, hctx->fd, revents);
1793 /* rtsigs didn't liked the close */
1794 cgi_connection_close(srv, hctx);
1795 } else if (revents & FDEVENT_ERR) {
1796 con->file_finished = 1;
1799 /* kill all connections to the cgi process */
1800 cgi_connection_close(srv, hctx);
1802 log_error_write(srv, __FILE__, __LINE__, "s", "cgi-FDEVENT_ERR");
1805 return HANDLER_ERROR;
1809 return HANDLER_FINISHED;
1813 static int cgi_env_add(char_array *env, const char *key, size_t key_len, const char *val, size_t val_len) {
1817 if (!key || !val) return -1;
1820 dst = malloc(key_len + val_len + 3);
1821 memcpy(dst, key, key_len);
1823 /* add the \0 from the value */
1824 memcpy(dst + key_len + 1, val, val_len + 1);
1827 if (env->size == 0) {
1829 env->ptr = malloc(env->size * sizeof(*env->ptr));
1830 @@ -678,45 +674,45 @@
1832 env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
1836 env->ptr[env->used++] = dst;
1842 static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer *cgi_handler) {
1847 char b2[INET6_ADDRSTRLEN + 1];
1852 int from_cgi_fds[2];
1860 if (cgi_handler->used > 1) {
1861 /* stat the exec file */
1862 if (-1 == (stat(cgi_handler->ptr, &st))) {
1863 - log_error_write(srv, __FILE__, __LINE__, "sbss",
1864 + log_error_write(srv, __FILE__, __LINE__, "sbss",
1865 "stat for cgi-handler", cgi_handler,
1866 "failed:", strerror(errno));
1872 if (pipe(to_cgi_fds)) {
1873 log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed:", strerror(errno));
1878 if (pipe(from_cgi_fds)) {
1879 log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed:", strerror(errno));
1885 switch (pid = fork()) {
1887 @@ -730,22 +726,22 @@
1890 server_socket *srv_sock = con->srv_socket;
1893 /* move stdout to from_cgi_fd[1] */
1894 close(STDOUT_FILENO);
1895 dup2(from_cgi_fds[1], STDOUT_FILENO);
1896 close(from_cgi_fds[1]);
1898 close(from_cgi_fds[0]);
1901 /* move the stdin to to_cgi_fd[0] */
1902 close(STDIN_FILENO);
1903 dup2(to_cgi_fds[0], STDIN_FILENO);
1904 close(to_cgi_fds[0]);
1906 close(to_cgi_fds[1]);
1911 * this is not nice, but it works
1913 * we feed the stderr of the CGI to our errorlog, if possible
1914 @@ -754,20 +750,20 @@
1915 close(STDERR_FILENO);
1916 dup2(srv->errorlog_fd, STDERR_FILENO);
1920 /* create environment */
1926 cgi_env_add(&env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION));
1928 if (!buffer_is_empty(con->server_name)) {
1929 cgi_env_add(&env, CONST_STR_LEN("SERVER_NAME"), CONST_BUF_LEN(con->server_name));
1932 - s = inet_ntop(srv_sock->addr.plain.sa_family,
1933 - srv_sock->addr.plain.sa_family == AF_INET6 ?
1934 + s = inet_ntop(srv_sock->addr.plain.sa_family,
1935 + srv_sock->addr.plain.sa_family == AF_INET6 ?
1936 (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
1937 (const void *) &(srv_sock->addr.ipv4.sin_addr),
1939 @@ -779,10 +775,10 @@
1940 cgi_env_add(&env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1"));
1942 s = get_http_version_name(con->request.http_version);
1945 cgi_env_add(&env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s));
1951 ntohs(srv_sock->addr.plain.sa_family == AF_INET6 ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
1953 @@ -790,10 +786,10 @@
1956 cgi_env_add(&env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf));
1960 - s = inet_ntop(srv_sock->addr.plain.sa_family,
1961 - srv_sock->addr.plain.sa_family == AF_INET6 ?
1962 + s = inet_ntop(srv_sock->addr.plain.sa_family,
1963 + srv_sock->addr.plain.sa_family == AF_INET6 ?
1964 (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
1965 (const void *) &(srv_sock->addr.ipv4.sin_addr),
1967 @@ -811,15 +807,18 @@
1968 cgi_env_add(&env, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200"));
1969 if (!buffer_is_empty(con->uri.query)) {
1970 cgi_env_add(&env, CONST_STR_LEN("QUERY_STRING"), CONST_BUF_LEN(con->uri.query));
1972 + /* set a empty QUERY_STRING */
1973 + cgi_env_add(&env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN(""));
1975 if (!buffer_is_empty(con->request.orig_uri)) {
1976 cgi_env_add(&env, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri));
1983 - s = inet_ntop(con->dst_addr.plain.sa_family,
1984 - con->dst_addr.plain.sa_family == AF_INET6 ?
1985 + s = inet_ntop(con->dst_addr.plain.sa_family,
1986 + con->dst_addr.plain.sa_family == AF_INET6 ?
1987 (const void *) &(con->dst_addr.ipv6.sin6_addr) :
1988 (const void *) &(con->dst_addr.ipv4.sin_addr),
1992 cgi_env_add(&env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s));
1997 ntohs(con->dst_addr.plain.sa_family == AF_INET6 ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
1999 @@ -836,19 +835,19 @@
2002 cgi_env_add(&env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf));
2005 if (!buffer_is_empty(con->authed_user)) {
2006 cgi_env_add(&env, CONST_STR_LEN("REMOTE_USER"),
2007 CONST_BUF_LEN(con->authed_user));
2011 /* request.content_length < SSIZE_MAX, see request.c */
2012 ltostr(buf, con->request.content_length);
2013 cgi_env_add(&env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf));
2014 cgi_env_add(&env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(con->physical.path));
2015 cgi_env_add(&env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
2016 cgi_env_add(&env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root));
2020 if (NULL != (s = getenv("LD_PRELOAD"))) {
2021 cgi_env_add(&env, CONST_STR_LEN("LD_PRELOAD"), s, strlen(s));
2022 @@ -863,24 +862,24 @@
2023 cgi_env_add(&env, CONST_STR_LEN("SYSTEMROOT"), s, strlen(s));
2028 for (n = 0; n < con->request.headers->used; n++) {
2032 ds = (data_string *)con->request.headers->data[n];
2035 if (ds->value->used && ds->key->used) {
2039 buffer_reset(p->tmp_buf);
2042 if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
2043 buffer_copy_string(p->tmp_buf, "HTTP_");
2044 p->tmp_buf->used--; /* strip \0 after HTTP_ */
2048 buffer_prepare_append(p->tmp_buf, ds->key->used + 2);
2051 for (j = 0; j < ds->key->used - 1; j++) {
2053 if (light_isalpha(ds->key->ptr[j])) {
2054 @@ -893,46 +892,46 @@
2055 p->tmp_buf->ptr[p->tmp_buf->used++] = cr;
2057 p->tmp_buf->ptr[p->tmp_buf->used++] = '\0';
2060 cgi_env_add(&env, CONST_BUF_LEN(p->tmp_buf), CONST_BUF_LEN(ds->value));
2065 for (n = 0; n < con->environment->used; n++) {
2069 ds = (data_string *)con->environment->data[n];
2072 if (ds->value->used && ds->key->used) {
2076 buffer_reset(p->tmp_buf);
2079 buffer_prepare_append(p->tmp_buf, ds->key->used + 2);
2082 for (j = 0; j < ds->key->used - 1; j++) {
2083 - p->tmp_buf->ptr[p->tmp_buf->used++] =
2084 - isalpha((unsigned char)ds->key->ptr[j]) ?
2085 + p->tmp_buf->ptr[p->tmp_buf->used++] =
2086 + isalpha((unsigned char)ds->key->ptr[j]) ?
2087 toupper((unsigned char)ds->key->ptr[j]) : '_';
2089 p->tmp_buf->ptr[p->tmp_buf->used++] = '\0';
2092 cgi_env_add(&env, CONST_BUF_LEN(p->tmp_buf), CONST_BUF_LEN(ds->value));
2097 if (env.size == env.used) {
2099 env.ptr = realloc(env.ptr, env.size * sizeof(*env.ptr));
2103 env.ptr[env.used] = NULL;
2108 args = malloc(sizeof(*args) * argc);
2112 if (cgi_handler->used > 1) {
2113 args[i++] = cgi_handler->ptr;
2116 /* search for the last / */
2117 if (NULL != (c = strrchr(con->physical.path->ptr, '/'))) {
2121 /* change to the physical directory */
2122 if (-1 == chdir(con->physical.path->ptr)) {
2123 log_error_write(srv, __FILE__, __LINE__, "ssb", "chdir failed:", strerror(errno), con->physical.path);
2124 @@ -954,12 +953,12 @@
2125 for (i = 3; i < 256; i++) {
2126 if (i != srv->errorlog_fd) close(i);
2131 execve(args[0], args, env.ptr);
2134 log_error_write(srv, __FILE__, __LINE__, "sss", "CGI failed:", strerror(errno), args[0]);
2140 @@ -974,11 +973,11 @@
2142 close(from_cgi_fds[1]);
2143 close(to_cgi_fds[0]);
2146 if (con->request.content_length) {
2147 chunkqueue *cq = con->request_content_queue;
2151 assert(chunkqueue_length(cq) == (off_t)con->request.content_length);
2153 /* there is content to send */
2154 @@ -993,16 +992,16 @@
2155 if (-1 == c->file.fd && /* open the file if not already open */
2156 -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
2157 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
2160 close(from_cgi_fds[0]);
2161 close(to_cgi_fds[1]);
2165 c->file.mmap.length = c->file.length;
2168 if (MAP_FAILED == (c->file.mmap.start = mmap(0, c->file.mmap.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
2169 - log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
2170 + log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
2171 strerror(errno), c->file.name, c->file.fd);
2173 close(from_cgi_fds[0]);
2174 @@ -1012,7 +1011,7 @@
2180 /* chunk_reset() or chunk_free() will cleanup for us */
2183 @@ -1020,7 +1019,7 @@
2186 con->http_status = 507;
2191 con->http_status = 403;
2192 @@ -1033,7 +1032,7 @@
2195 con->http_status = 507;
2200 con->http_status = 403;
2201 @@ -1056,103 +1055,100 @@
2204 close(to_cgi_fds[1]);
2207 /* register PID and wait for them asyncronously */
2209 buffer_reset(con->physical.path);
2212 hctx = cgi_handler_ctx_init();
2215 hctx->remote_conn = con;
2216 hctx->plugin_data = p;
2218 hctx->fd = from_cgi_fds[0];
2222 con->plugin_ctx[p->id] = hctx;
2225 fdevent_register(srv->ev, hctx->fd, cgi_handle_fdevent, hctx);
2226 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
2229 if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
2230 log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
2233 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
2234 fdevent_unregister(srv->ev, hctx->fd);
2237 log_error_write(srv, __FILE__, __LINE__, "sd", "cgi close:", hctx->fd);
2243 cgi_handler_ctx_free(hctx);
2246 con->plugin_ctx[p->id] = NULL;
2266 static int mod_cgi_patch_connection(server *srv, connection *con, plugin_data *p) {
2268 plugin_config *s = p->config_storage[0];
2273 + PATCH_OPTION(cgi);
2275 /* skip the first, the global context */
2276 for (i = 1; i < srv->config_context->used; i++) {
2277 data_config *dc = (data_config *)srv->config_context->data[i];
2278 s = p->config_storage[i];
2281 /* condition didn't match */
2282 if (!config_check_cond(srv, con, dc)) continue;
2286 for (j = 0; j < dc->value->used; j++) {
2287 data_unset *du = dc->value->data[j];
2290 if (buffer_is_equal_string(du->key, CONST_STR_LEN("cgi.assign"))) {
2292 + PATCH_OPTION(cgi);
2302 URIHANDLER_FUNC(cgi_is_handled) {
2304 plugin_data *p = p_d;
2305 buffer *fn = con->physical.path;
2308 if (fn->used == 0) return HANDLER_GO_ON;
2311 mod_cgi_patch_connection(srv, con, p);
2314 s_len = fn->used - 1;
2317 for (k = 0; k < p->conf.cgi->used; k++) {
2318 data_string *ds = (data_string *)p->conf.cgi->data[k];
2319 size_t ct_len = ds->key->used - 1;
2322 if (ds->key->used == 0) continue;
2323 if (s_len < ct_len) continue;
2326 if (0 == strncmp(fn->ptr + s_len - ct_len, ds->key->ptr, ct_len)) {
2327 if (cgi_create_env(srv, con, p, ds->value)) {
2328 con->http_status = 500;
2331 buffer_reset(con->physical.path);
2332 return HANDLER_FINISHED;
2334 @@ -1160,7 +1156,7 @@
2340 return HANDLER_GO_ON;
2343 @@ -1168,11 +1164,11 @@
2344 plugin_data *p = p_d;
2346 /* the trigger handle only cares about lonely PID which we have to wait for */
2350 for (ndx = 0; ndx < p->cgi_pid.used; ndx++) {
2354 switch(waitpid(p->cgi_pid.ptr[ndx], &status, WNOHANG)) {
2356 /* not finished yet */
2357 @@ -1182,7 +1178,7 @@
2360 log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno));
2363 return HANDLER_ERROR;
2366 @@ -1193,16 +1189,16 @@
2368 log_error_write(srv, __FILE__, __LINE__, "s", "cgi died ?");
2372 cgi_pid_del(srv, p, p->cgi_pid.ptr[ndx]);
2373 - /* del modified the buffer structure
2374 + /* del modified the buffer structure
2375 * and copies the last entry to the current one
2376 * -> recheck the current index
2383 return HANDLER_GO_ON;
2386 @@ -1210,15 +1206,15 @@
2388 plugin_data *p = p_d;
2389 handler_ctx *hctx = con->plugin_ctx[p->id];
2392 if (con->mode != p->id) return HANDLER_GO_ON;
2393 if (NULL == hctx) return HANDLER_GO_ON;
2397 log_error_write(srv, __FILE__, __LINE__, "sdd", "subrequest, pid =", hctx, hctx->pid);
2400 if (hctx->pid == 0) return HANDLER_FINISHED;
2403 switch(waitpid(hctx->pid, &status, WNOHANG)) {
2405 /* we only have for events here if we don't have the header yet,
2406 @@ -1228,61 +1224,61 @@
2407 return HANDLER_WAIT_FOR_EVENT;
2409 if (errno == EINTR) return HANDLER_WAIT_FOR_EVENT;
2412 if (errno == ECHILD && con->file_started == 0) {
2414 - * second round but still not response
2415 + * second round but still not response
2417 - return HANDLER_WAIT_FOR_EVENT;
2418 + return HANDLER_WAIT_FOR_EVENT;
2422 log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno));
2424 con->http_status = 500;
2430 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
2431 fdevent_unregister(srv->ev, hctx->fd);
2434 if (close(hctx->fd)) {
2435 log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno));
2439 cgi_handler_ctx_free(hctx);
2442 con->plugin_ctx[p->id] = NULL;
2445 return HANDLER_FINISHED;
2447 - /* cgi process exited cleanly
2449 - * check if we already got the response
2450 + /* cgi process exited cleanly
2452 + * check if we already got the response
2456 if (!con->file_started) return HANDLER_WAIT_FOR_EVENT;
2459 if (WIFEXITED(status)) {
2462 log_error_write(srv, __FILE__, __LINE__, "s", "cgi died ?");
2466 con->http_status = 500;
2475 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
2476 fdevent_unregister(srv->ev, hctx->fd);
2479 if (close(hctx->fd)) {
2480 log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno));
2484 cgi_handler_ctx_free(hctx);
2487 con->plugin_ctx[p->id] = NULL;
2488 return HANDLER_FINISHED;
2490 @@ -1306,8 +1302,8 @@
2491 p->init = mod_cgi_init;
2492 p->cleanup = mod_cgi_free;
2493 p->set_defaults = mod_fastcgi_set_defaults;
2502 Property changes on: src/mod_cgi.c
2503 ___________________________________________________________________
2507 Index: src/network_write.c
2508 ===================================================================
2509 --- src/network_write.c (.../tags/lighttpd-1.4.11) (revision 1159)
2510 +++ src/network_write.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
2512 #include <sys/types.h>
2513 #include <sys/stat.h>
2514 -#include <sys/time.h>
2518 -#include <unistd.h>
2521 +#include <assert.h>
2523 #include "network.h"
2524 #include "fdevent.h"
2526 #include "stat_cache.h"
2528 #include "sys-socket.h"
2529 +#include "sys-files.h"
2531 #include "network_backends.h"
2535 #ifdef HAVE_SYS_FILIO_H
2536 # include <sys/filio.h>
2539 #include <sys/resource.h>
2542 -int network_write_chunkqueue_write(server *srv, connection *con, int fd, chunkqueue *cq) {
2544 +* fill the chunkqueue will all the data that we can get
2546 +* this might be optimized into a readv() which uses the chunks
2549 +NETWORK_BACKEND_READ(read) {
2554 + /* check how much we have to read */
2555 + if (ioctl(fd, FIONREAD, &toread)) {
2556 + log_error_write(srv, __FILE__, __LINE__, "sd",
2559 + return NETWORK_STATUS_FATAL_ERROR;
2562 + if (toread == 0) return NETWORK_STATUS_WAIT_FOR_EVENT;
2565 + * our chunk queue is quiet large already
2567 + * let's buffer it to disk
2570 + b = chunkqueue_get_append_buffer(cq);
2572 + buffer_prepare_copy(b, toread);
2574 + if (-1 == (r = read(fd, b->ptr, toread))) {
2575 + log_error_write(srv, __FILE__, __LINE__, "sds",
2576 + "unexpected end-of-file (perhaps the proxy process died):",
2577 + fd, strerror(errno));
2578 + return NETWORK_STATUS_FATAL_ERROR;
2581 + /* this should be catched by the b > 0 above */
2584 + b->ptr[b->used - 1] = '\0';
2586 + return NETWORK_STATUS_SUCCESS;
2589 +NETWORK_BACKEND_WRITE(write) {
2591 size_t chunks_written = 0;
2594 for(c = cq->first; c; c = c->next) {
2595 int chunk_finished = 0;
2605 if (c->mem->used == 0) {
2611 offset = c->mem->ptr + c->offset;
2612 toSend = c->mem->used - 1 - c->offset;
2614 - if ((r = send(fd, offset, toSend, 0)) < 0) {
2615 - log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed: ", strerror(errno), fd);
2621 if ((r = write(fd, offset, toSend)) < 0) {
2622 log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed: ", strerror(errno), fd);
2626 + return NETWORK_STATUS_FATAL_ERROR;
2635 if (c->offset == (off_t)c->mem->used - 1) {
2643 @@ -76,93 +118,89 @@
2645 stat_cache_entry *sce = NULL;
2649 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
2650 log_error_write(srv, __FILE__, __LINE__, "sb",
2651 strerror(errno), c->file.name);
2653 + return NETWORK_STATUS_FATAL_ERROR;
2657 offset = c->file.start + c->offset;
2658 toSend = c->file.length - c->offset;
2661 if (offset > sce->st.st_size) {
2662 log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
2666 + return NETWORK_STATUS_FATAL_ERROR;
2669 if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
2670 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
2674 + return NETWORK_STATUS_FATAL_ERROR;
2678 #if defined USE_MMAP
2679 if (MAP_FAILED == (p = mmap(0, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
2680 log_error_write(srv, __FILE__, __LINE__, "ss", "mmap failed: ", strerror(errno));
2686 + return NETWORK_STATUS_FATAL_ERROR;
2690 if ((r = write(fd, p + offset, toSend)) <= 0) {
2691 log_error_write(srv, __FILE__, __LINE__, "ss", "write failed: ", strerror(errno));
2692 munmap(p, sce->st.st_size);
2694 + return NETWORK_STATUS_FATAL_ERROR;
2698 munmap(p, sce->st.st_size);
2700 buffer_prepare_copy(srv->tmp_buf, toSend);
2703 lseek(ifd, offset, SEEK_SET);
2704 if (-1 == (toSend = read(ifd, srv->tmp_buf->ptr, toSend))) {
2705 log_error_write(srv, __FILE__, __LINE__, "ss", "read: ", strerror(errno));
2710 + return NETWORK_STATUS_FATAL_ERROR;
2714 if (-1 == (r = send(fd, srv->tmp_buf->ptr, toSend, 0))) {
2715 log_error_write(srv, __FILE__, __LINE__, "ss", "write: ", strerror(errno));
2719 + return NETWORK_STATUS_FATAL_ERROR;
2726 if (c->offset == c->file.length) {
2736 log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
2740 + return NETWORK_STATUS_FATAL_ERROR;
2744 if (!chunk_finished) {
2745 /* not finished yet */
2755 - return chunks_written;
2756 + return NETWORK_STATUS_SUCCESS;
2760 -network_write_init(void) {
2761 - p->write = network_write_write_chunkset;
2765 Property changes on: src/network_write.c
2766 ___________________________________________________________________
2770 Index: src/joblist.c
2771 ===================================================================
2772 --- src/joblist.c (.../tags/lighttpd-1.4.11) (revision 1159)
2773 +++ src/joblist.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
2776 int joblist_append(server *srv, connection *con) {
2777 if (con->in_joblist) return 0;
2780 if (srv->joblist->size == 0) {
2781 srv->joblist->size = 16;
2782 srv->joblist->ptr = malloc(sizeof(*srv->joblist->ptr) * srv->joblist->size);
2784 srv->joblist->size += 16;
2785 srv->joblist->ptr = realloc(srv->joblist->ptr, sizeof(*srv->joblist->ptr) * srv->joblist->size);
2789 srv->joblist->ptr[srv->joblist->used++] = con;
2795 void joblist_free(server *srv, connections *joblist) {
2803 connection *fdwaitqueue_unshift(server *srv, connections *fdwaitqueue) {
2810 if (fdwaitqueue->used == 0) return NULL;
2813 con = fdwaitqueue->ptr[0];
2816 memmove(fdwaitqueue->ptr, &(fdwaitqueue->ptr[1]), --fdwaitqueue->used * sizeof(*(fdwaitqueue->ptr)));
2823 srv->fdwaitqueue->size += 16;
2824 srv->fdwaitqueue->ptr = realloc(srv->fdwaitqueue->ptr, sizeof(*(srv->fdwaitqueue->ptr)) * srv->fdwaitqueue->size);
2828 srv->fdwaitqueue->ptr[srv->fdwaitqueue->used++] = con;
2835 Property changes on: src/joblist.c
2836 ___________________________________________________________________
2840 Index: src/mod_cml.c
2841 ===================================================================
2842 --- src/mod_cml.c (.../tags/lighttpd-1.4.11) (revision 1159)
2843 +++ src/mod_cml.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
2848 -#include <unistd.h>
2853 /* init the plugin data */
2854 INIT_FUNC(mod_cml_init) {
2858 p = calloc(1, sizeof(*p));
2861 p->basedir = buffer_init();
2862 p->baseurl = buffer_init();
2863 p->trigger_handler = buffer_init();
2869 /* detroy the plugin data */
2870 FREE_FUNC(mod_cml_free) {
2871 plugin_data *p = p_d;
2876 if (!p) return HANDLER_GO_ON;
2879 if (p->config_storage) {
2881 for (i = 0; i < srv->config_context->used; i++) {
2882 plugin_config *s = p->config_storage[i];
2885 buffer_free(s->ext);
2888 buffer_free(s->mc_namespace);
2889 buffer_free(s->power_magnet);
2890 array_free(s->mc_hosts);
2893 #if defined(HAVE_MEMCACHE_H)
2894 if (s->mc) mc_free(s->mc);
2900 free(p->config_storage);
2904 buffer_free(p->trigger_handler);
2905 buffer_free(p->basedir);
2906 buffer_free(p->baseurl);
2912 return HANDLER_GO_ON;
2916 SETDEFAULTS_FUNC(mod_cml_set_defaults) {
2917 plugin_data *p = p_d;
2920 - config_values_t cv[] = {
2922 + config_values_t cv[] = {
2923 { "cml.extension", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
2924 { "cml.memcache-hosts", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
2925 { "cml.memcache-namespace", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
2926 { "cml.power-magnet", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
2927 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
2931 if (!p) return HANDLER_ERROR;
2934 p->config_storage = malloc(srv->config_context->used * sizeof(specific_config *));
2937 for (i = 0; i < srv->config_context->used; i++) {
2941 s = malloc(sizeof(plugin_config));
2942 s->ext = buffer_init();
2943 s->mc_hosts = array_init();
2945 #if defined(HAVE_MEMCACHE_H)
2950 cv[0].destination = s->ext;
2951 cv[1].destination = s->mc_hosts;
2952 cv[2].destination = s->mc_namespace;
2953 cv[3].destination = s->power_magnet;
2956 p->config_storage[i] = s;
2959 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
2960 return HANDLER_ERROR;
2964 if (s->mc_hosts->used) {
2965 #if defined(HAVE_MEMCACHE_H)
2970 for (k = 0; k < s->mc_hosts->used; k++) {
2971 data_string *ds = (data_string *)s->mc_hosts->data[k];
2974 if (0 != mc_server_add4(s->mc, ds->value->ptr)) {
2975 - log_error_write(srv, __FILE__, __LINE__, "sb",
2976 - "connection to host failed:",
2977 + log_error_write(srv, __FILE__, __LINE__, "sb",
2978 + "connection to host failed:",
2982 return HANDLER_ERROR;
2986 - log_error_write(srv, __FILE__, __LINE__, "s",
2987 + log_error_write(srv, __FILE__, __LINE__, "s",
2988 "memcache support is not compiled in but cml.memcache-hosts is set, aborting");
2989 return HANDLER_ERROR;
2995 return HANDLER_GO_ON;
3000 static int mod_cml_patch_connection(server *srv, connection *con, plugin_data *p) {
3002 plugin_config *s = p->config_storage[0];
3006 + PATCH_OPTION(ext);
3007 #if defined(HAVE_MEMCACHE_H)
3011 - PATCH(mc_namespace);
3012 - PATCH(power_magnet);
3014 + PATCH_OPTION(mc_namespace);
3015 + PATCH_OPTION(power_magnet);
3017 /* skip the first, the global context */
3018 for (i = 1; i < srv->config_context->used; i++) {
3019 data_config *dc = (data_config *)srv->config_context->data[i];
3020 s = p->config_storage[i];
3023 /* condition didn't match */
3024 if (!config_check_cond(srv, con, dc)) continue;
3028 for (j = 0; j < dc->value->used; j++) {
3029 data_unset *du = dc->value->data[j];
3032 if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.extension"))) {
3034 + PATCH_OPTION(ext);
3035 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.memcache-hosts"))) {
3036 #if defined(HAVE_MEMCACHE_H)
3040 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.memcache-namespace"))) {
3041 - PATCH(mc_namespace);
3042 + PATCH_OPTION(mc_namespace);
3043 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.power-magnet"))) {
3044 - PATCH(power_magnet);
3045 + PATCH_OPTION(power_magnet);
3055 int cache_call_lua(server *srv, connection *con, plugin_data *p, buffer *cml_file) {
3057 @@ -187,57 +183,57 @@
3059 buffer_copy_string_buffer(b, con->uri.path);
3060 for (c = b->ptr + b->used - 1; c > b->ptr && *c != '/'; c--);
3064 b->used = c - b->ptr + 2;
3070 buffer_copy_string_buffer(b, con->physical.path);
3071 for (c = b->ptr + b->used - 1; c > b->ptr && *c != '/'; c--);
3075 b->used = c - b->ptr + 2;
3081 /* prepare variables
3087 return cache_parse_lua(srv, con, p, cml_file);
3092 URIHANDLER_FUNC(mod_cml_power_magnet) {
3093 plugin_data *p = p_d;
3096 mod_cml_patch_connection(srv, con, p);
3099 buffer_reset(p->basedir);
3100 buffer_reset(p->baseurl);
3101 buffer_reset(p->trigger_handler);
3103 if (buffer_is_empty(p->conf.power_magnet)) return HANDLER_GO_ON;
3109 * cml.power-magnet = server.docroot + "/rewrite.cml"
3111 * is called on EACH request, take the original REQUEST_URI and modifies the
3112 - * request header as neccesary.
3113 + * request header as neccesary.
3116 * if file_exists("/maintainance.html") {
3117 * output_include = ( "/maintainance.html" )
3118 - * return CACHE_HIT
3119 + * return CACHE_HIT
3122 * as we only want to rewrite HTML like requests we should cover it in a conditional
3127 switch(cache_call_lua(srv, con, p, p->conf.power_magnet)) {
3128 @@ -266,20 +262,20 @@
3130 URIHANDLER_FUNC(mod_cml_is_handled) {
3131 plugin_data *p = p_d;
3134 if (buffer_is_empty(con->physical.path)) return HANDLER_ERROR;
3137 mod_cml_patch_connection(srv, con, p);
3140 buffer_reset(p->basedir);
3141 buffer_reset(p->baseurl);
3142 buffer_reset(p->trigger_handler);
3144 if (buffer_is_empty(p->conf.ext)) return HANDLER_GO_ON;
3147 if (!buffer_is_equal_right_len(con->physical.path, p->conf.ext, p->conf.ext->used - 1)) {
3148 return HANDLER_GO_ON;
3152 switch(cache_call_lua(srv, con, p, con->physical.path)) {
3154 @@ -311,15 +307,15 @@
3155 int mod_cml_plugin_init(plugin *p) {
3156 p->version = LIGHTTPD_VERSION_ID;
3157 p->name = buffer_init_string("cache");
3160 p->init = mod_cml_init;
3161 p->cleanup = mod_cml_free;
3162 p->set_defaults = mod_cml_set_defaults;
3165 p->handle_subrequest_start = mod_cml_is_handled;
3166 p->handle_physical = mod_cml_power_magnet;
3175 Property changes on: src/mod_cml.c
3176 ___________________________________________________________________
3181 Property changes on: src/joblist.h
3182 ___________________________________________________________________
3186 Index: src/mod_secure_download.c
3187 ===================================================================
3188 --- src/mod_secure_download.c (.../tags/lighttpd-1.4.11) (revision 1159)
3189 +++ src/mod_secure_download.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
3205 unsigned short timeout;
3215 plugin_config **config_storage;
3217 - plugin_config conf;
3219 + plugin_config conf;
3222 /* init the plugin data */
3223 INIT_FUNC(mod_secdownload_init) {
3227 p = calloc(1, sizeof(*p));
3230 p->md5 = buffer_init();
3237 FREE_FUNC(mod_secdownload_free) {
3238 plugin_data *p = p_d;
3242 if (!p) return HANDLER_GO_ON;
3245 if (p->config_storage) {
3247 for (i = 0; i < srv->config_context->used; i++) {
3248 plugin_config *s = p->config_storage[i];
3251 buffer_free(s->secret);
3252 buffer_free(s->doc_root);
3253 buffer_free(s->uri_prefix);
3258 free(p->config_storage);
3262 buffer_free(p->md5);
3268 return HANDLER_GO_ON;
3271 @@ -94,108 +94,104 @@
3272 SETDEFAULTS_FUNC(mod_secdownload_set_defaults) {
3273 plugin_data *p = p_d;
3276 - config_values_t cv[] = {
3278 + config_values_t cv[] = {
3279 { "secdownload.secret", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
3280 { "secdownload.document-root", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
3281 { "secdownload.uri-prefix", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
3282 { "secdownload.timeout", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
3283 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
3287 if (!p) return HANDLER_ERROR;
3290 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
3293 for (i = 0; i < srv->config_context->used; i++) {
3297 s = calloc(1, sizeof(plugin_config));
3298 s->secret = buffer_init();
3299 s->doc_root = buffer_init();
3300 s->uri_prefix = buffer_init();
3304 cv[0].destination = s->secret;
3305 cv[1].destination = s->doc_root;
3306 cv[2].destination = s->uri_prefix;
3307 cv[3].destination = &(s->timeout);
3310 p->config_storage[i] = s;
3313 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
3314 return HANDLER_ERROR;
3319 return HANDLER_GO_ON;
3323 * checks if the supplied string is a MD5 string
3326 * @param str a possible MD5 string
3327 * @return if the supplied string is a valid MD5 string 1 is returned otherwise 0
3330 int is_hex_len(const char *str, size_t len) {
3334 if (NULL == str) return 0;
3337 for (i = 0; i < len && *str; i++, str++) {
3338 /* illegal characters */
3339 if (!((*str >= '0' && *str <= '9') ||
3340 (*str >= 'a' && *str <= 'f') ||
3341 - (*str >= 'A' && *str <= 'F'))
3342 + (*str >= 'A' && *str <= 'F'))
3354 static int mod_secdownload_patch_connection(server *srv, connection *con, plugin_data *p) {
3356 plugin_config *s = p->config_storage[0];
3360 - PATCH(uri_prefix);
3364 + PATCH_OPTION(secret);
3365 + PATCH_OPTION(doc_root);
3366 + PATCH_OPTION(uri_prefix);
3367 + PATCH_OPTION(timeout);
3369 /* skip the first, the global context */
3370 for (i = 1; i < srv->config_context->used; i++) {
3371 data_config *dc = (data_config *)srv->config_context->data[i];
3372 s = p->config_storage[i];
3375 /* condition didn't match */
3376 if (!config_check_cond(srv, con, dc)) continue;
3380 for (j = 0; j < dc->value->used; j++) {
3381 data_unset *du = dc->value->data[j];
3384 if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.secret"))) {
3386 + PATCH_OPTION(secret);
3387 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.document-root"))) {
3389 + PATCH_OPTION(doc_root);
3390 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.uri-prefix"))) {
3391 - PATCH(uri_prefix);
3392 + PATCH_OPTION(uri_prefix);
3393 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.timeout"))) {
3395 + PATCH_OPTION(timeout);
3406 URIHANDLER_FUNC(mod_secdownload_uri_handler) {
3407 plugin_data *p = p_d;
3409 @@ -203,88 +199,88 @@
3410 const char *rel_uri, *ts_str, *md5_str;
3415 if (con->uri.path->used == 0) return HANDLER_GO_ON;
3418 mod_secdownload_patch_connection(srv, con, p);
3420 if (buffer_is_empty(p->conf.uri_prefix)) return HANDLER_GO_ON;
3423 if (buffer_is_empty(p->conf.secret)) {
3424 log_error_write(srv, __FILE__, __LINE__, "s",
3425 "secdownload.secret has to be set");
3426 return HANDLER_ERROR;
3430 if (buffer_is_empty(p->conf.doc_root)) {
3431 log_error_write(srv, __FILE__, __LINE__, "s",
3432 "secdownload.document-root has to be set");
3433 return HANDLER_ERROR;
3439 * /<uri-prefix>[a-f0-9]{32}/[a-f0-9]{8}/<rel-path>
3443 if (0 != strncmp(con->uri.path->ptr, p->conf.uri_prefix->ptr, p->conf.uri_prefix->used - 1)) return HANDLER_GO_ON;
3446 md5_str = con->uri.path->ptr + p->conf.uri_prefix->used - 1;
3449 if (!is_hex_len(md5_str, 32)) return HANDLER_GO_ON;
3450 if (*(md5_str + 32) != '/') return HANDLER_GO_ON;
3453 ts_str = md5_str + 32 + 1;
3456 if (!is_hex_len(ts_str, 8)) return HANDLER_GO_ON;
3457 if (*(ts_str + 8) != '/') return HANDLER_GO_ON;
3460 for (i = 0; i < 8; i++) {
3461 ts = (ts << 4) + hex2int(*(ts_str + i));
3466 - if (srv->cur_ts - ts > p->conf.timeout ||
3467 + if (srv->cur_ts - ts > p->conf.timeout ||
3468 srv->cur_ts - ts < -p->conf.timeout) {
3469 con->http_status = 408;
3472 return HANDLER_FINISHED;
3476 rel_uri = ts_str + 8;
3483 * <secret><rel-path><timestamp-hex>
3487 buffer_copy_string_buffer(p->md5, p->conf.secret);
3488 buffer_append_string(p->md5, rel_uri);
3489 buffer_append_string_len(p->md5, ts_str, 8);
3493 MD5_Update(&Md5Ctx, (unsigned char *)p->md5->ptr, p->md5->used - 1);
3494 MD5_Final(HA1, &Md5Ctx);
3497 buffer_copy_string_hex(p->md5, (char *)HA1, 16);
3500 if (0 != strncmp(md5_str, p->md5->ptr, 32)) {
3501 con->http_status = 403;
3503 - log_error_write(srv, __FILE__, __LINE__, "sss",
3505 + log_error_write(srv, __FILE__, __LINE__, "sss",
3507 md5_str, p->md5->ptr);
3510 return HANDLER_FINISHED;
3514 /* starting with the last / we should have relative-path to the docroot
3518 buffer_copy_string_buffer(con->physical.doc_root, p->conf.doc_root);
3519 buffer_copy_string(con->physical.rel_path, rel_uri);
3520 buffer_copy_string_buffer(con->physical.path, con->physical.doc_root);
3521 buffer_append_string_buffer(con->physical.path, con->physical.rel_path);
3524 return HANDLER_GO_ON;
3527 @@ -293,13 +289,13 @@
3528 int mod_secdownload_plugin_init(plugin *p) {
3529 p->version = LIGHTTPD_VERSION_ID;
3530 p->name = buffer_init_string("secdownload");
3533 p->init = mod_secdownload_init;
3534 p->handle_physical = mod_secdownload_uri_handler;
3535 p->set_defaults = mod_secdownload_set_defaults;
3536 p->cleanup = mod_secdownload_free;
3545 Property changes on: src/mod_secure_download.c
3546 ___________________________________________________________________
3550 Index: src/connections-glue.c
3551 ===================================================================
3552 --- src/connections-glue.c (.../tags/lighttpd-1.4.11) (revision 1159)
3553 +++ src/connections-glue.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
3555 case CON_STATE_REQUEST_END: return "req-end";
3556 case CON_STATE_RESPONSE_START: return "resp-start";
3557 case CON_STATE_RESPONSE_END: return "resp-end";
3558 - default: return "(unknown)";
3559 + default: return "(unknown)";
3564 case CON_STATE_REQUEST_END: return "Q";
3565 case CON_STATE_RESPONSE_START: return "s";
3566 case CON_STATE_RESPONSE_END: return "S";
3567 - default: return "x";
3568 + default: return "x";
3572 int connection_set_state(server *srv, connection *con, connection_state_t state) {
3583 Property changes on: src/connections-glue.c
3584 ___________________________________________________________________
3589 ===================================================================
3590 --- src/array.c (.../tags/lighttpd-1.4.11) (revision 1159)
3591 +++ src/array.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
3594 array *array_init(void) {
3598 a = calloc(1, sizeof(*a));
3602 a->next_power_of_2 = 1;
3609 void array_free(array *a) {
3614 if (!a->is_weakref) {
3615 for (i = 0; i < a->size; i++) {
3616 if (a->data[i]) a->data[i]->free(a->data[i]);
3621 if (a->data) free(a->data);
3622 if (a->sorted) free(a->sorted);
3628 void array_reset(array *a) {
3633 if (!a->is_weakref) {
3634 for (i = 0; i < a->used; i++) {
3635 a->data[i]->reset(a->data[i]);
3644 static int array_get_index(array *a, const char *key, size_t keylen, int *rndx) {
3649 if (key == NULL) return -1;
3652 /* try to find the string */
3653 for (i = pos = a->next_power_of_2 / 2; ; i >>= 1) {
3659 } else if (pos >= (int)a->used) {
3662 cmp = buffer_caseless_compare(key, keylen, a->data[a->sorted[pos]]->key->ptr, a->data[a->sorted[pos]]->key->used);
3667 ndx = a->sorted[pos];
3668 @@ -110,46 +110,46 @@
3674 if (rndx) *rndx = pos;
3680 data_unset *array_get_element(array *a, const char *key) {
3684 if (-1 != (ndx = array_get_index(a, key, strlen(key) + 1, NULL))) {
3685 /* found, leave here */
3688 return a->data[ndx];
3696 data_unset *array_get_unused_element(array *a, data_type_t t) {
3697 data_unset *ds = NULL;
3702 if (a->size == 0) return NULL;
3705 if (a->used == a->size) return NULL;
3707 if (a->data[a->used]) {
3708 ds = a->data[a->used];
3711 a->data[a->used] = NULL;
3718 /* replace or insert data, return the old one with the same key */
3719 data_unset *array_replace(array *a, data_unset *du) {
3723 if (-1 == (ndx = array_get_index(a, du->key->ptr, du->key->used, NULL))) {
3724 array_insert_unique(a, du);
3726 @@ -164,13 +164,13 @@
3731 - /* generate unique index if neccesary */
3733 + /* generate unique index if necessary */
3734 if (str->key->used == 0 || str->is_index_key) {
3735 buffer_copy_long(str->key, a->unique_ndx++);
3736 str->is_index_key = 1;
3740 /* try to find the string */
3741 if (-1 != (ndx = array_get_index(a, str->key->ptr, str->key->used, &pos))) {
3742 /* found, leave here */
3743 @@ -181,14 +181,14 @@
3752 if (a->used+1 > INT_MAX) {
3753 /* we can't handle more then INT_MAX entries: see array_get_index() */
3760 a->data = malloc(sizeof(*a->data) * a->size);
3761 @@ -204,27 +204,27 @@
3763 for (j = a->used; j < a->size; j++) a->data[j] = NULL;
3767 ndx = (int) a->used;
3770 a->data[a->used++] = str;
3776 buffer_caseless_compare(str->key->ptr, str->key->used, a->data[a->sorted[pos]]->key->ptr, a->data[a->sorted[pos]]->key->used) > 0)) {
3780 - /* move everything on step to the right */
3783 + /* move everything one step to the right */
3785 memmove(a->sorted + (pos + 1), a->sorted + (pos), (ndx - pos) * sizeof(*a->sorted));
3790 a->sorted[pos] = ndx;
3793 if (a->next_power_of_2 == (size_t)ndx) a->next_power_of_2 <<= 1;
3810 array_print_indent(depth);
3811 fprintf(stderr, ")");
3817 @@ -323,47 +323,47 @@
3829 ds = data_string_init();
3830 buffer_copy_string(ds->key, "abc");
3831 buffer_copy_string(ds->value, "alfrag");
3834 array_insert_unique(a, (data_unset *)ds);
3837 ds = data_string_init();
3838 buffer_copy_string(ds->key, "abc");
3839 buffer_copy_string(ds->value, "hameplman");
3842 array_insert_unique(a, (data_unset *)ds);
3845 ds = data_string_init();
3846 buffer_copy_string(ds->key, "123");
3847 buffer_copy_string(ds->value, "alfrag");
3850 array_insert_unique(a, (data_unset *)ds);
3853 dc = data_count_init();
3854 buffer_copy_string(dc->key, "def");
3857 array_insert_unique(a, (data_unset *)dc);
3860 dc = data_count_init();
3861 buffer_copy_string(dc->key, "def");
3864 array_insert_unique(a, (data_unset *)dc);
3873 fprintf(stderr, "%d\n",
3874 buffer_caseless_compare(CONST_STR_LEN("Content-Type"), CONST_STR_LEN("Content-type")));
3881 Property changes on: src/array.c
3882 ___________________________________________________________________
3886 Index: src/mod_cml.h
3887 ===================================================================
3888 --- src/mod_cml.h (.../tags/lighttpd-1.4.11) (revision 1159)
3889 +++ src/mod_cml.h (.../branches/lighttpd-merge-1.4.x) (revision 1159)
3897 buffer *mc_namespace;
3898 -#if defined(HAVE_MEMCACHE_H)
3899 +#if defined(HAVE_MEMCACHE_H)
3900 struct memcache *mc;
3902 buffer *power_magnet;
3913 buffer *trigger_handler;
3916 plugin_config **config_storage;
3918 - plugin_config conf;
3920 + plugin_config conf;
3923 int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn);
3925 Property changes on: src/mod_cml.h
3926 ___________________________________________________________________
3931 ===================================================================
3932 --- src/base.h (.../tags/lighttpd-1.4.11) (revision 1159)
3933 +++ src/base.h (.../branches/lighttpd-merge-1.4.x) (revision 1159)
3937 #include <sys/types.h>
3938 -#include <sys/time.h>
3939 #include <sys/stat.h>
3941 #ifdef HAVE_CONFIG_H
3943 #include "sys-socket.h"
3944 #include "splaytree.h"
3947 #if defined HAVE_LIBSSL && defined HAVE_OPENSSL_SSL_H
3948 # define USE_OPENSSL
3949 -# include <openssl/ssl.h>
3950 +# include <openssl/ssl.h>
3958 -#ifndef O_LARGEFILE
3959 -# define O_LARGEFILE 0
3964 # define SIZE_MAX SIZE_T_MAX
3967 /* solaris and NetBSD 1.3.x again */
3968 #if (!defined(HAVE_STDINT_H)) && (!defined(HAVE_INTTYPES_H)) && (!defined(uint32_t))
3969 -# define uint32_t u_int32_t
3970 +/* # define uint32_t u_int32_t */
3971 +typedef unsigned __int32 uint32_t;
3977 #include "settings.h"
3979 -typedef enum { T_CONFIG_UNSET,
3985 +typedef enum { T_CONFIG_UNSET,
3992 } config_values_type_t;
3994 -typedef enum { T_CONFIG_SCOPE_UNSET,
3995 - T_CONFIG_SCOPE_SERVER,
3996 +typedef enum { T_CONFIG_SCOPE_UNSET,
3997 + T_CONFIG_SCOPE_SERVER,
3998 T_CONFIG_SCOPE_CONNECTION
3999 } config_scope_type_t;
4006 config_values_type_t type;
4007 config_scope_type_t scope;
4009 @@ -142,40 +137,40 @@
4010 /* the request-line */
4018 http_method_t http_method;
4019 http_version_t http_version;
4022 buffer *request_line;
4025 /* strings to the header */
4026 buffer *http_host; /* not alloced */
4027 const char *http_range;
4028 const char *http_content_type;
4029 const char *http_if_modified_since;
4030 const char *http_if_none_match;
4037 size_t content_length; /* returned by strtoul() */
4040 /* internal representation */
4041 int accept_encoding;
4049 off_t content_length;
4050 - int keep_alive; /* used by the subrequests in proxy, cgi and fcgi to say the subrequest was keep-alive or not */
4052 + int keep_alive; /* used by the subrequests in proxy, cgi and fcgi to say whether the subrequest was keep-alive or not */
4059 HTTP_TRANSFER_ENCODING_IDENTITY, HTTP_TRANSFER_ENCODING_CHUNKED
4060 } transfer_encoding;
4062 @@ -191,21 +186,21 @@
4065 buffer *basedir; /* path = "(basedir)(.*)" */
4068 buffer *doc_root; /* path = doc_root + rel_path */
4093 - splay_tree *files; /* the nodes of the tree are stat_cache_entry's */
4095 + splay_tree *files; /* the nodes of the tree are stat_cache_entries */
4097 buffer *dir_name; /* for building the dirname from the filename */
4099 splay_tree *dirs; /* the nodes of the tree are fam_dir_entry */
4106 /* virtual-servers */
4107 buffer *document_root;
4108 buffer *server_name;
4111 buffer *dirlist_encoding;
4112 buffer *errorfile_prefix;
4115 unsigned short max_keep_alive_requests;
4116 unsigned short max_keep_alive_idle;
4117 unsigned short max_read_idle;
4118 @@ -244,16 +239,17 @@
4119 unsigned short use_xattr;
4120 unsigned short follow_symlink;
4121 unsigned short range_requests;
4127 unsigned short log_file_not_found;
4128 unsigned short log_request_header;
4129 unsigned short log_request_handling;
4130 unsigned short log_response_header;
4131 unsigned short log_condition_handling;
4134 + unsigned short log_condition_cache_handling;
4138 buffer *ssl_pemfile;
4139 buffer *ssl_ca_file;
4140 @@ -268,22 +264,22 @@
4142 unsigned short global_kbytes_per_second; /* */
4144 - off_t global_bytes_per_second_cnt;
4145 + off_t global_bytes_per_second_cnt;
4146 /* server-wide traffic-shaper
4149 * each context has the counter which is inited once
4150 - * a second by the global_kbytes_per_second config-var
4151 + * per second by the global_kbytes_per_second config-var
4153 * as soon as global_kbytes_per_second gets below 0
4154 * the connected conns are "offline" a little bit
4157 - * we somehow have to loose our "we are writable" signal
4158 + * we somehow have to lose our "we are writable" signal
4163 off_t *global_bytes_per_second_cnt_ptr; /* */
4169 @@ -291,18 +287,18 @@
4171 /* the order of the items should be the same as they are processed
4172 * read before write as we use this later */
4174 - CON_STATE_CONNECT,
4175 - CON_STATE_REQUEST_START,
4177 - CON_STATE_REQUEST_END,
4178 - CON_STATE_READ_POST,
4179 - CON_STATE_HANDLE_REQUEST,
4180 - CON_STATE_RESPONSE_START,
4182 - CON_STATE_RESPONSE_END,
4186 + CON_STATE_CONNECT,
4187 + CON_STATE_REQUEST_START,
4189 + CON_STATE_REQUEST_END,
4190 + CON_STATE_READ_POST,
4191 + CON_STATE_HANDLE_REQUEST,
4192 + CON_STATE_RESPONSE_START,
4194 + CON_STATE_RESPONSE_END,
4197 } connection_state_t;
4199 typedef enum { COND_RESULT_UNSET, COND_RESULT_FALSE, COND_RESULT_TRUE } cond_result_t;
4200 @@ -315,88 +311,88 @@
4203 connection_state_t state;
4207 time_t read_idle_ts;
4208 time_t close_timeout_ts;
4209 time_t write_request_ts;
4212 time_t connection_start;
4213 time_t request_start;
4216 struct timeval start_tv;
4219 size_t request_count; /* number of requests handled in this connection */
4220 size_t loops_per_request; /* to catch endless loops in a single request
4223 * used by mod_rewrite, mod_fastcgi, ... and others
4224 * this is self-protection
4228 int fd; /* the FD for this connection */
4229 int fde_ndx; /* index for the fdevent-handler */
4230 int ndx; /* reverse mapping to server->connection[ndx] */
4237 - int keep_alive; /* only request.c can enable it, all other just disable */
4240 + int keep_alive; /* only request.c can enable it, all others just disable */
4246 chunkqueue *write_queue; /* a large queue for low-level write ( HTTP response ) [ file, mem ] */
4247 chunkqueue *read_queue; /* a small queue for low-level read ( HTTP request ) [ mem ] */
4248 chunkqueue *request_content_queue; /* takes request-content into tempfile if necessary [ tempfile, mem ]*/
4251 int traffic_limit_reached;
4254 off_t bytes_written; /* used by mod_accesslog, mod_rrd */
4255 off_t bytes_written_cur_second; /* used by mod_accesslog, mod_rrd */
4256 off_t bytes_read; /* used by mod_accesslog, mod_rrd */
4264 buffer *dst_addr_buf;
4267 buffer *parse_request;
4268 unsigned int parsed_response; /* bitfield which contains the important header-fields of the parsed response header */
4273 - physical physical;
4274 + physical physical;
4281 buffer *authed_user;
4282 array *environment; /* used to pass lighttpd internal stuff to the FastCGI/CGI apps, setenv does that */
4292 connection_type mode;
4295 void **plugin_ctx; /* plugin connection specific config */
4298 specific_config conf; /* global connection specific config */
4299 cond_cache_t *cond_cache;
4302 buffer *server_name;
4306 buffer *error_handler;
4307 int error_handler_saved_status;
4308 int in_error_handler;
4311 void *srv_socket; /* reference to the server-socket (typecast to server_socket) */
4317 @@ -439,39 +435,48 @@
4322 + NETWORK_STATUS_UNSET,
4323 + NETWORK_STATUS_SUCCESS,
4324 + NETWORK_STATUS_FATAL_ERROR,
4325 + NETWORK_STATUS_CONNECTION_CLOSE,
4326 + NETWORK_STATUS_WAIT_FOR_EVENT,
4327 + NETWORK_STATUS_INTERRUPTED
4328 +} network_status_t;
4331 unsigned short port;
4335 buffer *errorlog_file;
4336 unsigned short errorlog_use_syslog;
4339 unsigned short dont_daemonize;
4348 buffer *event_handler;
4351 buffer *modules_dir;
4352 buffer *network_backend;
4354 array *upload_tempdirs;
4357 unsigned short max_worker;
4358 unsigned short max_fds;
4359 unsigned short max_conns;
4360 unsigned short max_request_size;
4363 unsigned short log_request_header_on_error;
4364 unsigned short log_state_handling;
4366 - enum { STAT_CACHE_ENGINE_UNSET,
4367 - STAT_CACHE_ENGINE_NONE,
4368 - STAT_CACHE_ENGINE_SIMPLE,
4369 - STAT_CACHE_ENGINE_FAM
4371 + enum { STAT_CACHE_ENGINE_UNSET,
4372 + STAT_CACHE_ENGINE_NONE,
4373 + STAT_CACHE_ENGINE_SIMPLE,
4374 + STAT_CACHE_ENGINE_FAM
4375 } stat_cache_engine;
4376 unsigned short enable_cores;
4378 @@ -480,14 +485,14 @@
4384 buffer *ssl_pemfile;
4385 buffer *ssl_ca_file;
4386 unsigned short use_ipv6;
4387 unsigned short is_ssl;
4396 @@ -495,37 +500,37 @@
4399 server_socket **ptr;
4404 } server_socket_array;
4406 typedef struct server {
4407 server_socket_array srv_sockets;
4412 enum { ERRORLOG_STDERR, ERRORLOG_FILE, ERRORLOG_SYSLOG } errorlog_mode;
4413 buffer *errorlog_buf;
4416 fdevents *ev, *ev_ins;
4419 buffer_plugin plugins;
4433 int max_fds; /* max possible fds */
4434 int cur_fds; /* currently used fds */
4435 int want_fds; /* waiting fds */
4436 int sockets_disabled;
4442 @@ -533,13 +538,13 @@
4443 buffer *response_header;
4444 buffer *response_range;
4448 buffer *tmp_chunk_len;
4451 buffer *empty_string; /* is necessary for cond_match */
4453 buffer *cond_check_buf;
4458 inet_ntop_cache_type inet_ntop_cache[INET_NTOP_CACHE_MAX];
4459 @@ -547,31 +552,31 @@
4460 mtime_cache_type mtime_cache[FILE_CACHE_MAX];
4467 time_t last_generated_date_ts;
4468 time_t last_generated_debug_ts;
4472 buffer *ts_debug_str;
4473 buffer *ts_date_str;
4478 array *config_touched;
4481 array *config_context;
4482 specific_config **config_storage;
4485 server_config srvconf;
4488 int config_deprecated;
4492 connections *joblist;
4493 connections *fdwaitqueue;
4496 stat_cache *stat_cache;
4499 @@ -588,18 +593,20 @@
4500 * fastcgi.backend.<key>.disconnects = ...
4505 fdevent_handler_t event_handler;
4507 - int (* network_backend_write)(struct server *srv, connection *con, int fd, chunkqueue *cq);
4508 - int (* network_backend_read)(struct server *srv, connection *con, int fd, chunkqueue *cq);
4509 + network_status_t (* network_backend_write)(struct server *srv, connection *con, int fd, chunkqueue *cq);
4510 + network_status_t (* network_backend_read)(struct server *srv, connection *con, int fd, chunkqueue *cq);
4512 - int (* network_ssl_backend_write)(struct server *srv, connection *con, SSL *ssl, chunkqueue *cq);
4513 - int (* network_ssl_backend_read)(struct server *srv, connection *con, SSL *ssl, chunkqueue *cq);
4514 + network_status_t (* network_ssl_backend_write)(struct server *srv, connection *con, SSL *ssl, chunkqueue *cq);
4515 + network_status_t (* network_ssl_backend_read)(struct server *srv, connection *con, SSL *ssl, chunkqueue *cq);
4526 Property changes on: src/base.h
4527 ___________________________________________________________________
4531 Index: src/mod_rewrite.c
4532 ===================================================================
4533 --- src/mod_rewrite.c (.../tags/lighttpd-1.4.11) (revision 1159)
4534 +++ src/mod_rewrite.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
4549 - rewrite_rule **ptr;
4553 -} rewrite_rule_buffer;
4556 - rewrite_rule_buffer *rewrite;
4557 + pcre_keyvalue_buffer *rewrite;
4559 data_config *context; /* to which apply me */
4568 plugin_config **config_storage;
4570 - plugin_config conf;
4572 + plugin_config conf;
4575 static handler_ctx * handler_ctx_init() {
4579 hctx = calloc(1, sizeof(*hctx));
4582 hctx->state = REWRITE_STATE_UNSET;
4589 @@ -63,207 +47,136 @@
4593 -rewrite_rule_buffer *rewrite_rule_buffer_init(void) {
4594 - rewrite_rule_buffer *kvb;
4596 - kvb = calloc(1, sizeof(*kvb));
4601 -int rewrite_rule_buffer_append(rewrite_rule_buffer *kvb, buffer *key, buffer *value, int once) {
4604 - const char *errptr;
4607 - if (!key) return -1;
4609 - if (kvb->size == 0) {
4613 - kvb->ptr = malloc(kvb->size * sizeof(*kvb->ptr));
4615 - for(i = 0; i < kvb->size; i++) {
4616 - kvb->ptr[i] = calloc(1, sizeof(**kvb->ptr));
4618 - } else if (kvb->used == kvb->size) {
4621 - kvb->ptr = realloc(kvb->ptr, kvb->size * sizeof(*kvb->ptr));
4623 - for(i = kvb->used; i < kvb->size; i++) {
4624 - kvb->ptr[i] = calloc(1, sizeof(**kvb->ptr));
4628 - if (NULL == (kvb->ptr[kvb->used]->key = pcre_compile(key->ptr,
4629 - 0, &errptr, &erroff, NULL))) {
4634 - kvb->ptr[kvb->used]->value = buffer_init();
4635 - buffer_copy_string_buffer(kvb->ptr[kvb->used]->value, value);
4636 - kvb->ptr[kvb->used]->once = once;
4651 -void rewrite_rule_buffer_free(rewrite_rule_buffer *kvb) {
4655 - for (i = 0; i < kvb->size; i++) {
4656 - if (kvb->ptr[i]->key) pcre_free(kvb->ptr[i]->key);
4657 - if (kvb->ptr[i]->value) buffer_free(kvb->ptr[i]->value);
4658 - free(kvb->ptr[i]);
4661 - if (kvb->ptr) free(kvb->ptr);
4668 INIT_FUNC(mod_rewrite_init) {
4672 p = calloc(1, sizeof(*p));
4675 p->match_buf = buffer_init();
4681 FREE_FUNC(mod_rewrite_free) {
4682 plugin_data *p = p_d;
4687 if (!p) return HANDLER_GO_ON;
4690 buffer_free(p->match_buf);
4691 if (p->config_storage) {
4693 for (i = 0; i < srv->config_context->used; i++) {
4694 plugin_config *s = p->config_storage[i];
4695 - rewrite_rule_buffer_free(s->rewrite);
4697 + pcre_keyvalue_buffer_free(s->rewrite);
4698 + buffer_free(s->once);
4702 free(p->config_storage);
4709 return HANDLER_GO_ON;
4712 static int parse_config_entry(server *srv, plugin_config *s, array *ca, const char *option, int once) {
4716 if (NULL != (du = array_get_element(ca, option))) {
4717 data_array *da = (data_array *)du;
4721 if (du->type != TYPE_ARRAY) {
4722 - log_error_write(srv, __FILE__, __LINE__, "sss",
4723 + log_error_write(srv, __FILE__, __LINE__, "sss",
4724 "unexpected type for key: ", option, "array of strings");
4727 return HANDLER_ERROR;
4731 da = (data_array *)du;
4734 for (j = 0; j < da->value->used; j++) {
4735 if (da->value->data[j]->type != TYPE_STRING) {
4736 - log_error_write(srv, __FILE__, __LINE__, "sssbs",
4737 - "unexpected type for key: ",
4739 + log_error_write(srv, __FILE__, __LINE__, "sssbs",
4740 + "unexpected type for key: ",
4742 "[", da->value->data[j]->key, "](string)");
4745 return HANDLER_ERROR;
4748 - if (0 != rewrite_rule_buffer_append(s->rewrite,
4749 - ((data_string *)(da->value->data[j]))->key,
4750 - ((data_string *)(da->value->data[j]))->value,
4753 + if (0 != pcre_keyvalue_buffer_append(s->rewrite,
4754 + ((data_string *)(da->value->data[j]))->key->ptr,
4755 + ((data_string *)(da->value->data[j]))->value->ptr)) {
4757 - log_error_write(srv, __FILE__, __LINE__, "sb",
4758 + log_error_write(srv, __FILE__, __LINE__, "sb",
4759 "pcre-compile failed for", da->value->data[j]->key);
4761 - log_error_write(srv, __FILE__, __LINE__, "s",
4762 + log_error_write(srv, __FILE__, __LINE__, "s",
4763 "pcre support is missing, please install libpcre and the headers");
4768 + buffer_append_string_len(s->once, CONST_STR_LEN("1"));
4770 + buffer_append_string_len(s->once, CONST_STR_LEN("0"));
4779 SETDEFAULTS_FUNC(mod_rewrite_set_defaults) {
4780 plugin_data *p = p_d;
4783 - config_values_t cv[] = {
4785 + config_values_t cv[] = {
4786 { "url.rewrite-repeat", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
4787 { "url.rewrite-once", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
4789 - /* old names, still supported
4792 + /* old names, still supported
4794 * url.rewrite remapped to url.rewrite-once
4795 * url.rewrite-final is url.rewrite-once
4799 { "url.rewrite", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
4800 { "url.rewrite-final", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
4801 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
4805 if (!p) return HANDLER_ERROR;
4809 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
4812 for (i = 0; i < srv->config_context->used; i++) {
4817 s = calloc(1, sizeof(plugin_config));
4818 - s->rewrite = rewrite_rule_buffer_init();
4820 - cv[0].destination = s->rewrite;
4821 - cv[1].destination = s->rewrite;
4822 - cv[2].destination = s->rewrite;
4824 + s->rewrite = pcre_keyvalue_buffer_init();
4825 + s->once = buffer_init();
4827 p->config_storage[i] = s;
4828 ca = ((data_config *)srv->config_context->data[i])->value;
4831 if (0 != config_insert_values_global(srv, ca, cv)) {
4832 return HANDLER_ERROR;
4836 parse_config_entry(srv, s, ca, "url.rewrite-once", 1);
4837 parse_config_entry(srv, s, ca, "url.rewrite-final", 1);
4838 parse_config_entry(srv, s, ca, "url.rewrite", 1);
4839 parse_config_entry(srv, s, ca, "url.rewrite-repeat", 0);
4843 return HANDLER_GO_ON;
4846 @@ -271,157 +184,107 @@
4848 plugin_config *s = p->config_storage[0];
4849 p->conf.rewrite = s->rewrite;
4851 + p->conf.once = s->once;
4853 /* skip the first, the global context */
4854 for (i = 1; i < srv->config_context->used; i++) {
4855 data_config *dc = (data_config *)srv->config_context->data[i];
4856 s = p->config_storage[i];
4859 if (COMP_HTTP_URL == dc->comp) continue;
4862 /* condition didn't match */
4863 if (!config_check_cond(srv, con, dc)) continue;
4867 for (j = 0; j < dc->value->used; j++) {
4868 data_unset *du = dc->value->data[j];
4871 if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite"))) {
4872 p->conf.rewrite = s->rewrite;
4873 + p->conf.once = s->once;
4874 p->conf.context = dc;
4875 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-once"))) {
4876 p->conf.rewrite = s->rewrite;
4877 + p->conf.once = s->once;
4878 p->conf.context = dc;
4879 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-repeat"))) {
4880 p->conf.rewrite = s->rewrite;
4881 + p->conf.once = s->once;
4882 p->conf.context = dc;
4883 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-final"))) {
4884 p->conf.rewrite = s->rewrite;
4885 + p->conf.once = s->once;
4886 p->conf.context = dc;
4895 URIHANDLER_FUNC(mod_rewrite_con_reset) {
4896 plugin_data *p = p_d;
4902 if (con->plugin_ctx[p->id]) {
4903 handler_ctx_free(con->plugin_ctx[p->id]);
4904 con->plugin_ctx[p->id] = NULL;
4908 return HANDLER_GO_ON;
4911 URIHANDLER_FUNC(mod_rewrite_uri_handler) {
4913 plugin_data *p = p_d;
4923 * e.g. rewrite /base/ to /index.php?section=base
4929 if (con->plugin_ctx[p->id]) {
4930 hctx = con->plugin_ctx[p->id];
4933 if (hctx->loops++ > 100) {
4934 - log_error_write(srv, __FILE__, __LINE__, "s",
4935 + log_error_write(srv, __FILE__, __LINE__, "s",
4936 "ENDLESS LOOP IN rewrite-rule DETECTED ... aborting request, perhaps you want to use url.rewrite-once instead of url.rewrite-repeat");
4939 return HANDLER_ERROR;
4943 if (hctx->state == REWRITE_STATE_FINISHED) return HANDLER_GO_ON;
4947 mod_rewrite_patch_connection(srv, con, p);
4949 if (!p->conf.rewrite) return HANDLER_GO_ON;
4952 buffer_copy_string_buffer(p->match_buf, con->request.uri);
4954 - for (i = 0; i < p->conf.rewrite->used; i++) {
4956 - const char *pattern;
4957 - size_t pattern_len;
4959 - rewrite_rule *rule = p->conf.rewrite->ptr[i];
4963 - match = rule->key;
4964 - pattern = rule->value->ptr;
4965 - pattern_len = rule->value->used - 1;
4967 - if ((n = pcre_exec(match, NULL, p->match_buf->ptr, p->match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) {
4968 - if (n != PCRE_ERROR_NOMATCH) {
4969 - log_error_write(srv, __FILE__, __LINE__, "sd",
4970 - "execution error while matching: ", n);
4971 - return HANDLER_ERROR;
4974 - const char **list;
4975 - size_t start, end;
4979 - pcre_get_substring_list(p->match_buf->ptr, ovec, n, &list);
4981 - /* search for $[0-9] */
4983 - buffer_reset(con->request.uri);
4985 - start = 0; end = pattern_len;
4986 - for (k = 0; k < pattern_len; k++) {
4987 - if ((pattern[k] == '$' || pattern[k] == '%') &&
4988 - isdigit((unsigned char)pattern[k + 1])) {
4991 - size_t num = pattern[k + 1] - '0';
4995 - buffer_append_string_len(con->request.uri, pattern + start, end - start);
4997 - if (pattern[k] == '$') {
4998 - /* n is always > 0 */
4999 - if (num < (size_t)n) {
5000 - buffer_append_string(con->request.uri, list[num]);
5003 - config_append_cond_match_buffer(con, p->conf.context, con->request.uri, num);
5011 - buffer_append_string_len(con->request.uri, pattern + start, pattern_len - start);
5015 - hctx = handler_ctx_init();
5017 - con->plugin_ctx[p->id] = hctx;
5019 - if (rule->once) hctx->state = REWRITE_STATE_FINISHED;
5021 - return HANDLER_COMEBACK;
5023 + i = config_exec_pcre_keyvalue_buffer(con, p->conf.rewrite, p->conf.context, p->match_buf, con->request.uri);
5026 + hctx = handler_ctx_init();
5028 + con->plugin_ctx[p->id] = hctx;
5030 + if (p->conf.once->ptr[i] == '1')
5031 + hctx->state = REWRITE_STATE_FINISHED;
5033 + return HANDLER_COMEBACK;
5035 + else if (i != PCRE_ERROR_NOMATCH) {
5036 + log_error_write(srv, __FILE__, __LINE__, "s",
5037 + "execution error while matching", i);
5045 @@ -434,17 +297,17 @@
5046 int mod_rewrite_plugin_init(plugin *p) {
5047 p->version = LIGHTTPD_VERSION_ID;
5048 p->name = buffer_init_string("rewrite");
5051 p->init = mod_rewrite_init;
5052 /* it has to stay _raw as we are matching on uri + querystring
5056 p->handle_uri_raw = mod_rewrite_uri_handler;
5057 p->set_defaults = mod_rewrite_set_defaults;
5058 p->cleanup = mod_rewrite_free;
5059 p->connection_reset = mod_rewrite_con_reset;
5068 Property changes on: src/mod_rewrite.c
5069 ___________________________________________________________________
5074 ===================================================================
5075 --- src/lempar.c (.../tags/lighttpd-1.4.11) (revision 1159)
5076 +++ src/lempar.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
5078 /* Next is all token values, in a form suitable for use by makeheaders.
5079 ** This section will be null unless lemon is run with the -m switch.
5083 ** These constants (all generated automatically by the parser generator)
5084 ** specify the various kinds of tokens (terminals) that the parser
5088 ** Each symbol here is a terminal symbol in the grammar.
5091 ** and nonterminals. "int" is used otherwise.
5092 ** YYNOCODE is a number of type YYCODETYPE which corresponds
5093 ** to no legal terminal or nonterminal number. This
5094 -** number is used to fill in empty slots of the hash
5095 +** number is used to fill in empty slots of the hash
5097 ** YYFALLBACK If defined, this indicates that one or more tokens
5098 ** have fall-back values which should be used if the
5100 ** and nonterminal numbers. "unsigned char" is
5101 ** used if there are fewer than 250 rules and
5102 ** states combined. "int" is used otherwise.
5103 -** ParseTOKENTYPE is the data type used for minor tokens given
5104 +** ParseTOKENTYPE is the data type used for minor tokens given
5105 ** directly to the parser from the tokenizer.
5106 ** YYMINORTYPE is the data type used for all minor tokens.
5107 ** This is typically a union of many types, one of
5109 /* Next are that tables used to determine what action to take based on the
5110 ** current state and lookahead token. These tables are used to implement
5111 ** functions that take a state number and lookahead value and return an
5115 ** Suppose the action integer is N. Then the action is determined as
5118 ** If the index value yy_shift_ofst[S]+X is out of range or if the value
5119 ** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S]
5120 ** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table
5121 -** and that yy_default[S] should be used instead.
5122 +** and that yy_default[S] should be used instead.
5124 ** The formula above is for computing the action when the lookahead is
5125 ** a terminal symbol. If the lookahead is a non-terminal (as occurs after
5128 /* The next table maps tokens into fallback tokens. If a construct
5129 ** like the following:
5132 ** %fallback ID X Y Z.
5134 ** appears in the grammer, then ID becomes a fallback token for X, Y,
5135 @@ -163,10 +163,10 @@
5141 ** Turn parser tracing on by giving a stream to which to write the trace
5142 ** and a prompt to preface each trace message. Tracing is turned off
5143 -** by making either argument NULL
5144 +** by making either argument NULL
5150 /* For tracing shifts, the names of all terminals and nonterminals
5151 ** are required. The following table supplies these names */
5152 -static const char *yyTokenName[] = {
5153 +static const char *yyTokenName[] = {
5163 ** This function allocates a new parser.
5164 ** The only argument is a pointer to a function which works like
5167 /* Here is inserted the actions which take place when a
5168 ** terminal or non-terminal is destroyed. This can happen
5169 ** when the symbol is popped from the stack during a
5170 - ** reduce or during error processing or when a parser is
5171 + ** reduce or during error processing or when a parser is
5172 ** being destroyed before it is finished parsing.
5174 ** Note: during a reduce, the only symbols destroyed are those
5181 ** Deallocate and destroy a parser. Destructors are all called for
5182 ** all stack elements before shutting the parser down.
5187 int stateno = pParser->yystack[pParser->yyidx].stateno;
5190 /* if( pParser->yyidx<0 ) return YY_NO_ACTION; */
5191 i = yy_shift_ofst[stateno];
5192 if( i==YY_SHIFT_USE_DFLT ){
5196 int stateno = pParser->yystack[pParser->yyidx].stateno;
5199 i = yy_reduce_ofst[stateno];
5200 if( i==YY_REDUCE_USE_DFLT ){
5201 return yy_default[stateno];
5204 yymsp = &yypParser->yystack[yypParser->yyidx];
5206 - if( yyTraceFILE && yyruleno>=0
5207 + if( yyTraceFILE && yyruleno>=0
5208 && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){
5209 fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt,
5210 yyRuleName[yyruleno]);
5212 #ifdef YYERRORSYMBOL
5213 /* A syntax error has occurred.
5214 ** The response to an error depends upon whether or not the
5215 - ** grammar defines an error token "ERROR".
5216 + ** grammar defines an error token "ERROR".
5218 ** This is what we do if the grammar does define ERROR:
5221 Property changes on: src/lempar.c
5222 ___________________________________________________________________
5226 Index: src/connections.c
5227 ===================================================================
5228 --- src/connections.c (.../tags/lighttpd-1.4.11) (revision 1159)
5229 +++ src/connections.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
5234 -#include <unistd.h>
5239 #include "inet_ntop_cache.h"
5242 -# include <openssl/ssl.h>
5243 -# include <openssl/err.h>
5244 +# include <openssl/ssl.h>
5245 +# include <openssl/err.h>
5248 #ifdef HAVE_SYS_FILIO_H
5252 #include "sys-socket.h"
5253 +#include "sys-files.h"
5258 static connection *connections_get_new_connection(server *srv) {
5259 connections *conns = srv->conns;
5263 if (conns->size == 0) {
5267 } else if (conns->size == conns->used) {
5269 conns->ptr = realloc(conns->ptr, sizeof(*conns->ptr) * conns->size);
5272 for (i = conns->used; i < conns->size; i++) {
5273 conns->ptr[i] = connection_init(srv);
5277 connection_reset(srv, conns->ptr[conns->used]);
5280 fprintf(stderr, "%s.%d: add: ", __FILE__, __LINE__);
5281 for (i = 0; i < conns->used + 1; i++) {
5282 fprintf(stderr, "%d ", conns->ptr[i]->fd);
5284 fprintf(stderr, "\n");
5289 conns->ptr[conns->used]->ndx = conns->used;
5290 return conns->ptr[conns->used++];
5294 connections *conns = srv->conns;
5298 if (con == NULL) return -1;
5301 if (-1 == con->ndx) return -1;
5307 /* not last element */
5310 if (i != conns->used - 1) {
5311 temp = conns->ptr[i];
5312 conns->ptr[i] = conns->ptr[conns->used - 1];
5313 conns->ptr[conns->used - 1] = temp;
5316 conns->ptr[i]->ndx = i;
5317 conns->ptr[conns->used - 1]->ndx = -1;
5326 fprintf(stderr, "%s.%d: del: (%d)", __FILE__, __LINE__, conns->used);
5327 @@ -104,25 +104,23 @@
5328 fprintf(stderr, "%d ", conns->ptr[i]->fd);
5330 fprintf(stderr, "\n");
5336 int connection_close(server *srv, connection *con) {
5338 server_socket *srv_sock = con->srv_socket;
5343 if (srv_sock->is_ssl) {
5344 if (con->ssl) SSL_free(con->ssl);
5350 fdevent_event_del(srv->ev, &(con->fde_ndx), con->fd);
5351 fdevent_unregister(srv->ev, con->fd);
5354 if (closesocket(con->fd)) {
5355 log_error_write(srv, __FILE__, __LINE__, "sds",
5356 "(warning) close:", con->fd, strerror(errno));
5357 @@ -133,207 +131,96 @@
5358 "(warning) close:", con->fd, strerror(errno));
5365 log_error_write(srv, __FILE__, __LINE__, "sd",
5366 "closed()", con->fd);
5370 connection_del(srv, con);
5371 connection_set_state(srv, con, CON_STATE_CONNECT);
5378 static void dump_packet(const unsigned char *data, size_t len) {
5382 if (len == 0) return;
5385 for (i = 0; i < len; i++) {
5386 if (i % 16 == 0) fprintf(stderr, " ");
5389 fprintf(stderr, "%02x ", data[i]);
5392 if ((i + 1) % 16 == 0) {
5393 fprintf(stderr, " ");
5394 for (j = 0; j <= i % 16; j++) {
5398 if (i-15+j >= len) break;
5404 fprintf(stderr, "%c", c > 32 && c < 128 ? c : '.');
5408 fprintf(stderr, "\n");
5413 if (len % 16 != 0) {
5414 for (j = i % 16; j < 16; j++) {
5415 fprintf(stderr, " ");
5419 fprintf(stderr, " ");
5420 for (j = i & ~0xf; j < len; j++) {
5425 fprintf(stderr, "%c", c > 32 && c < 128 ? c : '.');
5427 fprintf(stderr, "\n");
5432 -static int connection_handle_read(server *srv, connection *con) {
5437 - server_socket *srv_sock = con->srv_socket;
5440 - b = chunkqueue_get_append_buffer(con->read_queue);
5441 - buffer_prepare_copy(b, 4096);
5442 +static network_status_t connection_handle_read(server *srv, connection *con) {
5443 + off_t oldlen, newlen;
5446 - if (srv_sock->is_ssl) {
5447 - len = SSL_read(con->ssl, b->ptr, b->size - 1);
5449 - if (ioctl(con->fd, FIONREAD, &toread)) {
5450 - log_error_write(srv, __FILE__, __LINE__, "sd",
5451 - "unexpected end-of-file:",
5455 - buffer_prepare_copy(b, toread);
5456 + oldlen = chunkqueue_length(con->read_queue);
5458 - len = read(con->fd, b->ptr, b->size - 1);
5460 -#elif defined(__WIN32)
5461 - len = recv(con->fd, b->ptr, b->size - 1, 0);
5463 - if (ioctl(con->fd, FIONREAD, &toread)) {
5464 - log_error_write(srv, __FILE__, __LINE__, "sd",
5465 - "unexpected end-of-file:",
5469 - buffer_prepare_copy(b, toread);
5470 + switch(network_read_chunkqueue(srv, con, con->read_queue)) {
5471 + case NETWORK_STATUS_SUCCESS:
5473 + case NETWORK_STATUS_WAIT_FOR_EVENT:
5474 + con->is_readable = 0;
5475 + return NETWORK_STATUS_WAIT_FOR_EVENT;
5476 + case NETWORK_STATUS_INTERRUPTED:
5477 + con->is_readable = 1;
5478 + return NETWORK_STATUS_WAIT_FOR_EVENT;
5479 + case NETWORK_STATUS_CONNECTION_CLOSE:
5481 + con->is_readable = 0;
5482 + return NETWORK_STATUS_CONNECTION_CLOSE;
5483 + case NETWORK_STATUS_FATAL_ERROR:
5484 + con->is_readable = 0;
5486 - len = read(con->fd, b->ptr, b->size - 1);
5490 - con->is_readable = 0;
5493 - if (srv_sock->is_ssl) {
5496 - switch ((r = SSL_get_error(con->ssl, len))) {
5497 - case SSL_ERROR_WANT_READ:
5499 - case SSL_ERROR_SYSCALL:
5501 - * man SSL_get_error()
5503 - * SSL_ERROR_SYSCALL
5504 - * Some I/O error occurred. The OpenSSL error queue may contain more
5505 - * information on the error. If the error queue is empty (i.e.
5506 - * ERR_get_error() returns 0), ret can be used to find out more about
5507 - * the error: If ret == 0, an EOF was observed that violates the
5508 - * protocol. If ret == -1, the underlying BIO reported an I/O error
5509 - * (for socket I/O on Unix systems, consult errno for details).
5512 - while((ssl_err = ERR_get_error())) {
5513 - /* get all errors from the error-queue */
5514 - log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
5515 - r, ERR_error_string(ssl_err, NULL));
5517 + connection_set_state(srv, con, CON_STATE_ERROR);
5518 + return NETWORK_STATUS_FATAL_ERROR;
5526 - log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
5533 - case SSL_ERROR_ZERO_RETURN:
5534 - /* clean shutdown on the remote side */
5537 - /* FIXME: later */
5540 - /* fall thourgh */
5542 - while((ssl_err = ERR_get_error())) {
5543 - /* get all errors from the error-queue */
5544 - log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
5545 - r, ERR_error_string(ssl_err, NULL));
5550 - if (errno == EAGAIN) return 0;
5551 - if (errno == EINTR) {
5552 - /* we have been interrupted before we could read */
5553 - con->is_readable = 1;
5557 - if (errno != ECONNRESET) {
5558 - /* expected for keep-alive */
5559 - log_error_write(srv, __FILE__, __LINE__, "ssd", "connection closed - read failed: ", strerror(errno), errno);
5563 - if (errno == EAGAIN) return 0;
5564 - if (errno == EINTR) {
5565 - /* we have been interrupted before we could read */
5566 - con->is_readable = 1;
5570 - if (errno != ECONNRESET) {
5571 - /* expected for keep-alive */
5572 - log_error_write(srv, __FILE__, __LINE__, "ssd", "connection closed - read failed: ", strerror(errno), errno);
5575 - connection_set_state(srv, con, CON_STATE_ERROR);
5578 - } else if (len == 0) {
5579 - con->is_readable = 0;
5580 - /* the other end close the connection -> KEEP-ALIVE */
5581 + newlen = chunkqueue_length(con->read_queue);
5584 + con->bytes_read += (newlen - oldlen);
5587 - } else if ((size_t)len < b->size - 1) {
5588 - /* we got less then expected, wait for the next fd-event */
5590 - con->is_readable = 0;
5594 - b->ptr[b->used++] = '\0';
5596 - con->bytes_read += len;
5598 - dump_packet(b->ptr, len);
5602 + return NETWORK_STATUS_SUCCESS;
5605 static int connection_handle_write_prepare(server *srv, connection *con) {
5607 case HTTP_METHOD_GET:
5608 case HTTP_METHOD_POST:
5609 case HTTP_METHOD_HEAD:
5611 case HTTP_METHOD_PUT:
5612 case HTTP_METHOD_MKCOL:
5613 case HTTP_METHOD_DELETE:
5614 @@ -350,12 +238,14 @@
5615 case HTTP_METHOD_MOVE:
5616 case HTTP_METHOD_PROPFIND:
5617 case HTTP_METHOD_PROPPATCH:
5618 + case HTTP_METHOD_LOCK:
5619 + case HTTP_METHOD_UNLOCK:
5621 case HTTP_METHOD_OPTIONS:
5623 * 400 is coming from the request-parser BEFORE uri.path is set
5624 - * 403 is from the response handler when noone else catched it
5626 + * 403 is from the response handler when noone else catched it
5629 if (con->uri.path->used &&
5630 con->uri.path->ptr[0] != '*') {
5631 @@ -381,55 +271,58 @@
5637 if (con->http_status == 0) {
5638 con->http_status = 403;
5642 switch(con->http_status) {
5643 case 400: /* class: header + custom body */
5659 if (con->mode != DIRECT) break;
5662 con->file_finished = 0;
5665 buffer_reset(con->physical.path);
5668 /* try to send static errorfile */
5669 if (!buffer_is_empty(con->conf.errorfile_prefix)) {
5670 stat_cache_entry *sce = NULL;
5673 buffer_copy_string_buffer(con->physical.path, con->conf.errorfile_prefix);
5674 buffer_append_string(con->physical.path, get_http_status_body_name(con->http_status));
5677 if (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
5678 con->file_finished = 1;
5681 http_chunk_append_file(srv, con, con->physical.path, 0, sce->st.st_size);
5682 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
5686 - if (!con->file_finished) {
5688 + if (!con->file_finished) {
5692 buffer_reset(con->physical.path);
5695 con->file_finished = 1;
5696 b = chunkqueue_get_append_buffer(con->write_queue);
5699 /* build default error-page */
5700 - buffer_copy_string(b,
5701 + buffer_copy_string(b,
5702 "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
5703 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
5704 " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
5706 buffer_append_long(b, con->http_status);
5707 buffer_append_string(b, " - ");
5708 buffer_append_string(b, get_http_status_name(con->http_status));
5711 buffer_append_string(b,
5714 @@ -448,12 +341,12 @@
5715 buffer_append_long(b, con->http_status);
5716 buffer_append_string(b, " - ");
5717 buffer_append_string(b, get_http_status_name(con->http_status));
5719 - buffer_append_string(b,"</h1>\n"
5721 + buffer_append_string(b,"</h1>\n"
5727 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
5730 @@ -463,10 +356,10 @@
5736 case 206: /* write_queue is already prepared */
5737 con->file_finished = 1;
5741 case 205: /* class: header only */
5743 @@ -474,19 +367,19 @@
5744 /* disable chunked encoding again as we have no body */
5745 con->response.transfer_encoding &= ~HTTP_TRANSFER_ENCODING_CHUNKED;
5746 chunkqueue_reset(con->write_queue);
5749 con->file_finished = 1;
5755 if (con->file_finished) {
5756 - /* we have all the content and chunked encoding is not used, set a content-length */
5758 - if ((!(con->parsed_response & HTTP_CONTENT_LENGTH)) &&
5759 + /* we have all the content and chunked encoding is not used, set a content-length */
5761 + if ((!(con->parsed_response & HTTP_CONTENT_LENGTH)) &&
5762 (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) == 0) {
5763 buffer_copy_off_t(srv->tmp_buf, chunkqueue_length(con->write_queue));
5766 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Length"), CONST_BUF_LEN(srv->tmp_buf));
5769 @@ -495,74 +388,77 @@
5770 ((con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) == 0)) {
5771 con->keep_alive = 0;
5775 if (0 == (con->parsed_response & HTTP_CONNECTION)) {
5776 /* (f)cgi did'nt send Connection: header
5781 if (((con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) == 0) &&
5782 (con->parsed_response & HTTP_CONTENT_LENGTH) == 0) {
5783 /* without content_length, no keep-alive */
5786 con->keep_alive = 0;
5789 /* a subrequest disable keep-alive although the client wanted it */
5790 if (con->keep_alive && !con->response.keep_alive) {
5791 con->keep_alive = 0;
5794 /* FIXME: we have to drop the Connection: Header from the subrequest */
5800 if (con->request.http_method == HTTP_METHOD_HEAD) {
5801 chunkqueue_reset(con->write_queue);
5804 http_response_write_header(srv, con);
5810 static int connection_handle_write(server *srv, connection *con) {
5811 - switch(network_write_chunkqueue(srv, con, con->write_queue)) {
5813 + switch(network_write_chunkqueue(srv, con, con->write_queue)) {
5814 + case NETWORK_STATUS_SUCCESS:
5815 if (con->file_finished) {
5816 connection_set_state(srv, con, CON_STATE_RESPONSE_END);
5817 joblist_append(srv, con);
5820 - case -1: /* error on our side */
5821 + case NETWORK_STATUS_FATAL_ERROR: /* error on our side */
5822 log_error_write(srv, __FILE__, __LINE__, "sd",
5823 "connection closed: write failed on fd", con->fd);
5824 connection_set_state(srv, con, CON_STATE_ERROR);
5825 joblist_append(srv, con);
5827 - case -2: /* remote close */
5828 + case NETWORK_STATUS_CONNECTION_CLOSE: /* remote close */
5829 connection_set_state(srv, con, CON_STATE_ERROR);
5830 joblist_append(srv, con);
5833 + case NETWORK_STATUS_WAIT_FOR_EVENT:
5834 con->is_writable = 0;
5837 /* not finished yet -> WRITE */
5839 + case NETWORK_STATUS_INTERRUPTED:
5840 + con->is_writable = 1;
5842 + case NETWORK_STATUS_UNSET:
5852 connection *connection_init(server *srv) {
5858 con = calloc(1, sizeof(*con));
5864 @@ -573,32 +469,32 @@
5867 con->x = buffer_init();
5871 CLEAN(request.request_line);
5872 CLEAN(request.request);
5873 CLEAN(request.pathinfo);
5876 CLEAN(request.orig_uri);
5880 CLEAN(uri.authority);
5882 CLEAN(uri.path_raw);
5886 CLEAN(physical.doc_root);
5887 CLEAN(physical.path);
5888 CLEAN(physical.basedir);
5889 CLEAN(physical.rel_path);
5890 CLEAN(physical.etag);
5891 CLEAN(parse_request);
5896 CLEAN(error_handler);
5897 CLEAN(dst_addr_buf);
5901 con->write_queue = chunkqueue_init();
5902 con->read_queue = chunkqueue_init();
5903 @@ -608,26 +504,26 @@
5904 con->request.headers = array_init();
5905 con->response.headers = array_init();
5906 con->environment = array_init();
5909 /* init plugin specific connection structures */
5912 con->plugin_ctx = calloc(1, (srv->plugins.used + 1) * sizeof(void *));
5915 con->cond_cache = calloc(srv->config_context->used, sizeof(cond_cache_t));
5916 config_setup_connection(srv, con);
5922 void connections_free(server *srv) {
5923 connections *conns = srv->conns;
5928 for (i = 0; i < conns->size; i++) {
5929 connection *con = conns->ptr[i];
5932 connection_reset(srv, con);
5935 chunkqueue_free(con->write_queue);
5936 chunkqueue_free(con->read_queue);
5937 chunkqueue_free(con->request_content_queue);
5938 @@ -637,27 +533,27 @@
5941 buffer_free(con->x);
5945 CLEAN(request.request_line);
5946 CLEAN(request.request);
5947 CLEAN(request.pathinfo);
5950 CLEAN(request.orig_uri);
5954 CLEAN(uri.authority);
5956 CLEAN(uri.path_raw);
5960 CLEAN(physical.doc_root);
5961 CLEAN(physical.path);
5962 CLEAN(physical.basedir);
5963 CLEAN(physical.etag);
5964 CLEAN(physical.rel_path);
5965 CLEAN(parse_request);
5970 CLEAN(error_handler);
5971 @@ -665,97 +561,97 @@
5973 free(con->plugin_ctx);
5974 free(con->cond_cache);
5985 int connection_reset(server *srv, connection *con) {
5989 plugins_call_connection_reset(srv, con);
5992 con->is_readable = 1;
5993 con->is_writable = 1;
5994 con->http_status = 0;
5995 con->file_finished = 0;
5996 con->file_started = 0;
5997 con->got_response = 0;
6000 con->parsed_response = 0;
6003 con->bytes_written = 0;
6004 con->bytes_written_cur_second = 0;
6005 con->bytes_read = 0;
6006 con->bytes_header = 0;
6007 con->loops_per_request = 0;
6010 con->request.http_method = HTTP_METHOD_UNSET;
6011 con->request.http_version = HTTP_VERSION_UNSET;
6014 con->request.http_if_modified_since = NULL;
6015 con->request.http_if_none_match = NULL;
6018 con->response.keep_alive = 0;
6019 con->response.content_length = -1;
6020 con->response.transfer_encoding = 0;
6027 if (con->x) buffer_reset(con->x);
6031 CLEAN(request.request_line);
6032 CLEAN(request.pathinfo);
6033 CLEAN(request.request);
6036 CLEAN(request.orig_uri);
6040 CLEAN(uri.authority);
6042 CLEAN(uri.path_raw);
6046 CLEAN(physical.doc_root);
6047 CLEAN(physical.path);
6048 CLEAN(physical.basedir);
6049 CLEAN(physical.rel_path);
6050 CLEAN(physical.etag);
6053 CLEAN(parse_request);
6058 CLEAN(error_handler);
6064 - if (con->x) con->x->used = 0;
6066 + if (con->x) con->x->used = 0;
6072 con->request.x = NULL;
6077 CLEAN(http_content_type);
6079 con->request.content_length = 0;
6082 array_reset(con->request.headers);
6083 array_reset(con->response.headers);
6084 array_reset(con->environment);
6087 chunkqueue_reset(con->write_queue);
6088 chunkqueue_reset(con->request_content_queue);
6090 - /* the plugins should cleanup themself */
6091 + /* the plugins should cleanup themself */
6092 for (i = 0; i < srv->plugins.used; i++) {
6093 plugin *p = ((plugin **)(srv->plugins.ptr))[i];
6094 plugin_data *pd = p->data;
6097 con->plugin_ctx[pd->id] = NULL;
6101 #if COND_RESULT_UNSET
6102 for (i = srv->config_context->used - 1; i >= 0; i --) {
6103 con->cond_cache[i].result = COND_RESULT_UNSET;
6104 @@ -777,56 +673,56 @@
6106 memset(con->cond_cache, 0, sizeof(cond_cache_t) * srv->config_context->used);
6110 con->header_len = 0;
6111 con->in_error_handler = 0;
6114 config_setup_connection(srv, con);
6122 - * search for \r\n\r\n
6125 + * search for \r\n\r\n
6127 * this is a special 32bit version which is using a sliding window for
6128 - * the comparisions
6130 + * the comparisions
6139 * cmpbuf: abcd != cdef
6140 * cmpbuf: bcde != cdef
6141 * cmpbuf: cdef == cdef -> return &c
6143 - * cmpbuf and rnrn are treated as 32bit uint and bit-ops are used to
6145 + * cmpbuf and rnrn are treated as 32bit uint and bit-ops are used to
6146 * maintain cmpbuf and rnrn
6151 char *buffer_search_rnrn(buffer *b) {
6152 uint32_t cmpbuf, rnrn;
6157 if (b->used < 4) return NULL;
6160 rnrn = ('\r' << 24) | ('\n' << 16) |
6161 ('\r' << 8) | ('\n' << 0);
6164 cmpbuf = (b->ptr[0] << 24) | (b->ptr[1] << 16) |
6165 (b->ptr[2] << 8) | (b->ptr[3] << 0);
6169 for (i = 0; i < b->used - 4; i++) {
6170 if (cmpbuf == rnrn) return cp - 4;
6173 cmpbuf = (cmpbuf << 8 | *(cp++)) & 0xffffffff;
6180 @@ -840,22 +736,25 @@
6182 chunkqueue *cq = con->read_queue;
6183 chunkqueue *dst_cq = con->request_content_queue;
6186 if (con->is_readable) {
6187 con->read_idle_ts = srv->cur_ts;
6190 switch(connection_handle_read(srv, con)) {
6192 + case NETWORK_STATUS_FATAL_ERROR:
6195 + case NETWORK_STATUS_CONNECTION_CLOSE:
6196 /* remote side closed the connection
6197 * if we still have content, handle it, if not leave here */
6199 if (cq->first == cq->last &&
6200 - cq->first->mem->used == 0) {
6201 + (NULL == cq->first ||
6202 + cq->first->mem->used == 0)) {
6204 /* conn-closed, leave here */
6205 connection_set_state(srv, con, CON_STATE_ERROR);
6211 @@ -891,14 +790,14 @@
6212 /* the last node was empty */
6213 if (c->next == NULL) {
6225 /* nothing to handle */
6226 if (cq->first == NULL) return 0;
6228 @@ -906,25 +805,26 @@
6229 case CON_STATE_READ:
6230 /* prepare con->request.request */
6234 /* check if we need the full package */
6235 if (con->request.request->used == 0) {
6239 b.ptr = c->mem->ptr + c->offset;
6240 b.used = c->mem->used - c->offset;
6243 if (NULL != (h_term = buffer_search_rnrn(&b))) {
6245 * - copy everything incl. the terminator to request.request
6248 - buffer_copy_string_len(con->request.request,
6251 + buffer_copy_string_len(con->request.request,
6253 h_term - b.ptr + 4);
6256 /* the buffer has been read up to the terminator */
6257 c->offset += h_term - b.ptr + 4;
6260 /* not found, copy everything */
6261 buffer_copy_string_len(con->request.request, c->mem->ptr + c->offset, c->mem->used - c->offset - 1);
6262 @@ -932,14 +832,14 @@
6265 /* have to take care of overlapping header terminators */
6268 size_t l = con->request.request->used - 2;
6269 char *s = con->request.request->ptr;
6273 b.ptr = c->mem->ptr + c->offset;
6274 b.used = c->mem->used - c->offset;
6277 if (con->request.request->used - 1 > 3 &&
6281 c->mem->ptr[0] == '\n') {
6282 buffer_append_string_len(con->request.request, c->mem->ptr + c->offset, 1);
6286 h_term = con->request.request->ptr;
6287 } else if (con->request.request->used - 1 > 2 &&
6290 c->mem->ptr[1] == '\n') {
6291 buffer_append_string_len(con->request.request, c->mem->ptr + c->offset, 2);
6295 h_term = con->request.request->ptr;
6296 } else if (con->request.request->used - 1 > 1 &&
6298 @@ -968,17 +868,17 @@
6299 c->mem->ptr[2] == '\n') {
6300 buffer_append_string_len(con->request.request, c->mem->ptr + c->offset, 3);
6304 h_term = con->request.request->ptr;
6305 } else if (NULL != (h_term = buffer_search_string_len(&b, "\r\n\r\n", 4))) {
6307 * - copy everything incl. the terminator to request.request
6310 - buffer_append_string_len(con->request.request,
6311 - c->mem->ptr + c->offset,
6313 + buffer_append_string_len(con->request.request,
6314 + c->mem->ptr + c->offset,
6315 c->offset + h_term - b.ptr + 4);
6318 /* the buffer has been read up to the terminator */
6319 c->offset += h_term - b.ptr + 4;
6321 @@ -999,16 +899,16 @@
6322 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
6325 - case CON_STATE_READ_POST:
6326 + case CON_STATE_READ_POST:
6327 for (c = cq->first; c && (dst_cq->bytes_in != (off_t)con->request.content_length); c = c->next) {
6328 off_t weWant, weHave, toRead;
6331 weWant = con->request.content_length - dst_cq->bytes_in;
6334 assert(c->mem->used);
6337 weHave = c->mem->used - c->offset - 1;
6340 toRead = weHave > weWant ? weWant : weHave;
6342 /* the new way, copy everything into a chunkqueue whcih might use tempfiles */
6343 @@ -1017,13 +917,13 @@
6344 /* copy everything to max 1Mb sized tempfiles */
6347 - * if the last chunk is
6348 + * if the last chunk is
6349 * - smaller than 1Mb (size < 1Mb)
6350 * - not read yet (offset == 0)
6353 - * -> create a new chunk
6355 + * -> create a new chunk
6360 @@ -1056,14 +956,14 @@
6361 /* we have a chunk, let's write to it */
6363 if (dst_c->file.fd == -1) {
6364 - /* we don't have file to write to,
6365 + /* we don't have file to write to,
6366 * EACCES might be one reason.
6368 * Instead of sending 500 we send 413 and say the request is too large
6371 log_error_write(srv, __FILE__, __LINE__, "sbs",
6372 - "denying upload as opening to temp-file for upload failed:",
6373 + "denying upload as opening to temp-file for upload failed:",
6374 dst_c->file.name, strerror(errno));
6376 con->http_status = 413; /* Request-Entity too large */
6377 @@ -1074,15 +974,15 @@
6380 if (toRead != write(dst_c->file.fd, c->mem->ptr + c->offset, toRead)) {
6381 - /* write failed for some reason ... disk full ? */
6382 + /* write failed for some reason ... disk full ? */
6383 log_error_write(srv, __FILE__, __LINE__, "sbs",
6384 - "denying upload as writing to file failed:",
6385 + "denying upload as writing to file failed:",
6386 dst_c->file.name, strerror(errno));
6389 con->http_status = 413; /* Request-Entity too large */
6390 con->keep_alive = 0;
6391 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
6394 close(dst_c->file.fd);
6395 dst_c->file.fd = -1;
6397 @@ -1090,7 +990,7 @@
6400 dst_c->file.length += toRead;
6403 if (dst_cq->bytes_in + toRead == (off_t)con->request.content_length) {
6404 /* we read everything, close the chunk */
6405 close(dst_c->file.fd);
6406 @@ -1102,7 +1002,7 @@
6407 b = chunkqueue_get_append_buffer(dst_cq);
6408 buffer_copy_string_len(b, c->mem->ptr + c->offset, toRead);
6412 c->offset += toRead;
6413 dst_cq->bytes_in += toRead;
6415 @@ -1111,7 +1011,7 @@
6416 if (dst_cq->bytes_in == (off_t)con->request.content_length) {
6417 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
6424 @@ -1123,9 +1023,9 @@
6425 handler_t connection_handle_fdevent(void *s, void *context, int revents) {
6426 server *srv = (server *)s;
6427 connection *con = context;
6430 joblist_append(srv, con);
6433 if (revents & FDEVENT_IN) {
6434 con->is_readable = 1;
6436 @@ -1136,19 +1036,19 @@
6437 con->is_writable = 1;
6438 /* we don't need the event twice */
6444 if (revents & ~(FDEVENT_IN | FDEVENT_OUT)) {
6445 /* looks like an error */
6448 /* FIXME: revents = 0x19 still means that we should read from the queue */
6449 if (revents & FDEVENT_HUP) {
6450 if (con->state == CON_STATE_CLOSE) {
6451 con->close_timeout_ts = 0;
6453 /* sigio reports the wrong event here
6455 - * there was no HUP at all
6457 + * there was no HUP at all
6459 #ifdef USE_LINUX_SIGIO
6460 if (srv->ev->in_sigio == 1) {
6461 @@ -1160,32 +1060,39 @@
6463 connection_set_state(srv, con, CON_STATE_ERROR);
6468 } else if (revents & FDEVENT_ERR) {
6469 #ifndef USE_LINUX_SIGIO
6470 log_error_write(srv, __FILE__, __LINE__, "sd",
6471 "connection closed: poll() -> ERR", con->fd);
6474 connection_set_state(srv, con, CON_STATE_ERROR);
6476 log_error_write(srv, __FILE__, __LINE__, "sd",
6477 "connection closed: poll() -> ???", revents);
6483 if (con->state == CON_STATE_READ ||
6484 con->state == CON_STATE_READ_POST) {
6485 connection_handle_read_state(srv, con);
6487 + * if SSL_read() is not readin in the full packet we won't get
6488 + * a fdevent as the low-level has already fetched everything.
6490 + * we have to call the state-engine to read the rest of the packet
6492 + if (con->is_readable) joblist_append(srv, con);
6496 if (con->state == CON_STATE_WRITE &&
6497 !chunkqueue_is_empty(con->write_queue) &&
6501 if (-1 == connection_handle_write(srv, con)) {
6502 connection_set_state(srv, con, CON_STATE_ERROR);
6505 log_error_write(srv, __FILE__, __LINE__, "ds",
6507 "handle write failed.");
6508 @@ -1193,30 +1100,30 @@
6509 con->write_request_ts = srv->cur_ts;
6514 if (con->state == CON_STATE_CLOSE) {
6515 /* flush the read buffers */
6519 if (ioctl(con->fd, FIONREAD, &b)) {
6520 log_error_write(srv, __FILE__, __LINE__, "ss",
6521 "ioctl() failed", strerror(errno));
6527 log_error_write(srv, __FILE__, __LINE__, "sdd",
6528 "CLOSE-read()", con->fd, b);
6532 read(con->fd, buf, sizeof(buf));
6534 /* nothing to read */
6537 con->close_timeout_ts = 0;
6542 return HANDLER_FINISHED;
6545 @@ -1229,63 +1136,68 @@
6548 /* accept it and register the fd */
6551 cnt_len = sizeof(cnt_addr);
6553 if (-1 == (cnt = accept(srv_socket->fd, (struct sockaddr *) &cnt_addr, &cnt_len))) {
6555 + errno = WSAGetLastError();
6557 if ((errno != EAGAIN) &&
6558 + (errno != EWOULDBLOCK) &&
6560 - log_error_write(srv, __FILE__, __LINE__, "ssd", "accept failed:", strerror(errno), errno);
6561 + log_error_write(srv, __FILE__, __LINE__, "ssd", "accept failed:", strerror(errno), srv_socket->fd);
6571 /* ok, we have the connection, register it */
6573 log_error_write(srv, __FILE__, __LINE__, "sd",
6579 con = connections_get_new_connection(srv);
6585 gettimeofday(&(con->start_tv), NULL);
6588 fdevent_register(srv->ev, con->fd, connection_handle_fdevent, con);
6591 connection_set_state(srv, con, CON_STATE_REQUEST_START);
6594 con->connection_start = srv->cur_ts;
6595 con->dst_addr = cnt_addr;
6596 buffer_copy_string(con->dst_addr_buf, inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
6597 con->srv_socket = srv_socket;
6600 if (-1 == (fdevent_fcntl_set(srv->ev, con->fd))) {
6601 log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
6602 + connection_close(srv, con);
6606 /* connect FD to SSL */
6607 if (srv_socket->is_ssl) {
6608 if (NULL == (con->ssl = SSL_new(srv_socket->ssl_ctx))) {
6609 - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
6610 + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
6611 ERR_error_string(ERR_get_error(), NULL));
6613 + connection_close(srv, con);
6618 SSL_set_accept_state(con->ssl);
6622 if (1 != (SSL_set_fd(con->ssl, cnt))) {
6623 - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
6624 + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
6625 ERR_error_string(ERR_get_error(), NULL));
6626 + connection_close(srv, con);
6630 @@ -1300,10 +1212,10 @@
6632 server_socket *srv_sock = con->srv_socket;
6636 if (srv->srvconf.log_state_handling) {
6637 - log_error_write(srv, __FILE__, __LINE__, "sds",
6639 + log_error_write(srv, __FILE__, __LINE__, "sds",
6642 connection_get_state(con->state));
6644 @@ -1311,91 +1223,91 @@
6646 size_t ostate = con->state;
6650 switch (con->state) {
6651 case CON_STATE_REQUEST_START: /* transient */
6652 if (srv->srvconf.log_state_handling) {
6653 - log_error_write(srv, __FILE__, __LINE__, "sds",
6654 + log_error_write(srv, __FILE__, __LINE__, "sds",
6655 "state for fd", con->fd, connection_get_state(con->state));
6659 con->request_start = srv->cur_ts;
6660 con->read_idle_ts = srv->cur_ts;
6663 con->request_count++;
6664 con->loops_per_request = 0;
6667 connection_set_state(srv, con, CON_STATE_READ);
6671 case CON_STATE_REQUEST_END: /* transient */
6672 if (srv->srvconf.log_state_handling) {
6673 - log_error_write(srv, __FILE__, __LINE__, "sds",
6674 + log_error_write(srv, __FILE__, __LINE__, "sds",
6675 "state for fd", con->fd, connection_get_state(con->state));
6679 if (http_request_parse(srv, con)) {
6680 /* we have to read some data from the POST request */
6683 connection_set_state(srv, con, CON_STATE_READ_POST);
6689 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
6693 case CON_STATE_HANDLE_REQUEST:
6696 * the request is parsed
6699 * decided what to do with the request
6709 if (srv->srvconf.log_state_handling) {
6710 - log_error_write(srv, __FILE__, __LINE__, "sds",
6711 + log_error_write(srv, __FILE__, __LINE__, "sds",
6712 "state for fd", con->fd, connection_get_state(con->state));
6716 switch (r = http_response_prepare(srv, con)) {
6717 case HANDLER_FINISHED:
6718 if (con->http_status == 404 ||
6719 con->http_status == 403) {
6720 /* 404 error-handler */
6722 - if (con->in_error_handler == 0 &&
6724 + if (con->in_error_handler == 0 &&
6725 (!buffer_is_empty(con->conf.error_handler) ||
6726 !buffer_is_empty(con->error_handler))) {
6727 /* call error-handler */
6730 con->error_handler_saved_status = con->http_status;
6731 con->http_status = 0;
6734 if (buffer_is_empty(con->error_handler)) {
6735 buffer_copy_string_buffer(con->request.uri, con->conf.error_handler);
6737 buffer_copy_string_buffer(con->request.uri, con->error_handler);
6739 buffer_reset(con->physical.path);
6742 con->in_error_handler = 1;
6745 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
6750 } else if (con->in_error_handler) {
6751 /* error-handler is a 404 */
6754 /* continue as normal, status is the same */
6755 - log_error_write(srv, __FILE__, __LINE__, "sb",
6756 + log_error_write(srv, __FILE__, __LINE__, "sb",
6757 "Warning: Either the error-handler returned status 404 or the error-handler itself was not found:", con->request.uri);
6758 - log_error_write(srv, __FILE__, __LINE__, "sd",
6759 + log_error_write(srv, __FILE__, __LINE__, "sd",
6760 "returning the original status", con->error_handler_saved_status);
6761 - log_error_write(srv, __FILE__, __LINE__, "s",
6762 + log_error_write(srv, __FILE__, __LINE__, "s",
6763 "If this is a rails app: check your production.log");
6764 con->http_status = con->error_handler_saved_status;
6766 @@ -1403,26 +1315,26 @@
6767 /* error-handler is back and has generated content */
6768 /* if Status: was set, take it otherwise use 200 */
6772 if (con->http_status == 0) con->http_status = 200;
6775 /* we have something to send, go on */
6776 connection_set_state(srv, con, CON_STATE_RESPONSE_START);
6778 case HANDLER_WAIT_FOR_FD:
6782 fdwaitqueue_append(srv, con);
6785 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
6789 case HANDLER_COMEBACK:
6791 case HANDLER_WAIT_FOR_EVENT:
6792 /* come back here */
6793 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
6798 /* something went wrong */
6799 @@ -1432,44 +1344,44 @@
6800 log_error_write(srv, __FILE__, __LINE__, "sdd", "unknown ret-value: ", con->fd, r);
6806 case CON_STATE_RESPONSE_START:
6809 * the decision is done
6810 * - create the HTTP-Response-Header
6816 if (srv->srvconf.log_state_handling) {
6817 - log_error_write(srv, __FILE__, __LINE__, "sds",
6818 + log_error_write(srv, __FILE__, __LINE__, "sds",
6819 "state for fd", con->fd, connection_get_state(con->state));
6823 if (-1 == connection_handle_write_prepare(srv, con)) {
6824 connection_set_state(srv, con, CON_STATE_ERROR);
6831 connection_set_state(srv, con, CON_STATE_WRITE);
6833 case CON_STATE_RESPONSE_END: /* transient */
6834 /* log the request */
6837 if (srv->srvconf.log_state_handling) {
6838 - log_error_write(srv, __FILE__, __LINE__, "sds",
6839 + log_error_write(srv, __FILE__, __LINE__, "sds",
6840 "state for fd", con->fd, connection_get_state(con->state));
6844 plugins_call_handle_request_done(srv, con);
6850 if (con->keep_alive) {
6851 connection_set_state(srv, con, CON_STATE_REQUEST_START);
6856 con->request_start = srv->cur_ts;
6857 con->read_idle_ts = srv->cur_ts;
6859 @@ -1482,7 +1394,7 @@
6860 log_error_write(srv, __FILE__, __LINE__, "sd", "unhandling return value", r);
6866 if (srv_sock->is_ssl) {
6867 switch (SSL_shutdown(con->ssl)) {
6868 @@ -1490,44 +1402,44 @@
6872 - /* wait for fd-event
6874 + /* wait for fd-event
6876 * FIXME: wait for fdevent and call SSL_shutdown again
6884 - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
6885 + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
6886 ERR_error_string(ERR_get_error(), NULL));
6890 connection_close(srv, con);
6897 connection_reset(srv, con);
6901 case CON_STATE_CONNECT:
6902 if (srv->srvconf.log_state_handling) {
6903 - log_error_write(srv, __FILE__, __LINE__, "sds",
6904 + log_error_write(srv, __FILE__, __LINE__, "sds",
6905 "state for fd", con->fd, connection_get_state(con->state));
6909 chunkqueue_reset(con->read_queue);
6912 con->request_count = 0;
6916 case CON_STATE_CLOSE:
6917 if (srv->srvconf.log_state_handling) {
6918 - log_error_write(srv, __FILE__, __LINE__, "sds",
6919 + log_error_write(srv, __FILE__, __LINE__, "sds",
6920 "state for fd", con->fd, connection_get_state(con->state));
6924 if (con->keep_alive) {
6925 if (ioctl(con->fd, FIONREAD, &b)) {
6926 log_error_write(srv, __FILE__, __LINE__, "ss",
6927 @@ -1537,43 +1449,43 @@
6929 log_error_write(srv, __FILE__, __LINE__, "sdd",
6930 "CLOSE-read()", con->fd, b);
6934 read(con->fd, buf, sizeof(buf));
6936 /* nothing to read */
6939 con->close_timeout_ts = 0;
6942 con->close_timeout_ts = 0;
6946 if (srv->cur_ts - con->close_timeout_ts > 1) {
6947 connection_close(srv, con);
6950 if (srv->srvconf.log_state_handling) {
6951 - log_error_write(srv, __FILE__, __LINE__, "sd",
6952 + log_error_write(srv, __FILE__, __LINE__, "sd",
6953 "connection closed for fd", con->fd);
6959 case CON_STATE_READ_POST:
6960 case CON_STATE_READ:
6961 if (srv->srvconf.log_state_handling) {
6962 - log_error_write(srv, __FILE__, __LINE__, "sds",
6963 + log_error_write(srv, __FILE__, __LINE__, "sds",
6964 "state for fd", con->fd, connection_get_state(con->state));
6968 connection_handle_read_state(srv, con);
6970 case CON_STATE_WRITE:
6971 if (srv->srvconf.log_state_handling) {
6972 - log_error_write(srv, __FILE__, __LINE__, "sds",
6973 + log_error_write(srv, __FILE__, __LINE__, "sds",
6974 "state for fd", con->fd, connection_get_state(con->state));
6978 /* only try to write if we have something in the queue */
6979 if (!chunkqueue_is_empty(con->write_queue)) {
6981 @@ -1593,10 +1505,10 @@
6982 con->write_request_ts = srv->cur_ts;
6988 case CON_STATE_ERROR: /* transient */
6991 /* even if the connection was drop we still have to write it to the access log */
6992 if (con->http_status) {
6993 plugins_call_handle_request_done(srv, con);
6994 @@ -1612,19 +1524,19 @@
6995 SSL_shutdown(con->ssl);
6998 - log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
6999 - SSL_get_error(con->ssl, ret),
7000 + log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
7001 + SSL_get_error(con->ssl, ret),
7002 ERR_error_string(ERR_get_error(), NULL));
7012 - log_error_write(srv, __FILE__, __LINE__, "sd",
7013 - "emergency exit: direct",
7014 + log_error_write(srv, __FILE__, __LINE__, "sd",
7015 + "emergency exit: direct",
7019 @@ -1639,35 +1551,35 @@
7025 connection_reset(srv, con);
7028 /* close the connection */
7029 if ((con->keep_alive == 1) &&
7030 (0 == shutdown(con->fd, SHUT_WR))) {
7031 con->close_timeout_ts = srv->cur_ts;
7032 connection_set_state(srv, con, CON_STATE_CLOSE);
7035 if (srv->srvconf.log_state_handling) {
7036 - log_error_write(srv, __FILE__, __LINE__, "sd",
7037 + log_error_write(srv, __FILE__, __LINE__, "sd",
7038 "shutdown for fd", con->fd);
7041 connection_close(srv, con);
7045 con->keep_alive = 0;
7053 - log_error_write(srv, __FILE__, __LINE__, "sdd",
7054 + log_error_write(srv, __FILE__, __LINE__, "sdd",
7055 "unknown state:", con->fd, con->state);
7064 } else if (ostate == con->state) {
7065 @@ -1676,12 +1588,12 @@
7068 if (srv->srvconf.log_state_handling) {
7069 - log_error_write(srv, __FILE__, __LINE__, "sds",
7071 + log_error_write(srv, __FILE__, __LINE__, "sds",
7074 connection_get_state(con->state));
7078 switch(con->state) {
7079 case CON_STATE_READ_POST:
7080 case CON_STATE_READ:
7081 @@ -1689,11 +1601,11 @@
7082 fdevent_event_add(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_IN);
7084 case CON_STATE_WRITE:
7085 - /* request write-fdevent only if we really need it
7086 + /* request write-fdevent only if we really need it
7087 * - if we have data to write
7088 - * - if the socket is not writable yet
7089 + * - if the socket is not writable yet
7091 - if (!chunkqueue_is_empty(con->write_queue) &&
7092 + if (!chunkqueue_is_empty(con->write_queue) &&
7093 (con->is_writable == 0) &&
7094 (con->traffic_limit_reached == 0)) {
7095 fdevent_event_add(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_OUT);
7097 Property changes on: src/connections.c
7098 ___________________________________________________________________
7103 ===================================================================
7104 --- src/array.h (.../tags/lighttpd-1.4.11) (revision 1159)
7105 +++ src/array.h (.../branches/lighttpd-merge-1.4.x) (revision 1159)
7107 #define DATA_UNSET \
7110 - int is_index_key; /* 1 if key is a array index (autogenerated keys) */ \
7111 + int is_index_key; /* 1 if key is an array index (auto-generated keys) */ \
7112 struct data_unset *(*copy)(const struct data_unset *src); \
7113 void (* free)(struct data_unset *p); \
7114 void (* reset)(struct data_unset *p); \
7131 size_t next_power_of_2;
7132 int is_weakref; /* data is weakref, don't bother the data */
7161 COMP_SERVER_SOCKET, COMP_HTTP_URL, COMP_HTTP_HOST, COMP_HTTP_REFERER, COMP_HTTP_USERAGENT, COMP_HTTP_COOKIE, COMP_HTTP_REMOTEIP
7164 -/* $HTTP["host"] == "incremental.home.kneschke.de" { ... }
7165 +/* $HTTP["host"] == "incremental.home.kneschke.de" { ... }
7166 * for print: comp_key op string
7167 * for compare: comp cond string/regex
7170 typedef struct _data_config data_config;
7171 struct _data_config {
7186 int context_ndx; /* more or less like an id */
7190 /* for chaining only */
7207 @@ -120,13 +120,13 @@
7213 unsigned short port;
7220 int usage; /* fair-balancing needs the no. of connections active on this host */
7221 int last_used_ndx; /* round robin */
7224 Property changes on: src/array.h
7225 ___________________________________________________________________
7229 Index: src/mod_staticfile.c
7230 ===================================================================
7231 --- src/mod_staticfile.c (.../tags/lighttpd-1.4.11) (revision 1159)
7232 +++ src/mod_staticfile.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
7234 #include "http_chunk.h"
7235 #include "response.h"
7237 +#include "sys-files.h"
7238 +#include "sys-strings.h"
7240 * this is a staticfile for a lighttpd plugin
7255 plugin_config **config_storage;
7257 - plugin_config conf;
7259 + plugin_config conf;
7262 /* init the plugin data */
7263 INIT_FUNC(mod_staticfile_init) {
7267 p = calloc(1, sizeof(*p));
7270 p->range_buf = buffer_init();
7276 -/* detroy the plugin data */
7277 +/* destroy the plugin data */
7278 FREE_FUNC(mod_staticfile_free) {
7279 plugin_data *p = p_d;
7284 if (!p) return HANDLER_GO_ON;
7287 if (p->config_storage) {
7289 for (i = 0; i < srv->config_context->used; i++) {
7290 plugin_config *s = p->config_storage[i];
7293 array_free(s->exclude_ext);
7298 free(p->config_storage);
7300 buffer_free(p->range_buf);
7306 return HANDLER_GO_ON;
7310 SETDEFAULTS_FUNC(mod_staticfile_set_defaults) {
7311 plugin_data *p = p_d;
7314 - config_values_t cv[] = {
7316 + config_values_t cv[] = {
7317 { "static-file.exclude-extensions", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
7318 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
7322 if (!p) return HANDLER_ERROR;
7325 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
7328 for (i = 0; i < srv->config_context->used; i++) {
7332 s = calloc(1, sizeof(plugin_config));
7333 s->exclude_ext = array_init();
7336 cv[0].destination = s->exclude_ext;
7339 p->config_storage[i] = s;
7342 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
7343 return HANDLER_ERROR;
7348 return HANDLER_GO_ON;
7353 static int mod_staticfile_patch_connection(server *srv, connection *con, plugin_data *p) {
7355 plugin_config *s = p->config_storage[0];
7357 - PATCH(exclude_ext);
7360 + PATCH_OPTION(exclude_ext);
7362 /* skip the first, the global context */
7363 for (i = 1; i < srv->config_context->used; i++) {
7364 data_config *dc = (data_config *)srv->config_context->data[i];
7365 s = p->config_storage[i];
7368 /* condition didn't match */
7369 if (!config_check_cond(srv, con, dc)) continue;
7373 for (j = 0; j < dc->value->used; j++) {
7374 data_unset *du = dc->value->data[j];
7377 if (buffer_is_equal_string(du->key, CONST_STR_LEN("static-file.exclude-extensions"))) {
7378 - PATCH(exclude_ext);
7379 + PATCH_OPTION(exclude_ext);
7389 static int http_response_parse_range(server *srv, connection *con, plugin_data *p) {
7391 @@ -146,69 +145,69 @@
7393 stat_cache_entry *sce = NULL;
7394 buffer *content_type = NULL;
7397 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
7403 end = sce->st.st_size - 1;
7406 con->response.content_length = 0;
7409 if (NULL != (ds = (data_string *)array_get_element(con->response.headers, "Content-Type"))) {
7410 content_type = ds->value;
7414 for (s = con->request.http_range, error = 0;
7415 !error && *s && NULL != (minus = strchr(s, '-')); ) {
7424 le = strtoll(s, &err, 10);
7428 /* RFC 2616 - 14.35.1 */
7431 con->http_status = 416;
7433 } else if (*err == '\0') {
7438 end = sce->st.st_size - 1;
7439 start = sce->st.st_size + le;
7440 } else if (*err == ',') {
7445 end = sce->st.st_size - 1;
7446 start = sce->st.st_size + le;
7452 } else if (*(minus+1) == '\0' || *(minus+1) == ',') {
7456 la = strtoll(s, &err, 10);
7463 if (*(err + 1) == '\0') {
7467 end = sce->st.st_size - 1;
7471 } else if (*(err + 1) == ',') {
7476 end = sce->st.st_size - 1;
7479 @@ -220,64 +219,64 @@
7482 /* <start>-<stop> */
7485 la = strtoll(s, &err, 10);
7489 le = strtoll(minus+1, &err, 10);
7492 /* RFC 2616 - 14.35.1 */
7505 } else if (*err == ',') {
7528 if (start < 0) start = 0;
7531 /* RFC 2616 - 14.35.1 */
7532 if (end > sce->st.st_size - 1) end = sce->st.st_size - 1;
7535 if (start > sce->st.st_size - 1) {
7539 con->http_status = 416;
7546 /* write boundary-header */
7550 b = chunkqueue_get_append_buffer(con->write_queue);
7553 buffer_copy_string(b, "\r\n--");
7554 buffer_append_string(b, boundary);
7557 /* write Content-Range */
7558 buffer_append_string(b, "\r\nContent-Range: bytes ");
7559 buffer_append_off_t(b, start);
7560 @@ -285,54 +284,54 @@
7561 buffer_append_off_t(b, end);
7562 buffer_append_string(b, "/");
7563 buffer_append_off_t(b, sce->st.st_size);
7566 buffer_append_string(b, "\r\nContent-Type: ");
7567 buffer_append_string_buffer(b, content_type);
7570 /* write END-OF-HEADER */
7571 buffer_append_string(b, "\r\n\r\n");
7574 con->response.content_length += b->used - 1;
7580 chunkqueue_append_file(con->write_queue, con->physical.path, start, end - start + 1);
7581 con->response.content_length += end - start + 1;
7586 /* something went wrong */
7587 if (error) return -1;
7591 /* add boundary end */
7595 b = chunkqueue_get_append_buffer(con->write_queue);
7598 buffer_copy_string_len(b, "\r\n--", 4);
7599 buffer_append_string(b, boundary);
7600 buffer_append_string_len(b, "--\r\n", 4);
7603 con->response.content_length += b->used - 1;
7606 /* set header-fields */
7609 buffer_copy_string(p->range_buf, "multipart/byteranges; boundary=");
7610 buffer_append_string(p->range_buf, boundary);
7613 /* overwrite content-type */
7614 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(p->range_buf));
7616 /* add Content-Range-header */
7619 buffer_copy_string(p->range_buf, "bytes ");
7620 buffer_append_off_t(p->range_buf, start);
7621 buffer_append_string(p->range_buf, "-");
7622 buffer_append_off_t(p->range_buf, end);
7623 buffer_append_string(p->range_buf, "/");
7624 buffer_append_off_t(p->range_buf, sce->st.st_size);
7627 response_header_insert(srv, con, CONST_STR_LEN("Content-Range"), CONST_BUF_LEN(p->range_buf));
7630 @@ -347,12 +346,12 @@
7631 stat_cache_entry *sce = NULL;
7636 /* someone else has done a decision for us */
7637 if (con->http_status != 0) return HANDLER_GO_ON;
7638 if (con->uri.path->used == 0) return HANDLER_GO_ON;
7639 if (con->physical.path->used == 0) return HANDLER_GO_ON;
7642 /* someone else has handled this request */
7643 if (con->mode != DIRECT) return HANDLER_GO_ON;
7645 @@ -365,52 +364,52 @@
7647 return HANDLER_GO_ON;
7651 mod_staticfile_patch_connection(srv, con, p);
7654 s_len = con->uri.path->used - 1;
7657 /* ignore certain extensions */
7658 for (k = 0; k < p->conf.exclude_ext->used; k++) {
7659 - ds = (data_string *)p->conf.exclude_ext->data[k];
7661 + ds = (data_string *)p->conf.exclude_ext->data[k];
7663 if (ds->value->used == 0) continue;
7665 if (buffer_is_equal_right_len(con->physical.path, ds->value, ds->value->used - 1)) {
7666 return HANDLER_GO_ON;
7672 if (con->conf.log_request_handling) {
7673 log_error_write(srv, __FILE__, __LINE__, "s", "-- handling file as static file");
7677 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
7678 con->http_status = 403;
7681 log_error_write(srv, __FILE__, __LINE__, "sbsb",
7682 "not a regular file:", con->uri.path,
7683 "->", con->physical.path);
7686 return HANDLER_FINISHED;
7689 - /* we only handline regular files */
7691 + /* we only handle regular files */
7692 if (!S_ISREG(sce->st.st_mode)) {
7693 con->http_status = 404;
7696 if (con->conf.log_file_not_found) {
7697 log_error_write(srv, __FILE__, __LINE__, "sbsb",
7698 "not a regular file:", con->uri.path,
7703 return HANDLER_FINISHED;
7706 - /* mod_compress might set several data directly, don't overwrite them */
7708 + /* mod_compress might set several parameters directly; don't overwrite them */
7710 /* set response content-type, if not set already */
7712 if (NULL == array_get_element(con->response.headers, "Content-Type")) {
7713 @@ -420,15 +419,15 @@
7714 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
7719 if (NULL == array_get_element(con->response.headers, "ETag")) {
7720 /* generate e-tag */
7721 etag_mutate(con->physical.etag, sce->etag);
7724 response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
7726 response_header_overwrite(srv, con, CONST_STR_LEN("Accept-Ranges"), CONST_STR_LEN("bytes"));
7729 /* prepare header */
7730 if (NULL == (ds = (data_string *)array_get_element(con->response.headers, "Last-Modified"))) {
7731 mtime = strftime_cache_get(srv, sce->st.st_mtime);
7732 @@ -444,34 +443,34 @@
7733 /* check if we have a conditional GET */
7735 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If-Range"))) {
7736 - /* if the value is the same as our ETag, we do a Range-request,
7737 + /* if the value is the same as our ETag, we do a Range-request,
7738 * otherwise a full 200 */
7740 if (!buffer_is_equal(ds->value, con->physical.etag)) {
7741 do_range_request = 0;
7746 if (do_range_request) {
7747 /* content prepared, I'm done */
7748 con->file_finished = 1;
7751 if (0 == http_response_parse_range(srv, con, p)) {
7752 con->http_status = 206;
7754 return HANDLER_FINISHED;
7759 /* if we are still here, prepare body */
7761 - /* we add it here for all requests
7762 - * the HEAD request will drop it afterwards again
7764 + /* we add it here for all requests
7765 + * the HEAD request will drop it afterwards again
7767 http_chunk_append_file(srv, con, con->physical.path, 0, sce->st.st_size);
7770 con->file_finished = 1;
7773 return HANDLER_FINISHED;
7776 @@ -480,13 +479,13 @@
7777 int mod_staticfile_plugin_init(plugin *p) {
7778 p->version = LIGHTTPD_VERSION_ID;
7779 p->name = buffer_init_string("staticfile");
7782 p->init = mod_staticfile_init;
7783 p->handle_subrequest_start = mod_staticfile_subrequest;
7784 p->set_defaults = mod_staticfile_set_defaults;
7785 p->cleanup = mod_staticfile_free;
7794 Property changes on: src/mod_staticfile.c
7795 ___________________________________________________________________
7799 Index: src/data_integer.c
7800 ===================================================================
7801 --- src/data_integer.c (.../tags/lighttpd-1.4.11) (revision 1159)
7802 +++ src/data_integer.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
7805 static void data_integer_free(data_unset *d) {
7806 data_integer *ds = (data_integer *)d;
7809 buffer_free(ds->key);
7815 static void data_integer_reset(data_unset *d) {
7816 data_integer *ds = (data_integer *)d;
7819 /* reused integer elements */
7820 buffer_reset(ds->key);
7824 static int data_integer_insert_dup(data_unset *dst, data_unset *src) {
7836 data_integer *data_integer_init(void) {
7840 ds = calloc(1, sizeof(*ds));
7843 ds->key = buffer_init();
7847 ds->copy = data_integer_copy;
7848 ds->free = data_integer_free;
7849 ds->reset = data_integer_reset;
7850 ds->insert_dup = data_integer_insert_dup;
7851 ds->print = data_integer_print;
7852 ds->type = TYPE_INTEGER;
7858 Property changes on: src/data_integer.c
7859 ___________________________________________________________________
7864 Property changes on: src/connections.h
7865 ___________________________________________________________________
7869 Index: src/mod_alias.c
7870 ===================================================================
7871 --- src/mod_alias.c (.../tags/lighttpd-1.4.11) (revision 1159)
7872 +++ src/mod_alias.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
7877 +#include "sys-strings.h"
7879 /* plugin config for all request/connections */
7887 plugin_config **config_storage;
7889 - plugin_config conf;
7891 + plugin_config conf;
7894 /* init the plugin data */
7895 INIT_FUNC(mod_alias_init) {
7899 p = calloc(1, sizeof(*p));
7909 /* detroy the plugin data */
7910 FREE_FUNC(mod_alias_free) {
7911 plugin_data *p = p_d;
7914 if (!p) return HANDLER_GO_ON;
7917 if (p->config_storage) {
7921 for (i = 0; i < srv->config_context->used; i++) {
7922 plugin_config *s = p->config_storage[i];
7925 array_free(s->alias);
7930 free(p->config_storage);
7937 return HANDLER_GO_ON;
7941 SETDEFAULTS_FUNC(mod_alias_set_defaults) {
7942 plugin_data *p = p_d;
7945 - config_values_t cv[] = {
7947 + config_values_t cv[] = {
7948 { "alias.url", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
7949 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
7953 if (!p) return HANDLER_ERROR;
7956 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
7959 for (i = 0; i < srv->config_context->used; i++) {
7963 s = calloc(1, sizeof(plugin_config));
7964 - s->alias = array_init();
7965 + s->alias = array_init();
7966 cv[0].destination = s->alias;
7969 p->config_storage[i] = s;
7972 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
7973 return HANDLER_ERROR;
7975 @@ -110,76 +111,73 @@
7981 return HANDLER_GO_ON;
7986 static int mod_alias_patch_connection(server *srv, connection *con, plugin_data *p) {
7988 plugin_config *s = p->config_storage[0];
7993 + PATCH_OPTION(alias);
7995 /* skip the first, the global context */
7996 for (i = 1; i < srv->config_context->used; i++) {
7997 data_config *dc = (data_config *)srv->config_context->data[i];
7998 s = p->config_storage[i];
8001 /* condition didn't match */
8002 if (!config_check_cond(srv, con, dc)) continue;
8006 for (j = 0; j < dc->value->used; j++) {
8007 data_unset *du = dc->value->data[j];
8010 if (buffer_is_equal_string(du->key, CONST_STR_LEN("alias.url"))) {
8012 + PATCH_OPTION(alias);
8022 PHYSICALPATH_FUNC(mod_alias_physical_handler) {
8023 plugin_data *p = p_d;
8024 int uri_len, basedir_len;
8029 if (con->physical.path->used == 0) return HANDLER_GO_ON;
8032 mod_alias_patch_connection(srv, con, p);
8035 /* not to include the tailing slash */
8036 basedir_len = (con->physical.basedir->used - 1) - 1;
8037 uri_len = con->physical.path->used - 1 - basedir_len;
8038 uri_ptr = con->physical.path->ptr + basedir_len;
8041 for (k = 0; k < p->conf.alias->used; k++) {
8042 data_string *ds = (data_string *)p->conf.alias->data[k];
8043 int alias_len = ds->key->used - 1;
8046 if (alias_len > uri_len) continue;
8047 if (ds->key->used == 0) continue;
8050 if (0 == (con->conf.force_lowercase_filenames ?
8051 strncasecmp(uri_ptr, ds->key->ptr, alias_len) :
8052 strncmp(uri_ptr, ds->key->ptr, alias_len))) {
8056 buffer_copy_string_buffer(con->physical.basedir, ds->value);
8057 buffer_copy_string_buffer(srv->tmp_buf, ds->value);
8058 buffer_append_string(srv->tmp_buf, uri_ptr + alias_len);
8059 buffer_copy_string_buffer(con->physical.path, srv->tmp_buf);
8062 return HANDLER_GO_ON;
8068 return HANDLER_GO_ON;
8070 @@ -189,13 +187,13 @@
8071 int mod_alias_plugin_init(plugin *p) {
8072 p->version = LIGHTTPD_VERSION_ID;
8073 p->name = buffer_init_string("alias");
8076 p->init = mod_alias_init;
8077 p->handle_physical= mod_alias_physical_handler;
8078 p->set_defaults = mod_alias_set_defaults;
8079 p->cleanup = mod_alias_free;
8088 Property changes on: src/mod_alias.c
8089 ___________________________________________________________________
8093 Index: src/network.c
8094 ===================================================================
8095 --- src/network.c (.../tags/lighttpd-1.4.11) (revision 1159)
8096 +++ src/network.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
8098 #include <sys/types.h>
8099 #include <sys/stat.h>
8100 -#include <sys/time.h>
8104 -#include <unistd.h>
8111 #include "network.h"
8112 #include "fdevent.h"
8115 #include "network_backends.h"
8116 #include "sys-mmap.h"
8117 #include "sys-socket.h"
8118 +#include "sys-files.h"
8121 -# include <openssl/ssl.h>
8122 -# include <openssl/err.h>
8123 -# include <openssl/rand.h>
8124 +# include <openssl/ssl.h>
8125 +# include <openssl/err.h>
8126 +# include <openssl/rand.h>
8129 handler_t network_server_handle_fdevent(void *s, void *context, int revents) {
8131 server_socket *srv_socket = (server_socket *)context;
8139 if (revents != FDEVENT_IN) {
8140 - log_error_write(srv, __FILE__, __LINE__, "sdd",
8141 + log_error_write(srv, __FILE__, __LINE__, "sdd",
8142 "strange event for server socket",
8147 /* accept()s at most 100 connections directly
8149 - * we jump out after 100 to give the waiting connections a chance */
8150 + * we jump out after 100 to give the waiting connections a chance */
8151 for (loops = 0; loops < 100 && NULL != (con = connection_accept(srv, srv_socket)); loops++) {
8155 connection_state_machine(srv, con);
8158 switch(r = plugins_call_handle_joblist(srv, con)) {
8159 case HANDLER_FINISHED:
8163 int is_unix_domain_socket = 0;
8167 #ifdef SO_ACCEPTFILTER
8168 struct accept_filter_arg afa;
8173 WORD wVersionRequested;
8178 wVersionRequested = MAKEWORD( 2, 2 );
8181 err = WSAStartup( wVersionRequested, &wsaData );
8183 /* Tell the user that we could not find a usable */
8190 srv_socket = calloc(1, sizeof(*srv_socket));
8191 srv_socket->fd = -1;
8194 srv_socket->srv_token = buffer_init();
8195 buffer_copy_string_buffer(srv_socket->srv_token, host_token);
8199 buffer_copy_string_buffer(b, host_token);
8206 if (NULL == (sp = strrchr(b->ptr, ':'))) {
8207 log_error_write(srv, __FILE__, __LINE__, "sb", "value of $SERVER[\"socket\"] has to be \"ip:port\".", b);
8217 /* check for [ and ] */
8218 if (b->ptr[0] == '[' && *(sp-1) == ']') {
8230 port = strtol(sp, NULL, 10);
8232 if (host[0] == '/') {
8233 @@ -129,17 +130,17 @@
8234 is_unix_domain_socket = 1;
8235 } else if (port == 0 || port > 65535) {
8236 log_error_write(srv, __FILE__, __LINE__, "sd", "port out of range:", port);
8243 if (*host == '\0') host = NULL;
8245 if (is_unix_domain_socket) {
8246 #ifdef HAVE_SYS_UN_H
8248 srv_socket->addr.plain.sa_family = AF_UNIX;
8251 if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, 0))) {
8252 log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno));
8257 srv_socket->addr.plain.sa_family = AF_INET6;
8260 if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) {
8261 log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno));
8264 srv_socket->use_ipv6 = 1;
8269 if (srv_socket->fd == -1) {
8270 srv_socket->addr.plain.sa_family = AF_INET;
8271 if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) {
8272 @@ -170,16 +171,16 @@
8279 srv->cur_fds = srv_socket->fd;
8283 if (setsockopt(srv_socket->fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
8284 log_error_write(srv, __FILE__, __LINE__, "ss", "socketsockopt failed:", strerror(errno));
8289 switch(srv_socket->addr.plain.sa_family) {
8292 @@ -190,23 +191,23 @@
8294 struct addrinfo hints, *res;
8298 memset(&hints, 0, sizeof(hints));
8301 hints.ai_family = AF_INET6;
8302 hints.ai_socktype = SOCK_STREAM;
8303 hints.ai_protocol = IPPROTO_TCP;
8306 if (0 != (r = getaddrinfo(host, NULL, &hints, &res))) {
8307 - log_error_write(srv, __FILE__, __LINE__,
8308 - "sssss", "getaddrinfo failed: ",
8309 + log_error_write(srv, __FILE__, __LINE__,
8310 + "sssss", "getaddrinfo failed: ",
8311 gai_strerror(r), "'", host, "'");
8318 memcpy(&(srv_socket->addr), res->ai_addr, res->ai_addrlen);
8323 srv_socket->addr.ipv6.sin6_port = htons(port);
8324 @@ -221,33 +222,34 @@
8327 if (NULL == (he = gethostbyname(host))) {
8328 - log_error_write(srv, __FILE__, __LINE__,
8329 - "sds", "gethostbyname failed: ",
8330 + log_error_write(srv, __FILE__, __LINE__,
8331 + "sds", "gethostbyname failed: ",
8337 if (he->h_addrtype != AF_INET) {
8338 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype);
8343 if (he->h_length != sizeof(struct in_addr)) {
8344 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-length != sizeof(in_addr): ", he->h_length);
8349 memcpy(&(srv_socket->addr.ipv4.sin_addr.s_addr), he->h_addr_list[0], he->h_length);
8351 srv_socket->addr.ipv4.sin_port = htons(port);
8354 addr_len = sizeof(struct sockaddr_in);
8360 srv_socket->addr.un.sun_family = AF_UNIX;
8361 strcpy(srv_socket->addr.un.sun_path, host);
8365 addr_len = SUN_LEN(&srv_socket->addr.un);
8368 if (-1 != (fd = connect(srv_socket->fd, (struct sockaddr *) &(srv_socket->addr), addr_len))) {
8371 - log_error_write(srv, __FILE__, __LINE__, "ss",
8372 - "server socket is still in use:",
8373 + log_error_write(srv, __FILE__, __LINE__, "ss",
8374 + "server socket is still in use:",
8378 @@ -275,88 +277,89 @@
8382 - log_error_write(srv, __FILE__, __LINE__, "sds",
8383 - "testing socket failed:",
8384 + log_error_write(srv, __FILE__, __LINE__, "sds",
8385 + "testing socket failed:",
8386 host, strerror(errno));
8401 if (0 != bind(srv_socket->fd, (struct sockaddr *) &(srv_socket->addr), addr_len)) {
8402 switch(srv_socket->addr.plain.sa_family) {
8404 - log_error_write(srv, __FILE__, __LINE__, "sds",
8405 - "can't bind to socket:",
8406 + log_error_write(srv, __FILE__, __LINE__, "sds",
8407 + "can't bind to socket:",
8408 host, strerror(errno));
8411 - log_error_write(srv, __FILE__, __LINE__, "ssds",
8412 - "can't bind to port:",
8413 + log_error_write(srv, __FILE__, __LINE__, "ssds",
8414 + "can't bind to port:",
8415 host, port, strerror(errno));
8422 if (-1 == listen(srv_socket->fd, 128 * 8)) {
8423 log_error_write(srv, __FILE__, __LINE__, "ss", "listen failed: ", strerror(errno));
8430 if (srv->ssl_is_init == 0) {
8431 SSL_load_error_strings();
8433 srv->ssl_is_init = 1;
8436 if (0 == RAND_status()) {
8437 - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
8438 + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
8439 "not enough entropy in the pool");
8445 if (NULL == (s->ssl_ctx = SSL_CTX_new(SSLv23_server_method()))) {
8446 - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
8447 + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
8448 ERR_error_string(ERR_get_error(), NULL));
8453 if (buffer_is_empty(s->ssl_pemfile)) {
8454 log_error_write(srv, __FILE__, __LINE__, "s", "ssl.pemfile has to be set");
8459 if (!buffer_is_empty(s->ssl_ca_file)) {
8460 if (1 != SSL_CTX_load_verify_locations(s->ssl_ctx, s->ssl_ca_file->ptr, NULL)) {
8461 - log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
8462 + log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
8463 ERR_error_string(ERR_get_error(), NULL), s->ssl_ca_file);
8469 if (SSL_CTX_use_certificate_file(s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) {
8470 - log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
8471 + log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
8472 ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
8477 if (SSL_CTX_use_PrivateKey_file (s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) {
8478 - log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
8479 + log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
8480 ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile);
8485 if (SSL_CTX_check_private_key(s->ssl_ctx) != 1) {
8486 - log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:",
8487 + log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:",
8488 "Private key does not match the certificate public key, reason:",
8489 ERR_error_string(ERR_get_error(), NULL),
8491 @@ -364,15 +367,15 @@
8493 srv_socket->ssl_ctx = s->ssl_ctx;
8497 buffer_free(srv_socket->srv_token);
8503 - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
8505 + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
8506 "ssl requested but openssl support is not compiled in");
8512 @@ -390,10 +393,10 @@
8518 srv_socket->is_ssl = s->is_ssl;
8519 srv_socket->fde_ndx = -1;
8522 if (srv->srv_sockets.size == 0) {
8523 srv->srv_sockets.size = 4;
8524 srv->srv_sockets.used = 0;
8525 @@ -402,11 +405,10 @@
8526 srv->srv_sockets.size += 4;
8527 srv->srv_sockets.ptr = realloc(srv->srv_sockets.ptr, srv->srv_sockets.size * sizeof(server_socket));
8531 srv->srv_sockets.ptr[srv->srv_sockets.used++] = srv_socket;
8539 @@ -414,45 +416,58 @@
8541 for (i = 0; i < srv->srv_sockets.used; i++) {
8542 server_socket *srv_socket = srv->srv_sockets.ptr[i];
8545 if (srv_socket->fd != -1) {
8546 /* check if server fd are already registered */
8547 if (srv_socket->fde_ndx != -1) {
8548 fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd);
8549 fdevent_unregister(srv->ev, srv_socket->fd);
8553 close(srv_socket->fd);
8557 + if (srv_socket->is_ssl) {
8559 + SSL_CTX_free(srv_socket->ssl_ctx);
8563 buffer_free(srv_socket->srv_token);
8571 + ERR_free_strings();
8573 free(srv->srv_sockets.ptr);
8580 NETWORK_BACKEND_UNSET,
8582 NETWORK_BACKEND_WRITE,
8583 NETWORK_BACKEND_WRITEV,
8584 NETWORK_BACKEND_LINUX_SENDFILE,
8585 NETWORK_BACKEND_FREEBSD_SENDFILE,
8586 - NETWORK_BACKEND_SOLARIS_SENDFILEV
8587 + NETWORK_BACKEND_SOLARIS_SENDFILEV,
8589 + NETWORK_BACKEND_WIN32_SEND,
8590 + NETWORK_BACKEND_WIN32_TRANSMITFILE,
8591 } network_backend_t;
8593 int network_init(server *srv) {
8596 network_backend_t backend;
8599 - network_backend_t nb;
8601 - } network_backends[] = {
8604 + network_backend_t nb;
8606 + } network_backends[] = {
8607 /* lowest id wins */
8608 #if defined USE_LINUX_SENDFILE
8609 { NETWORK_BACKEND_LINUX_SENDFILE, "linux-sendfile" },
8610 @@ -466,21 +481,30 @@
8611 #if defined USE_WRITEV
8612 { NETWORK_BACKEND_WRITEV, "writev" },
8614 +#if defined USE_WRITE
8615 { NETWORK_BACKEND_WRITE, "write" },
8617 +#if defined USE_WIN32_TRANSMITFILE
8618 + { NETWORK_BACKEND_WIN32_TRANSMITFILE, "win32-transmitfile" },
8620 +#if defined USE_WIN32_SEND
8621 + { NETWORK_BACKEND_WIN32_SEND, "win32-send" },
8624 { NETWORK_BACKEND_UNSET, NULL }
8631 buffer_copy_string_buffer(b, srv->srvconf.bindhost);
8632 buffer_append_string(b, ":");
8633 buffer_append_long(b, srv->srvconf.port);
8636 if (0 != network_server_init(srv, b, srv->config_storage[0])) {
8643 srv->network_ssl_backend_write = network_write_chunkqueue_openssl;
8645 @@ -500,54 +524,80 @@
8646 if (NULL == network_backends[i].name) {
8647 /* we don't know it */
8649 - log_error_write(srv, __FILE__, __LINE__, "sb",
8650 - "server.network-backend has a unknown value:",
8651 + log_error_write(srv, __FILE__, __LINE__, "sb",
8652 + "server.network-backend has a unknown value:",
8653 srv->srvconf.network_backend);
8659 +#define SET_NETWORK_BACKEND(read, write) \
8660 + srv->network_backend_write = network_write_chunkqueue_##write;\
8661 + srv->network_backend_read = network_read_chunkqueue_##read
8663 +#define SET_NETWORK_BACKEND_SSL(read, write) \
8664 + srv->network_ssl_backend_write = network_write_chunkqueue_##write;\
8665 + srv->network_ssl_backend_read = network_read_chunkqueue_##read
8669 +#ifdef USE_WIN32_SEND
8670 + case NETWORK_BACKEND_WIN32_SEND:
8671 + SET_NETWORK_BACKEND(win32recv, win32send);
8673 +#ifdef USE_WIN32_TRANSMITFILE
8674 + case NETWORK_BACKEND_WIN32_TRANSMITFILE:
8675 + SET_NETWORK_BACKEND(win32recv, win32transmitfile);
8681 case NETWORK_BACKEND_WRITE:
8682 - srv->network_backend_write = network_write_chunkqueue_write;
8683 + SET_NETWORK_BACKEND(read, write);
8687 case NETWORK_BACKEND_WRITEV:
8688 - srv->network_backend_write = network_write_chunkqueue_writev;
8689 + SET_NETWORK_BACKEND(read, writev);
8692 #ifdef USE_LINUX_SENDFILE
8693 case NETWORK_BACKEND_LINUX_SENDFILE:
8694 - srv->network_backend_write = network_write_chunkqueue_linuxsendfile;
8695 + SET_NETWORK_BACKEND(read, linuxsendfile);
8698 #ifdef USE_FREEBSD_SENDFILE
8699 case NETWORK_BACKEND_FREEBSD_SENDFILE:
8700 - srv->network_backend_write = network_write_chunkqueue_freebsdsendfile;
8701 + SET_NETWORK_BACKEND(read, freebsdsendfile);
8704 #ifdef USE_SOLARIS_SENDFILEV
8705 case NETWORK_BACKEND_SOLARIS_SENDFILEV:
8706 - srv->network_backend_write = network_write_chunkqueue_solarissendfilev;
8707 + SET_NETWORK_BACKEND(read, solarissendfilev);
8715 + SET_NETWORK_BACKEND_SSL(openssl, openssl);
8718 /* check for $SERVER["socket"] */
8719 for (i = 1; i < srv->config_context->used; i++) {
8720 data_config *dc = (data_config *)srv->config_context->data[i];
8721 specific_config *s = srv->config_storage[i];
8726 if (COMP_SERVER_SOCKET != dc->comp) continue;
8729 if (dc->cond != CONFIG_COND_EQ) {
8730 log_error_write(srv, __FILE__, __LINE__, "s", "only == is allowed for $SERVER[\"socket\"].");
8736 @@ -558,36 +608,47 @@
8742 if (j == srv->srv_sockets.used) {
8743 if (0 != network_server_init(srv, dc->string, s)) return -1;
8751 int network_register_fdevents(server *srv) {
8754 if (-1 == fdevent_reset(srv->ev)) {
8758 /* register fdevents after reset */
8759 for (i = 0; i < srv->srv_sockets.used; i++) {
8760 server_socket *srv_socket = srv->srv_sockets.ptr[i];
8762 fdevent_register(srv->ev, srv_socket->fd, network_server_handle_fdevent, srv_socket);
8763 fdevent_event_add(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN);
8768 -int network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq) {
8770 +network_status_t network_read_chunkqueue(server *srv, connection *con, chunkqueue *cq) {
8771 + server_socket *srv_socket = con->srv_socket;
8773 + if (srv_socket->is_ssl) {
8775 + return srv->network_ssl_backend_read(srv, con, con->ssl, cq);
8777 + return NETWORK_STATUS_FATAL_ERROR;
8780 + return srv->network_backend_read(srv, con, con->fd, cq);
8784 +network_status_t network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq) {
8785 + network_status_t ret = NETWORK_STATUS_UNSET;
8791 server_socket *srv_socket = con->srv_socket;
8792 @@ -600,11 +661,11 @@
8793 joblist_append(srv, con);
8799 written = cq->bytes_out;
8803 /* Linux: put a cork into the socket as we want to combine the write() calls
8804 * but only if we really have multiple chunks
8807 setsockopt(con->fd, IPPROTO_TCP, TCP_CORK, &corked, sizeof(corked));
8812 if (srv_socket->is_ssl) {
8814 ret = srv->network_ssl_backend_write(srv, con, con->ssl, cq);
8815 @@ -621,12 +682,17 @@
8817 ret = srv->network_backend_write(srv, con, con->fd, cq);
8823 + case NETWORK_STATUS_WAIT_FOR_EVENT:
8824 + case NETWORK_STATUS_SUCCESS:
8825 chunkqueue_remove_finished_chunks(cq);
8826 - ret = chunkqueue_is_empty(cq) ? 0 : 1;
8837 @@ -639,13 +705,13 @@
8838 con->bytes_written_cur_second += written;
8840 *(con->conf.global_bytes_per_second_cnt_ptr) += written;
8843 if (con->conf.kbytes_per_second &&
8844 (con->bytes_written_cur_second > con->conf.kbytes_per_second * 1024)) {
8845 /* we reached the traffic limit */
8847 con->traffic_limit_reached = 1;
8848 joblist_append(srv, con);
8854 Property changes on: src/network.c
8855 ___________________________________________________________________
8859 Index: src/network.h
8860 ===================================================================
8861 --- src/network.h (.../tags/lighttpd-1.4.11) (revision 1159)
8862 +++ src/network.h (.../branches/lighttpd-merge-1.4.x) (revision 1159)
8867 -int network_write_chunkqueue(server *srv, connection *con, chunkqueue *c);
8868 +network_status_t network_write_chunkqueue(server *srv, connection *con, chunkqueue *c);
8869 +network_status_t network_read_chunkqueue(server *srv, connection *con, chunkqueue *c);
8871 int network_init(server *srv);
8872 int network_close(server *srv);
8874 Property changes on: src/network.h
8875 ___________________________________________________________________
8879 Index: src/fdevent_freebsd_kqueue.c
8880 ===================================================================
8881 --- src/fdevent_freebsd_kqueue.c (.../tags/lighttpd-1.4.11) (revision 1159)
8882 +++ src/fdevent_freebsd_kqueue.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
8884 #include <sys/types.h>
8886 -#include <unistd.h>
8905 ret = kevent(ev->kq_fd,
8914 if (filter == EVFILT_READ) {
8915 bitset_set_bit(ev->kq_bevents, fd);
8918 } else if (e == EVFILT_WRITE) {
8919 events |= FDEVENT_OUT;
8923 e = ev->kq_results[ndx].flags;
8926 @@ -152,10 +151,10 @@
8927 if (-1 == (ev->kq_fd = kqueue())) {
8928 fprintf(stderr, "%s.%d: kqueue failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
8929 __FILE__, __LINE__, strerror(errno));
8940 if (-1 == (ev->kq_fd = kqueue())) {
8941 fprintf(stderr, "%s.%d: kqueue failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
8942 __FILE__, __LINE__, strerror(errno));
8949 Property changes on: src/fdevent_freebsd_kqueue.c
8950 ___________________________________________________________________
8954 Index: src/configfile.c
8955 ===================================================================
8956 --- src/configfile.c (.../tags/lighttpd-1.4.11) (revision 1159)
8957 +++ src/configfile.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
8962 -#include <unistd.h>
8971 -#include "license.h"
8974 #include "configparser.h"
8975 #include "configfile.h"
8976 #include "proc_open.h"
8978 +#include "sys-files.h"
8979 +#include "sys-process.h"
8983 +#define PATH_MAX 64
8986 static int config_insert(server *srv) {
8989 buffer *stat_cache_string;
8991 - config_values_t cv[] = {
8993 + config_values_t cv[] = {
8994 { "server.bind", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 0 */
8995 { "server.errorlog", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 1 */
8996 { "server.errorfile-prefix", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 2 */
8998 { "server.tag", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 7 */
8999 { "server.use-ipv6", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 8 */
9000 { "server.modules", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_SERVER }, /* 9 */
9003 { "server.event-handler", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 10 */
9004 { "server.pid-file", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 11 */
9005 { "server.max-request-size", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 12 */
9007 { "server.max-keep-alive-requests", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 17 */
9008 { "server.name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 18 */
9009 { "server.max-keep-alive-idle", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 19 */
9012 { "server.max-read-idle", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 20 */
9013 { "server.max-write-idle", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 21 */
9014 { "server.error-handler-404", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 22 */
9016 { "mimetype.use-xattr", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 27 */
9017 { "mimetype.assign", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 28 */
9018 { "ssl.pemfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 29 */
9021 { "ssl.engine", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 30 */
9024 { "debug.log-file-not-found", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 31 */
9025 { "debug.log-request-handling", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 32 */
9026 { "debug.log-response-header", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 33 */
9027 { "debug.log-request-header", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 34 */
9030 { "server.protocol-http11", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 35 */
9031 { "debug.log-request-header-on-error", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 36 */
9032 { "debug.log-state-handling", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 37 */
9033 { "ssl.ca-file", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 38 */
9036 { "server.errorlog-use-syslog", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 39 */
9037 { "server.range-requests", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 40 */
9038 { "server.stat-cache-engine", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 41 */
9040 { "server.network-backend", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 43 */
9041 { "server.upload-dirs", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 44 */
9042 { "server.core-files", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 45 */
9044 + { "debug.log-condition-cache-handling", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 46 */
9046 { "server.host", "use server.bind instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
9047 { "server.docroot", "use server.document-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
9048 { "server.virtual-root", "load mod_simple_vhost and use simple-vhost.server-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
9050 { "server.groupid", "use server.groupname instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
9051 { "server.use-keep-alive", "use server.max-keep-alive-requests = 0 instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
9052 { "server.force-lower-case-files", "use server.force-lowercase-filenames instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
9055 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
9061 cv[0].destination = srv->srvconf.bindhost;
9062 cv[1].destination = srv->srvconf.errorlog_file;
9063 @@ -102,33 +105,33 @@
9064 cv[4].destination = srv->srvconf.username;
9065 cv[5].destination = srv->srvconf.groupname;
9066 cv[6].destination = &(srv->srvconf.port);
9069 cv[9].destination = srv->srvconf.modules;
9070 cv[10].destination = srv->srvconf.event_handler;
9071 cv[11].destination = srv->srvconf.pid_file;
9074 cv[13].destination = &(srv->srvconf.max_worker);
9075 cv[23].destination = &(srv->srvconf.max_fds);
9076 cv[36].destination = &(srv->srvconf.log_request_header_on_error);
9077 cv[37].destination = &(srv->srvconf.log_state_handling);
9080 cv[39].destination = &(srv->srvconf.errorlog_use_syslog);
9083 stat_cache_string = buffer_init();
9084 cv[41].destination = stat_cache_string;
9085 cv[43].destination = srv->srvconf.network_backend;
9086 cv[44].destination = srv->srvconf.upload_tempdirs;
9087 cv[45].destination = &(srv->srvconf.enable_cores);
9090 cv[42].destination = &(srv->srvconf.max_conns);
9091 cv[12].destination = &(srv->srvconf.max_request_size);
9092 srv->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
9094 assert(srv->config_storage);
9097 for (i = 0; i < srv->config_context->used; i++) {
9101 s = calloc(1, sizeof(specific_config));
9103 s->document_root = buffer_init();
9104 @@ -154,17 +157,18 @@
9105 s->global_kbytes_per_second = 0;
9106 s->global_bytes_per_second_cnt = 0;
9107 s->global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt;
9110 cv[2].destination = s->errorfile_prefix;
9113 cv[7].destination = s->server_tag;
9114 cv[8].destination = &(s->use_ipv6);
9120 cv[14].destination = s->document_root;
9121 cv[15].destination = &(s->force_lowercase_filenames);
9122 cv[16].destination = &(s->log_condition_handling);
9123 + cv[46].destination = &(s->log_condition_cache_handling);
9124 cv[17].destination = &(s->max_keep_alive_requests);
9125 cv[18].destination = s->server_name;
9126 cv[19].destination = &(s->max_keep_alive_idle);
9127 @@ -179,23 +183,23 @@
9128 cv[28].destination = s->mimetypes;
9129 cv[29].destination = s->ssl_pemfile;
9130 cv[30].destination = &(s->is_ssl);
9133 cv[31].destination = &(s->log_file_not_found);
9134 cv[32].destination = &(s->log_request_handling);
9135 cv[33].destination = &(s->log_response_header);
9136 cv[34].destination = &(s->log_request_header);
9139 cv[35].destination = &(s->allow_http11);
9140 cv[38].destination = s->ssl_ca_file;
9141 cv[40].destination = &(s->range_requests);
9144 srv->config_storage[i] = s;
9147 if (0 != (ret = config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv))) {
9153 if (buffer_is_empty(stat_cache_string)) {
9154 srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_SIMPLE;
9155 } else if (buffer_is_equal_string(stat_cache_string, CONST_STR_LEN("simple"))) {
9156 @@ -205,22 +209,22 @@
9157 } else if (buffer_is_equal_string(stat_cache_string, CONST_STR_LEN("disable"))) {
9158 srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_NONE;
9160 - log_error_write(srv, __FILE__, __LINE__, "sb",
9161 + log_error_write(srv, __FILE__, __LINE__, "sb",
9162 "server.stat-cache-engine can be one of \"disable\", \"simple\", \"fam\", but not:", stat_cache_string);
9163 ret = HANDLER_ERROR;
9167 buffer_free(stat_cache_string);
9176 -#define PATCH(x) con->conf.x = s->x
9178 + con->conf.x = s->x
9179 int config_setup_connection(server *srv, connection *con) {
9180 specific_config *s = srv->config_storage[0];
9183 PATCH(allow_http11);
9185 PATCH(document_root);
9186 @@ -236,20 +240,21 @@
9187 PATCH(kbytes_per_second);
9188 PATCH(global_kbytes_per_second);
9189 PATCH(global_bytes_per_second_cnt);
9192 con->conf.global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt;
9193 buffer_copy_string_buffer(con->server_name, s->server_name);
9196 PATCH(log_request_header);
9197 PATCH(log_response_header);
9198 PATCH(log_request_handling);
9199 PATCH(log_condition_handling);
9200 + PATCH(log_condition_cache_handling);
9201 PATCH(log_file_not_found);
9204 PATCH(range_requests);
9205 PATCH(force_lowercase_filenames);
9212 @@ -257,22 +262,22 @@
9214 int config_patch_connection(server *srv, connection *con, comp_key_t comp) {
9218 /* skip the first, the global context */
9219 for (i = 1; i < srv->config_context->used; i++) {
9220 data_config *dc = (data_config *)srv->config_context->data[i];
9221 specific_config *s = srv->config_storage[i];
9225 if (comp != dc->comp) continue;
9228 /* condition didn't match */
9229 if (!config_check_cond(srv, con, dc)) continue;
9233 for (j = 0; j < dc->value->used; j++) {
9234 data_unset *du = dc->value->data[j];
9237 if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.document-root"))) {
9238 PATCH(document_root);
9239 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.range-requests"))) {
9240 @@ -315,11 +320,13 @@
9241 PATCH(log_response_header);
9242 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-condition-handling"))) {
9243 PATCH(log_condition_handling);
9244 + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-condition-cache-handling"))) {
9245 + PATCH(log_condition_cache_handling);
9246 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-file-not-found"))) {
9247 PATCH(log_file_not_found);
9248 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.protocol-http11"))) {
9249 PATCH(allow_http11);
9250 - } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.force-lowercase-filenames"))) {
9251 + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.force-lowercase-filenames"))) {
9252 PATCH(force_lowercase_filenames);
9253 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.kbytes-per-second"))) {
9254 PATCH(global_kbytes_per_second);
9264 @@ -336,15 +343,15 @@
9270 const buffer *source;
9286 if (0 != stream_open(&(t->s), t->file)) {
9287 - log_error_write(srv, __FILE__, __LINE__, "sbss",
9288 + log_error_write(srv, __FILE__, __LINE__, "sbss",
9289 "opening configfile ", t->file, "failed:", strerror(errno));
9290 buffer_free(t->file);
9293 t->size = t->s.size;
9302 static int config_skip_comment(tokenizer_t *t) {
9304 assert(t->input[t->offset] == '#');
9305 - for (i = 1; t->input[t->offset + i] &&
9306 + for (i = 1; t->input[t->offset + i] &&
9307 (t->input[t->offset + i] != '\n' && t->input[t->offset + i] != '\r');
9310 @@ -411,44 +418,44 @@
9311 static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *token) {
9316 for (tid = 0; tid == 0 && t->offset < t->size && t->input[t->offset] ; ) {
9317 char c = t->input[t->offset];
9318 const char *start = NULL;
9325 if (t->input[t->offset + 1] == '>') {
9329 buffer_copy_string(token, "=>");
9332 tid = TK_ARRAY_ASSIGN;
9334 - log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
9335 + log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
9336 "source:", t->source,
9337 - "line:", t->line, "pos:", t->line_pos,
9338 + "line:", t->line, "pos:", t->line_pos,
9339 "use => for assignments in arrays");
9342 } else if (t->in_cond) {
9343 if (t->input[t->offset + 1] == '=') {
9347 buffer_copy_string(token, "==");
9351 } else if (t->input[t->offset + 1] == '~') {
9355 buffer_copy_string(token, "=~");
9360 - log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
9361 + log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
9362 "source:", t->source,
9363 - "line:", t->line, "pos:", t->line_pos,
9364 + "line:", t->line, "pos:", t->line_pos,
9365 "only =~ and == are allowed in the condition");
9368 @@ -456,51 +463,51 @@
9370 } else if (t->in_key) {
9374 buffer_copy_string_len(token, t->input + t->offset, 1);
9380 - log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
9381 + log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
9382 "source:", t->source,
9383 - "line:", t->line, "pos:", t->line_pos,
9384 + "line:", t->line, "pos:", t->line_pos,
9385 "unexpected equal-sign: =");
9394 if (t->input[t->offset + 1] == '=') {
9398 buffer_copy_string(token, "!=");
9402 } else if (t->input[t->offset + 1] == '~') {
9406 buffer_copy_string(token, "!~");
9411 - log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
9412 + log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
9413 "source:", t->source,
9414 - "line:", t->line, "pos:", t->line_pos,
9415 + "line:", t->line, "pos:", t->line_pos,
9416 "only !~ and != are allowed in the condition");
9422 - log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
9423 + log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
9424 "source:", t->source,
9425 - "line:", t->line, "pos:", t->line_pos,
9426 + "line:", t->line, "pos:", t->line_pos,
9427 "unexpected exclamation-marks: !");
9435 @@ -546,10 +553,10 @@
9437 if (t->in_brace > 0) {
9441 buffer_copy_string(token, "(COMMA)");
9448 @@ -557,70 +564,70 @@
9449 /* search for the terminating " */
9450 start = t->input + t->offset + 1;
9451 buffer_copy_string(token, "");
9454 for (i = 1; t->input[t->offset + i]; i++) {
9455 if (t->input[t->offset + i] == '\\' &&
9456 t->input[t->offset + i + 1] == '"') {
9459 buffer_append_string_len(token, start, t->input + t->offset + i - start);
9462 start = t->input + t->offset + i + 1;
9473 if (t->input[t->offset + i] == '"') {
9477 buffer_append_string_len(token, start, t->input + t->offset + i - start);
9484 if (t->input[t->offset + i] == '\0') {
9487 - log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
9489 + log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
9490 "source:", t->source,
9491 - "line:", t->line, "pos:", t->line_pos,
9492 + "line:", t->line, "pos:", t->line_pos,
9493 "missing closing quote");
9501 t->line_pos += i + 1;
9513 buffer_copy_string(token, "(");
9523 buffer_copy_string(token, ")");
9534 buffer_copy_string(token, "$");
9540 @@ -637,96 +644,88 @@
9549 buffer_copy_string(token, "{");
9562 buffer_copy_string(token, "}");
9574 buffer_copy_string(token, "[");
9587 buffer_copy_string(token, "]");
9592 t->line_pos += config_skip_comment(t);
9598 - for (i = 0; t->input[t->offset + i] &&
9599 + for (i = 0; t->input[t->offset + i] &&
9600 (isalpha((unsigned char)t->input[t->offset + i])
9604 if (i && t->input[t->offset + i]) {
9605 tid = TK_SRVVARNAME;
9606 buffer_copy_string_len(token, t->input + t->offset, i);
9613 - log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
9614 + log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
9615 "source:", t->source,
9616 - "line:", t->line, "pos:", t->line_pos,
9617 + "line:", t->line, "pos:", t->line_pos,
9618 "invalid character in condition");
9621 } else if (isdigit((unsigned char)c)) {
9622 /* take all digits */
9623 for (i = 0; t->input[t->offset + i] && isdigit((unsigned char)t->input[t->offset + i]); i++);
9626 /* was there it least a digit ? */
9627 - if (i && t->input[t->offset + i]) {
9632 buffer_copy_string_len(token, t->input + t->offset, i);
9639 - log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
9640 - "source:", t->source,
9641 - "line:", t->line, "pos:", t->line_pos,
9642 - "unexpected EOF");
9647 /* the key might consist of [-.0-9a-z] */
9648 - for (i = 0; t->input[t->offset + i] &&
9649 - (isalnum((unsigned char)t->input[t->offset + i]) ||
9650 + for (i = 0; t->input[t->offset + i] &&
9651 + (isalnum((unsigned char)t->input[t->offset + i]) ||
9652 t->input[t->offset + i] == '.' ||
9653 t->input[t->offset + i] == '_' || /* for env.* */
9654 t->input[t->offset + i] == '-'
9658 if (i && t->input[t->offset + i]) {
9659 buffer_copy_string_len(token, t->input + t->offset, i);
9662 if (strcmp(token->ptr, "include") == 0) {
9664 } else if (strcmp(token->ptr, "include_shell") == 0) {
9665 @@ -738,14 +737,14 @@
9675 - log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
9676 + log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
9677 "source:", t->source,
9678 - "line:", t->line, "pos:", t->line_pos,
9679 + "line:", t->line, "pos:", t->line_pos,
9680 "invalid character in variable name");
9683 @@ -753,16 +752,16 @@
9692 - log_error_write(srv, __FILE__, __LINE__, "sbsdsdbdd",
9693 + log_error_write(srv, __FILE__, __LINE__, "sbsdsdbdd",
9694 "source:", t->source,
9695 "line:", t->line, "pos:", t->line_pos,
9696 token, token->used - 1, tid);
9701 } else if (t->offset < t->size) {
9702 fprintf(stderr, "%s.%d: %d, %s\n",
9703 @@ -781,10 +780,11 @@
9704 pParser = configparserAlloc( malloc );
9705 lasttoken = buffer_init();
9706 token = buffer_init();
9708 while((1 == (ret = config_tokenizer(srv, t, &token_id, token))) && context->ok) {
9709 buffer_copy_string_buffer(lasttoken, token);
9710 configparser(pParser, token_id, token, context);
9713 token = buffer_init();
9716 @@ -797,14 +797,14 @@
9719 configparserFree(pParser, free);
9723 - log_error_write(srv, __FILE__, __LINE__, "sb",
9724 + log_error_write(srv, __FILE__, __LINE__, "sb",
9725 "configfile parser failed:", lasttoken);
9726 } else if (context->ok == 0) {
9727 - log_error_write(srv, __FILE__, __LINE__, "sbsdsdsb",
9728 + log_error_write(srv, __FILE__, __LINE__, "sbsdsdsb",
9729 "source:", t->source,
9730 - "line:", t->line, "pos:", t->line_pos,
9731 + "line:", t->line, "pos:", t->line_pos,
9732 "parser failed somehow near here:", lasttoken);
9747 if (0 != stream_open(&s, filename)) {
9748 - log_error_write(srv, __FILE__, __LINE__, "sbss",
9749 + log_error_write(srv, __FILE__, __LINE__, "sbss",
9750 "opening configfile ", filename, "failed:", strerror(errno));
9754 char oldpwd[PATH_MAX];
9756 if (NULL == getcwd(oldpwd, sizeof(oldpwd))) {
9757 - log_error_write(srv, __FILE__, __LINE__, "s",
9758 + log_error_write(srv, __FILE__, __LINE__, "s",
9759 "cannot get cwd", strerror(errno));
9765 if (0 != proc_open_buffer(&proc, cmd, NULL, out, NULL)) {
9766 - log_error_write(srv, __FILE__, __LINE__, "sbss",
9767 + log_error_write(srv, __FILE__, __LINE__, "sbss",
9768 "opening", source, "failed:", strerror(errno));
9771 @@ -896,13 +896,12 @@
9772 static void context_init(server *srv, config_t *context) {
9775 - context->configs_stack = array_init();
9776 - context->configs_stack->is_weakref = 1;
9777 + context->configs_stack = buffer_ptr_init(NULL);
9778 context->basedir = buffer_init();
9781 static void context_free(config_t *context) {
9782 - array_free(context->configs_stack);
9783 + buffer_ptr_free(context->configs_stack);
9784 buffer_free(context->basedir);
9787 @@ -918,18 +917,15 @@
9788 context_init(srv, &context);
9789 context.all_configs = srv->config_context;
9798 + /* use the current dir as basedir for all other includes
9800 + pos = strrchr(fn, DIR_SEPERATOR);
9803 buffer_copy_string_len(context.basedir, fn, pos - fn + 1);
9808 dc = data_config_init();
9809 buffer_copy_string(dc->key, "global");
9812 dpid->value = getpid();
9813 buffer_copy_string(dpid->key, "var.PID");
9814 array_insert_unique(srv->config, (data_unset *)dpid);
9817 dcwd = data_string_init();
9818 buffer_prepare_copy(dcwd->value, 1024);
9819 if (NULL != getcwd(dcwd->value->ptr, dcwd->value->size - 1)) {
9826 if (NULL != (modules = (data_array *)array_get_element(srv->config, "server.modules"))) {
9828 data_array *prepends;
9829 @@ -1026,22 +1022,23 @@
9830 buffer_copy_string(modules->key, "server.modules");
9831 array_insert_unique(srv->config, (data_unset *)modules);
9836 if (0 != config_insert(srv)) {
9845 int config_set_defaults(server *srv) {
9847 specific_config *s = srv->config_storage[0];
9848 struct stat st1, st2;
9850 - struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
9853 + struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
9855 /* - poll is most reliable
9856 * - select works everywhere
9857 * - linux-* are experimental
9858 @@ -1067,20 +1064,21 @@
9860 { FDEVENT_HANDLER_UNSET, NULL }
9864 - if (buffer_is_empty(s->document_root)) {
9865 - log_error_write(srv, __FILE__, __LINE__, "s",
9866 - "a default document-root has to be set");
9872 + if (buffer_is_empty(s->document_root)) {
9873 + log_error_write(srv, __FILE__, __LINE__, "s",
9874 + "a default document-root has to be set");
9879 if (buffer_is_empty(srv->srvconf.changeroot)) {
9880 - if (-1 == stat(s->document_root->ptr, &st1)) {
9881 - log_error_write(srv, __FILE__, __LINE__, "sb",
9882 + pathname_unix2local(s->document_root);
9883 + if (-1 == stat(s->document_root->ptr, &st1)) {
9884 + log_error_write(srv, __FILE__, __LINE__, "sbs",
9885 "base-docroot doesn't exist:",
9886 - s->document_root);
9887 + s->document_root, strerror(errno));
9891 @@ -1088,87 +1086,87 @@
9892 buffer_copy_string_buffer(srv->tmp_buf, srv->srvconf.changeroot);
9893 buffer_append_string_buffer(srv->tmp_buf, s->document_root);
9895 - if (-1 == stat(srv->tmp_buf->ptr, &st1)) {
9896 - log_error_write(srv, __FILE__, __LINE__, "sb",
9897 + if (-1 == stat(srv->tmp_buf->ptr, &st1)) {
9898 + log_error_write(srv, __FILE__, __LINE__, "sb",
9899 "base-docroot doesn't exist:",
9908 - buffer_copy_string_buffer(srv->tmp_buf, s->document_root);
9910 - buffer_to_lower(srv->tmp_buf);
9911 + buffer_copy_string_buffer(srv->tmp_buf, s->document_root);
9913 + buffer_to_lower(srv->tmp_buf);
9915 if (0 == stat(srv->tmp_buf->ptr, &st1)) {
9918 is_lower = buffer_is_equal(srv->tmp_buf, s->document_root);
9920 /* lower-case existed, check upper-case */
9921 - buffer_copy_string_buffer(srv->tmp_buf, s->document_root);
9922 + buffer_copy_string_buffer(srv->tmp_buf, s->document_root);
9924 - buffer_to_upper(srv->tmp_buf);
9925 + buffer_to_upper(srv->tmp_buf);
9927 /* we have to handle the special case that upper and lower-casing results in the same filename
9928 * as in server.document-root = "/" or "/12345/" */
9930 if (is_lower && buffer_is_equal(srv->tmp_buf, s->document_root)) {
9931 - /* lower-casing and upper-casing didn't result in
9932 - * an other filename, no need to stat(),
9933 + /* lower-casing and upper-casing didn't result in
9934 + * an other filename, no need to stat(),
9935 * just assume it is case-sensitive. */
9937 s->force_lowercase_filenames = 0;
9938 - } else if (0 == stat(srv->tmp_buf->ptr, &st2)) {
9939 + } else if (0 == stat(srv->tmp_buf->ptr, &st2)) {
9941 - /* upper case exists too, doesn't the FS handle this ? */
9943 - /* upper and lower have the same inode -> case-insensitve FS */
9945 - if (st1.st_ino == st2.st_ino) {
9946 - /* upper and lower have the same inode -> case-insensitve FS */
9948 - s->force_lowercase_filenames = 1;
9953 + /* upper case exists too, doesn't the FS handle this ? */
9955 + /* upper and lower have the same inode -> case-insensitve FS */
9957 + if (st1.st_ino == st2.st_ino) {
9958 + /* upper and lower have the same inode -> case-insensitve FS */
9960 + s->force_lowercase_filenames = 1;
9965 if (srv->srvconf.port == 0) {
9966 srv->srvconf.port = s->is_ssl ? 443 : 80;
9970 if (srv->srvconf.event_handler->used == 0) {
9971 /* choose a good default
9973 - * the event_handler list is sorted by 'goodness'
9975 + * the event_handler list is sorted by 'goodness'
9976 * taking the first available should be the best solution
9978 srv->event_handler = event_handlers[0].et;
9981 if (FDEVENT_HANDLER_UNSET == srv->event_handler) {
9982 - log_error_write(srv, __FILE__, __LINE__, "s",
9983 + log_error_write(srv, __FILE__, __LINE__, "s",
9984 "sorry, there is no event handler for this system");
9995 for (i = 0; event_handlers[i].name; i++) {
9996 if (0 == strcmp(event_handlers[i].name, srv->srvconf.event_handler->ptr)) {
9997 srv->event_handler = event_handlers[i].et;
10003 if (FDEVENT_HANDLER_UNSET == srv->event_handler) {
10004 - log_error_write(srv, __FILE__, __LINE__, "sb",
10005 - "the selected event-handler in unknown or not supported:",
10006 + log_error_write(srv, __FILE__, __LINE__, "sb",
10007 + "the selected event-handler in unknown or not supported:",
10008 srv->srvconf.event_handler );
10014 @@ -1176,19 +1174,19 @@
10016 if (buffer_is_empty(s->ssl_pemfile)) {
10017 /* PEM file is require */
10019 - log_error_write(srv, __FILE__, __LINE__, "s",
10021 + log_error_write(srv, __FILE__, __LINE__, "s",
10022 "ssl.pemfile has to be set");
10027 #ifndef USE_OPENSSL
10028 - log_error_write(srv, __FILE__, __LINE__, "s",
10029 + log_error_write(srv, __FILE__, __LINE__, "s",
10030 "ssl support is missing, recompile with --with-openssl");
10041 Property changes on: src/configfile.c
10042 ___________________________________________________________________
10043 Name: svn:eol-style
10046 Index: src/mod_trigger_b4_dl.c
10047 ===================================================================
10048 --- src/mod_trigger_b4_dl.c (.../tags/lighttpd-1.4.11) (revision 1159)
10049 +++ src/mod_trigger_b4_dl.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
10050 @@ -24,18 +24,18 @@
10053 * this is a trigger_b4_dl for a lighttpd plugin
10058 /* plugin config for all request/connections */
10061 buffer *db_filename;
10064 buffer *trigger_url;
10065 buffer *download_url;
10070 buffer *mc_namespace;
10071 #if defined(HAVE_PCRE_H)
10072 @@ -46,58 +46,58 @@
10076 -#if defined(HAVE_MEMCACHE_H)
10077 +#if defined(HAVE_MEMCACHE_H)
10078 struct memcache *mc;
10082 unsigned short trigger_timeout;
10083 unsigned short debug;
10093 plugin_config **config_storage;
10095 - plugin_config conf;
10097 + plugin_config conf;
10100 /* init the plugin data */
10101 INIT_FUNC(mod_trigger_b4_dl_init) {
10105 p = calloc(1, sizeof(*p));
10108 p->tmp_buf = buffer_init();
10114 /* detroy the plugin data */
10115 FREE_FUNC(mod_trigger_b4_dl_free) {
10116 plugin_data *p = p_d;
10121 if (!p) return HANDLER_GO_ON;
10124 if (p->config_storage) {
10126 for (i = 0; i < srv->config_context->used; i++) {
10127 plugin_config *s = p->config_storage[i];
10132 buffer_free(s->db_filename);
10133 buffer_free(s->download_url);
10134 buffer_free(s->trigger_url);
10135 buffer_free(s->deny_url);
10138 buffer_free(s->mc_namespace);
10139 array_free(s->mc_hosts);
10142 #if defined(HAVE_PCRE_H)
10143 if (s->trigger_regex) pcre_free(s->trigger_regex);
10144 if (s->download_regex) pcre_free(s->download_regex);
10145 @@ -108,16 +108,16 @@
10146 #if defined(HAVE_MEMCACHE_H)
10147 if (s->mc) mc_free(s->mc);
10153 free(p->config_storage);
10157 buffer_free(p->tmp_buf);
10163 return HANDLER_GO_ON;
10166 @@ -126,9 +126,9 @@
10167 SETDEFAULTS_FUNC(mod_trigger_b4_dl_set_defaults) {
10168 plugin_data *p = p_d;
10172 - config_values_t cv[] = {
10175 + config_values_t cv[] = {
10176 { "trigger-before-download.gdbm-filename", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
10177 { "trigger-before-download.trigger-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
10178 { "trigger-before-download.download-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
10179 @@ -139,18 +139,18 @@
10180 { "trigger-before-download.debug", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 7 */
10181 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
10185 if (!p) return HANDLER_ERROR;
10188 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
10191 for (i = 0; i < srv->config_context->used; i++) {
10193 #if defined(HAVE_PCRE_H)
10194 const char *errptr;
10199 s = calloc(1, sizeof(plugin_config));
10200 s->db_filename = buffer_init();
10201 s->download_url = buffer_init();
10202 @@ -158,7 +158,7 @@
10203 s->deny_url = buffer_init();
10204 s->mc_hosts = array_init();
10205 s->mc_namespace = buffer_init();
10208 cv[0].destination = s->db_filename;
10209 cv[1].destination = s->trigger_url;
10210 cv[2].destination = s->download_url;
10211 @@ -167,41 +167,41 @@
10212 cv[5].destination = s->mc_hosts;
10213 cv[6].destination = s->mc_namespace;
10214 cv[7].destination = &(s->debug);
10217 p->config_storage[i] = s;
10220 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
10221 return HANDLER_ERROR;
10223 #if defined(HAVE_GDBM_H)
10224 if (!buffer_is_empty(s->db_filename)) {
10225 if (NULL == (s->db = gdbm_open(s->db_filename->ptr, 4096, GDBM_WRCREAT | GDBM_NOLOCK, S_IRUSR | S_IWUSR, 0))) {
10226 - log_error_write(srv, __FILE__, __LINE__, "s",
10227 + log_error_write(srv, __FILE__, __LINE__, "s",
10228 "gdbm-open failed");
10229 return HANDLER_ERROR;
10233 -#if defined(HAVE_PCRE_H)
10234 +#if defined(HAVE_PCRE_H)
10235 if (!buffer_is_empty(s->download_url)) {
10236 if (NULL == (s->download_regex = pcre_compile(s->download_url->ptr,
10237 0, &errptr, &erroff, NULL))) {
10239 - log_error_write(srv, __FILE__, __LINE__, "sbss",
10240 - "compiling regex for download-url failed:",
10242 + log_error_write(srv, __FILE__, __LINE__, "sbss",
10243 + "compiling regex for download-url failed:",
10244 s->download_url, "pos:", erroff);
10245 return HANDLER_ERROR;
10250 if (!buffer_is_empty(s->trigger_url)) {
10251 if (NULL == (s->trigger_regex = pcre_compile(s->trigger_url->ptr,
10252 0, &errptr, &erroff, NULL))) {
10254 - log_error_write(srv, __FILE__, __LINE__, "sbss",
10255 - "compiling regex for trigger-url failed:",
10257 + log_error_write(srv, __FILE__, __LINE__, "sbss",
10258 + "compiling regex for trigger-url failed:",
10259 s->trigger_url, "pos:", erroff);
10262 return HANDLER_ERROR;
10265 @@ -211,100 +211,97 @@
10266 #if defined(HAVE_MEMCACHE_H)
10271 for (k = 0; k < s->mc_hosts->used; k++) {
10272 data_string *ds = (data_string *)s->mc_hosts->data[k];
10275 if (0 != mc_server_add4(s->mc, ds->value->ptr)) {
10276 - log_error_write(srv, __FILE__, __LINE__, "sb",
10277 - "connection to host failed:",
10278 + log_error_write(srv, __FILE__, __LINE__, "sb",
10279 + "connection to host failed:",
10283 return HANDLER_ERROR;
10287 - log_error_write(srv, __FILE__, __LINE__, "s",
10288 + log_error_write(srv, __FILE__, __LINE__, "s",
10289 "memcache support is not compiled in but trigger-before-download.memcache-hosts is set, aborting");
10290 return HANDLER_ERROR;
10296 #if (!defined(HAVE_GDBM_H) && !defined(HAVE_MEMCACHE_H)) || !defined(HAVE_PCRE_H)
10297 - log_error_write(srv, __FILE__, __LINE__, "s",
10298 + log_error_write(srv, __FILE__, __LINE__, "s",
10299 "(either gdbm or libmemcache) and pcre are require, but were not found, aborting");
10300 return HANDLER_ERROR;
10305 return HANDLER_GO_ON;
10308 -#define PATCH(x) \
10309 - p->conf.x = s->x;
10310 static int mod_trigger_b4_dl_patch_connection(server *srv, connection *con, plugin_data *p) {
10312 plugin_config *s = p->config_storage[0];
10315 #if defined(HAVE_GDBM)
10318 + PATCH_OPTION(db);
10320 #if defined(HAVE_PCRE_H)
10321 - PATCH(download_regex);
10322 - PATCH(trigger_regex);
10324 - PATCH(trigger_timeout);
10326 - PATCH(mc_namespace);
10328 + PATCH_OPTION(download_regex);
10329 + PATCH_OPTION(trigger_regex);
10331 + PATCH_OPTION(trigger_timeout);
10332 + PATCH_OPTION(deny_url);
10333 + PATCH_OPTION(mc_namespace);
10334 + PATCH_OPTION(debug);
10335 #if defined(HAVE_MEMCACHE_H)
10337 + PATCH_OPTION(mc);
10341 /* skip the first, the global context */
10342 for (i = 1; i < srv->config_context->used; i++) {
10343 data_config *dc = (data_config *)srv->config_context->data[i];
10344 s = p->config_storage[i];
10347 /* condition didn't match */
10348 if (!config_check_cond(srv, con, dc)) continue;
10352 for (j = 0; j < dc->value->used; j++) {
10353 data_unset *du = dc->value->data[j];
10355 if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.download-url"))) {
10356 #if defined(HAVE_PCRE_H)
10357 - PATCH(download_regex);
10358 + PATCH_OPTION(download_regex);
10360 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.trigger-url"))) {
10361 # if defined(HAVE_PCRE_H)
10362 - PATCH(trigger_regex);
10363 + PATCH_OPTION(trigger_regex);
10365 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.gdbm-filename"))) {
10366 #if defined(HAVE_GDBM_H)
10368 + PATCH_OPTION(db);
10370 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.trigger-timeout"))) {
10371 - PATCH(trigger_timeout);
10372 + PATCH_OPTION(trigger_timeout);
10373 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.debug"))) {
10375 + PATCH_OPTION(debug);
10376 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.deny-url"))) {
10378 + PATCH_OPTION(deny_url);
10379 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.memcache-namespace"))) {
10380 - PATCH(mc_namespace);
10381 + PATCH_OPTION(mc_namespace);
10382 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("trigger-before-download.memcache-hosts"))) {
10383 #if defined(HAVE_MEMCACHE_H)
10385 + PATCH_OPTION(mc);
10396 URIHANDLER_FUNC(mod_trigger_b4_dl_uri_handler) {
10397 plugin_data *p = p_d;
10398 @@ -315,20 +312,20 @@
10404 if (con->uri.path->used == 0) return HANDLER_GO_ON;
10407 mod_trigger_b4_dl_patch_connection(srv, con, p);
10410 if (!p->conf.trigger_regex || !p->conf.download_regex) return HANDLER_GO_ON;
10413 # if !defined(HAVE_GDBM_H) && !defined(HAVE_MEMCACHE_H)
10414 return HANDLER_GO_ON;
10415 # elif defined(HAVE_GDBM_H) && defined(HAVE_MEMCACHE_H)
10416 if (!p->conf.db && !p->conf.mc) return HANDLER_GO_ON;
10417 if (p->conf.db && p->conf.mc) {
10418 /* can't decide which one */
10421 return HANDLER_GO_ON;
10423 # elif defined(HAVE_GDBM_H)
10424 @@ -336,12 +333,12 @@
10426 if (!p->conf.mc) return HANDLER_GO_ON;
10430 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "X-Forwarded-For"))) {
10431 /* X-Forwarded-For contains the ip behind the proxy */
10434 remote_ip = ds->value->ptr;
10437 /* memcache can't handle spaces */
10439 remote_ip = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
10440 @@ -350,13 +347,13 @@
10441 if (p->conf.debug) {
10442 log_error_write(srv, __FILE__, __LINE__, "ss", "(debug) remote-ip:", remote_ip);
10446 /* check if URL is a trigger -> insert IP into DB */
10447 if ((n = pcre_exec(p->conf.trigger_regex, NULL, con->uri.path->ptr, con->uri.path->used - 1, 0, 0, ovec, 3 * N)) < 0) {
10448 if (n != PCRE_ERROR_NOMATCH) {
10449 log_error_write(srv, __FILE__, __LINE__, "sd",
10450 "execution error while matching:", n);
10453 return HANDLER_ERROR;
10456 @@ -364,34 +361,34 @@
10458 /* the trigger matched */
10462 key.dptr = (char *)remote_ip;
10463 key.dsize = strlen(remote_ip);
10466 val.dptr = (char *)&(srv->cur_ts);
10467 val.dsize = sizeof(srv->cur_ts);
10470 if (0 != gdbm_store(p->conf.db, key, val, GDBM_REPLACE)) {
10471 log_error_write(srv, __FILE__, __LINE__, "s",
10476 -# if defined(HAVE_MEMCACHE_H)
10477 +# if defined(HAVE_MEMCACHE_H)
10480 buffer_copy_string_buffer(p->tmp_buf, p->conf.mc_namespace);
10481 buffer_append_string(p->tmp_buf, remote_ip);
10484 for (i = 0; i < p->tmp_buf->used - 1; i++) {
10485 if (p->tmp_buf->ptr[i] == ' ') p->tmp_buf->ptr[i] = '-';
10489 if (p->conf.debug) {
10490 log_error_write(srv, __FILE__, __LINE__, "sb", "(debug) triggered IP:", p->tmp_buf);
10493 - if (0 != mc_set(p->conf.mc,
10494 + if (0 != mc_set(p->conf.mc,
10495 CONST_BUF_LEN(p->tmp_buf),
10496 (char *)&(srv->cur_ts), sizeof(srv->cur_ts),
10497 p->conf.trigger_timeout, 0)) {
10498 @@ -401,7 +398,7 @@
10504 /* check if URL is a download -> check IP in DB, update timestamp */
10505 if ((n = pcre_exec(p->conf.download_regex, NULL, con->uri.path->ptr, con->uri.path->used - 1, 0, 0, ovec, 3 * N)) < 0) {
10506 if (n != PCRE_ERROR_NOMATCH) {
10507 @@ -411,93 +408,93 @@
10510 /* the download uri matched */
10511 -# if defined(HAVE_GDBM_H)
10512 +# if defined(HAVE_GDBM_H)
10518 key.dptr = (char *)remote_ip;
10519 key.dsize = strlen(remote_ip);
10522 val = gdbm_fetch(p->conf.db, key);
10525 if (val.dptr == NULL) {
10526 /* not found, redirect */
10529 response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->conf.deny_url));
10532 con->http_status = 307;
10535 return HANDLER_FINISHED;
10539 last_hit = *(time_t *)(val.dptr);
10545 if (srv->cur_ts - last_hit > p->conf.trigger_timeout) {
10546 /* found, but timeout, redirect */
10549 response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->conf.deny_url));
10550 con->http_status = 307;
10554 if (0 != gdbm_delete(p->conf.db, key)) {
10555 log_error_write(srv, __FILE__, __LINE__, "s",
10561 return HANDLER_FINISHED;
10565 val.dptr = (char *)&(srv->cur_ts);
10566 val.dsize = sizeof(srv->cur_ts);
10569 if (0 != gdbm_store(p->conf.db, key, val, GDBM_REPLACE)) {
10570 log_error_write(srv, __FILE__, __LINE__, "s",
10576 -# if defined(HAVE_MEMCACHE_H)
10578 +# if defined(HAVE_MEMCACHE_H)
10584 buffer_copy_string_buffer(p->tmp_buf, p->conf.mc_namespace);
10585 buffer_append_string(p->tmp_buf, remote_ip);
10588 for (i = 0; i < p->tmp_buf->used - 1; i++) {
10589 if (p->tmp_buf->ptr[i] == ' ') p->tmp_buf->ptr[i] = '-';
10593 if (p->conf.debug) {
10594 log_error_write(srv, __FILE__, __LINE__, "sb", "(debug) checking IP:", p->tmp_buf);
10600 * memcached is do expiration for us, as long as we can fetch it every thing is ok
10601 - * and the timestamp is updated
10603 + * and the timestamp is updated
10606 - if (NULL == (r = mc_aget(p->conf.mc,
10607 + if (NULL == (r = mc_aget(p->conf.mc,
10608 CONST_BUF_LEN(p->tmp_buf)
10612 response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->conf.deny_url));
10615 con->http_status = 307;
10618 return HANDLER_FINISHED;
10625 /* set a new timeout */
10626 - if (0 != mc_set(p->conf.mc,
10627 + if (0 != mc_set(p->conf.mc,
10628 CONST_BUF_LEN(p->tmp_buf),
10629 (char *)&(srv->cur_ts), sizeof(srv->cur_ts),
10630 p->conf.trigger_timeout, 0)) {
10631 @@ -507,13 +504,13 @@
10644 return HANDLER_GO_ON;
10647 @@ -521,21 +518,21 @@
10648 TRIGGER_FUNC(mod_trigger_b4_dl_handle_trigger) {
10649 plugin_data *p = p_d;
10653 /* check DB each minute */
10654 if (srv->cur_ts % 60 != 0) return HANDLER_GO_ON;
10658 for (i = 0; i < srv->config_context->used; i++) {
10659 plugin_config *s = p->config_storage[i];
10660 datum key, val, okey;
10663 if (!s->db) continue;
10668 - /* according to the manual this loop + delete does delete all entries on its way
10671 + /* according to the manual this loop + delete does delete all entries on its way
10673 * we don't care as the next round will remove them. We don't have to perfect here.
10675 for (key = gdbm_firstkey(s->db); key.dptr; key = gdbm_nextkey(s->db, okey)) {
10676 @@ -544,21 +541,21 @@
10682 val = gdbm_fetch(s->db, key);
10685 last_hit = *(time_t *)(val.dptr);
10691 if (srv->cur_ts - last_hit > s->trigger_timeout) {
10692 gdbm_delete(s->db, key);
10698 if (okey.dptr) free(okey.dptr);
10701 /* reorg once a day */
10702 if ((srv->cur_ts % (60 * 60 * 24) != 0)) gdbm_reorganize(s->db);
10704 @@ -571,7 +568,7 @@
10705 int mod_trigger_b4_dl_plugin_init(plugin *p) {
10706 p->version = LIGHTTPD_VERSION_ID;
10707 p->name = buffer_init_string("trigger_b4_dl");
10710 p->init = mod_trigger_b4_dl_init;
10711 p->handle_uri_clean = mod_trigger_b4_dl_uri_handler;
10712 p->set_defaults = mod_trigger_b4_dl_set_defaults;
10713 @@ -579,8 +576,8 @@
10714 p->handle_trigger = mod_trigger_b4_dl_handle_trigger;
10716 p->cleanup = mod_trigger_b4_dl_free;
10725 Property changes on: src/mod_trigger_b4_dl.c
10726 ___________________________________________________________________
10727 Name: svn:eol-style
10730 Index: src/mod_evhost.c
10731 ===================================================================
10732 --- src/mod_evhost.c (.../tags/lighttpd-1.4.11) (revision 1159)
10733 +++ src/mod_evhost.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
10735 #include "response.h"
10736 #include "stat_cache.h"
10738 +#include "sys-files.h"
10741 /* unparsed pieces */
10742 buffer *path_pieces_raw;
10745 /* pieces for path creation */
10747 buffer **path_pieces;
10748 @@ -21,14 +23,14 @@
10751 plugin_config **config_storage;
10752 - plugin_config conf;
10753 + plugin_config conf;
10756 INIT_FUNC(mod_evhost_init) {
10760 p = calloc(1, sizeof(*p));
10763 p->tmp_buf = buffer_init();
10766 @@ -36,34 +38,34 @@
10768 FREE_FUNC(mod_evhost_free) {
10769 plugin_data *p = p_d;
10774 if (!p) return HANDLER_GO_ON;
10777 if (p->config_storage) {
10779 for (i = 0; i < srv->config_context->used; i++) {
10780 plugin_config *s = p->config_storage[i];
10785 if(s->path_pieces) {
10787 for (j = 0; j < s->len; j++) {
10788 buffer_free(s->path_pieces[j]);
10792 free(s->path_pieces);
10796 buffer_free(s->path_pieces_raw);
10801 free(p->config_storage);
10805 buffer_free(p->tmp_buf);
10808 @@ -73,30 +75,30 @@
10810 static void mod_evhost_parse_pattern(plugin_config *s) {
10811 char *ptr = s->path_pieces_raw->ptr,*pos;
10814 s->path_pieces = NULL;
10817 for(pos=ptr;*ptr;ptr++) {
10819 s->path_pieces = realloc(s->path_pieces,(s->len+2) * sizeof(*s->path_pieces));
10820 s->path_pieces[s->len] = buffer_init();
10821 s->path_pieces[s->len+1] = buffer_init();
10824 buffer_copy_string_len(s->path_pieces[s->len],pos,ptr-pos);
10828 buffer_copy_string_len(s->path_pieces[s->len+1],ptr++,2);
10837 s->path_pieces = realloc(s->path_pieces,(s->len+1) * sizeof(*s->path_pieces));
10838 s->path_pieces[s->len] = buffer_init();
10841 buffer_append_memory(s->path_pieces[s->len],pos,ptr-pos);
10847 @@ -104,9 +106,9 @@
10848 SETDEFAULTS_FUNC(mod_evhost_set_defaults) {
10849 plugin_data *p = p_d;
10857 * # define a pattern for the host url finding
10859 @@ -117,39 +119,39 @@
10860 * # %4 => subdomain 2 name
10862 * evhost.path-pattern = "/home/ckruse/dev/www/%3/htdocs/"
10867 - config_values_t cv[] = {
10869 + config_values_t cv[] = {
10870 { "evhost.path-pattern", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
10871 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
10875 if (!p) return HANDLER_ERROR;
10878 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
10881 for (i = 0; i < srv->config_context->used; i++) {
10885 s = calloc(1, sizeof(plugin_config));
10886 s->path_pieces_raw = buffer_init();
10887 s->path_pieces = NULL;
10891 cv[0].destination = s->path_pieces_raw;
10894 p->config_storage[i] = s;
10897 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
10898 return HANDLER_ERROR;
10902 if (s->path_pieces_raw->used != 0) {
10903 mod_evhost_parse_pattern(s);
10908 return HANDLER_GO_ON;
10911 @@ -158,7 +160,7 @@
10912 * - %0 - full hostname (authority w/o port)
10914 * - %2 - domain.tld
10919 static int mod_evhost_parse_host(connection *con,array *host) {
10920 @@ -168,7 +170,7 @@
10926 /* first, find the domain + tld */
10927 for(;ptr > con->uri.authority->ptr;ptr--) {
10929 @@ -179,18 +181,18 @@
10935 ds = data_string_init();
10936 buffer_copy_string(ds->key,"%0");
10939 /* if we stopped at a dot, skip the dot */
10940 if (*ptr == '.') ptr++;
10941 buffer_copy_string_len(ds->value, ptr, colon-ptr);
10944 array_insert_unique(host,(data_unset *)ds);
10947 /* if the : is not the start of the authority, go on parsing the hostname */
10950 if (colon != con->uri.authority->ptr) {
10951 for(ptr = colon - 1, i = 1; ptr > con->uri.authority->ptr; ptr--) {
10953 @@ -200,60 +202,56 @@
10954 buffer_copy_string(ds->key,"%");
10955 buffer_append_long(ds->key, i++);
10956 buffer_copy_string_len(ds->value,ptr+1,colon-ptr-1);
10959 array_insert_unique(host,(data_unset *)ds);
10966 /* if the . is not the first charactor of the hostname */
10967 if (colon != ptr) {
10968 ds = data_string_init();
10969 buffer_copy_string(ds->key,"%");
10970 buffer_append_long(ds->key, i++);
10971 buffer_copy_string_len(ds->value,ptr,colon-ptr);
10974 array_insert_unique(host,(data_unset *)ds);
10982 -#define PATCH(x) \
10983 - p->conf.x = s->x;
10984 static int mod_evhost_patch_connection(server *srv, connection *con, plugin_data *p) {
10986 plugin_config *s = p->config_storage[0];
10988 - PATCH(path_pieces);
10992 + PATCH_OPTION(path_pieces);
10993 + PATCH_OPTION(len);
10995 /* skip the first, the global context */
10996 for (i = 1; i < srv->config_context->used; i++) {
10997 data_config *dc = (data_config *)srv->config_context->data[i];
10998 s = p->config_storage[i];
11001 /* condition didn't match */
11002 if (!config_check_cond(srv, con, dc)) continue;
11006 for (j = 0; j < dc->value->used; j++) {
11007 data_unset *du = dc->value->data[j];
11010 if (buffer_is_equal_string(du->key, CONST_STR_LEN("evhost.path-pattern"))) {
11011 - PATCH(path_pieces);
11013 + PATCH_OPTION(path_pieces);
11014 + PATCH_OPTION(len);
11025 static handler_t mod_evhost_uri_handler(server *srv, connection *con, void *p_d) {
11026 plugin_data *p = p_d;
11028 @@ -261,29 +259,29 @@
11029 register char *ptr;
11031 stat_cache_entry *sce = NULL;
11034 /* not authority set */
11035 if (con->uri.authority->used == 0) return HANDLER_GO_ON;
11038 mod_evhost_patch_connection(srv, con, p);
11041 /* missing even default(global) conf */
11042 if (0 == p->conf.len) {
11043 return HANDLER_GO_ON;
11046 parsed_host = array_init();
11049 mod_evhost_parse_host(con, parsed_host);
11052 /* build document-root */
11053 buffer_reset(p->tmp_buf);
11056 for (i = 0; i < p->conf.len; i++) {
11057 ptr = p->conf.path_pieces[i]->ptr;
11062 if (*(ptr+1) == '%') {
11064 BUFFER_APPEND_STRING_CONST(p->tmp_buf,"%");
11065 @@ -298,11 +296,11 @@
11066 buffer_append_string_buffer(p->tmp_buf,p->conf.path_pieces[i]);
11070 - BUFFER_APPEND_SLASH(p->tmp_buf);
11073 + PATHNAME_APPEND_SLASH(p->tmp_buf);
11075 array_free(parsed_host);
11078 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->tmp_buf, &sce)) {
11079 log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), p->tmp_buf);
11081 @@ -310,11 +308,11 @@
11082 log_error_write(srv, __FILE__, __LINE__, "sb", "not a directory:", p->tmp_buf);
11088 buffer_copy_string_buffer(con->physical.doc_root, p->tmp_buf);
11092 return HANDLER_GO_ON;
11095 @@ -325,9 +323,9 @@
11096 p->set_defaults = mod_evhost_set_defaults;
11097 p->handle_docroot = mod_evhost_uri_handler;
11098 p->cleanup = mod_evhost_free;
11108 Property changes on: src/mod_evhost.c
11109 ___________________________________________________________________
11110 Name: svn:eol-style
11113 Index: src/splaytree.c
11114 ===================================================================
11115 --- src/splaytree.c (.../tags/lighttpd-1.4.11) (revision 1159)
11116 +++ src/splaytree.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
11117 @@ -56,19 +56,19 @@
11119 #define node_size splaytree_size
11121 -/* Splay using the key i (which may or may not be in the tree.)
11122 - * The starting root is t, and the tree used is defined by rat
11123 +/* Splay using the key i (which may or may not be in the tree.)
11124 + * The starting root is t, and the tree used is defined by rat
11125 * size fields are maintained */
11126 splay_tree * splaytree_splay (splay_tree *t, int i) {
11127 splay_tree N, *l, *r, *y;
11128 int comp, root_size, l_size, r_size;
11131 if (t == NULL) return t;
11132 N.left = N.right = NULL;
11134 root_size = node_size(t);
11135 l_size = r_size = 0;
11139 comp = compare(i, t->key);
11141 @@ -120,7 +120,7 @@
11143 r_size -= 1+node_size(y->right);
11147 l->right = t->left; /* assemble */
11148 r->left = t->right;
11151 Property changes on: src/splaytree.c
11152 ___________________________________________________________________
11153 Name: svn:eol-style
11157 ===================================================================
11158 --- src/chunk.c (.../tags/lighttpd-1.4.11) (revision 1159)
11159 +++ src/chunk.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
11162 * the network chunk-API
11169 #include <sys/types.h>
11170 #include <sys/stat.h>
11171 -#include <sys/mman.h>
11173 #include <stdlib.h>
11175 -#include <unistd.h>
11179 @@ -18,36 +16,39 @@
11183 +#include "sys-mmap.h"
11184 +#include "sys-files.h"
11186 chunkqueue *chunkqueue_init(void) {
11190 cq = calloc(1, sizeof(*cq));
11203 static chunk *chunk_init(void) {
11207 c = calloc(1, sizeof(*c));
11210 c->mem = buffer_init();
11211 c->file.name = buffer_init();
11213 c->file.mmap.start = MAP_FAILED;
11220 static void chunk_free(chunk *c) {
11224 buffer_free(c->mem);
11225 buffer_free(c->file.name);
11227 @@ -56,13 +57,13 @@
11229 static void chunk_reset(chunk *c) {
11233 buffer_reset(c->mem);
11235 if (c->file.is_temp && !buffer_is_empty(c->file.name)) {
11236 unlink(c->file.name->ptr);
11240 buffer_reset(c->file.name);
11242 if (c->file.fd != -1) {
11243 @@ -78,28 +79,28 @@
11245 void chunkqueue_free(chunkqueue *cq) {
11252 for (c = cq->first; c; ) {
11259 for (c = cq->unused; c; ) {
11269 static chunk *chunkqueue_get_unused_chunk(chunkqueue *cq) {
11272 - /* check if we have a unused chunk */
11274 + /* check if we have an unused chunk */
11278 @@ -109,18 +110,18 @@
11280 cq->unused_chunks--;
11287 static int chunkqueue_prepend_chunk(chunkqueue *cq, chunk *c) {
11288 c->next = cq->first;
11292 if (cq->last == NULL) {
11300 @@ -129,19 +130,19 @@
11301 cq->last->next = c;
11306 if (cq->first == NULL) {
11314 void chunkqueue_reset(chunkqueue *cq) {
11316 /* move everything to the unused queue */
11318 - /* mark all read written */
11320 + /* mark all read written */
11321 for (c = cq->first; c; c = c->next) {
11324 @@ -150,7 +151,7 @@
11326 c->offset = c->file.length;
11333 @@ -162,93 +163,93 @@
11335 int chunkqueue_append_file(chunkqueue *cq, buffer *fn, off_t offset, off_t len) {
11339 if (len == 0) return 0;
11342 c = chunkqueue_get_unused_chunk(cq);
11345 c->type = FILE_CHUNK;
11348 buffer_copy_string_buffer(c->file.name, fn);
11349 c->file.start = offset;
11350 c->file.length = len;
11354 chunkqueue_append_chunk(cq, c);
11360 int chunkqueue_append_buffer(chunkqueue *cq, buffer *mem) {
11364 if (mem->used == 0) return 0;
11367 c = chunkqueue_get_unused_chunk(cq);
11368 c->type = MEM_CHUNK;
11370 buffer_copy_string_buffer(c->mem, mem);
11373 chunkqueue_append_chunk(cq, c);
11379 int chunkqueue_prepend_buffer(chunkqueue *cq, buffer *mem) {
11383 if (mem->used == 0) return 0;
11386 c = chunkqueue_get_unused_chunk(cq);
11387 c->type = MEM_CHUNK;
11389 buffer_copy_string_buffer(c->mem, mem);
11392 chunkqueue_prepend_chunk(cq, c);
11398 int chunkqueue_append_mem(chunkqueue *cq, const char * mem, size_t len) {
11402 if (len == 0) return 0;
11405 c = chunkqueue_get_unused_chunk(cq);
11406 c->type = MEM_CHUNK;
11408 buffer_copy_string_len(c->mem, mem, len - 1);
11411 chunkqueue_append_chunk(cq, c);
11417 buffer * chunkqueue_get_prepend_buffer(chunkqueue *cq) {
11421 c = chunkqueue_get_unused_chunk(cq);
11424 c->type = MEM_CHUNK;
11426 buffer_reset(c->mem);
11429 chunkqueue_prepend_chunk(cq, c);
11435 buffer *chunkqueue_get_append_buffer(chunkqueue *cq) {
11439 c = chunkqueue_get_unused_chunk(cq);
11442 c->type = MEM_CHUNK;
11444 buffer_reset(c->mem);
11447 chunkqueue_append_chunk(cq, c);
11453 @@ -263,7 +264,7 @@
11454 chunk *chunkqueue_get_append_tempfile(chunkqueue *cq) {
11456 buffer *template = buffer_init_string("/var/tmp/lighttpd-upload-XXXXXX");
11459 c = chunkqueue_get_unused_chunk(cq);
11461 c->type = FILE_CHUNK;
11462 @@ -273,12 +274,12 @@
11465 /* we have several tempdirs, only if all of them fail we jump out */
11468 for (i = 0; i < cq->tempdirs->used; i++) {
11469 data_string *ds = (data_string *)cq->tempdirs->data[i];
11471 buffer_copy_string_buffer(template, ds->value);
11472 - BUFFER_APPEND_SLASH(template);
11473 + PATHNAME_APPEND_SLASH(template);
11474 BUFFER_APPEND_STRING_CONST(template, "lighttpd-upload-XXXXXX");
11476 if (-1 != (c->file.fd = mkstemp(template->ptr))) {
11477 @@ -300,7 +301,7 @@
11478 chunkqueue_append_chunk(cq, c);
11480 buffer_free(template);
11486 @@ -308,7 +309,7 @@
11487 off_t chunkqueue_length(chunkqueue *cq) {
11492 for (c = cq->first; c; c = c->next) {
11495 @@ -321,14 +322,14 @@
11504 off_t chunkqueue_written(chunkqueue *cq) {
11509 for (c = cq->first; c; c = c->next) {
11512 @@ -339,7 +340,7 @@
11521 @@ -358,9 +359,9 @@
11522 if (c->offset == (off_t)c->mem->used - 1) is_finished = 1;
11525 - if (c->offset == c->file.length) is_finished = 1;
11526 + if (c->offset == c->file.length) is_finished = 1;
11534 Property changes on: src/chunk.c
11535 ___________________________________________________________________
11536 Name: svn:eol-style
11539 Index: src/configfile.h
11540 ===================================================================
11541 --- src/configfile.h (.../tags/lighttpd-1.4.11) (revision 1159)
11542 +++ src/configfile.h (.../branches/lighttpd-merge-1.4.x) (revision 1159)
11546 array *all_configs;
11547 - array *configs_stack; /* to parse nested block */
11548 + buffer_ptr *configs_stack; /* to parse nested block */
11549 data_config *current; /* current started with { */
11553 Property changes on: src/configfile.h
11554 ___________________________________________________________________
11555 Name: svn:eol-style
11559 ===================================================================
11560 --- src/lemon.c (.../tags/lighttpd-1.4.11) (revision 1159)
11561 +++ src/lemon.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
11562 @@ -579,7 +579,7 @@
11565 /* Find a precedence symbol of every rule in the grammar.
11568 ** Those rules which have a precedence symbol coded in the input
11569 ** grammar using the "[symbol]" construct will already have the
11570 ** rp->precsym field filled. Other rules take as their precedence
11571 @@ -869,7 +869,7 @@
11572 cfp->status = INCOMPLETE;
11579 for(i=0; i<lemp->nstate; i++){
11580 @@ -900,7 +900,7 @@
11584 - /* Add all of the reduce actions
11585 + /* Add all of the reduce actions
11586 ** A reduce action is added for each element of the followset of
11587 ** a configuration which has its dot at the extreme right.
11589 @@ -1017,7 +1017,7 @@
11590 apx->type = RD_RESOLVED;
11595 apx->type==SH_RESOLVED ||
11596 apx->type==RD_RESOLVED ||
11597 apx->type==CONFLICT ||
11598 @@ -1350,7 +1350,7 @@
11599 OptInit(argv,options,stderr);
11601 printf("Lemon version 1.0\n");
11605 if( OptNArgs() < 1 ){
11606 fprintf(stderr,"Exactly one filename argument is required.\n");
11607 @@ -2031,7 +2031,7 @@
11611 - rp = (struct rule *)malloc( sizeof(struct rule) +
11612 + rp = (struct rule *)malloc( sizeof(struct rule) +
11613 sizeof(struct symbol*)*psp->nrhs + sizeof(char*)*psp->nrhs );
11615 ErrorMsg(psp->filename,psp->tokenlineno,
11616 @@ -2546,7 +2546,7 @@
11620 -/* Duplicate the input file without comments and without actions
11621 +/* Duplicate the input file without comments and without actions
11624 struct lemon *lemp;
11625 @@ -2822,7 +2822,7 @@
11626 PRIVATE FILE *tplt_open(lemp)
11627 struct lemon *lemp;
11634 @@ -2930,7 +2930,7 @@
11640 ** Generate code which executes when the rule "rp" is reduced. Write
11641 ** the code to "out". Make sure lineno stays up-to-date.
11643 @@ -3384,7 +3384,7 @@
11645 /* Output the yy_shift_ofst[] table */
11646 fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", mnTknOfst-1); lineno++;
11647 - fprintf(out, "static %s yy_shift_ofst[] = {\n",
11648 + fprintf(out, "static %s yy_shift_ofst[] = {\n",
11649 minimum_size_type(mnTknOfst-1, mxTknOfst)); lineno++;
11651 for(i=j=0; i<n; i++){
11652 @@ -3405,7 +3405,7 @@
11654 /* Output the yy_reduce_ofst[] table */
11655 fprintf(out, "#define YY_REDUCE_USE_DFLT (%d)\n", mnNtOfst-1); lineno++;
11656 - fprintf(out, "static %s yy_reduce_ofst[] = {\n",
11657 + fprintf(out, "static %s yy_reduce_ofst[] = {\n",
11658 minimum_size_type(mnNtOfst-1, mxNtOfst)); lineno++;
11660 for(i=j=0; i<n; i++){
11661 @@ -3480,7 +3480,7 @@
11662 tplt_xfer(lemp->name,in,out,&lineno);
11664 /* Generate code which executes every time a symbol is popped from
11665 - ** the stack while processing errors or while destroying the parser.
11666 + ** the stack while processing errors or while destroying the parser.
11667 ** (In other words, generate the %destructor actions)
11669 if( lemp->tokendest ){
11670 @@ -3522,7 +3522,7 @@
11671 tplt_print(out,lemp,lemp->overflow,lemp->overflowln,&lineno);
11672 tplt_xfer(lemp->name,in,out,&lineno);
11674 - /* Generate the table of rule information
11675 + /* Generate the table of rule information
11677 ** Note: This code depends on the fact that rules are number
11678 ** sequentually beginning with 0.
11679 @@ -3589,7 +3589,7 @@
11680 for(i=1; i<lemp->nterminal; i++){
11681 fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i);
11688 @@ -3630,7 +3630,7 @@
11694 /* Do not make a default if the number of rules to default
11695 ** is not at least 2 */
11696 if( nbest<2 ) continue;
11697 @@ -3781,7 +3781,7 @@
11701 - x1a->tbl = (x1node*)malloc(
11702 + x1a->tbl = (x1node*)malloc(
11703 (sizeof(x1node) + sizeof(x1node*))*1024 );
11706 @@ -3943,7 +3943,7 @@
11710 - x2a->tbl = (x2node*)malloc(
11711 + x2a->tbl = (x2node*)malloc(
11712 (sizeof(x2node) + sizeof(x2node*))*128 );
11715 @@ -4149,7 +4149,7 @@
11719 - x3a->tbl = (x3node*)malloc(
11720 + x3a->tbl = (x3node*)malloc(
11721 (sizeof(x3node) + sizeof(x3node*))*128 );
11724 @@ -4295,7 +4295,7 @@
11728 - x4a->tbl = (x4node*)malloc(
11729 + x4a->tbl = (x4node*)malloc(
11730 (sizeof(x4node) + sizeof(x4node*))*64 );
11734 Property changes on: src/lemon.c
11735 ___________________________________________________________________
11736 Name: svn:eol-style
11739 Index: src/sys-strings.h
11740 ===================================================================
11741 --- src/sys-strings.h (.../tags/lighttpd-1.4.11) (revision 0)
11742 +++ src/sys-strings.h (.../branches/lighttpd-merge-1.4.x) (revision 1159)
11744 +#ifndef _SYS_STRINGS_H_
11745 +#define _SYS_STRINGS_H_
11748 +#define strcasecmp stricmp
11749 +#define strncasecmp strnicmp
11750 +#define strtoll(p, e, b) _strtoi64(p, e, b)
11756 Property changes on: src/sys-strings.h
11757 ___________________________________________________________________
11758 Name: svn:eol-style
11761 Index: src/fdevent_solaris_devpoll.c
11762 ===================================================================
11763 --- src/fdevent_solaris_devpoll.c (.../tags/lighttpd-1.4.11) (revision 1159)
11764 +++ src/fdevent_solaris_devpoll.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
11766 #include <sys/types.h>
11768 -#include <unistd.h>
11769 #include <stdlib.h>
11771 #include <string.h>
11772 @@ -23,55 +22,55 @@
11774 static int fdevent_solaris_devpoll_event_del(fdevents *ev, int fde_ndx, int fd) {
11778 if (fde_ndx < 0) return -1;
11782 pfd.events = POLLREMOVE;
11786 if (-1 == write(ev->devpoll_fd, &pfd, sizeof(pfd))) {
11787 - fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n",
11788 - __FILE__, __LINE__,
11789 + fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n",
11790 + __FILE__, __LINE__,
11791 fd, strerror(errno));
11801 static int fdevent_solaris_devpoll_event_add(fdevents *ev, int fde_ndx, int fd, int events) {
11806 if (fde_ndx == -1) add = 1;
11810 pfd.events = events;
11814 if (-1 == write(ev->devpoll_fd, &pfd, sizeof(pfd))) {
11815 - fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n",
11816 - __FILE__, __LINE__,
11817 + fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n",
11818 + __FILE__, __LINE__,
11819 fd, strerror(errno));
11829 static int fdevent_solaris_devpoll_poll(fdevents *ev, int timeout_ms) {
11830 struct dvpoll dopoll;
11834 dopoll.dp_timeout = timeout_ms;
11835 dopoll.dp_nfds = ev->maxfds;
11836 dopoll.dp_fds = ev->devpollfds;
11839 ret = ioctl(ev->devpoll_fd, DP_POLL, &dopoll);
11845 @@ -85,11 +84,11 @@
11847 static int fdevent_solaris_devpoll_event_next_fdndx(fdevents *ev, int last_ndx) {
11853 i = (last_ndx < 0) ? 0 : last_ndx + 1;
11859 @@ -117,20 +116,20 @@
11860 ev->type = FDEVENT_HANDLER_SOLARIS_DEVPOLL;
11862 ev->x = fdevent_solaris_devpoll_##x;
11874 SET(event_next_fdndx);
11876 SET(event_get_revent);
11879 ev->devpollfds = malloc(sizeof(*ev->devpollfds) * ev->maxfds);
11882 if ((ev->devpoll_fd = open("/dev/poll", O_RDWR)) < 0) {
11883 fprintf(stderr, "%s.%d: opening /dev/poll failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
11884 __FILE__, __LINE__, strerror(errno));
11885 @@ -152,7 +151,7 @@
11887 fprintf(stderr, "%s.%d: solaris-devpoll not supported, try to set server.event-handler = \"poll\" or \"select\"\n",
11888 __FILE__, __LINE__);
11895 Property changes on: src/fdevent_solaris_devpoll.c
11896 ___________________________________________________________________
11897 Name: svn:eol-style
11900 Index: src/splaytree.h
11901 ===================================================================
11902 --- src/splaytree.h (.../tags/lighttpd-1.4.11) (revision 1159)
11903 +++ src/splaytree.h (.../branches/lighttpd-merge-1.4.x) (revision 1159)
11905 /* This macro returns the size of a node. Unlike "x->size", */
11906 /* it works even if x=NULL. The test could be avoided by using */
11907 /* a special version of NULL which was a real node with size 0. */
11913 Property changes on: src/splaytree.h
11914 ___________________________________________________________________
11915 Name: svn:eol-style
11919 ===================================================================
11920 --- src/chunk.h (.../tags/lighttpd-1.4.11) (revision 1159)
11921 +++ src/chunk.h (.../branches/lighttpd-merge-1.4.x) (revision 1159)
11924 typedef struct chunk {
11925 enum { UNUSED_CHUNK, MEM_CHUNK, FILE_CHUNK } type;
11928 buffer *mem; /* either the storage of the mem-chunk or the read-ahead buffer */
11931 @@ -16,28 +16,28 @@
11932 off_t length; /* octets to send from the starting offset */
11937 char *start; /* the start pointer of the mmap'ed area */
11938 size_t length; /* size of the mmap'ed area */
11939 - off_t offset; /* start is <n> octet away from the start of the file */
11940 + off_t offset; /* start is <n> octets away from the start of the file */
11943 - int is_temp; /* file is temporary and will be deleted if on cleanup */
11944 + int is_temp; /* file is temporary and will be deleted on cleanup */
11947 - off_t offset; /* octets sent from this chunk
11948 - the size of the chunk is either
11950 + off_t offset; /* octets sent from this chunk
11951 + the size of the chunk is either
11952 - mem-chunk: mem->used - 1
11953 - file-chunk: file.length
11957 struct chunk *next;
11966 size_t unused_chunks;
11969 Property changes on: src/chunk.h
11970 ___________________________________________________________________
11971 Name: svn:eol-style
11975 ===================================================================
11976 --- src/etag.c (.../tags/lighttpd-1.4.11) (revision 1159)
11977 +++ src/etag.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
11978 @@ -14,19 +14,19 @@
11979 buffer_append_off_t(etag, st->st_size);
11980 buffer_append_string_len(etag, CONST_STR_LEN("-"));
11981 buffer_append_long(etag, st->st_mtime);
11987 int etag_mutate(buffer *mut, buffer *etag) {
11991 for (h=0, i=0; i < etag->used; ++i) h = (h<<5)^(h>>27)^(etag->ptr[i]);
11995 buffer_copy_string_len(mut, CONST_STR_LEN("\""));
11996 buffer_append_long(mut, h);
11997 buffer_append_string_len(mut, CONST_STR_LEN("\""));
12003 Property changes on: src/etag.c
12004 ___________________________________________________________________
12005 Name: svn:eol-style
12008 Index: src/data_count.c
12009 ===================================================================
12010 --- src/data_count.c (.../tags/lighttpd-1.4.11) (revision 1159)
12011 +++ src/data_count.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
12012 @@ -16,53 +16,53 @@
12014 static void data_count_free(data_unset *d) {
12015 data_count *ds = (data_count *)d;
12018 buffer_free(ds->key);
12024 static void data_count_reset(data_unset *d) {
12025 data_count *ds = (data_count *)d;
12028 buffer_reset(ds->key);
12034 static int data_count_insert_dup(data_unset *dst, data_unset *src) {
12035 data_count *ds_dst = (data_count *)dst;
12036 data_count *ds_src = (data_count *)src;
12039 ds_dst->count += ds_src->count;
12048 static void data_count_print(const data_unset *d, int depth) {
12049 data_count *ds = (data_count *)d;
12053 fprintf(stderr, "count(%d)", ds->count);
12057 data_count *data_count_init(void) {
12061 ds = calloc(1, sizeof(*ds));
12064 ds->key = buffer_init();
12068 ds->copy = data_count_copy;
12069 ds->free = data_count_free;
12070 ds->reset = data_count_reset;
12071 ds->insert_dup = data_count_insert_dup;
12072 ds->print = data_count_print;
12073 ds->type = TYPE_COUNT;
12079 Property changes on: src/data_count.c
12080 ___________________________________________________________________
12081 Name: svn:eol-style
12084 Index: src/mod_skeleton.c
12085 ===================================================================
12086 --- src/mod_skeleton.c (.../tags/lighttpd-1.4.11) (revision 1159)
12087 +++ src/mod_skeleton.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
12088 @@ -14,13 +14,13 @@
12091 * this is a skeleton for a lighttpd plugin
12094 * just replaces every occurance of 'skeleton' by your plugin name
12100 * :%s/skeleton/myhandler/
12106 @@ -33,12 +33,12 @@
12115 plugin_config **config_storage;
12117 - plugin_config conf;
12119 + plugin_config conf;
12123 @@ -47,36 +47,36 @@
12125 static handler_ctx * handler_ctx_init() {
12126 handler_ctx * hctx;
12129 hctx = calloc(1, sizeof(*hctx));
12135 static void handler_ctx_free(handler_ctx *hctx) {
12141 /* init the plugin data */
12142 INIT_FUNC(mod_skeleton_init) {
12146 p = calloc(1, sizeof(*p));
12149 p->match_buf = buffer_init();
12155 /* detroy the plugin data */
12156 FREE_FUNC(mod_skeleton_free) {
12157 plugin_data *p = p_d;
12162 if (!p) return HANDLER_GO_ON;
12165 if (p->config_storage) {
12168 @@ -84,18 +84,18 @@
12169 plugin_config *s = p->config_storage[i];
12174 array_free(s->match);
12179 free(p->config_storage);
12183 buffer_free(p->match_buf);
12189 return HANDLER_GO_ON;
12192 @@ -104,91 +104,88 @@
12193 SETDEFAULTS_FUNC(mod_skeleton_set_defaults) {
12194 plugin_data *p = p_d;
12197 - config_values_t cv[] = {
12199 + config_values_t cv[] = {
12200 { "skeleton.array", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
12201 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
12205 if (!p) return HANDLER_ERROR;
12208 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
12211 for (i = 0; i < srv->config_context->used; i++) {
12215 s = calloc(1, sizeof(plugin_config));
12216 s->match = array_init();
12219 cv[0].destination = s->match;
12222 p->config_storage[i] = s;
12225 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
12226 return HANDLER_ERROR;
12231 return HANDLER_GO_ON;
12234 -#define PATCH(x) \
12235 - p->conf.x = s->x;
12236 static int mod_skeleton_patch_connection(server *srv, connection *con, plugin_data *p) {
12238 plugin_config *s = p->config_storage[0];
12243 + PATCH_OPTION(match);
12245 /* skip the first, the global context */
12246 for (i = 1; i < srv->config_context->used; i++) {
12247 data_config *dc = (data_config *)srv->config_context->data[i];
12248 s = p->config_storage[i];
12251 /* condition didn't match */
12252 if (!config_check_cond(srv, con, dc)) continue;
12256 for (j = 0; j < dc->value->used; j++) {
12257 data_unset *du = dc->value->data[j];
12260 if (buffer_is_equal_string(du->key, CONST_STR_LEN("skeleton.array"))) {
12262 + PATCH_OPTION(match);
12272 URIHANDLER_FUNC(mod_skeleton_uri_handler) {
12273 plugin_data *p = p_d;
12280 if (con->uri.path->used == 0) return HANDLER_GO_ON;
12283 mod_skeleton_patch_connection(srv, con, p);
12285 s_len = con->uri.path->used - 1;
12288 for (k = 0; k < p->conf.match->used; k++) {
12289 data_string *ds = (data_string *)p->conf.match->data[k];
12290 int ct_len = ds->value->used - 1;
12293 if (ct_len > s_len) continue;
12294 if (ds->value->used == 0) continue;
12297 if (0 == strncmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
12298 con->http_status = 403;
12301 return HANDLER_FINISHED;
12307 return HANDLER_GO_ON;
12309 @@ -198,13 +195,13 @@
12310 int mod_skeleton_plugin_init(plugin *p) {
12311 p->version = LIGHTTPD_VERSION_ID;
12312 p->name = buffer_init_string("skeleton");
12315 p->init = mod_skeleton_init;
12316 p->handle_uri_clean = mod_skeleton_uri_handler;
12317 p->set_defaults = mod_skeleton_set_defaults;
12318 p->cleanup = mod_skeleton_free;
12327 Property changes on: src/mod_skeleton.c
12328 ___________________________________________________________________
12329 Name: svn:eol-style
12332 Index: src/mod_scgi.c
12333 ===================================================================
12334 --- src/mod_scgi.c (.../tags/lighttpd-1.4.11) (revision 1159)
12335 +++ src/mod_scgi.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
12337 #include <sys/types.h>
12338 -#include <unistd.h>
12341 #include <string.h>
12345 #include "sys-socket.h"
12346 +#include "sys-files.h"
12347 +#include "sys-strings.h"
12348 +#include "sys-process.h"
12351 #ifndef UNIX_PATH_MAX
12352 # define UNIX_PATH_MAX 108
12354 @@ -46,30 +47,29 @@
12355 enum {EOL_UNSET, EOL_N, EOL_RN};
12363 * - add timeout for a connect to a non-scgi process
12364 * (use state_timestamp + state)
12369 typedef struct scgi_proc {
12370 size_t id; /* id will be between 1 and max_procs */
12371 buffer *socket; /* config.socket + "-" + id */
12372 unsigned port; /* config.port + pno */
12375 pid_t pid; /* PID of the spawned process (0 if not spawned locally) */
12378 size_t load; /* number of requests waiting on this process */
12380 time_t last_used; /* see idle_timeout */
12381 size_t requests; /* see max_requests */
12382 struct scgi_proc *prev, *next; /* see first */
12385 time_t disable_ts; /* replace by host->something */
12390 enum { PROC_STATE_UNSET, /* init-phase */
12392 PROC_STATE_KILLED, /* was killed as we don't have the load anymore */
12393 PROC_STATE_DIED, /* marked as dead, should be restarted */
12394 PROC_STATE_DISABLED /* proc disabled as it resulted in an error */
12400 @@ -86,20 +86,20 @@
12401 * sorted by lowest load
12403 * whenever a job is done move it up in the list
12404 - * until it is sorted, move it down as soon as the
12405 + * until it is sorted, move it down as soon as the
12408 - scgi_proc *first;
12409 - scgi_proc *unused_procs;
12410 + scgi_proc *first;
12411 + scgi_proc *unused_procs;
12415 * spawn at least min_procs, at max_procs.
12417 - * as soon as the load of the first entry
12418 + * as soon as the load of the first entry
12419 * is max_load_per_proc we spawn a new one
12420 - * and add it to the first entry and give it
12421 + * and add it to the first entry and give it
12427 unsigned short min_procs;
12428 @@ -111,44 +111,44 @@
12431 * kick the process from the list if it was not
12432 - * used for idle_timeout until min_procs is
12433 + * used for idle_timeout until min_procs is
12434 * reached. this helps to get the processlist
12435 * small again we had a small peak load.
12440 unsigned short idle_timeout;
12444 * time after a disabled remote connection is tried to be re-enabled
12452 unsigned short disable_time;
12455 * same scgi processes get a little bit larger
12456 - * than wanted. max_requests_per_proc kills a
12457 + * than wanted. max_requests_per_proc kills a
12458 * process after a number of handled requests.
12461 size_t max_requests_per_proc;
12472 - * if host is one of the local IP adresses the
12473 + * if host is one of the local IP adresses the
12474 * whole connection is local
12476 * if tcp/ip should be used host AND port have
12477 - * to be specified
12481 + * to be specified
12485 unsigned short port;
12488 @@ -161,7 +161,7 @@
12490 buffer *unixsocket;
12492 - /* if socket is local we can start the scgi
12493 + /* if socket is local we can start the scgi
12496 * bin-path is the path to the binary
12497 @@ -169,19 +169,19 @@
12498 * check min_procs and max_procs for the number
12499 * of process to start-up
12501 - buffer *bin_path;
12503 - /* bin-path is set bin-environment is taken to
12504 + buffer *bin_path;
12506 + /* bin-path is set bin-environment is taken to
12507 * create the environement before starting the
12515 array *bin_env_copy;
12519 - * docroot-translation between URL->phys and the
12520 + * docroot-translation between URL->phys and the
12524 @@ -192,7 +192,7 @@
12528 - * check_local tell you if the phys file is stat()ed
12529 + * check_local tell you if the phys file is stat()ed
12530 * or not. FastCGI doesn't care if the service is
12531 * remote. If the web-server side doesn't contain
12532 * the scgi-files we should not stat() for them
12533 @@ -202,33 +202,33 @@
12536 * append PATH_INFO to SCRIPT_FILENAME
12539 * php needs this if cgi.fix_pathinfo is provied
12545 ssize_t load; /* replace by host->load */
12547 size_t max_id; /* corresponds most of the time to
12551 only if a process is killed max_id waits for the process itself
12552 to die and decrements its afterwards */
12553 } scgi_extension_host;
12556 * one extension can have multiple hosts assigned
12557 - * one host can spawn additional processes on the same
12558 + * one host can spawn additional processes on the same
12559 * socket (if we control it)
12561 * ext -> host -> procs
12564 - * if the scgi process is remote that whole goes down
12565 + * if the scgi process is remote that whole goes down
12568 * ext -> host -> procs
12572 * in case of PHP and FCGI_CHILDREN we have again a procs
12573 * but we don't control it directly.
12574 @@ -239,7 +239,7 @@
12575 buffer *key; /* like .php */
12577 scgi_extension_host **hosts;
12583 @@ -253,14 +253,14 @@
12601 @@ -268,52 +268,51 @@
12602 /* generic plugin data, shared between all connections */
12611 buffer *parse_response;
12614 plugin_config **config_storage;
12617 plugin_config conf; /* this is only used as long as no handler_ctx is setup */
12620 /* connection specific data */
12621 -typedef enum { FCGI_STATE_INIT, FCGI_STATE_CONNECT, FCGI_STATE_PREPARE_WRITE,
12622 - FCGI_STATE_WRITE, FCGI_STATE_READ
12623 +typedef enum { FCGI_STATE_INIT, FCGI_STATE_CONNECT, FCGI_STATE_PREPARE_WRITE,
12624 + FCGI_STATE_WRITE, FCGI_STATE_READ
12625 } scgi_connection_state_t;
12628 - buffer *response;
12629 + buffer *response;
12630 size_t response_len;
12632 int response_padding;
12636 scgi_extension_host *host;
12639 scgi_connection_state_t state;
12640 time_t state_timestamp;
12643 int reconnects; /* number of reconnect attempts */
12650 buffer *response_header;
12653 int delayed; /* flag to mark that the connect() is delayed */
12657 int fd; /* fd to the scgi process */
12658 int fde_ndx; /* index into the fd-event buffer */
12664 plugin_config conf;
12667 connection *remote_conn; /* dumb pointer */
12668 plugin_data *plugin_data; /* dumb pointer */
12670 @@ -328,28 +327,28 @@
12672 static handler_ctx * handler_ctx_init() {
12673 handler_ctx * hctx;
12676 hctx = calloc(1, sizeof(*hctx));
12680 hctx->fde_ndx = -1;
12683 hctx->response = buffer_init();
12684 hctx->response_header = buffer_init();
12687 hctx->request_id = 0;
12688 hctx->state = FCGI_STATE_INIT;
12692 hctx->response_len = 0;
12693 hctx->response_type = 0;
12694 hctx->response_padding = 0;
12698 hctx->reconnects = 0;
12700 hctx->wb = chunkqueue_init();
12706 @@ -358,12 +357,12 @@
12707 buffer_free(hctx->response_header);
12709 chunkqueue_free(hctx->wb);
12713 if (hctx->rb->ptr) free(hctx->rb->ptr);
12721 @@ -372,20 +371,20 @@
12723 f = calloc(1, sizeof(*f));
12724 f->socket = buffer_init();
12734 void scgi_process_free(scgi_proc *f) {
12738 scgi_process_free(f->next);
12741 buffer_free(f->socket);
12747 @@ -400,62 +399,62 @@
12748 f->bin_path = buffer_init();
12749 f->bin_env = array_init();
12750 f->bin_env_copy = array_init();
12756 void scgi_host_free(scgi_extension_host *h) {
12760 buffer_free(h->host);
12761 buffer_free(h->unixsocket);
12762 buffer_free(h->docroot);
12763 buffer_free(h->bin_path);
12764 array_free(h->bin_env);
12765 array_free(h->bin_env_copy);
12768 scgi_process_free(h->first);
12769 scgi_process_free(h->unused_procs);
12777 scgi_exts *scgi_extensions_init() {
12780 f = calloc(1, sizeof(*f));
12786 void scgi_extensions_free(scgi_exts *f) {
12793 for (i = 0; i < f->used; i++) {
12794 scgi_extension *fe;
12801 for (j = 0; j < fe->used; j++) {
12802 scgi_extension_host *h;
12812 buffer_free(fe->key);
12826 @@ -504,99 +503,103 @@
12830 - fe->hosts[fe->used++] = fh;
12831 + fe->hosts[fe->used++] = fh;
12838 INIT_FUNC(mod_scgi_init) {
12842 p = calloc(1, sizeof(*p));
12845 p->scgi_env = buffer_init();
12848 p->path = buffer_init();
12849 p->parse_response = buffer_init();
12856 FREE_FUNC(mod_scgi_free) {
12857 plugin_data *p = p_d;
12862 buffer_free(p->scgi_env);
12863 buffer_free(p->path);
12864 buffer_free(p->parse_response);
12867 if (p->config_storage) {
12869 for (i = 0; i < srv->config_context->used; i++) {
12870 plugin_config *s = p->config_storage[i];
12879 for (j = 0; j < exts->used; j++) {
12880 scgi_extension *ex;
12883 ex = exts->exts[j];
12886 for (n = 0; n < ex->used; n++) {
12888 scgi_extension_host *host;
12891 host = ex->hosts[n];
12894 for (proc = host->first; proc; proc = proc->next) {
12896 if (proc->pid != 0) kill(proc->pid, SIGTERM);
12898 - if (proc->is_local &&
12901 + if (proc->is_local &&
12902 !buffer_is_empty(proc->socket)) {
12903 unlink(proc->socket->ptr);
12908 for (proc = host->unused_procs; proc; proc = proc->next) {
12910 if (proc->pid != 0) kill(proc->pid, SIGTERM);
12912 - if (proc->is_local &&
12915 + if (proc->is_local &&
12916 !buffer_is_empty(proc->socket)) {
12917 unlink(proc->socket->ptr);
12924 scgi_extensions_free(s->exts);
12929 free(p->config_storage);
12936 return HANDLER_GO_ON;
12939 static int env_add(char_array *env, const char *key, size_t key_len, const char *val, size_t val_len) {
12943 if (!key || !val) return -1;
12946 dst = malloc(key_len + val_len + 3);
12947 memcpy(dst, key, key_len);
12948 dst[key_len] = '=';
12949 /* add the \0 from the value */
12950 memcpy(dst + key_len + 1, val, val_len + 1);
12953 if (env->size == 0) {
12955 env->ptr = malloc(env->size * sizeof(*env->ptr));
12956 @@ -604,13 +607,13 @@
12958 env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
12962 env->ptr[env->used++] = dst;
12968 -static int scgi_spawn_connection(server *srv,
12969 +static int scgi_spawn_connection(server *srv,
12971 scgi_extension_host *host,
12973 @@ -622,31 +625,27 @@
12975 struct sockaddr_in scgi_addr_in;
12976 struct sockaddr *scgi_addr;
12987 if (p->conf.debug) {
12988 log_error_write(srv, __FILE__, __LINE__, "sdb",
12989 "new proc, socket:", proc->port, proc->socket);
12993 if (!buffer_is_empty(proc->socket)) {
12994 memset(&scgi_addr, 0, sizeof(scgi_addr));
12997 #ifdef HAVE_SYS_UN_H
12998 scgi_addr_un.sun_family = AF_UNIX;
12999 strcpy(scgi_addr_un.sun_path, proc->socket->ptr);
13003 servlen = SUN_LEN(&scgi_addr_un);
13005 - /* stevens says: */
13006 - servlen = proc->socket->used + sizeof(scgi_addr_un.sun_family);
13009 socket_type = AF_UNIX;
13010 scgi_addr = (struct sockaddr *) &scgi_addr_un;
13012 @@ -656,115 +655,115 @@
13015 scgi_addr_in.sin_family = AF_INET;
13018 if (buffer_is_empty(host->host)) {
13019 scgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
13021 struct hostent *he;
13024 /* set a usefull default */
13025 scgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
13030 if (NULL == (he = gethostbyname(host->host->ptr))) {
13031 - log_error_write(srv, __FILE__, __LINE__,
13032 - "sdb", "gethostbyname failed: ",
13033 + log_error_write(srv, __FILE__, __LINE__,
13034 + "sdb", "gethostbyname failed: ",
13035 h_errno, host->host);
13040 if (he->h_addrtype != AF_INET) {
13041 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype);
13046 if (he->h_length != sizeof(struct in_addr)) {
13047 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-length != sizeof(in_addr): ", he->h_length);
13052 memcpy(&(scgi_addr_in.sin_addr.s_addr), he->h_addr_list[0], he->h_length);
13056 scgi_addr_in.sin_port = htons(proc->port);
13057 servlen = sizeof(scgi_addr_in);
13060 socket_type = AF_INET;
13061 scgi_addr = (struct sockaddr *) &scgi_addr_in;
13065 if (-1 == (scgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
13066 - log_error_write(srv, __FILE__, __LINE__, "ss",
13067 + log_error_write(srv, __FILE__, __LINE__, "ss",
13068 "failed:", strerror(errno));
13073 if (-1 == connect(scgi_fd, scgi_addr, servlen)) {
13074 /* server is not up, spawn in */
13079 if (!buffer_is_empty(proc->socket)) {
13080 unlink(proc->socket->ptr);
13087 /* reopen socket */
13088 if (-1 == (scgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
13089 - log_error_write(srv, __FILE__, __LINE__, "ss",
13090 + log_error_write(srv, __FILE__, __LINE__, "ss",
13091 "socket failed:", strerror(errno));
13097 if (setsockopt(scgi_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
13098 - log_error_write(srv, __FILE__, __LINE__, "ss",
13099 + log_error_write(srv, __FILE__, __LINE__, "ss",
13100 "socketsockopt failed:", strerror(errno));
13105 /* create socket */
13106 if (-1 == bind(scgi_fd, scgi_addr, servlen)) {
13107 - log_error_write(srv, __FILE__, __LINE__, "sbds",
13108 - "bind failed for:",
13111 + log_error_write(srv, __FILE__, __LINE__, "sbds",
13112 + "bind failed for:",
13120 if (-1 == listen(scgi_fd, 1024)) {
13121 - log_error_write(srv, __FILE__, __LINE__, "ss",
13122 + log_error_write(srv, __FILE__, __LINE__, "ss",
13123 "listen failed:", strerror(errno));
13130 switch ((child = fork())) {
13140 /* create environment */
13146 /* we don't need the client socket */
13147 for (fd = 3; fd < 256; fd++) {
13148 if (fd != 2 && fd != scgi_fd) close(fd);
13152 /* build clean environment */
13153 if (host->bin_env_copy->used) {
13154 for (i = 0; i < host->bin_env_copy->used; i++) {
13155 data_string *ds = (data_string *)host->bin_env_copy->data[i];
13159 if (NULL != (ge = getenv(ds->value->ptr))) {
13160 env_add(&env, CONST_BUF_LEN(ds->value), ge, strlen(ge));
13162 @@ -772,44 +771,44 @@
13164 for (i = 0; environ[i]; i++) {
13168 if (NULL != (eq = strchr(environ[i], '='))) {
13169 env_add(&env, environ[i], eq - environ[i], eq+1, strlen(eq+1));
13175 /* create environment */
13176 for (i = 0; i < host->bin_env->used; i++) {
13177 data_string *ds = (data_string *)host->bin_env->data[i];
13180 env_add(&env, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
13184 for (i = 0; i < env.used; i++) {
13185 /* search for PHP_FCGI_CHILDREN */
13186 if (0 == strncmp(env.ptr[i], "PHP_FCGI_CHILDREN=", sizeof("PHP_FCGI_CHILDREN=") - 1)) break;
13190 /* not found, add a default */
13191 if (i == env.used) {
13192 env_add(&env, CONST_STR_LEN("PHP_FCGI_CHILDREN"), CONST_STR_LEN("1"));
13196 env.ptr[env.used] = NULL;
13200 buffer_copy_string(b, "exec ");
13201 buffer_append_string_buffer(b, host->bin_path);
13205 execle("/bin/sh", "sh", "-c", b->ptr, NULL, env.ptr);
13207 - log_error_write(srv, __FILE__, __LINE__, "sbs",
13209 + log_error_write(srv, __FILE__, __LINE__, "sbs",
13210 "execl failed for:", host->bin_path, strerror(errno));
13219 @@ -817,32 +816,32 @@
13226 select(0, NULL, NULL, NULL, &tv);
13229 switch (waitpid(child, &status, WNOHANG)) {
13231 /* child still running after timeout, good */
13234 /* no PID found ? should never happen */
13235 - log_error_write(srv, __FILE__, __LINE__, "ss",
13236 + log_error_write(srv, __FILE__, __LINE__, "ss",
13237 "pid not found:", strerror(errno));
13240 /* the child should not terminate at all */
13241 if (WIFEXITED(status)) {
13242 - log_error_write(srv, __FILE__, __LINE__, "sd",
13243 - "child exited (is this a SCGI binary ?):",
13244 + log_error_write(srv, __FILE__, __LINE__, "sd",
13245 + "child exited (is this a SCGI binary ?):",
13246 WEXITSTATUS(status));
13247 } else if (WIFSIGNALED(status)) {
13248 - log_error_write(srv, __FILE__, __LINE__, "sd",
13249 - "child signaled:",
13250 + log_error_write(srv, __FILE__, __LINE__, "sd",
13251 + "child signaled:",
13254 - log_error_write(srv, __FILE__, __LINE__, "sd",
13255 - "child died somehow:",
13256 + log_error_write(srv, __FILE__, __LINE__, "sd",
13257 + "child died somehow:",
13261 @@ -852,26 +851,26 @@
13263 proc->last_used = srv->cur_ts;
13264 proc->is_local = 1;
13271 proc->is_local = 0;
13275 if (p->conf.debug) {
13276 log_error_write(srv, __FILE__, __LINE__, "sb",
13277 "(debug) socket is already used, won't spawn:",
13283 proc->state = PROC_STATE_RUNNING;
13284 host->active_procs++;
13293 @@ -880,89 +879,89 @@
13294 plugin_data *p = p_d;
13298 - config_values_t cv[] = {
13300 + config_values_t cv[] = {
13301 { "scgi.server", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
13302 { "scgi.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
13303 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
13307 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
13310 for (i = 0; i < srv->config_context->used; i++) {
13315 s = malloc(sizeof(plugin_config));
13316 s->exts = scgi_extensions_init();
13320 cv[0].destination = s->exts;
13321 cv[1].destination = &(s->debug);
13324 p->config_storage[i] = s;
13325 ca = ((data_config *)srv->config_context->data[i])->value;
13328 if (0 != config_insert_values_global(srv, ca, cv)) {
13329 return HANDLER_ERROR;
13339 if (NULL != (du = array_get_element(ca, "scgi.server"))) {
13341 data_array *da = (data_array *)du;
13344 if (du->type != TYPE_ARRAY) {
13345 - log_error_write(srv, __FILE__, __LINE__, "sss",
13346 + log_error_write(srv, __FILE__, __LINE__, "sss",
13347 "unexpected type for key: ", "scgi.server", "array of strings");
13350 return HANDLER_ERROR;
13355 - * scgi.server = ( "<ext>" => ( ... ),
13359 + * scgi.server = ( "<ext>" => ( ... ),
13360 * "<ext>" => ( ... ) )
13364 for (j = 0; j < da->value->used; j++) {
13366 data_array *da_ext = (data_array *)da->value->data[j];
13369 if (da->value->data[j]->type != TYPE_ARRAY) {
13370 - log_error_write(srv, __FILE__, __LINE__, "sssbs",
13371 - "unexpected type for key: ", "scgi.server",
13372 + log_error_write(srv, __FILE__, __LINE__, "sssbs",
13373 + "unexpected type for key: ", "scgi.server",
13374 "[", da->value->data[j]->key, "](string)");
13377 return HANDLER_ERROR;
13381 - * da_ext->key == name of the extension
13384 + * da_ext->key == name of the extension
13388 - * scgi.server = ( "<ext>" =>
13389 - * ( "<host>" => ( ... ),
13392 + * scgi.server = ( "<ext>" =>
13393 + * ( "<host>" => ( ... ),
13394 * "<host>" => ( ... )
13401 for (n = 0; n < da_ext->value->used; n++) {
13402 data_array *da_host = (data_array *)da_ext->value->data[n];
13405 scgi_extension_host *df;
13407 - config_values_t fcv[] = {
13409 + config_values_t fcv[] = {
13410 { "host", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
13411 { "docroot", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
13412 { "socket", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
13413 { "bin-path", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
13416 { "check-local", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 4 */
13417 { "port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 5 */
13418 { "min-procs-not-working", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 7 this is broken for now */
13419 @@ -970,37 +969,37 @@
13420 { "max-load-per-proc", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 8 */
13421 { "idle-timeout", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 9 */
13422 { "disable-time", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 10 */
13425 { "bin-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 11 */
13426 { "bin-copy-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 12 */
13431 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
13435 if (da_host->type != TYPE_ARRAY) {
13436 - log_error_write(srv, __FILE__, __LINE__, "ssSBS",
13437 - "unexpected type for key:",
13439 + log_error_write(srv, __FILE__, __LINE__, "ssSBS",
13440 + "unexpected type for key:",
13442 "[", da_host->key, "](string)");
13445 return HANDLER_ERROR;
13449 df = scgi_host_init();
13452 df->check_local = 1;
13455 df->max_load_per_proc = 1;
13456 df->idle_timeout = 60;
13457 df->disable_time = 60;
13460 fcv[0].destination = df->host;
13461 fcv[1].destination = df->docroot;
13462 fcv[2].destination = df->unixsocket;
13463 fcv[3].destination = df->bin_path;
13466 fcv[4].destination = &(df->check_local);
13467 fcv[5].destination = &(df->port);
13468 fcv[6].destination = &(df->min_procs);
13469 @@ -1008,47 +1007,47 @@
13470 fcv[8].destination = &(df->max_load_per_proc);
13471 fcv[9].destination = &(df->idle_timeout);
13472 fcv[10].destination = &(df->disable_time);
13475 fcv[11].destination = df->bin_env;
13476 fcv[12].destination = df->bin_env_copy;
13481 if (0 != config_insert_values_internal(srv, da_host->value, fcv)) {
13482 return HANDLER_ERROR;
13485 - if ((!buffer_is_empty(df->host) || df->port) &&
13487 + if ((!buffer_is_empty(df->host) || df->port) &&
13488 !buffer_is_empty(df->unixsocket)) {
13489 - log_error_write(srv, __FILE__, __LINE__, "s",
13490 + log_error_write(srv, __FILE__, __LINE__, "s",
13491 "either host+port or socket");
13494 return HANDLER_ERROR;
13498 if (!buffer_is_empty(df->unixsocket)) {
13499 /* unix domain socket */
13502 if (df->unixsocket->used > UNIX_PATH_MAX - 2) {
13503 - log_error_write(srv, __FILE__, __LINE__, "s",
13504 + log_error_write(srv, __FILE__, __LINE__, "s",
13505 "path of the unixdomain socket is too large");
13506 return HANDLER_ERROR;
13511 - if (buffer_is_empty(df->host) &&
13513 + if (buffer_is_empty(df->host) &&
13514 buffer_is_empty(df->bin_path)) {
13515 - log_error_write(srv, __FILE__, __LINE__, "sbbbs",
13516 - "missing key (string):",
13517 + log_error_write(srv, __FILE__, __LINE__, "sbbbs",
13518 + "missing key (string):",
13525 return HANDLER_ERROR;
13526 } else if (df->port == 0) {
13527 - log_error_write(srv, __FILE__, __LINE__, "sbbbs",
13528 - "missing key (short):",
13529 + log_error_write(srv, __FILE__, __LINE__, "sbbbs",
13530 + "missing key (short):",
13534 @@ -1056,14 +1055,14 @@
13535 return HANDLER_ERROR;
13539 - if (!buffer_is_empty(df->bin_path)) {
13541 + if (!buffer_is_empty(df->bin_path)) {
13542 /* a local socket + self spawning */
13546 if (df->min_procs > df->max_procs) df->max_procs = df->min_procs;
13547 if (df->max_load_per_proc < 1) df->max_load_per_proc = 0;
13551 log_error_write(srv, __FILE__, __LINE__, "ssbsdsbsdsd",
13552 "--- scgi spawning local",
13553 @@ -1073,7 +1072,7 @@
13554 "\n\tmin-procs:", df->min_procs,
13555 "\n\tmax-procs:", df->max_procs);
13559 for (pno = 0; pno < df->min_procs; pno++) {
13562 @@ -1088,7 +1087,7 @@
13563 buffer_append_string(proc->socket, "-");
13564 buffer_append_long(proc->socket, pno);
13569 log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd",
13570 "--- scgi spawning",
13571 @@ -1096,53 +1095,53 @@
13572 "\n\tsocket", df->unixsocket,
13573 "\n\tcurrent:", pno, "/", df->min_procs);
13577 if (scgi_spawn_connection(srv, p, df, proc)) {
13578 log_error_write(srv, __FILE__, __LINE__, "s",
13579 "[ERROR]: spawning fcgi failed.");
13580 return HANDLER_ERROR;
13584 proc->next = df->first;
13585 if (df->first) df->first->prev = proc;
13594 fp = scgi_process_init();
13595 fp->id = df->num_procs++;
13597 df->active_procs++;
13598 fp->state = PROC_STATE_RUNNING;
13601 if (buffer_is_empty(df->unixsocket)) {
13602 fp->port = df->port;
13604 buffer_copy_string_buffer(fp->socket, df->unixsocket);
13616 /* if extension already exists, take it */
13617 scgi_extension_insert(s->exts, da_ext->key, df);
13624 return HANDLER_GO_ON;
13627 static int scgi_set_state(server *srv, handler_ctx *hctx, scgi_connection_state_t state) {
13628 hctx->state = state;
13629 hctx->state_timestamp = srv->cur_ts;
13635 @@ -1150,34 +1149,34 @@
13636 void scgi_connection_cleanup(server *srv, handler_ctx *hctx) {
13641 if (NULL == hctx) return;
13644 p = hctx->plugin_data;
13645 con = hctx->remote_conn;
13648 if (con->mode != p->id) {
13654 if (hctx->fd != -1) {
13655 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
13656 fdevent_unregister(srv->ev, hctx->fd);
13662 if (hctx->host && hctx->proc) {
13663 hctx->host->load--;
13666 if (hctx->got_proc) {
13667 /* after the connect the process gets a load */
13668 hctx->proc->load--;
13671 if (p->conf.debug) {
13672 log_error_write(srv, __FILE__, __LINE__, "sddb",
13676 hctx->proc->pid, hctx->proc->socket);
13678 @@ -1186,87 +1185,87 @@
13679 scgi_proclist_sort_down(srv, hctx->host, hctx->proc);
13684 handler_ctx_free(hctx);
13685 - con->plugin_ctx[p->id] = NULL;
13686 + con->plugin_ctx[p->id] = NULL;
13689 static int scgi_reconnect(server *srv, handler_ctx *hctx) {
13690 plugin_data *p = hctx->plugin_data;
13701 * connect was ok, connection was accepted
13702 * but the php accept loop checks after the accept if it should die or not.
13704 - * if yes we can only detect it at a write()
13707 + * if yes we can only detect it at a write()
13709 * next step is resetting this attemp and setup a connection again
13712 * if we have more then 5 reconnects for the same request, die
13719 * we have a connection but the child died by some other reason
13725 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
13726 fdevent_unregister(srv->ev, hctx->fd);
13731 scgi_set_state(srv, hctx, FCGI_STATE_INIT);
13734 hctx->request_id = 0;
13735 hctx->reconnects++;
13738 if (p->conf.debug) {
13739 log_error_write(srv, __FILE__, __LINE__, "sddb",
13743 hctx->proc->pid, hctx->proc->socket);
13747 hctx->proc->load--;
13748 scgi_proclist_sort_down(srv, hctx->host, hctx->proc);
13755 static handler_t scgi_connection_reset(server *srv, connection *con, void *p_d) {
13756 plugin_data *p = p_d;
13759 scgi_connection_cleanup(srv, con->plugin_ctx[p->id]);
13762 return HANDLER_GO_ON;
13766 static int scgi_env_add(buffer *env, const char *key, size_t key_len, const char *val, size_t val_len) {
13770 if (!key || !val) return -1;
13773 len = key_len + val_len + 2;
13776 buffer_prepare_append(env, len);
13778 - /* include the NUL */
13779 + /* include the NUL */
13780 memcpy(env->ptr + env->used, key, key_len + 1);
13781 env->used += key_len + 1;
13782 memcpy(env->ptr + env->used, val, val_len + 1);
13783 env->used += val_len + 1;
13796 @@ -1280,24 +1279,21 @@
13797 struct sockaddr_un scgi_addr_un;
13802 scgi_extension_host *host = hctx->host;
13803 scgi_proc *proc = hctx->proc;
13804 int scgi_fd = hctx->fd;
13807 memset(&scgi_addr, 0, sizeof(scgi_addr));
13810 if (!buffer_is_empty(proc->socket)) {
13811 #ifdef HAVE_SYS_UN_H
13812 /* use the unix domain socket */
13813 scgi_addr_un.sun_family = AF_UNIX;
13814 strcpy(scgi_addr_un.sun_path, proc->socket->ptr);
13817 servlen = SUN_LEN(&scgi_addr_un);
13819 - /* stevens says: */
13820 - servlen = proc->socket->used + sizeof(scgi_addr_un.sun_family);
13823 scgi_addr = (struct sockaddr *) &scgi_addr_un;
13826 @@ -1305,105 +1301,105 @@
13828 scgi_addr_in.sin_family = AF_INET;
13829 if (0 == inet_aton(host->host->ptr, &(scgi_addr_in.sin_addr))) {
13830 - log_error_write(srv, __FILE__, __LINE__, "sbs",
13831 - "converting IP-adress failed for", host->host,
13832 + log_error_write(srv, __FILE__, __LINE__, "sbs",
13833 + "converting IP-adress failed for", host->host,
13834 "\nBe sure to specify an IP address here");
13839 scgi_addr_in.sin_port = htons(proc->port);
13840 servlen = sizeof(scgi_addr_in);
13843 scgi_addr = (struct sockaddr *) &scgi_addr_in;
13847 if (-1 == connect(scgi_fd, scgi_addr, servlen)) {
13848 - if (errno == EINPROGRESS ||
13849 + if (errno == EINPROGRESS ||
13850 errno == EALREADY ||
13852 if (hctx->conf.debug) {
13853 - log_error_write(srv, __FILE__, __LINE__, "sd",
13854 + log_error_write(srv, __FILE__, __LINE__, "sd",
13855 "connect delayed, will continue later:", scgi_fd);
13861 - log_error_write(srv, __FILE__, __LINE__, "sdsddb",
13862 - "connect failed:", scgi_fd,
13863 + log_error_write(srv, __FILE__, __LINE__, "sdsddb",
13864 + "connect failed:", scgi_fd,
13865 strerror(errno), errno,
13866 proc->port, proc->socket);
13868 if (errno == EAGAIN) {
13869 /* this is Linux only */
13871 - log_error_write(srv, __FILE__, __LINE__, "s",
13873 + log_error_write(srv, __FILE__, __LINE__, "s",
13874 "If this happend on Linux: You have been run out of local ports. "
13875 "Check the manual, section Performance how to handle this.");
13883 if (hctx->conf.debug > 1) {
13884 - log_error_write(srv, __FILE__, __LINE__, "sd",
13885 + log_error_write(srv, __FILE__, __LINE__, "sd",
13886 "connect succeeded: ", scgi_fd);
13895 static int scgi_env_add_request_headers(server *srv, connection *con, plugin_data *p) {
13899 for (i = 0; i < con->request.headers->used; i++) {
13903 ds = (data_string *)con->request.headers->data[i];
13906 if (ds->value->used && ds->key->used) {
13908 buffer_reset(srv->tmp_buf);
13911 if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
13912 BUFFER_COPY_STRING_CONST(srv->tmp_buf, "HTTP_");
13913 srv->tmp_buf->used--;
13917 buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
13918 for (j = 0; j < ds->key->used - 1; j++) {
13919 - srv->tmp_buf->ptr[srv->tmp_buf->used++] =
13920 - light_isalpha(ds->key->ptr[j]) ?
13921 + srv->tmp_buf->ptr[srv->tmp_buf->used++] =
13922 + light_isalpha(ds->key->ptr[j]) ?
13923 ds->key->ptr[j] & ~32 : '_';
13925 srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
13928 scgi_env_add(p->scgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
13933 for (i = 0; i < con->environment->used; i++) {
13937 ds = (data_string *)con->environment->data[i];
13940 if (ds->value->used && ds->key->used) {
13942 buffer_reset(srv->tmp_buf);
13945 buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
13946 for (j = 0; j < ds->key->used - 1; j++) {
13947 - srv->tmp_buf->ptr[srv->tmp_buf->used++] =
13948 - isalpha((unsigned char)ds->key->ptr[j]) ?
13949 + srv->tmp_buf->ptr[srv->tmp_buf->used++] =
13950 + isalpha((unsigned char)ds->key->ptr[j]) ?
13951 toupper((unsigned char)ds->key->ptr[j]) : '_';
13953 srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
13956 scgi_env_add(p->scgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
13964 @@ -1415,20 +1411,20 @@
13965 char b2[INET6_ADDRSTRLEN + 1];
13970 plugin_data *p = hctx->plugin_data;
13971 scgi_extension_host *host= hctx->host;
13973 connection *con = hctx->remote_conn;
13974 server_socket *srv_sock = con->srv_socket;
13977 sock_addr our_addr;
13978 socklen_t our_addr_len;
13981 buffer_prepare_copy(p->scgi_env, 1024);
13983 /* CGI-SPEC 6.1.2, FastCGI spec 6.3 and SCGI spec */
13986 /* request.content_length < SSIZE_MAX, see request.c */
13987 ltostr(buf, con->request.content_length);
13988 scgi_env_add(p->scgi_env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf));
13989 @@ -1436,13 +1432,13 @@
13992 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION));
13995 if (con->server_name->used) {
13996 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_NAME"), CONST_BUF_LEN(con->server_name));
13999 - s = inet_ntop(srv_sock->addr.plain.sa_family,
14000 - srv_sock->addr.plain.sa_family == AF_INET6 ?
14001 + s = inet_ntop(srv_sock->addr.plain.sa_family,
14002 + srv_sock->addr.plain.sa_family == AF_INET6 ?
14003 (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
14004 (const void *) &(srv_sock->addr.ipv4.sin_addr),
14006 @@ -1451,48 +1447,48 @@
14008 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_NAME"), s, strlen(s));
14012 scgi_env_add(p->scgi_env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1"));
14018 ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
14020 ntohs(srv_sock->addr.ipv4.sin_port)
14025 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf));
14028 /* get the server-side of the connection to the client */
14029 our_addr_len = sizeof(our_addr);
14032 if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) {
14033 s = inet_ntop_cache_get_ip(srv, &(srv_sock->addr));
14035 s = inet_ntop_cache_get_ip(srv, &(our_addr));
14037 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_ADDR"), s, strlen(s));
14043 ntohs(con->dst_addr.plain.sa_family ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
14045 ntohs(con->dst_addr.ipv4.sin_port)
14050 scgi_env_add(p->scgi_env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf));
14053 s = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
14054 scgi_env_add(p->scgi_env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s));
14057 if (!buffer_is_empty(con->authed_user)) {
14058 scgi_env_add(p->scgi_env, CONST_STR_LEN("REMOTE_USER"),
14059 CONST_BUF_LEN(con->authed_user));
14065 * SCRIPT_NAME, PATH_INFO and PATH_TRANSLATED according to
14066 * http://cgi-spec.golux.com/draft-coar-cgi-v11-03-clean.html
14067 @@ -1500,12 +1496,12 @@
14070 scgi_env_add(p->scgi_env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
14073 if (!buffer_is_empty(con->request.pathinfo)) {
14074 scgi_env_add(p->scgi_env, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo));
14077 /* PATH_TRANSLATED is only defined if PATH_INFO is set */
14080 if (!buffer_is_empty(host->docroot)) {
14081 buffer_copy_string_buffer(p->path, host->docroot);
14083 @@ -1526,19 +1522,19 @@
14086 if (!buffer_is_empty(host->docroot)) {
14088 - * rewrite SCRIPT_FILENAME
14091 + * rewrite SCRIPT_FILENAME
14096 buffer_copy_string_buffer(p->path, host->docroot);
14097 buffer_append_string_buffer(p->path, con->uri.path);
14100 scgi_env_add(p->scgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
14101 scgi_env_add(p->scgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(host->docroot));
14103 buffer_copy_string_buffer(p->path, con->physical.path);
14106 scgi_env_add(p->scgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
14107 scgi_env_add(p->scgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root));
14109 @@ -1551,30 +1547,30 @@
14111 scgi_env_add(p->scgi_env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN(""));
14115 s = get_http_method_name(con->request.http_method);
14116 scgi_env_add(p->scgi_env, CONST_STR_LEN("REQUEST_METHOD"), s, strlen(s));
14117 scgi_env_add(p->scgi_env, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200")); /* if php is compiled with --force-redirect */
14118 s = get_http_version_name(con->request.http_version);
14119 scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s));
14123 if (srv_sock->is_ssl) {
14124 scgi_env_add(p->scgi_env, CONST_STR_LEN("HTTPS"), CONST_STR_LEN("on"));
14129 scgi_env_add_request_headers(srv, con, p);
14131 b = chunkqueue_get_append_buffer(hctx->wb);
14134 buffer_append_long(b, p->scgi_env->used);
14135 buffer_append_string_len(b, CONST_STR_LEN(":"));
14136 buffer_append_string_len(b, (const char *)p->scgi_env->ptr, p->scgi_env->used);
14137 buffer_append_string_len(b, CONST_STR_LEN(","));
14139 hctx->wb->bytes_in += b->used - 1;
14142 if (con->request.content_length) {
14143 chunkqueue *req_cq = con->request_content_queue;
14145 @@ -1587,7 +1583,7 @@
14147 /* we announce toWrite octects
14148 * now take all the request_content chunk that we need to fill this request
14152 switch (req_c->type) {
14154 @@ -1615,32 +1611,32 @@
14156 req_c->offset += weHave;
14157 req_cq->bytes_out += weHave;
14160 hctx->wb->bytes_in += weHave;
14174 for (i = 0; i < hctx->write_buffer->used; i++) {
14175 fprintf(stderr, "%02x ", hctx->write_buffer->ptr[i]);
14176 if ((i+1) % 16 == 0) {
14178 for (j = i-15; j <= i; j++) {
14179 - fprintf(stderr, "%c",
14180 + fprintf(stderr, "%c",
14181 isprint((unsigned char)hctx->write_buffer->ptr[j]) ? hctx->write_buffer->ptr[j] : '.');
14183 fprintf(stderr, "\n");
14192 @@ -1648,32 +1644,32 @@
14201 buffer_copy_string_buffer(p->parse_response, in);
14203 - for (s = p->parse_response->ptr;
14204 - NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n')));
14206 + for (s = p->parse_response->ptr;
14207 + NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n')));
14208 s = ns + (eol == EOL_RN ? 2 : 1), line++) {
14209 const char *key, *value;
14219 0 == strncmp(s, "HTTP/1.", 7)) {
14220 /* non-parsed header ... we parse them anyway */
14223 if ((s[7] == '1' ||
14227 /* after the space should be a status code for us */
14230 status = strtol(s+9, NULL, 10);
14233 if (con->http_status >= 100 &&
14234 con->http_status < 1000) {
14235 /* we expected 3 digits and didn't got them */
14236 @@ -1682,27 +1678,27 @@
14243 if (NULL == (value = strchr(s, ':'))) {
14244 /* we expect: "<key>: <value>\r\n" */
14249 key_len = value - key;
14254 while (*value == ' ' || *value == '\t') value++;
14257 if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
14258 ds = data_response_init();
14260 buffer_copy_string_len(ds->key, key, key_len);
14261 buffer_copy_string(ds->value, value);
14264 array_insert_unique(con->response.headers, (data_unset *)ds);
14269 if (0 == strncasecmp(key, "Date", key_len)) {
14270 @@ -1737,13 +1733,13 @@
14276 /* CGI/1.1 rev 03 - 7.2.1.2 */
14277 if ((con->parsed_response & HTTP_LOCATION) &&
14278 !(con->parsed_response & HTTP_STATUS)) {
14279 con->http_status = 302;
14286 @@ -1751,10 +1747,10 @@
14287 static int scgi_demux_response(server *srv, handler_ctx *hctx) {
14288 plugin_data *p = hctx->plugin_data;
14289 connection *con = hctx->remote_conn;
14296 buffer_prepare_copy(hctx->response, 1024);
14297 if (-1 == (n = read(hctx->fd, hctx->response->ptr, hctx->response->size - 1))) {
14298 if (errno == EAGAIN || errno == EINTR) {
14299 @@ -1765,143 +1761,143 @@
14300 log_error_write(srv, __FILE__, __LINE__, "sdd", strerror(errno), con->fd, hctx->fd);
14306 /* read finished */
14309 con->file_finished = 1;
14312 /* send final chunk */
14313 http_chunk_append_mem(srv, con, NULL, 0);
14314 joblist_append(srv, con);
14321 hctx->response->ptr[n] = '\0';
14322 hctx->response->used = n+1;
14325 /* split header from body */
14328 if (con->file_started == 0) {
14331 int header_end = 0;
14332 int cp, eol = EOL_UNSET;
14336 buffer_append_string_buffer(hctx->response_header, hctx->response);
14339 /* nph (non-parsed headers) */
14340 if (0 == strncmp(hctx->response_header->ptr, "HTTP/1.", 7)) in_header = 1;
14343 /* search for the \r\n\r\n or \n\n in the string */
14344 for (c = hctx->response_header->ptr, cp = 0, used = hctx->response_header->used - 1; used; c++, cp++, used--) {
14345 if (*c == ':') in_header = 1;
14346 else if (*c == '\n') {
14347 if (in_header == 0) {
14348 /* got a response without a response header */
14357 if (eol == EOL_UNSET) eol = EOL_N;
14360 if (*(c+1) == '\n') {
14366 } else if (used > 1 && *c == '\r' && *(c+1) == '\n') {
14367 if (in_header == 0) {
14368 /* got a response without a response header */
14377 if (eol == EOL_UNSET) eol = EOL_RN;
14381 - *(c+2) == '\r' &&
14382 + *(c+2) == '\r' &&
14399 /* no header, but a body */
14402 if (con->request.http_version == HTTP_VERSION_1_1) {
14403 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
14407 http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used);
14408 joblist_append(srv, con);
14410 size_t hlen = c - hctx->response_header->ptr + (eol == EOL_RN ? 4 : 2);
14411 size_t blen = hctx->response_header->used - hlen - 1;
14414 /* a small hack: terminate after at the second \r */
14415 hctx->response_header->used = hlen + 1 - (eol == EOL_RN ? 2 : 1);
14416 hctx->response_header->ptr[hlen - (eol == EOL_RN ? 2 : 1)] = '\0';
14419 /* parse the response header */
14420 scgi_response_parse(srv, con, p, hctx->response_header, eol);
14423 /* enable chunked-transfer-encoding */
14424 if (con->request.http_version == HTTP_VERSION_1_1 &&
14425 !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
14426 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
14430 if ((hctx->response->used != hlen) && blen > 0) {
14431 http_chunk_append_mem(srv, con, c + (eol == EOL_RN ? 4: 2), blen + 1);
14432 joblist_append(srv, con);
14437 con->file_started = 1;
14440 http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used);
14441 joblist_append(srv, con);
14447 log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), b->ptr);
14456 int scgi_proclist_sort_up(server *srv, scgi_extension_host *host, scgi_proc *proc) {
14462 - /* we have been the smallest of the current list
14463 - * and we want to insert the node sorted as soon
14465 + /* we have been the smallest of the current list
14466 + * and we want to insert the node sorted as soon
14479 /* nothing to sort, only one element */
14480 @@ -1909,9 +1905,9 @@
14482 for (p = proc; p->next && p->next->load < proc->load; p = p->next);
14484 - /* no need to move something
14485 + /* no need to move something
14492 @@ -1930,16 +1926,16 @@
14494 if (proc->prev) proc->prev->next = proc->next;
14495 if (proc->next) proc->next->prev = proc->prev;
14498 /* proc should be right of p */
14501 proc->next = p->next;
14503 if (p->next) p->next->prev = proc;
14506 for(p = host->first; p; p = p->next) {
14507 - log_error_write(srv, __FILE__, __LINE__, "dd",
14508 + log_error_write(srv, __FILE__, __LINE__, "dd",
14512 @@ -1951,21 +1947,21 @@
14514 int scgi_proclist_sort_down(server *srv, scgi_extension_host *host, scgi_proc *proc) {
14520 - /* we have been the smallest of the current list
14521 - * and we want to insert the node sorted as soon
14523 + /* we have been the smallest of the current list
14524 + * and we want to insert the node sorted as soon
14534 * the basic is idea is:
14535 - * - the last active scgi process should be still
14536 + * - the last active scgi process should be still
14537 * in ram and is not swapped out yet
14538 * - processes that are not reused will be killed
14539 * after some time by the trigger-handler
14540 @@ -1975,7 +1971,7 @@
14541 * ice-cold processes are propably unused since more
14542 * than 'unused-timeout', are swaped out and won't be
14543 * reused in the next seconds anyway.
14548 /* nothing to sort, only one element */
14549 @@ -1984,16 +1980,16 @@
14550 for (p = host->first; p != proc && p->load < proc->load; p = p->next);
14553 - /* no need to move something
14554 + /* no need to move something
14563 if (p == proc) return 0;
14566 /* we have to move left. If we are already the first element
14568 if (host->first == proc) return 0;
14569 @@ -2009,9 +2005,9 @@
14572 if (proc->prev == NULL) host->first = proc;
14575 for(p = host->first; p; p = p->next) {
14576 - log_error_write(srv, __FILE__, __LINE__, "dd",
14577 + log_error_write(srv, __FILE__, __LINE__, "dd",
14581 @@ -2023,41 +2019,42 @@
14583 static int scgi_restart_dead_procs(server *srv, plugin_data *p, scgi_extension_host *host) {
14587 for (proc = host->first; proc; proc = proc->next) {
14588 if (p->conf.debug) {
14589 - log_error_write(srv, __FILE__, __LINE__, "sbdbdddd",
14591 - host->host, proc->port,
14592 + log_error_write(srv, __FILE__, __LINE__, "sbdbdddd",
14594 + host->host, proc->port,
14603 if (0 == proc->is_local) {
14605 - * external servers might get disabled
14607 - * enable the server again, perhaps it is back again
14609 + * external servers might get disabled
14611 + * enable the server again, perhaps it is back again
14615 if ((proc->state == PROC_STATE_DISABLED) &&
14616 (srv->cur_ts - proc->disable_ts > host->disable_time)) {
14617 proc->state = PROC_STATE_RUNNING;
14618 host->active_procs++;
14620 - log_error_write(srv, __FILE__, __LINE__, "sbdb",
14621 - "fcgi-server re-enabled:",
14622 - host->host, host->port,
14624 + log_error_write(srv, __FILE__, __LINE__, "sbdb",
14625 + "fcgi-server re-enabled:",
14626 + host->host, host->port,
14630 /* the child should not terminate at all */
14634 if (proc->state == PROC_STATE_DIED_WAIT_FOR_PID) {
14636 switch(waitpid(proc->pid, &status, WNOHANG)) {
14638 /* child is still alive */
14639 @@ -2067,33 +2064,34 @@
14641 if (WIFEXITED(status)) {
14643 - log_error_write(srv, __FILE__, __LINE__, "sdsd",
14644 + log_error_write(srv, __FILE__, __LINE__, "sdsd",
14645 "child exited, pid:", proc->pid,
14646 "status:", WEXITSTATUS(status));
14648 } else if (WIFSIGNALED(status)) {
14649 - log_error_write(srv, __FILE__, __LINE__, "sd",
14650 - "child signaled:",
14651 + log_error_write(srv, __FILE__, __LINE__, "sd",
14652 + "child signaled:",
14655 - log_error_write(srv, __FILE__, __LINE__, "sd",
14656 - "child died somehow:",
14657 + log_error_write(srv, __FILE__, __LINE__, "sd",
14658 + "child died somehow:",
14663 proc->state = PROC_STATE_DIED;
14672 * local servers might died, but we restart them
14676 if (proc->state == PROC_STATE_DIED &&
14678 /* restart the child */
14681 if (p->conf.debug) {
14682 log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd",
14683 "--- scgi spawning",
14684 @@ -2101,18 +2099,18 @@
14685 "\n\tsocket", host->unixsocket,
14686 "\n\tcurrent:", 1, "/", host->min_procs);
14690 if (scgi_spawn_connection(srv, p, host, proc)) {
14691 log_error_write(srv, __FILE__, __LINE__, "s",
14692 "ERROR: spawning fcgi failed.");
14693 return HANDLER_ERROR;
14697 scgi_proclist_sort_down(srv, host, proc);
14706 @@ -2121,13 +2119,13 @@
14707 plugin_data *p = hctx->plugin_data;
14708 scgi_extension_host *host= hctx->host;
14709 connection *con = hctx->remote_conn;
14714 - /* sanity check */
14715 + /* sanity check */
14717 ((!host->host->used || !host->port) && !host->unixsocket->used)) {
14718 - log_error_write(srv, __FILE__, __LINE__, "sxddd",
14719 + log_error_write(srv, __FILE__, __LINE__, "sxddd",
14720 "write-req: error",
14723 @@ -2135,179 +2133,180 @@
14724 host->unixsocket->used);
14725 return HANDLER_ERROR;
14730 switch(hctx->state) {
14731 case FCGI_STATE_INIT:
14732 ret = host->unixsocket->used ? AF_UNIX : AF_INET;
14735 if (-1 == (hctx->fd = socket(ret, SOCK_STREAM, 0))) {
14736 if (errno == EMFILE ||
14738 - log_error_write(srv, __FILE__, __LINE__, "sd",
14739 + log_error_write(srv, __FILE__, __LINE__, "sd",
14740 "wait for fd at connection:", con->fd);
14743 return HANDLER_WAIT_FOR_FD;
14746 - log_error_write(srv, __FILE__, __LINE__, "ssdd",
14748 + log_error_write(srv, __FILE__, __LINE__, "ssdd",
14749 "socket failed:", strerror(errno), srv->cur_fds, srv->max_fds);
14750 return HANDLER_ERROR;
14752 hctx->fde_ndx = -1;
14758 fdevent_register(srv->ev, hctx->fd, scgi_handle_fdevent, hctx);
14761 if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
14762 - log_error_write(srv, __FILE__, __LINE__, "ss",
14763 + log_error_write(srv, __FILE__, __LINE__, "ss",
14764 "fcntl failed: ", strerror(errno));
14767 return HANDLER_ERROR;
14772 case FCGI_STATE_CONNECT:
14773 if (hctx->state == FCGI_STATE_INIT) {
14774 - for (hctx->proc = hctx->host->first;
14775 - hctx->proc && hctx->proc->state != PROC_STATE_RUNNING;
14776 + for (hctx->proc = hctx->host->first;
14777 + hctx->proc && hctx->proc->state != PROC_STATE_RUNNING;
14778 hctx->proc = hctx->proc->next);
14781 /* all childs are dead */
14782 if (hctx->proc == NULL) {
14783 hctx->fde_ndx = -1;
14786 return HANDLER_ERROR;
14790 if (hctx->proc->is_local) {
14791 hctx->pid = hctx->proc->pid;
14795 switch (scgi_establish_connection(srv, hctx)) {
14797 scgi_set_state(srv, hctx, FCGI_STATE_CONNECT);
14800 /* connection is in progress, wait for an event and call getsockopt() below */
14803 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
14806 return HANDLER_WAIT_FOR_EVENT;
14808 /* if ECONNREFUSED choose another connection -> FIXME */
14809 hctx->fde_ndx = -1;
14812 return HANDLER_ERROR;
14814 /* everything is ok, go on */
14822 socklen_t socket_error_len = sizeof(socket_error);
14825 /* try to finish the connect() */
14826 if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
14827 - log_error_write(srv, __FILE__, __LINE__, "ss",
14828 + log_error_write(srv, __FILE__, __LINE__, "ss",
14829 "getsockopt failed:", strerror(errno));
14832 return HANDLER_ERROR;
14834 if (socket_error != 0) {
14835 if (!hctx->proc->is_local || p->conf.debug) {
14836 /* local procs get restarted */
14839 log_error_write(srv, __FILE__, __LINE__, "ss",
14840 - "establishing connection failed:", strerror(socket_error),
14841 + "establishing connection failed:", strerror(socket_error),
14842 "port:", hctx->proc->port);
14846 return HANDLER_ERROR;
14851 /* ok, we have the connection */
14854 hctx->proc->load++;
14855 hctx->proc->last_used = srv->cur_ts;
14856 hctx->got_proc = 1;
14859 if (p->conf.debug) {
14860 log_error_write(srv, __FILE__, __LINE__, "sddbdd",
14865 - hctx->proc->socket,
14867 + hctx->proc->socket,
14872 /* move the proc-list entry down the list */
14873 scgi_proclist_sort_up(srv, hctx->host, hctx->proc);
14876 scgi_set_state(srv, hctx, FCGI_STATE_PREPARE_WRITE);
14878 case FCGI_STATE_PREPARE_WRITE:
14879 scgi_create_env(srv, hctx);
14882 scgi_set_state(srv, hctx, FCGI_STATE_WRITE);
14886 case FCGI_STATE_WRITE:
14887 - ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
14888 + ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
14890 chunkqueue_remove_finished_chunks(hctx->wb);
14894 if (errno == ENOTCONN) {
14895 - /* the connection got dropped after accept()
14897 - * this is most of the time a PHP which dies
14898 + /* the connection got dropped after accept()
14900 + * this is most of the time a PHP which dies
14901 * after PHP_FCGI_MAX_REQUESTS
14906 if (hctx->wb->bytes_out == 0 &&
14907 hctx->reconnects < 5) {
14908 - usleep(10000); /* take away the load of the webserver
14909 - * to let the php a chance to restart
14911 + usleep(10000); /* take away the load of the webserver
14912 + * to let the php a chance to restart
14916 scgi_reconnect(srv, hctx);
14919 return HANDLER_WAIT_FOR_FD;
14923 /* not reconnected ... why
14926 * far@#lighttpd report this for FreeBSD
14931 - log_error_write(srv, __FILE__, __LINE__, "ssdsd",
14933 + log_error_write(srv, __FILE__, __LINE__, "ssosd",
14934 "[REPORT ME] connection was dropped after accept(). reconnect() denied:",
14935 "write-offset:", hctx->wb->bytes_out,
14936 "reconnect attempts:", hctx->reconnects);
14939 return HANDLER_ERROR;
14943 if ((errno != EAGAIN) &&
14944 (errno != EINTR)) {
14946 - log_error_write(srv, __FILE__, __LINE__, "ssd",
14948 + log_error_write(srv, __FILE__, __LINE__, "ssd",
14949 "write failed:", strerror(errno), errno);
14952 return HANDLER_ERROR;
14954 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
14957 return HANDLER_WAIT_FOR_EVENT;
14962 if (hctx->wb->bytes_out == hctx->wb->bytes_in) {
14963 /* we don't need the out event anymore */
14964 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
14965 @@ -2315,10 +2314,10 @@
14966 scgi_set_state(srv, hctx, FCGI_STATE_READ);
14968 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
14971 return HANDLER_WAIT_FOR_EVENT;
14976 case FCGI_STATE_READ:
14977 /* waiting for a response */
14978 @@ -2327,67 +2326,67 @@
14979 log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state");
14980 return HANDLER_ERROR;
14984 return HANDLER_WAIT_FOR_EVENT;
14987 SUBREQUEST_FUNC(mod_scgi_handle_subrequest) {
14988 plugin_data *p = p_d;
14991 handler_ctx *hctx = con->plugin_ctx[p->id];
14993 scgi_extension_host *host;
14996 if (NULL == hctx) return HANDLER_GO_ON;
15000 if (con->mode != p->id) return HANDLER_GO_ON;
15003 /* ok, create the request */
15004 switch(scgi_write_request(srv, hctx)) {
15005 case HANDLER_ERROR:
15012 0 == proc->is_local &&
15013 proc->state != PROC_STATE_DISABLED) {
15014 /* only disable remote servers as we don't manage them*/
15016 - log_error_write(srv, __FILE__, __LINE__, "sbdb", "fcgi-server disabled:",
15018 + log_error_write(srv, __FILE__, __LINE__, "sbdb", "fcgi-server disabled:",
15024 /* disable this server */
15025 proc->disable_ts = srv->cur_ts;
15026 proc->state = PROC_STATE_DISABLED;
15027 host->active_procs--;
15031 if (hctx->state == FCGI_STATE_INIT ||
15032 hctx->state == FCGI_STATE_CONNECT) {
15033 - /* connect() or getsockopt() failed,
15034 - * restart the request-handling
15035 + /* connect() or getsockopt() failed,
15036 + * restart the request-handling
15038 if (proc && proc->is_local) {
15040 if (p->conf.debug) {
15041 - log_error_write(srv, __FILE__, __LINE__, "sbdb", "connect() to scgi failed, restarting the request-handling:",
15042 + log_error_write(srv, __FILE__, __LINE__, "sbdb", "connect() to scgi failed, restarting the request-handling:",
15050 * several hctx might reference the same proc
15053 * Only one of them should mark the proc as dead all the other
15054 * ones should just take a new one.
15057 * If a new proc was started with the old struct this might lead
15058 * the mark a perfect proc as dead otherwise
15062 if (proc->state == PROC_STATE_RUNNING &&
15063 hctx->pid == proc->pid) {
15064 @@ -2395,25 +2394,25 @@
15067 scgi_restart_dead_procs(srv, p, host);
15070 scgi_connection_cleanup(srv, hctx);
15073 buffer_reset(con->physical.path);
15074 con->mode = DIRECT;
15075 joblist_append(srv, con);
15077 - /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
15078 - * and hope that the childs will be restarted
15081 + /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
15082 + * and hope that the childs will be restarted
15085 return HANDLER_WAIT_FOR_FD;
15087 scgi_connection_cleanup(srv, hctx);
15090 buffer_reset(con->physical.path);
15091 con->mode = DIRECT;
15092 con->http_status = 503;
15095 return HANDLER_FINISHED;
15097 case HANDLER_WAIT_FOR_EVENT:
15098 @@ -2433,23 +2432,23 @@
15099 static handler_t scgi_connection_close(server *srv, handler_ctx *hctx) {
15104 if (NULL == hctx) return HANDLER_GO_ON;
15107 p = hctx->plugin_data;
15108 con = hctx->remote_conn;
15111 if (con->mode != p->id) return HANDLER_GO_ON;
15113 - log_error_write(srv, __FILE__, __LINE__, "ssdsd",
15114 - "emergency exit: scgi:",
15116 + log_error_write(srv, __FILE__, __LINE__, "ssdsd",
15117 + "emergency exit: scgi:",
15118 "connection-fd:", con->fd,
15119 "fcgi-fd:", hctx->fd);
15126 scgi_connection_cleanup(srv, hctx);
15129 return HANDLER_FINISHED;
15132 @@ -2459,7 +2458,7 @@
15133 handler_ctx *hctx = ctx;
15134 connection *con = hctx->remote_conn;
15135 plugin_data *p = hctx->plugin_data;
15138 scgi_proc *proc = hctx->proc;
15139 scgi_extension_host *host= hctx->host;
15141 @@ -2471,15 +2470,15 @@
15144 scgi_connection_cleanup(srv, hctx);
15147 joblist_append(srv, con);
15148 return HANDLER_FINISHED;
15150 if (proc->pid && proc->state != PROC_STATE_DIED) {
15154 /* only fetch the zombie if it is not already done */
15157 switch(waitpid(proc->pid, &status, WNOHANG)) {
15159 /* child is still alive */
15160 @@ -2489,19 +2488,19 @@
15162 /* the child should not terminate at all */
15163 if (WIFEXITED(status)) {
15164 - log_error_write(srv, __FILE__, __LINE__, "sdsd",
15165 + log_error_write(srv, __FILE__, __LINE__, "sdsd",
15166 "child exited, pid:", proc->pid,
15167 "status:", WEXITSTATUS(status));
15168 } else if (WIFSIGNALED(status)) {
15169 - log_error_write(srv, __FILE__, __LINE__, "sd",
15170 - "child signaled:",
15171 + log_error_write(srv, __FILE__, __LINE__, "sd",
15172 + "child signaled:",
15175 - log_error_write(srv, __FILE__, __LINE__, "sd",
15176 - "child died somehow:",
15177 + log_error_write(srv, __FILE__, __LINE__, "sd",
15178 + "child died somehow:",
15183 if (p->conf.debug) {
15184 log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd",
15185 "--- scgi spawning",
15186 @@ -2509,40 +2508,41 @@
15187 "\n\tsocket", host->unixsocket,
15188 "\n\tcurrent:", 1, "/", host->min_procs);
15192 if (scgi_spawn_connection(srv, p, host, proc)) {
15194 proc->state = PROC_STATE_DIED;
15196 scgi_proclist_sort_down(srv, host, proc);
15205 if (con->file_started == 0) {
15206 /* nothing has been send out yet, try to use another child */
15209 if (hctx->wb->bytes_out == 0 &&
15210 hctx->reconnects < 5) {
15211 scgi_reconnect(srv, hctx);
15213 - log_error_write(srv, __FILE__, __LINE__, "sdsdsd",
15215 + log_error_write(srv, __FILE__, __LINE__, "sdsdsd",
15216 "response not sent, request not sent, reconnection.",
15217 "connection-fd:", con->fd,
15218 "fcgi-fd:", hctx->fd);
15221 return HANDLER_WAIT_FOR_FD;
15224 - log_error_write(srv, __FILE__, __LINE__, "sdsdsd",
15226 + log_error_write(srv, __FILE__, __LINE__, "sosdsd",
15227 "response not sent, request sent:", hctx->wb->bytes_out,
15228 "connection-fd:", con->fd,
15229 "fcgi-fd:", hctx->fd);
15232 scgi_connection_cleanup(srv, hctx);
15235 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
15236 buffer_reset(con->physical.path);
15237 con->http_status = 500;
15238 @@ -2550,76 +2550,76 @@
15240 /* response might have been already started, kill the connection */
15241 scgi_connection_cleanup(srv, hctx);
15243 - log_error_write(srv, __FILE__, __LINE__, "ssdsd",
15245 + log_error_write(srv, __FILE__, __LINE__, "ssdsd",
15246 "response already sent out, termination connection",
15247 "connection-fd:", con->fd,
15248 "fcgi-fd:", hctx->fd);
15251 connection_set_state(srv, con, CON_STATE_ERROR);
15259 joblist_append(srv, con);
15260 return HANDLER_FINISHED;
15265 if (revents & FDEVENT_OUT) {
15266 if (hctx->state == FCGI_STATE_CONNECT ||
15267 hctx->state == FCGI_STATE_WRITE) {
15268 /* we are allowed to send something out
15271 * 1. in a unfinished connect() call
15272 * 2. in a unfinished write() call (long POST request)
15274 return mod_scgi_handle_subrequest(srv, con, p);
15276 - log_error_write(srv, __FILE__, __LINE__, "sd",
15277 - "got a FDEVENT_OUT and didn't know why:",
15278 + log_error_write(srv, __FILE__, __LINE__, "sd",
15279 + "got a FDEVENT_OUT and didn't know why:",
15285 /* perhaps this issue is already handled */
15286 if (revents & FDEVENT_HUP) {
15287 if (hctx->state == FCGI_STATE_CONNECT) {
15288 /* getoptsock will catch this one (right ?)
15290 - * if we are in connect we might get a EINPROGRESS
15291 - * in the first call and a FDEVENT_HUP in the
15293 + * if we are in connect we might get a EINPROGRESS
15294 + * in the first call and a FDEVENT_HUP in the
15298 * FIXME: as it is a bit ugly.
15302 return mod_scgi_handle_subrequest(srv, con, p);
15303 } else if (hctx->state == FCGI_STATE_READ &&
15304 hctx->proc->port == 0) {
15308 * ioctl says 8192 bytes to read from PHP and we receive directly a HUP for the socket
15309 * even if the FCGI_FIN packet is not received yet
15312 - log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd",
15313 - "error: unexpected close of scgi connection for",
15314 + log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd",
15315 + "error: unexpected close of scgi connection for",
15317 - "(no scgi process on host: ",
15318 + "(no scgi process on host: ",
15327 connection_set_state(srv, con, CON_STATE_ERROR);
15328 scgi_connection_close(srv, hctx);
15329 joblist_append(srv, con);
15331 } else if (revents & FDEVENT_ERR) {
15332 - log_error_write(srv, __FILE__, __LINE__, "s",
15333 + log_error_write(srv, __FILE__, __LINE__, "s",
15334 "fcgi: got a FDEVENT_ERR. Don't know why.");
15335 /* kill all connections to the scgi process */
15337 @@ -2628,43 +2628,40 @@
15338 scgi_connection_close(srv, hctx);
15339 joblist_append(srv, con);
15343 return HANDLER_FINISHED;
15345 -#define PATCH(x) \
15346 - p->conf.x = s->x;
15348 static int scgi_patch_connection(server *srv, connection *con, plugin_data *p) {
15350 plugin_config *s = p->config_storage[0];
15356 + PATCH_OPTION(exts);
15357 + PATCH_OPTION(debug);
15359 /* skip the first, the global context */
15360 for (i = 1; i < srv->config_context->used; i++) {
15361 data_config *dc = (data_config *)srv->config_context->data[i];
15362 s = p->config_storage[i];
15365 /* condition didn't match */
15366 if (!config_check_cond(srv, con, dc)) continue;
15370 for (j = 0; j < dc->value->used; j++) {
15371 data_unset *du = dc->value->data[j];
15374 if (buffer_is_equal_string(du->key, CONST_STR_LEN("scgi.server"))) {
15376 + PATCH_OPTION(exts);
15377 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("scgi.debug"))) {
15379 + PATCH_OPTION(debug);
15390 static handler_t scgi_check_extension(server *srv, connection *con, void *p_d, int uri_path_handler) {
15391 plugin_data *p = p_d;
15393 @@ -2673,30 +2670,30 @@
15396 scgi_extension *extension = NULL;
15399 /* Possibly, we processed already this request */
15400 if (con->file_started == 1) return HANDLER_GO_ON;
15403 fn = uri_path_handler ? con->uri.path : con->physical.path;
15405 if (buffer_is_empty(fn)) return HANDLER_GO_ON;
15407 s_len = fn->used - 1;
15410 scgi_patch_connection(srv, con, p);
15412 /* check if extension matches */
15413 for (k = 0; k < p->conf.exts->used; k++) {
15417 extension = p->conf.exts->exts[k];
15420 if (extension->key->used == 0) continue;
15423 ct_len = extension->key->used - 1;
15426 if (s_len < ct_len) continue;
15429 /* check extension in the form "/scgi_pattern" */
15430 if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
15432 @@ -2710,17 +2707,17 @@
15433 if (k == p->conf.exts->used) {
15434 return HANDLER_GO_ON;
15438 /* get best server */
15439 for (k = 0, ndx = -1; k < extension->used; k++) {
15440 scgi_extension_host *host = extension->hosts[k];
15443 /* we should have at least one proc that can do somthing */
15444 if (host->active_procs == 0) continue;
15446 if (used == -1 || host->load < used) {
15453 @@ -2728,12 +2725,12 @@
15454 /* found a server */
15456 scgi_extension_host *host = extension->hosts[ndx];
15459 - * if check-local is disabled, use the uri.path handler
15463 + * if check-local is disabled, use the uri.path handler
15468 /* init handler-context */
15469 if (uri_path_handler) {
15470 if (host->check_local == 0) {
15471 @@ -2741,7 +2738,7 @@
15474 hctx = handler_ctx_init();
15477 hctx->remote_conn = con;
15478 hctx->plugin_data = p;
15480 @@ -2749,45 +2746,45 @@
15482 hctx->conf.exts = p->conf.exts;
15483 hctx->conf.debug = p->conf.debug;
15486 con->plugin_ctx[p->id] = hctx;
15494 if (con->conf.log_request_handling) {
15495 log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_scgi");
15498 - /* the prefix is the SCRIPT_NAME,
15499 + /* the prefix is the SCRIPT_NAME,
15500 * everthing from start to the next slash
15501 * this is important for check-local = "disable"
15504 * if prefix = /admin.fcgi
15507 * /admin.fcgi/foo/bar
15510 * SCRIPT_NAME = /admin.fcgi
15511 * PATH_INFO = /foo/bar
15514 * if prefix = /fcgi-bin/
15517 * /fcgi-bin/foo/bar
15520 * SCRIPT_NAME = /fcgi-bin/foo
15527 /* the rewrite is only done for /prefix/? matches */
15528 if (extension->key->ptr[0] == '/' &&
15529 con->uri.path->used > extension->key->used &&
15530 NULL != (pathinfo = strchr(con->uri.path->ptr + extension->key->used - 1, '/'))) {
15531 - /* rewrite uri.path and pathinfo */
15533 + /* rewrite uri.path and pathinfo */
15535 buffer_copy_string(con->request.pathinfo, pathinfo);
15538 con->uri.path->used -= con->request.pathinfo->used - 1;
15539 con->uri.path->ptr[con->uri.path->used - 1] = '\0';
15541 @@ -2796,21 +2793,21 @@
15544 hctx = handler_ctx_init();
15547 hctx->remote_conn = con;
15548 hctx->plugin_data = p;
15553 hctx->conf.exts = p->conf.exts;
15554 hctx->conf.debug = p->conf.debug;
15557 con->plugin_ctx[p->id] = hctx;
15566 if (con->conf.log_request_handling) {
15567 log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_fastcgi");
15569 @@ -2821,11 +2818,11 @@
15570 /* no handler found */
15571 buffer_reset(con->physical.path);
15572 con->http_status = 500;
15574 - log_error_write(srv, __FILE__, __LINE__, "sb",
15575 - "no fcgi-handler found for:",
15577 + log_error_write(srv, __FILE__, __LINE__, "sb",
15578 + "no fcgi-handler found for:",
15582 return HANDLER_FINISHED;
15584 return HANDLER_GO_ON;
15585 @@ -2844,19 +2841,19 @@
15586 JOBLIST_FUNC(mod_scgi_handle_joblist) {
15587 plugin_data *p = p_d;
15588 handler_ctx *hctx = con->plugin_ctx[p->id];
15591 if (hctx == NULL) return HANDLER_GO_ON;
15593 if (hctx->fd != -1) {
15594 switch (hctx->state) {
15595 case FCGI_STATE_READ:
15596 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
15600 case FCGI_STATE_CONNECT:
15601 case FCGI_STATE_WRITE:
15602 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
15606 case FCGI_STATE_INIT:
15608 @@ -2873,21 +2870,21 @@
15610 static handler_t scgi_connection_close_callback(server *srv, connection *con, void *p_d) {
15611 plugin_data *p = p_d;
15614 return scgi_connection_close(srv, con->plugin_ctx[p->id]);
15617 TRIGGER_FUNC(mod_scgi_handle_trigger) {
15618 plugin_data *p = p_d;
15624 /* perhaps we should kill a connect attempt after 10-15 seconds
15627 * currently we wait for the TCP timeout which is on Linux 180 seconds
15636 /* check all childs if they are still up */
15637 @@ -2904,47 +2901,47 @@
15638 scgi_extension *ex;
15640 ex = exts->exts[j];
15643 for (n = 0; n < ex->used; n++) {
15647 unsigned long sum_load = 0;
15648 scgi_extension_host *host;
15651 host = ex->hosts[n];
15654 scgi_restart_dead_procs(srv, p, host);
15657 for (proc = host->first; proc; proc = proc->next) {
15658 sum_load += proc->load;
15662 if (host->num_procs &&
15663 host->num_procs < host->max_procs &&
15664 (sum_load / host->num_procs) > host->max_load_per_proc) {
15665 /* overload, spawn new child */
15666 scgi_proc *fp = NULL;
15669 if (p->conf.debug) {
15670 - log_error_write(srv, __FILE__, __LINE__, "s",
15671 + log_error_write(srv, __FILE__, __LINE__, "s",
15672 "overload detected, spawning a new child");
15676 for (fp = host->unused_procs; fp && fp->pid != 0; fp = fp->next);
15680 if (fp == host->unused_procs) host->unused_procs = fp->next;
15683 if (fp->next) fp->next->prev = NULL;
15688 fp = scgi_process_init();
15689 fp->id = host->max_id++;
15696 if (buffer_is_empty(host->unixsocket)) {
15697 fp->port = host->port + fp->id;
15699 @@ -2952,13 +2949,13 @@
15700 buffer_append_string(fp->socket, "-");
15701 buffer_append_long(fp->socket, fp->id);
15705 if (scgi_spawn_connection(srv, p, host, fp)) {
15706 log_error_write(srv, __FILE__, __LINE__, "s",
15707 "ERROR: spawning fcgi failed.");
15708 return HANDLER_ERROR;
15713 fp->next = host->first;
15715 @@ -2966,56 +2963,57 @@
15721 for (proc = host->first; proc; proc = proc->next) {
15722 if (proc->load != 0) break;
15723 if (host->num_procs <= host->min_procs) break;
15724 if (proc->pid == 0) continue;
15727 if (srv->cur_ts - proc->last_used > host->idle_timeout) {
15728 /* a proc is idling for a long time now,
15732 if (p->conf.debug) {
15733 - log_error_write(srv, __FILE__, __LINE__, "ssbsd",
15734 - "idle-timeout reached, terminating child:",
15735 - "socket:", proc->socket,
15736 + log_error_write(srv, __FILE__, __LINE__, "ssbsd",
15737 + "idle-timeout reached, terminating child:",
15738 + "socket:", proc->socket,
15745 if (proc->next) proc->next->prev = proc->prev;
15746 if (proc->prev) proc->prev->next = proc->next;
15749 if (proc->prev == NULL) host->first = proc->next;
15753 proc->next = host->unused_procs;
15756 if (host->unused_procs) host->unused_procs->prev = proc;
15757 host->unused_procs = proc;
15760 kill(proc->pid, SIGTERM);
15763 proc->state = PROC_STATE_KILLED;
15765 - log_error_write(srv, __FILE__, __LINE__, "ssbsd",
15767 - "socket:", proc->socket,
15769 + log_error_write(srv, __FILE__, __LINE__, "ssbsd",
15771 + "socket:", proc->socket,
15778 /* proc is now in unused, let the next second handle the next process */
15786 for (proc = host->unused_procs; proc; proc = proc->next) {
15790 if (proc->pid == 0) continue;
15793 switch (waitpid(proc->pid, &status, WNOHANG)) {
15795 /* child still running after timeout, good */
15796 @@ -3023,10 +3021,10 @@
15798 if (errno != EINTR) {
15799 /* no PID found ? should never happen */
15800 - log_error_write(srv, __FILE__, __LINE__, "sddss",
15801 + log_error_write(srv, __FILE__, __LINE__, "sddss",
15802 "pid ", proc->pid, proc->state,
15803 "not found:", strerror(errno));
15807 if (errno == ECHILD) {
15808 /* someone else has cleaned up for us */
15809 @@ -3040,25 +3038,26 @@
15810 /* the child should not terminate at all */
15811 if (WIFEXITED(status)) {
15812 if (proc->state != PROC_STATE_KILLED) {
15813 - log_error_write(srv, __FILE__, __LINE__, "sdb",
15815 + log_error_write(srv, __FILE__, __LINE__, "sdb",
15817 WEXITSTATUS(status), proc->socket);
15819 } else if (WIFSIGNALED(status)) {
15820 if (WTERMSIG(status) != SIGTERM) {
15821 - log_error_write(srv, __FILE__, __LINE__, "sd",
15822 - "child signaled:",
15823 + log_error_write(srv, __FILE__, __LINE__, "sd",
15824 + "child signaled:",
15828 - log_error_write(srv, __FILE__, __LINE__, "sd",
15829 - "child died somehow:",
15830 + log_error_write(srv, __FILE__, __LINE__, "sd",
15831 + "child died somehow:",
15835 proc->state = PROC_STATE_UNSET;
15842 @@ -3082,8 +3081,8 @@
15843 p->handle_subrequest = mod_scgi_handle_subrequest;
15844 p->handle_joblist = mod_scgi_handle_joblist;
15845 p->handle_trigger = mod_scgi_handle_trigger;
15854 Property changes on: src/mod_scgi.c
15855 ___________________________________________________________________
15856 Name: svn:eol-style
15859 Index: src/fastcgi.h
15860 ===================================================================
15861 --- src/fastcgi.h (.../tags/lighttpd-1.4.11) (revision 1159)
15862 +++ src/fastcgi.h (.../branches/lighttpd-merge-1.4.x) (revision 1159)
15868 * Defines for the FastCGI protocol.
15869 @@ -123,7 +123,7 @@
15873 - unsigned char type;
15874 + unsigned char type;
15875 unsigned char reserved[7];
15876 } FCGI_UnknownTypeBody;
15879 Property changes on: src/fastcgi.h
15880 ___________________________________________________________________
15881 Name: svn:eol-style
15885 ===================================================================
15886 --- src/etag.h (.../tags/lighttpd-1.4.11) (revision 1159)
15887 +++ src/etag.h (.../branches/lighttpd-merge-1.4.x) (revision 1159)
15890 #include <sys/types.h>
15891 #include <sys/stat.h>
15892 -#include <unistd.h>
15894 #include "buffer.h"
15896 int etag_is_equal(buffer *etag, const char *matches);
15897 int etag_create(buffer *etag, struct stat *st);
15898 int etag_mutate(buffer *mut, buffer *etag);
15904 Property changes on: src/etag.h
15905 ___________________________________________________________________
15906 Name: svn:eol-style
15909 Index: src/keyvalue.c
15910 ===================================================================
15911 --- src/keyvalue.c (.../tags/lighttpd-1.4.11) (revision 1159)
15912 +++ src/keyvalue.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
15914 { 504, "Gateway Timeout" },
15915 { 505, "HTTP Version Not Supported" },
15916 { 507, "Insufficient Storage" }, /* WebDAV */
15918 + { 509, "Bandwidth Limit exceeded" },
15923 @@ -102,12 +103,12 @@
15924 { 501, "501.html" },
15925 { 503, "503.html" },
15926 { 505, "505.html" },
15933 -const char *keyvalue_get_value(keyvalue *kv, int k) {
15934 +const char *keyvalue_get_value(keyvalue *kv, int k) {
15936 for (i = 0; kv[i].value; i++) {
15937 if (kv[i].key == k) return kv[i].value;
15938 @@ -115,7 +116,7 @@
15942 -int keyvalue_get_key(keyvalue *kv, const char *s) {
15943 +int keyvalue_get_key(keyvalue *kv, const char *s) {
15945 for (i = 0; kv[i].value; i++) {
15946 if (0 == strcmp(kv[i].value, s)) return kv[i].key;
15947 @@ -125,9 +126,9 @@
15949 keyvalue_buffer *keyvalue_buffer_init(void) {
15950 keyvalue_buffer *kvb;
15953 kvb = calloc(1, sizeof(*kvb));
15959 @@ -135,49 +136,49 @@
15961 if (kvb->size == 0) {
15965 kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
15968 for(i = 0; i < kvb->size; i++) {
15969 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
15971 } else if (kvb->used == kvb->size) {
15975 kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
15978 for(i = kvb->used; i < kvb->size; i++) {
15979 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
15984 kvb->kv[kvb->used]->key = key;
15985 kvb->kv[kvb->used]->value = strdup(value);
15994 void keyvalue_buffer_free(keyvalue_buffer *kvb) {
15998 for (i = 0; i < kvb->size; i++) {
15999 if (kvb->kv[i]->value) free(kvb->kv[i]->value);
16004 if (kvb->kv) free(kvb->kv);
16011 s_keyvalue_buffer *s_keyvalue_buffer_init(void) {
16012 s_keyvalue_buffer *kvb;
16015 kvb = calloc(1, sizeof(*kvb));
16021 @@ -186,50 +187,50 @@
16022 if (kvb->size == 0) {
16027 kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
16030 for(i = 0; i < kvb->size; i++) {
16031 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
16033 } else if (kvb->used == kvb->size) {
16037 kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
16040 for(i = kvb->used; i < kvb->size; i++) {
16041 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
16046 kvb->kv[kvb->used]->key = key ? strdup(key) : NULL;
16047 kvb->kv[kvb->used]->value = strdup(value);
16056 void s_keyvalue_buffer_free(s_keyvalue_buffer *kvb) {
16060 for (i = 0; i < kvb->size; i++) {
16061 if (kvb->kv[i]->key) free(kvb->kv[i]->key);
16062 if (kvb->kv[i]->value) free(kvb->kv[i]->value);
16067 if (kvb->kv) free(kvb->kv);
16074 httpauth_keyvalue_buffer *httpauth_keyvalue_buffer_init(void) {
16075 httpauth_keyvalue_buffer *kvb;
16078 kvb = calloc(1, sizeof(*kvb));
16084 @@ -237,42 +238,42 @@
16086 if (kvb->size == 0) {
16090 kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
16093 for(i = 0; i < kvb->size; i++) {
16094 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
16096 } else if (kvb->used == kvb->size) {
16100 kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
16103 for(i = kvb->used; i < kvb->size; i++) {
16104 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
16109 kvb->kv[kvb->used]->key = strdup(key);
16110 kvb->kv[kvb->used]->realm = strdup(realm);
16111 kvb->kv[kvb->used]->type = type;
16120 void httpauth_keyvalue_buffer_free(httpauth_keyvalue_buffer *kvb) {
16124 for (i = 0; i < kvb->size; i++) {
16125 if (kvb->kv[i]->key) free(kvb->kv[i]->key);
16126 if (kvb->kv[i]->realm) free(kvb->kv[i]->realm);
16131 if (kvb->kv) free(kvb->kv);
16137 @@ -306,9 +307,9 @@
16139 pcre_keyvalue_buffer *pcre_keyvalue_buffer_init(void) {
16140 pcre_keyvalue_buffer *kvb;
16143 kvb = calloc(1, sizeof(*kvb));
16149 @@ -319,46 +320,46 @@
16155 if (!key) return -1;
16158 if (kvb->size == 0) {
16163 kvb->kv = malloc(kvb->size * sizeof(*kvb->kv));
16166 for(i = 0; i < kvb->size; i++) {
16167 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
16169 } else if (kvb->used == kvb->size) {
16173 kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv));
16176 for(i = kvb->used; i < kvb->size; i++) {
16177 kvb->kv[i] = calloc(1, sizeof(**kvb->kv));
16182 kv = kvb->kv[kvb->used];
16183 if (NULL == (kv->key = pcre_compile(key,
16184 0, &errptr, &erroff, NULL))) {
16187 fprintf(stderr, "%s.%d: rexexp compilation error at %s\n", __FILE__, __LINE__, errptr);
16191 - if (NULL == (kv->key_extra = pcre_study(kv->key, 0, &errptr)) &&
16192 + if (NULL == (kv->key_extra = pcre_study(kv->key, 0, &errptr)) &&
16198 kv->value = buffer_init_string(value);
16207 @@ -380,9 +381,9 @@
16208 if (kv->value) buffer_free(kv->value);
16213 if (kvb->kv) free(kvb->kv);
16220 Property changes on: src/keyvalue.c
16221 ___________________________________________________________________
16222 Name: svn:eol-style
16225 Index: src/mod_mysql_vhost.c
16226 ===================================================================
16227 --- src/mod_mysql_vhost.c (.../tags/lighttpd-1.4.11) (revision 1159)
16228 +++ src/mod_mysql_vhost.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
16230 -#include <unistd.h>
16234 -#include <strings.h>
16235 +#include <string.h>
16237 #ifdef HAVE_CONFIG_H
16238 #include "config.h"
16241 +#ifdef HAVE_MYSQL_H
16242 +# ifdef HAVE_LIBMYSQL
16243 +# define HAVE_MYSQL
16250 @@ -16,61 +21,40 @@
16253 #include "stat_cache.h"
16254 -#ifdef DEBUG_MOD_MYSQL_VHOST
16257 +#include "sys-files.h"
16260 - * Plugin for lighttpd to use MySQL
16261 - * for domain to directory lookups,
16262 - * i.e virtual hosts (vhosts).
16264 - * Optionally sets fcgi_offset and fcgi_arg
16265 - * in preparation for fcgi.c to handle
16266 - * per-user fcgi chroot jails.
16268 - * /ada@riksnet.se 2004-12-06
16270 +#include "mod_sql_vhost_core.h"
16274 +#define CORE_PLUGIN "mod_sql_vhost_core"
16284 - buffer *hostname;
16285 - unsigned short port;
16289 buffer *mysql_post;
16291 + mod_sql_vhost_core_plugin_config *core;
16294 /* global plugin data */
16302 plugin_config **config_storage;
16304 - plugin_config conf;
16306 + plugin_config conf;
16309 -/* per connection plugin data */
16311 - buffer *server_name;
16312 - buffer *document_root;
16313 - buffer *fcgi_arg;
16314 - unsigned fcgi_offset;
16315 -} plugin_connection_data;
16316 +SQLVHOST_BACKEND_GETVHOST(mod_mysql_vhost_get_vhost);
16318 /* init the plugin data */
16319 INIT_FUNC(mod_mysql_vhost_init) {
16323 p = calloc(1, sizeof(*p));
16325 p->tmp_buf = buffer_init();
16326 @@ -83,144 +67,77 @@
16327 plugin_data *p = p_d;
16332 - log_error_write(srv, __FILE__, __LINE__, "ss",
16333 - "mod_mysql_vhost_cleanup", p ? "yes" : "NO");
16336 if (!p) return HANDLER_GO_ON;
16339 if (p->config_storage) {
16341 for (i = 0; i < srv->config_context->used; i++) {
16342 plugin_config *s = p->config_storage[i];
16347 mysql_close(s->mysql);
16349 - buffer_free(s->mydb);
16350 - buffer_free(s->myuser);
16351 - buffer_free(s->mypass);
16352 - buffer_free(s->mysock);
16354 buffer_free(s->mysql_pre);
16355 buffer_free(s->mysql_post);
16360 free(p->config_storage);
16362 buffer_free(p->tmp_buf);
16367 return HANDLER_GO_ON;
16370 -/* handle the plugin per connection data */
16371 -static void* mod_mysql_vhost_connection_data(server *srv, connection *con, void *p_d)
16373 - plugin_data *p = p_d;
16374 - plugin_connection_data *c = con->plugin_ctx[p->id];
16379 - log_error_write(srv, __FILE__, __LINE__, "ss",
16380 - "mod_mysql_connection_data", c ? "old" : "NEW");
16384 - c = calloc(1, sizeof(*c));
16386 - c->server_name = buffer_init();
16387 - c->document_root = buffer_init();
16388 - c->fcgi_arg = buffer_init();
16389 - c->fcgi_offset = 0;
16391 - return con->plugin_ctx[p->id] = c;
16394 -/* destroy the plugin per connection data */
16395 -CONNECTION_FUNC(mod_mysql_vhost_handle_connection_close) {
16396 - plugin_data *p = p_d;
16397 - plugin_connection_data *c = con->plugin_ctx[p->id];
16402 - log_error_write(srv, __FILE__, __LINE__, "ss",
16403 - "mod_mysql_vhost_handle_connection_close", c ? "yes" : "NO");
16406 - if (!c) return HANDLER_GO_ON;
16408 - buffer_free(c->server_name);
16409 - buffer_free(c->document_root);
16410 - buffer_free(c->fcgi_arg);
16411 - c->fcgi_offset = 0;
16415 - con->plugin_ctx[p->id] = NULL;
16416 - return HANDLER_GO_ON;
16419 /* set configuration values */
16420 SERVER_FUNC(mod_mysql_vhost_set_defaults) {
16421 plugin_data *p = p_d;
16422 + mod_sql_vhost_core_plugin_data *core_config;
16427 - config_values_t cv[] = {
16428 - { "mysql-vhost.db", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
16429 - { "mysql-vhost.user", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
16430 - { "mysql-vhost.pass", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
16431 - { "mysql-vhost.sock", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
16432 - { "mysql-vhost.sql", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
16433 - { "mysql-vhost.hostname", NULL, T_CONFIG_STRING,T_CONFIG_SCOPE_SERVER },
16434 - { "mysql-vhost.port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER },
16435 - { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
16438 + /* our very own plugin storage, one entry for each conditional
16440 + * srv->config_context->used is the number of conditionals
16442 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
16445 + /* get the config of the core-plugin */
16446 + core_config = plugin_get_config(srv, CORE_PLUGIN);
16449 + /* walk through all conditionals and check for assignments */
16450 for (i = 0; i < srv->config_context->used; i++) {
16457 + /* get the config from the core plugin for this conditional-context */
16458 s = calloc(1, sizeof(plugin_config));
16459 - s->mydb = buffer_init();
16460 - s->myuser = buffer_init();
16461 - s->mypass = buffer_init();
16462 - s->mysock = buffer_init();
16463 - s->hostname = buffer_init();
16464 - s->port = 0; /* default port for mysql */
16465 - sel = buffer_init();
16468 + s->core = core_config->config_storage[i];
16472 s->mysql_pre = buffer_init();
16473 s->mysql_post = buffer_init();
16475 - cv[0].destination = s->mydb;
16476 - cv[1].destination = s->myuser;
16477 - cv[2].destination = s->mypass;
16478 - cv[3].destination = s->mysock;
16479 - cv[4].destination = sel;
16480 - cv[5].destination = s->hostname;
16481 - cv[6].destination = &(s->port);
16484 p->config_storage[i] = s;
16486 - if (config_insert_values_global(srv,
16487 - ((data_config *)srv->config_context->data[i])->value,
16488 - cv)) return HANDLER_ERROR;
16490 - s->mysql_pre = buffer_init();
16491 - s->mysql_post = buffer_init();
16494 + /* check if we are the plugin for this backend */
16495 + if (!buffer_is_equal_string(s->core->backend, CONST_STR_LEN("mysql"))) continue;
16497 + /* attach us to the core-plugin */
16498 + s->core->backend_data = p;
16499 + s->core->get_vhost = mod_mysql_vhost_get_vhost;
16501 + sel = buffer_init();
16502 + buffer_copy_string_buffer(sel, s->core->select_vhost);
16504 if (sel->used && (qmark = index(sel->ptr, '?'))) {
16506 buffer_copy_string(s->mysql_pre, sel->ptr);
16507 @@ -228,35 +145,35 @@
16509 buffer_copy_string_buffer(s->mysql_pre, sel);
16520 * - password, default: empty
16521 * - socket, default: mysql default
16522 * - hostname, if set overrides socket
16523 * - port, default: 3306
16527 /* all have to be set */
16528 - if (!(buffer_is_empty(s->myuser) ||
16529 - buffer_is_empty(s->mydb))) {
16530 + if (!(buffer_is_empty(s->core->user) ||
16531 + buffer_is_empty(s->core->db))) {
16536 if (NULL == (s->mysql = mysql_init(NULL))) {
16537 log_error_write(srv, __FILE__, __LINE__, "s", "mysql_init() failed, exiting...");
16540 return HANDLER_ERROR;
16542 -#define FOO(x) (s->x->used ? s->x->ptr : NULL)
16544 - if (!mysql_real_connect(s->mysql, FOO(hostname), FOO(myuser), FOO(mypass),
16545 - FOO(mydb), s->port, FOO(mysock), 0)) {
16546 +#define FOO(x) (s->core->x->used ? s->core->x->ptr : NULL)
16548 + if (!mysql_real_connect(s->mysql, FOO(hostname), FOO(user), FOO(pass),
16549 + FOO(db), s->core->port, FOO(sock), 0)) {
16550 log_error_write(srv, __FILE__, __LINE__, "s", mysql_error(s->mysql));
16553 return HANDLER_ERROR;
16556 @@ -265,61 +182,47 @@
16557 /* otherwise we cannot be sure that mysql is fd i-1 */
16558 if (-1 == (fd = open("/dev/null", 0))) {
16560 - fcntl(fd-1, F_SETFD, FD_CLOEXEC);
16561 + fcntl(fd-1, F_SETFD, FD_CLOEXEC);
16570 return HANDLER_GO_ON;
16573 -#define PATCH(x) \
16574 - p->conf.x = s->x;
16575 static int mod_mysql_vhost_patch_connection(server *srv, connection *con, plugin_data *p) {
16578 plugin_config *s = p->config_storage[0];
16580 - PATCH(mysql_pre);
16581 - PATCH(mysql_post);
16587 + PATCH_OPTION(mysql_pre);
16588 + PATCH_OPTION(mysql_post);
16589 + PATCH_OPTION(mysql);
16591 /* skip the first, the global context */
16592 for (i = 1; i < srv->config_context->used; i++) {
16593 data_config *dc = (data_config *)srv->config_context->data[i];
16594 s = p->config_storage[i];
16597 /* condition didn't match */
16598 if (!config_check_cond(srv, con, dc)) continue;
16600 - /* merge config */
16601 - for (j = 0; j < dc->value->used; j++) {
16602 - data_unset *du = dc->value->data[j];
16604 - if (buffer_is_equal_string(du->key, CONST_STR_LEN("mysql-vhost.sql"))) {
16605 - PATCH(mysql_pre);
16606 - PATCH(mysql_post);
16613 + PATCH_OPTION(mysql);
16614 + PATCH_OPTION(mysql_pre);
16615 + PATCH_OPTION(mysql_post);
16625 -/* handle document root request */
16626 -CONNECTION_FUNC(mod_mysql_vhost_handle_docroot) {
16628 + * get the vhost info from the database
16630 +SQLVHOST_BACKEND_GETVHOST(mod_mysql_vhost_get_vhost) {
16631 plugin_data *p = p_d;
16632 - plugin_connection_data *c;
16633 - stat_cache_entry *sce;
16637 @@ -332,13 +235,6 @@
16639 if (!p->conf.mysql) return HANDLER_GO_ON;
16641 - /* sets up connection data if not done yet */
16642 - c = mod_mysql_vhost_connection_data(srv, con, p_d);
16644 - /* check if cached this connection */
16645 - if (c->server_name->used && /* con->uri.authority->used && */
16646 - buffer_is_equal(c->server_name, con->uri.authority)) goto GO_ON;
16648 /* build and run SQL query */
16649 buffer_copy_string_buffer(p->tmp_buf, p->conf.mysql_pre);
16650 if (p->conf.mysql_post->used) {
16651 @@ -347,77 +243,43 @@
16653 if (mysql_query(p->conf.mysql, p->tmp_buf->ptr)) {
16654 log_error_write(srv, __FILE__, __LINE__, "s", mysql_error(p->conf.mysql));
16657 + mysql_free_result(result);
16658 + return HANDLER_GO_ON;
16660 result = mysql_store_result(p->conf.mysql);
16661 cols = mysql_num_fields(result);
16662 row = mysql_fetch_row(result);
16664 if (!row || cols < 1) {
16665 /* no such virtual host */
16666 mysql_free_result(result);
16667 return HANDLER_GO_ON;
16670 - /* sanity check that really is a directory */
16671 - buffer_copy_string(p->tmp_buf, row[0]);
16672 - BUFFER_APPEND_SLASH(p->tmp_buf);
16673 + buffer_copy_string(docroot, row[0]);
16675 - if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->tmp_buf, &sce)) {
16676 - log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), p->tmp_buf);
16679 - if (!S_ISDIR(sce->st.st_mode)) {
16680 - log_error_write(srv, __FILE__, __LINE__, "sb", "Not a directory", p->tmp_buf);
16684 - /* cache the data */
16685 - buffer_copy_string_buffer(c->server_name, con->uri.authority);
16686 - buffer_copy_string_buffer(c->document_root, p->tmp_buf);
16688 - /* fcgi_offset and fcgi_arg are optional */
16689 - if (cols > 1 && row[1]) {
16690 - c->fcgi_offset = atoi(row[1]);
16692 - if (cols > 2 && row[2]) {
16693 - buffer_copy_string(c->fcgi_arg, row[2]);
16695 - c->fcgi_arg->used = 0;
16698 - c->fcgi_offset = c->fcgi_arg->used = 0;
16700 mysql_free_result(result);
16702 - /* fix virtual server and docroot */
16703 -GO_ON: buffer_copy_string_buffer(con->server_name, c->server_name);
16704 - buffer_copy_string_buffer(con->physical.doc_root, c->document_root);
16707 - log_error_write(srv, __FILE__, __LINE__, "sbbdb",
16708 - result ? "NOT CACHED" : "cached",
16709 - con->server_name, con->physical.doc_root,
16710 - c->fcgi_offset, c->fcgi_arg);
16712 - return HANDLER_GO_ON;
16714 -ERR500: if (result) mysql_free_result(result);
16715 - con->http_status = 500; /* Internal Error */
16716 - return HANDLER_FINISHED;
16717 + return HANDLER_GO_ON;
16720 /* this function is called at dlopen() time and inits the callbacks */
16721 int mod_mysql_vhost_plugin_init(plugin *p) {
16724 p->version = LIGHTTPD_VERSION_ID;
16725 p->name = buffer_init_string("mysql_vhost");
16727 p->init = mod_mysql_vhost_init;
16728 p->cleanup = mod_mysql_vhost_cleanup;
16729 - p->handle_request_done = mod_mysql_vhost_handle_connection_close;
16731 p->set_defaults = mod_mysql_vhost_set_defaults;
16732 - p->handle_docroot = mod_mysql_vhost_handle_docroot;
16734 + ds = data_string_init();
16735 + buffer_copy_string(ds->value, CORE_PLUGIN);
16736 + array_insert_unique(p->required_plugins, (data_unset *)ds);
16741 Index: src/request.c
16742 ===================================================================
16743 --- src/request.c (.../tags/lighttpd-1.4.11) (revision 1159)
16744 +++ src/request.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
16745 @@ -10,15 +10,17 @@
16746 #include "keyvalue.h"
16749 +#include "sys-strings.h"
16751 static int request_check_hostname(server *srv, connection *con, buffer *host) {
16752 enum { DOMAINLABEL, TOPLABEL } stage = TOPLABEL;
16757 - int is_ip = -1; /* -1 don't know yet, 0 no, 1 yes */
16758 + int is_ip = -1; /* -1 don't know yet, 0 no, 1 yes */
16765 @@ -32,17 +34,17 @@
16766 * IPv6address = "[" ... "]"
16772 if (!host || host->used == 0) return 0;
16775 host_len = host->used - 1;
16779 if (host->ptr[0] == '[') {
16780 char *c = host->ptr + 1;
16784 /* check portnumber */
16785 for (; *c && *c != ']'; c++) {
16787 @@ -53,12 +55,12 @@
16800 if (*(c+1) == ':') {
16801 for (c += 2; *c; c++) {
16802 @@ -69,39 +71,39 @@
16808 if (NULL != (colon = memchr(host->ptr, ':', host_len))) {
16809 char *c = colon + 1;
16812 /* check portnumber */
16814 if (!light_isdigit(*c)) return -1;
16818 /* remove the port from the host-len */
16819 host_len = colon - host->ptr;
16823 /* Host is empty */
16824 if (host_len == 0) return -1;
16827 /* scan from the right and skip the \0 */
16828 for (i = host_len - 1; i + 1 > 0; i--) {
16829 const char c = host->ptr[i];
16835 /* only switch stage, if this is not the last character */
16836 if (i != host_len - 1) {
16837 if (label_len == 0) {
16842 /* check the first character at right of the dot */
16844 if (!light_isalpha(host->ptr[i+1])) {
16848 } else if (!light_isdigit(host->ptr[i+1])) {
16850 @@ -111,9 +113,9 @@
16856 stage = DOMAINLABEL;
16861 } else if (i == 0) {
16862 @@ -135,7 +137,7 @@
16871 @@ -143,7 +145,7 @@
16872 if (label_len == 0) {
16879 } else if (!light_isdigit(c)) {
16880 @@ -156,12 +158,12 @@
16881 if (label_len == 0) {
16886 /* c is either - or alphanum here */
16887 if ('-' == host->ptr[i+1]) {
16894 } else if (i == 0) {
16895 @@ -176,20 +178,20 @@
16906 /* a IP has to consist of 4 parts */
16907 if (is_ip == 1 && level != 3) {
16912 if (label_len == 0) {
16920 @@ -201,53 +203,53 @@
16930 * val1, val2, val3, val4
16933 * into a array (more or less a explode() incl. striping of whitespaces
16937 if (b->used == 0) return 0;
16943 for (i =0; i < b->used - 1; ) {
16944 char *start = NULL, *end = NULL;
16953 for (; (*s == ' ' || *s == '\t') && i < b->used - 1; i++, s++);
16960 case 1: /* value */
16964 for (; *s != ',' && i < b->used - 1; i++, s++);
16968 for (; (*end == ' ' || *end == '\t') && end > start; end--);
16971 if (NULL == (ds = (data_string *)array_get_unused_element(vals, TYPE_STRING))) {
16972 ds = data_string_init();
16975 buffer_copy_string_len(ds->value, start, end-start+1);
16976 array_insert_unique(vals, (data_unset *)ds);
16984 /* end of string */
16990 @@ -263,7 +265,7 @@
16991 if (c <= 32) return 0;
16992 if (c == 127) return 0;
16993 if (c == 255) return 0;
16999 @@ -271,28 +273,28 @@
17000 char *uri = NULL, *proto = NULL, *method = NULL, con_length_set;
17001 int is_key = 1, key_len = 0, is_ws_after_key = 0, in_folding;
17002 char *value = NULL, *key = NULL;
17005 enum { HTTP_CONNECTION_UNSET, HTTP_CONNECTION_KEEPALIVE, HTTP_CONNECTION_CLOSE } keep_alive_set = HTTP_CONNECTION_UNSET;
17011 int request_line_stage = 0;
17018 data_string *ds = NULL;
17021 - * Request: "^(GET|POST|HEAD) ([^ ]+(\\?[^ ]+|)) (HTTP/1\\.[01])$"
17022 - * Option : "^([-a-zA-Z]+): (.+)$"
17025 + * Request: "^(GET|POST|HEAD) ([^ ]+(\\?[^ ]+|)) (HTTP/1\\.[01])$"
17026 + * Option : "^([-a-zA-Z]+): (.+)$"
17030 if (con->conf.log_request_header) {
17031 - log_error_write(srv, __FILE__, __LINE__, "sdsdSb",
17033 - "request-len:", con->request.request->used,
17034 + log_error_write(srv, __FILE__, __LINE__, "sdsdSb",
17036 + "request-len:", con->request.request->used,
17037 "\n", con->request.request);
17040 @@ -300,13 +302,13 @@
17041 con->request.request->ptr[0] == '\r' &&
17042 con->request.request->ptr[1] == '\n') {
17043 /* we are in keep-alive and might get \r\n after a previous POST request.*/
17046 buffer_copy_string_len(con->parse_request, con->request.request->ptr + 2, con->request.request->used - 1 - 2);
17048 /* fill the local request buffer */
17049 buffer_copy_string_buffer(con->parse_request, con->request.request);
17053 keep_alive_set = 0;
17054 con_length_set = 0;
17056 @@ -318,25 +320,25 @@
17058 for (i = 0, first = 0; i < con->parse_request->used && line == 0; i++) {
17059 char *cur = con->parse_request->ptr + i;
17065 if (con->parse_request->ptr[i+1] == '\n') {
17072 con->parse_request->ptr[i] = '\0';
17073 con->parse_request->ptr[i+1] = '\0';
17076 buffer_copy_string_len(con->request.request_line, con->parse_request->ptr, i);
17079 if (request_line_stage != 2) {
17080 con->http_status = 400;
17081 con->response.keep_alive = 0;
17082 con->keep_alive = 0;
17085 if (srv->srvconf.log_request_header_on_error) {
17086 log_error_write(srv, __FILE__, __LINE__, "s", "incomplete request line -> 400");
17087 log_error_write(srv, __FILE__, __LINE__, "Sb",
17088 @@ -345,36 +347,36 @@
17094 proto = con->parse_request->ptr + first;
17098 *(proto - 1) = '\0';
17101 /* we got the first one :) */
17102 if (-1 == (r = get_http_method_key(method))) {
17103 con->http_status = 501;
17104 con->response.keep_alive = 0;
17105 con->keep_alive = 0;
17108 if (srv->srvconf.log_request_header_on_error) {
17109 log_error_write(srv, __FILE__, __LINE__, "s", "unknown http-method -> 501");
17110 log_error_write(srv, __FILE__, __LINE__, "Sb",
17111 "request-header:\n",
17112 con->request.request);
17120 con->request.http_method = r;
17127 * HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT
17131 if (0 == strncmp(proto, "HTTP/", sizeof("HTTP/") - 1)) {
17132 char * major = proto + sizeof("HTTP/") - 1;
17133 char * minor = strchr(major, '.');
17134 @@ -413,10 +415,10 @@
17137 if (major_num == 1 && minor_num == 1) {
17138 - con->request.http_version = con->conf.allow_http11 ? HTTP_VERSION_1_1 : HTTP_VERSION_1_0;
17139 + con->request.http_version = HTTP_VERSION_1_1;
17140 } else if (major_num == 1 && minor_num == 0) {
17141 con->request.http_version = HTTP_VERSION_1_0;
17144 con->http_status = 505;
17146 if (srv->srvconf.log_request_header_on_error) {
17147 @@ -439,30 +441,30 @@
17153 if (0 == strncmp(uri, "http://", 7) &&
17154 NULL != (nuri = strchr(uri + 7, '/'))) {
17155 /* ignore the host-part */
17158 buffer_copy_string_len(con->request.uri, nuri, proto - nuri - 1);
17160 /* everything looks good so far */
17161 buffer_copy_string_len(con->request.uri, uri, proto - uri - 1);
17165 /* check uri for invalid characters */
17166 for (j = 0; j < con->request.uri->used - 1; j++) {
17167 if (!request_uri_is_valid_char(con->request.uri->ptr[j])) {
17168 unsigned char buf[2];
17169 con->http_status = 400;
17170 con->keep_alive = 0;
17173 if (srv->srvconf.log_request_header_on_error) {
17174 buf[0] = con->request.uri->ptr[j];
17178 if (con->request.uri->ptr[j] > 32 &&
17179 - con->request.uri->ptr[j] != 127) {
17180 + con->request.uri->ptr[j] != 127) {
17181 /* the character is printable -> print it */
17182 log_error_write(srv, __FILE__, __LINE__, "ss",
17183 "invalid character in URI -> 400",
17184 @@ -473,20 +475,20 @@
17185 "invalid character in URI -> 400",
17186 con->request.uri->ptr[j]);
17190 log_error_write(srv, __FILE__, __LINE__, "Sb",
17191 "request-header:\n",
17192 con->request.request);
17201 buffer_copy_string_buffer(con->request.orig_uri, con->request.uri);
17204 con->http_status = 0;
17210 @@ -494,14 +496,14 @@
17213 switch(request_line_stage) {
17217 - method = con->parse_request->ptr + first;
17218 + method = con->parse_request->ptr + first;
17223 - uri = con->parse_request->ptr + first;
17224 + uri = con->parse_request->ptr + first;
17228 @@ -509,7 +511,7 @@
17229 con->http_status = 400;
17230 con->response.keep_alive = 0;
17231 con->keep_alive = 0;
17234 if (srv->srvconf.log_request_header_on_error) {
17235 log_error_write(srv, __FILE__, __LINE__, "s", "overlong request line -> 400");
17236 log_error_write(srv, __FILE__, __LINE__, "Sb",
17237 @@ -518,12 +520,12 @@
17243 request_line_stage++;
17251 if (con->request.uri->used == 1) {
17252 @@ -540,30 +542,30 @@
17258 for (; i < con->parse_request->used && !done; i++) {
17259 char *cur = con->parse_request->ptr + i;
17268 * 1*<any CHAR except CTLs or separators>
17269 * CTLs == 0-31 + 127
17281 if (is_ws_after_key == 0) {
17282 key_len = i - first;
17284 is_ws_after_key = 0;
17290 @@ -584,8 +586,8 @@
17291 con->http_status = 400;
17292 con->keep_alive = 0;
17293 con->response.keep_alive = 0;
17295 - log_error_write(srv, __FILE__, __LINE__, "sbsds",
17297 + log_error_write(srv, __FILE__, __LINE__, "sbsds",
17298 "invalid character in key", con->request.request, cur, *cur, "-> 400");
17301 @@ -594,13 +596,13 @@
17313 key_len = i - first;
17316 /* skip every thing up to the : */
17317 for (j = 1; !got_colon; j++) {
17318 switch(con->parse_request->ptr[j + i]) {
17319 @@ -610,40 +612,40 @@
17334 if (srv->srvconf.log_request_header_on_error) {
17335 log_error_write(srv, __FILE__, __LINE__, "s", "WS character in key -> 400");
17336 log_error_write(srv, __FILE__, __LINE__, "Sb",
17337 "request-header:\n",
17338 con->request.request);
17342 con->http_status = 400;
17343 con->response.keep_alive = 0;
17344 con->keep_alive = 0;
17354 if (con->parse_request->ptr[i+1] == '\n' && i == first) {
17355 /* End of Header */
17356 con->parse_request->ptr[i] = '\0';
17357 con->parse_request->ptr[i+1] = '\0';
17368 if (srv->srvconf.log_request_header_on_error) {
17369 @@ -652,7 +654,7 @@
17370 "request-header:\n",
17371 con->request.request);
17375 con->http_status = 400;
17376 con->keep_alive = 0;
17377 con->response.keep_alive = 0;
17378 @@ -693,16 +695,16 @@
17379 con->http_status = 400;
17380 con->keep_alive = 0;
17381 con->response.keep_alive = 0;
17384 if (srv->srvconf.log_request_header_on_error) {
17385 - log_error_write(srv, __FILE__, __LINE__, "sbsds",
17386 + log_error_write(srv, __FILE__, __LINE__, "sbsds",
17387 "CTL character in key", con->request.request, cur, *cur, "-> 400");
17389 log_error_write(srv, __FILE__, __LINE__, "Sb",
17390 "request-header:\n",
17391 con->request.request);
17398 @@ -710,25 +712,25 @@
17404 if (con->parse_request->ptr[i+1] == '\n') {
17405 /* End of Headerline */
17406 con->parse_request->ptr[i] = '\0';
17407 con->parse_request->ptr[i+1] = '\0';
17415 if (srv->srvconf.log_request_header_on_error) {
17416 log_error_write(srv, __FILE__, __LINE__, "s", "WS at the start of first line -> 400");
17419 log_error_write(srv, __FILE__, __LINE__, "Sb",
17420 "request-header:\n",
17421 con->request.request);
17426 con->http_status = 400;
17427 con->keep_alive = 0;
17428 con->response.keep_alive = 0;
17429 @@ -738,9 +740,9 @@
17432 key = con->parse_request->ptr + first;
17435 s_len = cur - value;
17440 if (NULL == (ds = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
17441 @@ -748,86 +750,87 @@
17443 buffer_copy_string_len(ds->key, key, key_len);
17444 buffer_copy_string_len(ds->value, value, s_len);
17446 - /* retreive values
17450 + /* retreive values
17453 * the list of options is sorted to simplify the search
17457 if (0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Connection")))) {
17465 vals = srv->split_vals;
17470 http_request_split_value(vals, ds->value);
17473 for (vi = 0; vi < vals->used; vi++) {
17474 data_string *dsv = (data_string *)vals->data[vi];
17477 if (0 == buffer_caseless_compare(CONST_BUF_LEN(dsv->value), CONST_STR_LEN("keep-alive"))) {
17478 keep_alive_set = HTTP_CONNECTION_KEEPALIVE;
17482 } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(dsv->value), CONST_STR_LEN("close"))) {
17483 keep_alive_set = HTTP_CONNECTION_CLOSE;
17491 } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Content-Length")))) {
17493 unsigned long int r;
17497 if (con_length_set) {
17498 con->http_status = 400;
17499 con->keep_alive = 0;
17502 if (srv->srvconf.log_request_header_on_error) {
17503 - log_error_write(srv, __FILE__, __LINE__, "s",
17504 + log_error_write(srv, __FILE__, __LINE__, "s",
17505 "duplicate Content-Length-header -> 400");
17506 log_error_write(srv, __FILE__, __LINE__, "Sb",
17507 "request-header:\n",
17508 con->request.request);
17510 + ds->free((data_unset *) ds);
17515 if (ds->value->used == 0) SEGFAULT();
17518 for (j = 0; j < ds->value->used - 1; j++) {
17519 char c = ds->value->ptr[j];
17520 if (!isdigit((unsigned char)c)) {
17521 - log_error_write(srv, __FILE__, __LINE__, "sbs",
17522 + log_error_write(srv, __FILE__, __LINE__, "sbs",
17523 "content-length broken:", ds->value, "-> 400");
17526 con->http_status = 400;
17527 con->keep_alive = 0;
17530 array_insert_unique(con->request.headers, (data_unset *)ds);
17536 r = strtoul(ds->value->ptr, &err, 10);
17539 if (*err == '\0') {
17540 con_length_set = 1;
17541 con->request.content_length = r;
17543 - log_error_write(srv, __FILE__, __LINE__, "sbs",
17544 + log_error_write(srv, __FILE__, __LINE__, "sbs",
17545 "content-length broken:", ds->value, "-> 400");
17548 con->http_status = 400;
17549 con->keep_alive = 0;
17552 array_insert_unique(con->request.headers, (data_unset *)ds);
17555 @@ -838,23 +841,24 @@
17557 con->http_status = 400;
17558 con->keep_alive = 0;
17561 if (srv->srvconf.log_request_header_on_error) {
17562 - log_error_write(srv, __FILE__, __LINE__, "s",
17563 + log_error_write(srv, __FILE__, __LINE__, "s",
17564 "duplicate Content-Type-header -> 400");
17565 log_error_write(srv, __FILE__, __LINE__, "Sb",
17566 "request-header:\n",
17567 con->request.request);
17569 + ds->free((data_unset *) ds);
17572 } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Expect")))) {
17573 - /* HTTP 2616 8.2.3
17574 + /* HTTP 2616 8.2.3
17575 * Expect: 100-continue
17578 * -> (10.1.1) 100 (read content, process request, send final status-code)
17579 * -> (10.4.18) 417 (close)
17582 * (not handled at all yet, we always send 417 here)
17584 * What has to be added ?
17585 @@ -863,10 +867,10 @@
17591 con->http_status = 417;
17592 con->keep_alive = 0;
17595 array_insert_unique(con->request.headers, (data_unset *)ds);
17597 } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Host")))) {
17598 @@ -875,14 +879,15 @@
17600 con->http_status = 400;
17601 con->keep_alive = 0;
17604 if (srv->srvconf.log_request_header_on_error) {
17605 - log_error_write(srv, __FILE__, __LINE__, "s",
17606 + log_error_write(srv, __FILE__, __LINE__, "s",
17607 "duplicate Host-header -> 400");
17608 log_error_write(srv, __FILE__, __LINE__, "Sb",
17609 "request-header:\n",
17610 con->request.request);
17612 + ds->free((data_unset *) ds);
17615 } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("If-Modified-Since")))) {
17616 @@ -897,14 +902,15 @@
17618 con->http_status = 400;
17619 con->keep_alive = 0;
17622 if (srv->srvconf.log_request_header_on_error) {
17623 - log_error_write(srv, __FILE__, __LINE__, "s",
17624 + log_error_write(srv, __FILE__, __LINE__, "s",
17625 "duplicate If-Modified-Since header -> 400");
17626 log_error_write(srv, __FILE__, __LINE__, "Sb",
17627 "request-header:\n",
17628 con->request.request);
17630 + ds->free((data_unset *) ds);
17633 } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("If-None-Match")))) {
17634 @@ -914,47 +920,49 @@
17636 con->http_status = 400;
17637 con->keep_alive = 0;
17640 if (srv->srvconf.log_request_header_on_error) {
17641 - log_error_write(srv, __FILE__, __LINE__, "s",
17642 + log_error_write(srv, __FILE__, __LINE__, "s",
17643 "duplicate If-None-Match-header -> 400");
17644 log_error_write(srv, __FILE__, __LINE__, "Sb",
17645 "request-header:\n",
17646 con->request.request);
17648 + ds->free((data_unset *) ds);
17651 } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Range")))) {
17652 if (!con->request.http_range) {
17656 if (0 == strncasecmp(ds->value->ptr, "bytes=", 6) &&
17657 NULL != strchr(ds->value->ptr+6, '-')) {
17660 /* if dup, only the first one will survive */
17661 con->request.http_range = ds->value->ptr + 6;
17664 con->http_status = 400;
17665 con->keep_alive = 0;
17668 if (srv->srvconf.log_request_header_on_error) {
17669 - log_error_write(srv, __FILE__, __LINE__, "s",
17670 + log_error_write(srv, __FILE__, __LINE__, "s",
17671 "duplicate Range-header -> 400");
17672 log_error_write(srv, __FILE__, __LINE__, "Sb",
17673 "request-header:\n",
17674 con->request.request);
17676 + ds->free((data_unset *) ds);
17682 array_insert_unique(con->request.headers, (data_unset *)ds);
17684 /* empty header-fields are not allowed by HTTP-RFC, we just ignore them */
17692 @@ -963,10 +971,10 @@
17695 if (srv->srvconf.log_request_header_on_error) {
17696 - log_error_write(srv, __FILE__, __LINE__, "sbs",
17697 + log_error_write(srv, __FILE__, __LINE__, "sbs",
17698 "CR without LF", con->request.request, "-> 400");
17702 con->http_status = 400;
17703 con->keep_alive = 0;
17704 con->response.keep_alive = 0;
17705 @@ -982,28 +990,28 @@
17711 con->header_len = i;
17714 /* do some post-processing */
17716 if (con->request.http_version == HTTP_VERSION_1_1) {
17717 if (keep_alive_set != HTTP_CONNECTION_CLOSE) {
17718 /* no Connection-Header sent */
17721 /* HTTP/1.1 -> keep-alive default TRUE */
17722 con->keep_alive = 1;
17724 con->keep_alive = 0;
17728 /* RFC 2616, 14.23 */
17729 if (con->request.http_host == NULL ||
17730 buffer_is_empty(con->request.http_host)) {
17731 con->http_status = 400;
17732 con->response.keep_alive = 0;
17733 con->keep_alive = 0;
17736 if (srv->srvconf.log_request_header_on_error) {
17737 log_error_write(srv, __FILE__, __LINE__, "s", "HTTP/1.1 but Host missing -> 400");
17738 log_error_write(srv, __FILE__, __LINE__, "Sb",
17739 @@ -1015,18 +1023,18 @@
17741 if (keep_alive_set == HTTP_CONNECTION_KEEPALIVE) {
17742 /* no Connection-Header sent */
17745 /* HTTP/1.0 -> keep-alive default FALSE */
17746 con->keep_alive = 1;
17748 con->keep_alive = 0;
17753 /* check hostname field if it is set */
17754 if (NULL != con->request.http_host &&
17755 0 != request_check_hostname(srv, con, con->request.http_host)) {
17758 if (srv->srvconf.log_request_header_on_error) {
17759 log_error_write(srv, __FILE__, __LINE__, "s",
17760 "Invalid Hostname -> 400");
17761 @@ -1038,7 +1046,7 @@
17762 con->http_status = 400;
17763 con->response.keep_alive = 0;
17764 con->keep_alive = 0;
17770 @@ -1048,7 +1056,7 @@
17771 /* content-length is forbidden for those */
17772 if (con_length_set && con->request.content_length != 0) {
17773 /* content-length is missing */
17774 - log_error_write(srv, __FILE__, __LINE__, "s",
17775 + log_error_write(srv, __FILE__, __LINE__, "s",
17776 "GET/HEAD with content-length -> 400");
17778 con->keep_alive = 0;
17779 @@ -1060,7 +1068,7 @@
17780 /* content-length is required for them */
17781 if (!con_length_set) {
17782 /* content-length is missing */
17783 - log_error_write(srv, __FILE__, __LINE__, "s",
17784 + log_error_write(srv, __FILE__, __LINE__, "s",
17785 "POST-request, but content-length missing -> 411");
17787 con->keep_alive = 0;
17788 @@ -1073,16 +1081,16 @@
17789 /* the may have a content-length */
17796 /* check if we have read post data */
17797 if (con_length_set) {
17798 /* don't handle more the SSIZE_MAX bytes in content-length */
17799 if (con->request.content_length > SSIZE_MAX) {
17800 - con->http_status = 413;
17801 + con->http_status = 413;
17802 con->keep_alive = 0;
17804 - log_error_write(srv, __FILE__, __LINE__, "sds",
17805 + log_error_write(srv, __FILE__, __LINE__, "sds",
17806 "request-size too long:", con->request.content_length, "-> 413");
17809 @@ -1090,25 +1098,25 @@
17810 /* divide by 1024 as srvconf.max_request_size is in kBytes */
17811 if (srv->srvconf.max_request_size != 0 &&
17812 (con->request.content_length >> 10) > srv->srvconf.max_request_size) {
17813 - /* the request body itself is larger then
17814 + /* the request body itself is larger then
17815 * our our max_request_size
17819 con->http_status = 413;
17820 con->keep_alive = 0;
17822 - log_error_write(srv, __FILE__, __LINE__, "sds",
17824 + log_error_write(srv, __FILE__, __LINE__, "sds",
17825 "request-size too long:", con->request.content_length, "-> 413");
17832 /* we have content */
17833 if (con->request.content_length != 0) {
17842 @@ -1116,9 +1124,9 @@
17845 if (con->request.request->used < 5) return 0;
17848 if (0 == memcmp(con->request.request->ptr + con->request.request->used - 5, "\r\n\r\n", 4)) return 1;
17849 if (NULL != strstr(con->request.request->ptr, "\r\n\r\n")) return 1;
17855 Property changes on: src/request.c
17856 ___________________________________________________________________
17857 Name: svn:eol-style
17860 Index: src/network_backends.h
17861 ===================================================================
17862 --- src/network_backends.h (.../tags/lighttpd-1.4.11) (revision 1159)
17863 +++ src/network_backends.h (.../branches/lighttpd-merge-1.4.x) (revision 1159)
17864 @@ -43,16 +43,52 @@
17865 # define USE_AIX_SENDFILE
17869 +* unix can use read/write or recv/send on sockets
17870 +* win32 only recv/send
17873 +# define USE_WIN32_SEND
17874 +/* wait for async-io support
17875 +# define USE_WIN32_TRANSMITFILE
17878 +# define USE_WRITE
17882 +#include "network.h"
17884 +#define NETWORK_BACKEND_WRITE_CHUNK(x) \
17885 + network_status_t network_write_chunkqueue_##x(server *srv, connection *con, int fd, chunkqueue *cq, chunk *c)
17887 -int network_write_chunkqueue_write(server *srv, connection *con, int fd, chunkqueue *cq);
17888 -int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkqueue *cq);
17889 -int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd, chunkqueue *cq);
17890 -int network_write_chunkqueue_freebsdsendfile(server *srv, connection *con, int fd, chunkqueue *cq);
17891 -int network_write_chunkqueue_solarissendfilev(server *srv, connection *con, int fd, chunkqueue *cq);
17892 +#define NETWORK_BACKEND_WRITE(x) \
17893 + network_status_t network_write_chunkqueue_##x(server *srv, connection *con, int fd, chunkqueue *cq)
17894 +#define NETWORK_BACKEND_READ(x) \
17895 + network_status_t network_read_chunkqueue_##x(server *srv, connection *con, int fd, chunkqueue *cq)
17897 +NETWORK_BACKEND_WRITE_CHUNK(writev_mem);
17899 +NETWORK_BACKEND_WRITE(write);
17900 +NETWORK_BACKEND_WRITE(writev);
17901 +NETWORK_BACKEND_WRITE(linuxsendfile);
17902 +NETWORK_BACKEND_WRITE(freebsdsendfile);
17903 +NETWORK_BACKEND_WRITE(solarissendfilev);
17905 +NETWORK_BACKEND_WRITE(win32transmitfile);
17906 +NETWORK_BACKEND_WRITE(win32send);
17908 +NETWORK_BACKEND_READ(read);
17909 +NETWORK_BACKEND_READ(win32recv);
17912 -int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chunkqueue *cq);
17913 +#define NETWORK_BACKEND_WRITE_SSL(x) \
17914 + network_status_t network_write_chunkqueue_##x(server *srv, connection *con, SSL *ssl, chunkqueue *cq)
17915 +#define NETWORK_BACKEND_READ_SSL(x) \
17916 + network_status_t network_read_chunkqueue_##x(server *srv, connection *con, SSL *ssl, chunkqueue *cq)
17918 +NETWORK_BACKEND_WRITE_SSL(openssl);
17919 +NETWORK_BACKEND_READ_SSL(openssl);
17924 Property changes on: src/network_backends.h
17925 ___________________________________________________________________
17926 Name: svn:eol-style
17930 Property changes on: src/bitset.c
17931 ___________________________________________________________________
17932 Name: svn:eol-style
17935 Index: src/keyvalue.h
17936 ===================================================================
17937 --- src/keyvalue.h (.../tags/lighttpd-1.4.11) (revision 1159)
17938 +++ src/keyvalue.h (.../branches/lighttpd-merge-1.4.x) (revision 1159)
17944 - HTTP_METHOD_UNSET = -1,
17946 - HTTP_METHOD_POST,
17947 - HTTP_METHOD_HEAD,
17948 - HTTP_METHOD_OPTIONS,
17950 + HTTP_METHOD_UNSET = -1,
17952 + HTTP_METHOD_POST,
17953 + HTTP_METHOD_HEAD,
17954 + HTTP_METHOD_OPTIONS,
17955 HTTP_METHOD_PROPFIND, /* WebDAV */
17956 - HTTP_METHOD_MKCOL,
17958 - HTTP_METHOD_DELETE,
17959 - HTTP_METHOD_COPY,
17960 - HTTP_METHOD_MOVE,
17961 - HTTP_METHOD_PROPPATCH,
17962 + HTTP_METHOD_MKCOL,
17964 + HTTP_METHOD_DELETE,
17965 + HTTP_METHOD_COPY,
17966 + HTTP_METHOD_MOVE,
17967 + HTTP_METHOD_PROPPATCH,
17968 HTTP_METHOD_REPORT, /* DeltaV */
17969 HTTP_METHOD_CHECKOUT,
17970 HTTP_METHOD_CHECKIN,
17971 @@ -39,13 +39,13 @@
17989 pcre_extra *key_extra;
18003 httpauth_type type;
18004 } httpauth_keyvalue;
18006 Property changes on: src/keyvalue.h
18007 ___________________________________________________________________
18008 Name: svn:eol-style
18012 Property changes on: src/request.h
18013 ___________________________________________________________________
18014 Name: svn:eol-style
18017 Index: src/mod_flv_streaming.c
18018 ===================================================================
18019 --- src/mod_flv_streaming.c (.../tags/lighttpd-1.4.11) (revision 1159)
18020 +++ src/mod_flv_streaming.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
18021 @@ -23,35 +23,35 @@
18031 plugin_config **config_storage;
18033 - plugin_config conf;
18035 + plugin_config conf;
18038 /* init the plugin data */
18039 INIT_FUNC(mod_flv_streaming_init) {
18043 p = calloc(1, sizeof(*p));
18046 p->query_str = buffer_init();
18047 p->get_params = array_init();
18053 /* detroy the plugin data */
18054 FREE_FUNC(mod_flv_streaming_free) {
18055 plugin_data *p = p_d;
18060 if (!p) return HANDLER_GO_ON;
18063 if (p->config_storage) {
18066 @@ -59,19 +59,19 @@
18067 plugin_config *s = p->config_storage[i];
18072 array_free(s->extensions);
18077 free(p->config_storage);
18081 buffer_free(p->query_str);
18082 array_free(p->get_params);
18088 return HANDLER_GO_ON;
18091 @@ -80,83 +80,80 @@
18092 SETDEFAULTS_FUNC(mod_flv_streaming_set_defaults) {
18093 plugin_data *p = p_d;
18096 - config_values_t cv[] = {
18098 + config_values_t cv[] = {
18099 { "flv-streaming.extensions", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
18100 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
18104 if (!p) return HANDLER_ERROR;
18107 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
18110 for (i = 0; i < srv->config_context->used; i++) {
18114 s = calloc(1, sizeof(plugin_config));
18115 s->extensions = array_init();
18118 cv[0].destination = s->extensions;
18121 p->config_storage[i] = s;
18124 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
18125 return HANDLER_ERROR;
18130 return HANDLER_GO_ON;
18133 -#define PATCH(x) \
18134 - p->conf.x = s->x;
18135 static int mod_flv_streaming_patch_connection(server *srv, connection *con, plugin_data *p) {
18137 plugin_config *s = p->config_storage[0];
18139 - PATCH(extensions);
18142 + PATCH_OPTION(extensions);
18144 /* skip the first, the global context */
18145 for (i = 1; i < srv->config_context->used; i++) {
18146 data_config *dc = (data_config *)srv->config_context->data[i];
18147 s = p->config_storage[i];
18150 /* condition didn't match */
18151 if (!config_check_cond(srv, con, dc)) continue;
18155 for (j = 0; j < dc->value->used; j++) {
18156 data_unset *du = dc->value->data[j];
18159 if (buffer_is_equal_string(du->key, CONST_STR_LEN("flv-streaming.extensions"))) {
18160 - PATCH(extensions);
18161 + PATCH_OPTION(extensions);
18171 -static int split_get_params(server *srv, connection *con, array *get_params, buffer *qrystr) {
18172 +static int split_get_params(array *get_params, buffer *qrystr) {
18175 char *key = NULL, *val = NULL;
18181 /* we need the \0 */
18182 for (i = 0; i < qrystr->used; i++) {
18183 switch(qrystr->ptr[i]) {
18186 val = qrystr->ptr + i + 1;
18189 qrystr->ptr[i] = '\0';
18198 case '\0': /* fin symbol */
18199 @@ -167,7 +164,7 @@
18200 /* terminate the value */
18201 qrystr->ptr[i] = '\0';
18203 - if (NULL == (ds = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
18204 + if (NULL == (ds = (data_string *)array_get_unused_element(get_params, TYPE_STRING))) {
18205 ds = data_string_init();
18207 buffer_copy_string_len(ds->key, key, strlen(key));
18208 @@ -175,14 +172,14 @@
18210 array_insert_unique(get_params, (data_unset *)ds);
18214 key = qrystr->ptr + i + 1;
18225 @@ -190,34 +187,34 @@
18226 plugin_data *p = p_d;
18233 if (buffer_is_empty(con->physical.path)) return HANDLER_GO_ON;
18236 mod_flv_streaming_patch_connection(srv, con, p);
18238 s_len = con->physical.path->used - 1;
18241 for (k = 0; k < p->conf.extensions->used; k++) {
18242 data_string *ds = (data_string *)p->conf.extensions->data[k];
18243 int ct_len = ds->value->used - 1;
18246 if (ct_len > s_len) continue;
18247 if (ds->value->used == 0) continue;
18250 if (0 == strncmp(con->physical.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
18251 data_string *get_param;
18252 stat_cache_entry *sce = NULL;
18256 - /* if there is a start=[0-9]+ in the header use it as start,
18257 + /* if there is a start=[0-9]+ in the header use it as start,
18258 * otherwise send the full file */
18260 array_reset(p->get_params);
18261 buffer_copy_string_buffer(p->query_str, con->uri.query);
18262 - split_get_params(srv, con, p->get_params, p->query_str);
18263 + split_get_params(p->get_params, p->query_str);
18265 if (NULL == (get_param = (data_string *)array_get_element(p->get_params, "start"))) {
18266 return HANDLER_GO_ON;
18267 @@ -256,7 +253,7 @@
18268 return HANDLER_FINISHED;
18274 return HANDLER_GO_ON;
18276 @@ -266,13 +263,13 @@
18277 int mod_flv_streaming_plugin_init(plugin *p) {
18278 p->version = LIGHTTPD_VERSION_ID;
18279 p->name = buffer_init_string("flv_streaming");
18282 p->init = mod_flv_streaming_init;
18283 p->handle_physical = mod_flv_streaming_path_handler;
18284 p->set_defaults = mod_flv_streaming_set_defaults;
18285 p->cleanup = mod_flv_streaming_free;
18294 Property changes on: src/mod_flv_streaming.c
18295 ___________________________________________________________________
18296 Name: svn:eol-style
18300 Property changes on: src/bitset.h
18301 ___________________________________________________________________
18302 Name: svn:eol-style
18305 Index: src/sys-socket.c
18306 ===================================================================
18307 --- src/sys-socket.c (.../tags/lighttpd-1.4.11) (revision 0)
18308 +++ src/sys-socket.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
18310 +#include "sys-socket.h"
18312 +#ifndef HAVE_INET_ATON
18313 +/* win32 has inet_addr instead if inet_aton */
18314 +#ifdef HAVE_INET_ADDR
18315 +int inet_aton(const char *cp, struct in_addr *inp) {
18316 + struct in_addr a;
18318 + a.s_addr = inet_addr(cp);
18320 + if (INADDR_NONE == a.s_addr) {
18324 + inp->s_addr = a.s_addr;
18329 +#error no inet_aton emulation found
18332 \ No newline at end of file
18334 Property changes on: src/sys-socket.c
18335 ___________________________________________________________________
18336 Name: svn:eol-style
18339 Index: src/sys-socket.h
18340 ===================================================================
18341 --- src/sys-socket.h (.../tags/lighttpd-1.4.11) (revision 1159)
18342 +++ src/sys-socket.h (.../branches/lighttpd-merge-1.4.x) (revision 1159)
18344 #ifndef WIN32_SOCKET_H
18345 #define WIN32_SOCKET_H
18350 #include <winsock2.h>
18352 #define ECONNRESET WSAECONNRESET
18353 #define EINPROGRESS WSAEINPROGRESS
18354 #define EALREADY WSAEALREADY
18355 +#define ENOTCONN WSAENOTCONN
18356 +#define EWOULDBLOCK WSAEWOULDBLOCK
18357 #define ioctl ioctlsocket
18358 #define hstrerror(x) ""
18359 +#define STDIN_FILENO 0
18360 +#define STDOUT_FILENO 1
18361 +#define STDERR_FILENO 2
18362 +#define ssize_t int
18364 +int inet_aton(const char *cp, struct in_addr *inp);
18365 +#define HAVE_INET_ADDR
18366 +#undef HAVE_INET_ATON
18369 #include <sys/socket.h>
18370 #include <sys/ioctl.h>
18372 #include <sys/un.h>
18373 #include <arpa/inet.h>
18376 +#define SUN_LEN(su) \
18377 + (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
18384 Property changes on: src/sys-socket.h
18385 ___________________________________________________________________
18386 Name: svn:eol-style
18389 Index: src/sys-mmap.h
18390 ===================================================================
18391 --- src/sys-mmap.h (.../tags/lighttpd-1.4.11) (revision 1159)
18392 +++ src/sys-mmap.h (.../branches/lighttpd-merge-1.4.x) (revision 1159)
18394 #ifndef WIN32_MMAP_H
18395 #define WIN32_MMAP_H
18400 #define MAP_FAILED -1
18401 #define PROT_SHARED 0
18403 Property changes on: src/sys-mmap.h
18404 ___________________________________________________________________
18405 Name: svn:eol-style
18408 Index: src/inet_ntop_cache.c
18409 ===================================================================
18410 --- src/inet_ntop_cache.c (.../tags/lighttpd-1.4.11) (revision 1159)
18411 +++ src/inet_ntop_cache.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
18413 #include "sys-socket.h"
18415 const char * inet_ntop_cache_get_ip(server *srv, sock_addr *addr) {
18419 for (i = 0; i < INET_NTOP_CACHE_MAX; i++) {
18420 if (srv->inet_ntop_cache[i].ts != 0) {
18421 @@ -20,31 +20,31 @@
18422 srv->inet_ntop_cache[i].addr.ipv4.s_addr == addr->ipv4.sin_addr.s_addr) {
18423 /* IPv4 found in cache */
18432 if (i == INET_NTOP_CACHE_MAX) {
18433 /* not found in cache */
18437 - inet_ntop(addr->plain.sa_family,
18438 - addr->plain.sa_family == AF_INET6 ?
18439 + inet_ntop(addr->plain.sa_family,
18440 + addr->plain.sa_family == AF_INET6 ?
18441 (const void *) &(addr->ipv6.sin6_addr) :
18442 (const void *) &(addr->ipv4.sin_addr),
18443 srv->inet_ntop_cache[i].b2, INET6_ADDRSTRLEN);
18446 srv->inet_ntop_cache[i].ts = srv->cur_ts;
18447 srv->inet_ntop_cache[i].family = addr->plain.sa_family;
18450 if (srv->inet_ntop_cache[i].family == AF_INET) {
18451 srv->inet_ntop_cache[i].addr.ipv4.s_addr = addr->ipv4.sin_addr.s_addr;
18452 } else if (srv->inet_ntop_cache[i].family == AF_INET6) {
18453 memcpy(srv->inet_ntop_cache[i].addr.ipv6.s6_addr, addr->ipv6.sin6_addr.s6_addr, 16);
18458 return srv->inet_ntop_cache[i].b2;
18462 Property changes on: src/inet_ntop_cache.c
18463 ___________________________________________________________________
18464 Name: svn:eol-style
18467 Index: src/mod_rrdtool.c
18468 ===================================================================
18469 --- src/mod_rrdtool.c (.../tags/lighttpd-1.4.11) (revision 1159)
18470 +++ src/mod_rrdtool.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
18472 #include <stdlib.h>
18474 #include <string.h>
18475 -#include <unistd.h>
18479 @@ -20,10 +19,14 @@
18480 /* no need for waitpid if we don't have fork */
18481 #include <sys/wait.h>
18484 +#include "sys-files.h"
18485 +#include "sys-process.h"
18488 buffer *path_rrdtool_bin;
18492 double requests, *requests_ptr;
18493 double bytes_written, *bytes_written_ptr;
18494 double bytes_read, *bytes_read_ptr;
18495 @@ -31,84 +34,84 @@
18505 int read_fd, write_fd;
18509 int rrdtool_running;
18512 plugin_config **config_storage;
18513 plugin_config conf;
18516 INIT_FUNC(mod_rrd_init) {
18520 p = calloc(1, sizeof(*p));
18523 p->resp = buffer_init();
18524 p->cmd = buffer_init();
18530 FREE_FUNC(mod_rrd_free) {
18531 plugin_data *p = p_d;
18535 if (!p) return HANDLER_GO_ON;
18538 if (p->config_storage) {
18539 for (i = 0; i < srv->config_context->used; i++) {
18540 plugin_config *s = p->config_storage[i];
18543 buffer_free(s->path_rrdtool_bin);
18544 buffer_free(s->path_rrd);
18550 buffer_free(p->cmd);
18551 buffer_free(p->resp);
18554 free(p->config_storage);
18557 if (p->rrdtool_pid) {
18560 close(p->write_fd);
18563 /* collect status */
18564 waitpid(p->rrdtool_pid, &status, 0);
18572 return HANDLER_GO_ON;
18575 int mod_rrd_create_pipe(server *srv, plugin_data *p) {
18579 int to_rrdtool_fds[2];
18580 int from_rrdtool_fds[2];
18583 if (pipe(to_rrdtool_fds)) {
18584 - log_error_write(srv, __FILE__, __LINE__, "ss",
18585 + log_error_write(srv, __FILE__, __LINE__, "ss",
18586 "pipe failed: ", strerror(errno));
18591 if (pipe(from_rrdtool_fds)) {
18592 - log_error_write(srv, __FILE__, __LINE__, "ss",
18593 + log_error_write(srv, __FILE__, __LINE__, "ss",
18594 "pipe failed: ", strerror(errno));
18600 switch (pid = fork()) {
18602 @@ -117,33 +120,33 @@
18608 /* move stdout to from_rrdtool_fd[1] */
18609 close(STDOUT_FILENO);
18610 dup2(from_rrdtool_fds[1], STDOUT_FILENO);
18611 close(from_rrdtool_fds[1]);
18613 close(from_rrdtool_fds[0]);
18616 /* move the stdin to to_rrdtool_fd[0] */
18617 close(STDIN_FILENO);
18618 dup2(to_rrdtool_fds[0], STDIN_FILENO);
18619 close(to_rrdtool_fds[0]);
18621 close(to_rrdtool_fds[1]);
18624 close(STDERR_FILENO);
18627 if (srv->errorlog_mode == ERRORLOG_FILE) {
18628 dup2(srv->errorlog_fd, STDERR_FILENO);
18629 close(srv->errorlog_fd);
18635 args = malloc(sizeof(*args) * argc);
18639 args[i++] = p->conf.path_rrdtool_bin->ptr;
18642 @@ -152,12 +155,12 @@
18643 for (i = 3; i < 256; i++) {
18649 execv(args[0], args);
18652 log_error_write(srv, __FILE__, __LINE__, "sss", "spawing rrdtool failed: ", strerror(errno), args[0]);
18658 @@ -168,19 +171,19 @@
18664 close(from_rrdtool_fds[1]);
18665 close(to_rrdtool_fds[0]);
18668 /* register PID and wait for them asyncronously */
18669 p->write_fd = to_rrdtool_fds[1];
18670 p->read_fd = from_rrdtool_fds[0];
18671 p->rrdtool_pid = pid;
18682 @@ -189,19 +192,19 @@
18684 static int mod_rrdtool_create_rrd(server *srv, plugin_data *p, plugin_config *s) {
18688 /* check if DB already exists */
18689 if (0 == stat(s->path_rrd->ptr, &st)) {
18690 /* check if it is plain file */
18691 if (!S_ISREG(st.st_mode)) {
18692 - log_error_write(srv, __FILE__, __LINE__, "sb",
18693 + log_error_write(srv, __FILE__, __LINE__, "sb",
18694 "not a regular file:", s->path_rrd);
18695 return HANDLER_ERROR;
18699 /* create a new one */
18702 BUFFER_COPY_STRING_CONST(p->cmd, "create ");
18703 buffer_append_string_buffer(p->cmd, s->path_rrd);
18704 buffer_append_string(p->cmd, " --step 60 ");
18705 @@ -220,158 +223,155 @@
18706 buffer_append_string(p->cmd, "RRA:MIN:0.5:6:700 ");
18707 buffer_append_string(p->cmd, "RRA:MIN:0.5:24:775 ");
18708 buffer_append_string(p->cmd, "RRA:MIN:0.5:288:797\n");
18711 if (-1 == (r = write(p->write_fd, p->cmd->ptr, p->cmd->used - 1))) {
18712 - log_error_write(srv, __FILE__, __LINE__, "ss",
18713 + log_error_write(srv, __FILE__, __LINE__, "ss",
18714 "rrdtool-write: failed", strerror(errno));
18717 return HANDLER_ERROR;
18721 buffer_prepare_copy(p->resp, 4096);
18722 if (-1 == (r = read(p->read_fd, p->resp->ptr, p->resp->size))) {
18723 - log_error_write(srv, __FILE__, __LINE__, "ss",
18724 + log_error_write(srv, __FILE__, __LINE__, "ss",
18725 "rrdtool-read: failed", strerror(errno));
18728 return HANDLER_ERROR;
18735 if (p->resp->ptr[0] != 'O' ||
18736 p->resp->ptr[1] != 'K') {
18737 - log_error_write(srv, __FILE__, __LINE__, "sbb",
18738 + log_error_write(srv, __FILE__, __LINE__, "sbb",
18739 "rrdtool-response:", p->cmd, p->resp);
18742 return HANDLER_ERROR;
18747 return HANDLER_GO_ON;
18750 -#define PATCH(x) \
18751 - p->conf.x = s->x;
18752 static int mod_rrd_patch_connection(server *srv, connection *con, plugin_data *p) {
18754 plugin_config *s = p->config_storage[0];
18756 - PATCH(path_rrdtool_bin);
18760 + PATCH_OPTION(path_rrdtool_bin);
18761 + PATCH_OPTION(path_rrd);
18763 p->conf.bytes_written_ptr = &(s->bytes_written);
18764 p->conf.bytes_read_ptr = &(s->bytes_read);
18765 p->conf.requests_ptr = &(s->requests);
18768 /* skip the first, the global context */
18769 for (i = 1; i < srv->config_context->used; i++) {
18770 data_config *dc = (data_config *)srv->config_context->data[i];
18771 s = p->config_storage[i];
18774 /* condition didn't match */
18775 if (!config_check_cond(srv, con, dc)) continue;
18779 for (j = 0; j < dc->value->used; j++) {
18780 data_unset *du = dc->value->data[j];
18783 if (buffer_is_equal_string(du->key, CONST_STR_LEN("rrdtool.db-name"))) {
18785 + PATCH_OPTION(path_rrd);
18786 /* get pointers to double values */
18789 p->conf.bytes_written_ptr = &(s->bytes_written);
18790 p->conf.bytes_read_ptr = &(s->bytes_read);
18791 p->conf.requests_ptr = &(s->requests);
18801 SETDEFAULTS_FUNC(mod_rrd_set_defaults) {
18802 plugin_data *p = p_d;
18805 - config_values_t cv[] = {
18807 + config_values_t cv[] = {
18808 { "rrdtool.binary", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER },
18809 { "rrdtool.db-name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
18810 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
18814 if (!p) return HANDLER_ERROR;
18817 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
18820 for (i = 0; i < srv->config_context->used; i++) {
18824 s = calloc(1, sizeof(plugin_config));
18825 s->path_rrdtool_bin = buffer_init();
18826 s->path_rrd = buffer_init();
18828 s->bytes_written = 0;
18832 cv[0].destination = s->path_rrdtool_bin;
18833 cv[1].destination = s->path_rrd;
18836 p->config_storage[i] = s;
18839 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
18840 return HANDLER_ERROR;
18844 if (i > 0 && !buffer_is_empty(s->path_rrdtool_bin)) {
18845 /* path_rrdtool_bin is a global option */
18847 - log_error_write(srv, __FILE__, __LINE__, "s",
18849 + log_error_write(srv, __FILE__, __LINE__, "s",
18850 "rrdtool.binary can only be set as a global option.");
18853 return HANDLER_ERROR;
18860 p->conf.path_rrdtool_bin = p->config_storage[0]->path_rrdtool_bin;
18861 p->rrdtool_running = 0;
18864 /* check for dir */
18867 if (buffer_is_empty(p->conf.path_rrdtool_bin)) {
18868 - log_error_write(srv, __FILE__, __LINE__, "s",
18869 + log_error_write(srv, __FILE__, __LINE__, "s",
18870 "rrdtool.binary has to be set");
18871 return HANDLER_ERROR;
18875 /* open the pipe to rrdtool */
18876 if (mod_rrd_create_pipe(srv, p)) {
18877 return HANDLER_ERROR;
18881 p->rrdtool_running = 1;
18884 return HANDLER_GO_ON;
18887 TRIGGER_FUNC(mod_rrd_trigger) {
18888 plugin_data *p = p_d;
18892 if (!p->rrdtool_running) return HANDLER_GO_ON;
18893 if ((srv->cur_ts % 60) != 0) return HANDLER_GO_ON;
18896 for (i = 0; i < srv->config_context->used; i++) {
18897 plugin_config *s = p->config_storage[i];
18901 if (buffer_is_empty(s->path_rrd)) continue;
18904 /* write the data down every minute */
18907 if (HANDLER_GO_ON != mod_rrdtool_create_rrd(srv, p, s)) return HANDLER_ERROR;
18910 BUFFER_COPY_STRING_CONST(p->cmd, "update ");
18911 buffer_append_string_buffer(p->cmd, s->path_rrd);
18912 BUFFER_APPEND_STRING_CONST(p->cmd, " N:");
18913 @@ -381,69 +381,69 @@
18914 BUFFER_APPEND_STRING_CONST(p->cmd, ":");
18915 buffer_append_long(p->cmd, s->requests);
18916 BUFFER_APPEND_STRING_CONST(p->cmd, "\n");
18919 if (-1 == (r = write(p->write_fd, p->cmd->ptr, p->cmd->used - 1))) {
18920 p->rrdtool_running = 0;
18922 - log_error_write(srv, __FILE__, __LINE__, "ss",
18924 + log_error_write(srv, __FILE__, __LINE__, "ss",
18925 "rrdtool-write: failed", strerror(errno));
18928 return HANDLER_ERROR;
18932 buffer_prepare_copy(p->resp, 4096);
18933 if (-1 == (r = read(p->read_fd, p->resp->ptr, p->resp->size))) {
18934 p->rrdtool_running = 0;
18936 - log_error_write(srv, __FILE__, __LINE__, "ss",
18938 + log_error_write(srv, __FILE__, __LINE__, "ss",
18939 "rrdtool-read: failed", strerror(errno));
18942 return HANDLER_ERROR;
18949 if (p->resp->ptr[0] != 'O' ||
18950 p->resp->ptr[1] != 'K') {
18951 p->rrdtool_running = 0;
18953 - log_error_write(srv, __FILE__, __LINE__, "sbb",
18955 + log_error_write(srv, __FILE__, __LINE__, "sbb",
18956 "rrdtool-response:", p->cmd, p->resp);
18959 return HANDLER_ERROR;
18962 s->bytes_written = 0;
18967 return HANDLER_GO_ON;
18970 REQUESTDONE_FUNC(mod_rrd_account) {
18971 plugin_data *p = p_d;
18974 mod_rrd_patch_connection(srv, con, p);
18977 *(p->conf.requests_ptr) += 1;
18978 *(p->conf.bytes_written_ptr) += con->bytes_written;
18979 *(p->conf.bytes_read_ptr) += con->bytes_read;
18982 return HANDLER_GO_ON;
18985 int mod_rrdtool_plugin_init(plugin *p) {
18986 p->version = LIGHTTPD_VERSION_ID;
18987 p->name = buffer_init_string("rrd");
18990 p->init = mod_rrd_init;
18991 p->cleanup = mod_rrd_free;
18992 p->set_defaults= mod_rrd_set_defaults;
18995 p->handle_trigger = mod_rrd_trigger;
18996 p->handle_request_done = mod_rrd_account;
19005 Property changes on: src/mod_rrdtool.c
19006 ___________________________________________________________________
19007 Name: svn:eol-style
19011 Property changes on: src/inet_ntop_cache.h
19012 ___________________________________________________________________
19013 Name: svn:eol-style
19016 Index: src/mod_ssi_expr.c
19017 ===================================================================
19018 --- src/mod_ssi_expr.c (.../tags/lighttpd-1.4.11) (revision 1159)
19019 +++ src/mod_ssi_expr.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
19032 @@ -21,15 +21,15 @@
19034 ssi_val_t *ssi_val_init() {
19038 s = calloc(1, sizeof(*s));
19044 void ssi_val_free(ssi_val_t *s) {
19045 if (s->str) buffer_free(s->str);
19051 @@ -45,175 +45,175 @@
19052 ssi_tokenizer_t *t, int *token_id, buffer *token) {
19059 for (tid = 0; tid == 0 && t->offset < t->size && t->input[t->offset] ; ) {
19060 char c = t->input[t->offset];
19074 buffer_copy_string(token, "(=)");
19079 if (t->input[t->offset + 1] == '=') {
19087 buffer_copy_string(token, "(>=)");
19096 buffer_copy_string(token, "(>)");
19102 if (t->input[t->offset + 1] == '=') {
19110 buffer_copy_string(token, "(<=)");
19119 buffer_copy_string(token, "(<)");
19127 if (t->input[t->offset + 1] == '=') {
19135 buffer_copy_string(token, "(!=)");
19144 buffer_copy_string(token, "(!)");
19150 if (t->input[t->offset + 1] == '&') {
19158 buffer_copy_string(token, "(&&)");
19160 - log_error_write(srv, __FILE__, __LINE__, "sds",
19161 - "pos:", t->line_pos,
19162 + log_error_write(srv, __FILE__, __LINE__, "sds",
19163 + "pos:", t->line_pos,
19164 "missing second &");
19171 if (t->input[t->offset + 1] == '|') {
19179 buffer_copy_string(token, "(||)");
19181 - log_error_write(srv, __FILE__, __LINE__, "sds",
19182 - "pos:", t->line_pos,
19183 + log_error_write(srv, __FILE__, __LINE__, "sds",
19184 + "pos:", t->line_pos,
19185 "missing second |");
19199 /* search for the terminating " */
19200 for (i = 1; t->input[t->offset + i] && t->input[t->offset + i] != '\''; i++);
19203 if (t->input[t->offset + i]) {
19207 buffer_copy_string_len(token, t->input + t->offset + 1, i-1);
19210 t->offset += i + 1;
19211 t->line_pos += i + 1;
19215 - log_error_write(srv, __FILE__, __LINE__, "sds",
19216 - "pos:", t->line_pos,
19218 + log_error_write(srv, __FILE__, __LINE__, "sds",
19219 + "pos:", t->line_pos,
19220 "missing closing quote");
19236 buffer_copy_string(token, "(");
19246 buffer_copy_string(token, ")");
19249 if (t->input[t->offset + 1] == '{') {
19250 for (i = 2; t->input[t->offset + i] && t->input[t->offset + i] != '}'; i++);
19253 if (t->input[t->offset + i] != '}') {
19254 - log_error_write(srv, __FILE__, __LINE__, "sds",
19255 - "pos:", t->line_pos,
19256 + log_error_write(srv, __FILE__, __LINE__, "sds",
19257 + "pos:", t->line_pos,
19258 "missing closing quote");
19265 buffer_copy_string_len(token, t->input + t->offset + 2, i-3);
19267 for (i = 1; isalpha(t->input[t->offset + i]) || t->input[t->offset + i] == '_'; i++);
19270 buffer_copy_string_len(token, t->input + t->offset + 1, i-1);
19277 if (NULL != (ds = (data_string *)array_get_element(p->ssi_cgi_env, token->ptr))) {
19278 buffer_copy_string_buffer(token, ds->value);
19279 } else if (NULL != (ds = (data_string *)array_get_element(p->ssi_vars, token->ptr))) {
19280 @@ -221,16 +221,16 @@
19282 buffer_copy_string(token, "");
19292 for (i = 0; isgraph(t->input[t->offset + i]); i++) {
19293 char d = t->input[t->offset + i];
19300 @@ -244,25 +244,25 @@
19309 buffer_copy_string_len(token, t->input + t->offset, i);
19326 } else if (t->offset < t->size) {
19327 - log_error_write(srv, __FILE__, __LINE__, "sds",
19328 - "pos:", t->line_pos,
19329 + log_error_write(srv, __FILE__, __LINE__, "sds",
19330 + "pos:", t->line_pos,
19334 @@ -275,50 +275,50 @@
19342 t.size = strlen(expr);
19355 /* default context */
19358 pParser = ssiexprparserAlloc( malloc );
19359 token = buffer_init();
19360 while((1 == (ret = ssi_expr_tokenizer(srv, con, p, &t, &token_id, token))) && context.ok) {
19361 ssiexprparser(pParser, token_id, token, &context);
19364 token = buffer_init();
19366 ssiexprparser(pParser, 0, token, &context);
19367 ssiexprparserFree(pParser, free );
19370 buffer_free(token);
19374 - log_error_write(srv, __FILE__, __LINE__, "s",
19375 + log_error_write(srv, __FILE__, __LINE__, "s",
19376 "expr parser failed");
19381 if (context.ok == 0) {
19382 - log_error_write(srv, __FILE__, __LINE__, "sds",
19383 - "pos:", t.line_pos,
19384 + log_error_write(srv, __FILE__, __LINE__, "sds",
19385 + "pos:", t.line_pos,
19386 "parser failed somehow near here");
19390 - log_error_write(srv, __FILE__, __LINE__, "ssd",
19391 + log_error_write(srv, __FILE__, __LINE__, "ssd",
19397 return context.val.bo;
19400 Property changes on: src/mod_ssi_expr.c
19401 ___________________________________________________________________
19402 Name: svn:eol-style
19405 Index: src/response.c
19406 ===================================================================
19407 --- src/response.c (.../tags/lighttpd-1.4.11) (revision 1159)
19408 +++ src/response.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
19410 #include <stdlib.h>
19411 #include <string.h>
19413 -#include <unistd.h>
19415 #include <assert.h>
19417 @@ -24,15 +23,17 @@
19418 #include "plugin.h"
19420 #include "sys-socket.h"
19421 +#include "sys-files.h"
19422 +#include "sys-strings.h"
19424 int http_response_write_header(server *srv, connection *con) {
19428 int have_server = 0;
19431 b = chunkqueue_get_prepend_buffer(con->write_queue);
19434 if (con->request.http_version == HTTP_VERSION_1_1) {
19435 BUFFER_COPY_STRING_CONST(b, "HTTP/1.1 ");
19437 @@ -41,25 +42,26 @@
19438 buffer_append_long(b, con->http_status);
19439 BUFFER_APPEND_STRING_CONST(b, " ");
19440 buffer_append_string(b, get_http_status_name(con->http_status));
19443 if (con->request.http_version != HTTP_VERSION_1_1 || con->keep_alive == 0) {
19444 BUFFER_APPEND_STRING_CONST(b, "\r\nConnection: ");
19445 buffer_append_string(b, con->keep_alive ? "keep-alive" : "close");
19449 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
19450 BUFFER_APPEND_STRING_CONST(b, "\r\nTransfer-Encoding: chunked");
19456 /* add all headers */
19457 for (i = 0; i < con->response.headers->used; i++) {
19461 ds = (data_string *)con->response.headers->data[i];
19464 if (ds->value->used && ds->key->used &&
19465 - 0 != strncmp(ds->key->ptr, "X-LIGHTTPD-", sizeof("X-LIGHTTPD-") - 1)) {
19466 + 0 != strncmp(ds->key->ptr, "X-LIGHTTPD-", sizeof("X-LIGHTTPD-") - 1) &&
19467 + 0 != strcasecmp(ds->key->ptr, "X-Sendfile")) {
19468 if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Date"))) have_date = 1;
19469 if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Server"))) have_server = 1;
19471 @@ -68,28 +70,28 @@
19472 BUFFER_APPEND_STRING_CONST(b, ": ");
19473 buffer_append_string_buffer(b, ds->value);
19475 - log_error_write(srv, __FILE__, __LINE__, "bb",
19476 + log_error_write(srv, __FILE__, __LINE__, "bb",
19477 ds->key, ds->value);
19484 /* HTTP/1.1 requires a Date: header */
19485 BUFFER_APPEND_STRING_CONST(b, "\r\nDate: ");
19488 /* cache the generated timestamp */
19489 if (srv->cur_ts != srv->last_generated_date_ts) {
19490 buffer_prepare_copy(srv->ts_date_str, 255);
19492 - strftime(srv->ts_date_str->ptr, srv->ts_date_str->size - 1,
19494 + strftime(srv->ts_date_str->ptr, srv->ts_date_str->size - 1,
19495 "%a, %d %b %Y %H:%M:%S GMT", gmtime(&(srv->cur_ts)));
19498 srv->ts_date_str->used = strlen(srv->ts_date_str->ptr) + 1;
19501 srv->last_generated_date_ts = srv->cur_ts;
19505 buffer_append_string_buffer(b, srv->ts_date_str);
19508 @@ -101,16 +103,16 @@
19509 buffer_append_string_buffer(b, con->conf.server_tag);
19514 BUFFER_APPEND_STRING_CONST(b, "\r\n\r\n");
19519 con->bytes_header = b->used - 1;
19522 if (con->conf.log_response_header) {
19523 log_error_write(srv, __FILE__, __LINE__, "sSb", "Response-Header:", "\n", b);
19530 @@ -118,71 +120,71 @@
19532 handler_t http_response_prepare(server *srv, connection *con) {
19535 - /* looks like someone has already done a decision */
19536 - if (con->mode == DIRECT &&
19538 + /* looks like someone has already made a decision */
19539 + if (con->mode == DIRECT &&
19540 (con->http_status != 0 && con->http_status != 200)) {
19541 /* remove a packets in the queue */
19542 if (con->file_finished == 0) {
19543 chunkqueue_reset(con->write_queue);
19547 return HANDLER_FINISHED;
19551 /* no decision yet, build conf->filename */
19552 if (con->mode == DIRECT && con->physical.path->used == 0) {
19555 - /* we only come here when we have the parse the full request again
19557 - * a HANDLER_COMEBACK from mod_rewrite and mod_fastcgi might be a
19558 + /* we only come here when we have to parse the full request again
19560 + * a HANDLER_COMEBACK from mod_rewrite and mod_fastcgi might be a
19561 * problem here as mod_setenv might get called multiple times
19563 * fastcgi-auth might lead to a COMEBACK too
19564 * fastcgi again dead server too
19566 * mod_compress might add headers twice too
19572 if (con->conf.log_condition_handling) {
19573 log_error_write(srv, __FILE__, __LINE__, "s", "run condition");
19575 config_patch_connection(srv, con, COMP_SERVER_SOCKET); /* SERVERsocket */
19584 * - uri.path (secure)
19593 * Name according to RFC 2396
19602 * (scheme)://(authority)(path)?(query)
19610 buffer_copy_string(con->uri.scheme, con->conf.is_ssl ? "https" : "http");
19611 buffer_copy_string_buffer(con->uri.authority, con->request.http_host);
19612 buffer_to_lower(con->uri.authority);
19615 config_patch_connection(srv, con, COMP_HTTP_HOST); /* Host: */
19616 config_patch_connection(srv, con, COMP_HTTP_REMOTEIP); /* Client-IP */
19617 config_patch_connection(srv, con, COMP_HTTP_REFERER); /* Referer: */
19618 config_patch_connection(srv, con, COMP_HTTP_USERAGENT); /* User-Agent: */
19619 config_patch_connection(srv, con, COMP_HTTP_COOKIE); /* Cookie: */
19622 /** extract query string from request.uri */
19623 if (NULL != (qstr = strchr(con->request.uri->ptr, '?'))) {
19624 buffer_copy_string (con->uri.query, qstr + 1);
19625 @@ -200,22 +202,22 @@
19626 log_error_write(srv, __FILE__, __LINE__, "sb", "URI-path : ", con->uri.path_raw);
19627 log_error_write(srv, __FILE__, __LINE__, "sb", "URI-query : ", con->uri.query);
19631 /* disable keep-alive if requested */
19634 if (con->request_count > con->conf.max_keep_alive_requests) {
19635 con->keep_alive = 0;
19648 * - based on the raw URL
19654 switch(r = plugins_call_handle_uri_raw(srv, con)) {
19655 case HANDLER_GO_ON:
19657 @@ -229,14 +231,14 @@
19661 - /* build filename
19662 + /* build filename
19664 * - decode url-encodings (e.g. %20 -> ' ')
19665 * - remove path-modifiers (e.g. /../)
19673 if (con->request.http_method == HTTP_METHOD_OPTIONS &&
19674 con->uri.path_raw->ptr[0] == '*' && con->uri.path_raw->ptr[1] == '\0') {
19675 /* OPTIONS * ... */
19676 @@ -253,15 +255,20 @@
19686 * - based on the clean URL
19692 config_patch_connection(srv, con, COMP_HTTP_URL); /* HTTPurl */
19695 + /* do we have to downgrade to 1.0 ? */
19696 + if (!con->conf.allow_http11) {
19697 + con->request.http_version = HTTP_VERSION_1_0;
19700 switch(r = plugins_call_handle_uri_clean(srv, con)) {
19701 case HANDLER_GO_ON:
19703 @@ -274,11 +281,11 @@
19704 log_error_write(srv, __FILE__, __LINE__, "");
19709 if (con->request.http_method == HTTP_METHOD_OPTIONS &&
19710 con->uri.path->ptr[0] == '*' && con->uri.path_raw->ptr[1] == '\0') {
19711 - /* option requests are handled directly without checking of the path */
19713 + /* option requests are handled directly without checking the path */
19715 response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("OPTIONS, GET, HEAD, POST"));
19717 con->http_status = 200;
19718 @@ -288,46 +295,47 @@
19728 * logical filename (URI) becomes a physical filename here
19745 * ... ISREG() -> ok, go on
19746 * ... ISDIR() -> index-file -> redirect
19761 * SEARCH DOCUMENT ROOT
19765 /* set a default */
19768 buffer_copy_string_buffer(con->physical.doc_root, con->conf.document_root);
19769 buffer_copy_string_buffer(con->physical.rel_path, con->uri.path);
19771 -#if defined(__WIN32) || defined(__CYGWIN__)
19772 - /* strip dots from the end and spaces
19774 + filename_unix2local(con->physical.rel_path);
19775 +#if defined(_WIN32) || defined(__CYGWIN__)
19776 + /* strip dots and spaces from the end
19778 * windows/dos handle those filenames as the same file
19780 * foo == foo. == foo..... == "foo... " == "foo.. ./"
19782 - * This will affect in some cases PATHINFO
19783 + * This will affect PATHINFO in some cases
19785 * on native windows we could prepend the filename with \\?\ to circumvent
19786 * this behaviour. I have no idea how to push this through cygwin
19787 @@ -377,36 +385,41 @@
19788 log_error_write(srv, __FILE__, __LINE__, "");
19792 - /* MacOS X and Windows can't distiguish between upper and lower-case
19794 - * convert to lower-case
19796 + /* The default Mac OS X and Windows filesystems can't distiguish between
19797 + * upper- and lowercase, so convert to lowercase
19799 if (con->conf.force_lowercase_filenames) {
19800 buffer_to_lower(con->physical.rel_path);
19803 - /* the docroot plugins might set the servername, if they don't we take http-host */
19804 + /* the docroot plugins might set the servername; if they don't we take http-host */
19805 if (buffer_is_empty(con->server_name)) {
19806 buffer_copy_string_buffer(con->server_name, con->uri.authority);
19810 - * create physical filename
19813 + * create physical filename
19814 * -> physical.path = docroot + rel_path
19820 buffer_copy_string_buffer(con->physical.path, con->physical.doc_root);
19821 - BUFFER_APPEND_SLASH(con->physical.path);
19822 + PATHNAME_APPEND_SLASH(con->physical.path);
19823 buffer_copy_string_buffer(con->physical.basedir, con->physical.path);
19824 if (con->physical.rel_path->used &&
19825 - con->physical.rel_path->ptr[0] == '/') {
19826 + con->physical.rel_path->ptr[0] == DIR_SEPERATOR) {
19827 buffer_append_string_len(con->physical.path, con->physical.rel_path->ptr + 1, con->physical.rel_path->used - 2);
19829 buffer_append_string_buffer(con->physical.path, con->physical.rel_path);
19832 + /* win32: directories can't have a trailing slash */
19833 + if (con->physical.path->ptr[con->physical.path->used - 2] == DIR_SEPERATOR) {
19834 + con->physical.path->ptr[con->physical.path->used - 2] = '\0';
19835 + con->physical.path->used--;
19838 if (con->conf.log_request_handling) {
19839 log_error_write(srv, __FILE__, __LINE__, "s", "-- after doc_root");
19840 log_error_write(srv, __FILE__, __LINE__, "sb", "Doc-Root :", con->physical.doc_root);
19841 @@ -426,7 +439,7 @@
19842 log_error_write(srv, __FILE__, __LINE__, "");
19847 if (con->conf.log_request_handling) {
19848 log_error_write(srv, __FILE__, __LINE__, "s", "-- logical -> physical");
19849 log_error_write(srv, __FILE__, __LINE__, "sb", "Doc-Root :", con->physical.doc_root);
19850 @@ -434,38 +447,38 @@
19851 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
19856 - * Noone catched away the file from normal path of execution yet (like mod_access)
19860 + * No one took the file away from the normal path of execution yet (like mod_access)
19862 * Go on and check of the file exists at all
19866 if (con->mode == DIRECT) {
19867 char *slash = NULL;
19868 char *pathinfo = NULL;
19870 stat_cache_entry *sce = NULL;
19873 if (con->conf.log_request_handling) {
19874 log_error_write(srv, __FILE__, __LINE__, "s", "-- handling physical path");
19875 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
19879 if (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
19883 if (con->conf.log_request_handling) {
19884 log_error_write(srv, __FILE__, __LINE__, "s", "-- file found");
19885 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
19889 if (S_ISDIR(sce->st.st_mode)) {
19890 - if (con->physical.path->ptr[con->physical.path->used - 2] != '/') {
19891 + if (con->uri.path->ptr[con->uri.path->used - 2] != '/') {
19892 /* redirect to .../ */
19895 http_response_redirect_to_directory(srv, con);
19898 return HANDLER_FINISHED;
19900 } else if (!S_ISREG(sce->st.st_mode)) {
19901 @@ -477,12 +490,12 @@
19904 con->http_status = 403;
19907 if (con->conf.log_request_handling) {
19908 log_error_write(srv, __FILE__, __LINE__, "s", "-- access denied");
19909 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
19913 buffer_reset(con->physical.path);
19914 return HANDLER_FINISHED;
19916 @@ -499,77 +512,77 @@
19917 /* PATH_INFO ! :) */
19920 - /* we have no idea what happend. let's tell the user so. */
19921 + /* we have no idea what happened, so tell the user. */
19922 con->http_status = 500;
19923 buffer_reset(con->physical.path);
19926 log_error_write(srv, __FILE__, __LINE__, "ssbsb",
19927 "file not found ... or so: ", strerror(errno),
19929 "->", con->physical.path);
19932 return HANDLER_FINISHED;
19936 /* not found, perhaps PATHINFO */
19939 buffer_copy_string_buffer(srv->tmp_buf, con->physical.path);
19947 buffer_copy_string_len(con->physical.path, srv->tmp_buf->ptr, slash - srv->tmp_buf->ptr);
19949 buffer_copy_string_buffer(con->physical.path, srv->tmp_buf);
19953 if (0 == stat(con->physical.path->ptr, &(st)) &&
19954 S_ISREG(st.st_mode)) {
19960 if (pathinfo != NULL) {
19963 slash = strrchr(srv->tmp_buf->ptr, '/');
19966 if (pathinfo != NULL) {
19972 if (slash) pathinfo = slash;
19973 } while ((found == 0) && (slash != NULL) && (slash - srv->tmp_buf->ptr > con->physical.basedir->used - 2));
19977 - /* no it really doesn't exists */
19978 + /* no, it really doesn't exists */
19979 con->http_status = 404;
19982 if (con->conf.log_file_not_found) {
19983 log_error_write(srv, __FILE__, __LINE__, "sbsb",
19984 "file not found:", con->uri.path,
19985 "->", con->physical.path);
19989 buffer_reset(con->physical.path);
19992 return HANDLER_FINISHED;
19996 /* we have a PATHINFO */
19998 buffer_copy_string(con->request.pathinfo, pathinfo);
20006 con->uri.path->used -= strlen(pathinfo);
20007 con->uri.path->ptr[con->uri.path->used - 1] = '\0';
20011 if (con->conf.log_request_handling) {
20012 log_error_write(srv, __FILE__, __LINE__, "s", "-- after pathinfo check");
20013 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
20014 @@ -577,12 +590,12 @@
20015 log_error_write(srv, __FILE__, __LINE__, "sb", "Pathinfo :", con->request.pathinfo);
20020 if (con->conf.log_request_handling) {
20021 log_error_write(srv, __FILE__, __LINE__, "s", "-- handling subrequest");
20022 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
20026 /* call the handlers */
20027 switch(r = plugins_call_handle_subrequest_start(srv, con)) {
20028 case HANDLER_GO_ON:
20029 @@ -593,32 +606,32 @@
20030 if (con->conf.log_request_handling) {
20031 log_error_write(srv, __FILE__, __LINE__, "s", "-- subrequest finished");
20034 - /* something strange happend */
20036 + /* something strange happened */
20040 - /* if we are still here, no one wanted the file, status 403 is ok I think */
20043 + /* if we are still here, no one wanted the file; status 403 is ok I think */
20045 if (con->mode == DIRECT) {
20046 con->http_status = 403;
20049 return HANDLER_FINISHED;
20056 switch(r = plugins_call_handle_subrequest(srv, con)) {
20057 case HANDLER_GO_ON:
20058 - /* request was not handled, looks like we are done */
20059 + /* request was not handled; looks like we are done */
20060 return HANDLER_FINISHED;
20061 case HANDLER_FINISHED:
20062 /* request is finished */
20064 - /* something strange happend */
20065 + /* something strange happened */
20071 return HANDLER_COMEBACK;
20074 Property changes on: src/response.c
20075 ___________________________________________________________________
20076 Name: svn:eol-style
20079 Index: src/plugin.c
20080 ===================================================================
20081 --- src/plugin.c (.../tags/lighttpd-1.4.11) (revision 1159)
20082 +++ src/plugin.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
20083 @@ -13,27 +13,27 @@
20084 #include <valgrind/valgrind.h>
20094 * if you change this enum to add a new callback, be sure
20095 * - that PLUGIN_FUNC_SIZEOF is the last entry
20096 * - that you add PLUGIN_TO_SLOT twice:
20097 - * 1. as callback-dispatcher
20098 + * 1. as callback-dispatcher
20099 * 2. in plugins_call_init()
20111 - PLUGIN_FUNC_HANDLE_URI_CLEAN,
20112 - PLUGIN_FUNC_HANDLE_URI_RAW,
20113 + PLUGIN_FUNC_HANDLE_URI_CLEAN,
20114 + PLUGIN_FUNC_HANDLE_URI_RAW,
20115 PLUGIN_FUNC_HANDLE_REQUEST_DONE,
20116 PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE,
20117 PLUGIN_FUNC_HANDLE_TRIGGER,
20118 @@ -44,38 +44,42 @@
20119 PLUGIN_FUNC_HANDLE_DOCROOT,
20120 PLUGIN_FUNC_HANDLE_PHYSICAL,
20121 PLUGIN_FUNC_CONNECTION_RESET,
20122 - PLUGIN_FUNC_INIT,
20123 + PLUGIN_FUNC_INIT,
20124 PLUGIN_FUNC_CLEANUP,
20125 PLUGIN_FUNC_SET_DEFAULTS,
20131 static plugin *plugin_init(void) {
20135 p = calloc(1, sizeof(*p));
20138 + p->required_plugins = array_init();
20143 static void plugin_free(plugin *p) {
20144 int use_dlclose = 1;
20145 if (p->name) buffer_free(p->name);
20147 + array_free(p->required_plugins);
20148 #ifdef HAVE_VALGRIND_VALGRIND_H
20149 /*if (RUNNING_ON_VALGRIND) use_dlclose = 0;*/
20152 #ifndef LIGHTTPD_STATIC
20153 - if (use_dlclose && p->lib) {
20155 + if (use_dlclose && p->lib) {
20157 FreeLibrary(p->lib);
20168 @@ -89,17 +93,17 @@
20169 srv->plugins.size += 4;
20170 srv->plugins.ptr = realloc(srv->plugins.ptr, srv->plugins.size * sizeof(*ps));
20174 ps = srv->plugins.ptr;
20175 ps[srv->plugins.used++] = p;
20190 #ifdef LIGHTTPD_STATIC
20191 @@ -121,30 +125,35 @@
20193 int plugins_load(server *srv) {
20198 int (*init)(plugin *pl);
20206 for (i = 0; i < srv->srvconf.modules->used; i++) {
20207 data_string *d = (data_string *)srv->srvconf.modules->data[i];
20208 char *modules = d->value->ptr;
20211 buffer_copy_string_buffer(srv->tmp_buf, srv->srvconf.modules_dir);
20213 buffer_append_string(srv->tmp_buf, "/");
20214 buffer_append_string(srv->tmp_buf, modules);
20215 -#if defined(__WIN32) || defined(__CYGWIN__)
20216 +#if defined(_WIN32) || defined(__CYGWIN__)
20217 buffer_append_string(srv->tmp_buf, ".dll");
20219 buffer_append_string(srv->tmp_buf, ".so");
20226 if (NULL == (p->lib = LoadLibrary(srv->tmp_buf->ptr))) {
20229 - FORMAT_MESSAGE_ALLOCATE_BUFFER |
20230 + FORMAT_MESSAGE_ALLOCATE_BUFFER |
20231 FORMAT_MESSAGE_FROM_SYSTEM,
20234 @@ -152,36 +161,36 @@
20235 (LPTSTR) &lpMsgBuf,
20238 - log_error_write(srv, __FILE__, __LINE__, "ssb", "LoadLibrary() failed",
20239 + log_error_write(srv, __FILE__, __LINE__, "ssb", "LoadLibrary() failed",
20240 lpMsgBuf, srv->tmp_buf);
20251 if (NULL == (p->lib = dlopen(srv->tmp_buf->ptr, RTLD_LAZY))) {
20252 - log_error_write(srv, __FILE__, __LINE__, "sbs", "dlopen() failed for:",
20253 + log_error_write(srv, __FILE__, __LINE__, "sbs", "dlopen() failed for:",
20254 srv->tmp_buf, dlerror());
20265 buffer_reset(srv->tmp_buf);
20266 buffer_copy_string(srv->tmp_buf, modules);
20267 buffer_append_string(srv->tmp_buf, "_plugin_init");
20271 init = GetProcAddress(p->lib, srv->tmp_buf->ptr);
20273 if (init == NULL) {
20276 - FORMAT_MESSAGE_ALLOCATE_BUFFER |
20277 + FORMAT_MESSAGE_ALLOCATE_BUFFER |
20278 FORMAT_MESSAGE_FROM_SYSTEM,
20281 @@ -190,7 +199,7 @@
20284 log_error_write(srv, __FILE__, __LINE__, "sbs", "getprocaddress failed:", srv->tmp_buf, lpMsgBuf);
20290 @@ -203,24 +212,43 @@
20292 if ((error = dlerror()) != NULL) {
20293 log_error_write(srv, __FILE__, __LINE__, "s", error);
20303 log_error_write(srv, __FILE__, __LINE__, "ss", modules, "plugin init failed" );
20310 log_error_write(srv, __FILE__, __LINE__, "ss", modules, "plugin loaded" );
20312 + /* check if the required plugin is loaded */
20313 + for (k = 0; k < p->required_plugins->used; k++) {
20314 + data_string *req = (data_string *)p->required_plugins->data[k];
20316 + for (j = 0; j < i; j++) {
20317 + data_string *mod = (data_string *)srv->srvconf.modules->data[j];
20319 + if (buffer_is_equal(req->value, mod->value)) break;
20324 + log_error_write(srv, __FILE__, __LINE__, "ssbs", modules, "failed to load. required plugin", req->value, "was not loaded" );
20331 plugins_register(srv, p);
20338 @@ -253,8 +281,8 @@
20342 - * plugins that use
20344 + * plugins that use
20347 * - connection *con
20348 * - void *p_d (plugin_data *)
20349 @@ -301,12 +329,12 @@
20353 - * plugins that use
20355 + * plugins that use
20358 * - void *p_d (plugin_data *)
20362 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_TRIGGER, handle_trigger)
20363 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SIGHUP, handle_sighup)
20364 PLUGIN_TO_SLOT(PLUGIN_FUNC_CLEANUP, cleanup)
20365 @@ -314,18 +342,18 @@
20367 #undef PLUGIN_TO_SLOT
20378 handler_t plugins_call_handle_fdevent(server *srv, const fd_conn *fdc) {
20383 ps = srv->plugins.ptr;
20386 for (i = 0; i < srv->plugins.used; i++) {
20388 if (p->handle_fdevent) {
20389 @@ -344,34 +372,34 @@
20395 return HANDLER_GO_ON;
20401 * - call init function of all plugins to init the plugin-internals
20402 * - added each plugin that supports has callback to the corresponding slot
20405 * - is only called once.
20408 handler_t plugins_call_init(server *srv) {
20413 ps = srv->plugins.ptr;
20419 srv->plugin_slots = calloc(PLUGIN_FUNC_SIZEOF, sizeof(ps));
20422 for (i = 0; i < srv->plugins.used; i++) {
20424 /* check which calls are supported */
20430 #define PLUGIN_TO_SLOT(x, y) \
20432 plugin **slot = ((plugin ***)(srv->plugin_slots))[x]; \
20433 @@ -384,11 +412,11 @@
20440 - PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_CLEAN, handle_uri_clean);
20441 - PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_RAW, handle_uri_raw);
20445 + PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_CLEAN, handle_uri_clean);
20446 + PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_RAW, handle_uri_raw);
20447 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_REQUEST_DONE, handle_request_done);
20448 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE, handle_connection_close);
20449 PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_TRIGGER, handle_trigger);
20450 @@ -402,19 +430,19 @@
20451 PLUGIN_TO_SLOT(PLUGIN_FUNC_CLEANUP, cleanup);
20452 PLUGIN_TO_SLOT(PLUGIN_FUNC_SET_DEFAULTS, set_defaults);
20453 #undef PLUGIN_TO_SLOT
20457 if (NULL == (p->data = p->init())) {
20458 - log_error_write(srv, __FILE__, __LINE__, "sb",
20459 + log_error_write(srv, __FILE__, __LINE__, "sb",
20460 "plugin-init failed for module", p->name);
20461 return HANDLER_ERROR;
20465 /* used for con->mode, DIRECT == 0, plugins above that */
20466 ((plugin_data *)(p->data))->id = i + 1;
20469 if (p->version != LIGHTTPD_VERSION_ID) {
20470 - log_error_write(srv, __FILE__, __LINE__, "sb",
20471 + log_error_write(srv, __FILE__, __LINE__, "sb",
20472 "plugin-version doesn't match lighttpd-version for", p->name);
20473 return HANDLER_ERROR;
20475 @@ -422,29 +450,46 @@
20481 return HANDLER_GO_ON;
20485 + * get the config-storage of the named plugin
20487 +void *plugin_get_config(server *srv, const char *name) {
20490 + for (i = 0; i < srv->plugins.used; i++) {
20491 + plugin *p = ((plugin **)srv->plugins.ptr)[i];
20493 + if (buffer_is_equal_string(p->name, name, strlen(name))) {
20501 void plugins_free(server *srv) {
20503 plugins_call_cleanup(srv);
20506 for (i = 0; i < srv->plugins.used; i++) {
20507 plugin *p = ((plugin **)srv->plugins.ptr)[i];
20514 for (i = 0; srv->plugin_slots && i < PLUGIN_FUNC_SIZEOF; i++) {
20515 plugin **slot = ((plugin ***)(srv->plugin_slots))[i];
20518 if (slot) free(slot);
20522 free(srv->plugin_slots);
20523 srv->plugin_slots = NULL;
20526 free(srv->plugins.ptr);
20527 srv->plugins.ptr = NULL;
20528 srv->plugins.used = 0;
20530 Property changes on: src/plugin.c
20531 ___________________________________________________________________
20532 Name: svn:eol-style
20535 Index: src/stat_cache.c
20536 ===================================================================
20537 --- src/stat_cache.c (.../tags/lighttpd-1.4.11) (revision 1159)
20538 +++ src/stat_cache.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
20540 #include <stdlib.h>
20541 #include <string.h>
20543 -#include <unistd.h>
20546 #include <assert.h>
20550 #include "sys-mmap.h"
20551 +#include "sys-files.h"
20552 +#include "sys-strings.h"
20554 -/* NetBSD 1.3.x needs it */
20555 -#ifndef MAP_FAILED
20556 -# define MAP_FAILED -1
20559 -#ifndef O_LARGEFILE
20560 -# define O_LARGEFILE 0
20563 -#ifndef HAVE_LSTAT
20564 -#define lstat stat
20568 /* enables debug code for testing if all nodes in the stat-cache as accessable */
20569 #define DEBUG_STAT_CACHE
20572 * if we get a change-event from FAM, we increment the version in the FAM->dir mapping
20574 - * if the stat()-cache is queried we check if the version id for the directory is the
20575 - * same and return immediatly.
20576 + * if the stat()-cache is queried we check if the version id for the directory is the
20577 + * same and return immediatly.
20581 @@ -62,17 +50,17 @@
20582 * - for each FAMRequest we have to find the version in the directory cache (index as userdata)
20584 * stat <<-> directory <-> FAMRequest
20586 - * if file is deleted, directory is dirty, file is rechecked ...
20588 + * if file is deleted, directory is dirty, file is rechecked ...
20589 * if directory is deleted, directory mapping is removed
20603 @@ -83,16 +71,16 @@
20605 * - the hash-key is used as sorting criteria for a tree
20606 * - a splay-tree is used as we can use the caching effect of it
20610 /* we want to cleanup the stat-cache every few seconds, let's say 10
20612 * - remove entries which are outdated since 30s
20613 * - remove entries which are fresh but havn't been used since 60s
20614 * - if we don't have a stat-cache entry for a directory, release it from the monitor
20618 -#ifdef DEBUG_STAT_CACHE
20619 +#ifdef DEBUG_STAT_CACHE
20623 @@ -105,15 +93,15 @@
20625 stat_cache *stat_cache_init(void) {
20626 stat_cache *fc = NULL;
20629 fc = calloc(1, sizeof(*fc));
20632 fc->dir_name = buffer_init();
20634 fc->fam = calloc(1, sizeof(*fc->fam));
20637 -#ifdef DEBUG_STAT_CACHE
20638 +#ifdef DEBUG_STAT_CACHE
20642 @@ -122,24 +110,24 @@
20644 static stat_cache_entry * stat_cache_entry_init(void) {
20645 stat_cache_entry *sce = NULL;
20648 sce = calloc(1, sizeof(*sce));
20651 sce->name = buffer_init();
20652 sce->etag = buffer_init();
20653 sce->content_type = buffer_init();
20659 static void stat_cache_entry_free(void *data) {
20660 stat_cache_entry *sce = data;
20664 buffer_free(sce->etag);
20665 buffer_free(sce->name);
20666 buffer_free(sce->content_type);
20672 @@ -148,22 +136,22 @@
20673 fam_dir_entry *fam_dir = NULL;
20675 fam_dir = calloc(1, sizeof(*fam_dir));
20678 fam_dir->name = buffer_init();
20684 static void fam_dir_entry_free(void *data) {
20685 fam_dir_entry *fam_dir = data;
20688 if (!fam_dir) return;
20691 FAMCancelMonitor(fam_dir->fc, fam_dir->req);
20694 buffer_free(fam_dir->name);
20695 free(fam_dir->req);
20701 @@ -174,7 +162,7 @@
20702 splay_tree *node = sc->files;
20704 osize = sc->files->size;
20707 stat_cache_entry_free(node->data);
20708 sc->files = splaytree_delete(sc->files, node->key);
20710 @@ -187,12 +175,12 @@
20713 splay_tree *node = sc->dirs;
20716 osize = sc->dirs->size;
20718 fam_dir_entry_free(node->data);
20719 sc->dirs = splaytree_delete(sc->dirs, node->key);
20723 assert(NULL == sc->dirs);
20725 @@ -212,7 +200,7 @@
20726 static int stat_cache_attr_get(buffer *buf, char *name) {
20732 buffer_prepare_copy(buf, attrlen);
20734 @@ -251,15 +239,15 @@
20737 events = FAMPending(sc->fam);
20740 for (i = 0; i < events; i++) {
20742 fam_dir_entry *fam_dir;
20747 FAMNextEvent(sc->fam, &fe);
20753 @@ -280,7 +268,7 @@
20755 sc->dirs = splaytree_splay(sc->dirs, ndx);
20759 if (node && (node->key == ndx)) {
20760 int osize = splaytree_size(sc->dirs);
20762 @@ -308,7 +296,7 @@
20768 return HANDLER_GO_ON;
20771 @@ -332,7 +320,7 @@
20777 * - HANDLER_FINISHED on cache-miss (don't forget to reopen the file)
20778 * - HANDLER_ERROR on stat() failed -> see errno for problem
20780 @@ -348,16 +336,16 @@
20784 -#ifdef DEBUG_STAT_CACHE
20785 +#ifdef DEBUG_STAT_CACHE
20790 splay_tree *file_node = NULL;
20797 * check if the directory for this file has changed
20800 @@ -366,23 +354,23 @@
20801 file_ndx = hashme(name);
20802 sc->files = splaytree_splay(sc->files, file_ndx);
20804 -#ifdef DEBUG_STAT_CACHE
20805 +#ifdef DEBUG_STAT_CACHE
20806 for (i = 0; i < ctrl.used; i++) {
20807 if (ctrl.ptr[i] == file_ndx) break;
20811 if (sc->files && (sc->files->key == file_ndx)) {
20812 -#ifdef DEBUG_STAT_CACHE
20813 +#ifdef DEBUG_STAT_CACHE
20814 /* it was in the cache */
20815 assert(i < ctrl.used);
20818 - /* we have seen this file already and
20820 + /* we have seen this file already and
20821 * don't stat() it again in the same second */
20823 file_node = sc->files;
20826 sce = file_node->data;
20828 /* check if the name is the same, we might have a collision */
20829 @@ -390,7 +378,7 @@
20830 if (buffer_is_equal(name, sce->name)) {
20831 if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_SIMPLE) {
20832 if (sce->stat_ts == srv->cur_ts) {
20835 return HANDLER_GO_ON;
20838 @@ -400,15 +388,15 @@
20839 * file_node is used by the FAM check below to see if we know this file
20840 * and if we can save a stat().
20842 - * BUT, the sce is not reset here as the entry into the cache is ok, we
20843 + * BUT, the sce is not reset here as the entry into the cache is ok, we
20844 * it is just not pointing to our requested file.
20852 -#ifdef DEBUG_STAT_CACHE
20853 +#ifdef DEBUG_STAT_CACHE
20854 if (i != ctrl.used) {
20855 fprintf(stderr, "%s.%d: %08x was already inserted but not found in cache, %s\n", __FILE__, __LINE__, file_ndx, name->ptr);
20857 @@ -424,23 +412,23 @@
20860 dir_ndx = hashme(sc->dir_name);
20863 sc->dirs = splaytree_splay(sc->dirs, dir_ndx);
20866 if (sc->dirs && (sc->dirs->key == dir_ndx)) {
20867 dir_node = sc->dirs;
20871 if (dir_node && file_node) {
20872 /* we found a file */
20875 sce = file_node->data;
20876 fam_dir = dir_node->data;
20879 if (fam_dir->version == sce->dir_version) {
20880 /* the stat()-cache entry is still ok */
20885 return HANDLER_GO_ON;
20888 @@ -448,7 +436,7 @@
20894 * - open() + fstat() on a named-pipe results in a (intended) hang.
20895 * - stat() if regualar file + open() to see if we can read from it is better
20897 @@ -469,16 +457,16 @@
20904 osize = sc->files->size;
20907 sce = stat_cache_entry_init();
20908 buffer_copy_string_buffer(sce->name, name);
20910 - sc->files = splaytree_insert(sc->files, file_ndx, sce);
20911 -#ifdef DEBUG_STAT_CACHE
20913 + sc->files = splaytree_insert(sc->files, file_ndx, sce);
20914 +#ifdef DEBUG_STAT_CACHE
20915 if (ctrl.size == 0) {
20918 @@ -499,29 +487,29 @@
20920 sce->stat_ts = srv->cur_ts;
20922 - /* catch the obvious symlinks
20923 + /* catch the obvious symlinks
20925 * this is not a secure check as we still have a race-condition between
20926 - * the stat() and the open. We can only solve this by
20927 + * the stat() and the open. We can only solve this by
20928 * 1. open() the file
20929 * 2. fstat() the fd
20931 * and keeping the file open for the rest of the time. But this can
20932 * only be done at network level.
20936 if (S_ISLNK(st.st_mode) && !con->conf.follow_symlink) {
20937 return HANDLER_ERROR;
20940 - if (S_ISREG(st.st_mode)) {
20941 + if (S_ISREG(st.st_mode)) {
20942 /* determine mimetype */
20943 buffer_reset(sce->content_type);
20946 for (k = 0; k < con->conf.mimetypes->used; k++) {
20947 data_string *ds = (data_string *)con->conf.mimetypes->data[k];
20948 buffer *type = ds->key;
20951 if (type->used == 0) continue;
20953 /* check if the right side is the same */
20954 @@ -539,7 +527,7 @@
20962 (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_FAM)) {
20963 @@ -549,19 +537,19 @@
20964 fam_dir->fc = sc->fam;
20966 buffer_copy_string_buffer(fam_dir->name, sc->dir_name);
20969 fam_dir->version = 1;
20972 fam_dir->req = calloc(1, sizeof(FAMRequest));
20974 - if (0 != FAMMonitorDirectory(sc->fam, fam_dir->name->ptr,
20976 + if (0 != FAMMonitorDirectory(sc->fam, fam_dir->name->ptr,
20977 fam_dir->req, fam_dir)) {
20979 - log_error_write(srv, __FILE__, __LINE__, "sbs",
20980 - "monitoring dir failed:",
20983 + log_error_write(srv, __FILE__, __LINE__, "sbs",
20984 + "monitoring dir failed:",
20986 FamErrlist[FAMErrno]);
20989 fam_dir_entry_free(fam_dir);
20992 @@ -570,7 +558,7 @@
20993 osize = sc->dirs->size;
20996 - sc->dirs = splaytree_insert(sc->dirs, dir_ndx, fam_dir);
20997 + sc->dirs = splaytree_insert(sc->dirs, dir_ndx, fam_dir);
20999 assert(sc->dirs->data == fam_dir);
21000 assert(osize == (sc->dirs->size - 1));
21001 @@ -578,9 +566,9 @@
21003 fam_dir = dir_node->data;
21007 /* bind the fam_fc to the stat() cache entry */
21011 sce->dir_version = fam_dir->version;
21012 sce->dir_ndx = dir_ndx;
21013 @@ -594,11 +582,11 @@
21017 - * remove stat() from cache which havn't been stat()ed for
21018 + * remove stat() from cache which havn't been stat()ed for
21019 * more than 10 seconds
21022 - * walk though the stat-cache, collect the ids which are too old
21024 + * walk though the stat-cache, collect the ids which are too old
21025 * and remove them in a second loop
21028 @@ -639,9 +627,9 @@
21029 sc->files = splaytree_splay(sc->files, ndx);
21034 if (node && (node->key == ndx)) {
21035 -#ifdef DEBUG_STAT_CACHE
21036 +#ifdef DEBUG_STAT_CACHE
21038 int osize = splaytree_size(sc->files);
21039 stat_cache_entry *sce = node->data;
21040 @@ -649,7 +637,7 @@
21041 stat_cache_entry_free(node->data);
21042 sc->files = splaytree_delete(sc->files, ndx);
21044 -#ifdef DEBUG_STAT_CACHE
21045 +#ifdef DEBUG_STAT_CACHE
21046 for (j = 0; j < ctrl.used; j++) {
21047 if (ctrl.ptr[j] == ndx) {
21048 ctrl.ptr[j] = ctrl.ptr[--ctrl.used];
21050 Property changes on: src/stat_cache.c
21051 ___________________________________________________________________
21052 Name: svn:eol-style
21055 Index: src/sys-process.h
21056 ===================================================================
21057 --- src/sys-process.h (.../tags/lighttpd-1.4.11) (revision 0)
21058 +++ src/sys-process.h (.../branches/lighttpd-merge-1.4.x) (revision 1159)
21060 +#ifndef _SYS_PROCESS_H_
21061 +#define _SYS_PROCESS_H_
21064 +#include <process.h>
21066 +/* win32 has no fork() */
21067 +#define kill(x, y)
21068 +#define getpid() 0
21071 +#include <sys/wait.h>
21072 +#include <unistd.h>
21078 Property changes on: src/sys-process.h
21079 ___________________________________________________________________
21080 Name: svn:eol-style
21083 Index: src/mod_ssi_expr.h
21084 ===================================================================
21085 --- src/mod_ssi_expr.h (.../tags/lighttpd-1.4.11) (revision 1159)
21086 +++ src/mod_ssi_expr.h (.../branches/lighttpd-merge-1.4.x) (revision 1159)
21090 enum { SSI_TYPE_UNSET, SSI_TYPE_BOOL, SSI_TYPE_STRING } type;
21108 Property changes on: src/mod_ssi_expr.h
21109 ___________________________________________________________________
21110 Name: svn:eol-style
21113 Index: src/plugin.h
21114 ===================================================================
21115 --- src/plugin.h (.../tags/lighttpd-1.4.11) (revision 1159)
21116 +++ src/plugin.h (.../branches/lighttpd-merge-1.4.x) (revision 1159)
21119 #define INIT_FUNC(x) \
21122 + * The PATCH_OPTION() macro is used in the patch_connection() functions
21123 + * of the modules to update the config object for the current request.
21125 +#define PATCH_OPTION(x) \
21128 #define FREE_FUNC SERVER_FUNC
21129 #define TRIGGER_FUNC SERVER_FUNC
21130 @@ -25,19 +31,19 @@
21131 #define URIHANDLER_FUNC CONNECTION_FUNC
21133 #define PLUGIN_DATA size_t id
21140 buffer *name; /* name of the plugin */
21144 handler_t (* set_defaults) (server *srv, void *p_d);
21145 handler_t (* cleanup) (server *srv, void *p_d);
21146 /* is called ... */
21147 handler_t (* handle_trigger) (server *srv, void *p_d); /* once a second */
21148 handler_t (* handle_sighup) (server *srv, void *p_d); /* at a signup */
21151 handler_t (* handle_uri_raw) (server *srv, connection *con, void *p_d); /* after uri_raw is set */
21152 handler_t (* handle_uri_clean) (server *srv, connection *con, void *p_d); /* after uri is set */
21153 handler_t (* handle_docroot) (server *srv, connection *con, void *p_d); /* getting the document-root */
21154 @@ -45,20 +51,22 @@
21155 handler_t (* handle_request_done) (server *srv, connection *con, void *p_d); /* at the end of a request */
21156 handler_t (* handle_connection_close)(server *srv, connection *con, void *p_d); /* at the end of a connection */
21157 handler_t (* handle_joblist) (server *srv, connection *con, void *p_d); /* after all events are handled */
21161 - handler_t (* handle_subrequest_start)(server *srv, connection *con, void *p_d);
21163 - /* when a handler for the request
21167 + handler_t (* handle_subrequest_start)(server *srv, connection *con, void *p_d);
21169 + /* when a handler for the request
21172 handler_t (* handle_subrequest) (server *srv, connection *con, void *p_d); /* */
21173 handler_t (* connection_reset) (server *srv, connection *con, void *p_d); /* */
21177 /* dlopen handle */
21180 + array *required_plugins;
21183 int plugins_load(server *srv);
21185 int config_patch_connection(server *srv, connection *con, comp_key_t comp);
21186 int config_check_cond(server *srv, connection *con, data_config *dc);
21187 int config_append_cond_match_buffer(connection *con, data_config *dc, buffer *buf, int n);
21188 +int config_exec_pcre_keyvalue_buffer(connection *con, pcre_keyvalue_buffer *kvb, data_config *context, buffer *match_buf, buffer *result);
21190 +void *plugin_get_config(server *srv, const char *name);
21194 Property changes on: src/plugin.h
21195 ___________________________________________________________________
21196 Name: svn:eol-style
21200 Property changes on: src/stat_cache.h
21201 ___________________________________________________________________
21202 Name: svn:eol-style
21206 Property changes on: src/response.h
21207 ___________________________________________________________________
21208 Name: svn:eol-style
21211 Index: src/SConscript
21212 ===================================================================
21213 --- src/SConscript (.../tags/lighttpd-1.4.11) (revision 1159)
21214 +++ src/SConscript (.../branches/lighttpd-merge-1.4.x) (revision 1159)
21215 @@ -20,21 +20,49 @@
21216 http-header-glue.c \
21217 splaytree.c network_writev.c \
21218 network_write.c network_linux_sendfile.c \
21219 - network_freebsd_sendfile.c \
21220 + network_freebsd_sendfile.c network_win32_send.c \
21221 network_solaris_sendfilev.c network_openssl.c \
21223 + http_resp.c http_resp_parser.c ")
21225 -src = Split("server.c response.c connections.c network.c \
21226 +src = Split("server.c response.c connections.c network.c sys-socket.c sys-files.c\
21227 configfile.c configparser.c request.c proc_open.c")
21229 +if re.compile("win32").search(env['PLATFORM']):
21230 + src += [ 'getopt.c' ]
21232 lemon = env.Program('lemon', 'lemon.c')
21233 +def lemonemitter(target, source, env):
21235 + path = SCons.Util.to_String(target[0])
21236 + base, ext = os.path.splitext(path)
21237 + target += [ base + '.h' ]
21239 -configparser = env.Command(['configparser.c', 'configparser.h'], 'configparser.y', '(cd build; ../' + lemon[0].path + ' -q ../$SOURCE ../src/lempar.c; cd ..)')
21240 -env.Depends(configparser, lemon)
21241 + # the hard way to workaround scons bug
21242 + if os.path.exists(path) != os.path.exists(base + '.h'):
21243 + if os.path.exists(path):
21246 + os.remove(base + '.h')
21248 -mod_ssi_exprparser = env.Command(['mod_ssi_exprparser.c', 'mod_ssi_exprparser.h'], 'mod_ssi_exprparser.y', '(cd build; ../' + lemon[0].path + ' -q ../$SOURCE ../src/lempar.c; cd ..)')
21249 -env.Depends(mod_ssi_exprparser, lemon)
21250 + env.Depends(target, lemon)
21251 + return (target, source)
21253 +if re.compile("win32").search(env['PLATFORM']):
21254 + lemoncmd = '..\\' + lemon[0].path + ' -q ..\\$SOURCE ..\\src\\lempar.c || (del ..\\${TARGETS[0]} ..\\${TARGETS[1]} && exit 1)'
21256 + lemoncmd = '../' + lemon[0].path + ' -q ../$SOURCE ../src/lempar.c || (rm ../${TARGETS[0]} ../${TARGETS[1]} && exit 1)'
21257 +lemonbuilder = Builder(action=lemoncmd, chdir=1, emitter=lemonemitter, suffix='c')
21258 +env.Append(BUILDERS = {'Lemon': lemonbuilder})
21260 +configparser = env.Lemon('configparser.y');
21261 +mod_ssi_exprparser = env.Lemon('mod_ssi_exprparser.y');
21262 +http_resp_parser = env.Lemon('http_resp_parser.y');
21264 +env.Alias('http_resp', env.Program('http_resp',
21265 + [ 'http_resp_parser.c', 'http_resp.c', 'buffer.c', 'array.c', 'chunk.c',
21266 + 'keyvalue.c', 'data_string.c', 'http_resp_test.c'
21269 ## the modules and how they are built
21271 'mod_access' : { 'src' : [ 'mod_access.c' ] },
21273 'mod_cgi' : { 'src' : [ 'mod_cgi.c' ] },
21274 'mod_fastcgi' : { 'src' : [ 'mod_fastcgi.c' ] },
21275 'mod_scgi' : { 'src' : [ 'mod_scgi.c' ] },
21276 + 'mod_dirlisting' : { 'src' : [ 'mod_dirlisting.c' ], 'lib' : [ env['LIBPCRE'] ] },
21277 'mod_staticfile' : { 'src' : [ 'mod_staticfile.c' ] },
21278 - 'mod_dirlisting' : { 'src' : [ 'mod_dirlisting.c' ], 'lib' : [ env['LIBPCRE'] ] },
21280 'mod_indexfile' : { 'src' : [ 'mod_indexfile.c' ] },
21281 'mod_setenv' : { 'src' : [ 'mod_setenv.c' ] },
21282 'mod_rrdtool' : { 'src' : [ 'mod_rrdtool.c' ] },
21284 'src' : [ 'mod_auth.c', 'http_auth_digest.c', 'http_auth.c' ],
21285 'lib' : [ env['LIBCRYPT'], env['LIBLDAP'], env['LIBLBER'] ] },
21286 'mod_webdav' : { 'src' : [ 'mod_webdav.c' ], 'lib' : [ env['LIBXML2'], env['LIBSQLITE3'] ] },
21287 + 'mod_sql_vhost_core' : { 'src' : [ 'mod_sql_vhost_core.c' ] },
21288 'mod_mysql_vhost' : { 'src' : [ 'mod_mysql_vhost.c' ], 'lib' : [ env['LIBMYSQL'] ] },
21289 'mod_trigger_b4_dl' : { 'src' : [ 'mod_trigger_b4_dl.c' ], 'lib' : [ env['LIBPCRE'] ] },
21292 if modules[module].has_key('lib'):
21293 staticlib += modules[module]['lib']
21295 -open('plugin-static.h', 'w+').write(staticinit)
21296 +#file('plugin-static.h', 'wb+').write(staticinit)
21298 ## turn all src-files into objects
21300 @@ -148,7 +178,7 @@
21301 bin_linkflags += [ '-Wl,--export-dynamic' ]
21303 instbin = env.Program(bin_targets, src, LINKFLAGS = bin_linkflags, LIBS= [ env['LIBS'], common_lib, env['LIBDL'] ])
21304 -env.Depends(instbin, configparser)
21305 +env.Depends(instbin, configparser[1])
21307 spawn_fcgi = env.Program("spawn-fcgi", "spawn-fcgi.c")
21310 Property changes on: src/SConscript
21311 ___________________________________________________________________
21312 Name: svn:eol-style
21315 Index: src/data_array.c
21316 ===================================================================
21317 --- src/data_array.c (.../tags/lighttpd-1.4.11) (revision 1159)
21318 +++ src/data_array.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
21319 @@ -17,16 +17,16 @@
21321 static void data_array_free(data_unset *d) {
21322 data_array *ds = (data_array *)d;
21325 buffer_free(ds->key);
21326 array_free(ds->value);
21332 static void data_array_reset(data_unset *d) {
21333 data_array *ds = (data_array *)d;
21336 /* reused array elements */
21337 buffer_reset(ds->key);
21338 array_reset(ds->value);
21348 @@ -48,18 +48,18 @@
21350 data_array *data_array_init(void) {
21354 ds = calloc(1, sizeof(*ds));
21357 ds->key = buffer_init();
21358 ds->value = array_init();
21361 ds->copy = data_array_copy;
21362 ds->free = data_array_free;
21363 ds->reset = data_array_reset;
21364 ds->insert_dup = data_array_insert_dup;
21365 ds->print = data_array_print;
21366 ds->type = TYPE_ARRAY;
21372 Property changes on: src/data_array.c
21373 ___________________________________________________________________
21374 Name: svn:eol-style
21377 Index: src/mod_cml_funcs.c
21378 ===================================================================
21379 --- src/mod_cml_funcs.c (.../tags/lighttpd-1.4.11) (revision 1159)
21380 +++ src/mod_cml_funcs.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
21382 #include <stdlib.h>
21383 #include <string.h>
21385 -#include <unistd.h>
21386 -#include <dirent.h>
21390 #include "buffer.h"
21393 #include "plugin.h"
21394 #include "response.h"
21395 +#include "sys-files.h"
21397 #include "mod_cml.h"
21398 #include "mod_cml_funcs.h"
21408 @@ -42,29 +42,29 @@
21411 int n = lua_gettop(L);
21416 b.size = sizeof(hex);
21420 lua_pushstring(L, "md5: expected one argument");
21425 if (!lua_isstring(L, 1)) {
21426 lua_pushstring(L, "md5: argument has to be a string");
21432 MD5_Update(&Md5Ctx, (unsigned char *)lua_tostring(L, 1), lua_strlen(L, 1));
21433 MD5_Final(HA1, &Md5Ctx);
21436 buffer_copy_string_hex(&b, (char *)HA1, 16);
21439 lua_pushstring(L, b.ptr);
21445 @@ -72,37 +72,37 @@
21446 int f_file_mtime(lua_State *L) {
21448 int n = lua_gettop(L);
21452 lua_pushstring(L, "file_mtime: expected one argument");
21457 if (!lua_isstring(L, 1)) {
21458 lua_pushstring(L, "file_mtime: argument has to be a string");
21463 if (-1 == stat(lua_tostring(L, 1), &st)) {
21469 lua_pushnumber(L, st.st_mtime);
21476 int f_dir_files_iter(lua_State *L) {
21481 d = lua_touserdata(L, lua_upvalueindex(1));
21484 if (NULL == (de = readdir(d))) {
21491 lua_pushstring(L, de->d_name);
21492 @@ -113,75 +113,75 @@
21493 int f_dir_files(lua_State *L) {
21495 int n = lua_gettop(L);
21499 lua_pushstring(L, "dir_files: expected one argument");
21504 if (!lua_isstring(L, 1)) {
21505 lua_pushstring(L, "dir_files: argument has to be a string");
21509 - /* check if there is a valid DIR handle on the stack */
21511 + /* check if there is a valid DIR handle on the stack */
21512 if (NULL == (d = opendir(lua_tostring(L, 1)))) {
21518 /* push d into registry */
21519 lua_pushlightuserdata(L, d);
21520 lua_pushcclosure(L, f_dir_files_iter, 1);
21527 int f_file_isreg(lua_State *L) {
21529 int n = lua_gettop(L);
21533 lua_pushstring(L, "file_isreg: expected one argument");
21538 if (!lua_isstring(L, 1)) {
21539 lua_pushstring(L, "file_isreg: argument has to be a string");
21544 if (-1 == stat(lua_tostring(L, 1), &st)) {
21550 lua_pushnumber(L, S_ISREG(st.st_mode));
21556 int f_file_isdir(lua_State *L) {
21558 int n = lua_gettop(L);
21562 lua_pushstring(L, "file_isreg: expected one argument");
21567 if (!lua_isstring(L, 1)) {
21568 lua_pushstring(L, "file_isreg: argument has to be a string");
21573 if (-1 == stat(lua_tostring(L, 1), &st)) {
21579 lua_pushnumber(L, S_ISDIR(st.st_mode));
21585 @@ -192,33 +192,33 @@
21587 int n = lua_gettop(L);
21588 struct memcache *mc;
21591 if (!lua_islightuserdata(L, lua_upvalueindex(1))) {
21592 lua_pushstring(L, "where is my userdata ?");
21597 mc = lua_touserdata(L, lua_upvalueindex(1));
21601 lua_pushstring(L, "expected one argument");
21606 if (!lua_isstring(L, 1)) {
21607 lua_pushstring(L, "argument has to be a string");
21611 - if (NULL == (r = mc_aget(mc,
21613 + if (NULL == (r = mc_aget(mc,
21614 lua_tostring(L, 1), lua_strlen(L, 1)))) {
21617 lua_pushboolean(L, 0);
21625 lua_pushboolean(L, 1);
21628 @@ -226,74 +226,74 @@
21629 int f_memcache_get_string(lua_State *L) {
21631 int n = lua_gettop(L);
21634 struct memcache *mc;
21637 if (!lua_islightuserdata(L, lua_upvalueindex(1))) {
21638 lua_pushstring(L, "where is my userdata ?");
21643 mc = lua_touserdata(L, lua_upvalueindex(1));
21649 lua_pushstring(L, "expected one argument");
21654 if (!lua_isstring(L, 1)) {
21655 lua_pushstring(L, "argument has to be a string");
21659 - if (NULL == (r = mc_aget(mc,
21661 + if (NULL == (r = mc_aget(mc,
21662 lua_tostring(L, 1), lua_strlen(L, 1)))) {
21668 lua_pushstring(L, r);
21677 int f_memcache_get_long(lua_State *L) {
21679 int n = lua_gettop(L);
21682 struct memcache *mc;
21685 if (!lua_islightuserdata(L, lua_upvalueindex(1))) {
21686 lua_pushstring(L, "where is my userdata ?");
21691 mc = lua_touserdata(L, lua_upvalueindex(1));
21697 lua_pushstring(L, "expected one argument");
21702 if (!lua_isstring(L, 1)) {
21703 lua_pushstring(L, "argument has to be a string");
21707 - if (NULL == (r = mc_aget(mc,
21709 + if (NULL == (r = mc_aget(mc,
21710 lua_tostring(L, 1), lua_strlen(L, 1)))) {
21716 lua_pushnumber(L, strtol(r, NULL, 10));
21726 Property changes on: src/mod_cml_funcs.c
21727 ___________________________________________________________________
21728 Name: svn:eol-style
21731 Index: src/buffer.c
21732 ===================================================================
21733 --- src/buffer.c (.../tags/lighttpd-1.4.11) (revision 1159)
21734 +++ src/buffer.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
21735 @@ -12,20 +12,20 @@
21739 - * init the buffer
21741 + * init the buffer
21745 buffer* buffer_init(void) {
21749 b = malloc(sizeof(*b));
21765 - * free the buffer
21767 + * free the buffer
21771 void buffer_free(buffer *b) {
21772 @@ -49,39 +49,39 @@
21774 void buffer_reset(buffer *b) {
21778 /* limit don't reuse buffer larger than ... bytes */
21779 if (b->size > BUFFER_MAX_REUSE_SIZE) {
21792 - * allocate (if neccessary) enough space for 'size' bytes and
21794 + * allocate (if necessary) enough space for 'size' bytes and
21795 * set the 'used' counter to 0
21800 #define BUFFER_PIECE_SIZE 64
21802 int buffer_prepare_copy(buffer *b, size_t size) {
21805 - if ((0 == b->size) ||
21807 + if ((0 == b->size) ||
21808 (size > b->size)) {
21809 if (b->size) free(b->ptr);
21814 - /* always allocate a multiply of BUFFER_PIECE_SIZE */
21816 + /* always allocate a multiple of BUFFER_PIECE_SIZE */
21817 b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE);
21820 b->ptr = malloc(b->size);
21823 @@ -90,30 +90,30 @@
21828 - * increase the internal buffer (if neccessary) to append another 'size' byte
21830 + * increase the internal buffer (if necessary) to append another 'size' byte
21831 * ->used isn't changed
21836 int buffer_prepare_append(buffer *b, size_t size) {
21840 if (0 == b->size) {
21843 - /* always allocate a multiply of BUFFER_PIECE_SIZE */
21845 + /* always allocate a multiple of BUFFER_PIECE_SIZE */
21846 b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE);
21849 b->ptr = malloc(b->size);
21852 } else if (b->used + size > b->size) {
21855 - /* always allocate a multiply of BUFFER_PIECE_SIZE */
21857 + /* always allocate a multiple of BUFFER_PIECE_SIZE */
21858 b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE);
21861 b->ptr = realloc(b->ptr, b->size);
21864 @@ -122,7 +122,7 @@
21866 int buffer_copy_string(buffer *b, const char *s) {
21870 if (!s || !b) return -1;
21872 s_len = strlen(s) + 1;
21873 @@ -136,26 +136,26 @@
21875 int buffer_copy_string_len(buffer *b, const char *s, size_t s_len) {
21876 if (!s || !b) return -1;
21878 - /* removed optimization as we have to keep the empty string
21880 + /* removed optimization as we have to keep the empty string
21881 * in some cases for the config handling
21884 * url.access-deny = ( "" )
21886 if (s_len == 0) return 0;
21889 buffer_prepare_copy(b, s_len + 1);
21892 memcpy(b->ptr, s, s_len);
21893 b->ptr[s_len] = '\0';
21894 b->used = s_len + 1;
21900 int buffer_copy_string_buffer(buffer *b, const buffer *src) {
21901 if (!src) return -1;
21904 if (src->used == 0) {
21907 @@ -201,10 +201,10 @@
21910 * append a string to the end of the buffer
21912 - * the resulting buffer is terminated with a '\0'
21913 - * s is treated as a un-terminated string (a \0 is handled a normal character)
21916 + * the resulting buffer is terminated with a '\0'
21917 + * s is treated as an un-terminated string (a \0 is handled as a normal character)
21919 * @param b a buffer
21920 * @param s the string
21921 * @param s_len size of the string (without the terminating \0)
21922 @@ -228,7 +228,7 @@
21923 int buffer_append_string_buffer(buffer *b, const buffer *src) {
21924 if (!src) return -1;
21925 if (src->used == 0) return 0;
21928 return buffer_append_string_len(b, src->ptr, src->used - 1);
21931 @@ -245,9 +245,9 @@
21933 int buffer_copy_memory(buffer *b, const char *s, size_t s_len) {
21934 if (!s || !b) return -1;
21940 return buffer_append_memory(b, s, s_len);
21943 @@ -402,46 +402,115 @@
21947 - * init the buffer
21949 + * init the ptr buffer
21952 +buffer_ptr *buffer_ptr_init(buffer_ptr_free_t freer)
21954 + buffer_ptr *l = calloc(1, sizeof(buffer_ptr));
21961 + * free the buffer_array
21964 +void buffer_ptr_free(buffer_ptr *l)
21967 + buffer_ptr_clear(l);
21972 +void buffer_ptr_clear(buffer_ptr *l)
21974 + assert(NULL != l);
21976 + if (l->free && l->used) {
21978 + for (i = 0; i < l->used; i ++) {
21979 + l->free(l->ptr[i]);
21991 +void buffer_ptr_append(buffer_ptr* l, void *item)
21993 + assert(NULL != l);
21994 + if (l->ptr == NULL) {
21996 + l->ptr = (void **)malloc(sizeof(void *) * l->size);
21998 + else if (l->used == l->size) {
22000 + l->ptr = realloc(l->ptr, sizeof(void *) * l->size);
22002 + l->ptr[l->used++] = item;
22005 +void *buffer_ptr_pop(buffer_ptr* l)
22007 + assert(NULL != l && l->used > 0);
22008 + return l->ptr[--l->used];
22011 +void *buffer_ptr_top(buffer_ptr* l)
22013 + assert(NULL != l && l->used > 0);
22014 + return l->ptr[l->used-1];
22018 + * init the buffer
22022 buffer_array* buffer_array_init(void) {
22026 b = malloc(sizeof(*b));
22038 void buffer_array_reset(buffer_array *b) {
22045 /* if they are too large, reduce them */
22046 for (i = 0; i < b->used; i++) {
22047 buffer_reset(b->ptr[i]);
22056 - * free the buffer_array
22058 + * free the buffer_array
22062 void buffer_array_free(buffer_array *b) {
22067 for (i = 0; i < b->size; i++) {
22068 if (b->ptr[i]) buffer_free(b->ptr[i]);
22070 @@ -451,7 +520,7 @@
22072 buffer *buffer_array_append_get_buffer(buffer_array *b) {
22076 if (b->size == 0) {
22078 b->ptr = malloc(sizeof(*b->ptr) * b->size);
22079 @@ -467,13 +536,13 @@
22085 if (b->ptr[b->used] == NULL) {
22086 b->ptr[b->used] = buffer_init();
22090 b->ptr[b->used]->used = 0;
22093 return b->ptr[b->used++];
22096 @@ -482,23 +551,23 @@
22098 if (len == 0) return NULL;
22099 if (needle == NULL) return NULL;
22102 if (b->used < len) return NULL;
22105 for(i = 0; i < b->used - len; i++) {
22106 if (0 == memcmp(b->ptr + i, needle, len)) {
22115 buffer *buffer_init_string(const char *str) {
22116 buffer *b = buffer_init();
22119 buffer_copy_string(b, str);
22125 @@ -507,8 +576,8 @@
22129 - * check if two buffer contain the same data
22131 + * check if two buffers contain the same data
22133 * HISTORY: this function was pretty much optimized, but didn't handled
22134 * alignment properly.
22136 @@ -522,100 +591,100 @@
22138 int buffer_is_equal_string(buffer *a, const char *s, size_t b_len) {
22143 b.used = b_len + 1;
22146 return buffer_is_equal(a, &b);
22149 /* simple-assumption:
22151 - * most parts are equal and doing a case conversion needs time
22154 + * most parts are equal and doing a case conversion takes time
22157 int buffer_caseless_compare(const char *a, size_t a_len, const char *b, size_t b_len) {
22158 size_t ndx = 0, max_ndx;
22160 size_t mask = sizeof(*al) - 1;
22166 - /* is the alignment correct ? */
22168 + /* is the alignment correct? */
22169 if ( ((size_t)al & mask) == 0 &&
22170 ((size_t)bl & mask) == 0 ) {
22173 max_ndx = ((a_len < b_len) ? a_len : b_len) & ~mask;
22176 for (; ndx < max_ndx; ndx += sizeof(*al)) {
22177 if (*al != *bl) break;
22191 max_ndx = ((a_len < b_len) ? a_len : b_len);
22194 for (; ndx < max_ndx; ndx++) {
22195 char a1 = *a++, b1 = *b++;
22199 if ((a1 >= 'A' && a1 <= 'Z') && (b1 >= 'a' && b1 <= 'z'))
22201 else if ((a1 >= 'a' && a1 <= 'z') && (b1 >= 'A' && b1 <= 'Z'))
22203 if ((a1 - b1) != 0) return (a1 - b1);
22215 * check if the rightmost bytes of the string are equal.
22222 int buffer_is_equal_right_len(buffer *b1, buffer *b2, size_t len) {
22223 /* no, len -> equal */
22224 if (len == 0) return 1;
22227 /* len > 0, but empty buffers -> not equal */
22228 if (b1->used == 0 || b2->used == 0) return 0;
22231 /* buffers too small -> not equal */
22232 - if (b1->used - 1 < len || b1->used - 1 < len) return 0;
22234 - if (0 == strncmp(b1->ptr + b1->used - 1 - len,
22235 + if (b1->used - 1 < len || b2->used - 1 < len) return 0;
22237 + if (0 == strncmp(b1->ptr + b1->used - 1 - len,
22238 b2->ptr + b2->used - 1 - len, len)) {
22246 int buffer_copy_string_hex(buffer *b, const char *in, size_t in_len) {
22250 /* BO protection */
22251 if (in_len * 2 < in_len) return -1;
22254 buffer_prepare_copy(b, in_len * 2 + 1);
22257 for (i = 0; i < in_len; i++) {
22258 b->ptr[b->used++] = hex_chars[(in[i] >> 4) & 0x0F];
22259 b->ptr[b->used++] = hex_chars[in[i] & 0x0F];
22261 b->ptr[b->used++] = '\0';
22267 @@ -624,7 +693,7 @@
22268 0 1 2 3 4 5 6 7 8 9 A B C D E F
22270 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */
22271 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
22272 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
22273 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, /* 20 - 2F space " # $ % & ' + , / */
22274 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 30 - 3F : ; = ? @ < > */
22275 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 - 4F */
22276 @@ -646,7 +715,7 @@
22277 0 1 2 3 4 5 6 7 8 9 A B C D E F
22279 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */
22280 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
22281 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
22282 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, /* 20 - 2F space " # $ % & ' + , / */
22283 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 30 - 3F : ; = ? @ < > */
22284 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 - 4F */
22285 @@ -668,7 +737,7 @@
22286 0 1 2 3 4 5 6 7 8 9 A B C D E F
22288 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */
22289 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
22290 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
22291 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 20 - 2F & */
22292 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, /* 30 - 3F < > */
22293 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 - 4F */
22294 @@ -690,7 +759,7 @@
22295 0 1 2 3 4 5 6 7 8 9 A B C D E F
22297 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */
22298 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
22299 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
22300 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 20 - 2F & */
22301 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, /* 30 - 3F < > */
22302 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 - 4F */
22303 @@ -712,12 +781,12 @@
22304 0 1 2 3 4 5 6 7 8 9 A B C D E F
22306 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */
22307 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
22308 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */
22309 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 30 - 3F */
22310 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */
22311 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 50 - 5F */
22312 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */
22313 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */
22314 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */
22315 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 30 - 3F */
22316 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */
22317 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 50 - 5F */
22318 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */
22319 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 70 - 7F */
22320 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 80 - 8F */
22321 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 90 - 9F */
22322 @@ -734,13 +803,13 @@
22323 unsigned char *ds, *d;
22325 const char *map = NULL;
22328 if (!s || !b) return -1;
22331 if (b->ptr[b->used - 1] != '\0') {
22336 if (s_len == 0) return 0;
22339 @@ -760,12 +829,12 @@
22340 map = encoded_chars_hex;
22342 case ENCODING_UNSET:
22344 + return buffer_append_string_len(b, s, s_len);
22347 assert(map != NULL);
22349 - /* count to-be-encoded-characters */
22351 + /* count to-be-encoded characters */
22352 for (ds = (unsigned char *)s, d_len = 0, ndx = 0; ndx < s_len; ds++, ndx++) {
22355 @@ -787,9 +856,9 @@
22361 buffer_prepare_append(b, d_len);
22364 for (ds = (unsigned char *)s, d = (unsigned char *)b->ptr + b->used - 1, d_len = 0, ndx = 0; ndx < s_len; ds++, ndx++) {
22367 @@ -820,16 +889,16 @@
22371 - /* terminate buffer and calculate new length */
22372 + /* terminate buffer and calculate new length */
22373 b->ptr[b->used + d_len - 1] = '\0';
22382 -/* decodes url-special-chars inplace.
22383 +/* decodes url-special chars in-place.
22384 * replaces non-printable characters with '_'
22387 @@ -854,10 +923,10 @@
22388 low = hex2int(*(src + 2));
22390 high = (high << 4) | low;
22392 - /* map control-characters out */
22394 + /* map out control characters */
22395 if (high < 32 || high == 127) high = '_';
22401 @@ -891,7 +960,7 @@
22402 * /abc/./xyz gets /abc/xyz
22403 * /abc//xyz gets /abc/xyz
22405 - * NOTE: src and dest can point to the same buffer, in which case,
22406 + * NOTE: src and dest can point to the same buffer, in which case
22407 * the operation is performed in-place.
22410 @@ -979,7 +1048,7 @@
22412 int light_isxdigit(int c) {
22413 if (light_isdigit(c)) return 1;
22417 return (c >= 'a' && c <= 'f');
22419 @@ -993,31 +1062,56 @@
22420 return light_isdigit(c) || light_isalpha(c);
22423 +#undef BUFFER_CTYPE_FUNC
22424 +#define BUFFER_CTYPE_FUNC(type) \
22425 + int buffer_is##type(buffer *b) { \
22427 + if (b->used < 2) return 0; \
22429 + len = b->used - 1; \
22430 + /* c-string only */ \
22431 + if (b->ptr[len] != '\0') { \
22434 + /* check on the whole string */ \
22435 + for (i = 0; i < len; i ++) { \
22436 + if (!light_is##type(b->ptr[i])) { \
22443 +BUFFER_CTYPE_FUNC(digit)
22444 +BUFFER_CTYPE_FUNC(xdigit)
22445 +BUFFER_CTYPE_FUNC(alpha)
22446 +BUFFER_CTYPE_FUNC(alnum)
22448 int buffer_to_lower(buffer *b) {
22452 if (b->used == 0) return 0;
22455 for (c = b->ptr; *c; c++) {
22456 if (*c >= 'A' && *c <= 'Z') {
22466 int buffer_to_upper(buffer *b) {
22470 if (b->used == 0) return 0;
22473 for (c = b->ptr; *c; c++) {
22474 if (*c >= 'a' && *c <= 'z') {
22483 Property changes on: src/buffer.c
22484 ___________________________________________________________________
22485 Name: svn:eol-style
22488 Index: src/mod_simple_vhost.c
22489 ===================================================================
22490 --- src/mod_simple_vhost.c (.../tags/lighttpd-1.4.11) (revision 1159)
22491 +++ src/mod_simple_vhost.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
22494 #include "plugin.h"
22496 +#include "sys-files.h"
22498 #ifdef HAVE_CONFIG_H
22499 #include "config.h"
22502 buffer *server_root;
22503 buffer *default_host;
22504 buffer *document_root;
22507 buffer *docroot_cache_key;
22508 buffer *docroot_cache_value;
22509 buffer *docroot_cache_servername;
22510 @@ -28,138 +30,138 @@
22519 plugin_config **config_storage;
22520 - plugin_config conf;
22521 + plugin_config conf;
22524 INIT_FUNC(mod_simple_vhost_init) {
22528 p = calloc(1, sizeof(*p));
22531 p->doc_root = buffer_init();
22537 FREE_FUNC(mod_simple_vhost_free) {
22538 plugin_data *p = p_d;
22543 if (!p) return HANDLER_GO_ON;
22546 if (p->config_storage) {
22548 for (i = 0; i < srv->config_context->used; i++) {
22549 plugin_config *s = p->config_storage[i];
22552 buffer_free(s->document_root);
22553 buffer_free(s->default_host);
22554 buffer_free(s->server_root);
22557 buffer_free(s->docroot_cache_key);
22558 buffer_free(s->docroot_cache_value);
22559 buffer_free(s->docroot_cache_servername);
22566 free(p->config_storage);
22570 buffer_free(p->doc_root);
22576 return HANDLER_GO_ON;
22579 SETDEFAULTS_FUNC(mod_simple_vhost_set_defaults) {
22580 plugin_data *p = p_d;
22583 - config_values_t cv[] = {
22585 + config_values_t cv[] = {
22586 { "simple-vhost.server-root", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
22587 { "simple-vhost.default-host", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
22588 { "simple-vhost.document-root", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
22589 { "simple-vhost.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
22590 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
22594 if (!p) return HANDLER_ERROR;
22597 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
22600 for (i = 0; i < srv->config_context->used; i++) {
22604 s = calloc(1, sizeof(plugin_config));
22607 s->server_root = buffer_init();
22608 s->default_host = buffer_init();
22609 s->document_root = buffer_init();
22612 s->docroot_cache_key = buffer_init();
22613 s->docroot_cache_value = buffer_init();
22614 s->docroot_cache_servername = buffer_init();
22619 cv[0].destination = s->server_root;
22620 cv[1].destination = s->default_host;
22621 cv[2].destination = s->document_root;
22622 cv[3].destination = &(s->debug);
22627 p->config_storage[i] = s;
22630 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
22631 return HANDLER_ERROR;
22636 return HANDLER_GO_ON;
22639 static int build_doc_root(server *srv, connection *con, plugin_data *p, buffer *out, buffer *host) {
22640 stat_cache_entry *sce = NULL;
22643 buffer_prepare_copy(out, 128);
22645 if (p->conf.server_root->used) {
22646 buffer_copy_string_buffer(out, p->conf.server_root);
22650 /* a hostname has to start with a alpha-numerical character
22651 * and must not contain a slash "/"
22655 - BUFFER_APPEND_SLASH(out);
22658 + PATHNAME_APPEND_SLASH(out);
22660 if (NULL == (dp = strchr(host->ptr, ':'))) {
22661 buffer_append_string_buffer(out, host);
22663 buffer_append_string_len(out, host->ptr, dp - host->ptr);
22666 - BUFFER_APPEND_SLASH(out);
22668 + PATHNAME_APPEND_SLASH(out);
22670 if (p->conf.document_root->used > 2 && p->conf.document_root->ptr[0] == '/') {
22671 buffer_append_string_len(out, p->conf.document_root->ptr + 1, p->conf.document_root->used - 2);
22673 buffer_append_string_buffer(out, p->conf.document_root);
22674 - BUFFER_APPEND_SLASH(out);
22675 + PATHNAME_APPEND_SLASH(out);
22678 buffer_copy_string_buffer(out, con->conf.document_root);
22679 - BUFFER_APPEND_SLASH(out);
22680 + PATHNAME_APPEND_SLASH(out);
22684 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, out, &sce)) {
22685 if (p->conf.debug) {
22686 log_error_write(srv, __FILE__, __LINE__, "sb",
22687 @@ -169,57 +171,53 @@
22688 } else if (!S_ISDIR(sce->st.st_mode)) {
22697 -#define PATCH(x) \
22698 - p->conf.x = s->x;
22699 static int mod_simple_vhost_patch_connection(server *srv, connection *con, plugin_data *p) {
22701 plugin_config *s = p->config_storage[0];
22703 - PATCH(server_root);
22704 - PATCH(default_host);
22705 - PATCH(document_root);
22707 - PATCH(docroot_cache_key);
22708 - PATCH(docroot_cache_value);
22709 - PATCH(docroot_cache_servername);
22713 + PATCH_OPTION(server_root);
22714 + PATCH_OPTION(default_host);
22715 + PATCH_OPTION(document_root);
22717 + PATCH_OPTION(docroot_cache_key);
22718 + PATCH_OPTION(docroot_cache_value);
22719 + PATCH_OPTION(docroot_cache_servername);
22721 + PATCH_OPTION(debug);
22723 /* skip the first, the global context */
22724 for (i = 1; i < srv->config_context->used; i++) {
22725 data_config *dc = (data_config *)srv->config_context->data[i];
22726 s = p->config_storage[i];
22729 /* condition didn't match */
22730 if (!config_check_cond(srv, con, dc)) continue;
22734 for (j = 0; j < dc->value->used; j++) {
22735 data_unset *du = dc->value->data[j];
22738 if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.server-root"))) {
22739 - PATCH(server_root);
22740 - PATCH(docroot_cache_key);
22741 - PATCH(docroot_cache_value);
22742 - PATCH(docroot_cache_servername);
22743 + PATCH_OPTION(server_root);
22744 + PATCH_OPTION(docroot_cache_key);
22745 + PATCH_OPTION(docroot_cache_value);
22746 + PATCH_OPTION(docroot_cache_servername);
22747 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.default-host"))) {
22748 - PATCH(default_host);
22749 + PATCH_OPTION(default_host);
22750 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.document-root"))) {
22751 - PATCH(document_root);
22752 + PATCH_OPTION(document_root);
22753 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("simple-vhost.debug"))) {
22755 + PATCH_OPTION(debug);
22765 static handler_t mod_simple_vhost_docroot(server *srv, connection *con, void *p_data) {
22766 plugin_data *p = p_data;
22767 @@ -227,12 +225,12 @@
22769 * cache the last successfull translation from hostname (authority) to docroot
22770 * - this saves us a stat() call
22776 mod_simple_vhost_patch_connection(srv, con, p);
22778 - if (p->conf.docroot_cache_key->used &&
22780 + if (p->conf.docroot_cache_key->used &&
22781 con->uri.authority->used &&
22782 buffer_is_equal(p->conf.docroot_cache_key, con->uri.authority)) {
22784 @@ -243,8 +241,8 @@
22785 if ((con->uri.authority->used == 0) ||
22786 build_doc_root(srv, con, p, p->doc_root, con->uri.authority)) {
22787 /* not found, fallback the default-host */
22788 - if (build_doc_root(srv, con, p,
22790 + if (build_doc_root(srv, con, p,
22792 p->conf.default_host)) {
22793 return HANDLER_GO_ON;
22795 @@ -253,15 +251,15 @@
22797 buffer_copy_string_buffer(con->server_name, con->uri.authority);
22801 /* copy to cache */
22802 buffer_copy_string_buffer(p->conf.docroot_cache_key, con->uri.authority);
22803 buffer_copy_string_buffer(p->conf.docroot_cache_value, p->doc_root);
22804 buffer_copy_string_buffer(p->conf.docroot_cache_servername, con->server_name);
22807 buffer_copy_string_buffer(con->physical.doc_root, p->doc_root);
22811 return HANDLER_GO_ON;
22814 @@ -269,13 +267,13 @@
22815 int mod_simple_vhost_plugin_init(plugin *p) {
22816 p->version = LIGHTTPD_VERSION_ID;
22817 p->name = buffer_init_string("simple_vhost");
22820 p->init = mod_simple_vhost_init;
22821 p->set_defaults = mod_simple_vhost_set_defaults;
22822 p->handle_docroot = mod_simple_vhost_docroot;
22823 p->cleanup = mod_simple_vhost_free;
22832 Property changes on: src/mod_simple_vhost.c
22833 ___________________________________________________________________
22834 Name: svn:eol-style
22837 Index: src/mod_userdir.c
22838 ===================================================================
22839 --- src/mod_userdir.c (.../tags/lighttpd-1.4.11) (revision 1159)
22840 +++ src/mod_userdir.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
22842 #include "response.h"
22844 #include "plugin.h"
22845 +#include "sys-files.h"
22849 @@ -25,54 +26,54 @@
22859 plugin_config **config_storage;
22861 - plugin_config conf;
22863 + plugin_config conf;
22866 /* init the plugin data */
22867 INIT_FUNC(mod_userdir_init) {
22871 p = calloc(1, sizeof(*p));
22874 p->username = buffer_init();
22875 p->temp_path = buffer_init();
22881 /* detroy the plugin data */
22882 FREE_FUNC(mod_userdir_free) {
22883 plugin_data *p = p_d;
22886 if (!p) return HANDLER_GO_ON;
22889 if (p->config_storage) {
22893 for (i = 0; i < srv->config_context->used; i++) {
22894 plugin_config *s = p->config_storage[i];
22897 array_free(s->include_user);
22898 array_free(s->exclude_user);
22899 buffer_free(s->path);
22900 buffer_free(s->basepath);
22905 free(p->config_storage);
22909 buffer_free(p->username);
22910 buffer_free(p->temp_path);
22916 return HANDLER_GO_ON;
22919 @@ -81,81 +82,78 @@
22920 SETDEFAULTS_FUNC(mod_userdir_set_defaults) {
22921 plugin_data *p = p_d;
22924 - config_values_t cv[] = {
22926 + config_values_t cv[] = {
22927 { "userdir.path", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
22928 { "userdir.exclude-user", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
22929 { "userdir.include-user", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
22930 { "userdir.basepath", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
22931 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
22935 if (!p) return HANDLER_ERROR;
22938 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
22941 for (i = 0; i < srv->config_context->used; i++) {
22945 s = calloc(1, sizeof(plugin_config));
22946 s->exclude_user = array_init();
22947 s->include_user = array_init();
22948 s->path = buffer_init();
22949 s->basepath = buffer_init();
22952 cv[0].destination = s->path;
22953 cv[1].destination = s->exclude_user;
22954 cv[2].destination = s->include_user;
22955 cv[3].destination = s->basepath;
22958 p->config_storage[i] = s;
22961 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
22962 return HANDLER_ERROR;
22967 return HANDLER_GO_ON;
22970 -#define PATCH(x) \
22971 - p->conf.x = s->x;
22972 static int mod_userdir_patch_connection(server *srv, connection *con, plugin_data *p) {
22974 plugin_config *s = p->config_storage[0];
22977 - PATCH(exclude_user);
22978 - PATCH(include_user);
22982 + PATCH_OPTION(path);
22983 + PATCH_OPTION(exclude_user);
22984 + PATCH_OPTION(include_user);
22985 + PATCH_OPTION(basepath);
22987 /* skip the first, the global context */
22988 for (i = 1; i < srv->config_context->used; i++) {
22989 data_config *dc = (data_config *)srv->config_context->data[i];
22990 s = p->config_storage[i];
22993 /* condition didn't match */
22994 if (!config_check_cond(srv, con, dc)) continue;
22998 for (j = 0; j < dc->value->used; j++) {
22999 data_unset *du = dc->value->data[j];
23002 if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.path"))) {
23004 + PATCH_OPTION(path);
23005 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.exclude-user"))) {
23006 - PATCH(exclude_user);
23007 + PATCH_OPTION(exclude_user);
23008 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.include-user"))) {
23009 - PATCH(include_user);
23010 + PATCH_OPTION(include_user);
23011 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.basepath"))) {
23013 + PATCH_OPTION(basepath);
23023 URIHANDLER_FUNC(mod_userdir_docroot_handler) {
23024 plugin_data *p = p_d;
23025 @@ -169,18 +167,18 @@
23026 if (con->uri.path->used == 0) return HANDLER_GO_ON;
23028 mod_userdir_patch_connection(srv, con, p);
23031 uri_len = con->uri.path->used - 1;
23034 /* /~user/foo.html -> /home/user/public_html/foo.html */
23037 if (con->uri.path->ptr[0] != '/' ||
23038 con->uri.path->ptr[1] != '~') return HANDLER_GO_ON;
23041 if (NULL == (rel_url = strchr(con->uri.path->ptr + 2, '/'))) {
23042 /* / is missing -> redirect to .../ as we are a user - DIRECTORY ! :) */
23043 http_response_redirect_to_directory(srv, con);
23046 return HANDLER_FINISHED;
23049 @@ -188,10 +186,10 @@
23050 if (0 == rel_url - (con->uri.path->ptr + 2)) {
23051 return HANDLER_GO_ON;
23055 buffer_copy_string_len(p->username, con->uri.path->ptr + 2, rel_url - (con->uri.path->ptr + 2));
23057 - if (buffer_is_empty(p->conf.basepath)
23059 + if (buffer_is_empty(p->conf.basepath)
23061 && NULL == (pwd = getpwnam(p->username->ptr))
23063 @@ -200,31 +198,31 @@
23064 return HANDLER_GO_ON;
23069 for (k = 0; k < p->conf.exclude_user->used; k++) {
23070 data_string *ds = (data_string *)p->conf.exclude_user->data[k];
23073 if (buffer_is_equal(ds->value, p->username)) {
23074 /* user in exclude list */
23075 return HANDLER_GO_ON;
23080 if (p->conf.include_user->used) {
23081 int found_user = 0;
23082 for (k = 0; k < p->conf.include_user->used; k++) {
23083 data_string *ds = (data_string *)p->conf.include_user->data[k];
23086 if (buffer_is_equal(ds->value, p->username)) {
23087 /* user in include list */
23094 if (!found_user) return HANDLER_GO_ON;
23098 /* we build the physical path */
23100 if (buffer_is_empty(p->conf.basepath)) {
23101 @@ -252,23 +250,23 @@
23104 buffer_copy_string_buffer(p->temp_path, p->conf.basepath);
23105 - BUFFER_APPEND_SLASH(p->temp_path);
23106 + PATHNAME_APPEND_SLASH(p->temp_path);
23107 buffer_append_string_buffer(p->temp_path, p->username);
23109 - BUFFER_APPEND_SLASH(p->temp_path);
23110 - buffer_append_string_buffer(p->temp_path, p->conf.path);
23111 + PATHNAME_APPEND_SLASH(p->temp_path);
23112 + buffer_append_string_buffer(p->temp_path, p->conf.path);
23114 if (buffer_is_empty(p->conf.basepath)) {
23119 ret = stat(p->temp_path->ptr, &st);
23120 if (ret < 0 || S_ISDIR(st.st_mode) != 1) {
23121 return HANDLER_GO_ON;
23126 - BUFFER_APPEND_SLASH(p->temp_path);
23127 + PATHNAME_APPEND_SLASH(p->temp_path);
23128 buffer_append_string(p->temp_path, rel_url + 1); /* skip the / */
23129 buffer_copy_string_buffer(con->physical.path, p->temp_path);
23131 @@ -282,13 +280,13 @@
23132 int mod_userdir_plugin_init(plugin *p) {
23133 p->version = LIGHTTPD_VERSION_ID;
23134 p->name = buffer_init_string("userdir");
23137 p->init = mod_userdir_init;
23138 p->handle_physical = mod_userdir_docroot_handler;
23139 p->set_defaults = mod_userdir_set_defaults;
23140 p->cleanup = mod_userdir_free;
23149 Property changes on: src/mod_userdir.c
23150 ___________________________________________________________________
23151 Name: svn:eol-style
23155 Property changes on: src/mod_cml_funcs.h
23156 ___________________________________________________________________
23157 Name: svn:eol-style
23160 Index: src/buffer.h
23161 ===================================================================
23162 --- src/buffer.h (.../tags/lighttpd-1.4.11) (revision 1159)
23163 +++ src/buffer.h (.../branches/lighttpd-merge-1.4.x) (revision 1159)
23164 @@ -12,27 +12,44 @@
23175 +typedef void (*buffer_ptr_free_t)(void *p);
23181 + buffer_ptr_free_t free;
23195 - size_t offset; /* input-pointer */
23197 - size_t used; /* output-pointer */
23199 + size_t offset; /* input pointer */
23201 + size_t used; /* output pointer */
23205 +buffer_ptr *buffer_ptr_init(buffer_ptr_free_t freer);
23206 +void buffer_ptr_free(buffer_ptr *b);
23207 +void buffer_ptr_clear(buffer_ptr *b);
23208 +void buffer_ptr_append(buffer_ptr *b, void *item);
23209 +void *buffer_ptr_pop(buffer_ptr *b);
23210 +void *buffer_ptr_top(buffer_ptr *b);
23212 buffer_array* buffer_array_init(void);
23213 void buffer_array_free(buffer_array *b);
23214 void buffer_array_reset(buffer_array *b);
23216 buffer* buffer_init_string(const char *str);
23217 void buffer_free(buffer *b);
23218 void buffer_reset(buffer *b);
23221 int buffer_prepare_copy(buffer *b, size_t size);
23222 int buffer_prepare_append(buffer *b, size_t size);
23228 - ENCODING_REL_URI, /* for coding a rel-uri (/with space/and%percent) nicely as part of a href */
23229 - ENCODING_REL_URI_PART, /* same as ENC_REL_URL plus coding / too as %2F */
23230 - ENCODING_HTML, /* & becomes & and so on */
23231 + ENCODING_REL_URI, /* for coding a rel-uri (/with space/and%percent) nicely as part of an href */
23232 + ENCODING_REL_URI_PART, /* same as ENC_REL_URL plus encoding "/" as "%2F" */
23233 + ENCODING_HTML, /* "&" becomes "&" and so on */
23234 ENCODING_MINIMAL_XML, /* minimal encoding for xml */
23235 ENCODING_HEX /* encode string as hex */
23236 } buffer_encoding_t;
23237 @@ -111,19 +128,21 @@
23238 int light_isalpha(int c);
23239 int light_isalnum(int c);
23241 +#define BUFFER_CTYPE_FUNC(type) int buffer_is##type(buffer *b);
23242 +BUFFER_CTYPE_FUNC(digit)
23243 +BUFFER_CTYPE_FUNC(xdigit)
23244 +BUFFER_CTYPE_FUNC(alpha)
23245 +BUFFER_CTYPE_FUNC(alnum)
23247 #define BUFFER_APPEND_STRING_CONST(x, y) \
23248 buffer_append_string_len(x, y, sizeof(y) - 1)
23250 #define BUFFER_COPY_STRING_CONST(x, y) \
23251 buffer_copy_string_len(x, y, sizeof(y) - 1)
23253 -#define BUFFER_APPEND_SLASH(x) \
23254 - if (x->used > 1 && x->ptr[x->used - 2] != '/') { BUFFER_APPEND_STRING_CONST(x, "/"); }
23256 #define CONST_STR_LEN(x) x, x ? sizeof(x) - 1 : 0
23257 #define CONST_BUF_LEN(x) x->ptr, x->used ? x->used - 1 : 0
23260 #define SEGFAULT() do { fprintf(stderr, "%s.%d: aborted\n", __FILE__, __LINE__); abort(); } while(0)
23261 #define UNUSED(x) ( (void)(x) )
23264 Property changes on: src/buffer.h
23265 ___________________________________________________________________
23266 Name: svn:eol-style
23269 Index: src/mod_proxy.c
23270 ===================================================================
23271 --- src/mod_proxy.c (.../tags/lighttpd-1.4.11) (revision 1159)
23272 +++ src/mod_proxy.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
23274 #include <sys/types.h>
23276 -#include <unistd.h>
23279 #include <string.h>
23282 #include "inet_ntop_cache.h"
23284 +#include "network.h"
23286 +#include "http_resp.h"
23290 #ifdef HAVE_SYS_FILIO_H
23294 #include "sys-socket.h"
23295 +#include "sys-files.h"
23296 +#include "sys-strings.h"
23298 #define data_proxy data_fastcgi
23299 #define data_proxy_init data_fastcgi_init
23300 @@ -38,16 +42,16 @@
23301 #define PROXY_RETRY_TIMEOUT 60
23305 - * the proxy module is based on the fastcgi module
23308 + * the proxy module is based on the fastcgi module
23310 * 28.06.2004 Jan Kneschke The first release
23311 * 01.07.2004 Evgeny Rodichev Several bugfixes and cleanups
23312 * - co-ordinate up- and downstream flows correctly (proxy_demux_response
23313 * and proxy_handle_fdevent)
23314 * - correctly transfer upstream http_response_status;
23315 * - some unused structures removed.
23318 * TODO: - delay upstream read if write_queue is too large
23319 * (to prevent memory eating, like in apache). Shoud be
23321 @@ -66,26 +70,31 @@
23324 proxy_balance_t balance;
23326 + array *last_used_backends; /* "extension" : last_used_backend */
23333 buffer *parse_response;
23334 buffer *balance_buf;
23337 + array *ignore_headers;
23339 plugin_config **config_storage;
23342 plugin_config conf;
23346 - PROXY_STATE_INIT,
23347 - PROXY_STATE_CONNECT,
23348 - PROXY_STATE_PREPARE_WRITE,
23349 - PROXY_STATE_WRITE,
23350 - PROXY_STATE_READ,
23351 - PROXY_STATE_ERROR
23353 + PROXY_STATE_INIT,
23354 + PROXY_STATE_CONNECT,
23355 + PROXY_STATE_PREPARE_WRITE,
23356 + PROXY_STATE_WRITE,
23357 + PROXY_STATE_RESPONSE_HEADER,
23358 + PROXY_STATE_RESPONSE_CONTENT,
23359 + PROXY_STATE_ERROR
23360 } proxy_connection_state_t;
23362 enum { PROXY_STDOUT, PROXY_END_REQUEST };
23363 @@ -93,19 +102,20 @@
23365 proxy_connection_state_t state;
23366 time_t state_timestamp;
23373 buffer *response_header;
23379 int fd; /* fd to the proxy process */
23380 int fde_ndx; /* index into the fd-event buffer */
23382 size_t path_info_offset; /* start of path_info in uri.path */
23385 connection *remote_conn; /* dump pointer */
23386 plugin_data *plugin_data; /* dump pointer */
23388 @@ -116,21 +126,22 @@
23390 static handler_ctx * handler_ctx_init() {
23391 handler_ctx * hctx;
23395 hctx = calloc(1, sizeof(*hctx));
23398 hctx->state = PROXY_STATE_INIT;
23402 hctx->response = buffer_init();
23403 hctx->response_header = buffer_init();
23405 hctx->wb = chunkqueue_init();
23406 + hctx->rb = chunkqueue_init();
23409 hctx->fde_ndx = -1;
23415 @@ -138,47 +149,70 @@
23416 buffer_free(hctx->response);
23417 buffer_free(hctx->response_header);
23418 chunkqueue_free(hctx->wb);
23420 + chunkqueue_free(hctx->rb);
23425 INIT_FUNC(mod_proxy_init) {
23430 + char *hop2hop_headers[] = {
23437 p = calloc(1, sizeof(*p));
23440 p->parse_response = buffer_init();
23441 p->balance_buf = buffer_init();
23443 + p->ignore_headers = array_init();
23445 + for (i = 0; hop2hop_headers[i]; i++) {
23448 + if (NULL == (ds = (data_string *)array_get_unused_element(p->ignore_headers, TYPE_STRING))) {
23449 + ds = data_string_init();
23452 + buffer_copy_string(ds->value, hop2hop_headers[i]);
23453 + array_insert_unique(p->ignore_headers, (data_unset *)ds);
23460 FREE_FUNC(mod_proxy_free) {
23461 plugin_data *p = p_d;
23466 buffer_free(p->parse_response);
23467 buffer_free(p->balance_buf);
23470 if (p->config_storage) {
23472 for (i = 0; i < srv->config_context->used; i++) {
23473 plugin_config *s = p->config_storage[i];
23478 array_free(s->extensions);
23480 + array_free(s->last_used_backends);
23485 free(p->config_storage);
23489 + free(p->ignore_headers);
23494 return HANDLER_GO_ON;
23497 @@ -186,37 +220,38 @@
23498 plugin_data *p = p_d;
23502 - config_values_t cv[] = {
23504 + config_values_t cv[] = {
23505 { "proxy.server", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
23506 { "proxy.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
23507 { "proxy.balance", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
23508 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
23512 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
23515 for (i = 0; i < srv->config_context->used; i++) {
23520 s = malloc(sizeof(plugin_config));
23521 - s->extensions = array_init();
23522 + s->extensions = array_init();
23523 + s->last_used_backends = array_init();
23527 cv[0].destination = s->extensions;
23528 cv[1].destination = &(s->debug);
23529 cv[2].destination = p->balance_buf;
23531 buffer_reset(p->balance_buf);
23534 p->config_storage[i] = s;
23535 ca = ((data_config *)srv->config_context->data[i])->value;
23538 if (0 != config_insert_values_global(srv, ca, cv)) {
23539 return HANDLER_ERROR;
23543 if (buffer_is_empty(p->balance_buf)) {
23544 s->balance = PROXY_BALANCE_FAIR;
23545 } else if (buffer_is_equal_string(p->balance_buf, CONST_STR_LEN("fair"))) {
23546 @@ -226,7 +261,7 @@
23547 } else if (buffer_is_equal_string(p->balance_buf, CONST_STR_LEN("hash"))) {
23548 s->balance = PROXY_BALANCE_HASH;
23550 - log_error_write(srv, __FILE__, __LINE__, "sb",
23551 + log_error_write(srv, __FILE__, __LINE__, "sb",
23552 "proxy.balance has to be one of: fair, round-robin, hash, but not:", p->balance_buf);
23553 return HANDLER_ERROR;
23555 @@ -234,91 +269,91 @@
23556 if (NULL != (du = array_get_element(ca, "proxy.server"))) {
23558 data_array *da = (data_array *)du;
23561 if (du->type != TYPE_ARRAY) {
23562 - log_error_write(srv, __FILE__, __LINE__, "sss",
23563 + log_error_write(srv, __FILE__, __LINE__, "sss",
23564 "unexpected type for key: ", "proxy.server", "array of strings");
23567 return HANDLER_ERROR;
23573 * proxy.server = ( "<ext>" => ...,
23578 for (j = 0; j < da->value->used; j++) {
23579 data_array *da_ext = (data_array *)da->value->data[j];
23583 if (da_ext->type != TYPE_ARRAY) {
23584 - log_error_write(srv, __FILE__, __LINE__, "sssbs",
23585 - "unexpected type for key: ", "proxy.server",
23586 + log_error_write(srv, __FILE__, __LINE__, "sssbs",
23587 + "unexpected type for key: ", "proxy.server",
23588 "[", da->value->data[j]->key, "](string)");
23591 return HANDLER_ERROR;
23595 - * proxy.server = ( "<ext>" =>
23596 - * ( "<host>" => ( ... ),
23599 + * proxy.server = ( "<ext>" =>
23600 + * ( "<host>" => ( ... ),
23601 * "<host>" => ( ... )
23608 for (n = 0; n < da_ext->value->used; n++) {
23609 data_array *da_host = (data_array *)da_ext->value->data[n];
23615 - config_values_t pcv[] = {
23617 + config_values_t pcv[] = {
23618 { "host", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
23619 { "port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
23620 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
23624 if (da_host->type != TYPE_ARRAY) {
23625 - log_error_write(srv, __FILE__, __LINE__, "ssSBS",
23626 - "unexpected type for key:",
23628 + log_error_write(srv, __FILE__, __LINE__, "ssSBS",
23629 + "unexpected type for key:",
23631 "[", da_ext->value->data[n]->key, "](string)");
23634 return HANDLER_ERROR;
23638 df = data_proxy_init();
23644 buffer_copy_string_buffer(df->key, da_host->key);
23647 pcv[0].destination = df->host;
23648 pcv[1].destination = &(df->port);
23651 if (0 != config_insert_values_internal(srv, da_host->value, pcv)) {
23652 return HANDLER_ERROR;
23656 if (buffer_is_empty(df->host)) {
23657 - log_error_write(srv, __FILE__, __LINE__, "sbbbs",
23658 - "missing key (string):",
23659 + log_error_write(srv, __FILE__, __LINE__, "sbbbs",
23660 + "missing key (string):",
23667 return HANDLER_ERROR;
23671 /* if extension already exists, take it */
23674 if (NULL == (dfa = (data_array *)array_get_element(s->extensions, da_ext->key->ptr))) {
23675 dfa = data_array_init();
23678 buffer_copy_string_buffer(dfa->key, da_ext->key);
23681 array_insert_unique(dfa->value, (data_unset *)df);
23682 array_insert_unique(s->extensions, (data_unset *)dfa);
23684 @@ -328,19 +363,19 @@
23690 return HANDLER_GO_ON;
23693 void proxy_connection_close(server *srv, handler_ctx *hctx) {
23698 if (NULL == hctx) return;
23701 p = hctx->plugin_data;
23702 con = hctx->remote_conn;
23705 if (hctx->fd != -1) {
23706 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
23707 fdevent_unregister(srv->ev, hctx->fd);
23708 @@ -348,47 +383,56 @@
23714 handler_ctx_free(hctx);
23715 - con->plugin_ctx[p->id] = NULL;
23716 + con->plugin_ctx[p->id] = NULL;
23719 static int proxy_establish_connection(server *srv, handler_ctx *hctx) {
23720 struct sockaddr *proxy_addr;
23721 struct sockaddr_in proxy_addr_in;
23725 plugin_data *p = hctx->plugin_data;
23726 data_proxy *host= hctx->host;
23727 int proxy_fd = hctx->fd;
23730 memset(&proxy_addr, 0, sizeof(proxy_addr));
23733 proxy_addr_in.sin_family = AF_INET;
23734 proxy_addr_in.sin_addr.s_addr = inet_addr(host->host->ptr);
23735 proxy_addr_in.sin_port = htons(host->port);
23736 servlen = sizeof(proxy_addr_in);
23739 proxy_addr = (struct sockaddr *) &proxy_addr_in;
23742 if (-1 == connect(proxy_fd, proxy_addr, servlen)) {
23743 - if (errno == EINPROGRESS || errno == EALREADY) {
23745 + errno = WSAGetLastError();
23749 + case WSAEWOULDBLOCK:
23751 + case EINPROGRESS:
23753 if (p->conf.debug) {
23754 - log_error_write(srv, __FILE__, __LINE__, "sd",
23755 + log_error_write(srv, __FILE__, __LINE__, "sd",
23756 "connect delayed:", proxy_fd);
23763 - log_error_write(srv, __FILE__, __LINE__, "sdsd",
23766 + log_error_write(srv, __FILE__, __LINE__, "sdsd",
23767 "connect failed:", proxy_fd, strerror(errno), errno);
23773 + fprintf(stderr, "%s.%d: connected fd = %d\r\n", __FILE__, __LINE__, proxy_fd);
23774 if (p->conf.debug) {
23775 - log_error_write(srv, __FILE__, __LINE__, "sd",
23776 + log_error_write(srv, __FILE__, __LINE__, "sd",
23777 "connect succeeded: ", proxy_fd);
23780 @@ -422,25 +466,26 @@
23782 static int proxy_create_env(server *srv, handler_ctx *hctx) {
23786 connection *con = hctx->remote_conn;
23787 + plugin_data *p = hctx->plugin_data;
23793 b = chunkqueue_get_append_buffer(hctx->wb);
23797 buffer_copy_string(b, get_http_method_name(con->request.http_method));
23798 BUFFER_APPEND_STRING_CONST(b, " ");
23801 buffer_append_string_buffer(b, con->request.uri);
23802 BUFFER_APPEND_STRING_CONST(b, " HTTP/1.0\r\n");
23804 proxy_append_header(con, "X-Forwarded-For", (char *)inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
23805 - /* http_host is NOT is just a pointer to a buffer
23806 + /* http_host is NOT is just a pointer to a buffer
23807 * which is NULL if it is not set */
23808 - if (con->request.http_host &&
23809 + if (con->request.http_host &&
23810 !buffer_is_empty(con->request.http_host)) {
23811 proxy_set_header(con, "X-Host", con->request.http_host->ptr);
23813 @@ -449,24 +494,26 @@
23814 /* request header */
23815 for (i = 0; i < con->request.headers->used; i++) {
23819 ds = (data_string *)con->request.headers->data[i];
23822 if (ds->value->used && ds->key->used) {
23823 - if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Connection"))) continue;
23826 + /* don't copy hop-to-hop headers */
23827 + if (array_get_element(p->ignore_headers, ds->key->ptr)) continue;
23829 buffer_append_string_buffer(b, ds->key);
23830 BUFFER_APPEND_STRING_CONST(b, ": ");
23831 buffer_append_string_buffer(b, ds->value);
23832 BUFFER_APPEND_STRING_CONST(b, "\r\n");
23837 BUFFER_APPEND_STRING_CONST(b, "\r\n");
23840 hctx->wb->bytes_in += b->used - 1;
23844 if (con->request.content_length) {
23845 chunkqueue *req_cq = con->request_content_queue;
23847 @@ -479,7 +526,7 @@
23849 /* we announce toWrite octects
23850 * now take all the request_content chunk that we need to fill this request
23854 switch (req_c->type) {
23856 @@ -507,223 +554,125 @@
23858 req_c->offset += weHave;
23859 req_cq->bytes_out += weHave;
23862 hctx->wb->bytes_in += weHave;
23879 static int proxy_set_state(server *srv, handler_ctx *hctx, proxy_connection_state_t state) {
23880 hctx->state = state;
23881 hctx->state_timestamp = srv->cur_ts;
23888 -static int proxy_response_parse(server *srv, connection *con, plugin_data *p, buffer *in) {
23890 - int http_response_status = -1;
23893 +static void chunkqueue_print(chunkqueue *cq) {
23896 - /* \r\n -> \0\0 */
23898 - buffer_copy_string_buffer(p->parse_response, in);
23900 - for (s = p->parse_response->ptr; NULL != (ns = strstr(s, "\r\n")); s = ns + 2) {
23901 - char *key, *value;
23908 + for (c = cq->first; c; c = c->next) {
23909 + fprintf(stderr, "%s", c->mem->ptr + c->offset);
23911 + fprintf(stderr, "\r\n");
23914 - if (-1 == http_response_status) {
23915 - /* The first line of a Response message is the Status-Line */
23916 +static int proxy_demux_response(server *srv, handler_ctx *hctx) {
23917 + plugin_data *p = hctx->plugin_data;
23918 + connection *con = hctx->remote_conn;
23919 + int proxy_fd = hctx->fd;
23920 + chunkqueue *next_queue = NULL;
23923 - for (key=s; *key && *key != ' '; key++);
23924 + switch(srv->network_backend_read(srv, con, proxy_fd, hctx->rb)) {
23925 + case NETWORK_STATUS_SUCCESS:
23926 + /* we got content */
23928 + case NETWORK_STATUS_CONNECTION_CLOSE:
23929 + /* we are done, get out of here */
23930 + con->file_finished = 1;
23933 - http_response_status = (int) strtol(key, NULL, 10);
23934 - if (http_response_status <= 0) http_response_status = 502;
23936 - http_response_status = 502;
23938 + /* close the chunk-queue with a empty chunk */
23939 + http_chunk_append_mem(srv, con, NULL, 0);
23940 + joblist_append(srv, con);
23942 - con->http_status = http_response_status;
23943 - con->parsed_response |= HTTP_STATUS;
23947 - if (NULL == (value = strchr(s, ':'))) {
23948 - /* now we expect: "<key>: <value>\n" */
23957 + /* looks like we got some content
23959 + * split off the header from the incoming stream
23963 - key_len = value - key;
23967 - while (*value == ' ' || *value == '\t') value++;
23971 - switch(key_len) {
23973 - if (0 == strncasecmp(key, "Date", key_len)) {
23974 - con->parsed_response |= HTTP_DATE;
23978 - if (0 == strncasecmp(key, "Location", key_len)) {
23979 - con->parsed_response |= HTTP_LOCATION;
23983 - if (0 == strncasecmp(key, "Connection", key_len)) {
23988 - if (0 == strncasecmp(key, "Content-Length", key_len)) {
23989 - con->response.content_length = strtol(value, NULL, 10);
23990 - con->parsed_response |= HTTP_CONTENT_LENGTH;
23996 + if (hctx->state == PROXY_STATE_RESPONSE_HEADER) {
23997 + http_resp *resp = http_response_init();
23999 - if (copy_header) {
24000 - if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
24001 - ds = data_response_init();
24003 - buffer_copy_string_len(ds->key, key, key_len);
24004 - buffer_copy_string(ds->value, value);
24006 - array_insert_unique(con->response.headers, (data_unset *)ds);
24012 + /* the response header is not fully received yet,
24014 + * extract the http-response header from the rb-cq
24016 + fprintf(stderr, "%s.%d: network-read\r\n", __FILE__, __LINE__);
24017 + chunkqueue_print(hctx->rb);
24019 + switch (http_response_parse_cq(hctx->rb, resp)) {
24020 + case PARSE_ERROR:
24021 + /* parsing failed */
24023 -static int proxy_demux_response(server *srv, handler_ctx *hctx) {
24028 - plugin_data *p = hctx->plugin_data;
24029 - connection *con = hctx->remote_conn;
24030 - int proxy_fd = hctx->fd;
24032 - /* check how much we have to read */
24033 - if (ioctl(hctx->fd, FIONREAD, &b)) {
24034 - log_error_write(srv, __FILE__, __LINE__, "sd",
24035 - "ioctl failed: ",
24039 + con->http_status = 502; /* Bad Gateway */
24041 + case PARSE_NEED_MORE:
24043 + case PARSE_SUCCESS:
24044 + con->http_status = resp->status;
24046 + fprintf(stderr, "%s.%d: parsing done\r\n", __FILE__, __LINE__);
24047 + chunkqueue_print(hctx->rb);
24049 - if (p->conf.debug) {
24050 - log_error_write(srv, __FILE__, __LINE__, "sd",
24051 - "proxy - have to read:", b);
24053 + con->file_started = 1;
24056 - if (hctx->response->used == 0) {
24057 - /* avoid too small buffer */
24058 - buffer_prepare_append(hctx->response, b + 1);
24059 - hctx->response->used = 1;
24061 - buffer_prepare_append(hctx->response, hctx->response->used + b);
24064 - if (-1 == (r = read(hctx->fd, hctx->response->ptr + hctx->response->used - 1, b))) {
24065 - log_error_write(srv, __FILE__, __LINE__, "sds",
24066 - "unexpected end-of-file (perhaps the proxy process died):",
24067 - proxy_fd, strerror(errno));
24071 - /* this should be catched by the b > 0 above */
24074 - hctx->response->used += r;
24075 - hctx->response->ptr[hctx->response->used - 1] = '\0';
24076 + hctx->state = PROXY_STATE_RESPONSE_CONTENT;
24082 - log_error_write(srv, __FILE__, __LINE__, "sdsbs",
24083 - "demux: Response buffer len", hctx->response->used, ":", hctx->response, ":");
24085 + /* FIXME: pass the response-header to the other plugins to
24086 + * setup the filter-queue
24088 + * - use next-queue instead of con->write_queue
24091 - if (0 == con->got_response) {
24092 - con->got_response = 1;
24093 - buffer_prepare_copy(hctx->response_header, 128);
24096 - if (0 == con->file_started) {
24099 - /* search for the \r\n\r\n in the string */
24100 - if (NULL != (c = buffer_search_string_len(hctx->response, "\r\n\r\n", 4))) {
24101 - size_t hlen = c - hctx->response->ptr + 4;
24102 - size_t blen = hctx->response->used - hlen - 1;
24105 - buffer_append_string_len(hctx->response_header, hctx->response->ptr, c - hctx->response->ptr + 4);
24107 - log_error_write(srv, __FILE__, __LINE__, "sb", "Header:", hctx->response_header);
24109 - /* parse the response header */
24110 - proxy_response_parse(srv, con, p, hctx->response_header);
24112 - /* enable chunked-transfer-encoding */
24113 - if (con->request.http_version == HTTP_VERSION_1_1 &&
24114 - !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
24115 - con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
24118 - con->file_started = 1;
24120 - http_chunk_append_mem(srv, con, c + 4, blen + 1);
24121 - joblist_append(srv, con);
24123 - hctx->response->used = 0;
24126 - http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used);
24127 - joblist_append(srv, con);
24128 - hctx->response->used = 0;
24132 - /* reading from upstream done */
24133 - con->file_finished = 1;
24135 - http_chunk_append_mem(srv, con, NULL, 0);
24136 - joblist_append(srv, con);
24139 + next_queue = con->write_queue;
24141 + assert(hctx->state == PROXY_STATE_RESPONSE_CONTENT);
24143 + /* FIXME: if we have a content-length or chunked-encoding
24146 + * for now we wait for EOF on the socket */
24148 + /* copy the content to the next cq */
24149 + for (c = hctx->rb->first; c; c = c->next) {
24150 + http_chunk_append_mem(srv, con, c->mem->ptr + c->offset, c->mem->used - c->offset);
24152 + c->offset = c->mem->used - 1;
24157 + chunkqueue_remove_finished_chunks(hctx->rb);
24163 @@ -731,12 +680,12 @@
24164 data_proxy *host= hctx->host;
24165 plugin_data *p = hctx->plugin_data;
24166 connection *con = hctx->remote_conn;
24174 (!host->host->used || !host->port)) return -1;
24177 switch(hctx->state) {
24178 case PROXY_STATE_INIT:
24179 if (-1 == (hctx->fd = socket(AF_INET, SOCK_STREAM, 0))) {
24180 @@ -744,19 +693,19 @@
24181 return HANDLER_ERROR;
24183 hctx->fde_ndx = -1;
24189 fdevent_register(srv->ev, hctx->fd, proxy_handle_fdevent, hctx);
24192 if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
24193 log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno));
24196 return HANDLER_ERROR;
24203 case PROXY_STATE_CONNECT:
24204 /* try to finish the connect() */
24205 if (hctx->state == PROXY_STATE_INIT) {
24206 @@ -764,16 +713,16 @@
24207 switch (proxy_establish_connection(srv, hctx)) {
24209 proxy_set_state(srv, hctx, PROXY_STATE_CONNECT);
24212 /* connection is in progress, wait for an event and call getsockopt() below */
24215 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
24218 return HANDLER_WAIT_FOR_EVENT;
24220 /* if ECONNREFUSED choose another connection -> FIXME */
24221 hctx->fde_ndx = -1;
24224 return HANDLER_ERROR;
24226 /* everything is ok, go on */
24227 @@ -782,152 +731,152 @@
24230 socklen_t socket_error_len = sizeof(socket_error);
24232 - /* we don't need it anymore */
24234 + /* we don't need it anymore */
24235 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
24237 /* try to finish the connect() */
24238 if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
24239 - log_error_write(srv, __FILE__, __LINE__, "ss",
24240 + log_error_write(srv, __FILE__, __LINE__, "ss",
24241 "getsockopt failed:", strerror(errno));
24244 return HANDLER_ERROR;
24246 if (socket_error != 0) {
24247 log_error_write(srv, __FILE__, __LINE__, "ss",
24248 - "establishing connection failed:", strerror(socket_error),
24249 + "establishing connection failed:", strerror(socket_error),
24250 "port:", hctx->host->port);
24253 return HANDLER_ERROR;
24255 if (p->conf.debug) {
24256 - log_error_write(srv, __FILE__, __LINE__, "s", "proxy - connect - delayed success");
24257 + log_error_write(srv, __FILE__, __LINE__, "s", "proxy - connect - delayed success");
24259 + fprintf(stderr, "%s.%d: connected fd = %d\r\n", __FILE__, __LINE__, hctx->fd);
24263 proxy_set_state(srv, hctx, PROXY_STATE_PREPARE_WRITE);
24265 case PROXY_STATE_PREPARE_WRITE:
24266 proxy_create_env(srv, hctx);
24269 proxy_set_state(srv, hctx, PROXY_STATE_WRITE);
24273 case PROXY_STATE_WRITE:;
24274 - ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
24275 + ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
24277 chunkqueue_remove_finished_chunks(hctx->wb);
24280 - if (errno != EAGAIN &&
24281 - errno != EINTR) {
24282 - log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), errno);
24284 - return HANDLER_ERROR;
24286 - fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
24288 + case NETWORK_STATUS_FATAL_ERROR:
24289 + log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), errno);
24291 - return HANDLER_WAIT_FOR_EVENT;
24293 + return HANDLER_ERROR;
24294 + case NETWORK_STATUS_WAIT_FOR_EVENT:
24296 + fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
24298 + return HANDLER_WAIT_FOR_EVENT;
24301 if (hctx->wb->bytes_out == hctx->wb->bytes_in) {
24302 - proxy_set_state(srv, hctx, PROXY_STATE_READ);
24303 + proxy_set_state(srv, hctx, PROXY_STATE_RESPONSE_HEADER);
24305 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
24306 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
24308 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
24311 return HANDLER_WAIT_FOR_EVENT;
24315 return HANDLER_WAIT_FOR_EVENT;
24316 - case PROXY_STATE_READ:
24317 + case PROXY_STATE_RESPONSE_HEADER:
24318 /* waiting for a response */
24320 return HANDLER_WAIT_FOR_EVENT;
24322 log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state");
24323 return HANDLER_ERROR;
24327 return HANDLER_GO_ON;
24330 -#define PATCH(x) \
24331 - p->conf.x = s->x;
24332 static int mod_proxy_patch_connection(server *srv, connection *con, plugin_data *p) {
24334 plugin_config *s = p->config_storage[0];
24336 - PATCH(extensions);
24341 + PATCH_OPTION(extensions);
24342 + PATCH_OPTION(debug);
24343 + PATCH_OPTION(balance);
24344 + PATCH_OPTION(last_used_backends);
24346 /* skip the first, the global context */
24347 for (i = 1; i < srv->config_context->used; i++) {
24348 data_config *dc = (data_config *)srv->config_context->data[i];
24349 s = p->config_storage[i];
24352 /* condition didn't match */
24353 if (!config_check_cond(srv, con, dc)) continue;
24357 for (j = 0; j < dc->value->used; j++) {
24358 data_unset *du = dc->value->data[j];
24361 if (buffer_is_equal_string(du->key, CONST_STR_LEN("proxy.server"))) {
24362 - PATCH(extensions);
24363 + PATCH_OPTION(extensions);
24364 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("proxy.debug"))) {
24366 + PATCH_OPTION(debug);
24367 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("proxy.balance"))) {
24369 + PATCH_OPTION(balance);
24370 + PATCH_OPTION(last_used_backends);
24380 SUBREQUEST_FUNC(mod_proxy_handle_subrequest) {
24381 plugin_data *p = p_d;
24384 handler_ctx *hctx = con->plugin_ctx[p->id];
24388 if (NULL == hctx) return HANDLER_GO_ON;
24390 mod_proxy_patch_connection(srv, con, p);
24397 if (con->mode != p->id) return HANDLER_GO_ON;
24400 /* ok, create the request */
24401 switch(proxy_write_request(srv, hctx)) {
24402 case HANDLER_ERROR:
24403 - log_error_write(srv, __FILE__, __LINE__, "sbdd", "proxy-server disabled:",
24404 + log_error_write(srv, __FILE__, __LINE__, "sbdd", "proxy-server disabled:",
24410 /* disable this server */
24411 host->is_disabled = 1;
24412 host->disable_ts = srv->cur_ts;
24415 proxy_connection_close(srv, hctx);
24417 - /* reset the enviroment and restart the sub-request */
24419 + /* reset the enviroment and restart the sub-request */
24420 buffer_reset(con->physical.path);
24421 con->mode = DIRECT;
24423 joblist_append(srv, con);
24425 - /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
24426 - * and hope that the childs will be restarted
24428 + /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop
24429 + * and hope that the childs will be restarted
24433 return HANDLER_WAIT_FOR_FD;
24434 @@ -938,7 +887,7 @@
24440 if (con->file_started == 1) {
24441 return HANDLER_FINISHED;
24443 @@ -951,13 +900,14 @@
24444 handler_ctx *hctx = ctx;
24445 connection *con = hctx->remote_conn;
24446 plugin_data *p = hctx->plugin_data;
24451 if ((revents & FDEVENT_IN) &&
24452 - hctx->state == PROXY_STATE_READ) {
24453 + (hctx->state == PROXY_STATE_RESPONSE_HEADER ||
24454 + hctx->state == PROXY_STATE_RESPONSE_CONTENT)) {
24456 if (p->conf.debug) {
24457 - log_error_write(srv, __FILE__, __LINE__, "sd",
24458 + log_error_write(srv, __FILE__, __LINE__, "sd",
24459 "proxy: fdevent-in", hctx->state);
24462 @@ -966,10 +916,10 @@
24465 hctx->host->usage--;
24469 proxy_connection_close(srv, hctx);
24472 joblist_append(srv, con);
24473 return HANDLER_FINISHED;
24475 @@ -982,53 +932,53 @@
24476 /* response might have been already started, kill the connection */
24477 connection_set_state(srv, con, CON_STATE_ERROR);
24481 joblist_append(srv, con);
24482 return HANDLER_FINISHED;
24487 if (revents & FDEVENT_OUT) {
24488 if (p->conf.debug) {
24489 - log_error_write(srv, __FILE__, __LINE__, "sd",
24490 + log_error_write(srv, __FILE__, __LINE__, "sd",
24491 "proxy: fdevent-out", hctx->state);
24494 if (hctx->state == PROXY_STATE_CONNECT ||
24495 hctx->state == PROXY_STATE_WRITE) {
24496 /* we are allowed to send something out
24499 * 1. in a unfinished connect() call
24500 * 2. in a unfinished write() call (long POST request)
24502 return mod_proxy_handle_subrequest(srv, con, p);
24504 - log_error_write(srv, __FILE__, __LINE__, "sd",
24505 + log_error_write(srv, __FILE__, __LINE__, "sd",
24506 "proxy: out", hctx->state);
24511 /* perhaps this issue is already handled */
24512 if (revents & FDEVENT_HUP) {
24513 if (p->conf.debug) {
24514 - log_error_write(srv, __FILE__, __LINE__, "sd",
24515 + log_error_write(srv, __FILE__, __LINE__, "sd",
24516 "proxy: fdevent-hup", hctx->state);
24520 if (hctx->state == PROXY_STATE_CONNECT) {
24521 /* connect() -> EINPROGRESS -> HUP */
24525 - * what is proxy is doing if it can't reach the next hop ?
24527 + * what is proxy is doing if it can't reach the next hop ?
24532 proxy_connection_close(srv, hctx);
24533 joblist_append(srv, con);
24536 con->http_status = 503;
24537 con->mode = DIRECT;
24540 return HANDLER_FINISHED;
24543 @@ -1038,13 +988,13 @@
24544 joblist_append(srv, con);
24545 } else if (revents & FDEVENT_ERR) {
24546 /* kill all connections to the proxy process */
24549 log_error_write(srv, __FILE__, __LINE__, "sd", "proxy-FDEVENT_ERR, but no HUP", revents);
24551 joblist_append(srv, con);
24552 proxy_connection_close(srv, hctx);
24556 return HANDLER_FINISHED;
24559 @@ -1058,44 +1008,49 @@
24561 data_array *extension = NULL;
24562 size_t path_info_offset;
24564 + data_integer *last_used_backend;
24565 + data_proxy *host = NULL;
24566 + handler_ctx *hctx = NULL;
24568 + array *backends = NULL;
24570 /* Possibly, we processed already this request */
24571 if (con->file_started == 1) return HANDLER_GO_ON;
24574 mod_proxy_patch_connection(srv, con, p);
24577 fn = con->uri.path;
24579 if (fn->used == 0) {
24580 return HANDLER_ERROR;
24584 s_len = fn->used - 1;
24589 path_info_offset = 0;
24591 - if (p->conf.debug) {
24592 + if (p->conf.debug) {
24593 log_error_write(srv, __FILE__, __LINE__, "s", "proxy - start");
24596 /* check if extension matches */
24597 for (k = 0; k < p->conf.extensions->used; k++) {
24601 extension = (data_array *)p->conf.extensions->data[k];
24604 if (extension->key->used == 0) continue;
24607 ct_len = extension->key->used - 1;
24610 if (s_len < ct_len) continue;
24613 /* check extension in the form "/proxy_pattern" */
24614 if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
24615 if (s_len > ct_len + 1) {
24619 if (0 != (pi_offset = strchr(fn->ptr + ct_len + 1, '/'))) {
24620 path_info_offset = pi_offset - fn->ptr;
24622 @@ -1106,12 +1061,14 @@
24628 if (k == p->conf.extensions->used) {
24629 return HANDLER_GO_ON;
24632 - if (p->conf.debug) {
24633 + backends = extension->value;
24635 + if (p->conf.debug) {
24636 log_error_write(srv, __FILE__, __LINE__, "s", "proxy - ext found");
24639 @@ -1120,34 +1077,34 @@
24640 /* hash balancing */
24642 if (p->conf.debug) {
24643 - log_error_write(srv, __FILE__, __LINE__, "sd",
24644 - "proxy - used hash balancing, hosts:", extension->value->used);
24645 + log_error_write(srv, __FILE__, __LINE__, "sd",
24646 + "proxy - used hash balancing, hosts:", backends->used);
24649 - for (k = 0, ndx = -1, last_max = ULONG_MAX; k < extension->value->used; k++) {
24650 - data_proxy *host = (data_proxy *)extension->value->data[k];
24651 + for (k = 0, ndx = -1, last_max = ULONG_MAX; k < backends->used; k++) {
24652 unsigned long cur_max;
24654 - if (host->is_disabled) continue;
24656 + data_proxy *cur = (data_proxy *)backends->data[k];
24658 + if (cur->is_disabled) continue;
24660 cur_max = generate_crc32c(CONST_BUF_LEN(con->uri.path)) +
24661 - generate_crc32c(CONST_BUF_LEN(host->host)) + /* we can cache this */
24662 + generate_crc32c(CONST_BUF_LEN(cur->host)) + /* we can cache this */
24663 generate_crc32c(CONST_BUF_LEN(con->uri.authority));
24666 if (p->conf.debug) {
24667 - log_error_write(srv, __FILE__, __LINE__, "sbbbd",
24668 + log_error_write(srv, __FILE__, __LINE__, "sbbbd",
24669 "proxy - election:",
24673 con->uri.authority,
24677 - if ((last_max == ULONG_MAX) || /* first round */
24678 - (cur_max > last_max)) {
24679 + if (host == NULL || (cur_max > last_max)) {
24680 last_max = cur_max;
24687 @@ -1155,19 +1112,20 @@
24688 case PROXY_BALANCE_FAIR:
24689 /* fair balancing */
24690 if (p->conf.debug) {
24691 - log_error_write(srv, __FILE__, __LINE__, "s",
24692 + log_error_write(srv, __FILE__, __LINE__, "s",
24693 "proxy - used fair balancing");
24696 - for (k = 0, ndx = -1, max_usage = INT_MAX; k < extension->value->used; k++) {
24697 - data_proxy *host = (data_proxy *)extension->value->data[k];
24699 - if (host->is_disabled) continue;
24700 + /* try to find the host with the lowest load */
24701 + for (k = 0, max_usage = 0; k < backends->used; k++) {
24702 + data_proxy *cur = (data_proxy *)backends->data[k];
24704 - if (host->usage < max_usage) {
24705 - max_usage = host->usage;
24708 + if (cur->is_disabled) continue;
24710 + if (NULL == host || cur->usage < max_usage) {
24711 + max_usage = cur->usage;
24717 @@ -1175,89 +1133,100 @@
24718 case PROXY_BALANCE_RR:
24720 if (p->conf.debug) {
24721 - log_error_write(srv, __FILE__, __LINE__, "s",
24722 + log_error_write(srv, __FILE__, __LINE__, "s",
24723 "proxy - used round-robin balancing");
24726 /* just to be sure */
24727 - assert(extension->value->used < INT_MAX);
24729 - for (k = 0, ndx = -1, max_usage = INT_MAX; k < extension->value->used; k++) {
24730 - data_proxy *host = (data_proxy *)extension->value->data[k];
24732 - if (host->is_disabled) continue;
24733 + assert(backends->used < INT_MAX);
24735 - /* first usable ndx */
24736 - if (max_usage == INT_MAX) {
24739 + /* send each request to another host:
24743 + * if we have three hosts it is
24745 + * 1 .. 2 .. 3 .. 1 .. 2 .. 3
24749 - /* get next ndx */
24750 - if ((int)k > host->last_used_ndx) {
24752 - host->last_used_ndx = k;
24753 + /* walk through the list */
24754 + last_used_backend = (data_integer *)array_get_element(p->conf.last_used_backends, extension->key->ptr);
24758 + if (NULL == last_used_backend) {
24759 + last_used_backend = data_integer_init();
24761 + buffer_copy_string_buffer(last_used_backend->key, extension->key);
24762 + last_used_backend->value = 0;
24764 + array_insert_unique(p->conf.last_used_backends, (data_unset *)last_used_backend);
24767 - /* didn't found a higher id, wrap to the start */
24768 - if (ndx != -1 && max_usage != INT_MAX) {
24771 + /* scan all but the last host to see if they are up
24772 + * take the first running host */
24773 + for (k = last_used_backend->value + 1; (int)(k % backends->used) != last_used_backend->value; k++) {
24774 + data_proxy *cur = (data_proxy *)backends->data[k % backends->used];
24776 + if (cur->is_disabled) continue;
24780 + last_used_backend->value = k;
24785 + if (NULL == host) {
24786 + /* we found nothing better, fallback to the last used backend
24787 + * and check if it is still up */
24788 + host = (data_proxy *)backends->data[last_used_backend->value];
24790 + if (host->is_disabled) host = NULL;
24798 - /* found a server */
24800 - data_proxy *host = (data_proxy *)extension->value->data[ndx];
24803 - * if check-local is disabled, use the uri.path handler
24807 - /* init handler-context */
24808 - handler_ctx *hctx;
24809 - hctx = handler_ctx_init();
24811 - hctx->path_info_offset = path_info_offset;
24812 - hctx->remote_conn = con;
24813 - hctx->plugin_data = p;
24814 - hctx->host = host;
24816 - con->plugin_ctx[p->id] = hctx;
24820 - con->mode = p->id;
24822 - if (p->conf.debug) {
24823 - log_error_write(srv, __FILE__, __LINE__, "sbd",
24824 - "proxy - found a host",
24825 - host->host, host->port);
24828 - return HANDLER_GO_ON;
24830 - /* no handler found */
24831 + /* we havn't found a host */
24832 + if (NULL == host) {
24833 con->http_status = 500;
24835 - log_error_write(srv, __FILE__, __LINE__, "sb",
24836 - "no proxy-handler found for:",
24838 + log_error_write(srv, __FILE__, __LINE__, "sb",
24839 + "no proxy-handler found for:",
24843 return HANDLER_FINISHED;
24846 + /* init handler-context */
24847 + hctx = handler_ctx_init();
24849 + hctx->path_info_offset = path_info_offset;
24850 + hctx->remote_conn = con;
24851 + hctx->plugin_data = p;
24852 + hctx->host = host;
24854 + con->plugin_ctx[p->id] = hctx;
24858 + /* we handle this request */
24859 + con->mode = p->id;
24861 + if (p->conf.debug) {
24862 + log_error_write(srv, __FILE__, __LINE__, "sbd",
24863 + "proxy - found a host",
24864 + host->host, host->port);
24867 return HANDLER_GO_ON;
24870 static handler_t mod_proxy_connection_close_callback(server *srv, connection *con, void *p_d) {
24871 plugin_data *p = p_d;
24874 proxy_connection_close(srv, con->plugin_ctx[p->id]);
24876 return HANDLER_GO_ON;
24877 @@ -1276,11 +1245,11 @@
24879 for (i = 0; i < srv->config_context->used; i++) {
24880 plugin_config *s = p->config_storage[i];
24882 - if (!s) continue;
24884 + if (!s) continue;
24886 /* get the extensions for all configs */
24889 for (k = 0; k < s->extensions->used; k++) {
24890 data_array *extension = (data_array *)s->extensions->data[k];
24892 @@ -1290,8 +1259,8 @@
24894 if (!host->is_disabled ||
24895 srv->cur_ts - host->disable_ts < 5) continue;
24897 - log_error_write(srv, __FILE__, __LINE__, "sbd",
24899 + log_error_write(srv, __FILE__, __LINE__, "sbd",
24900 "proxy - re-enabled:",
24901 host->host, host->port);
24903 @@ -1317,8 +1286,8 @@
24904 p->handle_uri_clean = mod_proxy_check_extension;
24905 p->handle_subrequest = mod_proxy_handle_subrequest;
24906 p->handle_trigger = mod_proxy_trigger;
24915 Property changes on: src/mod_proxy.c
24916 ___________________________________________________________________
24917 Name: svn:eol-style
24920 Index: src/Makefile.am
24921 ===================================================================
24922 --- src/Makefile.am (.../tags/lighttpd-1.4.11) (revision 1159)
24923 +++ src/Makefile.am (.../branches/lighttpd-merge-1.4.x) (revision 1159)
24924 @@ -16,14 +16,19 @@
24926 configparser.y: lemon
24927 mod_ssi_exprparser.y: lemon
24928 +http_resp_parser.y: lemon
24930 configparser.c configparser.h: configparser.y
24931 rm -f configparser.h
24932 - $(LEMON) -q $(srcdir)/configparser.y $(srcdir)/lempar.c
24933 + $(LEMON) -q $(srcdir)/$< $(srcdir)/lempar.c
24935 +http_resp_parser.c http_resp_parser.h: http_resp_parser.y
24936 + rm -f http_resp_parser.h
24937 + $(LEMON) -q $(srcdir)/$< $(srcdir)/lempar.c
24939 mod_ssi_exprparser.c mod_ssi_exprparser.h: mod_ssi_exprparser.y
24940 rm -f mod_ssi_exprparser.h
24941 - $(LEMON) -q $(srcdir)/mod_ssi_exprparser.y $(srcdir)/lempar.c
24942 + $(LEMON) -q $(srcdir)/$< $(srcdir)/lempar.c
24945 configfile.c: configparser.h
24947 network_write.c network_linux_sendfile.c \
24948 network_freebsd_sendfile.c network_writev.c \
24949 network_solaris_sendfilev.c network_openssl.c \
24951 + splaytree.c http_resp.c http_resp_parser.c
24953 src = server.c response.c connections.c network.c \
24954 configfile.c configparser.c request.c proc_open.c
24957 lib_LTLIBRARIES += mod_webdav.la
24958 mod_webdav_la_SOURCES = mod_webdav.c
24959 -mod_webdav_la_CFLAGS = $(AM_CFLAGS) $(XML_CFLAGS) $(SQLITE_CFLAGS)
24960 +mod_webdav_la_CFLAGS = $(AM_CFLAGS) $(XML_CFLAGS) $(SQLITE_CFLAGS)
24961 mod_webdav_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
24962 -mod_webdav_la_LIBADD = $(common_libadd) $(XML_LIBS) $(SQLITE_LIBS)
24963 +mod_webdav_la_LIBADD = $(common_libadd) $(XML_LIBS) $(SQLITE_LIBS) $(UUID_LIB)
24965 lib_LTLIBRARIES += mod_cml.la
24966 mod_cml_la_SOURCES = mod_cml.c mod_cml_lua.c mod_cml_funcs.c
24967 @@ -103,6 +108,11 @@
24968 mod_mysql_vhost_la_LIBADD = $(MYSQL_LIBS) $(common_libadd)
24969 mod_mysql_vhost_la_CPPFLAGS = $(MYSQL_INCLUDE)
24971 +lib_LTLIBRARIES += mod_sql_vhost_core.la
24972 +mod_sql_vhost_core_la_SOURCES = mod_sql_vhost_core.c
24973 +mod_sql_vhost_core_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
24974 +mod_sql_vhost_core_la_LIBADD = $(common_libadd)
24976 lib_LTLIBRARIES += mod_cgi.la
24977 mod_cgi_la_SOURCES = mod_cgi.c
24978 mod_cgi_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
24979 @@ -240,7 +250,7 @@
24980 mod_ssi.h mod_ssi_expr.h inet_ntop_cache.h \
24981 configparser.h mod_ssi_exprparser.h \
24982 sys-mmap.h sys-socket.h mod_cml.h mod_cml_funcs.h \
24983 - splaytree.h proc_open.h
24984 + splaytree.h proc_open.h http_resp.h mod_sql_vhost_core.h
24986 DEFS= @DEFS@ -DLIBRARY_DIR="\"$(libdir)\""
24989 Property changes on: src/Makefile.am
24990 ___________________________________________________________________
24991 Name: svn:eol-style
24994 Index: src/network_writev.c
24995 ===================================================================
24996 --- src/network_writev.c (.../tags/lighttpd-1.4.11) (revision 1159)
24997 +++ src/network_writev.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
24998 @@ -28,10 +28,10 @@
25001 # if defined(__FreeBSD__) || defined(__APPLE__) || defined(__NetBSD__)
25002 -/* FreeBSD 4.7 defines it in sys/uio.h only if _KERNEL is specified */
25003 +/* FreeBSD 4.7 defines it in sys/uio.h only if _KERNEL is specified */
25004 # define UIO_MAXIOV 1024
25005 # elif defined(__sgi)
25006 -/* IRIX 6.5 has sysconf(_SC_IOV_MAX) which might return 512 or bigger */
25007 +/* IRIX 6.5 has sysconf(_SC_IOV_MAX) which might return 512 or bigger */
25008 # define UIO_MAXIOV 512
25009 # elif defined(__sun)
25010 /* Solaris (and SunOS?) defines IOV_MAX instead */
25011 @@ -51,105 +51,119 @@
25012 #define LOCAL_BUFFERING 1
25015 -int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkqueue *cq) {
25017 +NETWORK_BACKEND_WRITE_CHUNK(writev_mem) {
25022 + size_t num_chunks, i;
25023 + struct iovec chunks[UIO_MAXIOV];
25024 + chunk *tc; /* transfer chunks */
25025 + size_t num_bytes = 0;
25027 + /* we can't send more then SSIZE_MAX bytes in one chunk */
25029 + /* build writev list
25031 + * 1. limit: num_chunks < UIO_MAXIOV
25032 + * 2. limit: num_bytes < SSIZE_MAX
25034 + for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
25036 + for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
25037 + if (tc->mem->used == 0) {
25038 + chunks[i].iov_base = tc->mem->ptr;
25039 + chunks[i].iov_len = 0;
25041 + offset = tc->mem->ptr + tc->offset;
25042 + toSend = tc->mem->used - 1 - tc->offset;
25044 + chunks[i].iov_base = offset;
25046 + /* protect the return value of writev() */
25047 + if (toSend > SSIZE_MAX ||
25048 + num_bytes + toSend > SSIZE_MAX) {
25049 + chunks[i].iov_len = SSIZE_MAX - num_bytes;
25051 + num_chunks = i + 1;
25054 + chunks[i].iov_len = toSend;
25057 + num_bytes += toSend;
25061 + if ((r = writev(fd, chunks, num_chunks)) < 0) {
25069 + return NETWORK_STATUS_CONNECTION_CLOSE;
25071 + log_error_write(srv, __FILE__, __LINE__, "ssd",
25072 + "writev failed:", strerror(errno), fd);
25074 + return NETWORK_STATUS_FATAL_ERROR;
25078 + cq->bytes_out += r;
25080 + /* check which chunks have been written */
25082 + for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
25083 + if (r >= (ssize_t)chunks[i].iov_len) {
25085 + r -= chunks[i].iov_len;
25086 + tc->offset += chunks[i].iov_len;
25088 + /* partially written */
25095 + return NETWORK_STATUS_SUCCESS;
25098 +NETWORK_BACKEND_WRITE(writev) {
25100 size_t chunks_written = 0;
25103 for(c = cq->first; c; c = c->next) {
25104 int chunk_finished = 0;
25106 + network_status_t ret;
25109 - case MEM_CHUNK: {
25114 - size_t num_chunks, i;
25115 - struct iovec chunks[UIO_MAXIOV];
25117 - size_t num_bytes = 0;
25119 - /* we can't send more then SSIZE_MAX bytes in one chunk */
25121 - /* build writev list
25123 - * 1. limit: num_chunks < UIO_MAXIOV
25124 - * 2. limit: num_bytes < SSIZE_MAX
25126 - for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
25128 - for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
25129 - if (tc->mem->used == 0) {
25130 - chunks[i].iov_base = tc->mem->ptr;
25131 - chunks[i].iov_len = 0;
25133 - offset = tc->mem->ptr + tc->offset;
25134 - toSend = tc->mem->used - 1 - tc->offset;
25136 - chunks[i].iov_base = offset;
25138 - /* protect the return value of writev() */
25139 - if (toSend > SSIZE_MAX ||
25140 - num_bytes + toSend > SSIZE_MAX) {
25141 - chunks[i].iov_len = SSIZE_MAX - num_bytes;
25143 - num_chunks = i + 1;
25146 - chunks[i].iov_len = toSend;
25149 - num_bytes += toSend;
25153 - if ((r = writev(fd, chunks, num_chunks)) < 0) {
25163 - log_error_write(srv, __FILE__, __LINE__, "ssd",
25164 - "writev failed:", strerror(errno), fd);
25170 - cq->bytes_out += r;
25172 + ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, c);
25174 - /* check which chunks have been written */
25176 - for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
25177 - if (r >= (ssize_t)chunks[i].iov_len) {
25179 - r -= chunks[i].iov_len;
25180 - tc->offset += chunks[i].iov_len;
25182 + /* check which chunks are finished now */
25183 + for (tc = c; tc; tc = tc->next) {
25184 + /* finished the chunk */
25185 + if (tc->offset == tc->mem->used - 1) {
25186 + /* skip the first c->next as that will be done by the c = c->next in the other for()-loop */
25187 if (chunk_finished) {
25188 - /* skip the chunks from further touches */
25189 - chunks_written++;
25192 - /* chunks_written + c = c->next is done in the for()*/
25193 - chunk_finished++;
25194 + chunk_finished = 1;
25197 - /* partially written */
25200 - chunk_finished = 0;
25207 + if (ret != NETWORK_STATUS_SUCCESS) {
25216 @@ -159,26 +173,26 @@
25217 #define KByte * 1024
25218 #define MByte * 1024 KByte
25219 #define GByte * 1024 MByte
25220 - const off_t we_want_to_mmap = 512 KByte;
25221 + const off_t we_want_to_mmap = 512 KByte;
25222 char *start = NULL;
25224 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
25225 log_error_write(srv, __FILE__, __LINE__, "sb",
25226 strerror(errno), c->file.name);
25228 + return NETWORK_STATUS_FATAL_ERROR;
25231 abs_offset = c->file.start + c->offset;
25234 if (abs_offset > sce->st.st_size) {
25235 - log_error_write(srv, __FILE__, __LINE__, "sb",
25236 + log_error_write(srv, __FILE__, __LINE__, "sb",
25237 "file was shrinked:", c->file.name);
25241 + return NETWORK_STATUS_FATAL_ERROR;
25244 - /* mmap the buffer
25246 + /* mmap the buffer
25248 * - new mmap as the we are at the end of the last one */
25249 if (c->file.mmap.start == MAP_FAILED ||
25250 abs_offset == (off_t)(c->file.mmap.offset + c->file.mmap.length)) {
25251 @@ -188,7 +202,7 @@
25252 * adaptive mem-mapping
25254 * we mmap() the whole file. If someone has alot large files and 32bit
25255 - * machine the virtual address area will be unrun and we will have a failing
25256 + * machine the virtual address area will be unrun and we will have a failing
25259 * only mmap 16M in one chunk and move the window as soon as we have finished
25260 @@ -234,8 +248,8 @@
25261 if (-1 == c->file.fd) { /* open the file if not already open */
25262 if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
25263 log_error_write(srv, __FILE__, __LINE__, "sbs", "open failed for:", c->file.name, strerror(errno));
25267 + return NETWORK_STATUS_FATAL_ERROR;
25270 fcntl(c->file.fd, F_SETFD, FD_CLOEXEC);
25271 @@ -245,10 +259,10 @@
25272 if (MAP_FAILED == (c->file.mmap.start = mmap(0, to_mmap, PROT_READ, MAP_SHARED, c->file.fd, c->file.mmap.offset))) {
25273 /* close it here, otherwise we'd have to set FD_CLOEXEC */
25275 - log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed:",
25276 + log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed:",
25277 strerror(errno), c->file.name, c->file.fd);
25280 + return NETWORK_STATUS_FATAL_ERROR;
25283 c->file.mmap.length = to_mmap;
25284 @@ -258,7 +272,7 @@
25285 #ifdef HAVE_MADVISE
25286 /* don't advise files < 64Kb */
25287 if (c->file.mmap.length > (64 KByte)) {
25288 - /* darwin 7 is returning EINVAL all the time and I don't know how to
25289 + /* darwin 7 is returning EINVAL all the time and I don't know how to
25290 * detect this at runtime.i
25292 * ignore the return value for now */
25293 @@ -274,12 +288,12 @@
25294 toSend = (c->file.mmap.offset + c->file.mmap.length) - (abs_offset);
25297 - log_error_write(srv, __FILE__, __LINE__, "soooo",
25298 + log_error_write(srv, __FILE__, __LINE__, "soooo",
25299 "toSend is negative:",
25301 c->file.mmap.length,
25303 - c->file.mmap.offset);
25304 + c->file.mmap.offset);
25305 assert(toSend < 0);
25308 @@ -297,18 +311,18 @@
25313 + return NETWORK_STATUS_CONNECTION_CLOSE;
25315 - log_error_write(srv, __FILE__, __LINE__, "ssd",
25316 + log_error_write(srv, __FILE__, __LINE__, "ssd",
25317 "write failed:", strerror(errno), fd);
25321 + return NETWORK_STATUS_FATAL_ERROR;
25327 cq->bytes_out += r;
25330 if (c->offset == c->file.length) {
25331 chunk_finished = 1;
25333 @@ -318,26 +332,26 @@
25334 c->file.mmap.start = MAP_FAILED;
25344 log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
25348 + return NETWORK_STATUS_FATAL_ERROR;
25352 if (!chunk_finished) {
25353 /* not finished yet */
25363 - return chunks_written;
25364 + return NETWORK_STATUS_SUCCESS;
25369 Property changes on: src/network_writev.c
25370 ___________________________________________________________________
25371 Name: svn:eol-style
25374 Index: src/mod_expire.c
25375 ===================================================================
25376 --- src/mod_expire.c (.../tags/lighttpd-1.4.11) (revision 1159)
25377 +++ src/mod_expire.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
25379 #include "stat_cache.h"
25382 - * this is a expire module for a lighttpd
25384 + * this is a expire module for a lighttpd
25386 * set 'Expires:' HTTP Headers on demand
25389 @@ -27,51 +27,51 @@
25395 buffer *expire_tstmp;
25398 plugin_config **config_storage;
25400 - plugin_config conf;
25402 + plugin_config conf;
25405 /* init the plugin data */
25406 INIT_FUNC(mod_expire_init) {
25410 p = calloc(1, sizeof(*p));
25413 p->expire_tstmp = buffer_init();
25416 buffer_prepare_copy(p->expire_tstmp, 255);
25422 /* detroy the plugin data */
25423 FREE_FUNC(mod_expire_free) {
25424 plugin_data *p = p_d;
25429 if (!p) return HANDLER_GO_ON;
25432 buffer_free(p->expire_tstmp);
25435 if (p->config_storage) {
25437 for (i = 0; i < srv->config_context->used; i++) {
25438 plugin_config *s = p->config_storage[i];
25441 array_free(s->expire_url);
25446 free(p->config_storage);
25453 return HANDLER_GO_ON;
25456 @@ -79,25 +79,25 @@
25469 * '(access|modification) [plus] {<num> <type>}*'
25472 * e.g. 'access 1 years'
25476 if (expire->used == 0) {
25477 - log_error_write(srv, __FILE__, __LINE__, "s",
25478 + log_error_write(srv, __FILE__, __LINE__, "s",
25487 if (0 == strncmp(ts, "access ", 7)) {
25490 @@ -110,39 +110,39 @@
25491 "invalid <base>:", ts);
25496 if (0 == strncmp(ts, "plus ", 5)) {
25497 /* skip the optional plus */
25502 /* the rest is just <number> (years|months|days|hours|minutes|seconds) */
25508 if (NULL == (space = strchr(ts, ' '))) {
25509 - log_error_write(srv, __FILE__, __LINE__, "ss",
25510 + log_error_write(srv, __FILE__, __LINE__, "ss",
25511 "missing space after <num>:", ts);
25516 num = strtol(ts, &err, 10);
25518 - log_error_write(srv, __FILE__, __LINE__, "ss",
25519 + log_error_write(srv, __FILE__, __LINE__, "ss",
25520 "missing <type> after <num>:", ts);
25528 if (NULL != (space = strchr(ts, ' '))) {
25538 0 == strncmp(ts, "years", slen)) {
25539 num *= 60 * 60 * 24 * 30 * 12;
25540 } else if (slen == 6 &&
25541 @@ -161,13 +161,13 @@
25542 0 == strncmp(ts, "seconds", slen)) {
25545 - log_error_write(srv, __FILE__, __LINE__, "ss",
25546 + log_error_write(srv, __FILE__, __LINE__, "ss",
25547 "unknown type:", ts);
25557 if (0 == strcmp(ts, "years")) {
25558 @@ -183,19 +183,19 @@
25559 } else if (0 == strcmp(ts, "seconds")) {
25562 - log_error_write(srv, __FILE__, __LINE__, "ss",
25563 + log_error_write(srv, __FILE__, __LINE__, "ss",
25564 "unknown type:", ts);
25577 if (offset != NULL) *offset = retts;
25583 @@ -205,102 +205,99 @@
25584 SETDEFAULTS_FUNC(mod_expire_set_defaults) {
25585 plugin_data *p = p_d;
25588 - config_values_t cv[] = {
25590 + config_values_t cv[] = {
25591 { "expire.url", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
25592 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
25596 if (!p) return HANDLER_ERROR;
25599 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
25602 for (i = 0; i < srv->config_context->used; i++) {
25606 s = calloc(1, sizeof(plugin_config));
25607 s->expire_url = array_init();
25610 cv[0].destination = s->expire_url;
25613 p->config_storage[i] = s;
25616 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
25617 return HANDLER_ERROR;
25621 for (k = 0; k < s->expire_url->used; k++) {
25622 data_string *ds = (data_string *)s->expire_url->data[k];
25626 if (-1 == mod_expire_get_offset(srv, p, ds->value, NULL)) {
25627 - log_error_write(srv, __FILE__, __LINE__, "sb",
25628 + log_error_write(srv, __FILE__, __LINE__, "sb",
25629 "parsing expire.url failed:", ds->value);
25630 return HANDLER_ERROR;
25638 return HANDLER_GO_ON;
25641 -#define PATCH(x) \
25642 - p->conf.x = s->x;
25643 static int mod_expire_patch_connection(server *srv, connection *con, plugin_data *p) {
25645 plugin_config *s = p->config_storage[0];
25647 - PATCH(expire_url);
25650 + PATCH_OPTION(expire_url);
25652 /* skip the first, the global context */
25653 for (i = 1; i < srv->config_context->used; i++) {
25654 data_config *dc = (data_config *)srv->config_context->data[i];
25655 s = p->config_storage[i];
25658 /* condition didn't match */
25659 if (!config_check_cond(srv, con, dc)) continue;
25663 for (j = 0; j < dc->value->used; j++) {
25664 data_unset *du = dc->value->data[j];
25667 if (buffer_is_equal_string(du->key, CONST_STR_LEN("expire.url"))) {
25668 - PATCH(expire_url);
25669 + PATCH_OPTION(expire_url);
25679 URIHANDLER_FUNC(mod_expire_path_handler) {
25680 plugin_data *p = p_d;
25685 if (con->uri.path->used == 0) return HANDLER_GO_ON;
25688 mod_expire_patch_connection(srv, con, p);
25691 s_len = con->uri.path->used - 1;
25694 for (k = 0; k < p->conf.expire_url->used; k++) {
25695 data_string *ds = (data_string *)p->conf.expire_url->data[k];
25696 int ct_len = ds->key->used - 1;
25699 if (ct_len > s_len) continue;
25700 if (ds->key->used == 0) continue;
25703 if (0 == strncmp(con->uri.path->ptr, ds->key->ptr, ct_len)) {
25707 stat_cache_entry *sce = NULL;
25710 stat_cache_get_entry(srv, con, con->physical.path, &sce);
25713 switch(mod_expire_get_offset(srv, p, ds->value, &ts)) {
25716 @@ -308,38 +305,38 @@
25722 t = (ts + sce->st.st_mtime);
25725 /* -1 is handled at parse-time */
25730 - if (0 == (len = strftime(p->expire_tstmp->ptr, p->expire_tstmp->size - 1,
25733 + if (0 == (len = strftime(p->expire_tstmp->ptr, p->expire_tstmp->size - 1,
25734 "%a, %d %b %Y %H:%M:%S GMT", gmtime(&(t))))) {
25735 /* could not set expire header, out of mem */
25738 return HANDLER_GO_ON;
25744 p->expire_tstmp->used = len + 1;
25749 response_header_overwrite(srv, con, CONST_STR_LEN("Expires"), CONST_BUF_LEN(p->expire_tstmp));
25753 buffer_copy_string(p->expire_tstmp, "max-age=");
25754 buffer_append_long(p->expire_tstmp, ts);
25757 response_header_overwrite(srv, con, CONST_STR_LEN("Cache-Control"), CONST_BUF_LEN(p->expire_tstmp));
25760 return HANDLER_GO_ON;
25766 return HANDLER_GO_ON;
25768 @@ -349,13 +346,13 @@
25769 int mod_expire_plugin_init(plugin *p) {
25770 p->version = LIGHTTPD_VERSION_ID;
25771 p->name = buffer_init_string("expire");
25774 p->init = mod_expire_init;
25775 p->handle_subrequest_start = mod_expire_path_handler;
25776 p->set_defaults = mod_expire_set_defaults;
25777 p->cleanup = mod_expire_free;
25786 Property changes on: src/mod_expire.c
25787 ___________________________________________________________________
25788 Name: svn:eol-style
25791 Index: src/network_openssl.c
25792 ===================================================================
25793 --- src/network_openssl.c (.../tags/lighttpd-1.4.11) (revision 1159)
25794 +++ src/network_openssl.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
25795 @@ -23,17 +23,87 @@
25797 #include "stat_cache.h"
25799 -# include <openssl/ssl.h>
25800 -# include <openssl/err.h>
25801 +# include <openssl/ssl.h>
25802 +# include <openssl/err.h>
25804 -int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chunkqueue *cq) {
25805 +NETWORK_BACKEND_READ_SSL(openssl) {
25809 + b = chunkqueue_get_append_buffer(cq);
25810 + buffer_prepare_copy(b, 8192);
25811 + len = SSL_read(ssl, b->ptr, b->size - 1);
25813 + log_error_write(srv, __FILE__, __LINE__, "so", "SSL:", len);
25818 + switch ((r = SSL_get_error(con->ssl, len))) {
25819 + case SSL_ERROR_WANT_READ:
25820 + return NETWORK_STATUS_WAIT_FOR_EVENT;
25821 + case SSL_ERROR_SYSCALL:
25823 + * man SSL_get_error()
25825 + * SSL_ERROR_SYSCALL
25826 + * Some I/O error occurred. The OpenSSL error queue may contain more
25827 + * information on the error. If the error queue is empty (i.e.
25828 + * ERR_get_error() returns 0), ret can be used to find out more about
25829 + * the error: If ret == 0, an EOF was observed that violates the
25830 + * protocol. If ret == -1, the underlying BIO reported an I/O error
25831 + * (for socket I/O on Unix systems, consult errno for details).
25834 + while((ssl_err = ERR_get_error())) {
25835 + /* get all errors from the error-queue */
25836 + log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
25837 + r, ERR_error_string(ssl_err, NULL));
25842 + log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
25844 + strerror(errno));
25849 + case SSL_ERROR_ZERO_RETURN:
25850 + /* clean shutdown on the remote side */
25853 + /* FIXME: later */
25856 + /* fall thourgh */
25858 + while((ssl_err = ERR_get_error())) {
25859 + /* get all errors from the error-queue */
25860 + log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:",
25861 + r, ERR_error_string(ssl_err, NULL));
25869 + b->ptr[b->used - 1] = '\0';
25871 + return NETWORK_STATUS_SUCCESS;
25875 +NETWORK_BACKEND_WRITE_SSL(openssl) {
25878 size_t chunks_written = 0;
25880 /* this is a 64k sendbuffer
25882 - * it has to stay at the same location all the time to satisfy the needs
25883 + * it has to stay at the same location all the time to satisfy the needs
25884 * of SSL_write to pass the SAME parameter in case of a _WANT_WRITE
25886 * the buffer is allocated once, is NOT realloced and is NOT freed at shutdown
25887 @@ -43,14 +113,14 @@
25888 * In reality we would like to use mmap() but we don't have a guarantee that
25889 * we get the same mmap() address for each call. On openbsd the mmap() address
25891 - * That means either we keep the mmap() open or we do a read() into a
25892 - * constant buffer
25893 + * That means either we keep the mmap() open or we do a read() into a
25894 + * constant buffer
25896 #define LOCAL_SEND_BUFSIZE (64 * 1024)
25897 static char *local_send_buffer = NULL;
25899 /* the remote side closed the connection before without shutdown request
25903 * if keep-alive is disabled */
25905 @@ -60,32 +130,34 @@
25907 for(c = cq->first; c; c = c->next) {
25908 int chunk_finished = 0;
25919 if (c->mem->used == 0) {
25920 chunk_finished = 1;
25925 offset = c->mem->ptr + c->offset;
25926 toSend = c->mem->used - 1 - c->offset;
25930 * SSL_write man-page
25934 * When an SSL_write() operation has to be repeated because of
25935 * SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, it must be
25936 * repeated with the same arguments.
25939 + * SSL_write(..., 0) return 0 which is handle as an error (Success)
25940 + * checking toSend and not calling SSL_write() is simpler
25943 - if ((r = SSL_write(ssl, offset, toSend)) <= 0) {
25945 + if (toSend != 0 && (r = SSL_write(ssl, offset, toSend)) <= 0) {
25948 switch ((ssl_r = SSL_get_error(ssl, r))) {
25950 /* perhaps we have error waiting in our error-queue */
25951 if (0 != (err = ERR_get_error())) {
25953 - log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
25954 + log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
25956 ERR_error_string(err, NULL));
25957 } while((err = ERR_get_error()));
25958 @@ -105,43 +177,43 @@
25962 - log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
25963 + log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
25969 /* neither error-queue nor errno ? */
25970 - log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
25971 + log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
25978 case SSL_ERROR_ZERO_RETURN:
25979 /* clean shutdown on the remote side */
25982 if (r == 0) return -2;
25987 while((err = ERR_get_error())) {
25988 - log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
25989 + log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
25991 ERR_error_string(err, NULL));
25999 cq->bytes_out += r;
26003 if (c->offset == (off_t)c->mem->used - 1) {
26004 chunk_finished = 1;
26011 @@ -150,7 +222,7 @@
26012 stat_cache_entry *sce = NULL;
26014 int write_wait = 0;
26017 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
26018 log_error_write(srv, __FILE__, __LINE__, "sb",
26019 strerror(errno), c->file.name);
26020 @@ -164,13 +236,13 @@
26023 off_t offset = c->file.start + c->offset;
26024 - off_t toSend = c->file.length - c->offset;
26025 + off_t toSend = c->file.length - c->offset;
26027 if (toSend > LOCAL_SEND_BUFSIZE) toSend = LOCAL_SEND_BUFSIZE;
26030 if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
26031 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed:", strerror(errno));
26037 @@ -183,9 +255,9 @@
26040 s = local_send_buffer;
26046 if ((r = SSL_write(ssl, s, toSend)) <= 0) {
26049 @@ -197,7 +269,7 @@
26050 /* perhaps we have error waiting in our error-queue */
26051 if (0 != (err = ERR_get_error())) {
26053 - log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
26054 + log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
26056 ERR_error_string(err, NULL));
26057 } while((err = ERR_get_error()));
26058 @@ -207,58 +279,58 @@
26062 - log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
26063 + log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:",
26069 /* neither error-queue nor errno ? */
26070 - log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
26071 + log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):",
26078 case SSL_ERROR_ZERO_RETURN:
26079 /* clean shutdown on the remote side */
26082 if (r == 0) return -2;
26087 while((err = ERR_get_error())) {
26088 - log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
26089 + log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:",
26091 ERR_error_string(err, NULL));
26099 cq->bytes_out += r;
26103 if (c->offset == c->file.length) {
26104 chunk_finished = 1;
26106 } while(!chunk_finished && !write_wait);
26112 log_error_write(srv, __FILE__, __LINE__, "s", "type not known");
26119 if (!chunk_finished) {
26120 /* not finished yet */
26131 Property changes on: src/network_openssl.c
26132 ___________________________________________________________________
26133 Name: svn:eol-style
26136 Index: src/network_freebsd_sendfile.c
26137 ===================================================================
26138 --- src/network_freebsd_sendfile.c (.../tags/lighttpd-1.4.11) (revision 1159)
26139 +++ src/network_freebsd_sendfile.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
26140 @@ -26,142 +26,61 @@
26143 # ifdef __FreeBSD__
26144 -/* FreeBSD 4.7, 4.9 defined it in sys/uio.h only if _KERNEL is specified */
26145 +/* FreeBSD 4.7, 4.9 defined it in sys/uio.h only if _KERNEL is specified */
26146 # define UIO_MAXIOV 1024
26150 -int network_write_chunkqueue_freebsdsendfile(server *srv, connection *con, int fd, chunkqueue *cq) {
26151 +NETWORK_BACKEND_WRITE(freebsdsendfile) {
26153 size_t chunks_written = 0;
26156 for(c = cq->first; c; c = c->next, chunks_written++) {
26157 int chunk_finished = 0;
26159 + network_status_t ret;
26162 - case MEM_CHUNK: {
26167 - size_t num_chunks, i;
26168 - struct iovec chunks[UIO_MAXIOV];
26170 - size_t num_bytes = 0;
26172 - /* we can't send more then SSIZE_MAX bytes in one chunk */
26174 - /* build writev list
26176 - * 1. limit: num_chunks < UIO_MAXIOV
26177 - * 2. limit: num_bytes < SSIZE_MAX
26179 - for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
26181 - for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
26182 - if (tc->mem->used == 0) {
26183 - chunks[i].iov_base = tc->mem->ptr;
26184 - chunks[i].iov_len = 0;
26186 - offset = tc->mem->ptr + tc->offset;
26187 - toSend = tc->mem->used - 1 - tc->offset;
26189 - chunks[i].iov_base = offset;
26191 - /* protect the return value of writev() */
26192 - if (toSend > SSIZE_MAX ||
26193 - num_bytes + toSend > SSIZE_MAX) {
26194 - chunks[i].iov_len = SSIZE_MAX - num_bytes;
26196 - num_chunks = i + 1;
26199 - chunks[i].iov_len = toSend;
26202 - num_bytes += toSend;
26206 - if ((r = writev(fd, chunks, num_chunks)) < 0) {
26216 - log_error_write(srv, __FILE__, __LINE__, "ssd",
26217 - "writev failed:", strerror(errno), fd);
26222 + ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, &c);
26225 + if (ret != NETWORK_STATUS_SUCCESS) {
26229 - /* check which chunks have been written */
26230 - cq->bytes_out += r;
26232 - for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
26233 - if (r >= (ssize_t)chunks[i].iov_len) {
26235 - r -= chunks[i].iov_len;
26236 - tc->offset += chunks[i].iov_len;
26238 - if (chunk_finished) {
26239 - /* skip the chunks from further touches */
26240 - chunks_written++;
26243 - /* chunks_written + c = c->next is done in the for()*/
26244 - chunk_finished++;
26247 - /* partially written */
26250 - chunk_finished = 0;
26257 + chunk_finished = 1;
26264 stat_cache_entry *sce = NULL;
26268 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
26269 log_error_write(srv, __FILE__, __LINE__, "sb",
26270 strerror(errno), c->file.name);
26272 + return NETWORK_STATUS_FATAL_ERROR;
26276 offset = c->file.start + c->offset;
26277 /* limit the toSend to 2^31-1 bytes in a chunk */
26278 - toSend = c->file.length - c->offset > ((1 << 30) - 1) ?
26279 + toSend = c->file.length - c->offset > ((1 << 30) - 1) ?
26280 ((1 << 30) - 1) : c->file.length - c->offset;
26283 if (offset > sce->st.st_size) {
26284 log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
26288 + return NETWORK_STATUS_FATAL_ERROR;
26292 if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
26293 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
26297 + return NETWORK_STATUS_FATAL_ERROR;
26304 /* FreeBSD sendfile() */
26305 if (-1 == sendfile(ifd, fd, offset, toSend, NULL, &r, 0)) {
26307 @@ -169,39 +88,39 @@
26312 + return NETWORK_STATUS_CONNECTION_CLOSE;
26314 log_error_write(srv, __FILE__, __LINE__, "ssd", "sendfile: ", strerror(errno), errno);
26317 + return NETWORK_STATUS_FATAL_ERROR;
26324 cq->bytes_out += r;
26327 if (c->offset == c->file.length) {
26328 chunk_finished = 1;
26337 log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
26344 if (!chunk_finished) {
26345 /* not finished yet */
26352 - return chunks_written;
26353 + return NETWORK_STATUS_SUCCESS;
26358 Property changes on: src/network_freebsd_sendfile.c
26359 ___________________________________________________________________
26360 Name: svn:eol-style
26364 Property changes on: src/http_auth_digest.c
26365 ___________________________________________________________________
26366 Name: svn:eol-style
26369 Index: src/mod_redirect.c
26370 ===================================================================
26371 --- src/mod_redirect.c (.../tags/lighttpd-1.4.11) (revision 1159)
26372 +++ src/mod_redirect.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
26373 @@ -22,35 +22,35 @@
26379 plugin_config **config_storage;
26381 - plugin_config conf;
26383 + plugin_config conf;
26386 INIT_FUNC(mod_redirect_init) {
26390 p = calloc(1, sizeof(*p));
26393 p->match_buf = buffer_init();
26394 p->location = buffer_init();
26400 FREE_FUNC(mod_redirect_free) {
26401 plugin_data *p = p_d;
26404 if (!p) return HANDLER_GO_ON;
26406 if (p->config_storage) {
26408 for (i = 0; i < srv->config_context->used; i++) {
26409 plugin_config *s = p->config_storage[i];
26412 pcre_keyvalue_buffer_free(s->redirect);
26417 free(p->config_storage);
26420 buffer_free(p->match_buf);
26421 buffer_free(p->location);
26427 return HANDLER_GO_ON;
26430 @@ -69,195 +69,137 @@
26431 plugin_data *p = p_d;
26435 - config_values_t cv[] = {
26437 + config_values_t cv[] = {
26438 { "url.redirect", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
26439 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
26443 if (!p) return HANDLER_ERROR;
26447 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
26450 for (i = 0; i < srv->config_context->used; i++) {
26454 data_array *da = (data_array *)du;
26457 s = calloc(1, sizeof(plugin_config));
26458 s->redirect = pcre_keyvalue_buffer_init();
26461 cv[0].destination = s->redirect;
26464 p->config_storage[i] = s;
26465 ca = ((data_config *)srv->config_context->data[i])->value;
26468 if (0 != config_insert_values_global(srv, ca, cv)) {
26469 return HANDLER_ERROR;
26473 if (NULL == (du = array_get_element(ca, "url.redirect"))) {
26474 /* no url.redirect defined */
26479 if (du->type != TYPE_ARRAY) {
26480 - log_error_write(srv, __FILE__, __LINE__, "sss",
26481 + log_error_write(srv, __FILE__, __LINE__, "sss",
26482 "unexpected type for key: ", "url.redirect", "array of strings");
26485 return HANDLER_ERROR;
26489 da = (data_array *)du;
26492 for (j = 0; j < da->value->used; j++) {
26493 if (da->value->data[j]->type != TYPE_STRING) {
26494 - log_error_write(srv, __FILE__, __LINE__, "sssbs",
26495 - "unexpected type for key: ",
26497 + log_error_write(srv, __FILE__, __LINE__, "sssbs",
26498 + "unexpected type for key: ",
26500 "[", da->value->data[j]->key, "](string)");
26503 return HANDLER_ERROR;
26506 - if (0 != pcre_keyvalue_buffer_append(s->redirect,
26508 + if (0 != pcre_keyvalue_buffer_append(s->redirect,
26509 ((data_string *)(da->value->data[j]))->key->ptr,
26510 ((data_string *)(da->value->data[j]))->value->ptr)) {
26512 - log_error_write(srv, __FILE__, __LINE__, "sb",
26514 + log_error_write(srv, __FILE__, __LINE__, "sb",
26515 "pcre-compile failed for", da->value->data[j]->key);
26521 return HANDLER_GO_ON;
26524 static int mod_redirect_patch_connection(server *srv, connection *con, plugin_data *p) {
26526 plugin_config *s = p->config_storage[0];
26529 p->conf.redirect = s->redirect;
26532 /* skip the first, the global context */
26533 for (i = 1; i < srv->config_context->used; i++) {
26534 data_config *dc = (data_config *)srv->config_context->data[i];
26535 s = p->config_storage[i];
26538 /* condition didn't match */
26539 if (!config_check_cond(srv, con, dc)) continue;
26543 for (j = 0; j < dc->value->used; j++) {
26544 data_unset *du = dc->value->data[j];
26547 if (0 == strcmp(du->key->ptr, "url.redirect")) {
26548 p->conf.redirect = s->redirect;
26549 p->conf.context = dc;
26558 static handler_t mod_redirect_uri_handler(server *srv, connection *con, void *p_data) {
26560 plugin_data *p = p_data;
26569 * e.g. redirect /base/ to /index.php?section=base
26575 mod_redirect_patch_connection(srv, con, p);
26578 buffer_copy_string_buffer(p->match_buf, con->request.uri);
26580 - for (i = 0; i < p->conf.redirect->used; i++) {
26582 - pcre_extra *extra;
26583 - const char *pattern;
26584 - size_t pattern_len;
26586 - pcre_keyvalue *kv = p->conf.redirect->kv[i];
26591 - extra = kv->key_extra;
26592 - pattern = kv->value->ptr;
26593 - pattern_len = kv->value->used - 1;
26595 - if ((n = pcre_exec(match, extra, p->match_buf->ptr, p->match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) {
26596 - if (n != PCRE_ERROR_NOMATCH) {
26597 - log_error_write(srv, __FILE__, __LINE__, "sd",
26598 - "execution error while matching: ", n);
26599 - return HANDLER_ERROR;
26602 - const char **list;
26603 - size_t start, end;
26607 - pcre_get_substring_list(p->match_buf->ptr, ovec, n, &list);
26609 - /* search for $[0-9] */
26611 - buffer_reset(p->location);
26613 - start = 0; end = pattern_len;
26614 - for (k = 0; k < pattern_len; k++) {
26615 - if ((pattern[k] == '$' || pattern[k] == '%') &&
26616 - isdigit((unsigned char)pattern[k + 1])) {
26619 - size_t num = pattern[k + 1] - '0';
26623 - buffer_append_string_len(p->location, pattern + start, end - start);
26625 - if (pattern[k] == '$') {
26626 - /* n is always > 0 */
26627 - if (num < (size_t)n) {
26628 - buffer_append_string(p->location, list[num]);
26631 - config_append_cond_match_buffer(con, p->conf.context, p->location, num);
26639 - buffer_append_string_len(p->location, pattern + start, pattern_len - start);
26643 - response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->location));
26645 - con->http_status = 301;
26646 - con->file_finished = 1;
26648 - return HANDLER_FINISHED;
26650 + i = config_exec_pcre_keyvalue_buffer(con, p->conf.redirect, p->conf.context, p->match_buf, p->location);
26653 + response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->location));
26655 + con->http_status = 301;
26656 + con->file_finished = 1;
26658 + return HANDLER_FINISHED;
26660 + else if (i != PCRE_ERROR_NOMATCH) {
26661 + log_error_write(srv, __FILE__, __LINE__, "s",
26662 + "execution error while matching", i);
26674 return HANDLER_GO_ON;
26677 @@ -265,13 +207,13 @@
26678 int mod_redirect_plugin_init(plugin *p) {
26679 p->version = LIGHTTPD_VERSION_ID;
26680 p->name = buffer_init_string("redirect");
26683 p->init = mod_redirect_init;
26684 p->handle_uri_clean = mod_redirect_uri_handler;
26685 p->set_defaults = mod_redirect_set_defaults;
26686 p->cleanup = mod_redirect_free;
26695 Property changes on: src/mod_redirect.c
26696 ___________________________________________________________________
26697 Name: svn:eol-style
26700 Index: src/http_auth.c
26701 ===================================================================
26702 --- src/http_auth.c (.../tags/lighttpd-1.4.11) (revision 1159)
26703 +++ src/http_auth.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
26705 #include <string.h>
26708 -#include <unistd.h>
26711 #include "server.h"
26712 @@ -31,23 +30,14 @@
26713 #include "http_auth_digest.h"
26714 #include "stream.h"
26716 +#include "sys-strings.h"
26719 # include <openssl/md5.h>
26726 -#include <security/pam_appl.h>
26727 -#include <security/pam_misc.h>
26729 -static struct pam_conv conv = {
26735 handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s);
26737 static const char base64_pad = '=';
26738 @@ -75,25 +65,25 @@
26739 unsigned char *result;
26744 size_t in_len = strlen(in);
26747 buffer_prepare_copy(out, in_len);
26750 result = (unsigned char *)out->ptr;
26754 /* run through the whole string, converting as we go */
26755 for (i = 0; i < in_len; i++) {
26759 if (ch == '\0') break;
26762 if (ch == base64_pad) break;
26765 ch = base64_reverse_table[ch];
26766 if (ch < 0) continue;
26771 result[j] = ch << 2;
26772 @@ -125,168 +115,168 @@
26784 static int http_auth_get_password(server *srv, mod_auth_plugin_data *p, buffer *username, buffer *realm, buffer *password) {
26788 if (!username->used|| !realm->used) return -1;
26791 if (p->conf.auth_backend == AUTH_BACKEND_HTDIGEST) {
26796 if (buffer_is_empty(p->conf.auth_htdigest_userfile)) return -1;
26799 if (0 != stream_open(&f, p->conf.auth_htdigest_userfile)) {
26800 log_error_write(srv, __FILE__, __LINE__, "sbss", "opening digest-userfile", p->conf.auth_htdigest_userfile, "failed:", strerror(errno));
26810 while (f_line - f.start != f.size) {
26811 char *f_user, *f_pwd, *e, *f_realm;
26812 size_t u_len, pwd_len, r_len;
26822 - * user:realm:md5(user:realm:password)
26824 + * user:realm:md5(user:realm:password)
26828 if (NULL == (f_realm = memchr(f_user, ':', f.size - (f_user - f.start) ))) {
26829 - log_error_write(srv, __FILE__, __LINE__, "sbs",
26830 - "parsed error in", p->conf.auth_htdigest_userfile,
26831 + log_error_write(srv, __FILE__, __LINE__, "sbs",
26832 + "parsed error in", p->conf.auth_htdigest_userfile,
26833 "expected 'username:realm:hashed password'");
26843 if (NULL == (f_pwd = memchr(f_realm + 1, ':', f.size - (f_realm + 1 - f.start)))) {
26844 - log_error_write(srv, __FILE__, __LINE__, "sbs",
26845 - "parsed error in", p->conf.auth_plain_userfile,
26846 + log_error_write(srv, __FILE__, __LINE__, "sbs",
26847 + "parsed error in", p->conf.auth_plain_userfile,
26848 "expected 'username:realm:hashed password'");
26858 /* get pointers to the fields */
26859 - u_len = f_realm - f_user;
26860 + u_len = f_realm - f_user;
26862 r_len = f_pwd - f_realm;
26866 if (NULL != (e = memchr(f_pwd, '\n', f.size - (f_pwd - f.start)))) {
26867 pwd_len = e - f_pwd;
26869 pwd_len = f.size - (f_pwd - f.start);
26873 if (username->used - 1 == u_len &&
26874 (realm->used - 1 == r_len) &&
26875 (0 == strncmp(username->ptr, f_user, u_len)) &&
26876 (0 == strncmp(realm->ptr, f_realm, r_len))) {
26880 buffer_copy_string_len(password, f_pwd, pwd_len);
26897 } else if (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD ||
26898 p->conf.auth_backend == AUTH_BACKEND_PLAIN) {
26904 auth_fn = (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD) ? p->conf.auth_htpasswd_userfile : p->conf.auth_plain_userfile;
26907 if (buffer_is_empty(auth_fn)) return -1;
26910 if (0 != stream_open(&f, auth_fn)) {
26911 - log_error_write(srv, __FILE__, __LINE__, "sbss",
26912 + log_error_write(srv, __FILE__, __LINE__, "sbss",
26913 "opening plain-userfile", auth_fn, "failed:", strerror(errno));
26923 while (f_line - f.start != f.size) {
26924 char *f_user, *f_pwd, *e;
26925 size_t u_len, pwd_len;
26936 * user:crypted passwd
26940 if (NULL == (f_pwd = memchr(f_user, ':', f.size - (f_user - f.start) ))) {
26941 - log_error_write(srv, __FILE__, __LINE__, "sbs",
26942 - "parsed error in", auth_fn,
26943 + log_error_write(srv, __FILE__, __LINE__, "sbs",
26944 + "parsed error in", auth_fn,
26945 "expected 'username:hashed password'");
26955 /* get pointers to the fields */
26956 - u_len = f_pwd - f_user;
26957 + u_len = f_pwd - f_user;
26961 if (NULL != (e = memchr(f_pwd, '\n', f.size - (f_pwd - f.start)))) {
26962 pwd_len = e - f_pwd;
26964 pwd_len = f.size - (f_pwd - f.start);
26968 if (username->used - 1 == u_len &&
26969 (0 == strncmp(username->ptr, f_user, u_len))) {
26973 buffer_copy_string_len(password, f_pwd, pwd_len);
26990 } else if (p->conf.auth_backend == AUTH_BACKEND_LDAP) {
27000 @@ -296,7 +286,7 @@
27002 data_string *require;
27009 @@ -304,12 +294,12 @@
27010 /* search auth-directives for path */
27011 for (i = 0; i < p->conf.auth_require->used; i++) {
27012 if (p->conf.auth_require->data[i]->key->used == 0) continue;
27015 if (0 == strncmp(url, p->conf.auth_require->data[i]->key->ptr, p->conf.auth_require->data[i]->key->used - 1)) {
27021 if (i == p->conf.auth_require->used) {
27024 @@ -317,72 +307,72 @@
27025 req = ((data_array *)(p->conf.auth_require->data[i]))->value;
27027 require = (data_string *)array_get_element(req, "require");
27030 /* if we get here, the user we got a authed user */
27031 if (0 == strcmp(require->value->ptr, "valid-user")) {
27036 /* user=name1|group=name3|host=name4 */
27039 /* seperate the string by | */
27041 log_error_write(srv, __FILE__, __LINE__, "sb", "rules", require->value);
27046 username_len = username ? strlen(username) : 0;
27049 r = rules = require->value->ptr;
27054 const char *k, *v, *e;
27055 int k_len, v_len, r_len;
27058 e = strchr(r, '|');
27064 r_len = strlen(rules) - (r - rules);
27068 /* from r to r + r_len is a rule */
27071 if (0 == strncmp(r, "valid-user", r_len)) {
27072 - log_error_write(srv, __FILE__, __LINE__, "sb",
27073 + log_error_write(srv, __FILE__, __LINE__, "sb",
27074 "parsing the 'require' section in 'auth.require' failed: valid-user cannot be combined with other require rules",
27080 /* search for = in the rules */
27081 if (NULL == (eq = strchr(r, '='))) {
27082 - log_error_write(srv, __FILE__, __LINE__, "sb",
27083 - "parsing the 'require' section in 'auth.require' failed: a = is missing",
27084 + log_error_write(srv, __FILE__, __LINE__, "sb",
27085 + "parsing the 'require' section in 'auth.require' failed: a = is missing",
27091 /* = out of range */
27092 if (eq > r + r_len) {
27093 - log_error_write(srv, __FILE__, __LINE__, "sb",
27094 + log_error_write(srv, __FILE__, __LINE__, "sb",
27095 "parsing the 'require' section in 'auth.require' failed: = out of range",
27103 /* the part before the = is user|group|host */
27109 v_len = r_len - k_len - 1;
27113 if (0 == strncmp(k, "user", k_len)) {
27116 username_len == v_len &&
27117 0 == strncmp(username, v, v_len)) {
27119 @@ -404,19 +394,19 @@
27120 log_error_write(srv, __FILE__, __LINE__, "s", "unknown key");
27130 log_error_write(srv, __FILE__, __LINE__, "s", "nothing matched");
27141 * @param password password-string from the auth-backend
27142 * @param pw password-string from the client
27144 @@ -426,16 +416,16 @@
27147 if (p->conf.auth_backend == AUTH_BACKEND_HTDIGEST) {
27152 - * user:realm:md5(user:realm:password)
27154 + * user:realm:md5(user:realm:password)
27164 MD5_Update(&Md5Ctx, (unsigned char *)username->ptr, username->used - 1);
27165 MD5_Update(&Md5Ctx, (unsigned char *)":", 1);
27166 @@ -443,24 +433,24 @@
27167 MD5_Update(&Md5Ctx, (unsigned char *)":", 1);
27168 MD5_Update(&Md5Ctx, (unsigned char *)pw, strlen(pw));
27169 MD5_Final(HA1, &Md5Ctx);
27175 if (0 == strcmp(password->ptr, a1)) {
27178 - } else if (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD) {
27180 + } else if (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD) {
27184 size_t salt_len = 0;
27190 * user:crypted password
27196 * CRYPT_STD_DES 2-character (Default)
27197 * CRYPT_EXT_DES 9-character
27198 @@ -478,7 +468,7 @@
27200 } else if (password->ptr[0] == '$' && password->ptr[2] == '$') {
27201 char *dollar = NULL;
27204 if (NULL == (dollar = strchr(password->ptr + 3, '$'))) {
27205 fprintf(stderr, "%s.%d\n", __FILE__, __LINE__);
27207 @@ -495,7 +485,7 @@
27208 strncpy(salt, password->ptr, salt_len);
27210 salt[salt_len] = '\0';
27213 crypted = crypt(pw, salt);
27215 if (0 == strcmp(password->ptr, crypted)) {
27216 @@ -503,40 +493,13 @@
27218 fprintf(stderr, "%s.%d\n", __FILE__, __LINE__);
27222 - } else if (p->conf.auth_backend == AUTH_BACKEND_PLAIN) {
27225 + } else if (p->conf.auth_backend == AUTH_BACKEND_PLAIN) {
27226 if (0 == strcmp(password->ptr, pw)) {
27229 - } else if (p->conf.auth_backend == AUTH_BACKEND_PAM) {
27231 - pam_handle_t *pamh=NULL;
27234 - retval = pam_start("lighttpd", username->ptr, &conv, &pamh);
27236 - if (retval == PAM_SUCCESS)
27237 - retval = pam_authenticate(pamh, 0); /* is user really user? */
27239 - if (retval == PAM_SUCCESS)
27240 - retval = pam_acct_mgmt(pamh, 0); /* permitted access? */
27242 - /* This is where we have been authorized or not. */
27244 - if (pam_end(pamh,retval) != PAM_SUCCESS) { /* close Linux-PAM */
27246 - log_error_write(srv, __FILE__, __LINE__, "s", "failed to release authenticator");
27249 - if (retval == PAM_SUCCESS) {
27250 - log_error_write(srv, __FILE__, __LINE__, "s", "Authenticated");
27253 - log_error_write(srv, __FILE__, __LINE__, "s", "Not Authenticated");
27256 - } else if (p->conf.auth_backend == AUTH_BACKEND_LDAP) {
27257 + } else if (p->conf.auth_backend == AUTH_BACKEND_LDAP) {
27260 LDAPMessage *lm, *first;
27261 @@ -544,45 +507,45 @@
27263 char *attrs[] = { LDAP_NO_ATTRS, NULL };
27267 /* for now we stay synchronous */
27272 * 1. connect anonymously (done in plugin init)
27273 * 2. get DN for uid = username
27274 * 3. auth against ldap server
27275 * 4. (optional) check a field
27285 * we have to protect us againt username which modifies out filter in
27290 for (i = 0; i < username->used - 1; i++) {
27291 char c = username->ptr[i];
27297 - log_error_write(srv, __FILE__, __LINE__, "sbd",
27299 + log_error_write(srv, __FILE__, __LINE__, "sbd",
27300 "ldap: invalid character (a-zA-Z0-9 allowed) in username:", username, i);
27313 buffer_copy_string_buffer(p->ldap_filter, p->conf.ldap_filter_pre);
27314 buffer_append_string_buffer(p->ldap_filter, username);
27315 buffer_append_string_buffer(p->ldap_filter, p->conf.ldap_filter_post);
27321 if (p->conf.ldap == NULL ||
27322 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))) {
27323 @@ -590,71 +553,71 @@
27325 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))) {
27327 - log_error_write(srv, __FILE__, __LINE__, "sssb",
27328 + log_error_write(srv, __FILE__, __LINE__, "sssb",
27329 "ldap:", ldap_err2string(ret), "filter:", p->ldap_filter);
27337 if (NULL == (first = ldap_first_entry(p->conf.ldap, lm))) {
27338 log_error_write(srv, __FILE__, __LINE__, "s", "ldap ...");
27348 if (NULL == (dn = ldap_get_dn(p->conf.ldap, first))) {
27349 log_error_write(srv, __FILE__, __LINE__, "s", "ldap ...");
27365 if (NULL == (ldap = ldap_init(p->conf.auth_ldap_hostname->ptr, LDAP_PORT))) {
27366 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap ...", strerror(errno));
27371 ret = LDAP_VERSION3;
27372 if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &ret))) {
27373 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
27376 ldap_unbind_s(ldap);
27383 if (p->conf.auth_ldap_starttls == 1) {
27384 if (LDAP_OPT_SUCCESS != (ret = ldap_start_tls_s(ldap, NULL, NULL))) {
27385 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap startTLS failed:", ldap_err2string(ret));
27388 ldap_unbind_s(ldap);
27397 if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(ldap, dn, pw))) {
27398 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
27401 ldap_unbind_s(ldap);
27409 ldap_unbind_s(ldap);
27412 /* everything worked, good, access granted */
27418 @@ -664,65 +627,65 @@
27419 int http_auth_basic_check(server *srv, connection *con, mod_auth_plugin_data *p, array *req, buffer *url, const char *realm_str) {
27420 buffer *username, *password;
27424 data_string *realm;
27427 realm = (data_string *)array_get_element(req, "realm");
27430 username = buffer_init();
27431 password = buffer_init();
27434 base64_decode(username, realm_str);
27437 /* r2 == user:password */
27438 if (NULL == (pw = strchr(username->ptr, ':'))) {
27439 buffer_free(username);
27442 log_error_write(srv, __FILE__, __LINE__, "sb", ": is missing in", username);
27452 username->used = pw - username->ptr;
27455 /* copy password to r1 */
27456 if (http_auth_get_password(srv, p, username, realm->value, password)) {
27457 buffer_free(username);
27458 buffer_free(password);
27461 log_error_write(srv, __FILE__, __LINE__, "s", "get_password failed");
27468 /* password doesn't match */
27469 if (http_auth_basic_password_compare(srv, p, req, username, realm->value, password, pw)) {
27470 log_error_write(srv, __FILE__, __LINE__, "sbb", "password doesn't match for", con->uri.path, username);
27473 buffer_free(username);
27474 buffer_free(password);
27481 /* value is our allow-rules */
27482 if (http_auth_match_rules(srv, p, url->ptr, username->ptr, NULL, NULL)) {
27483 buffer_free(username);
27484 buffer_free(password);
27487 log_error_write(srv, __FILE__, __LINE__, "s", "rules didn't match");
27494 /* remember the username */
27495 buffer_copy_string_buffer(p->auth_user, username);
27498 buffer_free(username);
27499 buffer_free(password);
27505 @@ -735,7 +698,7 @@
27506 int http_auth_digest_check(server *srv, connection *con, mod_auth_plugin_data *p, array *req, buffer *url, const char *realm_str) {
27514 @@ -745,19 +708,19 @@
27521 const char *m = NULL;
27523 buffer *password, *b, *username_buf, *realm_buf;
27534 /* init pointers */
27536 x, sizeof(x)-1, NULL
27537 @@ -771,11 +734,11 @@
27540 { S("response=") },
27548 dkv[0].ptr = &username;
27549 dkv[1].ptr = &realm;
27550 dkv[2].ptr = &nonce;
27551 @@ -786,24 +749,24 @@
27553 dkv[8].ptr = &respons;
27560 for (i = 0; dkv[i].key; i++) {
27561 *(dkv[i].ptr) = NULL;
27567 if (p->conf.auth_backend != AUTH_BACKEND_HTDIGEST &&
27568 p->conf.auth_backend != AUTH_BACKEND_PLAIN) {
27569 - log_error_write(srv, __FILE__, __LINE__, "s",
27570 + log_error_write(srv, __FILE__, __LINE__, "s",
27571 "digest: unsupported backend (only htdigest or plain)");
27578 b = buffer_init_string(realm_str);
27581 /* parse credentials from client */
27582 for (c = b->ptr; *c; c++) {
27583 /* skip whitespaces */
27584 @@ -812,18 +775,18 @@
27586 for (i = 0; dkv[i].key; i++) {
27587 if ((0 == strncmp(c, dkv[i].key, dkv[i].key_len))) {
27588 - if ((c[dkv[i].key_len] == '"') &&
27589 + if ((c[dkv[i].key_len] == '"') &&
27590 (NULL != (e = strchr(c + dkv[i].key_len + 1, '"')))) {
27591 /* value with "..." */
27592 *(dkv[i].ptr) = c + dkv[i].key_len + 1;
27597 } else if (NULL != (e = strchr(c + dkv[i].key_len, ','))) {
27598 /* value without "...", terminated by ',' */
27599 *(dkv[i].ptr) = c + dkv[i].key_len;
27605 /* value without "...", terminated by EOL */
27606 @@ -833,7 +796,7 @@
27612 if (p->conf.auth_debug > 1) {
27613 log_error_write(srv, __FILE__, __LINE__, "ss", "username", username);
27614 log_error_write(srv, __FILE__, __LINE__, "ss", "realm", realm);
27615 @@ -845,22 +808,22 @@
27616 log_error_write(srv, __FILE__, __LINE__, "ss", "nc", nc);
27617 log_error_write(srv, __FILE__, __LINE__, "ss", "response", respons);
27621 /* check if everything is transmitted */
27627 (qop && (!nc || !cnonce)) ||
27629 /* missing field */
27631 - log_error_write(srv, __FILE__, __LINE__, "s",
27633 + log_error_write(srv, __FILE__, __LINE__, "s",
27634 "digest: missing field");
27638 - m = get_http_method_name(con->request.http_method);
27639 + m = get_http_method_name(con->request.http_method);
27641 /* password-string == HA1 */
27642 password = buffer_init();
27643 @@ -873,10 +836,10 @@
27644 buffer_free(realm_buf);
27649 buffer_free(username_buf);
27650 buffer_free(realm_buf);
27653 if (p->conf.auth_backend == AUTH_BACKEND_PLAIN) {
27654 /* generate password from plain-text */
27656 @@ -890,16 +853,16 @@
27658 /* transform the 32-byte-hex-md5 to a 16-byte-md5 */
27659 for (i = 0; i < HASHLEN; i++) {
27660 - HA1[i] = hex2int(password->ptr[i*2]) << 4;
27661 - HA1[i] |= hex2int(password->ptr[i*2+1]);
27662 + HA1[i] = hex2int(password->ptr[i*2]) << 4;
27663 + HA1[i] |= hex2int(password->ptr[i*2+1]);
27666 /* we already check that above */
27671 buffer_free(password);
27675 strcasecmp(algorithm, "md5-sess") == 0) {
27677 @@ -910,9 +873,9 @@
27678 MD5_Update(&Md5Ctx, (unsigned char *)cnonce, strlen(cnonce));
27679 MD5_Final(HA1, &Md5Ctx);
27686 /* calculate H(A2) */
27688 MD5_Update(&Md5Ctx, (unsigned char *)m, strlen(m));
27689 @@ -924,7 +887,7 @@
27691 MD5_Final(HA2, &Md5Ctx);
27692 CvtHex(HA2, HA2Hex);
27695 /* calculate response */
27697 MD5_Update(&Md5Ctx, (unsigned char *)a1, HASHHEXLEN);
27698 @@ -942,39 +905,39 @@
27699 MD5_Update(&Md5Ctx, (unsigned char *)HA2Hex, HASHHEXLEN);
27700 MD5_Final(RespHash, &Md5Ctx);
27701 CvtHex(RespHash, a2);
27704 if (0 != strcmp(a2, respons)) {
27705 /* digest not ok */
27708 if (p->conf.auth_debug) {
27709 - log_error_write(srv, __FILE__, __LINE__, "sss",
27710 + log_error_write(srv, __FILE__, __LINE__, "sss",
27711 "digest: digest mismatch", a2, respons);
27714 - log_error_write(srv, __FILE__, __LINE__, "sss",
27716 + log_error_write(srv, __FILE__, __LINE__, "sss",
27717 "digest: auth failed for", username, "wrong password");
27725 /* value is our allow-rules */
27726 if (http_auth_match_rules(srv, p, url->ptr, username, NULL, NULL)) {
27729 - log_error_write(srv, __FILE__, __LINE__, "s",
27731 + log_error_write(srv, __FILE__, __LINE__, "s",
27732 "digest: rules did match");
27739 /* remember the username */
27740 buffer_copy_string(p->auth_user, username);
27746 if (p->conf.auth_debug) {
27747 - log_error_write(srv, __FILE__, __LINE__, "s",
27748 + log_error_write(srv, __FILE__, __LINE__, "s",
27749 "digest: auth ok");
27752 @@ -985,23 +948,23 @@
27760 /* generate shared-secret */
27762 MD5_Update(&Md5Ctx, (unsigned char *)fn->ptr, fn->used - 1);
27763 MD5_Update(&Md5Ctx, (unsigned char *)"+", 1);
27766 /* we assume sizeof(time_t) == 4 here, but if not it ain't a problem at all */
27767 ltostr(hh, srv->cur_ts);
27768 MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
27769 ltostr(hh, rand());
27770 MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
27773 MD5_Final(h, &Md5Ctx);
27782 Property changes on: src/http_auth.c
27783 ___________________________________________________________________
27784 Name: svn:eol-style
27787 Index: src/mod_usertrack.c
27788 ===================================================================
27789 --- src/mod_usertrack.c (.../tags/lighttpd-1.4.11) (revision 1159)
27790 +++ src/mod_usertrack.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
27791 @@ -24,44 +24,44 @@
27797 plugin_config **config_storage;
27799 - plugin_config conf;
27801 + plugin_config conf;
27804 /* init the plugin data */
27805 INIT_FUNC(mod_usertrack_init) {
27809 p = calloc(1, sizeof(*p));
27815 /* detroy the plugin data */
27816 FREE_FUNC(mod_usertrack_free) {
27817 plugin_data *p = p_d;
27823 if (!p) return HANDLER_GO_ON;
27826 if (p->config_storage) {
27828 for (i = 0; i < srv->config_context->used; i++) {
27829 plugin_config *s = p->config_storage[i];
27832 buffer_free(s->cookie_name);
27833 buffer_free(s->cookie_domain);
27838 free(p->config_storage);
27845 return HANDLER_GO_ON;
27848 @@ -70,38 +70,38 @@
27849 SETDEFAULTS_FUNC(mod_usertrack_set_defaults) {
27850 plugin_data *p = p_d;
27853 - config_values_t cv[] = {
27855 + config_values_t cv[] = {
27856 { "usertrack.cookie-name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
27857 { "usertrack.cookie-max-age", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
27858 { "usertrack.cookie-domain", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
27860 - { "usertrack.cookiename", NULL, T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_CONNECTION },
27862 + { "usertrack.cookiename", NULL, T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_CONNECTION },
27863 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
27867 if (!p) return HANDLER_ERROR;
27870 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
27873 for (i = 0; i < srv->config_context->used; i++) {
27877 s = calloc(1, sizeof(plugin_config));
27878 s->cookie_name = buffer_init();
27879 s->cookie_domain = buffer_init();
27880 s->cookie_max_age = 0;
27883 cv[0].destination = s->cookie_name;
27884 cv[1].destination = &(s->cookie_max_age);
27885 cv[2].destination = s->cookie_domain;
27888 p->config_storage[i] = s;
27891 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
27892 return HANDLER_ERROR;
27896 if (buffer_is_empty(s->cookie_name)) {
27897 buffer_copy_string(s->cookie_name, "TRACKID");
27899 @@ -109,68 +109,65 @@
27900 for (j = 0; j < s->cookie_name->used - 1; j++) {
27901 char c = s->cookie_name->ptr[j] | 32;
27902 if (c < 'a' || c > 'z') {
27903 - log_error_write(srv, __FILE__, __LINE__, "sb",
27904 - "invalid character in usertrack.cookie-name:",
27905 + log_error_write(srv, __FILE__, __LINE__, "sb",
27906 + "invalid character in usertrack.cookie-name:",
27910 return HANDLER_ERROR;
27916 if (!buffer_is_empty(s->cookie_domain)) {
27918 for (j = 0; j < s->cookie_domain->used - 1; j++) {
27919 char c = s->cookie_domain->ptr[j];
27920 if (c <= 32 || c >= 127 || c == '"' || c == '\\') {
27921 - log_error_write(srv, __FILE__, __LINE__, "sb",
27922 - "invalid character in usertrack.cookie-domain:",
27923 + log_error_write(srv, __FILE__, __LINE__, "sb",
27924 + "invalid character in usertrack.cookie-domain:",
27928 return HANDLER_ERROR;
27935 return HANDLER_GO_ON;
27938 -#define PATCH(x) \
27939 - p->conf.x = s->x;
27940 static int mod_usertrack_patch_connection(server *srv, connection *con, plugin_data *p) {
27942 plugin_config *s = p->config_storage[0];
27944 - PATCH(cookie_name);
27945 - PATCH(cookie_domain);
27946 - PATCH(cookie_max_age);
27949 + PATCH_OPTION(cookie_name);
27950 + PATCH_OPTION(cookie_domain);
27951 + PATCH_OPTION(cookie_max_age);
27953 /* skip the first, the global context */
27954 for (i = 1; i < srv->config_context->used; i++) {
27955 data_config *dc = (data_config *)srv->config_context->data[i];
27956 s = p->config_storage[i];
27959 /* condition didn't match */
27960 if (!config_check_cond(srv, con, dc)) continue;
27964 for (j = 0; j < dc->value->used; j++) {
27965 data_unset *du = dc->value->data[j];
27968 if (buffer_is_equal_string(du->key, CONST_STR_LEN("usertrack.cookie-name"))) {
27969 - PATCH(cookie_name);
27970 + PATCH_OPTION(cookie_name);
27971 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("usertrack.cookie-max-age"))) {
27972 - PATCH(cookie_max_age);
27973 + PATCH_OPTION(cookie_max_age);
27974 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("usertrack.cookie-domain"))) {
27975 - PATCH(cookie_domain);
27976 + PATCH_OPTION(cookie_domain);
27986 URIHANDLER_FUNC(mod_usertrack_uri_handler) {
27987 plugin_data *p = p_d;
27988 @@ -178,38 +175,38 @@
27989 unsigned char h[16];
27994 if (con->uri.path->used == 0) return HANDLER_GO_ON;
27997 mod_usertrack_patch_connection(srv, con, p);
28000 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Cookie"))) {
28002 /* we have a cookie, does it contain a valid name ? */
28004 - /* parse the cookie
28007 + /* parse the cookie
28009 * check for cookiename + (WS | '=')
28015 if (NULL != (g = strstr(ds->value->ptr, p->conf.cookie_name->ptr))) {
28020 for (nc = g + p->conf.cookie_name->used-1; *nc == ' ' || *nc == '\t'; nc++);
28024 /* ok, found the key of our own cookie */
28027 if (strlen(nc) > 32) {
28029 return HANDLER_GO_ON;
28038 if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
28039 ds = data_response_init();
28040 @@ -217,39 +214,39 @@
28041 buffer_copy_string(ds->key, "Set-Cookie");
28042 buffer_copy_string_buffer(ds->value, p->conf.cookie_name);
28043 buffer_append_string(ds->value, "=");
28047 /* taken from mod_auth.c */
28050 /* generate shared-secret */
28052 MD5_Update(&Md5Ctx, (unsigned char *)con->uri.path->ptr, con->uri.path->used - 1);
28053 MD5_Update(&Md5Ctx, (unsigned char *)"+", 1);
28056 /* we assume sizeof(time_t) == 4 here, but if not it ain't a problem at all */
28057 ltostr(hh, srv->cur_ts);
28058 MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
28059 ltostr(hh, rand());
28060 MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
28063 MD5_Final(h, &Md5Ctx);
28066 buffer_append_string_encoded(ds->value, (char *)h, 16, ENCODING_HEX);
28067 buffer_append_string(ds->value, "; Path=/");
28068 buffer_append_string(ds->value, "; Version=1");
28071 if (!buffer_is_empty(p->conf.cookie_domain)) {
28072 buffer_append_string(ds->value, "; Domain=");
28073 buffer_append_string_encoded(ds->value, CONST_BUF_LEN(p->conf.cookie_domain), ENCODING_REL_URI);
28077 if (p->conf.cookie_max_age) {
28078 buffer_append_string(ds->value, "; max-age=");
28079 buffer_append_long(ds->value, p->conf.cookie_max_age);
28083 array_insert_unique(con->response.headers, (data_unset *)ds);
28086 return HANDLER_GO_ON;
28089 @@ -258,13 +255,13 @@
28090 int mod_usertrack_plugin_init(plugin *p) {
28091 p->version = LIGHTTPD_VERSION_ID;
28092 p->name = buffer_init_string("usertrack");
28095 p->init = mod_usertrack_init;
28096 p->handle_uri_clean = mod_usertrack_uri_handler;
28097 p->set_defaults = mod_usertrack_set_defaults;
28098 p->cleanup = mod_usertrack_free;
28107 Property changes on: src/mod_usertrack.c
28108 ___________________________________________________________________
28109 Name: svn:eol-style
28112 Index: src/http_auth_digest.h
28113 ===================================================================
28114 --- src/http_auth_digest.h (.../tags/lighttpd-1.4.11) (revision 1159)
28115 +++ src/http_auth_digest.h (.../branches/lighttpd-merge-1.4.x) (revision 1159)
28126 Property changes on: src/http_auth_digest.h
28127 ___________________________________________________________________
28128 Name: svn:eol-style
28131 Index: src/http_auth.h
28132 ===================================================================
28133 --- src/http_auth.h (.../tags/lighttpd-1.4.11) (revision 1159)
28134 +++ src/http_auth.h (.../branches/lighttpd-merge-1.4.x) (revision 1159)
28139 -typedef enum { AUTH_BACKEND_UNSET, AUTH_BACKEND_PLAIN,
28140 - AUTH_BACKEND_LDAP, AUTH_BACKEND_HTPASSWD,
28141 - AUTH_BACKEND_HTDIGEST, AUTH_BACKEND_PAM } auth_backend_t;
28143 + AUTH_BACKEND_UNSET,
28144 + AUTH_BACKEND_PLAIN,
28145 + AUTH_BACKEND_LDAP,
28146 + AUTH_BACKEND_HTPASSWD,
28147 + AUTH_BACKEND_HTDIGEST
28152 array *auth_require;
28155 buffer *auth_plain_groupfile;
28156 buffer *auth_plain_userfile;
28159 buffer *auth_htdigest_userfile;
28160 buffer *auth_htpasswd_userfile;
28163 buffer *auth_backend_conf;
28166 buffer *auth_ldap_hostname;
28167 buffer *auth_ldap_basedn;
28168 buffer *auth_ldap_binddn;
28169 @@ -32,15 +36,15 @@
28170 buffer *auth_ldap_filter;
28171 buffer *auth_ldap_cafile;
28172 unsigned short auth_ldap_starttls;
28175 unsigned short auth_debug;
28179 auth_backend_t auth_backend;
28186 buffer *ldap_filter_pre;
28187 buffer *ldap_filter_post;
28189 @@ -49,15 +53,15 @@
28198 buffer *ldap_filter;
28202 mod_auth_plugin_config **config_storage;
28205 mod_auth_plugin_config conf; /* this is only used as long as no handler_ctx is setup */
28206 } mod_auth_plugin_data;
28209 Property changes on: src/http_auth.h
28210 ___________________________________________________________________
28211 Name: svn:eol-style
28214 Index: src/mod_webdav.c
28215 ===================================================================
28216 --- src/mod_webdav.c (.../tags/lighttpd-1.4.11) (revision 1159)
28217 +++ src/mod_webdav.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
28220 #include <stdlib.h>
28221 #include <string.h>
28222 -#include <dirent.h>
28224 -#include <unistd.h>
28227 #include <assert.h>
28228 -#include <sys/mman.h>
28230 #ifdef HAVE_CONFIG_H
28231 #include "config.h"
28233 #include <sqlite3.h>
28236 +#if defined(HAVE_LIBXML_H) && defined(HAVE_SQLITE3_H) && defined(HAVE_UUID_H)
28238 +#include <uuid/uuid.h>
28243 #include "buffer.h"
28244 @@ -33,13 +35,16 @@
28245 #include "stream.h"
28246 #include "stat_cache.h"
28248 +#include "sys-files.h"
28249 +#include "sys-mmap.h"
28250 +#include "sys-strings.h"
28253 * this is a webdav for a lighttpd plugin
28255 - * at least a very basic one.
28256 + * at least a very basic one.
28257 * - for now it is read-only and we only support PROPFIND
28263 @@ -58,64 +63,70 @@
28264 sqlite3_stmt *stmt_delete_prop;
28265 sqlite3_stmt *stmt_select_prop;
28266 sqlite3_stmt *stmt_select_propnames;
28269 sqlite3_stmt *stmt_delete_uri;
28270 sqlite3_stmt *stmt_move_uri;
28271 sqlite3_stmt *stmt_copy_uri;
28273 + sqlite3_stmt *stmt_remove_lock;
28274 + sqlite3_stmt *stmt_create_lock;
28275 + sqlite3_stmt *stmt_read_lock;
28276 + sqlite3_stmt *stmt_read_lock_by_uri;
28277 + sqlite3_stmt *stmt_refresh_lock;
28289 plugin_config **config_storage;
28291 - plugin_config conf;
28293 + plugin_config conf;
28296 /* init the plugin data */
28297 INIT_FUNC(mod_webdav_init) {
28301 p = calloc(1, sizeof(*p));
28304 p->tmp_buf = buffer_init();
28306 p->uri.scheme = buffer_init();
28307 p->uri.path_raw = buffer_init();
28308 p->uri.path = buffer_init();
28309 p->uri.authority = buffer_init();
28312 p->physical.path = buffer_init();
28313 p->physical.rel_path = buffer_init();
28314 p->physical.doc_root = buffer_init();
28315 p->physical.basedir = buffer_init();
28321 /* detroy the plugin data */
28322 FREE_FUNC(mod_webdav_free) {
28323 plugin_data *p = p_d;
28328 if (!p) return HANDLER_GO_ON;
28331 if (p->config_storage) {
28333 for (i = 0; i < srv->config_context->used; i++) {
28334 plugin_config *s = p->config_storage[i];
28339 buffer_free(s->sqlite_db_name);
28340 #ifdef USE_PROPPATCH
28343 sqlite3_finalize(s->stmt_delete_prop);
28344 sqlite3_finalize(s->stmt_delete_uri);
28345 sqlite3_finalize(s->stmt_copy_uri);
28346 @@ -123,9 +134,15 @@
28347 sqlite3_finalize(s->stmt_update_prop);
28348 sqlite3_finalize(s->stmt_select_prop);
28349 sqlite3_finalize(s->stmt_select_propnames);
28351 + sqlite3_finalize(s->stmt_read_lock);
28352 + sqlite3_finalize(s->stmt_read_lock_by_uri);
28353 + sqlite3_finalize(s->stmt_create_lock);
28354 + sqlite3_finalize(s->stmt_remove_lock);
28355 + sqlite3_finalize(s->stmt_refresh_lock);
28356 sqlite3_close(s->sql);
28362 free(p->config_storage);
28363 @@ -135,16 +152,16 @@
28364 buffer_free(p->uri.path_raw);
28365 buffer_free(p->uri.path);
28366 buffer_free(p->uri.authority);
28369 buffer_free(p->physical.path);
28370 buffer_free(p->physical.rel_path);
28371 buffer_free(p->physical.doc_root);
28372 buffer_free(p->physical.basedir);
28375 buffer_free(p->tmp_buf);
28381 return HANDLER_GO_ON;
28384 @@ -153,32 +170,32 @@
28385 SETDEFAULTS_FUNC(mod_webdav_set_defaults) {
28386 plugin_data *p = p_d;
28389 - config_values_t cv[] = {
28391 + config_values_t cv[] = {
28392 { "webdav.activate", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
28393 { "webdav.is-readonly", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
28394 { "webdav.sqlite-db-name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
28395 { "webdav.log-xml", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
28396 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
28400 if (!p) return HANDLER_ERROR;
28403 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
28406 for (i = 0; i < srv->config_context->used; i++) {
28410 s = calloc(1, sizeof(plugin_config));
28411 s->sqlite_db_name = buffer_init();
28414 cv[0].destination = &(s->enabled);
28415 cv[1].destination = &(s->is_readonly);
28416 cv[2].destination = s->sqlite_db_name;
28417 cv[3].destination = &(s->log_xml);
28420 p->config_storage[i] = s;
28423 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
28424 return HANDLER_ERROR;
28426 @@ -193,8 +210,26 @@
28427 return HANDLER_ERROR;
28430 - if (SQLITE_OK != sqlite3_prepare(s->sql,
28431 - CONST_STR_LEN("SELECT value FROM properties WHERE resource = ? AND prop = ? AND ns = ?"),
28432 + if (SQLITE_OK != sqlite3_exec(s->sql,
28433 + "CREATE TABLE properties ("
28434 + " resource TEXT NOT NULL,"
28435 + " prop TEXT NOT NULL,"
28436 + " ns TEXT NOT NULL,"
28437 + " value TEXT NOT NULL,"
28438 + " PRIMARY KEY(resource, prop, ns))",
28439 + NULL, NULL, &err)) {
28441 + if (0 != strcmp(err, "table properties already exists")) {
28442 + log_error_write(srv, __FILE__, __LINE__, "ss", "can't open transaction:", err);
28443 + sqlite3_free(err);
28445 + return HANDLER_ERROR;
28447 + sqlite3_free(err);
28450 + if (SQLITE_OK != sqlite3_prepare(s->sql,
28451 + CONST_STR_LEN("SELECT value FROM properties WHERE resource = ? AND prop = ? AND ns = ?"),
28452 &(s->stmt_select_prop), &next_stmt)) {
28453 /* prepare failed */
28455 @@ -202,8 +237,8 @@
28456 return HANDLER_ERROR;
28459 - if (SQLITE_OK != sqlite3_prepare(s->sql,
28460 - CONST_STR_LEN("SELECT ns, prop FROM properties WHERE resource = ?"),
28461 + if (SQLITE_OK != sqlite3_prepare(s->sql,
28462 + CONST_STR_LEN("SELECT ns, prop FROM properties WHERE resource = ?"),
28463 &(s->stmt_select_propnames), &next_stmt)) {
28464 /* prepare failed */
28466 @@ -211,16 +246,67 @@
28467 return HANDLER_ERROR;
28470 - if (SQLITE_OK != sqlite3_exec(s->sql,
28471 - "CREATE TABLE properties ("
28473 + if (SQLITE_OK != sqlite3_prepare(s->sql,
28474 + CONST_STR_LEN("REPLACE INTO properties (resource, prop, ns, value) VALUES (?, ?, ?, ?)"),
28475 + &(s->stmt_update_prop), &next_stmt)) {
28476 + /* prepare failed */
28478 + log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed:", sqlite3_errmsg(s->sql));
28479 + return HANDLER_ERROR;
28482 + if (SQLITE_OK != sqlite3_prepare(s->sql,
28483 + CONST_STR_LEN("DELETE FROM properties WHERE resource = ? AND prop = ? AND ns = ?"),
28484 + &(s->stmt_delete_prop), &next_stmt)) {
28485 + /* prepare failed */
28486 + log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
28488 + return HANDLER_ERROR;
28491 + if (SQLITE_OK != sqlite3_prepare(s->sql,
28492 + CONST_STR_LEN("DELETE FROM properties WHERE resource = ?"),
28493 + &(s->stmt_delete_uri), &next_stmt)) {
28494 + /* prepare failed */
28495 + log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
28497 + return HANDLER_ERROR;
28500 + if (SQLITE_OK != sqlite3_prepare(s->sql,
28501 + CONST_STR_LEN("INSERT INTO properties SELECT ?, prop, ns, value FROM properties WHERE resource = ?"),
28502 + &(s->stmt_copy_uri), &next_stmt)) {
28503 + /* prepare failed */
28504 + log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
28506 + return HANDLER_ERROR;
28509 + if (SQLITE_OK != sqlite3_prepare(s->sql,
28510 + CONST_STR_LEN("UPDATE properties SET resource = ? WHERE resource = ?"),
28511 + &(s->stmt_move_uri), &next_stmt)) {
28512 + /* prepare failed */
28513 + log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
28515 + return HANDLER_ERROR;
28520 + if (SQLITE_OK != sqlite3_exec(s->sql,
28521 + "CREATE TABLE locks ("
28522 + " locktoken TEXT NOT NULL,"
28523 " resource TEXT NOT NULL,"
28524 - " prop TEXT NOT NULL,"
28525 - " ns TEXT NOT NULL,"
28526 - " value TEXT NOT NULL,"
28527 - " PRIMARY KEY(resource, prop, ns))",
28528 + " lockscope TEXT NOT NULL,"
28529 + " locktype TEXT NOT NULL,"
28530 + " owner TEXT NOT NULL,"
28531 + " depth INT NOT NULL,"
28532 + " timeout TIMESTAMP NOT NULL,"
28533 + " PRIMARY KEY(locktoken))",
28534 NULL, NULL, &err)) {
28536 - if (0 != strcmp(err, "table properties already exists")) {
28537 + if (0 != strcmp(err, "table locks already exists")) {
28538 log_error_write(srv, __FILE__, __LINE__, "ss", "can't open transaction:", err);
28541 @@ -228,127 +314,138 @@
28546 - if (SQLITE_OK != sqlite3_prepare(s->sql,
28547 - CONST_STR_LEN("REPLACE INTO properties (resource, prop, ns, value) VALUES (?, ?, ?, ?)"),
28548 - &(s->stmt_update_prop), &next_stmt)) {
28550 + if (SQLITE_OK != sqlite3_prepare(s->sql,
28551 + CONST_STR_LEN("INSERT INTO locks (locktoken, resource, lockscope, locktype, owner, depth, timeout) VALUES (?,?,?,?,?,?, CURRENT_TIME + 600)"),
28552 + &(s->stmt_create_lock), &next_stmt)) {
28553 /* prepare failed */
28554 + log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
28556 - log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed:", sqlite3_errmsg(s->sql));
28557 return HANDLER_ERROR;
28560 - if (SQLITE_OK != sqlite3_prepare(s->sql,
28561 - CONST_STR_LEN("DELETE FROM properties WHERE resource = ? AND prop = ? AND ns = ?"),
28562 - &(s->stmt_delete_prop), &next_stmt)) {
28563 + if (SQLITE_OK != sqlite3_prepare(s->sql,
28564 + CONST_STR_LEN("DELETE FROM locks WHERE locktoken = ?"),
28565 + &(s->stmt_remove_lock), &next_stmt)) {
28566 /* prepare failed */
28567 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
28569 return HANDLER_ERROR;
28572 - if (SQLITE_OK != sqlite3_prepare(s->sql,
28573 - CONST_STR_LEN("DELETE FROM properties WHERE resource = ?"),
28574 - &(s->stmt_delete_uri), &next_stmt)) {
28575 + if (SQLITE_OK != sqlite3_prepare(s->sql,
28576 + CONST_STR_LEN("SELECT locktoken, resource, lockscope, locktype, owner, depth, timeout FROM locks WHERE locktoken = ?"),
28577 + &(s->stmt_read_lock), &next_stmt)) {
28578 /* prepare failed */
28579 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
28581 return HANDLER_ERROR;
28584 - if (SQLITE_OK != sqlite3_prepare(s->sql,
28585 - CONST_STR_LEN("INSERT INTO properties SELECT ?, prop, ns, value FROM properties WHERE resource = ?"),
28586 - &(s->stmt_copy_uri), &next_stmt)) {
28587 + if (SQLITE_OK != sqlite3_prepare(s->sql,
28588 + CONST_STR_LEN("SELECT locktoken, resource, lockscope, locktype, owner, depth, timeout FROM locks WHERE resource = ?"),
28589 + &(s->stmt_read_lock_by_uri), &next_stmt)) {
28590 /* prepare failed */
28591 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
28593 return HANDLER_ERROR;
28596 - if (SQLITE_OK != sqlite3_prepare(s->sql,
28597 - CONST_STR_LEN("UPDATE properties SET resource = ? WHERE resource = ?"),
28598 - &(s->stmt_move_uri), &next_stmt)) {
28599 + if (SQLITE_OK != sqlite3_prepare(s->sql,
28600 + CONST_STR_LEN("UPDATE locks SET timeout = CURRENT_TIME + 600 WHERE locktoken = ?"),
28601 + &(s->stmt_refresh_lock), &next_stmt)) {
28602 /* prepare failed */
28603 log_error_write(srv, __FILE__, __LINE__, "ss", "sqlite3_prepare failed", sqlite3_errmsg(s->sql));
28605 return HANDLER_ERROR;
28610 log_error_write(srv, __FILE__, __LINE__, "s", "Sorry, no sqlite3 and libxml2 support include, compile with --with-webdav-props");
28611 return HANDLER_ERROR;
28617 return HANDLER_GO_ON;
28620 -#define PATCH(x) \
28621 - p->conf.x = s->x;
28622 static int mod_webdav_patch_connection(server *srv, connection *con, plugin_data *p) {
28624 plugin_config *s = p->config_storage[0];
28627 - PATCH(is_readonly);
28631 + PATCH_OPTION(enabled);
28632 + PATCH_OPTION(is_readonly);
28633 + PATCH_OPTION(log_xml);
28635 #ifdef USE_PROPPATCH
28637 - PATCH(stmt_update_prop);
28638 - PATCH(stmt_delete_prop);
28639 - PATCH(stmt_select_prop);
28640 - PATCH(stmt_select_propnames);
28641 + PATCH_OPTION(sql);
28642 + PATCH_OPTION(stmt_update_prop);
28643 + PATCH_OPTION(stmt_delete_prop);
28644 + PATCH_OPTION(stmt_select_prop);
28645 + PATCH_OPTION(stmt_select_propnames);
28647 - PATCH(stmt_delete_uri);
28648 - PATCH(stmt_move_uri);
28649 - PATCH(stmt_copy_uri);
28650 + PATCH_OPTION(stmt_delete_uri);
28651 + PATCH_OPTION(stmt_move_uri);
28652 + PATCH_OPTION(stmt_copy_uri);
28654 + PATCH_OPTION(stmt_remove_lock);
28655 + PATCH_OPTION(stmt_refresh_lock);
28656 + PATCH_OPTION(stmt_create_lock);
28657 + PATCH_OPTION(stmt_read_lock);
28658 + PATCH_OPTION(stmt_read_lock_by_uri);
28660 /* skip the first, the global context */
28661 for (i = 1; i < srv->config_context->used; i++) {
28662 data_config *dc = (data_config *)srv->config_context->data[i];
28663 s = p->config_storage[i];
28666 /* condition didn't match */
28667 if (!config_check_cond(srv, con, dc)) continue;
28671 for (j = 0; j < dc->value->used; j++) {
28672 data_unset *du = dc->value->data[j];
28675 if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.activate"))) {
28677 + PATCH_OPTION(enabled);
28678 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.is-readonly"))) {
28679 - PATCH(is_readonly);
28680 + PATCH_OPTION(is_readonly);
28681 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.log-xml"))) {
28683 + PATCH_OPTION(log_xml);
28684 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("webdav.sqlite-db-name"))) {
28685 #ifdef USE_PROPPATCH
28687 - PATCH(stmt_update_prop);
28688 - PATCH(stmt_delete_prop);
28689 - PATCH(stmt_select_prop);
28690 - PATCH(stmt_select_propnames);
28692 - PATCH(stmt_delete_uri);
28693 - PATCH(stmt_move_uri);
28694 - PATCH(stmt_copy_uri);
28695 + PATCH_OPTION(sql);
28696 + PATCH_OPTION(stmt_update_prop);
28697 + PATCH_OPTION(stmt_delete_prop);
28698 + PATCH_OPTION(stmt_select_prop);
28699 + PATCH_OPTION(stmt_select_propnames);
28701 + PATCH_OPTION(stmt_delete_uri);
28702 + PATCH_OPTION(stmt_move_uri);
28703 + PATCH_OPTION(stmt_copy_uri);
28705 + PATCH_OPTION(stmt_remove_lock);
28706 + PATCH_OPTION(stmt_refresh_lock);
28707 + PATCH_OPTION(stmt_create_lock);
28708 + PATCH_OPTION(stmt_read_lock);
28709 + PATCH_OPTION(stmt_read_lock_by_uri);
28720 URIHANDLER_FUNC(mod_webdav_uri_handler) {
28721 plugin_data *p = p_d;
28726 if (con->uri.path->used == 0) return HANDLER_GO_ON;
28729 mod_webdav_patch_connection(srv, con, p);
28731 if (!p->conf.enabled) return HANDLER_GO_ON;
28732 @@ -362,20 +459,20 @@
28733 if (p->conf.is_readonly) {
28734 response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("PROPFIND"));
28736 - response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("PROPFIND, DELETE, MKCOL, PUT, MOVE, COPY, PROPPATCH"));
28737 + response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("PROPFIND, DELETE, MKCOL, PUT, MOVE, COPY, PROPPATCH, LOCK, UNLOCK"));
28746 return HANDLER_GO_ON;
28748 -static int webdav_gen_prop_tag(server *srv, connection *con,
28752 +static int webdav_gen_prop_tag(server *srv, connection *con,
28759 @@ -414,7 +511,7 @@
28760 buffer_append_string_buffer(b, dst->rel_path);
28761 buffer_append_string(b,"</D:href>\n");
28762 buffer_append_string(b,"<D:status>\n");
28765 if (con->request.http_version == HTTP_VERSION_1_1) {
28766 BUFFER_COPY_STRING_CONST(b, "HTTP/1.1 ");
28768 @@ -458,11 +555,11 @@
28770 /* bind the values to the insert */
28772 - sqlite3_bind_text(stmt, 1,
28773 - dst->rel_path->ptr,
28774 + sqlite3_bind_text(stmt, 1,
28775 + dst->rel_path->ptr,
28776 dst->rel_path->used - 1,
28780 if (SQLITE_DONE != sqlite3_step(stmt)) {
28783 @@ -493,14 +590,14 @@
28784 (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')) {
28786 /* ignore the parent dir */
28790 buffer_copy_string_buffer(d.path, dst->path);
28791 - BUFFER_APPEND_SLASH(d.path);
28792 + PATHNAME_APPEND_SLASH(d.path);
28793 buffer_append_string(d.path, de->d_name);
28796 buffer_copy_string_buffer(d.rel_path, dst->rel_path);
28797 - BUFFER_APPEND_SLASH(d.rel_path);
28798 + PATHNAME_APPEND_SLASH(d.rel_path);
28799 buffer_append_string(d.rel_path, de->d_name);
28801 /* stat and unlink afterwards */
28802 @@ -508,7 +605,7 @@
28803 /* don't about it yet, rmdir will fail too */
28804 } else if (S_ISDIR(st.st_mode)) {
28805 have_multi_status = webdav_delete_dir(srv, con, p, &d, b);
28808 /* try to unlink it */
28809 if (-1 == rmdir(d.path->ptr)) {
28811 @@ -535,11 +632,11 @@
28813 /* bind the values to the insert */
28815 - sqlite3_bind_text(stmt, 1,
28817 + sqlite3_bind_text(stmt, 1,
28819 d.rel_path->used - 1,
28823 if (SQLITE_DONE != sqlite3_step(stmt)) {
28826 @@ -569,7 +666,7 @@
28827 if (stream_open(&s, src->path)) {
28832 if (-1 == (ofd = open(dst->path->ptr, O_WRONLY|O_TRUNC|O_CREAT|(overwrite ? 0 : O_EXCL), 0600))) {
28833 /* opening the destination failed for some reason */
28835 @@ -601,7 +698,7 @@
28844 @@ -614,16 +711,16 @@
28845 sqlite3_reset(stmt);
28847 /* bind the values to the insert */
28848 - sqlite3_bind_text(stmt, 1,
28849 - dst->rel_path->ptr,
28850 + sqlite3_bind_text(stmt, 1,
28851 + dst->rel_path->ptr,
28852 dst->rel_path->used - 1,
28855 - sqlite3_bind_text(stmt, 2,
28856 - src->rel_path->ptr,
28857 + sqlite3_bind_text(stmt, 2,
28858 + src->rel_path->ptr,
28859 src->rel_path->used - 1,
28863 if (SQLITE_DONE != sqlite3_step(stmt)) {
28866 @@ -655,21 +752,21 @@
28867 (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0')) {
28872 buffer_copy_string_buffer(s.path, src->path);
28873 - BUFFER_APPEND_SLASH(s.path);
28874 + PATHNAME_APPEND_SLASH(s.path);
28875 buffer_append_string(s.path, de->d_name);
28877 buffer_copy_string_buffer(d.path, dst->path);
28878 - BUFFER_APPEND_SLASH(d.path);
28879 + PATHNAME_APPEND_SLASH(d.path);
28880 buffer_append_string(d.path, de->d_name);
28882 buffer_copy_string_buffer(s.rel_path, src->rel_path);
28883 - BUFFER_APPEND_SLASH(s.rel_path);
28884 + PATHNAME_APPEND_SLASH(s.rel_path);
28885 buffer_append_string(s.rel_path, de->d_name);
28887 buffer_copy_string_buffer(d.rel_path, dst->rel_path);
28888 - BUFFER_APPEND_SLASH(d.rel_path);
28889 + PATHNAME_APPEND_SLASH(d.rel_path);
28890 buffer_append_string(d.rel_path, de->d_name);
28892 if (-1 == stat(s.path->ptr, &st)) {
28893 @@ -692,16 +789,16 @@
28894 sqlite3_reset(stmt);
28896 /* bind the values to the insert */
28897 - sqlite3_bind_text(stmt, 1,
28898 - dst->rel_path->ptr,
28899 + sqlite3_bind_text(stmt, 1,
28900 + dst->rel_path->ptr,
28901 dst->rel_path->used - 1,
28904 - sqlite3_bind_text(stmt, 2,
28905 - src->rel_path->ptr,
28906 + sqlite3_bind_text(stmt, 2,
28907 + src->rel_path->ptr,
28908 src->rel_path->used - 1,
28912 if (SQLITE_DONE != sqlite3_step(stmt)) {
28915 @@ -721,7 +818,7 @@
28916 buffer_free(s.rel_path);
28917 buffer_free(d.path);
28918 buffer_free(d.rel_path);
28924 @@ -748,12 +845,12 @@
28925 if (S_ISDIR(sce->st.st_mode)) {
28926 buffer_append_string(b, "<D:getcontenttype>httpd/unix-directory</D:getcontenttype>");
28928 - } else if(S_ISREG(sce->st.st_mode)) {
28929 + } else if(S_ISREG(sce->st.st_mode)) {
28930 for (k = 0; k < con->conf.mimetypes->used; k++) {
28931 data_string *ds = (data_string *)con->conf.mimetypes->data[k];
28934 if (ds->key->used == 0) continue;
28937 if (buffer_is_equal_right_len(dst->path, ds->key, ds->key->used - 1)) {
28938 buffer_append_string(b,"<D:getcontenttype>");
28939 buffer_append_string_buffer(b, ds->value);
28940 @@ -807,23 +904,23 @@
28942 /* bind the values to the insert */
28944 - sqlite3_bind_text(stmt, 1,
28945 - dst->rel_path->ptr,
28946 + sqlite3_bind_text(stmt, 1,
28947 + dst->rel_path->ptr,
28948 dst->rel_path->used - 1,
28950 - sqlite3_bind_text(stmt, 2,
28951 + sqlite3_bind_text(stmt, 2,
28955 - sqlite3_bind_text(stmt, 3,
28956 + sqlite3_bind_text(stmt, 3,
28962 - while (SQLITE_ROW == sqlite3_step(p->conf.stmt_select_prop)) {
28963 + while (SQLITE_ROW == sqlite3_step(stmt)) {
28964 /* there is a row for us, we only expect a single col 'value' */
28965 - webdav_gen_prop_tag(srv, con, prop_name, prop_ns, (char *)sqlite3_column_text(p->conf.stmt_select_prop, 0), b);
28966 + webdav_gen_prop_tag(srv, con, prop_name, prop_ns, (char *)sqlite3_column_text(stmt, 0), b);
28970 @@ -840,7 +937,7 @@
28974 -webdav_property live_properties[] = {
28975 +webdav_property live_properties[] = {
28976 { "DAV:", "creationdate" },
28977 { "DAV:", "displayname" },
28978 { "DAV:", "getcontentlanguage" },
28979 @@ -871,8 +968,8 @@
28980 webdav_property *prop;
28982 prop = props->ptr[i];
28984 - if (0 != webdav_get_property(srv, con, p,
28986 + if (0 != webdav_get_property(srv, con, p,
28987 dst, prop->prop, prop->ns, b_200)) {
28988 webdav_gen_prop_tag(srv, con, prop->prop, prop->ns, NULL, b_404);
28990 @@ -916,12 +1013,12 @@
28991 if (-1 == c->file.fd && /* open the file if not already open */
28992 -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
28993 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
29000 if (MAP_FAILED == (c->file.mmap.start = mmap(0, c->file.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
29001 - log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
29002 + log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
29003 strerror(errno), c->file.name, c->file.fd);
29006 @@ -938,7 +1035,7 @@
29007 if (XML_ERR_OK != (err = xmlParseChunk(ctxt, c->file.mmap.start + c->offset, weHave, 0))) {
29008 log_error_write(srv, __FILE__, __LINE__, "sddd", "xmlParseChunk failed at:", cq->bytes_out, weHave, err);
29012 c->offset += weHave;
29013 cq->bytes_out += weHave;
29015 @@ -956,7 +1053,7 @@
29016 if (XML_ERR_OK != (err = xmlParseChunk(ctxt, c->mem->ptr + c->offset, weHave, 0))) {
29017 log_error_write(srv, __FILE__, __LINE__, "sddd", "xmlParseChunk failed at:", cq->bytes_out, weHave, err);
29021 c->offset += weHave;
29022 cq->bytes_out += weHave;
29024 @@ -991,6 +1088,113 @@
29028 +int webdav_lockdiscovery(server *srv, connection *con,
29029 + buffer *locktoken, const char *lockscope, const char *locktype, int depth) {
29033 + response_header_overwrite(srv, con, CONST_STR_LEN("Lock-Token"), CONST_BUF_LEN(locktoken));
29035 + response_header_overwrite(srv, con,
29036 + CONST_STR_LEN("Content-Type"),
29037 + CONST_STR_LEN("text/xml; charset=\"utf-8\""));
29039 + b = chunkqueue_get_append_buffer(con->write_queue);
29041 + buffer_copy_string(b, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
29043 + buffer_append_string(b,"<D:prop xmlns:D=\"DAV:\" xmlns:ns0=\"urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/\">\n");
29044 + buffer_append_string(b,"<D:lockdiscovery>\n");
29045 + buffer_append_string(b,"<D:activelock>\n");
29047 + buffer_append_string(b,"<D:lockscope>");
29048 + buffer_append_string(b,"<D:");
29049 + buffer_append_string(b, lockscope);
29050 + buffer_append_string(b, "/>");
29051 + buffer_append_string(b,"</D:lockscope>\n");
29053 + buffer_append_string(b,"<D:locktype>");
29054 + buffer_append_string(b,"<D:");
29055 + buffer_append_string(b, locktype);
29056 + buffer_append_string(b, "/>");
29057 + buffer_append_string(b,"</D:locktype>\n");
29059 + buffer_append_string(b,"<D:depth>");
29060 + buffer_append_string(b, depth == 0 ? "0" : "infinity");
29061 + buffer_append_string(b,"</D:depth>\n");
29063 + buffer_append_string(b,"<D:timeout>");
29064 + buffer_append_string(b, "Second-600");
29065 + buffer_append_string(b,"</D:timeout>\n");
29067 + buffer_append_string(b,"<D:owner>");
29068 + buffer_append_string(b,"</D:owner>\n");
29070 + buffer_append_string(b,"<D:locktoken>");
29071 + buffer_append_string(b, "<D:href>");
29072 + buffer_append_string_buffer(b, locktoken);
29073 + buffer_append_string(b, "</D:href>");
29074 + buffer_append_string(b,"</D:locktoken>\n");
29076 + buffer_append_string(b,"</D:activelock>\n");
29077 + buffer_append_string(b,"</D:lockdiscovery>\n");
29078 + buffer_append_string(b,"</D:prop>\n");
29083 + * check if resource is having the right locks to access to resource
29088 +int webdav_has_lock(server *srv, connection *con, plugin_data *p, buffer *uri) {
29089 + int has_lock = 1;
29099 + * there is NOT, AND and OR
29100 + * and a list can be tagged
29102 + * (<lock-token>) is untagged
29103 + * <tag> (<lock-token>) is tagged
29105 + * as long as we don't handle collections it is simple. :)
29107 + * X-Litmus: locks: 11 (owner_modify)
29108 + * If: <http://127.0.0.1:1025/dav/litmus/lockme> (<opaquelocktoken:2165478d-0611-49c4-be92-e790d68a38f1>)
29110 + * X-Litmus: locks: 16 (fail_cond_put)
29111 + * If: (<DAV:no-lock> ["-1622396671"])
29113 + if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If"))) {
29115 + /* we didn't provided a lock-token -> */
29116 + /* if the resource is locked -> 423 */
29118 + sqlite3_stmt *stmt = p->conf.stmt_read_lock_by_uri;
29120 + sqlite3_reset(stmt);
29122 + sqlite3_bind_text(stmt, 1,
29123 + CONST_BUF_LEN(uri),
29124 + SQLITE_TRANSIENT);
29126 + while (SQLITE_ROW == sqlite3_step(stmt)) {
29135 URIHANDLER_FUNC(mod_webdav_subrequest_handler) {
29136 plugin_data *p = p_d;
29138 @@ -1001,7 +1205,8 @@
29141 webdav_properties *req_props;
29143 + stat_cache_entry *sce = NULL;
29147 if (!p->conf.enabled) return HANDLER_GO_ON;
29148 @@ -1019,7 +1224,19 @@
29151 /* is there a content-body ? */
29154 + switch (stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
29155 + case HANDLER_ERROR:
29156 + if (errno == ENOENT) {
29157 + con->http_status = 404;
29158 + return HANDLER_FINISHED;
29166 #ifdef USE_PROPPATCH
29167 /* any special requests or just allprop ? */
29168 if (con->request.content_length) {
29169 @@ -1087,12 +1304,12 @@
29170 /* get all property names (EMPTY) */
29171 sqlite3_reset(stmt);
29172 /* bind the values to the insert */
29174 - sqlite3_bind_text(stmt, 1,
29175 - con->uri.path->ptr,
29177 + sqlite3_bind_text(stmt, 1,
29178 + con->uri.path->ptr,
29179 con->uri.path->used - 1,
29183 if (SQLITE_DONE != sqlite3_step(stmt)) {
29186 @@ -1115,13 +1332,13 @@
29187 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/xml; charset=\"utf-8\""));
29189 b = chunkqueue_get_append_buffer(con->write_queue);
29192 buffer_copy_string(b, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
29194 buffer_append_string(b,"<D:multistatus xmlns:D=\"DAV:\" xmlns:ns0=\"urn:uuid:c2f41010-65b3-11d1-a29f-00aa00c14882/\">\n");
29199 prop_200 = buffer_init();
29200 prop_404 = buffer_init();
29202 @@ -1129,7 +1346,7 @@
29205 webdav_get_props(srv, con, p, &(con->physical), req_props, prop_200, prop_404);
29208 buffer_append_string(b,"<D:response>\n");
29209 buffer_append_string(b,"<D:href>");
29210 buffer_append_string_buffer(b, con->uri.scheme);
29211 @@ -1145,9 +1362,9 @@
29212 buffer_append_string_buffer(b, prop_200);
29214 buffer_append_string(b,"</D:prop>\n");
29217 buffer_append_string(b,"<D:status>HTTP/1.1 200 OK</D:status>\n");
29220 buffer_append_string(b,"</D:propstat>\n");
29222 if (!buffer_is_empty(prop_404)) {
29223 @@ -1157,16 +1374,16 @@
29224 buffer_append_string_buffer(b, prop_404);
29226 buffer_append_string(b,"</D:prop>\n");
29229 buffer_append_string(b,"<D:status>HTTP/1.1 404 Not Found</D:status>\n");
29232 buffer_append_string(b,"</D:propstat>\n");
29235 buffer_append_string(b,"</D:response>\n");
29240 if (NULL != (dir = opendir(con->physical.path->ptr))) {
29243 @@ -1179,16 +1396,16 @@
29244 if (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0') {
29246 /* ignore the parent dir */
29250 buffer_copy_string_buffer(d.path, dst->path);
29251 - BUFFER_APPEND_SLASH(d.path);
29252 + PATHNAME_APPEND_SLASH(d.path);
29254 buffer_copy_string_buffer(d.rel_path, dst->rel_path);
29255 - BUFFER_APPEND_SLASH(d.rel_path);
29256 + PATHNAME_APPEND_SLASH(d.rel_path);
29258 if (de->d_name[0] == '.' && de->d_name[1] == '\0') {
29259 - /* don't append the . */
29260 + /* don't append the . */
29262 buffer_append_string(d.path, de->d_name);
29263 buffer_append_string(d.rel_path, de->d_name);
29264 @@ -1198,7 +1415,7 @@
29265 buffer_reset(prop_404);
29267 webdav_get_props(srv, con, p, &d, req_props, prop_200, prop_404);
29270 buffer_append_string(b,"<D:response>\n");
29271 buffer_append_string(b,"<D:href>");
29272 buffer_append_string_buffer(b, con->uri.scheme);
29273 @@ -1214,9 +1431,9 @@
29274 buffer_append_string_buffer(b, prop_200);
29276 buffer_append_string(b,"</D:prop>\n");
29279 buffer_append_string(b,"<D:status>HTTP/1.1 200 OK</D:status>\n");
29282 buffer_append_string(b,"</D:propstat>\n");
29284 if (!buffer_is_empty(prop_404)) {
29285 @@ -1226,9 +1443,9 @@
29286 buffer_append_string_buffer(b, prop_404);
29288 buffer_append_string(b,"</D:prop>\n");
29291 buffer_append_string(b,"<D:status>HTTP/1.1 404 Not Found</D:status>\n");
29294 buffer_append_string(b,"</D:propstat>\n");
29297 @@ -1275,7 +1492,7 @@
29299 return HANDLER_FINISHED;
29303 /* let's create the directory */
29305 if (-1 == mkdir(con->physical.path->ptr, 0700)) {
29306 @@ -1303,7 +1520,13 @@
29307 con->http_status = 403;
29308 return HANDLER_FINISHED;
29312 + /* does the client have a lock for this connection ? */
29313 + if (!webdav_has_lock(srv, con, p, con->uri.path)) {
29314 + con->http_status = 423;
29315 + return HANDLER_FINISHED;
29318 /* stat and unlink afterwards */
29319 if (-1 == stat(con->physical.path->ptr, &st)) {
29320 /* don't about it yet, unlink will fail too */
29321 @@ -1323,7 +1546,7 @@
29322 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/xml; charset=\"utf-8\""));
29324 b = chunkqueue_get_append_buffer(con->write_queue);
29327 buffer_copy_string(b, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
29329 buffer_append_string(b,"<D:multistatus xmlns:D=\"DAV:\">\n");
29330 @@ -1331,7 +1554,7 @@
29331 buffer_append_string_buffer(b, multi_status_resp);
29333 buffer_append_string(b,"</D:multistatus>\n");
29336 if (p->conf.log_xml) {
29337 log_error_write(srv, __FILE__, __LINE__, "sb", "XML-response-body:", b);
29339 @@ -1340,7 +1563,7 @@
29340 con->file_finished = 1;
29342 /* everything went fine, remove the directory */
29345 if (-1 == rmdir(con->physical.path->ptr)) {
29348 @@ -1375,97 +1598,174 @@
29349 case HTTP_METHOD_PUT: {
29351 chunkqueue *cq = con->request_content_queue;
29353 + data_string *ds_range;
29355 if (p->conf.is_readonly) {
29356 con->http_status = 403;
29357 return HANDLER_FINISHED;
29360 + /* is a exclusive lock set on the source */
29361 + if (!webdav_has_lock(srv, con, p, con->uri.path)) {
29362 + con->http_status = 423;
29363 + return HANDLER_FINISHED;
29367 assert(chunkqueue_length(cq) == (off_t)con->request.content_length);
29369 - /* taken what we have in the request-body and write it to a file */
29370 - if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_CREAT|O_TRUNC, 0600))) {
29371 - /* we can't open the file */
29372 - con->http_status = 403;
29373 + /* RFC2616 Section 9.6 PUT requires us to send 501 on all Content-* we don't support
29374 + * - most important Content-Range
29377 + * Example: Content-Range: bytes 100-1037/1038 */
29379 + if (NULL != (ds_range = (data_string *)array_get_element(con->request.headers, "Content-Range"))) {
29380 + const char *num = ds_range->value->ptr;
29382 + char *err = NULL;
29384 + if (0 != strncmp(num, "bytes ", 6)) {
29385 + con->http_status = 501; /* not implemented */
29387 + return HANDLER_FINISHED;
29390 + /* we only support <num>- ... */
29395 + while (*num == ' ' || *num == '\t') num++;
29397 + if (*num == '\0') {
29398 + con->http_status = 501; /* not implemented */
29400 + return HANDLER_FINISHED;
29403 + offset = strtoll(num, &err, 10);
29405 + if (*err != '-' || offset < 0) {
29406 + con->http_status = 501; /* not implemented */
29408 + return HANDLER_FINISHED;
29411 + if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY, 0600))) {
29414 + con->http_status = 404; /* not found */
29417 + con->http_status = 403; /* not found */
29420 + return HANDLER_FINISHED;
29423 + if (-1 == lseek(fd, offset, SEEK_SET)) {
29424 + con->http_status = 501; /* not implemented */
29428 + return HANDLER_FINISHED;
29430 + con->http_status = 200; /* modified */
29433 + /* take what we have in the request-body and write it to a file */
29435 - con->http_status = 201; /* created */
29436 - con->file_finished = 1;
29437 + /* if the file doesn't exist, create it */
29438 + if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_TRUNC, 0600))) {
29439 + if (errno == ENOENT &&
29440 + -1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0600))) {
29441 + /* we can't open the file */
29442 + con->http_status = 403;
29444 - for (c = cq->first; c; c = cq->first) {
29446 + return HANDLER_FINISHED;
29448 + con->http_status = 201; /* created */
29451 + con->http_status = 200; /* modified */
29455 - /* copy all chunks */
29456 - switch(c->type) {
29458 + con->file_finished = 1;
29460 - if (c->file.mmap.start == MAP_FAILED) {
29461 - if (-1 == c->file.fd && /* open the file if not already open */
29462 - -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
29463 - log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
29468 - if (MAP_FAILED == (c->file.mmap.start = mmap(0, c->file.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
29469 - log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
29470 - strerror(errno), c->file.name, c->file.fd);
29471 + for (c = cq->first; c; c = cq->first) {
29476 + /* copy all chunks */
29477 + switch(c->type) {
29480 - c->file.mmap.length = c->file.length;
29481 + if (c->file.mmap.start == MAP_FAILED) {
29482 + if (-1 == c->file.fd && /* open the file if not already open */
29483 + -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
29484 + log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
29486 - close(c->file.fd);
29489 - /* chunk_reset() or chunk_free() will cleanup for us */
29493 - if ((r = write(fd, c->file.mmap.start + c->offset, c->file.length - c->offset)) < 0) {
29496 - con->http_status = 507;
29500 - con->http_status = 403;
29503 + if (MAP_FAILED == (c->file.mmap.start = mmap(0, c->file.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) {
29504 + log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ",
29505 + strerror(errno), c->file.name, c->file.fd);
29511 - if ((r = write(fd, c->mem->ptr + c->offset, c->mem->used - c->offset - 1)) < 0) {
29514 - con->http_status = 507;
29518 - con->http_status = 403;
29522 + c->file.mmap.length = c->file.length;
29524 + close(c->file.fd);
29527 + /* chunk_reset() or chunk_free() will cleanup for us */
29530 + if ((r = write(fd, c->file.mmap.start + c->offset, c->file.length - c->offset)) < 0) {
29533 + con->http_status = 507;
29537 + con->http_status = 403;
29541 - case UNUSED_CHUNK:
29546 + if ((r = write(fd, c->mem->ptr + c->offset, c->mem->used - c->offset - 1)) < 0) {
29549 + con->http_status = 507;
29553 - cq->bytes_out += r;
29558 + con->http_status = 403;
29562 - chunkqueue_remove_finished_chunks(cq);
29564 + case UNUSED_CHUNK:
29571 + cq->bytes_out += r;
29575 + chunkqueue_remove_finished_chunks(cq);
29579 return HANDLER_FINISHED;
29581 - case HTTP_METHOD_MOVE:
29582 + case HTTP_METHOD_MOVE:
29583 case HTTP_METHOD_COPY: {
29584 buffer *destination = NULL;
29586 @@ -1475,7 +1775,15 @@
29587 con->http_status = 403;
29588 return HANDLER_FINISHED;
29592 + /* is a exclusive lock set on the source */
29593 + if (con->request.http_method == HTTP_METHOD_MOVE) {
29594 + if (!webdav_has_lock(srv, con, p, con->uri.path)) {
29595 + con->http_status = 423;
29596 + return HANDLER_FINISHED;
29600 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Destination"))) {
29601 destination = ds->value;
29603 @@ -1549,10 +1857,10 @@
29606 buffer_copy_string_buffer(p->physical.path, p->physical.doc_root);
29607 - BUFFER_APPEND_SLASH(p->physical.path);
29608 + PATHNAME_APPEND_SLASH(p->physical.path);
29609 buffer_copy_string_buffer(p->physical.basedir, p->physical.path);
29611 - /* don't add a second / */
29612 + /* don't add a second / */
29613 if (p->physical.rel_path->ptr[0] == '/') {
29614 buffer_append_string_len(p->physical.path, p->physical.rel_path->ptr + 1, p->physical.rel_path->used - 2);
29616 @@ -1613,6 +1921,12 @@
29617 /* it is just a file, good */
29620 + /* does the client have a lock for this connection ? */
29621 + if (!webdav_has_lock(srv, con, p, p->uri.path)) {
29622 + con->http_status = 423;
29623 + return HANDLER_FINISHED;
29626 /* destination exists */
29627 if (0 == (r = stat(p->physical.path->ptr, &st))) {
29628 if (S_ISDIR(st.st_mode)) {
29629 @@ -1636,7 +1950,7 @@
29630 return HANDLER_FINISHED;
29632 } else if (overwrite == 0) {
29633 - /* destination exists, but overwrite is not set */
29634 + /* destination exists, but overwrite is not set */
29635 con->http_status = 412;
29636 return HANDLER_FINISHED;
29638 @@ -1655,16 +1969,16 @@
29639 sqlite3_reset(stmt);
29641 /* bind the values to the insert */
29642 - sqlite3_bind_text(stmt, 1,
29643 - p->uri.path->ptr,
29644 + sqlite3_bind_text(stmt, 1,
29645 + p->uri.path->ptr,
29646 p->uri.path->used - 1,
29649 - sqlite3_bind_text(stmt, 2,
29650 - con->uri.path->ptr,
29651 + sqlite3_bind_text(stmt, 2,
29652 + con->uri.path->ptr,
29653 con->uri.path->used - 1,
29657 if (SQLITE_DONE != sqlite3_step(stmt)) {
29658 log_error_write(srv, __FILE__, __LINE__, "ss", "sql-move failed:", sqlite3_errmsg(p->conf.sql));
29660 @@ -1691,12 +2005,17 @@
29662 return HANDLER_FINISHED;
29664 - case HTTP_METHOD_PROPPATCH: {
29665 + case HTTP_METHOD_PROPPATCH:
29666 if (p->conf.is_readonly) {
29667 con->http_status = 403;
29668 return HANDLER_FINISHED;
29671 + if (!webdav_has_lock(srv, con, p, con->uri.path)) {
29672 + con->http_status = 423;
29673 + return HANDLER_FINISHED;
29676 /* check if destination exists */
29677 if (-1 == stat(con->physical.path->ptr, &st)) {
29679 @@ -1737,7 +2056,7 @@
29681 sqlite3_stmt *stmt;
29683 - stmt = (0 == xmlStrcmp(cmd->name, BAD_CAST "remove")) ?
29684 + stmt = (0 == xmlStrcmp(cmd->name, BAD_CAST "remove")) ?
29685 p->conf.stmt_delete_prop : p->conf.stmt_update_prop;
29687 for (props = cmd->children; props; props = props->next) {
29688 @@ -1762,34 +2081,35 @@
29690 /* bind the values to the insert */
29692 - sqlite3_bind_text(stmt, 1,
29693 - con->uri.path->ptr,
29694 + sqlite3_bind_text(stmt, 1,
29695 + con->uri.path->ptr,
29696 con->uri.path->used - 1,
29698 - sqlite3_bind_text(stmt, 2,
29699 + sqlite3_bind_text(stmt, 2,
29700 (char *)prop->name,
29701 strlen((char *)prop->name),
29704 - sqlite3_bind_text(stmt, 3,
29705 + sqlite3_bind_text(stmt, 3,
29706 (char *)prop->ns->href,
29707 strlen((char *)prop->ns->href),
29710 - sqlite3_bind_text(stmt, 3,
29711 + sqlite3_bind_text(stmt, 3,
29716 if (stmt == p->conf.stmt_update_prop) {
29717 - sqlite3_bind_text(stmt, 4,
29718 + sqlite3_bind_text(stmt, 4,
29719 (char *)xmlNodeGetContent(prop),
29720 strlen((char *)xmlNodeGetContent(prop)),
29725 if (SQLITE_DONE != (r = sqlite3_step(stmt))) {
29726 - log_error_write(srv, __FILE__, __LINE__, "ss", "sql-set failed:", sqlite3_errmsg(p->conf.sql));
29727 + log_error_write(srv, __FILE__, __LINE__, "ss",
29728 + "sql-set failed:", sqlite3_errmsg(p->conf.sql));
29732 @@ -1804,7 +2124,7 @@
29734 goto propmatch_cleanup;
29738 con->http_status = 400;
29740 if (SQLITE_OK != sqlite3_exec(p->conf.sql, "COMMIT", NULL, NULL, &err)) {
29741 @@ -1821,6 +2141,7 @@
29748 con->http_status = 400;
29749 @@ -1830,11 +2151,307 @@
29751 con->http_status = 501;
29752 return HANDLER_FINISHED;
29754 + case HTTP_METHOD_LOCK:
29756 + * a mac wants to write
29758 + * LOCK /dav/expire.txt HTTP/1.1\r\n
29759 + * User-Agent: WebDAVFS/1.3 (01308000) Darwin/8.1.0 (Power Macintosh)\r\n
29760 + * Accept: * / *\r\n
29762 + * Timeout: Second-600\r\n
29763 + * Content-Type: text/xml; charset=\"utf-8\"\r\n
29764 + * Content-Length: 229\r\n
29765 + * Connection: keep-alive\r\n
29766 + * Host: 192.168.178.23:1025\r\n
29768 + * <?xml version=\"1.0\" encoding=\"utf-8\"?>\n
29769 + * <D:lockinfo xmlns:D=\"DAV:\">\n
29770 + * <D:lockscope><D:exclusive/></D:lockscope>\n
29771 + * <D:locktype><D:write/></D:locktype>\n
29773 + * <D:href>http://www.apple.com/webdav_fs/</D:href>\n
29775 + * </D:lockinfo>\n
29778 + if (depth != 0 && depth != -1) {
29779 + con->http_status = 400;
29781 + return HANDLER_FINISHED;
29785 + if (con->request.content_length) {
29787 + buffer *hdr_if = NULL;
29789 + if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If"))) {
29790 + hdr_if = ds->value;
29793 + /* we don't support Depth: Infinity on locks */
29794 + if (hdr_if == NULL && depth == -1) {
29795 + con->http_status = 409; /* Conflict */
29797 + return HANDLER_FINISHED;
29800 + if (1 == webdav_parse_chunkqueue(srv, con, p, con->request_content_queue, &xml)) {
29801 + xmlNode *rootnode = xmlDocGetRootElement(xml);
29803 + assert(rootnode);
29805 + if (0 == xmlStrcmp(rootnode->name, BAD_CAST "lockinfo")) {
29806 + xmlNode *lockinfo;
29807 + const xmlChar *lockscope = NULL, *locktype = NULL, *owner = NULL;
29809 + for (lockinfo = rootnode->children; lockinfo; lockinfo = lockinfo->next) {
29810 + if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "lockscope")) {
29812 + for (value = lockinfo->children; value; value = value->next) {
29813 + if ((0 == xmlStrcmp(value->name, BAD_CAST "exclusive")) ||
29814 + (0 == xmlStrcmp(value->name, BAD_CAST "shared"))) {
29815 + lockscope = value->name;
29817 + con->http_status = 400;
29820 + return HANDLER_FINISHED;
29823 + } else if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "locktype")) {
29825 + for (value = lockinfo->children; value; value = value->next) {
29826 + if ((0 == xmlStrcmp(value->name, BAD_CAST "write"))) {
29827 + locktype = value->name;
29829 + con->http_status = 400;
29832 + return HANDLER_FINISHED;
29836 + } else if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "owner")) {
29840 + if (lockscope && locktype) {
29841 + sqlite3_stmt *stmt = p->conf.stmt_read_lock_by_uri;
29843 + /* is this resourse already locked ? */
29845 + /* SELECT locktoken, resource, lockscope, locktype, owner, depth, timeout
29847 + * WHERE resource = ? */
29851 + sqlite3_reset(stmt);
29853 + sqlite3_bind_text(stmt, 1,
29854 + p->uri.path->ptr,
29855 + p->uri.path->used - 1,
29856 + SQLITE_TRANSIENT);
29858 + /* it is the PK */
29859 + while (SQLITE_ROW == sqlite3_step(stmt)) {
29860 + /* we found a lock
29861 + * 1. is it compatible ?
29862 + * 2. is it ours */
29863 + char *sql_lockscope = (char *)sqlite3_column_text(stmt, 2);
29865 + if (strcmp(sql_lockscope, "exclusive")) {
29866 + con->http_status = 423;
29867 + } else if (0 == xmlStrcmp(lockscope, BAD_CAST "exclusive")) {
29868 + /* resourse is locked with a shared lock
29869 + * client wants exclusive */
29870 + con->http_status = 423;
29873 + if (con->http_status == 423) {
29875 + return HANDLER_FINISHED;
29879 + stmt = p->conf.stmt_create_lock;
29881 + /* create a lock-token */
29883 + char uuid[37] /* 36 + \0 */;
29885 + uuid_generate(id);
29886 + uuid_unparse(id, uuid);
29888 + buffer_copy_string(p->tmp_buf, "opaquelocktoken:");
29889 + buffer_append_string(p->tmp_buf, uuid);
29891 + /* "CREATE TABLE locks ("
29892 + * " locktoken TEXT NOT NULL,"
29893 + * " resource TEXT NOT NULL,"
29894 + * " lockscope TEXT NOT NULL,"
29895 + * " locktype TEXT NOT NULL,"
29896 + * " owner TEXT NOT NULL,"
29897 + * " depth INT NOT NULL,"
29900 + sqlite3_reset(stmt);
29902 + sqlite3_bind_text(stmt, 1,
29903 + CONST_BUF_LEN(p->tmp_buf),
29904 + SQLITE_TRANSIENT);
29906 + sqlite3_bind_text(stmt, 2,
29907 + CONST_BUF_LEN(con->uri.path),
29908 + SQLITE_TRANSIENT);
29910 + sqlite3_bind_text(stmt, 3,
29912 + xmlStrlen(lockscope),
29913 + SQLITE_TRANSIENT);
29915 + sqlite3_bind_text(stmt, 4,
29917 + xmlStrlen(locktype),
29918 + SQLITE_TRANSIENT);
29921 + sqlite3_bind_text(stmt, 5,
29924 + SQLITE_TRANSIENT);
29927 + sqlite3_bind_int(stmt, 6,
29931 + if (SQLITE_DONE != sqlite3_step(stmt)) {
29932 + log_error_write(srv, __FILE__, __LINE__, "ss",
29933 + "create lock:", sqlite3_errmsg(p->conf.sql));
29936 + /* looks like we survived */
29937 + webdav_lockdiscovery(srv, con, p->tmp_buf, lockscope, locktype, depth);
29939 + con->http_status = 201;
29940 + con->file_finished = 1;
29946 + return HANDLER_FINISHED;
29948 + con->http_status = 400;
29949 + return HANDLER_FINISHED;
29953 + if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If"))) {
29954 + buffer *locktoken = ds->value;
29955 + sqlite3_stmt *stmt = p->conf.stmt_refresh_lock;
29957 + /* remove the < > around the token */
29958 + if (locktoken->used < 6) {
29959 + con->http_status = 400;
29961 + return HANDLER_FINISHED;
29964 + buffer_copy_string_len(p->tmp_buf, locktoken->ptr + 2, locktoken->used - 5);
29966 + sqlite3_reset(stmt);
29968 + sqlite3_bind_text(stmt, 1,
29969 + CONST_BUF_LEN(p->tmp_buf),
29970 + SQLITE_TRANSIENT);
29972 + if (SQLITE_DONE != sqlite3_step(stmt)) {
29973 + log_error_write(srv, __FILE__, __LINE__, "ss",
29974 + "refresh lock:", sqlite3_errmsg(p->conf.sql));
29977 + webdav_lockdiscovery(srv, con, p->tmp_buf, "exclusive", "write", 0);
29979 + con->http_status = 200;
29980 + con->file_finished = 1;
29981 + return HANDLER_FINISHED;
29983 + /* we need a lock-token to refresh */
29984 + con->http_status = 400;
29986 + return HANDLER_FINISHED;
29991 + con->http_status = 501;
29992 + return HANDLER_FINISHED;
29994 + case HTTP_METHOD_UNLOCK:
29996 + if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Lock-Token"))) {
29997 + buffer *locktoken = ds->value;
29998 + sqlite3_stmt *stmt = p->conf.stmt_remove_lock;
30000 + /* remove the < > around the token */
30001 + if (locktoken->used < 4) {
30002 + con->http_status = 400;
30004 + return HANDLER_FINISHED;
30010 + * if the resourse is locked:
30011 + * - by us: unlock
30012 + * - by someone else: 401
30013 + * if the resource is not locked:
30017 + buffer_copy_string_len(p->tmp_buf, locktoken->ptr + 1, locktoken->used - 3);
30019 + sqlite3_reset(stmt);
30021 + sqlite3_bind_text(stmt, 1,
30022 + CONST_BUF_LEN(p->tmp_buf),
30023 + SQLITE_TRANSIENT);
30025 + sqlite3_bind_text(stmt, 2,
30026 + CONST_BUF_LEN(con->uri.path),
30027 + SQLITE_TRANSIENT);
30029 + if (SQLITE_DONE != sqlite3_step(stmt)) {
30030 + log_error_write(srv, __FILE__, __LINE__, "ss",
30031 + "remove lock:", sqlite3_errmsg(p->conf.sql));
30034 + if (0 == sqlite3_changes(p->conf.sql)) {
30035 + con->http_status = 401;
30037 + con->http_status = 204;
30039 + return HANDLER_FINISHED;
30041 + /* we need a lock-token to unlock */
30042 + con->http_status = 400;
30044 + return HANDLER_FINISHED;
30048 + con->http_status = 501;
30049 + return HANDLER_FINISHED;
30057 return HANDLER_GO_ON;
30059 @@ -1845,14 +2462,14 @@
30060 int mod_webdav_plugin_init(plugin *p) {
30061 p->version = LIGHTTPD_VERSION_ID;
30062 p->name = buffer_init_string("webdav");
30065 p->init = mod_webdav_init;
30066 p->handle_uri_clean = mod_webdav_uri_handler;
30067 p->handle_physical = mod_webdav_subrequest_handler;
30068 p->set_defaults = mod_webdav_set_defaults;
30069 p->cleanup = mod_webdav_free;
30078 Property changes on: src/mod_webdav.c
30079 ___________________________________________________________________
30080 Name: svn:eol-style
30083 Index: src/configparser.y
30084 ===================================================================
30085 --- src/configparser.y (.../tags/lighttpd-1.4.11) (revision 1159)
30086 +++ src/configparser.y (.../branches/lighttpd-merge-1.4.x) (revision 1159)
30087 @@ -21,52 +21,34 @@
30088 dc->parent = ctx->current;
30089 array_insert_unique(dc->parent->childs, (data_unset *)dc);
30091 - array_insert_unique(ctx->configs_stack, (data_unset *)ctx->current);
30092 + buffer_ptr_append(ctx->configs_stack, (void *)ctx->current);
30096 static data_config *configparser_pop(config_t *ctx) {
30097 data_config *old = ctx->current;
30098 - ctx->current = (data_config *) array_pop(ctx->configs_stack);
30099 + ctx->current = (data_config *) buffer_ptr_pop(ctx->configs_stack);
30103 /* return a copied variable */
30104 static data_unset *configparser_get_variable(config_t *ctx, const buffer *key) {
30105 - if (strncmp(key->ptr, "env.", sizeof("env.") - 1) == 0) {
30110 - if (NULL != (env = getenv(key->ptr + 4))) {
30112 - ds = data_string_init();
30113 - buffer_append_string(ds->value, env);
30114 - return (data_unset *)ds;
30117 - fprintf(stderr, "Undefined env variable: %s\n", key->ptr + 4);
30126 - fprintf(stderr, "get var %s\n", key->ptr);
30127 + fprintf(stderr, "get var %s\n", key->ptr);
30129 - for (dc = ctx->current; dc; dc = dc->parent) {
30130 + for (dc = ctx->current; dc; dc = dc->parent) {
30132 - fprintf(stderr, "get var on block: %s\n", dc->key->ptr);
30133 - array_print(dc->value, 0);
30134 + fprintf(stderr, "get var on block: %s\n", dc->key->ptr);
30135 + array_print(dc->value, 0);
30137 - if (NULL != (du = array_get_element(dc->value, key->ptr))) {
30138 - return du->copy(du);
30140 + if (NULL != (du = array_get_element(dc->value, key->ptr))) {
30141 + return du->copy(du);
30143 - fprintf(stderr, "Undefined config variable: %s\n", key->ptr);
30150 /* op1 is to be eat/return by this function, op1->key is not cared
30151 @@ -141,6 +123,7 @@
30152 %type aelement {data_unset *}
30153 %type condline {data_config *}
30154 %type condlines {data_config *}
30155 +%type global {data_config *}
30156 %type aelements {array *}
30157 %type array {array *}
30158 %type key {buffer *}
30159 @@ -161,7 +144,12 @@
30161 varline ::= key(A) ASSIGN expression(B). {
30162 buffer_copy_string_buffer(B->key, A);
30163 - if (NULL == array_get_element(ctx->current->value, B->key->ptr)) {
30164 + if (strncmp(A->ptr, "env.", sizeof("env.") - 1) == 0) {
30165 + fprintf(stderr, "Setting env variable is not supported in conditional %d %s: %s\n",
30166 + ctx->current->context_ndx,
30167 + ctx->current->key->ptr, A->ptr);
30169 + } else if (NULL == array_get_element(ctx->current->value, B->key->ptr)) {
30170 array_insert_unique(ctx->current->value, B);
30173 @@ -180,7 +168,12 @@
30174 array *vars = ctx->current->value;
30177 - if (NULL != (du = array_get_element(vars, A->ptr))) {
30178 + if (strncmp(A->ptr, "env.", sizeof("env.") - 1) == 0) {
30179 + fprintf(stderr, "Appending env variable is not supported in conditional %d %s: %s\n",
30180 + ctx->current->context_ndx,
30181 + ctx->current->key->ptr, A->ptr);
30183 + } else if (NULL != (du = array_get_element(vars, A->ptr))) {
30184 /* exists in current block */
30185 du = configparser_merge_data(du, B);
30187 @@ -190,6 +183,7 @@
30188 buffer_copy_string_buffer(du->key, A);
30189 array_replace(vars, du);
30192 } else if (NULL != (du = configparser_get_variable(ctx, A))) {
30193 du = configparser_merge_data(du, B);
30195 @@ -199,15 +193,13 @@
30196 buffer_copy_string_buffer(du->key, A);
30197 array_insert_unique(ctx->current->value, du);
30201 - fprintf(stderr, "Undefined config variable in conditional %d %s: %s\n",
30202 - ctx->current->context_ndx,
30203 - ctx->current->key->ptr, A->ptr);
30205 + buffer_copy_string_buffer(B->key, A);
30206 + array_insert_unique(ctx->current->value, B);
30214 @@ -239,7 +231,24 @@
30217 value(A) ::= key(B). {
30218 - A = configparser_get_variable(ctx, B);
30219 + if (strncmp(B->ptr, "env.", sizeof("env.") - 1) == 0) {
30222 + if (NULL != (env = getenv(B->ptr + 4))) {
30224 + ds = data_string_init();
30225 + buffer_append_string(ds->value, env);
30226 + A = (data_unset *)ds;
30230 + fprintf(stderr, "Undefined env variable: %s\n", B->ptr + 4);
30233 + } else if (NULL == (A = configparser_get_variable(ctx, B))) {
30234 + fprintf(stderr, "Undefined config variable: %s\n", B->ptr);
30238 /* make a dummy so it won't crash */
30239 A = (data_unset *)data_string_init();
30240 @@ -267,6 +276,9 @@
30241 ((data_array *)(A))->value = B;
30244 +array(A) ::= LPARAN RPARAN. {
30245 + A = array_init();
30247 array(A) ::= LPARAN aelements(B) RPARAN. {
30251 Property changes on: src/configparser.y
30252 ___________________________________________________________________
30253 Name: svn:eol-style
30256 Index: src/http_resp_parser.y
30257 ===================================================================
30258 --- src/http_resp_parser.y (.../tags/lighttpd-1.4.11) (revision 0)
30259 +++ src/http_resp_parser.y (.../branches/lighttpd-merge-1.4.x) (revision 1159)
30262 +%token_type {buffer *}
30263 +%extra_argument {http_resp_ctx_t *ctx}
30264 +%name http_resp_parser
30267 +#include <assert.h>
30268 +#include <string.h>
30269 +#include "http_resp.h"
30270 +#include "keyvalue.h"
30271 +#include "array.h"
30278 +%type protocol { int }
30279 +%type response_hdr { http_resp * }
30280 +%type number { int }
30281 +%type headers { array * }
30282 +%type header { data_string * }
30283 +%token_destructor { buffer_free($$); }
30285 +/* just headers + Status: ... */
30286 +response_hdr ::= headers(HDR) CRLF . {
30287 + http_resp *resp = ctx->resp;
30290 + resp->protocol = HTTP_VERSION_UNSET;
30292 + buffer_copy_string(resp->reason, ""); /* no reason */
30293 + array_free(resp->headers);
30294 + resp->headers = HDR;
30296 + if (NULL == (ds = (data_string *)array_get_element(HDR, "Status"))) {
30297 + resp->status = 0;
30300 + resp->status = strtol(ds->value->ptr, &err, 10);
30302 + if (*err != '\0') {
30303 + buffer_copy_string(ctx->errmsg, "expected a number: ");
30304 + buffer_append_string_buffer(ctx->errmsg, ds->value);
30313 +/* HTTP/1.0 <status> ... */
30314 +response_hdr ::= protocol(B) number(C) reason(D) CRLF headers(HDR) CRLF . {
30315 + http_resp *resp = ctx->resp;
30317 + resp->status = C;
30318 + resp->protocol = B;
30319 + buffer_copy_string_buffer(resp->reason, D);
30321 + array_free(resp->headers);
30323 + resp->headers = HDR;
30328 +protocol(A) ::= STRING(B). {
30329 + if (buffer_is_equal_string(B, CONST_STR_LEN("HTTP/1.0"))) {
30330 + A = HTTP_VERSION_1_0;
30331 + } else if (buffer_is_equal_string(B, CONST_STR_LEN("HTTP/1.1"))) {
30332 + A = HTTP_VERSION_1_1;
30334 + buffer_copy_string(ctx->errmsg, "unknown protocol: ");
30335 + buffer_append_string_buffer(ctx->errmsg, B);
30341 +number(A) ::= STRING(B). {
30343 + A = strtol(B->ptr, &err, 10);
30345 + if (*err != '\0') {
30346 + buffer_copy_string(ctx->errmsg, "expected a number: ");
30347 + buffer_append_string_buffer(ctx->errmsg, B);
30353 +reason(A) ::= STRING(B). {
30354 + buffer_copy_string_buffer(A, B);
30357 +reason(A) ::= reason(C) STRING(B). {
30360 + buffer_append_string(A, " ");
30361 + buffer_append_string_buffer(A, B);
30366 +headers(HDRS) ::= headers(SRC) header(HDR). {
30369 + array_insert_unique(HDRS, (data_unset *)HDR);
30374 +headers(HDRS) ::= header(HDR). {
30375 + HDRS = array_init();
30377 + array_insert_unique(HDRS, (data_unset *)HDR);
30379 +header(HDR) ::= STRING(A) COLON STRING(B) CRLF. {
30380 + HDR = data_string_init();
30382 + buffer_copy_string_buffer(HDR->key, A);
30383 + buffer_copy_string_buffer(HDR->value, B);
30386 Property changes on: src/http_resp_parser.y
30387 ___________________________________________________________________
30388 Name: svn:eol-style
30392 Property changes on: src/crc32.c
30393 ___________________________________________________________________
30394 Name: svn:eol-style
30398 ===================================================================
30399 --- src/crc32.h (.../tags/lighttpd-1.4.11) (revision 1159)
30400 +++ src/crc32.h (.../branches/lighttpd-merge-1.4.x) (revision 1159)
30404 #include <sys/types.h>
30405 +#include <stdlib.h>
30407 #if defined HAVE_STDINT_H
30408 #include <stdint.h>
30410 #include <inttypes.h>
30414 +#define uint32_t unsigned __int32
30417 uint32_t generate_crc32c(char *string, size_t length);
30421 Property changes on: src/crc32.h
30422 ___________________________________________________________________
30423 Name: svn:eol-style
30426 Index: src/mod_status.c
30427 ===================================================================
30428 --- src/mod_status.c (.../tags/lighttpd-1.4.11) (revision 1159)
30429 +++ src/mod_status.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
30432 #include <stdlib.h>
30433 #include <string.h>
30434 -#include <unistd.h>
30438 @@ -29,114 +28,114 @@
30444 double traffic_out;
30448 double mod_5s_traffic_out[5];
30449 double mod_5s_requests[5];
30453 double rel_traffic_out;
30454 double rel_requests;
30457 double abs_traffic_out;
30458 double abs_requests;
30461 double bytes_written;
30464 buffer *module_list;
30467 plugin_config **config_storage;
30469 - plugin_config conf;
30471 + plugin_config conf;
30474 INIT_FUNC(mod_status_init) {
30479 p = calloc(1, sizeof(*p));
30482 p->traffic_out = p->requests = 0;
30483 p->rel_traffic_out = p->rel_requests = 0;
30484 p->abs_traffic_out = p->abs_requests = 0;
30485 p->bytes_written = 0;
30486 p->module_list = buffer_init();
30489 for (i = 0; i < 5; i++) {
30490 p->mod_5s_traffic_out[i] = p->mod_5s_requests[i] = 0;
30497 FREE_FUNC(mod_status_free) {
30498 plugin_data *p = p_d;
30503 if (!p) return HANDLER_GO_ON;
30506 buffer_free(p->module_list);
30509 if (p->config_storage) {
30511 for (i = 0; i < srv->config_context->used; i++) {
30512 plugin_config *s = p->config_storage[i];
30515 buffer_free(s->status_url);
30516 buffer_free(s->statistics_url);
30517 buffer_free(s->config_url);
30522 free(p->config_storage);
30531 return HANDLER_GO_ON;
30534 SETDEFAULTS_FUNC(mod_status_set_defaults) {
30535 plugin_data *p = p_d;
30538 - config_values_t cv[] = {
30540 + config_values_t cv[] = {
30541 { "status.status-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
30542 { "status.config-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
30543 { "status.enable-sort", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },
30544 { "status.statistics-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
30545 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
30549 if (!p) return HANDLER_ERROR;
30552 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
30555 for (i = 0; i < srv->config_context->used; i++) {
30559 s = calloc(1, sizeof(plugin_config));
30560 s->config_url = buffer_init();
30561 s->status_url = buffer_init();
30563 s->statistics_url = buffer_init();
30566 cv[0].destination = s->status_url;
30567 cv[1].destination = s->config_url;
30568 cv[2].destination = &(s->sort);
30569 cv[3].destination = s->statistics_url;
30572 p->config_storage[i] = s;
30575 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
30576 return HANDLER_ERROR;
30581 return HANDLER_GO_ON;
30584 @@ -151,7 +150,7 @@
30585 buffer_append_string(b, value);
30586 BUFFER_APPEND_STRING_CONST(b, "</td>\n");
30587 BUFFER_APPEND_STRING_CONST(b, " </tr>\n");
30593 @@ -161,13 +160,13 @@
30594 buffer_append_string(b, key);
30595 BUFFER_APPEND_STRING_CONST(b, "</th>\n");
30596 BUFFER_APPEND_STRING_CONST(b, " </tr>\n");
30602 static int mod_status_header_append_sort(buffer *b, void *p_d, const char* key) {
30603 plugin_data *p = p_d;
30606 if (p->conf.sort) {
30607 BUFFER_APPEND_STRING_CONST(b, "<th class=\"status\"><a href=\"#\" class=\"sortheader\" onclick=\"resort(this);return false;\">");
30608 buffer_append_string(b, key);
30609 @@ -177,13 +176,13 @@
30610 buffer_append_string(b, key);
30611 BUFFER_APPEND_STRING_CONST(b, "</th>\n");
30618 static int mod_status_get_multiplier(double *avg, char *multiplier, int size) {
30622 if (*avg > size) { *avg /= size; *multiplier = 'k'; }
30623 if (*avg > size) { *avg /= size; *multiplier = 'M'; }
30624 if (*avg > size) { *avg /= size; *multiplier = 'G'; }
30625 @@ -202,21 +201,21 @@
30628 char multiplier = '\0';
30634 int days, hours, mins, seconds;
30637 b = chunkqueue_get_append_buffer(con->write_queue);
30639 - BUFFER_COPY_STRING_CONST(b,
30640 + BUFFER_COPY_STRING_CONST(b,
30641 "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
30642 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
30643 " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
30644 "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n"
30646 " <title>Status</title>\n");
30649 BUFFER_APPEND_STRING_CONST(b,
30650 " <style type=\"text/css\">\n"
30651 " table.status { border: black solid thin; }\n"
30652 @@ -226,14 +225,14 @@
30653 " a.sortheader { background-color: black; color: white; font-weight: bold; text-decoration: none; display: block; }\n"
30654 " span.sortarrow { color: white; text-decoration: none; }\n"
30658 if (p->conf.sort) {
30659 BUFFER_APPEND_STRING_CONST(b,
30660 "<script type=\"text/javascript\">\n"
30662 "var sort_column;\n"
30663 "var prev_span = null;\n");
30666 BUFFER_APPEND_STRING_CONST(b,
30667 "function get_inner_text(el) {\n"
30668 " if((typeof el == 'string')||(typeof el == 'undefined'))\n"
30669 @@ -251,7 +250,7 @@
30675 BUFFER_APPEND_STRING_CONST(b,
30676 "function sortfn(a,b) {\n"
30677 " var at = get_inner_text(a.cells[sort_column]);\n"
30678 @@ -266,7 +265,7 @@
30679 " else return 1;\n"
30684 BUFFER_APPEND_STRING_CONST(b,
30685 "function resort(lnk) {\n"
30686 " var span = lnk.childNodes[1];\n"
30687 @@ -276,7 +275,7 @@
30688 " rows[j-1] = table.rows[j];\n"
30689 " sort_column = lnk.parentNode.cellIndex;\n"
30690 " rows.sort(sortfn);\n");
30693 BUFFER_APPEND_STRING_CONST(b,
30694 " if (prev_span != null) prev_span.innerHTML = '';\n"
30695 " if (span.getAttribute('sortdir')=='down') {\n"
30696 @@ -294,175 +293,175 @@
30701 - BUFFER_APPEND_STRING_CONST(b,
30703 + BUFFER_APPEND_STRING_CONST(b,
30712 /* connection listing */
30713 BUFFER_APPEND_STRING_CONST(b, "<h1>Server-Status</h1>");
30715 - BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\">");
30716 - BUFFER_APPEND_STRING_CONST(b, "<tr><td>Hostname</td><td class=\"string\">");
30718 + BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\" id=\"status\" summary=\"Server Status\">");
30719 + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Hostname</td><td class=\"string\"><span id=\"host_addr\">");
30720 buffer_append_string_buffer(b, con->uri.authority);
30721 - BUFFER_APPEND_STRING_CONST(b, " (");
30722 + BUFFER_APPEND_STRING_CONST(b, "</span> (<span id=\"host_name\">");
30723 buffer_append_string_buffer(b, con->server_name);
30724 - BUFFER_APPEND_STRING_CONST(b, ")</td></tr>\n");
30725 - BUFFER_APPEND_STRING_CONST(b, "<tr><td>Uptime</td><td class=\"string\">");
30727 + BUFFER_APPEND_STRING_CONST(b, "</span>)</td></tr>\n");
30728 + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Uptime</td><td class=\"string\" id=\"uptime\">");
30730 ts = srv->cur_ts - srv->startup_ts;
30733 days = ts / (60 * 60 * 24);
30734 ts %= (60 * 60 * 24);
30737 hours = ts / (60 * 60);
30749 buffer_append_long(b, days);
30750 BUFFER_APPEND_STRING_CONST(b, " days ");
30755 buffer_append_long(b, hours);
30756 BUFFER_APPEND_STRING_CONST(b, " hours ");
30761 buffer_append_long(b, mins);
30762 BUFFER_APPEND_STRING_CONST(b, " min ");
30766 buffer_append_long(b, seconds);
30767 BUFFER_APPEND_STRING_CONST(b, " s");
30770 BUFFER_APPEND_STRING_CONST(b, "</td></tr>\n");
30771 BUFFER_APPEND_STRING_CONST(b, "<tr><td>Started at</td><td class=\"string\">");
30774 ts = srv->startup_ts;
30776 - strftime(buf, sizeof(buf) - 1, "%Y-%m-%d %H:%M:%S", localtime(&ts));
30778 + strftime(buf, sizeof(buf) - 1, "<span id=\"start_date\">%Y-%m-%d</span> <span id=\"start_time\">%H:%M:%S</span>", localtime(&ts));
30779 buffer_append_string(b, buf);
30780 BUFFER_APPEND_STRING_CONST(b, "</td></tr>\n");
30785 BUFFER_APPEND_STRING_CONST(b, "<tr><th colspan=\"2\">absolute (since start)</th></tr>\n");
30787 - BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\">");
30789 + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\" ><span id=\"requests\">");
30790 avg = p->abs_requests;
30792 mod_status_get_multiplier(&avg, &multiplier, 1000);
30795 buffer_append_long(b, avg);
30796 - BUFFER_APPEND_STRING_CONST(b, " ");
30797 + BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_mult\">");
30798 if (multiplier) buffer_append_string_len(b, &multiplier, 1);
30799 - BUFFER_APPEND_STRING_CONST(b, "req</td></tr>\n");
30801 - BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\">");
30802 + BUFFER_APPEND_STRING_CONST(b, "</span>req</td></tr>\n");
30804 + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\"><span id=\"traffic\">");
30805 avg = p->abs_traffic_out;
30807 mod_status_get_multiplier(&avg, &multiplier, 1024);
30809 sprintf(buf, "%.2f", avg);
30810 buffer_append_string(b, buf);
30811 - BUFFER_APPEND_STRING_CONST(b, " ");
30812 + BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"traffic_mult\">");
30813 if (multiplier) buffer_append_string_len(b, &multiplier, 1);
30814 - BUFFER_APPEND_STRING_CONST(b, "byte</td></tr>\n");
30815 + BUFFER_APPEND_STRING_CONST(b, "</span>byte</td></tr>\n");
30819 BUFFER_APPEND_STRING_CONST(b, "<tr><th colspan=\"2\">average (since start)</th></tr>\n");
30821 - BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\">");
30823 + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\"><span id=\"requests_avg\">");
30824 avg = p->abs_requests / (srv->cur_ts - srv->startup_ts);
30826 mod_status_get_multiplier(&avg, &multiplier, 1000);
30828 buffer_append_long(b, avg);
30829 - BUFFER_APPEND_STRING_CONST(b, " ");
30830 + BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_avg_mult\">");
30831 if (multiplier) buffer_append_string_len(b, &multiplier, 1);
30832 - BUFFER_APPEND_STRING_CONST(b, "req/s</td></tr>\n");
30834 - BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\">");
30835 + BUFFER_APPEND_STRING_CONST(b, "</span>req/s</td></tr>\n");
30837 + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\"><span id=\"traffic_avg\">");
30838 avg = p->abs_traffic_out / (srv->cur_ts - srv->startup_ts);
30840 mod_status_get_multiplier(&avg, &multiplier, 1024);
30842 sprintf(buf, "%.2f", avg);
30843 buffer_append_string(b, buf);
30844 - BUFFER_APPEND_STRING_CONST(b, " ");
30845 + BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"traffic_avg_mult\">");
30846 if (multiplier) buffer_append_string_len(b, &multiplier, 1);
30847 - BUFFER_APPEND_STRING_CONST(b, "byte/s</td></tr>\n");
30848 + BUFFER_APPEND_STRING_CONST(b, "</span>byte/s</td></tr>\n");
30854 BUFFER_APPEND_STRING_CONST(b, "<tr><th colspan=\"2\">average (5s sliding average)</th></tr>\n");
30855 for (j = 0, avg = 0; j < 5; j++) {
30856 avg += p->mod_5s_requests[j];
30862 - BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\">");
30864 + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\"><span id=\"requests_sliding_avg\">");
30866 mod_status_get_multiplier(&avg, &multiplier, 1000);
30868 buffer_append_long(b, avg);
30869 - BUFFER_APPEND_STRING_CONST(b, " ");
30870 + BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_sliding_avg_mult\">");
30871 if (multiplier) buffer_append_string_len(b, &multiplier, 1);
30873 - BUFFER_APPEND_STRING_CONST(b, "req/s</td></tr>\n");
30876 + BUFFER_APPEND_STRING_CONST(b, "</span>req/s</td></tr>\n");
30878 for (j = 0, avg = 0; j < 5; j++) {
30879 avg += p->mod_5s_traffic_out[j];
30885 - BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\">");
30887 + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\"><span id=\"requests_sliding_traffic\">");
30889 mod_status_get_multiplier(&avg, &multiplier, 1024);
30891 sprintf(buf, "%.2f", avg);
30892 buffer_append_string(b, buf);
30893 - BUFFER_APPEND_STRING_CONST(b, " ");
30894 + BUFFER_APPEND_STRING_CONST(b, "</span> <span id=\"requests_sliding_traffic_mult\">");
30895 if (multiplier) buffer_append_string_len(b, &multiplier, 1);
30896 - BUFFER_APPEND_STRING_CONST(b, "byte/s</td></tr>\n");
30898 + BUFFER_APPEND_STRING_CONST(b, "</span>byte/s</td></tr>\n");
30900 BUFFER_APPEND_STRING_CONST(b, "</table>\n");
30905 BUFFER_APPEND_STRING_CONST(b, "<hr />\n<pre><b>legend</b>\n");
30906 BUFFER_APPEND_STRING_CONST(b, ". = connect, C = close, E = hard error\n");
30907 BUFFER_APPEND_STRING_CONST(b, "r = read, R = read-POST, W = write, h = handle-request\n");
30908 BUFFER_APPEND_STRING_CONST(b, "q = request-start, Q = request-end\n");
30909 BUFFER_APPEND_STRING_CONST(b, "s = response-start, S = response-end\n");
30911 - BUFFER_APPEND_STRING_CONST(b, "<b>");
30913 + BUFFER_APPEND_STRING_CONST(b, "<strong><span id=\"connections\">");
30914 buffer_append_long(b, srv->conns->used);
30915 - BUFFER_APPEND_STRING_CONST(b, " connections</b>\n");
30917 + BUFFER_APPEND_STRING_CONST(b, "</span> connections</strong>\n");
30919 for (j = 0; j < srv->conns->used; j++) {
30920 connection *c = srv->conns->ptr[j];
30921 const char *state = connection_get_short_state(c->state);
30924 buffer_append_string_len(b, state, 1);
30927 if (((j + 1) % 50) == 0) {
30928 BUFFER_APPEND_STRING_CONST(b, "\n");
30933 BUFFER_APPEND_STRING_CONST(b, "\n</pre><hr />\n<h2>Connections</h2>\n");
30935 - BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\">\n");
30937 + BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\" summary=\"Current connections\" id=\"clients\">\n");
30938 BUFFER_APPEND_STRING_CONST(b, "<tr>");
30939 mod_status_header_append_sort(b, p_d, "Client IP");
30940 mod_status_header_append_sort(b, p_d, "Read");
30941 @@ -473,16 +472,16 @@
30942 mod_status_header_append_sort(b, p_d, "URI");
30943 mod_status_header_append_sort(b, p_d, "File");
30944 BUFFER_APPEND_STRING_CONST(b, "</tr>\n");
30947 for (j = 0; j < srv->conns->used; j++) {
30948 connection *c = srv->conns->ptr[j];
30950 - BUFFER_APPEND_STRING_CONST(b, "<tr><td class=\"string\">");
30953 + BUFFER_APPEND_STRING_CONST(b, "<tr><td class=\"string ip\">");
30955 buffer_append_string(b, inet_ntop_cache_get_ip(srv, &(c->dst_addr)));
30957 - BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int\">");
30960 + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int bytes_read\">");
30962 if (con->request.content_length) {
30963 buffer_append_long(b, c->request_content_queue->bytes_in);
30964 BUFFER_APPEND_STRING_CONST(b, "/");
30965 @@ -490,55 +489,55 @@
30967 BUFFER_APPEND_STRING_CONST(b, "0/0");
30970 - BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int\">");
30973 + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int bytes_written\">");
30975 buffer_append_off_t(b, chunkqueue_written(c->write_queue));
30976 BUFFER_APPEND_STRING_CONST(b, "/");
30977 buffer_append_off_t(b, chunkqueue_length(c->write_queue));
30979 - BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
30982 + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string state\">");
30984 buffer_append_string(b, connection_get_state(c->state));
30986 - BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int\">");
30989 + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int time\">");
30991 buffer_append_long(b, srv->cur_ts - c->request_start);
30993 - BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
30996 + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string host\">");
30998 if (buffer_is_empty(c->server_name)) {
30999 buffer_append_string_buffer(b, c->uri.authority);
31002 buffer_append_string_buffer(b, c->server_name);
31005 - BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
31008 + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string uri\">");
31010 if (!buffer_is_empty(c->uri.path)) {
31011 buffer_append_string_encoded(b, CONST_BUF_LEN(c->uri.path), ENCODING_HTML);
31014 - BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">");
31017 + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string file\">");
31019 buffer_append_string_buffer(b, c->physical.path);
31022 BUFFER_APPEND_STRING_CONST(b, "</td></tr>\n");
31026 - BUFFER_APPEND_STRING_CONST(b,
31029 + BUFFER_APPEND_STRING_CONST(b,
31033 - BUFFER_APPEND_STRING_CONST(b,
31036 + BUFFER_APPEND_STRING_CONST(b,
31042 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
31048 @@ -548,7 +547,7 @@
31054 b = chunkqueue_get_append_buffer(con->write_queue);
31056 /* output total number of requests */
31057 @@ -556,19 +555,19 @@
31058 avg = p->abs_requests;
31059 buffer_append_long(b, avg);
31060 BUFFER_APPEND_STRING_CONST(b, "\n");
31063 /* output total traffic out in kbytes */
31064 BUFFER_APPEND_STRING_CONST(b, "Total kBytes: ");
31065 avg = p->abs_traffic_out / 1024;
31066 buffer_append_long(b, avg);
31067 BUFFER_APPEND_STRING_CONST(b, "\n");
31070 /* output uptime */
31071 BUFFER_APPEND_STRING_CONST(b, "Uptime: ");
31072 ts = srv->cur_ts - srv->startup_ts;
31073 buffer_append_long(b, ts);
31074 BUFFER_APPEND_STRING_CONST(b, "\n");
31077 /* output busy servers */
31078 BUFFER_APPEND_STRING_CONST(b, "BusyServers: ");
31079 buffer_append_long(b, srv->conns->used);
31080 @@ -577,7 +576,7 @@
31081 /* set text/plain output */
31083 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/plain"));
31089 @@ -591,10 +590,10 @@
31090 /* we have nothing to send */
31091 con->http_status = 204;
31092 con->file_finished = 1;
31095 return HANDLER_FINISHED;
31099 b = chunkqueue_get_append_buffer(con->write_queue);
31101 for (i = 0; i < st->used; i++) {
31102 @@ -605,27 +604,27 @@
31103 buffer_append_long(b, ((data_integer *)(st->data[ndx]))->value);
31104 buffer_append_string(b, "\n");
31108 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/plain"));
31111 con->http_status = 200;
31112 con->file_finished = 1;
31115 return HANDLER_FINISHED;
31119 static handler_t mod_status_handle_server_status(server *srv, connection *con, void *p_d) {
31122 if (buffer_is_equal_string(con->uri.query, CONST_STR_LEN("auto"))) {
31123 mod_status_handle_server_status_text(srv, con, p_d);
31125 mod_status_handle_server_status_html(srv, con, p_d);
31129 con->http_status = 200;
31130 con->file_finished = 1;
31133 return HANDLER_FINISHED;
31136 @@ -634,9 +633,9 @@
31137 plugin_data *p = p_d;
31138 buffer *b, *m = p->module_list;
31141 - struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
31144 + struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
31146 /* - poll is most reliable
31147 * - select works everywhere
31148 * - linux-* are experimental
31149 @@ -661,10 +660,10 @@
31151 { FDEVENT_HANDLER_UNSET, NULL }
31155 b = chunkqueue_get_append_buffer(con->write_queue);
31157 - BUFFER_COPY_STRING_CONST(b,
31159 + BUFFER_COPY_STRING_CONST(b,
31160 "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n"
31161 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n"
31162 " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
31163 @@ -675,7 +674,7 @@
31165 " <h1>" PACKAGE_NAME " " PACKAGE_VERSION "</h1>\n"
31166 " <table border=\"1\">\n");
31169 mod_status_header_append(b, "Server-Features");
31171 mod_status_row_append(b, "RegEx Conditionals", "enabled");
31172 @@ -683,21 +682,21 @@
31173 mod_status_row_append(b, "RegEx Conditionals", "disabled - pcre missing");
31175 mod_status_header_append(b, "Network Engine");
31178 for (i = 0; event_handlers[i].name; i++) {
31179 if (event_handlers[i].et == srv->event_handler) {
31180 mod_status_row_append(b, "fd-Event-Handler", event_handlers[i].name);
31186 mod_status_header_append(b, "Config-File-Settings");
31189 for (i = 0; i < srv->plugins.used; i++) {
31190 plugin **ps = srv->plugins.ptr;
31193 plugin *pl = ps[i];
31197 buffer_copy_string_buffer(m, pl->name);
31199 @@ -705,137 +704,135 @@
31200 buffer_append_string_buffer(m, pl->name);
31205 mod_status_row_append(b, "Loaded Modules", m->ptr);
31208 BUFFER_APPEND_STRING_CONST(b, " </table>\n");
31210 - BUFFER_APPEND_STRING_CONST(b,
31212 + BUFFER_APPEND_STRING_CONST(b,
31218 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
31221 con->http_status = 200;
31222 con->file_finished = 1;
31225 return HANDLER_FINISHED;
31228 -#define PATCH(x) \
31229 - p->conf.x = s->x;
31230 static int mod_status_patch_connection(server *srv, connection *con, plugin_data *p) {
31232 plugin_config *s = p->config_storage[0];
31234 - PATCH(status_url);
31235 - PATCH(config_url);
31237 - PATCH(statistics_url);
31240 + PATCH_OPTION(status_url);
31241 + PATCH_OPTION(config_url);
31242 + PATCH_OPTION(sort);
31243 + PATCH_OPTION(statistics_url);
31245 /* skip the first, the global context */
31246 for (i = 1; i < srv->config_context->used; i++) {
31247 data_config *dc = (data_config *)srv->config_context->data[i];
31248 s = p->config_storage[i];
31251 /* condition didn't match */
31252 if (!config_check_cond(srv, con, dc)) continue;
31256 for (j = 0; j < dc->value->used; j++) {
31257 data_unset *du = dc->value->data[j];
31260 if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.status-url"))) {
31261 - PATCH(status_url);
31262 + PATCH_OPTION(status_url);
31263 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.config-url"))) {
31264 - PATCH(config_url);
31265 + PATCH_OPTION(config_url);
31266 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.enable-sort"))) {
31268 + PATCH_OPTION(sort);
31269 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.statistics-url"))) {
31270 - PATCH(statistics_url);
31272 + PATCH_OPTION(statistics_url);
31281 static handler_t mod_status_handler(server *srv, connection *con, void *p_d) {
31282 plugin_data *p = p_d;
31285 mod_status_patch_connection(srv, con, p);
31287 - if (!buffer_is_empty(p->conf.status_url) &&
31289 + if (!buffer_is_empty(p->conf.status_url) &&
31290 buffer_is_equal(p->conf.status_url, con->uri.path)) {
31291 return mod_status_handle_server_status(srv, con, p_d);
31292 - } else if (!buffer_is_empty(p->conf.config_url) &&
31293 + } else if (!buffer_is_empty(p->conf.config_url) &&
31294 buffer_is_equal(p->conf.config_url, con->uri.path)) {
31295 return mod_status_handle_server_config(srv, con, p_d);
31296 - } else if (!buffer_is_empty(p->conf.statistics_url) &&
31297 + } else if (!buffer_is_empty(p->conf.statistics_url) &&
31298 buffer_is_equal(p->conf.statistics_url, con->uri.path)) {
31299 return mod_status_handle_server_statistics(srv, con, p_d);
31303 return HANDLER_GO_ON;
31306 TRIGGER_FUNC(mod_status_trigger) {
31307 plugin_data *p = p_d;
31311 /* check all connections */
31312 for (i = 0; i < srv->conns->used; i++) {
31313 connection *c = srv->conns->ptr[i];
31316 p->bytes_written += c->bytes_written_cur_second;
31320 /* a sliding average */
31321 p->mod_5s_traffic_out[p->mod_5s_ndx] = p->bytes_written;
31322 p->mod_5s_requests [p->mod_5s_ndx] = p->requests;
31325 p->mod_5s_ndx = (p->mod_5s_ndx+1) % 5;
31328 p->abs_traffic_out += p->bytes_written;
31329 p->rel_traffic_out += p->bytes_written;
31332 p->bytes_written = 0;
31335 /* reset storage - second */
31336 p->traffic_out = 0;
31340 return HANDLER_GO_ON;
31343 REQUESTDONE_FUNC(mod_status_account) {
31344 plugin_data *p = p_d;
31354 p->bytes_written += con->bytes_written_cur_second;
31357 return HANDLER_GO_ON;
31360 int mod_status_plugin_init(plugin *p) {
31361 p->version = LIGHTTPD_VERSION_ID;
31362 p->name = buffer_init_string("status");
31365 p->init = mod_status_init;
31366 p->cleanup = mod_status_free;
31367 p->set_defaults= mod_status_set_defaults;
31370 p->handle_uri_clean = mod_status_handler;
31371 p->handle_trigger = mod_status_trigger;
31372 p->handle_request_done = mod_status_account;
31381 Property changes on: src/mod_status.c
31382 ___________________________________________________________________
31383 Name: svn:eol-style
31387 Property changes on: src/md5.c
31388 ___________________________________________________________________
31389 Name: svn:eol-style
31392 Index: src/mod_sql_vhost_core.c
31393 ===================================================================
31394 --- src/mod_sql_vhost_core.c (.../tags/lighttpd-1.4.11) (revision 0)
31395 +++ src/mod_sql_vhost_core.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
31397 +#include <stdio.h>
31398 +#include <errno.h>
31399 +#include <fcntl.h>
31400 +#include <string.h>
31402 +#ifdef HAVE_CONFIG_H
31403 +#include "config.h"
31406 +#include "plugin.h"
31409 +#include "stat_cache.h"
31411 +#include "mod_sql_vhost_core.h"
31413 +#define plugin_data mod_sql_vhost_core_plugin_data
31414 +#define plugin_config mod_sql_vhost_core_plugin_config
31416 +/* init the plugin data */
31417 +INIT_FUNC(mod_sql_vhost_core_init) {
31420 + p = calloc(1, sizeof(*p));
31422 + p->docroot = buffer_init();
31423 + p->host = buffer_init();
31428 +/* cleanup the plugin data */
31429 +SERVER_FUNC(mod_sql_vhost_core_cleanup) {
31430 + plugin_data *p = p_d;
31434 + if (!p) return HANDLER_GO_ON;
31436 + if (p->config_storage) {
31438 + for (i = 0; i < srv->config_context->used; i++) {
31439 + plugin_config *s = p->config_storage[i];
31441 + if (!s) continue;
31443 + buffer_free(s->db);
31444 + buffer_free(s->user);
31445 + buffer_free(s->pass);
31446 + buffer_free(s->sock);
31447 + buffer_free(s->backend);
31451 + free(p->config_storage);
31453 + buffer_free(p->docroot);
31454 + buffer_free(p->host);
31458 + return HANDLER_GO_ON;
31461 +/* set configuration values */
31462 +SERVER_FUNC(mod_sql_vhost_core_set_defaults) {
31463 + plugin_data *p = p_d;
31467 + config_values_t cv[] = {
31468 + { "sql-vhost.db", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 0 * e.g. vhost */
31469 + { "sql-vhost.user", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 1 * lighty */
31470 + { "sql-vhost.pass", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 2 * secrect */
31471 + { "sql-vhost.sock", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 3 * /tmp/mysql.sock */
31472 + { "sql-vhost.select-vhost", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 4 * SELECT ... FROM hosts WHERE hostname = ? */
31473 + { "sql-vhost.hostname", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 5 * 127.0.0.1 */
31474 + { "sql-vhost.port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, /* 6 * 3306 */
31475 + { "sql-vhost.backend", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 7 * mysql */
31477 + /* backward compat */
31478 + { "mysql-vhost.db", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 8 == 0 */
31479 + { "mysql-vhost.user", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 9 == 1 */
31480 + { "mysql-vhost.pass", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 10 == 2 */
31481 + { "mysql-vhost.sock", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 11 == 3 */
31482 + { "mysql-vhost.sql", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 12 == 4 */
31483 + { "mysql-vhost.hostname", NULL, T_CONFIG_STRING,T_CONFIG_SCOPE_SERVER }, /* 13 == 5 */
31484 + { "mysql-vhost.port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, /* 14 == 6 */
31486 + { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
31489 + p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
31491 + for (i = 0; i < srv->config_context->used; i++) {
31492 + plugin_config *s;
31494 + s = calloc(1, sizeof(plugin_config));
31495 + s->db = buffer_init();
31496 + s->user = buffer_init();
31497 + s->pass = buffer_init();
31498 + s->sock = buffer_init();
31499 + s->hostname = buffer_init();
31500 + s->backend = buffer_init();
31501 + s->port = 0; /* default port for mysql */
31502 + s->select_vhost = buffer_init();
31503 + s->backend_data = NULL;
31505 + cv[0].destination = s->db;
31506 + cv[1].destination = s->user;
31507 + cv[2].destination = s->pass;
31508 + cv[3].destination = s->sock;
31509 + cv[4].destination = s->select_vhost;
31510 + cv[5].destination = s->hostname;
31511 + cv[6].destination = &(s->port);
31512 + cv[7].destination = s->backend;
31514 + /* backend compat */
31515 + cv[8].destination = cv[0].destination;
31516 + cv[9].destination = cv[1].destination;
31517 + cv[10].destination = cv[2].destination;
31518 + cv[11].destination = cv[3].destination;
31519 + cv[12].destination = cv[4].destination;
31520 + cv[13].destination = cv[5].destination;
31521 + cv[14].destination = cv[6].destination;
31523 + p->config_storage[i] = s;
31525 + if (config_insert_values_global(srv,
31526 + ((data_config *)srv->config_context->data[i])->value,
31527 + cv)) return HANDLER_ERROR;
31529 + /* we only parse the config, the backend plugin will patch itself into the plugin-struct */
31532 + return HANDLER_GO_ON;
31535 +static int mod_sql_vhost_core_patch_connection(server *srv, connection *con, plugin_data *p) {
31537 + plugin_config *s = p->config_storage[0];
31539 + PATCH_OPTION(backend_data);
31540 + PATCH_OPTION(get_vhost);
31542 + /* skip the first, the global context */
31543 + for (i = 1; i < srv->config_context->used; i++) {
31544 + data_config *dc = (data_config *)srv->config_context->data[i];
31545 + s = p->config_storage[i];
31547 + /* condition didn't match */
31548 + if (!config_check_cond(srv, con, dc)) continue;
31550 + if (s->backend_data) {
31551 + PATCH_OPTION(backend_data);
31552 + PATCH_OPTION(get_vhost);
31559 +/* handle document root request */
31560 +CONNECTION_FUNC(mod_sql_vhost_core_handle_docroot) {
31561 + plugin_data *p = p_d;
31562 + stat_cache_entry *sce;
31564 + /* no host specified? */
31565 + if (!con->uri.authority->used) return HANDLER_GO_ON;
31567 + mod_sql_vhost_core_patch_connection(srv, con, p);
31569 + /* do we have backend ? */
31570 + if (!p->conf.get_vhost) return HANDLER_GO_ON;
31572 + /* ask the backend for the data */
31573 + if (0 != p->conf.get_vhost(srv, con, p->conf.backend_data, p->docroot, p->host)) {
31574 + return HANDLER_GO_ON;
31577 + if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->docroot, &sce)) {
31578 + log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), p->docroot);
31579 + return HANDLER_GO_ON;
31581 + if (!S_ISDIR(sce->st.st_mode)) {
31582 + log_error_write(srv, __FILE__, __LINE__, "sb", "Not a directory", p->docroot);
31583 + return HANDLER_GO_ON;
31586 + buffer_copy_string_buffer(con->server_name, p->host);
31587 + buffer_copy_string_buffer(con->physical.doc_root, p->docroot);
31589 + return HANDLER_GO_ON;
31592 +/* this function is called at dlopen() time and inits the callbacks */
31593 +int mod_sql_vhost_core_plugin_init(plugin *p) {
31594 + p->version = LIGHTTPD_VERSION_ID;
31595 + p->name = buffer_init_string("mod_sql_vhost_core");
31597 + p->init = mod_sql_vhost_core_init;
31598 + p->cleanup = mod_sql_vhost_core_cleanup;
31600 + p->set_defaults = mod_sql_vhost_core_set_defaults;
31601 + p->handle_docroot = mod_sql_vhost_core_handle_docroot;
31606 Index: src/mod_compress.c
31607 ===================================================================
31608 --- src/mod_compress.c (.../tags/lighttpd-1.4.11) (revision 1159)
31609 +++ src/mod_compress.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
31611 #include <sys/stat.h>
31614 -#include <unistd.h>
31616 #include <stdlib.h>
31617 #include <string.h>
31619 #include "buffer.h"
31620 #include "response.h"
31621 #include "stat_cache.h"
31622 +#include "http_chunk.h"
31624 #include "plugin.h"
31629 #include "sys-mmap.h"
31630 +#include "sys-files.h"
31632 /* request: accept-encoding */
31633 #define HTTP_ACCEPT_ENCODING_IDENTITY BV(0)
31634 @@ -55,97 +56,127 @@
31640 plugin_config **config_storage;
31641 - plugin_config conf;
31642 + plugin_config conf;
31645 INIT_FUNC(mod_compress_init) {
31649 p = calloc(1, sizeof(*p));
31652 p->ofn = buffer_init();
31653 p->b = buffer_init();
31659 FREE_FUNC(mod_compress_free) {
31660 plugin_data *p = p_d;
31665 if (!p) return HANDLER_GO_ON;
31668 buffer_free(p->ofn);
31672 if (p->config_storage) {
31674 for (i = 0; i < srv->config_context->used; i++) {
31675 plugin_config *s = p->config_storage[i];
31680 array_free(s->compress);
31681 buffer_free(s->compress_cache_dir);
31686 free(p->config_storage);
31695 return HANDLER_GO_ON;
31698 +void mkdir_recursive(const char *dir) {
31700 + char dir_copy[256];
31701 + char *p = dir_copy;
31703 + if (!dir || !dir[0])
31706 + strncpy(dir_copy, dir, sizeof(dir_copy) / sizeof(dir_copy[0]));
31708 + while ((p = strchr(p + 1, '/')) != NULL) {
31711 + if ((mkdir(dir_copy, 0700) != 0) && (errno != EEXIST))
31717 + mkdir(dir, 0700);
31720 SETDEFAULTS_FUNC(mod_compress_setdefaults) {
31721 plugin_data *p = p_d;
31724 - config_values_t cv[] = {
31726 + config_values_t cv[] = {
31727 { "compress.cache-dir", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
31728 { "compress.filetype", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },
31729 { "compress.max-filesize", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
31730 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
31734 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
31737 for (i = 0; i < srv->config_context->used; i++) {
31741 s = calloc(1, sizeof(plugin_config));
31742 s->compress_cache_dir = buffer_init();
31743 s->compress = array_init();
31744 s->compress_max_filesize = 0;
31747 cv[0].destination = s->compress_cache_dir;
31748 cv[1].destination = s->compress;
31749 cv[2].destination = &(s->compress_max_filesize);
31752 p->config_storage[i] = s;
31755 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
31756 return HANDLER_ERROR;
31760 if (!buffer_is_empty(s->compress_cache_dir)) {
31762 if (0 != stat(s->compress_cache_dir->ptr, &st)) {
31763 - log_error_write(srv, __FILE__, __LINE__, "sbs", "can't stat compress.cache-dir",
31765 + log_error_write(srv, __FILE__, __LINE__, "sbs", "can't stat compress.cache-dir, attempting to create",
31766 s->compress_cache_dir, strerror(errno));
31768 - return HANDLER_ERROR;
31769 + mkdir_recursive(s->compress_cache_dir->ptr);
31771 + if (0 != stat(s->compress_cache_dir->ptr, &st)) {
31773 + log_error_write(srv, __FILE__, __LINE__, "sbs", "can't stat compress.cache-dir, create failed",
31774 + s->compress_cache_dir, strerror(errno));
31776 + return HANDLER_ERROR;
31783 return HANDLER_GO_ON;
31789 @@ -153,32 +184,32 @@
31802 - if (Z_OK != deflateInit2(&z,
31804 + if (Z_OK != deflateInit2(&z,
31805 Z_DEFAULT_COMPRESSION,
31808 -MAX_WBITS, /* supress zlib-header */
31810 Z_DEFAULT_STRATEGY)) {
31815 z.next_in = (unsigned char *)start;
31816 z.avail_in = st_size;
31822 buffer_prepare_copy(p->b, (z.avail_in * 1.1) + 12 + 18);
31825 /* write gzip header */
31828 c = (unsigned char *)p->b->ptr;
31831 @@ -190,24 +221,24 @@
31832 c[7] = (mtime >> 24) & 0xff;
31833 c[8] = 0x00; /* extra flags */
31834 c[9] = 0x03; /* UNIX */
31838 z.next_out = (unsigned char *)p->b->ptr + p->b->used;
31839 z.avail_out = p->b->size - p->b->used - 8;
31843 if (Z_STREAM_END != deflate(&z, Z_FINISH)) {
31850 p->b->used += z.total_out;
31853 crc = generate_crc32c(start, st_size);
31856 c = (unsigned char *)p->b->ptr + p->b->used;
31859 c[0] = (crc >> 0) & 0xff;
31860 c[1] = (crc >> 8) & 0xff;
31861 c[2] = (crc >> 16) & 0xff;
31862 @@ -221,51 +252,51 @@
31863 if (Z_OK != deflateEnd(&z)) {
31871 static int deflate_file_to_buffer_deflate(server *srv, connection *con, plugin_data *p, unsigned char *start, off_t st_size) {
31882 - if (Z_OK != deflateInit2(&z,
31884 + if (Z_OK != deflateInit2(&z,
31885 Z_DEFAULT_COMPRESSION,
31888 -MAX_WBITS, /* supress zlib-header */
31890 Z_DEFAULT_STRATEGY)) {
31896 z.avail_in = st_size;
31900 buffer_prepare_copy(p->b, (z.avail_in * 1.1) + 12);
31903 z.next_out = (unsigned char *)p->b->ptr;
31904 z.avail_out = p->b->size;
31908 if (Z_STREAM_END != deflate(&z, Z_FINISH)) {
31915 p->b->used += z.total_out;
31918 if (Z_OK != deflateEnd(&z)) {
31926 @@ -274,48 +305,48 @@
31928 static int deflate_file_to_buffer_bzip2(server *srv, connection *con, plugin_data *p, unsigned char *start, off_t st_size) {
31939 - if (BZ_OK != BZ2_bzCompressInit(&bz,
31941 + if (BZ_OK != BZ2_bzCompressInit(&bz,
31942 9, /* blocksize = 900k */
31944 0)) { /* workFactor: default */
31949 bz.next_in = (char *)start;
31950 bz.avail_in = st_size;
31951 bz.total_in_lo32 = 0;
31952 bz.total_in_hi32 = 0;
31955 buffer_prepare_copy(p->b, (bz.avail_in * 1.1) + 12);
31958 bz.next_out = p->b->ptr;
31959 bz.avail_out = p->b->size;
31960 bz.total_out_lo32 = 0;
31961 bz.total_out_hi32 = 0;
31964 if (BZ_STREAM_END != BZ2_bzCompress(&bz, BZ_FINISH)) {
31965 BZ2_bzCompressEnd(&bz);
31970 /* file is too large for now */
31971 if (bz.total_out_hi32) return -1;
31975 p->b->used = bz.total_out_lo32;
31978 if (BZ_OK != BZ2_bzCompressEnd(&bz)) {
31986 @@ -326,47 +357,50 @@
31988 const char *filename = fn->ptr;
31991 + stat_cache_entry *compressed_sce = NULL;
31993 + if (buffer_is_empty(p->conf.compress_cache_dir)) return -1;
31996 if ((off_t)(sce->st.st_size * 1.1) < sce->st.st_size) return -1;
31998 - /* don't mmap files > 128Mb
32001 + /* don't mmap files > 128Mb
32003 * we could use a sliding window, but currently there is no need for it
32007 if (sce->st.st_size > 128 * 1024 * 1024) return -1;
32010 buffer_reset(p->ofn);
32011 buffer_copy_string_buffer(p->ofn, p->conf.compress_cache_dir);
32012 - BUFFER_APPEND_SLASH(p->ofn);
32014 + PATHNAME_APPEND_SLASH(p->ofn);
32016 if (0 == strncmp(con->physical.path->ptr, con->physical.doc_root->ptr, con->physical.doc_root->used-1)) {
32017 size_t offset = p->ofn->used - 1;
32018 char *dir, *nextdir;
32021 buffer_append_string(p->ofn, con->physical.path->ptr + con->physical.doc_root->used - 1);
32024 buffer_copy_string_buffer(p->b, p->ofn);
32028 for (dir = p->b->ptr + offset; NULL != (nextdir = strchr(dir, '/')); dir = nextdir + 1) {
32032 if (-1 == mkdir(p->b->ptr, 0700)) {
32033 if (errno != EEXIST) {
32034 log_error_write(srv, __FILE__, __LINE__, "sbss", "creating cache-directory", p->b, "failed", strerror(errno));
32045 buffer_append_string_buffer(p->ofn, con->uri.path);
32050 case HTTP_ACCEPT_ENCODING_GZIP:
32051 buffer_append_string(p->ofn, "-gzip-");
32052 @@ -381,55 +415,64 @@
32053 log_error_write(srv, __FILE__, __LINE__, "sd", "unknown compression type", type);
32058 buffer_append_string_buffer(p->ofn, sce->etag);
32062 + if (HANDLER_ERROR != stat_cache_get_entry(srv, con, p->ofn, &compressed_sce)) {
32063 + /* file exists */
32065 + http_chunk_append_file(srv, con, p->ofn, 0, compressed_sce->st.st_size);
32066 + con->file_finished = 1;
32071 if (-1 == (ofd = open(p->ofn->ptr, O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0600))) {
32072 if (errno == EEXIST) {
32073 /* cache-entry exists */
32075 - log_error_write(srv, __FILE__, __LINE__, "bs", p->ofn, "compress-cache hit");
32077 - buffer_copy_string_buffer(con->physical.path, p->ofn);
32083 - log_error_write(srv, __FILE__, __LINE__, "sbss", "creating cachefile", p->ofn, "failed", strerror(errno));
32086 + log_error_write(srv, __FILE__, __LINE__, "sbss",
32087 + "creating cachefile", p->ofn,
32088 + "failed", strerror(errno));
32093 - log_error_write(srv, __FILE__, __LINE__, "bs", p->ofn, "compress-cache miss");
32096 if (-1 == (ifd = open(filename, O_RDONLY | O_BINARY))) {
32097 - log_error_write(srv, __FILE__, __LINE__, "sbss", "opening plain-file", fn, "failed", strerror(errno));
32099 + log_error_write(srv, __FILE__, __LINE__, "sbss",
32100 + "opening plain-file", fn,
32101 + "failed", strerror(errno));
32112 if (MAP_FAILED == (start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
32113 - log_error_write(srv, __FILE__, __LINE__, "sbss", "mmaping", fn, "failed", strerror(errno));
32115 + log_error_write(srv, __FILE__, __LINE__, "sbss",
32117 + "failed", strerror(errno));
32127 - case HTTP_ACCEPT_ENCODING_GZIP:
32128 + case HTTP_ACCEPT_ENCODING_GZIP:
32129 ret = deflate_file_to_buffer_gzip(srv, con, p, start, sce->st.st_size, sce->st.st_mtime);
32131 - case HTTP_ACCEPT_ENCODING_DEFLATE:
32132 + case HTTP_ACCEPT_ENCODING_DEFLATE:
32133 ret = deflate_file_to_buffer_deflate(srv, con, p, start, sce->st.st_size);
32137 - case HTTP_ACCEPT_ENCODING_BZIP2:
32138 + case HTTP_ACCEPT_ENCODING_BZIP2:
32139 ret = deflate_file_to_buffer_bzip2(srv, con, p, start, sce->st.st_size);
32142 @@ -437,26 +480,27 @@
32148 if (-1 == (r = write(ofd, p->b->ptr, p->b->used))) {
32149 - munmap(start, sce->st.st_size);
32150 + munmap(start, sce->st.st_size);
32157 if ((size_t)r != p->b->used) {
32163 munmap(start, sce->st.st_size);
32168 if (ret != 0) return -1;
32170 - buffer_copy_string_buffer(con->physical.path, p->ofn);
32173 + http_chunk_append_file(srv, con, p->ofn, 0, r);
32174 + con->file_finished = 1;
32179 @@ -465,43 +509,44 @@
32186 if ((off_t)(sce->st.st_size * 1.1) < sce->st.st_size) return -1;
32189 /* don't mmap files > 128M
32192 * we could use a sliding window, but currently there is no need for it
32196 if (sce->st.st_size > 128 * 1024 * 1024) return -1;
32200 if (-1 == (ifd = open(fn->ptr, O_RDONLY | O_BINARY))) {
32201 log_error_write(srv, __FILE__, __LINE__, "sbss", "opening plain-file", fn, "failed", strerror(errno));
32208 - if (MAP_FAILED == (start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) {
32210 + start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0);
32214 + if (MAP_FAILED == start) {
32215 log_error_write(srv, __FILE__, __LINE__, "sbss", "mmaping", fn, "failed", strerror(errno));
32225 - case HTTP_ACCEPT_ENCODING_GZIP:
32226 + case HTTP_ACCEPT_ENCODING_GZIP:
32227 ret = deflate_file_to_buffer_gzip(srv, con, p, start, sce->st.st_size, sce->st.st_mtime);
32229 - case HTTP_ACCEPT_ENCODING_DEFLATE:
32230 + case HTTP_ACCEPT_ENCODING_DEFLATE:
32231 ret = deflate_file_to_buffer_deflate(srv, con, p, start, sce->st.st_size);
32235 - case HTTP_ACCEPT_ENCODING_BZIP2:
32236 + case HTTP_ACCEPT_ENCODING_BZIP2:
32237 ret = deflate_file_to_buffer_bzip2(srv, con, p, start, sce->st.st_size);
32240 @@ -509,69 +554,64 @@
32246 munmap(start, sce->st.st_size);
32250 if (ret != 0) return -1;
32253 chunkqueue_reset(con->write_queue);
32254 b = chunkqueue_get_append_buffer(con->write_queue);
32255 buffer_copy_memory(b, p->b->ptr, p->b->used + 1);
32258 buffer_reset(con->physical.path);
32261 con->file_finished = 1;
32262 con->file_started = 1;
32269 -#define PATCH(x) \
32270 - p->conf.x = s->x;
32271 static int mod_compress_patch_connection(server *srv, connection *con, plugin_data *p) {
32273 plugin_config *s = p->config_storage[0];
32275 - PATCH(compress_cache_dir);
32277 - PATCH(compress_max_filesize);
32279 + PATCH_OPTION(compress_cache_dir);
32280 + PATCH_OPTION(compress);
32281 + PATCH_OPTION(compress_max_filesize);
32283 /* skip the first, the global context */
32284 for (i = 1; i < srv->config_context->used; i++) {
32285 data_config *dc = (data_config *)srv->config_context->data[i];
32286 s = p->config_storage[i];
32289 /* condition didn't match */
32290 if (!config_check_cond(srv, con, dc)) continue;
32294 for (j = 0; j < dc->value->used; j++) {
32295 data_unset *du = dc->value->data[j];
32298 if (buffer_is_equal_string(du->key, CONST_STR_LEN("compress.cache-dir"))) {
32299 - PATCH(compress_cache_dir);
32300 + PATCH_OPTION(compress_cache_dir);
32301 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("compress.filetype"))) {
32303 + PATCH_OPTION(compress);
32304 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("compress.max-filesize"))) {
32305 - PATCH(compress_max_filesize);
32306 + PATCH_OPTION(compress_max_filesize);
32316 PHYSICALPATH_FUNC(mod_compress_physical) {
32317 plugin_data *p = p_d;
32320 stat_cache_entry *sce = NULL;
32323 /* only GET and POST can get compressed */
32324 - if (con->request.http_method != HTTP_METHOD_GET &&
32325 + if (con->request.http_method != HTTP_METHOD_GET &&
32326 con->request.http_method != HTTP_METHOD_POST) {
32327 return HANDLER_GO_ON;
32329 @@ -579,46 +619,49 @@
32330 if (buffer_is_empty(con->physical.path)) {
32331 return HANDLER_GO_ON;
32335 mod_compress_patch_connection(srv, con, p);
32338 max_fsize = p->conf.compress_max_filesize;
32340 stat_cache_get_entry(srv, con, con->physical.path, &sce);
32342 /* don't compress files that are too large as we need to much time to handle them */
32343 if (max_fsize && (sce->st.st_size >> 10) > max_fsize) return HANDLER_GO_ON;
32346 + /* compressing the file might lead to larger files instead */
32347 + if (sce->st.st_size < 128) return HANDLER_GO_ON;
32349 /* check if mimetype is in compress-config */
32350 for (m = 0; m < p->conf.compress->used; m++) {
32351 data_string *compress_ds = (data_string *)p->conf.compress->data[m];
32354 if (!compress_ds) {
32355 log_error_write(srv, __FILE__, __LINE__, "sbb", "evil", con->physical.path, con->uri.path);
32358 return HANDLER_GO_ON;
32362 if (buffer_is_equal(compress_ds->value, sce->content_type)) {
32363 /* mimetype found */
32367 /* the response might change according to Accept-Encoding */
32368 response_header_insert(srv, con, CONST_STR_LEN("Vary"), CONST_STR_LEN("Accept-Encoding"));
32371 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Accept-Encoding"))) {
32372 int accept_encoding = 0;
32373 char *value = ds->value->ptr;
32374 int srv_encodings = 0;
32375 int matched_encodings = 0;
32378 /* get client side support encodings */
32379 if (NULL != strstr(value, "gzip")) accept_encoding |= HTTP_ACCEPT_ENCODING_GZIP;
32380 if (NULL != strstr(value, "deflate")) accept_encoding |= HTTP_ACCEPT_ENCODING_DEFLATE;
32381 if (NULL != strstr(value, "compress")) accept_encoding |= HTTP_ACCEPT_ENCODING_COMPRESS;
32382 if (NULL != strstr(value, "bzip2")) accept_encoding |= HTTP_ACCEPT_ENCODING_BZIP2;
32383 if (NULL != strstr(value, "identity")) accept_encoding |= HTTP_ACCEPT_ENCODING_IDENTITY;
32386 /* get server side supported ones */
32388 srv_encodings |= HTTP_ACCEPT_ENCODING_BZIP2;
32389 @@ -627,18 +670,31 @@
32390 srv_encodings |= HTTP_ACCEPT_ENCODING_GZIP;
32391 srv_encodings |= HTTP_ACCEPT_ENCODING_DEFLATE;
32395 /* find matching entries */
32396 matched_encodings = accept_encoding & srv_encodings;
32399 if (matched_encodings) {
32400 const char *dflt_gzip = "gzip";
32401 const char *dflt_deflate = "deflate";
32402 const char *dflt_bzip2 = "bzip2";
32405 const char *compression_name = NULL;
32406 int compression_type = 0;
32410 + mtime = strftime_cache_get(srv, sce->st.st_mtime);
32411 + etag_mutate(con->physical.etag, sce->etag);
32413 + response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
32414 + response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
32416 + /* perhaps we don't even have to compress the file as the browser still has the
32417 + * current version */
32418 + if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, mtime)) {
32419 + return HANDLER_FINISHED;
32422 /* select best matching encoding */
32423 if (matched_encodings & HTTP_ACCEPT_ENCODING_BZIP2) {
32424 compression_type = HTTP_ACCEPT_ENCODING_BZIP2;
32425 @@ -650,31 +706,21 @@
32426 compression_type = HTTP_ACCEPT_ENCODING_DEFLATE;
32427 compression_name = dflt_deflate;
32431 - if (p->conf.compress_cache_dir->used) {
32432 - if (0 == deflate_file_to_file(srv, con, p,
32433 - con->physical.path, sce, compression_type)) {
32436 - response_header_overwrite(srv, con, CONST_STR_LEN("Content-Encoding"), compression_name, strlen(compression_name));
32438 - mtime = strftime_cache_get(srv, sce->st.st_mtime);
32439 - response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime));
32441 - etag_mutate(con->physical.etag, sce->etag);
32442 - response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag));
32443 + /* deflate it to file (cached) or to memory */
32444 + if (0 == deflate_file_to_file(srv, con, p,
32445 + con->physical.path, sce, compression_type) ||
32446 + 0 == deflate_file_to_buffer(srv, con, p,
32447 + con->physical.path, sce, compression_type)) {
32449 - response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
32450 + response_header_overwrite(srv, con,
32451 + CONST_STR_LEN("Content-Encoding"),
32452 + compression_name, strlen(compression_name));
32454 - return HANDLER_GO_ON;
32456 - } else if (0 == deflate_file_to_buffer(srv, con, p,
32457 - con->physical.path, sce, compression_type)) {
32459 - response_header_overwrite(srv, con, CONST_STR_LEN("Content-Encoding"), compression_name, strlen(compression_name));
32460 - response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type));
32462 + response_header_overwrite(srv, con,
32463 + CONST_STR_LEN("Content-Type"),
32464 + CONST_BUF_LEN(sce->content_type));
32466 return HANDLER_FINISHED;
32469 @@ -682,20 +728,20 @@
32475 return HANDLER_GO_ON;
32478 int mod_compress_plugin_init(plugin *p) {
32479 p->version = LIGHTTPD_VERSION_ID;
32480 p->name = buffer_init_string("compress");
32483 p->init = mod_compress_init;
32484 p->set_defaults = mod_compress_setdefaults;
32485 p->handle_subrequest_start = mod_compress_physical;
32486 p->cleanup = mod_compress_free;
32495 Property changes on: src/mod_compress.c
32496 ___________________________________________________________________
32497 Name: svn:eol-style
32501 ===================================================================
32502 --- src/md5.h (.../tags/lighttpd-1.4.11) (revision 1159)
32503 +++ src/md5.h (.../branches/lighttpd-merge-1.4.x) (revision 1159)
32505 # include <inttypes.h>
32509 +#define UINT4 unsigned __int32
32510 +#define UINT2 unsigned __int16
32511 +#define POINTER unsigned char *
32513 #define UINT4 uint32_t
32514 #define UINT2 uint16_t
32515 #define POINTER unsigned char *
32521 Property changes on: src/md5.h
32522 ___________________________________________________________________
32523 Name: svn:eol-style
32527 Property changes on: src/.cvsignore
32528 ___________________________________________________________________
32529 Name: svn:eol-style
32532 Index: src/mod_ssi.c
32533 ===================================================================
32534 --- src/mod_ssi.c (.../tags/lighttpd-1.4.11) (revision 1159)
32535 +++ src/mod_ssi.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
32537 #include <string.h>
32540 -#include <unistd.h>
32545 #include "inet_ntop_cache.h"
32547 #include "sys-socket.h"
32548 +#include "sys-strings.h"
32549 +#include "sys-files.h"
32553 @@ -39,15 +40,15 @@
32554 /* init the plugin data */
32555 INIT_FUNC(mod_ssi_init) {
32559 p = calloc(1, sizeof(*p));
32562 p->timefmt = buffer_init();
32563 p->stat_fn = buffer_init();
32566 p->ssi_vars = array_init();
32567 p->ssi_cgi_env = array_init();
32573 @@ -55,21 +56,21 @@
32574 FREE_FUNC(mod_ssi_free) {
32575 plugin_data *p = p_d;
32579 if (!p) return HANDLER_GO_ON;
32582 if (p->config_storage) {
32584 for (i = 0; i < srv->config_context->used; i++) {
32585 plugin_config *s = p->config_storage[i];
32588 array_free(s->ssi_extension);
32593 free(p->config_storage);
32597 array_free(p->ssi_vars);
32598 array_free(p->ssi_cgi_env);
32602 buffer_free(p->timefmt);
32603 buffer_free(p->stat_fn);
32609 return HANDLER_GO_ON;
32612 @@ -92,36 +93,36 @@
32613 const char *errptr;
32617 - config_values_t cv[] = {
32619 + config_values_t cv[] = {
32620 { "ssi.extension", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
32621 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
32625 if (!p) return HANDLER_ERROR;
32628 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
32631 for (i = 0; i < srv->config_context->used; i++) {
32635 s = calloc(1, sizeof(plugin_config));
32636 s->ssi_extension = array_init();
32639 cv[0].destination = s->ssi_extension;
32642 p->config_storage[i] = s;
32645 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
32646 return HANDLER_ERROR;
32652 /* allow 2 params */
32653 if (NULL == (p->ssi_regex = pcre_compile("<!--#([a-z]+)\\s+(?:([a-z]+)=\"(.*?)(?<!\\\\)\"\\s*)?(?:([a-z]+)=\"(.*?)(?<!\\\\)\"\\s*)?-->", 0, &errptr, &erroff, NULL))) {
32654 log_error_write(srv, __FILE__, __LINE__, "sds",
32658 return HANDLER_ERROR;
32660 @@ -130,52 +131,52 @@
32661 "mod_ssi: pcre support is missing, please recompile with pcre support or remove mod_ssi from the list of modules");
32662 return HANDLER_ERROR;
32666 return HANDLER_GO_ON;
32669 int ssi_env_add(array *env, const char *key, const char *val) {
32673 if (NULL == (ds = (data_string *)array_get_unused_element(env, TYPE_STRING))) {
32674 ds = data_string_init();
32676 buffer_copy_string(ds->key, key);
32677 buffer_copy_string(ds->value, val);
32680 array_insert_unique(env, (data_unset *)ds);
32688 * the next two functions are take from fcgi.c
32693 static int ssi_env_add_request_headers(server *srv, connection *con, plugin_data *p) {
32697 for (i = 0; i < con->request.headers->used; i++) {
32701 ds = (data_string *)con->request.headers->data[i];
32704 if (ds->value->used && ds->key->used) {
32706 buffer_reset(srv->tmp_buf);
32709 /* don't forward the Authorization: Header */
32710 if (0 == strcasecmp(ds->key->ptr, "AUTHORIZATION")) {
32715 if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
32716 buffer_copy_string(srv->tmp_buf, "HTTP_");
32717 srv->tmp_buf->used--;
32721 buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
32722 for (j = 0; j < ds->key->used - 1; j++) {
32724 @@ -189,33 +190,33 @@
32725 srv->tmp_buf->ptr[srv->tmp_buf->used++] = c;
32727 srv->tmp_buf->ptr[srv->tmp_buf->used] = '\0';
32730 ssi_env_add(p->ssi_cgi_env, srv->tmp_buf->ptr, ds->value->ptr);
32738 static int build_ssi_cgi_vars(server *srv, connection *con, plugin_data *p) {
32742 server_socket *srv_sock = con->srv_socket;
32746 char b2[INET6_ADDRSTRLEN + 1];
32749 #define CONST_STRING(x) \
32753 array_reset(p->ssi_cgi_env);
32756 ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_SOFTWARE"), PACKAGE_NAME"/"PACKAGE_VERSION);
32757 ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_NAME"),
32759 - inet_ntop(srv_sock->addr.plain.sa_family,
32760 - srv_sock->addr.plain.sa_family == AF_INET6 ?
32761 + inet_ntop(srv_sock->addr.plain.sa_family,
32762 + srv_sock->addr.plain.sa_family == AF_INET6 ?
32763 (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
32764 (const void *) &(srv_sock->addr.ipv4.sin_addr),
32766 @@ -224,28 +225,28 @@
32769 ssi_env_add(p->ssi_cgi_env, CONST_STRING("GATEWAY_INTERFACE"), "CGI/1.1");
32775 ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
32777 ntohs(srv_sock->addr.ipv4.sin_port)
32782 ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_PORT"), buf);
32785 ssi_env_add(p->ssi_cgi_env, CONST_STRING("REMOTE_ADDR"),
32786 inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
32789 if (con->authed_user->used) {
32790 ssi_env_add(p->ssi_cgi_env, CONST_STRING("REMOTE_USER"),
32791 con->authed_user->ptr);
32795 if (con->request.content_length > 0) {
32796 /* CGI-SPEC 6.1.2 and FastCGI spec 6.3 */
32799 /* request.content_length < SSIZE_MAX, see request.c */
32800 ltostr(buf, con->request.content_length);
32801 ssi_env_add(p->ssi_cgi_env, CONST_STRING("CONTENT_LENGTH"), buf);
32802 @@ -271,30 +272,30 @@
32803 if (con->request.pathinfo->used) {
32804 ssi_env_add(p->ssi_cgi_env, CONST_STRING("PATH_INFO"), con->request.pathinfo->ptr);
32808 ssi_env_add(p->ssi_cgi_env, CONST_STRING("SCRIPT_FILENAME"), con->physical.path->ptr);
32809 ssi_env_add(p->ssi_cgi_env, CONST_STRING("DOCUMENT_ROOT"), con->physical.doc_root->ptr);
32812 ssi_env_add(p->ssi_cgi_env, CONST_STRING("REQUEST_URI"), con->request.uri->ptr);
32813 ssi_env_add(p->ssi_cgi_env, CONST_STRING("QUERY_STRING"), con->uri.query->used ? con->uri.query->ptr : "");
32814 ssi_env_add(p->ssi_cgi_env, CONST_STRING("REQUEST_METHOD"), get_http_method_name(con->request.http_method));
32815 ssi_env_add(p->ssi_cgi_env, CONST_STRING("REDIRECT_STATUS"), "200");
32816 ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_PROTOCOL"), get_http_version_name(con->request.http_version));
32819 ssi_env_add_request_headers(srv, con, p);
32825 -static int process_ssi_stmt(server *srv, connection *con, plugin_data *p,
32826 +static int process_ssi_stmt(server *srv, connection *con, plugin_data *p,
32827 const char **l, size_t n) {
32828 size_t i, ssicmd = 0;
32836 - enum { SSI_UNSET, SSI_ECHO, SSI_FSIZE, SSI_INCLUDE, SSI_FLASTMOD,
32837 + enum { SSI_UNSET, SSI_ECHO, SSI_FSIZE, SSI_INCLUDE, SSI_FLASTMOD,
32838 SSI_CONFIG, SSI_PRINTENV, SSI_SET, SSI_IF, SSI_ELIF,
32839 SSI_ELSE, SSI_ENDIF, SSI_EXEC } type;
32841 @@ -310,27 +311,27 @@
32842 { "endif", SSI_ENDIF },
32843 { "else", SSI_ELSE },
32844 { "exec", SSI_EXEC },
32847 { NULL, SSI_UNSET }
32851 for (i = 0; ssicmds[i].var; i++) {
32852 if (0 == strcmp(l[1], ssicmds[i].var)) {
32853 ssicmd = ssicmds[i].type;
32862 int var = 0, enc = 0;
32863 const char *var_val = NULL;
32864 stat_cache_entry *sce = NULL;
32870 - enum { SSI_ECHO_UNSET, SSI_ECHO_DATE_GMT, SSI_ECHO_DATE_LOCAL, SSI_ECHO_DOCUMENT_NAME, SSI_ECHO_DOCUMENT_URI,
32871 + enum { SSI_ECHO_UNSET, SSI_ECHO_DATE_GMT, SSI_ECHO_DATE_LOCAL, SSI_ECHO_DOCUMENT_NAME, SSI_ECHO_DOCUMENT_URI,
32872 SSI_ECHO_LAST_MODIFIED, SSI_ECHO_USER_NAME } type;
32874 { "DATE_GMT", SSI_ECHO_DATE_GMT },
32875 @@ -339,27 +340,27 @@
32876 { "DOCUMENT_URI", SSI_ECHO_DOCUMENT_URI },
32877 { "LAST_MODIFIED", SSI_ECHO_LAST_MODIFIED },
32878 { "USER_NAME", SSI_ECHO_USER_NAME },
32881 { NULL, SSI_ECHO_UNSET }
32888 enum { SSI_ENC_UNSET, SSI_ENC_URL, SSI_ENC_NONE, SSI_ENC_ENTITY } type;
32890 { "url", SSI_ENC_URL },
32891 { "none", SSI_ENC_NONE },
32892 { "entity", SSI_ENC_ENTITY },
32895 { NULL, SSI_ENC_UNSET }
32899 for (i = 2; i < n; i += 2) {
32900 if (0 == strcmp(l[i], "var")) {
32907 for (j = 0; echovars[j].var; j++) {
32908 if (0 == strcmp(l[i+1], echovars[j].var)) {
32909 var = echovars[j].type;
32910 @@ -368,7 +369,7 @@
32912 } else if (0 == strcmp(l[i], "encoding")) {
32916 for (j = 0; encvars[j].var; j++) {
32917 if (0 == strcmp(l[i+1], encvars[j].var)) {
32918 enc = encvars[j].type;
32919 @@ -377,26 +378,26 @@
32922 log_error_write(srv, __FILE__, __LINE__, "sss",
32923 - "ssi: unknow attribute for ",
32924 + "ssi: unknow attribute for ",
32930 if (p->if_is_false) break;
32934 log_error_write(srv, __FILE__, __LINE__, "sss",
32937 l[1], "var is missing");
32941 stat_cache_get_entry(srv, con, con->physical.path, &sce);
32945 case SSI_ECHO_USER_NAME: {
32949 b = chunkqueue_get_append_buffer(con->write_queue);
32951 if (NULL == (pw = getpwuid(sce->st.st_uid))) {
32952 @@ -411,7 +412,7 @@
32954 case SSI_ECHO_LAST_MODIFIED: {
32955 time_t t = sce->st.st_mtime;
32958 b = chunkqueue_get_append_buffer(con->write_queue);
32959 if (0 == strftime(buf, sizeof(buf), p->timefmt->ptr, localtime(&t))) {
32960 buffer_copy_string(b, "(none)");
32961 @@ -422,7 +423,7 @@
32963 case SSI_ECHO_DATE_LOCAL: {
32964 time_t t = time(NULL);
32967 b = chunkqueue_get_append_buffer(con->write_queue);
32968 if (0 == strftime(buf, sizeof(buf), p->timefmt->ptr, localtime(&t))) {
32969 buffer_copy_string(b, "(none)");
32970 @@ -433,7 +434,7 @@
32972 case SSI_ECHO_DATE_GMT: {
32973 time_t t = time(NULL);
32976 b = chunkqueue_get_append_buffer(con->write_queue);
32977 if (0 == strftime(buf, sizeof(buf), p->timefmt->ptr, gmtime(&t))) {
32978 buffer_copy_string(b, "(none)");
32979 @@ -444,7 +445,7 @@
32981 case SSI_ECHO_DOCUMENT_NAME: {
32985 b = chunkqueue_get_append_buffer(con->write_queue);
32986 if (NULL == (sl = strrchr(con->physical.path->ptr, '/'))) {
32987 buffer_copy_string_buffer(b, con->physical.path);
32988 @@ -461,15 +462,15 @@
32991 /* check if it is a cgi-var */
32994 b = chunkqueue_get_append_buffer(con->write_queue);
32997 if (NULL != (ds = (data_string *)array_get_element(p->ssi_cgi_env, var_val))) {
32998 buffer_copy_string_buffer(b, ds->value);
33000 buffer_copy_string(b, "(none)");
33007 @@ -481,7 +482,7 @@
33008 const char * file_path = NULL, *virt_path = NULL;
33013 for (i = 2; i < n; i += 2) {
33014 if (0 == strcmp(l[i], "file")) {
33015 file_path = l[i+1];
33016 @@ -489,28 +490,28 @@
33017 virt_path = l[i+1];
33019 log_error_write(srv, __FILE__, __LINE__, "sss",
33020 - "ssi: unknow attribute for ",
33021 + "ssi: unknow attribute for ",
33027 if (!file_path && !virt_path) {
33028 log_error_write(srv, __FILE__, __LINE__, "sss",
33031 l[1], "file or virtual are missing");
33036 if (file_path && virt_path) {
33037 log_error_write(srv, __FILE__, __LINE__, "sss",
33040 l[1], "only one of file and virtual is allowed here");
33047 if (p->if_is_false) break;
33051 /* current doc-root */
33052 if (NULL == (sl = strrchr(con->physical.path->ptr, '/'))) {
33053 @@ -519,46 +520,46 @@
33054 buffer_copy_string_len(p->stat_fn, con->physical.path->ptr, sl - con->physical.path->ptr + 1);
33057 - buffer_copy_string(srv->tmp_buf, file_path);
33058 + buffer_copy_string(srv->tmp_buf, file_path);
33059 buffer_urldecode_path(srv->tmp_buf);
33060 - buffer_path_simplify(srv->tmp_buf, srv->tmp_buf);
33061 - buffer_append_string_buffer(p->stat_fn, srv->tmp_buf);
33062 + buffer_path_simplify(srv->tmp_buf, srv->tmp_buf);
33063 + buffer_append_string_buffer(p->stat_fn, srv->tmp_buf);
33068 if (virt_path[0] == '/') {
33069 buffer_copy_string(p->stat_fn, virt_path);
33071 /* there is always a / */
33072 sl = strrchr(con->uri.path->ptr, '/');
33075 buffer_copy_string_len(p->stat_fn, con->uri.path->ptr, sl - con->uri.path->ptr + 1);
33076 buffer_append_string(p->stat_fn, virt_path);
33080 buffer_urldecode_path(p->stat_fn);
33081 buffer_path_simplify(srv->tmp_buf, p->stat_fn);
33084 /* we have an uri */
33087 buffer_copy_string_buffer(p->stat_fn, con->physical.doc_root);
33088 buffer_append_string_buffer(p->stat_fn, srv->tmp_buf);
33092 if (0 == stat(p->stat_fn->ptr, &st)) {
33093 time_t t = st.st_mtime;
33098 b = chunkqueue_get_append_buffer(con->write_queue);
33101 const char *abr[] = { " B", " kB", " MB", " GB", " TB", NULL };
33104 off_t s = st.st_size;
33107 for (j = 0; s > 1024 && abr[j+1]; s /= 1024, j++);
33110 buffer_copy_off_t(b, s);
33111 buffer_append_string(b, abr[j]);
33113 @@ -579,7 +580,7 @@
33116 log_error_write(srv, __FILE__, __LINE__, "sbs",
33117 - "ssi: stating failed ",
33118 + "ssi: stating failed ",
33119 p->stat_fn, strerror(errno));
33122 @@ -593,33 +594,33 @@
33125 log_error_write(srv, __FILE__, __LINE__, "sss",
33126 - "ssi: unknow attribute for ",
33127 + "ssi: unknow attribute for ",
33133 if (p->if_is_false) break;
33140 if (NULL == (ds = (data_string *)array_get_unused_element(p->ssi_vars, TYPE_STRING))) {
33141 ds = data_string_init();
33143 buffer_copy_string(ds->key, key);
33144 buffer_copy_string(ds->value, val);
33147 array_insert_unique(p->ssi_vars, (data_unset *)ds);
33149 log_error_write(srv, __FILE__, __LINE__, "sss",
33150 - "ssi: var and value have to be set in",
33151 + "ssi: var and value have to be set in",
33158 if (p->if_is_false) break;
33161 for (i = 2; i < n; i += 2) {
33162 if (0 == strcmp(l[i], "timefmt")) {
33163 buffer_copy_string(p->timefmt, l[i+1]);
33164 @@ -632,63 +633,65 @@
33165 log_error_write(srv, __FILE__, __LINE__, "sssss",
33166 "ssi: unknow value for attribute '",
33173 log_error_write(srv, __FILE__, __LINE__, "sss",
33174 - "ssi: unknow attribute for ",
33175 + "ssi: unknow attribute for ",
33181 if (p->if_is_false) break;
33184 b = chunkqueue_get_append_buffer(con->write_queue);
33185 buffer_copy_string(b, "<pre>");
33186 for (i = 0; i < p->ssi_vars->used; i++) {
33187 data_string *ds = (data_string *)p->ssi_vars->data[p->ssi_vars->sorted[i]];
33190 buffer_append_string_buffer(b, ds->key);
33191 buffer_append_string(b, ": ");
33192 buffer_append_string_buffer(b, ds->value);
33193 buffer_append_string(b, "<br />");
33197 buffer_append_string(b, "</pre>");
33204 const char *cmd = NULL;
33206 int from_exec_fds[2];
33209 for (i = 2; i < n; i += 2) {
33210 if (0 == strcmp(l[i], "cmd")) {
33213 log_error_write(srv, __FILE__, __LINE__, "sss",
33214 - "ssi: unknow attribute for ",
33215 + "ssi: unknow attribute for ",
33221 if (p->if_is_false) break;
33224 /* create a return pipe and send output to the html-page
33226 - * as exec is assumed evil it is implemented synchronously
33228 + * as exec is assumed evil it is implemented synchronously
33235 if (pipe(from_exec_fds)) {
33236 - log_error_write(srv, __FILE__, __LINE__, "ss",
33237 + log_error_write(srv, __FILE__, __LINE__, "ss",
33238 "pipe failed: ", strerror(errno));
33244 switch (pid = fork()) {
33246 @@ -698,14 +701,14 @@
33247 close(from_exec_fds[1]);
33249 close(from_exec_fds[0]);
33253 close(STDIN_FILENO);
33256 execl("/bin/sh", "sh", "-c", cmd, NULL);
33259 log_error_write(srv, __FILE__, __LINE__, "sss", "spawing exec failed:", strerror(errno), cmd);
33265 @@ -718,9 +721,9 @@
33271 close(from_exec_fds[1]);
33274 /* wait for the client to end */
33275 if (-1 == waitpid(pid, &status, 0)) {
33276 log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed:", strerror(errno));
33277 @@ -730,7 +733,7 @@
33280 if (ioctl(from_exec_fds[0], FIONREAD, &toread)) {
33281 - log_error_write(srv, __FILE__, __LINE__, "s",
33282 + log_error_write(srv, __FILE__, __LINE__, "s",
33283 "unexpected end-of-file (perhaps the ssi-exec process died)");
33286 @@ -738,10 +741,10 @@
33288 b = chunkqueue_get_append_buffer(con->write_queue);
33290 - buffer_prepare_copy(b, toread + 1);
33291 + buffer_prepare_copy(b, toread + 1);
33293 if ((r = read(from_exec_fds[0], b->ptr, b->size - 1)) < 0) {
33294 - /* read failed */
33295 + /* read failed */
33299 @@ -755,59 +758,58 @@
33300 log_error_write(srv, __FILE__, __LINE__, "s", "process exited abnormally");
33302 close(from_exec_fds[0]);
33317 const char *expr = NULL;
33320 for (i = 2; i < n; i += 2) {
33321 if (0 == strcmp(l[i], "expr")) {
33324 log_error_write(srv, __FILE__, __LINE__, "sss",
33325 - "ssi: unknow attribute for ",
33326 + "ssi: unknow attribute for ",
33333 log_error_write(srv, __FILE__, __LINE__, "sss",
33336 l[1], "expr missing");
33341 if ((!p->if_is_false) &&
33342 - ((p->if_is_false_level == 0) ||
33343 + ((p->if_is_false_level == 0) ||
33344 (p->if_level < p->if_is_false_level))) {
33345 switch (ssi_eval_expr(srv, con, p, expr)) {
33348 - p->if_is_false = 1;
33350 + p->if_is_false = 1;
33351 p->if_is_false_level = p->if_level;
33354 - p->if_is_false = 0;
33356 + p->if_is_false = 0;
33371 if (p->if_is_false) {
33372 if ((p->if_level == p->if_is_false_level) &&
33373 (p->if_is_false_endif == 0)) {
33374 @@ -815,11 +817,11 @@
33377 p->if_is_false = 1;
33380 p->if_is_false_level = p->if_level;
33387 const char *expr = NULL;
33388 @@ -828,52 +830,52 @@
33391 log_error_write(srv, __FILE__, __LINE__, "sss",
33392 - "ssi: unknow attribute for ",
33393 + "ssi: unknow attribute for ",
33400 log_error_write(srv, __FILE__, __LINE__, "sss",
33403 l[1], "expr missing");
33411 if (p->if_level == p->if_is_false_level) {
33412 if ((p->if_is_false) &&
33413 (p->if_is_false_endif == 0)) {
33414 switch (ssi_eval_expr(srv, con, p, expr)) {
33417 - p->if_is_false = 1;
33419 + p->if_is_false = 1;
33420 p->if_is_false_level = p->if_level;
33423 - p->if_is_false = 0;
33425 + p->if_is_false = 0;
33429 - p->if_is_false = 1;
33430 + p->if_is_false = 1;
33431 p->if_is_false_level = p->if_level;
33432 p->if_is_false_endif = 1;
33446 if (p->if_level == p->if_is_false_level) {
33447 p->if_is_false = 0;
33448 p->if_is_false_endif = 0;
33454 log_error_write(srv, __FILE__, __LINE__, "ss",
33455 @@ -881,41 +883,41 @@
33466 static int mod_ssi_handle_request(server *srv, connection *con, plugin_data *p) {
33477 /* get a stream to the file */
33480 array_reset(p->ssi_vars);
33481 array_reset(p->ssi_cgi_env);
33482 buffer_copy_string(p->timefmt, "%a, %d %b %Y %H:%M:%S %Z");
33484 build_ssi_cgi_vars(srv, con, p);
33485 p->if_is_false = 0;
33488 if (-1 == stream_open(&s, con->physical.path)) {
33489 log_error_write(srv, __FILE__, __LINE__, "sb",
33490 "stream-open: ", con->physical.path);
33498 - * <!--#element attribute=value attribute=value ... -->
33500 + * <!--#element attribute=value attribute=value ... -->
33503 - * errmsg -- missing
33504 + * errmsg -- missing
33508 @@ -937,13 +939,13 @@
33525 @@ -951,118 +953,115 @@
33537 - * The current date in Greenwich Mean Time.
33539 - * The current date in the local time zone.
33541 - * The filename (excluding directories) of the document requested by the user.
33543 - * 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.
33545 - * The last modification date of the document requested by the user.
33548 + * The current date in Greenwich Mean Time.
33550 + * The current date in the local time zone.
33552 + * The filename (excluding directories) of the document requested by the user.
33554 + * 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.
33556 + * The last modification date of the document requested by the user.
33558 * Contains the owner of the file which included it.
33562 -#ifdef HAVE_PCRE_H
33563 +#ifdef HAVE_PCRE_H
33564 for (i = 0; (n = pcre_exec(p->ssi_regex, NULL, s.start, s.size, i, 0, ovec, N * 3)) > 0; i = ovec[1]) {
33566 /* take everything from last offset to current match pos */
33569 if (!p->if_is_false) chunkqueue_append_file(con->write_queue, con->physical.path, i, ovec[0] - i);
33572 pcre_get_substring_list(s.start, ovec, n, &l);
33573 process_ssi_stmt(srv, con, p, l, n);
33574 pcre_free_substring_list(l);
33579 case PCRE_ERROR_NOMATCH:
33580 /* copy everything/the rest */
33581 chunkqueue_append_file(con->write_queue, con->physical.path, i, s.size - i);
33586 log_error_write(srv, __FILE__, __LINE__, "sd",
33587 "execution error while matching: ", n);
33599 con->file_started = 1;
33600 con->file_finished = 1;
33603 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
33606 /* reset physical.path */
33607 buffer_reset(con->physical.path);
33613 -#define PATCH(x) \
33614 - p->conf.x = s->x;
33615 static int mod_ssi_patch_connection(server *srv, connection *con, plugin_data *p) {
33617 plugin_config *s = p->config_storage[0];
33619 - PATCH(ssi_extension);
33622 + PATCH_OPTION(ssi_extension);
33624 /* skip the first, the global context */
33625 for (i = 1; i < srv->config_context->used; i++) {
33626 data_config *dc = (data_config *)srv->config_context->data[i];
33627 s = p->config_storage[i];
33630 /* condition didn't match */
33631 if (!config_check_cond(srv, con, dc)) continue;
33635 for (j = 0; j < dc->value->used; j++) {
33636 data_unset *du = dc->value->data[j];
33639 if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssi.extension"))) {
33640 - PATCH(ssi_extension);
33641 + PATCH_OPTION(ssi_extension);
33651 URIHANDLER_FUNC(mod_ssi_physical_path) {
33652 plugin_data *p = p_d;
33656 if (con->physical.path->used == 0) return HANDLER_GO_ON;
33659 mod_ssi_patch_connection(srv, con, p);
33662 for (k = 0; k < p->conf.ssi_extension->used; k++) {
33663 data_string *ds = (data_string *)p->conf.ssi_extension->data[k];
33666 if (ds->value->used == 0) continue;
33669 if (buffer_is_equal_right_len(con->physical.path, ds->value, ds->value->used - 1)) {
33670 /* handle ssi-request */
33673 if (mod_ssi_handle_request(srv, con, p)) {
33675 con->http_status = 500;
33679 return HANDLER_FINISHED;
33685 return HANDLER_GO_ON;
33687 @@ -1072,13 +1071,13 @@
33688 int mod_ssi_plugin_init(plugin *p) {
33689 p->version = LIGHTTPD_VERSION_ID;
33690 p->name = buffer_init_string("ssi");
33693 p->init = mod_ssi_init;
33694 p->handle_subrequest_start = mod_ssi_physical_path;
33695 p->set_defaults = mod_ssi_set_defaults;
33696 p->cleanup = mod_ssi_free;
33705 Property changes on: src/mod_ssi.c
33706 ___________________________________________________________________
33707 Name: svn:eol-style
33710 Index: src/spawn-fcgi.c
33711 ===================================================================
33712 --- src/spawn-fcgi.c (.../tags/lighttpd-1.4.11) (revision 1159)
33713 +++ src/spawn-fcgi.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
33715 #include <sys/types.h>
33716 -#include <sys/time.h>
33717 #include <sys/stat.h>
33719 #include <stdlib.h>
33720 #include <string.h>
33723 -#include <unistd.h>
33727 #ifdef HAVE_CONFIG_H
33728 #include "config.h"
33738 #include "sys-socket.h"
33739 +#include "sys-files.h"
33741 #ifdef HAVE_SYS_WAIT_H
33742 #include <sys/wait.h>
33743 @@ -45,28 +43,28 @@
33745 int socket_type, status;
33746 struct timeval tv = { 0, 100 * 1000 };
33749 struct sockaddr_un fcgi_addr_un;
33750 struct sockaddr_in fcgi_addr_in;
33751 struct sockaddr *fcgi_addr;
33757 if (child_count < 2) {
33762 if (child_count > 256) {
33770 memset(&fcgi_addr, 0, sizeof(fcgi_addr));
33773 fcgi_addr_un.sun_family = AF_UNIX;
33774 strcpy(fcgi_addr_un.sun_path, unixsocket);
33778 servlen = SUN_LEN(&fcgi_addr_un);
33780 @@ -84,50 +82,50 @@
33782 fcgi_addr_in.sin_port = htons(port);
33783 servlen = sizeof(fcgi_addr_in);
33786 socket_type = AF_INET;
33787 fcgi_addr = (struct sockaddr *) &fcgi_addr_in;
33791 if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
33792 - fprintf(stderr, "%s.%d\n",
33793 + fprintf(stderr, "%s.%d\n",
33794 __FILE__, __LINE__);
33799 if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) {
33800 /* server is not up, spawn in */
33805 if (unixsocket) unlink(unixsocket);
33811 /* reopen socket */
33812 if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
33813 - fprintf(stderr, "%s.%d\n",
33814 + fprintf(stderr, "%s.%d\n",
33815 __FILE__, __LINE__);
33820 if (setsockopt(fcgi_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
33821 - fprintf(stderr, "%s.%d\n",
33822 + fprintf(stderr, "%s.%d\n",
33823 __FILE__, __LINE__);
33827 /* create socket */
33828 if (-1 == bind(fcgi_fd, fcgi_addr, servlen)) {
33829 - fprintf(stderr, "%s.%d: bind failed: %s\n",
33830 + fprintf(stderr, "%s.%d: bind failed: %s\n",
33831 __FILE__, __LINE__,
33837 if (-1 == listen(fcgi_fd, 1024)) {
33838 - fprintf(stderr, "%s.%d: fd = -1\n",
33839 + fprintf(stderr, "%s.%d: fd = -1\n",
33840 __FILE__, __LINE__);
33843 @@ -137,42 +135,45 @@
33851 char cgi_childs[64];
33858 + /* loose control terminal */
33861 /* is save as we limit to 256 childs */
33862 sprintf(cgi_childs, "PHP_FCGI_CHILDREN=%d", child_count);
33865 if(fcgi_fd != FCGI_LISTENSOCK_FILENO) {
33866 close(FCGI_LISTENSOCK_FILENO);
33867 dup2(fcgi_fd, FCGI_LISTENSOCK_FILENO);
33872 /* we don't need the client socket */
33873 for (i = 3; i < 256; i++) {
33878 /* create environment */
33881 putenv(cgi_childs);
33884 /* fork and replace shell */
33885 b = malloc(strlen("exec ") + strlen(appPath) + 1);
33886 strcpy(b, "exec ");
33887 strcat(b, appPath);
33891 execl("/bin/sh", "sh", "-c", b, NULL);
33900 @@ -180,47 +181,47 @@
33907 select(0, NULL, NULL, NULL, &tv);
33910 switch (waitpid(child, &status, WNOHANG)) {
33912 - fprintf(stderr, "%s.%d: child spawned successfully: PID: %d\n",
33913 + fprintf(stderr, "%s.%d: child spawned successfully: PID: %d\n",
33914 __FILE__, __LINE__,
33918 /* write pid file */
33919 if (pid_fd != -1) {
33920 /* assume a 32bit pid_t */
33924 snprintf(pidbuf, sizeof(pidbuf) - 1, "%d", child);
33927 write(pid_fd, pidbuf, strlen(pidbuf));
33937 if (WIFEXITED(status)) {
33938 - fprintf(stderr, "%s.%d: child exited with: %d, %s\n",
33939 + fprintf(stderr, "%s.%d: child exited with: %d, %s\n",
33940 __FILE__, __LINE__,
33941 WEXITSTATUS(status), strerror(WEXITSTATUS(status)));
33942 } else if (WIFSIGNALED(status)) {
33943 - fprintf(stderr, "%s.%d: child signaled: %d\n",
33944 + fprintf(stderr, "%s.%d: child signaled: %d\n",
33945 __FILE__, __LINE__,
33948 - fprintf(stderr, "%s.%d: child died somehow: %d\n",
33949 + fprintf(stderr, "%s.%d: child died somehow: %d\n",
33950 __FILE__, __LINE__,
33959 @@ -228,16 +229,16 @@
33960 __FILE__, __LINE__);
33972 void show_version () {
33973 char *b = "spawn-fcgi" "-" PACKAGE_VERSION \
33974 -" - spawns fastcgi processes\n"
33975 +" - spawns fastcgi processes\n"
33977 write(1, b, strlen(b));
33979 @@ -265,7 +266,7 @@
33982 int main(int argc, char **argv) {
33983 - char *fcgi_app = NULL, *changeroot = NULL, *username = NULL,
33984 + char *fcgi_app = NULL, *changeroot = NULL, *username = NULL,
33985 *groupname = NULL, *unixsocket = NULL, *pid_file = NULL,
33987 unsigned short port = 0;
33988 @@ -273,9 +274,9 @@
33994 i_am_root = (getuid() == 0);
33997 while(-1 != (o = getopt(argc, argv, "c:f:g:hna:p:u:vC:s:P:"))) {
33999 case 'f': fcgi_app = optarg; break;
34000 @@ -290,137 +291,137 @@
34001 case 'P': pid_file = optarg; /* PID file */ break;
34002 case 'v': show_version(); return 0;
34003 case 'h': show_help(); return 0;
34012 if (fcgi_app == NULL || (port == 0 && unixsocket == NULL)) {
34018 if (unixsocket && port) {
34019 - fprintf(stderr, "%s.%d: %s\n",
34020 + fprintf(stderr, "%s.%d: %s\n",
34021 __FILE__, __LINE__,
34022 "either a unix domain socket or a tcp-port, but not both\n");
34029 if (unixsocket && strlen(unixsocket) > UNIX_PATH_MAX - 1) {
34030 - fprintf(stderr, "%s.%d: %s\n",
34031 + fprintf(stderr, "%s.%d: %s\n",
34032 __FILE__, __LINE__,
34033 "path of the unix socket is too long\n");
34040 if (!i_am_root && (geteuid() == 0 || getegid() == 0)) {
34041 /* we are setuid-root */
34043 - fprintf(stderr, "%s.%d: %s\n",
34045 + fprintf(stderr, "%s.%d: %s\n",
34046 __FILE__, __LINE__,
34047 "Are you nuts ? Don't apply a SUID bit to this binary\n");
34056 (-1 == (pid_fd = open(pid_file, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)))) {
34058 if (errno != EEXIST) {
34059 - fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n",
34060 + fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n",
34061 __FILE__, __LINE__,
34062 pid_file, strerror(errno));
34069 /* ok, file exists */
34072 if (0 != stat(pid_file, &st)) {
34073 - fprintf(stderr, "%s.%d: stating pid-file '%s' failed: %s\n",
34074 + fprintf(stderr, "%s.%d: stating pid-file '%s' failed: %s\n",
34075 __FILE__, __LINE__,
34076 pid_file, strerror(errno));
34083 /* is it a regular file ? */
34086 if (!S_ISREG(st.st_mode)) {
34087 - fprintf(stderr, "%s.%d: pid-file exists and isn't regular file: '%s'\n",
34088 + fprintf(stderr, "%s.%d: pid-file exists and isn't regular file: '%s'\n",
34089 __FILE__, __LINE__,
34097 if (-1 == (pid_fd = open(pid_file, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
34098 - fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n",
34099 + fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n",
34100 __FILE__, __LINE__,
34101 pid_file, strerror(errno));
34110 struct group *grp = NULL;
34111 struct passwd *pwd = NULL;
34114 /* set user and group */
34118 if (NULL == (pwd = getpwnam(username))) {
34119 - fprintf(stderr, "%s.%d: %s, %s\n",
34120 + fprintf(stderr, "%s.%d: %s, %s\n",
34121 __FILE__, __LINE__,
34122 "can't find username", username);
34127 if (pwd->pw_uid == 0) {
34128 - fprintf(stderr, "%s.%d: %s\n",
34129 + fprintf(stderr, "%s.%d: %s\n",
34130 __FILE__, __LINE__,
34131 "I will not set uid to 0\n");
34138 if (NULL == (grp = getgrnam(groupname))) {
34139 - fprintf(stderr, "%s.%d: %s %s\n",
34140 + fprintf(stderr, "%s.%d: %s %s\n",
34141 __FILE__, __LINE__,
34142 - "can't find groupname",
34143 + "can't find groupname",
34147 if (grp->gr_gid == 0) {
34148 - fprintf(stderr, "%s.%d: %s\n",
34149 + fprintf(stderr, "%s.%d: %s\n",
34150 __FILE__, __LINE__,
34151 "I will not set gid to 0\n");
34158 if (-1 == chroot(changeroot)) {
34159 - fprintf(stderr, "%s.%d: %s %s\n",
34160 + fprintf(stderr, "%s.%d: %s %s\n",
34161 __FILE__, __LINE__,
34162 "chroot failed: ", strerror(errno));
34165 if (-1 == chdir("/")) {
34166 - fprintf(stderr, "%s.%d: %s %s\n",
34167 + fprintf(stderr, "%s.%d: %s %s\n",
34168 __FILE__, __LINE__,
34169 "chdir failed: ", strerror(errno));
34175 /* drop root privs */
34177 setgid(grp->gr_gid);
34178 @@ -428,7 +429,7 @@
34180 if (username) setuid(pwd->pw_uid);
34184 return fcgi_spawn_connection(fcgi_app, addr, port, unixsocket, child_count, pid_fd, nofork);
34188 Property changes on: src/spawn-fcgi.c
34189 ___________________________________________________________________
34190 Name: svn:eol-style
34193 Index: src/mod_sql_vhost_core.h
34194 ===================================================================
34195 --- src/mod_sql_vhost_core.h (.../tags/lighttpd-1.4.11) (revision 0)
34196 +++ src/mod_sql_vhost_core.h (.../branches/lighttpd-merge-1.4.x) (revision 1159)
34198 +#ifndef _MOD_SQL_VHOST_CORE_H_
34199 +#define _MOD_SQL_VHOST_CORE_H_
34201 +#include "buffer.h"
34202 +#include "plugin.h"
34204 +#define SQLVHOST_BACKEND_GETVHOST_PARAMS \
34205 + (server *srv, connection *con, void *p_d, buffer *docroot, buffer *host)
34207 +#define SQLVHOST_BACKEND_GETVHOST_RETVAL handler_t
34209 +#define SQLVHOST_BACKEND_GETVHOST(name) \
34210 + SQLVHOST_BACKEND_GETVHOST_RETVAL name SQLVHOST_BACKEND_GETVHOST_PARAMS
34212 +#define SQLVHOST_BACKEND_GETVHOST_PTR(name) \
34213 + SQLVHOST_BACKEND_GETVHOST_RETVAL (* name)SQLVHOST_BACKEND_GETVHOST_PARAMS
34221 + buffer *hostname;
34222 + unsigned short port;
34225 + void *backend_data;
34227 + buffer *select_vhost;
34229 + SQLVHOST_BACKEND_GETVHOST_PTR(get_vhost);
34230 +} mod_sql_vhost_core_plugin_config;
34232 +/* global plugin data */
34239 + mod_sql_vhost_core_plugin_config **config_storage;
34241 + mod_sql_vhost_core_plugin_config conf;
34242 +} mod_sql_vhost_core_plugin_data;
34247 Index: src/mod_auth.c
34248 ===================================================================
34249 --- src/mod_auth.c (.../tags/lighttpd-1.4.11) (revision 1159)
34250 +++ src/mod_auth.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
34251 @@ -5,168 +5,167 @@
34252 #include <string.h>
34255 -#include <unistd.h>
34257 #include "plugin.h"
34258 #include "http_auth.h"
34260 #include "response.h"
34262 +#include "sys-strings.h"
34263 +#include "sys-files.h"
34265 handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s);
34269 * the basic and digest auth framework
34272 * - config handling
34273 * - protocol handling
34276 - * http_auth_digest.c
34280 + * http_auth_digest.c
34285 INIT_FUNC(mod_auth_init) {
34286 mod_auth_plugin_data *p;
34289 p = calloc(1, sizeof(*p));
34292 p->tmp_buf = buffer_init();
34295 p->auth_user = buffer_init();
34297 p->ldap_filter = buffer_init();
34304 FREE_FUNC(mod_auth_free) {
34305 mod_auth_plugin_data *p = p_d;
34310 if (!p) return HANDLER_GO_ON;
34313 buffer_free(p->tmp_buf);
34314 buffer_free(p->auth_user);
34316 buffer_free(p->ldap_filter);
34320 if (p->config_storage) {
34322 for (i = 0; i < srv->config_context->used; i++) {
34323 mod_auth_plugin_config *s = p->config_storage[i];
34329 array_free(s->auth_require);
34330 buffer_free(s->auth_plain_groupfile);
34331 buffer_free(s->auth_plain_userfile);
34332 buffer_free(s->auth_htdigest_userfile);
34333 buffer_free(s->auth_htpasswd_userfile);
34334 buffer_free(s->auth_backend_conf);
34337 buffer_free(s->auth_ldap_hostname);
34338 buffer_free(s->auth_ldap_basedn);
34339 buffer_free(s->auth_ldap_binddn);
34340 buffer_free(s->auth_ldap_bindpw);
34341 buffer_free(s->auth_ldap_filter);
34342 buffer_free(s->auth_ldap_cafile);
34346 buffer_free(s->ldap_filter_pre);
34347 buffer_free(s->ldap_filter_post);
34350 if (s->ldap) ldap_unbind_s(s->ldap);
34356 free(p->config_storage);
34363 return HANDLER_GO_ON;
34366 -#define PATCH(x) \
34367 - p->conf.x = s->x;
34368 static int mod_auth_patch_connection(server *srv, connection *con, mod_auth_plugin_data *p) {
34370 mod_auth_plugin_config *s = p->config_storage[0];
34372 - PATCH(auth_backend);
34373 - PATCH(auth_plain_groupfile);
34374 - PATCH(auth_plain_userfile);
34375 - PATCH(auth_htdigest_userfile);
34376 - PATCH(auth_htpasswd_userfile);
34377 - PATCH(auth_require);
34378 - PATCH(auth_debug);
34379 - PATCH(auth_ldap_hostname);
34380 - PATCH(auth_ldap_basedn);
34381 - PATCH(auth_ldap_binddn);
34382 - PATCH(auth_ldap_bindpw);
34383 - PATCH(auth_ldap_filter);
34384 - PATCH(auth_ldap_cafile);
34385 - PATCH(auth_ldap_starttls);
34386 + PATCH_OPTION(auth_backend);
34387 + PATCH_OPTION(auth_plain_groupfile);
34388 + PATCH_OPTION(auth_plain_userfile);
34389 + PATCH_OPTION(auth_htdigest_userfile);
34390 + PATCH_OPTION(auth_htpasswd_userfile);
34391 + PATCH_OPTION(auth_require);
34392 + PATCH_OPTION(auth_debug);
34393 + PATCH_OPTION(auth_ldap_hostname);
34394 + PATCH_OPTION(auth_ldap_basedn);
34395 + PATCH_OPTION(auth_ldap_binddn);
34396 + PATCH_OPTION(auth_ldap_bindpw);
34397 + PATCH_OPTION(auth_ldap_filter);
34398 + PATCH_OPTION(auth_ldap_cafile);
34399 + PATCH_OPTION(auth_ldap_starttls);
34402 - PATCH(ldap_filter_pre);
34403 - PATCH(ldap_filter_post);
34404 + PATCH_OPTION(ldap);
34405 + PATCH_OPTION(ldap_filter_pre);
34406 + PATCH_OPTION(ldap_filter_post);
34410 /* skip the first, the global context */
34411 for (i = 1; i < srv->config_context->used; i++) {
34412 data_config *dc = (data_config *)srv->config_context->data[i];
34413 s = p->config_storage[i];
34416 /* condition didn't match */
34417 if (!config_check_cond(srv, con, dc)) continue;
34421 for (j = 0; j < dc->value->used; j++) {
34422 data_unset *du = dc->value->data[j];
34425 if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend"))) {
34426 - PATCH(auth_backend);
34427 + PATCH_OPTION(auth_backend);
34428 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.plain.groupfile"))) {
34429 - PATCH(auth_plain_groupfile);
34430 + PATCH_OPTION(auth_plain_groupfile);
34431 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.plain.userfile"))) {
34432 - PATCH(auth_plain_userfile);
34433 + PATCH_OPTION(auth_plain_userfile);
34434 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.htdigest.userfile"))) {
34435 - PATCH(auth_htdigest_userfile);
34436 + PATCH_OPTION(auth_htdigest_userfile);
34437 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.htpasswd.userfile"))) {
34438 - PATCH(auth_htpasswd_userfile);
34439 + PATCH_OPTION(auth_htpasswd_userfile);
34440 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.require"))) {
34441 - PATCH(auth_require);
34442 + PATCH_OPTION(auth_require);
34443 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.debug"))) {
34444 - PATCH(auth_debug);
34445 + PATCH_OPTION(auth_debug);
34446 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.hostname"))) {
34447 - PATCH(auth_ldap_hostname);
34448 + PATCH_OPTION(auth_ldap_hostname);
34451 - PATCH(ldap_filter_pre);
34452 - PATCH(ldap_filter_post);
34453 + PATCH_OPTION(ldap);
34454 + PATCH_OPTION(ldap_filter_pre);
34455 + PATCH_OPTION(ldap_filter_post);
34457 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.base-dn"))) {
34458 - PATCH(auth_ldap_basedn);
34459 + PATCH_OPTION(auth_ldap_basedn);
34460 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.filter"))) {
34461 - PATCH(auth_ldap_filter);
34462 + PATCH_OPTION(auth_ldap_filter);
34463 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.ca-file"))) {
34464 - PATCH(auth_ldap_cafile);
34465 + PATCH_OPTION(auth_ldap_cafile);
34466 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.starttls"))) {
34467 - PATCH(auth_ldap_starttls);
34468 + PATCH_OPTION(auth_ldap_starttls);
34478 static handler_t mod_auth_uri_handler(server *srv, connection *con, void *p_d) {
34480 @@ -175,22 +174,22 @@
34482 mod_auth_plugin_data *p = p_d;
34486 /* select the right config */
34487 mod_auth_patch_connection(srv, con, p);
34490 if (p->conf.auth_require == NULL) return HANDLER_GO_ON;
34500 /* do we have to ask for auth ? */
34504 auth_satisfied = 0;
34507 /* search auth-directives for path */
34508 for (k = 0; k < p->conf.auth_require->used; k++) {
34509 buffer *req = p->conf.auth_require->data[k]->key;
34510 @@ -212,31 +211,31 @@
34516 /* nothing to do for us */
34517 if (auth_required == 0) return HANDLER_GO_ON;
34520 req = ((data_array *)(p->conf.auth_require->data[k]))->value;
34523 /* try to get Authorization-header */
34526 if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Authorization"))) {
34527 http_authorization = ds->value->ptr;
34531 if (ds && ds->value && ds->value->used) {
34533 data_string *method;
34536 method = (data_string *)array_get_element(req, "method");
34539 /* parse auth-header */
34540 if (NULL != (auth_realm = strchr(http_authorization, ' '))) {
34541 int auth_type_len = auth_realm - http_authorization;
34544 if ((auth_type_len == 5) &&
34545 (0 == strncmp(http_authorization, "Basic", auth_type_len))) {
34548 if (0 == strcmp(method->value->ptr, "basic")) {
34549 auth_satisfied = http_auth_basic_check(srv, con, p, req, con->uri.path, auth_realm+1);
34551 @@ -245,43 +244,43 @@
34552 if (0 == strcmp(method->value->ptr, "digest")) {
34553 if (-1 == (auth_satisfied = http_auth_digest_check(srv, con, p, req, con->uri.path, auth_realm+1))) {
34554 con->http_status = 400;
34557 /* a field was missing */
34560 return HANDLER_FINISHED;
34564 - log_error_write(srv, __FILE__, __LINE__, "ss",
34565 + log_error_write(srv, __FILE__, __LINE__, "ss",
34566 "unknown authentification type:",
34567 http_authorization);
34573 if (!auth_satisfied) {
34574 data_string *method, *realm;
34575 method = (data_string *)array_get_element(req, "method");
34576 realm = (data_string *)array_get_element(req, "realm");
34579 con->http_status = 401;
34582 if (0 == strcmp(method->value->ptr, "basic")) {
34583 buffer_copy_string(p->tmp_buf, "Basic realm=\"");
34584 buffer_append_string_buffer(p->tmp_buf, realm->value);
34585 buffer_append_string(p->tmp_buf, "\"");
34588 response_header_insert(srv, con, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(p->tmp_buf));
34589 } else if (0 == strcmp(method->value->ptr, "digest")) {
34591 http_auth_digest_generate_nonce(srv, p, srv->tmp_buf, hh);
34594 buffer_copy_string(p->tmp_buf, "Digest realm=\"");
34595 buffer_append_string_buffer(p->tmp_buf, realm->value);
34596 buffer_append_string(p->tmp_buf, "\", nonce=\"");
34597 buffer_append_string(p->tmp_buf, hh);
34598 buffer_append_string(p->tmp_buf, "\", qop=\"auth\"");
34601 response_header_insert(srv, con, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(p->tmp_buf));
34604 @@ -289,18 +288,18 @@
34605 return HANDLER_FINISHED;
34607 /* the REMOTE_USER header */
34610 buffer_copy_string_buffer(con->authed_user, p->auth_user);
34614 return HANDLER_GO_ON;
34617 SETDEFAULTS_FUNC(mod_auth_set_defaults) {
34618 mod_auth_plugin_data *p = p_d;
34621 - config_values_t cv[] = {
34623 + config_values_t cv[] = {
34624 { "auth.backend", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
34625 { "auth.backend.plain.groupfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
34626 { "auth.backend.plain.userfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
34627 @@ -317,7 +316,7 @@
34628 { "auth.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 13 */
34629 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
34633 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
34635 for (i = 0; i < srv->config_context->used; i++) {
34636 @@ -325,14 +324,14 @@
34642 s = calloc(1, sizeof(mod_auth_plugin_config));
34643 s->auth_plain_groupfile = buffer_init();
34644 s->auth_plain_userfile = buffer_init();
34645 s->auth_htdigest_userfile = buffer_init();
34646 s->auth_htpasswd_userfile = buffer_init();
34647 s->auth_backend_conf = buffer_init();
34650 s->auth_ldap_hostname = buffer_init();
34651 s->auth_ldap_basedn = buffer_init();
34652 s->auth_ldap_binddn = buffer_init();
34653 @@ -341,15 +340,15 @@
34654 s->auth_ldap_cafile = buffer_init();
34655 s->auth_ldap_starttls = 0;
34659 s->auth_require = array_init();
34663 s->ldap_filter_pre = buffer_init();
34664 s->ldap_filter_post = buffer_init();
34669 cv[0].destination = s->auth_backend_conf;
34670 cv[1].destination = s->auth_plain_groupfile;
34671 cv[2].destination = s->auth_plain_userfile;
34672 @@ -364,14 +363,14 @@
34673 cv[11].destination = s->auth_htdigest_userfile;
34674 cv[12].destination = s->auth_htpasswd_userfile;
34675 cv[13].destination = &(s->auth_debug);
34678 p->config_storage[i] = s;
34679 ca = ((data_config *)srv->config_context->data[i])->value;
34682 if (0 != config_insert_values_global(srv, ca, cv)) {
34683 return HANDLER_ERROR;
34687 if (s->auth_backend_conf->used) {
34688 if (0 == strcmp(s->auth_backend_conf->ptr, "htpasswd")) {
34689 s->auth_backend = AUTH_BACKEND_HTPASSWD;
34690 @@ -383,31 +382,31 @@
34691 s->auth_backend = AUTH_BACKEND_LDAP;
34693 log_error_write(srv, __FILE__, __LINE__, "sb", "auth.backend not supported:", s->auth_backend_conf);
34696 return HANDLER_ERROR;
34700 /* no auth.require for this section */
34701 if (NULL == (da = (data_array *)array_get_element(ca, "auth.require"))) continue;
34704 if (da->type != TYPE_ARRAY) continue;
34707 for (n = 0; n < da->value->used; n++) {
34709 data_array *da_file = (data_array *)da->value->data[n];
34710 const char *method, *realm, *require;
34713 if (da->value->data[n]->type != TYPE_ARRAY) {
34714 - log_error_write(srv, __FILE__, __LINE__, "ss",
34715 - "auth.require should contain an array as in:",
34716 + log_error_write(srv, __FILE__, __LINE__, "ss",
34717 + "auth.require should contain an array as in:",
34718 "auth.require = ( \"...\" => ( ..., ...) )");
34720 return HANDLER_ERROR;
34724 method = realm = require = NULL;
34727 for (m = 0; m < da_file->value->used; m++) {
34728 if (da_file->value->data[m]->type == TYPE_STRING) {
34729 if (0 == strcmp(da_file->value->data[m]->key->ptr, "method")) {
34730 @@ -417,8 +416,8 @@
34731 } else if (0 == strcmp(da_file->value->data[m]->key->ptr, "require")) {
34732 require = ((data_string *)(da_file->value->data[m]))->value->ptr;
34734 - log_error_write(srv, __FILE__, __LINE__, "ssbs",
34735 - "the field is unknown in:",
34736 + log_error_write(srv, __FILE__, __LINE__, "ssbs",
34737 + "the field is unknown in:",
34738 "auth.require = ( \"...\" => ( ..., -> \"",
34739 da_file->value->data[m]->key,
34740 "\" <- => \"...\" ) )");
34741 @@ -426,19 +425,19 @@
34742 return HANDLER_ERROR;
34745 - log_error_write(srv, __FILE__, __LINE__, "ssbs",
34746 - "a string was expected for:",
34747 + log_error_write(srv, __FILE__, __LINE__, "ssbs",
34748 + "a string was expected for:",
34749 "auth.require = ( \"...\" => ( ..., -> \"",
34750 da_file->value->data[m]->key,
34751 "\" <- => \"...\" ) )");
34754 return HANDLER_ERROR;
34759 if (method == NULL) {
34760 - log_error_write(srv, __FILE__, __LINE__, "ss",
34761 - "the require field is missing in:",
34762 + log_error_write(srv, __FILE__, __LINE__, "ss",
34763 + "the require field is missing in:",
34764 "auth.require = ( \"...\" => ( ..., \"method\" => \"...\" ) )");
34765 return HANDLER_ERROR;
34767 @@ -450,60 +449,60 @@
34768 return HANDLER_ERROR;
34773 if (realm == NULL) {
34774 - log_error_write(srv, __FILE__, __LINE__, "ss",
34775 - "the require field is missing in:",
34776 + log_error_write(srv, __FILE__, __LINE__, "ss",
34777 + "the require field is missing in:",
34778 "auth.require = ( \"...\" => ( ..., \"realm\" => \"...\" ) )");
34779 return HANDLER_ERROR;
34783 if (require == NULL) {
34784 - log_error_write(srv, __FILE__, __LINE__, "ss",
34785 - "the require field is missing in:",
34786 + log_error_write(srv, __FILE__, __LINE__, "ss",
34787 + "the require field is missing in:",
34788 "auth.require = ( \"...\" => ( ..., \"require\" => \"...\" ) )");
34789 return HANDLER_ERROR;
34793 if (method && realm && require) {
34798 a = data_array_init();
34799 buffer_copy_string_buffer(a->key, da_file->key);
34802 ds = data_string_init();
34805 buffer_copy_string(ds->key, "method");
34806 buffer_copy_string(ds->value, method);
34809 array_insert_unique(a->value, (data_unset *)ds);
34812 ds = data_string_init();
34815 buffer_copy_string(ds->key, "realm");
34816 buffer_copy_string(ds->value, realm);
34819 array_insert_unique(a->value, (data_unset *)ds);
34822 ds = data_string_init();
34825 buffer_copy_string(ds->key, "require");
34826 buffer_copy_string(ds->value, require);
34829 array_insert_unique(a->value, (data_unset *)ds);
34832 array_insert_unique(s->auth_require, (data_unset *)a);
34837 switch(s->auth_backend) {
34838 case AUTH_BACKEND_PLAIN:
34839 if (s->auth_plain_userfile->used) {
34842 if (-1 == (fd = open(s->auth_plain_userfile->ptr, O_RDONLY))) {
34843 - log_error_write(srv, __FILE__, __LINE__, "sbss",
34844 + log_error_write(srv, __FILE__, __LINE__, "sbss",
34845 "opening auth.backend.plain.userfile:", s->auth_plain_userfile,
34846 "failed:", strerror(errno));
34847 return HANDLER_ERROR;
34848 @@ -516,7 +515,7 @@
34851 if (-1 == (fd = open(s->auth_htpasswd_userfile->ptr, O_RDONLY))) {
34852 - log_error_write(srv, __FILE__, __LINE__, "sbss",
34853 + log_error_write(srv, __FILE__, __LINE__, "sbss",
34854 "opening auth.backend.htpasswd.userfile:", s->auth_htpasswd_userfile,
34855 "failed:", strerror(errno));
34856 return HANDLER_ERROR;
34857 @@ -529,7 +528,7 @@
34860 if (-1 == (fd = open(s->auth_htdigest_userfile->ptr, O_RDONLY))) {
34861 - log_error_write(srv, __FILE__, __LINE__, "sbss",
34862 + log_error_write(srv, __FILE__, __LINE__, "sbss",
34863 "opening auth.backend.htdigest.userfile:", s->auth_htdigest_userfile,
34864 "failed:", strerror(errno));
34865 return HANDLER_ERROR;
34866 @@ -554,75 +553,75 @@
34867 handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s) {
34872 if (s->auth_ldap_basedn->used == 0) {
34873 log_error_write(srv, __FILE__, __LINE__, "s", "ldap: auth.backend.ldap.base-dn has to be set");
34876 return HANDLER_ERROR;
34881 if (s->auth_ldap_filter->used) {
34888 if (NULL == (dollar = strchr(s->auth_ldap_filter->ptr, '$'))) {
34889 log_error_write(srv, __FILE__, __LINE__, "s", "ldap: auth.backend.ldap.filter is missing a replace-operator '$'");
34892 return HANDLER_ERROR;
34896 buffer_copy_string_len(s->ldap_filter_pre, s->auth_ldap_filter->ptr, dollar - s->auth_ldap_filter->ptr);
34897 buffer_copy_string(s->ldap_filter_post, dollar+1);
34901 if (s->auth_ldap_hostname->used) {
34902 if (NULL == (s->ldap = ldap_init(s->auth_ldap_hostname->ptr, LDAP_PORT))) {
34903 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap ...", strerror(errno));
34906 return HANDLER_ERROR;
34910 ret = LDAP_VERSION3;
34911 if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(s->ldap, LDAP_OPT_PROTOCOL_VERSION, &ret))) {
34912 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
34915 return HANDLER_ERROR;
34918 if (s->auth_ldap_starttls) {
34919 - /* if no CA file is given, it is ok, as we will use encryption
34920 + /* if no CA file is given, it is ok, as we will use encryption
34921 * if the server requires a CAfile it will tell us */
34922 if (!buffer_is_empty(s->auth_ldap_cafile)) {
34923 - if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE,
34924 + if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE,
34925 s->auth_ldap_cafile->ptr))) {
34926 - log_error_write(srv, __FILE__, __LINE__, "ss",
34927 + log_error_write(srv, __FILE__, __LINE__, "ss",
34928 "Loading CA certificate failed:", ldap_err2string(ret));
34931 return HANDLER_ERROR;
34936 if (LDAP_OPT_SUCCESS != (ret = ldap_start_tls_s(s->ldap, NULL, NULL))) {
34937 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap startTLS failed:", ldap_err2string(ret));
34940 return HANDLER_ERROR;
34948 if (s->auth_ldap_binddn->used) {
34949 if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(s->ldap, s->auth_ldap_binddn->ptr, s->auth_ldap_bindpw->ptr))) {
34950 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
34953 return HANDLER_ERROR;
34956 if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(s->ldap, NULL, NULL))) {
34957 log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
34960 return HANDLER_ERROR;
34963 @@ -641,8 +640,8 @@
34964 p->set_defaults = mod_auth_set_defaults;
34965 p->handle_uri_clean = mod_auth_uri_handler;
34966 p->cleanup = mod_auth_free;
34975 Property changes on: src/mod_auth.c
34976 ___________________________________________________________________
34977 Name: svn:eol-style
34980 Index: src/mod_ssi.h
34981 ===================================================================
34982 --- src/mod_ssi.h (.../tags/lighttpd-1.4.11) (revision 1159)
34983 +++ src/mod_ssi.h (.../branches/lighttpd-merge-1.4.x) (revision 1159)
34984 @@ -19,23 +19,23 @@
34989 -#ifdef HAVE_PCRE_H
34991 +#ifdef HAVE_PCRE_H
35003 array *ssi_cgi_env;
35006 int if_level, if_is_false_level, if_is_false, if_is_false_endif;
35009 plugin_config **config_storage;
35011 - plugin_config conf;
35013 + plugin_config conf;
35016 int ssi_eval_expr(server *srv, connection *con, plugin_data *p, const char *expr);
35018 Property changes on: src/mod_ssi.h
35019 ___________________________________________________________________
35020 Name: svn:eol-style
35023 Index: src/settings.h
35024 ===================================================================
35025 --- src/settings.h (.../tags/lighttpd-1.4.11) (revision 1159)
35026 +++ src/settings.h (.../branches/lighttpd-merge-1.4.x) (revision 1159)
35029 * max size of a buffer which will just be reset
35030 * to ->used = 0 instead of really freeing the buffer
35033 * 64kB (no real reason, just a guess)
35035 #define BUFFER_MAX_REUSE_SIZE (4 * 1024)
35038 * max size of the HTTP request header
35041 * 32k should be enough for everything (just a guess)
35045 #define MAX_HTTP_REQUEST_HEADER (32 * 1024)
35047 -typedef enum { HANDLER_UNSET,
35049 +typedef enum { HANDLER_UNSET,
35052 - HANDLER_COMEBACK,
35053 - HANDLER_WAIT_FOR_EVENT,
35054 + HANDLER_COMEBACK,
35055 + HANDLER_WAIT_FOR_EVENT,
35057 HANDLER_WAIT_FOR_FD
35060 Property changes on: src/settings.h
35061 ___________________________________________________________________
35062 Name: svn:eol-style
35066 Property changes on: src/mod_auth.h
35067 ___________________________________________________________________
35068 Name: svn:eol-style
35071 Index: src/mod_cml_lua.c
35072 ===================================================================
35073 --- src/mod_cml_lua.c (.../tags/lighttpd-1.4.11) (revision 1159)
35074 +++ src/mod_cml_lua.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
35087 #include <lualib.h>
35088 +#include <lauxlib.h>
35092 @@ -39,11 +40,11 @@
35094 static const char * load_file(lua_State *L, void *data, size_t *size) {
35101 if (rm->done) return 0;
35104 *size = rm->st.size;
35106 return rm->st.start;
35107 @@ -51,47 +52,47 @@
35109 static int lua_to_c_get_string(lua_State *L, const char *varname, buffer *b) {
35113 lua_pushstring(L, varname);
35116 curelem = lua_gettop(L);
35117 lua_gettable(L, LUA_GLOBALSINDEX);
35120 /* it should be a table */
35121 if (!lua_isstring(L, curelem)) {
35122 lua_settop(L, curelem - 1);
35129 buffer_copy_string(b, lua_tostring(L, curelem));
35135 assert(curelem - 1 == lua_gettop(L));
35141 static int lua_to_c_is_table(lua_State *L, const char *varname) {
35145 lua_pushstring(L, varname);
35148 curelem = lua_gettop(L);
35149 lua_gettable(L, LUA_GLOBALSINDEX);
35152 /* it should be a table */
35153 if (!lua_istable(L, curelem)) {
35154 lua_settop(L, curelem - 1);
35161 lua_settop(L, curelem - 1);
35164 assert(curelem - 1 == lua_gettop(L));
35171 lua_pushlstring(L, key, key_len);
35172 lua_pushlstring(L, val, val_len);
35173 lua_settable(L, tbl);
35179 @@ -108,21 +109,21 @@
35182 char *key = NULL, *val = NULL;
35188 /* we need the \0 */
35189 for (i = 0; i < qrystr->used; i++) {
35190 switch(qrystr->ptr[i]) {
35193 val = qrystr->ptr + i + 1;
35196 qrystr->ptr[i] = '\0';
35205 case '\0': /* fin symbol */
35206 @@ -131,19 +132,19 @@
35208 /* terminate the value */
35209 qrystr->ptr[i] = '\0';
35211 - c_to_lua_push(L, tbl,
35213 + c_to_lua_push(L, tbl,
35219 key = qrystr->ptr + i + 1;
35230 @@ -151,21 +152,21 @@
35236 if (NULL != (d = array_get_element(con->request.headers, "Cookie"))) {
35237 data_string *ds = (data_string *)d;
35238 size_t key = 0, value = 0;
35239 size_t is_key = 1, is_sid = 0;
35244 if (!DATA_IS_STRING(d)) return -1;
35245 if (ds->value->used == 0) return -1;
35248 if (ds->value->ptr[0] == '\0' ||
35249 ds->value->ptr[0] == '=' ||
35250 ds->value->ptr[0] == ';') return -1;
35253 buffer_reset(p->session_id);
35254 for (i = 0; i < ds->value->used; i++) {
35255 switch(ds->value->ptr[i]) {
35256 @@ -176,16 +177,16 @@
35269 buffer_copy_string_len(p->session_id, ds->value->ptr + value, i - value);
35276 @@ -204,48 +205,43 @@
35286 int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn) {
35291 buffer *b = buffer_init();
35292 int header_tbl = 0;
35296 stream_open(&rm.st, fn);
35299 /* push the lua file to the interpreter and see what happends */
35303 - luaopen_table(L);
35304 - luaopen_string(L);
35308 + L = luaL_newstate();
35309 + luaL_openlibs(L);
35311 /* register functions */
35312 lua_register(L, "md5", f_crypto_md5);
35313 lua_register(L, "file_mtime", f_file_mtime);
35314 lua_register(L, "file_isreg", f_file_isreg);
35315 lua_register(L, "file_isdir", f_file_isreg);
35316 lua_register(L, "dir_files", f_dir_files);
35319 #ifdef HAVE_MEMCACHE_H
35320 lua_pushliteral(L, "memcache_get_long");
35321 lua_pushlightuserdata(L, p->conf.mc);
35322 lua_pushcclosure(L, f_memcache_get_long, 1);
35323 lua_settable(L, LUA_GLOBALSINDEX);
35326 lua_pushliteral(L, "memcache_get_string");
35327 lua_pushlightuserdata(L, p->conf.mc);
35328 lua_pushcclosure(L, f_memcache_get_string, 1);
35329 lua_settable(L, LUA_GLOBALSINDEX);
35332 lua_pushliteral(L, "memcache_exists");
35333 lua_pushlightuserdata(L, p->conf.mc);
35334 lua_pushcclosure(L, f_memcache_exists, 1);
35335 @@ -255,11 +251,11 @@
35336 lua_pushliteral(L, "request");
35338 lua_settable(L, LUA_GLOBALSINDEX);
35341 lua_pushliteral(L, "request");
35342 header_tbl = lua_gettop(L);
35343 lua_gettable(L, LUA_GLOBALSINDEX);
35346 c_to_lua_push(L, header_tbl, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri));
35347 c_to_lua_push(L, header_tbl, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
35348 c_to_lua_push(L, header_tbl, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(con->physical.path));
35349 @@ -267,84 +263,84 @@
35350 if (!buffer_is_empty(con->request.pathinfo)) {
35351 c_to_lua_push(L, header_tbl, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo));
35355 c_to_lua_push(L, header_tbl, CONST_STR_LEN("CWD"), CONST_BUF_LEN(p->basedir));
35356 c_to_lua_push(L, header_tbl, CONST_STR_LEN("BASEURL"), CONST_BUF_LEN(p->baseurl));
35359 /* register GET parameter */
35360 lua_pushliteral(L, "get");
35362 lua_settable(L, LUA_GLOBALSINDEX);
35365 lua_pushliteral(L, "get");
35366 header_tbl = lua_gettop(L);
35367 lua_gettable(L, LUA_GLOBALSINDEX);
35370 buffer_copy_string_buffer(b, con->uri.query);
35371 cache_export_get_params(L, header_tbl, b);
35374 - /* 2 default constants */
35375 + /* 2 default constants */
35376 lua_pushliteral(L, "CACHE_HIT");
35377 lua_pushboolean(L, 0);
35378 lua_settable(L, LUA_GLOBALSINDEX);
35381 lua_pushliteral(L, "CACHE_MISS");
35382 lua_pushboolean(L, 1);
35383 lua_settable(L, LUA_GLOBALSINDEX);
35386 /* load lua program */
35387 if (lua_load(L, load_file, &rm, fn->ptr) || lua_pcall(L,0,1,0)) {
35388 log_error_write(srv, __FILE__, __LINE__, "s",
35389 lua_tostring(L,-1));
35396 /* get return value */
35397 ret = (int)lua_tonumber(L, -1);
35400 - /* fetch the data from lua */
35402 + /* fetch the data from lua */
35403 lua_to_c_get_string(L, "trigger_handler", p->trigger_handler);
35406 if (0 == lua_to_c_get_string(L, "output_contenttype", b)) {
35407 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(b));
35412 /* up to now it is a cache-hit, check if all files exist */
35419 if (!lua_to_c_is_table(L, "output_include")) {
35420 log_error_write(srv, __FILE__, __LINE__, "s",
35421 "output_include is missing or not a table");
35429 lua_pushstring(L, "output_include");
35432 curelem = lua_gettop(L);
35433 lua_gettable(L, LUA_GLOBALSINDEX);
35435 /* HOW-TO build a etag ?
35436 - * as we don't just have one file we have to take the stat()
35437 + * as we don't just have one file we have to take the stat()
35438 * from all base files, merge them and build the etag from
35442 * The mtime of the content is the mtime of the freshest base file
35448 lua_pushnil(L); /* first key */
35449 while (lua_next(L, curelem) != 0) {
35450 stat_cache_entry *sce = NULL;
35451 /* key' is at index -2 and value' at index -1 */
35454 if (lua_isstring(L, -1)) {
35455 const char *s = lua_tostring(L, -1);
35457 @@ -364,18 +360,18 @@
35458 /* a file is missing, call the handler to generate it */
35459 if (!buffer_is_empty(p->trigger_handler)) {
35460 ret = 1; /* cache-miss */
35463 log_error_write(srv, __FILE__, __LINE__, "s",
35464 "a file is missing, calling handler");
35469 /* handler not set -> 500 */
35473 log_error_write(srv, __FILE__, __LINE__, "s",
35474 "a file missing and no handler set");
35480 @@ -393,12 +389,12 @@
35486 lua_pop(L, 1); /* removes value'; keeps key' for next iteration */
35490 lua_settop(L, curelem - 1);
35495 char timebuf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
35496 @@ -410,9 +406,9 @@
35498 /* no Last-Modified specified */
35499 if ((mtime) && (NULL == ds)) {
35502 strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&mtime));
35505 response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), timebuf, sizeof(timebuf) - 1);
35508 @@ -428,9 +424,9 @@
35514 if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, &tbuf)) {
35515 - /* ok, the client already has our content,
35516 + /* ok, the client already has our content,
35517 * no need to send it again */
35519 chunkqueue_reset(con->write_queue);
35520 @@ -440,24 +436,24 @@
35521 chunkqueue_reset(con->write_queue);
35526 if (ret == 1 && !buffer_is_empty(p->trigger_handler)) {
35528 buffer_copy_string_buffer(con->uri.path, p->baseurl);
35529 buffer_append_string_buffer(con->uri.path, p->trigger_handler);
35532 buffer_copy_string_buffer(con->physical.path, p->basedir);
35533 buffer_append_string_buffer(con->physical.path, p->trigger_handler);
35536 chunkqueue_reset(con->write_queue);
35544 stream_close(&rm.st);
35548 return ret /* cache-error */;
35552 Property changes on: src/mod_cml_lua.c
35553 ___________________________________________________________________
35554 Name: svn:eol-style
35557 Index: src/fdevent_linux_rtsig.c
35558 ===================================================================
35559 --- src/fdevent_linux_rtsig.c (.../tags/lighttpd-1.4.11) (revision 1159)
35560 +++ src/fdevent_linux_rtsig.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
35562 #include <sys/types.h>
35564 -#include <unistd.h>
35565 #include <stdlib.h>
35567 #include <string.h>
35569 #include "fdevent.h"
35570 #include "settings.h"
35571 #include "buffer.h"
35572 +#include "sys-process.h"
35574 #ifdef USE_LINUX_SIGIO
35575 static void fdevent_linux_rtsig_free(fdevents *ev) {
35576 @@ -26,19 +26,19 @@
35578 static int fdevent_linux_rtsig_event_del(fdevents *ev, int fde_ndx, int fd) {
35579 if (fde_ndx < 0) return -1;
35582 if ((size_t)fde_ndx >= ev->used) {
35583 fprintf(stderr, "%s.%d: del! out of range %d %zu\n", __FILE__, __LINE__, fde_ndx, ev->used);
35588 if (ev->pollfds[fde_ndx].fd == fd) {
35589 size_t k = fde_ndx;
35592 ev->pollfds[k].fd = -1;
35594 bitset_clear_bit(ev->sigbset, fd);
35597 if (ev->unused.size == 0) {
35598 ev->unused.size = 16;
35599 ev->unused.ptr = malloc(sizeof(*(ev->unused.ptr)) * ev->unused.size);
35600 @@ -46,29 +46,29 @@
35601 ev->unused.size += 16;
35602 ev->unused.ptr = realloc(ev->unused.ptr, sizeof(*(ev->unused.ptr)) * ev->unused.size);
35606 ev->unused.ptr[ev->unused.used++] = k;
35608 fprintf(stderr, "%s.%d: del! %d %d\n", __FILE__, __LINE__, ev->pollfds[fde_ndx].fd, fd);
35619 static int fdevent_linux_rtsig_event_compress(fdevents *ev) {
35623 if (ev->used == 0) return 0;
35624 if (ev->unused.used != 0) return 0;
35627 for (j = ev->used - 1; j + 1 > 0; j--) {
35628 if (ev->pollfds[j].fd == -1) ev->used--;
35637 @@ -78,21 +78,21 @@
35638 if (fde_ndx != -1) {
35639 if (ev->pollfds[fde_ndx].fd == fd) {
35640 ev->pollfds[fde_ndx].events = events;
35645 fprintf(stderr, "%s.%d: add: (%d, %d)\n", __FILE__, __LINE__, fde_ndx, ev->pollfds[fde_ndx].fd);
35650 if (ev->unused.used > 0) {
35651 int k = ev->unused.ptr[--ev->unused.used];
35654 ev->pollfds[k].fd = fd;
35655 ev->pollfds[k].events = events;
35657 bitset_set_bit(ev->sigbset, fd);
35662 if (ev->size == 0) {
35663 @@ -102,12 +102,12 @@
35665 ev->pollfds = realloc(ev->pollfds, sizeof(*ev->pollfds) * ev->size);
35669 ev->pollfds[ev->used].fd = fd;
35670 ev->pollfds[ev->used].events = events;
35672 bitset_set_bit(ev->sigbset, fd);
35678 @@ -115,20 +115,20 @@
35679 static int fdevent_linux_rtsig_poll(fdevents *ev, int timeout_ms) {
35680 struct timespec ts;
35685 fdevent_linux_rtsig_event_compress(ev);
35692 ts.tv_sec = timeout_ms / 1000;
35693 ts.tv_nsec = (timeout_ms % 1000) * 1000000;
35694 r = sigtimedwait(&(ev->sigset), &(ev->siginfo), &(ts));
35699 if (errno == EAGAIN) return 0;
35702 } else if (r == SIGIO) {
35703 struct sigaction act;
35705 @@ -140,7 +140,7 @@
35706 /* re-enable the signal queue */
35707 act.sa_handler = SIG_DFL;
35708 sigaction(ev->signum, &act, NULL);
35712 r = poll(ev->pollfds, ev->used, timeout_ms);
35714 @@ -162,12 +162,12 @@
35715 if (ev->siginfo.si_band == POLLERR) {
35716 fprintf(stderr, "event: %d %02lx %02x %s\n", ev->siginfo.si_fd, ev->siginfo.si_band, errno, strerror(errno));
35721 fprintf(stderr, "+\n");
35726 return ev->siginfo.si_band & 0x3f;
35728 if (ndx >= ev->used) {
35729 @@ -188,13 +188,13 @@
35731 static int fdevent_linux_rtsig_fcntl_set(fdevents *ev, int fd) {
35732 static pid_t pid = 0;
35735 if (pid == 0) pid = getpid();
35738 if (-1 == fcntl(fd, F_SETSIG, ev->signum)) return -1;
35741 if (-1 == fcntl(fd, F_SETOWN, (int) pid)) return -1;
35744 return fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK | O_RDWR);
35747 @@ -205,12 +205,12 @@
35753 i = (ndx < 0) ? 0 : ndx + 1;
35754 for (; i < ev->used; i++) {
35755 if (ev->pollfds[i].revents) break;
35762 @@ -219,34 +219,34 @@
35763 ev->type = FDEVENT_HANDLER_LINUX_RTSIG;
35765 ev->x = fdevent_linux_rtsig_##x;
35776 SET(event_next_fdndx);
35779 SET(event_get_revent);
35782 ev->signum = SIGRTMIN + 1;
35785 sigemptyset(&(ev->sigset));
35786 sigaddset(&(ev->sigset), ev->signum);
35787 sigaddset(&(ev->sigset), SIGIO);
35788 if (-1 == sigprocmask(SIG_BLOCK, &(ev->sigset), NULL)) {
35789 fprintf(stderr, "%s.%d: sigprocmask failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
35790 __FILE__, __LINE__, strerror(errno));
35799 ev->sigbset = bitset_init(ev->maxfds);
35806 Property changes on: src/fdevent_linux_rtsig.c
35807 ___________________________________________________________________
35808 Name: svn:eol-style
35811 Index: src/network_win32_send.c
35812 ===================================================================
35813 --- src/network_win32_send.c (.../tags/lighttpd-1.4.11) (revision 0)
35814 +++ src/network_win32_send.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
35816 +#include <sys/types.h>
35817 +#include <sys/stat.h>
35819 +#include <errno.h>
35820 +#include <fcntl.h>
35821 +#include <string.h>
35822 +#include <stdlib.h>
35823 +#include <assert.h>
35824 +#include <stdio.h>
35826 +#include "network.h"
35827 +#include "fdevent.h"
35829 +#include "stat_cache.h"
35831 +#include "sys-socket.h"
35832 +#include "sys-files.h"
35834 +#include "network_backends.h"
35836 +#ifdef USE_WIN32_SEND
35838 +* fill the chunkqueue will all the data that we can get
35840 +* this might be optimized into a readv() which uses the chunks
35844 +NETWORK_BACKEND_READ(win32recv) {
35849 + /* check how much we have to read */
35850 + if (ioctlsocket(fd, FIONREAD, &toread)) {
35851 + log_error_write(srv, __FILE__, __LINE__, "sd",
35852 + "ioctl failed: ",
35854 + return NETWORK_STATUS_FATAL_ERROR;
35857 + if (toread == 0) {
35858 + /* win32 is strange */
35859 + return con->bytes_read ? NETWORK_STATUS_CONNECTION_CLOSE : NETWORK_STATUS_WAIT_FOR_EVENT;
35863 + * our chunk queue is quiet large already
35865 + * let's buffer it to disk
35868 + b = chunkqueue_get_append_buffer(cq);
35870 + buffer_prepare_copy(b, toread + 1);
35872 + r = recv(fd, b->ptr, toread, 0);
35874 + /* something went wrong */
35876 + errno = WSAGetLastError();
35878 + if (errno == WSAEWOULDBLOCK) return NETWORK_STATUS_WAIT_FOR_EVENT;
35879 + if (errno == EINTR) {
35880 + /* we have been interrupted before we could read */
35881 + return NETWORK_STATUS_INTERRUPTED;
35884 + if (errno == WSAECONNRESET) {
35885 + /* expected for keep-alive */
35886 + return NETWORK_STATUS_CONNECTION_CLOSE;
35889 + log_error_write(srv, __FILE__, __LINE__, "ssdd",
35890 + "connection closed - read failed: ",
35891 + strerror(errno), con->fd, errno);
35893 + return NETWORK_STATUS_FATAL_ERROR;
35895 + /* this should be catched by the b > 0 above */
35897 + b->used += r + 1;
35898 + b->ptr[b->used - 1] = '\0';
35900 + return NETWORK_STATUS_SUCCESS;
35903 +NETWORK_BACKEND_WRITE(win32send) {
35905 + size_t chunks_written = 0;
35907 + for(c = cq->first; c; c = c->next) {
35908 + int chunk_finished = 0;
35910 + switch(c->type) {
35911 + case MEM_CHUNK: {
35916 + if (c->mem->used == 0) {
35917 + chunk_finished = 1;
35921 + offset = c->mem->ptr + c->offset;
35922 + toSend = c->mem->used - 1 - c->offset;
35924 + if ((r = send(fd, offset, toSend, 0)) < 0) {
35925 + errno = WSAGetLastError();
35928 + case WSAEWOULDBLOCK:
35929 + return NETWORK_STATUS_WAIT_FOR_EVENT;
35930 + case WSAECONNABORTED:
35931 + case WSAECONNRESET:
35932 + return NETWORK_STATUS_CONNECTION_CLOSE;
35934 + log_error_write(srv, __FILE__, __LINE__, "sdd", "send to socket:", errno, fd);
35935 + return NETWORK_STATUS_FATAL_ERROR;
35938 + return NETWORK_STATUS_FATAL_ERROR;
35942 + cq->bytes_out += r;
35944 + if (c->offset == (off_t)c->mem->used - 1) {
35945 + chunk_finished = 1;
35950 + case FILE_CHUNK: {
35954 + stat_cache_entry *sce = NULL;
35956 + if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
35957 + log_error_write(srv, __FILE__, __LINE__, "sb",
35958 + strerror(errno), c->file.name);
35959 + return NETWORK_STATUS_FATAL_ERROR;
35962 + offset = c->file.start + c->offset;
35964 + if (offset > sce->st.st_size) {
35965 + log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
35967 + return NETWORK_STATUS_FATAL_ERROR;
35971 + if (-1 == c->file.fd) {
35972 + if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY|O_BINARY|O_SEQUENTIAL))) {
35973 + log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
35975 + return NETWORK_STATUS_FATAL_ERROR;
35979 + if (-1 == lseek(c->file.fd, offset, SEEK_SET)) {
35980 + log_error_write(srv, __FILE__, __LINE__, "ss", "lseek failed: ", strerror(errno));
35984 + off_t haveRead = 0;
35987 + /* only send 64k blocks */
35988 + toSend = c->file.length - c->offset > 256 * 1024 ? 256 * 1024 : c->file.length - c->offset;
35990 + buffer_prepare_copy(srv->tmp_buf, toSend);
35992 + if (-1 == (haveRead = read(c->file.fd, srv->tmp_buf->ptr, toSend))) {
35993 + log_error_write(srv, __FILE__, __LINE__, "ss", "read from file: ", strerror(errno));
35996 + return NETWORK_STATUS_FATAL_ERROR;
35999 + if (-1 == (r = send(fd, srv->tmp_buf->ptr, haveRead, 0))) {
36000 + errno = WSAGetLastError();
36003 + case WSAEWOULDBLOCK:
36004 + return NETWORK_STATUS_WAIT_FOR_EVENT;
36005 + case WSAECONNABORTED:
36006 + case WSAECONNRESET:
36007 + return NETWORK_STATUS_CONNECTION_CLOSE;
36009 + log_error_write(srv, __FILE__, __LINE__, "sd", "send to socket:", errno);
36011 + return NETWORK_STATUS_FATAL_ERROR;
36016 + cq->bytes_out += r;
36018 + if (r != haveRead) {
36023 + if (c->offset == c->file.length) {
36024 + chunk_finished = 1;
36031 + log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
36033 + return NETWORK_STATUS_FATAL_ERROR;
36036 + if (!chunk_finished) {
36037 + /* not finished yet */
36039 + return NETWORK_STATUS_WAIT_FOR_EVENT;
36042 + chunks_written++;
36044 + fprintf(stderr, "%s.%d: chunks_written: %d\r\n", __FILE__, __LINE__, chunks_written);
36046 + return NETWORK_STATUS_SUCCESS;
36051 Property changes on: src/network_win32_send.c
36052 ___________________________________________________________________
36053 Name: svn:eol-style
36056 Index: src/data_string.c
36057 ===================================================================
36058 --- src/data_string.c (.../tags/lighttpd-1.4.11) (revision 1159)
36059 +++ src/data_string.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
36060 @@ -17,16 +17,16 @@
36062 static void data_string_free(data_unset *d) {
36063 data_string *ds = (data_string *)d;
36066 buffer_free(ds->key);
36067 buffer_free(ds->value);
36073 static void data_string_reset(data_unset *d) {
36074 data_string *ds = (data_string *)d;
36077 /* reused array elements */
36078 buffer_reset(ds->key);
36079 buffer_reset(ds->value);
36080 @@ -35,23 +35,23 @@
36081 static int data_string_insert_dup(data_unset *dst, data_unset *src) {
36082 data_string *ds_dst = (data_string *)dst;
36083 data_string *ds_src = (data_string *)src;
36086 if (ds_dst->value->used) {
36087 buffer_append_string(ds_dst->value, ", ");
36088 buffer_append_string_buffer(ds_dst->value, ds_src->value);
36090 buffer_copy_string_buffer(ds_dst->value, ds_src->value);
36100 static int data_response_insert_dup(data_unset *dst, data_unset *src) {
36101 data_string *ds_dst = (data_string *)dst;
36102 data_string *ds_src = (data_string *)src;
36105 if (ds_dst->value->used) {
36106 buffer_append_string(ds_dst->value, "\r\n");
36107 buffer_append_string_buffer(ds_dst->value, ds_dst->key);
36110 buffer_copy_string_buffer(ds_dst->value, ds_src->value);
36120 @@ -77,28 +77,28 @@
36122 data_string *data_string_init(void) {
36126 ds = calloc(1, sizeof(*ds));
36130 ds->key = buffer_init();
36131 ds->value = buffer_init();
36134 ds->copy = data_string_copy;
36135 ds->free = data_string_free;
36136 ds->reset = data_string_reset;
36137 ds->insert_dup = data_string_insert_dup;
36138 ds->print = data_string_print;
36139 ds->type = TYPE_STRING;
36145 data_string *data_response_init(void) {
36149 ds = data_string_init();
36150 ds->insert_dup = data_response_insert_dup;
36156 Property changes on: src/data_string.c
36157 ___________________________________________________________________
36158 Name: svn:eol-style
36161 Index: src/http-header-glue.c
36162 ===================================================================
36163 --- src/http-header-glue.c (.../tags/lighttpd-1.4.11) (revision 1159)
36164 +++ src/http-header-glue.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
36165 @@ -45,20 +45,20 @@
36166 # ifdef HAVE_STRUCT_SOCKADDR_STORAGE
36167 static size_t get_sa_len(const struct sockaddr *addr) {
36168 switch (addr->sa_family) {
36173 return (sizeof (struct sockaddr_in));
36179 return (sizeof (struct sockaddr_in6));
36184 return (sizeof (struct sockaddr));
36189 # define SA_LEN(addr) (get_sa_len(addr))
36192 int response_header_insert(server *srv, connection *con, const char *key, size_t keylen, const char *value, size_t vallen) {
36198 if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
36199 @@ -82,32 +82,32 @@
36201 buffer_copy_string_len(ds->key, key, keylen);
36202 buffer_copy_string_len(ds->value, value, vallen);
36205 array_insert_unique(con->response.headers, (data_unset *)ds);
36211 int response_header_overwrite(server *srv, connection *con, const char *key, size_t keylen, const char *value, size_t vallen) {
36217 /* if there already is a key by this name overwrite the value */
36218 if (NULL != (ds = (data_string *)array_get_element(con->response.headers, key))) {
36219 buffer_copy_string(ds->value, value);
36226 return response_header_insert(srv, con, key, keylen, value, vallen);
36229 int http_response_redirect_to_directory(server *srv, connection *con) {
36236 if (con->conf.is_ssl) {
36237 buffer_copy_string(o, "https://");
36239 @@ -123,36 +123,36 @@
36241 sock_addr our_addr;
36242 socklen_t our_addr_len;
36245 our_addr_len = sizeof(our_addr);
36248 if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) {
36249 con->http_status = 500;
36252 log_error_write(srv, __FILE__, __LINE__, "ss",
36253 "can't get sockname", strerror(errno));
36263 /* Lookup name: secondly try to get hostname for bind address */
36264 switch(our_addr.plain.sa_family) {
36267 - if (0 != getnameinfo((const struct sockaddr *)(&our_addr.ipv6),
36268 - SA_LEN((const struct sockaddr *)&our_addr.ipv6),
36269 + if (0 != getnameinfo((const struct sockaddr *)(&our_addr.ipv6),
36270 + SA_LEN((const struct sockaddr *)&our_addr.ipv6),
36271 hbuf, sizeof(hbuf), NULL, 0, 0)) {
36274 char dst[INET6_ADDRSTRLEN];
36277 log_error_write(srv, __FILE__, __LINE__,
36278 "SSSS", "NOTICE: getnameinfo failed: ",
36279 strerror(errno), ", using ip-address instead");
36281 - buffer_append_string(o,
36282 - inet_ntop(AF_INET6, (char *)&our_addr.ipv6.sin6_addr,
36284 + buffer_append_string(o,
36285 + inet_ntop(AF_INET6, (char *)&our_addr.ipv6.sin6_addr,
36286 dst, sizeof(dst)));
36288 buffer_append_string(o, hbuf);
36289 @@ -164,7 +164,7 @@
36290 log_error_write(srv, __FILE__, __LINE__,
36291 "SdSS", "NOTICE: gethostbyaddr failed: ",
36292 h_errno, ", using ip-address instead");
36295 buffer_append_string(o, inet_ntoa(our_addr.ipv4.sin_addr));
36297 buffer_append_string(o, he->h_name);
36298 @@ -173,12 +173,12 @@
36300 log_error_write(srv, __FILE__, __LINE__,
36301 "S", "ERROR: unsupported address-type");
36308 - if (!((con->conf.is_ssl == 0 && srv->srvconf.port == 80) ||
36310 + if (!((con->conf.is_ssl == 0 && srv->srvconf.port == 80) ||
36311 (con->conf.is_ssl == 1 && srv->srvconf.port == 443))) {
36312 buffer_append_string(o, ":");
36313 buffer_append_long(o, srv->srvconf.port);
36314 @@ -190,41 +190,41 @@
36315 buffer_append_string(o, "?");
36316 buffer_append_string_buffer(o, con->uri.query);
36320 response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(o));
36323 con->http_status = 301;
36324 con->file_finished = 1;
36333 buffer * strftime_cache_get(server *srv, time_t last_mod) {
36338 for (i = 0; i < FILE_CACHE_MAX; i++) {
36339 /* found cache-entry */
36340 if (srv->mtime_cache[i].mtime == last_mod) return srv->mtime_cache[i].str;
36343 /* found empty slot */
36344 if (srv->mtime_cache[i].mtime == 0) break;
36348 if (i == FILE_CACHE_MAX) {
36353 srv->mtime_cache[i].mtime = last_mod;
36354 buffer_prepare_copy(srv->mtime_cache[i].str, 1024);
36355 tm = gmtime(&(srv->mtime_cache[i].mtime));
36356 - srv->mtime_cache[i].str->used = strftime(srv->mtime_cache[i].str->ptr,
36357 + srv->mtime_cache[i].str->used = strftime(srv->mtime_cache[i].str->ptr,
36358 srv->mtime_cache[i].str->size - 1,
36359 "%a, %d %b %Y %H:%M:%S GMT", tm);
36360 srv->mtime_cache[i].str->used++;
36363 return srv->mtime_cache[i].str;
36366 @@ -239,56 +239,60 @@
36367 * request. That is, if no entity tags match, then the server MUST NOT
36368 * return a 304 (Not Modified) response.
36372 /* last-modified handling */
36373 if (con->request.http_if_none_match) {
36374 if (etag_is_equal(con->physical.etag, con->request.http_if_none_match)) {
36375 - if (con->request.http_method == HTTP_METHOD_GET ||
36376 + if (con->request.http_method == HTTP_METHOD_GET ||
36377 con->request.http_method == HTTP_METHOD_HEAD) {
36380 /* check if etag + last-modified */
36381 if (con->request.http_if_modified_since) {
36386 if (NULL == (semicolon = strchr(con->request.http_if_modified_since, ';'))) {
36387 used_len = strlen(con->request.http_if_modified_since);
36389 used_len = semicolon - con->request.http_if_modified_since;
36393 if (0 == strncmp(con->request.http_if_modified_since, mtime->ptr, used_len)) {
36394 con->http_status = 304;
36395 return HANDLER_FINISHED;
36397 +#ifdef HAVE_STRPTIME
36398 char buf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
36399 + time_t t_header, t_file;
36402 - /* convert to timestamp */
36403 - if (used_len < sizeof(buf)) {
36404 - time_t t_header, t_file;
36407 - strncpy(buf, con->request.http_if_modified_since, used_len);
36408 - buf[used_len] = '\0';
36410 - strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm);
36411 - t_header = mktime(&tm);
36413 - strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm);
36414 - t_file = mktime(&tm);
36415 + /* check if we can safely copy the string */
36416 + if (used_len >= sizeof(buf)) {
36417 + log_error_write(srv, __FILE__, __LINE__, "ssdd",
36418 + "DEBUG: Last-Modified check failed as the received timestamp was too long:",
36419 + con->request.http_if_modified_since, used_len, sizeof(buf) - 1);
36421 - if (t_file > t_header) {
36422 - con->http_status = 304;
36423 - return HANDLER_FINISHED;
36426 - log_error_write(srv, __FILE__, __LINE__, "ssdd",
36427 - "DEBUG: Last-Modified check failed as the received timestamp was too long:",
36428 - con->request.http_if_modified_since, used_len, sizeof(buf) - 1);
36430 con->http_status = 412;
36431 return HANDLER_FINISHED;
36435 + strncpy(buf, con->request.http_if_modified_since, used_len);
36436 + buf[used_len] = '\0';
36438 + strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm);
36439 + t_header = mktime(&tm);
36441 + strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm);
36442 + t_file = mktime(&tm);
36444 + if (t_file > t_header) return HANDLER_GO_ON;
36446 + con->http_status = 304;
36447 + return HANDLER_FINISHED;
36449 + return HANDLER_GO_ON;
36453 con->http_status = 304;
36454 @@ -302,16 +306,41 @@
36455 } else if (con->request.http_if_modified_since) {
36460 if (NULL == (semicolon = strchr(con->request.http_if_modified_since, ';'))) {
36461 used_len = strlen(con->request.http_if_modified_since);
36463 used_len = semicolon - con->request.http_if_modified_since;
36467 if (0 == strncmp(con->request.http_if_modified_since, mtime->ptr, used_len)) {
36468 con->http_status = 304;
36469 return HANDLER_FINISHED;
36471 +#ifdef HAVE_STRPTIME
36472 + char buf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")];
36473 + time_t t_header, t_file;
36476 + /* convert to timestamp */
36477 + if (used_len >= sizeof(buf)) return HANDLER_GO_ON;
36479 + strncpy(buf, con->request.http_if_modified_since, used_len);
36480 + buf[used_len] = '\0';
36482 + strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm);
36483 + t_header = mktime(&tm);
36485 + strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm);
36486 + t_file = mktime(&tm);
36488 + if (t_file > t_header) return HANDLER_GO_ON;
36490 + con->http_status = 304;
36491 + return HANDLER_FINISHED;
36493 + return HANDLER_GO_ON;
36499 Property changes on: src/http-header-glue.c
36500 ___________________________________________________________________
36501 Name: svn:eol-style
36504 Index: src/mod_evasive.c
36505 ===================================================================
36506 --- src/mod_evasive.c (.../tags/lighttpd-1.4.11) (revision 1159)
36507 +++ src/mod_evasive.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
36508 @@ -31,100 +31,97 @@
36514 plugin_config **config_storage;
36516 - plugin_config conf;
36518 + plugin_config conf;
36521 INIT_FUNC(mod_evasive_init) {
36525 p = calloc(1, sizeof(*p));
36531 FREE_FUNC(mod_evasive_free) {
36532 plugin_data *p = p_d;
36537 if (!p) return HANDLER_GO_ON;
36540 if (p->config_storage) {
36542 for (i = 0; i < srv->config_context->used; i++) {
36543 plugin_config *s = p->config_storage[i];
36548 free(p->config_storage);
36555 return HANDLER_GO_ON;
36558 SETDEFAULTS_FUNC(mod_evasive_set_defaults) {
36559 plugin_data *p = p_d;
36562 - config_values_t cv[] = {
36564 + config_values_t cv[] = {
36565 { "evasive.max-conns-per-ip", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
36566 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
36570 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
36573 for (i = 0; i < srv->config_context->used; i++) {
36577 s = calloc(1, sizeof(plugin_config));
36581 cv[0].destination = &(s->max_conns);
36584 p->config_storage[i] = s;
36587 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
36588 return HANDLER_ERROR;
36593 return HANDLER_GO_ON;
36596 -#define PATCH(x) \
36597 - p->conf.x = s->x;
36598 static int mod_evasive_patch_connection(server *srv, connection *con, plugin_data *p) {
36600 plugin_config *s = p->config_storage[0];
36602 - PATCH(max_conns);
36604 + PATCH_OPTION(max_conns);
36606 /* skip the first, the global context */
36607 for (i = 1; i < srv->config_context->used; i++) {
36608 data_config *dc = (data_config *)srv->config_context->data[i];
36609 s = p->config_storage[i];
36612 /* condition didn't match */
36613 if (!config_check_cond(srv, con, dc)) continue;
36617 for (j = 0; j < dc->value->used; j++) {
36618 data_unset *du = dc->value->data[j];
36621 if (buffer_is_equal_string(du->key, CONST_STR_LEN("evasive.max-conns-per-ip"))) {
36622 - PATCH(max_conns);
36623 + PATCH_OPTION(max_conns);
36633 URIHANDLER_FUNC(mod_evasive_uri_handler) {
36634 plugin_data *p = p_d;
36635 @@ -132,10 +129,10 @@
36638 if (con->uri.path->used == 0) return HANDLER_GO_ON;
36641 mod_evasive_patch_connection(srv, con, p);
36643 - /* no limit set, nothing to block */
36645 + /* no limit set, nothing to block */
36646 if (p->conf.max_conns == 0) return HANDLER_GO_ON;
36648 for (j = 0; j < srv->conns->used; j++) {
36649 @@ -147,7 +144,7 @@
36650 if (c->dst_addr.ipv4.sin_addr.s_addr == con->dst_addr.ipv4.sin_addr.s_addr &&
36651 c->state > CON_STATE_REQUEST_END) {
36655 if (conns_by_ip > p->conf.max_conns) {
36656 log_error_write(srv, __FILE__, __LINE__, "ss",
36657 inet_ntop_cache_get_ip(srv, &(con->dst_addr)),
36658 @@ -158,7 +155,7 @@
36664 return HANDLER_GO_ON;
36667 @@ -166,13 +163,13 @@
36668 int mod_evasive_plugin_init(plugin *p) {
36669 p->version = LIGHTTPD_VERSION_ID;
36670 p->name = buffer_init_string("evasive");
36673 p->init = mod_evasive_init;
36674 p->set_defaults = mod_evasive_set_defaults;
36675 p->handle_uri_clean = mod_evasive_uri_handler;
36676 p->cleanup = mod_evasive_free;
36685 Property changes on: src/mod_evasive.c
36686 ___________________________________________________________________
36687 Name: svn:eol-style
36690 Index: src/mod_setenv.c
36691 ===================================================================
36692 --- src/mod_setenv.c (.../tags/lighttpd-1.4.11) (revision 1159)
36693 +++ src/mod_setenv.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
36694 @@ -18,25 +18,25 @@
36696 array *request_header;
36697 array *response_header;
36700 array *environment;
36707 plugin_config **config_storage;
36709 - plugin_config conf;
36711 + plugin_config conf;
36714 static handler_ctx * handler_ctx_init() {
36715 handler_ctx * hctx;
36718 hctx = calloc(1, sizeof(*hctx));
36727 @@ -48,36 +48,36 @@
36728 /* init the plugin data */
36729 INIT_FUNC(mod_setenv_init) {
36733 p = calloc(1, sizeof(*p));
36739 /* detroy the plugin data */
36740 FREE_FUNC(mod_setenv_free) {
36741 plugin_data *p = p_d;
36746 if (!p) return HANDLER_GO_ON;
36749 if (p->config_storage) {
36751 for (i = 0; i < srv->config_context->used; i++) {
36752 plugin_config *s = p->config_storage[i];
36755 array_free(s->request_header);
36756 array_free(s->response_header);
36757 array_free(s->environment);
36762 free(p->config_storage);
36769 return HANDLER_GO_ON;
36772 @@ -86,86 +86,83 @@
36773 SETDEFAULTS_FUNC(mod_setenv_set_defaults) {
36774 plugin_data *p = p_d;
36777 - config_values_t cv[] = {
36779 + config_values_t cv[] = {
36780 { "setenv.add-request-header", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
36781 { "setenv.add-response-header", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
36782 { "setenv.add-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
36783 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
36787 if (!p) return HANDLER_ERROR;
36790 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
36793 for (i = 0; i < srv->config_context->used; i++) {
36797 s = calloc(1, sizeof(plugin_config));
36798 s->request_header = array_init();
36799 s->response_header = array_init();
36800 s->environment = array_init();
36803 cv[0].destination = s->request_header;
36804 cv[1].destination = s->response_header;
36805 cv[2].destination = s->environment;
36808 p->config_storage[i] = s;
36811 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
36812 return HANDLER_ERROR;
36817 return HANDLER_GO_ON;
36820 -#define PATCH(x) \
36821 - p->conf.x = s->x;
36822 static int mod_setenv_patch_connection(server *srv, connection *con, plugin_data *p) {
36824 plugin_config *s = p->config_storage[0];
36826 - PATCH(request_header);
36827 - PATCH(response_header);
36828 - PATCH(environment);
36831 + PATCH_OPTION(request_header);
36832 + PATCH_OPTION(response_header);
36833 + PATCH_OPTION(environment);
36835 /* skip the first, the global context */
36836 for (i = 1; i < srv->config_context->used; i++) {
36837 data_config *dc = (data_config *)srv->config_context->data[i];
36838 s = p->config_storage[i];
36841 /* condition didn't match */
36842 if (!config_check_cond(srv, con, dc)) continue;
36846 for (j = 0; j < dc->value->used; j++) {
36847 data_unset *du = dc->value->data[j];
36850 if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-request-header"))) {
36851 - PATCH(request_header);
36852 + PATCH_OPTION(request_header);
36853 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-response-header"))) {
36854 - PATCH(response_header);
36855 + PATCH_OPTION(response_header);
36856 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-environment"))) {
36857 - PATCH(environment);
36858 + PATCH_OPTION(environment);
36868 URIHANDLER_FUNC(mod_setenv_uri_handler) {
36869 plugin_data *p = p_d;
36874 if (con->plugin_ctx[p->id]) {
36875 hctx = con->plugin_ctx[p->id];
36877 hctx = handler_ctx_init();
36880 con->plugin_ctx[p->id] = hctx;
36883 @@ -180,52 +177,52 @@
36884 for (k = 0; k < p->conf.request_header->used; k++) {
36885 data_string *ds = (data_string *)p->conf.request_header->data[k];
36886 data_string *ds_dst;
36889 if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
36890 ds_dst = data_string_init();
36894 buffer_copy_string_buffer(ds_dst->key, ds->key);
36895 buffer_copy_string_buffer(ds_dst->value, ds->value);
36898 array_insert_unique(con->request.headers, (data_unset *)ds_dst);
36902 for (k = 0; k < p->conf.environment->used; k++) {
36903 data_string *ds = (data_string *)p->conf.environment->data[k];
36904 data_string *ds_dst;
36907 if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) {
36908 ds_dst = data_string_init();
36912 buffer_copy_string_buffer(ds_dst->key, ds->key);
36913 buffer_copy_string_buffer(ds_dst->value, ds->value);
36916 array_insert_unique(con->environment, (data_unset *)ds_dst);
36920 for (k = 0; k < p->conf.response_header->used; k++) {
36921 data_string *ds = (data_string *)p->conf.response_header->data[k];
36924 response_header_insert(srv, con, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
36929 return HANDLER_GO_ON;
36932 REQUESTDONE_FUNC(mod_setenv_reset) {
36933 plugin_data *p = p_d;
36939 if (con->plugin_ctx[p->id]) {
36940 handler_ctx_free(con->plugin_ctx[p->id]);
36941 con->plugin_ctx[p->id] = NULL;
36944 - return HANDLER_GO_ON;
36945 + return HANDLER_GO_ON;
36948 /* this function is called at dlopen() time and inits the callbacks */
36949 @@ -233,15 +230,15 @@
36950 int mod_setenv_plugin_init(plugin *p) {
36951 p->version = LIGHTTPD_VERSION_ID;
36952 p->name = buffer_init_string("setenv");
36955 p->init = mod_setenv_init;
36956 p->handle_uri_clean = mod_setenv_uri_handler;
36957 p->set_defaults = mod_setenv_set_defaults;
36958 p->cleanup = mod_setenv_free;
36961 p->handle_request_done = mod_setenv_reset;
36969 Property changes on: src/mod_setenv.c
36970 ___________________________________________________________________
36971 Name: svn:eol-style
36974 Index: src/mod_indexfile.c
36975 ===================================================================
36976 --- src/mod_indexfile.c (.../tags/lighttpd-1.4.11) (revision 1159)
36977 +++ src/mod_indexfile.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
36978 @@ -20,51 +20,51 @@
36987 plugin_config **config_storage;
36989 - plugin_config conf;
36991 + plugin_config conf;
36994 /* init the plugin data */
36995 INIT_FUNC(mod_indexfile_init) {
36999 p = calloc(1, sizeof(*p));
37002 p->tmp_buf = buffer_init();
37008 /* detroy the plugin data */
37009 FREE_FUNC(mod_indexfile_free) {
37010 plugin_data *p = p_d;
37015 if (!p) return HANDLER_GO_ON;
37018 if (p->config_storage) {
37020 for (i = 0; i < srv->config_context->used; i++) {
37021 plugin_config *s = p->config_storage[i];
37026 array_free(s->indexfiles);
37031 free(p->config_storage);
37035 buffer_free(p->tmp_buf);
37041 return HANDLER_GO_ON;
37044 @@ -73,131 +73,128 @@
37045 SETDEFAULTS_FUNC(mod_indexfile_set_defaults) {
37046 plugin_data *p = p_d;
37049 - config_values_t cv[] = {
37051 + config_values_t cv[] = {
37052 { "index-file.names", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
37053 { "server.indexfiles", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
37054 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
37058 if (!p) return HANDLER_ERROR;
37061 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
37064 for (i = 0; i < srv->config_context->used; i++) {
37068 s = calloc(1, sizeof(plugin_config));
37069 s->indexfiles = array_init();
37072 cv[0].destination = s->indexfiles;
37073 cv[1].destination = s->indexfiles; /* old name for [0] */
37076 p->config_storage[i] = s;
37079 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
37080 return HANDLER_ERROR;
37085 return HANDLER_GO_ON;
37088 -#define PATCH(x) \
37089 - p->conf.x = s->x;
37090 static int mod_indexfile_patch_connection(server *srv, connection *con, plugin_data *p) {
37092 plugin_config *s = p->config_storage[0];
37094 - PATCH(indexfiles);
37097 + PATCH_OPTION(indexfiles);
37099 /* skip the first, the global context */
37100 for (i = 1; i < srv->config_context->used; i++) {
37101 data_config *dc = (data_config *)srv->config_context->data[i];
37102 s = p->config_storage[i];
37105 /* condition didn't match */
37106 if (!config_check_cond(srv, con, dc)) continue;
37110 for (j = 0; j < dc->value->used; j++) {
37111 data_unset *du = dc->value->data[j];
37114 if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.indexfiles"))) {
37115 - PATCH(indexfiles);
37116 + PATCH_OPTION(indexfiles);
37117 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("index-file.names"))) {
37118 - PATCH(indexfiles);
37119 + PATCH_OPTION(indexfiles);
37129 URIHANDLER_FUNC(mod_indexfile_subrequest) {
37130 plugin_data *p = p_d;
37132 stat_cache_entry *sce = NULL;
37135 if (con->uri.path->used == 0) return HANDLER_GO_ON;
37136 if (con->uri.path->ptr[con->uri.path->used - 2] != '/') return HANDLER_GO_ON;
37139 mod_indexfile_patch_connection(srv, con, p);
37142 if (con->conf.log_request_handling) {
37143 log_error_write(srv, __FILE__, __LINE__, "s", "-- handling the request as Indexfile");
37144 log_error_write(srv, __FILE__, __LINE__, "sb", "URI :", con->uri.path);
37149 for (k = 0; k < p->conf.indexfiles->used; k++) {
37150 data_string *ds = (data_string *)p->conf.indexfiles->data[k];
37153 if (ds->value && ds->value->ptr[0] == '/') {
37154 - /* if the index-file starts with a prefix as use this file as
37155 + /* if the index-file starts with a prefix as use this file as
37156 * index-generator */
37157 buffer_copy_string_buffer(p->tmp_buf, con->physical.doc_root);
37159 buffer_copy_string_buffer(p->tmp_buf, con->physical.path);
37161 buffer_append_string_buffer(p->tmp_buf, ds->value);
37164 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->tmp_buf, &sce)) {
37165 if (errno == EACCES) {
37166 con->http_status = 403;
37167 buffer_reset(con->physical.path);
37170 return HANDLER_FINISHED;
37174 if (errno != ENOENT &&
37175 errno != ENOTDIR) {
37176 /* we have no idea what happend. let's tell the user so. */
37179 con->http_status = 500;
37182 log_error_write(srv, __FILE__, __LINE__, "ssbsb",
37183 "file not found ... or so: ", strerror(errno),
37185 "->", con->physical.path);
37188 buffer_reset(con->physical.path);
37191 return HANDLER_FINISHED;
37197 /* rewrite uri.path to the real path (/ -> /index.php) */
37198 buffer_append_string_buffer(con->uri.path, ds->value);
37199 buffer_copy_string_buffer(con->physical.path, p->tmp_buf);
37202 /* fce is already set up a few lines above */
37205 return HANDLER_GO_ON;
37210 return HANDLER_GO_ON;
37212 @@ -207,13 +204,13 @@
37213 int mod_indexfile_plugin_init(plugin *p) {
37214 p->version = LIGHTTPD_VERSION_ID;
37215 p->name = buffer_init_string("indexfile");
37218 p->init = mod_indexfile_init;
37219 p->handle_subrequest_start = mod_indexfile_subrequest;
37220 p->set_defaults = mod_indexfile_set_defaults;
37221 p->cleanup = mod_indexfile_free;
37230 Property changes on: src/mod_indexfile.c
37231 ___________________________________________________________________
37232 Name: svn:eol-style
37235 Index: src/mod_uploadprogress.c
37236 ===================================================================
37237 --- src/mod_uploadprogress.c (.../tags/lighttpd-1.4.11) (revision 1159)
37238 +++ src/mod_uploadprogress.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
37242 * this is a uploadprogress for a lighttpd plugin
37251 connection_map_entry **ptr;
37257 @@ -36,26 +36,26 @@
37263 connection_map *con_map;
37266 plugin_config **config_storage;
37268 - plugin_config conf;
37270 + plugin_config conf;
37281 /* init the plugin data */
37282 connection_map *connection_map_init() {
37283 connection_map *cm;
37286 cm = calloc(1, sizeof(*cm));
37292 @@ -63,22 +63,22 @@
37294 for (i = 0; i < cm->size; i++) {
37295 connection_map_entry *cme = cm->ptr[i];
37302 buffer_free(cme->con_id);
37311 int connection_map_insert(connection_map *cm, connection *con, buffer *con_id) {
37312 connection_map_entry *cme;
37316 if (cm->size == 0) {
37318 cm->ptr = malloc(cm->size * sizeof(*(cm->ptr)));
37325 if (cm->ptr[cm->used]) {
37326 /* is already alloced, just reuse it */
37327 cme = cm->ptr[cm->used];
37328 @@ -102,21 +102,21 @@
37329 cme->con_id = buffer_init();
37330 buffer_copy_string_buffer(cme->con_id, con_id);
37334 cm->ptr[cm->used++] = cme;
37340 connection *connection_map_get_connection(connection_map *cm, buffer *con_id) {
37344 for (i = 0; i < cm->used; i++) {
37345 connection_map_entry *cme = cm->ptr[i];
37348 if (buffer_is_equal(cme->con_id, con_id)) {
37349 /* found connection */
37355 @@ -125,66 +125,66 @@
37357 int connection_map_remove_connection(connection_map *cm, connection *con) {
37361 for (i = 0; i < cm->used; i++) {
37362 connection_map_entry *cme = cm->ptr[i];
37365 if (cme->con == con) {
37366 /* found connection */
37369 buffer_reset(cme->con_id);
37376 /* swap positions with the last entry */
37378 cm->ptr[i] = cm->ptr[cm->used];
37379 cm->ptr[cm->used] = cme;
37391 /* init the plugin data */
37392 INIT_FUNC(mod_uploadprogress_init) {
37396 p = calloc(1, sizeof(*p));
37399 p->con_map = connection_map_init();
37405 /* detroy the plugin data */
37406 FREE_FUNC(mod_uploadprogress_free) {
37407 plugin_data *p = p_d;
37412 if (!p) return HANDLER_GO_ON;
37415 if (p->config_storage) {
37417 for (i = 0; i < srv->config_context->used; i++) {
37418 plugin_config *s = p->config_storage[i];
37421 buffer_free(s->progress_url);
37426 free(p->config_storage);
37430 connection_map_free(p->con_map);
37436 return HANDLER_GO_ON;
37439 @@ -193,80 +193,77 @@
37440 SETDEFAULTS_FUNC(mod_uploadprogress_set_defaults) {
37441 plugin_data *p = p_d;
37444 - config_values_t cv[] = {
37446 + config_values_t cv[] = {
37447 { "upload-progress.progress-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
37448 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
37452 if (!p) return HANDLER_ERROR;
37455 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
37458 for (i = 0; i < srv->config_context->used; i++) {
37462 s = calloc(1, sizeof(plugin_config));
37463 s->progress_url = buffer_init();
37466 cv[0].destination = s->progress_url;
37469 p->config_storage[i] = s;
37472 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
37473 return HANDLER_ERROR;
37478 return HANDLER_GO_ON;
37481 -#define PATCH(x) \
37482 - p->conf.x = s->x;
37483 static int mod_uploadprogress_patch_connection(server *srv, connection *con, plugin_data *p) {
37485 plugin_config *s = p->config_storage[0];
37487 - PATCH(progress_url);
37490 + PATCH_OPTION(progress_url);
37492 /* skip the first, the global context */
37493 for (i = 1; i < srv->config_context->used; i++) {
37494 data_config *dc = (data_config *)srv->config_context->data[i];
37495 s = p->config_storage[i];
37498 /* condition didn't match */
37499 if (!config_check_cond(srv, con, dc)) continue;
37503 for (j = 0; j < dc->value->used; j++) {
37504 data_unset *du = dc->value->data[j];
37507 if (buffer_is_equal_string(du->key, CONST_STR_LEN("upload-progress.progress-url"))) {
37508 - PATCH(progress_url);
37509 + PATCH_OPTION(progress_url);
37524 - * for the first request we check if it is a post-request
37527 + * for the first request we check if it is a post-request
37529 * if no, move out, don't care about them
37531 - * if yes, take the connection structure and register it locally
37533 + * if yes, take the connection structure and register it locally
37534 * in the progress-struct together with an session-id (md5 ... )
37537 * if the connections closes, cleanup the entry in the progress-struct
37540 * a second request can now get the info about the size of the upload,
37541 * the received bytes
37546 URIHANDLER_FUNC(mod_uploadprogress_uri_handler) {
37547 @@ -275,21 +272,21 @@
37550 connection *post_con = NULL;
37555 if (con->uri.path->used == 0) return HANDLER_GO_ON;
37558 mod_uploadprogress_patch_connection(srv, con, p);
37561 /* check if this is a POST request */
37562 switch(con->request.http_method) {
37563 case HTTP_METHOD_POST:
37564 /* the request has to contain a 32byte ID */
37567 if (NULL == (ds = (data_string *)array_get_element(con->request.headers, "X-Progress-ID"))) {
37568 if (!buffer_is_empty(con->uri.query)) {
37569 - /* perhaps the POST request is using the querystring to pass the X-Progress-ID */
37570 + /* perhaps the POST request is using the querystring to pass the X-Progress-ID */
37571 b = con->uri.query;
37573 return HANDLER_GO_ON;
37574 @@ -297,34 +294,34 @@
37580 if (b->used != 32 + 1) {
37581 log_error_write(srv, __FILE__, __LINE__, "sd",
37582 "len of progress-id != 32:", b->used - 1);
37583 return HANDLER_GO_ON;
37587 for (i = 0; i < b->used - 1; i++) {
37588 char c = b->ptr[i];
37591 if (!light_isxdigit(c)) {
37592 log_error_write(srv, __FILE__, __LINE__, "sb",
37593 "non-xdigit in progress-id:", b);
37594 return HANDLER_GO_ON;
37599 connection_map_insert(p->con_map, con, b);
37602 return HANDLER_GO_ON;
37603 case HTTP_METHOD_GET:
37604 if (!buffer_is_equal(con->uri.path, p->conf.progress_url)) {
37605 return HANDLER_GO_ON;
37609 if (NULL == (ds = (data_string *)array_get_element(con->request.headers, "X-Progress-ID"))) {
37610 if (!buffer_is_empty(con->uri.query)) {
37611 - /* perhaps the GET request is using the querystring to pass the X-Progress-ID */
37612 + /* perhaps the GET request is using the querystring to pass the X-Progress-ID */
37613 b = con->uri.query;
37615 return HANDLER_GO_ON;
37616 @@ -332,23 +329,23 @@
37622 if (b->used != 32 + 1) {
37623 log_error_write(srv, __FILE__, __LINE__, "sd",
37624 "len of progress-id != 32:", b->used - 1);
37625 return HANDLER_GO_ON;
37629 for (i = 0; i < b->used - 1; i++) {
37630 char c = b->ptr[i];
37633 if (!light_isxdigit(c)) {
37634 log_error_write(srv, __FILE__, __LINE__, "sb",
37635 "non-xdigit in progress-id:", b);
37636 return HANDLER_GO_ON;
37641 buffer_reset(con->physical.path);
37643 con->file_started = 1;
37644 @@ -362,21 +359,21 @@
37645 "ID no known:", b);
37647 b = chunkqueue_get_append_buffer(con->write_queue);
37650 BUFFER_APPEND_STRING_CONST(b, "starting");
37652 return HANDLER_FINISHED;
37656 response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/xml"));
37659 /* just an attempt the force the IE/proxies to NOT cache the request ... doesn't help :( */
37660 response_header_overwrite(srv, con, CONST_STR_LEN("Pragma"), CONST_STR_LEN("no-cache"));
37661 response_header_overwrite(srv, con, CONST_STR_LEN("Expires"), CONST_STR_LEN("Thu, 19 Nov 1981 08:52:00 GMT"));
37662 response_header_overwrite(srv, con, CONST_STR_LEN("Cache-Control"), CONST_STR_LEN("no-store, no-cache, must-revalidate, post-check=0, pre-check=0"));
37665 b = chunkqueue_get_append_buffer(con->write_queue);
37669 BUFFER_COPY_STRING_CONST(b, "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>");
37670 BUFFER_APPEND_STRING_CONST(b, "<upload>");
37671 @@ -387,7 +384,7 @@
37672 buffer_append_off_t(b, post_con->request_content_queue->bytes_in);
37673 BUFFER_APPEND_STRING_CONST(b, "</received>");
37674 BUFFER_APPEND_STRING_CONST(b, "</upload>");
37677 log_error_write(srv, __FILE__, __LINE__, "sb", "...", b);
37679 return HANDLER_FINISHED;
37680 @@ -400,15 +397,15 @@
37682 REQUESTDONE_FUNC(mod_uploadprogress_request_done) {
37683 plugin_data *p = p_d;
37688 if (con->uri.path->used == 0) return HANDLER_GO_ON;
37691 if (connection_map_remove_connection(p->con_map, con)) {
37696 return HANDLER_GO_ON;
37699 @@ -417,14 +414,14 @@
37700 int mod_uploadprogress_plugin_init(plugin *p) {
37701 p->version = LIGHTTPD_VERSION_ID;
37702 p->name = buffer_init_string("uploadprogress");
37705 p->init = mod_uploadprogress_init;
37706 p->handle_uri_clean = mod_uploadprogress_uri_handler;
37707 p->handle_request_done = mod_uploadprogress_request_done;
37708 p->set_defaults = mod_uploadprogress_set_defaults;
37709 p->cleanup = mod_uploadprogress_free;
37718 Property changes on: src/mod_uploadprogress.c
37719 ___________________________________________________________________
37720 Name: svn:eol-style
37723 Index: src/http_resp.c
37724 ===================================================================
37725 --- src/http_resp.c (.../tags/lighttpd-1.4.11) (revision 0)
37726 +++ src/http_resp.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
37728 +#include <string.h>
37729 +#include <stdlib.h>
37730 +#include <stdio.h>
37731 +#include <assert.h>
37733 +#include "http_resp.h"
37734 +#include "http_resp_parser.h"
37736 +/* declare prototypes for the parser */
37737 +void *http_resp_parserAlloc(void *(*mallocProc)(size_t));
37738 +void http_resp_parserFree(void *p, void (*freeProc)(void*));
37739 +void http_resp_parserTrace(FILE *TraceFILE, char *zTracePrompt);
37740 +void http_resp_parser(void *, int, buffer *, http_resp_ctx_t *);
37745 + chunk *c; /* current chunk in the chunkqueue */
37746 + size_t offset; /* current offset in current chunk */
37749 + size_t lookup_offset;
37752 + int is_statusline;
37753 +} http_resp_tokenizer_t;
37755 +http_resp *http_response_init(void) {
37756 + http_resp *resp = calloc(1, sizeof(*resp));
37758 + resp->reason = buffer_init();
37759 + resp->headers = array_init();
37764 +void http_response_reset(http_resp *resp) {
37765 + if (!resp) return;
37767 + buffer_reset(resp->reason);
37768 + array_reset(resp->headers);
37772 +void http_response_free(http_resp *resp) {
37773 + if (!resp) return;
37775 + buffer_free(resp->reason);
37776 + array_free(resp->headers);
37781 +static int http_resp_get_next_char(http_resp_tokenizer_t *t, unsigned char *c) {
37782 + if (t->offset == t->c->mem->used - 1) {
37783 + /* end of chunk, open next chunk */
37785 + if (!t->c->next) return -1;
37787 + t->c = t->c->next;
37791 + *c = t->c->mem->ptr[t->offset++];
37793 + t->lookup_offset = t->offset;
37794 + t->lookup_c = t->c;
37797 + fprintf(stderr, "%s.%d: get: %c (%d) at offset: %d\r\n", __FILE__, __LINE__, *c > 31 ? *c : ' ', *c, t->offset - 1);
37803 +static int http_resp_lookup_next_char(http_resp_tokenizer_t *t, unsigned char *c) {
37804 + if (t->lookup_offset == t->lookup_c->mem->used - 1) {
37805 + /* end of chunk, open next chunk */
37807 + if (!t->lookup_c->next) return -1;
37809 + t->lookup_c = t->lookup_c->next;
37810 + t->lookup_offset = 0;
37813 + *c = t->lookup_c->mem->ptr[t->lookup_offset++];
37815 + fprintf(stderr, "%s.%d: lookup: %c (%d) at offset: %d\r\n", __FILE__, __LINE__, *c > 31 ? *c : ' ', *c, t->lookup_offset - 1);
37822 +static int http_resp_tokenizer(
37823 + http_resp_tokenizer_t *t,
37830 + /* push the token to the parser */
37832 + while (tid == 0 && 0 == http_resp_get_next_char(t, &c)) {
37846 + if (0 != http_resp_lookup_next_char(t, &c)) return -1;
37851 + t->c = t->lookup_c;
37852 + t->offset = t->lookup_offset;
37854 + t->is_statusline = 0;
37857 + fprintf(stderr, "%s.%d: CR with out LF\r\n", __FILE__, __LINE__);
37864 + t->is_statusline = 0;
37869 + while (c >= 32 && c != 127 && c != 255) {
37870 + if (t->is_statusline) {
37871 + if (c == ':') {t->is_statusline = 0; break; } /* this is not a status line by a real header */
37872 + if (c == 32) break; /* the space is a splitter in the statusline */
37875 + if (c == ':') break; /* the : is the splitter between key and value */
37878 + if (0 != http_resp_lookup_next_char(t, &c)) return -1;
37881 + if (t->c == t->lookup_c &&
37882 + t->offset == t->lookup_offset + 1) {
37884 + fprintf(stderr, "%s.%d: invalid char in string\n", __FILE__, __LINE__);
37890 + /* the lookup points to the first invalid char */
37891 + t->lookup_offset--;
37893 + /* no overlapping string */
37894 + if (t->c == t->lookup_c) {
37895 + buffer_copy_string_len(token, t->c->mem->ptr + t->offset - 1, t->lookup_offset - t->offset + 1);
37897 + /* first chunk */
37898 + buffer_copy_string_len(token, t->c->mem->ptr + t->offset - 1, t->c->mem->used - t->offset);
37900 + /* chunks in the middle */
37901 + for (t->c = t->c->next; t->c != t->lookup_c; t->c = t->c->next) {
37902 + buffer_append_string_buffer(token, t->c->mem);
37903 + t->offset = t->c->mem->used - 1;
37907 + buffer_append_string_len(token, t->c->mem->ptr, t->lookup_offset);
37910 + t->offset = t->lookup_offset;
37925 +parse_status_t http_response_parse_cq(chunkqueue *cq, http_resp *resp) {
37926 + http_resp_tokenizer_t t;
37927 + void *pParser = NULL;
37928 + int token_id = 0;
37929 + buffer *token = NULL;
37930 + http_resp_ctx_t context;
37931 + parse_status_t ret = PARSE_UNSET;
37932 + int last_token_id = 0;
37936 + t.offset = t.c->offset;
37938 + t.is_statusline = 1;
37941 + context.errmsg = buffer_init();
37942 + context.resp = resp;
37944 + pParser = http_resp_parserAlloc( malloc );
37945 + token = buffer_init();
37946 + /* http_resp_parserTrace(stderr, "http-response: "); */
37948 + while((1 == http_resp_tokenizer(&t, &token_id, token)) && context.ok) {
37949 + http_resp_parser(pParser, token_id, token, &context);
37951 + token = buffer_init();
37953 + if (last_token_id == TK_CRLF &&
37954 + token_id == TK_CRLF) break;
37956 + last_token_id = token_id;
37959 + /* oops, the parser failed */
37960 + if (context.ok == 0) {
37961 + ret = PARSE_ERROR;
37963 + fprintf(stderr, "%s.%d: parsing failed at: ...%20s\r\n",
37964 + __FILE__, __LINE__, t.c->mem->ptr + t.offset);
37967 + http_resp_parser(pParser, 0, token, &context);
37968 + http_resp_parserFree(pParser, free );
37970 + if (context.ok == 0) {
37971 + /* we are missing the some tokens */
37973 + if (ret == PARSE_UNSET) ret = PARSE_NEED_MORE;
37977 + for (c = cq->first; c != t.c; c = c->next) {
37978 + c->offset = c->mem->used - 1;
37981 + c->offset = t.offset;
37983 + ret = PARSE_SUCCESS;
37986 + buffer_free(token);
37992 Property changes on: src/http_resp.c
37993 ___________________________________________________________________
37994 Name: svn:eol-style
37997 Index: src/data_fastcgi.c
37998 ===================================================================
37999 --- src/data_fastcgi.c (.../tags/lighttpd-1.4.11) (revision 1159)
38000 +++ src/data_fastcgi.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
38001 @@ -17,53 +17,53 @@
38003 static void data_fastcgi_free(data_unset *d) {
38004 data_fastcgi *ds = (data_fastcgi *)d;
38007 buffer_free(ds->key);
38008 buffer_free(ds->host);
38014 static void data_fastcgi_reset(data_unset *d) {
38015 data_fastcgi *ds = (data_fastcgi *)d;
38018 buffer_reset(ds->key);
38019 buffer_reset(ds->host);
38024 static int data_fastcgi_insert_dup(data_unset *dst, data_unset *src) {
38033 static void data_fastcgi_print(const data_unset *d, int depth) {
38034 data_fastcgi *ds = (data_fastcgi *)d;
38038 fprintf(stderr, "fastcgi(%s)", ds->host->ptr);
38042 data_fastcgi *data_fastcgi_init(void) {
38046 ds = calloc(1, sizeof(*ds));
38049 ds->key = buffer_init();
38050 ds->host = buffer_init();
38052 ds->is_disabled = 0;
38055 ds->copy = data_fastcgi_copy;
38056 ds->free = data_fastcgi_free;
38057 ds->reset = data_fastcgi_reset;
38058 ds->insert_dup = data_fastcgi_insert_dup;
38059 ds->print = data_fastcgi_print;
38060 ds->type = TYPE_FASTCGI;
38066 Property changes on: src/data_fastcgi.c
38067 ___________________________________________________________________
38068 Name: svn:eol-style
38072 Property changes on: src/mod_ssi_exprparser.h
38073 ___________________________________________________________________
38074 Name: svn:eol-style
38077 Index: src/http_resp.h
38078 ===================================================================
38079 --- src/http_resp.h (.../tags/lighttpd-1.4.11) (revision 0)
38080 +++ src/http_resp.h (.../branches/lighttpd-merge-1.4.x) (revision 1159)
38082 +#ifndef _HTTP_RESP_H_
38083 +#define _HTTP_RESP_H_
38085 +#include "array.h"
38086 +#include "chunk.h"
38096 + int protocol; /* http/1.0, http/1.1 */
38097 + int status; /* e.g. 200 */
38098 + buffer *reason; /* e.g. Ok */
38107 +} http_resp_ctx_t;
38109 +http_resp *http_response_init(void);
38110 +void http_response_free(http_resp *resp);
38111 +void http_response_reset(http_resp *resp);
38113 +parse_status_t http_response_parse_cq(chunkqueue *cq, http_resp *http_response);
38117 Property changes on: src/http_resp.h
38118 ___________________________________________________________________
38119 Name: svn:eol-style
38122 Index: src/mod_fastcgi.c
38123 ===================================================================
38124 --- src/mod_fastcgi.c (.../tags/lighttpd-1.4.11) (revision 1159)
38125 +++ src/mod_fastcgi.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
38127 #include <sys/types.h>
38128 -#include <unistd.h>
38131 #include <string.h>
38133 #include "inet_ntop_cache.h"
38134 #include "stat_cache.h"
38136 -#include <fastcgi.h>
38137 +#include "fastcgi.h"
38140 #ifdef HAVE_SYS_FILIO_H
38144 #include "sys-socket.h"
38145 +#include "sys-files.h"
38146 +#include "sys-strings.h"
38147 +#include "sys-process.h"
38149 +#include "http_resp.h"
38151 #ifndef UNIX_PATH_MAX
38152 # define UNIX_PATH_MAX 108
38153 @@ -45,14 +48,13 @@
38154 #include <sys/wait.h>
38164 * - add timeout for a connect to a non-fastcgi process
38165 * (use state_timestamp + state)
38170 typedef struct fcgi_proc {
38172 unsigned port; /* config.port + pno */
38174 buffer *connection_name; /* either tcp:<host>:<port> or unix:<socket> for debuggin purposes */
38177 pid_t pid; /* PID of the spawned process (0 if not spawned locally) */
38180 @@ -70,20 +72,20 @@
38181 time_t last_used; /* see idle_timeout */
38182 size_t requests; /* see max_requests */
38183 struct fcgi_proc *prev, *next; /* see first */
38186 time_t disabled_until; /* this proc is disabled until, use something else until than */
38193 PROC_STATE_UNSET, /* init-phase */
38194 PROC_STATE_RUNNING, /* alive */
38195 - PROC_STATE_OVERLOADED, /* listen-queue is full,
38196 + PROC_STATE_OVERLOADED, /* listen-queue is full,
38197 don't send something to this proc for the next 2 seconds */
38198 PROC_STATE_DIED_WAIT_FOR_PID, /* */
38199 PROC_STATE_DIED, /* marked as dead, should be restarted */
38200 PROC_STATE_KILLED /* was killed as we don't have the load anymore */
38206 @@ -94,20 +96,20 @@
38207 * sorted by lowest load
38209 * whenever a job is done move it up in the list
38210 - * until it is sorted, move it down as soon as the
38211 + * until it is sorted, move it down as soon as the
38214 - fcgi_proc *first;
38215 - fcgi_proc *unused_procs;
38216 + fcgi_proc *first;
38217 + fcgi_proc *unused_procs;
38221 * spawn at least min_procs, at max_procs.
38223 - * as soon as the load of the first entry
38224 + * as soon as the load of the first entry
38225 * is max_load_per_proc we spawn a new one
38226 - * and add it to the first entry and give it
38227 + * and add it to the first entry and give it
38233 unsigned short min_procs;
38234 @@ -119,44 +121,44 @@
38237 * kick the process from the list if it was not
38238 - * used for idle_timeout until min_procs is
38239 + * used for idle_timeout until min_procs is
38240 * reached. this helps to get the processlist
38241 * small again we had a small peak load.
38246 unsigned short idle_timeout;
38250 * time after a disabled remote connection is tried to be re-enabled
38258 unsigned short disable_time;
38261 * same fastcgi processes get a little bit larger
38262 - * than wanted. max_requests_per_proc kills a
38263 + * than wanted. max_requests_per_proc kills a
38264 * process after a number of handled requests.
38267 size_t max_requests_per_proc;
38278 - * if host is one of the local IP adresses the
38279 + * if host is one of the local IP adresses the
38280 * whole connection is local
38282 * if tcp/ip should be used host AND port have
38283 - * to be specified
38287 + * to be specified
38291 unsigned short port;
38294 @@ -169,7 +171,7 @@
38296 buffer *unixsocket;
38298 - /* if socket is local we can start the fastcgi
38299 + /* if socket is local we can start the fastcgi
38302 * bin-path is the path to the binary
38303 @@ -177,19 +179,19 @@
38304 * check min_procs and max_procs for the number
38305 * of process to start-up
38307 - buffer *bin_path;
38309 - /* bin-path is set bin-environment is taken to
38310 + buffer *bin_path;
38312 + /* bin-path is set bin-environment is taken to
38313 * create the environement before starting the
38321 array *bin_env_copy;
38325 - * docroot-translation between URL->phys and the
38326 + * docroot-translation between URL->phys and the
38330 @@ -208,7 +210,7 @@
38331 unsigned short mode;
38334 - * check_local tell you if the phys file is stat()ed
38335 + * check_local tell you if the phys file is stat()ed
38336 * or not. FastCGI doesn't care if the service is
38337 * remote. If the web-server side doesn't contain
38338 * the fastcgi-files we should not stat() for them
38339 @@ -218,11 +220,11 @@
38342 * append PATH_INFO to SCRIPT_FILENAME
38345 * php needs this if cgi.fix_pathinfo is provied
38351 unsigned short break_scriptfilename_for_php;
38354 @@ -231,12 +233,12 @@
38357 unsigned short allow_xsendfile;
38360 ssize_t load; /* replace by host->load */
38362 size_t max_id; /* corresponds most of the time to
38366 only if a process is killed max_id waits for the process itself
38367 to die and decrements its afterwards */
38369 @@ -245,17 +247,17 @@
38372 * one extension can have multiple hosts assigned
38373 - * one host can spawn additional processes on the same
38374 + * one host can spawn additional processes on the same
38375 * socket (if we control it)
38377 * ext -> host -> procs
38380 - * if the fastcgi process is remote that whole goes down
38381 + * if the fastcgi process is remote that whole goes down
38384 * ext -> host -> procs
38388 * in case of PHP and FCGI_CHILDREN we have again a procs
38389 * but we don't control it directly.
38390 @@ -268,7 +270,7 @@
38393 fcgi_extension_host **hosts;
38399 @@ -282,10 +284,10 @@
38406 array *ext_mapping;
38412 @@ -297,7 +299,7 @@
38421 @@ -306,44 +308,44 @@
38424 buffer_uint fcgi_request_id;
38431 - buffer *parse_response;
38438 plugin_config **config_storage;
38441 plugin_config conf; /* this is only used as long as no handler_ctx is setup */
38444 /* connection specific data */
38449 - FCGI_STATE_CONNECT_DELAYED,
38450 - FCGI_STATE_PREPARE_WRITE,
38451 - FCGI_STATE_WRITE,
38454 + FCGI_STATE_CONNECT_DELAYED,
38455 + FCGI_STATE_PREPARE_WRITE,
38456 + FCGI_STATE_WRITE,
38458 } fcgi_connection_state_t;
38462 fcgi_extension_host *host;
38463 fcgi_extension *ext;
38466 fcgi_connection_state_t state;
38467 time_t state_timestamp;
38470 int reconnects; /* number of reconnect attempts */
38472 - chunkqueue *rb; /* read queue */
38474 + chunkqueue *rb; /* the raw fcgi read-queue */
38475 + chunkqueue *http_rb; /* the decoded read-queue for http-parsing */
38476 chunkqueue *wb; /* write queue */
38478 - buffer *response_header;
38482 int fd; /* fd to the fastcgi process */
38483 int fde_ndx; /* index into the fd-event buffer */
38484 @@ -352,9 +354,9 @@
38487 int send_content_body;
38490 plugin_config conf;
38493 connection *remote_conn; /* dumb pointer */
38494 plugin_data *plugin_data; /* dumb pointer */
38496 @@ -380,7 +382,7 @@
38500 -/* dummies of the statistic framework functions
38501 +/* dummies of the statistic framework functions
38502 * they will be moved to a statistics.c later */
38503 int status_counter_inc(server *srv, const char *s, size_t len) {
38504 data_integer *di = status_counter_get_counter(srv, s, len);
38505 @@ -429,7 +431,7 @@
38506 CLEAN(".connected");
38513 fastcgi_status_copy_procname(b, host, NULL); \
38514 @@ -438,33 +440,32 @@
38524 static handler_ctx * handler_ctx_init() {
38525 handler_ctx * hctx;
38528 hctx = calloc(1, sizeof(*hctx));
38532 hctx->fde_ndx = -1;
38534 - hctx->response_header = buffer_init();
38537 hctx->request_id = 0;
38538 hctx->state = FCGI_STATE_INIT;
38545 hctx->reconnects = 0;
38546 hctx->send_content_body = 1;
38548 hctx->rb = chunkqueue_init();
38549 + hctx->http_rb = chunkqueue_init();
38550 hctx->wb = chunkqueue_init();
38556 @@ -473,10 +474,9 @@
38557 hctx->host->load--;
38561 - buffer_free(hctx->response_header);
38563 chunkqueue_free(hctx->rb);
38564 + chunkqueue_free(hctx->http_rb);
38565 chunkqueue_free(hctx->wb);
38568 @@ -488,21 +488,21 @@
38569 f = calloc(1, sizeof(*f));
38570 f->unixsocket = buffer_init();
38571 f->connection_name = buffer_init();
38581 void fastcgi_process_free(fcgi_proc *f) {
38585 fastcgi_process_free(f->next);
38588 buffer_free(f->unixsocket);
38589 buffer_free(f->connection_name);
38595 @@ -519,13 +519,13 @@
38596 f->bin_env = array_init();
38597 f->bin_env_copy = array_init();
38598 f->strip_request_uri = buffer_init();
38604 void fastcgi_host_free(fcgi_extension_host *h) {
38608 buffer_free(h->id);
38609 buffer_free(h->host);
38610 buffer_free(h->unixsocket);
38611 @@ -534,49 +534,49 @@
38612 buffer_free(h->strip_request_uri);
38613 array_free(h->bin_env);
38614 array_free(h->bin_env_copy);
38617 fastcgi_process_free(h->first);
38618 fastcgi_process_free(h->unused_procs);
38626 fcgi_exts *fastcgi_extensions_init() {
38629 f = calloc(1, sizeof(*f));
38635 void fastcgi_extensions_free(fcgi_exts *f) {
38642 for (i = 0; i < f->used; i++) {
38643 fcgi_extension *fe;
38650 for (j = 0; j < fe->used; j++) {
38651 fcgi_extension_host *h;
38657 fastcgi_host_free(h);
38661 buffer_free(fe->key);
38675 @@ -625,24 +625,25 @@
38679 - fe->hosts[fe->used++] = fh;
38680 + fe->hosts[fe->used++] = fh;
38687 INIT_FUNC(mod_fastcgi_init) {
38691 p = calloc(1, sizeof(*p));
38694 p->fcgi_env = buffer_init();
38697 p->path = buffer_init();
38698 - p->parse_response = buffer_init();
38700 + p->resp = http_response_init();
38702 p->statuskey = buffer_init();
38708 @@ -650,81 +651,82 @@
38709 FREE_FUNC(mod_fastcgi_free) {
38710 plugin_data *p = p_d;
38711 buffer_uint *r = &(p->fcgi_request_id);
38716 if (r->ptr) free(r->ptr);
38719 buffer_free(p->fcgi_env);
38720 buffer_free(p->path);
38721 - buffer_free(p->parse_response);
38722 buffer_free(p->statuskey);
38725 + http_response_free(p->resp);
38727 if (p->config_storage) {
38729 for (i = 0; i < srv->config_context->used; i++) {
38730 plugin_config *s = p->config_storage[i];
38739 for (j = 0; j < exts->used; j++) {
38740 fcgi_extension *ex;
38743 ex = exts->exts[j];
38746 for (n = 0; n < ex->used; n++) {
38748 fcgi_extension_host *host;
38751 host = ex->hosts[n];
38754 for (proc = host->first; proc; proc = proc->next) {
38755 if (proc->pid != 0) kill(proc->pid, SIGTERM);
38757 - if (proc->is_local &&
38759 + if (proc->is_local &&
38760 !buffer_is_empty(proc->unixsocket)) {
38761 unlink(proc->unixsocket->ptr);
38766 for (proc = host->unused_procs; proc; proc = proc->next) {
38767 if (proc->pid != 0) kill(proc->pid, SIGTERM);
38769 - if (proc->is_local &&
38771 + if (proc->is_local &&
38772 !buffer_is_empty(proc->unixsocket)) {
38773 unlink(proc->unixsocket->ptr);
38780 fastcgi_extensions_free(s->exts);
38781 array_free(s->ext_mapping);
38786 free(p->config_storage);
38793 return HANDLER_GO_ON;
38796 static int env_add(char_array *env, const char *key, size_t key_len, const char *val, size_t val_len) {
38800 if (!key || !val) return -1;
38803 dst = malloc(key_len + val_len + 3);
38804 memcpy(dst, key, key_len);
38805 dst[key_len] = '=';
38806 /* add the \0 from the value */
38807 memcpy(dst + key_len + 1, val, val_len + 1);
38810 if (env->size == 0) {
38812 env->ptr = malloc(env->size * sizeof(*env->ptr));
38813 @@ -732,9 +734,9 @@
38815 env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
38819 env->ptr[env->used++] = dst;
38825 @@ -753,15 +755,15 @@
38826 if (env->size == 0) {
38828 env->ptr = malloc(env->size * sizeof(*env->ptr));
38829 - } else if (env->size == env->used) {
38830 + } else if (env->size == env->used) {
38832 env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr));
38838 env->ptr[env->used++] = start;
38841 start = b->ptr + i + 1;
38844 @@ -794,7 +796,7 @@
38848 -static int fcgi_spawn_connection(server *srv,
38849 +static int fcgi_spawn_connection(server *srv,
38851 fcgi_extension_host *host,
38853 @@ -806,31 +808,27 @@
38855 struct sockaddr_in fcgi_addr_in;
38856 struct sockaddr *fcgi_addr;
38867 if (p->conf.debug) {
38868 log_error_write(srv, __FILE__, __LINE__, "sdb",
38869 "new proc, socket:", proc->port, proc->unixsocket);
38873 if (!buffer_is_empty(proc->unixsocket)) {
38874 memset(&fcgi_addr, 0, sizeof(fcgi_addr));
38877 #ifdef HAVE_SYS_UN_H
38878 fcgi_addr_un.sun_family = AF_UNIX;
38879 strcpy(fcgi_addr_un.sun_path, proc->unixsocket->ptr);
38883 servlen = SUN_LEN(&fcgi_addr_un);
38885 - /* stevens says: */
38886 - servlen = proc->unixsocket->used + sizeof(fcgi_addr_un.sun_family);
38889 socket_type = AF_UNIX;
38890 fcgi_addr = (struct sockaddr *) &fcgi_addr_un;
38892 @@ -844,108 +842,108 @@
38895 fcgi_addr_in.sin_family = AF_INET;
38898 if (buffer_is_empty(host->host)) {
38899 fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
38901 struct hostent *he;
38904 /* set a usefull default */
38905 fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY);
38910 if (NULL == (he = gethostbyname(host->host->ptr))) {
38911 - log_error_write(srv, __FILE__, __LINE__,
38912 - "sdb", "gethostbyname failed: ",
38913 + log_error_write(srv, __FILE__, __LINE__,
38914 + "sdb", "gethostbyname failed: ",
38915 h_errno, host->host);
38920 if (he->h_addrtype != AF_INET) {
38921 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype);
38926 if (he->h_length != sizeof(struct in_addr)) {
38927 log_error_write(srv, __FILE__, __LINE__, "sd", "addr-length != sizeof(in_addr): ", he->h_length);
38932 memcpy(&(fcgi_addr_in.sin_addr.s_addr), he->h_addr_list[0], he->h_length);
38936 fcgi_addr_in.sin_port = htons(proc->port);
38937 servlen = sizeof(fcgi_addr_in);
38940 socket_type = AF_INET;
38941 fcgi_addr = (struct sockaddr *) &fcgi_addr_in;
38944 buffer_copy_string(proc->connection_name, "tcp:");
38945 buffer_append_string_buffer(proc->connection_name, host->host);
38946 buffer_append_string(proc->connection_name, ":");
38947 buffer_append_long(proc->connection_name, proc->port);
38951 if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
38952 - log_error_write(srv, __FILE__, __LINE__, "ss",
38953 + log_error_write(srv, __FILE__, __LINE__, "ss",
38954 "failed:", strerror(errno));
38959 if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) {
38960 /* server is not up, spawn in */
38964 - if (errno != ENOENT &&
38966 + if (errno != ENOENT &&
38967 !buffer_is_empty(proc->unixsocket)) {
38968 unlink(proc->unixsocket->ptr);
38975 /* reopen socket */
38976 if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) {
38977 - log_error_write(srv, __FILE__, __LINE__, "ss",
38978 + log_error_write(srv, __FILE__, __LINE__, "ss",
38979 "socket failed:", strerror(errno));
38985 if (setsockopt(fcgi_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) {
38986 - log_error_write(srv, __FILE__, __LINE__, "ss",
38987 + log_error_write(srv, __FILE__, __LINE__, "ss",
38988 "socketsockopt failed:", strerror(errno));
38993 /* create socket */
38994 if (-1 == bind(fcgi_fd, fcgi_addr, servlen)) {
38995 - log_error_write(srv, __FILE__, __LINE__, "sbs",
38996 - "bind failed for:",
38997 + log_error_write(srv, __FILE__, __LINE__, "sbs",
38998 + "bind failed for:",
38999 proc->connection_name,
39005 if (-1 == listen(fcgi_fd, 1024)) {
39006 - log_error_write(srv, __FILE__, __LINE__, "ss",
39007 + log_error_write(srv, __FILE__, __LINE__, "ss",
39008 "listen failed:", strerror(errno));
39015 switch ((child = fork())) {
39023 /* create environment */
39032 @@ -955,18 +953,18 @@
39033 dup2(fcgi_fd, FCGI_LISTENSOCK_FILENO);
39038 /* we don't need the client socket */
39039 for (i = 3; i < 256; i++) {
39044 /* build clean environment */
39045 if (host->bin_env_copy->used) {
39046 for (i = 0; i < host->bin_env_copy->used; i++) {
39047 data_string *ds = (data_string *)host->bin_env_copy->data[i];
39051 if (NULL != (ge = getenv(ds->value->ptr))) {
39052 env_add(&env, CONST_BUF_LEN(ds->value), ge, strlen(ge));
39054 @@ -974,39 +972,39 @@
39056 for (i = 0; environ[i]; i++) {
39060 if (NULL != (eq = strchr(environ[i], '='))) {
39061 env_add(&env, environ[i], eq - environ[i], eq+1, strlen(eq+1));
39067 /* create environment */
39068 for (i = 0; i < host->bin_env->used; i++) {
39069 data_string *ds = (data_string *)host->bin_env->data[i];
39072 env_add(&env, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value));
39076 for (i = 0; i < env.used; i++) {
39077 /* search for PHP_FCGI_CHILDREN */
39078 if (0 == strncmp(env.ptr[i], "PHP_FCGI_CHILDREN=", sizeof("PHP_FCGI_CHILDREN=") - 1)) break;
39082 /* not found, add a default */
39083 if (i == env.used) {
39084 env_add(&env, CONST_STR_LEN("PHP_FCGI_CHILDREN"), CONST_STR_LEN("1"));
39088 env.ptr[env.used] = NULL;
39090 parse_binpath(&arg, host->bin_path);
39093 /* chdir into the base of the bin-path,
39094 * search for the last / */
39095 if (NULL != (c = strrchr(arg.ptr[0], '/'))) {
39099 /* change to the physical directory */
39100 if (-1 == chdir(arg.ptr[0])) {
39102 @@ -1018,12 +1016,12 @@
39105 execve(arg.ptr[0], arg.ptr, env.ptr);
39107 - log_error_write(srv, __FILE__, __LINE__, "sbs",
39109 + log_error_write(srv, __FILE__, __LINE__, "sbs",
39110 "execve failed for:", host->bin_path, strerror(errno));
39119 @@ -1031,17 +1029,17 @@
39126 select(0, NULL, NULL, NULL, &tv);
39129 switch (waitpid(child, &status, WNOHANG)) {
39131 /* child still running after timeout, good */
39134 /* no PID found ? should never happen */
39135 - log_error_write(srv, __FILE__, __LINE__, "ss",
39136 + log_error_write(srv, __FILE__, __LINE__, "ss",
39137 "pid not found:", strerror(errno));
39140 @@ -1049,10 +1047,10 @@
39141 "the fastcgi-backend", host->bin_path, "failed to start:");
39142 /* the child should not terminate at all */
39143 if (WIFEXITED(status)) {
39144 - log_error_write(srv, __FILE__, __LINE__, "sdb",
39145 - "child exited with status",
39146 + log_error_write(srv, __FILE__, __LINE__, "sdb",
39147 + "child exited with status",
39148 WEXITSTATUS(status), host->bin_path);
39149 - log_error_write(srv, __FILE__, __LINE__, "s",
39150 + log_error_write(srv, __FILE__, __LINE__, "s",
39151 "if you try do run PHP as FastCGI backend make sure you use the FastCGI enabled version.\n"
39152 "You can find out if it is the right one by executing 'php -v' and it should display '(cgi-fcgi)' "
39153 "in the output, NOT (cgi) NOR (cli)\n"
39154 @@ -1060,8 +1058,8 @@
39155 log_error_write(srv, __FILE__, __LINE__, "s",
39156 "If this is PHP on Gentoo add fastcgi to the USE flags");
39157 } else if (WIFSIGNALED(status)) {
39158 - log_error_write(srv, __FILE__, __LINE__, "sd",
39159 - "terminated by signal:",
39160 + log_error_write(srv, __FILE__, __LINE__, "sd",
39161 + "terminated by signal:",
39164 if (WTERMSIG(status) == 11) {
39165 @@ -1071,8 +1069,8 @@
39166 "If this is PHP try to remove the byte-code caches for now and try again.");
39169 - log_error_write(srv, __FILE__, __LINE__, "sd",
39170 - "child died somehow:",
39171 + log_error_write(srv, __FILE__, __LINE__, "sd",
39172 + "child died somehow:",
39176 @@ -1082,26 +1080,26 @@
39178 proc->last_used = srv->cur_ts;
39179 proc->is_local = 1;
39186 proc->is_local = 0;
39190 if (p->conf.debug) {
39191 log_error_write(srv, __FILE__, __LINE__, "sb",
39192 "(debug) socket is already used, won't spawn:",
39193 proc->connection_name);
39198 proc->state = PROC_STATE_RUNNING;
39199 host->active_procs++;
39208 @@ -1111,93 +1109,93 @@
39211 buffer *fcgi_mode = buffer_init();
39213 - config_values_t cv[] = {
39215 + config_values_t cv[] = {
39216 { "fastcgi.server", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
39217 { "fastcgi.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
39218 { "fastcgi.map-extensions", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
39219 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
39223 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
39226 for (i = 0; i < srv->config_context->used; i++) {
39231 s = malloc(sizeof(plugin_config));
39232 s->exts = fastcgi_extensions_init();
39234 s->ext_mapping = array_init();
39237 cv[0].destination = s->exts;
39238 cv[1].destination = &(s->debug);
39239 cv[2].destination = s->ext_mapping;
39242 p->config_storage[i] = s;
39243 ca = ((data_config *)srv->config_context->data[i])->value;
39246 if (0 != config_insert_values_global(srv, ca, cv)) {
39247 return HANDLER_ERROR;
39257 if (NULL != (du = array_get_element(ca, "fastcgi.server"))) {
39259 data_array *da = (data_array *)du;
39262 if (du->type != TYPE_ARRAY) {
39263 - log_error_write(srv, __FILE__, __LINE__, "sss",
39264 + log_error_write(srv, __FILE__, __LINE__, "sss",
39265 "unexpected type for key: ", "fastcgi.server", "array of strings");
39268 return HANDLER_ERROR;
39273 - * fastcgi.server = ( "<ext>" => ( ... ),
39277 + * fastcgi.server = ( "<ext>" => ( ... ),
39278 * "<ext>" => ( ... ) )
39282 for (j = 0; j < da->value->used; j++) {
39284 data_array *da_ext = (data_array *)da->value->data[j];
39287 if (da->value->data[j]->type != TYPE_ARRAY) {
39288 - log_error_write(srv, __FILE__, __LINE__, "sssbs",
39289 - "unexpected type for key: ", "fastcgi.server",
39290 + log_error_write(srv, __FILE__, __LINE__, "sssbs",
39291 + "unexpected type for key: ", "fastcgi.server",
39292 "[", da->value->data[j]->key, "](string)");
39295 return HANDLER_ERROR;
39299 - * da_ext->key == name of the extension
39302 + * da_ext->key == name of the extension
39306 - * fastcgi.server = ( "<ext>" =>
39307 - * ( "<host>" => ( ... ),
39310 + * fastcgi.server = ( "<ext>" =>
39311 + * ( "<host>" => ( ... ),
39312 * "<host>" => ( ... )
39319 for (n = 0; n < da_ext->value->used; n++) {
39320 data_array *da_host = (data_array *)da_ext->value->data[n];
39323 fcgi_extension_host *host;
39325 - config_values_t fcv[] = {
39327 + config_values_t fcv[] = {
39328 { "host", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
39329 { "docroot", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
39330 { "mode", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
39331 { "socket", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
39332 { "bin-path", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 4 */
39335 { "check-local", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 5 */
39336 { "port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 6 */
39337 { "min-procs-not-working", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 7 this is broken for now */
39338 @@ -1205,28 +1203,28 @@
39339 { "max-load-per-proc", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 9 */
39340 { "idle-timeout", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 10 */
39341 { "disable-time", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 11 */
39344 { "bin-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 12 */
39345 { "bin-copy-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 13 */
39348 { "broken-scriptfilename", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 14 */
39349 { "allow-x-send-file", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 15 */
39350 { "strip-request-uri", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 16 */
39353 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
39357 if (da_host->type != TYPE_ARRAY) {
39358 - log_error_write(srv, __FILE__, __LINE__, "ssSBS",
39359 - "unexpected type for key:",
39360 - "fastcgi.server",
39361 + log_error_write(srv, __FILE__, __LINE__, "ssSBS",
39362 + "unexpected type for key:",
39363 + "fastcgi.server",
39364 "[", da_host->key, "](string)");
39367 return HANDLER_ERROR;
39371 host = fastcgi_host_init();
39374 buffer_copy_string_buffer(host->id, da_host->key);
39376 host->check_local = 1;
39377 @@ -1238,13 +1236,13 @@
39378 host->disable_time = 60;
39379 host->break_scriptfilename_for_php = 0;
39380 host->allow_xsendfile = 0; /* handle X-LIGHTTPD-send-file */
39383 fcv[0].destination = host->host;
39384 fcv[1].destination = host->docroot;
39385 fcv[2].destination = fcgi_mode;
39386 fcv[3].destination = host->unixsocket;
39387 fcv[4].destination = host->bin_path;
39390 fcv[5].destination = &(host->check_local);
39391 fcv[6].destination = &(host->port);
39392 fcv[7].destination = &(host->min_procs);
39393 @@ -1252,35 +1250,35 @@
39394 fcv[9].destination = &(host->max_load_per_proc);
39395 fcv[10].destination = &(host->idle_timeout);
39396 fcv[11].destination = &(host->disable_time);
39399 fcv[12].destination = host->bin_env;
39400 fcv[13].destination = host->bin_env_copy;
39401 fcv[14].destination = &(host->break_scriptfilename_for_php);
39402 fcv[15].destination = &(host->allow_xsendfile);
39403 fcv[16].destination = host->strip_request_uri;
39406 if (0 != config_insert_values_internal(srv, da_host->value, fcv)) {
39407 return HANDLER_ERROR;
39410 - if ((!buffer_is_empty(host->host) || host->port) &&
39412 + if ((!buffer_is_empty(host->host) || host->port) &&
39413 !buffer_is_empty(host->unixsocket)) {
39414 - log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
39415 + log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
39416 "either host/port or socket have to be set in:",
39419 da_ext->key, " => (",
39420 da_host->key, " ( ...");
39422 return HANDLER_ERROR;
39426 if (!buffer_is_empty(host->unixsocket)) {
39427 /* unix domain socket */
39430 if (host->unixsocket->used > UNIX_PATH_MAX - 2) {
39431 - log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
39432 + log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
39433 "unixsocket is too long in:",
39436 da_ext->key, " => (",
39437 da_host->key, " ( ...");
39439 @@ -1288,37 +1286,37 @@
39444 - if (buffer_is_empty(host->host) &&
39446 + if (buffer_is_empty(host->host) &&
39447 buffer_is_empty(host->bin_path)) {
39448 - log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
39449 + log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
39450 "host or binpath have to be set in:",
39453 da_ext->key, " => (",
39454 da_host->key, " ( ...");
39457 return HANDLER_ERROR;
39458 } else if (host->port == 0) {
39459 - log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
39460 + log_error_write(srv, __FILE__, __LINE__, "sbsbsbs",
39461 "port has to be set in:",
39464 da_ext->key, " => (",
39465 da_host->key, " ( ...");
39467 return HANDLER_ERROR;
39471 - if (!buffer_is_empty(host->bin_path)) {
39473 + if (!buffer_is_empty(host->bin_path)) {
39474 /* a local socket + self spawning */
39477 /* HACK: just to make sure the adaptive spawing is disabled */
39478 host->min_procs = host->max_procs;
39481 if (host->min_procs > host->max_procs) host->max_procs = host->min_procs;
39482 if (host->max_load_per_proc < 1) host->max_load_per_proc = 0;
39486 log_error_write(srv, __FILE__, __LINE__, "ssbsdsbsdsd",
39487 "--- fastcgi spawning local",
39488 @@ -1328,7 +1326,7 @@
39489 "\n\tmin-procs:", host->min_procs,
39490 "\n\tmax-procs:", host->max_procs);
39494 for (pno = 0; pno < host->min_procs; pno++) {
39497 @@ -1343,7 +1341,7 @@
39498 buffer_append_string(proc->unixsocket, "-");
39499 buffer_append_long(proc->unixsocket, pno);
39504 log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd",
39505 "--- fastcgi spawning",
39506 @@ -1351,7 +1349,7 @@
39507 "\n\tsocket", host->unixsocket,
39508 "\n\tcurrent:", pno, "/", host->min_procs);
39512 if (fcgi_spawn_connection(srv, p, host, proc)) {
39513 log_error_write(srv, __FILE__, __LINE__, "s",
39514 "[ERROR]: spawning fcgi failed.");
39515 @@ -1359,35 +1357,35 @@
39518 fastcgi_status_init(srv, p->statuskey, host, proc);
39521 proc->next = host->first;
39522 if (host->first) host->first->prev = proc;
39525 host->first = proc;
39531 proc = fastcgi_process_init();
39532 proc->id = host->num_procs++;
39534 host->active_procs++;
39535 proc->state = PROC_STATE_RUNNING;
39538 if (buffer_is_empty(host->unixsocket)) {
39539 proc->port = host->port;
39541 buffer_copy_string_buffer(proc->unixsocket, host->unixsocket);
39545 fastcgi_status_init(srv, p->statuskey, host, proc);
39547 host->first = proc;
39550 host->min_procs = 1;
39551 host->max_procs = 1;
39555 if (!buffer_is_empty(fcgi_mode)) {
39556 if (strcmp(fcgi_mode->ptr, "responder") == 0) {
39557 host->mode = FCGI_RESPONDER;
39558 @@ -1411,16 +1409,16 @@
39564 buffer_free(fcgi_mode);
39567 return HANDLER_GO_ON;
39570 static int fcgi_set_state(server *srv, handler_ctx *hctx, fcgi_connection_state_t state) {
39571 hctx->state = state;
39572 hctx->state_timestamp = srv->cur_ts;
39578 @@ -1429,13 +1427,13 @@
39581 buffer_uint *r = &(p->fcgi_request_id);
39586 for (i = 0; i < r->used; i++) {
39587 if (r->ptr[i] > m) m = r->ptr[i];
39591 if (r->size == 0) {
39593 r->ptr = malloc(sizeof(*r->ptr) * r->size);
39594 @@ -1443,54 +1441,54 @@
39596 r->ptr = realloc(r->ptr, sizeof(*r->ptr) * r->size);
39600 r->ptr[r->used++] = ++m;
39606 static int fcgi_requestid_del(server *srv, plugin_data *p, size_t request_id) {
39608 buffer_uint *r = &(p->fcgi_request_id);
39613 for (i = 0; i < r->used; i++) {
39614 if (r->ptr[i] == request_id) break;
39618 if (i != r->used) {
39622 if (i != r->used - 1) {
39623 r->ptr[i] = r->ptr[r->used - 1];
39631 void fcgi_connection_close(server *srv, handler_ctx *hctx) {
39636 if (NULL == hctx) return;
39639 p = hctx->plugin_data;
39640 con = hctx->remote_conn;
39643 if (con->mode != p->id) {
39649 if (hctx->fd != -1) {
39650 fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd);
39651 fdevent_unregister(srv->ev, hctx->fd);
39657 if (hctx->request_id != 0) {
39658 fcgi_requestid_del(srv, p, hctx->request_id);
39660 @@ -1499,7 +1497,7 @@
39661 if (hctx->got_proc) {
39662 /* after the connect the process gets a load */
39663 hctx->proc->load--;
39666 status_counter_dec(srv, CONST_STR_LEN("fastcgi.active-requests"));
39668 fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
39669 @@ -1509,39 +1507,39 @@
39671 if (p->conf.debug) {
39672 log_error_write(srv, __FILE__, __LINE__, "ssdsbsd",
39673 - "released proc:",
39674 - "pid:", hctx->proc->pid,
39675 - "socket:", hctx->proc->connection_name,
39676 + "released proc:",
39677 + "pid:", hctx->proc->pid,
39678 + "socket:", hctx->proc->connection_name,
39679 "load:", hctx->proc->load);
39686 handler_ctx_free(hctx);
39687 - con->plugin_ctx[p->id] = NULL;
39688 + con->plugin_ctx[p->id] = NULL;
39691 static int fcgi_reconnect(server *srv, handler_ctx *hctx) {
39692 plugin_data *p = hctx->plugin_data;
39703 * connect was ok, connection was accepted
39704 * but the php accept loop checks after the accept if it should die or not.
39706 - * if yes we can only detect it at a write()
39709 + * if yes we can only detect it at a write()
39711 * next step is resetting this attemp and setup a connection again
39714 * if we have more then 5 reconnects for the same request, die
39721 * we have a connection but the child died by some other reason
39726 if (hctx->fd != -1) {
39727 @@ -1551,59 +1549,59 @@
39733 fcgi_requestid_del(srv, p, hctx->request_id);
39736 fcgi_set_state(srv, hctx, FCGI_STATE_INIT);
39739 hctx->request_id = 0;
39740 hctx->reconnects++;
39743 if (p->conf.debug > 2) {
39745 log_error_write(srv, __FILE__, __LINE__, "sdb",
39746 - "release proc for reconnect:",
39747 + "release proc for reconnect:",
39748 hctx->proc->pid, hctx->proc->connection_name);
39750 log_error_write(srv, __FILE__, __LINE__, "sb",
39751 - "release proc for reconnect:",
39752 + "release proc for reconnect:",
39753 hctx->host->unixsocket);
39757 - if (hctx->proc && hctx->got_proc) {
39758 + if (hctx->proc && hctx->got_proc) {
39759 hctx->proc->load--;
39762 /* perhaps another host gives us more luck */
39763 hctx->host->load--;
39771 static handler_t fcgi_connection_reset(server *srv, connection *con, void *p_d) {
39772 plugin_data *p = p_d;
39775 fcgi_connection_close(srv, con->plugin_ctx[p->id]);
39778 return HANDLER_GO_ON;
39782 static int fcgi_env_add(buffer *env, const char *key, size_t key_len, const char *val, size_t val_len) {
39786 if (!key || !val) return -1;
39789 len = key_len + val_len;
39792 len += key_len > 127 ? 4 : 1;
39793 len += val_len > 127 ? 4 : 1;
39796 buffer_prepare_append(env, len);
39799 if (key_len > 127) {
39800 env->ptr[env->used++] = ((key_len >> 24) & 0xff) | 0x80;
39801 env->ptr[env->used++] = (key_len >> 16) & 0xff;
39802 @@ -1612,7 +1610,7 @@
39804 env->ptr[env->used++] = (key_len >> 0) & 0xff;
39808 if (val_len > 127) {
39809 env->ptr[env->used++] = ((val_len >> 24) & 0xff) | 0x80;
39810 env->ptr[env->used++] = (val_len >> 16) & 0xff;
39811 @@ -1621,12 +1619,12 @@
39813 env->ptr[env->used++] = (val_len >> 0) & 0xff;
39817 memcpy(env->ptr + env->used, key, key_len);
39818 env->used += key_len;
39819 memcpy(env->ptr + env->used, val, val_len);
39820 env->used += val_len;
39826 @@ -1639,11 +1637,11 @@
39827 header->contentLengthB1 = (contentLength >> 8) & 0xff;
39828 header->paddingLength = paddingLength;
39829 header->reserved = 0;
39840 @@ -1665,26 +1663,23 @@
39841 struct sockaddr_un fcgi_addr_un;
39846 fcgi_extension_host *host = hctx->host;
39847 fcgi_proc *proc = hctx->proc;
39848 int fcgi_fd = hctx->fd;
39851 memset(&fcgi_addr, 0, sizeof(fcgi_addr));
39854 if (!buffer_is_empty(proc->unixsocket)) {
39855 #ifdef HAVE_SYS_UN_H
39856 /* use the unix domain socket */
39857 fcgi_addr_un.sun_family = AF_UNIX;
39858 strcpy(fcgi_addr_un.sun_path, proc->unixsocket->ptr);
39861 servlen = SUN_LEN(&fcgi_addr_un);
39863 - /* stevens says: */
39864 - servlen = proc->unixsocket->used + sizeof(fcgi_addr_un.sun_family);
39867 fcgi_addr = (struct sockaddr *) &fcgi_addr_un;
39870 if (buffer_is_empty(proc->connection_name)) {
39871 /* on remote spawing we have to set the connection-name now */
39872 buffer_copy_string(proc->connection_name, "unix:");
39873 @@ -1695,16 +1690,18 @@
39876 fcgi_addr_in.sin_family = AF_INET;
39878 if (0 == inet_aton(host->host->ptr, &(fcgi_addr_in.sin_addr))) {
39879 - log_error_write(srv, __FILE__, __LINE__, "sbs",
39880 - "converting IP-adress failed for", host->host,
39881 + log_error_write(srv, __FILE__, __LINE__, "sbs",
39882 + "converting IP-adress failed for", host->host,
39883 "\nBe sure to specify an IP address here");
39889 fcgi_addr_in.sin_port = htons(proc->port);
39890 servlen = sizeof(fcgi_addr_in);
39893 fcgi_addr = (struct sockaddr *) &fcgi_addr_in;
39895 if (buffer_is_empty(proc->connection_name)) {
39896 @@ -1715,20 +1712,20 @@
39897 buffer_append_long(proc->connection_name, proc->port);
39902 if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) {
39903 - if (errno == EINPROGRESS ||
39904 + if (errno == EINPROGRESS ||
39905 errno == EALREADY ||
39907 if (hctx->conf.debug > 2) {
39908 - log_error_write(srv, __FILE__, __LINE__, "sb",
39909 + log_error_write(srv, __FILE__, __LINE__, "sb",
39910 "connect delayed, will continue later:", proc->connection_name);
39914 return CONNECTION_DELAYED;
39915 } else if (errno == EAGAIN) {
39916 if (hctx->conf.debug) {
39917 - log_error_write(srv, __FILE__, __LINE__, "sbsd",
39918 + log_error_write(srv, __FILE__, __LINE__, "sbsd",
39919 "This means that the you have more incoming requests than your fastcgi-backend can handle in parallel. "
39920 "Perhaps it helps to spawn more fastcgi backend or php-children, if not decrease server.max-connections."
39921 "The load for this fastcgi backend", proc->connection_name, "is", proc->load);
39922 @@ -1736,8 +1733,8 @@
39924 return CONNECTION_OVERLOADED;
39926 - log_error_write(srv, __FILE__, __LINE__, "sssb",
39927 - "connect failed:",
39928 + log_error_write(srv, __FILE__, __LINE__, "sssb",
39929 + "connect failed:",
39930 strerror(errno), "on",
39931 proc->connection_name);
39933 @@ -1747,7 +1744,7 @@
39935 hctx->reconnects = 0;
39936 if (hctx->conf.debug > 1) {
39937 - log_error_write(srv, __FILE__, __LINE__, "sd",
39938 + log_error_write(srv, __FILE__, __LINE__, "sd",
39939 "connect succeeded: ", fcgi_fd);
39942 @@ -1756,21 +1753,21 @@
39944 static int fcgi_env_add_request_headers(server *srv, connection *con, plugin_data *p) {
39948 for (i = 0; i < con->request.headers->used; i++) {
39952 ds = (data_string *)con->request.headers->data[i];
39955 if (ds->value->used && ds->key->used) {
39957 buffer_reset(srv->tmp_buf);
39960 if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) {
39961 BUFFER_COPY_STRING_CONST(srv->tmp_buf, "HTTP_");
39962 srv->tmp_buf->used--;
39966 buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
39967 for (j = 0; j < ds->key->used - 1; j++) {
39969 @@ -1784,20 +1781,20 @@
39970 srv->tmp_buf->ptr[srv->tmp_buf->used++] = c;
39972 srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
39975 fcgi_env_add(p->fcgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
39980 for (i = 0; i < con->environment->used; i++) {
39984 ds = (data_string *)con->environment->data[i];
39987 if (ds->value->used && ds->key->used) {
39989 buffer_reset(srv->tmp_buf);
39992 buffer_prepare_append(srv->tmp_buf, ds->key->used + 2);
39993 for (j = 0; j < ds->key->used - 1; j++) {
39995 @@ -1811,11 +1808,11 @@
39996 srv->tmp_buf->ptr[srv->tmp_buf->used++] = c;
39998 srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0';
40001 fcgi_env_add(p->fcgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value));
40009 @@ -1824,24 +1821,24 @@
40010 FCGI_BeginRequestRecord beginRecord;
40011 FCGI_Header header;
40018 char b2[INET6_ADDRSTRLEN + 1];
40022 plugin_data *p = hctx->plugin_data;
40023 fcgi_extension_host *host= hctx->host;
40025 connection *con = hctx->remote_conn;
40026 server_socket *srv_sock = con->srv_socket;
40029 sock_addr our_addr;
40030 socklen_t our_addr_len;
40033 /* send FCGI_BEGIN_REQUEST */
40036 fcgi_header(&(beginRecord.header), FCGI_BEGIN_REQUEST, request_id, sizeof(beginRecord.body), 0);
40037 beginRecord.body.roleB0 = host->mode;
40038 beginRecord.body.roleB1 = 0;
40039 @@ -1849,21 +1846,21 @@
40040 memset(beginRecord.body.reserved, 0, sizeof(beginRecord.body.reserved));
40042 b = chunkqueue_get_append_buffer(hctx->wb);
40045 buffer_copy_memory(b, (const char *)&beginRecord, sizeof(beginRecord));
40048 /* send FCGI_PARAMS */
40049 buffer_prepare_copy(p->fcgi_env, 1024);
40052 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION));
40055 if (con->server_name->used) {
40056 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_NAME"), CONST_BUF_LEN(con->server_name));
40059 - s = inet_ntop(srv_sock->addr.plain.sa_family,
40060 - srv_sock->addr.plain.sa_family == AF_INET6 ?
40061 + s = inet_ntop(srv_sock->addr.plain.sa_family,
40062 + srv_sock->addr.plain.sa_family == AF_INET6 ?
40063 (const void *) &(srv_sock->addr.ipv6.sin6_addr) :
40064 (const void *) &(srv_sock->addr.ipv4.sin_addr),
40066 @@ -1872,50 +1869,50 @@
40068 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_NAME"), s, strlen(s));
40072 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1"));
40078 ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port)
40080 ntohs(srv_sock->addr.ipv4.sin_port)
40085 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf));
40088 /* get the server-side of the connection to the client */
40089 our_addr_len = sizeof(our_addr);
40092 if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) {
40093 s = inet_ntop_cache_get_ip(srv, &(srv_sock->addr));
40095 s = inet_ntop_cache_get_ip(srv, &(our_addr));
40097 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_ADDR"), s, strlen(s));
40103 ntohs(con->dst_addr.plain.sa_family ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port)
40105 ntohs(con->dst_addr.ipv4.sin_port)
40110 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf));
40113 s = inet_ntop_cache_get_ip(srv, &(con->dst_addr));
40114 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s));
40117 if (!buffer_is_empty(con->authed_user)) {
40118 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_USER"),
40119 CONST_BUF_LEN(con->authed_user));
40123 if (con->request.content_length > 0 && host->mode != FCGI_AUTHORIZER) {
40124 /* CGI-SPEC 6.1.2 and FastCGI spec 6.3 */
40127 /* request.content_length < SSIZE_MAX, see request.c */
40128 ltostr(buf, con->request.content_length);
40129 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf));
40130 @@ -1930,12 +1927,12 @@
40133 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path));
40136 if (!buffer_is_empty(con->request.pathinfo)) {
40137 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo));
40140 /* PATH_TRANSLATED is only defined if PATH_INFO is set */
40143 if (!buffer_is_empty(host->docroot)) {
40144 buffer_copy_string_buffer(p->path, host->docroot);
40146 @@ -1957,27 +1954,27 @@
40149 if (!buffer_is_empty(host->docroot)) {
40151 - * rewrite SCRIPT_FILENAME
40154 + * rewrite SCRIPT_FILENAME
40159 buffer_copy_string_buffer(p->path, host->docroot);
40160 buffer_append_string_buffer(p->path, con->uri.path);
40163 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
40164 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(host->docroot));
40166 buffer_copy_string_buffer(p->path, con->physical.path);
40168 - /* cgi.fix_pathinfo need a broken SCRIPT_FILENAME to find out what PATH_INFO is itself
40171 + /* cgi.fix_pathinfo need a broken SCRIPT_FILENAME to find out what PATH_INFO is itself
40173 * see src/sapi/cgi_main.c, init_request_info()
40175 if (host->break_scriptfilename_for_php) {
40176 buffer_append_string_buffer(p->path, con->request.pathinfo);
40180 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path));
40181 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root));
40183 @@ -1987,7 +1984,7 @@
40187 - * stripping /app1 or /app1/ should lead to
40188 + * stripping /app1 or /app1/ should lead to
40192 @@ -2001,7 +1998,7 @@
40193 0 == strncmp(con->request.orig_uri->ptr, host->strip_request_uri->ptr, host->strip_request_uri->used - 1)) {
40194 /* the left is the same */
40196 - fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_URI"),
40197 + fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_URI"),
40198 con->request.orig_uri->ptr + (host->strip_request_uri->used - 2),
40199 con->request.orig_uri->used - (host->strip_request_uri->used - 2));
40201 @@ -2018,26 +2015,26 @@
40203 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN(""));
40207 s = get_http_method_name(con->request.http_method);
40208 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_METHOD"), s, strlen(s));
40209 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200")); /* if php is compiled with --force-redirect */
40210 s = get_http_version_name(con->request.http_version);
40211 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s));
40215 if (srv_sock->is_ssl) {
40216 fcgi_env_add(p->fcgi_env, CONST_STR_LEN("HTTPS"), CONST_STR_LEN("on"));
40223 fcgi_env_add_request_headers(srv, con, p);
40226 fcgi_header(&(header), FCGI_PARAMS, request_id, p->fcgi_env->used, 0);
40227 buffer_append_memory(b, (const char *)&header, sizeof(header));
40228 buffer_append_memory(b, (const char *)p->fcgi_env->ptr, p->fcgi_env->used);
40231 fcgi_header(&(header), FCGI_PARAMS, request_id, 0, 0);
40232 buffer_append_memory(b, (const char *)&header, sizeof(header));
40234 @@ -2057,7 +2054,7 @@
40236 /* we announce toWrite octects
40237 * now take all the request_content chunk that we need to fill this request
40241 b = chunkqueue_get_append_buffer(hctx->wb);
40242 fcgi_header(&(header), FCGI_STDIN, request_id, weWant, 0);
40243 @@ -2080,16 +2077,16 @@
40244 if (weHave > weWant - written) weHave = weWant - written;
40246 if (p->conf.debug > 10) {
40247 - fprintf(stderr, "%s.%d: sending %lld bytes from (%lld / %lld) %s\n",
40248 - __FILE__, __LINE__,
40251 - req_c->file.length,
40252 + fprintf(stderr, "%s.%d: sending %lld bytes from (%lld / %lld) %s\n",
40253 + __FILE__, __LINE__,
40256 + req_c->file.length,
40257 req_c->file.name->ptr);
40260 assert(weHave != 0);
40263 chunkqueue_append_file(hctx->wb, req_c->file.name, req_c->offset, weHave);
40265 req_c->offset += weHave;
40266 @@ -2104,7 +2101,7 @@
40267 * - we reference the tempfile from the request-content-queue several times
40268 * if the req_c is larger than FCGI_MAX_LENGTH
40269 * - we can't simply cleanup the request-content-queue as soon as possible
40270 - * as it would remove the tempfiles
40271 + * as it would remove the tempfiles
40272 * - the idea is to 'steal' the tempfiles and attach the is_temp flag to the last
40273 * referencing chunk of the fastcgi-write-queue
40275 @@ -2141,7 +2138,7 @@
40276 req_c->offset += weHave;
40277 req_cq->bytes_out += weHave;
40281 hctx->wb->bytes_in += weHave;
40283 if (req_c->offset == req_c->mem->used - 1) {
40284 @@ -2155,12 +2152,12 @@
40290 b->used++; /* add virtual \0 */
40296 b = chunkqueue_get_append_buffer(hctx->wb);
40297 /* terminate STDIN */
40298 fcgi_header(&(header), FCGI_STDIN, request_id, 0, 0);
40299 @@ -2175,118 +2172,19 @@
40300 if ((i+1) % 16 == 0) {
40302 for (j = i-15; j <= i; j++) {
40303 - fprintf(stderr, "%c",
40304 + fprintf(stderr, "%c",
40305 isprint((unsigned char)hctx->write_buffer->ptr[j]) ? hctx->write_buffer->ptr[j] : '.');
40307 fprintf(stderr, "\n");
40315 -static int fcgi_response_parse(server *srv, connection *con, plugin_data *p, buffer *in) {
40318 - handler_ctx *hctx = con->plugin_ctx[p->id];
40319 - fcgi_extension_host *host= hctx->host;
40323 - buffer_copy_string_buffer(p->parse_response, in);
40325 - /* search for \n */
40326 - for (s = p->parse_response->ptr; NULL != (ns = strchr(s, '\n')); s = ns + 1) {
40327 - char *key, *value;
40331 - /* a good day. Someone has read the specs and is sending a \r\n to us */
40333 - if (ns > p->parse_response->ptr &&
40334 - *(ns-1) == '\r') {
40341 - if (NULL == (value = strchr(s, ':'))) {
40342 - /* we expect: "<key>: <value>\n" */
40346 - key_len = value - key;
40350 - while (*value == ' ' || *value == '\t') value++;
40352 - if (host->mode != FCGI_AUTHORIZER ||
40353 - !(con->http_status == 0 ||
40354 - con->http_status == 200)) {
40355 - /* authorizers shouldn't affect the response headers sent back to the client */
40357 - /* don't forward Status: */
40358 - if (0 != strncasecmp(key, "Status", key_len)) {
40359 - if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
40360 - ds = data_response_init();
40362 - buffer_copy_string_len(ds->key, key, key_len);
40363 - buffer_copy_string(ds->value, value);
40365 - array_insert_unique(con->response.headers, (data_unset *)ds);
40369 - switch(key_len) {
40371 - if (0 == strncasecmp(key, "Date", key_len)) {
40372 - con->parsed_response |= HTTP_DATE;
40376 - if (0 == strncasecmp(key, "Status", key_len)) {
40377 - con->http_status = strtol(value, NULL, 10);
40378 - con->parsed_response |= HTTP_STATUS;
40382 - if (0 == strncasecmp(key, "Location", key_len)) {
40383 - con->parsed_response |= HTTP_LOCATION;
40387 - if (0 == strncasecmp(key, "Connection", key_len)) {
40388 - con->response.keep_alive = (0 == strcasecmp(value, "Keep-Alive")) ? 1 : 0;
40389 - con->parsed_response |= HTTP_CONNECTION;
40393 - if (0 == strncasecmp(key, "Content-Length", key_len)) {
40394 - con->response.content_length = strtol(value, NULL, 10);
40395 - con->parsed_response |= HTTP_CONTENT_LENGTH;
40397 - if (con->response.content_length < 0) con->response.content_length = 0;
40405 - /* CGI/1.1 rev 03 - 7.2.1.2 */
40406 - if ((con->parsed_response & HTTP_LOCATION) &&
40407 - !(con->parsed_response & HTTP_STATUS)) {
40408 - con->http_status = 302;
40420 @@ -2327,9 +2225,9 @@
40424 - /* we have at least a header, now check how much me have to fetch */
40425 + /* we have at least a header, now check how much me have to fetch */
40426 header = (FCGI_Header *)(packet->b->ptr);
40429 packet->len = (header->contentLengthB0 | (header->contentLengthB1 << 8)) + header->paddingLength;
40430 packet->request_id = (header->requestIdB0 | (header->requestIdB1 << 8));
40431 packet->type = header->type;
40432 @@ -2348,7 +2246,7 @@
40433 size_t weHave = c->mem->used - c->offset - offset - 1;
40435 if (weHave > weWant) weHave = weWant;
40438 buffer_append_string_len(packet->b, c->mem->ptr + c->offset + offset, weHave);
40440 /* we only skipped the first 8 bytes as they are the fcgi header */
40441 @@ -2380,65 +2278,37 @@
40444 chunkqueue_remove_finished_chunks(hctx->rb);
40450 static int fcgi_demux_response(server *srv, handler_ctx *hctx) {
40456 plugin_data *p = hctx->plugin_data;
40457 connection *con = hctx->remote_conn;
40458 - int fcgi_fd = hctx->fd;
40459 fcgi_extension_host *host= hctx->host;
40460 fcgi_proc *proc = hctx->proc;
40463 - * check how much we have to read
40465 - if (ioctl(hctx->fd, FIONREAD, &toread)) {
40466 - log_error_write(srv, __FILE__, __LINE__, "sd",
40467 - "unexpected end-of-file (perhaps the fastcgi process died):",
40472 - /* init read-buffer */
40474 - if (toread > 0) {
40477 - b = chunkqueue_get_append_buffer(hctx->rb);
40478 - buffer_prepare_copy(b, toread + 1);
40480 - /* append to read-buffer */
40481 - if (-1 == (r = read(hctx->fd, b->ptr, toread))) {
40482 - log_error_write(srv, __FILE__, __LINE__, "sds",
40483 - "unexpected end-of-file (perhaps the fastcgi process died):",
40484 - fcgi_fd, strerror(errno));
40488 - /* this should be catched by the b > 0 above */
40491 - b->used = r + 1; /* one extra for the fake \0 */
40492 - b->ptr[b->used - 1] = '\0';
40494 - log_error_write(srv, __FILE__, __LINE__, "ssdsb",
40495 + switch(srv->network_backend_read(srv, con, hctx->fd, hctx->rb)) {
40496 + case NETWORK_STATUS_WAIT_FOR_EVENT:
40497 + /* we are only triggered when there is a event */
40498 + log_error_write(srv, __FILE__, __LINE__, "ssdsb",
40499 "unexpected end-of-file (perhaps the fastcgi process died):",
40501 "socket:", proc->connection_name);
40504 + case NETWORK_STATUS_SUCCESS:
40507 + log_error_write(srv, __FILE__, __LINE__, "s", "fastcgi-read failed");
40512 * parse the fastcgi packets and forward the content to the write-queue
40517 fastcgi_response_packet packet;
40519 @@ -2454,92 +2324,135 @@
40521 /* is the header already finished */
40522 if (0 == con->file_started) {
40527 - /* search for header terminator
40529 - * if we start with \r\n check if last packet terminated with \r\n
40530 - * if we start with \n check if last packet terminated with \n
40531 - * search for \r\n\r\n
40532 - * search for \n\n
40534 + int have_content_length = 0;
40535 + int need_more = 0;
40538 - if (hctx->response_header->used == 0) {
40539 - buffer_copy_string_buffer(hctx->response_header, packet.b);
40541 - buffer_append_string_buffer(hctx->response_header, packet.b);
40543 + /* append the current packet to the chunk queue */
40544 + chunkqueue_append_buffer(hctx->http_rb, packet.b);
40545 + http_response_reset(p->resp);
40547 - if (NULL != (c = buffer_search_string_len(hctx->response_header, CONST_STR_LEN("\r\n\r\n")))) {
40548 - blen = hctx->response_header->used - (c - hctx->response_header->ptr) - 4;
40549 - hctx->response_header->used = (c - hctx->response_header->ptr) + 3;
40550 - c += 4; /* point the the start of the response */
40551 - } else if (NULL != (c = buffer_search_string_len(hctx->response_header, CONST_STR_LEN("\n\n")))) {
40552 - blen = hctx->response_header->used - (c - hctx->response_header->ptr) - 2;
40553 - hctx->response_header->used = c - hctx->response_header->ptr + 2;
40554 - c += 2; /* point the the start of the response */
40556 - /* no luck, no header found */
40557 + switch(http_response_parse_cq(hctx->http_rb, p->resp)) {
40558 + case PARSE_ERROR:
40559 + /* parsing the response header failed */
40561 + con->http_status = 502; /* Bad Gateway */
40564 + case PARSE_NEED_MORE:
40566 + break; /* leave the loop */
40567 + case PARSE_SUCCESS:
40570 + /* should not happen */
40574 - /* parse the response header */
40575 - fcgi_response_parse(srv, con, p, hctx->response_header);
40576 + if (need_more) break;
40578 - con->file_started = 1;
40579 + chunkqueue_remove_finished_chunks(hctx->http_rb);
40581 - if (host->mode == FCGI_AUTHORIZER &&
40582 - (con->http_status == 0 ||
40583 - con->http_status == 200)) {
40584 - /* a authorizer with approved the static request, ignore the content here */
40585 - hctx->send_content_body = 0;
40586 + con->http_status = p->resp->status;
40588 + /* handle the header fields */
40589 + if (host->mode == FCGI_AUTHORIZER) {
40590 + /* auth mode is a bit different */
40592 + if (con->http_status == 0 ||
40593 + con->http_status == 200) {
40594 + /* a authorizer with approved the static request, ignore the content here */
40595 + hctx->send_content_body = 0;
40599 - if (host->allow_xsendfile &&
40600 - NULL != (ds = (data_string *) array_get_element(con->response.headers, "X-LIGHTTPD-send-file"))) {
40601 - stat_cache_entry *sce;
40602 + /* copy the http-headers */
40603 + for (i = 0; i < p->resp->headers->used; i++) {
40604 + const char *ign[] = { "Status", NULL };
40608 - if (HANDLER_ERROR != stat_cache_get_entry(srv, con, ds->value, &sce)) {
40610 + data_string *header = (data_string *)p->resp->headers->data[i];
40612 - http_chunk_append_file(srv, con, ds->value, 0, sce->st.st_size);
40613 - hctx->send_content_body = 0; /* ignore the content */
40614 - joblist_append(srv, con);
40615 + /* ignore all headers in AUTHORIZER mode */
40616 + if (host->mode == FCGI_AUTHORIZER) continue;
40618 + /* some headers are ignored by default */
40619 + for (j = 0; ign[j]; j++) {
40620 + if (0 == strcasecmp(ign[j], header->key->ptr)) break;
40623 + if (ign[j]) continue;
40625 + if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Location"))) {
40626 + /* CGI/1.1 rev 03 - 7.2.1.2 */
40627 + con->http_status = 302;
40628 + } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("Content-Length"))) {
40629 + have_content_length = 1;
40630 + } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("X-Sendfile")) ||
40631 + 0 == buffer_caseless_compare(CONST_BUF_LEN(header->key), CONST_STR_LEN("X-LIGHTTPD-send-file"))) {
40633 - if (hctx->send_content_body && blen > 1) {
40634 - /* enable chunked-transfer-encoding */
40635 + stat_cache_entry *sce;
40637 + if (host->allow_xsendfile &&
40638 + HANDLER_ERROR != stat_cache_get_entry(srv, con, header->value, &sce)) {
40639 + http_chunk_append_file(srv, con, header->value, 0, sce->st.st_size);
40640 + hctx->send_content_body = 0; /* ignore the content */
40642 + joblist_append(srv, con);
40645 + continue; /* ignore header */
40648 + if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
40649 + ds = data_response_init();
40651 + buffer_copy_string_buffer(ds->key, header->key);
40652 + buffer_copy_string_buffer(ds->value, header->value);
40654 + array_insert_unique(con->response.headers, (data_unset *)ds);
40657 + /* header is complete ... go on with the body */
40659 + con->file_started = 1;
40661 + if (hctx->send_content_body) {
40662 + chunk *c = hctx->http_rb->first;
40664 + /* if we don't have a content-length enable chunked encoding
40667 + * TODO: move this to a later stage in the filter-queue
40669 if (con->request.http_version == HTTP_VERSION_1_1 &&
40670 - !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
40671 + !have_content_length) {
40672 con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
40675 - http_chunk_append_mem(srv, con, c, blen);
40676 + /* copy the rest of the data */
40677 + for (c = hctx->http_rb->first; c; c = c->next) {
40678 + if (c->mem->used > 1) {
40679 + http_chunk_append_mem(srv, con, c->mem->ptr + c->offset, c->mem->used - c->offset);
40680 + c->offset = c->mem->used - 1;
40683 + chunkqueue_remove_finished_chunks(hctx->http_rb);
40684 joblist_append(srv, con);
40686 } else if (hctx->send_content_body && packet.b->used > 1) {
40687 - if (con->request.http_version == HTTP_VERSION_1_1 &&
40688 - !(con->parsed_response & HTTP_CONTENT_LENGTH)) {
40689 - /* enable chunked-transfer-encoding */
40690 - con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED;
40693 http_chunk_append_mem(srv, con, packet.b->ptr, packet.b->used);
40694 joblist_append(srv, con);
40698 - log_error_write(srv, __FILE__, __LINE__, "sb",
40699 + log_error_write(srv, __FILE__, __LINE__, "sb",
40700 "FastCGI-stderr:", packet.b);
40704 case FCGI_END_REQUEST:
40705 con->file_finished = 1;
40708 if (host->mode != FCGI_AUTHORIZER ||
40709 !(con->http_status == 0 ||
40710 con->http_status == 200)) {
40711 @@ -2547,39 +2460,39 @@
40712 http_chunk_append_mem(srv, con, NULL, 0);
40713 joblist_append(srv, con);
40720 - log_error_write(srv, __FILE__, __LINE__, "sd",
40721 + log_error_write(srv, __FILE__, __LINE__, "sd",
40722 "FastCGI: header.type not handled: ", packet.type);
40725 buffer_free(packet.b);
40732 static int fcgi_restart_dead_procs(server *srv, plugin_data *p, fcgi_extension_host *host) {
40736 for (proc = host->first; proc; proc = proc->next) {
40739 if (p->conf.debug > 2) {
40740 - log_error_write(srv, __FILE__, __LINE__, "sbdddd",
40742 + log_error_write(srv, __FILE__, __LINE__, "sbdddd",
40744 proc->connection_name,
40754 * if the remote side is overloaded, we check back after <n> seconds
40758 switch (proc->state) {
40759 case PROC_STATE_KILLED:
40760 @@ -2592,13 +2505,13 @@
40762 case PROC_STATE_OVERLOADED:
40763 if (srv->cur_ts <= proc->disabled_until) break;
40766 proc->state = PROC_STATE_RUNNING;
40767 host->active_procs++;
40769 - log_error_write(srv, __FILE__, __LINE__, "sbdb",
40770 - "fcgi-server re-enabled:",
40771 - host->host, host->port,
40773 + log_error_write(srv, __FILE__, __LINE__, "sbdb",
40774 + "fcgi-server re-enabled:",
40775 + host->host, host->port,
40778 case PROC_STATE_DIED_WAIT_FOR_PID:
40779 @@ -2606,7 +2519,7 @@
40780 if (!proc->is_local) break;
40782 /* the child should not terminate at all */
40785 switch(waitpid(proc->pid, &status, WNOHANG)) {
40787 /* child is still alive */
40788 @@ -2616,45 +2529,45 @@
40790 if (WIFEXITED(status)) {
40792 - log_error_write(srv, __FILE__, __LINE__, "sdsd",
40793 + log_error_write(srv, __FILE__, __LINE__, "sdsd",
40794 "child exited, pid:", proc->pid,
40795 "status:", WEXITSTATUS(status));
40797 } else if (WIFSIGNALED(status)) {
40798 - log_error_write(srv, __FILE__, __LINE__, "sd",
40799 - "child signaled:",
40800 + log_error_write(srv, __FILE__, __LINE__, "sd",
40801 + "child signaled:",
40804 - log_error_write(srv, __FILE__, __LINE__, "sd",
40805 - "child died somehow:",
40806 + log_error_write(srv, __FILE__, __LINE__, "sd",
40807 + "child died somehow:",
40812 proc->state = PROC_STATE_DIED;
40817 /* fall through if we have a dead proc now */
40818 if (proc->state != PROC_STATE_DIED) break;
40820 case PROC_STATE_DIED:
40821 - /* local proc get restarted by us,
40822 + /* local proc get restarted by us,
40823 * remote ones hopefully by the admin */
40826 if (proc->is_local) {
40827 /* we still have connections bound to this proc,
40828 * let them terminate first */
40829 if (proc->load != 0) break;
40832 /* restart the child */
40835 if (p->conf.debug) {
40836 log_error_write(srv, __FILE__, __LINE__, "ssbsdsd",
40837 "--- fastcgi spawning",
40838 "\n\tsocket", proc->connection_name,
40839 "\n\tcurrent:", 1, "/", host->min_procs);
40843 if (fcgi_spawn_connection(srv, p, host, proc)) {
40844 log_error_write(srv, __FILE__, __LINE__, "s",
40845 "ERROR: spawning fcgi failed.");
40846 @@ -2662,18 +2575,18 @@
40849 if (srv->cur_ts <= proc->disabled_until) break;
40852 proc->state = PROC_STATE_RUNNING;
40853 host->active_procs++;
40855 - log_error_write(srv, __FILE__, __LINE__, "sb",
40856 - "fcgi-server re-enabled:",
40858 + log_error_write(srv, __FILE__, __LINE__, "sb",
40859 + "fcgi-server re-enabled:",
40860 proc->connection_name);
40870 @@ -2682,19 +2595,19 @@
40871 fcgi_extension_host *host= hctx->host;
40872 connection *con = hctx->remote_conn;
40878 - /* sanity check */
40879 + /* sanity check */
40881 ((!host->host->used || !host->port) && !host->unixsocket->used)) {
40882 - log_error_write(srv, __FILE__, __LINE__, "sxddd",
40883 + log_error_write(srv, __FILE__, __LINE__, "sxddd",
40884 "write-req: error",
40888 host->unixsocket->used);
40891 hctx->proc->disabled_until = srv->cur_ts + 10;
40892 hctx->proc->state = PROC_STATE_DIED;
40894 @@ -2705,12 +2618,12 @@
40895 if (hctx->state == FCGI_STATE_CONNECT_DELAYED) {
40897 socklen_t socket_error_len = sizeof(socket_error);
40900 /* try to finish the connect() */
40901 if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) {
40902 - log_error_write(srv, __FILE__, __LINE__, "ss",
40903 + log_error_write(srv, __FILE__, __LINE__, "ss",
40904 "getsockopt failed:", strerror(errno));
40907 hctx->proc->disabled_until = srv->cur_ts + 10;
40908 hctx->proc->state = PROC_STATE_DIED;
40910 @@ -2719,12 +2632,12 @@
40911 if (socket_error != 0) {
40912 if (!hctx->proc->is_local || p->conf.debug) {
40913 /* local procs get restarted */
40916 log_error_write(srv, __FILE__, __LINE__, "sssb",
40917 - "establishing connection failed:", strerror(socket_error),
40918 + "establishing connection failed:", strerror(socket_error),
40919 "socket:", hctx->proc->connection_name);
40923 hctx->proc->disabled_until = srv->cur_ts + 5;
40925 if (hctx->proc->is_local) {
40926 @@ -2732,17 +2645,17 @@
40928 hctx->proc->state = PROC_STATE_DIED;
40932 hctx->proc->state = PROC_STATE_DIED;
40935 fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
40936 buffer_append_string(p->statuskey, ".died");
40938 status_counter_inc(srv, CONST_BUF_LEN(p->statuskey));
40941 return HANDLER_ERROR;
40943 - /* go on with preparing the request */
40944 + /* go on with preparing the request */
40945 hctx->state = FCGI_STATE_PREPARE_WRITE;
40948 @@ -2755,14 +2668,14 @@
40949 /* do we have a running process for this host (max-procs) ? */
40952 - for (proc = hctx->host->first;
40953 - proc && proc->state != PROC_STATE_RUNNING;
40954 + for (proc = hctx->host->first;
40955 + proc && proc->state != PROC_STATE_RUNNING;
40956 proc = proc->next);
40959 /* all childs are dead */
40960 if (proc == NULL) {
40961 hctx->fde_ndx = -1;
40964 return HANDLER_ERROR;
40967 @@ -2775,50 +2688,50 @@
40970 ret = host->unixsocket->used ? AF_UNIX : AF_INET;
40973 if (-1 == (hctx->fd = socket(ret, SOCK_STREAM, 0))) {
40974 if (errno == EMFILE ||
40976 - log_error_write(srv, __FILE__, __LINE__, "sd",
40977 + log_error_write(srv, __FILE__, __LINE__, "sd",
40978 "wait for fd at connection:", con->fd);
40981 return HANDLER_WAIT_FOR_FD;
40984 - log_error_write(srv, __FILE__, __LINE__, "ssdd",
40986 + log_error_write(srv, __FILE__, __LINE__, "ssdd",
40987 "socket failed:", strerror(errno), srv->cur_fds, srv->max_fds);
40988 return HANDLER_ERROR;
40990 hctx->fde_ndx = -1;
40996 fdevent_register(srv->ev, hctx->fd, fcgi_handle_fdevent, hctx);
40999 if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) {
41000 - log_error_write(srv, __FILE__, __LINE__, "ss",
41001 + log_error_write(srv, __FILE__, __LINE__, "ss",
41002 "fcntl failed:", strerror(errno));
41005 return HANDLER_ERROR;
41009 if (hctx->proc->is_local) {
41010 hctx->pid = hctx->proc->pid;
41014 switch (fcgi_establish_connection(srv, hctx)) {
41015 case CONNECTION_DELAYED:
41016 /* connection is in progress, wait for an event and call getsockopt() below */
41019 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
41022 fcgi_set_state(srv, hctx, FCGI_STATE_CONNECT_DELAYED);
41023 return HANDLER_WAIT_FOR_EVENT;
41024 case CONNECTION_OVERLOADED:
41025 /* cool down the backend, it is overloaded
41028 - log_error_write(srv, __FILE__, __LINE__, "ssdsd",
41029 + log_error_write(srv, __FILE__, __LINE__, "ssdsd",
41030 "backend is overloaded, we disable it for a 2 seconds and send the request to another backend instead:",
41031 "reconnects:", hctx->reconnects,
41032 "load:", host->load);
41033 @@ -2831,7 +2744,7 @@
41034 buffer_append_string(p->statuskey, ".overloaded");
41036 status_counter_inc(srv, CONST_BUF_LEN(p->statuskey));
41039 return HANDLER_ERROR;
41040 case CONNECTION_DEAD:
41041 /* we got a hard error from the backend like
41042 @@ -2840,19 +2753,19 @@
41044 * for check if the host is back in 5 seconds
41048 hctx->proc->disabled_until = srv->cur_ts + 5;
41049 if (hctx->proc->is_local) {
41050 hctx->proc->state = PROC_STATE_DIED_WAIT_FOR_PID;
41052 hctx->proc->state = PROC_STATE_DIED;
41055 - log_error_write(srv, __FILE__, __LINE__, "ssdsd",
41057 + log_error_write(srv, __FILE__, __LINE__, "ssdsd",
41058 "backend died, we disable it for a 5 seconds and send the request to another backend instead:",
41059 "reconnects:", hctx->reconnects,
41060 "load:", host->load);
41063 fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc);
41064 buffer_append_string(p->statuskey, ".died");
41066 @@ -2863,19 +2776,19 @@
41067 /* everything is ok, go on */
41069 fcgi_set_state(srv, hctx, FCGI_STATE_PREPARE_WRITE);
41073 case CONNECTION_UNSET:
41078 case FCGI_STATE_PREPARE_WRITE:
41079 /* ok, we have the connection */
41082 hctx->proc->load++;
41083 hctx->proc->last_used = srv->cur_ts;
41084 hctx->got_proc = 1;
41087 status_counter_inc(srv, CONST_STR_LEN("fastcgi.requests"));
41088 status_counter_inc(srv, CONST_STR_LEN("fastcgi.active-requests"));
41090 @@ -2898,9 +2811,9 @@
41092 if (p->conf.debug) {
41093 log_error_write(srv, __FILE__, __LINE__, "ssdsbsd",
41095 - "pid:", hctx->proc->pid,
41096 - "socket:", hctx->proc->connection_name,
41098 + "pid:", hctx->proc->pid,
41099 + "socket:", hctx->proc->connection_name,
41100 "load:", hctx->proc->load);
41103 @@ -2908,62 +2821,63 @@
41104 if (hctx->request_id == 0) {
41105 hctx->request_id = fcgi_requestid_new(srv, p);
41107 - log_error_write(srv, __FILE__, __LINE__, "sd",
41108 + log_error_write(srv, __FILE__, __LINE__, "sd",
41109 "fcgi-request is already in use:", hctx->request_id);
41114 fcgi_create_env(srv, hctx, hctx->request_id);
41117 fcgi_set_state(srv, hctx, FCGI_STATE_WRITE);
41121 case FCGI_STATE_WRITE:
41122 - ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
41123 + ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb);
41125 chunkqueue_remove_finished_chunks(hctx->wb);
41131 - /* the connection got dropped after accept()
41133 - * this is most of the time a PHP which dies
41134 + /* the connection got dropped after accept()
41136 + * this is most of the time a PHP which dies
41137 * after PHP_FCGI_MAX_REQUESTS
41142 if (hctx->wb->bytes_out == 0 &&
41143 hctx->reconnects < 5) {
41144 - usleep(10000); /* take away the load of the webserver
41145 - * to let the php a chance to restart
41147 + usleep(10000); /* take away the load of the webserver
41148 + * to let the php a chance to restart
41152 fcgi_reconnect(srv, hctx);
41155 return HANDLER_WAIT_FOR_FD;
41159 /* not reconnected ... why
41162 * far@#lighttpd report this for FreeBSD
41167 - log_error_write(srv, __FILE__, __LINE__, "ssdsd",
41169 + log_error_write(srv, __FILE__, __LINE__, "ssosd",
41170 "[REPORT ME] connection was dropped after accept(). reconnect() denied:",
41171 "write-offset:", hctx->wb->bytes_out,
41172 "reconnect attempts:", hctx->reconnects);
41175 return HANDLER_ERROR;
41178 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
41181 return HANDLER_WAIT_FOR_EVENT;
41183 - log_error_write(srv, __FILE__, __LINE__, "ssd",
41184 + log_error_write(srv, __FILE__, __LINE__, "ssd",
41185 "write failed:", strerror(errno), errno);
41188 return HANDLER_ERROR;
41191 @@ -2975,7 +2889,7 @@
41192 fcgi_set_state(srv, hctx, FCGI_STATE_READ);
41194 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
41197 return HANDLER_WAIT_FOR_EVENT;
41200 @@ -2987,7 +2901,7 @@
41201 log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state");
41202 return HANDLER_ERROR;
41206 return HANDLER_WAIT_FOR_EVENT;
41209 @@ -2996,18 +2910,18 @@
41211 SUBREQUEST_FUNC(mod_fastcgi_handle_subrequest) {
41212 plugin_data *p = p_d;
41215 handler_ctx *hctx = con->plugin_ctx[p->id];
41217 fcgi_extension_host *host;
41220 if (NULL == hctx) return HANDLER_GO_ON;
41224 if (con->mode != p->id) return HANDLER_GO_ON;
41226 /* we don't have a host yet, choose one
41227 - * -> this happens in the first round
41228 + * -> this happens in the first round
41229 * and when the host died and we have to select a new one */
41230 if (hctx->host == NULL) {
41232 @@ -3016,23 +2930,23 @@
41233 /* get best server */
41234 for (k = 0, ndx = -1; k < hctx->ext->used; k++) {
41235 host = hctx->ext->hosts[k];
41238 /* we should have at least one proc that can do something */
41239 if (host->active_procs == 0) continue;
41241 if (used == -1 || host->load < used) {
41250 /* found a server */
41252 /* all hosts are down */
41254 fcgi_connection_close(srv, hctx);
41257 con->http_status = 500;
41258 con->mode = DIRECT;
41260 @@ -3040,16 +2954,16 @@
41263 host = hctx->ext->hosts[ndx];
41266 - * if check-local is disabled, use the uri.path handler
41270 + * if check-local is disabled, use the uri.path handler
41275 /* init handler-context */
41278 - /* we put a connection on this host, move the other new connections to other hosts
41279 + /* we put a connection on this host, move the other new connections to other hosts
41281 * as soon as hctx->host is unassigned, decrease the load again */
41282 hctx->host->load++;
41283 @@ -3063,7 +2977,7 @@
41284 case HANDLER_ERROR:
41289 if (hctx->state == FCGI_STATE_INIT ||
41290 hctx->state == FCGI_STATE_CONNECT_DELAYED) {
41291 if (proc) host->active_procs--;
41292 @@ -3078,7 +2992,7 @@
41293 return HANDLER_WAIT_FOR_FD;
41295 fcgi_connection_close(srv, hctx);
41298 buffer_reset(con->physical.path);
41299 con->mode = DIRECT;
41300 con->http_status = 500;
41301 @@ -3088,12 +3002,12 @@
41304 fcgi_connection_close(srv, hctx);
41307 buffer_reset(con->physical.path);
41308 con->mode = DIRECT;
41309 con->http_status = 503;
41310 joblist_append(srv, con); /* really ? */
41313 return HANDLER_FINISHED;
41315 case HANDLER_WAIT_FOR_EVENT:
41316 @@ -3115,7 +3029,7 @@
41317 handler_ctx *hctx = ctx;
41318 connection *con = hctx->remote_conn;
41319 plugin_data *p = hctx->plugin_data;
41322 fcgi_proc *proc = hctx->proc;
41323 fcgi_extension_host *host= hctx->host;
41325 @@ -3125,8 +3039,8 @@
41330 - if (host->mode == FCGI_AUTHORIZER &&
41332 + if (host->mode == FCGI_AUTHORIZER &&
41333 (con->http_status == 200 ||
41334 con->http_status == 0)) {
41336 @@ -3136,26 +3050,26 @@
41339 buffer_copy_string_buffer(con->physical.doc_root, host->docroot);
41342 buffer_copy_string_buffer(con->physical.path, host->docroot);
41343 buffer_append_string_buffer(con->physical.path, con->uri.path);
41344 fcgi_connection_close(srv, hctx);
41347 con->mode = DIRECT;
41348 con->file_started = 1; /* fcgi_extension won't touch the request afterwards */
41351 fcgi_connection_close(srv, hctx);
41355 joblist_append(srv, con);
41356 return HANDLER_FINISHED;
41358 if (proc->pid && proc->state != PROC_STATE_DIED) {
41362 /* only fetch the zombie if it is not already done */
41365 switch(waitpid(proc->pid, &status, WNOHANG)) {
41367 /* child is still alive */
41368 @@ -3165,60 +3079,61 @@
41370 /* the child should not terminate at all */
41371 if (WIFEXITED(status)) {
41372 - log_error_write(srv, __FILE__, __LINE__, "sdsd",
41373 + log_error_write(srv, __FILE__, __LINE__, "sdsd",
41374 "child exited, pid:", proc->pid,
41375 "status:", WEXITSTATUS(status));
41376 } else if (WIFSIGNALED(status)) {
41377 - log_error_write(srv, __FILE__, __LINE__, "sd",
41378 - "child signaled:",
41379 + log_error_write(srv, __FILE__, __LINE__, "sd",
41380 + "child signaled:",
41383 - log_error_write(srv, __FILE__, __LINE__, "sd",
41384 - "child died somehow:",
41385 + log_error_write(srv, __FILE__, __LINE__, "sd",
41386 + "child died somehow:",
41391 if (p->conf.debug) {
41392 log_error_write(srv, __FILE__, __LINE__, "ssbsdsd",
41393 "--- fastcgi spawning",
41394 "\n\tsocket", proc->connection_name,
41395 "\n\tcurrent:", 1, "/", host->min_procs);
41399 if (fcgi_spawn_connection(srv, p, host, proc)) {
41400 /* respawning failed, retry later */
41401 proc->state = PROC_STATE_DIED;
41403 - log_error_write(srv, __FILE__, __LINE__, "s",
41404 + log_error_write(srv, __FILE__, __LINE__, "s",
41405 "respawning failed, will retry later");
41414 if (con->file_started == 0) {
41415 /* nothing has been send out yet, try to use another child */
41418 if (hctx->wb->bytes_out == 0 &&
41419 hctx->reconnects < 5) {
41420 fcgi_reconnect(srv, hctx);
41422 - log_error_write(srv, __FILE__, __LINE__, "ssbsbs",
41424 + log_error_write(srv, __FILE__, __LINE__, "ssbsbs",
41425 "response not received, request not sent",
41426 - "on socket:", proc->connection_name,
41427 + "on socket:", proc->connection_name,
41428 "for", con->uri.path, ", reconnecting");
41431 return HANDLER_WAIT_FOR_FD;
41434 - log_error_write(srv, __FILE__, __LINE__, "sosbsbs",
41436 + log_error_write(srv, __FILE__, __LINE__, "sosbsbs",
41437 "response not received, request sent:", hctx->wb->bytes_out,
41438 - "on socket:", proc->connection_name,
41439 + "on socket:", proc->connection_name,
41440 "for", con->uri.path, ", closing connection");
41443 fcgi_connection_close(srv, hctx);
41446 connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST);
41447 buffer_reset(con->physical.path);
41448 con->http_status = 500;
41449 @@ -3226,76 +3141,76 @@
41451 /* response might have been already started, kill the connection */
41452 fcgi_connection_close(srv, hctx);
41454 - log_error_write(srv, __FILE__, __LINE__, "ssbsbs",
41456 + log_error_write(srv, __FILE__, __LINE__, "ssbsbs",
41457 "response already sent out, but backend returned error",
41458 - "on socket:", proc->connection_name,
41459 + "on socket:", proc->connection_name,
41460 "for", con->uri.path, ", terminating connection");
41463 connection_set_state(srv, con, CON_STATE_ERROR);
41471 joblist_append(srv, con);
41472 return HANDLER_FINISHED;
41477 if (revents & FDEVENT_OUT) {
41478 if (hctx->state == FCGI_STATE_CONNECT_DELAYED ||
41479 hctx->state == FCGI_STATE_WRITE) {
41480 /* we are allowed to send something out
41483 * 1. in a unfinished connect() call
41484 * 2. in a unfinished write() call (long POST request)
41486 return mod_fastcgi_handle_subrequest(srv, con, p);
41488 - log_error_write(srv, __FILE__, __LINE__, "sd",
41489 - "got a FDEVENT_OUT and didn't know why:",
41490 + log_error_write(srv, __FILE__, __LINE__, "sd",
41491 + "got a FDEVENT_OUT and didn't know why:",
41497 /* perhaps this issue is already handled */
41498 if (revents & FDEVENT_HUP) {
41499 if (hctx->state == FCGI_STATE_CONNECT_DELAYED) {
41500 /* getoptsock will catch this one (right ?)
41502 - * if we are in connect we might get a EINPROGRESS
41503 - * in the first call and a FDEVENT_HUP in the
41505 + * if we are in connect we might get a EINPROGRESS
41506 + * in the first call and a FDEVENT_HUP in the
41510 * FIXME: as it is a bit ugly.
41514 return mod_fastcgi_handle_subrequest(srv, con, p);
41515 } else if (hctx->state == FCGI_STATE_READ &&
41516 hctx->proc->port == 0) {
41520 * ioctl says 8192 bytes to read from PHP and we receive directly a HUP for the socket
41521 * even if the FCGI_FIN packet is not received yet
41524 - log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd",
41525 - "error: unexpected close of fastcgi connection for",
41526 + log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd",
41527 + "error: unexpected close of fastcgi connection for",
41529 - "(no fastcgi process on host:",
41530 + "(no fastcgi process on host:",
41539 connection_set_state(srv, con, CON_STATE_ERROR);
41540 fcgi_connection_close(srv, hctx);
41541 joblist_append(srv, con);
41543 } else if (revents & FDEVENT_ERR) {
41544 - log_error_write(srv, __FILE__, __LINE__, "s",
41545 + log_error_write(srv, __FILE__, __LINE__, "s",
41546 "fcgi: got a FDEVENT_ERR. Don't know why.");
41547 /* kill all connections to the fastcgi process */
41549 @@ -3304,46 +3219,43 @@
41550 fcgi_connection_close(srv, hctx);
41551 joblist_append(srv, con);
41555 return HANDLER_FINISHED;
41557 -#define PATCH(x) \
41558 - p->conf.x = s->x;
41560 static int fcgi_patch_connection(server *srv, connection *con, plugin_data *p) {
41562 plugin_config *s = p->config_storage[0];
41566 - PATCH(ext_mapping);
41569 + PATCH_OPTION(exts);
41570 + PATCH_OPTION(debug);
41571 + PATCH_OPTION(ext_mapping);
41573 /* skip the first, the global context */
41574 for (i = 1; i < srv->config_context->used; i++) {
41575 data_config *dc = (data_config *)srv->config_context->data[i];
41576 s = p->config_storage[i];
41579 /* condition didn't match */
41580 if (!config_check_cond(srv, con, dc)) continue;
41584 for (j = 0; j < dc->value->used; j++) {
41585 data_unset *du = dc->value->data[j];
41588 if (buffer_is_equal_string(du->key, CONST_STR_LEN("fastcgi.server"))) {
41590 + PATCH_OPTION(exts);
41591 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("fastcgi.debug"))) {
41593 + PATCH_OPTION(debug);
41594 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("fastcgi.map-extensions"))) {
41595 - PATCH(ext_mapping);
41596 + PATCH_OPTION(ext_mapping);
41607 static handler_t fcgi_check_extension(server *srv, connection *con, void *p_d, int uri_path_handler) {
41608 plugin_data *p = p_d;
41610 @@ -3351,16 +3263,16 @@
41612 fcgi_extension *extension = NULL;
41613 fcgi_extension_host *host = NULL;
41616 /* Possibly, we processed already this request */
41617 if (con->file_started == 1) return HANDLER_GO_ON;
41619 fn = uri_path_handler ? con->uri.path : con->physical.path;
41621 if (buffer_is_empty(fn)) return HANDLER_GO_ON;
41624 s_len = fn->used - 1;
41627 fcgi_patch_connection(srv, con, p);
41629 /* fastcgi.map-extensions maps extensions to existing fastcgi.server entries
41630 @@ -3368,24 +3280,24 @@
41631 * fastcgi.map-extensions = ( ".php3" => ".php" )
41633 * fastcgi.server = ( ".php" => ... )
41638 /* check if extension-mapping matches */
41639 for (k = 0; k < p->conf.ext_mapping->used; k++) {
41640 data_string *ds = (data_string *)p->conf.ext_mapping->data[k];
41641 size_t ct_len; /* length of the config entry */
41644 if (ds->key->used == 0) continue;
41647 ct_len = ds->key->used - 1;
41650 if (s_len < ct_len) continue;
41653 /* found a mapping */
41654 if (0 == strncmp(fn->ptr + s_len - ct_len, ds->key->ptr, ct_len)) {
41655 /* check if we know the extension */
41658 /* we can reuse k here */
41659 for (k = 0; k < p->conf.exts->used; k++) {
41660 extension = p->conf.exts->exts[k];
41661 @@ -3407,15 +3319,15 @@
41662 /* check if extension matches */
41663 for (k = 0; k < p->conf.exts->used; k++) {
41664 size_t ct_len; /* length of the config entry */
41667 extension = p->conf.exts->exts[k];
41670 if (extension->key->used == 0) continue;
41673 ct_len = extension->key->used - 1;
41676 if (s_len < ct_len) continue;
41679 /* check extension in the form "/fcgi_pattern" */
41680 if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) {
41682 @@ -3441,10 +3353,10 @@
41686 - /* we found one host that is alive */
41687 + /* we found one host that is alive */
41693 /* sorry, we don't have a server alive for this ext */
41694 buffer_reset(con->physical.path);
41695 @@ -3459,72 +3371,72 @@
41696 "on", extension->key,
41701 return HANDLER_FINISHED;
41704 /* a note about no handler is not sent yey */
41705 extension->note_is_sent = 0;
41708 - * if check-local is disabled, use the uri.path handler
41711 + * if check-local is disabled, use the uri.path handler
41716 /* init handler-context */
41717 if (uri_path_handler) {
41718 if (host->check_local == 0) {
41723 hctx = handler_ctx_init();
41726 hctx->remote_conn = con;
41727 hctx->plugin_data = p;
41729 hctx->ext = extension;
41733 hctx->conf.exts = p->conf.exts;
41734 hctx->conf.debug = p->conf.debug;
41737 con->plugin_ctx[p->id] = hctx;
41743 if (con->conf.log_request_handling) {
41744 - log_error_write(srv, __FILE__, __LINE__, "s",
41745 + log_error_write(srv, __FILE__, __LINE__, "s",
41746 "handling it in mod_fastcgi");
41749 - /* the prefix is the SCRIPT_NAME,
41751 + /* the prefix is the SCRIPT_NAME,
41752 * everthing from start to the next slash
41753 * this is important for check-local = "disable"
41756 * if prefix = /admin.fcgi
41759 * /admin.fcgi/foo/bar
41762 * SCRIPT_NAME = /admin.fcgi
41763 * PATH_INFO = /foo/bar
41766 * if prefix = /fcgi-bin/
41769 * /fcgi-bin/foo/bar
41772 * SCRIPT_NAME = /fcgi-bin/foo
41779 /* the rewrite is only done for /prefix/? matches */
41780 if (extension->key->ptr[0] == '/' &&
41781 con->uri.path->used > extension->key->used &&
41782 NULL != (pathinfo = strchr(con->uri.path->ptr + extension->key->used - 1, '/'))) {
41783 - /* rewrite uri.path and pathinfo */
41785 + /* rewrite uri.path and pathinfo */
41787 buffer_copy_string(con->request.pathinfo, pathinfo);
41790 con->uri.path->used -= con->request.pathinfo->used - 1;
41791 con->uri.path->ptr[con->uri.path->used - 1] = '\0';
41793 @@ -3532,19 +3444,19 @@
41796 hctx = handler_ctx_init();
41799 hctx->remote_conn = con;
41800 hctx->plugin_data = p;
41802 hctx->ext = extension;
41805 hctx->conf.exts = p->conf.exts;
41806 hctx->conf.debug = p->conf.debug;
41809 con->plugin_ctx[p->id] = hctx;
41815 if (con->conf.log_request_handling) {
41816 log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_fastcgi");
41818 @@ -3566,19 +3478,19 @@
41819 JOBLIST_FUNC(mod_fastcgi_handle_joblist) {
41820 plugin_data *p = p_d;
41821 handler_ctx *hctx = con->plugin_ctx[p->id];
41824 if (hctx == NULL) return HANDLER_GO_ON;
41826 if (hctx->fd != -1) {
41827 switch (hctx->state) {
41828 case FCGI_STATE_READ:
41829 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN);
41833 case FCGI_STATE_CONNECT_DELAYED:
41834 case FCGI_STATE_WRITE:
41835 fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT);
41839 case FCGI_STATE_INIT:
41841 @@ -3595,7 +3507,7 @@
41843 static handler_t fcgi_connection_close_callback(server *srv, connection *con, void *p_d) {
41844 plugin_data *p = p_d;
41847 fcgi_connection_close(srv, con->plugin_ctx[p->id]);
41849 return HANDLER_GO_ON;
41850 @@ -3604,16 +3516,39 @@
41851 TRIGGER_FUNC(mod_fastcgi_handle_trigger) {
41852 plugin_data *p = p_d;
41858 /* perhaps we should kill a connect attempt after 10-15 seconds
41861 * currently we wait for the TCP timeout which is on Linux 180 seconds
41868 + for (i = 0; i < srv->conns->used; i++) {
41869 + connection *con = srv->conns->ptr[i];
41870 + handler_ctx *hctx = con->plugin_ctx[p->id];
41872 + /* if a connection is ours and is in handle-req for more than max-request-time
41873 + * kill the connection */
41875 + if (con->mode != p->id) continue;
41876 + if (con->state != CON_STATE_HANDLE_REQUEST) continue;
41877 + if (srv->cur_ts < con->request_start + 60) continue;
41879 + /* the request is waiting for a FCGI_STDOUT since 60 seconds */
41881 + /* kill the connection */
41883 + log_error_write(srv, __FILE__, __LINE__, "s", "fastcgi backend didn't responded after 60 seconds");
41885 + fcgi_connection_close(srv, hctx);
41887 + con->mode = DIRECT;
41888 + con->http_status = 500;
41890 + joblist_append(srv, con);
41893 /* check all childs if they are still up */
41895 for (i = 0; i < srv->config_context->used; i++) {
41896 @@ -3628,45 +3563,45 @@
41897 fcgi_extension *ex;
41899 ex = exts->exts[j];
41902 for (n = 0; n < ex->used; n++) {
41906 unsigned long sum_load = 0;
41907 fcgi_extension_host *host;
41910 host = ex->hosts[n];
41913 fcgi_restart_dead_procs(srv, p, host);
41916 for (proc = host->first; proc; proc = proc->next) {
41917 sum_load += proc->load;
41921 if (host->num_procs &&
41922 host->num_procs < host->max_procs &&
41923 (sum_load / host->num_procs) > host->max_load_per_proc) {
41924 /* overload, spawn new child */
41925 if (p->conf.debug) {
41926 - log_error_write(srv, __FILE__, __LINE__, "s",
41927 + log_error_write(srv, __FILE__, __LINE__, "s",
41928 "overload detected, spawning a new child");
41932 for (proc = host->unused_procs; proc && proc->pid != 0; proc = proc->next);
41936 if (proc == host->unused_procs) host->unused_procs = proc->next;
41939 if (proc->next) proc->next->prev = NULL;
41944 proc = fastcgi_process_init();
41945 proc->id = host->max_id++;
41952 if (buffer_is_empty(host->unixsocket)) {
41953 proc->port = host->port + proc->id;
41955 @@ -3674,13 +3609,13 @@
41956 buffer_append_string(proc->unixsocket, "-");
41957 buffer_append_long(proc->unixsocket, proc->id);
41961 if (fcgi_spawn_connection(srv, p, host, proc)) {
41962 log_error_write(srv, __FILE__, __LINE__, "s",
41963 "ERROR: spawning fcgi failed.");
41964 return HANDLER_ERROR;
41969 proc->next = host->first;
41971 @@ -3688,56 +3623,56 @@
41973 host->first = proc;
41977 for (proc = host->first; proc; proc = proc->next) {
41978 if (proc->load != 0) break;
41979 if (host->num_procs <= host->min_procs) break;
41980 if (proc->pid == 0) continue;
41983 if (srv->cur_ts - proc->last_used > host->idle_timeout) {
41984 /* a proc is idling for a long time now,
41988 if (p->conf.debug) {
41989 - log_error_write(srv, __FILE__, __LINE__, "ssbsd",
41990 - "idle-timeout reached, terminating child:",
41991 - "socket:", proc->connection_name,
41992 + log_error_write(srv, __FILE__, __LINE__, "ssbsd",
41993 + "idle-timeout reached, terminating child:",
41994 + "socket:", proc->connection_name,
42001 if (proc->next) proc->next->prev = proc->prev;
42002 if (proc->prev) proc->prev->next = proc->next;
42005 if (proc->prev == NULL) host->first = proc->next;
42009 proc->next = host->unused_procs;
42012 if (host->unused_procs) host->unused_procs->prev = proc;
42013 host->unused_procs = proc;
42016 kill(proc->pid, SIGTERM);
42019 proc->state = PROC_STATE_KILLED;
42021 - log_error_write(srv, __FILE__, __LINE__, "ssbsd",
42023 - "socket:", proc->connection_name,
42025 + log_error_write(srv, __FILE__, __LINE__, "ssbsd",
42027 + "socket:", proc->connection_name,
42034 /* proc is now in unused, let the next second handle the next process */
42041 for (proc = host->unused_procs; proc; proc = proc->next) {
42045 if (proc->pid == 0) continue;
42048 switch (waitpid(proc->pid, &status, WNOHANG)) {
42050 /* child still running after timeout, good */
42051 @@ -3745,10 +3680,10 @@
42053 if (errno != EINTR) {
42054 /* no PID found ? should never happen */
42055 - log_error_write(srv, __FILE__, __LINE__, "sddss",
42056 + log_error_write(srv, __FILE__, __LINE__, "sddss",
42057 "pid ", proc->pid, proc->state,
42058 "not found:", strerror(errno));
42062 if (errno == ECHILD) {
42063 /* someone else has cleaned up for us */
42064 @@ -3762,25 +3697,26 @@
42065 /* the child should not terminate at all */
42066 if (WIFEXITED(status)) {
42067 if (proc->state != PROC_STATE_KILLED) {
42068 - log_error_write(srv, __FILE__, __LINE__, "sdb",
42070 + log_error_write(srv, __FILE__, __LINE__, "sdb",
42072 WEXITSTATUS(status), proc->connection_name);
42074 } else if (WIFSIGNALED(status)) {
42075 if (WTERMSIG(status) != SIGTERM) {
42076 - log_error_write(srv, __FILE__, __LINE__, "sd",
42077 - "child signaled:",
42078 + log_error_write(srv, __FILE__, __LINE__, "sd",
42079 + "child signaled:",
42083 - log_error_write(srv, __FILE__, __LINE__, "sd",
42084 - "child died somehow:",
42085 + log_error_write(srv, __FILE__, __LINE__, "sd",
42086 + "child died somehow:",
42090 proc->state = PROC_STATE_UNSET;
42097 @@ -3804,8 +3740,8 @@
42098 p->handle_subrequest = mod_fastcgi_handle_subrequest;
42099 p->handle_joblist = mod_fastcgi_handle_joblist;
42100 p->handle_trigger = mod_fastcgi_handle_trigger;
42109 Property changes on: src/mod_fastcgi.c
42110 ___________________________________________________________________
42111 Name: svn:eol-style
42114 Index: src/fdevent_poll.c
42115 ===================================================================
42116 --- src/fdevent_poll.c (.../tags/lighttpd-1.4.11) (revision 1159)
42117 +++ src/fdevent_poll.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
42119 #include <sys/types.h>
42121 -#include <unistd.h>
42122 #include <stdlib.h>
42124 #include <string.h>
42125 @@ -20,19 +19,19 @@
42127 static int fdevent_poll_event_del(fdevents *ev, int fde_ndx, int fd) {
42128 if (fde_ndx < 0) return -1;
42131 if ((size_t)fde_ndx >= ev->used) {
42132 fprintf(stderr, "%s.%d: del! out of range %d %zd\n", __FILE__, __LINE__, fde_ndx, ev->used);
42137 if (ev->pollfds[fde_ndx].fd == fd) {
42138 size_t k = fde_ndx;
42141 ev->pollfds[k].fd = -1;
42142 /* ev->pollfds[k].events = 0; */
42143 /* ev->pollfds[k].revents = 0; */
42146 if (ev->unused.size == 0) {
42147 ev->unused.size = 16;
42148 ev->unused.ptr = malloc(sizeof(*(ev->unused.ptr)) * ev->unused.size);
42149 @@ -40,47 +39,47 @@
42150 ev->unused.size += 16;
42151 ev->unused.ptr = realloc(ev->unused.ptr, sizeof(*(ev->unused.ptr)) * ev->unused.size);
42155 ev->unused.ptr[ev->unused.used++] = k;
42165 static int fdevent_poll_event_compress(fdevents *ev) {
42169 if (ev->used == 0) return 0;
42170 if (ev->unused.used != 0) return 0;
42173 for (j = ev->used - 1; j + 1 > 0 && ev->pollfds[j].fd == -1; j--) ev->used--;
42180 static int fdevent_poll_event_add(fdevents *ev, int fde_ndx, int fd, int events) {
42184 if (fde_ndx != -1) {
42185 if (ev->pollfds[fde_ndx].fd == fd) {
42186 ev->pollfds[fde_ndx].events = events;
42191 fprintf(stderr, "%s.%d: add: (%d, %d)\n", __FILE__, __LINE__, fde_ndx, ev->pollfds[fde_ndx].fd);
42196 if (ev->unused.used > 0) {
42197 int k = ev->unused.ptr[--ev->unused.used];
42200 ev->pollfds[k].fd = fd;
42201 ev->pollfds[k].events = events;
42206 if (ev->size == 0) {
42207 @@ -90,10 +89,10 @@
42209 ev->pollfds = realloc(ev->pollfds, sizeof(*ev->pollfds) * ev->size);
42213 ev->pollfds[ev->used].fd = fd;
42214 ev->pollfds[ev->used].events = events;
42220 @@ -109,12 +108,12 @@
42222 if (ndx >= ev->used) {
42223 fprintf(stderr, "%s.%d: dying because: event: %zd >= %zd\n", __FILE__, __LINE__, ndx, ev->used);
42233 if (ev->pollfds[ndx].revents & POLLNVAL) {
42234 /* should never happen */
42236 @@ -131,7 +130,7 @@
42237 if (poll_r & POLLHUP) r |= FDEVENT_HUP;
42238 if (poll_r & POLLNVAL) r |= FDEVENT_NVAL;
42239 if (poll_r & POLLPRI) r |= FDEVENT_PRI;
42242 return ev->pollfds[ndx].revents;
42245 @@ -141,12 +140,12 @@
42247 static int fdevent_poll_event_next_fdndx(fdevents *ev, int ndx) {
42251 i = (ndx < 0) ? 0 : ndx + 1;
42252 for (; i < ev->used; i++) {
42253 if (ev->pollfds[i].revents) break;
42260 @@ -154,17 +153,17 @@
42261 ev->type = FDEVENT_HANDLER_POLL;
42263 ev->x = fdevent_poll_##x;
42274 SET(event_next_fdndx);
42276 SET(event_get_revent);
42283 Property changes on: src/fdevent_poll.c
42284 ___________________________________________________________________
42285 Name: svn:eol-style
42288 Index: src/network_solaris_sendfilev.c
42289 ===================================================================
42290 --- src/network_solaris_sendfilev.c (.../tags/lighttpd-1.4.11) (revision 1159)
42291 +++ src/network_solaris_sendfilev.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
42292 @@ -29,114 +29,34 @@
42296 - * a very simple sendfilev() interface for solaris which can be optimised a lot more
42297 + * a very simple sendfilev() interface for solaris which can be optimised a lot more
42298 * as solaris sendfilev() supports 'sending everythin in one syscall()'
42300 - * If you want such an interface and need the performance, just give me an account on
42303 + * If you want such an interface and need the performance, just give me an account on
42305 * - jan@kneschke.de
42309 -int network_write_chunkqueue_solarissendfilev(server *srv, connection *con, int fd, chunkqueue *cq) {
42310 +NETWORK_BACKEND_WRITE(solarissendfilev) {
42312 size_t chunks_written = 0;
42315 for(c = cq->first; c; c = c->next, chunks_written++) {
42316 int chunk_finished = 0;
42318 + network_status_t ret;
42321 - case MEM_CHUNK: {
42326 - size_t num_chunks, i;
42327 - struct iovec chunks[UIO_MAXIOV];
42330 - size_t num_bytes = 0;
42332 - /* we can't send more then SSIZE_MAX bytes in one chunk */
42334 - /* build writev list
42336 - * 1. limit: num_chunks < UIO_MAXIOV
42337 - * 2. limit: num_bytes < SSIZE_MAX
42339 - for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next);
42341 - for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
42342 - if (tc->mem->used == 0) {
42343 - chunks[i].iov_base = tc->mem->ptr;
42344 - chunks[i].iov_len = 0;
42346 - offset = tc->mem->ptr + tc->offset;
42347 - toSend = tc->mem->used - 1 - tc->offset;
42349 - chunks[i].iov_base = offset;
42351 - /* protect the return value of writev() */
42352 - if (toSend > SSIZE_MAX ||
42353 - num_bytes + toSend > SSIZE_MAX) {
42354 - chunks[i].iov_len = SSIZE_MAX - num_bytes;
42356 - num_chunks = i + 1;
42359 - chunks[i].iov_len = toSend;
42362 - num_bytes += toSend;
42365 + ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, &c);
42367 + if (ret != NETWORK_STATUS_SUCCESS) {
42371 - if ((r = writev(fd, chunks, num_chunks)) < 0) {
42381 - log_error_write(srv, __FILE__, __LINE__, "ssd",
42382 - "writev failed:", strerror(errno), fd);
42388 - /* check which chunks have been written */
42389 - cq->bytes_out += r;
42391 - for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
42392 - if (r >= (ssize_t)chunks[i].iov_len) {
42394 - r -= chunks[i].iov_len;
42395 - tc->offset += chunks[i].iov_len;
42397 - if (chunk_finished) {
42398 - /* skip the chunks from further touches */
42399 - chunks_written++;
42402 - /* chunks_written + c = c->next is done in the for()*/
42403 - chunk_finished++;
42406 - /* partially written */
42409 - chunk_finished = 0;
42416 + chunk_finished = 1;
42423 @@ -144,25 +64,25 @@
42424 sendfilevec_t fvec;
42425 stat_cache_entry *sce = NULL;
42429 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
42430 log_error_write(srv, __FILE__, __LINE__, "sb",
42431 strerror(errno), c->file.name);
42436 offset = c->file.start + c->offset;
42437 toSend = c->file.length - c->offset;
42440 if (offset > sce->st.st_size) {
42441 log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name);
42447 if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) {
42448 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
42454 @@ -170,44 +90,43 @@
42456 fvec.sfv_off = offset;
42457 fvec.sfv_len = toSend;
42460 /* Solaris sendfilev() */
42461 if (-1 == (r = sendfilev(fd, &fvec, 1, &written))) {
42462 if (errno != EAGAIN) {
42463 log_error_write(srv, __FILE__, __LINE__, "ssd", "sendfile: ", strerror(errno), errno);
42468 + return NETWORK_STATUS_FATAL_ERROR;
42477 c->offset += written;
42478 cq->bytes_out += written;
42481 if (c->offset == c->file.length) {
42482 chunk_finished = 1;
42490 log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
42494 + return NETWORK_STATUS_FATAL_ERROR;
42498 if (!chunk_finished) {
42499 /* not finished yet */
42506 - return chunks_written;
42507 + return NETWORK_STATUS_SUCCESS;
42512 Property changes on: src/network_solaris_sendfilev.c
42513 ___________________________________________________________________
42514 Name: svn:eol-style
42517 Index: src/fdevent_select.c
42518 ===================================================================
42519 --- src/fdevent_select.c (.../tags/lighttpd-1.4.11) (revision 1159)
42520 +++ src/fdevent_select.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
42522 -#include <sys/time.h>
42523 #include <sys/types.h>
42525 -#include <unistd.h>
42526 #include <stdlib.h>
42527 #include <string.h>
42529 #include <signal.h>
42531 #include <assert.h>
42532 +#include <stdio.h>
42534 #include "fdevent.h"
42535 #include "settings.h"
42536 #include "buffer.h"
42538 +#include "sys-socket.h"
42542 static int fdevent_select_reset(fdevents *ev) {
42546 /* we should be protected by max-fds, but you never know */
42548 assert(fd < FD_SETSIZE);
42551 if (events & FDEVENT_IN) {
42552 FD_SET(fd, &(ev->select_set_read));
42553 @@ -49,28 +52,28 @@
42554 FD_SET(fd, &(ev->select_set_write));
42556 FD_SET(fd, &(ev->select_set_error));
42559 if (fd > ev->select_max_fd) ev->select_max_fd = fd;
42565 static int fdevent_select_poll(fdevents *ev, int timeout_ms) {
42569 tv.tv_sec = timeout_ms / 1000;
42570 tv.tv_usec = (timeout_ms % 1000) * 1000;
42573 ev->select_read = ev->select_set_read;
42574 ev->select_write = ev->select_set_write;
42575 ev->select_error = ev->select_set_error;
42578 return select(ev->select_max_fd + 1, &(ev->select_read), &(ev->select_write), &(ev->select_error), &tv);
42581 static int fdevent_select_event_get_revent(fdevents *ev, size_t ndx) {
42585 if (FD_ISSET(ndx, &(ev->select_read))) {
42586 revents |= FDEVENT_IN;
42589 if (FD_ISSET(ndx, &(ev->select_error))) {
42590 revents |= FDEVENT_ERR;
42597 @@ -92,15 +95,15 @@
42599 static int fdevent_select_event_next_fdndx(fdevents *ev, int ndx) {
42603 i = (ndx < 0) ? 0 : ndx + 1;
42606 for (; i < ev->select_max_fd + 1; i++) {
42607 if (FD_ISSET(i, &(ev->select_read))) break;
42608 if (FD_ISSET(i, &(ev->select_write))) break;
42609 if (FD_ISSET(i, &(ev->select_error))) break;
42616 @@ -108,17 +111,17 @@
42617 ev->type = FDEVENT_HANDLER_SELECT;
42619 ev->x = fdevent_select_##x;
42630 SET(event_next_fdndx);
42632 SET(event_get_revent);
42639 Property changes on: src/fdevent_select.c
42640 ___________________________________________________________________
42641 Name: svn:eol-style
42644 Index: src/stream.c
42645 ===================================================================
42646 --- src/stream.c (.../tags/lighttpd-1.4.11) (revision 1159)
42647 +++ src/stream.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
42649 #include <sys/types.h>
42650 #include <sys/stat.h>
42652 -#include <unistd.h>
42655 #include "stream.h"
42659 #include "sys-mmap.h"
42660 +#include "sys-files.h"
42663 # define O_BINARY 0
42664 @@ -19,39 +19,39 @@
42668 -#elif defined __WIN32
42669 +#elif defined _WIN32
42677 if (-1 == stat(fn->ptr, &st)) {
42682 f->size = st.st_size;
42685 if (-1 == (fd = open(fn->ptr, O_RDONLY | O_BINARY))) {
42690 f->start = mmap(0, f->size, PROT_READ, MAP_SHARED, fd, 0);
42696 if (MAP_FAILED == f->start) {
42700 -#elif defined __WIN32
42701 - fh = CreateFile(fn->ptr,
42706 - FILE_ATTRIBUTE_READONLY,
42707 +#elif defined _WIN32
42708 + fh = CreateFile(fn->ptr,
42713 + FILE_ATTRIBUTE_READONLY,
42716 if (!fh) return -1;
42721 - FORMAT_MESSAGE_ALLOCATE_BUFFER |
42722 + FORMAT_MESSAGE_ALLOCATE_BUFFER |
42723 FORMAT_MESSAGE_FROM_SYSTEM,
42732 p = MapViewOfFile(mh,
42739 -# error no mmap found
42740 +# error no mmap found
42748 Property changes on: src/stream.c
42749 ___________________________________________________________________
42750 Name: svn:eol-style
42754 Property changes on: src/mod_ssi_exprparser.y
42755 ___________________________________________________________________
42756 Name: svn:eol-style
42759 Index: src/mod_access.c
42760 ===================================================================
42761 --- src/mod_access.c (.../tags/lighttpd-1.4.11) (revision 1159)
42762 +++ src/mod_access.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
42763 @@ -8,126 +8,125 @@
42765 #include "plugin.h"
42767 +#include "sys-strings.h"
42770 array *access_deny;
42777 plugin_config **config_storage;
42779 - plugin_config conf;
42781 + plugin_config conf;
42784 INIT_FUNC(mod_access_init) {
42788 p = calloc(1, sizeof(*p));
42794 FREE_FUNC(mod_access_free) {
42795 plugin_data *p = p_d;
42800 if (!p) return HANDLER_GO_ON;
42803 if (p->config_storage) {
42805 for (i = 0; i < srv->config_context->used; i++) {
42806 plugin_config *s = p->config_storage[i];
42809 array_free(s->access_deny);
42814 free(p->config_storage);
42821 return HANDLER_GO_ON;
42824 SETDEFAULTS_FUNC(mod_access_set_defaults) {
42825 plugin_data *p = p_d;
42828 - config_values_t cv[] = {
42830 + config_values_t cv[] = {
42831 { "url.access-deny", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },
42832 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
42836 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
42839 for (i = 0; i < srv->config_context->used; i++) {
42843 s = calloc(1, sizeof(plugin_config));
42844 s->access_deny = array_init();
42847 cv[0].destination = s->access_deny;
42850 p->config_storage[i] = s;
42853 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
42854 return HANDLER_ERROR;
42859 return HANDLER_GO_ON;
42862 -#define PATCH(x) \
42863 - p->conf.x = s->x;
42864 static int mod_access_patch_connection(server *srv, connection *con, plugin_data *p) {
42866 plugin_config *s = p->config_storage[0];
42868 - PATCH(access_deny);
42870 + PATCH_OPTION(access_deny);
42872 /* skip the first, the global context */
42873 for (i = 1; i < srv->config_context->used; i++) {
42874 data_config *dc = (data_config *)srv->config_context->data[i];
42875 s = p->config_storage[i];
42878 /* condition didn't match */
42879 if (!config_check_cond(srv, con, dc)) continue;
42883 for (j = 0; j < dc->value->used; j++) {
42884 data_unset *du = dc->value->data[j];
42887 if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.access-deny"))) {
42888 - PATCH(access_deny);
42889 + PATCH_OPTION(access_deny);
42899 URIHANDLER_FUNC(mod_access_uri_handler) {
42900 plugin_data *p = p_d;
42905 if (con->uri.path->used == 0) return HANDLER_GO_ON;
42908 mod_access_patch_connection(srv, con, p);
42911 s_len = con->uri.path->used - 1;
42914 for (k = 0; k < p->conf.access_deny->used; k++) {
42915 data_string *ds = (data_string *)p->conf.access_deny->data[k];
42916 int ct_len = ds->value->used - 1;
42919 if (ct_len > s_len) continue;
42922 if (ds->value->used == 0) continue;
42924 /* if we have a case-insensitive FS we have to lower-case the URI here too */
42925 @@ -135,18 +134,18 @@
42926 if (con->conf.force_lowercase_filenames) {
42927 if (0 == strncasecmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
42928 con->http_status = 403;
42931 return HANDLER_FINISHED;
42934 if (0 == strncmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) {
42935 con->http_status = 403;
42938 return HANDLER_FINISHED;
42945 return HANDLER_GO_ON;
42947 @@ -155,13 +154,13 @@
42948 int mod_access_plugin_init(plugin *p) {
42949 p->version = LIGHTTPD_VERSION_ID;
42950 p->name = buffer_init_string("access");
42953 p->init = mod_access_init;
42954 p->set_defaults = mod_access_set_defaults;
42955 p->handle_uri_clean = mod_access_uri_handler;
42956 p->cleanup = mod_access_free;
42965 Property changes on: src/mod_access.c
42966 ___________________________________________________________________
42967 Name: svn:eol-style
42971 Property changes on: src/stream.h
42972 ___________________________________________________________________
42973 Name: svn:eol-style
42976 Index: src/mod_accesslog.c
42977 ===================================================================
42978 --- src/mod_accesslog.c (.../tags/lighttpd-1.4.11) (revision 1159)
42979 +++ src/mod_accesslog.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
42982 #include <stdlib.h>
42983 #include <string.h>
42984 -#include <fcntl.h>
42985 -#include <unistd.h>
42986 +#include <fcntl.h> /* only the defines on windows */
42991 #include "inet_ntop_cache.h"
42993 #include "sys-socket.h"
42994 +#include "sys-files.h"
42996 #ifdef HAVE_SYSLOG_H
42997 # include <syslog.h>
43005 FORMAT_UNSUPPORTED,
43009 FORMAT_BYTES_OUT_NO_HEADER,
43013 FORMAT_REMOTE_ADDR,
43016 @@ -59,20 +59,20 @@
43017 FORMAT_CONNECTION_STATUS,
43022 FORMAT_RESPONSE_HEADER
43031 * "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\""
43036 -const format_mapping fmap[] =
43038 +const format_mapping fmap[] =
43040 { '%', FORMAT_PERCENT },
43041 { 'h', FORMAT_REMOTE_HOST },
43042 { 'l', FORMAT_REMOTE_IDENT },
43044 { 's', FORMAT_STATUS },
43045 { 'b', FORMAT_BYTES_OUT_NO_HEADER },
43046 { 'i', FORMAT_HEADER },
43049 { 'a', FORMAT_REMOTE_ADDR },
43050 { 'A', FORMAT_LOCAL_ADDR },
43051 { 'B', FORMAT_BYTES_OUT_NO_HEADER },
43052 @@ -103,23 +103,23 @@
43053 { 'X', FORMAT_CONNECTION_STATUS },
43054 { 'I', FORMAT_BYTES_IN },
43055 { 'O', FORMAT_BYTES_OUT },
43058 { 'o', FORMAT_RESPONSE_HEADER },
43061 { '\0', FORMAT_UNSET }
43066 enum { FIELD_UNSET, FIELD_STRING, FIELD_FORMAT } type;
43074 format_field **ptr;
43080 @@ -128,39 +128,39 @@
43081 buffer *access_logfile;
43083 unsigned short use_syslog;
43089 time_t last_generated_accesslog_ts;
43090 time_t *last_generated_accesslog_ts_ptr;
43095 buffer *access_logbuffer;
43096 buffer *ts_accesslog_str;
43099 format_fields *parsed_format;
43106 plugin_config **config_storage;
43107 - plugin_config conf;
43108 + plugin_config conf;
43111 INIT_FUNC(mod_accesslog_init) {
43115 p = calloc(1, sizeof(*p));
43121 int accesslog_parse_format(server *srv, format_fields *fields, buffer *format) {
43122 size_t i, j, k = 0, start = 0;
43125 for (i = 0; i < format->used - 1; i++) {
43128 switch(format->ptr[i]) {
43131 @@ -173,19 +173,19 @@
43132 fields->size += 16;
43133 fields->ptr = realloc(fields->ptr, fields->size * sizeof(format_fields * ));
43137 fields->ptr[fields->used] = malloc(sizeof(format_fields));
43138 fields->ptr[fields->used]->type = FIELD_STRING;
43139 fields->ptr[fields->used]->string = buffer_init();
43142 buffer_copy_string_len(fields->ptr[fields->used]->string, format->ptr + start, i - start);
43151 /* we need a new field */
43154 if (fields->size == 0) {
43157 @@ -194,43 +194,43 @@
43158 fields->size += 16;
43159 fields->ptr = realloc(fields->ptr, fields->size * sizeof(format_fields * ));
43163 /* search for the terminating command */
43164 switch (format->ptr[i+1]) {
43170 for (j = 0; fmap[j].key != '\0'; j++) {
43171 if (fmap[j].key != format->ptr[i+2]) continue;
43177 fields->ptr[fields->used] = malloc(sizeof(format_fields));
43178 fields->ptr[fields->used]->type = FIELD_FORMAT;
43179 fields->ptr[fields->used]->field = fmap[j].type;
43180 fields->ptr[fields->used]->string = NULL;
43190 if (fmap[j].key == '\0') {
43191 log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
43201 /* go forward to } */
43204 for (k = i+2; k < format->used - 1; k++) {
43205 if (format->ptr[k] == '}') break;
43209 if (k == format->used - 1) {
43210 log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
43212 @@ -239,62 +239,62 @@
43213 log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
43218 for (j = 0; fmap[j].key != '\0'; j++) {
43219 if (fmap[j].key != format->ptr[k+1]) continue;
43225 fields->ptr[fields->used] = malloc(sizeof(format_fields));
43226 fields->ptr[fields->used]->type = FIELD_FORMAT;
43227 fields->ptr[fields->used]->field = fmap[j].type;
43228 fields->ptr[fields->used]->string = buffer_init();
43231 buffer_copy_string_len(fields->ptr[fields->used]->string, format->ptr + i + 2, k - (i + 2));
43241 if (fmap[j].key == '\0') {
43242 log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
43252 for (j = 0; fmap[j].key != '\0'; j++) {
43253 if (fmap[j].key != format->ptr[i+1]) continue;
43259 fields->ptr[fields->used] = malloc(sizeof(format_fields));
43260 fields->ptr[fields->used]->type = FIELD_FORMAT;
43261 fields->ptr[fields->used]->field = fmap[j].type;
43262 fields->ptr[fields->used]->string = NULL;
43272 if (fmap[j].key == '\0') {
43273 log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed");
43291 /* copy the string */
43292 if (fields->size == 0) {
43293 @@ -305,32 +305,32 @@
43294 fields->size += 16;
43295 fields->ptr = realloc(fields->ptr, fields->size * sizeof(format_fields * ));
43299 fields->ptr[fields->used] = malloc(sizeof(format_fields));
43300 fields->ptr[fields->used]->type = FIELD_STRING;
43301 fields->ptr[fields->used]->string = buffer_init();
43304 buffer_copy_string_len(fields->ptr[fields->used]->string, format->ptr + start, i - start);
43314 FREE_FUNC(mod_accesslog_free) {
43315 plugin_data *p = p_d;
43319 if (!p) return HANDLER_GO_ON;
43322 if (p->config_storage) {
43325 for (i = 0; i < srv->config_context->used; i++) {
43326 plugin_config *s = p->config_storage[i];
43331 if (s->access_logbuffer->used) {
43332 if (s->use_syslog) {
43333 # ifdef HAVE_SYSLOG_H
43334 @@ -342,14 +342,14 @@
43335 write(s->log_access_fd, s->access_logbuffer->ptr, s->access_logbuffer->used - 1);
43340 if (s->log_access_fd != -1) close(s->log_access_fd);
43343 buffer_free(s->ts_accesslog_str);
43344 buffer_free(s->access_logbuffer);
43345 buffer_free(s->format);
43346 buffer_free(s->access_logfile);
43349 if (s->parsed_format) {
43351 for (j = 0; j < s->parsed_format->used; j++) {
43352 @@ -359,36 +359,36 @@
43353 free(s->parsed_format->ptr);
43354 free(s->parsed_format);
43362 free(p->config_storage);
43369 return HANDLER_GO_ON;
43372 SETDEFAULTS_FUNC(log_access_open) {
43373 plugin_data *p = p_d;
43376 - config_values_t cv[] = {
43378 + config_values_t cv[] = {
43379 { "accesslog.filename", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
43380 { "accesslog.use-syslog", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },
43381 { "accesslog.format", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
43382 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
43386 if (!p) return HANDLER_ERROR;
43389 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
43392 for (i = 0; i < srv->config_context->used; i++) {
43396 s = calloc(1, sizeof(plugin_config));
43397 s->access_logfile = buffer_init();
43398 s->format = buffer_init();
43399 @@ -397,44 +397,44 @@
43400 s->log_access_fd = -1;
43401 s->last_generated_accesslog_ts = 0;
43402 s->last_generated_accesslog_ts_ptr = &(s->last_generated_accesslog_ts);
43407 cv[0].destination = s->access_logfile;
43408 cv[1].destination = &(s->use_syslog);
43409 cv[2].destination = s->format;
43412 p->config_storage[i] = s;
43415 if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
43416 return HANDLER_ERROR;
43420 if (i == 0 && buffer_is_empty(s->format)) {
43421 /* set a default logfile string */
43424 buffer_copy_string(s->format, "%h %V %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"");
43431 if (s->format->used) {
43432 s->parsed_format = calloc(1, sizeof(*(s->parsed_format)));
43435 if (-1 == accesslog_parse_format(srv, s->parsed_format, s->format)) {
43437 - log_error_write(srv, __FILE__, __LINE__, "sb",
43438 + log_error_write(srv, __FILE__, __LINE__, "sb",
43439 "parsing accesslog-definition failed:", s->format);
43441 return HANDLER_ERROR;
43446 for (j = 0; j < s->parsed_format->used; j++) {
43447 switch (s->parsed_format->ptr[j]->type) {
43449 - log_error_write(srv, __FILE__, __LINE__, "ssds",
43450 + log_error_write(srv, __FILE__, __LINE__, "ssds",
43451 "config:", "format", s->parsed_format->ptr[j]->field,
43452 - s->parsed_format->ptr[j]->string ?
43453 + s->parsed_format->ptr[j]->string ?
43454 s->parsed_format->ptr[j]->string->ptr : "" );
43457 @@ -446,52 +446,52 @@
43463 if (s->use_syslog) {
43464 /* ignore the next checks */
43469 if (buffer_is_empty(s->access_logfile)) continue;
43472 if (s->access_logfile->ptr[0] == '|') {
43474 /* create write pipe and spawn process */
43481 if (pipe(to_log_fds)) {
43482 log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed: ", strerror(errno));
43483 return HANDLER_ERROR;
43488 switch (pid = fork()) {
43494 close(STDIN_FILENO);
43495 dup2(to_log_fds[0], STDIN_FILENO);
43496 close(to_log_fds[0]);
43498 close(to_log_fds[1]);
43501 /* we don't need the client socket */
43502 for (i = 3; i < 256; i++) {
43506 - /* exec the log-process (skip the | )
43509 + /* exec the log-process (skip the | )
43514 execl("/bin/sh", "sh", "-c", s->access_logfile->ptr + 1, NULL);
43516 - log_error_write(srv, __FILE__, __LINE__, "sss",
43517 - "spawning log-process failed: ", strerror(errno),
43518 + log_error_write(srv, __FILE__, __LINE__, "sss",
43519 + "spawning log-process failed: ", strerror(errno),
43520 s->access_logfile->ptr + 1);
43526 @@ -500,27 +500,28 @@
43529 close(to_log_fds[0]);
43532 s->log_access_fd = to_log_fds[1];
43540 - } else if (-1 == (s->log_access_fd =
43541 + } else if (-1 == (s->log_access_fd =
43542 open(s->access_logfile->ptr, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
43544 - log_error_write(srv, __FILE__, __LINE__, "ssb",
43545 - "opening access-log failed:",
43547 + log_error_write(srv, __FILE__, __LINE__, "ssb",
43548 + "opening access-log failed:",
43549 strerror(errno), s->access_logfile);
43552 return HANDLER_ERROR;
43555 fcntl(s->log_access_fd, F_SETFD, FD_CLOEXEC);
43561 return HANDLER_GO_ON;
43564 @@ -529,7 +530,7 @@
43567 if (!p->config_storage) return HANDLER_GO_ON;
43570 for (i = 0; i < srv->config_context->used; i++) {
43571 plugin_config *s = p->config_storage[i];
43573 @@ -544,90 +545,87 @@
43574 } else if (s->log_access_fd != -1) {
43575 write(s->log_access_fd, s->access_logbuffer->ptr, s->access_logbuffer->used - 1);
43579 buffer_reset(s->access_logbuffer);
43583 if (s->use_syslog == 0 &&
43584 !buffer_is_empty(s->access_logfile) &&
43585 s->access_logfile->ptr[0] != '|') {
43588 close(s->log_access_fd);
43590 - if (-1 == (s->log_access_fd =
43592 + if (-1 == (s->log_access_fd =
43593 open(s->access_logfile->ptr, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
43596 log_error_write(srv, __FILE__, __LINE__, "ss", "cycling access-log failed:", strerror(errno));
43599 return HANDLER_ERROR;
43605 return HANDLER_GO_ON;
43608 -#define PATCH(x) \
43609 - p->conf.x = s->x;
43610 static int mod_accesslog_patch_connection(server *srv, connection *con, plugin_data *p) {
43612 plugin_config *s = p->config_storage[0];
43614 - PATCH(access_logfile);
43616 - PATCH(log_access_fd);
43617 - PATCH(last_generated_accesslog_ts_ptr);
43618 - PATCH(access_logbuffer);
43619 - PATCH(ts_accesslog_str);
43620 - PATCH(parsed_format);
43621 - PATCH(use_syslog);
43624 + PATCH_OPTION(access_logfile);
43625 + PATCH_OPTION(format);
43626 + PATCH_OPTION(log_access_fd);
43627 + PATCH_OPTION(last_generated_accesslog_ts_ptr);
43628 + PATCH_OPTION(access_logbuffer);
43629 + PATCH_OPTION(ts_accesslog_str);
43630 + PATCH_OPTION(parsed_format);
43631 + PATCH_OPTION(use_syslog);
43633 /* skip the first, the global context */
43634 for (i = 1; i < srv->config_context->used; i++) {
43635 data_config *dc = (data_config *)srv->config_context->data[i];
43636 s = p->config_storage[i];
43639 /* condition didn't match */
43640 if (!config_check_cond(srv, con, dc)) continue;
43644 for (j = 0; j < dc->value->used; j++) {
43645 data_unset *du = dc->value->data[j];
43648 if (buffer_is_equal_string(du->key, CONST_STR_LEN("accesslog.filename"))) {
43649 - PATCH(access_logfile);
43650 - PATCH(log_access_fd);
43651 - PATCH(last_generated_accesslog_ts_ptr);
43652 - PATCH(access_logbuffer);
43653 - PATCH(ts_accesslog_str);
43654 + PATCH_OPTION(access_logfile);
43655 + PATCH_OPTION(log_access_fd);
43656 + PATCH_OPTION(last_generated_accesslog_ts_ptr);
43657 + PATCH_OPTION(access_logbuffer);
43658 + PATCH_OPTION(ts_accesslog_str);
43659 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("accesslog.format"))) {
43661 - PATCH(parsed_format);
43662 + PATCH_OPTION(format);
43663 + PATCH_OPTION(parsed_format);
43664 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("accesslog.use-syslog"))) {
43665 - PATCH(use_syslog);
43666 + PATCH_OPTION(use_syslog);
43676 REQUESTDONE_FUNC(log_access_write) {
43677 plugin_data *p = p_d;
43686 mod_accesslog_patch_connection(srv, con, p);
43689 b = p->conf.access_logbuffer;
43690 if (b->used == 0) {
43691 buffer_copy_string(b, "");
43695 for (j = 0; j < p->conf.parsed_format->used; j++) {
43696 switch(p->conf.parsed_format->ptr[j]->type) {
43698 @@ -636,14 +634,14 @@
43700 switch(p->conf.parsed_format->ptr[j]->field) {
43701 case FORMAT_TIMESTAMP:
43704 /* cache the generated timestamp */
43705 if (srv->cur_ts != *(p->conf.last_generated_accesslog_ts_ptr)) {
43707 #if defined(HAVE_STRUCT_TM_GMTOFF)
43708 long scd, hrs, min;
43712 buffer_prepare_copy(p->conf.ts_accesslog_str, 255);
43713 #if defined(HAVE_STRUCT_TM_GMTOFF)
43714 # ifdef HAVE_LOCALTIME_R
43715 @@ -653,17 +651,17 @@
43716 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)));
43718 p->conf.ts_accesslog_str->used = strlen(p->conf.ts_accesslog_str->ptr) + 1;
43721 buffer_append_string(p->conf.ts_accesslog_str, tm.tm_gmtoff >= 0 ? "+" : "-");
43724 scd = abs(tm.tm_gmtoff);
43726 min = (scd % 3600) / 60;
43730 if (hrs < 10) buffer_append_string(p->conf.ts_accesslog_str, "0");
43731 buffer_append_long(p->conf.ts_accesslog_str, hrs);
43734 if (min < 10) buffer_append_string(p->conf.ts_accesslog_str, "0");
43735 buffer_append_long(p->conf.ts_accesslog_str, min);
43736 BUFFER_APPEND_STRING_CONST(p->conf.ts_accesslog_str, "]");
43737 @@ -676,20 +674,20 @@
43739 p->conf.ts_accesslog_str->used = strlen(p->conf.ts_accesslog_str->ptr) + 1;
43743 *(p->conf.last_generated_accesslog_ts_ptr) = srv->cur_ts;
43748 buffer_append_string_buffer(b, p->conf.ts_accesslog_str);
43752 case FORMAT_REMOTE_HOST:
43755 /* handle inet_ntop cache */
43758 buffer_append_string(b, inet_ntop_cache_get_ip(srv, &(con->dst_addr)));
43762 case FORMAT_REMOTE_IDENT:
43764 @@ -710,10 +708,10 @@
43765 case FORMAT_STATUS:
43766 buffer_append_long(b, con->http_status);
43770 case FORMAT_BYTES_OUT_NO_HEADER:
43771 if (con->bytes_written > 0) {
43772 - buffer_append_off_t(b,
43773 + buffer_append_off_t(b,
43774 con->bytes_written - con->bytes_header <= 0 ? 0 : con->bytes_written - con->bytes_header);
43776 BUFFER_APPEND_STRING_CONST(b, "-");
43777 @@ -772,7 +770,7 @@
43780 case FORMAT_REQUEST_PROTOCOL:
43781 - buffer_append_string(b,
43782 + buffer_append_string(b,
43783 con->request.http_version == HTTP_VERSION_1_1 ? "HTTP/1.1" : "HTTP/1.0");
43785 case FORMAT_REQUEST_METHOD:
43786 @@ -801,7 +799,7 @@
43787 { 'D', FORMAT_TIME_USED_MS },
43788 { 'e', FORMAT_ENV },
43795 @@ -809,7 +807,7 @@
43801 BUFFER_APPEND_STRING_CONST(b, "\n");
43803 if (p->conf.use_syslog || /* syslog doesn't cache */
43804 @@ -828,7 +826,7 @@
43810 return HANDLER_GO_ON;
43813 @@ -836,15 +834,15 @@
43814 int mod_accesslog_plugin_init(plugin *p) {
43815 p->version = LIGHTTPD_VERSION_ID;
43816 p->name = buffer_init_string("accesslog");
43819 p->init = mod_accesslog_init;
43820 p->set_defaults= log_access_open;
43821 p->cleanup = mod_accesslog_free;
43824 p->handle_request_done = log_access_write;
43825 p->handle_sighup = log_access_cycle;
43834 Property changes on: src/mod_accesslog.c
43835 ___________________________________________________________________
43836 Name: svn:eol-style
43839 Index: src/fdevent_linux_sysepoll.c
43840 ===================================================================
43841 --- src/fdevent_linux_sysepoll.c (.../tags/lighttpd-1.4.11) (revision 1159)
43842 +++ src/fdevent_linux_sysepoll.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
43844 #include <sys/types.h>
43846 -#include <unistd.h>
43847 #include <stdlib.h>
43849 #include <string.h>
43851 #include "settings.h"
43852 #include "buffer.h"
43854 +#include "sys-files.h"
43856 #ifdef USE_LINUX_EPOLL
43857 static void fdevent_linux_sysepoll_free(fdevents *ev) {
43858 close(ev->epoll_fd);
43859 @@ -20,36 +21,36 @@
43861 static int fdevent_linux_sysepoll_event_del(fdevents *ev, int fde_ndx, int fd) {
43862 struct epoll_event ep;
43865 if (fde_ndx < 0) return -1;
43868 memset(&ep, 0, sizeof(ep));
43872 ep.data.ptr = NULL;
43875 if (0 != epoll_ctl(ev->epoll_fd, EPOLL_CTL_DEL, fd, &ep)) {
43876 fprintf(stderr, "%s.%d: epoll_ctl failed: %s, dying\n", __FILE__, __LINE__, strerror(errno));
43891 static int fdevent_linux_sysepoll_event_add(fdevents *ev, int fde_ndx, int fd, int events) {
43892 struct epoll_event ep;
43896 if (fde_ndx == -1) add = 1;
43899 memset(&ep, 0, sizeof(ep));
43905 if (events & FDEVENT_IN) ep.events |= EPOLLIN;
43906 if (events & FDEVENT_OUT) ep.events |= EPOLLOUT;
43908 @@ -60,20 +61,20 @@
43914 ep.events |= EPOLLERR | EPOLLHUP /* | EPOLLET */;
43917 ep.data.ptr = NULL;
43921 if (0 != epoll_ctl(ev->epoll_fd, add ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, fd, &ep)) {
43922 fprintf(stderr, "%s.%d: epoll_ctl failed: %s, dying\n", __FILE__, __LINE__, strerror(errno));
43935 @@ -83,14 +84,14 @@
43937 static int fdevent_linux_sysepoll_event_get_revent(fdevents *ev, size_t ndx) {
43941 e = ev->epoll_events[ndx].events;
43942 if (e & EPOLLIN) events |= FDEVENT_IN;
43943 if (e & EPOLLOUT) events |= FDEVENT_OUT;
43944 if (e & EPOLLERR) events |= FDEVENT_ERR;
43945 if (e & EPOLLHUP) events |= FDEVENT_HUP;
43946 if (e & EPOLLPRI) events |= FDEVENT_PRI;
43952 @@ -98,17 +99,17 @@
43954 fprintf(stderr, "%s.%d: %d, %d\n", __FILE__, __LINE__, ndx, ev->epoll_events[ndx].data.fd);
43958 return ev->epoll_events[ndx].data.fd;
43961 static int fdevent_linux_sysepoll_event_next_fdndx(fdevents *ev, int ndx) {
43967 i = (ndx < 0) ? 0 : ndx + 1;
43973 @@ -116,17 +117,17 @@
43974 ev->type = FDEVENT_HANDLER_LINUX_SYSEPOLL;
43976 ev->x = fdevent_linux_sysepoll_##x;
43987 SET(event_next_fdndx);
43989 SET(event_get_revent);
43992 if (-1 == (ev->epoll_fd = epoll_create(ev->maxfds))) {
43993 fprintf(stderr, "%s.%d: epoll_create failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n",
43994 __FILE__, __LINE__, strerror(errno));
43995 @@ -154,7 +155,7 @@
43997 fprintf(stderr, "%s.%d: linux-sysepoll not supported, try to set server.event-handler = \"poll\" or \"select\"\n",
43998 __FILE__, __LINE__);
44005 Property changes on: src/fdevent_linux_sysepoll.c
44006 ___________________________________________________________________
44007 Name: svn:eol-style
44010 Index: src/server.c
44011 ===================================================================
44012 --- src/server.c (.../tags/lighttpd-1.4.11) (revision 1159)
44013 +++ src/server.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
44015 #include <sys/types.h>
44016 -#include <sys/time.h>
44017 #include <sys/stat.h>
44019 #include <string.h>
44022 -#include <unistd.h>
44023 #include <stdlib.h>
44025 #include <signal.h>
44027 #include "plugin.h"
44028 #include "joblist.h"
44029 #include "network_backends.h"
44032 +/* use local getopt implementation */
44033 +# undef HAVE_GETOPT_H
44035 #ifdef HAVE_GETOPT_H
44036 #include <getopt.h>
44038 +#include "getopt.h"
44041 #ifdef HAVE_VALGRIND_VALGRIND_H
44043 /* #define USE_ALARM */
44047 +#undef HAVE_SIGNAL
44050 +#include "sys-files.h"
44051 +#include "sys-process.h"
44053 static volatile sig_atomic_t srv_shutdown = 0;
44054 static volatile sig_atomic_t graceful_shutdown = 0;
44055 +static volatile sig_atomic_t graceful_restart = 0;
44056 static volatile sig_atomic_t handle_sig_alarm = 1;
44057 static volatile sig_atomic_t handle_sig_hup = 0;
44062 case SIGTERM: srv_shutdown = 1; break;
44065 if (graceful_shutdown) srv_shutdown = 1;
44066 - else graceful_shutdown = 1;
44067 + else graceful_shutdown = 1;
44070 case SIGALRM: handle_sig_alarm = 1; break;
44072 static void signal_handler(int sig) {
44074 case SIGTERM: srv_shutdown = 1; break;
44077 if (graceful_shutdown) srv_shutdown = 1;
44078 - else graceful_shutdown = 1;
44079 + else graceful_shutdown = 1;
44082 case SIGALRM: handle_sig_alarm = 1; break;
44083 @@ -110,25 +121,26 @@
44084 signal(SIGTSTP, SIG_IGN);
44086 if (0 != fork()) exit(0);
44089 if (-1 == setsid()) exit(0);
44091 signal(SIGHUP, SIG_IGN);
44093 if (0 != fork()) exit(0);
44096 if (0 != chdir("/")) exit(0);
44100 static server *server_init(void) {
44104 server *srv = calloc(1, sizeof(*srv));
44106 + srv->max_fds = 1024;
44108 srv->x = buffer_init();
44111 CLEAN(response_header);
44112 CLEAN(parse_full_path);
44113 CLEAN(ts_debug_str);
44114 @@ -138,7 +150,7 @@
44116 srv->empty_string = buffer_init_string("");
44117 CLEAN(cond_check_buf);
44120 CLEAN(srvconf.errorlog_file);
44121 CLEAN(srvconf.groupname);
44122 CLEAN(srvconf.username);
44123 @@ -146,58 +158,58 @@
44124 CLEAN(srvconf.bindhost);
44125 CLEAN(srvconf.event_handler);
44126 CLEAN(srvconf.pid_file);
44129 CLEAN(tmp_chunk_len);
44134 srv->x = array_init();
44137 CLEAN(config_context);
44138 CLEAN(config_touched);
44143 for (i = 0; i < FILE_CACHE_MAX; i++) {
44144 srv->mtime_cache[i].str = buffer_init();
44148 srv->cur_ts = time(NULL);
44149 srv->startup_ts = srv->cur_ts;
44152 srv->conns = calloc(1, sizeof(*srv->conns));
44153 assert(srv->conns);
44156 srv->joblist = calloc(1, sizeof(*srv->joblist));
44157 assert(srv->joblist);
44160 srv->fdwaitqueue = calloc(1, sizeof(*srv->fdwaitqueue));
44161 assert(srv->fdwaitqueue);
44164 srv->srvconf.modules = array_init();
44165 srv->srvconf.modules_dir = buffer_init_string(LIBRARY_DIR);
44166 srv->srvconf.network_backend = buffer_init();
44167 srv->srvconf.upload_tempdirs = array_init();
44171 srv->errorlog_fd = -1;
44172 srv->errorlog_mode = ERRORLOG_STDERR;
44174 srv->split_vals = array_init();
44180 static void server_free(server *srv) {
44184 for (i = 0; i < FILE_CACHE_MAX; i++) {
44185 buffer_free(srv->mtime_cache[i].str);
44190 buffer_free(srv->x);
44193 CLEAN(response_header);
44194 CLEAN(parse_full_path);
44195 CLEAN(ts_debug_str);
44196 @@ -207,7 +219,7 @@
44198 CLEAN(empty_string);
44199 CLEAN(cond_check_buf);
44202 CLEAN(srvconf.errorlog_file);
44203 CLEAN(srvconf.groupname);
44204 CLEAN(srvconf.username);
44205 @@ -217,7 +229,7 @@
44206 CLEAN(srvconf.pid_file);
44207 CLEAN(srvconf.modules_dir);
44208 CLEAN(srvconf.network_backend);
44211 CLEAN(tmp_chunk_len);
44214 @@ -225,15 +237,15 @@
44215 fdevent_unregister(srv->ev, srv->fd);
44217 fdevent_free(srv->ev);
44223 if (srv->config_storage) {
44224 for (i = 0; i < srv->config_context->used; i++) {
44225 specific_config *s = srv->config_storage[i];
44230 buffer_free(s->document_root);
44231 buffer_free(s->server_name);
44232 buffer_free(s->server_tag);
44233 @@ -242,32 +254,32 @@
44234 buffer_free(s->error_handler);
44235 buffer_free(s->errorfile_prefix);
44236 array_free(s->mimetypes);
44241 free(srv->config_storage);
44242 srv->config_storage = NULL;
44247 array_free(srv->x);
44250 CLEAN(config_context);
44251 CLEAN(config_touched);
44253 CLEAN(srvconf.upload_tempdirs);
44257 joblist_free(srv, srv->joblist);
44258 fdwaitqueue_free(srv, srv->fdwaitqueue);
44261 if (srv->stat_cache) {
44262 stat_cache_free(srv->stat_cache);
44265 array_free(srv->srvconf.modules);
44266 array_free(srv->split_vals);
44272 @@ -281,14 +293,12 @@
44273 " - a light and fast webserver\n" \
44274 "Build-Date: " __DATE__ " " __TIME__ "\n";
44278 write(STDOUT_FILENO, b, strlen(b));
44281 static void show_features (void) {
44283 - printf("\nEvent Handlers:\n\n%s",
44285 + const char *s = ""
44287 "\t+ select (generic)\n"
44289 @@ -355,11 +365,6 @@
44291 "\t- crypt support\n"
44294 - "\t+ PAM support\n"
44296 - "\t- PAM support\n"
44299 "\t+ SSL Support\n"
44301 @@ -371,9 +376,9 @@
44302 "\t- PCRE support\n"
44305 - "\t+ mySQL support\n"
44306 + "\t+ MySQL support\n"
44308 - "\t- mySQL support\n"
44309 + "\t- MySQL support\n"
44311 #if defined(HAVE_LDAP_H) && defined(HAVE_LBER_H) && defined(HAVE_LIBLDAP) && defined(HAVE_LIBLBER)
44312 "\t+ LDAP support\n"
44313 @@ -410,8 +415,11 @@
44315 "\t- GDBM support\n"
44323 + printf("\nEvent Handlers:\n\n%s", s);
44326 static void show_help (void) {
44327 @@ -433,12 +441,12 @@
44328 " -h show this help\n" \
44334 write(STDOUT_FILENO, b, strlen(b));
44337 -int main (int argc, char **argv) {
44338 +int main (int argc, char **argv, char **envp) {
44339 server *srv = NULL;
44340 int print_config = 0;
44341 int test_config = 0;
44342 @@ -447,33 +455,37 @@
44343 int num_childs = 0;
44344 int pid_fd = -1, fd;
44347 + char *optarg = NULL;
44350 #ifdef HAVE_SIGACTION
44351 struct sigaction act;
44353 #ifdef HAVE_GETRLIMIT
44354 struct rlimit rlim;
44359 struct itimerval interval;
44362 interval.it_interval.tv_sec = 1;
44363 interval.it_interval.tv_usec = 0;
44364 interval.it_value.tv_sec = 1;
44365 interval.it_value.tv_usec = 0;
44371 /* for nice %b handling in strfime() */
44372 setlocale(LC_TIME, "C");
44375 if (NULL == (srv = server_init())) {
44376 fprintf(stderr, "did this really happen?\n");
44381 /* init structs done */
44384 srv->srvconf.port = 0;
44386 i_am_root = (getuid() == 0);
44387 @@ -481,14 +493,19 @@
44390 srv->srvconf.dont_daemonize = 0;
44393 while(-1 != (o = getopt(argc, argv, "f:m:hvVDpt"))) {
44396 - if (config_read(srv, optarg)) {
44399 + /* evil HACK for windows, optarg is not set */
44400 + optarg = argv[optind-1];
44402 + if (config_read(srv, optarg)) {
44409 buffer_copy_string(srv->srvconf.modules_dir, optarg);
44410 @@ -497,23 +514,23 @@
44411 case 't': test_config = 1; break;
44412 case 'D': srv->srvconf.dont_daemonize = 1; break;
44413 case 'v': show_version(); return 0;
44414 - case 'V': show_features(); return 0;
44415 + case 'V': show_features(); return 0;
44416 case 'h': show_help(); return 0;
44426 if (!srv->config_storage) {
44427 log_error_write(srv, __FILE__, __LINE__, "s",
44428 "No configuration available. Try using -f option.");
44436 if (print_config) {
44437 data_unset *dc = srv->config_context->data[0];
44439 @@ -533,7 +550,7 @@
44445 /* close stdin and stdout, as they are not needed */
44446 /* move stdin to /dev/null */
44447 if (-1 != (fd = open("/dev/null", O_RDONLY))) {
44448 @@ -541,54 +558,55 @@
44449 dup2(fd, STDIN_FILENO);
44454 /* move stdout to /dev/null */
44455 if (-1 != (fd = open("/dev/null", O_WRONLY))) {
44456 close(STDOUT_FILENO);
44457 dup2(fd, STDOUT_FILENO);
44462 if (0 != config_set_defaults(srv)) {
44463 - log_error_write(srv, __FILE__, __LINE__, "s",
44464 + log_error_write(srv, __FILE__, __LINE__, "s",
44465 "setting default values failed");
44473 if (!i_am_root && (geteuid() == 0 || getegid() == 0)) {
44474 /* we are setuid-root */
44476 - log_error_write(srv, __FILE__, __LINE__, "s",
44478 + log_error_write(srv, __FILE__, __LINE__, "s",
44479 "Are you nuts ? Don't apply a SUID bit to this binary");
44488 /* check document-root */
44489 if (srv->config_storage[0]->document_root->used <= 1) {
44490 - log_error_write(srv, __FILE__, __LINE__, "s",
44491 + log_error_write(srv, __FILE__, __LINE__, "s",
44492 "document-root is not set\n");
44502 if (plugins_load(srv)) {
44503 log_error_write(srv, __FILE__, __LINE__, "s",
44504 "loading plugins finally failed");
44516 /* open pid file BEFORE chroot */
44517 if (srv->srvconf.pid_file->used) {
44518 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))) {
44519 @@ -598,18 +616,18 @@
44520 "opening pid-file failed:", srv->srvconf.pid_file, strerror(errno));
44525 if (0 != stat(srv->srvconf.pid_file->ptr, &st)) {
44526 log_error_write(srv, __FILE__, __LINE__, "sbs",
44527 "stating existing pid-file failed:", srv->srvconf.pid_file, strerror(errno));
44531 if (!S_ISREG(st.st_mode)) {
44532 log_error_write(srv, __FILE__, __LINE__, "sb",
44533 "pid-file exists and isn't regular file:", srv->srvconf.pid_file);
44538 if (-1 == (pid_fd = open(srv->srvconf.pid_file->ptr, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) {
44539 log_error_write(srv, __FILE__, __LINE__, "sbs",
44540 "opening pid-file failed:", srv->srvconf.pid_file, strerror(errno));
44541 @@ -617,13 +635,14 @@
44547 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
44548 /* select limits itself
44550 * as it is a hard limit and will lead to a segfault we add some safety
44552 - srv->max_fds = FD_SETSIZE - 200;
44553 + fprintf(stderr, "%s.%d: max parallel connections: %d\r\n", __FILE__, __LINE__, FD_SETSIZE);
44554 + srv->max_fds = FD_SETSIZE - 4;
44556 srv->max_fds = 4096;
44558 @@ -636,7 +655,7 @@
44559 #ifdef HAVE_VALGRIND_VALGRIND_H
44560 if (RUNNING_ON_VALGRIND) use_rlimit = 0;
44564 #ifdef HAVE_GETRLIMIT
44565 if (0 != getrlimit(RLIMIT_NOFILE, &rlim)) {
44566 log_error_write(srv, __FILE__, __LINE__,
44567 @@ -644,13 +663,13 @@
44573 if (use_rlimit && srv->srvconf.max_fds) {
44577 rlim.rlim_cur = srv->srvconf.max_fds;
44578 rlim.rlim_max = srv->srvconf.max_fds;
44581 if (0 != setrlimit(RLIMIT_NOFILE, &rlim)) {
44582 log_error_write(srv, __FILE__, __LINE__,
44583 "ss", "couldn't set 'max filedescriptors'",
44584 @@ -659,7 +678,7 @@
44588 - /* #372: solaris need some fds extra for devpoll */
44589 + /* #372: solaris need some fds extra for devpoll */
44590 if (rlim.rlim_cur > 10) rlim.rlim_cur -= 10;
44592 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
44593 @@ -677,33 +696,33 @@
44594 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
44595 /* don't raise the limit above FD_SET_SIZE */
44596 if (srv->max_fds > FD_SETSIZE - 200) {
44597 - log_error_write(srv, __FILE__, __LINE__, "sd",
44598 + log_error_write(srv, __FILE__, __LINE__, "sd",
44599 "can't raise max filedescriptors above", FD_SETSIZE - 200,
44600 "if event-handler is 'select'. Use 'poll' or something else or reduce server.max-fds.");
44608 /* set user and group */
44609 if (srv->srvconf.username->used) {
44610 if (NULL == (pwd = getpwnam(srv->srvconf.username->ptr))) {
44611 - log_error_write(srv, __FILE__, __LINE__, "sb",
44612 + log_error_write(srv, __FILE__, __LINE__, "sb",
44613 "can't find username", srv->srvconf.username);
44618 if (pwd->pw_uid == 0) {
44619 log_error_write(srv, __FILE__, __LINE__, "s",
44620 "I will not set uid to 0\n");
44626 if (srv->srvconf.groupname->used) {
44627 if (NULL == (grp = getgrnam(srv->srvconf.groupname->ptr))) {
44628 - log_error_write(srv, __FILE__, __LINE__, "sb",
44629 + log_error_write(srv, __FILE__, __LINE__, "sb",
44630 "can't find groupname", srv->srvconf.groupname);
44633 @@ -713,15 +732,15 @@
44639 /* we need root-perms for port < 1024 */
44640 if (0 != network_init(srv)) {
44647 -#ifdef HAVE_CHROOT
44648 +#ifdef HAVE_CHROOT
44649 if (srv->srvconf.changeroot->used) {
44652 @@ -761,7 +780,7 @@
44655 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
44656 - srv->max_fds = rlim.rlim_cur < FD_SETSIZE - 200 ? rlim.rlim_cur : FD_SETSIZE - 200;
44657 + srv->max_fds = rlim.rlim_cur < FD_SETSIZE - 4 ? rlim.rlim_cur : FD_SETSIZE - 4;
44659 srv->max_fds = rlim.rlim_cur;
44661 @@ -775,18 +794,18 @@
44663 if (srv->event_handler == FDEVENT_HANDLER_SELECT) {
44664 /* don't raise the limit above FD_SET_SIZE */
44665 - if (srv->max_fds > FD_SETSIZE - 200) {
44666 - log_error_write(srv, __FILE__, __LINE__, "sd",
44667 - "can't raise max filedescriptors above", FD_SETSIZE - 200,
44668 + if (srv->max_fds > FD_SETSIZE - 4) {
44669 + log_error_write(srv, __FILE__, __LINE__, "sd",
44670 + "can't raise max filedescriptors above", FD_SETSIZE - 4,
44671 "if event-handler is 'select'. Use 'poll' or something else or reduce server.max-fds.");
44677 if (0 != network_init(srv)) {
44685 @@ -802,25 +821,27 @@
44686 /* or use the default */
44687 srv->max_conns = srv->max_fds;
44691 if (HANDLER_GO_ON != plugins_call_init(srv)) {
44692 log_error_write(srv, __FILE__, __LINE__, "s", "Initialization of plugins failed. Going down.");
44696 network_close(srv);
44705 /* network is up, let's deamonize ourself */
44706 if (srv->srvconf.dont_daemonize == 0) daemonize();
44710 srv->gid = getgid();
44711 srv->uid = getuid();
44715 /* write pid file */
44716 if (pid_fd != -1) {
44717 buffer_copy_long(srv->tmp_buf, getpid());
44718 @@ -829,17 +850,17 @@
44724 if (HANDLER_GO_ON != plugins_call_set_defaults(srv)) {
44725 log_error_write(srv, __FILE__, __LINE__, "s", "Configuration of plugins failed. Going down.");
44729 network_close(srv);
44737 /* dump unused config-keys */
44738 for (i = 0; i < srv->config_context->used; i++) {
44739 array *config = ((data_config *)srv->config_context->data[i])->value;
44740 @@ -847,43 +868,42 @@
44742 for (j = 0; config && j < config->used; j++) {
44743 data_unset *du = config->data[j];
44746 /* all var.* is known as user defined variable */
44747 if (strncmp(du->key->ptr, "var.", sizeof("var.") - 1) == 0) {
44751 if (NULL == array_get_element(srv->config_touched, du->key->ptr)) {
44752 - log_error_write(srv, __FILE__, __LINE__, "sbs",
44753 + log_error_write(srv, __FILE__, __LINE__, "sbs",
44754 "WARNING: unknown config-key:",
44762 if (srv->config_deprecated) {
44763 - log_error_write(srv, __FILE__, __LINE__, "s",
44764 + log_error_write(srv, __FILE__, __LINE__, "s",
44765 "Configuration contains deprecated keys. Going down.");
44769 network_close(srv);
44777 if (-1 == log_error_open(srv)) {
44778 - log_error_write(srv, __FILE__, __LINE__, "s",
44779 + log_error_write(srv, __FILE__, __LINE__, "s",
44780 "opening errorlog failed, dying");
44784 network_close(srv);
44791 #ifdef HAVE_SIGACTION
44792 memset(&act, 0, sizeof(act));
44793 act.sa_handler = SIG_IGN;
44794 @@ -903,7 +923,7 @@
44795 sigaction(SIGHUP, &act, NULL);
44796 sigaction(SIGALRM, &act, NULL);
44797 sigaction(SIGCHLD, &act, NULL);
44800 #elif defined(HAVE_SIGNAL)
44801 /* ignore the SIGPIPE from sendfile() */
44802 signal(SIGPIPE, SIG_IGN);
44803 @@ -914,20 +934,20 @@
44804 signal(SIGCHLD, signal_handler);
44805 signal(SIGINT, signal_handler);
44810 signal(SIGALRM, signal_handler);
44813 /* setup periodic timer (1 second) */
44814 if (setitimer(ITIMER_REAL, &interval, NULL)) {
44815 log_error_write(srv, __FILE__, __LINE__, "s", "setting timer failed");
44820 getitimer(ITIMER_REAL, &interval);
44825 /* start watcher and workers */
44826 num_childs = srv->srvconf.max_worker;
44827 if (num_childs > 0) {
44828 @@ -957,13 +977,13 @@
44832 - if (NULL == (srv->ev = fdevent_init(srv->max_fds + 1, srv->event_handler))) {
44833 + if (NULL == (srv->ev = fdevent_init(/*srv->max_fds + 1*/ 4096, srv->event_handler))) {
44834 log_error_write(srv, __FILE__, __LINE__,
44835 "s", "fdevent_init failed");
44839 - * kqueue() is called here, select resets its internals,
44841 + * kqueue() is called here, select resets its internals,
44842 * all server sockets get their handlers
44845 @@ -971,7 +991,7 @@
44847 network_close(srv);
44854 @@ -986,7 +1006,7 @@
44856 if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_FAM) {
44857 if (0 != FAMOpen2(srv->stat_cache->fam, "lighttpd")) {
44858 - log_error_write(srv, __FILE__, __LINE__, "s",
44859 + log_error_write(srv, __FILE__, __LINE__, "s",
44860 "could not open a fam connection, dieing.");
44863 @@ -1018,16 +1038,40 @@
44869 if (handle_sig_hup) {
44873 /* reset notification */
44874 handle_sig_hup = 0;
44881 + /* send the old process into a graceful-shutdown and start a
44882 + * new process right away
44885 + * - if webserver is running on port < 1024 (e.g. 80, 433)
44886 + * we don't have the permissions to bind to that port anymore
44890 + if (0 == (pid = fork())) {
44891 + execve(argv[0], argv, envp);
44894 + } else if (pid == -1) {
44899 + graceful_shutdown = 1; /* shutdown without killing running connections */
44900 + graceful_restart = 1; /* don't delete pid file */
44903 /* cycle logfiles */
44906 switch(r = plugins_call_handle_sighup(srv)) {
44907 case HANDLER_GO_ON:
44909 @@ -1035,30 +1079,31 @@
44910 log_error_write(srv, __FILE__, __LINE__, "sd", "sighup-handler return with an error", r);
44915 if (-1 == log_error_cycle(srv)) {
44916 log_error_write(srv, __FILE__, __LINE__, "s", "cycling errorlog failed, dying");
44925 if (handle_sig_alarm) {
44930 /* reset notification */
44931 handle_sig_alarm = 0;
44935 /* get current time */
44936 min_ts = time(NULL);
44939 if (min_ts != srv->cur_ts) {
44941 connections *conns = srv->conns;
44945 switch(r = plugins_call_handle_trigger(srv)) {
44946 case HANDLER_GO_ON:
44948 @@ -1069,21 +1114,21 @@
44949 log_error_write(srv, __FILE__, __LINE__, "d", r);
44954 /* trigger waitpid */
44955 srv->cur_ts = min_ts;
44957 - /* cleanup stat-cache */
44959 + /* cleanup stat-cache */
44960 stat_cache_trigger_cleanup(srv);
44962 - * check all connections for timeouts
44964 + * check all connections for timeouts
44967 for (ndx = 0; ndx < conns->used; ndx++) {
44973 con = conns->ptr[ndx];
44975 if (con->state == CON_STATE_READ ||
44976 @@ -1092,7 +1137,7 @@
44977 if (srv->cur_ts - con->read_idle_ts > con->conf.max_read_idle) {
44980 - log_error_write(srv, __FILE__, __LINE__, "sd",
44981 + log_error_write(srv, __FILE__, __LINE__, "sd",
44982 "connection closed - read-timeout:", con->fd);
44984 connection_set_state(srv, con, CON_STATE_ERROR);
44985 @@ -1102,7 +1147,7 @@
44986 if (srv->cur_ts - con->read_idle_ts > con->conf.max_keep_alive_idle) {
44989 - log_error_write(srv, __FILE__, __LINE__, "sd",
44990 + log_error_write(srv, __FILE__, __LINE__, "sd",
44991 "connection closed - read-timeout:", con->fd);
44993 connection_set_state(srv, con, CON_STATE_ERROR);
44994 @@ -1110,20 +1155,20 @@
45000 if ((con->state == CON_STATE_WRITE) &&
45001 - (con->write_request_ts != 0)) {
45002 + (con->write_request_ts != 0)) {
45004 if (srv->cur_ts - con->write_request_ts > 60) {
45005 - log_error_write(srv, __FILE__, __LINE__, "sdd",
45006 + log_error_write(srv, __FILE__, __LINE__, "sdd",
45007 "connection closed - pre-write-request-timeout:", con->fd, srv->cur_ts - con->write_request_ts);
45012 if (srv->cur_ts - con->write_request_ts > con->conf.max_write_idle) {
45015 - log_error_write(srv, __FILE__, __LINE__, "sbsosds",
45016 + log_error_write(srv, __FILE__, __LINE__, "sbsosds",
45017 "NOTE: a request for",
45019 "timed out after writing",
45020 @@ -1138,35 +1183,35 @@
45022 /* we don't like div by zero */
45023 if (0 == (t_diff = srv->cur_ts - con->connection_start)) t_diff = 1;
45025 - if (con->traffic_limit_reached &&
45026 - (con->conf.kbytes_per_second == 0 ||
45028 + if (con->traffic_limit_reached &&
45029 + (con->conf.kbytes_per_second == 0 ||
45030 ((con->bytes_written / t_diff) < con->conf.kbytes_per_second * 1024))) {
45031 /* enable connection again */
45032 con->traffic_limit_reached = 0;
45040 connection_state_machine(srv, con);
45042 con->bytes_written_cur_second = 0;
45043 *(con->conf.global_bytes_per_second_cnt_ptr) = 0;
45048 fprintf(stderr, "connection-state: ");
45053 fprintf(stderr, "c[%d,%d]: %s ",
45056 connection_get_state(con->state));
45061 if (cs == 1) fprintf(stderr, "\n");
45064 @@ -1181,18 +1226,18 @@
45065 server_socket *srv_socket = srv->srv_sockets.ptr[i];
45066 fdevent_event_add(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN);
45070 log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets enabled again");
45073 srv->sockets_disabled = 0;
45076 if ((srv->cur_fds + srv->want_fds > srv->max_fds * 0.9) || /* out of fds */
45077 (srv->conns->used > srv->max_conns) || /* out of connections */
45078 - (graceful_shutdown)) { /* graceful_shutdown */
45079 + (graceful_shutdown)) { /* graceful_shutdown */
45081 /* disable server-fds */
45084 for (i = 0; i < srv->srv_sockets.used; i++) {
45085 server_socket *srv_socket = srv->srv_sockets.ptr[i];
45086 fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd);
45087 @@ -1211,7 +1256,7 @@
45088 /* network_close() will cleanup after us */
45093 if (graceful_shutdown) {
45094 log_error_write(srv, __FILE__, __LINE__, "s", "[note] graceful shutdown started");
45095 } else if (srv->conns->used > srv->max_conns) {
45096 @@ -1219,7 +1264,7 @@
45098 log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets disabled, out-of-fds");
45102 srv->sockets_disabled = 1;
45105 @@ -1229,16 +1274,16 @@
45106 * we are ready to terminate without harming anyone */
45111 /* we still have some fds to share */
45112 - if (srv->want_fds) {
45113 + if (srv->want_fds) {
45114 /* check the fdwaitqueue for waiting fds */
45115 int free_fds = srv->max_fds - srv->cur_fds - 16;
45119 for (; free_fds > 0 && NULL != (con = fdwaitqueue_unshift(srv, srv->fdwaitqueue)); free_fds--) {
45120 connection_state_machine(srv, con);
45126 @@ -1249,27 +1294,27 @@
45130 - log_error_write(srv, __FILE__, __LINE__, "sd",
45131 + log_error_write(srv, __FILE__, __LINE__, "sd",
45138 fdevent_handler handler;
45143 fd_ndx = fdevent_event_next_fdndx (srv->ev, fd_ndx);
45144 revents = fdevent_event_get_revent (srv->ev, fd_ndx);
45145 fd = fdevent_event_get_fd (srv->ev, fd_ndx);
45146 handler = fdevent_get_handler(srv->ev, fd);
45147 context = fdevent_get_context(srv->ev, fd);
45150 /* connection_handle_fdevent needs a joblist_append */
45152 - log_error_write(srv, __FILE__, __LINE__, "sdd",
45153 + log_error_write(srv, __FILE__, __LINE__, "sdd",
45154 "event for", fd, revents);
45157 switch (r = (*handler)(srv, context, revents)) {
45158 case HANDLER_FINISHED:
45159 case HANDLER_GO_ON:
45160 @@ -1286,17 +1331,17 @@
45163 } else if (n < 0 && errno != EINTR) {
45164 - log_error_write(srv, __FILE__, __LINE__, "ss",
45165 - "fdevent_poll failed:",
45166 + log_error_write(srv, __FILE__, __LINE__, "ss",
45167 + "fdevent_poll failed:",
45172 for (ndx = 0; ndx < srv->joblist->used; ndx++) {
45173 connection *con = srv->joblist->ptr[ndx];
45177 connection_state_machine(srv, con);
45180 switch(r = plugins_call_handle_joblist(srv, con)) {
45181 case HANDLER_FINISHED:
45182 case HANDLER_GO_ON:
45183 @@ -1305,32 +1350,33 @@
45184 log_error_write(srv, __FILE__, __LINE__, "d", r);
45189 con->in_joblist = 0;
45193 srv->joblist->used = 0;
45196 - if (srv->srvconf.pid_file->used &&
45198 + if (0 == graceful_restart &&
45199 + srv->srvconf.pid_file->used &&
45200 srv->srvconf.changeroot->used == 0) {
45201 if (0 != unlink(srv->srvconf.pid_file->ptr)) {
45202 if (errno != EACCES && errno != EPERM) {
45203 - log_error_write(srv, __FILE__, __LINE__, "sbds",
45204 - "unlink failed for:",
45205 + log_error_write(srv, __FILE__, __LINE__, "sbds",
45206 + "unlink failed for:",
45207 srv->srvconf.pid_file,
45216 log_error_close(srv);
45217 network_close(srv);
45218 connections_free(srv);
45226 Property changes on: src/server.c
45227 ___________________________________________________________________
45228 Name: svn:eol-style
45231 Index: src/mod_dirlisting.c
45232 ===================================================================
45233 --- src/mod_dirlisting.c (.../tags/lighttpd-1.4.11) (revision 1159)
45234 +++ src/mod_dirlisting.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
45237 #include <stdlib.h>
45238 #include <string.h>
45239 -#include <dirent.h>
45240 #include <assert.h>
45243 -#include <unistd.h>
45248 #include <attr/attributes.h>
45251 +#include "sys-files.h"
45252 +#include "sys-strings.h"
45254 /* plugin config for all request/connections */
45258 unsigned short hide_readme_file;
45259 unsigned short show_header;
45260 unsigned short hide_header_file;
45263 excludes_buffer *excludes;
45265 buffer *external_css;
45266 @@ -63,13 +64,13 @@
45273 buffer *content_charset;
45276 plugin_config **config_storage;
45278 - plugin_config conf;
45280 + plugin_config conf;
45283 excludes_buffer *excludes_buffer_init(void) {
45284 @@ -146,44 +147,44 @@
45285 /* init the plugin data */
45286 INIT_FUNC(mod_dirlisting_init) {
45290 p = calloc(1, sizeof(*p));
45292 p->tmp_buf = buffer_init();
45293 p->content_charset = buffer_init();
45299 /* detroy the plugin data */
45300 FREE_FUNC(mod_dirlisting_free) {
45301 plugin_data *p = p_d;
45306 if (!p) return HANDLER_GO_ON;
45309 if (p->config_storage) {
45311 for (i = 0; i < srv->config_context->used; i++) {
45312 plugin_config *s = p->config_storage[i];
45318 excludes_buffer_free(s->excludes);
45319 buffer_free(s->external_css);
45320 buffer_free(s->encoding);
45325 free(p->config_storage);
45329 buffer_free(p->tmp_buf);
45330 buffer_free(p->content_charset);
45336 return HANDLER_GO_ON;
45339 @@ -215,10 +216,10 @@
45340 if (0 != excludes_buffer_append(s->excludes,
45341 ((data_string *)(da->value->data[j]))->value)) {
45343 - log_error_write(srv, __FILE__, __LINE__, "sb",
45344 + log_error_write(srv, __FILE__, __LINE__, "sb",
45345 "pcre-compile failed for", ((data_string *)(da->value->data[j]))->value);
45347 - log_error_write(srv, __FILE__, __LINE__, "s",
45348 + log_error_write(srv, __FILE__, __LINE__, "s",
45349 "pcre support is missing, please install libpcre and the headers");
45352 @@ -233,8 +234,8 @@
45353 SETDEFAULTS_FUNC(mod_dirlisting_set_defaults) {
45354 plugin_data *p = p_d;
45357 - config_values_t cv[] = {
45359 + config_values_t cv[] = {
45360 { "dir-listing.exclude", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
45361 { "dir-listing.activate", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
45362 { "dir-listing.hide-dotfiles", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
45363 @@ -245,18 +246,18 @@
45364 { "dir-listing.show-header", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 7 */
45365 { "dir-listing.hide-header-file", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 8 */
45366 { "server.dir-listing", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 9 */
45369 { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
45373 if (!p) return HANDLER_ERROR;
45376 p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
45379 for (i = 0; i < srv->config_context->used; i++) {
45384 s = calloc(1, sizeof(plugin_config));
45385 s->excludes = excludes_buffer_init();
45386 s->dir_listing = 0;
45387 @@ -267,7 +268,7 @@
45388 s->show_header = 0;
45389 s->hide_header_file = 0;
45390 s->encoding = buffer_init();
45393 cv[0].destination = s->excludes;
45394 cv[1].destination = &(s->dir_listing);
45395 cv[2].destination = &(s->hide_dot_files);
45396 @@ -292,60 +293,57 @@
45397 return HANDLER_GO_ON;
45400 -#define PATCH(x) \
45401 - p->conf.x = s->x;
45402 static int mod_dirlisting_patch_connection(server *srv, connection *con, plugin_data *p) {
45404 plugin_config *s = p->config_storage[0];
45406 - PATCH(dir_listing);
45407 - PATCH(external_css);
45408 - PATCH(hide_dot_files);
45410 - PATCH(show_readme);
45411 - PATCH(hide_readme_file);
45412 - PATCH(show_header);
45413 - PATCH(hide_header_file);
45416 + PATCH_OPTION(dir_listing);
45417 + PATCH_OPTION(external_css);
45418 + PATCH_OPTION(hide_dot_files);
45419 + PATCH_OPTION(encoding);
45420 + PATCH_OPTION(show_readme);
45421 + PATCH_OPTION(hide_readme_file);
45422 + PATCH_OPTION(show_header);
45423 + PATCH_OPTION(hide_header_file);
45424 + PATCH_OPTION(excludes);
45426 /* skip the first, the global context */
45427 for (i = 1; i < srv->config_context->used; i++) {
45428 data_config *dc = (data_config *)srv->config_context->data[i];
45429 s = p->config_storage[i];
45432 /* condition didn't match */
45433 if (!config_check_cond(srv, con, dc)) continue;
45437 for (j = 0; j < dc->value->used; j++) {
45438 data_unset *du = dc->value->data[j];
45441 if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.activate")) ||
45442 buffer_is_equal_string(du->key, CONST_STR_LEN("server.dir-listing"))) {
45443 - PATCH(dir_listing);
45444 + PATCH_OPTION(dir_listing);
45445 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.hide-dotfiles"))) {
45446 - PATCH(hide_dot_files);
45447 + PATCH_OPTION(hide_dot_files);
45448 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.external-css"))) {
45449 - PATCH(external_css);
45450 + PATCH_OPTION(external_css);
45451 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.encoding"))) {
45453 + PATCH_OPTION(encoding);
45454 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.show-readme"))) {
45455 - PATCH(show_readme);
45456 + PATCH_OPTION(show_readme);
45457 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.hide-readme-file"))) {
45458 - PATCH(hide_readme_file);
45459 + PATCH_OPTION(hide_readme_file);
45460 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.show-header"))) {
45461 - PATCH(show_header);
45462 + PATCH_OPTION(show_header);
45463 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.hide-header-file"))) {
45464 - PATCH(hide_header_file);
45465 + PATCH_OPTION(hide_header_file);
45466 } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("dir-listing.excludes"))) {
45468 + PATCH_OPTION(excludes);
45480 @@ -432,7 +430,7 @@
45482 static void http_list_directory_header(server *srv, connection *con, plugin_data *p, buffer *out) {
45486 BUFFER_APPEND_STRING_CONST(out,
45487 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n"
45488 "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\">\n"
45489 @@ -492,11 +490,11 @@
45490 if (p->conf.show_header) {
45492 /* if we have a HEADER file, display it in <pre class="header"></pre> */
45495 buffer_copy_string_buffer(p->tmp_buf, con->physical.path);
45496 - BUFFER_APPEND_SLASH(p->tmp_buf);
45497 + PATHNAME_APPEND_SLASH(p->tmp_buf);
45498 BUFFER_APPEND_STRING_CONST(p->tmp_buf, "HEADER.txt");
45501 if (-1 != stream_open(&s, p->tmp_buf)) {
45502 BUFFER_APPEND_STRING_CONST(out, "<pre class=\"header\">");
45503 buffer_append_string_encoded(out, s.start, s.size, ENCODING_MINIMAL_XML);
45504 @@ -531,21 +529,21 @@
45506 static void http_list_directory_footer(server *srv, connection *con, plugin_data *p, buffer *out) {
45510 BUFFER_APPEND_STRING_CONST(out,
45517 if (p->conf.show_readme) {
45519 /* if we have a README file, display it in <pre class="readme"></pre> */
45522 buffer_copy_string_buffer(p->tmp_buf, con->physical.path);
45523 - BUFFER_APPEND_SLASH(p->tmp_buf);
45524 + PATHNAME_APPEND_SLASH(p->tmp_buf);
45525 BUFFER_APPEND_STRING_CONST(p->tmp_buf, "README.txt");
45528 if (-1 != stream_open(&s, p->tmp_buf)) {
45529 BUFFER_APPEND_STRING_CONST(out, "<pre class=\"readme\">");
45530 buffer_append_string_encoded(out, s.start, s.size, ENCODING_MINIMAL_XML);
45531 @@ -553,7 +551,7 @@
45537 BUFFER_APPEND_STRING_CONST(out,
45538 "<div class=\"foot\">"
45540 @@ -595,7 +593,7 @@
45543 if (dir->used == 0) return -1;
45548 #ifdef HAVE_PATHCONF
45549 @@ -606,19 +604,24 @@
45550 name_max = 256; /* stupid default */
45553 -#elif defined __WIN32
45554 +#elif defined _WIN32
45555 name_max = FILENAME_MAX;
45557 name_max = NAME_MAX;
45561 path = malloc(dir->used + name_max);
45563 strcpy(path, dir->ptr);
45565 + /* append \*.* to the path and keep the \ as part of the pathname */
45566 + strcat(path, "\\*.*");
45569 path_file = path + i;
45571 if (NULL == (dp = opendir(path))) {
45572 - log_error_write(srv, __FILE__, __LINE__, "sbs",
45573 + log_error_write(srv, __FILE__, __LINE__, "sbs",
45574 "opendir failed:", dir, strerror(errno));
45577 @@ -633,7 +636,7 @@
45579 files.size = DIRLIST_BLOB_SIZE;
45583 while ((dent = readdir(dp)) != NULL) {
45584 unsigned short exclude_match = 0;
45586 @@ -686,15 +689,17 @@
45589 i = strlen(dent->d_name);
45592 /* NOTE: the manual says, d_name is never more than NAME_MAX
45593 * so this should actually not be a buffer-overflow-risk
45595 if (i > (size_t)name_max) continue;
45598 memcpy(path_file, dent->d_name, i + 1);
45599 - if (stat(path, &st) != 0)
45600 + if (stat(path, &st) != 0) {
45601 + fprintf(stderr, "%s.%d: %s, %s\r\n", __FILE__, __LINE__, path, strerror(errno));
45606 if (S_ISDIR(st.st_mode))
45607 @@ -740,7 +745,7 @@
45609 strftime(datebuf, sizeof(datebuf), "%Y-%b-%d %H:%M:%S", localtime(&(tmp->mtime)));
45613 BUFFER_APPEND_STRING_CONST(out, "<tr><td class=\"n\"><a href=\"");
45614 buffer_append_string_encoded(out, DIRLIST_ENT_NAME(tmp), tmp->namelen, ENCODING_REL_URI_PART);
45615 BUFFER_APPEND_STRING_CONST(out, "/\">");
45616 @@ -758,7 +763,7 @@
45618 content_type = NULL;
45622 if (con->conf.use_xattr) {
45623 memcpy(path_file, DIRLIST_ENT_NAME(tmp), tmp->namelen + 1);
45624 attrlen = sizeof(attrval) - 1;
45625 @@ -768,7 +773,7 @@
45631 if (content_type == NULL) {
45632 content_type = "application/octet-stream";
45633 for (k = 0; k < con->conf.mimetypes->used; k++) {
45634 @@ -788,7 +793,7 @@
45640 #ifdef HAVE_LOCALTIME_R
45641 localtime_r(&(tmp->mtime), &tm);
45642 strftime(datebuf, sizeof(datebuf), "%Y-%b-%d %H:%M:%S", &tm);
45643 @@ -837,36 +842,36 @@
45644 URIHANDLER_FUNC(mod_dirlisting_subrequest) {
45645 plugin_data *p = p_d;
45646 stat_cache_entry *sce = NULL;
45652 if (con->physical.path->used == 0) return HANDLER_GO_ON;
45653 if (con->uri.path->used == 0) return HANDLER_GO_ON;
45654 if (con->uri.path->ptr[con->uri.path->used - 2] != '/') return HANDLER_GO_ON;
45657 mod_dirlisting_patch_connection(srv, con, p);
45659 if (!p->conf.dir_listing) return HANDLER_GO_ON;
45662 if (con->conf.log_request_handling) {
45663 log_error_write(srv, __FILE__, __LINE__, "s", "-- handling the request as Dir-Listing");
45664 log_error_write(srv, __FILE__, __LINE__, "sb", "URI :", con->uri.path);
45668 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
45669 fprintf(stderr, "%s.%d: %s\n", __FILE__, __LINE__, con->physical.path->ptr);
45674 if (!S_ISDIR(sce->st.st_mode)) return HANDLER_GO_ON;
45677 if (http_list_directory(srv, con, p, con->physical.path)) {
45678 /* dirlisting failed */
45679 con->http_status = 403;
45683 buffer_reset(con->physical.path);
45687 return HANDLER_FINISHED;
45689 @@ -876,13 +881,13 @@
45690 int mod_dirlisting_plugin_init(plugin *p) {
45691 p->version = LIGHTTPD_VERSION_ID;
45692 p->name = buffer_init_string("dirlisting");
45695 p->init = mod_dirlisting_init;
45696 p->handle_subrequest_start = mod_dirlisting_subrequest;
45697 p->set_defaults = mod_dirlisting_set_defaults;
45698 p->cleanup = mod_dirlisting_free;
45707 Property changes on: src/mod_dirlisting.c
45708 ___________________________________________________________________
45709 Name: svn:eol-style
45712 Index: src/http_chunk.c
45713 ===================================================================
45714 --- src/http_chunk.c (.../tags/lighttpd-1.4.11) (revision 1159)
45715 +++ src/http_chunk.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
45718 * the HTTP chunk-API
45725 #include <sys/types.h>
45728 #include <stdlib.h>
45730 -#include <unistd.h>
45734 @@ -23,19 +22,19 @@
45735 static int http_chunk_append_len(server *srv, connection *con, size_t len) {
45736 size_t i, olen = len, j;
45740 b = srv->tmp_chunk_len;
45744 buffer_copy_string(b, "0");
45746 for (i = 0; i < 8 && len; i++) {
45751 /* i is the number of hex digits we have */
45752 buffer_prepare_copy(b, i + 1);
45755 for (j = i-1, len = olen; j+1 > 0; j--) {
45756 b->ptr[j] = (len & 0xf) + (((len & 0xf) <= 9) ? '0' : 'a' - 10);
45758 @@ -43,61 +42,61 @@
45760 b->ptr[b->used++] = '\0';
45764 buffer_append_string(b, "\r\n");
45765 chunkqueue_append_buffer(con->write_queue, b);
45772 int http_chunk_append_file(server *srv, connection *con, buffer *fn, off_t offset, off_t len) {
45776 if (!con) return -1;
45779 cq = con->write_queue;
45782 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
45783 http_chunk_append_len(srv, con, len);
45787 chunkqueue_append_file(cq, fn, offset, len);
45790 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED && len > 0) {
45791 chunkqueue_append_mem(cq, "\r\n", 2 + 1);
45798 int http_chunk_append_buffer(server *srv, connection *con, buffer *mem) {
45802 if (!con) return -1;
45805 cq = con->write_queue;
45808 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
45809 http_chunk_append_len(srv, con, mem->used - 1);
45813 chunkqueue_append_buffer(cq, mem);
45816 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED && mem->used > 0) {
45817 chunkqueue_append_mem(cq, "\r\n", 2 + 1);
45824 int http_chunk_append_mem(server *srv, connection *con, const char * mem, size_t len) {
45828 if (!con) return -1;
45831 cq = con->write_queue;
45835 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
45836 http_chunk_append_len(srv, con, 0);
45837 @@ -107,17 +106,17 @@
45843 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
45844 http_chunk_append_len(srv, con, len - 1);
45848 chunkqueue_append_mem(cq, mem, len);
45851 if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
45852 chunkqueue_append_mem(cq, "\r\n", 2 + 1);
45859 @@ -125,9 +124,9 @@
45860 off_t http_chunkqueue_length(server *srv, connection *con) {
45862 log_error_write(srv, __FILE__, __LINE__, "s", "connection is NULL!!");
45869 return chunkqueue_length(con->write_queue);
45872 Property changes on: src/http_chunk.c
45873 ___________________________________________________________________
45874 Name: svn:eol-style
45878 Property changes on: src/server.h
45879 ___________________________________________________________________
45880 Name: svn:eol-style
45884 Property changes on: src/http_chunk.h
45885 ___________________________________________________________________
45886 Name: svn:eol-style
45889 Index: src/sys-files.c
45890 ===================================================================
45891 --- src/sys-files.c (.../tags/lighttpd-1.4.11) (revision 0)
45892 +++ src/sys-files.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
45894 +#include "sys-files.h"
45897 +#include "buffer.h"
45898 +DIR *opendir(const char *dn) {
45899 + DIR *d = malloc(sizeof(*d));
45901 + if (INVALID_HANDLE_VALUE == (d->h = FindFirstFile(dn, &(d->finddata)))) {
45908 +struct dirent *readdir(DIR *d) {
45909 + if (!d->dent.d_name) {
45910 + /* opendir has set a finddata already, push it out */
45912 + d->dent.d_name = d->finddata.cFileName;
45913 + return &(d->dent);
45915 + if (FindNextFile(d->h, &(d->finddata))) {
45916 + d->dent.d_name = d->finddata.cFileName;
45917 + return &(d->dent);
45923 +void closedir(DIR *d) {
45929 +buffer *pathname_unix2local(buffer *fn) {
45932 + for (i = 0; i < fn->used; i++) {
45933 + if (fn->ptr[i] == '/') {
45934 + fn->ptr[i] = '\\';
45941 +buffer *filename_unix2local(buffer *fn) {
45944 + for (i = 0; i < fn->used; i++) {
45945 + if (fn->ptr[i] == '/') {
45946 + fn->ptr[i] = '\\';
45950 + buffer_prepare_append(fn, 4);
45951 + memmove(fn->ptr + 4, fn->ptr, fn->used);
45952 + memcpy(fn->ptr, "\\\\?\\", 4);
45958 \ No newline at end of file
45960 Property changes on: src/sys-files.c
45961 ___________________________________________________________________
45962 Name: svn:eol-style
45965 Index: src/network_linux_sendfile.c
45966 ===================================================================
45967 --- src/network_linux_sendfile.c (.../tags/lighttpd-1.4.11) (revision 1159)
45968 +++ src/network_linux_sendfile.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
45969 @@ -26,122 +26,54 @@
45970 /* on linux 2.4.29 + debian/ubuntu we have crashes if this is enabled */
45971 #undef HAVE_POSIX_FADVISE
45973 -int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd, chunkqueue *cq) {
45975 +NETWORK_BACKEND_WRITE(linuxsendfile) {
45977 size_t chunks_written = 0;
45980 for(c = cq->first; c; c = c->next, chunks_written++) {
45981 int chunk_finished = 0;
45983 + network_status_t ret;
45986 - case MEM_CHUNK: {
45991 - size_t num_chunks, i;
45992 - struct iovec chunks[UIO_MAXIOV];
45994 - size_t num_bytes = 0;
45996 - /* we can't send more then SSIZE_MAX bytes in one chunk */
45998 - /* build writev list
46000 - * 1. limit: num_chunks < UIO_MAXIOV
46001 - * 2. limit: num_bytes < SSIZE_MAX
46003 - for (num_chunks = 0, tc = c;
46004 - tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV;
46005 - tc = tc->next, num_chunks++);
46007 - for (tc = c, i = 0; i < num_chunks; tc = tc->next, i++) {
46008 - if (tc->mem->used == 0) {
46009 - chunks[i].iov_base = tc->mem->ptr;
46010 - chunks[i].iov_len = 0;
46012 - offset = tc->mem->ptr + tc->offset;
46013 - toSend = tc->mem->used - 1 - tc->offset;
46015 - chunks[i].iov_base = offset;
46017 - /* protect the return value of writev() */
46018 - if (toSend > SSIZE_MAX ||
46019 - num_bytes + toSend > SSIZE_MAX) {
46020 - chunks[i].iov_len = SSIZE_MAX - num_bytes;
46022 - num_chunks = i + 1;
46025 - chunks[i].iov_len = toSend;
46028 - num_bytes += toSend;
46032 - if ((r = writev(fd, chunks, num_chunks)) < 0) {
46042 - log_error_write(srv, __FILE__, __LINE__, "ssd",
46043 - "writev failed:", strerror(errno), fd);
46049 - /* check which chunks have been written */
46050 - cq->bytes_out += r;
46052 + ret = network_write_chunkqueue_writev_mem(srv, con, fd, cq, c);
46054 - for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) {
46055 - if (r >= (ssize_t)chunks[i].iov_len) {
46057 - r -= chunks[i].iov_len;
46058 - tc->offset += chunks[i].iov_len;
46060 + /* check which chunks are finished now */
46061 + for (tc = c; tc; tc = tc->next) {
46062 + /* finished the chunk */
46063 + if (tc->offset == tc->mem->used - 1) {
46064 + /* skip the first c->next as that will be done by the c = c->next in the other for()-loop */
46065 if (chunk_finished) {
46066 - /* skip the chunks from further touches */
46067 - chunks_written++;
46070 - /* chunks_written + c = c->next is done in the for()*/
46071 - chunk_finished++;
46072 + chunk_finished = 1;
46075 - /* partially written */
46078 - chunk_finished = 0;
46085 + if (ret != NETWORK_STATUS_SUCCESS) {
46095 stat_cache_entry *sce = NULL;
46098 offset = c->file.start + c->offset;
46099 /* limit the toSend to 2^31-1 bytes in a chunk */
46100 - toSend = c->file.length - c->offset > ((1 << 30) - 1) ?
46101 + toSend = c->file.length - c->offset > ((1 << 30) - 1) ?
46102 ((1 << 30) - 1) : c->file.length - c->offset;
46104 - /* open file if not already opened */
46106 + /* open file if not already opened */
46107 if (-1 == c->file.fd) {
46108 if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) {
46109 log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno));
46116 /* tell the kernel that we want to stream the file */
46117 if (-1 == posix_fadvise(c->file.fd, 0, 0, POSIX_FADV_SEQUENTIAL)) {
46118 if (ENOSYS != errno) {
46119 - log_error_write(srv, __FILE__, __LINE__, "ssd",
46120 + log_error_write(srv, __FILE__, __LINE__, "ssd",
46121 "posix_fadvise failed:", strerror(errno), c->file.fd);
46124 @@ -168,7 +100,7 @@
46128 - log_error_write(srv, __FILE__, __LINE__, "ssd",
46129 + log_error_write(srv, __FILE__, __LINE__, "ssd",
46130 "sendfile failed:", strerror(errno), fd);
46133 @@ -179,7 +111,7 @@
46135 * - the file shrinked -> error
46136 * - the remote side closed inbetween -> remote-close */
46139 if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
46140 /* file is gone ? */
46142 @@ -196,22 +128,22 @@
46143 #ifdef HAVE_POSIX_FADVISE
46146 -#define M * 1024 K
46147 +#define M * 1024 K
46148 #define READ_AHEAD 4 M
46149 /* check if we need a new chunk */
46150 if ((c->offset & ~(READ_AHEAD - 1)) != ((c->offset + r) & ~(READ_AHEAD - 1))) {
46151 /* tell the kernel that we want to stream the file */
46152 if (-1 == posix_fadvise(c->file.fd, (c->offset + r) & ~(READ_AHEAD - 1), READ_AHEAD, POSIX_FADV_NOREUSE)) {
46153 - log_error_write(srv, __FILE__, __LINE__, "ssd",
46154 + log_error_write(srv, __FILE__, __LINE__, "ssd",
46155 "posix_fadvise failed:", strerror(errno), c->file.fd);
46163 cq->bytes_out += r;
46166 if (c->offset == c->file.length) {
46167 chunk_finished = 1;
46169 @@ -222,19 +154,19 @@
46180 log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known");
46187 if (!chunk_finished) {
46188 /* not finished yet */
46195 Property changes on: src/network_linux_sendfile.c
46196 ___________________________________________________________________
46197 Name: svn:eol-style
46201 ===================================================================
46202 --- src/log.c (.../tags/lighttpd-1.4.11) (revision 1159)
46203 +++ src/log.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
46208 -#include <unistd.h>
46209 #include <string.h>
46210 #include <stdlib.h>
46213 #include "config.h"
46217 +#undef HAVE_SYSLOG_H
46220 #ifdef HAVE_SYSLOG_H
46221 #include <syslog.h>
46227 +#include "sys-files.h"
46229 #ifdef HAVE_VALGRIND_VALGRIND_H
46230 #include <valgrind/valgrind.h>
46232 @@ -31,38 +36,38 @@
46233 # define O_LARGEFILE 0
46238 * open the errorlog
46241 * we have 3 possibilities:
46242 * - stderr (default)
46248 * if the open failed, report to the user and die
46253 int log_error_open(server *srv) {
46255 int close_stderr = 1;
46258 #ifdef HAVE_SYSLOG_H
46259 /* perhaps someone wants to use syslog() */
46260 openlog("lighttpd", LOG_CONS | LOG_PID, LOG_DAEMON);
46262 srv->errorlog_mode = ERRORLOG_STDERR;
46265 if (srv->srvconf.errorlog_use_syslog) {
46266 srv->errorlog_mode = ERRORLOG_SYSLOG;
46267 } else if (!buffer_is_empty(srv->srvconf.errorlog_file)) {
46268 const char *logfile = srv->srvconf.errorlog_file->ptr;
46271 if (-1 == (srv->errorlog_fd = open(logfile, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
46272 - log_error_write(srv, __FILE__, __LINE__, "SSSS",
46273 + log_error_write(srv, __FILE__, __LINE__, "SSSS",
46274 "opening errorlog '", logfile,
46275 "' failed: ", strerror(errno));
46281 @@ -71,15 +76,15 @@
46283 srv->errorlog_mode = ERRORLOG_FILE;
46287 log_error_write(srv, __FILE__, __LINE__, "s", "server started");
46290 #ifdef HAVE_VALGRIND_VALGRIND_H
46291 /* don't close stderr for debugging purposes if run in valgrind */
46292 if (RUNNING_ON_VALGRIND) close_stderr = 0;
46294 if (srv->errorlog_mode == ERRORLOG_STDERR) close_stderr = 0;
46297 /* move stderr to /dev/null */
46298 if (close_stderr &&
46299 -1 != (fd = open("/dev/null", O_WRONLY))) {
46300 @@ -90,33 +95,33 @@
46306 * open the errorlog
46309 * if the open failed, report to the user and die
46310 * if no filename is given, use syslog instead
46315 int log_error_cycle(server *srv) {
46316 /* only cycle if we are not in syslog-mode */
46319 if (srv->errorlog_mode == ERRORLOG_FILE) {
46320 const char *logfile = srv->srvconf.errorlog_file->ptr;
46321 /* already check of opening time */
46327 if (-1 == (new_fd = open(logfile, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) {
46328 /* write to old log */
46329 - log_error_write(srv, __FILE__, __LINE__, "SSSSS",
46330 + log_error_write(srv, __FILE__, __LINE__, "SSSSS",
46331 "cycling errorlog '", logfile,
46332 "' failed: ", strerror(errno),
46333 ", falling back to syslog()");
46336 close(srv->errorlog_fd);
46337 srv->errorlog_fd = -1;
46338 -#ifdef HAVE_SYSLOG_H
46339 +#ifdef HAVE_SYSLOG_H
46340 srv->errorlog_mode = ERRORLOG_SYSLOG;
46343 @@ -125,15 +130,15 @@
46344 srv->errorlog_fd = new_fd;
46349 log_error_write(srv, __FILE__, __LINE__, "s", "logfiles cycled");
46355 int log_error_close(server *srv) {
46356 log_error_write(srv, __FILE__, __LINE__, "s", "server stopped");
46359 switch(srv->errorlog_mode) {
46360 case ERRORLOG_FILE:
46361 close(srv->errorlog_fd);
46362 @@ -146,13 +151,13 @@
46363 case ERRORLOG_STDERR:
46371 int log_error_write(server *srv, const char *filename, unsigned int line, const char *fmt, ...) {
46375 switch(srv->errorlog_mode) {
46376 case ERRORLOG_FILE:
46377 case ERRORLOG_STDERR:
46378 @@ -161,7 +166,7 @@
46379 buffer_prepare_copy(srv->ts_debug_str, 255);
46380 strftime(srv->ts_debug_str->ptr, srv->ts_debug_str->size - 1, "%Y-%m-%d %H:%M:%S", localtime(&(srv->cur_ts)));
46381 srv->ts_debug_str->used = strlen(srv->ts_debug_str->ptr) + 1;
46384 srv->last_generated_debug_ts = srv->cur_ts;
46387 @@ -173,19 +178,19 @@
46388 BUFFER_COPY_STRING_CONST(srv->errorlog_buf, "(");
46393 buffer_append_string(srv->errorlog_buf, filename);
46394 BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, ".");
46395 buffer_append_long(srv->errorlog_buf, line);
46396 BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, ") ");
46401 for(va_start(ap, fmt); *fmt; fmt++) {
46409 case 's': /* string */
46410 s = va_arg(ap, char *);
46411 @@ -227,7 +232,7 @@
46420 @@ -236,7 +241,7 @@
46426 switch(srv->errorlog_mode) {
46427 case ERRORLOG_FILE:
46428 BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, "\n");
46429 @@ -246,11 +251,13 @@
46430 BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, "\n");
46431 write(STDERR_FILENO, srv->errorlog_buf->ptr, srv->errorlog_buf->used - 1);
46433 +#ifdef HAVE_SYSLOG_H
46434 case ERRORLOG_SYSLOG:
46435 syslog(LOG_ERR, "%s", srv->errorlog_buf->ptr);
46445 Property changes on: src/log.c
46446 ___________________________________________________________________
46447 Name: svn:eol-style
46450 Index: src/sys-files.h
46451 ===================================================================
46452 --- src/sys-files.h (.../tags/lighttpd-1.4.11) (revision 0)
46453 +++ src/sys-files.h (.../branches/lighttpd-merge-1.4.x) (revision 1159)
46455 +#ifndef _SYS_FILES_H_
46456 +#define _SYS_FILES_H_
46458 +#define DIR_SEPERATOR_UNIX '/'
46459 +#define DIR_SEPERATOR_WIN '\\'
46462 +#include <windows.h>
46463 +#include <io.h> /* open */
46464 +#include <direct.h> /* chdir */
46466 +#include "buffer.h"
46468 +#define DIR_SEPERATOR DIR_SEPERATOR_WIN
46470 +#define __S_ISTYPE(mode, mask) (((mode) & _S_IFMT) == (mask))
46472 +#define S_ISDIR(mode) __S_ISTYPE((mode), _S_IFDIR)
46473 +#define S_ISCHR(mode) __S_ISTYPE((mode), _S_IFCHR)
46474 +#define S_ISBLK(mode) __S_ISTYPE((mode), _S_IFBLK)
46475 +#define S_ISREG(mode) __S_ISTYPE((mode), _S_IFREG)
46476 +/* we don't support symlinks */
46477 +#define S_ISLNK(mode) 0
46479 +#define lstat stat
46480 +#define mkstemp mktemp
46481 +#define mkdir(x, y) mkdir(x)
46484 + const char *d_name;
46489 + WIN32_FIND_DATA finddata;
46490 + struct dirent dent;
46493 +DIR *opendir(const char *dn);
46494 +struct dirent *readdir(DIR *d);
46495 +void closedir(DIR *d);
46497 +buffer *filename_unix2local(buffer *b);
46498 +buffer *pathname_unix2local(buffer *b);
46501 +#include <unistd.h>
46502 +#include <dirent.h>
46504 +#define DIR_SEPERATOR DIR_SEPERATOR_UNIX
46506 +#define filename_unix2local(x) (x)
46507 +#define pathname_unix2local(x) (x)
46510 +#define PATHNAME_APPEND_SLASH(x) \
46511 + if (x->used > 1 && x->ptr[x->used - 2] != DIR_SEPERATOR) { \
46512 + char sl[2] = { DIR_SEPERATOR, 0 }; \
46513 + BUFFER_APPEND_STRING_CONST(x, sl); \
46516 +#ifndef O_LARGEFILE
46517 +# define O_LARGEFILE 0
46523 Property changes on: src/sys-files.h
46524 ___________________________________________________________________
46525 Name: svn:eol-style
46528 Index: src/proc_open.c
46529 ===================================================================
46530 --- src/proc_open.c (.../tags/lighttpd-1.4.11) (revision 1159)
46531 +++ src/proc_open.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
46532 @@ -13,13 +13,13 @@
46538 /* {{{ win32 stuff */
46539 # define SHELLENV "ComSpec"
46540 # define SECURITY_DC , SECURITY_ATTRIBUTES *security
46541 # define SECURITY_CC , security
46542 # define pipe(pair) (CreatePipe(&pair[0], &pair[1], security, 2048L) ? 0 : -1)
46543 -static inline HANDLE dup_handle(HANDLE src, BOOL inherit, BOOL closeorig)
46544 +static HANDLE dup_handle(HANDLE src, BOOL inherit, BOOL closeorig)
46546 HANDLE copy, self = GetCurrentProcess();
46548 @@ -148,11 +148,14 @@
46551 SECURITY_ATTRIBUTES security;
46552 - const char *shell;
46553 + const char *shell = NULL;
46554 + const char *windir = NULL;
46557 - if (NULL == (shell = getenv(SHELLENV))) {
46558 - fprintf(stderr, "env %s is required", SHELLENV);
46559 + if (NULL == (shell = getenv(SHELLENV)) &&
46560 + NULL == (windir = getenv("SystemRoot")) &&
46561 + NULL == (windir = getenv("windir"))) {
46562 + fprintf(stderr, "One of %s,%%SystemRoot,%%windir is required", SHELLENV);
46566 @@ -177,17 +180,23 @@
46567 memset(&pi, 0, sizeof(pi));
46569 cmdline = buffer_init();
46570 - buffer_append_string(cmdline, shell);
46572 + buffer_append_string(cmdline, shell);
46574 + buffer_append_string(cmdline, windir);
46575 + buffer_append_string(cmdline, "\\system32\\cmd.exe");
46577 buffer_append_string_len(cmdline, CONST_STR_LEN(" /c "));
46578 buffer_append_string(cmdline, command);
46579 procok = CreateProcess(NULL, cmdline->ptr, &security, &security, TRUE,
46580 NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);
46581 - buffer_free(cmdline);
46583 if (FALSE == procok) {
46584 - fprintf(stderr, "failed to CreateProcess");
46585 + fprintf(stderr, "failed to CreateProcess: %s", cmdline->ptr);
46586 + buffer_free(cmdline);
46589 + buffer_free(cmdline);
46591 proc->child = pi.hProcess;
46592 CloseHandle(pi.hThread);
46593 @@ -226,8 +235,7 @@
46596 if (NULL == (shell = getenv(SHELLENV))) {
46597 - fprintf(stderr, "env %s is required", SHELLENV);
46599 + shell = "/bin/sh";
46602 if (proc_open_pipes(proc) != 0) {
46603 @@ -262,11 +270,11 @@
46607 -#endif /* WIN32 */
46608 +#endif /* _WIN32 */
46610 /* {{{ proc_read_fd_to_buffer */
46611 static void proc_read_fd_to_buffer(int fd, buffer *b) {
46613 + int s; /* win32 has not ssize_t */
46616 buffer_prepare_append(b, 512);
46618 Property changes on: src/proc_open.c
46619 ___________________________________________________________________
46620 Name: svn:eol-style
46624 ===================================================================
46625 --- src/log.h (.../tags/lighttpd-1.4.11) (revision 1159)
46626 +++ src/log.h (.../branches/lighttpd-merge-1.4.x) (revision 1159)
46628 int log_error_close(server *srv);
46629 int log_error_write(server *srv, const char *filename, unsigned int line, const char *fmt, ...);
46630 int log_error_cycle(server *srv);
46635 Property changes on: src/log.h
46636 ___________________________________________________________________
46637 Name: svn:eol-style
46640 Index: src/proc_open.h
46641 ===================================================================
46642 --- src/proc_open.h (.../tags/lighttpd-1.4.11) (revision 1159)
46643 +++ src/proc_open.h (.../branches/lighttpd-merge-1.4.x) (revision 1159)
46646 #include "buffer.h"
46650 #include <windows.h>
46651 typedef HANDLE descriptor_t;
46652 typedef HANDLE proc_pid_t;
46654 Property changes on: src/proc_open.h
46655 ___________________________________________________________________
46656 Name: svn:eol-style
46659 Index: src/fdevent.c
46660 ===================================================================
46661 --- src/fdevent.c (.../tags/lighttpd-1.4.11) (revision 1159)
46662 +++ src/fdevent.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
46665 #include "settings.h"
46667 -#include <unistd.h>
46668 #include <stdlib.h>
46669 #include <string.h>
46671 @@ -12,59 +11,61 @@
46672 #include "fdevent.h"
46673 #include "buffer.h"
46675 +#include "sys-socket.h"
46677 fdevents *fdevent_init(size_t maxfds, fdevent_handler_t type) {
46681 ev = calloc(1, sizeof(*ev));
46682 ev->fdarray = calloc(maxfds, sizeof(*ev->fdarray));
46683 ev->maxfds = maxfds;
46687 case FDEVENT_HANDLER_POLL:
46688 if (0 != fdevent_poll_init(ev)) {
46689 - fprintf(stderr, "%s.%d: event-handler poll failed\n",
46690 + fprintf(stderr, "%s.%d: event-handler poll failed\n",
46691 __FILE__, __LINE__);
46697 case FDEVENT_HANDLER_SELECT:
46698 if (0 != fdevent_select_init(ev)) {
46699 - fprintf(stderr, "%s.%d: event-handler select failed\n",
46700 + fprintf(stderr, "%s.%d: event-handler select failed\n",
46701 __FILE__, __LINE__);
46705 case FDEVENT_HANDLER_LINUX_RTSIG:
46706 if (0 != fdevent_linux_rtsig_init(ev)) {
46707 - fprintf(stderr, "%s.%d: event-handler linux-rtsig failed, try to set server.event-handler = \"poll\" or \"select\"\n",
46708 + fprintf(stderr, "%s.%d: event-handler linux-rtsig failed, try to set server.event-handler = \"poll\" or \"select\"\n",
46709 __FILE__, __LINE__);
46713 case FDEVENT_HANDLER_LINUX_SYSEPOLL:
46714 if (0 != fdevent_linux_sysepoll_init(ev)) {
46715 - fprintf(stderr, "%s.%d: event-handler linux-sysepoll failed, try to set server.event-handler = \"poll\" or \"select\"\n",
46716 + fprintf(stderr, "%s.%d: event-handler linux-sysepoll failed, try to set server.event-handler = \"poll\" or \"select\"\n",
46717 __FILE__, __LINE__);
46721 case FDEVENT_HANDLER_SOLARIS_DEVPOLL:
46722 if (0 != fdevent_solaris_devpoll_init(ev)) {
46723 - fprintf(stderr, "%s.%d: event-handler solaris-devpoll failed, try to set server.event-handler = \"poll\" or \"select\"\n",
46724 + fprintf(stderr, "%s.%d: event-handler solaris-devpoll failed, try to set server.event-handler = \"poll\" or \"select\"\n",
46725 __FILE__, __LINE__);
46729 case FDEVENT_HANDLER_FREEBSD_KQUEUE:
46730 if (0 != fdevent_freebsd_kqueue_init(ev)) {
46731 - fprintf(stderr, "%s.%d: event-handler freebsd-kqueue failed, try to set server.event-handler = \"poll\" or \"select\"\n",
46732 + fprintf(stderr, "%s.%d: event-handler freebsd-kqueue failed, try to set server.event-handler = \"poll\" or \"select\"\n",
46733 __FILE__, __LINE__);
46738 - fprintf(stderr, "%s.%d: event-handler is unknown, try to set server.event-handler = \"poll\" or \"select\"\n",
46739 + fprintf(stderr, "%s.%d: event-handler is unknown, try to set server.event-handler = \"poll\" or \"select\"\n",
46740 __FILE__, __LINE__);
46743 @@ -75,26 +76,26 @@
46744 void fdevent_free(fdevents *ev) {
46749 if (ev->free) ev->free(ev);
46752 for (i = 0; i < ev->maxfds; i++) {
46753 if (ev->fdarray[i]) free(ev->fdarray[i]);
46761 int fdevent_reset(fdevents *ev) {
46762 if (ev->reset) return ev->reset(ev);
46768 fdnode *fdnode_init() {
46772 fdn = calloc(1, sizeof(*fdn));
46775 @@ -106,12 +107,12 @@
46777 int fdevent_register(fdevents *ev, int fd, fdevent_handler handler, void *ctx) {
46781 fdn = fdnode_init();
46782 fdn->handler = handler;
46787 ev->fdarray[fd] = fdn;
46790 @@ -121,31 +122,31 @@
46793 fdn = ev->fdarray[fd];
46799 ev->fdarray[fd] = NULL;
46805 int fdevent_event_del(fdevents *ev, int *fde_ndx, int fd) {
46806 int fde = fde_ndx ? *fde_ndx : -1;
46809 if (ev->event_del) fde = ev->event_del(ev, fde, fd);
46812 if (fde_ndx) *fde_ndx = fde;
46818 int fdevent_event_add(fdevents *ev, int *fde_ndx, int fd, int events) {
46819 int fde = fde_ndx ? *fde_ndx : -1;
46822 if (ev->event_add) fde = ev->event_add(ev, fde, fd, events);
46825 if (fde_ndx) *fde_ndx = fde;
46831 @@ -156,38 +157,43 @@
46833 int fdevent_event_get_revent(fdevents *ev, size_t ndx) {
46834 if (ev->event_get_revent == NULL) SEGFAULT();
46837 return ev->event_get_revent(ev, ndx);
46840 int fdevent_event_get_fd(fdevents *ev, size_t ndx) {
46841 if (ev->event_get_fd == NULL) SEGFAULT();
46844 return ev->event_get_fd(ev, ndx);
46847 fdevent_handler fdevent_get_handler(fdevents *ev, int fd) {
46848 if (ev->fdarray[fd] == NULL) SEGFAULT();
46849 if (ev->fdarray[fd]->fd != fd) SEGFAULT();
46852 return ev->fdarray[fd]->handler;
46855 void * fdevent_get_context(fdevents *ev, int fd) {
46856 if (ev->fdarray[fd] == NULL) SEGFAULT();
46857 if (ev->fdarray[fd]->fd != fd) SEGFAULT();
46860 return ev->fdarray[fd]->ctx;
46863 int fdevent_fcntl_set(fdevents *ev, int fd) {
46868 /* close fd on exec (cgi) */
46869 fcntl(fd, F_SETFD, FD_CLOEXEC);
46871 if ((ev) && (ev->fcntl_set)) return ev->fcntl_set(ev, fd);
46874 return fcntl(fd, F_SETFL, O_NONBLOCK | O_RDWR);
46875 +#elif defined _WIN32
46876 + return ioctlsocket(fd, FIONBIO, &i);
46880 @@ -196,7 +202,7 @@
46882 int fdevent_event_next_fdndx(fdevents *ev, int ndx) {
46883 if (ev->event_next_fdndx) return ev->event_next_fdndx(ev, ndx);
46890 Property changes on: src/fdevent.c
46891 ___________________________________________________________________
46892 Name: svn:eol-style
46896 Property changes on: src
46897 ___________________________________________________________________
46909 mod_ssi_exprparser.c
46922 mod_ssi_exprparser.c
46935 Property changes on: distribute.sh.in
46936 ___________________________________________________________________
46937 Name: svn:eol-style
46941 Property changes on: README
46942 ___________________________________________________________________
46943 Name: svn:eol-style
46947 Property changes on: openwrt/lighttpd.conf
46948 ___________________________________________________________________
46949 Name: svn:eol-style
46953 Property changes on: openwrt/control.in
46954 ___________________________________________________________________
46955 Name: svn:eol-style
46959 Property changes on: openwrt/S51lighttpd
46960 ___________________________________________________________________
46961 Name: svn:eol-style
46965 Property changes on: openwrt/conffiles
46966 ___________________________________________________________________
46967 Name: svn:eol-style
46971 Property changes on: openwrt/Makefile.am
46972 ___________________________________________________________________
46973 Name: svn:eol-style
46977 Property changes on: openwrt/lighttpd.mk.in
46978 ___________________________________________________________________
46979 Name: svn:eol-style
46983 Property changes on: openwrt/.cvsignore
46984 ___________________________________________________________________
46985 Name: svn:eol-style
46988 Index: cygwin/lighttpd.README.in
46989 ===================================================================
46990 --- cygwin/lighttpd.README.in (.../tags/lighttpd-1.4.11) (revision 1159)
46991 +++ cygwin/lighttpd.README.in (.../branches/lighttpd-merge-1.4.x) (revision 1159)
46992 @@ -1,114 +1,114 @@
46994 -------------------------------------------
\r
46995 -A fast, secure and flexible webserver
\r
46997 -Runtime requirements:
\r
46998 - cygwin-1.5.10 or newer
\r
46999 - crypt-1.1 or newer
\r
47000 - libbz2_1-1.0.2 or newer
\r
47001 - libpcre0-4.5 or newer
\r
47002 - openssl-0.9.7d or newer
\r
47003 - zlib-1.2.1 or newer
\r
47005 -Build requirements:
\r
47006 - cygwin-1.5.10 or newer
\r
47007 - gcc-3.3.1-3 or newer
\r
47008 - binutils-20030901-1 or newer
\r
47017 -Canonical homepage:
\r
47018 - http://jan.kneschke.de/projects/lighttpd/
\r
47020 -Canonical download:
\r
47021 - http://jan.kneschke.de/projects/lighttpd/download
\r
47023 -------------------------------------
\r
47025 -Build instructions:
\r
47026 - unpack lighttpd-@VERSION@-<REL>-src.tar.bz2
\r
47027 - if you use setup to install this src package, it will be
\r
47028 - unpacked under /usr/src automatically
\r
47030 - ./lighttpd-@VERSION@-<REL>.sh all
\r
47032 -This will create:
\r
47033 - /usr/src/lighttpd-@VERSION@-<REL>.tar.bz2
\r
47034 - /usr/src/lighttpd-@VERSION@-<REL>-src.tar.bz2
\r
47036 -Or use './lighttpd-@VERSION@-<REL>.sh prep' to get a patched source directory
\r
47038 --------------------------------------------
\r
47040 -Files included in the binary distribution:
\r
47042 - /etc/lighttpd/lighttpd.conf.default
\r
47043 - /usr/lib/cyglightcomp.dll
\r
47044 - /usr/lib/lighttpd/mod_access.dll
\r
47045 - /usr/lib/lighttpd/mod_accesslog.dll
\r
47046 - /usr/lib/lighttpd/mod_auth.dll
\r
47047 - /usr/lib/lighttpd/mod_cgi.dll
\r
47048 - /usr/lib/lighttpd/mod_compress.dll
\r
47049 - /usr/lib/lighttpd/mod_evhost.dll
\r
47050 - /usr/lib/lighttpd/mod_expire.dll
\r
47051 - /usr/lib/lighttpd/mod_fastcgi.dll
\r
47052 - /usr/lib/lighttpd/mod_httptls.dll
\r
47053 - /usr/lib/lighttpd/mod_maps.dll
\r
47054 - /usr/lib/lighttpd/mod_proxy.dll
\r
47055 - /usr/lib/lighttpd/mod_redirect.dll
\r
47056 - /usr/lib/lighttpd/mod_rewrite.dll
\r
47057 - /usr/lib/lighttpd/mod_rrdtool.dll
\r
47058 - /usr/lib/lighttpd/mod_secdownload.dll
\r
47059 - /usr/lib/lighttpd/mod_simple_vhost.dll
\r
47060 - /usr/lib/lighttpd/mod_ssi.dll
\r
47061 - /usr/lib/lighttpd/mod_status.dll
\r
47062 - /usr/lib/lighttpd/mod_usertrack.dll
\r
47063 - /usr/sbin/lighttpd.exe
\r
47064 - /usr/share/doc/Cygwin/lighttpd-1.3.0.README
\r
47065 - /usr/share/doc/lighttpd-1.3.0/accesslog.txt
\r
47066 - /usr/share/doc/lighttpd-1.3.0/authentification.txt
\r
47067 - /usr/share/doc/lighttpd-1.3.0/AUTHORS
\r
47068 - /usr/share/doc/lighttpd-1.3.0/cgi.txt
\r
47069 - /usr/share/doc/lighttpd-1.3.0/ChangeLog
\r
47070 - /usr/share/doc/lighttpd-1.3.0/compress.txt
\r
47071 - /usr/share/doc/lighttpd-1.3.0/configuration.txt
\r
47072 - /usr/share/doc/lighttpd-1.3.0/COPYING
\r
47073 - /usr/share/doc/lighttpd-1.3.0/fastcgi-state.txt
\r
47074 - /usr/share/doc/lighttpd-1.3.0/fastcgi.txt
\r
47075 - /usr/share/doc/lighttpd-1.3.0/features.txt
\r
47076 - /usr/share/doc/lighttpd-1.3.0/INSTALL
\r
47077 - /usr/share/doc/lighttpd-1.3.0/NEWS
\r
47078 - /usr/share/doc/lighttpd-1.3.0/performance.txt
\r
47079 - /usr/share/doc/lighttpd-1.3.0/plugins.txt
\r
47080 - /usr/share/doc/lighttpd-1.3.0/proxy.txt
\r
47081 - /usr/share/doc/lighttpd-1.3.0/README
\r
47082 - /usr/share/doc/lighttpd-1.3.0/redirect.txt
\r
47083 - /usr/share/doc/lighttpd-1.3.0/rewrite.txt
\r
47084 - /usr/share/doc/lighttpd-1.3.0/rrdtool.txt
\r
47085 - /usr/share/doc/lighttpd-1.3.0/secdownload.txt
\r
47086 - /usr/share/doc/lighttpd-1.3.0/security.txt
\r
47087 - /usr/share/doc/lighttpd-1.3.0/simple-vhost.txt
\r
47088 - /usr/share/doc/lighttpd-1.3.0/skeleton.txt
\r
47089 - /usr/share/doc/lighttpd-1.3.0/ssi.txt
\r
47090 - /usr/share/doc/lighttpd-1.3.0/state.txt
\r
47091 - /usr/share/man/man1/lighttpd.1.gz
\r
47093 -------------------
\r
47097 ----------- lighttpd-1.3.1-1 -----------
\r
47099 -Updated to 1.3.1
\r
47101 ----------- lighttpd-1.3.0-1 -----------
\r
47104 -Cygwin port maintained by: Jan Kneschke <jan@kneschke.de>
\r
47105 -Please address all questions to the Cygwin mailing list at <cygwin@cygwin.com>
\r
47108 +------------------------------------------
47109 +A fast, secure and flexible webserver
47111 +Runtime requirements:
47112 + cygwin-1.5.10 or newer
47113 + crypt-1.1 or newer
47114 + libbz2_1-1.0.2 or newer
47115 + libpcre0-4.5 or newer
47116 + openssl-0.9.7d or newer
47117 + zlib-1.2.1 or newer
47119 +Build requirements:
47120 + cygwin-1.5.10 or newer
47121 + gcc-3.3.1-3 or newer
47122 + binutils-20030901-1 or newer
47131 +Canonical homepage:
47132 + http://jan.kneschke.de/projects/lighttpd/
47134 +Canonical download:
47135 + http://jan.kneschke.de/projects/lighttpd/download
47137 +------------------------------------
47139 +Build instructions:
47140 + unpack lighttpd-@VERSION@-<REL>-src.tar.bz2
47141 + if you use setup to install this src package, it will be
47142 + unpacked under /usr/src automatically
47144 + ./lighttpd-@VERSION@-<REL>.sh all
47147 + /usr/src/lighttpd-@VERSION@-<REL>.tar.bz2
47148 + /usr/src/lighttpd-@VERSION@-<REL>-src.tar.bz2
47150 +Or use './lighttpd-@VERSION@-<REL>.sh prep' to get a patched source directory
47152 +-------------------------------------------
47154 +Files included in the binary distribution:
47156 + /etc/lighttpd/lighttpd.conf.default
47157 + /usr/lib/cyglightcomp.dll
47158 + /usr/lib/lighttpd/mod_access.dll
47159 + /usr/lib/lighttpd/mod_accesslog.dll
47160 + /usr/lib/lighttpd/mod_auth.dll
47161 + /usr/lib/lighttpd/mod_cgi.dll
47162 + /usr/lib/lighttpd/mod_compress.dll
47163 + /usr/lib/lighttpd/mod_evhost.dll
47164 + /usr/lib/lighttpd/mod_expire.dll
47165 + /usr/lib/lighttpd/mod_fastcgi.dll
47166 + /usr/lib/lighttpd/mod_httptls.dll
47167 + /usr/lib/lighttpd/mod_maps.dll
47168 + /usr/lib/lighttpd/mod_proxy.dll
47169 + /usr/lib/lighttpd/mod_redirect.dll
47170 + /usr/lib/lighttpd/mod_rewrite.dll
47171 + /usr/lib/lighttpd/mod_rrdtool.dll
47172 + /usr/lib/lighttpd/mod_secdownload.dll
47173 + /usr/lib/lighttpd/mod_simple_vhost.dll
47174 + /usr/lib/lighttpd/mod_ssi.dll
47175 + /usr/lib/lighttpd/mod_status.dll
47176 + /usr/lib/lighttpd/mod_usertrack.dll
47177 + /usr/sbin/lighttpd.exe
47178 + /usr/share/doc/Cygwin/lighttpd-1.3.0.README
47179 + /usr/share/doc/lighttpd-1.3.0/accesslog.txt
47180 + /usr/share/doc/lighttpd-1.3.0/authentification.txt
47181 + /usr/share/doc/lighttpd-1.3.0/AUTHORS
47182 + /usr/share/doc/lighttpd-1.3.0/cgi.txt
47183 + /usr/share/doc/lighttpd-1.3.0/ChangeLog
47184 + /usr/share/doc/lighttpd-1.3.0/compress.txt
47185 + /usr/share/doc/lighttpd-1.3.0/configuration.txt
47186 + /usr/share/doc/lighttpd-1.3.0/COPYING
47187 + /usr/share/doc/lighttpd-1.3.0/fastcgi-state.txt
47188 + /usr/share/doc/lighttpd-1.3.0/fastcgi.txt
47189 + /usr/share/doc/lighttpd-1.3.0/features.txt
47190 + /usr/share/doc/lighttpd-1.3.0/INSTALL
47191 + /usr/share/doc/lighttpd-1.3.0/NEWS
47192 + /usr/share/doc/lighttpd-1.3.0/performance.txt
47193 + /usr/share/doc/lighttpd-1.3.0/plugins.txt
47194 + /usr/share/doc/lighttpd-1.3.0/proxy.txt
47195 + /usr/share/doc/lighttpd-1.3.0/README
47196 + /usr/share/doc/lighttpd-1.3.0/redirect.txt
47197 + /usr/share/doc/lighttpd-1.3.0/rewrite.txt
47198 + /usr/share/doc/lighttpd-1.3.0/rrdtool.txt
47199 + /usr/share/doc/lighttpd-1.3.0/secdownload.txt
47200 + /usr/share/doc/lighttpd-1.3.0/security.txt
47201 + /usr/share/doc/lighttpd-1.3.0/simple-vhost.txt
47202 + /usr/share/doc/lighttpd-1.3.0/skeleton.txt
47203 + /usr/share/doc/lighttpd-1.3.0/ssi.txt
47204 + /usr/share/doc/lighttpd-1.3.0/state.txt
47205 + /usr/share/man/man1/lighttpd.1.gz
47207 +------------------
47211 +---------- lighttpd-1.3.1-1 -----------
47215 +---------- lighttpd-1.3.0-1 -----------
47218 +Cygwin port maintained by: Jan Kneschke <jan@kneschke.de>
47219 +Please address all questions to the Cygwin mailing list at <cygwin@cygwin.com>
47222 Property changes on: cygwin/lighttpd.README.in
47223 ___________________________________________________________________
47224 Name: svn:eol-style
47228 Property changes on: cygwin/setup.hint
47229 ___________________________________________________________________
47230 Name: svn:eol-style
47234 Property changes on: cygwin/Makefile.am
47235 ___________________________________________________________________
47236 Name: svn:eol-style
47240 Property changes on: cygwin/.cvsignore
47241 ___________________________________________________________________
47242 Name: svn:eol-style
47246 Property changes on: tests/mod-auth.t
47247 ___________________________________________________________________
47248 Name: svn:eol-style
47252 Property changes on: tests/mod-access.t
47253 ___________________________________________________________________
47254 Name: svn:eol-style
47257 Index: tests/bug-12.conf
47258 ===================================================================
47259 --- tests/bug-12.conf (.../tags/lighttpd-1.4.11) (revision 1159)
47260 +++ tests/bug-12.conf (.../branches/lighttpd-merge-1.4.x) (revision 1159)
47262 -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47263 -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
47264 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47265 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
47267 ## bind to port (default: 80)
47271 ## bind to localhost (default: all interfaces)
47272 server.bind = "localhost"
47273 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
47274 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
47275 server.name = "www.example.org"
47276 server.tag = "Apache 1.3.29"
47279 ######################## MODULE CONFIG ############################
47282 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
47283 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
47285 mimetype.assign = ( ".png" => "image/png",
47286 ".jpg" => "image/jpeg",
47288 ".c" => "text/plain",
47289 ".conf" => "text/plain" )
47291 -compress.cache-dir = "@SRCDIR@/tmp/lighttpd/cache/compress/"
47292 +compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
47293 compress.filetype = ("text/plain", "text/html")
47295 setenv.add-environment = ( "TRAC_ENV" => "foo")
47297 "host" => "127.0.0.1",
47299 # "mode" => "authorizer",
47300 -# "docroot" => "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/",
47301 +# "docroot" => env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/",
47305 @@ -108,7 +108,7 @@
47306 ssl.pemfile = "server.pem"
47308 auth.backend = "plain"
47309 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
47310 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
47311 auth.backend.plain.groupfile = "lighttpd.group"
47313 auth.backend.ldap.hostname = "localhost"
47314 @@ -151,15 +151,15 @@
47315 status.config-url = "/server-config"
47317 simple-vhost.document-root = "pages"
47318 -simple-vhost.server-root = "@SRCDIR@/tmp/lighttpd/servers/"
47319 +simple-vhost.server-root = env.SRCDIR + "/tmp/lighttpd/servers/"
47320 simple-vhost.default-host = "www.example.org"
47322 $HTTP["host"] == "vvv.example.org" {
47323 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47324 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47327 $HTTP["host"] == "zzz.example.org" {
47328 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47329 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47330 server.name = "zzz.example.org"
47334 Property changes on: tests/bug-12.conf
47335 ___________________________________________________________________
47336 Name: svn:eol-style
47340 Property changes on: tests/mod-secdownload.t
47341 ___________________________________________________________________
47342 Name: svn:eol-style
47345 Index: tests/fastcgi-10.conf
47346 ===================================================================
47347 --- tests/fastcgi-10.conf (.../tags/lighttpd-1.4.11) (revision 1159)
47348 +++ tests/fastcgi-10.conf (.../branches/lighttpd-merge-1.4.x) (revision 1159)
47350 -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47351 -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
47352 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47353 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
47355 ## bind to port (default: 80)
47358 ## bind to localhost (default: all interfaces)
47359 server.bind = "localhost"
47360 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
47361 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
47362 server.name = "www.example.org"
47363 server.tag = "Apache 1.3.29"
47366 ######################## MODULE CONFIG ############################
47369 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
47370 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
47372 mimetype.assign = ( ".png" => "image/png",
47373 ".jpg" => "image/jpeg",
47375 ".c" => "text/plain",
47376 ".conf" => "text/plain" )
47378 -compress.cache-dir = "@SRCDIR@/tmp/lighttpd/cache/compress/"
47379 +compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
47380 compress.filetype = ("text/plain", "text/html")
47384 ssl.pemfile = "server.pem"
47386 auth.backend = "plain"
47387 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
47388 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
47389 auth.backend.plain.groupfile = "lighttpd.group"
47391 auth.backend.ldap.hostname = "localhost"
47392 @@ -128,11 +128,11 @@
47393 status.config-url = "/server-config"
47395 $HTTP["host"] == "vvv.example.org" {
47396 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47397 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47400 $HTTP["host"] == "zzz.example.org" {
47401 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47402 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47403 server.name = "zzz.example.org"
47407 Property changes on: tests/fastcgi-10.conf
47408 ___________________________________________________________________
47409 Name: svn:eol-style
47412 Index: tests/bug-06.conf
47413 ===================================================================
47414 --- tests/bug-06.conf (.../tags/lighttpd-1.4.11) (revision 1159)
47415 +++ tests/bug-06.conf (.../branches/lighttpd-merge-1.4.x) (revision 1159)
47417 -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47418 -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
47419 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47420 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
47422 ## bind to port (default: 80)
47426 ## bind to localhost (default: all interfaces)
47427 server.bind = "localhost"
47428 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
47429 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
47430 server.name = "www.example.org"
47431 server.tag = "Apache 1.3.29"
47434 ######################## MODULE CONFIG ############################
47437 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
47438 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
47440 mimetype.assign = ( ".png" => "image/png",
47441 ".jpg" => "image/jpeg",
47443 ".c" => "text/plain",
47444 ".conf" => "text/plain" )
47446 -compress.cache-dir = "@SRCDIR@/tmp/lighttpd/cache/compress/"
47447 +compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
47448 compress.filetype = ("text/plain", "text/html")
47450 setenv.add-environment = ( "TRAC_ENV" => "foo")
47452 "host" => "127.0.0.1",
47454 # "mode" => "authorizer",
47455 -# "docroot" => "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/",
47456 +# "docroot" => env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/",
47460 @@ -106,7 +106,7 @@
47461 ssl.pemfile = "server.pem"
47463 auth.backend = "plain"
47464 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
47465 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
47466 auth.backend.plain.groupfile = "lighttpd.group"
47468 auth.backend.ldap.hostname = "localhost"
47469 @@ -149,15 +149,15 @@
47470 status.config-url = "/server-config"
47472 simple-vhost.document-root = "pages"
47473 -simple-vhost.server-root = "@SRCDIR@/tmp/lighttpd/servers/"
47474 +simple-vhost.server-root = env.SRCDIR + "/tmp/lighttpd/servers/"
47475 simple-vhost.default-host = "www.example.org"
47477 $HTTP["host"] == "vvv.example.org" {
47478 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47479 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47482 $HTTP["host"] == "zzz.example.org" {
47483 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47484 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47485 server.name = "zzz.example.org"
47489 Property changes on: tests/bug-06.conf
47490 ___________________________________________________________________
47491 Name: svn:eol-style
47495 Property changes on: tests/core-response.t
47496 ___________________________________________________________________
47497 Name: svn:eol-style
47500 Index: tests/proxy-backend-2.conf
47501 ===================================================================
47502 --- tests/proxy-backend-2.conf (.../tags/lighttpd-1.4.11) (revision 0)
47503 +++ tests/proxy-backend-2.conf (.../branches/lighttpd-merge-1.4.x) (revision 1159)
47505 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47506 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd-backend-2.pid"
47508 +include "default.conf"
47511 +server.tag = "proxy-backend-2"
47513 Property changes on: tests/proxy-backend-2.conf
47514 ___________________________________________________________________
47515 Name: svn:eol-style
47519 Property changes on: tests/request.t
47520 ___________________________________________________________________
47521 Name: svn:eol-style
47525 Property changes on: tests/mod-userdir.t
47526 ___________________________________________________________________
47527 Name: svn:eol-style
47530 Index: tests/core-keepalive.t
47531 ===================================================================
47532 --- tests/core-keepalive.t (.../tags/lighttpd-1.4.11) (revision 1159)
47533 +++ tests/core-keepalive.t (.../branches/lighttpd-merge-1.4.x) (revision 1159)
47536 GET /12345.txt HTTP/1.0
47537 Host: 123.example.org
47538 -Connection: keep-alive
47542 $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } , { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
47544 Property changes on: tests/core-keepalive.t
47545 ___________________________________________________________________
47546 Name: svn:eol-style
47549 Index: tests/var-include.conf
47550 ===================================================================
47551 --- tests/var-include.conf (.../tags/lighttpd-1.4.11) (revision 1159)
47552 +++ tests/var-include.conf (.../branches/lighttpd-merge-1.4.x) (revision 1159)
47554 debug.log-request-handling = "enable"
47555 debug.log-condition-handling = "enable"
47557 -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47558 -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
47559 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47560 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
47562 ## bind to port (default: 80)
47565 ## bind to localhost (default: all interfaces)
47566 server.bind = "localhost"
47567 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
47568 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
47569 server.name = "www.example.org"
47570 server.tag = "Apache 1.3.29"
47572 @@ -21,19 +21,19 @@
47573 ######################## MODULE CONFIG ############################
47576 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
47577 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
47579 mimetype.assign = ( ".html" => "text/html" )
47581 url.redirect = ("^" => "/default")
47583 $HTTP["host"] == "www.example.org" {
47584 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47585 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47586 server.name = "www.example.org"
47587 url.redirect = ("^" => "/redirect")
47589 $HTTP["host"] == "test.example.org" {
47590 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47591 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47592 server.name = "test.example.org"
47596 Property changes on: tests/var-include.conf
47597 ___________________________________________________________________
47598 Name: svn:eol-style
47602 Property changes on: tests/cleanup.sh
47603 ___________________________________________________________________
47604 Name: svn:eol-style
47607 Index: tests/mod-proxy.t
47608 ===================================================================
47609 --- tests/mod-proxy.t (.../tags/lighttpd-1.4.11) (revision 1159)
47610 +++ tests/mod-proxy.t (.../branches/lighttpd-merge-1.4.x) (revision 1159)
47615 -use Test::More tests => 6;
47616 +use Test::More tests => 21;
47619 -my $tf_real = LightyTest->new();
47620 my $tf_proxy = LightyTest->new();
47621 +my $tf_backend1 = LightyTest->new();
47622 +my $tf_backend2 = LightyTest->new();
47626 @@ -20,18 +21,25 @@
47627 ## 1. the real webserver
47628 ## 2. the proxy server
47630 -$tf_real->{PORT} = 2048;
47631 -$tf_real->{CONFIGFILE} = 'lighttpd.conf';
47632 -$tf_real->{LIGHTTPD_PIDFILE} = $tf_real->{SRCDIR}.'/tmp/lighttpd/lighttpd.pid';
47634 -$tf_proxy->{PORT} = 2050;
47635 +$tf_proxy->{PORT} = 2048;
47636 $tf_proxy->{CONFIGFILE} = 'proxy.conf';
47637 $tf_proxy->{LIGHTTPD_PIDFILE} = $tf_proxy->{SRCDIR}.'/tmp/lighttpd/lighttpd-proxy.pid';
47639 -ok($tf_real->start_proc == 0, "Starting lighttpd") or die();
47640 +$tf_backend1->{PORT} = 2050;
47641 +$tf_backend1->{CONFIGFILE} = 'proxy-backend-1.conf';
47642 +$tf_backend1->{LIGHTTPD_PIDFILE} = $tf_backend1->{SRCDIR}.'/tmp/lighttpd/lighttpd-backend-1.pid';
47644 +$tf_backend2->{PORT} = 2051;
47645 +$tf_backend2->{CONFIGFILE} = 'proxy-backend-2.conf';
47646 +$tf_backend2->{LIGHTTPD_PIDFILE} = $tf_backend2->{SRCDIR}.'/tmp/lighttpd/lighttpd-backend-2.pid';
47649 +ok($tf_backend1->start_proc == 0, "Starting lighttpd") or die();
47651 ok($tf_proxy->start_proc == 0, "Starting lighttpd as proxy") or die();
47655 $t->{REQUEST} = ( <<EOF
47656 GET /index.html HTTP/1.0
47657 Host: www.example.org
47658 @@ -45,9 +53,121 @@
47659 Host: www.example.org
47662 -$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'Server' => 'Apache 1.3.29' } ];
47663 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'Server' => 'proxy-backend-1' } ];
47664 ok($tf_proxy->handle_http($t) == 0, 'drop Server from real server');
47666 +$t->{REQUEST} = ( <<EOF
47667 +GET /balance-rr/foo HTTP/1.0
47668 +Host: www.example.org
47671 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
47672 +ok($tf_proxy->handle_http($t) == 0, 'balance rr - one backend');
47674 +$t->{REQUEST} = ( <<EOF
47675 +GET /balance-rr/foo HTTP/1.0
47676 +Host: www.example.org
47679 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
47680 +ok($tf_proxy->handle_http($t) == 0, 'balance rr - one host down, failover');
47682 +$t->{REQUEST} = ( <<EOF
47683 +GET /balance-fair/foo HTTP/1.0
47684 +Host: www.example.org
47687 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
47688 +ok($tf_proxy->handle_http($t) == 0, 'balance fair - one backend');
47690 +## backend 2 starting
47691 +ok($tf_backend2->start_proc == 0, "Starting second proxy backend") or die();
47693 +$t->{REQUEST} = ( <<EOF
47694 +GET /balance-rr/foo HTTP/1.0
47695 +Host: www.example.org
47698 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
47699 +ok($tf_proxy->handle_http($t) == 0, 'balance rr - lb, backend 1');
47701 +$t->{REQUEST} = ( <<EOF
47702 +GET /balance-rr/foo HTTP/1.0
47703 +Host: www.example.org
47706 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
47707 +ok($tf_proxy->handle_http($t) == 0, 'balance rr - lb, backend 2');
47709 +$t->{REQUEST} = ( <<EOF
47710 +GET /balance-hash/foo HTTP/1.0
47711 +Host: www.example.org
47714 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
47715 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 1');
47717 +$t->{REQUEST} = ( <<EOF
47718 +GET /balance-hash/foo HTTP/1.0
47719 +Host: www.example.org
47722 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-1' } ];
47723 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 1 - same URL');
47725 +$t->{REQUEST} = ( <<EOF
47726 +GET /balance-hash/bar HTTP/1.0
47727 +Host: www.example.org
47730 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
47731 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 2');
47733 +$t->{REQUEST} = ( <<EOF
47734 +GET /balance-hash/bar HTTP/1.0
47735 +Host: www.example.org
47738 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
47739 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - lb, backend 2 - same URL');
47741 +## backend 1 stopping, failover
47742 +ok($tf_backend1->stop_proc == 0, "Stopping backend 1");
47744 +$t->{REQUEST} = ( <<EOF
47745 +GET /balance-hash/foo HTTP/1.0
47746 +Host: www.example.org
47749 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
47750 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - failover to backend 2');
47752 +$t->{REQUEST} = ( <<EOF
47753 +GET /balance-hash/bar HTTP/1.0
47754 +Host: www.example.org
47757 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
47758 +ok($tf_proxy->handle_http($t) == 0, 'balance hash - failover to backend 2 - same URL');
47760 +$t->{REQUEST} = ( <<EOF
47761 +GET /balance-rr/foo HTTP/1.0
47762 +Host: www.example.org
47765 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
47766 +ok($tf_proxy->handle_http($t) == 0, 'balance rr - failover to backend 2');
47768 +$t->{REQUEST} = ( <<EOF
47769 +GET /balance-fair/foo HTTP/1.0
47770 +Host: www.example.org
47773 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404, 'Server' => 'proxy-backend-2' } ];
47774 +ok($tf_proxy->handle_http($t) == 0, 'balance fair - failover to backend 2');
47777 +ok($tf_backend2->stop_proc == 0, "Stopping lighttpd");
47779 ok($tf_proxy->stop_proc == 0, "Stopping lighttpd proxy");
47781 -ok($tf_real->stop_proc == 0, "Stopping lighttpd");
47783 Property changes on: tests/mod-proxy.t
47784 ___________________________________________________________________
47785 Name: svn:eol-style
47789 Property changes on: tests/core-var-include.t
47790 ___________________________________________________________________
47791 Name: svn:eol-style
47794 Index: tests/lowercase.conf
47795 ===================================================================
47796 --- tests/lowercase.conf (.../tags/lighttpd-1.4.11) (revision 1159)
47797 +++ tests/lowercase.conf (.../branches/lighttpd-merge-1.4.x) (revision 1159)
47799 -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47800 -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
47801 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47802 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
47804 ## bind to port (default: 80)
47807 ## bind to localhost (default: all interfaces)
47808 server.bind = "localhost"
47809 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
47810 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
47812 server.force-lowercase-filenames = "enable"
47815 ".py" => "/usr/bin/python" )
47817 auth.backend = "plain"
47818 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
47819 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
47821 -auth.backend.htpasswd.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.htpasswd"
47822 +auth.backend.htpasswd.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.htpasswd"
47824 $HTTP["host"] == "lowercase-auth" {
47825 auth.require = ( "/image.jpg" =>
47827 Property changes on: tests/lowercase.conf
47828 ___________________________________________________________________
47829 Name: svn:eol-style
47832 Index: tests/condition.conf
47833 ===================================================================
47834 --- tests/condition.conf (.../tags/lighttpd-1.4.11) (revision 1159)
47835 +++ tests/condition.conf (.../branches/lighttpd-merge-1.4.x) (revision 1159)
47837 debug.log-request-handling = "enable"
47838 debug.log-condition-handling = "enable"
47840 -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47841 -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
47842 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47843 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
47845 ## bind to port (default: 80)
47848 ## bind to localhost (default: all interfaces)
47849 server.bind = "localhost"
47850 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
47851 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
47852 server.name = "www.example.org"
47853 server.tag = "Apache 1.3.29"
47855 @@ -22,25 +22,25 @@
47856 ######################## MODULE CONFIG ############################
47859 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
47860 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
47862 mimetype.assign = ( ".html" => "text/html" )
47864 url.redirect = ("^" => "/default")
47866 $HTTP["host"] == "www.example.org" {
47867 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47868 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47869 server.name = "www.example.org"
47870 url.redirect = ("^" => "/match_1")
47872 else $HTTP["host"] == "test1.example.org" {
47873 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47874 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47875 server.name = "test1.example.org"
47876 url.redirect = ("^" => "/match_2")
47879 else $HTTP["host"] == "test2.example.org" {
47880 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47881 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47882 server.name = "test2.example.org"
47883 url.redirect = ("^" => "/match_3")
47888 else $HTTP["host"] == "test3.example.org" {
47889 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
47890 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
47891 server.name = "test3.example.org"
47892 url.redirect = ("^" => "/match_4")
47895 Property changes on: tests/condition.conf
47896 ___________________________________________________________________
47897 Name: svn:eol-style
47901 Property changes on: tests/lighttpd.htpasswd
47902 ___________________________________________________________________
47903 Name: svn:eol-style
47907 Property changes on: tests/.cvsignore
47908 ___________________________________________________________________
47909 Name: svn:eol-style
47913 Property changes on: tests/core-request.t
47914 ___________________________________________________________________
47915 Name: svn:eol-style
47919 Property changes on: tests/mod-redirect.t
47920 ___________________________________________________________________
47921 Name: svn:eol-style
47925 Property changes on: tests/mod-cgi.t
47926 ___________________________________________________________________
47927 Name: svn:eol-style
47931 Property changes on: tests/mod-setenv.t
47932 ___________________________________________________________________
47933 Name: svn:eol-style
47936 Index: tests/cachable.t
47937 ===================================================================
47938 --- tests/cachable.t (.../tags/lighttpd-1.4.11) (revision 0)
47939 +++ tests/cachable.t (.../branches/lighttpd-merge-1.4.x) (revision 1159)
47941 +#!/usr/bin/env perl
47943 + # add current source dir to the include-path
47944 + # we need this for make distcheck
47945 + (my $srcdir = $0) =~ s#/[^/]+$#/#;
47946 + unshift @INC, $srcdir;
47951 +use Test::More tests => 12;
47954 +my $tf = LightyTest->new();
47957 +$tf->{CONFIGFILE} = 'lighttpd.conf';
47959 +ok($tf->start_proc == 0, "Starting lighttpd") or die();
47961 +## check if If-Modified-Since, If-None-Match works
47963 +$t->{REQUEST} = ( <<EOF
47965 +If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT
47968 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
47969 +ok($tf->handle_http($t) == 0, 'Conditional GET - old If-Modified-Since');
47971 +$t->{REQUEST} = ( <<EOF
47973 +If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT; foo
47976 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
47977 +ok($tf->handle_http($t) == 0, 'Conditional GET - old If-Modified-Since, comment');
47979 +my $now = $t->{date};
47981 +$t->{REQUEST} = ( <<EOF
47983 +If-Modified-Since: $now
47986 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
47987 +ok($tf->handle_http($t) == 0, 'Conditional GET - new If-Modified-Since');
47989 +$t->{REQUEST} = ( <<EOF
47991 +If-Modified-Since: $now; foo
47994 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
47995 +ok($tf->handle_http($t) == 0, 'Conditional GET - new If-Modified-Since, comment');
47997 +$t->{REQUEST} = ( <<EOF
47999 +If-None-Match: foo
48002 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
48003 +ok($tf->handle_http($t) == 0, 'Conditional GET - old If-None-Match');
48005 +my $etag = $t->{etag};
48007 +$t->{REQUEST} = ( <<EOF
48009 +If-None-Match: $etag
48012 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
48013 +ok($tf->handle_http($t) == 0, 'Conditional GET - old If-None-Match');
48015 +$t->{REQUEST} = ( <<EOF
48017 +If-None-Match: $etag
48018 +If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT; foo
48021 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
48022 +ok($tf->handle_http($t) == 0, 'Conditional GET - ETag + old Last-Modified');
48024 +$t->{REQUEST} = ( <<EOF
48026 +If-None-Match: $etag
48027 +If-Modified-Since: $now; foo
48030 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
48031 +ok($tf->handle_http($t) == 0, 'Conditional GET - ETag, Last-Modified + comment');
48033 +$t->{REQUEST} = ( <<EOF
48035 +If-None-Match: Foo
48036 +If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT; foo
48039 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
48040 +ok($tf->handle_http($t) == 0, 'Conditional GET - old ETAG + old Last-Modified');
48042 +$t->{REQUEST} = ( <<EOF
48044 +If-None-Match: $etag
48045 +If-Modified-Since: $now foo
48048 +$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 412 } ];
48049 +ok($tf->handle_http($t) == 0, 'Conditional GET - ETag + Last-Modified + overlong timestamp');
48051 +ok($tf->stop_proc == 0, "Stopping lighttpd");
48054 Property changes on: tests/cachable.t
48055 ___________________________________________________________________
48056 Name: svn:executable
48058 Name: svn:eol-style
48062 Property changes on: tests/var-include-sub.conf
48063 ___________________________________________________________________
48064 Name: svn:eol-style
48067 Index: tests/fastcgi-13.conf
48068 ===================================================================
48069 --- tests/fastcgi-13.conf (.../tags/lighttpd-1.4.11) (revision 1159)
48070 +++ tests/fastcgi-13.conf (.../branches/lighttpd-merge-1.4.x) (revision 1159)
48072 -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48073 -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
48074 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48075 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48077 debug.log-request-header = "enable"
48078 debug.log-response-header = "enable"
48081 ## bind to localhost (default: all interfaces)
48082 server.bind = "localhost"
48083 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48084 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48085 server.name = "www.example.org"
48086 server.tag = "Apache 1.3.29"
48089 ######################## MODULE CONFIG ############################
48092 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48093 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
48095 mimetype.assign = ( ".png" => "image/png",
48096 ".jpg" => "image/jpeg",
48098 ".c" => "text/plain",
48099 ".conf" => "text/plain" )
48101 -compress.cache-dir = "@SRCDIR@/tmp/lighttpd/cache/compress/"
48102 +compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
48103 compress.filetype = ("text/plain", "text/html")
48106 @@ -102,7 +102,7 @@
48107 ssl.pemfile = "server.pem"
48109 auth.backend = "plain"
48110 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
48111 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
48112 auth.backend.plain.groupfile = "lighttpd.group"
48114 auth.backend.ldap.hostname = "localhost"
48115 @@ -145,11 +145,11 @@
48116 status.config-url = "/server-config"
48118 $HTTP["host"] == "vvv.example.org" {
48119 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48120 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48123 $HTTP["host"] == "zzz.example.org" {
48124 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48125 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48126 server.name = "zzz.example.org"
48130 Property changes on: tests/fastcgi-13.conf
48131 ___________________________________________________________________
48132 Name: svn:eol-style
48136 Property changes on: tests/lowercase.t
48137 ___________________________________________________________________
48138 Name: svn:eol-style
48142 Property changes on: tests/SConscript
48143 ___________________________________________________________________
48144 Name: svn:eol-style
48147 Index: tests/fcgi-responder.c
48148 ===================================================================
48149 --- tests/fcgi-responder.c (.../tags/lighttpd-1.4.11) (revision 1159)
48150 +++ tests/fcgi-responder.c (.../branches/lighttpd-merge-1.4.x) (revision 1159)
48153 int num_requests = 2;
48155 - while (num_requests > 0 &&
48156 - FCGI_Accept() >= 0) {
48159 - if (NULL != (p = getenv("QUERY_STRING"))) {
48160 + while (num_requests > 0 && FCGI_Accept() >= 0) {
48162 + char* doc_root = NULL;
48163 + char fname[4096];
48164 + char* pfname = (char *)fname;
48166 + doc_root = getenv("DOCUMENT_ROOT");
48167 + p = getenv("QUERY_STRING");
48169 + if (NULL != p && NULL != doc_root) {
48170 + snprintf(pfname, sizeof(fname), "%s/phpinfo.php", doc_root);
48171 if (0 == strcmp(p, "lf")) {
48172 printf("Status: 200 OK\n\n");
48173 } else if (0 == strcmp(p, "crlf")) {
48175 printf("Status: 200 OK\r\n");
48178 + } else if (0 == strcmp(p,"x-lighttpd-send-file")) {
48179 + printf("Status: 200 OK\r\n");
48180 + printf("X-LIGHTTPD-send-file: %s\r\n", pfname);
48182 + } else if (0 == strcmp(p,"xsendfile")) {
48183 + printf("Status: 200 OK\r\n");
48184 + printf("X-Sendfile: %s\r\n", pfname);
48186 + } else if (0 == strcmp(p,"xsendfile-mixed-case")) {
48187 + printf("Status: 200 OK\r\n");
48188 + printf("X-SeNdFiLe: %s\r\n", pfname);
48190 } else if (0 == strcmp(p, "die-at-end")) {
48191 printf("Status: 200 OK\r\n\r\n");
48194 Property changes on: tests/fcgi-responder.c
48195 ___________________________________________________________________
48196 Name: svn:eol-style
48200 Property changes on: tests/fcgi-auth.c
48201 ___________________________________________________________________
48202 Name: svn:eol-style
48205 Index: tests/proxy-backend-1.conf
48206 ===================================================================
48207 --- tests/proxy-backend-1.conf (.../tags/lighttpd-1.4.11) (revision 0)
48208 +++ tests/proxy-backend-1.conf (.../branches/lighttpd-merge-1.4.x) (revision 1159)
48210 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48211 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd-backend-1.pid"
48213 +include "default.conf"
48216 +server.tag = "proxy-backend-1"
48218 Property changes on: tests/proxy-backend-1.conf
48219 ___________________________________________________________________
48220 Name: svn:eol-style
48224 Property changes on: tests/wrapper.sh
48225 ___________________________________________________________________
48226 Name: svn:eol-style
48230 Property changes on: tests/core.t
48231 ___________________________________________________________________
48232 Name: svn:eol-style
48236 Property changes on: tests/lighttpd.user
48237 ___________________________________________________________________
48238 Name: svn:eol-style
48241 Index: tests/mod-fastcgi.t
48242 ===================================================================
48243 --- tests/mod-fastcgi.t (.../tags/lighttpd-1.4.11) (revision 1159)
48244 +++ tests/mod-fastcgi.t (.../branches/lighttpd-merge-1.4.x) (revision 1159)
48249 -use Test::More tests => 47;
48250 +use Test::More tests => 49;
48253 my $tf = LightyTest->new();
48258 - skip "no PHP running on port 1026", 30 unless $tf->listening_on(1026);
48259 + skip "no PHP running on port 1026", 29 unless $tf->listening_on(1026);
48261 ok($tf->start_proc == 0, "Starting lighttpd") or die();
48263 @@ -223,7 +223,7 @@
48267 - skip "no php found", 4 unless -x "/home/jan/Documents/php-5.1.0/sapi/cgi/php";
48268 + skip "no php found", 4 unless -x "/home/jan/Documents/php-5.1.0/sapi/cgi/php";
48269 $tf->{CONFIGFILE} = 'fastcgi-13.conf';
48270 ok($tf->start_proc == 0, "Starting lighttpd with $tf->{CONFIGFILE}") or die();
48271 $t->{REQUEST} = ( <<EOF
48272 @@ -285,7 +285,35 @@
48273 $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => 'test123' } ];
48274 ok($tf->handle_http($t) == 0, 'line-ending \r\n + \r\n');
48276 + # X-LIGHTTPD-send-file
48277 $t->{REQUEST} = ( <<EOF
48278 +GET /index.fcgi?x-lighttpd-send-file HTTP/1.0
48279 +Host: www.example.org
48282 + $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '<?php phpinfo(); ?>
48284 + ok($tf->handle_http($t) == 0, 'X-LIGHTTPD-send-file');
48286 + $t->{REQUEST} = ( <<EOF
48287 +GET /index.fcgi?xsendfile HTTP/1.0
48288 +Host: www.example.org
48291 + $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '<?php phpinfo(); ?>
48293 + ok($tf->handle_http($t) == 0, 'X-Sendfile');
48295 + $t->{REQUEST} = ( <<EOF
48296 +GET /index.fcgi?xsendfile-mixed-case HTTP/1.0
48297 +Host: www.example.org
48300 + $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '<?php phpinfo(); ?>
48302 + ok($tf->handle_http($t) == 0, 'X-SeNdFiLe in mixed case');
48304 + $t->{REQUEST} = ( <<EOF
48305 GET /index.fcgi?die-at-end HTTP/1.0
48306 Host: www.example.org
48309 Property changes on: tests/mod-fastcgi.t
48310 ___________________________________________________________________
48311 Name: svn:eol-style
48315 Property changes on: tests/mod-rewrite.t
48316 ___________________________________________________________________
48317 Name: svn:eol-style
48320 Index: tests/lighttpd.conf
48321 ===================================================================
48322 --- tests/lighttpd.conf (.../tags/lighttpd-1.4.11) (revision 1159)
48323 +++ tests/lighttpd.conf (.../branches/lighttpd-merge-1.4.x) (revision 1159)
48325 -debug.log-request-handling = "enable"
48326 -debug.log-condition-handling = "enable"
48327 -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48328 -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
48329 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48330 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48331 +server.tag = "Apache 1.3.29"
48333 ## 64 Mbyte ... nice limit
48334 server.max-request-size = 65000
48336 -## bind to port (default: 80)
48337 -server.port = 2048
48338 +include "default.conf"
48340 -## bind to localhost (default: all interfaces)
48341 -server.bind = "localhost"
48342 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48343 -server.name = "www.example.org"
48344 -server.tag = "Apache 1.3.29"
48345 +setenv.add-request-header = ( "FOO" => "foo")
48346 +setenv.add-response-header = ( "BAR" => "foo")
48348 -server.dir-listing = "enable"
48350 -#server.event-handler = "linux-sysepoll"
48351 -#server.event-handler = "linux-rtsig"
48353 -#server.modules.path = ""
48354 -server.modules = (
48357 - "mod_secdownload",
48363 - "mod_simple_vhost",
48366 -# "mod_localizer",
48372 - "mod_accesslog" )
48374 -server.indexfiles = ( "index.php", "index.html",
48375 - "index.htm", "default.htm" )
48378 -######################## MODULE CONFIG ############################
48380 -ssi.extension = ( ".shtml" )
48382 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48384 -mimetype.assign = ( ".png" => "image/png",
48385 - ".jpg" => "image/jpeg",
48386 - ".jpeg" => "image/jpeg",
48387 - ".gif" => "image/gif",
48388 - ".html" => "text/html",
48389 - ".htm" => "text/html",
48390 - ".pdf" => "application/pdf",
48391 - ".swf" => "application/x-shockwave-flash",
48392 - ".spl" => "application/futuresplash",
48393 - ".txt" => "text/plain",
48394 - ".tar.gz" => "application/x-tgz",
48395 - ".tgz" => "application/x-tgz",
48396 - ".gz" => "application/x-gzip",
48397 - ".c" => "text/plain",
48398 - ".conf" => "text/plain" )
48400 $HTTP["host"] == "cache.example.org" {
48401 - compress.cache-dir = "@SRCDIR@/tmp/lighttpd/cache/compress/"
48402 + compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
48404 -compress.filetype = ("text/plain", "text/html")
48406 -setenv.add-environment = ( "TRAC_ENV" => "tracenv", "SETENV" => "setenv")
48407 -setenv.add-request-header = ( "FOO" => "foo")
48408 -setenv.add-response-header = ( "BAR" => "foo")
48410 $HTTP["url"] =~ "\.pdf$" {
48411 server.range-requests = "disable"
48413 @@ -85,76 +23,31 @@
48414 "/prefix.fcgi" => ( ( "host" => "127.0.0.1", "port" => 1026, "check-local" => "disable", "broken-scriptfilename" => "enable" ) )
48418 -cgi.assign = ( ".pl" => "/usr/bin/perl",
48419 - ".cgi" => "/usr/bin/perl",
48420 - ".py" => "/usr/bin/python" )
48422 -userdir.include-user = ( "jan" )
48423 -userdir.path = "/"
48425 -ssl.engine = "disable"
48426 -ssl.pemfile = "server.pem"
48428 $HTTP["host"] == "auth-htpasswd.example.org" {
48429 auth.backend = "htpasswd"
48432 -auth.backend = "plain"
48433 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
48435 -auth.backend.htpasswd.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.htpasswd"
48438 -auth.require = ( "/server-status" =>
48440 - "method" => "digest",
48441 - "realm" => "download archiv",
48442 - "require" => "group=www|user=jan|host=192.168.2.10"
48444 - "/server-config" =>
48446 - "method" => "basic",
48447 - "realm" => "download archiv",
48448 - "require" => "valid-user"
48452 -url.access-deny = ( "~", ".inc")
48454 -url.rewrite = ( "^/rewrite/foo($|\?.+)" => "/indexfile/rewrite.php$1",
48455 - "^/rewrite/bar(?:$|\?(.+))" => "/indexfile/rewrite.php?bar&$1" )
48457 -expire.url = ( "/expire/access" => "access 2 hours",
48458 - "/expire/modification" => "access plus 1 seconds 2 minutes")
48460 -#cache.cache-dir = "/home/weigon/wwwroot/cache/"
48462 -#### status module
48463 -status.status-url = "/server-status"
48464 -status.config-url = "/server-config"
48466 $HTTP["host"] == "vvv.example.org" {
48467 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48468 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48469 secdownload.secret = "verysecret"
48470 - secdownload.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48471 + secdownload.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48472 secdownload.uri-prefix = "/sec/"
48473 secdownload.timeout = 120
48476 $HTTP["host"] == "zzz.example.org" {
48477 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48478 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48479 server.name = "zzz.example.org"
48482 $HTTP["host"] == "no-simple.example.org" {
48483 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/123.example.org/pages/"
48484 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/123.example.org/pages/"
48485 server.name = "zzz.example.org"
48488 $HTTP["host"] !~ "(no-simple\.example\.org)" {
48489 simple-vhost.document-root = "pages"
48490 - simple-vhost.server-root = "@SRCDIR@/tmp/lighttpd/servers/"
48491 + simple-vhost.server-root = env.SRCDIR + "/tmp/lighttpd/servers/"
48492 simple-vhost.default-host = "www.example.org"
48496 Property changes on: tests/lighttpd.conf
48497 ___________________________________________________________________
48498 Name: svn:eol-style
48501 Index: tests/fastcgi-responder.conf
48502 ===================================================================
48503 --- tests/fastcgi-responder.conf (.../tags/lighttpd-1.4.11) (revision 1159)
48504 +++ tests/fastcgi-responder.conf (.../branches/lighttpd-merge-1.4.x) (revision 1159)
48506 -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48507 -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
48508 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48509 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48511 #debug.log-request-header = "enable"
48512 #debug.log-response-header = "enable"
48515 ## bind to localhost (default: all interfaces)
48516 server.bind = "localhost"
48517 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48518 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48519 server.name = "www.example.org"
48520 server.tag = "Apache 1.3.29"
48523 ######################## MODULE CONFIG ############################
48526 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48527 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
48529 mimetype.assign = ( ".png" => "image/png",
48530 ".jpg" => "image/jpeg",
48532 ".c" => "text/plain",
48533 ".conf" => "text/plain" )
48535 -compress.cache-dir = "@SRCDIR@/tmp/lighttpd/cache/compress/"
48536 +compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
48537 compress.filetype = ("text/plain", "text/html")
48540 @@ -90,10 +90,11 @@
48542 "host" => "127.0.0.1",
48544 - "bin-path" => "@SRCDIR@/fcgi-responder",
48545 + "bin-path" => env.SRCDIR + "/fcgi-responder",
48546 "check-local" => "disable",
48549 + "min-procs" => 1,
48550 + "allow-x-send-file" => "enable",
48554 @@ -109,7 +110,7 @@
48555 ssl.pemfile = "server.pem"
48557 auth.backend = "plain"
48558 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
48559 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
48560 auth.backend.plain.groupfile = "lighttpd.group"
48562 auth.backend.ldap.hostname = "localhost"
48563 @@ -152,11 +153,11 @@
48564 status.config-url = "/server-config"
48566 $HTTP["host"] == "vvv.example.org" {
48567 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48568 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48571 $HTTP["host"] == "zzz.example.org" {
48572 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48573 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48574 server.name = "zzz.example.org"
48578 Property changes on: tests/fastcgi-responder.conf
48579 ___________________________________________________________________
48580 Name: svn:eol-style
48583 Index: tests/fastcgi-auth.conf
48584 ===================================================================
48585 --- tests/fastcgi-auth.conf (.../tags/lighttpd-1.4.11) (revision 1159)
48586 +++ tests/fastcgi-auth.conf (.../branches/lighttpd-merge-1.4.x) (revision 1159)
48588 -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48589 -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd.pid"
48590 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48591 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd.pid"
48593 debug.log-request-header = "enable"
48594 debug.log-response-header = "enable"
48597 ## bind to localhost (default: all interfaces)
48598 server.bind = "localhost"
48599 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48600 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48601 server.name = "www.example.org"
48602 server.tag = "Apache 1.3.29"
48605 ######################## MODULE CONFIG ############################
48608 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48609 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
48611 mimetype.assign = ( ".png" => "image/png",
48612 ".jpg" => "image/jpeg",
48614 ".c" => "text/plain",
48615 ".conf" => "text/plain" )
48617 -compress.cache-dir = "@SRCDIR@/tmp/lighttpd/cache/compress/"
48618 +compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
48619 compress.filetype = ("text/plain", "text/html")
48624 "host" => "127.0.0.1",
48626 - "bin-path" => "@SRCDIR@/fcgi-auth",
48627 + "bin-path" => env.SRCDIR + "/fcgi-auth",
48628 "mode" => "authorizer",
48629 - "docroot" => "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/",
48630 + "docroot" => env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/",
48634 @@ -106,7 +106,7 @@
48635 ssl.pemfile = "server.pem"
48637 auth.backend = "plain"
48638 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
48639 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
48640 auth.backend.plain.groupfile = "lighttpd.group"
48642 auth.backend.ldap.hostname = "localhost"
48643 @@ -149,11 +149,11 @@
48644 status.config-url = "/server-config"
48646 $HTTP["host"] == "vvv.example.org" {
48647 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48648 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48651 $HTTP["host"] == "zzz.example.org" {
48652 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48653 + server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48654 server.name = "zzz.example.org"
48658 Property changes on: tests/fastcgi-auth.conf
48659 ___________________________________________________________________
48660 Name: svn:eol-style
48663 Index: tests/proxy.conf
48664 ===================================================================
48665 --- tests/proxy.conf (.../tags/lighttpd-1.4.11) (revision 1159)
48666 +++ tests/proxy.conf (.../branches/lighttpd-merge-1.4.x) (revision 1159)
48668 -server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48669 -server.pid-file = "@SRCDIR@/tmp/lighttpd/lighttpd-proxy.pid"
48670 +server.document-root = env.SRCDIR + "/tmp/lighttpd/servers/www.example.org/pages/"
48671 +server.pid-file = env.SRCDIR + "/tmp/lighttpd/lighttpd-proxy.pid"
48672 +server.tag = "proxy"
48674 -## bind to port (default: 80)
48675 -server.port = 2050
48676 +include "default.conf"
48678 -## bind to localhost (default: all interfaces)
48679 -server.bind = "localhost"
48680 -server.errorlog = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.error.log"
48681 -server.name = "www.example.org"
48682 -server.tag = "Proxy"
48684 -server.dir-listing = "enable"
48686 -#server.event-handler = "linux-sysepoll"
48687 -#server.event-handler = "linux-rtsig"
48689 -#server.modules.path = ""
48690 -server.modules = (
48698 - "mod_simple_vhost",
48701 -# "mod_localizer",
48707 - "mod_accesslog" )
48709 -server.indexfiles = ( "index.php", "index.html",
48710 - "index.htm", "default.htm" )
48713 -######################## MODULE CONFIG ############################
48716 -accesslog.filename = "@SRCDIR@/tmp/lighttpd/logs/lighttpd.access.log"
48718 -mimetype.assign = ( ".png" => "image/png",
48719 - ".jpg" => "image/jpeg",
48720 - ".jpeg" => "image/jpeg",
48721 - ".gif" => "image/gif",
48722 - ".html" => "text/html",
48723 - ".htm" => "text/html",
48724 - ".pdf" => "application/pdf",
48725 - ".swf" => "application/x-shockwave-flash",
48726 - ".spl" => "application/futuresplash",
48727 - ".txt" => "text/plain",
48728 - ".tar.gz" => "application/x-tgz",
48729 - ".tgz" => "application/x-tgz",
48730 - ".gz" => "application/x-gzip",
48731 - ".c" => "text/plain",
48732 - ".conf" => "text/plain" )
48734 -compress.cache-dir = "@SRCDIR@/tmp/lighttpd/cache/compress/"
48735 -compress.filetype = ("text/plain", "text/html")
48737 -setenv.add-environment = ( "TRAC_ENV" => "foo")
48738 -setenv.add-request-header = ( "FOO" => "foo")
48739 -setenv.add-response-header = ( "BAR" => "foo")
48742 -proxy.server = ( "" => (
48744 - "host" => "127.0.0.1",
48749 +## 127.0.0.1 and 127.0.0.2 are the same host
48751 + "" => (( "host" => "127.0.0.1",
48752 + "port" => 2050 ),
48753 + ( "host" => "127.0.0.2",
48758 -cgi.assign = ( ".pl" => "/usr/bin/perl",
48759 - ".cgi" => "/usr/bin/perl",
48760 - ".py" => "/usr/bin/python" )
48762 -userdir.include-user = ( "jan" )
48763 -userdir.path = "/"
48765 -ssl.engine = "disable"
48766 -ssl.pemfile = "server.pem"
48768 -auth.backend = "plain"
48769 -auth.backend.plain.userfile = "@SRCDIR@/tmp/lighttpd/lighttpd.user"
48770 -auth.backend.plain.groupfile = "lighttpd.group"
48772 -auth.backend.ldap.hostname = "localhost"
48773 -auth.backend.ldap.base-dn = "dc=my-domain,dc=com"
48774 -auth.backend.ldap.filter = "(uid=$)"
48776 -auth.require = ( "/server-status" =>
48778 - "method" => "digest",
48779 - "realm" => "download archiv",
48780 -# "require" => ("group=www", "user=jan", "host=192.168.2.10")
48781 - "require" => "group=www|user=jan|host=192.168.2.10"
48785 - "method" => "basic",
48786 - "realm" => "download archiv",
48787 -# "require" => ("group=www", "user=jan", "host=192.168.2.10")
48788 - "require" => "user=jan"
48790 - "/server-config" =>
48792 - "method" => "basic",
48793 - "realm" => "download archiv",
48794 -# "require" => ("group=www", "user=jan", "user=weigon", "host=192.168.2.10")
48795 - "require" => "group=www|user=jan|host=192.168.2.10"
48799 -url.access-deny = ( "~", ".inc")
48801 -url.redirect = ( "^/redirect/$" => "http://localhost:2048/" )
48803 -url.rewrite = ( "^/rewrite/foo($|\?.+)" => "/indexfile/rewrite.php$1",
48804 - "^/rewrite/bar(?:$|\?(.+))" => "/indexfile/rewrite.php?bar&$1" )
48806 -expire.url = ( "/expire/access" => "access 2 hours",
48807 - "/expire/modification" => "access plus 1 seconds 2 minutes")
48809 -#cache.cache-dir = "/home/weigon/wwwroot/cache/"
48811 -#### status module
48812 -status.status-url = "/server-status"
48813 -status.config-url = "/server-config"
48815 -$HTTP["host"] == "vvv.example.org" {
48816 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48817 +$HTTP["url"] =~ "^/balance-rr/" {
48818 + proxy.balance = "round-robin"
48821 -$HTTP["host"] == "zzz.example.org" {
48822 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/www.example.org/pages/"
48823 - server.name = "zzz.example.org"
48824 +$HTTP["url"] =~ "^/balance-hash/" {
48825 + proxy.balance = "hash"
48828 -$HTTP["host"] == "no-simple.example.org" {
48829 - server.document-root = "@SRCDIR@/tmp/lighttpd/servers/123.example.org/pages/"
48830 - server.name = "zzz.example.org"
48831 +$HTTP["url"] =~ "^/balance-fair/" {
48832 + proxy.balance = "fair"
48835 -$HTTP["host"] !~ "(no-simple\.example\.org)" {
48836 - simple-vhost.document-root = "pages"
48837 - simple-vhost.server-root = "@SRCDIR@/tmp/lighttpd/servers/"
48838 - simple-vhost.default-host = "www.example.org"
48842 Property changes on: tests/proxy.conf
48843 ___________________________________________________________________
48844 Name: svn:eol-style
48848 Property changes on: tests/prepare.sh
48849 ___________________________________________________________________
48850 Name: svn:eol-style
48853 Index: tests/default.conf
48854 ===================================================================
48855 --- tests/default.conf (.../tags/lighttpd-1.4.11) (revision 0)
48856 +++ tests/default.conf (.../branches/lighttpd-merge-1.4.x) (revision 1159)
48858 +server.name = "www.example.org"
48860 +## bind to port (default: 80)
48861 +server.port = env.PORT
48864 +server.dir-listing = "enable"
48866 +#server.event-handler = "linux-sysepoll"
48867 +#server.event-handler = "linux-rtsig"
48869 +server.modules = (
48876 + "mod_simple_vhost",
48878 + "mod_secdownload",
48885 + "mod_accesslog" )
48887 +server.indexfiles = ( "index.php", "index.html",
48888 + "index.htm", "default.htm" )
48890 +ssi.extension = ( ".shtml" )
48892 +######################## MODULE CONFIG ############################
48895 +accesslog.filename = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.access.log"
48896 +server.errorlog = env.SRCDIR + "/tmp/lighttpd/logs/lighttpd.error.log"
48898 +mimetype.assign = ( ".png" => "image/png",
48899 + ".jpg" => "image/jpeg",
48900 + ".jpeg" => "image/jpeg",
48901 + ".gif" => "image/gif",
48902 + ".html" => "text/html",
48903 + ".htm" => "text/html",
48904 + ".pdf" => "application/pdf",
48905 + ".swf" => "application/x-shockwave-flash",
48906 + ".spl" => "application/futuresplash",
48907 + ".txt" => "text/plain",
48908 + ".tar.gz" => "application/x-tgz",
48909 + ".tgz" => "application/x-tgz",
48910 + ".gz" => "application/x-gzip",
48911 + ".c" => "text/plain",
48912 + ".conf" => "text/plain" )
48914 +compress.cache-dir = env.SRCDIR + "/tmp/lighttpd/cache/compress/"
48915 +compress.filetype = ("text/plain", "text/html")
48917 +setenv.add-environment = ( "TRAC_ENV" => "tracenv", "SETENV" => "setenv")
48919 +cgi.assign = ( ".pl" => "/usr/bin/perl",
48920 + ".cgi" => "/usr/bin/perl",
48921 + ".py" => "/usr/bin/python" )
48923 +userdir.include-user = ( "jan" )
48924 +userdir.path = "/"
48926 +ssl.engine = "disable"
48927 +ssl.pemfile = "server.pem"
48929 +auth.backend = "plain"
48930 +auth.backend.plain.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.user"
48931 +auth.backend.htpasswd.userfile = env.SRCDIR + "/tmp/lighttpd/lighttpd.htpasswd"
48932 +auth.backend.plain.groupfile = "lighttpd.group"
48934 +auth.backend.ldap.hostname = "localhost"
48935 +auth.backend.ldap.base-dn = "dc=my-domain,dc=com"
48936 +auth.backend.ldap.filter = "(uid=$)"
48938 +auth.require = ( "/server-status" =>
48940 + "method" => "digest",
48941 + "realm" => "download archiv",
48942 + "require" => "valid-user"
48946 + "method" => "basic",
48947 + "realm" => "download archiv",
48948 + "require" => "user=jan"
48950 + "/server-config" =>
48952 + "method" => "basic",
48953 + "realm" => "download archiv",
48954 + "require" => "valid-user"
48958 +url.access-deny = ( "~", ".inc")
48960 +url.redirect = ( "^/redirect/$" => "http://localhost:2048/" )
48962 +url.rewrite = ( "^/rewrite/foo($|\?.+)" => "/indexfile/rewrite.php$1",
48963 + "^/rewrite/bar(?:$|\?(.+))" => "/indexfile/rewrite.php?bar&$1" )
48965 +#### status module
48966 +status.status-url = "/server-status"
48967 +status.config-url = "/server-config"
48970 Property changes on: tests/default.conf
48971 ___________________________________________________________________
48972 Name: svn:eol-style
48976 Property changes on: tests/docroot/www/get-header.pl
48977 ___________________________________________________________________
48978 Name: svn:eol-style
48982 Property changes on: tests/docroot/www/nph-status.pl
48983 ___________________________________________________________________
48984 Name: svn:eol-style
48988 Property changes on: tests/docroot/www/cgi-pathinfo.pl
48989 ___________________________________________________________________
48990 Name: svn:eol-style
48994 Property changes on: tests/docroot/www/ssi.shtml
48995 ___________________________________________________________________
48996 Name: svn:eol-style
49000 Property changes on: tests/docroot/www/index.txt
49001 ___________________________________________________________________
49002 Name: svn:eol-style
49006 Property changes on: tests/docroot/www/exec-date.shtml
49007 ___________________________________________________________________
49008 Name: svn:eol-style
49012 Property changes on: tests/docroot/www/redirect.php
49013 ___________________________________________________________________
49014 Name: svn:eol-style
49018 Property changes on: tests/docroot/www/get-post-len.pl
49019 ___________________________________________________________________
49020 Name: svn:eol-style
49024 Property changes on: tests/docroot/www/cgi.php
49025 ___________________________________________________________________
49026 Name: svn:eol-style
49030 Property changes on: tests/docroot/www/phpinfo.php
49031 ___________________________________________________________________
49032 Name: svn:eol-style
49036 Property changes on: tests/docroot/www/get-env.php
49037 ___________________________________________________________________
49038 Name: svn:eol-style
49042 Property changes on: tests/docroot/www/expire/access.txt
49043 ___________________________________________________________________
49044 Name: svn:eol-style
49048 Property changes on: tests/docroot/www/expire/modification.txt
49049 ___________________________________________________________________
49050 Name: svn:eol-style
49054 Property changes on: tests/docroot/www/expire/Makefile.am
49055 ___________________________________________________________________
49056 Name: svn:eol-style
49060 Property changes on: tests/docroot/www/get-server-env.php
49061 ___________________________________________________________________
49062 Name: svn:eol-style
49066 Property changes on: tests/docroot/www/prefix.fcgi
49067 ___________________________________________________________________
49068 Name: svn:eol-style
49072 Property changes on: tests/docroot/www/go/cgi.php
49073 ___________________________________________________________________
49074 Name: svn:eol-style
49078 Property changes on: tests/docroot/www/go/Makefile.am
49079 ___________________________________________________________________
49080 Name: svn:eol-style
49084 Property changes on: tests/docroot/www/indexfile/rewrite.php
49085 ___________________________________________________________________
49086 Name: svn:eol-style
49090 Property changes on: tests/docroot/www/indexfile/Makefile.am
49091 ___________________________________________________________________
49092 Name: svn:eol-style
49096 Property changes on: tests/docroot/www/indexfile/return-404.php
49097 ___________________________________________________________________
49098 Name: svn:eol-style
49102 Property changes on: tests/docroot/www/indexfile/index.php
49103 ___________________________________________________________________
49104 Name: svn:eol-style
49108 Property changes on: tests/docroot/www/Makefile.am
49109 ___________________________________________________________________
49110 Name: svn:eol-style
49114 Property changes on: tests/docroot/www/index.html
49115 ___________________________________________________________________
49116 Name: svn:eol-style
49120 Property changes on: tests/docroot/www/cgi.pl
49121 ___________________________________________________________________
49122 Name: svn:eol-style
49126 Property changes on: tests/docroot/123/12345.html
49127 ___________________________________________________________________
49128 Name: svn:eol-style
49132 Property changes on: tests/docroot/123/dummyfile.bla
49133 ___________________________________________________________________
49134 Name: svn:eol-style
49138 Property changes on: tests/docroot/123/Makefile.am
49139 ___________________________________________________________________
49140 Name: svn:eol-style
49144 Property changes on: tests/docroot/123/phpinfo.php
49145 ___________________________________________________________________
49146 Name: svn:eol-style
49150 Property changes on: tests/docroot/123/12345.txt
49151 ___________________________________________________________________
49152 Name: svn:eol-style
49156 Property changes on: tests/docroot/Makefile.am
49157 ___________________________________________________________________
49158 Name: svn:eol-style
49161 Index: tests/Makefile.am
49162 ===================================================================
49163 --- tests/Makefile.am (.../tags/lighttpd-1.4.11) (revision 1159)
49164 +++ tests/Makefile.am (.../branches/lighttpd-merge-1.4.x) (revision 1159)
49165 @@ -39,10 +39,15 @@
49181 TESTS_ENVIRONMENT=$(srcdir)/wrapper.sh $(srcdir) $(top_builddir)
49183 Property changes on: tests/Makefile.am
49184 ___________________________________________________________________
49185 Name: svn:eol-style
49189 Property changes on: tests/mod-compress.t
49190 ___________________________________________________________________
49191 Name: svn:eol-style
49194 Index: tests/LightyTest.pm
49195 ===================================================================
49196 --- tests/LightyTest.pm (.../tags/lighttpd-1.4.11) (revision 1159)
49197 +++ tests/LightyTest.pm (.../branches/lighttpd-merge-1.4.x) (revision 1159)
49198 @@ -87,14 +87,14 @@
49199 # pre-process configfile if necessary
49202 - unlink($self->{TESTDIR}."/tmp/cfg.file");
49203 - system("cat ".$self->{SRCDIR}."/".$self->{CONFIGFILE}.' | perl -pe "s#\@SRCDIR\@#'.$self->{BASEDIR}.'/tests/#" > '.$self->{TESTDIR}.'/tmp/cfg.file');
49204 + $ENV{'SRCDIR'} = $self->{BASEDIR}.'/tests';
49205 + $ENV{'PORT'} = $self->{PORT};
49207 unlink($self->{LIGHTTPD_PIDFILE});
49209 - system($self->{LIGHTTPD_PATH}." -f ".$self->{TESTDIR}."/tmp/cfg.file -m ".$self->{MODULES_PATH});
49210 + system($self->{LIGHTTPD_PATH}." -f ".$self->{SRCDIR}."/".$self->{CONFIGFILE}." -m ".$self->{MODULES_PATH});
49212 - 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}." &");
49213 + system("valgrind --tool=memcheck --show-reachable=yes --leak-check=yes --logfile=foo ".$self->{LIGHTTPD_PATH}." -D -f ".$self->{SRCDIR}."/".$self->{CONFIGFILE}." -m ".$self->{MODULES_PATH}." &");
49216 select(undef, undef, undef, 0.1);
49217 @@ -184,7 +184,7 @@
49218 (my $h = $1) =~ tr/[A-Z]/[a-z]/;
49220 if (defined $resp_hdr{$h}) {
49221 - diag(sprintf("header %s is duplicated: %s and %s\n",
49222 + diag(sprintf("header '%s' is duplicated: '%s' and '%s'\n",
49223 $h, $resp_hdr{$h}, $2));
49225 $resp_hdr{$h} = $2;
49226 @@ -196,6 +196,9 @@
49230 + $t->{etag} = $resp_hdr{'etag'};
49231 + $t->{date} = $resp_hdr{'date'};
49234 if (defined $resp_hdr{"content-length"}) {
49235 $resp_body = substr($lines, 0, $resp_hdr{"content-length"});
49237 Property changes on: tests/LightyTest.pm
49238 ___________________________________________________________________
49239 Name: svn:eol-style
49243 Property changes on: tests/mod-ssi.t
49244 ___________________________________________________________________
49245 Name: svn:eol-style
49249 Property changes on: tests/core-condition.t
49250 ___________________________________________________________________
49251 Name: svn:eol-style
49255 Property changes on: tests/run-tests.pl
49256 ___________________________________________________________________
49257 Name: svn:eol-style
49261 Property changes on: tests
49262 ___________________________________________________________________
49282 Property changes on: doc/redirect.txt
49283 ___________________________________________________________________
49284 Name: svn:eol-style
49287 Index: doc/performance.txt
49288 ===================================================================
49289 --- doc/performance.txt (.../tags/lighttpd-1.4.11) (revision 1159)
49290 +++ doc/performance.txt (.../branches/lighttpd-merge-1.4.x) (revision 1159)
49291 @@ -183,6 +183,8 @@
49293 server.stat-cache-engine = "fam" # either fam, simple or disabled
49295 +See http://oss.sgi.com/projects/fam/faq.html for information about FAM.
49296 +See http://www.gnome.org/~veillard/gamin/overview.html for information about gamin.
49298 Platform-Specific Notes
49299 =======================
49301 Property changes on: doc/performance.txt
49302 ___________________________________________________________________
49303 Name: svn:eol-style
49307 Property changes on: doc/ssl.txt
49308 ___________________________________________________________________
49309 Name: svn:eol-style
49312 Index: doc/secdownload.txt
49313 ===================================================================
49314 --- doc/secdownload.txt (.../tags/lighttpd-1.4.11) (revision 1159)
49315 +++ doc/secdownload.txt (.../branches/lighttpd-merge-1.4.x) (revision 1159)
49316 @@ -118,7 +118,7 @@
49317 $secret = "verysecret";
49318 $uri_prefix = "/dl/";
49321 + # filename, make sure it's started with a "/" or you'll get 404 in the browser
49322 $f = "/secret-file.txt";
49324 # current timestamp
49326 Property changes on: doc/secdownload.txt
49327 ___________________________________________________________________
49328 Name: svn:eol-style
49332 Property changes on: doc/accesslog.txt
49333 ___________________________________________________________________
49334 Name: svn:eol-style
49338 Property changes on: doc/setenv.txt
49339 ___________________________________________________________________
49340 Name: svn:eol-style
49344 Property changes on: doc/sysconfig.lighttpd
49345 ___________________________________________________________________
49346 Name: svn:eol-style
49350 Property changes on: doc/traffic-shaping.txt
49351 ___________________________________________________________________
49352 Name: svn:eol-style
49356 Property changes on: doc/security.txt
49357 ___________________________________________________________________
49358 Name: svn:eol-style
49362 Property changes on: doc/trigger_b4_dl.txt
49363 ___________________________________________________________________
49364 Name: svn:eol-style
49368 Property changes on: doc/spawn-php.sh
49369 ___________________________________________________________________
49370 Name: svn:eol-style
49374 Property changes on: doc/webdav.txt
49375 ___________________________________________________________________
49376 Name: svn:eol-style
49380 Property changes on: doc/rc.lighttpd.redhat
49381 ___________________________________________________________________
49382 Name: svn:eol-style
49386 Property changes on: doc/userdir.txt
49387 ___________________________________________________________________
49388 Name: svn:eol-style
49392 Property changes on: doc/features.txt
49393 ___________________________________________________________________
49394 Name: svn:eol-style
49398 Property changes on: doc/rrdtool-graph.sh
49399 ___________________________________________________________________
49400 Name: svn:eol-style
49404 Property changes on: doc/proxy.txt
49405 ___________________________________________________________________
49406 Name: svn:eol-style
49410 Property changes on: doc/status.txt
49411 ___________________________________________________________________
49412 Name: svn:eol-style
49416 Property changes on: doc/mysqlvhost.txt
49417 ___________________________________________________________________
49418 Name: svn:eol-style
49421 Index: doc/compress.txt
49422 ===================================================================
49423 --- doc/compress.txt (.../tags/lighttpd-1.4.11) (revision 1159)
49424 +++ doc/compress.txt (.../branches/lighttpd-merge-1.4.x) (revision 1159)
49425 @@ -22,13 +22,39 @@
49428 Output compression reduces the network load and can improve the overall
49429 -throughput of the webserver.
49430 +throughput of the webserver. All major http-clients support compression by
49431 +announcing it in the Accept-Encoding header. This is used to negotiate the
49432 +most suitable compression method. We support deflate, gzip and bzip2.
49434 -Only static content is supported up to now.
49435 +deflate (RFC1950, RFC1951) and gzip (RFC1952) depend on zlib while bzip2
49436 +depends on libbzip2. bzip2 is only supported by lynx and some other console
49439 -The server negotiates automaticly which compression method is used.
49440 -Supported are gzip, deflate, bzip.
49441 +Currently we limit to compression support to static files.
49446 +mod_compress can stored compressed files on disk to optimized the compression
49447 +on a second request away. As soon as compress.cache-dir is set the files are
49450 +The names of the cache files are made of the filename, the compression method
49451 +and the etag associated to the file.
49453 +Cleaning the cache is left to the user. A cron job deleting files older than
49454 +10 days should do fine.
49459 +The module limits the compression of files to files larger than 128 Byte and
49460 +smaller than 128 MByte.
49462 +The lower limit is set as small files tend to become larger by compressing due
49463 +to the compression headers, the upper limit is set to work sensable with
49464 +memory and cpu-time.
49469 @@ -47,15 +73,28 @@
49470 Default: not set, compress the file for every request
49473 - mimetypes where might get compressed
49474 + mimetypes which might get compressed
49478 compress.filetype = ("text/plain", "text/html")
49480 + Keep in mind that compressed JavaScript and CSS files are broken in some
49485 +compress.max-file-size
49486 + maximum size of the original file to be compressed kBytes.
49488 + This is meant to protect the server against DoSing as compressing large
49489 + (let's say 1Gbyte) takes a lot of time and would delay the whole operation
49492 + There is a hard upper limit of 128Mbyte.
49494 + Default: unlimited (== hard-limit of 128MByte)
49496 Compressing Dynamic Content
49497 ===========================
49500 Property changes on: doc/compress.txt
49501 ___________________________________________________________________
49502 Name: svn:eol-style
49506 Property changes on: doc/fastcgi-state.txt
49507 ___________________________________________________________________
49508 Name: svn:eol-style
49512 Property changes on: doc/.cvsignore
49513 ___________________________________________________________________
49514 Name: svn:eol-style
49518 Property changes on: doc/lighttpd.1
49519 ___________________________________________________________________
49520 Name: svn:eol-style
49524 Property changes on: doc/access.txt
49525 ___________________________________________________________________
49526 Name: svn:eol-style
49530 Property changes on: doc/cgi.txt
49531 ___________________________________________________________________
49532 Name: svn:eol-style
49536 Property changes on: doc/rc.lighttpd
49537 ___________________________________________________________________
49538 Name: svn:eol-style
49542 Property changes on: doc/fastcgi-state.dot
49543 ___________________________________________________________________
49544 Name: svn:eol-style
49547 Index: doc/configuration.txt
49548 ===================================================================
49549 --- doc/configuration.txt (.../tags/lighttpd-1.4.11) (revision 1159)
49550 +++ doc/configuration.txt (.../branches/lighttpd-merge-1.4.x) (revision 1159)
49551 @@ -511,3 +511,10 @@
49553 debug.log-request-handling
49556 +debug.log-condition-handling
49557 + default: disabled
49559 +debug.log-condition-cache-handling
49560 + for developers only
49561 + default: disabled
49563 Property changes on: doc/configuration.txt
49564 ___________________________________________________________________
49565 Name: svn:eol-style
49569 Property changes on: doc/oldstyle.css
49570 ___________________________________________________________________
49571 Name: svn:eol-style
49575 Property changes on: doc/dirlisting.txt
49576 ___________________________________________________________________
49577 Name: svn:eol-style
49581 Property changes on: doc/evhost.txt
49582 ___________________________________________________________________
49583 Name: svn:eol-style
49587 Property changes on: doc/cml.txt
49588 ___________________________________________________________________
49589 Name: svn:eol-style
49593 Property changes on: doc/lighttpd.user
49594 ___________________________________________________________________
49595 Name: svn:eol-style
49599 Property changes on: doc/authentication.txt
49600 ___________________________________________________________________
49601 Name: svn:eol-style
49605 Property changes on: doc/spawn-fcgi.1
49606 ___________________________________________________________________
49607 Name: svn:eol-style
49610 Index: doc/fastcgi.txt
49611 ===================================================================
49612 --- doc/fastcgi.txt (.../tags/lighttpd-1.4.11) (revision 1159)
49613 +++ doc/fastcgi.txt (.../branches/lighttpd-merge-1.4.x) (revision 1159)
49614 @@ -144,8 +144,8 @@
49615 PHP can extract PATH_INFO from it (default: disabled)
49616 :"disable-time": time to wait before a disabled backend is checked
49618 - :"allow-x-send-file": controls if X-LIGHTTPD-send-file headers
49620 + :"allow-x-send-file": controls if X-LIGHTTPD-send-file and X-Sendfile
49621 + headers are allowed
49623 If bin-path is set:
49626 Property changes on: doc/fastcgi.txt
49627 ___________________________________________________________________
49628 Name: svn:eol-style
49632 Property changes on: doc/state.txt
49633 ___________________________________________________________________
49634 Name: svn:eol-style
49638 Property changes on: doc/rewrite.txt
49639 ___________________________________________________________________
49640 Name: svn:eol-style
49644 Property changes on: doc/plugins.txt
49645 ___________________________________________________________________
49646 Name: svn:eol-style
49650 Property changes on: doc/newstyle.css
49651 ___________________________________________________________________
49652 Name: svn:eol-style
49656 Property changes on: doc/skeleton.txt
49657 ___________________________________________________________________
49658 Name: svn:eol-style
49662 Property changes on: doc/rrdtool.txt
49663 ___________________________________________________________________
49664 Name: svn:eol-style
49667 Index: doc/lighttpd.conf
49668 ===================================================================
49669 --- doc/lighttpd.conf (.../tags/lighttpd-1.4.11) (revision 1159)
49670 +++ doc/lighttpd.conf (.../branches/lighttpd-merge-1.4.x) (revision 1159)
49671 @@ -172,10 +172,11 @@
49672 #dir-listing.activate = "enable"
49674 ## enable debugging
49675 -#debug.log-request-header = "enable"
49676 -#debug.log-response-header = "enable"
49677 -#debug.log-request-handling = "enable"
49678 -#debug.log-file-not-found = "enable"
49679 +#debug.log-request-header = "enable"
49680 +#debug.log-response-header = "enable"
49681 +#debug.log-request-handling = "enable"
49682 +#debug.log-file-not-found = "enable"
49683 +#debug.log-condition-handling = "enable"
49685 ### only root can use these options
49688 Property changes on: doc/lighttpd.conf
49689 ___________________________________________________________________
49690 Name: svn:eol-style
49694 Property changes on: doc/scgi.txt
49695 ___________________________________________________________________
49696 Name: svn:eol-style
49700 Property changes on: doc/state.dot
49701 ___________________________________________________________________
49702 Name: svn:eol-style
49706 Property changes on: doc/alias.txt
49707 ___________________________________________________________________
49708 Name: svn:eol-style
49712 Property changes on: doc/simple-vhost.txt
49713 ___________________________________________________________________
49714 Name: svn:eol-style
49718 Property changes on: doc/Makefile.am
49719 ___________________________________________________________________
49720 Name: svn:eol-style
49724 Property changes on: doc/expire.txt
49725 ___________________________________________________________________
49726 Name: svn:eol-style
49730 Property changes on: doc/ssi.txt
49731 ___________________________________________________________________
49732 Name: svn:eol-style
49736 Property changes on: INSTALL
49737 ___________________________________________________________________
49738 Name: svn:eol-style
49742 ===================================================================
49743 --- SConstruct (.../tags/lighttpd-1.4.11) (revision 1159)
49744 +++ SConstruct (.../branches/lighttpd-merge-1.4.x) (revision 1159)
49746 PackageOption('with_xml', 'enable xml support', 'no'),
49747 PackageOption('with_pcre', 'enable pcre support', 'yes'),
49748 PathOption('CC', 'path to the c-compiler', None),
49749 + PathOption('PSDK_HOME', 'path to the platform SDK', None),
49750 + PathOption('VC_TOOLKIT_HOME', 'path to the Visual C++ Toolkit', None),
49751 BoolOption('build_dynamic', 'enable dynamic build', 'yes'),
49752 BoolOption('build_static', 'enable static build', 'no'),
49753 BoolOption('build_fullstatic', 'enable fullstatic build', 'no'),
49754 @@ -92,25 +94,46 @@
49755 BoolOption('with_gzip', 'enable gzip compression', 'no'),
49756 BoolOption('with_bzip2', 'enable bzip2 compression', 'no'),
49757 BoolOption('with_lua', 'enable lua support for mod_cml', 'no'),
49758 + BoolOption('with_uuid', 'enable LOCK support (requires uuid) for mod_webdav', 'no'),
49759 BoolOption('with_ldap', 'enable ldap auth support', 'no'))
49762 - env = os.environ,
49764 - CPPPATH = Split('#build')
49768 env.Help(opts.GenerateHelpText(env))
49769 +cpppath = [ '#build/' ]
49770 +libpath = [ '/lib/', '/usr/lib/', '/usr/local/lib/' ]
49771 +path = [ '/bin/', '/usr/bin/' ]
49773 if env.subst('${CC}') is not '':
49774 env['CC'] = env.subst('${CC}')
49776 +if env.subst('${VC_TOOLKIT_HOME}') is not '':
49777 + cpppath += [ '${VC_TOOLKIT_HOME}/include' ]
49778 + libpath += [ '${VC_TOOLKIT_HOME}/lib' ]
49779 + path += [ env.subst('${VC_TOOLKIT_HOME}/bin') ]
49781 +if env.subst('${PSDK_HOME}') is not '':
49782 + cpppath += [ '${PSDK_HOME}/include' ]
49783 + libpath += [ '${PSDK_HOME}/lib' ]
49784 + path += [ env.subst('${PSDK_HOME}/bin') ]
49787 +## build new environment with a clean PATH
49789 +env = Environment(options = opts, ENV = { "PATH" : path})
49791 +env.Append(CPPPATH = cpppath)
49792 +env.Append(LIBPATH = libpath)
49794 env['package'] = package
49795 env['version'] = version
49796 if env['CC'] == 'gcc':
49797 ## we need x-open 6 and bsd 4.3 features
49798 env.Append(CCFLAGS = Split('-Wall -O2 -g -W -pedantic -Wunused -Wshadow -std=gnu99'))
49801 + env.Append(CCFLAGS = Split('/Zi /W3'))
49802 # cache configure checks
49804 autoconf = Configure(env, custom_tests = {'CheckStructMember': checkStructMember })
49805 @@ -158,7 +181,7 @@
49806 checkFuncs(autoconf, Split('fork stat lstat strftime dup2 getcwd inet_ntoa inet_ntop memset mmap munmap strchr \
49807 strdup strerror strstr strtol sendfile getopt socket \
49808 gethostbyname poll sigtimedwait epoll_ctl getrlimit chroot \
49809 - getuid select signal pathconf madvise prctl\
49810 + getuid select signal pathconf madvise prctl inet_aton \
49811 writev sigaction sendfile64 send_file kqueue port_create localtime_r posix_fadvise'))
49813 checkTypes(autoconf, Split('pid_t size_t off_t'))
49814 @@ -206,6 +229,10 @@
49815 if autoconf.CheckLibWithHeader('lua', 'lua.h', 'C'):
49816 autoconf.env.Append(CPPFLAGS = [ '-DHAVE_LUA_H', '-DHAVE_LIBLUA' ], LIBLUA = 'lua', LIBLUALIB = 'lualib')
49818 + if env['with_uuid']:
49819 + if autoconf.CheckLibWithHeader('uuid', 'uuid/uuid.h', 'C'):
49820 + autoconf.env.Append(CPPFLAGS = [ '-DHAVE_UUID_H' ], LIBUUID = 'uuid')
49823 if autoconf.CheckLibWithHeader('fcgi', 'fastcgi.h', 'C'):
49824 autoconf.env.Append(LIBFCGI = 'fcgi')
49825 @@ -252,6 +279,9 @@
49826 env.Append(COMMON_LIB = 'bin')
49827 elif re.compile("darwin|aix").search(env['PLATFORM']):
49828 env.Append(COMMON_LIB = 'lib')
49829 +elif re.compile("win32").search(env['PLATFORM']):
49830 + env['LIBS'] += [ 'wsock32' ]
49831 + env.Append(COMMON_LIB = False)
49833 env.Append(COMMON_LIB = False)
49836 Property changes on: SConstruct
49837 ___________________________________________________________________
49838 Name: svn:eol-style
49842 Property changes on: COPYING
49843 ___________________________________________________________________
49844 Name: svn:eol-style
49848 Property changes on: Makefile.am
49849 ___________________________________________________________________
49850 Name: svn:eol-style
49854 Property changes on: config.py-sample
49855 ___________________________________________________________________
49856 Name: svn:eol-style
49860 Property changes on: autogen.sh
49861 ___________________________________________________________________
49862 Name: svn:eol-style
49866 ===================================================================
49867 --- INSTALL.svn (.../tags/lighttpd-1.4.11) (revision 0)
49868 +++ INSTALL.svn (.../branches/lighttpd-merge-1.4.x) (revision 1159)
49872 +Installation from svn repo
49877 +:Revision: $Revision$
49881 +subversion (required, for svn co, svn up)
49882 +perl (optional, for check)
49883 +php (optional, for check)
49885 +Choose one of the build systems:
49886 +1. build with autotools
49887 +autotools (required for autogen.sh)
49889 +2. build with scons:
49890 +an text editor (for config.py)
49891 +scons v0.96.91.D001 or newer (required for scons build)
49893 +Check out the source
49895 +Review which source you want to checkout at:
49896 +http://trac.lighttpd.net/trac/browser
49897 +http://trac.lighttpd.net/trac/browser/tags
49899 +note the current lastest version is lighttpd-merge-1.4.x not trunk:
49900 +http://trac.lighttpd.net/trac/browser/branches/lighttpd-merge-1.4.x
49902 +and check it out by ::
49904 + svn co svn://svn.lighttpd.net/lighttpd/branches/lighttpd-merge-1.4.x
49907 +Build, Test and Install
49913 + $ cd lighttpd-1.x.x
49915 +if you have problem with autogen.sh, check aclocal autoconf automake version
49917 +check configure options
49918 + $ ./configure --help
49919 + $ ./configure --prefix=/usr/local/lighttpd/ --enable-...
49922 + $ src/lighttpd -Df your_test.conf
49923 + (Ctrl+C once or twice to terminate lighttpd)
49930 +copy and modify config.py for your own needs with your favorite editor:
49931 + $ cp config.py-sample config.py
49932 + $ $EDITOR config.py
49934 +make sure your scons version is up to date, v0.96.91.D001 works. old version is known to have problem to build lighttpd.
49935 + $ scons --version
49938 + $ src/lighttpd -Df your_test.conf
49939 + (Ctrl+C once or twice to terminate lighttpd)
49943 +as scons make some file owned by root now, you have to do:
49944 + # chown yourusername:yourgroup -R .
49948 +take look at the configfile in ./doc/lighttpd.conf,
49949 +make your own copy of that file before modify it for your needs.
49951 +Keep up to date with lastest svn repo
49955 +and follow the instructions in "Build and Install".
49957 +Do not make a non-released version on production server, you have been warned.
49959 Property changes on: INSTALL.svn
49960 ___________________________________________________________________
49961 Name: svn:eol-style
49965 ===================================================================
49966 --- NEWS (.../tags/lighttpd-1.4.11) (revision 1159)
49967 +++ NEWS (.../branches/lighttpd-merge-1.4.x) (revision 1159)
49972 +- 1.4.12 - 2006-..-..
49974 + * added handling of Content-Range to PUT requests in mod_webdav
49975 + * added handling of ETag and If-Modified-Since to mod_compress if
49976 + cache-dir is not set
49977 + * added experimental LOCK support for mod_webdav
49978 + * added support for X-Sendfile as addition to X-LIGHTTPD-send-file.
49979 + This allows compatibility with mod_xsendfile for apache
49980 + (http://celebnamer.celebworld.ws/stuff/mod_xsendfile/)
49981 + * fixed handling of If-Modified-Since if Etag is not set
49982 + * fixed hanging fastcgi connections
49983 + * fixed stalling SSL POST requests
49984 + * fixed round-robin load-balancing in mod_proxy
49985 + * TODO: add fail-over to mod-proxy
49986 + * TODO: fix CACHE_HIT/MISS in mod_cml
49987 + * TODO: finish LOCK/UNLOCK in mod_webdav
49989 - 1.4.11 - 2006-03-09
49991 * added ability to specify which ip address spawn-fci listens on
49993 Property changes on: NEWS
49994 ___________________________________________________________________
49995 Name: svn:eol-style
49999 Property changes on: .cvsignore
50000 ___________________________________________________________________
50001 Name: svn:eol-style
50005 Property changes on: lighttpd.spec.in
50006 ___________________________________________________________________
50007 Name: svn:eol-style
50011 Property changes on: .
50012 ___________________________________________________________________
50051 + 4e593b4a-acb2-b240-a177-dc497f6e1bd5:/lighttpd/lighttpd-1.4.x-win32:631