Property changes on: debian/menu.ex ___________________________________________________________________ Name: svn:eol-style + native Property changes on: debian/control ___________________________________________________________________ Name: svn:eol-style + native Property changes on: debian/emacsen-remove.ex ___________________________________________________________________ Name: svn:eol-style + native Property changes on: debian/watch.ex ___________________________________________________________________ Name: svn:eol-style + native Property changes on: debian/manpage.1.ex ___________________________________________________________________ Name: svn:eol-style + native Property changes on: debian/manpage.xml.ex ___________________________________________________________________ Name: svn:eol-style + native Property changes on: debian/compat ___________________________________________________________________ Name: svn:eol-style + native Property changes on: debian/manpage.sgml.ex ___________________________________________________________________ Name: svn:eol-style + native Property changes on: debian/init.d ___________________________________________________________________ Name: svn:eol-style + native Property changes on: debian/emacsen-startup.ex ___________________________________________________________________ Name: svn:eol-style + native Property changes on: debian/changelog ___________________________________________________________________ Name: svn:eol-style + native Property changes on: debian/docs ___________________________________________________________________ Name: svn:eol-style + native Property changes on: debian/README.Debian.ex ___________________________________________________________________ Name: svn:eol-style + native Property changes on: debian/emacsen-install.ex ___________________________________________________________________ Name: svn:eol-style + native Property changes on: debian/rules ___________________________________________________________________ Name: svn:eol-style + native Property changes on: debian/cron.d.ex ___________________________________________________________________ Name: svn:eol-style + native Property changes on: debian/postrm.ex ___________________________________________________________________ Name: svn:eol-style + native Property changes on: debian/preinst.ex ___________________________________________________________________ Name: svn:eol-style + native Property changes on: debian/prerm.ex ___________________________________________________________________ Name: svn:eol-style + native Property changes on: debian/dirs ___________________________________________________________________ Name: svn:eol-style + native Property changes on: debian/lighttpd.postinst ___________________________________________________________________ Name: svn:eol-style + native Property changes on: debian/lighttpd.conf ___________________________________________________________________ Name: svn:eol-style + native Property changes on: debian/lighttpd.doc-base.EX ___________________________________________________________________ Name: svn:eol-style + native Property changes on: debian/copyright ___________________________________________________________________ Name: svn:eol-style + native Property changes on: debian/conffiles ___________________________________________________________________ Name: svn:eol-style + native Property changes on: debian/Makefile.am ___________________________________________________________________ Name: svn:eol-style + native Property changes on: debian/lighttpd-default.ex ___________________________________________________________________ Name: svn:eol-style + native Property changes on: debian/.cvsignore ___________________________________________________________________ Name: svn:eol-style + native Property changes on: debian/lighttpd.logrotate ___________________________________________________________________ Name: svn:eol-style + native Property changes on: AUTHORS ___________________________________________________________________ Name: svn:eol-style + native Index: configure.in =================================================================== --- configure.in (.../tags/lighttpd-1.4.11) (revision 1159) +++ configure.in (.../branches/lighttpd-merge-1.4.x) (revision 1159) @@ -1,7 +1,7 @@ # -*- Autoconf -*- # Process this file with autoconf to produce a configure script. AC_PREREQ(2.57) -AC_INIT(lighttpd, 1.4.11, jan@kneschke.de) +AC_INIT(lighttpd, 1.4.12, jan@kneschke.de) AC_CONFIG_SRCDIR([src/server.c]) AC_CANONICAL_TARGET @@ -66,7 +66,7 @@ AC_TYPE_PID_T AC_TYPE_SIZE_T -AC_CHECK_MEMBER(struct tm.tm_gmtoff,AC_DEFINE([HAVE_STRUCT_TM_GMTOFF],[1],[gmtoff in struct tm]),,[#include ]) +AC_CHECK_MEMBER(struct tm.tm_gmtoff,[AC_DEFINE([HAVE_STRUCT_TM_GMTOFF],[1],[gmtoff in struct tm])],,[#include ]) AC_CHECK_TYPES(struct sockaddr_storage,,,[#include ]) AC_CHECK_TYPES(socklen_t,,,[#include #include ]) @@ -339,6 +339,22 @@ AC_DEFINE([HAVE_SQLITE3], [1], [libsqlite3]) AC_DEFINE([HAVE_SQLITE3_H], [1], [sqlite3.h]) ]) + + AC_MSG_CHECKING(for locks in mod_webdav) + AC_ARG_WITH(webdav-locks, AC_HELP_STRING([--with-webdav-locks],[locks in mod_webdav]), + [WITH_WEBDAV_LOCKS=$withval],[WITH_WEBDAV_LOCKS=no]) + AC_MSG_RESULT([$WITH_WEBDAV_LOCKS]) + + if test "$WITH_WEBDAV_LOCKS" != "no"; then + AC_CHECK_LIB(uuid, uuid_unparse, [ + AC_CHECK_HEADERS([uuid/uuid.h],[ + UUID_LIB=-luuid + AC_DEFINE([HAVE_UUID], [1], [libuuid]) + AC_DEFINE([HAVE_UUID_H], [1], [uuid/uuid.h is available]) + ]) + ]) + + fi fi dnl Check for gdbm @@ -381,31 +397,12 @@ AC_MSG_RESULT($WITH_LUA) if test "$WITH_LUA" != "no"; then - AC_PATH_PROG(LUACONFIG, lua-config) - - if test x"$LUACONFIG" != x; then - LUA_CFLAGS=`$LUACONFIG --include` - LUA_LIBS=`$LUACONFIG --libs --extralibs` + # try pkgconfig + PKG_CHECK_MODULES(LUA, lua >= 5.1, [ AC_DEFINE([HAVE_LUA], [1], [liblua]) AC_DEFINE([HAVE_LUA_H], [1], [lua.h]) - else - AC_CHECK_LIB(lua, lua_open, [ - AC_CHECK_HEADERS([lua.h],[ - LUA_LIBS="-llua -llualib" - AC_DEFINE([HAVE_LUA], [1], [liblua]) - AC_DEFINE([HAVE_LUA_H], [1], [lua.h]) - ]) - ]) - fi + ]) - if test x"$LUA_LIBS" = x; then - # try pkgconfig - PKG_CHECK_MODULES(LUA, lua, [ - AC_DEFINE([HAVE_LUA], [1], [liblua]) - AC_DEFINE([HAVE_LUA_H], [1], [lua.h]) - ]) - fi - AC_SUBST(LUA_CFLAGS) AC_SUBST(LUA_LIBS) fi @@ -440,7 +437,7 @@ esac AC_CHECK_FUNCS([dup2 getcwd inet_ntoa inet_ntop memset mmap munmap strchr \ - strdup strerror strstr strtol sendfile getopt socket \ + strdup strerror strstr strtol sendfile getopt socket lstat \ gethostbyname poll sigtimedwait epoll_ctl getrlimit chroot \ getuid select signal pathconf madvise posix_fadvise posix_madvise \ writev sigaction sendfile64 send_file kqueue port_create localtime_r]) @@ -538,7 +535,7 @@ AC_OUTPUT -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" +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" plugins="mod_rewrite mod_redirect mod_ssi mod_trigger_b4_dl" features="regex-conditionals" @@ -642,6 +639,14 @@ disable_feature="$disable_feature $features" fi +features="webdav-locks" +if test "x$UUID_LIB" \!= x; then + enable_feature="$enable_feature $features" +else + disable_feature="$disable_feature $features" +fi + + ## output $ECHO Property changes on: configure.in ___________________________________________________________________ Name: svn:eol-style + native Property changes on: ChangeLog ___________________________________________________________________ Name: svn:eol-style + native Index: src/data_config.c =================================================================== --- src/data_config.c (.../tags/lighttpd-1.4.11) (revision 1159) +++ src/data_config.c (.../branches/lighttpd-merge-1.4.x) (revision 1159) @@ -17,26 +17,26 @@ static void data_config_free(data_unset *d) { data_config *ds = (data_config *)d; - + buffer_free(ds->key); buffer_free(ds->op); buffer_free(ds->comp_key); - + array_free(ds->value); array_free(ds->childs); - + if (ds->string) buffer_free(ds->string); #ifdef HAVE_PCRE_H if (ds->regex) pcre_free(ds->regex); if (ds->regex_study) pcre_free(ds->regex_study); #endif - + free(d); } static void data_config_reset(data_unset *d) { data_config *ds = (data_config *)d; - + /* reused array elements */ buffer_reset(ds->key); buffer_reset(ds->comp_key); @@ -45,9 +45,9 @@ static int data_config_insert_dup(data_unset *dst, data_unset *src) { UNUSED(dst); - + src->free(src); - + return 0; } @@ -56,7 +56,7 @@ array *a = (array *)ds->value; size_t i; size_t maxlen; - + if (0 == ds->context_ndx) { fprintf(stderr, "config {\n"); } @@ -117,22 +117,22 @@ data_config *data_config_init(void) { data_config *ds; - + ds = calloc(1, sizeof(*ds)); - + ds->key = buffer_init(); ds->op = buffer_init(); ds->comp_key = buffer_init(); ds->value = array_init(); ds->childs = array_init(); ds->childs->is_weakref = 1; - + ds->copy = data_config_copy; ds->free = data_config_free; ds->reset = data_config_reset; ds->insert_dup = data_config_insert_dup; ds->print = data_config_print; ds->type = TYPE_CONFIG; - + return ds; } Property changes on: src/data_config.c ___________________________________________________________________ Name: svn:eol-style + native Index: src/configfile-glue.c =================================================================== --- src/configfile-glue.c (.../tags/lighttpd-1.4.11) (revision 1159) +++ src/configfile-glue.c (.../branches/lighttpd-merge-1.4.x) (revision 1159) @@ -1,4 +1,5 @@ #include +#include #include "base.h" #include "buffer.h" @@ -11,10 +12,10 @@ * are the external interface of lighttpd. The functions * are used by the server itself and the plugins. * - * The main-goal is to have a small library in the end - * which is linked against both and which will define + * The main-goal is to have a small library in the end + * which is linked against both and which will define * the interface itself in the end. - * + * */ @@ -24,56 +25,60 @@ int config_insert_values_internal(server *srv, array *ca, const config_values_t cv[]) { size_t i; data_unset *du; - + for (i = 0; cv[i].key; i++) { - + if (NULL == (du = array_get_element(ca, cv[i].key))) { /* no found */ - + continue; } - + switch (cv[i].type) { case T_CONFIG_ARRAY: if (du->type == TYPE_ARRAY) { size_t j; data_array *da = (data_array *)du; - + for (j = 0; j < da->value->used; j++) { if (da->value->data[j]->type == TYPE_STRING) { data_string *ds = data_string_init(); - + buffer_copy_string_buffer(ds->value, ((data_string *)(da->value->data[j]))->value); if (!da->is_index_key) { /* the id's were generated automaticly, as we copy now we might have to renumber them - * this is used to prepend server.modules by mod_indexfiles as it has to be loaded + * this is used to prepend server.modules by mod_indexfiles as it has to be loaded * before mod_fastcgi and friends */ buffer_copy_string_buffer(ds->key, ((data_string *)(da->value->data[j]))->key); } - + array_insert_unique(cv[i].destination, (data_unset *)ds); } else { - log_error_write(srv, __FILE__, __LINE__, "sssd", - "the key of and array can only be a string or a integer, variable:", - cv[i].key, "type:", da->value->data[j]->type); - + log_error_write(srv, __FILE__, __LINE__, "sssd", + "the key of and array can only be a string or a integer, variable:", + cv[i].key, "type:", da->value->data[j]->type); + return -1; } } } else { log_error_write(srv, __FILE__, __LINE__, "sss", "unexpected type for key: ", cv[i].key, "array of strings"); - + return -1; } break; case T_CONFIG_STRING: if (du->type == TYPE_STRING) { data_string *ds = (data_string *)du; - + buffer_copy_string_buffer(cv[i].destination, ds->value); + } else if (du->type == TYPE_INTEGER) { + data_integer *di = (data_integer *)du; + + buffer_copy_long(cv[i].destination, di->value); } else { log_error_write(srv, __FILE__, __LINE__, "ssss", "unexpected type for key: ", cv[i].key, "(string)", "\"...\""); - + return -1; } break; @@ -81,15 +86,20 @@ switch(du->type) { case TYPE_INTEGER: { data_integer *di = (data_integer *)du; - + *((unsigned short *)(cv[i].destination)) = di->value; break; } case TYPE_STRING: { data_string *ds = (data_string *)du; - + + if (buffer_isdigit(ds->value)) { + *((unsigned short *)(cv[i].destination)) = strtol(ds->value->ptr, NULL, 10); + break; + } + log_error_write(srv, __FILE__, __LINE__, "ssb", "get a string but expected a short:", cv[i].key, ds->value); - + return -1; } default: @@ -100,19 +110,19 @@ case T_CONFIG_BOOLEAN: if (du->type == TYPE_STRING) { data_string *ds = (data_string *)du; - + if (buffer_is_equal_string(ds->value, CONST_STR_LEN("enable"))) { *((unsigned short *)(cv[i].destination)) = 1; } else if (buffer_is_equal_string(ds->value, CONST_STR_LEN("disable"))) { *((unsigned short *)(cv[i].destination)) = 0; } else { log_error_write(srv, __FILE__, __LINE__, "ssbs", "ERROR: unexpected value for key:", cv[i].key, ds->value, "(enable|disable)"); - + return -1; } } else { log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: unexpected type for key:", cv[i].key, "(string)", "\"(enable|disable)\""); - + return -1; } break; @@ -121,9 +131,9 @@ break; case T_CONFIG_DEPRECATED: log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: found deprecated key:", cv[i].key, "-", (char *)(cv[i].destination)); - + srv->config_deprecated = 1; - + break; } } @@ -133,25 +143,25 @@ int config_insert_values_global(server *srv, array *ca, const config_values_t cv[]) { size_t i; data_unset *du; - + for (i = 0; cv[i].key; i++) { data_string *touched; - + if (NULL == (du = array_get_element(ca, cv[i].key))) { /* no found */ - + continue; } - + /* touched */ touched = data_string_init(); - + buffer_copy_string(touched->value, ""); buffer_copy_string_buffer(touched->key, du->key); - + array_insert_unique(srv->config_touched, (data_unset *)touched); } - + return config_insert_values_internal(srv, ca, cv); } @@ -191,25 +201,25 @@ } /* pass the rules */ - + switch (dc->comp) { case COMP_HTTP_HOST: { char *ck_colon = NULL, *val_colon = NULL; - + if (!buffer_is_empty(con->uri.authority)) { - - /* + + /* * append server-port to the HTTP_POST if necessary */ - + l = con->uri.authority; - + switch(dc->cond) { case CONFIG_COND_NE: case CONFIG_COND_EQ: ck_colon = strchr(dc->string->ptr, ':'); val_colon = strchr(l->ptr, ':'); - + if (ck_colon == val_colon) { /* nothing to do with it */ break; @@ -230,21 +240,21 @@ break; } } else { - l = NULL; + l = srv->empty_string; } break; } case COMP_HTTP_REMOTEIP: { char *nm_slash; - /* handle remoteip limitations - * + /* handle remoteip limitations + * * "10.0.0.1" is provided for all comparisions - * + * * only for == and != we support - * + * * "10.0.0.1/24" */ - + if ((dc->cond == CONFIG_COND_EQ || dc->cond == CONFIG_COND_NE) && (con->dst_addr.plain.sa_family == AF_INET) && @@ -253,41 +263,48 @@ long nm; char *err; struct in_addr val_inp; - + + if (con->conf.log_condition_handling) { + l = srv->empty_string; + + log_error_write(srv, __FILE__, __LINE__, "bsbsb", dc->comp_key, + "(", l, ") compare to", dc->string); + } + if (*(nm_slash+1) == '\0') { log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: no number after / ", dc->string); - + return COND_RESULT_FALSE; } - + nm_bits = strtol(nm_slash + 1, &err, 10); - + if (*err) { log_error_write(srv, __FILE__, __LINE__, "sbs", "ERROR: non-digit found in netmask:", dc->string, *err); - + return COND_RESULT_FALSE; } - + /* take IP convert to the native */ buffer_copy_string_len(srv->cond_check_buf, dc->string->ptr, nm_slash - dc->string->ptr); -#ifdef __WIN32 +#ifdef _WIN32 if (INADDR_NONE == (val_inp.s_addr = inet_addr(srv->cond_check_buf->ptr))) { log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: ip addr is invalid:", srv->cond_check_buf); - + return COND_RESULT_FALSE; } #else if (0 == inet_aton(srv->cond_check_buf->ptr, &val_inp)) { log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: ip addr is invalid:", srv->cond_check_buf); - + return COND_RESULT_FALSE; } #endif - + /* build netmask */ nm = htonl(~((1 << (32 - nm_bits)) - 1)); - + if ((val_inp.s_addr & nm) == (con->dst_addr.ipv4.sin_addr.s_addr & nm)) { return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_TRUE : COND_RESULT_FALSE; } else { @@ -308,7 +325,7 @@ case COMP_HTTP_REFERER: { data_string *ds; - + if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Referer"))) { l = ds->value; } else { @@ -338,7 +355,7 @@ default: return COND_RESULT_FALSE; } - + if (NULL == l) { if (con->conf.log_condition_handling) { log_error_write(srv, __FILE__, __LINE__, "bsbs", dc->comp_key, @@ -346,10 +363,10 @@ } return COND_RESULT_FALSE; } - + if (con->conf.log_condition_handling) { log_error_write(srv, __FILE__, __LINE__, "bsbsb", dc->comp_key, - "(", l, ") compare to ", dc->string); + "(", l, ") compare to", dc->string); } switch(dc->cond) { case CONFIG_COND_NE: @@ -365,13 +382,13 @@ case CONFIG_COND_MATCH: { cond_cache_t *cache = &con->cond_cache[dc->context_ndx]; int n; - + #ifndef elementsof #define elementsof(x) (sizeof(x) / sizeof(x[0])) #endif n = pcre_exec(dc->regex, dc->regex_study, l->ptr, l->used - 1, 0, 0, cache->matches, elementsof(cache->matches)); - + cache->patterncount = n; if (n > 0) { cache->comp_value = l; @@ -387,7 +404,7 @@ /* no way */ break; } - + return COND_RESULT_FALSE; } @@ -395,6 +412,9 @@ cond_cache_t *caches = con->cond_cache; if (COND_RESULT_UNSET == caches[dc->context_ndx].result) { + if (con->conf.log_condition_handling) { + log_error_write(srv, __FILE__, __LINE__, "sds", "=== start of", dc->context_ndx, "condition block ==="); + } if (COND_RESULT_TRUE == (caches[dc->context_ndx].result = config_check_cond_nocache(srv, con, dc))) { if (dc->next) { data_config *c; @@ -409,11 +429,11 @@ } if (con->conf.log_condition_handling) { log_error_write(srv, __FILE__, __LINE__, "dss", dc->context_ndx, - "(uncached) result:", + "result:", caches[dc->context_ndx].result == COND_RESULT_TRUE ? "true" : "false"); } } else { - if (con->conf.log_condition_handling) { + if (con->conf.log_condition_cache_handling) { log_error_write(srv, __FILE__, __LINE__, "dss", dc->context_ndx, "(cached) result:", caches[dc->context_ndx].result == COND_RESULT_TRUE ? "true" : "false"); @@ -423,9 +443,6 @@ } int config_check_cond(server *srv, connection *con, data_config *dc) { - if (con->conf.log_condition_handling) { - log_error_write(srv, __FILE__, __LINE__, "s", "=== start of condition block ==="); - } return (config_check_cond_cached(srv, con, dc) == COND_RESULT_TRUE); } @@ -443,3 +460,85 @@ return 1; } +/* return <0 on error + * return 0-x if matched (and replaced) + */ +int config_exec_pcre_keyvalue_buffer(connection *con, pcre_keyvalue_buffer *kvb, data_config *context, buffer *match_buf, buffer *result) +{ +#ifdef HAVE_PCRE_H + pcre *match; + pcre_extra *extra; + const char *pattern; + size_t pattern_len; + int n; + size_t i; + pcre_keyvalue *kv; +# define N 10 + int ovec[N * 3]; + + for (i = 0; i < kvb->used; i++) { + kv = kvb->kv[i]; + + match = kv->key; + extra = kv->key_extra; + pattern = kv->value->ptr; + pattern_len = kv->value->used - 1; + + if ((n = pcre_exec(match, extra, match_buf->ptr, match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) { + if (n != PCRE_ERROR_NOMATCH) { + return n; + } + } else { + const char **list; + size_t start, end; + size_t k; + + /* it matched */ + pcre_get_substring_list(match_buf->ptr, ovec, n, &list); + + /* search for $[0-9] */ + + buffer_reset(result); + + start = 0; end = pattern_len; + for (k = 0; k < pattern_len; k++) { + if ((pattern[k] == '$' || pattern[k] == '%') && + isdigit((unsigned char)pattern[k + 1])) { + /* got one */ + + size_t num = pattern[k + 1] - '0'; + + end = k; + + buffer_append_string_len(result, pattern + start, end - start); + + if (pattern[k] == '$') { + /* n is always > 0 */ + if (num < (size_t)n) { + buffer_append_string(result, list[num]); + } + } else { + config_append_cond_match_buffer(con, context, result, num); + } + + k++; + start = k + 1; + } + } + + buffer_append_string_len(result, pattern + start, pattern_len - start); + + pcre_free(list); + + return i; + } + } + + return PCRE_ERROR_NOMATCH; +#undef N +#else + UNUSED(kvb); + return -2; +#endif +} + Property changes on: src/configfile-glue.c ___________________________________________________________________ Name: svn:eol-style + native Index: src/fdevent.h =================================================================== --- src/fdevent.h (.../tags/lighttpd-1.4.11) (revision 1159) +++ src/fdevent.h (.../branches/lighttpd-merge-1.4.x) (revision 1159) @@ -17,13 +17,13 @@ # include #endif -/* MacOS 10.3.x has poll.h under /usr/include/, all other unixes +/* MacOS 10.3.x has poll.h under /usr/include/, all other unixes * under /usr/include/sys/ */ #if defined HAVE_POLL && (defined(HAVE_SYS_POLL_H) || defined(HAVE_POLL_H)) # define USE_POLL # ifdef HAVE_POLL_H # include -# else +# else # include # endif # if defined HAVE_SIGTIMEDWAIT && defined(__linux__) @@ -31,9 +31,11 @@ # include # endif #endif - +#ifdef _WIN32 +# define HAVE_SELECT +#endif #if defined HAVE_SELECT -# ifdef __WIN32 +# ifdef _WIN32 # include # endif # define USE_SELECT @@ -67,14 +69,14 @@ #define FDEVENT_HUP BV(4) #define FDEVENT_NVAL BV(5) -typedef enum { FD_EVENT_TYPE_UNSET = -1, - FD_EVENT_TYPE_CONNECTION, - FD_EVENT_TYPE_FCGI_CONNECTION, - FD_EVENT_TYPE_DIRWATCH, - FD_EVENT_TYPE_CGI_CONNECTION +typedef enum { FD_EVENT_TYPE_UNSET = -1, + FD_EVENT_TYPE_CONNECTION, + FD_EVENT_TYPE_FCGI_CONNECTION, + FD_EVENT_TYPE_DIRWATCH, + FD_EVENT_TYPE_CGI_CONNECTION } fd_event_t; -typedef enum { FDEVENT_HANDLER_UNSET, +typedef enum { FDEVENT_HANDLER_UNSET, FDEVENT_HANDLER_SELECT, FDEVENT_HANDLER_POLL, FDEVENT_HANDLER_LINUX_RTSIG, @@ -86,7 +88,7 @@ /** * a mapping from fd to connection structure - * + * */ typedef struct { int fd; /**< the fd */ @@ -98,41 +100,41 @@ typedef struct { fd_conn *ptr; - + size_t size; size_t used; } fd_conn_buffer; /** * array of unused fd's - * + * */ typedef struct _fdnode { fdevent_handler handler; void *ctx; int fd; - + struct _fdnode *prev, *next; } fdnode; typedef struct { int *ptr; - + size_t used; size_t size; } buffer_int; /** * fd-event handler for select(), poll() and rt-signals on Linux 2.4 - * + * */ typedef struct fdevents { fdevent_handler_t type; - + fdnode **fdarray; size_t maxfds; - + #ifdef USE_LINUX_SIGIO int in_sigio; int signum; @@ -146,21 +148,21 @@ #endif #ifdef USE_POLL struct pollfd *pollfds; - + size_t size; size_t used; - + buffer_int unused; #endif #ifdef USE_SELECT fd_set select_read; fd_set select_write; fd_set select_error; - + fd_set select_set_read; fd_set select_set_write; fd_set select_set_error; - + int select_max_fd; #endif #ifdef USE_SOLARIS_DEVPOLL @@ -177,16 +179,16 @@ #endif int (*reset)(struct fdevents *ev); void (*free)(struct fdevents *ev); - + int (*event_add)(struct fdevents *ev, int fde_ndx, int fd, int events); int (*event_del)(struct fdevents *ev, int fde_ndx, int fd); int (*event_get_revent)(struct fdevents *ev, size_t ndx); int (*event_get_fd)(struct fdevents *ev, size_t ndx); - + int (*event_next_fdndx)(struct fdevents *ev, int ndx); - + int (*poll)(struct fdevents *ev, int timeout_ms); - + int (*fcntl_set)(struct fdevents *ev, int fd); } fdevents; Property changes on: src/fdevent.h ___________________________________________________________________ Name: svn:eol-style + native Index: src/mod_cgi.c =================================================================== --- src/mod_cgi.c (.../tags/lighttpd-1.4.11) (revision 1159) +++ src/mod_cgi.c (.../branches/lighttpd-merge-1.4.x) (revision 1159) @@ -1,21 +1,8 @@ #include -#ifdef __WIN32 -#include -#else -#include -#include -#include -#include - -#include -#endif - -#include #include #include #include -#include #include #include #include @@ -29,9 +16,16 @@ #include "connections.h" #include "joblist.h" #include "http_chunk.h" +#include "fdevent.h" #include "plugin.h" +#include "sys-files.h" +#include "sys-mmap.h" +#include "sys-socket.h" +#include "sys-strings.h" +#include "sys-process.h" + #ifdef HAVE_SYS_FILIO_H # include #endif @@ -40,11 +34,12 @@ typedef struct { char **ptr; - + size_t size; size_t used; } char_array; +#define pid_t int typedef struct { pid_t *ptr; size_t used; @@ -58,23 +53,23 @@ typedef struct { PLUGIN_DATA; buffer_pid_t cgi_pid; - + buffer *tmp_buf; buffer *parse_response; - + plugin_config **config_storage; - - plugin_config conf; + + plugin_config conf; } plugin_data; typedef struct { pid_t pid; int fd; int fde_ndx; /* index into the fd-event buffer */ - + connection *remote_conn; /* dumb pointer */ plugin_data *plugin_data; /* dumb pointer */ - + buffer *response; buffer *response_header; } handler_ctx; @@ -83,17 +78,17 @@ handler_ctx *hctx = calloc(1, sizeof(*hctx)); assert(hctx); - + hctx->response = buffer_init(); hctx->response_header = buffer_init(); - + return hctx; } static void cgi_handler_ctx_free(handler_ctx *hctx) { buffer_free(hctx->response); buffer_free(hctx->response_header); - + free(hctx); } @@ -101,14 +96,14 @@ INIT_FUNC(mod_cgi_init) { plugin_data *p; - + p = calloc(1, sizeof(*p)); assert(p); - + p->tmp_buf = buffer_init(); p->parse_response = buffer_init(); - + return p; } @@ -116,62 +111,62 @@ FREE_FUNC(mod_cgi_free) { plugin_data *p = p_d; buffer_pid_t *r = &(p->cgi_pid); - + UNUSED(srv); - + if (p->config_storage) { size_t i; for (i = 0; i < srv->config_context->used; i++) { plugin_config *s = p->config_storage[i]; - + array_free(s->cgi); - + free(s); } free(p->config_storage); } - + if (r->ptr) free(r->ptr); - + buffer_free(p->tmp_buf); buffer_free(p->parse_response); - + free(p); - + return HANDLER_GO_ON; } SETDEFAULTS_FUNC(mod_fastcgi_set_defaults) { plugin_data *p = p_d; size_t i = 0; - - config_values_t cv[] = { + + config_values_t cv[] = { { "cgi.assign", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET} }; if (!p) return HANDLER_ERROR; - + p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *)); - + for (i = 0; i < srv->config_context->used; i++) { plugin_config *s; - + s = calloc(1, sizeof(plugin_config)); assert(s); - + s->cgi = array_init(); - + cv[0].destination = s->cgi; - + p->config_storage[i] = s; - + if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) { return HANDLER_ERROR; } } - + return HANDLER_GO_ON; } @@ -180,13 +175,13 @@ int m = -1; size_t i; buffer_pid_t *r = &(p->cgi_pid); - + UNUSED(srv); for (i = 0; i < r->used; i++) { if (r->ptr[i] > m) m = r->ptr[i]; } - + if (r->size == 0) { r->size = 16; r->ptr = malloc(sizeof(*r->ptr) * r->size); @@ -194,31 +189,31 @@ r->size += 16; r->ptr = realloc(r->ptr, sizeof(*r->ptr) * r->size); } - + r->ptr[r->used++] = pid; - + return m; } static int cgi_pid_del(server *srv, plugin_data *p, pid_t pid) { size_t i; buffer_pid_t *r = &(p->cgi_pid); - + UNUSED(srv); for (i = 0; i < r->used; i++) { if (r->ptr[i] == pid) break; } - + if (i != r->used) { /* found */ - + if (i != r->used - 1) { r->ptr[i] = r->ptr[r->used - 1]; } r->used--; } - + return 0; } @@ -226,32 +221,32 @@ char *ns; const char *s; int line = 0; - + UNUSED(srv); - + buffer_copy_string_buffer(p->parse_response, in); - - for (s = p->parse_response->ptr; - NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n'))); + + for (s = p->parse_response->ptr; + NULL != (ns = (eol == EOL_RN ? strstr(s, "\r\n") : strchr(s, '\n'))); s = ns + (eol == EOL_RN ? 2 : 1), line++) { const char *key, *value; int key_len; data_string *ds; - + ns[0] = '\0'; - - if (line == 0 && + + if (line == 0 && 0 == strncmp(s, "HTTP/1.", 7)) { /* non-parsed header ... we parse them anyway */ - + if ((s[7] == '1' || s[7] == '0') && s[8] == ' ') { int status; /* after the space should be a status code for us */ - + status = strtol(s+9, NULL, 10); - + if (con->http_status >= 100 && con->http_status < 1000) { /* we expected 3 digits and didn't got them */ @@ -260,27 +255,27 @@ } } } else { - + key = s; if (NULL == (value = strchr(s, ':'))) { /* we expect: ": \r\n" */ continue; } - + key_len = value - key; value += 1; - + /* skip LWS */ while (*value == ' ' || *value == '\t') value++; - + if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) { ds = data_response_init(); } buffer_copy_string_len(ds->key, key, key_len); buffer_copy_string(ds->value, value); - + array_insert_unique(con->response.headers, (data_unset *)ds); - + switch(key_len) { case 4: if (0 == strncasecmp(key, "Date", key_len)) { @@ -315,13 +310,13 @@ } } } - + /* CGI/1.1 rev 03 - 7.2.1.2 */ if ((con->parsed_response & HTTP_LOCATION) && !(con->parsed_response & HTTP_STATUS)) { con->http_status = 302; } - + return 0; } @@ -329,10 +324,10 @@ static int cgi_demux_response(server *srv, handler_ctx *hctx) { plugin_data *p = hctx->plugin_data; connection *con = hctx->remote_conn; - + while(1) { int n; - + buffer_prepare_copy(hctx->response, 1024); if (-1 == (n = read(hctx->fd, hctx->response->ptr, hctx->response->size - 1))) { if (errno == EAGAIN || errno == EINTR) { @@ -343,125 +338,125 @@ log_error_write(srv, __FILE__, __LINE__, "sdd", strerror(errno), con->fd, hctx->fd); return FDEVENT_HANDLED_ERROR; } - + if (n == 0) { /* read finished */ - + con->file_finished = 1; - + /* send final chunk */ http_chunk_append_mem(srv, con, NULL, 0); joblist_append(srv, con); - + return FDEVENT_HANDLED_FINISHED; } - + hctx->response->ptr[n] = '\0'; hctx->response->used = n+1; - + /* split header from body */ - + if (con->file_started == 0) { char *c; int in_header = 0; int header_end = 0; int cp, eol = EOL_UNSET; size_t used = 0; - + buffer_append_string_buffer(hctx->response_header, hctx->response); - + /* nph (non-parsed headers) */ if (0 == strncmp(hctx->response_header->ptr, "HTTP/1.", 7)) in_header = 1; - + /* search for the \r\n\r\n or \n\n in the string */ for (c = hctx->response_header->ptr, cp = 0, used = hctx->response_header->used - 1; used; c++, cp++, used--) { if (*c == ':') in_header = 1; else if (*c == '\n') { if (in_header == 0) { /* got a response without a response header */ - + c = NULL; header_end = 1; break; } - + if (eol == EOL_UNSET) eol = EOL_N; - + if (*(c+1) == '\n') { header_end = 1; break; } - + } else if (used > 1 && *c == '\r' && *(c+1) == '\n') { if (in_header == 0) { /* got a response without a response header */ - + c = NULL; header_end = 1; break; } - + if (eol == EOL_UNSET) eol = EOL_RN; - + if (used > 3 && - *(c+2) == '\r' && + *(c+2) == '\r' && *(c+3) == '\n') { header_end = 1; break; } - + /* skip the \n */ c++; cp++; used--; } } - + if (header_end) { if (c == NULL) { /* no header, but a body */ - + if (con->request.http_version == HTTP_VERSION_1_1) { con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED; } - + http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used); joblist_append(srv, con); } else { size_t hlen = c - hctx->response_header->ptr + (eol == EOL_RN ? 4 : 2); size_t blen = hctx->response_header->used - hlen - 1; - + /* a small hack: terminate after at the second \r */ hctx->response_header->used = hlen + 1 - (eol == EOL_RN ? 2 : 1); hctx->response_header->ptr[hlen - (eol == EOL_RN ? 2 : 1)] = '\0'; - + /* parse the response header */ cgi_response_parse(srv, con, p, hctx->response_header, eol); - + /* enable chunked-transfer-encoding */ if (con->request.http_version == HTTP_VERSION_1_1 && !(con->parsed_response & HTTP_CONTENT_LENGTH)) { con->response.transfer_encoding = HTTP_TRANSFER_ENCODING_CHUNKED; } - + if ((hctx->response->used != hlen) && blen > 0) { http_chunk_append_mem(srv, con, c + (eol == EOL_RN ? 4: 2), blen + 1); joblist_append(srv, con); } } - + con->file_started = 1; } } else { http_chunk_append_mem(srv, con, hctx->response->ptr, hctx->response->used); joblist_append(srv, con); } - -#if 0 + +#if 0 log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), b->ptr); #endif } - + return FDEVENT_HANDLED_NOT_FINISHED; } @@ -470,45 +465,46 @@ pid_t pid; plugin_data *p; connection *con; - + if (NULL == hctx) return HANDLER_GO_ON; - + p = hctx->plugin_data; con = hctx->remote_conn; - + if (con->mode != p->id) return HANDLER_GO_ON; -#ifndef __WIN32 - +#ifndef _WIN32 + /* the connection to the browser went away, but we still have a connection - * to the CGI script + * to the CGI script * * close cgi-connection */ - + if (hctx->fd != -1) { /* close connection to the cgi-script */ fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); fdevent_unregister(srv->ev, hctx->fd); - + if (close(hctx->fd)) { log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno)); } - + hctx->fd = -1; hctx->fde_ndx = -1; } - + pid = hctx->pid; - + con->plugin_ctx[p->id] = NULL; - + /* is this a good idea ? */ cgi_handler_ctx_free(hctx); - + /* if waitpid hasn't been called by response.c yet, do it here */ if (pid) { /* check if the CGI-script is already gone */ +#ifndef _WIN32 switch(waitpid(pid, &status, WNOHANG)) { case 0: /* not finished yet */ @@ -519,19 +515,19 @@ case -1: /* */ if (errno == EINTR) break; - - /* - * errno == ECHILD happens if _subrequest catches the process-status before + + /* + * errno == ECHILD happens if _subrequest catches the process-status before * we have read the response of the cgi process - * + * * -> catch status * -> WAIT_FOR_EVENT * -> read response * -> we get here with waitpid == ECHILD - * + * */ if (errno == ECHILD) return HANDLER_GO_ON; - + log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno)); return HANDLER_ERROR; default: @@ -541,13 +537,13 @@ con->http_status = 500; con->mode = DIRECT; } - + if (WIFEXITED(status)) { #if 0 log_error_write(srv, __FILE__, __LINE__, "sd", "(debug) cgi exited fine, pid:", pid); #endif pid = 0; - + return HANDLER_GO_ON; } else { log_error_write(srv, __FILE__, __LINE__, "sd", "cgi died, pid:", pid); @@ -555,20 +551,20 @@ return HANDLER_GO_ON; } } - - + + kill(pid, SIGTERM); - +#endif /* cgi-script is still alive, queue the PID for removal */ cgi_pid_add(srv, p, pid); } -#endif +#endif return HANDLER_GO_ON; } static handler_t cgi_connection_close_callback(server *srv, connection *con, void *p_d) { plugin_data *p = p_d; - + return cgi_connection_close(srv, con->plugin_ctx[p->id]); } @@ -577,43 +573,43 @@ server *srv = (server *)s; handler_ctx *hctx = ctx; connection *con = hctx->remote_conn; - + joblist_append(srv, con); - + if (hctx->fd == -1) { log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), "invalid cgi-fd"); - + return HANDLER_ERROR; } - + if (revents & FDEVENT_IN) { switch (cgi_demux_response(srv, hctx)) { case FDEVENT_HANDLED_NOT_FINISHED: break; case FDEVENT_HANDLED_FINISHED: /* we are done */ - + #if 0 log_error_write(srv, __FILE__, __LINE__, "ddss", con->fd, hctx->fd, connection_get_state(con->state), "finished"); #endif cgi_connection_close(srv, hctx); - - /* if we get a IN|HUP and have read everything don't exec the close twice */ + + /* if we get a IN|HUP and have read everything don't exec the close twice */ return HANDLER_FINISHED; case FDEVENT_HANDLED_ERROR: connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST); con->http_status = 500; con->mode = DIRECT; - + log_error_write(srv, __FILE__, __LINE__, "s", "demuxer failed: "); break; } } - + if (revents & FDEVENT_OUT) { /* nothing to do */ } - + /* perhaps this issue is already handled */ if (revents & FDEVENT_HUP) { /* check if we still have a unfinished header package which is a body in reality */ @@ -623,54 +619,54 @@ http_chunk_append_mem(srv, con, hctx->response_header->ptr, hctx->response_header->used); joblist_append(srv, con); } - + if (con->file_finished == 0) { http_chunk_append_mem(srv, con, NULL, 0); joblist_append(srv, con); } - + con->file_finished = 1; - + if (chunkqueue_is_empty(con->write_queue)) { /* there is nothing left to write */ connection_set_state(srv, con, CON_STATE_RESPONSE_END); } else { /* used the write-handler to finish the request on demand */ - + } - + # if 0 log_error_write(srv, __FILE__, __LINE__, "sddd", "got HUP from cgi", con->fd, hctx->fd, revents); # endif - + /* rtsigs didn't liked the close */ cgi_connection_close(srv, hctx); } else if (revents & FDEVENT_ERR) { con->file_finished = 1; - + /* kill all connections to the cgi process */ cgi_connection_close(srv, hctx); #if 1 log_error_write(srv, __FILE__, __LINE__, "s", "cgi-FDEVENT_ERR"); -#endif +#endif return HANDLER_ERROR; } - + return HANDLER_FINISHED; } static int cgi_env_add(char_array *env, const char *key, size_t key_len, const char *val, size_t val_len) { char *dst; - + if (!key || !val) return -1; - + dst = malloc(key_len + val_len + 3); memcpy(dst, key, key_len); dst[key_len] = '='; /* add the \0 from the value */ memcpy(dst + key_len + 1, val, val_len + 1); - + if (env->size == 0) { env->size = 16; env->ptr = malloc(env->size * sizeof(*env->ptr)); @@ -678,45 +674,45 @@ env->size += 16; env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr)); } - + env->ptr[env->used++] = dst; - + return 0; } static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer *cgi_handler) { pid_t pid; - + #ifdef HAVE_IPV6 char b2[INET6_ADDRSTRLEN + 1]; #endif - + int to_cgi_fds[2]; int from_cgi_fds[2]; struct stat st; - -#ifndef __WIN32 - + +#ifndef _WIN32 + if (cgi_handler->used > 1) { /* stat the exec file */ if (-1 == (stat(cgi_handler->ptr, &st))) { - log_error_write(srv, __FILE__, __LINE__, "sbss", + log_error_write(srv, __FILE__, __LINE__, "sbss", "stat for cgi-handler", cgi_handler, "failed:", strerror(errno)); return -1; } } - + if (pipe(to_cgi_fds)) { log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed:", strerror(errno)); return -1; } - + if (pipe(from_cgi_fds)) { log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed:", strerror(errno)); return -1; } - + /* fork, execve */ switch (pid = fork()) { case 0: { @@ -730,22 +726,22 @@ char *c; const char *s; server_socket *srv_sock = con->srv_socket; - + /* move stdout to from_cgi_fd[1] */ close(STDOUT_FILENO); dup2(from_cgi_fds[1], STDOUT_FILENO); close(from_cgi_fds[1]); /* not needed */ close(from_cgi_fds[0]); - + /* move the stdin to to_cgi_fd[0] */ close(STDIN_FILENO); dup2(to_cgi_fds[0], STDIN_FILENO); close(to_cgi_fds[0]); /* not needed */ close(to_cgi_fds[1]); - - /* HACK: + + /* HACK: * this is not nice, but it works * * we feed the stderr of the CGI to our errorlog, if possible @@ -754,20 +750,20 @@ close(STDERR_FILENO); dup2(srv->errorlog_fd, STDERR_FILENO); } - + /* create environment */ env.ptr = NULL; env.size = 0; env.used = 0; - + cgi_env_add(&env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION)); if (!buffer_is_empty(con->server_name)) { cgi_env_add(&env, CONST_STR_LEN("SERVER_NAME"), CONST_BUF_LEN(con->server_name)); } else { #ifdef HAVE_IPV6 - s = inet_ntop(srv_sock->addr.plain.sa_family, - srv_sock->addr.plain.sa_family == AF_INET6 ? + s = inet_ntop(srv_sock->addr.plain.sa_family, + srv_sock->addr.plain.sa_family == AF_INET6 ? (const void *) &(srv_sock->addr.ipv6.sin6_addr) : (const void *) &(srv_sock->addr.ipv4.sin_addr), b2, sizeof(b2)-1); @@ -779,10 +775,10 @@ cgi_env_add(&env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1")); s = get_http_version_name(con->request.http_version); - + cgi_env_add(&env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s)); - - ltostr(buf, + + ltostr(buf, #ifdef HAVE_IPV6 ntohs(srv_sock->addr.plain.sa_family == AF_INET6 ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port) #else @@ -790,10 +786,10 @@ #endif ); cgi_env_add(&env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf)); - + #ifdef HAVE_IPV6 - s = inet_ntop(srv_sock->addr.plain.sa_family, - srv_sock->addr.plain.sa_family == AF_INET6 ? + s = inet_ntop(srv_sock->addr.plain.sa_family, + srv_sock->addr.plain.sa_family == AF_INET6 ? (const void *) &(srv_sock->addr.ipv6.sin6_addr) : (const void *) &(srv_sock->addr.ipv4.sin_addr), b2, sizeof(b2)-1); @@ -811,15 +807,18 @@ cgi_env_add(&env, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200")); if (!buffer_is_empty(con->uri.query)) { cgi_env_add(&env, CONST_STR_LEN("QUERY_STRING"), CONST_BUF_LEN(con->uri.query)); + } else { + /* set a empty QUERY_STRING */ + cgi_env_add(&env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN("")); } if (!buffer_is_empty(con->request.orig_uri)) { cgi_env_add(&env, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri)); } - - + + #ifdef HAVE_IPV6 - s = inet_ntop(con->dst_addr.plain.sa_family, - con->dst_addr.plain.sa_family == AF_INET6 ? + s = inet_ntop(con->dst_addr.plain.sa_family, + con->dst_addr.plain.sa_family == AF_INET6 ? (const void *) &(con->dst_addr.ipv6.sin6_addr) : (const void *) &(con->dst_addr.ipv4.sin_addr), b2, sizeof(b2)-1); @@ -828,7 +827,7 @@ #endif cgi_env_add(&env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s)); - ltostr(buf, + ltostr(buf, #ifdef HAVE_IPV6 ntohs(con->dst_addr.plain.sa_family == AF_INET6 ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port) #else @@ -836,19 +835,19 @@ #endif ); cgi_env_add(&env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf)); - + if (!buffer_is_empty(con->authed_user)) { cgi_env_add(&env, CONST_STR_LEN("REMOTE_USER"), CONST_BUF_LEN(con->authed_user)); } - + /* request.content_length < SSIZE_MAX, see request.c */ ltostr(buf, con->request.content_length); cgi_env_add(&env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf)); cgi_env_add(&env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(con->physical.path)); cgi_env_add(&env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path)); cgi_env_add(&env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root)); - + /* for valgrind */ if (NULL != (s = getenv("LD_PRELOAD"))) { cgi_env_add(&env, CONST_STR_LEN("LD_PRELOAD"), s, strlen(s)); @@ -863,24 +862,24 @@ cgi_env_add(&env, CONST_STR_LEN("SYSTEMROOT"), s, strlen(s)); } #endif - + for (n = 0; n < con->request.headers->used; n++) { data_string *ds; - + ds = (data_string *)con->request.headers->data[n]; - + if (ds->value->used && ds->key->used) { size_t j; - + buffer_reset(p->tmp_buf); - + if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) { buffer_copy_string(p->tmp_buf, "HTTP_"); p->tmp_buf->used--; /* strip \0 after HTTP_ */ } - + buffer_prepare_append(p->tmp_buf, ds->key->used + 2); - + for (j = 0; j < ds->key->used - 1; j++) { char cr = '_'; if (light_isalpha(ds->key->ptr[j])) { @@ -893,46 +892,46 @@ p->tmp_buf->ptr[p->tmp_buf->used++] = cr; } p->tmp_buf->ptr[p->tmp_buf->used++] = '\0'; - + cgi_env_add(&env, CONST_BUF_LEN(p->tmp_buf), CONST_BUF_LEN(ds->value)); } } - + for (n = 0; n < con->environment->used; n++) { data_string *ds; - + ds = (data_string *)con->environment->data[n]; - + if (ds->value->used && ds->key->used) { size_t j; - + buffer_reset(p->tmp_buf); - + buffer_prepare_append(p->tmp_buf, ds->key->used + 2); - + for (j = 0; j < ds->key->used - 1; j++) { - p->tmp_buf->ptr[p->tmp_buf->used++] = - isalpha((unsigned char)ds->key->ptr[j]) ? + p->tmp_buf->ptr[p->tmp_buf->used++] = + isalpha((unsigned char)ds->key->ptr[j]) ? toupper((unsigned char)ds->key->ptr[j]) : '_'; } p->tmp_buf->ptr[p->tmp_buf->used++] = '\0'; - + cgi_env_add(&env, CONST_BUF_LEN(p->tmp_buf), CONST_BUF_LEN(ds->value)); } } - + if (env.size == env.used) { env.size += 16; env.ptr = realloc(env.ptr, env.size * sizeof(*env.ptr)); } - + env.ptr[env.used] = NULL; - + /* set up args */ argc = 3; args = malloc(sizeof(*args) * argc); i = 0; - + if (cgi_handler->used > 1) { args[i++] = cgi_handler->ptr; } @@ -942,7 +941,7 @@ /* search for the last / */ if (NULL != (c = strrchr(con->physical.path->ptr, '/'))) { *c = '\0'; - + /* change to the physical directory */ if (-1 == chdir(con->physical.path->ptr)) { log_error_write(srv, __FILE__, __LINE__, "ssb", "chdir failed:", strerror(errno), con->physical.path); @@ -954,12 +953,12 @@ for (i = 3; i < 256; i++) { if (i != srv->errorlog_fd) close(i); } - + /* exec the cgi */ execve(args[0], args, env.ptr); - + log_error_write(srv, __FILE__, __LINE__, "sss", "CGI failed:", strerror(errno), args[0]); - + /* */ SEGFAULT(); break; @@ -974,11 +973,11 @@ close(from_cgi_fds[1]); close(to_cgi_fds[0]); - + if (con->request.content_length) { chunkqueue *cq = con->request_content_queue; chunk *c; - + assert(chunkqueue_length(cq) == (off_t)con->request.content_length); /* there is content to send */ @@ -993,16 +992,16 @@ if (-1 == c->file.fd && /* open the file if not already open */ -1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) { log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno)); - + close(from_cgi_fds[0]); close(to_cgi_fds[1]); return -1; } c->file.mmap.length = c->file.length; - + if (MAP_FAILED == (c->file.mmap.start = mmap(0, c->file.mmap.length, PROT_READ, MAP_SHARED, c->file.fd, 0))) { - log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ", + log_error_write(srv, __FILE__, __LINE__, "ssbd", "mmap failed: ", strerror(errno), c->file.name, c->file.fd); close(from_cgi_fds[0]); @@ -1012,7 +1011,7 @@ close(c->file.fd); c->file.fd = -1; - + /* chunk_reset() or chunk_free() will cleanup for us */ } @@ -1020,7 +1019,7 @@ switch(errno) { case ENOSPC: con->http_status = 507; - + break; default: con->http_status = 403; @@ -1033,7 +1032,7 @@ switch(errno) { case ENOSPC: con->http_status = 507; - + break; default: con->http_status = 403; @@ -1056,103 +1055,100 @@ } close(to_cgi_fds[1]); - + /* register PID and wait for them asyncronously */ con->mode = p->id; buffer_reset(con->physical.path); - + hctx = cgi_handler_ctx_init(); - + hctx->remote_conn = con; hctx->plugin_data = p; hctx->pid = pid; hctx->fd = from_cgi_fds[0]; hctx->fde_ndx = -1; - + con->plugin_ctx[p->id] = hctx; - + fdevent_register(srv->ev, hctx->fd, cgi_handle_fdevent, hctx); fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN); - + if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) { log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno)); - + fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); fdevent_unregister(srv->ev, hctx->fd); - + log_error_write(srv, __FILE__, __LINE__, "sd", "cgi close:", hctx->fd); - + close(hctx->fd); - + cgi_handler_ctx_free(hctx); - + con->plugin_ctx[p->id] = NULL; - + return -1; } - + break; } } - + return 0; #else return -1; #endif } -#define PATCH(x) \ - p->conf.x = s->x; static int mod_cgi_patch_connection(server *srv, connection *con, plugin_data *p) { size_t i, j; plugin_config *s = p->config_storage[0]; - - PATCH(cgi); - + + PATCH_OPTION(cgi); + /* skip the first, the global context */ for (i = 1; i < srv->config_context->used; i++) { data_config *dc = (data_config *)srv->config_context->data[i]; s = p->config_storage[i]; - + /* condition didn't match */ if (!config_check_cond(srv, con, dc)) continue; - + /* merge config */ for (j = 0; j < dc->value->used; j++) { data_unset *du = dc->value->data[j]; - + if (buffer_is_equal_string(du->key, CONST_STR_LEN("cgi.assign"))) { - PATCH(cgi); + PATCH_OPTION(cgi); } } } - + return 0; } -#undef PATCH URIHANDLER_FUNC(cgi_is_handled) { size_t k, s_len; plugin_data *p = p_d; buffer *fn = con->physical.path; - + if (fn->used == 0) return HANDLER_GO_ON; - + mod_cgi_patch_connection(srv, con, p); - + s_len = fn->used - 1; - + for (k = 0; k < p->conf.cgi->used; k++) { data_string *ds = (data_string *)p->conf.cgi->data[k]; size_t ct_len = ds->key->used - 1; - + if (ds->key->used == 0) continue; if (s_len < ct_len) continue; - + if (0 == strncmp(fn->ptr + s_len - ct_len, ds->key->ptr, ct_len)) { if (cgi_create_env(srv, con, p, ds->value)) { con->http_status = 500; - + buffer_reset(con->physical.path); return HANDLER_FINISHED; } @@ -1160,7 +1156,7 @@ break; } } - + return HANDLER_GO_ON; } @@ -1168,11 +1164,11 @@ plugin_data *p = p_d; size_t ndx; /* the trigger handle only cares about lonely PID which we have to wait for */ -#ifndef __WIN32 +#ifndef _WIN32 for (ndx = 0; ndx < p->cgi_pid.used; ndx++) { int status; - + switch(waitpid(p->cgi_pid.ptr[ndx], &status, WNOHANG)) { case 0: /* not finished yet */ @@ -1182,7 +1178,7 @@ break; case -1: log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno)); - + return HANDLER_ERROR; default: @@ -1193,16 +1189,16 @@ } else { log_error_write(srv, __FILE__, __LINE__, "s", "cgi died ?"); } - + cgi_pid_del(srv, p, p->cgi_pid.ptr[ndx]); - /* del modified the buffer structure + /* del modified the buffer structure * and copies the last entry to the current one * -> recheck the current index */ ndx--; } } -#endif +#endif return HANDLER_GO_ON; } @@ -1210,15 +1206,15 @@ int status; plugin_data *p = p_d; handler_ctx *hctx = con->plugin_ctx[p->id]; - + if (con->mode != p->id) return HANDLER_GO_ON; if (NULL == hctx) return HANDLER_GO_ON; - + #if 0 log_error_write(srv, __FILE__, __LINE__, "sdd", "subrequest, pid =", hctx, hctx->pid); -#endif +#endif if (hctx->pid == 0) return HANDLER_FINISHED; -#ifndef __WIN32 +#ifndef _WIN32 switch(waitpid(hctx->pid, &status, WNOHANG)) { case 0: /* we only have for events here if we don't have the header yet, @@ -1228,61 +1224,61 @@ return HANDLER_WAIT_FOR_EVENT; case -1: if (errno == EINTR) return HANDLER_WAIT_FOR_EVENT; - + if (errno == ECHILD && con->file_started == 0) { /* - * second round but still not response + * second round but still not response */ - return HANDLER_WAIT_FOR_EVENT; + return HANDLER_WAIT_FOR_EVENT; } - + log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno)); con->mode = DIRECT; con->http_status = 500; - + hctx->pid = 0; - + fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); fdevent_unregister(srv->ev, hctx->fd); - + if (close(hctx->fd)) { log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno)); } - + cgi_handler_ctx_free(hctx); - + con->plugin_ctx[p->id] = NULL; - + return HANDLER_FINISHED; default: - /* cgi process exited cleanly - * - * check if we already got the response + /* cgi process exited cleanly + * + * check if we already got the response */ - + if (!con->file_started) return HANDLER_WAIT_FOR_EVENT; - + if (WIFEXITED(status)) { /* nothing */ } else { log_error_write(srv, __FILE__, __LINE__, "s", "cgi died ?"); - + con->mode = DIRECT; con->http_status = 500; - + } - + hctx->pid = 0; - + fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); fdevent_unregister(srv->ev, hctx->fd); - + if (close(hctx->fd)) { log_error_write(srv, __FILE__, __LINE__, "sds", "cgi close failed ", hctx->fd, strerror(errno)); } - + cgi_handler_ctx_free(hctx); - + con->plugin_ctx[p->id] = NULL; return HANDLER_FINISHED; } @@ -1306,8 +1302,8 @@ p->init = mod_cgi_init; p->cleanup = mod_cgi_free; p->set_defaults = mod_fastcgi_set_defaults; - + p->data = NULL; - + return 0; } Property changes on: src/mod_cgi.c ___________________________________________________________________ Name: svn:eol-style + native Index: src/network_write.c =================================================================== --- src/network_write.c (.../tags/lighttpd-1.4.11) (revision 1159) +++ src/network_write.c (.../branches/lighttpd-merge-1.4.x) (revision 1159) @@ -1,11 +1,11 @@ #include #include -#include + #include #include -#include #include #include +#include #include "network.h" #include "fdevent.h" @@ -13,9 +13,12 @@ #include "stat_cache.h" #include "sys-socket.h" +#include "sys-files.h" #include "network_backends.h" +#ifdef USE_WRITE + #ifdef HAVE_SYS_FILIO_H # include #endif @@ -24,47 +27,86 @@ #include #endif -int network_write_chunkqueue_write(server *srv, connection *con, int fd, chunkqueue *cq) { +/** +* fill the chunkqueue will all the data that we can get +* +* this might be optimized into a readv() which uses the chunks +* as vectors +*/ +NETWORK_BACKEND_READ(read) { + int toread; + buffer *b; + off_t r; + + /* check how much we have to read */ + if (ioctl(fd, FIONREAD, &toread)) { + log_error_write(srv, __FILE__, __LINE__, "sd", + "ioctl failed: ", + fd); + return NETWORK_STATUS_FATAL_ERROR; + } + + if (toread == 0) return NETWORK_STATUS_WAIT_FOR_EVENT; + + /* + * our chunk queue is quiet large already + * + * let's buffer it to disk + */ + + b = chunkqueue_get_append_buffer(cq); + + buffer_prepare_copy(b, toread); + + if (-1 == (r = read(fd, b->ptr, toread))) { + log_error_write(srv, __FILE__, __LINE__, "sds", + "unexpected end-of-file (perhaps the proxy process died):", + fd, strerror(errno)); + return NETWORK_STATUS_FATAL_ERROR; + } + + /* this should be catched by the b > 0 above */ + assert(r); + b->used += r + 1; + b->ptr[b->used - 1] = '\0'; + + return NETWORK_STATUS_SUCCESS; +} + +NETWORK_BACKEND_WRITE(write) { chunk *c; size_t chunks_written = 0; - + for(c = cq->first; c; c = c->next) { int chunk_finished = 0; - + switch(c->type) { case MEM_CHUNK: { char * offset; size_t toSend; ssize_t r; - + if (c->mem->used == 0) { chunk_finished = 1; break; } - + offset = c->mem->ptr + c->offset; toSend = c->mem->used - 1 - c->offset; -#ifdef __WIN32 - if ((r = send(fd, offset, toSend, 0)) < 0) { - log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed: ", strerror(errno), fd); - - return -1; - } -#else + if ((r = write(fd, offset, toSend)) < 0) { log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed: ", strerror(errno), fd); - - return -1; + + return NETWORK_STATUS_FATAL_ERROR; } -#endif - + c->offset += r; cq->bytes_out += r; - + if (c->offset == (off_t)c->mem->used - 1) { chunk_finished = 1; } - + break; } case FILE_CHUNK: { @@ -76,93 +118,89 @@ size_t toSend; stat_cache_entry *sce = NULL; int ifd; - + if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) { log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), c->file.name); - return -1; + return NETWORK_STATUS_FATAL_ERROR; } - + offset = c->file.start + c->offset; toSend = c->file.length - c->offset; - + if (offset > sce->st.st_size) { log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name); - - return -1; + + return NETWORK_STATUS_FATAL_ERROR; } if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) { log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno)); - - return -1; + + return NETWORK_STATUS_FATAL_ERROR; } - + #if defined USE_MMAP if (MAP_FAILED == (p = mmap(0, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) { log_error_write(srv, __FILE__, __LINE__, "ss", "mmap failed: ", strerror(errno)); close(ifd); - - return -1; + + return NETWORK_STATUS_FATAL_ERROR; } close(ifd); if ((r = write(fd, p + offset, toSend)) <= 0) { log_error_write(srv, __FILE__, __LINE__, "ss", "write failed: ", strerror(errno)); munmap(p, sce->st.st_size); - return -1; + return NETWORK_STATUS_FATAL_ERROR; } - + munmap(p, sce->st.st_size); #else buffer_prepare_copy(srv->tmp_buf, toSend); - + lseek(ifd, offset, SEEK_SET); if (-1 == (toSend = read(ifd, srv->tmp_buf->ptr, toSend))) { log_error_write(srv, __FILE__, __LINE__, "ss", "read: ", strerror(errno)); close(ifd); - - return -1; + + return NETWORK_STATUS_FATAL_ERROR; } close(ifd); if (-1 == (r = send(fd, srv->tmp_buf->ptr, toSend, 0))) { log_error_write(srv, __FILE__, __LINE__, "ss", "write: ", strerror(errno)); - - return -1; + + return NETWORK_STATUS_FATAL_ERROR; } #endif c->offset += r; cq->bytes_out += r; - + if (c->offset == c->file.length) { chunk_finished = 1; } - + break; } default: - + log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known"); - - return -1; + + return NETWORK_STATUS_FATAL_ERROR; } - + if (!chunk_finished) { /* not finished yet */ - + break; } - + chunks_written++; } - return chunks_written; + return NETWORK_STATUS_SUCCESS; } -#if 0 -network_write_init(void) { - p->write = network_write_write_chunkset; -} #endif Property changes on: src/network_write.c ___________________________________________________________________ Name: svn:eol-style + native Index: src/joblist.c =================================================================== --- src/joblist.c (.../tags/lighttpd-1.4.11) (revision 1159) +++ src/joblist.c (.../branches/lighttpd-merge-1.4.x) (revision 1159) @@ -7,7 +7,7 @@ int joblist_append(server *srv, connection *con) { if (con->in_joblist) return 0; - + if (srv->joblist->size == 0) { srv->joblist->size = 16; srv->joblist->ptr = malloc(sizeof(*srv->joblist->ptr) * srv->joblist->size); @@ -15,15 +15,15 @@ srv->joblist->size += 16; srv->joblist->ptr = realloc(srv->joblist->ptr, sizeof(*srv->joblist->ptr) * srv->joblist->size); } - + srv->joblist->ptr[srv->joblist->used++] = con; - + return 0; } void joblist_free(server *srv, connections *joblist) { UNUSED(srv); - + free(joblist->ptr); free(joblist); } @@ -31,14 +31,14 @@ connection *fdwaitqueue_unshift(server *srv, connections *fdwaitqueue) { connection *con; UNUSED(srv); - - + + if (fdwaitqueue->used == 0) return NULL; - + con = fdwaitqueue->ptr[0]; - + memmove(fdwaitqueue->ptr, &(fdwaitqueue->ptr[1]), --fdwaitqueue->used * sizeof(*(fdwaitqueue->ptr))); - + return con; } @@ -50,9 +50,9 @@ srv->fdwaitqueue->size += 16; srv->fdwaitqueue->ptr = realloc(srv->fdwaitqueue->ptr, sizeof(*(srv->fdwaitqueue->ptr)) * srv->fdwaitqueue->size); } - + srv->fdwaitqueue->ptr[srv->fdwaitqueue->used++] = con; - + return 0; } Property changes on: src/joblist.c ___________________________________________________________________ Name: svn:eol-style + native Index: src/mod_cml.c =================================================================== --- src/mod_cml.c (.../tags/lighttpd-1.4.11) (revision 1159) +++ src/mod_cml.c (.../branches/lighttpd-merge-1.4.x) (revision 1159) @@ -4,7 +4,6 @@ #include #include #include -#include #include #include "buffer.h" @@ -20,50 +19,50 @@ /* init the plugin data */ INIT_FUNC(mod_cml_init) { plugin_data *p; - + p = calloc(1, sizeof(*p)); - + p->basedir = buffer_init(); p->baseurl = buffer_init(); p->trigger_handler = buffer_init(); - + return p; } /* detroy the plugin data */ FREE_FUNC(mod_cml_free) { plugin_data *p = p_d; - + UNUSED(srv); if (!p) return HANDLER_GO_ON; - + if (p->config_storage) { size_t i; for (i = 0; i < srv->config_context->used; i++) { plugin_config *s = p->config_storage[i]; - + buffer_free(s->ext); - + buffer_free(s->mc_namespace); buffer_free(s->power_magnet); array_free(s->mc_hosts); - + #if defined(HAVE_MEMCACHE_H) if (s->mc) mc_free(s->mc); #endif - + free(s); } free(p->config_storage); } - + buffer_free(p->trigger_handler); buffer_free(p->basedir); buffer_free(p->baseurl); - + free(p); - + return HANDLER_GO_ON; } @@ -72,22 +71,22 @@ SETDEFAULTS_FUNC(mod_cml_set_defaults) { plugin_data *p = p_d; size_t i = 0; - - config_values_t cv[] = { + + config_values_t cv[] = { { "cml.extension", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ { "cml.memcache-hosts", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */ { "cml.memcache-namespace", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */ { "cml.power-magnet", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } }; - + if (!p) return HANDLER_ERROR; - + p->config_storage = malloc(srv->config_context->used * sizeof(specific_config *)); - + for (i = 0; i < srv->config_context->used; i++) { plugin_config *s; - + s = malloc(sizeof(plugin_config)); s->ext = buffer_init(); s->mc_hosts = array_init(); @@ -96,87 +95,84 @@ #if defined(HAVE_MEMCACHE_H) s->mc = NULL; #endif - + cv[0].destination = s->ext; cv[1].destination = s->mc_hosts; cv[2].destination = s->mc_namespace; cv[3].destination = s->power_magnet; - + p->config_storage[i] = s; - + if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) { return HANDLER_ERROR; } - + if (s->mc_hosts->used) { #if defined(HAVE_MEMCACHE_H) size_t k; s->mc = mc_new(); - + for (k = 0; k < s->mc_hosts->used; k++) { data_string *ds = (data_string *)s->mc_hosts->data[k]; - + if (0 != mc_server_add4(s->mc, ds->value->ptr)) { - log_error_write(srv, __FILE__, __LINE__, "sb", - "connection to host failed:", + log_error_write(srv, __FILE__, __LINE__, "sb", + "connection to host failed:", ds->value); - + return HANDLER_ERROR; } } #else - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "memcache support is not compiled in but cml.memcache-hosts is set, aborting"); return HANDLER_ERROR; #endif } } - + return HANDLER_GO_ON; } -#define PATCH(x) \ - p->conf.x = s->x; static int mod_cml_patch_connection(server *srv, connection *con, plugin_data *p) { size_t i, j; plugin_config *s = p->config_storage[0]; - - PATCH(ext); + + PATCH_OPTION(ext); #if defined(HAVE_MEMCACHE_H) - PATCH(mc); + PATCH_OPTION(mc); #endif - PATCH(mc_namespace); - PATCH(power_magnet); - + PATCH_OPTION(mc_namespace); + PATCH_OPTION(power_magnet); + /* skip the first, the global context */ for (i = 1; i < srv->config_context->used; i++) { data_config *dc = (data_config *)srv->config_context->data[i]; s = p->config_storage[i]; - + /* condition didn't match */ if (!config_check_cond(srv, con, dc)) continue; - + /* merge config */ for (j = 0; j < dc->value->used; j++) { data_unset *du = dc->value->data[j]; - + if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.extension"))) { - PATCH(ext); + PATCH_OPTION(ext); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.memcache-hosts"))) { #if defined(HAVE_MEMCACHE_H) - PATCH(mc); + PATCH_OPTION(mc); #endif } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.memcache-namespace"))) { - PATCH(mc_namespace); + PATCH_OPTION(mc_namespace); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.power-magnet"))) { - PATCH(power_magnet); + PATCH_OPTION(power_magnet); } } } - + return 0; } -#undef PATCH int cache_call_lua(server *srv, connection *con, plugin_data *p, buffer *cml_file) { buffer *b; @@ -187,57 +183,57 @@ b = p->baseurl; buffer_copy_string_buffer(b, con->uri.path); for (c = b->ptr + b->used - 1; c > b->ptr && *c != '/'; c--); - + if (*c == '/') { b->used = c - b->ptr + 2; *(c+1) = '\0'; } - + b = p->basedir; buffer_copy_string_buffer(b, con->physical.path); for (c = b->ptr + b->used - 1; c > b->ptr && *c != '/'; c--); - + if (*c == '/') { b->used = c - b->ptr + 2; *(c+1) = '\0'; } - + /* prepare variables * - cookie-based * - get-param-based */ - + return cache_parse_lua(srv, con, p, cml_file); - + } URIHANDLER_FUNC(mod_cml_power_magnet) { plugin_data *p = p_d; - + mod_cml_patch_connection(srv, con, p); - + buffer_reset(p->basedir); buffer_reset(p->baseurl); buffer_reset(p->trigger_handler); if (buffer_is_empty(p->conf.power_magnet)) return HANDLER_GO_ON; - - /* + + /* * power-magnet: * cml.power-magnet = server.docroot + "/rewrite.cml" * * is called on EACH request, take the original REQUEST_URI and modifies the - * request header as neccesary. + * request header as neccesary. * * First use: * if file_exists("/maintainance.html") { * output_include = ( "/maintainance.html" ) - * return CACHE_HIT + * return CACHE_HIT * } * * as we only want to rewrite HTML like requests we should cover it in a conditional - * + * * */ switch(cache_call_lua(srv, con, p, p->conf.power_magnet)) { @@ -266,20 +262,20 @@ URIHANDLER_FUNC(mod_cml_is_handled) { plugin_data *p = p_d; - + if (buffer_is_empty(con->physical.path)) return HANDLER_ERROR; - + mod_cml_patch_connection(srv, con, p); - + buffer_reset(p->basedir); buffer_reset(p->baseurl); buffer_reset(p->trigger_handler); if (buffer_is_empty(p->conf.ext)) return HANDLER_GO_ON; - + if (!buffer_is_equal_right_len(con->physical.path, p->conf.ext, p->conf.ext->used - 1)) { return HANDLER_GO_ON; - } + } switch(cache_call_lua(srv, con, p, con->physical.path)) { case -1: @@ -311,15 +307,15 @@ int mod_cml_plugin_init(plugin *p) { p->version = LIGHTTPD_VERSION_ID; p->name = buffer_init_string("cache"); - + p->init = mod_cml_init; p->cleanup = mod_cml_free; p->set_defaults = mod_cml_set_defaults; - + p->handle_subrequest_start = mod_cml_is_handled; p->handle_physical = mod_cml_power_magnet; - + p->data = NULL; - + return 0; } Property changes on: src/mod_cml.c ___________________________________________________________________ Name: svn:eol-style + native Property changes on: src/joblist.h ___________________________________________________________________ Name: svn:eol-style + native Index: src/mod_secure_download.c =================================================================== --- src/mod_secure_download.c (.../tags/lighttpd-1.4.11) (revision 1159) +++ src/mod_secure_download.c (.../branches/lighttpd-merge-1.4.x) (revision 1159) @@ -25,7 +25,7 @@ #ifdef USE_OPENSSL #define IN const #else -#define IN +#define IN #endif #define OUT @@ -36,28 +36,28 @@ buffer *doc_root; buffer *secret; buffer *uri_prefix; - + unsigned short timeout; } plugin_config; typedef struct { PLUGIN_DATA; - + buffer *md5; - + plugin_config **config_storage; - - plugin_config conf; + + plugin_config conf; } plugin_data; /* init the plugin data */ INIT_FUNC(mod_secdownload_init) { plugin_data *p; - + p = calloc(1, sizeof(*p)); - + p->md5 = buffer_init(); - + return p; } @@ -65,27 +65,27 @@ FREE_FUNC(mod_secdownload_free) { plugin_data *p = p_d; UNUSED(srv); - + if (!p) return HANDLER_GO_ON; - + if (p->config_storage) { size_t i; for (i = 0; i < srv->config_context->used; i++) { plugin_config *s = p->config_storage[i]; - + buffer_free(s->secret); buffer_free(s->doc_root); buffer_free(s->uri_prefix); - + free(s); } free(p->config_storage); } - + buffer_free(p->md5); - + free(p); - + return HANDLER_GO_ON; } @@ -94,108 +94,104 @@ SETDEFAULTS_FUNC(mod_secdownload_set_defaults) { plugin_data *p = p_d; size_t i = 0; - - config_values_t cv[] = { + + config_values_t cv[] = { { "secdownload.secret", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ { "secdownload.document-root", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 1 */ { "secdownload.uri-prefix", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */ { "secdownload.timeout", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 3 */ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } }; - + if (!p) return HANDLER_ERROR; - + p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *)); - + for (i = 0; i < srv->config_context->used; i++) { plugin_config *s; - + s = calloc(1, sizeof(plugin_config)); s->secret = buffer_init(); s->doc_root = buffer_init(); s->uri_prefix = buffer_init(); s->timeout = 60; - + cv[0].destination = s->secret; cv[1].destination = s->doc_root; cv[2].destination = s->uri_prefix; cv[3].destination = &(s->timeout); - + p->config_storage[i] = s; - + if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) { return HANDLER_ERROR; } } - + return HANDLER_GO_ON; } /** * checks if the supplied string is a MD5 string - * + * * @param str a possible MD5 string * @return if the supplied string is a valid MD5 string 1 is returned otherwise 0 */ int is_hex_len(const char *str, size_t len) { size_t i; - + if (NULL == str) return 0; - + for (i = 0; i < len && *str; i++, str++) { /* illegal characters */ if (!((*str >= '0' && *str <= '9') || (*str >= 'a' && *str <= 'f') || - (*str >= 'A' && *str <= 'F')) + (*str >= 'A' && *str <= 'F')) ) { return 0; } } - + return i == len; } -#define PATCH(x) \ - p->conf.x = s->x; static int mod_secdownload_patch_connection(server *srv, connection *con, plugin_data *p) { size_t i, j; plugin_config *s = p->config_storage[0]; - - PATCH(secret); - PATCH(doc_root); - PATCH(uri_prefix); - PATCH(timeout); - + + PATCH_OPTION(secret); + PATCH_OPTION(doc_root); + PATCH_OPTION(uri_prefix); + PATCH_OPTION(timeout); + /* skip the first, the global context */ for (i = 1; i < srv->config_context->used; i++) { data_config *dc = (data_config *)srv->config_context->data[i]; s = p->config_storage[i]; - + /* condition didn't match */ if (!config_check_cond(srv, con, dc)) continue; - + /* merge config */ for (j = 0; j < dc->value->used; j++) { data_unset *du = dc->value->data[j]; - + if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.secret"))) { - PATCH(secret); + PATCH_OPTION(secret); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.document-root"))) { - PATCH(doc_root); + PATCH_OPTION(doc_root); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.uri-prefix"))) { - PATCH(uri_prefix); + PATCH_OPTION(uri_prefix); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.timeout"))) { - PATCH(timeout); + PATCH_OPTION(timeout); } } } - + return 0; } -#undef PATCH - URIHANDLER_FUNC(mod_secdownload_uri_handler) { plugin_data *p = p_d; MD5_CTX Md5Ctx; @@ -203,88 +199,88 @@ const char *rel_uri, *ts_str, *md5_str; time_t ts = 0; size_t i; - + if (con->uri.path->used == 0) return HANDLER_GO_ON; - + mod_secdownload_patch_connection(srv, con, p); if (buffer_is_empty(p->conf.uri_prefix)) return HANDLER_GO_ON; - + if (buffer_is_empty(p->conf.secret)) { log_error_write(srv, __FILE__, __LINE__, "s", "secdownload.secret has to be set"); return HANDLER_ERROR; } - + if (buffer_is_empty(p->conf.doc_root)) { log_error_write(srv, __FILE__, __LINE__, "s", "secdownload.document-root has to be set"); return HANDLER_ERROR; } - - /* + + /* * /[a-f0-9]{32}/[a-f0-9]{8}/ */ - + if (0 != strncmp(con->uri.path->ptr, p->conf.uri_prefix->ptr, p->conf.uri_prefix->used - 1)) return HANDLER_GO_ON; - + md5_str = con->uri.path->ptr + p->conf.uri_prefix->used - 1; - + if (!is_hex_len(md5_str, 32)) return HANDLER_GO_ON; if (*(md5_str + 32) != '/') return HANDLER_GO_ON; - + ts_str = md5_str + 32 + 1; - + if (!is_hex_len(ts_str, 8)) return HANDLER_GO_ON; if (*(ts_str + 8) != '/') return HANDLER_GO_ON; - + for (i = 0; i < 8; i++) { ts = (ts << 4) + hex2int(*(ts_str + i)); } - + /* timed-out */ - if (srv->cur_ts - ts > p->conf.timeout || + if (srv->cur_ts - ts > p->conf.timeout || srv->cur_ts - ts < -p->conf.timeout) { con->http_status = 408; - + return HANDLER_FINISHED; } - + rel_uri = ts_str + 8; - - /* checking MD5 - * + + /* checking MD5 + * * */ - + buffer_copy_string_buffer(p->md5, p->conf.secret); buffer_append_string(p->md5, rel_uri); buffer_append_string_len(p->md5, ts_str, 8); - + MD5_Init(&Md5Ctx); MD5_Update(&Md5Ctx, (unsigned char *)p->md5->ptr, p->md5->used - 1); MD5_Final(HA1, &Md5Ctx); - + buffer_copy_string_hex(p->md5, (char *)HA1, 16); - + if (0 != strncmp(md5_str, p->md5->ptr, 32)) { con->http_status = 403; - - log_error_write(srv, __FILE__, __LINE__, "sss", + + log_error_write(srv, __FILE__, __LINE__, "sss", "md5 invalid:", md5_str, p->md5->ptr); - + return HANDLER_FINISHED; } - + /* starting with the last / we should have relative-path to the docroot */ - + buffer_copy_string_buffer(con->physical.doc_root, p->conf.doc_root); buffer_copy_string(con->physical.rel_path, rel_uri); buffer_copy_string_buffer(con->physical.path, con->physical.doc_root); buffer_append_string_buffer(con->physical.path, con->physical.rel_path); - + return HANDLER_GO_ON; } @@ -293,13 +289,13 @@ int mod_secdownload_plugin_init(plugin *p) { p->version = LIGHTTPD_VERSION_ID; p->name = buffer_init_string("secdownload"); - + p->init = mod_secdownload_init; p->handle_physical = mod_secdownload_uri_handler; p->set_defaults = mod_secdownload_set_defaults; p->cleanup = mod_secdownload_free; - + p->data = NULL; - + return 0; } Property changes on: src/mod_secure_download.c ___________________________________________________________________ Name: svn:eol-style + native Index: src/connections-glue.c =================================================================== --- src/connections-glue.c (.../tags/lighttpd-1.4.11) (revision 1159) +++ src/connections-glue.c (.../branches/lighttpd-merge-1.4.x) (revision 1159) @@ -13,7 +13,7 @@ case CON_STATE_REQUEST_END: return "req-end"; case CON_STATE_RESPONSE_START: return "resp-start"; case CON_STATE_RESPONSE_END: return "resp-end"; - default: return "(unknown)"; + default: return "(unknown)"; } } @@ -30,15 +30,15 @@ case CON_STATE_REQUEST_END: return "Q"; case CON_STATE_RESPONSE_START: return "s"; case CON_STATE_RESPONSE_END: return "S"; - default: return "x"; + default: return "x"; } } int connection_set_state(server *srv, connection *con, connection_state_t state) { UNUSED(srv); - + con->state = state; - + return 0; } Property changes on: src/connections-glue.c ___________________________________________________________________ Name: svn:eol-style + native Index: src/array.c =================================================================== --- src/array.c (.../tags/lighttpd-1.4.11) (revision 1159) +++ src/array.c (.../branches/lighttpd-merge-1.4.x) (revision 1159) @@ -11,12 +11,12 @@ array *array_init(void) { array *a; - + a = calloc(1, sizeof(*a)); assert(a); - + a->next_power_of_2 = 1; - + return a; } @@ -43,29 +43,29 @@ void array_free(array *a) { size_t i; if (!a) return; - + if (!a->is_weakref) { for (i = 0; i < a->size; i++) { if (a->data[i]) a->data[i]->free(a->data[i]); } } - + if (a->data) free(a->data); if (a->sorted) free(a->sorted); - + free(a); } void array_reset(array *a) { size_t i; if (!a) return; - + if (!a->is_weakref) { for (i = 0; i < a->used; i++) { a->data[i]->reset(a->data[i]); } } - + a->used = 0; } @@ -84,20 +84,20 @@ static int array_get_index(array *a, const char *key, size_t keylen, int *rndx) { int ndx = -1; int i, pos = 0; - + if (key == NULL) return -1; - + /* try to find the string */ for (i = pos = a->next_power_of_2 / 2; ; i >>= 1) { int cmp; - + if (pos < 0) { pos += i; } else if (pos >= (int)a->used) { pos -= i; } else { cmp = buffer_caseless_compare(key, keylen, a->data[a->sorted[pos]]->key->ptr, a->data[a->sorted[pos]]->key->used); - + if (cmp == 0) { /* found */ ndx = a->sorted[pos]; @@ -110,46 +110,46 @@ } if (i == 0) break; } - + if (rndx) *rndx = pos; - + return ndx; } data_unset *array_get_element(array *a, const char *key) { int ndx; - + if (-1 != (ndx = array_get_index(a, key, strlen(key) + 1, NULL))) { /* found, leave here */ - + return a->data[ndx]; - } - + } + return NULL; } data_unset *array_get_unused_element(array *a, data_type_t t) { data_unset *ds = NULL; - + UNUSED(t); if (a->size == 0) return NULL; - + if (a->used == a->size) return NULL; if (a->data[a->used]) { ds = a->data[a->used]; - + a->data[a->used] = NULL; } - + return ds; } /* replace or insert data, return the old one with the same key */ data_unset *array_replace(array *a, data_unset *du) { int ndx; - + if (-1 == (ndx = array_get_index(a, du->key->ptr, du->key->used, NULL))) { array_insert_unique(a, du); return NULL; @@ -164,13 +164,13 @@ int ndx = -1; int pos = 0; size_t j; - - /* generate unique index if neccesary */ + + /* generate unique index if necessary */ if (str->key->used == 0 || str->is_index_key) { buffer_copy_long(str->key, a->unique_ndx++); str->is_index_key = 1; } - + /* try to find the string */ if (-1 != (ndx = array_get_index(a, str->key->ptr, str->key->used, &pos))) { /* found, leave here */ @@ -181,14 +181,14 @@ } return 0; } - + /* insert */ - + if (a->used+1 > INT_MAX) { /* we can't handle more then INT_MAX entries: see array_get_index() */ return -1; } - + if (a->size == 0) { a->size = 16; a->data = malloc(sizeof(*a->data) * a->size); @@ -204,27 +204,27 @@ assert(a->sorted); for (j = a->used; j < a->size; j++) a->data[j] = NULL; } - + ndx = (int) a->used; - + a->data[a->used++] = str; - + if (pos != ndx && - ((pos < 0) || + ((pos < 0) || buffer_caseless_compare(str->key->ptr, str->key->used, a->data[a->sorted[pos]]->key->ptr, a->data[a->sorted[pos]]->key->used) > 0)) { pos++; - } - - /* move everything on step to the right */ + } + + /* move everything one step to the right */ if (pos != ndx) { memmove(a->sorted + (pos + 1), a->sorted + (pos), (ndx - pos) * sizeof(*a->sorted)); } - + /* insert */ a->sorted[pos] = ndx; - + if (a->next_power_of_2 == (size_t)ndx) a->next_power_of_2 <<= 1; - + return 0; } @@ -254,7 +254,7 @@ size_t i; size_t maxlen; int oneline = 1; - + if (a->used > 5) { oneline = 0; } @@ -314,7 +314,7 @@ } array_print_indent(depth); fprintf(stderr, ")"); - + return 0; } @@ -323,47 +323,47 @@ array *a; data_string *ds; data_count *dc; - + UNUSED(argc); UNUSED(argv); a = array_init(); - + ds = data_string_init(); buffer_copy_string(ds->key, "abc"); buffer_copy_string(ds->value, "alfrag"); - + array_insert_unique(a, (data_unset *)ds); - + ds = data_string_init(); buffer_copy_string(ds->key, "abc"); buffer_copy_string(ds->value, "hameplman"); - + array_insert_unique(a, (data_unset *)ds); - + ds = data_string_init(); buffer_copy_string(ds->key, "123"); buffer_copy_string(ds->value, "alfrag"); - + array_insert_unique(a, (data_unset *)ds); - + dc = data_count_init(); buffer_copy_string(dc->key, "def"); - + array_insert_unique(a, (data_unset *)dc); - + dc = data_count_init(); buffer_copy_string(dc->key, "def"); - + array_insert_unique(a, (data_unset *)dc); - + array_print(a, 0); - + array_free(a); - + fprintf(stderr, "%d\n", buffer_caseless_compare(CONST_STR_LEN("Content-Type"), CONST_STR_LEN("Content-type"))); - + return 0; } #endif Property changes on: src/array.c ___________________________________________________________________ Name: svn:eol-style + native Index: src/mod_cml.h =================================================================== --- src/mod_cml.h (.../tags/lighttpd-1.4.11) (revision 1159) +++ src/mod_cml.h (.../branches/lighttpd-merge-1.4.x) (revision 1159) @@ -16,10 +16,10 @@ typedef struct { buffer *ext; - + array *mc_hosts; buffer *mc_namespace; -#if defined(HAVE_MEMCACHE_H) +#if defined(HAVE_MEMCACHE_H) struct memcache *mc; #endif buffer *power_magnet; @@ -27,15 +27,15 @@ typedef struct { PLUGIN_DATA; - + buffer *basedir; buffer *baseurl; - + buffer *trigger_handler; - + plugin_config **config_storage; - - plugin_config conf; + + plugin_config conf; } plugin_data; int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn); Property changes on: src/mod_cml.h ___________________________________________________________________ Name: svn:eol-style + native Index: src/base.h =================================================================== --- src/base.h (.../tags/lighttpd-1.4.11) (revision 1159) +++ src/base.h (.../branches/lighttpd-merge-1.4.x) (revision 1159) @@ -2,7 +2,6 @@ #define _BASE_H_ #include -#include #include #ifdef HAVE_CONFIG_H @@ -26,10 +25,9 @@ #include "sys-socket.h" #include "splaytree.h" - #if defined HAVE_LIBSSL && defined HAVE_OPENSSL_SSL_H # define USE_OPENSSL -# include +# include #endif #ifdef HAVE_FAM_H @@ -40,10 +38,6 @@ # define O_BINARY 0 #endif -#ifndef O_LARGEFILE -# define O_LARGEFILE 0 -#endif - #ifndef SIZE_MAX # ifdef SIZE_T_MAX # define SIZE_MAX SIZE_T_MAX @@ -70,7 +64,8 @@ /* solaris and NetBSD 1.3.x again */ #if (!defined(HAVE_STDINT_H)) && (!defined(HAVE_INTTYPES_H)) && (!defined(uint32_t)) -# define uint32_t u_int32_t +/* # define uint32_t u_int32_t */ +typedef unsigned __int32 uint32_t; #endif @@ -80,24 +75,24 @@ #include "settings.h" -typedef enum { T_CONFIG_UNSET, - T_CONFIG_STRING, - T_CONFIG_SHORT, - T_CONFIG_BOOLEAN, - T_CONFIG_ARRAY, - T_CONFIG_LOCAL, +typedef enum { T_CONFIG_UNSET, + T_CONFIG_STRING, + T_CONFIG_SHORT, + T_CONFIG_BOOLEAN, + T_CONFIG_ARRAY, + T_CONFIG_LOCAL, T_CONFIG_DEPRECATED } config_values_type_t; -typedef enum { T_CONFIG_SCOPE_UNSET, - T_CONFIG_SCOPE_SERVER, +typedef enum { T_CONFIG_SCOPE_UNSET, + T_CONFIG_SCOPE_SERVER, T_CONFIG_SCOPE_CONNECTION } config_scope_type_t; typedef struct { const char *key; void *destination; - + config_values_type_t type; config_scope_type_t scope; } config_values_t; @@ -142,40 +137,40 @@ /* the request-line */ buffer *request; buffer *uri; - + buffer *orig_uri; - + http_method_t http_method; http_version_t http_version; - + buffer *request_line; - + /* strings to the header */ buffer *http_host; /* not alloced */ const char *http_range; const char *http_content_type; const char *http_if_modified_since; const char *http_if_none_match; - + array *headers; - + /* CONTENT */ size_t content_length; /* returned by strtoul() */ - + /* internal representation */ int accept_encoding; - + /* internal */ buffer *pathinfo; } request; typedef struct { off_t content_length; - int keep_alive; /* used by the subrequests in proxy, cgi and fcgi to say the subrequest was keep-alive or not */ - + int keep_alive; /* used by the subrequests in proxy, cgi and fcgi to say whether the subrequest was keep-alive or not */ + array *headers; - - enum { + + enum { HTTP_TRANSFER_ENCODING_IDENTITY, HTTP_TRANSFER_ENCODING_CHUNKED } transfer_encoding; } response; @@ -191,21 +186,21 @@ typedef struct { buffer *path; buffer *basedir; /* path = "(basedir)(.*)" */ - + buffer *doc_root; /* path = doc_root + rel_path */ buffer *rel_path; - + buffer *etag; } physical; typedef struct { buffer *name; buffer *etag; - + struct stat st; - + time_t stat_ts; - + #ifdef HAVE_FAM_H int dir_version; int dir_ndx; @@ -215,8 +210,8 @@ } stat_cache_entry; typedef struct { - splay_tree *files; /* the nodes of the tree are stat_cache_entry's */ - + splay_tree *files; /* the nodes of the tree are stat_cache_entries */ + buffer *dir_name; /* for building the dirname from the filename */ #ifdef HAVE_FAM_H splay_tree *dirs; /* the nodes of the tree are fam_dir_entry */ @@ -228,7 +223,7 @@ typedef struct { array *mimetypes; - + /* virtual-servers */ buffer *document_root; buffer *server_name; @@ -236,7 +231,7 @@ buffer *server_tag; buffer *dirlist_encoding; buffer *errorfile_prefix; - + unsigned short max_keep_alive_requests; unsigned short max_keep_alive_idle; unsigned short max_read_idle; @@ -244,16 +239,17 @@ unsigned short use_xattr; unsigned short follow_symlink; unsigned short range_requests; - + /* debug */ - + unsigned short log_file_not_found; unsigned short log_request_header; unsigned short log_request_handling; unsigned short log_response_header; unsigned short log_condition_handling; - - + unsigned short log_condition_cache_handling; + + /* server wide */ buffer *ssl_pemfile; buffer *ssl_ca_file; @@ -268,22 +264,22 @@ /* configside */ unsigned short global_kbytes_per_second; /* */ - off_t global_bytes_per_second_cnt; + off_t global_bytes_per_second_cnt; /* server-wide traffic-shaper - * + * * each context has the counter which is inited once - * a second by the global_kbytes_per_second config-var + * per second by the global_kbytes_per_second config-var * * as soon as global_kbytes_per_second gets below 0 * the connected conns are "offline" a little bit * * the problem: - * we somehow have to loose our "we are writable" signal + * we somehow have to lose our "we are writable" signal * on the way. - * + * */ off_t *global_bytes_per_second_cnt_ptr; /* */ - + #ifdef USE_OPENSSL SSL_CTX *ssl_ctx; #endif @@ -291,18 +287,18 @@ /* the order of the items should be the same as they are processed * read before write as we use this later */ -typedef enum { - CON_STATE_CONNECT, - CON_STATE_REQUEST_START, - CON_STATE_READ, - CON_STATE_REQUEST_END, - CON_STATE_READ_POST, - CON_STATE_HANDLE_REQUEST, - CON_STATE_RESPONSE_START, - CON_STATE_WRITE, - CON_STATE_RESPONSE_END, - CON_STATE_ERROR, - CON_STATE_CLOSE +typedef enum { + CON_STATE_CONNECT, + CON_STATE_REQUEST_START, + CON_STATE_READ, + CON_STATE_REQUEST_END, + CON_STATE_READ_POST, + CON_STATE_HANDLE_REQUEST, + CON_STATE_RESPONSE_START, + CON_STATE_WRITE, + CON_STATE_RESPONSE_END, + CON_STATE_ERROR, + CON_STATE_CLOSE } connection_state_t; typedef enum { COND_RESULT_UNSET, COND_RESULT_FALSE, COND_RESULT_TRUE } cond_result_t; @@ -315,88 +311,88 @@ typedef struct { connection_state_t state; - + /* timestamps */ time_t read_idle_ts; time_t close_timeout_ts; time_t write_request_ts; - + time_t connection_start; time_t request_start; - + struct timeval start_tv; - + size_t request_count; /* number of requests handled in this connection */ size_t loops_per_request; /* to catch endless loops in a single request - * + * * used by mod_rewrite, mod_fastcgi, ... and others * this is self-protection */ - + int fd; /* the FD for this connection */ int fde_ndx; /* index for the fdevent-handler */ int ndx; /* reverse mapping to server->connection[ndx] */ - + /* fd states */ int is_readable; int is_writable; - - int keep_alive; /* only request.c can enable it, all other just disable */ - + + int keep_alive; /* only request.c can enable it, all others just disable */ + int file_started; int file_finished; - + chunkqueue *write_queue; /* a large queue for low-level write ( HTTP response ) [ file, mem ] */ chunkqueue *read_queue; /* a small queue for low-level read ( HTTP request ) [ mem ] */ chunkqueue *request_content_queue; /* takes request-content into tempfile if necessary [ tempfile, mem ]*/ - + int traffic_limit_reached; - + off_t bytes_written; /* used by mod_accesslog, mod_rrd */ off_t bytes_written_cur_second; /* used by mod_accesslog, mod_rrd */ off_t bytes_read; /* used by mod_accesslog, mod_rrd */ off_t bytes_header; - + int http_status; - + sock_addr dst_addr; buffer *dst_addr_buf; /* request */ buffer *parse_request; unsigned int parsed_response; /* bitfield which contains the important header-fields of the parsed response header */ - + request request; request_uri uri; - physical physical; + physical physical; response response; - + size_t header_len; - + buffer *authed_user; array *environment; /* used to pass lighttpd internal stuff to the FastCGI/CGI apps, setenv does that */ - + /* response */ int got_response; - + int in_joblist; - + connection_type mode; - + void **plugin_ctx; /* plugin connection specific config */ - + specific_config conf; /* global connection specific config */ cond_cache_t *cond_cache; - + buffer *server_name; - + /* error-handler */ buffer *error_handler; int error_handler_saved_status; int in_error_handler; - + void *srv_socket; /* reference to the server-socket (typecast to server_socket) */ - + #ifdef USE_OPENSSL SSL *ssl; #endif @@ -439,39 +435,48 @@ size_t size; } buffer_plugin; +typedef enum { + NETWORK_STATUS_UNSET, + NETWORK_STATUS_SUCCESS, + NETWORK_STATUS_FATAL_ERROR, + NETWORK_STATUS_CONNECTION_CLOSE, + NETWORK_STATUS_WAIT_FOR_EVENT, + NETWORK_STATUS_INTERRUPTED +} network_status_t; + typedef struct { unsigned short port; buffer *bindhost; - + buffer *errorlog_file; unsigned short errorlog_use_syslog; - + unsigned short dont_daemonize; buffer *changeroot; buffer *username; buffer *groupname; - + buffer *pid_file; - + buffer *event_handler; - + buffer *modules_dir; buffer *network_backend; array *modules; array *upload_tempdirs; - + unsigned short max_worker; unsigned short max_fds; unsigned short max_conns; unsigned short max_request_size; - + unsigned short log_request_header_on_error; unsigned short log_state_handling; - - enum { STAT_CACHE_ENGINE_UNSET, - STAT_CACHE_ENGINE_NONE, - STAT_CACHE_ENGINE_SIMPLE, - STAT_CACHE_ENGINE_FAM + + enum { STAT_CACHE_ENGINE_UNSET, + STAT_CACHE_ENGINE_NONE, + STAT_CACHE_ENGINE_SIMPLE, + STAT_CACHE_ENGINE_FAM } stat_cache_engine; unsigned short enable_cores; } server_config; @@ -480,14 +485,14 @@ sock_addr addr; int fd; int fde_ndx; - + buffer *ssl_pemfile; buffer *ssl_ca_file; unsigned short use_ipv6; unsigned short is_ssl; - + buffer *srv_token; - + #ifdef USE_OPENSSL SSL_CTX *ssl_ctx; #endif @@ -495,37 +500,37 @@ typedef struct { server_socket **ptr; - + size_t size; size_t used; } server_socket_array; typedef struct server { server_socket_array srv_sockets; - + /* the errorlog */ int errorlog_fd; enum { ERRORLOG_STDERR, ERRORLOG_FILE, ERRORLOG_SYSLOG } errorlog_mode; buffer *errorlog_buf; - + fdevents *ev, *ev_ins; - + buffer_plugin plugins; void *plugin_slots; - + /* counters */ int con_opened; int con_read; int con_written; int con_closed; - + int ssl_is_init; - + int max_fds; /* max possible fds */ int cur_fds; /* currently used fds */ int want_fds; /* waiting fds */ int sockets_disabled; - + size_t max_conns; /* buffers */ @@ -533,13 +538,13 @@ buffer *response_header; buffer *response_range; buffer *tmp_buf; - + buffer *tmp_chunk_len; - + buffer *empty_string; /* is necessary for cond_match */ buffer *cond_check_buf; - + /* caches */ #ifdef HAVE_IPV6 inet_ntop_cache_type inet_ntop_cache[INET_NTOP_CACHE_MAX]; @@ -547,31 +552,31 @@ mtime_cache_type mtime_cache[FILE_CACHE_MAX]; array *split_vals; - + /* Timestamps */ time_t cur_ts; time_t last_generated_date_ts; time_t last_generated_debug_ts; time_t startup_ts; - + buffer *ts_debug_str; buffer *ts_date_str; - + /* config-file */ array *config; array *config_touched; - + array *config_context; specific_config **config_storage; - + server_config srvconf; - + int config_deprecated; - + connections *conns; connections *joblist; connections *fdwaitqueue; - + stat_cache *stat_cache; /** @@ -588,18 +593,20 @@ * fastcgi.backend..disconnects = ... */ array *status; - + fdevent_handler_t event_handler; - int (* network_backend_write)(struct server *srv, connection *con, int fd, chunkqueue *cq); - int (* network_backend_read)(struct server *srv, connection *con, int fd, chunkqueue *cq); + network_status_t (* network_backend_write)(struct server *srv, connection *con, int fd, chunkqueue *cq); + network_status_t (* network_backend_read)(struct server *srv, connection *con, int fd, chunkqueue *cq); #ifdef USE_OPENSSL - int (* network_ssl_backend_write)(struct server *srv, connection *con, SSL *ssl, chunkqueue *cq); - int (* network_ssl_backend_read)(struct server *srv, connection *con, SSL *ssl, chunkqueue *cq); + network_status_t (* network_ssl_backend_write)(struct server *srv, connection *con, SSL *ssl, chunkqueue *cq); + network_status_t (* network_ssl_backend_read)(struct server *srv, connection *con, SSL *ssl, chunkqueue *cq); #endif +#ifdef HAVE_PWD_H uid_t uid; gid_t gid; +#endif } server; Property changes on: src/base.h ___________________________________________________________________ Name: svn:eol-style + native Index: src/mod_rewrite.c =================================================================== --- src/mod_rewrite.c (.../tags/lighttpd-1.4.11) (revision 1159) +++ src/mod_rewrite.c (.../branches/lighttpd-merge-1.4.x) (revision 1159) @@ -13,24 +13,8 @@ #endif typedef struct { -#ifdef HAVE_PCRE_H - pcre *key; -#endif - - buffer *value; - - int once; -} rewrite_rule; - -typedef struct { - rewrite_rule **ptr; - - size_t used; - size_t size; -} rewrite_rule_buffer; - -typedef struct { - rewrite_rule_buffer *rewrite; + pcre_keyvalue_buffer *rewrite; + buffer *once; data_config *context; /* to which apply me */ } plugin_config; @@ -42,20 +26,20 @@ typedef struct { PLUGIN_DATA; buffer *match_buf; - + plugin_config **config_storage; - - plugin_config conf; + + plugin_config conf; } plugin_data; static handler_ctx * handler_ctx_init() { handler_ctx * hctx; - + hctx = calloc(1, sizeof(*hctx)); - + hctx->state = REWRITE_STATE_UNSET; hctx->loops = 0; - + return hctx; } @@ -63,207 +47,136 @@ free(hctx); } -rewrite_rule_buffer *rewrite_rule_buffer_init(void) { - rewrite_rule_buffer *kvb; - - kvb = calloc(1, sizeof(*kvb)); - - return kvb; -} -int rewrite_rule_buffer_append(rewrite_rule_buffer *kvb, buffer *key, buffer *value, int once) { -#ifdef HAVE_PCRE_H - size_t i; - const char *errptr; - int erroff; - - if (!key) return -1; - - if (kvb->size == 0) { - kvb->size = 4; - kvb->used = 0; - - kvb->ptr = malloc(kvb->size * sizeof(*kvb->ptr)); - - for(i = 0; i < kvb->size; i++) { - kvb->ptr[i] = calloc(1, sizeof(**kvb->ptr)); - } - } else if (kvb->used == kvb->size) { - kvb->size += 4; - - kvb->ptr = realloc(kvb->ptr, kvb->size * sizeof(*kvb->ptr)); - - for(i = kvb->used; i < kvb->size; i++) { - kvb->ptr[i] = calloc(1, sizeof(**kvb->ptr)); - } - } - - if (NULL == (kvb->ptr[kvb->used]->key = pcre_compile(key->ptr, - 0, &errptr, &erroff, NULL))) { - - return -1; - } - - kvb->ptr[kvb->used]->value = buffer_init(); - buffer_copy_string_buffer(kvb->ptr[kvb->used]->value, value); - kvb->ptr[kvb->used]->once = once; - - kvb->used++; - - return 0; -#else - UNUSED(kvb); - UNUSED(value); - UNUSED(once); - UNUSED(key); - - return -1; -#endif -} - -void rewrite_rule_buffer_free(rewrite_rule_buffer *kvb) { -#ifdef HAVE_PCRE_H - size_t i; - - for (i = 0; i < kvb->size; i++) { - if (kvb->ptr[i]->key) pcre_free(kvb->ptr[i]->key); - if (kvb->ptr[i]->value) buffer_free(kvb->ptr[i]->value); - free(kvb->ptr[i]); - } - - if (kvb->ptr) free(kvb->ptr); -#endif - - free(kvb); -} - - INIT_FUNC(mod_rewrite_init) { plugin_data *p; - + p = calloc(1, sizeof(*p)); - + p->match_buf = buffer_init(); - + return p; } FREE_FUNC(mod_rewrite_free) { plugin_data *p = p_d; - + UNUSED(srv); if (!p) return HANDLER_GO_ON; - + buffer_free(p->match_buf); if (p->config_storage) { size_t i; for (i = 0; i < srv->config_context->used; i++) { plugin_config *s = p->config_storage[i]; - rewrite_rule_buffer_free(s->rewrite); - + pcre_keyvalue_buffer_free(s->rewrite); + buffer_free(s->once); + free(s); } free(p->config_storage); } - + free(p); - + return HANDLER_GO_ON; } static int parse_config_entry(server *srv, plugin_config *s, array *ca, const char *option, int once) { data_unset *du; - + if (NULL != (du = array_get_element(ca, option))) { data_array *da = (data_array *)du; size_t j; - + if (du->type != TYPE_ARRAY) { - log_error_write(srv, __FILE__, __LINE__, "sss", + log_error_write(srv, __FILE__, __LINE__, "sss", "unexpected type for key: ", option, "array of strings"); - + return HANDLER_ERROR; } - + da = (data_array *)du; - + for (j = 0; j < da->value->used; j++) { if (da->value->data[j]->type != TYPE_STRING) { - log_error_write(srv, __FILE__, __LINE__, "sssbs", - "unexpected type for key: ", - option, + log_error_write(srv, __FILE__, __LINE__, "sssbs", + "unexpected type for key: ", + option, "[", da->value->data[j]->key, "](string)"); - + return HANDLER_ERROR; } - - if (0 != rewrite_rule_buffer_append(s->rewrite, - ((data_string *)(da->value->data[j]))->key, - ((data_string *)(da->value->data[j]))->value, - once)) { + + if (0 != pcre_keyvalue_buffer_append(s->rewrite, + ((data_string *)(da->value->data[j]))->key->ptr, + ((data_string *)(da->value->data[j]))->value->ptr)) { #ifdef HAVE_PCRE_H - log_error_write(srv, __FILE__, __LINE__, "sb", + log_error_write(srv, __FILE__, __LINE__, "sb", "pcre-compile failed for", da->value->data[j]->key); #else - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "pcre support is missing, please install libpcre and the headers"); #endif } + + if (once) { + buffer_append_string_len(s->once, CONST_STR_LEN("1")); + } else { + buffer_append_string_len(s->once, CONST_STR_LEN("0")); + } } } - + return 0; } SETDEFAULTS_FUNC(mod_rewrite_set_defaults) { plugin_data *p = p_d; size_t i = 0; - - config_values_t cv[] = { + + config_values_t cv[] = { { "url.rewrite-repeat", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ { "url.rewrite-once", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 1 */ - - /* old names, still supported - * + + /* old names, still supported + * * url.rewrite remapped to url.rewrite-once * url.rewrite-final is url.rewrite-once - * + * */ { "url.rewrite", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 2 */ { "url.rewrite-final", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 3 */ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } }; - + if (!p) return HANDLER_ERROR; - + /* 0 */ p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *)); - + for (i = 0; i < srv->config_context->used; i++) { plugin_config *s; array *ca; - + s = calloc(1, sizeof(plugin_config)); - s->rewrite = rewrite_rule_buffer_init(); - - cv[0].destination = s->rewrite; - cv[1].destination = s->rewrite; - cv[2].destination = s->rewrite; - + s->rewrite = pcre_keyvalue_buffer_init(); + s->once = buffer_init(); + p->config_storage[i] = s; ca = ((data_config *)srv->config_context->data[i])->value; - + if (0 != config_insert_values_global(srv, ca, cv)) { return HANDLER_ERROR; } - + parse_config_entry(srv, s, ca, "url.rewrite-once", 1); parse_config_entry(srv, s, ca, "url.rewrite-final", 1); parse_config_entry(srv, s, ca, "url.rewrite", 1); parse_config_entry(srv, s, ca, "url.rewrite-repeat", 0); } - + return HANDLER_GO_ON; } #ifdef HAVE_PCRE_H @@ -271,157 +184,107 @@ size_t i, j; plugin_config *s = p->config_storage[0]; p->conf.rewrite = s->rewrite; - + p->conf.once = s->once; + /* skip the first, the global context */ for (i = 1; i < srv->config_context->used; i++) { data_config *dc = (data_config *)srv->config_context->data[i]; s = p->config_storage[i]; - + if (COMP_HTTP_URL == dc->comp) continue; - + /* condition didn't match */ if (!config_check_cond(srv, con, dc)) continue; - + /* merge config */ for (j = 0; j < dc->value->used; j++) { data_unset *du = dc->value->data[j]; - + if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite"))) { p->conf.rewrite = s->rewrite; + p->conf.once = s->once; p->conf.context = dc; } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-once"))) { p->conf.rewrite = s->rewrite; + p->conf.once = s->once; p->conf.context = dc; } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-repeat"))) { p->conf.rewrite = s->rewrite; + p->conf.once = s->once; p->conf.context = dc; } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("url.rewrite-final"))) { p->conf.rewrite = s->rewrite; + p->conf.once = s->once; p->conf.context = dc; } } } - + return 0; } #endif URIHANDLER_FUNC(mod_rewrite_con_reset) { plugin_data *p = p_d; - + UNUSED(srv); - + if (con->plugin_ctx[p->id]) { handler_ctx_free(con->plugin_ctx[p->id]); con->plugin_ctx[p->id] = NULL; } - + return HANDLER_GO_ON; } URIHANDLER_FUNC(mod_rewrite_uri_handler) { #ifdef HAVE_PCRE_H plugin_data *p = p_d; - size_t i; + int i; handler_ctx *hctx; - /* + /* * REWRITE URL - * + * * e.g. rewrite /base/ to /index.php?section=base - * + * */ - + if (con->plugin_ctx[p->id]) { hctx = con->plugin_ctx[p->id]; - + if (hctx->loops++ > 100) { - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "ENDLESS LOOP IN rewrite-rule DETECTED ... aborting request, perhaps you want to use url.rewrite-once instead of url.rewrite-repeat"); - + return HANDLER_ERROR; } - + if (hctx->state == REWRITE_STATE_FINISHED) return HANDLER_GO_ON; } - + mod_rewrite_patch_connection(srv, con, p); if (!p->conf.rewrite) return HANDLER_GO_ON; - + buffer_copy_string_buffer(p->match_buf, con->request.uri); - - for (i = 0; i < p->conf.rewrite->used; i++) { - pcre *match; - const char *pattern; - size_t pattern_len; - int n; - rewrite_rule *rule = p->conf.rewrite->ptr[i]; -# define N 10 - int ovec[N * 3]; - - match = rule->key; - pattern = rule->value->ptr; - pattern_len = rule->value->used - 1; - - if ((n = pcre_exec(match, NULL, p->match_buf->ptr, p->match_buf->used - 1, 0, 0, ovec, 3 * N)) < 0) { - if (n != PCRE_ERROR_NOMATCH) { - log_error_write(srv, __FILE__, __LINE__, "sd", - "execution error while matching: ", n); - return HANDLER_ERROR; - } - } else { - const char **list; - size_t start, end; - size_t k; - - /* it matched */ - pcre_get_substring_list(p->match_buf->ptr, ovec, n, &list); - - /* search for $[0-9] */ - - buffer_reset(con->request.uri); - - start = 0; end = pattern_len; - for (k = 0; k < pattern_len; k++) { - if ((pattern[k] == '$' || pattern[k] == '%') && - isdigit((unsigned char)pattern[k + 1])) { - /* got one */ - - size_t num = pattern[k + 1] - '0'; - - end = k; - - buffer_append_string_len(con->request.uri, pattern + start, end - start); - - if (pattern[k] == '$') { - /* n is always > 0 */ - if (num < (size_t)n) { - buffer_append_string(con->request.uri, list[num]); - } - } else { - config_append_cond_match_buffer(con, p->conf.context, con->request.uri, num); - } - - k++; - start = k + 1; - } - } - - buffer_append_string_len(con->request.uri, pattern + start, pattern_len - start); - - pcre_free(list); - - hctx = handler_ctx_init(); - - con->plugin_ctx[p->id] = hctx; - - if (rule->once) hctx->state = REWRITE_STATE_FINISHED; - - return HANDLER_COMEBACK; - } + i = config_exec_pcre_keyvalue_buffer(con, p->conf.rewrite, p->conf.context, p->match_buf, con->request.uri); + + if (i >= 0) { + hctx = handler_ctx_init(); + + con->plugin_ctx[p->id] = hctx; + + if (p->conf.once->ptr[i] == '1') + hctx->state = REWRITE_STATE_FINISHED; + + return HANDLER_COMEBACK; } + else if (i != PCRE_ERROR_NOMATCH) { + log_error_write(srv, __FILE__, __LINE__, "s", + "execution error while matching", i); + } #undef N - + #else UNUSED(srv); UNUSED(con); @@ -434,17 +297,17 @@ int mod_rewrite_plugin_init(plugin *p) { p->version = LIGHTTPD_VERSION_ID; p->name = buffer_init_string("rewrite"); - + p->init = mod_rewrite_init; /* it has to stay _raw as we are matching on uri + querystring */ - + p->handle_uri_raw = mod_rewrite_uri_handler; p->set_defaults = mod_rewrite_set_defaults; p->cleanup = mod_rewrite_free; p->connection_reset = mod_rewrite_con_reset; - + p->data = NULL; - + return 0; } Property changes on: src/mod_rewrite.c ___________________________________________________________________ Name: svn:eol-style + native Index: src/lempar.c =================================================================== --- src/lempar.c (.../tags/lighttpd-1.4.11) (revision 1159) +++ src/lempar.c (.../branches/lighttpd-merge-1.4.x) (revision 1159) @@ -8,10 +8,10 @@ /* Next is all token values, in a form suitable for use by makeheaders. ** This section will be null unless lemon is run with the -m switch. */ -/* +/* ** These constants (all generated automatically by the parser generator) ** specify the various kinds of tokens (terminals) that the parser -** understands. +** understands. ** ** Each symbol here is a terminal symbol in the grammar. */ @@ -29,7 +29,7 @@ ** and nonterminals. "int" is used otherwise. ** YYNOCODE is a number of type YYCODETYPE which corresponds ** to no legal terminal or nonterminal number. This -** number is used to fill in empty slots of the hash +** number is used to fill in empty slots of the hash ** table. ** YYFALLBACK If defined, this indicates that one or more tokens ** have fall-back values which should be used if the @@ -38,7 +38,7 @@ ** and nonterminal numbers. "unsigned char" is ** used if there are fewer than 250 rules and ** states combined. "int" is used otherwise. -** ParseTOKENTYPE is the data type used for minor tokens given +** ParseTOKENTYPE is the data type used for minor tokens given ** directly to the parser from the tokenizer. ** YYMINORTYPE is the data type used for all minor tokens. ** This is typically a union of many types, one of @@ -62,7 +62,7 @@ /* Next are that tables used to determine what action to take based on the ** current state and lookahead token. These tables are used to implement ** functions that take a state number and lookahead value and return an -** action integer. +** action integer. ** ** Suppose the action integer is N. Then the action is determined as ** follows @@ -87,7 +87,7 @@ ** If the index value yy_shift_ofst[S]+X is out of range or if the value ** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X or if yy_shift_ofst[S] ** is equal to YY_SHIFT_USE_DFLT, it means that the action is not in the table -** and that yy_default[S] should be used instead. +** and that yy_default[S] should be used instead. ** ** The formula above is for computing the action when the lookahead is ** a terminal symbol. If the lookahead is a non-terminal (as occurs after @@ -111,7 +111,7 @@ /* The next table maps tokens into fallback tokens. If a construct ** like the following: -** +** ** %fallback ID X Y Z. ** ** appears in the grammer, then ID becomes a fallback token for X, Y, @@ -163,10 +163,10 @@ #endif /* NDEBUG */ #ifndef NDEBUG -/* +/* ** Turn parser tracing on by giving a stream to which to write the trace ** and a prompt to preface each trace message. Tracing is turned off -** by making either argument NULL +** by making either argument NULL ** ** Inputs: **