diff options
author | Arno Töll <arno@debian.org> | 2012-11-21 23:03:42 +0100 |
---|---|---|
committer | Arno Töll <arno@debian.org> | 2012-11-21 23:03:42 +0100 |
commit | 1b24d86e6b2179692e60091dec59f797cd308b9e (patch) | |
tree | c5502d40d82fdef69ab9c1e4ed69904fefea9ac1 /src | |
parent | 6a6df8dc258631c6eaccb03bf08845241f6dfa4a (diff) | |
download | lighttpd-1b24d86e6b2179692e60091dec59f797cd308b9e.tar.gz |
Imported Upstream version 1.4.13upstream/1.4.13
Diffstat (limited to 'src')
106 files changed, 7929 insertions, 7569 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 3381100..49b3bfd 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,7 +1,7 @@ AM_CFLAGS = $(FAM_CFLAGS) noinst_PROGRAMS=proc_open lemon # simple-fcgi #graphic evalo bench ajp ssl error_test adserver gen-license -sbin_PROGRAMS=lighttpd +sbin_PROGRAMS=lighttpd bin_PROGRAMS=spawn-fcgi LEMON=$(top_builddir)/src/lemon @@ -11,8 +11,8 @@ lemon_SOURCES=lemon.c #simple_fcgi_LDADD=-lfcgi if CROSS_COMPILING -configparser.c configparser.h: -mod_ssi_exprparser.c mod_ssi_exprparser.h: +configparser.c configparser.h: +mod_ssi_exprparser.c mod_ssi_exprparser.h: else configparser.y: lemon mod_ssi_exprparser.y: lemon @@ -21,7 +21,7 @@ configparser.c configparser.h: configparser.y rm -f configparser.h $(LEMON) -q $(srcdir)/configparser.y $(srcdir)/lempar.c -mod_ssi_exprparser.c mod_ssi_exprparser.h: mod_ssi_exprparser.y +mod_ssi_exprparser.c mod_ssi_exprparser.h: mod_ssi_exprparser.y rm -f mod_ssi_exprparser.h $(LEMON) -q $(srcdir)/mod_ssi_exprparser.y $(srcdir)/lempar.c endif @@ -47,13 +47,13 @@ common_src=buffer.c log.c \ network_freebsd_sendfile.c network_writev.c \ network_solaris_sendfilev.c network_openssl.c \ splaytree.c status_counter.c - + src = server.c response.c connections.c network.c \ configfile.c configparser.c request.c proc_open.c spawn_fcgi_SOURCES=spawn-fcgi.c -lib_LTLIBRARIES = +lib_LTLIBRARIES = if NO_RDYNAMIC # if the linker doesn't allow referencing symbols of the binary @@ -67,11 +67,11 @@ liblightcomp_la_LIBADD = $(PCRE_LIB) $(SSL_LIB) $(FAM_LIBS) common_libadd = liblightcomp.la else src += $(common_src) -common_libadd = +common_libadd = endif lib_LTLIBRARIES += mod_flv_streaming.la -mod_flv_streaming_la_SOURCES = mod_flv_streaming.c +mod_flv_streaming_la_SOURCES = mod_flv_streaming.c mod_flv_streaming_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined mod_flv_streaming_la_LIBADD = $(common_libadd) @@ -82,9 +82,9 @@ mod_evasive_la_LIBADD = $(common_libadd) lib_LTLIBRARIES += mod_webdav.la mod_webdav_la_SOURCES = mod_webdav.c -mod_webdav_la_CFLAGS = $(AM_CFLAGS) $(XML_CFLAGS) $(SQLITE_CFLAGS) +mod_webdav_la_CFLAGS = $(AM_CFLAGS) $(XML_CFLAGS) $(SQLITE_CFLAGS) mod_webdav_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined -mod_webdav_la_LIBADD = $(common_libadd) $(XML_LIBS) $(SQLITE_LIBS) +mod_webdav_la_LIBADD = $(common_libadd) $(XML_LIBS) $(SQLITE_LIBS) $(UUID_LIBS) lib_LTLIBRARIES += mod_magnet.la mod_magnet_la_SOURCES = mod_magnet.c mod_magnet_cache.c @@ -110,42 +110,42 @@ mod_mysql_vhost_la_LIBADD = $(MYSQL_LIBS) $(common_libadd) mod_mysql_vhost_la_CPPFLAGS = $(MYSQL_INCLUDE) lib_LTLIBRARIES += mod_cgi.la -mod_cgi_la_SOURCES = mod_cgi.c +mod_cgi_la_SOURCES = mod_cgi.c mod_cgi_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined mod_cgi_la_LIBADD = $(common_libadd) lib_LTLIBRARIES += mod_scgi.la -mod_scgi_la_SOURCES = mod_scgi.c +mod_scgi_la_SOURCES = mod_scgi.c mod_scgi_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined mod_scgi_la_LIBADD = $(common_libadd) lib_LTLIBRARIES += mod_staticfile.la -mod_staticfile_la_SOURCES = mod_staticfile.c +mod_staticfile_la_SOURCES = mod_staticfile.c mod_staticfile_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined mod_staticfile_la_LIBADD = $(common_libadd) lib_LTLIBRARIES += mod_dirlisting.la -mod_dirlisting_la_SOURCES = mod_dirlisting.c +mod_dirlisting_la_SOURCES = mod_dirlisting.c mod_dirlisting_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined mod_dirlisting_la_LIBADD = $(common_libadd) $(PCRE_LIB) lib_LTLIBRARIES += mod_indexfile.la -mod_indexfile_la_SOURCES = mod_indexfile.c +mod_indexfile_la_SOURCES = mod_indexfile.c mod_indexfile_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined mod_indexfile_la_LIBADD = $(common_libadd) lib_LTLIBRARIES += mod_setenv.la -mod_setenv_la_SOURCES = mod_setenv.c +mod_setenv_la_SOURCES = mod_setenv.c mod_setenv_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined mod_setenv_la_LIBADD = $(common_libadd) lib_LTLIBRARIES += mod_alias.la -mod_alias_la_SOURCES = mod_alias.c +mod_alias_la_SOURCES = mod_alias.c mod_alias_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined mod_alias_la_LIBADD = $(common_libadd) lib_LTLIBRARIES += mod_userdir.la -mod_userdir_la_SOURCES = mod_userdir.c +mod_userdir_la_SOURCES = mod_userdir.c mod_userdir_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined mod_userdir_la_LIBADD = $(common_libadd) @@ -165,7 +165,7 @@ mod_proxy_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined mod_proxy_la_LIBADD = $(common_libadd) lib_LTLIBRARIES += mod_ssi.la -mod_ssi_la_SOURCES = mod_ssi_exprparser.c mod_ssi_expr.c mod_ssi.c +mod_ssi_la_SOURCES = mod_ssi_exprparser.c mod_ssi_expr.c mod_ssi.c mod_ssi_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined mod_ssi_la_LIBADD = $(common_libadd) $(PCRE_LIB) @@ -193,7 +193,7 @@ lib_LTLIBRARIES += mod_simple_vhost.la mod_simple_vhost_la_SOURCES = mod_simple_vhost.c mod_simple_vhost_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined mod_simple_vhost_la_LIBADD = $(common_libadd) - + lib_LTLIBRARIES += mod_fastcgi.la mod_fastcgi_la_SOURCES = mod_fastcgi.c mod_fastcgi_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined @@ -205,7 +205,7 @@ mod_access_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined mod_access_la_LIBADD = $(common_libadd) lib_LTLIBRARIES += mod_compress.la -mod_compress_la_SOURCES = mod_compress.c +mod_compress_la_SOURCES = mod_compress.c mod_compress_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined mod_compress_la_LIBADD = $(Z_LIB) $(BZ_LIB) $(common_libadd) diff --git a/src/Makefile.in b/src/Makefile.in index ff69c2a..e3ea4c1 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -221,7 +221,8 @@ mod_usertrack_la_DEPENDENCIES = $(am__DEPENDENCIES_2) am_mod_usertrack_la_OBJECTS = mod_usertrack.lo mod_usertrack_la_OBJECTS = $(am_mod_usertrack_la_OBJECTS) mod_webdav_la_DEPENDENCIES = $(am__DEPENDENCIES_2) \ - $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) + $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \ + $(am__DEPENDENCIES_1) am_mod_webdav_la_OBJECTS = mod_webdav_la-mod_webdav.lo mod_webdav_la_OBJECTS = $(am_mod_webdav_la_OBJECTS) binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) @@ -384,7 +385,6 @@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ -LUACONFIG = @LUACONFIG@ LUA_CFLAGS = @LUA_CFLAGS@ LUA_LIBS = @LUA_LIBS@ MAINT = @MAINT@ @@ -417,6 +417,7 @@ SQLITE_LIBS = @SQLITE_LIBS@ SSL_LIB = @SSL_LIB@ STRIP = @STRIP@ U = @U@ +UUID_LIBS = @UUID_LIBS@ VERSION = @VERSION@ XML_CFLAGS = @XML_CFLAGS@ XML_LIBS = @XML_LIBS@ @@ -514,16 +515,16 @@ lib_LTLIBRARIES = $(am__append_1) mod_flv_streaming.la mod_evasive.la \ @NO_RDYNAMIC_TRUE@liblightcomp_la_LIBADD = $(PCRE_LIB) $(SSL_LIB) $(FAM_LIBS) @NO_RDYNAMIC_FALSE@common_libadd = @NO_RDYNAMIC_TRUE@common_libadd = liblightcomp.la -mod_flv_streaming_la_SOURCES = mod_flv_streaming.c +mod_flv_streaming_la_SOURCES = mod_flv_streaming.c mod_flv_streaming_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined mod_flv_streaming_la_LIBADD = $(common_libadd) mod_evasive_la_SOURCES = mod_evasive.c mod_evasive_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined mod_evasive_la_LIBADD = $(common_libadd) mod_webdav_la_SOURCES = mod_webdav.c -mod_webdav_la_CFLAGS = $(AM_CFLAGS) $(XML_CFLAGS) $(SQLITE_CFLAGS) +mod_webdav_la_CFLAGS = $(AM_CFLAGS) $(XML_CFLAGS) $(SQLITE_CFLAGS) mod_webdav_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined -mod_webdav_la_LIBADD = $(common_libadd) $(XML_LIBS) $(SQLITE_LIBS) +mod_webdav_la_LIBADD = $(common_libadd) $(XML_LIBS) $(SQLITE_LIBS) $(UUID_LIBS) mod_magnet_la_SOURCES = mod_magnet.c mod_magnet_cache.c mod_magnet_la_CFLAGS = $(AM_CFLAGS) $(LUA_CFLAGS) mod_magnet_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined @@ -539,28 +540,28 @@ mod_mysql_vhost_la_SOURCES = mod_mysql_vhost.c mod_mysql_vhost_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined mod_mysql_vhost_la_LIBADD = $(MYSQL_LIBS) $(common_libadd) mod_mysql_vhost_la_CPPFLAGS = $(MYSQL_INCLUDE) -mod_cgi_la_SOURCES = mod_cgi.c +mod_cgi_la_SOURCES = mod_cgi.c mod_cgi_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined mod_cgi_la_LIBADD = $(common_libadd) -mod_scgi_la_SOURCES = mod_scgi.c +mod_scgi_la_SOURCES = mod_scgi.c mod_scgi_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined mod_scgi_la_LIBADD = $(common_libadd) -mod_staticfile_la_SOURCES = mod_staticfile.c +mod_staticfile_la_SOURCES = mod_staticfile.c mod_staticfile_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined mod_staticfile_la_LIBADD = $(common_libadd) -mod_dirlisting_la_SOURCES = mod_dirlisting.c +mod_dirlisting_la_SOURCES = mod_dirlisting.c mod_dirlisting_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined mod_dirlisting_la_LIBADD = $(common_libadd) $(PCRE_LIB) -mod_indexfile_la_SOURCES = mod_indexfile.c +mod_indexfile_la_SOURCES = mod_indexfile.c mod_indexfile_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined mod_indexfile_la_LIBADD = $(common_libadd) -mod_setenv_la_SOURCES = mod_setenv.c +mod_setenv_la_SOURCES = mod_setenv.c mod_setenv_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined mod_setenv_la_LIBADD = $(common_libadd) -mod_alias_la_SOURCES = mod_alias.c +mod_alias_la_SOURCES = mod_alias.c mod_alias_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined mod_alias_la_LIBADD = $(common_libadd) -mod_userdir_la_SOURCES = mod_userdir.c +mod_userdir_la_SOURCES = mod_userdir.c mod_userdir_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined mod_userdir_la_LIBADD = $(common_libadd) mod_rrdtool_la_SOURCES = mod_rrdtool.c @@ -572,7 +573,7 @@ mod_usertrack_la_LIBADD = $(common_libadd) mod_proxy_la_SOURCES = mod_proxy.c mod_proxy_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined mod_proxy_la_LIBADD = $(common_libadd) -mod_ssi_la_SOURCES = mod_ssi_exprparser.c mod_ssi_expr.c mod_ssi.c +mod_ssi_la_SOURCES = mod_ssi_exprparser.c mod_ssi_expr.c mod_ssi.c mod_ssi_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined mod_ssi_la_LIBADD = $(common_libadd) $(PCRE_LIB) mod_secdownload_la_SOURCES = mod_secure_download.c @@ -593,7 +594,7 @@ mod_fastcgi_la_LIBADD = $(common_libadd) mod_access_la_SOURCES = mod_access.c mod_access_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined mod_access_la_LIBADD = $(common_libadd) -mod_compress_la_SOURCES = mod_compress.c +mod_compress_la_SOURCES = mod_compress.c mod_compress_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined mod_compress_la_LIBADD = $(Z_LIB) $(BZ_LIB) $(common_libadd) mod_auth_la_SOURCES = mod_auth.c http_auth_digest.c http_auth.c @@ -1544,8 +1545,8 @@ uninstall-am: uninstall-binPROGRAMS uninstall-info-am \ #simple_fcgi_SOURCES=simple-fcgi.c #simple_fcgi_LDADD=-lfcgi -@CROSS_COMPILING_TRUE@configparser.c configparser.h: -@CROSS_COMPILING_TRUE@mod_ssi_exprparser.c mod_ssi_exprparser.h: +@CROSS_COMPILING_TRUE@configparser.c configparser.h: +@CROSS_COMPILING_TRUE@mod_ssi_exprparser.c mod_ssi_exprparser.h: @CROSS_COMPILING_FALSE@configparser.y: lemon @CROSS_COMPILING_FALSE@mod_ssi_exprparser.y: lemon @@ -1553,7 +1554,7 @@ uninstall-am: uninstall-binPROGRAMS uninstall-info-am \ @CROSS_COMPILING_FALSE@ rm -f configparser.h @CROSS_COMPILING_FALSE@ $(LEMON) -q $(srcdir)/configparser.y $(srcdir)/lempar.c -@CROSS_COMPILING_FALSE@mod_ssi_exprparser.c mod_ssi_exprparser.h: mod_ssi_exprparser.y +@CROSS_COMPILING_FALSE@mod_ssi_exprparser.c mod_ssi_exprparser.h: mod_ssi_exprparser.y @CROSS_COMPILING_FALSE@ rm -f mod_ssi_exprparser.h @CROSS_COMPILING_FALSE@ $(LEMON) -q $(srcdir)/mod_ssi_exprparser.y $(srcdir)/lempar.c diff --git a/src/array.c b/src/array.c index 3e1b32d..e35455b 100644 --- a/src/array.c +++ b/src/array.c @@ -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 @@ array *array_init_array(array *src) { 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 @@ data_unset *array_pop(array *a) { 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 @@ static int array_get_index(array *a, const char *key, size_t keylen, int *rndx) } 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 array_insert_unique(array *a, data_unset *str) { int ndx = -1; int pos = 0; size_t j; - + /* generate unique index if neccesary */ 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 @@ int array_insert_unique(array *a, data_unset *str) { } 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 @@ int array_insert_unique(array *a, data_unset *str) { 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 */ 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 @@ int array_print(array *a, int depth) { size_t i; size_t maxlen; int oneline = 1; - + if (a->used > 5) { oneline = 0; } @@ -314,7 +314,7 @@ int array_print(array *a, int depth) { } array_print_indent(depth); fprintf(stdout, ")"); - + return 0; } @@ -323,47 +323,47 @@ int main (int argc, char **argv) { 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 diff --git a/src/array.h b/src/array.h index b9687d7..862295c 100644 --- a/src/array.h +++ b/src/array.h @@ -29,21 +29,21 @@ typedef struct data_unset { typedef struct { data_unset **data; - + size_t *sorted; - + size_t used; size_t size; - + size_t unique_ndx; - + size_t next_power_of_2; int is_weakref; /* data is weakref, don't bother the data */ } array; typedef struct { DATA_UNSET; - + int count; } data_count; @@ -51,7 +51,7 @@ data_count *data_count_init(void); typedef struct { DATA_UNSET; - + buffer *value; } data_string; @@ -60,7 +60,7 @@ data_string *data_response_init(void); typedef struct { DATA_UNSET; - + array *value; } data_array; @@ -69,8 +69,8 @@ data_array *data_array_init(void); /** * possible compare ops in the configfile parser */ -typedef enum { - CONFIG_COND_UNSET, +typedef enum { + CONFIG_COND_UNSET, CONFIG_COND_EQ, /** == */ CONFIG_COND_MATCH, /** =~ */ CONFIG_COND_NE, /** != */ @@ -82,17 +82,17 @@ typedef enum { */ typedef enum { COMP_UNSET, - COMP_SERVER_SOCKET, - COMP_HTTP_URL, - COMP_HTTP_HOST, - COMP_HTTP_REFERER, - COMP_HTTP_USERAGENT, - COMP_HTTP_COOKIE, + COMP_SERVER_SOCKET, + COMP_HTTP_URL, + COMP_HTTP_HOST, + COMP_HTTP_REFERER, + COMP_HTTP_USERAGENT, + COMP_HTTP_COOKIE, COMP_HTTP_REMOTEIP, COMP_HTTP_QUERYSTRING } comp_key_t; -/* $HTTP["host"] == "incremental.home.kneschke.de" { ... } +/* $HTTP["host"] == "incremental.home.kneschke.de" { ... } * for print: comp_key op string * for compare: comp cond string/regex */ @@ -100,15 +100,15 @@ typedef enum { typedef struct _data_config data_config; struct _data_config { DATA_UNSET; - + array *value; - + buffer *comp_key; comp_key_t comp; - + config_cond_t cond; buffer *op; - + int context_ndx; /* more or less like an id */ array *childs; /* nested */ @@ -116,7 +116,7 @@ struct _data_config { /* for chaining only */ data_config *prev; data_config *next; - + buffer *string; #ifdef HAVE_PCRE_H pcre *regex; @@ -128,7 +128,7 @@ data_config *data_config_init(void); typedef struct { DATA_UNSET; - + int value; } data_integer; @@ -138,13 +138,13 @@ typedef struct { DATA_UNSET; buffer *host; - + unsigned short port; time_t disable_ts; int is_disabled; size_t balance; - + int usage; /* fair-balancing needs the no. of connections active on this host */ int last_used_ndx; /* round robin */ } data_fastcgi; @@ -29,7 +29,7 @@ #if defined HAVE_LIBSSL && defined HAVE_OPENSSL_SSL_H # define USE_OPENSSL -# include <openssl/ssl.h> +# include <openssl/ssl.h> #endif #ifdef HAVE_FAM_H @@ -80,25 +80,25 @@ typedef int socklen_t; #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, T_CONFIG_UNSUPPORTED } 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; @@ -143,29 +143,29 @@ typedef struct { /* 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; @@ -173,10 +173,10 @@ typedef struct { 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 */ - + array *headers; - - enum { + + enum { HTTP_TRANSFER_ENCODING_IDENTITY, HTTP_TRANSFER_ENCODING_CHUNKED } transfer_encoding; } response; @@ -192,21 +192,21 @@ typedef struct { 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_LSTAT char is_symlink; #endif @@ -221,7 +221,7 @@ typedef struct { typedef struct { splay_tree *files; /* the nodes of the tree are stat_cache_entry's */ - + 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 */ @@ -234,7 +234,7 @@ typedef struct { typedef struct { array *mimetypes; - + /* virtual-servers */ buffer *document_root; buffer *server_name; @@ -242,7 +242,7 @@ typedef struct { 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; @@ -250,16 +250,16 @@ typedef struct { 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; - - + + /* server wide */ buffer *ssl_pemfile; buffer *ssl_ca_file; @@ -277,9 +277,9 @@ typedef struct { /* 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 * @@ -287,12 +287,12 @@ typedef struct { * the connected conns are "offline" a little bit * * the problem: - * we somehow have to loose our "we are writable" signal + * we somehow have to loose our "we are writable" signal * on the way. - * + * */ off_t *global_bytes_per_second_cnt_ptr; /* */ - + #ifdef USE_OPENSSL SSL_CTX *ssl_ctx; #endif @@ -300,18 +300,18 @@ typedef struct { /* 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; @@ -324,88 +324,88 @@ typedef struct { 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 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; buffer *ssl_error_want_reuse_buffer; @@ -452,36 +452,36 @@ typedef struct { 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; @@ -490,16 +490,16 @@ typedef struct { sock_addr addr; int fd; int fde_ndx; - + buffer *ssl_pemfile; buffer *ssl_ca_file; buffer *ssl_cipher_list; unsigned short ssl_use_sslv2; unsigned short use_ipv6; unsigned short is_ssl; - + buffer *srv_token; - + #ifdef USE_OPENSSL SSL_CTX *ssl_ctx; #endif @@ -507,37 +507,37 @@ typedef struct { 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 */ @@ -545,13 +545,13 @@ typedef struct server { 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]; @@ -559,32 +559,32 @@ typedef struct server { 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; - + short int config_deprecated; short int config_unsupported; - + connections *conns; connections *joblist; connections *fdwaitqueue; - + stat_cache *stat_cache; /** @@ -601,7 +601,7 @@ typedef struct server { * fastcgi.backend.<key>.disconnects = ... */ array *status; - + fdevent_handler_t event_handler; int (* network_backend_write)(struct server *srv, connection *con, int fd, chunkqueue *cq); diff --git a/src/buffer.c b/src/buffer.c index 2026738..cf25d5b 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -12,20 +12,20 @@ static const char hex_chars[] = "0123456789abcdef"; /** - * init the buffer - * + * init the buffer + * */ buffer* buffer_init(void) { buffer *b; - + b = malloc(sizeof(*b)); assert(b); - + b->ptr = NULL; b->size = 0; b->used = 0; - + return b; } @@ -36,8 +36,8 @@ buffer *buffer_init_buffer(buffer *src) { } /** - * free the buffer - * + * free the buffer + * */ void buffer_free(buffer *b) { @@ -49,39 +49,39 @@ void buffer_free(buffer *b) { void buffer_reset(buffer *b) { if (!b) return; - + /* limit don't reuse buffer larger than ... bytes */ if (b->size > BUFFER_MAX_REUSE_SIZE) { free(b->ptr); b->ptr = NULL; b->size = 0; } - + b->used = 0; } /** - * - * allocate (if neccessary) enough space for 'size' bytes and + * + * allocate (if neccessary) enough space for 'size' bytes and * set the 'used' counter to 0 - * + * */ #define BUFFER_PIECE_SIZE 64 int buffer_prepare_copy(buffer *b, size_t size) { if (!b) return -1; - - if ((0 == b->size) || + + if ((0 == b->size) || (size > b->size)) { if (b->size) free(b->ptr); - + b->size = size; - + /* always allocate a multiply of BUFFER_PIECE_SIZE */ b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE); - + b->ptr = malloc(b->size); assert(b->ptr); } @@ -90,30 +90,30 @@ int buffer_prepare_copy(buffer *b, size_t size) { } /** - * + * * increase the internal buffer (if neccessary) to append another 'size' byte * ->used isn't changed - * + * */ int buffer_prepare_append(buffer *b, size_t size) { if (!b) return -1; - + if (0 == b->size) { b->size = size; - + /* always allocate a multiply of BUFFER_PIECE_SIZE */ b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE); - + b->ptr = malloc(b->size); b->used = 0; assert(b->ptr); } else if (b->used + size > b->size) { b->size += size; - + /* always allocate a multiply of BUFFER_PIECE_SIZE */ b->size += BUFFER_PIECE_SIZE - (b->size % BUFFER_PIECE_SIZE); - + b->ptr = realloc(b->ptr, b->size); assert(b->ptr); } @@ -122,7 +122,7 @@ int buffer_prepare_append(buffer *b, size_t size) { int buffer_copy_string(buffer *b, const char *s) { size_t s_len; - + if (!s || !b) return -1; s_len = strlen(s) + 1; @@ -136,26 +136,26 @@ int buffer_copy_string(buffer *b, const char *s) { int buffer_copy_string_len(buffer *b, const char *s, size_t s_len) { if (!s || !b) return -1; -#if 0 - /* removed optimization as we have to keep the empty string +#if 0 + /* removed optimization as we have to keep the empty string * in some cases for the config handling - * + * * url.access-deny = ( "" ) */ if (s_len == 0) return 0; -#endif +#endif buffer_prepare_copy(b, s_len + 1); - + memcpy(b->ptr, s, s_len); b->ptr[s_len] = '\0'; b->used = s_len + 1; - + return 0; } int buffer_copy_string_buffer(buffer *b, const buffer *src) { if (!src) return -1; - + if (src->used == 0) { b->used = 0; return 0; @@ -201,10 +201,10 @@ int buffer_append_string_rfill(buffer *b, const char *s, size_t maxlen) { /** * append a string to the end of the buffer - * - * the resulting buffer is terminated with a '\0' + * + * the resulting buffer is terminated with a '\0' * s is treated as a un-terminated string (a \0 is handled a normal character) - * + * * @param b a buffer * @param s the string * @param s_len size of the string (without the terminating \0) @@ -228,7 +228,7 @@ int buffer_append_string_len(buffer *b, const char *s, size_t s_len) { int buffer_append_string_buffer(buffer *b, const buffer *src) { if (!src) return -1; if (src->used == 0) return 0; - + return buffer_append_string_len(b, src->ptr, src->used - 1); } @@ -245,9 +245,9 @@ int buffer_append_memory(buffer *b, const char *s, size_t s_len) { int buffer_copy_memory(buffer *b, const char *s, size_t s_len) { if (!s || !b) return -1; - + b->used = 0; - + return buffer_append_memory(b, s, s_len); } @@ -402,46 +402,46 @@ char hex2int(unsigned char hex) { /** - * init the buffer - * + * init the buffer + * */ buffer_array* buffer_array_init(void) { buffer_array *b; - + b = malloc(sizeof(*b)); - + assert(b); b->ptr = NULL; b->size = 0; b->used = 0; - + return b; } void buffer_array_reset(buffer_array *b) { size_t i; - + if (!b) return; - + /* if they are too large, reduce them */ for (i = 0; i < b->used; i++) { buffer_reset(b->ptr[i]); } - + b->used = 0; } /** - * free the buffer_array - * + * free the buffer_array + * */ void buffer_array_free(buffer_array *b) { size_t i; if (!b) return; - + for (i = 0; i < b->size; i++) { if (b->ptr[i]) buffer_free(b->ptr[i]); } @@ -451,7 +451,7 @@ void buffer_array_free(buffer_array *b) { buffer *buffer_array_append_get_buffer(buffer_array *b) { size_t i; - + if (b->size == 0) { b->size = 16; b->ptr = malloc(sizeof(*b->ptr) * b->size); @@ -467,13 +467,13 @@ buffer *buffer_array_append_get_buffer(buffer_array *b) { b->ptr[i] = NULL; } } - + if (b->ptr[b->used] == NULL) { b->ptr[b->used] = buffer_init(); } - + b->ptr[b->used]->used = 0; - + return b->ptr[b->used++]; } @@ -482,23 +482,23 @@ char * buffer_search_string_len(buffer *b, const char *needle, size_t len) { size_t i; if (len == 0) return NULL; if (needle == NULL) return NULL; - + if (b->used < len) return NULL; - + for(i = 0; i < b->used - len; i++) { if (0 == memcmp(b->ptr + i, needle, len)) { return b->ptr + i; } } - + return NULL; } buffer *buffer_init_string(const char *str) { buffer *b = buffer_init(); - + buffer_copy_string(b, str); - + return b; } @@ -508,7 +508,7 @@ int buffer_is_empty(buffer *b) { /** * check if two buffer contain the same data - * + * * HISTORY: this function was pretty much optimized, but didn't handled * alignment properly. */ @@ -522,100 +522,100 @@ int buffer_is_equal(buffer *a, buffer *b) { int buffer_is_equal_string(buffer *a, const char *s, size_t b_len) { buffer b; - + b.ptr = (char *)s; b.used = b_len + 1; - + return buffer_is_equal(a, &b); } /* simple-assumption: - * + * * most parts are equal and doing a case conversion needs time - * + * */ int buffer_caseless_compare(const char *a, size_t a_len, const char *b, size_t b_len) { size_t ndx = 0, max_ndx; size_t *al, *bl; size_t mask = sizeof(*al) - 1; - + al = (size_t *)a; bl = (size_t *)b; - + /* is the alignment correct ? */ if ( ((size_t)al & mask) == 0 && ((size_t)bl & mask) == 0 ) { - + max_ndx = ((a_len < b_len) ? a_len : b_len) & ~mask; - + for (; ndx < max_ndx; ndx += sizeof(*al)) { if (*al != *bl) break; al++; bl++; - + } - + } - + a = (char *)al; b = (char *)bl; - + max_ndx = ((a_len < b_len) ? a_len : b_len); - + for (; ndx < max_ndx; ndx++) { char a1 = *a++, b1 = *b++; - + if (a1 != b1) { if ((a1 >= 'A' && a1 <= 'Z') && (b1 >= 'a' && b1 <= 'z')) a1 |= 32; else if ((a1 >= 'a' && a1 <= 'z') && (b1 >= 'A' && b1 <= 'Z')) b1 |= 32; if ((a1 - b1) != 0) return (a1 - b1); - + } } - + return 0; } /** * check if the rightmost bytes of the string are equal. - * - * + * + * */ int buffer_is_equal_right_len(buffer *b1, buffer *b2, size_t len) { /* no, len -> equal */ if (len == 0) return 1; - + /* len > 0, but empty buffers -> not equal */ if (b1->used == 0 || b2->used == 0) return 0; - + /* buffers too small -> not equal */ if (b1->used - 1 < len || b1->used - 1 < len) return 0; - - if (0 == strncmp(b1->ptr + b1->used - 1 - len, + + if (0 == strncmp(b1->ptr + b1->used - 1 - len, b2->ptr + b2->used - 1 - len, len)) { return 1; } - + return 0; } int buffer_copy_string_hex(buffer *b, const char *in, size_t in_len) { size_t i; - + /* BO protection */ if (in_len * 2 < in_len) return -1; - + buffer_prepare_copy(b, in_len * 2 + 1); - + for (i = 0; i < in_len; i++) { b->ptr[b->used++] = hex_chars[(in[i] >> 4) & 0x0F]; b->ptr[b->used++] = hex_chars[in[i] & 0x0F]; } b->ptr[b->used++] = '\0'; - + return 0; } @@ -624,7 +624,7 @@ const char encoded_chars_rel_uri_part[] = { 0 1 2 3 4 5 6 7 8 9 A B C D E F */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */ 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, /* 20 - 2F space " # $ % & ' + , / */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 30 - 3F : ; = ? @ < > */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 - 4F */ @@ -646,7 +646,7 @@ const char encoded_chars_rel_uri[] = { 0 1 2 3 4 5 6 7 8 9 A B C D E F */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */ 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, /* 20 - 2F space " # $ % & ' + , / */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 30 - 3F : ; = ? @ < > */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 - 4F */ @@ -668,7 +668,7 @@ const char encoded_chars_html[] = { 0 1 2 3 4 5 6 7 8 9 A B C D E F */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 20 - 2F & */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, /* 30 - 3F < > */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 - 4F */ @@ -690,7 +690,7 @@ const char encoded_chars_minimal_xml[] = { 0 1 2 3 4 5 6 7 8 9 A B C D E F */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */ 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 20 - 2F & */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, /* 30 - 3F < > */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 40 - 4F */ @@ -712,12 +712,12 @@ const char encoded_chars_hex[] = { 0 1 2 3 4 5 6 7 8 9 A B C D E F */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 00 - 0F control chars */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 30 - 3F */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 50 - 5F */ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 10 - 1F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 20 - 2F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 30 - 3F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 40 - 4F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 50 - 5F */ + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 60 - 6F */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 70 - 7F */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 80 - 8F */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 90 - 9F */ @@ -734,13 +734,13 @@ int buffer_append_string_encoded(buffer *b, const char *s, size_t s_len, buffer_ unsigned char *ds, *d; size_t d_len, ndx; const char *map = NULL; - + if (!s || !b) return -1; - + if (b->ptr[b->used - 1] != '\0') { SEGFAULT(); } - + if (s_len == 0) return 0; switch(encoding) { @@ -764,7 +764,7 @@ int buffer_append_string_encoded(buffer *b, const char *s, size_t s_len, buffer_ } assert(map != NULL); - + /* count to-be-encoded-characters */ for (ds = (unsigned char *)s, d_len = 0, ndx = 0; ndx < s_len; ds++, ndx++) { if (map[*ds]) { @@ -787,9 +787,9 @@ int buffer_append_string_encoded(buffer *b, const char *s, size_t s_len, buffer_ d_len ++; } } - + buffer_prepare_append(b, d_len); - + for (ds = (unsigned char *)s, d = (unsigned char *)b->ptr + b->used - 1, d_len = 0, ndx = 0; ndx < s_len; ds++, ndx++) { if (map[*ds]) { switch(encoding) { @@ -820,9 +820,9 @@ int buffer_append_string_encoded(buffer *b, const char *s, size_t s_len, buffer_ } } - /* terminate buffer and calculate new length */ + /* terminate buffer and calculate new length */ b->ptr[b->used + d_len - 1] = '\0'; - + b->used += d_len; return 0; @@ -854,10 +854,10 @@ static int buffer_urldecode_internal(buffer *url, int is_query) { low = hex2int(*(src + 2)); if (low != 0xFF) { high = (high << 4) | low; - - /* map control-characters out */ + + /* map control-characters out */ if (high < 32 || high == 127) high = '_'; - + *dst = high; src += 2; } @@ -925,7 +925,7 @@ int buffer_path_simplify(buffer *dest, buffer *src) } walk = src->ptr; #endif - + while (*walk == ' ') { walk++; } @@ -991,7 +991,7 @@ int light_isdigit(int c) { int light_isxdigit(int c) { if (light_isdigit(c)) return 1; - + c |= 32; return (c >= 'a' && c <= 'f'); } @@ -1007,29 +1007,29 @@ int light_isalnum(int c) { int buffer_to_lower(buffer *b) { char *c; - + if (b->used == 0) return 0; - + for (c = b->ptr; *c; c++) { if (*c >= 'A' && *c <= 'Z') { *c |= 32; } } - + return 0; } int buffer_to_upper(buffer *b) { char *c; - + if (b->used == 0) return 0; - + for (c = b->ptr; *c; c++) { if (*c >= 'a' && *c <= 'z') { *c &= ~32; } } - + return 0; } diff --git a/src/buffer.h b/src/buffer.h index 3ca22e5..82a5f83 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -12,23 +12,23 @@ typedef struct { char *ptr; - + size_t used; size_t size; } buffer; typedef struct { buffer **ptr; - + size_t used; size_t size; } buffer_array; typedef struct { char *ptr; - + size_t offset; /* input-pointer */ - + size_t used; /* output-pointer */ size_t size; } read_buffer; @@ -43,7 +43,7 @@ buffer* buffer_init_buffer(buffer *b); buffer* buffer_init_string(const char *str); void buffer_free(buffer *b); void buffer_reset(buffer *b); - + int buffer_prepare_copy(buffer *b, size_t size); int buffer_prepare_append(buffer *b, size_t size); diff --git a/src/chunk.c b/src/chunk.c index 776d59e..f5ec564 100644 --- a/src/chunk.c +++ b/src/chunk.c @@ -1,7 +1,7 @@ /** * the network chunk-API - * - * + * + * */ #include <sys/types.h> @@ -20,34 +20,34 @@ chunkqueue *chunkqueue_init(void) { chunkqueue *cq; - + cq = calloc(1, sizeof(*cq)); - + cq->first = NULL; cq->last = NULL; - + cq->unused = NULL; - + return cq; } static chunk *chunk_init(void) { chunk *c; - + c = calloc(1, sizeof(*c)); - + c->mem = buffer_init(); c->file.name = buffer_init(); c->file.fd = -1; c->file.mmap.start = MAP_FAILED; c->next = NULL; - + return c; } static void chunk_free(chunk *c) { if (!c) return; - + buffer_free(c->mem); buffer_free(c->file.name); @@ -56,13 +56,13 @@ static void chunk_free(chunk *c) { static void chunk_reset(chunk *c) { if (!c) return; - + buffer_reset(c->mem); if (c->file.is_temp && !buffer_is_empty(c->file.name)) { unlink(c->file.name->ptr); } - + buffer_reset(c->file.name); if (c->file.fd != -1) { @@ -78,27 +78,27 @@ static void chunk_reset(chunk *c) { void chunkqueue_free(chunkqueue *cq) { chunk *c, *pc; - + if (!cq) return; - + for (c = cq->first; c; ) { pc = c; c = c->next; chunk_free(pc); } - + for (c = cq->unused; c; ) { pc = c; c = c->next; chunk_free(pc); } - + free(cq); } static chunk *chunkqueue_get_unused_chunk(chunkqueue *cq) { chunk *c; - + /* check if we have a unused chunk */ if (!cq->unused) { c = chunk_init(); @@ -109,18 +109,18 @@ static chunk *chunkqueue_get_unused_chunk(chunkqueue *cq) { c->next = NULL; cq->unused_chunks--; } - + return c; } static int chunkqueue_prepend_chunk(chunkqueue *cq, chunk *c) { c->next = cq->first; cq->first = c; - + if (cq->last == NULL) { cq->last = c; } - + return 0; } @@ -129,19 +129,19 @@ static int chunkqueue_append_chunk(chunkqueue *cq, chunk *c) { cq->last->next = c; } cq->last = c; - + if (cq->first == NULL) { cq->first = c; } - + return 0; } void chunkqueue_reset(chunkqueue *cq) { chunk *c; /* move everything to the unused queue */ - - /* mark all read written */ + + /* mark all read written */ for (c = cq->first; c; c = c->next) { switch(c->type) { case MEM_CHUNK: @@ -150,7 +150,7 @@ void chunkqueue_reset(chunkqueue *cq) { case FILE_CHUNK: c->offset = c->file.length; break; - default: + default: break; } } @@ -162,110 +162,110 @@ void chunkqueue_reset(chunkqueue *cq) { int chunkqueue_append_file(chunkqueue *cq, buffer *fn, off_t offset, off_t len) { chunk *c; - + if (len == 0) return 0; - + c = chunkqueue_get_unused_chunk(cq); - + c->type = FILE_CHUNK; - + buffer_copy_string_buffer(c->file.name, fn); c->file.start = offset; c->file.length = len; c->offset = 0; - + chunkqueue_append_chunk(cq, c); - + return 0; } int chunkqueue_append_buffer(chunkqueue *cq, buffer *mem) { chunk *c; - + if (mem->used == 0) return 0; - + c = chunkqueue_get_unused_chunk(cq); c->type = MEM_CHUNK; c->offset = 0; buffer_copy_string_buffer(c->mem, mem); - + chunkqueue_append_chunk(cq, c); - + return 0; } int chunkqueue_append_buffer_weak(chunkqueue *cq, buffer *mem) { chunk *c; - + if (mem->used == 0) return 0; - + c = chunkqueue_get_unused_chunk(cq); c->type = MEM_CHUNK; c->offset = 0; if (c->mem) buffer_free(c->mem); c->mem = mem; - + chunkqueue_append_chunk(cq, c); - + return 0; } int chunkqueue_prepend_buffer(chunkqueue *cq, buffer *mem) { chunk *c; - + if (mem->used == 0) return 0; - + c = chunkqueue_get_unused_chunk(cq); c->type = MEM_CHUNK; c->offset = 0; buffer_copy_string_buffer(c->mem, mem); - + chunkqueue_prepend_chunk(cq, c); - + return 0; } int chunkqueue_append_mem(chunkqueue *cq, const char * mem, size_t len) { chunk *c; - + if (len == 0) return 0; - + c = chunkqueue_get_unused_chunk(cq); c->type = MEM_CHUNK; c->offset = 0; buffer_copy_string_len(c->mem, mem, len - 1); - + chunkqueue_append_chunk(cq, c); - + return 0; } buffer * chunkqueue_get_prepend_buffer(chunkqueue *cq) { chunk *c; - + c = chunkqueue_get_unused_chunk(cq); - + c->type = MEM_CHUNK; c->offset = 0; buffer_reset(c->mem); - + chunkqueue_prepend_chunk(cq, c); - + return c->mem; } buffer *chunkqueue_get_append_buffer(chunkqueue *cq) { chunk *c; - + c = chunkqueue_get_unused_chunk(cq); - + c->type = MEM_CHUNK; c->offset = 0; buffer_reset(c->mem); - + chunkqueue_append_chunk(cq, c); - + return c->mem; } @@ -280,7 +280,7 @@ int chunkqueue_set_tempdirs(chunkqueue *cq, array *tempdirs) { chunk *chunkqueue_get_append_tempfile(chunkqueue *cq) { chunk *c; buffer *template = buffer_init_string("/var/tmp/lighttpd-upload-XXXXXX"); - + c = chunkqueue_get_unused_chunk(cq); c->type = FILE_CHUNK; @@ -290,7 +290,7 @@ chunk *chunkqueue_get_append_tempfile(chunkqueue *cq) { size_t i; /* we have several tempdirs, only if all of them fail we jump out */ - + for (i = 0; i < cq->tempdirs->used; i++) { data_string *ds = (data_string *)cq->tempdirs->data[i]; @@ -317,7 +317,7 @@ chunk *chunkqueue_get_append_tempfile(chunkqueue *cq) { chunkqueue_append_chunk(cq, c); buffer_free(template); - + return c; } @@ -325,7 +325,7 @@ chunk *chunkqueue_get_append_tempfile(chunkqueue *cq) { off_t chunkqueue_length(chunkqueue *cq) { off_t len = 0; chunk *c; - + for (c = cq->first; c; c = c->next) { switch (c->type) { case MEM_CHUNK: @@ -338,14 +338,14 @@ off_t chunkqueue_length(chunkqueue *cq) { break; } } - + return len; } off_t chunkqueue_written(chunkqueue *cq) { off_t len = 0; chunk *c; - + for (c = cq->first; c; c = c->next) { switch (c->type) { case MEM_CHUNK: @@ -356,7 +356,7 @@ off_t chunkqueue_written(chunkqueue *cq) { break; } } - + return len; } @@ -375,9 +375,9 @@ int chunkqueue_remove_finished_chunks(chunkqueue *cq) { if (c->mem->used == 0 || (c->offset == (off_t)c->mem->used - 1)) is_finished = 1; break; case FILE_CHUNK: - if (c->offset == c->file.length) is_finished = 1; + if (c->offset == c->file.length) is_finished = 1; break; - default: + default: break; } diff --git a/src/chunk.h b/src/chunk.h index 3893919..c3c91ab 100644 --- a/src/chunk.h +++ b/src/chunk.h @@ -6,7 +6,7 @@ typedef struct chunk { enum { UNUSED_CHUNK, MEM_CHUNK, FILE_CHUNK } type; - + buffer *mem; /* either the storage of the mem-chunk or the read-ahead buffer */ struct { @@ -16,7 +16,7 @@ typedef struct chunk { off_t length; /* octets to send from the starting offset */ int fd; - struct { + struct { char *start; /* the start pointer of the mmap'ed area */ size_t length; /* size of the mmap'ed area */ off_t offset; /* start is <n> octet away from the start of the file */ @@ -24,20 +24,20 @@ typedef struct chunk { int is_temp; /* file is temporary and will be deleted if on cleanup */ } file; - - off_t offset; /* octets sent from this chunk - the size of the chunk is either + + off_t offset; /* octets sent from this chunk + the size of the chunk is either - mem-chunk: mem->used - 1 - file-chunk: file.length */ - + struct chunk *next; } chunk; typedef struct { chunk *first; chunk *last; - + chunk *unused; size_t unused_chunks; diff --git a/src/configfile-glue.c b/src/configfile-glue.c index 5d1c8ec..d783689 100644 --- a/src/configfile-glue.c +++ b/src/configfile-glue.c @@ -11,10 +11,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 +24,56 @@ 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 an 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 an 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__, "ss", cv[i].key, "should have been a array of strings like ... = ( \"...\" )"); - + 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 { log_error_write(srv, __FILE__, __LINE__, "ssss", cv[i].key, "should have been a string like ... = \"...\""); - + return -1; } break; @@ -81,15 +81,15 @@ int config_insert_values_internal(server *srv, array *ca, const config_values_t 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; - + log_error_write(srv, __FILE__, __LINE__, "ssb", "got a string but expected a short:", cv[i].key, ds->value); - + return -1; } default: @@ -100,19 +100,19 @@ int config_insert_values_internal(server *srv, array *ca, const config_values_t 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,15 +121,15 @@ int config_insert_values_internal(server *srv, array *ca, const config_values_t break; case T_CONFIG_UNSUPPORTED: log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: found unsupported key:", cv[i].key, "-", (char *)(cv[i].destination)); - + srv->config_unsupported = 1; - + 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; } } @@ -139,25 +139,25 @@ int config_insert_values_internal(server *srv, array *ca, const config_values_t 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); } @@ -197,25 +197,25 @@ static cond_result_t config_check_cond_nocache(server *srv, connection *con, dat } /* 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; @@ -242,15 +242,15 @@ static cond_result_t config_check_cond_nocache(server *srv, connection *con, dat } 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) && @@ -259,41 +259,41 @@ static cond_result_t config_check_cond_nocache(server *srv, connection *con, dat long nm; char *err; struct in_addr val_inp; - + 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 { @@ -318,7 +318,7 @@ static cond_result_t config_check_cond_nocache(server *srv, connection *con, dat case COMP_HTTP_REFERER: { data_string *ds; - + if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Referer"))) { l = ds->value; } else { @@ -348,7 +348,7 @@ static cond_result_t config_check_cond_nocache(server *srv, connection *con, dat default: return COND_RESULT_FALSE; } - + if (NULL == l) { if (con->conf.log_condition_handling) { log_error_write(srv, __FILE__, __LINE__, "bsbs", dc->comp_key, @@ -356,7 +356,7 @@ static cond_result_t config_check_cond_nocache(server *srv, connection *con, dat } 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); @@ -375,13 +375,13 @@ static cond_result_t config_check_cond_nocache(server *srv, connection *con, dat 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; @@ -397,7 +397,7 @@ static cond_result_t config_check_cond_nocache(server *srv, connection *con, dat /* no way */ break; } - + return COND_RESULT_FALSE; } @@ -440,7 +440,7 @@ void config_cond_cache_reset(server *srv, connection *con) { con->cond_cache[i].result = COND_RESULT_UNSET; con->cond_cache[i].patterncount = 0; } -#else +#else memset(con->cond_cache, 0, sizeof(cond_cache_t) * srv->config_context->used); #endif } diff --git a/src/configfile.c b/src/configfile.c index e5d1610..1d3d532 100644 --- a/src/configfile.c +++ b/src/configfile.c @@ -26,8 +26,8 @@ static int config_insert(server *srv) { size_t i; int ret = 0; buffer *stat_cache_string; - - config_values_t cv[] = { + + config_values_t cv[] = { { "server.bind", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 0 */ { "server.errorlog", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 1 */ { "server.errorfile-prefix", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 2 */ @@ -38,7 +38,7 @@ static int config_insert(server *srv) { { "server.tag", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 7 */ { "server.use-ipv6", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 8 */ { "server.modules", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_SERVER }, /* 9 */ - + { "server.event-handler", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 10 */ { "server.pid-file", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 11 */ { "server.max-request-size", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 12 */ @@ -49,7 +49,7 @@ static int config_insert(server *srv) { { "server.max-keep-alive-requests", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 17 */ { "server.name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 18 */ { "server.max-keep-alive-idle", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 19 */ - + { "server.max-read-idle", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 20 */ { "server.max-write-idle", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 21 */ { "server.error-handler-404", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 22 */ @@ -67,19 +67,19 @@ static int config_insert(server *srv) { { "mimetype.use-xattr", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 27 */ { "mimetype.assign", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 28 */ { "ssl.pemfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 29 */ - + { "ssl.engine", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 30 */ - + { "debug.log-file-not-found", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 31 */ { "debug.log-request-handling", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 32 */ { "debug.log-response-header", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 33 */ { "debug.log-request-header", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 34 */ - + { "server.protocol-http11", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 35 */ { "debug.log-request-header-on-error", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 36 */ { "debug.log-state-handling", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 37 */ { "ssl.ca-file", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 38 */ - + { "server.errorlog-use-syslog", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 39 */ { "server.range-requests", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 40 */ { "server.stat-cache-engine", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 41 */ @@ -89,7 +89,7 @@ static int config_insert(server *srv) { { "server.core-files", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 45 */ { "ssl.cipher-list", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 46 */ { "ssl.use-sslv2", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 47 */ - + { "server.host", "use server.bind instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET }, { "server.docroot", "use server.document-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET }, { "server.virtual-root", "load mod_simple_vhost and use simple-vhost.server-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET }, @@ -99,11 +99,11 @@ static int config_insert(server *srv) { { "server.groupid", "use server.groupname instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET }, { "server.use-keep-alive", "use server.max-keep-alive-requests = 0 instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET }, { "server.force-lower-case-files", "use server.force-lowercase-filenames instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET }, - + { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } }; - + /* 0 */ cv[0].destination = srv->srvconf.bindhost; cv[1].destination = srv->srvconf.errorlog_file; @@ -111,33 +111,33 @@ static int config_insert(server *srv) { cv[4].destination = srv->srvconf.username; cv[5].destination = srv->srvconf.groupname; cv[6].destination = &(srv->srvconf.port); - + cv[9].destination = srv->srvconf.modules; cv[10].destination = srv->srvconf.event_handler; cv[11].destination = srv->srvconf.pid_file; - + cv[13].destination = &(srv->srvconf.max_worker); cv[23].destination = &(srv->srvconf.max_fds); cv[36].destination = &(srv->srvconf.log_request_header_on_error); cv[37].destination = &(srv->srvconf.log_state_handling); - + cv[39].destination = &(srv->srvconf.errorlog_use_syslog); - + stat_cache_string = buffer_init(); cv[41].destination = stat_cache_string; cv[43].destination = srv->srvconf.network_backend; cv[44].destination = srv->srvconf.upload_tempdirs; cv[45].destination = &(srv->srvconf.enable_cores); - + cv[42].destination = &(srv->srvconf.max_conns); cv[12].destination = &(srv->srvconf.max_request_size); srv->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *)); assert(srv->config_storage); - + for (i = 0; i < srv->config_context->used; i++) { specific_config *s; - + s = calloc(1, sizeof(specific_config)); assert(s); s->document_root = buffer_init(); @@ -167,13 +167,13 @@ static int config_insert(server *srv) { s->global_kbytes_per_second = 0; s->global_bytes_per_second_cnt = 0; s->global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt; - + cv[2].destination = s->errorfile_prefix; - + cv[7].destination = s->server_tag; cv[8].destination = &(s->use_ipv6); - - + + /* 13 max-worker */ cv[14].destination = s->document_root; cv[15].destination = &(s->force_lowercase_filenames); @@ -194,26 +194,26 @@ static int config_insert(server *srv) { cv[28].destination = s->mimetypes; cv[29].destination = s->ssl_pemfile; cv[30].destination = &(s->is_ssl); - + cv[31].destination = &(s->log_file_not_found); cv[32].destination = &(s->log_request_handling); cv[33].destination = &(s->log_response_header); cv[34].destination = &(s->log_request_header); - + cv[35].destination = &(s->allow_http11); cv[38].destination = s->ssl_ca_file; cv[40].destination = &(s->range_requests); - + cv[46].destination = s->ssl_cipher_list; cv[47].destination = &(s->ssl_use_sslv2); srv->config_storage[i] = s; - + if (0 != (ret = config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv))) { break; } } - + if (buffer_is_empty(stat_cache_string)) { srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_SIMPLE; } else if (buffer_is_equal_string(stat_cache_string, CONST_STR_LEN("simple"))) { @@ -223,22 +223,22 @@ static int config_insert(server *srv) { } else if (buffer_is_equal_string(stat_cache_string, CONST_STR_LEN("disable"))) { srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_NONE; } else { - log_error_write(srv, __FILE__, __LINE__, "sb", + log_error_write(srv, __FILE__, __LINE__, "sb", "server.stat-cache-engine can be one of \"disable\", \"simple\", \"fam\", but not:", stat_cache_string); ret = HANDLER_ERROR; } - + buffer_free(stat_cache_string); - + return ret; - + } #define PATCH(x) con->conf.x = s->x int config_setup_connection(server *srv, connection *con) { specific_config *s = srv->config_storage[0]; - + PATCH(allow_http11); PATCH(mimetypes); PATCH(document_root); @@ -256,20 +256,20 @@ int config_setup_connection(server *srv, connection *con) { PATCH(kbytes_per_second); PATCH(global_kbytes_per_second); PATCH(global_bytes_per_second_cnt); - + con->conf.global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt; buffer_copy_string_buffer(con->server_name, s->server_name); - + PATCH(log_request_header); PATCH(log_response_header); PATCH(log_request_handling); PATCH(log_condition_handling); PATCH(log_file_not_found); - + PATCH(range_requests); PATCH(force_lowercase_filenames); PATCH(is_ssl); - + PATCH(ssl_pemfile); PATCH(ssl_ca_file); PATCH(ssl_cipher_list); @@ -281,22 +281,22 @@ int config_setup_connection(server *srv, connection *con) { int config_patch_connection(server *srv, connection *con, comp_key_t comp) { size_t i, j; - + /* 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]; specific_config *s = srv->config_storage[i]; - + /* not our stage */ if (comp != 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("server.document-root"))) { PATCH(document_root); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.range-requests"))) { @@ -349,7 +349,7 @@ int config_patch_connection(server *srv, connection *con, comp_key_t comp) { PATCH(log_file_not_found); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.protocol-http11"))) { PATCH(allow_http11); - } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.force-lowercase-filenames"))) { + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.force-lowercase-filenames"))) { PATCH(force_lowercase_filenames); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.kbytes-per-second"))) { PATCH(global_kbytes_per_second); @@ -358,7 +358,7 @@ int config_patch_connection(server *srv, connection *con, comp_key_t comp) { } } } - + return 0; } #undef PATCH @@ -366,15 +366,15 @@ int config_patch_connection(server *srv, connection *con, comp_key_t comp) { typedef struct { int foo; int bar; - + const buffer *source; const char *input; size_t offset; size_t size; - + int line_pos; int line; - + int in_key; int in_brace; int in_cond; @@ -392,7 +392,7 @@ static int tokenizer_open(server *srv, tokenizer_t *t, buffer *basedir, const ch } if (0 != stream_open(&(t->s), t->file)) { - log_error_write(srv, __FILE__, __LINE__, "sbss", + log_error_write(srv, __FILE__, __LINE__, "sbss", "opening configfile ", t->file, "failed:", strerror(errno)); buffer_free(t->file); return -1; @@ -403,7 +403,7 @@ static int tokenizer_open(server *srv, tokenizer_t *t, buffer *basedir, const ch t->size = t->s.size; t->line = 1; t->line_pos = 1; - + t->in_key = 1; t->in_brace = 0; t->in_cond = 0; @@ -431,7 +431,7 @@ static int config_skip_newline(tokenizer_t *t) { static int config_skip_comment(tokenizer_t *t) { int i; assert(t->input[t->offset] == '#'); - for (i = 1; t->input[t->offset + i] && + for (i = 1; t->input[t->offset + i] && (t->input[t->offset + i] != '\n' && t->input[t->offset + i] != '\r'); i++); t->offset += i; @@ -441,44 +441,44 @@ static int config_skip_comment(tokenizer_t *t) { static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *token) { int tid = 0; size_t i; - + for (tid = 0; tid == 0 && t->offset < t->size && t->input[t->offset] ; ) { char c = t->input[t->offset]; const char *start = NULL; - + switch (c) { - case '=': + case '=': if (t->in_brace) { if (t->input[t->offset + 1] == '>') { t->offset += 2; - + buffer_copy_string(token, "=>"); - + tid = TK_ARRAY_ASSIGN; } else { - log_error_write(srv, __FILE__, __LINE__, "sbsdsds", + log_error_write(srv, __FILE__, __LINE__, "sbsdsds", "source:", t->source, - "line:", t->line, "pos:", t->line_pos, + "line:", t->line, "pos:", t->line_pos, "use => for assignments in arrays"); return -1; } } else if (t->in_cond) { if (t->input[t->offset + 1] == '=') { t->offset += 2; - + buffer_copy_string(token, "=="); - + tid = TK_EQ; } else if (t->input[t->offset + 1] == '~') { t->offset += 2; - + buffer_copy_string(token, "=~"); - + tid = TK_MATCH; } else { - log_error_write(srv, __FILE__, __LINE__, "sbsdsds", + log_error_write(srv, __FILE__, __LINE__, "sbsdsds", "source:", t->source, - "line:", t->line, "pos:", t->line_pos, + "line:", t->line, "pos:", t->line_pos, "only =~ and == are allowed in the condition"); return -1; } @@ -486,51 +486,51 @@ static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer * t->in_cond = 0; } else if (t->in_key) { tid = TK_ASSIGN; - + buffer_copy_string_len(token, t->input + t->offset, 1); - + t->offset++; t->line_pos++; } else { - log_error_write(srv, __FILE__, __LINE__, "sbsdsds", + log_error_write(srv, __FILE__, __LINE__, "sbsdsds", "source:", t->source, - "line:", t->line, "pos:", t->line_pos, + "line:", t->line, "pos:", t->line_pos, "unexpected equal-sign: ="); return -1; } - + break; - case '!': + case '!': if (t->in_cond) { if (t->input[t->offset + 1] == '=') { t->offset += 2; - + buffer_copy_string(token, "!="); - + tid = TK_NE; } else if (t->input[t->offset + 1] == '~') { t->offset += 2; - + buffer_copy_string(token, "!~"); - + tid = TK_NOMATCH; } else { - log_error_write(srv, __FILE__, __LINE__, "sbsdsds", + log_error_write(srv, __FILE__, __LINE__, "sbsdsds", "source:", t->source, - "line:", t->line, "pos:", t->line_pos, + "line:", t->line, "pos:", t->line_pos, "only !~ and != are allowed in the condition"); return -1; } t->in_key = 1; t->in_cond = 0; } else { - log_error_write(srv, __FILE__, __LINE__, "sbsdsds", + log_error_write(srv, __FILE__, __LINE__, "sbsdsds", "source:", t->source, - "line:", t->line, "pos:", t->line_pos, + "line:", t->line, "pos:", t->line_pos, "unexpected exclamation-marks: !"); return -1; } - + break; case '\t': case ' ': @@ -576,10 +576,10 @@ static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer * case ',': if (t->in_brace > 0) { tid = TK_COMMA; - + buffer_copy_string(token, "(COMMA)"); } - + t->offset++; t->line_pos++; break; @@ -587,70 +587,70 @@ static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer * /* search for the terminating " */ start = t->input + t->offset + 1; buffer_copy_string(token, ""); - + for (i = 1; t->input[t->offset + i]; i++) { if (t->input[t->offset + i] == '\\' && t->input[t->offset + i + 1] == '"') { - + buffer_append_string_len(token, start, t->input + t->offset + i - start); - + start = t->input + t->offset + i + 1; - + /* skip the " */ i++; continue; } - - + + if (t->input[t->offset + i] == '"') { tid = TK_STRING; - + buffer_append_string_len(token, start, t->input + t->offset + i - start); - + break; } } if (t->input[t->offset + i] == '\0') { /* ERROR */ - - log_error_write(srv, __FILE__, __LINE__, "sbsdsds", + + log_error_write(srv, __FILE__, __LINE__, "sbsdsds", "source:", t->source, - "line:", t->line, "pos:", t->line_pos, + "line:", t->line, "pos:", t->line_pos, "missing closing quote"); - + return -1; } - + t->offset += i + 1; t->line_pos += i + 1; - + break; case '(': t->offset++; t->in_brace++; - + tid = TK_LPARAN; - + buffer_copy_string(token, "("); break; case ')': t->offset++; t->in_brace--; - + tid = TK_RPARAN; - + buffer_copy_string(token, ")"); break; case '$': t->offset++; - + tid = TK_DOLLAR; t->in_cond = 1; t->in_key = 0; - + buffer_copy_string(token, "$"); - + break; case '+': @@ -667,88 +667,88 @@ static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer * case '{': t->offset++; - + tid = TK_LCURLY; - + buffer_copy_string(token, "{"); - + break; - + case '}': t->offset++; - + tid = TK_RCURLY; - + buffer_copy_string(token, "}"); - + break; case '[': t->offset++; - + tid = TK_LBRACKET; - + buffer_copy_string(token, "["); - + break; - + case ']': t->offset++; - + tid = TK_RBRACKET; - + buffer_copy_string(token, "]"); - + break; case '#': t->line_pos += config_skip_comment(t); - + break; default: if (t->in_cond) { - for (i = 0; t->input[t->offset + i] && + for (i = 0; t->input[t->offset + i] && (isalpha((unsigned char)t->input[t->offset + i]) ); i++); - + if (i && t->input[t->offset + i]) { tid = TK_SRVVARNAME; buffer_copy_string_len(token, t->input + t->offset, i); - + t->offset += i; t->line_pos += i; } else { /* ERROR */ - log_error_write(srv, __FILE__, __LINE__, "sbsdsds", + log_error_write(srv, __FILE__, __LINE__, "sbsdsds", "source:", t->source, - "line:", t->line, "pos:", t->line_pos, + "line:", t->line, "pos:", t->line_pos, "invalid character in condition"); return -1; } } else if (isdigit((unsigned char)c)) { /* take all digits */ for (i = 0; t->input[t->offset + i] && isdigit((unsigned char)t->input[t->offset + i]); i++); - + /* was there it least a digit ? */ if (i) { tid = TK_INTEGER; - + buffer_copy_string_len(token, t->input + t->offset, i); - + t->offset += i; t->line_pos += i; } } else { /* the key might consist of [-.0-9a-z] */ - for (i = 0; t->input[t->offset + i] && - (isalnum((unsigned char)t->input[t->offset + i]) || + for (i = 0; t->input[t->offset + i] && + (isalnum((unsigned char)t->input[t->offset + i]) || t->input[t->offset + i] == '.' || t->input[t->offset + i] == '_' || /* for env.* */ t->input[t->offset + i] == '-' ); i++); - + if (i && t->input[t->offset + i]) { buffer_copy_string_len(token, t->input + t->offset, i); - + if (strcmp(token->ptr, "include") == 0) { tid = TK_INCLUDE; } else if (strcmp(token->ptr, "include_shell") == 0) { @@ -760,14 +760,14 @@ static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer * } else { tid = TK_LKEY; } - + t->offset += i; t->line_pos += i; } else { /* ERROR */ - log_error_write(srv, __FILE__, __LINE__, "sbsdsds", + log_error_write(srv, __FILE__, __LINE__, "sbsdsds", "source:", t->source, - "line:", t->line, "pos:", t->line_pos, + "line:", t->line, "pos:", t->line_pos, "invalid character in variable name"); return -1; } @@ -775,16 +775,16 @@ static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer * break; } } - + if (tid) { *token_id = tid; #if 0 - log_error_write(srv, __FILE__, __LINE__, "sbsdsdbdd", + log_error_write(srv, __FILE__, __LINE__, "sbsdsdbdd", "source:", t->source, "line:", t->line, "pos:", t->line_pos, token, token->used - 1, tid); #endif - + return 1; } else if (t->offset < t->size) { fprintf(stderr, "%s.%d: %d, %s\n", @@ -806,7 +806,7 @@ static int config_parse(server *srv, config_t *context, tokenizer_t *t) { while((1 == (ret = config_tokenizer(srv, t, &token_id, token))) && context->ok) { buffer_copy_string_buffer(lasttoken, token); configparser(pParser, token_id, token, context); - + token = buffer_init(); } buffer_free(token); @@ -819,14 +819,14 @@ static int config_parse(server *srv, config_t *context, tokenizer_t *t) { } } configparserFree(pParser, free); - + if (ret == -1) { - log_error_write(srv, __FILE__, __LINE__, "sb", + log_error_write(srv, __FILE__, __LINE__, "sb", "configfile parser failed at:", lasttoken); } else if (context->ok == 0) { - log_error_write(srv, __FILE__, __LINE__, "sbsdsdsb", + log_error_write(srv, __FILE__, __LINE__, "sbsdsdsb", "source:", t->source, - "line:", t->line, "pos:", t->line_pos, + "line:", t->line, "pos:", t->line_pos, "parser failed somehow near here:", lasttoken); ret = -1; } @@ -843,7 +843,7 @@ static int tokenizer_init(tokenizer_t *t, const buffer *source, const char *inpu t->offset = 0; t->line = 1; t->line_pos = 1; - + t->in_key = 1; t->in_brace = 0; t->in_cond = 0; @@ -866,7 +866,7 @@ int config_parse_file(server *srv, config_t *context, const char *fn) { } if (0 != stream_open(&s, filename)) { - log_error_write(srv, __FILE__, __LINE__, "sbss", + log_error_write(srv, __FILE__, __LINE__, "sbss", "opening configfile ", filename, "failed:", strerror(errno)); ret = -1; } else { @@ -888,7 +888,7 @@ int config_parse_cmd(server *srv, config_t *context, const char *cmd) { char oldpwd[PATH_MAX]; if (NULL == getcwd(oldpwd, sizeof(oldpwd))) { - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "cannot get cwd", strerror(errno)); return -1; } @@ -901,7 +901,7 @@ int config_parse_cmd(server *srv, config_t *context, const char *cmd) { } if (0 != proc_open_buffer(&proc, cmd, NULL, out, NULL)) { - log_error_write(srv, __FILE__, __LINE__, "sbss", + log_error_write(srv, __FILE__, __LINE__, "sbss", "opening", source, "failed:", strerror(errno)); ret = -1; } else { @@ -951,7 +951,7 @@ int config_read(server *srv, const char *fn) { buffer_copy_string_len(context.basedir, fn, pos - fn + 1); fn = pos + 1; } - + dc = data_config_init(); buffer_copy_string(dc->key, "global"); @@ -966,7 +966,7 @@ int config_read(server *srv, const char *fn) { dpid->value = getpid(); buffer_copy_string(dpid->key, "var.PID"); array_insert_unique(srv->config, (data_unset *)dpid); - + dcwd = data_string_init(); buffer_prepare_copy(dcwd->value, 1024); if (NULL != getcwd(dcwd->value->ptr, dcwd->value->size - 1)) { @@ -990,7 +990,7 @@ int config_read(server *srv, const char *fn) { } else { return -1; } - + if (NULL != (modules = (data_array *)array_get_element(srv->config, "server.modules"))) { data_string *ds; data_array *prepends; @@ -1048,12 +1048,12 @@ int config_read(server *srv, const char *fn) { buffer_copy_string(modules->key, "server.modules"); array_insert_unique(srv->config, (data_unset *)modules); } - + if (0 != config_insert(srv)) { return -1; } - + return 0; } @@ -1061,9 +1061,9 @@ int config_set_defaults(server *srv) { size_t i; specific_config *s = srv->config_storage[0]; struct stat st1, st2; - - struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] = - { + + struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] = + { /* - poll is most reliable * - select works everywhere * - linux-* are experimental @@ -1089,20 +1089,20 @@ int config_set_defaults(server *srv) { #endif { FDEVENT_HANDLER_UNSET, NULL } }; - - - if (buffer_is_empty(s->document_root)) { - log_error_write(srv, __FILE__, __LINE__, "s", - "a default document-root has to be set"); - - return -1; - } - + + + if (buffer_is_empty(s->document_root)) { + log_error_write(srv, __FILE__, __LINE__, "s", + "a default document-root has to be set"); + + return -1; + } + if (buffer_is_empty(srv->srvconf.changeroot)) { - if (-1 == stat(s->document_root->ptr, &st1)) { - log_error_write(srv, __FILE__, __LINE__, "sb", + if (-1 == stat(s->document_root->ptr, &st1)) { + log_error_write(srv, __FILE__, __LINE__, "sb", "base-docroot doesn't exist:", - s->document_root); + s->document_root); return -1; } @@ -1110,18 +1110,18 @@ int config_set_defaults(server *srv) { buffer_copy_string_buffer(srv->tmp_buf, srv->srvconf.changeroot); buffer_append_string_buffer(srv->tmp_buf, s->document_root); - if (-1 == stat(srv->tmp_buf->ptr, &st1)) { - log_error_write(srv, __FILE__, __LINE__, "sb", + if (-1 == stat(srv->tmp_buf->ptr, &st1)) { + log_error_write(srv, __FILE__, __LINE__, "sb", "base-docroot doesn't exist:", - srv->tmp_buf); + srv->tmp_buf); return -1; } - + } - - buffer_copy_string_buffer(srv->tmp_buf, s->document_root); - buffer_to_lower(srv->tmp_buf); + buffer_copy_string_buffer(srv->tmp_buf, s->document_root); + + buffer_to_lower(srv->tmp_buf); if (0 == stat(srv->tmp_buf->ptr, &st1)) { int is_lower = 0; @@ -1129,68 +1129,68 @@ int config_set_defaults(server *srv) { is_lower = buffer_is_equal(srv->tmp_buf, s->document_root); /* lower-case existed, check upper-case */ - buffer_copy_string_buffer(srv->tmp_buf, s->document_root); + buffer_copy_string_buffer(srv->tmp_buf, s->document_root); - buffer_to_upper(srv->tmp_buf); + buffer_to_upper(srv->tmp_buf); /* we have to handle the special case that upper and lower-casing results in the same filename * as in server.document-root = "/" or "/12345/" */ if (is_lower && buffer_is_equal(srv->tmp_buf, s->document_root)) { - /* lower-casing and upper-casing didn't result in - * an other filename, no need to stat(), + /* lower-casing and upper-casing didn't result in + * an other filename, no need to stat(), * just assume it is case-sensitive. */ s->force_lowercase_filenames = 0; - } else if (0 == stat(srv->tmp_buf->ptr, &st2)) { - - /* upper case exists too, doesn't the FS handle this ? */ - - /* upper and lower have the same inode -> case-insensitve FS */ - - if (st1.st_ino == st2.st_ino) { - /* upper and lower have the same inode -> case-insensitve FS */ - - s->force_lowercase_filenames = 1; - } - } - } - + } else if (0 == stat(srv->tmp_buf->ptr, &st2)) { + + /* upper case exists too, doesn't the FS handle this ? */ + + /* upper and lower have the same inode -> case-insensitve FS */ + + if (st1.st_ino == st2.st_ino) { + /* upper and lower have the same inode -> case-insensitve FS */ + + s->force_lowercase_filenames = 1; + } + } + } + if (srv->srvconf.port == 0) { srv->srvconf.port = s->is_ssl ? 443 : 80; } - + if (srv->srvconf.event_handler->used == 0) { /* choose a good default - * - * the event_handler list is sorted by 'goodness' + * + * the event_handler list is sorted by 'goodness' * taking the first available should be the best solution */ srv->event_handler = event_handlers[0].et; - + if (FDEVENT_HANDLER_UNSET == srv->event_handler) { - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "sorry, there is no event handler for this system"); - + return -1; } } else { /* * User override */ - + for (i = 0; event_handlers[i].name; i++) { if (0 == strcmp(event_handlers[i].name, srv->srvconf.event_handler->ptr)) { srv->event_handler = event_handlers[i].et; break; } } - + if (FDEVENT_HANDLER_UNSET == srv->event_handler) { - log_error_write(srv, __FILE__, __LINE__, "sb", - "the selected event-handler in unknown or not supported:", + log_error_write(srv, __FILE__, __LINE__, "sb", + "the selected event-handler in unknown or not supported:", srv->srvconf.event_handler ); - + return -1; } } @@ -1198,19 +1198,19 @@ int config_set_defaults(server *srv) { if (s->is_ssl) { if (buffer_is_empty(s->ssl_pemfile)) { /* PEM file is require */ - - log_error_write(srv, __FILE__, __LINE__, "s", + + log_error_write(srv, __FILE__, __LINE__, "s", "ssl.pemfile has to be set"); return -1; } - + #ifndef USE_OPENSSL - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "ssl support is missing, recompile with --with-openssl"); - + return -1; #endif } - + return 0; } diff --git a/src/configparser.c b/src/configparser.c index 266a1c7..292cff0 100644 --- a/src/configparser.c +++ b/src/configparser.c @@ -110,10 +110,10 @@ data_unset *configparser_merge_data(data_unset *op1, const data_unset *op2) { /* 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. */ @@ -130,7 +130,7 @@ data_unset *configparser_merge_data(data_unset *op1, const data_unset *op2) { ** 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 @@ -139,7 +139,7 @@ data_unset *configparser_merge_data(data_unset *op1, const data_unset *op2) { ** and nonterminal numbers. "unsigned char" is ** used if there are fewer than 250 rules and ** states combined. "int" is used otherwise. -** configparserTOKENTYPE is the data type used for minor tokens given +** configparserTOKENTYPE 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 @@ -185,7 +185,7 @@ typedef union { /* 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 @@ -210,7 +210,7 @@ typedef union { ** 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 @@ -292,7 +292,7 @@ static YYACTIONTYPE yy_default[] = { /* 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, @@ -343,10 +343,10 @@ static char *yyTracePrompt = 0; #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: ** <ul> @@ -371,7 +371,7 @@ void configparserTrace(FILE *TraceFILE, char *zTracePrompt){ #ifndef NDEBUG /* For tracing shifts, the names of all terminals and nonterminals ** are required. The following table supplies these names */ -static const char *yyTokenName[] = { +static const char *yyTokenName[] = { "$", "EOL", "ASSIGN", "APPEND", "LKEY", "PLUS", "STRING", "INTEGER", "LPARAN", "RPARAN", "COMMA", "ARRAY_ASSIGN", @@ -450,7 +450,7 @@ const char *configparserTokenName(int tokenType){ #endif } -/* +/* ** This function allocates a new parser. ** The only argument is a pointer to a function which works like ** malloc. @@ -481,7 +481,7 @@ static void yy_destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor){ /* Here is inserted the actions which take place when a ** terminal or non-terminal is destroyed. This can happen ** when the symbol is popped from the stack during a - ** reduce or during error processing or when a parser is + ** reduce or during error processing or when a parser is ** being destroyed before it is finished parsing. ** ** Note: during a reduce, the only symbols destroyed are those @@ -582,7 +582,7 @@ static int yy_pop_parser_stack(yyParser *pParser){ return yymajor; } -/* +/* ** Deallocate and destroy a parser. Destructors are all called for ** all stack elements before shutting the parser down. ** @@ -618,7 +618,7 @@ static int yy_find_shift_action( ){ int i; int stateno = pParser->yystack[pParser->yyidx].stateno; - + /* if( pParser->yyidx<0 ) return YY_NO_ACTION; */ i = yy_shift_ofst[stateno]; if( i==YY_SHIFT_USE_DFLT ){ @@ -662,7 +662,7 @@ static int yy_find_reduce_action( ){ int i; int stateno = pParser->yystack[pParser->yyidx].stateno; - + i = yy_reduce_ofst[stateno]; if( i==YY_REDUCE_USE_DFLT ){ return yy_default[stateno]; @@ -786,7 +786,7 @@ static void yy_reduce( configparserARG_FETCH; yymsp = &yypParser->yystack[yypParser->yyidx]; #ifndef NDEBUG - if( yyTraceFILE && yyruleno>=0 + if( yyTraceFILE && yyruleno>=0 && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){ fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt, yyRuleName[yyruleno]); @@ -845,7 +845,7 @@ static void yy_reduce( array_insert_unique(ctx->current->value, yymsp[0].minor.yy41); yymsp[0].minor.yy41 = NULL; } else { - fprintf(stderr, "Duplicate config variable in conditional %d %s: %s\n", + fprintf(stderr, "Duplicate config variable in conditional %d %s: %s\n", ctx->current->context_ndx, ctx->current->key->ptr, yymsp[0].minor.yy41->key->ptr); ctx->ok = 0; @@ -1024,13 +1024,13 @@ static void yy_reduce( array_insert_unique(yymsp[-2].minor.yy40, yymsp[0].minor.yy41); yymsp[0].minor.yy41 = NULL; } else { - fprintf(stderr, "Duplicate array-key: %s\n", + fprintf(stderr, "Duplicate array-key: %s\n", yymsp[0].minor.yy41->key->ptr); ctx->ok = 0; yymsp[0].minor.yy41->free(yymsp[0].minor.yy41); yymsp[0].minor.yy41 = NULL; } - + yygotominor.yy40 = yymsp[-2].minor.yy40; yymsp[-2].minor.yy40 = NULL; } @@ -1069,7 +1069,7 @@ static void yy_reduce( buffer_copy_string_buffer(yymsp[0].minor.yy41->key, yymsp[-2].minor.yy43); buffer_free(yymsp[-2].minor.yy43); yymsp[-2].minor.yy43 = NULL; - + yygotominor.yy41 = yymsp[0].minor.yy41; yymsp[0].minor.yy41 = NULL; } @@ -1096,7 +1096,7 @@ static void yy_reduce( #line 336 "./configparser.y" { data_config *cur; - + cur = ctx->current; configparser_pop(ctx); @@ -1136,7 +1136,7 @@ static void yy_reduce( #line 361 "./configparser.y" { data_config *cur; - + cur = ctx->current; configparser_pop(ctx); @@ -1187,7 +1187,7 @@ static void yy_reduce( buffer_append_string_buffer(b, op); rvalue = ((data_string*)yymsp[0].minor.yy41)->value; buffer_append_string_buffer(b, rvalue); - + if (NULL != (dc = (data_config *)array_get_element(ctx->all_configs, b->ptr))) { configparser_push(ctx, dc, 0); } else { @@ -1209,7 +1209,7 @@ static void yy_reduce( size_t i; dc = data_config_init(); - + buffer_copy_string_buffer(dc->key, b); buffer_copy_string_buffer(dc->op, op); buffer_copy_string_buffer(dc->comp_key, yymsp[-5].minor.yy0); @@ -1217,7 +1217,7 @@ static void yy_reduce( buffer_append_string_buffer(dc->comp_key, yymsp[-3].minor.yy43); buffer_append_string_len(dc->comp_key, CONST_STR_LEN("\"]")); dc->cond = yymsp[-1].minor.yy27; - + for (i = 0; comps[i].comp_key; i ++) { if (buffer_is_equal_string( dc->comp_key, comps[i].comp_key, comps[i].len)) { @@ -1240,20 +1240,20 @@ static void yy_reduce( #ifdef HAVE_PCRE_H const char *errptr; int erroff; - - if (NULL == (dc->regex = + + if (NULL == (dc->regex = pcre_compile(rvalue->ptr, 0, &errptr, &erroff, NULL))) { dc->string = buffer_init_string(errptr); dc->cond = CONFIG_COND_UNSET; - fprintf(stderr, "parsing regex failed: %s -> %s at offset %d\n", + fprintf(stderr, "parsing regex failed: %s -> %s at offset %d\n", rvalue->ptr, errptr, erroff); ctx->ok = 0; } else if (NULL == (dc->regex_study = - pcre_study(dc->regex, 0, &errptr)) && + pcre_study(dc->regex, 0, &errptr)) && errptr != NULL) { - fprintf(stderr, "studying regex failed: %s -> %s\n", + fprintf(stderr, "studying regex failed: %s -> %s\n", rvalue->ptr, errptr); ctx->ok = 0; } else { @@ -1261,7 +1261,7 @@ static void yy_reduce( } #else fprintf(stderr, "can't handle '$%s[%s] =~ ...' as you compiled without pcre support. \n" - "(perhaps just a missing pcre-devel package ?) \n", + "(perhaps just a missing pcre-devel package ?) \n", yymsp[-5].minor.yy0->ptr, yymsp[-3].minor.yy43->ptr); ctx->ok = 0; #endif @@ -1269,12 +1269,12 @@ static void yy_reduce( } default: - fprintf(stderr, "unknown condition for $%s[%s]\n", + fprintf(stderr, "unknown condition for $%s[%s]\n", yymsp[-5].minor.yy0->ptr, yymsp[-3].minor.yy43->ptr); ctx->ok = 0; break; } - + configparser_push(ctx, dc, 1); } @@ -1510,7 +1510,7 @@ void configparser( #ifdef YYERRORSYMBOL /* A syntax error has occurred. ** The response to an error depends upon whether or not the - ** grammar defines an error token "ERROR". + ** grammar defines an error token "ERROR". ** ** This is what we do if the grammar does define ERROR: ** diff --git a/src/configparser.y b/src/configparser.y index 122f424..b5bc785 100644 --- a/src/configparser.y +++ b/src/configparser.y @@ -152,7 +152,7 @@ varline ::= key(A) ASSIGN expression(B). { array_insert_unique(ctx->current->value, B); B = NULL; } else { - fprintf(stderr, "Duplicate config variable in conditional %d %s: %s\n", + fprintf(stderr, "Duplicate config variable in conditional %d %s: %s\n", ctx->current->context_ndx, ctx->current->key->ptr, B->key->ptr); ctx->ok = 0; @@ -288,13 +288,13 @@ aelements(A) ::= aelements(C) COMMA aelement(B). { array_insert_unique(C, B); B = NULL; } else { - fprintf(stderr, "Duplicate array-key: %s\n", + fprintf(stderr, "Duplicate array-key: %s\n", B->key->ptr); ctx->ok = 0; B->free(B); B = NULL; } - + A = C; C = NULL; } @@ -318,7 +318,7 @@ aelement(A) ::= stringop(B) ARRAY_ASSIGN expression(C). { buffer_copy_string_buffer(C->key, B); buffer_free(B); B = NULL; - + A = C; C = NULL; } @@ -335,7 +335,7 @@ globalstart ::= GLOBAL. { global(A) ::= globalstart LCURLY metalines RCURLY. { data_config *cur; - + cur = ctx->current; configparser_pop(ctx); @@ -360,7 +360,7 @@ condlines(A) ::= condline(B). { condline(A) ::= context LCURLY metalines RCURLY. { data_config *cur; - + cur = ctx->current; configparser_pop(ctx); @@ -404,7 +404,7 @@ context ::= DOLLAR SRVVARNAME(B) LBRACKET stringop(C) RBRACKET cond(E) expressio buffer_append_string_buffer(b, op); rvalue = ((data_string*)D)->value; buffer_append_string_buffer(b, rvalue); - + if (NULL != (dc = (data_config *)array_get_element(ctx->all_configs, b->ptr))) { configparser_push(ctx, dc, 0); } else { @@ -426,7 +426,7 @@ context ::= DOLLAR SRVVARNAME(B) LBRACKET stringop(C) RBRACKET cond(E) expressio size_t i; dc = data_config_init(); - + buffer_copy_string_buffer(dc->key, b); buffer_copy_string_buffer(dc->op, op); buffer_copy_string_buffer(dc->comp_key, B); @@ -434,7 +434,7 @@ context ::= DOLLAR SRVVARNAME(B) LBRACKET stringop(C) RBRACKET cond(E) expressio buffer_append_string_buffer(dc->comp_key, C); buffer_append_string_len(dc->comp_key, CONST_STR_LEN("\"]")); dc->cond = E; - + for (i = 0; comps[i].comp_key; i ++) { if (buffer_is_equal_string( dc->comp_key, comps[i].comp_key, comps[i].len)) { @@ -457,20 +457,20 @@ context ::= DOLLAR SRVVARNAME(B) LBRACKET stringop(C) RBRACKET cond(E) expressio #ifdef HAVE_PCRE_H const char *errptr; int erroff; - - if (NULL == (dc->regex = + + if (NULL == (dc->regex = pcre_compile(rvalue->ptr, 0, &errptr, &erroff, NULL))) { dc->string = buffer_init_string(errptr); dc->cond = CONFIG_COND_UNSET; - fprintf(stderr, "parsing regex failed: %s -> %s at offset %d\n", + fprintf(stderr, "parsing regex failed: %s -> %s at offset %d\n", rvalue->ptr, errptr, erroff); ctx->ok = 0; } else if (NULL == (dc->regex_study = - pcre_study(dc->regex, 0, &errptr)) && + pcre_study(dc->regex, 0, &errptr)) && errptr != NULL) { - fprintf(stderr, "studying regex failed: %s -> %s\n", + fprintf(stderr, "studying regex failed: %s -> %s\n", rvalue->ptr, errptr); ctx->ok = 0; } else { @@ -478,7 +478,7 @@ context ::= DOLLAR SRVVARNAME(B) LBRACKET stringop(C) RBRACKET cond(E) expressio } #else fprintf(stderr, "can't handle '$%s[%s] =~ ...' as you compiled without pcre support. \n" - "(perhaps just a missing pcre-devel package ?) \n", + "(perhaps just a missing pcre-devel package ?) \n", B->ptr, C->ptr); ctx->ok = 0; #endif @@ -486,12 +486,12 @@ context ::= DOLLAR SRVVARNAME(B) LBRACKET stringop(C) RBRACKET cond(E) expressio } default: - fprintf(stderr, "unknown condition for $%s[%s]\n", + fprintf(stderr, "unknown condition for $%s[%s]\n", B->ptr, C->ptr); ctx->ok = 0; break; } - + configparser_push(ctx, dc, 1); } diff --git a/src/connections-glue.c b/src/connections-glue.c index ac6d267..89180b4 100644 --- a/src/connections-glue.c +++ b/src/connections-glue.c @@ -13,7 +13,7 @@ const char *connection_get_state(connection_state_t state) { 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 @@ const char *connection_get_short_state(connection_state_t state) { 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; } diff --git a/src/connections.c b/src/connections.c index 4e5a4fb..5596eff 100644 --- a/src/connections.c +++ b/src/connections.c @@ -26,8 +26,8 @@ #include "inet_ntop_cache.h" #ifdef USE_OPENSSL -# include <openssl/ssl.h> -# include <openssl/err.h> +# include <openssl/ssl.h> +# include <openssl/err.h> #endif #ifdef HAVE_SYS_FILIO_H @@ -43,7 +43,7 @@ typedef struct { static connection *connections_get_new_connection(server *srv) { connections *conns = srv->conns; size_t i; - + if (conns->size == 0) { conns->size = 128; conns->ptr = NULL; @@ -54,21 +54,21 @@ static connection *connections_get_new_connection(server *srv) { } else if (conns->size == conns->used) { conns->size += 128; conns->ptr = realloc(conns->ptr, sizeof(*conns->ptr) * conns->size); - + for (i = conns->used; i < conns->size; i++) { conns->ptr[i] = connection_init(srv); } } connection_reset(srv, conns->ptr[conns->used]); -#if 0 +#if 0 fprintf(stderr, "%s.%d: add: ", __FILE__, __LINE__); for (i = 0; i < conns->used + 1; i++) { fprintf(stderr, "%d ", conns->ptr[i]->fd); } fprintf(stderr, "\n"); -#endif - +#endif + conns->ptr[conns->used]->ndx = conns->used; return conns->ptr[conns->used++]; } @@ -77,26 +77,26 @@ static int connection_del(server *srv, connection *con) { size_t i; connections *conns = srv->conns; connection *temp; - + if (con == NULL) return -1; - + if (-1 == con->ndx) return -1; - + i = con->ndx; - + /* not last element */ - + if (i != conns->used - 1) { temp = conns->ptr[i]; conns->ptr[i] = conns->ptr[conns->used - 1]; conns->ptr[conns->used - 1] = temp; - + conns->ptr[i]->ndx = i; conns->ptr[conns->used - 1]->ndx = -1; } - + conns->used--; - + con->ndx = -1; #if 0 fprintf(stderr, "%s.%d: del: (%d)", __FILE__, __LINE__, conns->used); @@ -104,7 +104,7 @@ static int connection_del(server *srv, connection *con) { fprintf(stderr, "%d ", conns->ptr[i]->fd); } fprintf(stderr, "\n"); -#endif +#endif return 0; } @@ -112,14 +112,14 @@ int connection_close(server *srv, connection *con) { #ifdef USE_OPENSSL server_socket *srv_sock = con->srv_socket; #endif - + #ifdef USE_OPENSSL if (srv_sock->is_ssl) { if (con->ssl) SSL_free(con->ssl); con->ssl = NULL; } #endif - + fdevent_event_del(srv->ev, &(con->fde_ndx), con->fd); fdevent_unregister(srv->ev, con->fd); #ifdef __WIN32 @@ -133,62 +133,62 @@ int connection_close(server *srv, connection *con) { "(warning) close:", con->fd, strerror(errno)); } #endif - + srv->cur_fds--; #if 0 log_error_write(srv, __FILE__, __LINE__, "sd", "closed()", con->fd); #endif - + connection_del(srv, con); connection_set_state(srv, con, CON_STATE_CONNECT); - + return 0; } #if 0 static void dump_packet(const unsigned char *data, size_t len) { size_t i, j; - + if (len == 0) return; - + for (i = 0; i < len; i++) { if (i % 16 == 0) fprintf(stderr, " "); - + fprintf(stderr, "%02x ", data[i]); - + if ((i + 1) % 16 == 0) { fprintf(stderr, " "); for (j = 0; j <= i % 16; j++) { unsigned char c; - + if (i-15+j >= len) break; - + c = data[i-15+j]; - + fprintf(stderr, "%c", c > 32 && c < 128 ? c : '.'); } - + fprintf(stderr, "\n"); } } - + if (len % 16 != 0) { for (j = i % 16; j < 16; j++) { fprintf(stderr, " "); } - + fprintf(stderr, " "); for (j = i & ~0xf; j < len; j++) { unsigned char c; - + c = data[j]; fprintf(stderr, "%c", c > 32 && c < 128 ? c : '.'); } fprintf(stderr, "\n"); } } -#endif +#endif static int connection_handle_read_ssl(server *srv, connection *con) { #ifdef USE_OPENSSL @@ -216,10 +216,10 @@ static int connection_handle_read_ssl(server *srv, connection *con) { if (len > 0) { b->used = len; b->ptr[b->used++] = '\0'; - + /* we move the buffer to the chunk-queue, no need to free it */ - chunkqueue_append_buffer_weak(con->read_queue, b); + chunkqueue_append_buffer_weak(con->read_queue, b); con->bytes_read += len; b = NULL; } @@ -240,52 +240,52 @@ static int connection_handle_read_ssl(server *srv, connection *con) { case SSL_ERROR_SYSCALL: /** * man SSL_get_error() - * + * * SSL_ERROR_SYSCALL - * Some I/O error occurred. The OpenSSL error queue may contain more + * Some I/O error occurred. The OpenSSL error queue may contain more * information on the error. If the error queue is empty (i.e. - * ERR_get_error() returns 0), ret can be used to find out more about + * ERR_get_error() returns 0), ret can be used to find out more about * the error: If ret == 0, an EOF was observed that violates the - * protocol. If ret == -1, the underlying BIO reported an I/O error + * protocol. If ret == -1, the underlying BIO reported an I/O error * (for socket I/O on Unix systems, consult errno for details). * */ while((ssl_err = ERR_get_error())) { /* get all errors from the error-queue */ - log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:", + log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:", r, ERR_error_string(ssl_err, NULL)); } switch(errno) { default: - log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:", + log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:", len, r, errno, strerror(errno)); break; } - + break; case SSL_ERROR_ZERO_RETURN: /* clean shutdown on the remote side */ - + if (r == 0) { /* FIXME: later */ } - + /* fall thourgh */ default: while((ssl_err = ERR_get_error())) { /* get all errors from the error-queue */ - log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:", + log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:", r, ERR_error_string(ssl_err, NULL)); } break; } - + connection_set_state(srv, con, CON_STATE_ERROR); buffer_free(b); - + return -1; } else if (len == 0) { con->is_readable = 0; @@ -318,34 +318,34 @@ static int connection_handle_read(server *srv, connection *con) { len = recv(con->fd, b->ptr, b->size - 1, 0); #else if (ioctl(con->fd, FIONREAD, &toread)) { - log_error_write(srv, __FILE__, __LINE__, "sd", + log_error_write(srv, __FILE__, __LINE__, "sd", "unexpected end-of-file:", con->fd); return -1; } b = chunkqueue_get_append_buffer(con->read_queue); - buffer_prepare_copy(b, toread); + buffer_prepare_copy(b, toread + 1); len = read(con->fd, b->ptr, b->size - 1); #endif - + if (len < 0) { con->is_readable = 0; - + if (errno == EAGAIN) return 0; if (errno == EINTR) { /* we have been interrupted before we could read */ con->is_readable = 1; return 0; } - + if (errno != ECONNRESET) { /* expected for keep-alive */ log_error_write(srv, __FILE__, __LINE__, "ssd", "connection closed - read failed: ", strerror(errno), errno); } connection_set_state(srv, con, CON_STATE_ERROR); - + return -1; } else if (len == 0) { con->is_readable = 0; @@ -356,18 +356,18 @@ static int connection_handle_read(server *srv, connection *con) { return -2; } else if ((size_t)len < b->size - 1) { /* we got less then expected, wait for the next fd-event */ - + con->is_readable = 0; } - + b->used = len; b->ptr[b->used++] = '\0'; - + con->bytes_read += len; #if 0 dump_packet(b->ptr, len); #endif - + return 0; } @@ -385,12 +385,14 @@ static int connection_handle_write_prepare(server *srv, connection *con) { case HTTP_METHOD_MOVE: case HTTP_METHOD_PROPFIND: case HTTP_METHOD_PROPPATCH: + case HTTP_METHOD_LOCK: + case HTTP_METHOD_UNLOCK: break; case HTTP_METHOD_OPTIONS: /* * 400 is coming from the request-parser BEFORE uri.path is set - * 403 is from the response handler when noone else catched it - * + * 403 is from the response handler when noone else catched it + * * */ if (con->uri.path->used && con->uri.path->ptr[0] != '*') { @@ -416,55 +418,56 @@ static int connection_handle_write_prepare(server *srv, connection *con) { break; } } - + if (con->http_status == 0) { con->http_status = 403; } - + switch(con->http_status) { case 400: /* class: header + custom body */ case 401: case 403: case 404: case 408: + case 409: case 411: case 416: case 423: case 500: case 501: case 503: - case 505: + case 505: if (con->mode != DIRECT) break; - + con->file_finished = 0; - + buffer_reset(con->physical.path); - + /* try to send static errorfile */ if (!buffer_is_empty(con->conf.errorfile_prefix)) { stat_cache_entry *sce = NULL; - + buffer_copy_string_buffer(con->physical.path, con->conf.errorfile_prefix); buffer_append_string(con->physical.path, get_http_status_body_name(con->http_status)); - + if (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) { con->file_finished = 1; - + http_chunk_append_file(srv, con, con->physical.path, 0, sce->st.st_size); response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type)); } } - - if (!con->file_finished) { + + if (!con->file_finished) { buffer *b; - + buffer_reset(con->physical.path); - + con->file_finished = 1; b = chunkqueue_get_append_buffer(con->write_queue); - + /* build default error-page */ - buffer_copy_string(b, + buffer_copy_string(b, "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n" "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n" " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n" @@ -474,7 +477,7 @@ static int connection_handle_write_prepare(server *srv, connection *con) { buffer_append_long(b, con->http_status); buffer_append_string(b, " - "); buffer_append_string(b, get_http_status_name(con->http_status)); - + buffer_append_string(b, "</title>\n" " </head>\n" @@ -483,12 +486,12 @@ static int connection_handle_write_prepare(server *srv, connection *con) { buffer_append_long(b, con->http_status); buffer_append_string(b, " - "); buffer_append_string(b, get_http_status_name(con->http_status)); - - buffer_append_string(b,"</h1>\n" + + buffer_append_string(b,"</h1>\n" " </body>\n" "</html>\n" ); - + response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html")); } /* fall through */ @@ -498,10 +501,10 @@ static int connection_handle_write_prepare(server *srv, connection *con) { case 301: case 302: break; - + case 206: /* write_queue is already prepared */ con->file_finished = 1; - + break; case 205: /* class: header only */ case 304: @@ -509,20 +512,27 @@ static int connection_handle_write_prepare(server *srv, connection *con) { /* disable chunked encoding again as we have no body */ con->response.transfer_encoding &= ~HTTP_TRANSFER_ENCODING_CHUNKED; chunkqueue_reset(con->write_queue); - + con->file_finished = 1; break; } - + if (con->file_finished) { - /* we have all the content and chunked encoding is not used, set a content-length */ - - if ((!(con->parsed_response & HTTP_CONTENT_LENGTH)) && + /* we have all the content and chunked encoding is not used, set a content-length */ + + if ((!(con->parsed_response & HTTP_CONTENT_LENGTH)) && (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) == 0) { - buffer_copy_off_t(srv->tmp_buf, chunkqueue_length(con->write_queue)); - - response_header_overwrite(srv, con, CONST_STR_LEN("Content-Length"), CONST_BUF_LEN(srv->tmp_buf)); + off_t qlen = chunkqueue_length(con->write_queue); + + /* if we have no content for a GET/PORT request, send Content-Length: 0 + * if it is a HEAD request, don't generate a Content-Length as + * the backend might have already cut it off */ + if (qlen > 0 || con->request.http_method != HTTP_METHOD_HEAD) { + buffer_copy_off_t(srv->tmp_buf, chunkqueue_length(con->write_queue)); + + response_header_overwrite(srv, con, CONST_STR_LEN("Content-Length"), CONST_BUF_LEN(srv->tmp_buf)); + } } } else { /* disable keep-alive if size-info for the body is missing */ @@ -530,34 +540,39 @@ static int connection_handle_write_prepare(server *srv, connection *con) { ((con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) == 0)) { con->keep_alive = 0; } - + if (0 == (con->parsed_response & HTTP_CONNECTION)) { /* (f)cgi did'nt send Connection: header - * + * * shall we ? */ if (((con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) == 0) && (con->parsed_response & HTTP_CONTENT_LENGTH) == 0) { /* without content_length, no keep-alive */ - + con->keep_alive = 0; } } else { /* a subrequest disable keep-alive although the client wanted it */ if (con->keep_alive && !con->response.keep_alive) { con->keep_alive = 0; - + /* FIXME: we have to drop the Connection: Header from the subrequest */ } } } - + if (con->request.http_method == HTTP_METHOD_HEAD) { + /** + * a HEAD request has the same as a GET + * without the content + */ chunkqueue_reset(con->write_queue); + con->response.transfer_encoding &= ~HTTP_TRANSFER_ENCODING_CHUNKED; } http_response_write_header(srv, con); - + return 0; } @@ -581,11 +596,11 @@ static int connection_handle_write(server *srv, connection *con) { break; case 1: con->is_writable = 0; - + /* not finished yet -> WRITE */ break; } - + return 0; } @@ -593,11 +608,11 @@ static int connection_handle_write(server *srv, connection *con) { connection *connection_init(server *srv) { connection *con; - + UNUSED(srv); con = calloc(1, sizeof(*con)); - + con->fd = 0; con->ndx = -1; con->fde_ndx = -1; @@ -608,32 +623,32 @@ connection *connection_init(server *srv) { #define CLEAN(x) \ con->x = buffer_init(); - + CLEAN(request.uri); CLEAN(request.request_line); CLEAN(request.request); CLEAN(request.pathinfo); - + CLEAN(request.orig_uri); - + CLEAN(uri.scheme); CLEAN(uri.authority); CLEAN(uri.path); CLEAN(uri.path_raw); CLEAN(uri.query); - + CLEAN(physical.doc_root); CLEAN(physical.path); CLEAN(physical.basedir); CLEAN(physical.rel_path); CLEAN(physical.etag); CLEAN(parse_request); - + CLEAN(authed_user); CLEAN(server_name); CLEAN(error_handler); CLEAN(dst_addr_buf); - + #undef CLEAN con->write_queue = chunkqueue_init(); con->read_queue = chunkqueue_init(); @@ -643,26 +658,26 @@ connection *connection_init(server *srv) { con->request.headers = array_init(); con->response.headers = array_init(); con->environment = array_init(); - + /* init plugin specific connection structures */ - + con->plugin_ctx = calloc(1, (srv->plugins.used + 1) * sizeof(void *)); - + con->cond_cache = calloc(srv->config_context->used, sizeof(cond_cache_t)); config_setup_connection(srv, con); - + return con; } void connections_free(server *srv) { connections *conns = srv->conns; - size_t i; - + size_t i; + for (i = 0; i < conns->size; i++) { connection *con = conns->ptr[i]; - + connection_reset(srv, con); - + chunkqueue_free(con->write_queue); chunkqueue_free(con->read_queue); chunkqueue_free(con->request_content_queue); @@ -672,27 +687,27 @@ void connections_free(server *srv) { #define CLEAN(x) \ buffer_free(con->x); - + CLEAN(request.uri); CLEAN(request.request_line); CLEAN(request.request); CLEAN(request.pathinfo); - + CLEAN(request.orig_uri); - + CLEAN(uri.scheme); CLEAN(uri.authority); CLEAN(uri.path); CLEAN(uri.path_raw); CLEAN(uri.query); - + CLEAN(physical.doc_root); CLEAN(physical.path); CLEAN(physical.basedir); CLEAN(physical.etag); CLEAN(physical.rel_path); CLEAN(parse_request); - + CLEAN(authed_user); CLEAN(server_name); CLEAN(error_handler); @@ -700,97 +715,97 @@ void connections_free(server *srv) { #undef CLEAN free(con->plugin_ctx); free(con->cond_cache); - + free(con); } - + free(conns->ptr); } int connection_reset(server *srv, connection *con) { size_t i; - + plugins_call_connection_reset(srv, con); - + con->is_readable = 1; con->is_writable = 1; con->http_status = 0; con->file_finished = 0; con->file_started = 0; con->got_response = 0; - + con->parsed_response = 0; - + con->bytes_written = 0; con->bytes_written_cur_second = 0; con->bytes_read = 0; con->bytes_header = 0; con->loops_per_request = 0; - + con->request.http_method = HTTP_METHOD_UNSET; con->request.http_version = HTTP_VERSION_UNSET; - + con->request.http_if_modified_since = NULL; con->request.http_if_none_match = NULL; - + con->response.keep_alive = 0; con->response.content_length = -1; con->response.transfer_encoding = 0; - + con->mode = DIRECT; - + #define CLEAN(x) \ if (con->x) buffer_reset(con->x); - + CLEAN(request.uri); CLEAN(request.request_line); CLEAN(request.pathinfo); CLEAN(request.request); - + CLEAN(request.orig_uri); - + CLEAN(uri.scheme); CLEAN(uri.authority); CLEAN(uri.path); CLEAN(uri.path_raw); CLEAN(uri.query); - + CLEAN(physical.doc_root); CLEAN(physical.path); CLEAN(physical.basedir); CLEAN(physical.rel_path); CLEAN(physical.etag); - + CLEAN(parse_request); - + CLEAN(authed_user); CLEAN(server_name); CLEAN(error_handler); -#undef CLEAN - +#undef CLEAN + #define CLEAN(x) \ - if (con->x) con->x->used = 0; - + if (con->x) con->x->used = 0; + #undef CLEAN - + #define CLEAN(x) \ con->request.x = NULL; - + CLEAN(http_host); CLEAN(http_range); CLEAN(http_content_type); #undef CLEAN con->request.content_length = 0; - + array_reset(con->request.headers); array_reset(con->response.headers); array_reset(con->environment); - + chunkqueue_reset(con->write_queue); chunkqueue_reset(con->request_content_queue); - /* the plugins should cleanup themself */ + /* the plugins should cleanup themself */ for (i = 0; i < srv->plugins.used; i++) { plugin *p = ((plugin **)(srv->plugins.ptr))[i]; plugin_data *pd = p->data; @@ -803,7 +818,7 @@ int connection_reset(server *srv, connection *con) { con->plugin_ctx[pd->id] = NULL; } - + #if COND_RESULT_UNSET for (i = srv->config_context->used - 1; i >= 0; i --) { con->cond_cache[i].result = COND_RESULT_UNSET; @@ -819,12 +834,12 @@ int connection_reset(server *srv, connection *con) { con->ssl_error_want_reuse_buffer = NULL; } #endif - + con->header_len = 0; con->in_error_handler = 0; - + config_setup_connection(srv, con); - + return 0; } @@ -834,16 +849,16 @@ int connection_reset(server *srv, connection *con) { * we get called by the state-engine and by the fdevent-handler */ int connection_handle_read_state(server *srv, connection *con) { - int ostate = con->state; + connection_state_t ostate = con->state; chunk *c, *last_chunk; off_t last_offset; chunkqueue *cq = con->read_queue; chunkqueue *dst_cq = con->request_content_queue; int is_closed = 0; /* the connection got closed, if we don't have a complete header, -> error */ - + if (con->is_readable) { con->read_idle_ts = srv->cur_ts; - + switch(connection_handle_read(srv, con)) { case -1: return -1; @@ -884,14 +899,14 @@ int connection_handle_read_state(server *srv, connection *con) { /* the last node was empty */ if (c->next == NULL) { cq->last = c; - } + } c = c->next; } else { c = c->next; } } - + /* we might have got several packets at once */ @@ -911,7 +926,7 @@ int connection_handle_read_state(server *srv, connection *con) { for (c = cq->first; !last_chunk && c; c = c->next) { buffer b; size_t i; - + b.ptr = c->mem->ptr + c->offset; b.used = c->mem->used - c->offset; @@ -926,7 +941,7 @@ int connection_handle_read_state(server *srv, connection *con) { if (have_chars >= 4) { /* all chars are in this buffer */ - + if (0 == strncmp(b.ptr + i, "\r\n\r\n", 4)) { /* found */ last_chunk = c; @@ -949,7 +964,7 @@ int connection_handle_read_state(server *srv, connection *con) { 0 == strncmp(lookahead_chunk->mem->ptr, "\r\n\r\n" + have_chars, missing_chars)) { last_chunk = lookahead_chunk; - last_offset = missing_chars + 1; + last_offset = missing_chars; break; } @@ -971,16 +986,16 @@ int connection_handle_read_state(server *srv, connection *con) { for (c = cq->first; c; c = c->next) { buffer b; - + b.ptr = c->mem->ptr + c->offset; b.used = c->mem->used - c->offset; - + if (c == last_chunk) { b.used = last_offset + 1; } buffer_append_string_buffer(con->request.request, &b); - + if (c == last_chunk) { c->offset += last_offset; @@ -1000,16 +1015,16 @@ int connection_handle_read_state(server *srv, connection *con) { connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST); } break; - case CON_STATE_READ_POST: + case CON_STATE_READ_POST: for (c = cq->first; c && (dst_cq->bytes_in != (off_t)con->request.content_length); c = c->next) { off_t weWant, weHave, toRead; - + weWant = con->request.content_length - dst_cq->bytes_in; - + assert(c->mem->used); - + weHave = c->mem->used - c->offset - 1; - + toRead = weHave > weWant ? weWant : weHave; /* the new way, copy everything into a chunkqueue whcih might use tempfiles */ @@ -1018,13 +1033,13 @@ int connection_handle_read_state(server *srv, connection *con) { /* copy everything to max 1Mb sized tempfiles */ /* - * if the last chunk is + * if the last chunk is * - smaller than 1Mb (size < 1Mb) * - not read yet (offset == 0) * -> append to it * otherwise - * -> create a new chunk - * + * -> create a new chunk + * * */ if (dst_cq->last && @@ -1057,14 +1072,14 @@ int connection_handle_read_state(server *srv, connection *con) { /* we have a chunk, let's write to it */ if (dst_c->file.fd == -1) { - /* we don't have file to write to, + /* we don't have file to write to, * EACCES might be one reason. * * Instead of sending 500 we send 413 and say the request is too large * */ log_error_write(srv, __FILE__, __LINE__, "sbs", - "denying upload as opening to temp-file for upload failed:", + "denying upload as opening to temp-file for upload failed:", dst_c->file.name, strerror(errno)); con->http_status = 413; /* Request-Entity too large */ @@ -1075,15 +1090,15 @@ int connection_handle_read_state(server *srv, connection *con) { } if (toRead != write(dst_c->file.fd, c->mem->ptr + c->offset, toRead)) { - /* write failed for some reason ... disk full ? */ + /* write failed for some reason ... disk full ? */ log_error_write(srv, __FILE__, __LINE__, "sbs", - "denying upload as writing to file failed:", + "denying upload as writing to file failed:", dst_c->file.name, strerror(errno)); - + con->http_status = 413; /* Request-Entity too large */ con->keep_alive = 0; connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST); - + close(dst_c->file.fd); dst_c->file.fd = -1; @@ -1091,7 +1106,7 @@ int connection_handle_read_state(server *srv, connection *con) { } dst_c->file.length += toRead; - + if (dst_cq->bytes_in + toRead == (off_t)con->request.content_length) { /* we read everything, close the chunk */ close(dst_c->file.fd); @@ -1103,7 +1118,7 @@ int connection_handle_read_state(server *srv, connection *con) { b = chunkqueue_get_append_buffer(dst_cq); buffer_copy_string_len(b, c->mem->ptr + c->offset, toRead); } - + c->offset += toRead; dst_cq->bytes_in += toRead; } @@ -1112,8 +1127,9 @@ int connection_handle_read_state(server *srv, connection *con) { if (dst_cq->bytes_in == (off_t)con->request.content_length) { connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST); } - + break; + default: break; } /* the connection got closed and we didn't got enough data to leave one of the READ states @@ -1130,9 +1146,9 @@ int connection_handle_read_state(server *srv, connection *con) { handler_t connection_handle_fdevent(void *s, void *context, int revents) { server *srv = (server *)s; connection *con = context; - + joblist_append(srv, con); - + if (revents & FDEVENT_IN) { con->is_readable = 1; #if 0 @@ -1143,19 +1159,19 @@ handler_t connection_handle_fdevent(void *s, void *context, int revents) { con->is_writable = 1; /* we don't need the event twice */ } - - + + if (revents & ~(FDEVENT_IN | FDEVENT_OUT)) { /* looks like an error */ - + /* FIXME: revents = 0x19 still means that we should read from the queue */ if (revents & FDEVENT_HUP) { if (con->state == CON_STATE_CLOSE) { con->close_timeout_ts = 0; } else { /* sigio reports the wrong event here - * - * there was no HUP at all + * + * there was no HUP at all */ #ifdef USE_LINUX_SIGIO if (srv->ev->in_sigio == 1) { @@ -1167,32 +1183,32 @@ handler_t connection_handle_fdevent(void *s, void *context, int revents) { #else connection_set_state(srv, con, CON_STATE_ERROR); #endif - + } } else if (revents & FDEVENT_ERR) { #ifndef USE_LINUX_SIGIO log_error_write(srv, __FILE__, __LINE__, "sd", "connection closed: poll() -> ERR", con->fd); -#endif +#endif connection_set_state(srv, con, CON_STATE_ERROR); } else { log_error_write(srv, __FILE__, __LINE__, "sd", "connection closed: poll() -> ???", revents); - } + } } - + if (con->state == CON_STATE_READ || con->state == CON_STATE_READ_POST) { connection_handle_read_state(srv, con); } - + if (con->state == CON_STATE_WRITE && !chunkqueue_is_empty(con->write_queue) && con->is_writable) { - + if (-1 == connection_handle_write(srv, con)) { connection_set_state(srv, con, CON_STATE_ERROR); - + log_error_write(srv, __FILE__, __LINE__, "ds", con->fd, "handle write failed."); @@ -1200,30 +1216,30 @@ handler_t connection_handle_fdevent(void *s, void *context, int revents) { con->write_request_ts = srv->cur_ts; } } - + if (con->state == CON_STATE_CLOSE) { /* flush the read buffers */ int b; - + if (ioctl(con->fd, FIONREAD, &b)) { log_error_write(srv, __FILE__, __LINE__, "ss", "ioctl() failed", strerror(errno)); } - + if (b > 0) { char buf[1024]; log_error_write(srv, __FILE__, __LINE__, "sdd", "CLOSE-read()", con->fd, b); - + /* */ read(con->fd, buf, sizeof(buf)); } else { /* nothing to read */ - + con->close_timeout_ts = 0; } } - + return HANDLER_FINISHED; } @@ -1236,7 +1252,7 @@ connection *connection_accept(server *srv, server_socket *srv_socket) { sock_addr cnt_addr; socklen_t cnt_len; /* accept it and register the fd */ - + cnt_len = sizeof(cnt_addr); if (-1 == (cnt = accept(srv_socket->fd, (struct sockaddr *) &cnt_addr, &cnt_len))) { @@ -1256,32 +1272,32 @@ connection *connection_accept(server *srv, server_socket *srv_socket) { return NULL; } else { connection *con; - + srv->cur_fds++; - + /* ok, we have the connection, register it */ #if 0 log_error_write(srv, __FILE__, __LINE__, "sd", "appected()", cnt); #endif srv->con_opened++; - + con = connections_get_new_connection(srv); - + con->fd = cnt; con->fde_ndx = -1; -#if 0 +#if 0 gettimeofday(&(con->start_tv), NULL); -#endif +#endif fdevent_register(srv->ev, con->fd, connection_handle_fdevent, con); - + connection_set_state(srv, con, CON_STATE_REQUEST_START); - + con->connection_start = srv->cur_ts; con->dst_addr = cnt_addr; buffer_copy_string(con->dst_addr_buf, inet_ntop_cache_get_ip(srv, &(con->dst_addr))); con->srv_socket = srv_socket; - + if (-1 == (fdevent_fcntl_set(srv->ev, con->fd))) { log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno)); return NULL; @@ -1290,17 +1306,17 @@ connection *connection_accept(server *srv, server_socket *srv_socket) { /* connect FD to SSL */ if (srv_socket->is_ssl) { if (NULL == (con->ssl = SSL_new(srv_socket->ssl_ctx))) { - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", ERR_error_string(ERR_get_error(), NULL)); - + return NULL; } - + SSL_set_accept_state(con->ssl); con->conf.is_ssl=1; - + if (1 != (SSL_set_fd(con->ssl, cnt))) { - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", ERR_error_string(ERR_get_error(), NULL)); return NULL; } @@ -1316,10 +1332,10 @@ int connection_state_machine(server *srv, connection *con) { #ifdef USE_OPENSSL server_socket *srv_sock = con->srv_socket; #endif - + if (srv->srvconf.log_state_handling) { - log_error_write(srv, __FILE__, __LINE__, "sds", - "state at start", + log_error_write(srv, __FILE__, __LINE__, "sds", + "state at start", con->fd, connection_get_state(con->state)); } @@ -1327,20 +1343,20 @@ int connection_state_machine(server *srv, connection *con) { while (done == 0) { size_t ostate = con->state; int b; - + switch (con->state) { case CON_STATE_REQUEST_START: /* transient */ if (srv->srvconf.log_state_handling) { - log_error_write(srv, __FILE__, __LINE__, "sds", + log_error_write(srv, __FILE__, __LINE__, "sds", "state for fd", con->fd, connection_get_state(con->state)); } - + con->request_start = srv->cur_ts; con->read_idle_ts = srv->cur_ts; - + con->request_count++; con->loops_per_request = 0; - + connection_set_state(srv, con, CON_STATE_READ); /* patch con->conf.is_ssl if the connection is a ssl-socket already */ @@ -1348,103 +1364,96 @@ int connection_state_machine(server *srv, connection *con) { #ifdef USE_OPENSSL con->conf.is_ssl = srv_sock->is_ssl; #endif - + break; case CON_STATE_REQUEST_END: /* transient */ if (srv->srvconf.log_state_handling) { - log_error_write(srv, __FILE__, __LINE__, "sds", + log_error_write(srv, __FILE__, __LINE__, "sds", "state for fd", con->fd, connection_get_state(con->state)); } - + if (http_request_parse(srv, con)) { /* we have to read some data from the POST request */ - + connection_set_state(srv, con, CON_STATE_READ_POST); break; } - + connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST); - + break; case CON_STATE_HANDLE_REQUEST: - /* + /* * the request is parsed - * + * * decided what to do with the request - * - - * - * + * - + * + * */ - + if (srv->srvconf.log_state_handling) { - log_error_write(srv, __FILE__, __LINE__, "sds", + log_error_write(srv, __FILE__, __LINE__, "sds", "state for fd", con->fd, connection_get_state(con->state)); } - + switch (r = http_response_prepare(srv, con)) { case HANDLER_FINISHED: if (con->http_status == 404 || con->http_status == 403) { /* 404 error-handler */ - - if (con->in_error_handler == 0 && + + if (con->in_error_handler == 0 && (!buffer_is_empty(con->conf.error_handler) || !buffer_is_empty(con->error_handler))) { /* call error-handler */ - + con->error_handler_saved_status = con->http_status; con->http_status = 0; - + if (buffer_is_empty(con->error_handler)) { buffer_copy_string_buffer(con->request.uri, con->conf.error_handler); } else { buffer_copy_string_buffer(con->request.uri, con->error_handler); } buffer_reset(con->physical.path); - + con->in_error_handler = 1; - + connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST); - + done = -1; break; } else if (con->in_error_handler) { /* error-handler is a 404 */ - - /* continue as normal, status is the same */ - log_error_write(srv, __FILE__, __LINE__, "sb", - "Warning: Either the error-handler returned status 404 or the error-handler itself was not found:", con->request.uri); - log_error_write(srv, __FILE__, __LINE__, "sd", - "returning the original status", con->error_handler_saved_status); - log_error_write(srv, __FILE__, __LINE__, "s", - "If this is a rails app: check your production.log"); + con->http_status = con->error_handler_saved_status; } } else if (con->in_error_handler) { /* error-handler is back and has generated content */ /* if Status: was set, take it otherwise use 200 */ } - + if (con->http_status == 0) con->http_status = 200; - + /* we have something to send, go on */ connection_set_state(srv, con, CON_STATE_RESPONSE_START); break; case HANDLER_WAIT_FOR_FD: srv->want_fds++; - + fdwaitqueue_append(srv, con); - + connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST); - + break; case HANDLER_COMEBACK: done = -1; case HANDLER_WAIT_FOR_EVENT: /* come back here */ connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST); - + break; case HANDLER_ERROR: /* something went wrong */ @@ -1454,44 +1463,44 @@ int connection_state_machine(server *srv, connection *con) { log_error_write(srv, __FILE__, __LINE__, "sdd", "unknown ret-value: ", con->fd, r); break; } - + break; case CON_STATE_RESPONSE_START: - /* + /* * the decision is done * - create the HTTP-Response-Header - * + * */ - + if (srv->srvconf.log_state_handling) { - log_error_write(srv, __FILE__, __LINE__, "sds", + log_error_write(srv, __FILE__, __LINE__, "sds", "state for fd", con->fd, connection_get_state(con->state)); } - + if (-1 == connection_handle_write_prepare(srv, con)) { connection_set_state(srv, con, CON_STATE_ERROR); - + break; } - + connection_set_state(srv, con, CON_STATE_WRITE); break; case CON_STATE_RESPONSE_END: /* transient */ /* log the request */ - + if (srv->srvconf.log_state_handling) { - log_error_write(srv, __FILE__, __LINE__, "sds", + log_error_write(srv, __FILE__, __LINE__, "sds", "state for fd", con->fd, connection_get_state(con->state)); } - + plugins_call_handle_request_done(srv, con); - + srv->con_written++; - + if (con->keep_alive) { connection_set_state(srv, con, CON_STATE_REQUEST_START); - -#if 0 + +#if 0 con->request_start = srv->cur_ts; con->read_idle_ts = srv->cur_ts; #endif @@ -1504,7 +1513,7 @@ int connection_state_machine(server *srv, connection *con) { log_error_write(srv, __FILE__, __LINE__, "sd", "unhandling return value", r); break; } - + #ifdef USE_OPENSSL if (srv_sock->is_ssl) { switch (SSL_shutdown(con->ssl)) { @@ -1512,44 +1521,44 @@ int connection_state_machine(server *srv, connection *con) { /* done */ break; case 0: - /* wait for fd-event - * + /* wait for fd-event + * * FIXME: wait for fdevent and call SSL_shutdown again - * + * */ - + break; default: - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", ERR_error_string(ERR_get_error(), NULL)); } } #endif connection_close(srv, con); - + srv->con_closed++; } - + connection_reset(srv, con); - + break; case CON_STATE_CONNECT: if (srv->srvconf.log_state_handling) { - log_error_write(srv, __FILE__, __LINE__, "sds", + log_error_write(srv, __FILE__, __LINE__, "sds", "state for fd", con->fd, connection_get_state(con->state)); } - + chunkqueue_reset(con->read_queue); - + con->request_count = 0; - + break; case CON_STATE_CLOSE: if (srv->srvconf.log_state_handling) { - log_error_write(srv, __FILE__, __LINE__, "sds", + log_error_write(srv, __FILE__, __LINE__, "sds", "state for fd", con->fd, connection_get_state(con->state)); } - + if (con->keep_alive) { if (ioctl(con->fd, FIONREAD, &b)) { log_error_write(srv, __FILE__, __LINE__, "ss", @@ -1559,43 +1568,43 @@ int connection_state_machine(server *srv, connection *con) { char buf[1024]; log_error_write(srv, __FILE__, __LINE__, "sdd", "CLOSE-read()", con->fd, b); - + /* */ read(con->fd, buf, sizeof(buf)); } else { /* nothing to read */ - + con->close_timeout_ts = 0; } } else { con->close_timeout_ts = 0; } - + if (srv->cur_ts - con->close_timeout_ts > 1) { connection_close(srv, con); - + if (srv->srvconf.log_state_handling) { - log_error_write(srv, __FILE__, __LINE__, "sd", + log_error_write(srv, __FILE__, __LINE__, "sd", "connection closed for fd", con->fd); } } - + break; case CON_STATE_READ_POST: case CON_STATE_READ: if (srv->srvconf.log_state_handling) { - log_error_write(srv, __FILE__, __LINE__, "sds", + log_error_write(srv, __FILE__, __LINE__, "sds", "state for fd", con->fd, connection_get_state(con->state)); } - + connection_handle_read_state(srv, con); break; case CON_STATE_WRITE: if (srv->srvconf.log_state_handling) { - log_error_write(srv, __FILE__, __LINE__, "sds", + log_error_write(srv, __FILE__, __LINE__, "sds", "state for fd", con->fd, connection_get_state(con->state)); } - + /* only try to write if we have something in the queue */ if (!chunkqueue_is_empty(con->write_queue)) { #if 0 @@ -1615,10 +1624,10 @@ int connection_state_machine(server *srv, connection *con) { con->write_request_ts = srv->cur_ts; } } - + break; case CON_STATE_ERROR: /* transient */ - + /* even if the connection was drop we still have to write it to the access log */ if (con->http_status) { plugins_call_handle_request_done(srv, con); @@ -1634,19 +1643,19 @@ int connection_state_machine(server *srv, connection *con) { SSL_shutdown(con->ssl); break; default: - log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:", - SSL_get_error(con->ssl, ret), + log_error_write(srv, __FILE__, __LINE__, "sds", "SSL:", + SSL_get_error(con->ssl, ret), ERR_error_string(ERR_get_error(), NULL)); return -1; } } #endif - + switch(con->mode) { case DIRECT: #if 0 - log_error_write(srv, __FILE__, __LINE__, "sd", - "emergency exit: direct", + log_error_write(srv, __FILE__, __LINE__, "sd", + "emergency exit: direct", con->fd); #endif break; @@ -1661,35 +1670,35 @@ int connection_state_machine(server *srv, connection *con) { } break; } - + connection_reset(srv, con); - + /* close the connection */ if ((con->keep_alive == 1) && (0 == shutdown(con->fd, SHUT_WR))) { con->close_timeout_ts = srv->cur_ts; connection_set_state(srv, con, CON_STATE_CLOSE); - + if (srv->srvconf.log_state_handling) { - log_error_write(srv, __FILE__, __LINE__, "sd", + log_error_write(srv, __FILE__, __LINE__, "sd", "shutdown for fd", con->fd); } } else { connection_close(srv, con); } - + con->keep_alive = 0; - + srv->con_closed++; - + break; default: - log_error_write(srv, __FILE__, __LINE__, "sdd", + log_error_write(srv, __FILE__, __LINE__, "sdd", "unknown state:", con->fd, con->state); - + break; } - + if (done == -1) { done = 0; } else if (ostate == con->state) { @@ -1698,12 +1707,12 @@ int connection_state_machine(server *srv, connection *con) { } if (srv->srvconf.log_state_handling) { - log_error_write(srv, __FILE__, __LINE__, "sds", - "state at exit:", + log_error_write(srv, __FILE__, __LINE__, "sds", + "state at exit:", con->fd, connection_get_state(con->state)); } - + switch(con->state) { case CON_STATE_READ_POST: case CON_STATE_READ: @@ -1711,11 +1720,11 @@ int connection_state_machine(server *srv, connection *con) { fdevent_event_add(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_IN); break; case CON_STATE_WRITE: - /* request write-fdevent only if we really need it + /* request write-fdevent only if we really need it * - if we have data to write - * - if the socket is not writable yet + * - if the socket is not writable yet */ - if (!chunkqueue_is_empty(con->write_queue) && + if (!chunkqueue_is_empty(con->write_queue) && (con->is_writable == 0) && (con->traffic_limit_reached == 0)) { fdevent_event_add(srv->ev, &(con->fde_ndx), con->fd, FDEVENT_OUT); diff --git a/src/data_array.c b/src/data_array.c index 9dfa6fd..c07effb 100644 --- a/src/data_array.c +++ b/src/data_array.c @@ -17,16 +17,16 @@ static data_unset *data_array_copy(const data_unset *s) { static void data_array_free(data_unset *d) { data_array *ds = (data_array *)d; - + buffer_free(ds->key); array_free(ds->value); - + free(d); } static void data_array_reset(data_unset *d) { data_array *ds = (data_array *)d; - + /* reused array elements */ buffer_reset(ds->key); array_reset(ds->value); @@ -36,7 +36,7 @@ static int data_array_insert_dup(data_unset *dst, data_unset *src) { UNUSED(dst); src->free(src); - + return 0; } @@ -48,18 +48,18 @@ static void data_array_print(const data_unset *d, int depth) { data_array *data_array_init(void) { data_array *ds; - + ds = calloc(1, sizeof(*ds)); - + ds->key = buffer_init(); ds->value = array_init(); - + ds->copy = data_array_copy; ds->free = data_array_free; ds->reset = data_array_reset; ds->insert_dup = data_array_insert_dup; ds->print = data_array_print; ds->type = TYPE_ARRAY; - + return ds; } diff --git a/src/data_config.c b/src/data_config.c index 03595a3..a3b8cff 100644 --- a/src/data_config.c +++ b/src/data_config.c @@ -17,26 +17,26 @@ static data_unset *data_config_copy(const data_unset *s) { 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 void data_config_reset(data_unset *d) { static int data_config_insert_dup(data_unset *dst, data_unset *src) { UNUSED(dst); - + src->free(src); - + return 0; } @@ -56,7 +56,7 @@ static void data_config_print(const data_unset *d, int depth) { array *a = (array *)ds->value; size_t i; size_t maxlen; - + if (0 == ds->context_ndx) { fprintf(stdout, "config {\n"); } @@ -117,22 +117,22 @@ static void data_config_print(const data_unset *d, int depth) { 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; } diff --git a/src/data_count.c b/src/data_count.c index fbc35e0..5c5a5f0 100644 --- a/src/data_count.c +++ b/src/data_count.c @@ -16,53 +16,53 @@ static data_unset *data_count_copy(const data_unset *s) { static void data_count_free(data_unset *d) { data_count *ds = (data_count *)d; - + buffer_free(ds->key); - + free(d); } static void data_count_reset(data_unset *d) { data_count *ds = (data_count *)d; - + buffer_reset(ds->key); - + ds->count = 0; } static int data_count_insert_dup(data_unset *dst, data_unset *src) { data_count *ds_dst = (data_count *)dst; data_count *ds_src = (data_count *)src; - + ds_dst->count += ds_src->count; - + src->free(src); - + return 0; } static void data_count_print(const data_unset *d, int depth) { data_count *ds = (data_count *)d; UNUSED(depth); - + fprintf(stdout, "count(%d)", ds->count); } data_count *data_count_init(void) { data_count *ds; - + ds = calloc(1, sizeof(*ds)); - + ds->key = buffer_init(); ds->count = 1; - + ds->copy = data_count_copy; ds->free = data_count_free; ds->reset = data_count_reset; ds->insert_dup = data_count_insert_dup; ds->print = data_count_print; ds->type = TYPE_COUNT; - + return ds; } diff --git a/src/data_fastcgi.c b/src/data_fastcgi.c index ad981bf..83e9266 100644 --- a/src/data_fastcgi.c +++ b/src/data_fastcgi.c @@ -17,53 +17,53 @@ static data_unset *data_fastcgi_copy(const data_unset *s) { static void data_fastcgi_free(data_unset *d) { data_fastcgi *ds = (data_fastcgi *)d; - + buffer_free(ds->key); buffer_free(ds->host); - + free(d); } static void data_fastcgi_reset(data_unset *d) { data_fastcgi *ds = (data_fastcgi *)d; - + buffer_reset(ds->key); buffer_reset(ds->host); - + } static int data_fastcgi_insert_dup(data_unset *dst, data_unset *src) { UNUSED(dst); src->free(src); - + return 0; } static void data_fastcgi_print(const data_unset *d, int depth) { data_fastcgi *ds = (data_fastcgi *)d; UNUSED(depth); - + fprintf(stdout, "fastcgi(%s)", ds->host->ptr); } data_fastcgi *data_fastcgi_init(void) { data_fastcgi *ds; - + ds = calloc(1, sizeof(*ds)); - + ds->key = buffer_init(); ds->host = buffer_init(); ds->port = 0; ds->is_disabled = 0; - + ds->copy = data_fastcgi_copy; ds->free = data_fastcgi_free; ds->reset = data_fastcgi_reset; ds->insert_dup = data_fastcgi_insert_dup; ds->print = data_fastcgi_print; ds->type = TYPE_FASTCGI; - + return ds; } diff --git a/src/data_integer.c b/src/data_integer.c index c557b90..5423407 100644 --- a/src/data_integer.c +++ b/src/data_integer.c @@ -16,15 +16,15 @@ static data_unset *data_integer_copy(const data_unset *s) { static void data_integer_free(data_unset *d) { data_integer *ds = (data_integer *)d; - + buffer_free(ds->key); - + free(d); } static void data_integer_reset(data_unset *d) { data_integer *ds = (data_integer *)d; - + /* reused integer elements */ buffer_reset(ds->key); ds->value = 0; @@ -32,9 +32,9 @@ static void data_integer_reset(data_unset *d) { static int data_integer_insert_dup(data_unset *dst, data_unset *src) { UNUSED(dst); - + src->free(src); - + return 0; } @@ -48,18 +48,18 @@ static void data_integer_print(const data_unset *d, int depth) { data_integer *data_integer_init(void) { data_integer *ds; - + ds = calloc(1, sizeof(*ds)); - + ds->key = buffer_init(); ds->value = 0; - + ds->copy = data_integer_copy; ds->free = data_integer_free; ds->reset = data_integer_reset; ds->insert_dup = data_integer_insert_dup; ds->print = data_integer_print; ds->type = TYPE_INTEGER; - + return ds; } diff --git a/src/data_string.c b/src/data_string.c index 391af9e..e7aab1a 100644 --- a/src/data_string.c +++ b/src/data_string.c @@ -17,16 +17,16 @@ static data_unset *data_string_copy(const data_unset *s) { static void data_string_free(data_unset *d) { data_string *ds = (data_string *)d; - + buffer_free(ds->key); buffer_free(ds->value); - + free(d); } static void data_string_reset(data_unset *d) { data_string *ds = (data_string *)d; - + /* reused array elements */ buffer_reset(ds->key); buffer_reset(ds->value); @@ -35,23 +35,23 @@ static void data_string_reset(data_unset *d) { static int data_string_insert_dup(data_unset *dst, data_unset *src) { data_string *ds_dst = (data_string *)dst; data_string *ds_src = (data_string *)src; - + if (ds_dst->value->used) { buffer_append_string(ds_dst->value, ", "); buffer_append_string_buffer(ds_dst->value, ds_src->value); } else { buffer_copy_string_buffer(ds_dst->value, ds_src->value); } - + src->free(src); - + return 0; } static int data_response_insert_dup(data_unset *dst, data_unset *src) { data_string *ds_dst = (data_string *)dst; data_string *ds_src = (data_string *)src; - + if (ds_dst->value->used) { buffer_append_string(ds_dst->value, "\r\n"); buffer_append_string_buffer(ds_dst->value, ds_dst->key); @@ -60,9 +60,9 @@ static int data_response_insert_dup(data_unset *dst, data_unset *src) { } else { buffer_copy_string_buffer(ds_dst->value, ds_src->value); } - + src->free(src); - + return 0; } @@ -77,28 +77,28 @@ static void data_string_print(const data_unset *d, int depth) { data_string *data_string_init(void) { data_string *ds; - + ds = calloc(1, sizeof(*ds)); assert(ds); - + ds->key = buffer_init(); ds->value = buffer_init(); - + ds->copy = data_string_copy; ds->free = data_string_free; ds->reset = data_string_reset; ds->insert_dup = data_string_insert_dup; ds->print = data_string_print; ds->type = TYPE_STRING; - + return ds; } data_string *data_response_init(void) { data_string *ds; - + ds = data_string_init(); ds->insert_dup = data_response_insert_dup; - + return ds; } @@ -14,19 +14,19 @@ int etag_create(buffer *etag, struct stat *st) { buffer_append_off_t(etag, st->st_size); buffer_append_string_len(etag, CONST_STR_LEN("-")); buffer_append_long(etag, st->st_mtime); - + return 0; } int etag_mutate(buffer *mut, buffer *etag) { size_t h, i; - + for (h=0, i=0; i < etag->used; ++i) h = (h<<5)^(h>>27)^(etag->ptr[i]); - + buffer_reset(mut); buffer_copy_string_len(mut, CONST_STR_LEN("\"")); buffer_append_long(mut, h); buffer_append_string_len(mut, CONST_STR_LEN("\"")); - + return 0; } @@ -10,6 +10,6 @@ int etag_is_equal(buffer *etag, const char *matches); int etag_create(buffer *etag, struct stat *st); int etag_mutate(buffer *mut, buffer *etag); - + #endif diff --git a/src/fastcgi.h b/src/fastcgi.h index 15f1dea..31c00ad 100644 --- a/src/fastcgi.h +++ b/src/fastcgi.h @@ -1,4 +1,4 @@ -/* +/* * fastcgi.h -- * * Defines for the FastCGI protocol. @@ -123,7 +123,7 @@ typedef struct { typedef struct { - unsigned char type; + unsigned char type; unsigned char reserved[7]; } FCGI_UnknownTypeBody; diff --git a/src/fdevent.c b/src/fdevent.c index fdf834f..e59e110 100644 --- a/src/fdevent.c +++ b/src/fdevent.c @@ -14,57 +14,57 @@ fdevents *fdevent_init(size_t maxfds, fdevent_handler_t type) { fdevents *ev; - + ev = calloc(1, sizeof(*ev)); ev->fdarray = calloc(maxfds, sizeof(*ev->fdarray)); ev->maxfds = maxfds; - + switch(type) { case FDEVENT_HANDLER_POLL: if (0 != fdevent_poll_init(ev)) { - fprintf(stderr, "%s.%d: event-handler poll failed\n", + fprintf(stderr, "%s.%d: event-handler poll failed\n", __FILE__, __LINE__); - + return NULL; } break; case FDEVENT_HANDLER_SELECT: if (0 != fdevent_select_init(ev)) { - fprintf(stderr, "%s.%d: event-handler select failed\n", + fprintf(stderr, "%s.%d: event-handler select failed\n", __FILE__, __LINE__); return NULL; } break; case FDEVENT_HANDLER_LINUX_RTSIG: if (0 != fdevent_linux_rtsig_init(ev)) { - fprintf(stderr, "%s.%d: event-handler linux-rtsig failed, try to set server.event-handler = \"poll\" or \"select\"\n", + fprintf(stderr, "%s.%d: event-handler linux-rtsig failed, try to set server.event-handler = \"poll\" or \"select\"\n", __FILE__, __LINE__); return NULL; } break; case FDEVENT_HANDLER_LINUX_SYSEPOLL: if (0 != fdevent_linux_sysepoll_init(ev)) { - fprintf(stderr, "%s.%d: event-handler linux-sysepoll failed, try to set server.event-handler = \"poll\" or \"select\"\n", + fprintf(stderr, "%s.%d: event-handler linux-sysepoll failed, try to set server.event-handler = \"poll\" or \"select\"\n", __FILE__, __LINE__); return NULL; } break; case FDEVENT_HANDLER_SOLARIS_DEVPOLL: if (0 != fdevent_solaris_devpoll_init(ev)) { - fprintf(stderr, "%s.%d: event-handler solaris-devpoll failed, try to set server.event-handler = \"poll\" or \"select\"\n", + fprintf(stderr, "%s.%d: event-handler solaris-devpoll failed, try to set server.event-handler = \"poll\" or \"select\"\n", __FILE__, __LINE__); return NULL; } break; case FDEVENT_HANDLER_FREEBSD_KQUEUE: if (0 != fdevent_freebsd_kqueue_init(ev)) { - fprintf(stderr, "%s.%d: event-handler freebsd-kqueue failed, try to set server.event-handler = \"poll\" or \"select\"\n", + fprintf(stderr, "%s.%d: event-handler freebsd-kqueue failed, try to set server.event-handler = \"poll\" or \"select\"\n", __FILE__, __LINE__); return NULL; } break; default: - fprintf(stderr, "%s.%d: event-handler is unknown, try to set server.event-handler = \"poll\" or \"select\"\n", + fprintf(stderr, "%s.%d: event-handler is unknown, try to set server.event-handler = \"poll\" or \"select\"\n", __FILE__, __LINE__); return NULL; } @@ -75,26 +75,26 @@ fdevents *fdevent_init(size_t maxfds, fdevent_handler_t type) { void fdevent_free(fdevents *ev) { size_t i; if (!ev) return; - + if (ev->free) ev->free(ev); - + for (i = 0; i < ev->maxfds; i++) { if (ev->fdarray[i]) free(ev->fdarray[i]); } - + free(ev->fdarray); free(ev); } int fdevent_reset(fdevents *ev) { if (ev->reset) return ev->reset(ev); - + return 0; } fdnode *fdnode_init() { fdnode *fdn; - + fdn = calloc(1, sizeof(*fdn)); fdn->fd = -1; return fdn; @@ -106,12 +106,12 @@ void fdnode_free(fdnode *fdn) { int fdevent_register(fdevents *ev, int fd, fdevent_handler handler, void *ctx) { fdnode *fdn; - + fdn = fdnode_init(); fdn->handler = handler; fdn->fd = fd; fdn->ctx = ctx; - + ev->fdarray[fd] = fdn; return 0; @@ -121,31 +121,31 @@ int fdevent_unregister(fdevents *ev, int fd) { fdnode *fdn; if (!ev) return 0; fdn = ev->fdarray[fd]; - + fdnode_free(fdn); - + ev->fdarray[fd] = NULL; - + return 0; } int fdevent_event_del(fdevents *ev, int *fde_ndx, int fd) { int fde = fde_ndx ? *fde_ndx : -1; - + if (ev->event_del) fde = ev->event_del(ev, fde, fd); - + if (fde_ndx) *fde_ndx = fde; - + return 0; } int fdevent_event_add(fdevents *ev, int *fde_ndx, int fd, int events) { int fde = fde_ndx ? *fde_ndx : -1; - + if (ev->event_add) fde = ev->event_add(ev, fde, fd, events); - + if (fde_ndx) *fde_ndx = fde; - + return 0; } @@ -156,27 +156,27 @@ int fdevent_poll(fdevents *ev, int timeout_ms) { int fdevent_event_get_revent(fdevents *ev, size_t ndx) { if (ev->event_get_revent == NULL) SEGFAULT(); - + return ev->event_get_revent(ev, ndx); } int fdevent_event_get_fd(fdevents *ev, size_t ndx) { if (ev->event_get_fd == NULL) SEGFAULT(); - + return ev->event_get_fd(ev, ndx); } fdevent_handler fdevent_get_handler(fdevents *ev, int fd) { if (ev->fdarray[fd] == NULL) SEGFAULT(); if (ev->fdarray[fd]->fd != fd) SEGFAULT(); - + return ev->fdarray[fd]->handler; } void * fdevent_get_context(fdevents *ev, int fd) { if (ev->fdarray[fd] == NULL) SEGFAULT(); if (ev->fdarray[fd]->fd != fd) SEGFAULT(); - + return ev->fdarray[fd]->ctx; } @@ -186,7 +186,7 @@ int fdevent_fcntl_set(fdevents *ev, int fd) { fcntl(fd, F_SETFD, FD_CLOEXEC); #endif if ((ev) && (ev->fcntl_set)) return ev->fcntl_set(ev, fd); -#ifdef O_NONBLOCK +#ifdef O_NONBLOCK return fcntl(fd, F_SETFL, O_NONBLOCK | O_RDWR); #else return 0; @@ -196,7 +196,7 @@ int fdevent_fcntl_set(fdevents *ev, int fd) { int fdevent_event_next_fdndx(fdevents *ev, int ndx) { if (ev->event_next_fdndx) return ev->event_next_fdndx(ev, ndx); - + return -1; } diff --git a/src/fdevent.h b/src/fdevent.h index 0bc05ca..5629e9c 100644 --- a/src/fdevent.h +++ b/src/fdevent.h @@ -17,13 +17,13 @@ # include <sys/epoll.h> #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 <poll.h> -# else +# else # include <sys/poll.h> # endif # if defined HAVE_SIGTIMEDWAIT && defined(__linux__) @@ -67,14 +67,14 @@ typedef handler_t (*fdevent_handler)(void *srv, void *ctx, int revents); #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 +86,7 @@ typedef enum { FDEVENT_HANDLER_UNSET, /** * a mapping from fd to connection structure - * + * */ typedef struct { int fd; /**< the fd */ @@ -98,41 +98,41 @@ typedef struct { 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 +146,21 @@ typedef struct fdevents { #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 +177,16 @@ typedef struct fdevents { #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; diff --git a/src/fdevent_freebsd_kqueue.c b/src/fdevent_freebsd_kqueue.c index b955726..e21d6fd 100644 --- a/src/fdevent_freebsd_kqueue.c +++ b/src/fdevent_freebsd_kqueue.c @@ -48,7 +48,7 @@ static int fdevent_freebsd_kqueue_event_del(fdevents *ev, int fde_ndx, int fd) { return -1; } - + return -1; } @@ -65,7 +65,7 @@ static int fdevent_freebsd_kqueue_event_add(fdevents *ev, int fde_ndx, int fd, i ts.tv_sec = 0; ts.tv_nsec = 0; - + ret = kevent(ev->kq_fd, &kev, 1, NULL, 0, @@ -77,7 +77,7 @@ static int fdevent_freebsd_kqueue_event_add(fdevents *ev, int fde_ndx, int fd, i return -1; } - + if (filter == EVFILT_READ) { bitset_set_bit(ev->kq_bevents, fd); } else { @@ -124,7 +124,7 @@ static int fdevent_freebsd_kqueue_event_get_revent(fdevents *ev, size_t ndx) { } else if (e == EVFILT_WRITE) { events |= FDEVENT_OUT; } - + e = ev->kq_results[ndx].flags; if (e & EV_EOF) { @@ -152,10 +152,10 @@ static int fdevent_freebsd_kqueue_reset(fdevents *ev) { if (-1 == (ev->kq_fd = kqueue())) { fprintf(stderr, "%s.%d: kqueue failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n", __FILE__, __LINE__, strerror(errno)); - + return -1; } - + return 0; } @@ -186,7 +186,7 @@ int fdevent_freebsd_kqueue_init(fdevents *ev) { if (-1 == (ev->kq_fd = kqueue())) { fprintf(stderr, "%s.%d: kqueue failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n", __FILE__, __LINE__, strerror(errno)); - + return -1; } diff --git a/src/fdevent_linux_rtsig.c b/src/fdevent_linux_rtsig.c index dcefff8..924e4c7 100644 --- a/src/fdevent_linux_rtsig.c +++ b/src/fdevent_linux_rtsig.c @@ -26,19 +26,19 @@ static void fdevent_linux_rtsig_free(fdevents *ev) { static int fdevent_linux_rtsig_event_del(fdevents *ev, int fde_ndx, int fd) { if (fde_ndx < 0) return -1; - + if ((size_t)fde_ndx >= ev->used) { fprintf(stderr, "%s.%d: del! out of range %d %zu\n", __FILE__, __LINE__, fde_ndx, ev->used); SEGFAULT(); } - + if (ev->pollfds[fde_ndx].fd == fd) { size_t k = fde_ndx; - + ev->pollfds[k].fd = -1; bitset_clear_bit(ev->sigbset, fd); - + if (ev->unused.size == 0) { ev->unused.size = 16; ev->unused.ptr = malloc(sizeof(*(ev->unused.ptr)) * ev->unused.size); @@ -46,29 +46,29 @@ static int fdevent_linux_rtsig_event_del(fdevents *ev, int fde_ndx, int fd) { ev->unused.size += 16; ev->unused.ptr = realloc(ev->unused.ptr, sizeof(*(ev->unused.ptr)) * ev->unused.size); } - + ev->unused.ptr[ev->unused.used++] = k; } else { fprintf(stderr, "%s.%d: del! %d %d\n", __FILE__, __LINE__, ev->pollfds[fde_ndx].fd, fd); - + SEGFAULT(); } - + return -1; } #if 0 static int fdevent_linux_rtsig_event_compress(fdevents *ev) { size_t j; - + if (ev->used == 0) return 0; if (ev->unused.used != 0) return 0; - + for (j = ev->used - 1; j + 1 > 0; j--) { if (ev->pollfds[j].fd == -1) ev->used--; } - - + + return 0; } #endif @@ -78,21 +78,21 @@ static int fdevent_linux_rtsig_event_add(fdevents *ev, int fde_ndx, int fd, int if (fde_ndx != -1) { if (ev->pollfds[fde_ndx].fd == fd) { ev->pollfds[fde_ndx].events = events; - + return fde_ndx; } fprintf(stderr, "%s.%d: add: (%d, %d)\n", __FILE__, __LINE__, fde_ndx, ev->pollfds[fde_ndx].fd); SEGFAULT(); } - + if (ev->unused.used > 0) { int k = ev->unused.ptr[--ev->unused.used]; - + ev->pollfds[k].fd = fd; ev->pollfds[k].events = events; bitset_set_bit(ev->sigbset, fd); - + return k; } else { if (ev->size == 0) { @@ -102,12 +102,12 @@ static int fdevent_linux_rtsig_event_add(fdevents *ev, int fde_ndx, int fd, int ev->size += 16; ev->pollfds = realloc(ev->pollfds, sizeof(*ev->pollfds) * ev->size); } - + ev->pollfds[ev->used].fd = fd; ev->pollfds[ev->used].events = events; bitset_set_bit(ev->sigbset, fd); - + return ev->used++; } } @@ -115,20 +115,20 @@ static int fdevent_linux_rtsig_event_add(fdevents *ev, int fde_ndx, int fd, int static int fdevent_linux_rtsig_poll(fdevents *ev, int timeout_ms) { struct timespec ts; int r; - + #if 0 fdevent_linux_rtsig_event_compress(ev); #endif - + ev->in_sigio = 1; - + ts.tv_sec = timeout_ms / 1000; ts.tv_nsec = (timeout_ms % 1000) * 1000000; r = sigtimedwait(&(ev->sigset), &(ev->siginfo), &(ts)); - - if (r == -1) { + + if (r == -1) { if (errno == EAGAIN) return 0; - return r; + return r; } else if (r == SIGIO) { struct sigaction act; @@ -140,7 +140,7 @@ static int fdevent_linux_rtsig_poll(fdevents *ev, int timeout_ms) { /* re-enable the signal queue */ act.sa_handler = SIG_DFL; sigaction(ev->signum, &act, NULL); - + ev->in_sigio = 0; r = poll(ev->pollfds, ev->used, timeout_ms); @@ -162,12 +162,12 @@ static int fdevent_linux_rtsig_event_get_revent(fdevents *ev, size_t ndx) { if (ev->siginfo.si_band == POLLERR) { fprintf(stderr, "event: %d %02lx %02x %s\n", ev->siginfo.si_fd, ev->siginfo.si_band, errno, strerror(errno)); } -# endif +# endif if (ndx != 0) { fprintf(stderr, "+\n"); return 0; } - + return ev->siginfo.si_band & 0x3f; } else { if (ndx >= ev->used) { @@ -188,13 +188,13 @@ static int fdevent_linux_rtsig_event_get_fd(fdevents *ev, size_t ndx) { static int fdevent_linux_rtsig_fcntl_set(fdevents *ev, int fd) { static pid_t pid = 0; - + if (pid == 0) pid = getpid(); - + if (-1 == fcntl(fd, F_SETSIG, ev->signum)) return -1; - + if (-1 == fcntl(fd, F_SETOWN, (int) pid)) return -1; - + return fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK | O_RDWR); } @@ -205,12 +205,12 @@ static int fdevent_linux_rtsig_event_next_fdndx(fdevents *ev, int ndx) { return -1; } else { size_t i; - + i = (ndx < 0) ? 0 : ndx + 1; for (; i < ev->used; i++) { if (ev->pollfds[i].revents) break; } - + return i; } } @@ -219,34 +219,34 @@ int fdevent_linux_rtsig_init(fdevents *ev) { ev->type = FDEVENT_HANDLER_LINUX_RTSIG; #define SET(x) \ ev->x = fdevent_linux_rtsig_##x; - + SET(free); SET(poll); - + SET(event_del); SET(event_add); - + SET(event_next_fdndx); SET(fcntl_set); SET(event_get_fd); SET(event_get_revent); - + ev->signum = SIGRTMIN + 1; - + sigemptyset(&(ev->sigset)); sigaddset(&(ev->sigset), ev->signum); sigaddset(&(ev->sigset), SIGIO); if (-1 == sigprocmask(SIG_BLOCK, &(ev->sigset), NULL)) { fprintf(stderr, "%s.%d: sigprocmask failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n", __FILE__, __LINE__, strerror(errno)); - + return -1; } - + ev->in_sigio = 1; ev->sigbset = bitset_init(ev->maxfds); - + return 0; } #else diff --git a/src/fdevent_linux_sysepoll.c b/src/fdevent_linux_sysepoll.c index 31caabd..64125f0 100644 --- a/src/fdevent_linux_sysepoll.c +++ b/src/fdevent_linux_sysepoll.c @@ -20,36 +20,36 @@ static void fdevent_linux_sysepoll_free(fdevents *ev) { static int fdevent_linux_sysepoll_event_del(fdevents *ev, int fde_ndx, int fd) { struct epoll_event ep; - + if (fde_ndx < 0) return -1; - + memset(&ep, 0, sizeof(ep)); - + ep.data.fd = fd; ep.data.ptr = NULL; - + if (0 != epoll_ctl(ev->epoll_fd, EPOLL_CTL_DEL, fd, &ep)) { fprintf(stderr, "%s.%d: epoll_ctl failed: %s, dying\n", __FILE__, __LINE__, strerror(errno)); - + SEGFAULT(); - + return 0; } - - + + return -1; } static int fdevent_linux_sysepoll_event_add(fdevents *ev, int fde_ndx, int fd, int events) { struct epoll_event ep; int add = 0; - + if (fde_ndx == -1) add = 1; - + memset(&ep, 0, sizeof(ep)); - + ep.events = 0; - + if (events & FDEVENT_IN) ep.events |= EPOLLIN; if (events & FDEVENT_OUT) ep.events |= EPOLLOUT; @@ -60,20 +60,20 @@ static int fdevent_linux_sysepoll_event_add(fdevents *ev, int fde_ndx, int fd, i * sent. * */ - + ep.events |= EPOLLERR | EPOLLHUP /* | EPOLLET */; - + ep.data.ptr = NULL; ep.data.fd = fd; - + if (0 != epoll_ctl(ev->epoll_fd, add ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, fd, &ep)) { fprintf(stderr, "%s.%d: epoll_ctl failed: %s, dying\n", __FILE__, __LINE__, strerror(errno)); - + SEGFAULT(); - + return 0; } - + return fd; } @@ -83,14 +83,14 @@ static int fdevent_linux_sysepoll_poll(fdevents *ev, int timeout_ms) { static int fdevent_linux_sysepoll_event_get_revent(fdevents *ev, size_t ndx) { int events = 0, e; - + e = ev->epoll_events[ndx].events; if (e & EPOLLIN) events |= FDEVENT_IN; if (e & EPOLLOUT) events |= FDEVENT_OUT; if (e & EPOLLERR) events |= FDEVENT_ERR; if (e & EPOLLHUP) events |= FDEVENT_HUP; if (e & EPOLLPRI) events |= FDEVENT_PRI; - + return e; } @@ -98,17 +98,17 @@ static int fdevent_linux_sysepoll_event_get_fd(fdevents *ev, size_t ndx) { # if 0 fprintf(stderr, "%s.%d: %d, %d\n", __FILE__, __LINE__, ndx, ev->epoll_events[ndx].data.fd); # endif - + return ev->epoll_events[ndx].data.fd; } static int fdevent_linux_sysepoll_event_next_fdndx(fdevents *ev, int ndx) { size_t i; - + UNUSED(ev); i = (ndx < 0) ? 0 : ndx + 1; - + return i; } @@ -116,17 +116,17 @@ int fdevent_linux_sysepoll_init(fdevents *ev) { ev->type = FDEVENT_HANDLER_LINUX_SYSEPOLL; #define SET(x) \ ev->x = fdevent_linux_sysepoll_##x; - + SET(free); SET(poll); - + SET(event_del); SET(event_add); - + SET(event_next_fdndx); SET(event_get_fd); SET(event_get_revent); - + if (-1 == (ev->epoll_fd = epoll_create(ev->maxfds))) { fprintf(stderr, "%s.%d: epoll_create failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n", __FILE__, __LINE__, strerror(errno)); @@ -154,7 +154,7 @@ int fdevent_linux_sysepoll_init(fdevents *ev) { fprintf(stderr, "%s.%d: linux-sysepoll not supported, try to set server.event-handler = \"poll\" or \"select\"\n", __FILE__, __LINE__); - + return -1; } #endif diff --git a/src/fdevent_poll.c b/src/fdevent_poll.c index 7d8017a..11d2c5e 100644 --- a/src/fdevent_poll.c +++ b/src/fdevent_poll.c @@ -20,19 +20,19 @@ static void fdevent_poll_free(fdevents *ev) { static int fdevent_poll_event_del(fdevents *ev, int fde_ndx, int fd) { if (fde_ndx < 0) return -1; - + if ((size_t)fde_ndx >= ev->used) { fprintf(stderr, "%s.%d: del! out of range %d %zd\n", __FILE__, __LINE__, fde_ndx, ev->used); SEGFAULT(); } - + if (ev->pollfds[fde_ndx].fd == fd) { size_t k = fde_ndx; - + ev->pollfds[k].fd = -1; /* ev->pollfds[k].events = 0; */ /* ev->pollfds[k].revents = 0; */ - + if (ev->unused.size == 0) { ev->unused.size = 16; ev->unused.ptr = malloc(sizeof(*(ev->unused.ptr)) * ev->unused.size); @@ -40,47 +40,47 @@ static int fdevent_poll_event_del(fdevents *ev, int fde_ndx, int fd) { ev->unused.size += 16; ev->unused.ptr = realloc(ev->unused.ptr, sizeof(*(ev->unused.ptr)) * ev->unused.size); } - + ev->unused.ptr[ev->unused.used++] = k; } else { SEGFAULT(); } - + return -1; } #if 0 static int fdevent_poll_event_compress(fdevents *ev) { size_t j; - + if (ev->used == 0) return 0; if (ev->unused.used != 0) return 0; - + for (j = ev->used - 1; j + 1 > 0 && ev->pollfds[j].fd == -1; j--) ev->used--; - + return 0; } #endif static int fdevent_poll_event_add(fdevents *ev, int fde_ndx, int fd, int events) { /* known index */ - + if (fde_ndx != -1) { if (ev->pollfds[fde_ndx].fd == fd) { ev->pollfds[fde_ndx].events = events; - + return fde_ndx; } fprintf(stderr, "%s.%d: add: (%d, %d)\n", __FILE__, __LINE__, fde_ndx, ev->pollfds[fde_ndx].fd); SEGFAULT(); } - + if (ev->unused.used > 0) { int k = ev->unused.ptr[--ev->unused.used]; - + ev->pollfds[k].fd = fd; ev->pollfds[k].events = events; - + return k; } else { if (ev->size == 0) { @@ -90,10 +90,10 @@ static int fdevent_poll_event_add(fdevents *ev, int fde_ndx, int fd, int events) ev->size += 16; ev->pollfds = realloc(ev->pollfds, sizeof(*ev->pollfds) * ev->size); } - + ev->pollfds[ev->used].fd = fd; ev->pollfds[ev->used].events = events; - + return ev->used++; } } @@ -109,12 +109,12 @@ static int fdevent_poll_event_get_revent(fdevents *ev, size_t ndx) { int r, poll_r; if (ndx >= ev->used) { fprintf(stderr, "%s.%d: dying because: event: %zd >= %zd\n", __FILE__, __LINE__, ndx, ev->used); - + SEGFAULT(); - + return 0; } - + if (ev->pollfds[ndx].revents & POLLNVAL) { /* should never happen */ SEGFAULT(); @@ -131,7 +131,7 @@ static int fdevent_poll_event_get_revent(fdevents *ev, size_t ndx) { if (poll_r & POLLHUP) r |= FDEVENT_HUP; if (poll_r & POLLNVAL) r |= FDEVENT_NVAL; if (poll_r & POLLPRI) r |= FDEVENT_PRI; - + return ev->pollfds[ndx].revents; } @@ -141,12 +141,12 @@ static int fdevent_poll_event_get_fd(fdevents *ev, size_t ndx) { static int fdevent_poll_event_next_fdndx(fdevents *ev, int ndx) { size_t i; - + i = (ndx < 0) ? 0 : ndx + 1; for (; i < ev->used; i++) { if (ev->pollfds[i].revents) break; } - + return i; } @@ -154,17 +154,17 @@ int fdevent_poll_init(fdevents *ev) { ev->type = FDEVENT_HANDLER_POLL; #define SET(x) \ ev->x = fdevent_poll_##x; - + SET(free); SET(poll); - + SET(event_del); SET(event_add); - + SET(event_next_fdndx); SET(event_get_fd); SET(event_get_revent); - + return 0; } diff --git a/src/fdevent_select.c b/src/fdevent_select.c index 3eb10f3..4dcb754 100644 --- a/src/fdevent_select.c +++ b/src/fdevent_select.c @@ -49,28 +49,28 @@ static int fdevent_select_event_add(fdevents *ev, int fde_ndx, int fd, int event FD_SET(fd, &(ev->select_set_write)); } FD_SET(fd, &(ev->select_set_error)); - + if (fd > ev->select_max_fd) ev->select_max_fd = fd; - + return fd; } static int fdevent_select_poll(fdevents *ev, int timeout_ms) { struct timeval tv; - + tv.tv_sec = timeout_ms / 1000; tv.tv_usec = (timeout_ms % 1000) * 1000; - + ev->select_read = ev->select_set_read; ev->select_write = ev->select_set_write; ev->select_error = ev->select_set_error; - + return select(ev->select_max_fd + 1, &(ev->select_read), &(ev->select_write), &(ev->select_error), &tv); } static int fdevent_select_event_get_revent(fdevents *ev, size_t ndx) { int revents = 0; - + if (FD_ISSET(ndx, &(ev->select_read))) { revents |= FDEVENT_IN; } @@ -80,7 +80,7 @@ static int fdevent_select_event_get_revent(fdevents *ev, size_t ndx) { if (FD_ISSET(ndx, &(ev->select_error))) { revents |= FDEVENT_ERR; } - + return revents; } @@ -92,15 +92,15 @@ static int fdevent_select_event_get_fd(fdevents *ev, size_t ndx) { static int fdevent_select_event_next_fdndx(fdevents *ev, int ndx) { int i; - + i = (ndx < 0) ? 0 : ndx + 1; - + for (; i < ev->select_max_fd + 1; i++) { if (FD_ISSET(i, &(ev->select_read))) break; if (FD_ISSET(i, &(ev->select_write))) break; if (FD_ISSET(i, &(ev->select_error))) break; } - + return i; } @@ -108,17 +108,17 @@ int fdevent_select_init(fdevents *ev) { ev->type = FDEVENT_HANDLER_SELECT; #define SET(x) \ ev->x = fdevent_select_##x; - + SET(reset); SET(poll); - + SET(event_del); SET(event_add); - + SET(event_next_fdndx); SET(event_get_fd); SET(event_get_revent); - + return 0; } diff --git a/src/fdevent_solaris_devpoll.c b/src/fdevent_solaris_devpoll.c index 91238b0..f77daef 100644 --- a/src/fdevent_solaris_devpoll.c +++ b/src/fdevent_solaris_devpoll.c @@ -23,55 +23,55 @@ static void fdevent_solaris_devpoll_free(fdevents *ev) { static int fdevent_solaris_devpoll_event_del(fdevents *ev, int fde_ndx, int fd) { struct pollfd pfd; - + if (fde_ndx < 0) return -1; - + pfd.fd = fd; pfd.events = POLLREMOVE; pfd.revents = 0; - + if (-1 == write(ev->devpoll_fd, &pfd, sizeof(pfd))) { - fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n", - __FILE__, __LINE__, + fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n", + __FILE__, __LINE__, fd, strerror(errno)); - + return -1; } - + return -1; } static int fdevent_solaris_devpoll_event_add(fdevents *ev, int fde_ndx, int fd, int events) { struct pollfd pfd; int add = 0; - + if (fde_ndx == -1) add = 1; - + pfd.fd = fd; pfd.events = events; pfd.revents = 0; - + if (-1 == write(ev->devpoll_fd, &pfd, sizeof(pfd))) { - fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n", - __FILE__, __LINE__, + fprintf(stderr, "%s.%d: (del) write failed: (%d, %s)\n", + __FILE__, __LINE__, fd, strerror(errno)); - + return -1; } - + return fd; } static int fdevent_solaris_devpoll_poll(fdevents *ev, int timeout_ms) { struct dvpoll dopoll; int ret; - + dopoll.dp_timeout = timeout_ms; dopoll.dp_nfds = ev->maxfds; dopoll.dp_fds = ev->devpollfds; - + ret = ioctl(ev->devpoll_fd, DP_POLL, &dopoll); - + return ret; } @@ -85,11 +85,11 @@ static int fdevent_solaris_devpoll_event_get_fd(fdevents *ev, size_t ndx) { static int fdevent_solaris_devpoll_event_next_fdndx(fdevents *ev, int last_ndx) { size_t i; - + UNUSED(ev); i = (last_ndx < 0) ? 0 : last_ndx + 1; - + return i; } @@ -117,20 +117,20 @@ int fdevent_solaris_devpoll_init(fdevents *ev) { ev->type = FDEVENT_HANDLER_SOLARIS_DEVPOLL; #define SET(x) \ ev->x = fdevent_solaris_devpoll_##x; - + SET(free); SET(poll); SET(reset); - + SET(event_del); SET(event_add); - + SET(event_next_fdndx); SET(event_get_fd); SET(event_get_revent); - + ev->devpollfds = malloc(sizeof(*ev->devpollfds) * ev->maxfds); - + if ((ev->devpoll_fd = open("/dev/poll", O_RDWR)) < 0) { fprintf(stderr, "%s.%d: opening /dev/poll failed (%s), try to set server.event-handler = \"poll\" or \"select\"\n", __FILE__, __LINE__, strerror(errno)); @@ -152,7 +152,7 @@ int fdevent_solaris_devpoll_init(fdevents *ev) { fprintf(stderr, "%s.%d: solaris-devpoll not supported, try to set server.event-handler = \"poll\" or \"select\"\n", __FILE__, __LINE__); - + return -1; } #endif diff --git a/src/http-header-glue.c b/src/http-header-glue.c index b40f374..9786ed8 100644 --- a/src/http-header-glue.c +++ b/src/http-header-glue.c @@ -45,20 +45,20 @@ # ifdef HAVE_STRUCT_SOCKADDR_STORAGE static size_t get_sa_len(const struct sockaddr *addr) { switch (addr->sa_family) { - + # ifdef AF_INET case AF_INET: return (sizeof (struct sockaddr_in)); # endif - + # ifdef AF_INET6 case AF_INET6: return (sizeof (struct sockaddr_in6)); # endif - + default: return (sizeof (struct sockaddr)); - + } } # define SA_LEN(addr) (get_sa_len(addr)) @@ -74,7 +74,7 @@ static size_t get_sa_len(const struct sockaddr *addr) { int response_header_insert(server *srv, connection *con, const char *key, size_t keylen, const char *value, size_t vallen) { data_string *ds; - + UNUSED(srv); if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) { @@ -82,32 +82,32 @@ int response_header_insert(server *srv, connection *con, const char *key, size_t } buffer_copy_string_len(ds->key, key, keylen); buffer_copy_string_len(ds->value, value, vallen); - + array_insert_unique(con->response.headers, (data_unset *)ds); - + return 0; } int response_header_overwrite(server *srv, connection *con, const char *key, size_t keylen, const char *value, size_t vallen) { data_string *ds; - + UNUSED(srv); /* if there already is a key by this name overwrite the value */ if (NULL != (ds = (data_string *)array_get_element(con->response.headers, key))) { buffer_copy_string(ds->value, value); - + return 0; } - + return response_header_insert(srv, con, key, keylen, value, vallen); } int http_response_redirect_to_directory(server *srv, connection *con) { buffer *o; - + o = buffer_init(); - + if (con->conf.is_ssl) { buffer_copy_string(o, "https://"); } else { @@ -123,36 +123,36 @@ int http_response_redirect_to_directory(server *srv, connection *con) { #endif sock_addr our_addr; socklen_t our_addr_len; - + our_addr_len = sizeof(our_addr); - + if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) { con->http_status = 500; - + log_error_write(srv, __FILE__, __LINE__, "ss", "can't get sockname", strerror(errno)); - + buffer_free(o); return 0; } - - + + /* Lookup name: secondly try to get hostname for bind address */ switch(our_addr.plain.sa_family) { #ifdef HAVE_IPV6 case AF_INET6: - if (0 != getnameinfo((const struct sockaddr *)(&our_addr.ipv6), - SA_LEN((const struct sockaddr *)&our_addr.ipv6), + if (0 != getnameinfo((const struct sockaddr *)(&our_addr.ipv6), + SA_LEN((const struct sockaddr *)&our_addr.ipv6), hbuf, sizeof(hbuf), NULL, 0, 0)) { - + char dst[INET6_ADDRSTRLEN]; - + log_error_write(srv, __FILE__, __LINE__, "SSSS", "NOTICE: getnameinfo failed: ", strerror(errno), ", using ip-address instead"); - - buffer_append_string(o, - inet_ntop(AF_INET6, (char *)&our_addr.ipv6.sin6_addr, + + buffer_append_string(o, + inet_ntop(AF_INET6, (char *)&our_addr.ipv6.sin6_addr, dst, sizeof(dst))); } else { buffer_append_string(o, hbuf); @@ -164,7 +164,7 @@ int http_response_redirect_to_directory(server *srv, connection *con) { log_error_write(srv, __FILE__, __LINE__, "SdSS", "NOTICE: gethostbyaddr failed: ", h_errno, ", using ip-address instead"); - + buffer_append_string(o, inet_ntoa(our_addr.ipv4.sin_addr)); } else { buffer_append_string(o, he->h_name); @@ -173,12 +173,12 @@ int http_response_redirect_to_directory(server *srv, connection *con) { default: log_error_write(srv, __FILE__, __LINE__, "S", "ERROR: unsupported address-type"); - + buffer_free(o); return -1; } - - if (!((con->conf.is_ssl == 0 && srv->srvconf.port == 80) || + + if (!((con->conf.is_ssl == 0 && srv->srvconf.port == 80) || (con->conf.is_ssl == 1 && srv->srvconf.port == 443))) { buffer_append_string(o, ":"); buffer_append_long(o, srv->srvconf.port); @@ -190,41 +190,41 @@ int http_response_redirect_to_directory(server *srv, connection *con) { buffer_append_string(o, "?"); buffer_append_string_buffer(o, con->uri.query); } - + response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(o)); - + con->http_status = 301; con->file_finished = 1; - + buffer_free(o); - + return 0; } buffer * strftime_cache_get(server *srv, time_t last_mod) { struct tm *tm; size_t i; - + for (i = 0; i < FILE_CACHE_MAX; i++) { /* found cache-entry */ if (srv->mtime_cache[i].mtime == last_mod) return srv->mtime_cache[i].str; - + /* found empty slot */ if (srv->mtime_cache[i].mtime == 0) break; } - + if (i == FILE_CACHE_MAX) { i = 0; } - + srv->mtime_cache[i].mtime = last_mod; buffer_prepare_copy(srv->mtime_cache[i].str, 1024); tm = gmtime(&(srv->mtime_cache[i].mtime)); - srv->mtime_cache[i].str->used = strftime(srv->mtime_cache[i].str->ptr, + srv->mtime_cache[i].str->used = strftime(srv->mtime_cache[i].str->ptr, srv->mtime_cache[i].str->size - 1, "%a, %d %b %Y %H:%M:%S GMT", tm); srv->mtime_cache[i].str->used++; - + return srv->mtime_cache[i].str; } @@ -239,24 +239,24 @@ int http_response_handle_cachable(server *srv, connection *con, buffer *mtime) { * request. That is, if no entity tags match, then the server MUST NOT * return a 304 (Not Modified) response. */ - + /* last-modified handling */ if (con->request.http_if_none_match) { if (etag_is_equal(con->physical.etag, con->request.http_if_none_match)) { - if (con->request.http_method == HTTP_METHOD_GET || + if (con->request.http_method == HTTP_METHOD_GET || con->request.http_method == HTTP_METHOD_HEAD) { - + /* check if etag + last-modified */ if (con->request.http_if_modified_since) { size_t used_len; char *semicolon; - + if (NULL == (semicolon = strchr(con->request.http_if_modified_since, ';'))) { used_len = strlen(con->request.http_if_modified_since); } else { used_len = semicolon - con->request.http_if_modified_since; } - + if (0 == strncmp(con->request.http_if_modified_since, mtime->ptr, used_len)) { con->http_status = 304; return HANDLER_FINISHED; @@ -267,26 +267,26 @@ int http_response_handle_cachable(server *srv, connection *con, buffer *mtime) { /* check if we can safely copy the string */ if (used_len >= sizeof(buf)) { - log_error_write(srv, __FILE__, __LINE__, "ssdd", - "DEBUG: Last-Modified check failed as the received timestamp was too long:", + log_error_write(srv, __FILE__, __LINE__, "ssdd", + "DEBUG: Last-Modified check failed as the received timestamp was too long:", con->request.http_if_modified_since, used_len, sizeof(buf) - 1); - + con->http_status = 412; return HANDLER_FINISHED; } - + strncpy(buf, con->request.http_if_modified_since, used_len); buf[used_len] = '\0'; - + strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm); t_header = mktime(&tm); - + strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm); t_file = mktime(&tm); if (t_file > t_header) return HANDLER_GO_ON; - + con->http_status = 304; return HANDLER_FINISHED; } @@ -308,7 +308,7 @@ int http_response_handle_cachable(server *srv, connection *con, buffer *mtime) { } else { used_len = semicolon - con->request.http_if_modified_since; } - + if (0 == strncmp(con->request.http_if_modified_since, mtime->ptr, used_len)) { con->http_status = 304; return HANDLER_FINISHED; @@ -322,10 +322,10 @@ int http_response_handle_cachable(server *srv, connection *con, buffer *mtime) { strncpy(buf, con->request.http_if_modified_since, used_len); buf[used_len] = '\0'; - + strptime(buf, "%a, %d %b %Y %H:%M:%S GMT", &tm); t_header = mktime(&tm); - + strptime(mtime->ptr, "%a, %d %b %Y %H:%M:%S GMT", &tm); t_file = mktime(&tm); diff --git a/src/http_auth.c b/src/http_auth.c index 0d4637e..ae2560c 100644 --- a/src/http_auth.c +++ b/src/http_auth.c @@ -37,6 +37,21 @@ # include "md5.h" #endif +/** + * the $apr1$ handling is taken from apache 1.3.x + */ + +/* + * The apr_md5_encode() routine uses much code obtained from the FreeBSD 3.0 + * MD5 crypt() function, which is licenced as follows: + * ---------------------------------------------------------------------------- + * "THE BEER-WARE LICENSE" (Revision 42): + * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you + * can do whatever you want with this stuff. If we meet some day, and you think + * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp + * ---------------------------------------------------------------------------- + */ + handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s); static const char base64_pad = '='; @@ -64,25 +79,25 @@ static unsigned char * base64_decode(buffer *out, const char *in) { unsigned char *result; int ch, j = 0, k; size_t i; - + size_t in_len = strlen(in); - + buffer_prepare_copy(out, in_len); - + result = (unsigned char *)out->ptr; - + ch = in[0]; /* run through the whole string, converting as we go */ for (i = 0; i < in_len; i++) { ch = in[i]; - + if (ch == '\0') break; - + if (ch == base64_pad) break; - + ch = base64_reverse_table[ch]; if (ch < 0) continue; - + switch(i % 4) { case 0: result[j] = ch << 2; @@ -114,168 +129,168 @@ static unsigned char * base64_decode(buffer *out, const char *in) { } } result[k] = '\0'; - + out->used = k; - + return result; } static int http_auth_get_password(server *srv, mod_auth_plugin_data *p, buffer *username, buffer *realm, buffer *password) { int ret = -1; - + if (!username->used|| !realm->used) return -1; - + if (p->conf.auth_backend == AUTH_BACKEND_HTDIGEST) { stream f; char * f_line; - + if (buffer_is_empty(p->conf.auth_htdigest_userfile)) return -1; - + if (0 != stream_open(&f, p->conf.auth_htdigest_userfile)) { log_error_write(srv, __FILE__, __LINE__, "sbss", "opening digest-userfile", p->conf.auth_htdigest_userfile, "failed:", strerror(errno)); - + return -1; } - + f_line = f.start; - + while (f_line - f.start != f.size) { char *f_user, *f_pwd, *e, *f_realm; size_t u_len, pwd_len, r_len; - + f_user = f_line; - - /* + + /* * htdigest format - * - * user:realm:md5(user:realm:password) + * + * user:realm:md5(user:realm:password) */ - + if (NULL == (f_realm = memchr(f_user, ':', f.size - (f_user - f.start) ))) { - log_error_write(srv, __FILE__, __LINE__, "sbs", - "parsed error in", p->conf.auth_htdigest_userfile, + log_error_write(srv, __FILE__, __LINE__, "sbs", + "parsed error in", p->conf.auth_htdigest_userfile, "expected 'username:realm:hashed password'"); - + stream_close(&f); - + return -1; } - + if (NULL == (f_pwd = memchr(f_realm + 1, ':', f.size - (f_realm + 1 - f.start)))) { - log_error_write(srv, __FILE__, __LINE__, "sbs", - "parsed error in", p->conf.auth_plain_userfile, + log_error_write(srv, __FILE__, __LINE__, "sbs", + "parsed error in", p->conf.auth_plain_userfile, "expected 'username:realm:hashed password'"); - + stream_close(&f); - + return -1; } - + /* get pointers to the fields */ - u_len = f_realm - f_user; + u_len = f_realm - f_user; f_realm++; r_len = f_pwd - f_realm; f_pwd++; - + if (NULL != (e = memchr(f_pwd, '\n', f.size - (f_pwd - f.start)))) { pwd_len = e - f_pwd; } else { pwd_len = f.size - (f_pwd - f.start); } - + if (username->used - 1 == u_len && (realm->used - 1 == r_len) && (0 == strncmp(username->ptr, f_user, u_len)) && (0 == strncmp(realm->ptr, f_realm, r_len))) { /* found */ - + buffer_copy_string_len(password, f_pwd, pwd_len); - + ret = 0; break; } - + /* EOL */ if (!e) break; - + f_line = e + 1; } - + stream_close(&f); } else if (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD || p->conf.auth_backend == AUTH_BACKEND_PLAIN) { stream f; char * f_line; buffer *auth_fn; - + auth_fn = (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD) ? p->conf.auth_htpasswd_userfile : p->conf.auth_plain_userfile; - + if (buffer_is_empty(auth_fn)) return -1; - + if (0 != stream_open(&f, auth_fn)) { - log_error_write(srv, __FILE__, __LINE__, "sbss", + log_error_write(srv, __FILE__, __LINE__, "sbss", "opening plain-userfile", auth_fn, "failed:", strerror(errno)); - + return -1; } - + f_line = f.start; - + while (f_line - f.start != f.size) { char *f_user, *f_pwd, *e; size_t u_len, pwd_len; - + f_user = f_line; - - /* + + /* * htpasswd format - * + * * user:crypted passwd */ - + if (NULL == (f_pwd = memchr(f_user, ':', f.size - (f_user - f.start) ))) { - log_error_write(srv, __FILE__, __LINE__, "sbs", - "parsed error in", auth_fn, + log_error_write(srv, __FILE__, __LINE__, "sbs", + "parsed error in", auth_fn, "expected 'username:hashed password'"); - + stream_close(&f); - + return -1; } - + /* get pointers to the fields */ - u_len = f_pwd - f_user; + u_len = f_pwd - f_user; f_pwd++; - + if (NULL != (e = memchr(f_pwd, '\n', f.size - (f_pwd - f.start)))) { pwd_len = e - f_pwd; } else { pwd_len = f.size - (f_pwd - f.start); } - + if (username->used - 1 == u_len && (0 == strncmp(username->ptr, f_user, u_len))) { /* found */ - + buffer_copy_string_len(password, f_pwd, pwd_len); - + ret = 0; break; } - + /* EOL */ if (!e) break; - + f_line = e + 1; } - + stream_close(&f); } else if (p->conf.auth_backend == AUTH_BACKEND_LDAP) { ret = 0; } else { return -1; } - + return ret; } @@ -285,7 +300,7 @@ static int http_auth_match_rules(server *srv, mod_auth_plugin_data *p, const cha int username_len; data_string *require; array *req; - + UNUSED(group); UNUSED(host); @@ -293,12 +308,12 @@ static int http_auth_match_rules(server *srv, mod_auth_plugin_data *p, const cha /* search auth-directives for path */ for (i = 0; i < p->conf.auth_require->used; i++) { if (p->conf.auth_require->data[i]->key->used == 0) continue; - + if (0 == strncmp(url, p->conf.auth_require->data[i]->key->ptr, p->conf.auth_require->data[i]->key->used - 1)) { break; } } - + if (i == p->conf.auth_require->used) { return -1; } @@ -306,72 +321,72 @@ static int http_auth_match_rules(server *srv, mod_auth_plugin_data *p, const cha req = ((data_array *)(p->conf.auth_require->data[i]))->value; require = (data_string *)array_get_element(req, "require"); - + /* if we get here, the user we got a authed user */ if (0 == strcmp(require->value->ptr, "valid-user")) { return 0; } - + /* user=name1|group=name3|host=name4 */ - + /* seperate the string by | */ #if 0 log_error_write(srv, __FILE__, __LINE__, "sb", "rules", require->value); -#endif - +#endif + username_len = username ? strlen(username) : 0; - + r = rules = require->value->ptr; - + while (1) { const char *eq; const char *k, *v, *e; int k_len, v_len, r_len; - + e = strchr(r, '|'); - + if (e) { r_len = e - r; } else { r_len = strlen(rules) - (r - rules); } - + /* from r to r + r_len is a rule */ - + if (0 == strncmp(r, "valid-user", r_len)) { - log_error_write(srv, __FILE__, __LINE__, "sb", + log_error_write(srv, __FILE__, __LINE__, "sb", "parsing the 'require' section in 'auth.require' failed: valid-user cannot be combined with other require rules", require->value); return -1; } - + /* search for = in the rules */ if (NULL == (eq = strchr(r, '='))) { - log_error_write(srv, __FILE__, __LINE__, "sb", - "parsing the 'require' section in 'auth.require' failed: a = is missing", + log_error_write(srv, __FILE__, __LINE__, "sb", + "parsing the 'require' section in 'auth.require' failed: a = is missing", require->value); return -1; } - + /* = out of range */ if (eq > r + r_len) { - log_error_write(srv, __FILE__, __LINE__, "sb", + log_error_write(srv, __FILE__, __LINE__, "sb", "parsing the 'require' section in 'auth.require' failed: = out of range", require->value); - + return -1; } - + /* the part before the = is user|group|host */ - + k = r; k_len = eq - r; v = eq + 1; v_len = r_len - k_len - 1; - + if (k_len == 4) { if (0 == strncmp(k, "user", k_len)) { - if (username && + if (username && username_len == v_len && 0 == strncmp(username, v, v_len)) { return 0; @@ -393,19 +408,191 @@ static int http_auth_match_rules(server *srv, mod_auth_plugin_data *p, const cha log_error_write(srv, __FILE__, __LINE__, "s", "unknown key"); return -1; } - + if (!e) break; r = e + 1; } - + log_error_write(srv, __FILE__, __LINE__, "s", "nothing matched"); - + return -1; } +#define APR_MD5_DIGESTSIZE 16 +#define APR1_ID "$apr1$" + +/* + * The following MD5 password encryption code was largely borrowed from + * the FreeBSD 3.0 /usr/src/lib/libcrypt/crypt.c file, which is + * licenced as stated at the top of this file. + */ + +static void to64(char *s, unsigned long v, int n) +{ + static unsigned char itoa64[] = /* 0 ... 63 => ASCII - 64 */ + "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + + while (--n >= 0) { + *s++ = itoa64[v&0x3f]; + v >>= 6; + } +} + +static void apr_md5_encode(const char *pw, const char *salt, char *result, size_t nbytes) { + /* + * Minimum size is 8 bytes for salt, plus 1 for the trailing NUL, + * plus 4 for the '$' separators, plus the password hash itself. + * Let's leave a goodly amount of leeway. + */ + + char passwd[120], *p; + const char *sp, *ep; + unsigned char final[APR_MD5_DIGESTSIZE]; + ssize_t sl, pl, i; + MD5_CTX ctx, ctx1; + unsigned long l; + + /* + * Refine the salt first. It's possible we were given an already-hashed + * string as the salt argument, so extract the actual salt value from it + * if so. Otherwise just use the string up to the first '$' as the salt. + */ + sp = salt; + + /* + * If it starts with the magic string, then skip that. + */ + if (!strncmp(sp, APR1_ID, strlen(APR1_ID))) { + sp += strlen(APR1_ID); + } + + /* + * It stops at the first '$' or 8 chars, whichever comes first + */ + for (ep = sp; (*ep != '\0') && (*ep != '$') && (ep < (sp + 8)); ep++) { + continue; + } + + /* + * Get the length of the true salt + */ + sl = ep - sp; + + /* + * 'Time to make the doughnuts..' + */ + MD5_Init(&ctx); + + /* + * The password first, since that is what is most unknown + */ + MD5_Update(&ctx, pw, strlen(pw)); + + /* + * Then our magic string + */ + MD5_Update(&ctx, APR1_ID, strlen(APR1_ID)); + + /* + * Then the raw salt + */ + MD5_Update(&ctx, sp, sl); + + /* + * Then just as many characters of the MD5(pw, salt, pw) + */ + MD5_Init(&ctx1); + MD5_Update(&ctx1, pw, strlen(pw)); + MD5_Update(&ctx1, sp, sl); + MD5_Update(&ctx1, pw, strlen(pw)); + MD5_Final(final, &ctx1); + for (pl = strlen(pw); pl > 0; pl -= APR_MD5_DIGESTSIZE) { + MD5_Update(&ctx, final, + (pl > APR_MD5_DIGESTSIZE) ? APR_MD5_DIGESTSIZE : pl); + } + + /* + * Don't leave anything around in vm they could use. + */ + memset(final, 0, sizeof(final)); + + /* + * Then something really weird... + */ + for (i = strlen(pw); i != 0; i >>= 1) { + if (i & 1) { + MD5_Update(&ctx, final, 1); + } + else { + MD5_Update(&ctx, pw, 1); + } + } + + /* + * Now make the output string. We know our limitations, so we + * can use the string routines without bounds checking. + */ + strcpy(passwd, APR1_ID); + strncat(passwd, sp, sl); + strcat(passwd, "$"); + + MD5_Final(final, &ctx); + + /* + * And now, just to make sure things don't run too fast.. + * On a 60 Mhz Pentium this takes 34 msec, so you would + * need 30 seconds to build a 1000 entry dictionary... + */ + for (i = 0; i < 1000; i++) { + MD5_Init(&ctx1); + if (i & 1) { + MD5_Update(&ctx1, pw, strlen(pw)); + } + else { + MD5_Update(&ctx1, final, APR_MD5_DIGESTSIZE); + } + if (i % 3) { + MD5_Update(&ctx1, sp, sl); + } + + if (i % 7) { + MD5_Update(&ctx1, pw, strlen(pw)); + } + + if (i & 1) { + MD5_Update(&ctx1, final, APR_MD5_DIGESTSIZE); + } + else { + MD5_Update(&ctx1, pw, strlen(pw)); + } + MD5_Final(final,&ctx1); + } + + p = passwd + strlen(passwd); + + l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p, l, 4); p += 4; + l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p, l, 4); p += 4; + l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p, l, 4); p += 4; + l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p, l, 4); p += 4; + l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p, l, 4); p += 4; + l = final[11] ; to64(p, l, 2); p += 2; + *p = '\0'; + + /* + * Don't leave anything around in vm they could use. + */ + memset(final, 0, sizeof(final)); + + /* FIXME + */ +#define apr_cpystrn strncpy + apr_cpystrn(result, passwd, nbytes - 1); +} + + /** - * - * + * + * * @param password password-string from the auth-backend * @param pw password-string from the client */ @@ -415,16 +602,16 @@ static int http_auth_basic_password_compare(server *srv, mod_auth_plugin_data *p UNUSED(req); if (p->conf.auth_backend == AUTH_BACKEND_HTDIGEST) { - /* + /* * htdigest format - * - * user:realm:md5(user:realm:password) + * + * user:realm:md5(user:realm:password) */ - + MD5_CTX Md5Ctx; HASH HA1; char a1[256]; - + MD5_Init(&Md5Ctx); MD5_Update(&Md5Ctx, (unsigned char *)username->ptr, username->used - 1); MD5_Update(&Md5Ctx, (unsigned char *)":", 1); @@ -432,24 +619,32 @@ static int http_auth_basic_password_compare(server *srv, mod_auth_plugin_data *p MD5_Update(&Md5Ctx, (unsigned char *)":", 1); MD5_Update(&Md5Ctx, (unsigned char *)pw, strlen(pw)); MD5_Final(HA1, &Md5Ctx); - + CvtHex(HA1, a1); - + if (0 == strcmp(password->ptr, a1)) { return 0; } - } else if (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD) { -#ifdef HAVE_CRYPT + } else if (p->conf.auth_backend == AUTH_BACKEND_HTPASSWD) { + char sample[120]; + if (!strncmp(password->ptr, APR1_ID, strlen(APR1_ID))) { + /* + * The hash was created using $apr1$ custom algorithm. + */ + apr_md5_encode(pw, password->ptr, sample, sizeof(sample)); + return (strcmp(sample, password->ptr) == 0) ? 0 : 1; + } else { +#ifdef HAVE_CRYPT char salt[32]; char *crypted; size_t salt_len = 0; - /* + /* * htpasswd format - * + * * user:crypted password */ - /* + /* * Algorithm Salt * CRYPT_STD_DES 2-character (Default) * CRYPT_EXT_DES 9-character @@ -467,7 +662,7 @@ static int http_auth_basic_password_compare(server *srv, mod_auth_plugin_data *p salt_len = 2; } else if (password->ptr[0] == '$' && password->ptr[2] == '$') { char *dollar = NULL; - + if (NULL == (dollar = strchr(password->ptr + 3, '$'))) { fprintf(stderr, "%s.%d\n", __FILE__, __LINE__); return -1; @@ -484,7 +679,7 @@ static int http_auth_basic_password_compare(server *srv, mod_auth_plugin_data *p strncpy(salt, password->ptr, salt_len); salt[salt_len] = '\0'; - + crypted = crypt(pw, salt); if (0 == strcmp(password->ptr, crypted)) { @@ -492,13 +687,14 @@ static int http_auth_basic_password_compare(server *srv, mod_auth_plugin_data *p } else { fprintf(stderr, "%s.%d\n", __FILE__, __LINE__); } - -#endif - } else if (p->conf.auth_backend == AUTH_BACKEND_PLAIN) { + +#endif + } + } else if (p->conf.auth_backend == AUTH_BACKEND_PLAIN) { if (0 == strcmp(password->ptr, pw)) { return 0; } - } else if (p->conf.auth_backend == AUTH_BACKEND_LDAP) { + } else if (p->conf.auth_backend == AUTH_BACKEND_LDAP) { #ifdef USE_LDAP LDAP *ldap; LDAPMessage *lm, *first; @@ -506,45 +702,45 @@ static int http_auth_basic_password_compare(server *srv, mod_auth_plugin_data *p int ret; char *attrs[] = { LDAP_NO_ATTRS, NULL }; size_t i; - + /* for now we stay synchronous */ - - /* + + /* * 1. connect anonymously (done in plugin init) * 2. get DN for uid = username * 3. auth against ldap server * 4. (optional) check a field * 5. disconnect - * + * */ - + /* check username - * + * * we have to protect us againt username which modifies out filter in * a unpleasant way */ - + for (i = 0; i < username->used - 1; i++) { char c = username->ptr[i]; - + if (!isalpha(c) && !isdigit(c)) { - - log_error_write(srv, __FILE__, __LINE__, "sbd", + + log_error_write(srv, __FILE__, __LINE__, "sbd", "ldap: invalid character (a-zA-Z0-9 allowed) in username:", username, i); - + return -1; } } - - - + + + /* build filter */ buffer_copy_string_buffer(p->ldap_filter, p->conf.ldap_filter_pre); buffer_append_string_buffer(p->ldap_filter, username); buffer_append_string_buffer(p->ldap_filter, p->conf.ldap_filter_post); - - + + /* 2. */ if (p->conf.ldap == NULL || LDAP_SUCCESS != (ret = ldap_search_s(p->conf.ldap, p->conf.auth_ldap_basedn->ptr, LDAP_SCOPE_SUBTREE, p->ldap_filter->ptr, attrs, 0, &lm))) { @@ -552,71 +748,71 @@ static int http_auth_basic_password_compare(server *srv, mod_auth_plugin_data *p return -1; if (LDAP_SUCCESS != (ret = ldap_search_s(p->conf.ldap, p->conf.auth_ldap_basedn->ptr, LDAP_SCOPE_SUBTREE, p->ldap_filter->ptr, attrs, 0, &lm))) { - log_error_write(srv, __FILE__, __LINE__, "sssb", + log_error_write(srv, __FILE__, __LINE__, "sssb", "ldap:", ldap_err2string(ret), "filter:", p->ldap_filter); - + return -1; } } - + if (NULL == (first = ldap_first_entry(p->conf.ldap, lm))) { log_error_write(srv, __FILE__, __LINE__, "s", "ldap ..."); - + ldap_msgfree(lm); - + return -1; } - + if (NULL == (dn = ldap_get_dn(p->conf.ldap, first))) { log_error_write(srv, __FILE__, __LINE__, "s", "ldap ..."); - + ldap_msgfree(lm); - + return -1; } - + ldap_msgfree(lm); - - + + /* 3. */ if (NULL == (ldap = ldap_init(p->conf.auth_ldap_hostname->ptr, LDAP_PORT))) { log_error_write(srv, __FILE__, __LINE__, "ss", "ldap ...", strerror(errno)); return -1; } - + ret = LDAP_VERSION3; if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &ret))) { log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret)); - + ldap_unbind_s(ldap); - + return -1; } - + if (p->conf.auth_ldap_starttls == 1) { if (LDAP_OPT_SUCCESS != (ret = ldap_start_tls_s(ldap, NULL, NULL))) { log_error_write(srv, __FILE__, __LINE__, "ss", "ldap startTLS failed:", ldap_err2string(ret)); - + ldap_unbind_s(ldap); - + return -1; } } - + if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(ldap, dn, pw))) { log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret)); - + ldap_unbind_s(ldap); - + return -1; } - + /* 5. */ ldap_unbind_s(ldap); - + /* everything worked, good, access granted */ - + return 0; #endif } @@ -626,65 +822,65 @@ static int http_auth_basic_password_compare(server *srv, mod_auth_plugin_data *p int http_auth_basic_check(server *srv, connection *con, mod_auth_plugin_data *p, array *req, buffer *url, const char *realm_str) { buffer *username, *password; char *pw; - + data_string *realm; - + realm = (data_string *)array_get_element(req, "realm"); - + username = buffer_init(); password = buffer_init(); - + base64_decode(username, realm_str); - + /* r2 == user:password */ if (NULL == (pw = strchr(username->ptr, ':'))) { buffer_free(username); - + log_error_write(srv, __FILE__, __LINE__, "sb", ": is missing in", username); - + return 0; } - + *pw++ = '\0'; - + username->used = pw - username->ptr; - + /* copy password to r1 */ if (http_auth_get_password(srv, p, username, realm->value, password)) { buffer_free(username); buffer_free(password); - + log_error_write(srv, __FILE__, __LINE__, "s", "get_password failed"); - + return 0; } - + /* password doesn't match */ if (http_auth_basic_password_compare(srv, p, req, username, realm->value, password, pw)) { log_error_write(srv, __FILE__, __LINE__, "sbb", "password doesn't match for", con->uri.path, username); - + buffer_free(username); buffer_free(password); - + return 0; } - + /* value is our allow-rules */ if (http_auth_match_rules(srv, p, url->ptr, username->ptr, NULL, NULL)) { buffer_free(username); buffer_free(password); - + log_error_write(srv, __FILE__, __LINE__, "s", "rules didn't match"); - + return 0; } - + /* remember the username */ buffer_copy_string_buffer(p->auth_user, username); - + buffer_free(username); buffer_free(password); - + return 1; } @@ -697,7 +893,7 @@ typedef struct { int http_auth_digest_check(server *srv, connection *con, mod_auth_plugin_data *p, array *req, buffer *url, const char *realm_str) { char a1[256]; char a2[256]; - + char *username; char *realm; char *nonce; @@ -707,18 +903,18 @@ int http_auth_digest_check(server *srv, connection *con, mod_auth_plugin_data *p char *cnonce; char *nc; char *respons; - + char *e, *c; const char *m = NULL; int i; buffer *password, *b, *username_buf, *realm_buf; - + MD5_CTX Md5Ctx; HASH HA1; HASH HA2; HASH RespHash; HASHHEX HA2Hex; - + /* init pointers */ #define S(x) \ @@ -733,11 +929,11 @@ int http_auth_digest_check(server *srv, connection *con, mod_auth_plugin_data *p { S("cnonce=") }, { S("nc=") }, { S("response=") }, - + { NULL, 0, NULL } }; #undef S - + dkv[0].ptr = &username; dkv[1].ptr = &realm; dkv[2].ptr = &nonce; @@ -748,24 +944,24 @@ int http_auth_digest_check(server *srv, connection *con, mod_auth_plugin_data *p dkv[7].ptr = &nc; dkv[8].ptr = &respons; dkv[9].ptr = NULL; - + UNUSED(req); - + for (i = 0; dkv[i].key; i++) { *(dkv[i].ptr) = NULL; } - - + + if (p->conf.auth_backend != AUTH_BACKEND_HTDIGEST && p->conf.auth_backend != AUTH_BACKEND_PLAIN) { - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "digest: unsupported backend (only htdigest or plain)"); - + return -1; } - + b = buffer_init_string(realm_str); - + /* parse credentials from client */ for (c = b->ptr; *c; c++) { /* skip whitespaces */ @@ -774,18 +970,18 @@ int http_auth_digest_check(server *srv, connection *con, mod_auth_plugin_data *p for (i = 0; dkv[i].key; i++) { if ((0 == strncmp(c, dkv[i].key, dkv[i].key_len))) { - if ((c[dkv[i].key_len] == '"') && + if ((c[dkv[i].key_len] == '"') && (NULL != (e = strchr(c + dkv[i].key_len + 1, '"')))) { /* value with "..." */ *(dkv[i].ptr) = c + dkv[i].key_len + 1; c = e; - + *e = '\0'; } else if (NULL != (e = strchr(c + dkv[i].key_len, ','))) { /* value without "...", terminated by ',' */ *(dkv[i].ptr) = c + dkv[i].key_len; c = e; - + *e = '\0'; } else { /* value without "...", terminated by EOL */ @@ -795,7 +991,7 @@ int http_auth_digest_check(server *srv, connection *con, mod_auth_plugin_data *p } } } - + if (p->conf.auth_debug > 1) { log_error_write(srv, __FILE__, __LINE__, "ss", "username", username); log_error_write(srv, __FILE__, __LINE__, "ss", "realm", realm); @@ -807,22 +1003,22 @@ int http_auth_digest_check(server *srv, connection *con, mod_auth_plugin_data *p log_error_write(srv, __FILE__, __LINE__, "ss", "nc", nc); log_error_write(srv, __FILE__, __LINE__, "ss", "response", respons); } - + /* check if everything is transmitted */ - if (!username || + if (!username || !realm || !nonce || !uri || (qop && (!nc || !cnonce)) || !respons ) { /* missing field */ - - log_error_write(srv, __FILE__, __LINE__, "s", + + log_error_write(srv, __FILE__, __LINE__, "s", "digest: missing field"); return -1; } - m = get_http_method_name(con->request.http_method); + m = get_http_method_name(con->request.http_method); /* password-string == HA1 */ password = buffer_init(); @@ -835,10 +1031,10 @@ int http_auth_digest_check(server *srv, connection *con, mod_auth_plugin_data *p buffer_free(realm_buf); return 0; } - + buffer_free(username_buf); buffer_free(realm_buf); - + if (p->conf.auth_backend == AUTH_BACKEND_PLAIN) { /* generate password from plain-text */ MD5_Init(&Md5Ctx); @@ -852,16 +1048,16 @@ int http_auth_digest_check(server *srv, connection *con, mod_auth_plugin_data *p /* HA1 */ /* transform the 32-byte-hex-md5 to a 16-byte-md5 */ for (i = 0; i < HASHLEN; i++) { - HA1[i] = hex2int(password->ptr[i*2]) << 4; - HA1[i] |= hex2int(password->ptr[i*2+1]); + HA1[i] = hex2int(password->ptr[i*2]) << 4; + HA1[i] |= hex2int(password->ptr[i*2+1]); } } else { /* we already check that above */ SEGFAULT(); } - + buffer_free(password); - + if (algorithm && strcasecmp(algorithm, "md5-sess") == 0) { MD5_Init(&Md5Ctx); @@ -872,9 +1068,9 @@ int http_auth_digest_check(server *srv, connection *con, mod_auth_plugin_data *p MD5_Update(&Md5Ctx, (unsigned char *)cnonce, strlen(cnonce)); MD5_Final(HA1, &Md5Ctx); } - + CvtHex(HA1, a1); - + /* calculate H(A2) */ MD5_Init(&Md5Ctx); MD5_Update(&Md5Ctx, (unsigned char *)m, strlen(m)); @@ -886,7 +1082,7 @@ int http_auth_digest_check(server *srv, connection *con, mod_auth_plugin_data *p } MD5_Final(HA2, &Md5Ctx); CvtHex(HA2, HA2Hex); - + /* calculate response */ MD5_Init(&Md5Ctx); MD5_Update(&Md5Ctx, (unsigned char *)a1, HASHHEXLEN); @@ -904,39 +1100,39 @@ int http_auth_digest_check(server *srv, connection *con, mod_auth_plugin_data *p MD5_Update(&Md5Ctx, (unsigned char *)HA2Hex, HASHHEXLEN); MD5_Final(RespHash, &Md5Ctx); CvtHex(RespHash, a2); - + if (0 != strcmp(a2, respons)) { /* digest not ok */ - + if (p->conf.auth_debug) { - log_error_write(srv, __FILE__, __LINE__, "sss", + log_error_write(srv, __FILE__, __LINE__, "sss", "digest: digest mismatch", a2, respons); } - - log_error_write(srv, __FILE__, __LINE__, "sss", + + log_error_write(srv, __FILE__, __LINE__, "sss", "digest: auth failed for", username, "wrong password"); - + buffer_free(b); return 0; } - + /* value is our allow-rules */ if (http_auth_match_rules(srv, p, url->ptr, username, NULL, NULL)) { buffer_free(b); - - log_error_write(srv, __FILE__, __LINE__, "s", + + log_error_write(srv, __FILE__, __LINE__, "s", "digest: rules did match"); - + return 0; } - + /* remember the username */ buffer_copy_string(p->auth_user, username); - + buffer_free(b); - + if (p->conf.auth_debug) { - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "digest: auth ok"); } return 1; @@ -947,23 +1143,23 @@ int http_auth_digest_generate_nonce(server *srv, mod_auth_plugin_data *p, buffer HASH h; MD5_CTX Md5Ctx; char hh[32]; - + UNUSED(p); /* generate shared-secret */ MD5_Init(&Md5Ctx); MD5_Update(&Md5Ctx, (unsigned char *)fn->ptr, fn->used - 1); MD5_Update(&Md5Ctx, (unsigned char *)"+", 1); - + /* we assume sizeof(time_t) == 4 here, but if not it ain't a problem at all */ ltostr(hh, srv->cur_ts); MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh)); ltostr(hh, rand()); MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh)); - + MD5_Final(h, &Md5Ctx); - + CvtHex(h, out); - + return 0; } diff --git a/src/http_auth.h b/src/http_auth.h index b69007e..d469c0d 100644 --- a/src/http_auth.h +++ b/src/http_auth.h @@ -20,15 +20,15 @@ typedef enum { typedef struct { /* auth */ array *auth_require; - + buffer *auth_plain_groupfile; buffer *auth_plain_userfile; - + buffer *auth_htdigest_userfile; buffer *auth_htpasswd_userfile; - + buffer *auth_backend_conf; - + buffer *auth_ldap_hostname; buffer *auth_ldap_basedn; buffer *auth_ldap_binddn; @@ -36,15 +36,15 @@ typedef struct { buffer *auth_ldap_filter; buffer *auth_ldap_cafile; unsigned short auth_ldap_starttls; - + unsigned short auth_debug; - + /* generated */ auth_backend_t auth_backend; - + #ifdef USE_LDAP LDAP *ldap; - + buffer *ldap_filter_pre; buffer *ldap_filter_post; #endif @@ -53,15 +53,15 @@ typedef struct { typedef struct { PLUGIN_DATA; buffer *tmp_buf; - + buffer *auth_user; #ifdef USE_LDAP buffer *ldap_filter; #endif - + mod_auth_plugin_config **config_storage; - + mod_auth_plugin_config conf; /* this is only used as long as no handler_ctx is setup */ } mod_auth_plugin_data; diff --git a/src/http_auth_digest.h b/src/http_auth_digest.h index 8bffce4..25d95ee 100644 --- a/src/http_auth_digest.h +++ b/src/http_auth_digest.h @@ -12,7 +12,7 @@ typedef char HASHHEX[HASHHEXLEN+1]; #ifdef USE_OPENSSL #define IN const #else -#define IN +#define IN #endif #define OUT diff --git a/src/http_chunk.c b/src/http_chunk.c index 281e86b..669ff32 100644 --- a/src/http_chunk.c +++ b/src/http_chunk.c @@ -1,7 +1,7 @@ /** * the HTTP chunk-API - * - * + * + * */ #include <sys/types.h> @@ -23,19 +23,19 @@ static int http_chunk_append_len(server *srv, connection *con, size_t len) { size_t i, olen = len, j; buffer *b; - + b = srv->tmp_chunk_len; - + if (len == 0) { buffer_copy_string(b, "0"); } else { for (i = 0; i < 8 && len; i++) { len >>= 4; } - + /* i is the number of hex digits we have */ buffer_prepare_copy(b, i + 1); - + for (j = i-1, len = olen; j+1 > 0; j--) { b->ptr[j] = (len & 0xf) + (((len & 0xf) <= 9) ? '0' : 'a' - 10); len >>= 4; @@ -43,61 +43,61 @@ static int http_chunk_append_len(server *srv, connection *con, size_t len) { b->used = i; b->ptr[b->used++] = '\0'; } - + buffer_append_string(b, "\r\n"); chunkqueue_append_buffer(con->write_queue, b); - + return 0; } int http_chunk_append_file(server *srv, connection *con, buffer *fn, off_t offset, off_t len) { chunkqueue *cq; - + if (!con) return -1; - + cq = con->write_queue; - + if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) { http_chunk_append_len(srv, con, len); } - + chunkqueue_append_file(cq, fn, offset, len); - + if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED && len > 0) { chunkqueue_append_mem(cq, "\r\n", 2 + 1); } - + return 0; } int http_chunk_append_buffer(server *srv, connection *con, buffer *mem) { chunkqueue *cq; - + if (!con) return -1; - + cq = con->write_queue; - + if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) { http_chunk_append_len(srv, con, mem->used - 1); } - + chunkqueue_append_buffer(cq, mem); - + if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED && mem->used > 0) { chunkqueue_append_mem(cq, "\r\n", 2 + 1); } - + return 0; } int http_chunk_append_mem(server *srv, connection *con, const char * mem, size_t len) { chunkqueue *cq; - + if (!con) return -1; - + cq = con->write_queue; - + if (len == 0) { if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) { chunkqueue_append_mem(cq, "0\r\n\r\n", 5 + 1); @@ -106,17 +106,17 @@ int http_chunk_append_mem(server *srv, connection *con, const char * mem, size_t } return 0; } - + if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) { http_chunk_append_len(srv, con, len - 1); } - + chunkqueue_append_mem(cq, mem, len); - + if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) { chunkqueue_append_mem(cq, "\r\n", 2 + 1); } - + return 0; } @@ -124,9 +124,9 @@ int http_chunk_append_mem(server *srv, connection *con, const char * mem, size_t off_t http_chunkqueue_length(server *srv, connection *con) { if (!con) { log_error_write(srv, __FILE__, __LINE__, "s", "connection is NULL!!"); - + return 0; } - + return chunkqueue_length(con->write_queue); } diff --git a/src/inet_ntop_cache.c b/src/inet_ntop_cache.c index c0b3aa1..76d40f3 100644 --- a/src/inet_ntop_cache.c +++ b/src/inet_ntop_cache.c @@ -8,7 +8,7 @@ #include "sys-socket.h" const char * inet_ntop_cache_get_ip(server *srv, sock_addr *addr) { -#ifdef HAVE_IPV6 +#ifdef HAVE_IPV6 size_t ndx = 0, i; for (i = 0; i < INET_NTOP_CACHE_MAX; i++) { if (srv->inet_ntop_cache[i].ts != 0) { @@ -20,31 +20,31 @@ const char * inet_ntop_cache_get_ip(server *srv, sock_addr *addr) { srv->inet_ntop_cache[i].addr.ipv4.s_addr == addr->ipv4.sin_addr.s_addr) { /* IPv4 found in cache */ break; - + } } } - + if (i == INET_NTOP_CACHE_MAX) { /* not found in cache */ - + i = ndx; - inet_ntop(addr->plain.sa_family, - addr->plain.sa_family == AF_INET6 ? + inet_ntop(addr->plain.sa_family, + addr->plain.sa_family == AF_INET6 ? (const void *) &(addr->ipv6.sin6_addr) : (const void *) &(addr->ipv4.sin_addr), srv->inet_ntop_cache[i].b2, INET6_ADDRSTRLEN); - + srv->inet_ntop_cache[i].ts = srv->cur_ts; srv->inet_ntop_cache[i].family = addr->plain.sa_family; - + if (srv->inet_ntop_cache[i].family == AF_INET) { srv->inet_ntop_cache[i].addr.ipv4.s_addr = addr->ipv4.sin_addr.s_addr; } else if (srv->inet_ntop_cache[i].family == AF_INET6) { memcpy(srv->inet_ntop_cache[i].addr.ipv6.s6_addr, addr->ipv6.sin6_addr.s6_addr, 16); } } - + return srv->inet_ntop_cache[i].b2; #else UNUSED(srv); diff --git a/src/joblist.c b/src/joblist.c index dcab955..4ce3842 100644 --- a/src/joblist.c +++ b/src/joblist.c @@ -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 @@ int joblist_append(server *srv, connection *con) { 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 @@ void joblist_free(server *srv, connections *joblist) { 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 @@ int fdwaitqueue_append(server *srv, connection *con) { 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; } diff --git a/src/keyvalue.c b/src/keyvalue.c index 2b21d55..ae5df2f 100644 --- a/src/keyvalue.c +++ b/src/keyvalue.c @@ -87,7 +87,7 @@ static keyvalue http_status[] = { { 504, "Gateway Timeout" }, { 505, "HTTP Version Not Supported" }, { 507, "Insufficient Storage" }, /* WebDAV */ - + { -1, NULL } }; @@ -102,12 +102,12 @@ static keyvalue http_status_body[] = { { 501, "501.html" }, { 503, "503.html" }, { 505, "505.html" }, - + { -1, NULL } }; -const char *keyvalue_get_value(keyvalue *kv, int k) { +const char *keyvalue_get_value(keyvalue *kv, int k) { int i; for (i = 0; kv[i].value; i++) { if (kv[i].key == k) return kv[i].value; @@ -115,7 +115,7 @@ const char *keyvalue_get_value(keyvalue *kv, int k) { return NULL; } -int keyvalue_get_key(keyvalue *kv, const char *s) { +int keyvalue_get_key(keyvalue *kv, const char *s) { int i; for (i = 0; kv[i].value; i++) { if (0 == strcmp(kv[i].value, s)) return kv[i].key; @@ -125,9 +125,9 @@ int keyvalue_get_key(keyvalue *kv, const char *s) { keyvalue_buffer *keyvalue_buffer_init(void) { keyvalue_buffer *kvb; - + kvb = calloc(1, sizeof(*kvb)); - + return kvb; } @@ -135,49 +135,49 @@ int keyvalue_buffer_append(keyvalue_buffer *kvb, int key, const char *value) { size_t i; if (kvb->size == 0) { kvb->size = 4; - + kvb->kv = malloc(kvb->size * sizeof(*kvb->kv)); - + for(i = 0; i < kvb->size; i++) { kvb->kv[i] = calloc(1, sizeof(**kvb->kv)); } } else if (kvb->used == kvb->size) { kvb->size += 4; - + kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv)); - + for(i = kvb->used; i < kvb->size; i++) { kvb->kv[i] = calloc(1, sizeof(**kvb->kv)); } } - + kvb->kv[kvb->used]->key = key; kvb->kv[kvb->used]->value = strdup(value); - + kvb->used++; - + return 0; } void keyvalue_buffer_free(keyvalue_buffer *kvb) { size_t i; - + for (i = 0; i < kvb->size; i++) { if (kvb->kv[i]->value) free(kvb->kv[i]->value); free(kvb->kv[i]); } - + if (kvb->kv) free(kvb->kv); - + free(kvb); } s_keyvalue_buffer *s_keyvalue_buffer_init(void) { s_keyvalue_buffer *kvb; - + kvb = calloc(1, sizeof(*kvb)); - + return kvb; } @@ -186,50 +186,50 @@ int s_keyvalue_buffer_append(s_keyvalue_buffer *kvb, const char *key, const char if (kvb->size == 0) { kvb->size = 4; kvb->used = 0; - + kvb->kv = malloc(kvb->size * sizeof(*kvb->kv)); - + for(i = 0; i < kvb->size; i++) { kvb->kv[i] = calloc(1, sizeof(**kvb->kv)); } } else if (kvb->used == kvb->size) { kvb->size += 4; - + kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv)); - + for(i = kvb->used; i < kvb->size; i++) { kvb->kv[i] = calloc(1, sizeof(**kvb->kv)); } } - + kvb->kv[kvb->used]->key = key ? strdup(key) : NULL; kvb->kv[kvb->used]->value = strdup(value); - + kvb->used++; - + return 0; } void s_keyvalue_buffer_free(s_keyvalue_buffer *kvb) { size_t i; - + for (i = 0; i < kvb->size; i++) { if (kvb->kv[i]->key) free(kvb->kv[i]->key); if (kvb->kv[i]->value) free(kvb->kv[i]->value); free(kvb->kv[i]); } - + if (kvb->kv) free(kvb->kv); - + free(kvb); } httpauth_keyvalue_buffer *httpauth_keyvalue_buffer_init(void) { httpauth_keyvalue_buffer *kvb; - + kvb = calloc(1, sizeof(*kvb)); - + return kvb; } @@ -237,42 +237,42 @@ int httpauth_keyvalue_buffer_append(httpauth_keyvalue_buffer *kvb, const char *k size_t i; if (kvb->size == 0) { kvb->size = 4; - + kvb->kv = malloc(kvb->size * sizeof(*kvb->kv)); - + for(i = 0; i < kvb->size; i++) { kvb->kv[i] = calloc(1, sizeof(**kvb->kv)); } } else if (kvb->used == kvb->size) { kvb->size += 4; - + kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv)); - + for(i = kvb->used; i < kvb->size; i++) { kvb->kv[i] = calloc(1, sizeof(**kvb->kv)); } } - + kvb->kv[kvb->used]->key = strdup(key); kvb->kv[kvb->used]->realm = strdup(realm); kvb->kv[kvb->used]->type = type; - + kvb->used++; - + return 0; } void httpauth_keyvalue_buffer_free(httpauth_keyvalue_buffer *kvb) { size_t i; - + for (i = 0; i < kvb->size; i++) { if (kvb->kv[i]->key) free(kvb->kv[i]->key); if (kvb->kv[i]->realm) free(kvb->kv[i]->realm); free(kvb->kv[i]); } - + if (kvb->kv) free(kvb->kv); - + free(kvb); } @@ -306,9 +306,9 @@ http_method_t get_http_method_key(const char *s) { pcre_keyvalue_buffer *pcre_keyvalue_buffer_init(void) { pcre_keyvalue_buffer *kvb; - + kvb = calloc(1, sizeof(*kvb)); - + return kvb; } @@ -319,46 +319,46 @@ int pcre_keyvalue_buffer_append(pcre_keyvalue_buffer *kvb, const char *key, cons int erroff; pcre_keyvalue *kv; #endif - + if (!key) return -1; #ifdef HAVE_PCRE_H if (kvb->size == 0) { kvb->size = 4; kvb->used = 0; - + kvb->kv = malloc(kvb->size * sizeof(*kvb->kv)); - + for(i = 0; i < kvb->size; i++) { kvb->kv[i] = calloc(1, sizeof(**kvb->kv)); } } else if (kvb->used == kvb->size) { kvb->size += 4; - + kvb->kv = realloc(kvb->kv, kvb->size * sizeof(*kvb->kv)); - + for(i = kvb->used; i < kvb->size; i++) { kvb->kv[i] = calloc(1, sizeof(**kvb->kv)); } } - + kv = kvb->kv[kvb->used]; if (NULL == (kv->key = pcre_compile(key, 0, &errptr, &erroff, NULL))) { - + fprintf(stderr, "%s.%d: rexexp compilation error at %s\n", __FILE__, __LINE__, errptr); return -1; } - if (NULL == (kv->key_extra = pcre_study(kv->key, 0, &errptr)) && + if (NULL == (kv->key_extra = pcre_study(kv->key, 0, &errptr)) && errptr != NULL) { return -1; } - + kv->value = buffer_init_string(value); - + kvb->used++; - + return 0; #else UNUSED(kvb); @@ -380,9 +380,9 @@ void pcre_keyvalue_buffer_free(pcre_keyvalue_buffer *kvb) { if (kv->value) buffer_free(kv->value); free(kv); } - + if (kvb->kv) free(kvb->kv); #endif - + free(kvb); } diff --git a/src/keyvalue.h b/src/keyvalue.h index 5caca63..1f37837 100644 --- a/src/keyvalue.h +++ b/src/keyvalue.h @@ -9,19 +9,19 @@ # include <pcre.h> #endif -typedef enum { - HTTP_METHOD_UNSET = -1, - HTTP_METHOD_GET, - HTTP_METHOD_POST, - HTTP_METHOD_HEAD, - HTTP_METHOD_OPTIONS, +typedef enum { + HTTP_METHOD_UNSET = -1, + HTTP_METHOD_GET, + HTTP_METHOD_POST, + HTTP_METHOD_HEAD, + HTTP_METHOD_OPTIONS, HTTP_METHOD_PROPFIND, /* WebDAV */ - HTTP_METHOD_MKCOL, - HTTP_METHOD_PUT, - HTTP_METHOD_DELETE, - HTTP_METHOD_COPY, - HTTP_METHOD_MOVE, - HTTP_METHOD_PROPPATCH, + HTTP_METHOD_MKCOL, + HTTP_METHOD_PUT, + HTTP_METHOD_DELETE, + HTTP_METHOD_COPY, + HTTP_METHOD_MOVE, + HTTP_METHOD_PROPPATCH, HTTP_METHOD_REPORT, /* DeltaV */ HTTP_METHOD_CHECKOUT, HTTP_METHOD_CHECKIN, @@ -39,13 +39,13 @@ typedef enum { HTTP_VERSION_UNSET = -1, HTTP_VERSION_1_0, HTTP_VERSION_1_1 } htt typedef struct { int key; - + char *value; } keyvalue; typedef struct { char *key; - + char *value; } s_keyvalue; @@ -54,7 +54,7 @@ typedef struct { pcre *key; pcre_extra *key_extra; #endif - + buffer *value; } pcre_keyvalue; @@ -62,7 +62,7 @@ typedef enum { HTTP_AUTH_BASIC, HTTP_AUTH_DIGEST } httpauth_type; typedef struct { char *key; - + char *realm; httpauth_type type; } httpauth_keyvalue; diff --git a/src/lemon.c b/src/lemon.c index dd87cdf..5dcf144 100644 --- a/src/lemon.c +++ b/src/lemon.c @@ -579,7 +579,7 @@ int line; */ /* Find a precedence symbol of every rule in the grammar. -** +** ** Those rules which have a precedence symbol coded in the input ** grammar using the "[symbol]" construct will already have the ** rp->precsym field filled. Other rules take as their precedence @@ -869,7 +869,7 @@ struct lemon *lemp; cfp->status = INCOMPLETE; } } - + do{ progress = 0; for(i=0; i<lemp->nstate; i++){ @@ -900,7 +900,7 @@ struct lemon *lemp; struct symbol *sp; struct rule *rp; - /* Add all of the reduce actions + /* Add all of the reduce actions ** A reduce action is added for each element of the followset of ** a configuration which has its dot at the extreme right. */ @@ -1017,7 +1017,7 @@ struct symbol *errsym; /* The error symbol (if defined. NULL otherwise) */ apx->type = RD_RESOLVED; } }else{ - assert( + assert( apx->type==SH_RESOLVED || apx->type==RD_RESOLVED || apx->type==CONFLICT || @@ -1350,7 +1350,7 @@ char **argv; OptInit(argv,options,stderr); if( version ){ printf("Lemon version 1.0\n"); - exit(0); + exit(0); } if( OptNArgs() < 1 ){ fprintf(stderr,"Exactly one filename argument is required.\n"); @@ -2031,7 +2031,7 @@ to follow the previous rule."); case IN_RHS: if( x[0]=='.' ){ struct rule *rp; - rp = (struct rule *)malloc( sizeof(struct rule) + + rp = (struct rule *)malloc( sizeof(struct rule) + sizeof(struct symbol*)*psp->nrhs + sizeof(char*)*psp->nrhs ); if( rp==0 ){ ErrorMsg(psp->filename,psp->tokenlineno, @@ -2546,7 +2546,7 @@ char *mode; return fp; } -/* Duplicate the input file without comments and without actions +/* Duplicate the input file without comments and without actions ** on rules */ void Reprint(lemp) struct lemon *lemp; @@ -2822,7 +2822,7 @@ int *lineno; PRIVATE FILE *tplt_open(lemp) struct lemon *lemp; { - + char buf[1000]; FILE *in; char *tpltname; @@ -2930,7 +2930,7 @@ struct lemon *lemp; return ret; } -/* +/* ** Generate code which executes when the rule "rp" is reduced. Write ** the code to "out". Make sure lineno stays up-to-date. */ @@ -3384,7 +3384,7 @@ int mhflag; /* Output in makeheaders format if true */ /* Output the yy_shift_ofst[] table */ fprintf(out, "#define YY_SHIFT_USE_DFLT (%d)\n", mnTknOfst-1); lineno++; - fprintf(out, "static %s yy_shift_ofst[] = {\n", + fprintf(out, "static %s yy_shift_ofst[] = {\n", minimum_size_type(mnTknOfst-1, mxTknOfst)); lineno++; n = lemp->nstate; for(i=j=0; i<n; i++){ @@ -3405,7 +3405,7 @@ int mhflag; /* Output in makeheaders format if true */ /* Output the yy_reduce_ofst[] table */ fprintf(out, "#define YY_REDUCE_USE_DFLT (%d)\n", mnNtOfst-1); lineno++; - fprintf(out, "static %s yy_reduce_ofst[] = {\n", + fprintf(out, "static %s yy_reduce_ofst[] = {\n", minimum_size_type(mnNtOfst-1, mxNtOfst)); lineno++; n = lemp->nstate; for(i=j=0; i<n; i++){ @@ -3480,7 +3480,7 @@ int mhflag; /* Output in makeheaders format if true */ tplt_xfer(lemp->name,in,out,&lineno); /* Generate code which executes every time a symbol is popped from - ** the stack while processing errors or while destroying the parser. + ** the stack while processing errors or while destroying the parser. ** (In other words, generate the %destructor actions) */ if( lemp->tokendest ){ @@ -3522,7 +3522,7 @@ int mhflag; /* Output in makeheaders format if true */ tplt_print(out,lemp,lemp->overflow,lemp->overflowln,&lineno); tplt_xfer(lemp->name,in,out,&lineno); - /* Generate the table of rule information + /* Generate the table of rule information ** ** Note: This code depends on the fact that rules are number ** sequentually beginning with 0. @@ -3589,7 +3589,7 @@ struct lemon *lemp; for(i=1; i<lemp->nterminal; i++){ fprintf(out,"#define %s%-30s %2d\n",prefix,lemp->symbols[i]->name,i); } - fclose(out); + fclose(out); } return; } @@ -3630,7 +3630,7 @@ struct lemon *lemp; rbest = rp; } } - + /* Do not make a default if the number of rules to default ** is not at least 2 */ if( nbest<2 ) continue; @@ -3781,7 +3781,7 @@ void Strsafe_init(){ if( x1a ){ x1a->size = 1024; x1a->count = 0; - x1a->tbl = (x1node*)malloc( + x1a->tbl = (x1node*)malloc( (sizeof(x1node) + sizeof(x1node*))*1024 ); if( x1a->tbl==0 ){ free(x1a); @@ -3943,7 +3943,7 @@ void Symbol_init(){ if( x2a ){ x2a->size = 128; x2a->count = 0; - x2a->tbl = (x2node*)malloc( + x2a->tbl = (x2node*)malloc( (sizeof(x2node) + sizeof(x2node*))*128 ); if( x2a->tbl==0 ){ free(x2a); @@ -4149,7 +4149,7 @@ void State_init(){ if( x3a ){ x3a->size = 128; x3a->count = 0; - x3a->tbl = (x3node*)malloc( + x3a->tbl = (x3node*)malloc( (sizeof(x3node) + sizeof(x3node*))*128 ); if( x3a->tbl==0 ){ free(x3a); @@ -4295,7 +4295,7 @@ void Configtable_init(){ if( x4a ){ x4a->size = 64; x4a->count = 0; - x4a->tbl = (x4node*)malloc( + x4a->tbl = (x4node*)malloc( (sizeof(x4node) + sizeof(x4node*))*64 ); if( x4a->tbl==0 ){ free(x4a); diff --git a/src/lempar.c b/src/lempar.c index ee1edbf..9ab9075 100644 --- a/src/lempar.c +++ b/src/lempar.c @@ -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 @@ static char *yyTracePrompt = 0; #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: ** <ul> @@ -191,7 +191,7 @@ void ParseTrace(FILE *TraceFILE, char *zTracePrompt){ #ifndef NDEBUG /* For tracing shifts, the names of all terminals and nonterminals ** are required. The following table supplies these names */ -static const char *yyTokenName[] = { +static const char *yyTokenName[] = { %% }; #endif /* NDEBUG */ @@ -220,7 +220,7 @@ const char *ParseTokenName(int tokenType){ #endif } -/* +/* ** This function allocates a new parser. ** The only argument is a pointer to a function which works like ** malloc. @@ -251,7 +251,7 @@ static void yy_destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor){ /* Here is inserted the actions which take place when a ** terminal or non-terminal is destroyed. This can happen ** when the symbol is popped from the stack during a - ** reduce or during error processing or when a parser is + ** reduce or during error processing or when a parser is ** being destroyed before it is finished parsing. ** ** Note: during a reduce, the only symbols destroyed are those @@ -289,7 +289,7 @@ static int yy_pop_parser_stack(yyParser *pParser){ return yymajor; } -/* +/* ** Deallocate and destroy a parser. Destructors are all called for ** all stack elements before shutting the parser down. ** @@ -325,7 +325,7 @@ static int yy_find_shift_action( ){ int i; int stateno = pParser->yystack[pParser->yyidx].stateno; - + /* if( pParser->yyidx<0 ) return YY_NO_ACTION; */ i = yy_shift_ofst[stateno]; if( i==YY_SHIFT_USE_DFLT ){ @@ -369,7 +369,7 @@ static int yy_find_reduce_action( ){ int i; int stateno = pParser->yystack[pParser->yyidx].stateno; - + i = yy_reduce_ofst[stateno]; if( i==YY_REDUCE_USE_DFLT ){ return yy_default[stateno]; @@ -455,7 +455,7 @@ static void yy_reduce( ParseARG_FETCH; yymsp = &yypParser->yystack[yypParser->yyidx]; #ifndef NDEBUG - if( yyTraceFILE && yyruleno>=0 + if( yyTraceFILE && yyruleno>=0 && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){ fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt, yyRuleName[yyruleno]); @@ -608,7 +608,7 @@ void Parse( #ifdef YYERRORSYMBOL /* A syntax error has occurred. ** The response to an error depends upon whether or not the - ** grammar defines an error token "ERROR". + ** grammar defines an error token "ERROR". ** ** This is what we do if the grammar does define ERROR: ** @@ -31,38 +31,38 @@ # define O_LARGEFILE 0 #endif -/** +/** * open the errorlog - * + * * we have 3 possibilities: * - stderr (default) - * - syslog + * - syslog * - logfile - * + * * if the open failed, report to the user and die - * + * */ int log_error_open(server *srv) { int fd; int close_stderr = 1; - + #ifdef HAVE_SYSLOG_H /* perhaps someone wants to use syslog() */ openlog("lighttpd", LOG_CONS | LOG_PID, LOG_DAEMON); #endif srv->errorlog_mode = ERRORLOG_STDERR; - + if (srv->srvconf.errorlog_use_syslog) { srv->errorlog_mode = ERRORLOG_SYSLOG; } else if (!buffer_is_empty(srv->srvconf.errorlog_file)) { const char *logfile = srv->srvconf.errorlog_file->ptr; - + if (-1 == (srv->errorlog_fd = open(logfile, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) { - log_error_write(srv, __FILE__, __LINE__, "SSSS", + log_error_write(srv, __FILE__, __LINE__, "SSSS", "opening errorlog '", logfile, "' failed: ", strerror(errno)); - + return -1; } #ifdef FD_CLOEXEC @@ -71,15 +71,15 @@ int log_error_open(server *srv) { #endif srv->errorlog_mode = ERRORLOG_FILE; } - + log_error_write(srv, __FILE__, __LINE__, "s", "server started"); - + #ifdef HAVE_VALGRIND_VALGRIND_H /* don't close stderr for debugging purposes if run in valgrind */ if (RUNNING_ON_VALGRIND) close_stderr = 0; #endif if (srv->errorlog_mode == ERRORLOG_STDERR) close_stderr = 0; - + /* move stderr to /dev/null */ if (close_stderr && -1 != (fd = open("/dev/null", O_WRONLY))) { @@ -90,33 +90,33 @@ int log_error_open(server *srv) { return 0; } -/** +/** * open the errorlog - * + * * if the open failed, report to the user and die * if no filename is given, use syslog instead - * + * */ int log_error_cycle(server *srv) { /* only cycle if we are not in syslog-mode */ - + if (srv->errorlog_mode == ERRORLOG_FILE) { const char *logfile = srv->srvconf.errorlog_file->ptr; /* already check of opening time */ - + int new_fd; - + if (-1 == (new_fd = open(logfile, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) { /* write to old log */ - log_error_write(srv, __FILE__, __LINE__, "SSSSS", + log_error_write(srv, __FILE__, __LINE__, "SSSSS", "cycling errorlog '", logfile, "' failed: ", strerror(errno), ", falling back to syslog()"); - + close(srv->errorlog_fd); srv->errorlog_fd = -1; -#ifdef HAVE_SYSLOG_H +#ifdef HAVE_SYSLOG_H srv->errorlog_mode = ERRORLOG_SYSLOG; #endif } else { @@ -125,15 +125,15 @@ int log_error_cycle(server *srv) { srv->errorlog_fd = new_fd; } } - + log_error_write(srv, __FILE__, __LINE__, "s", "logfiles cycled"); - + return 0; } int log_error_close(server *srv) { log_error_write(srv, __FILE__, __LINE__, "s", "server stopped"); - + switch(srv->errorlog_mode) { case ERRORLOG_FILE: close(srv->errorlog_fd); @@ -146,13 +146,13 @@ int log_error_close(server *srv) { case ERRORLOG_STDERR: break; } - + return 0; } int log_error_write(server *srv, const char *filename, unsigned int line, const char *fmt, ...) { va_list ap; - + switch(srv->errorlog_mode) { case ERRORLOG_FILE: case ERRORLOG_STDERR: @@ -161,7 +161,7 @@ int log_error_write(server *srv, const char *filename, unsigned int line, const buffer_prepare_copy(srv->ts_debug_str, 255); strftime(srv->ts_debug_str->ptr, srv->ts_debug_str->size - 1, "%Y-%m-%d %H:%M:%S", localtime(&(srv->cur_ts))); srv->ts_debug_str->used = strlen(srv->ts_debug_str->ptr) + 1; - + srv->last_generated_debug_ts = srv->cur_ts; } @@ -173,19 +173,19 @@ int log_error_write(server *srv, const char *filename, unsigned int line, const BUFFER_COPY_STRING_CONST(srv->errorlog_buf, "("); break; } - + buffer_append_string(srv->errorlog_buf, filename); BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, "."); buffer_append_long(srv->errorlog_buf, line); BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, ") "); - - + + for(va_start(ap, fmt); *fmt; fmt++) { int d; char *s; buffer *b; off_t o; - + switch(*fmt) { case 's': /* string */ s = va_arg(ap, char *); @@ -227,7 +227,7 @@ int log_error_write(server *srv, const char *filename, unsigned int line, const break; case '(': case ')': - case '<': + case '<': case '>': case ',': case ' ': @@ -236,7 +236,7 @@ int log_error_write(server *srv, const char *filename, unsigned int line, const } } va_end(ap); - + switch(srv->errorlog_mode) { case ERRORLOG_FILE: BUFFER_APPEND_STRING_CONST(srv->errorlog_buf, "\n"); @@ -250,7 +250,7 @@ int log_error_write(server *srv, const char *filename, unsigned int line, const syslog(LOG_ERR, "%s", srv->errorlog_buf->ptr); break; } - + return 0; } @@ -9,5 +9,5 @@ int log_error_open(server *srv); int log_error_close(server *srv); int log_error_write(server *srv, const char *filename, unsigned int line, const char *fmt, ...); int log_error_cycle(server *srv); - + #endif diff --git a/src/mod_access.c b/src/mod_access.c index f3f7071..3fc0599 100644 --- a/src/mod_access.c +++ b/src/mod_access.c @@ -14,70 +14,70 @@ typedef struct { typedef struct { PLUGIN_DATA; - + plugin_config **config_storage; - - plugin_config conf; + + plugin_config conf; } plugin_data; INIT_FUNC(mod_access_init) { plugin_data *p; - + p = calloc(1, sizeof(*p)); - + return p; } FREE_FUNC(mod_access_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]; - + array_free(s->access_deny); - + free(s); } free(p->config_storage); } - + free(p); - + return HANDLER_GO_ON; } SETDEFAULTS_FUNC(mod_access_set_defaults) { plugin_data *p = p_d; size_t i = 0; - - config_values_t cv[] = { + + config_values_t cv[] = { { "url.access-deny", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } }; - + 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->access_deny = array_init(); - + cv[0].destination = s->access_deny; - + 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; } @@ -88,25 +88,25 @@ static int mod_access_patch_connection(server *srv, connection *con, plugin_data plugin_config *s = p->config_storage[0]; PATCH(access_deny); - + /* 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("url.access-deny"))) { PATCH(access_deny); } } } - + return 0; } #undef PATCH @@ -115,19 +115,19 @@ URIHANDLER_FUNC(mod_access_uri_handler) { plugin_data *p = p_d; int s_len; size_t k; - + if (con->uri.path->used == 0) return HANDLER_GO_ON; - + mod_access_patch_connection(srv, con, p); - + s_len = con->uri.path->used - 1; - + for (k = 0; k < p->conf.access_deny->used; k++) { data_string *ds = (data_string *)p->conf.access_deny->data[k]; int ct_len = ds->value->used - 1; - + if (ct_len > s_len) continue; - + if (ds->value->used == 0) continue; /* if we have a case-insensitive FS we have to lower-case the URI here too */ @@ -135,18 +135,18 @@ URIHANDLER_FUNC(mod_access_uri_handler) { if (con->conf.force_lowercase_filenames) { if (0 == strncasecmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) { con->http_status = 403; - + return HANDLER_FINISHED; } } else { if (0 == strncmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) { con->http_status = 403; - + return HANDLER_FINISHED; } } } - + /* not found */ return HANDLER_GO_ON; } @@ -155,13 +155,13 @@ URIHANDLER_FUNC(mod_access_uri_handler) { int mod_access_plugin_init(plugin *p) { p->version = LIGHTTPD_VERSION_ID; p->name = buffer_init_string("access"); - + p->init = mod_access_init; p->set_defaults = mod_access_set_defaults; p->handle_uri_clean = mod_access_uri_handler; p->cleanup = mod_access_free; - + p->data = NULL; - + return 0; } diff --git a/src/mod_accesslog.c b/src/mod_accesslog.c index bdd0dbc..b00cf06 100644 --- a/src/mod_accesslog.c +++ b/src/mod_accesslog.c @@ -29,7 +29,7 @@ typedef struct { char key; - enum { + enum { FORMAT_UNSET, FORMAT_UNSUPPORTED, FORMAT_PERCENT, @@ -41,7 +41,7 @@ typedef struct { FORMAT_STATUS, FORMAT_BYTES_OUT_NO_HEADER, FORMAT_HEADER, - + FORMAT_REMOTE_ADDR, FORMAT_LOCAL_ADDR, FORMAT_COOKIE, @@ -59,20 +59,20 @@ typedef struct { FORMAT_CONNECTION_STATUS, FORMAT_BYTES_IN, FORMAT_BYTES_OUT, - + FORMAT_RESPONSE_HEADER } type; } format_mapping; /** - * - * + * + * * "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" - * + * */ -const format_mapping fmap[] = -{ +const format_mapping fmap[] = +{ { '%', FORMAT_PERCENT }, { 'h', FORMAT_REMOTE_HOST }, { 'l', FORMAT_REMOTE_IDENT }, @@ -82,7 +82,7 @@ const format_mapping fmap[] = { 's', FORMAT_STATUS }, { 'b', FORMAT_BYTES_OUT_NO_HEADER }, { 'i', FORMAT_HEADER }, - + { 'a', FORMAT_REMOTE_ADDR }, { 'A', FORMAT_LOCAL_ADDR }, { 'B', FORMAT_BYTES_OUT_NO_HEADER }, @@ -103,23 +103,23 @@ const format_mapping fmap[] = { 'X', FORMAT_CONNECTION_STATUS }, { 'I', FORMAT_BYTES_IN }, { 'O', FORMAT_BYTES_OUT }, - + { 'o', FORMAT_RESPONSE_HEADER }, - + { '\0', FORMAT_UNSET } }; typedef struct { enum { FIELD_UNSET, FIELD_STRING, FIELD_FORMAT } type; - + buffer *string; int field; } format_field; typedef struct { format_field **ptr; - + size_t used; size_t size; } format_fields; @@ -128,39 +128,39 @@ typedef struct { buffer *access_logfile; buffer *format; unsigned short use_syslog; - - + + int log_access_fd; time_t last_generated_accesslog_ts; time_t *last_generated_accesslog_ts_ptr; - - + + buffer *access_logbuffer; buffer *ts_accesslog_str; - + format_fields *parsed_format; } plugin_config; typedef struct { PLUGIN_DATA; - + plugin_config **config_storage; - plugin_config conf; + plugin_config conf; } plugin_data; INIT_FUNC(mod_accesslog_init) { plugin_data *p; - + p = calloc(1, sizeof(*p)); - + return p; } int accesslog_parse_format(server *srv, format_fields *fields, buffer *format) { size_t i, j, k = 0, start = 0; - + for (i = 0; i < format->used - 1; i++) { - + switch(format->ptr[i]) { case '%': if (start != i) { @@ -173,19 +173,19 @@ int accesslog_parse_format(server *srv, format_fields *fields, buffer *format) { fields->size += 16; fields->ptr = realloc(fields->ptr, fields->size * sizeof(format_fields * )); } - + fields->ptr[fields->used] = malloc(sizeof(format_fields)); fields->ptr[fields->used]->type = FIELD_STRING; fields->ptr[fields->used]->string = buffer_init(); - + buffer_copy_string_len(fields->ptr[fields->used]->string, format->ptr + start, i - start); - + fields->used++; } - - + + /* we need a new field */ - + if (fields->size == 0) { fields->size = 16; fields->used = 0; @@ -194,43 +194,43 @@ int accesslog_parse_format(server *srv, format_fields *fields, buffer *format) { fields->size += 16; fields->ptr = realloc(fields->ptr, fields->size * sizeof(format_fields * )); } - + /* search for the terminating command */ switch (format->ptr[i+1]) { case '>': case '<': /* only for s */ - + for (j = 0; fmap[j].key != '\0'; j++) { if (fmap[j].key != format->ptr[i+2]) continue; - + /* found key */ - + fields->ptr[fields->used] = malloc(sizeof(format_fields)); fields->ptr[fields->used]->type = FIELD_FORMAT; fields->ptr[fields->used]->field = fmap[j].type; fields->ptr[fields->used]->string = NULL; - + fields->used++; - + break; } - + if (fmap[j].key == '\0') { log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed"); return -1; } - + start = i + 3; - + break; case '{': /* go forward to } */ - + for (k = i+2; k < format->used - 1; k++) { if (format->ptr[k] == '}') break; } - + if (k == format->used - 1) { log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed"); return -1; @@ -239,62 +239,62 @@ int accesslog_parse_format(server *srv, format_fields *fields, buffer *format) { log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed"); return -1; } - + for (j = 0; fmap[j].key != '\0'; j++) { if (fmap[j].key != format->ptr[k+1]) continue; - + /* found key */ - + fields->ptr[fields->used] = malloc(sizeof(format_fields)); fields->ptr[fields->used]->type = FIELD_FORMAT; fields->ptr[fields->used]->field = fmap[j].type; fields->ptr[fields->used]->string = buffer_init(); - + buffer_copy_string_len(fields->ptr[fields->used]->string, format->ptr + i + 2, k - (i + 2)); - + fields->used++; - + break; } - + if (fmap[j].key == '\0') { log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed"); return -1; } - + start = k + 2; - + break; default: for (j = 0; fmap[j].key != '\0'; j++) { if (fmap[j].key != format->ptr[i+1]) continue; - + /* found key */ - + fields->ptr[fields->used] = malloc(sizeof(format_fields)); fields->ptr[fields->used]->type = FIELD_FORMAT; fields->ptr[fields->used]->field = fmap[j].type; fields->ptr[fields->used]->string = NULL; - + fields->used++; - + break; } - + if (fmap[j].key == '\0') { log_error_write(srv, __FILE__, __LINE__, "ss", "config: ", "failed"); return -1; } - + start = i + 2; - + break; } - + break; } } - + if (start < i) { /* copy the string */ if (fields->size == 0) { @@ -305,32 +305,32 @@ int accesslog_parse_format(server *srv, format_fields *fields, buffer *format) { fields->size += 16; fields->ptr = realloc(fields->ptr, fields->size * sizeof(format_fields * )); } - + fields->ptr[fields->used] = malloc(sizeof(format_fields)); fields->ptr[fields->used]->type = FIELD_STRING; fields->ptr[fields->used]->string = buffer_init(); - + buffer_copy_string_len(fields->ptr[fields->used]->string, format->ptr + start, i - start); - + fields->used++; } - + return 0; } FREE_FUNC(mod_accesslog_free) { plugin_data *p = p_d; size_t i; - + if (!p) return HANDLER_GO_ON; - + if (p->config_storage) { - + for (i = 0; i < srv->config_context->used; i++) { plugin_config *s = p->config_storage[i]; if (!s) continue; - + if (s->access_logbuffer->used) { if (s->use_syslog) { # ifdef HAVE_SYSLOG_H @@ -342,14 +342,14 @@ FREE_FUNC(mod_accesslog_free) { write(s->log_access_fd, s->access_logbuffer->ptr, s->access_logbuffer->used - 1); } } - + if (s->log_access_fd != -1) close(s->log_access_fd); - + buffer_free(s->ts_accesslog_str); buffer_free(s->access_logbuffer); buffer_free(s->format); buffer_free(s->access_logfile); - + if (s->parsed_format) { size_t j; for (j = 0; j < s->parsed_format->used; j++) { @@ -359,36 +359,36 @@ FREE_FUNC(mod_accesslog_free) { free(s->parsed_format->ptr); free(s->parsed_format); } - + free(s); } - + free(p->config_storage); } - + free(p); - + return HANDLER_GO_ON; } SETDEFAULTS_FUNC(log_access_open) { plugin_data *p = p_d; size_t i = 0; - - config_values_t cv[] = { + + config_values_t cv[] = { { "accesslog.filename", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, { "accesslog.use-syslog", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, { "accesslog.format", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, { 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->access_logfile = buffer_init(); s->format = buffer_init(); @@ -397,44 +397,44 @@ SETDEFAULTS_FUNC(log_access_open) { s->log_access_fd = -1; s->last_generated_accesslog_ts = 0; s->last_generated_accesslog_ts_ptr = &(s->last_generated_accesslog_ts); - - + + cv[0].destination = s->access_logfile; cv[1].destination = &(s->use_syslog); cv[2].destination = s->format; - + 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 (i == 0 && buffer_is_empty(s->format)) { /* set a default logfile string */ - + buffer_copy_string(s->format, "%h %V %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\""); } - + /* parse */ - + if (s->format->used) { s->parsed_format = calloc(1, sizeof(*(s->parsed_format))); - + if (-1 == accesslog_parse_format(srv, s->parsed_format, s->format)) { - log_error_write(srv, __FILE__, __LINE__, "sb", + log_error_write(srv, __FILE__, __LINE__, "sb", "parsing accesslog-definition failed:", s->format); return HANDLER_ERROR; } #if 0 - /* debugging */ + /* debugging */ for (j = 0; j < s->parsed_format->used; j++) { switch (s->parsed_format->ptr[j]->type) { case FIELD_FORMAT: - log_error_write(srv, __FILE__, __LINE__, "ssds", + log_error_write(srv, __FILE__, __LINE__, "ssds", "config:", "format", s->parsed_format->ptr[j]->field, - s->parsed_format->ptr[j]->string ? + s->parsed_format->ptr[j]->string ? s->parsed_format->ptr[j]->string->ptr : "" ); break; case FIELD_STRING: @@ -446,52 +446,52 @@ SETDEFAULTS_FUNC(log_access_open) { } #endif } - + if (s->use_syslog) { /* ignore the next checks */ continue; } - + if (buffer_is_empty(s->access_logfile)) continue; - + if (s->access_logfile->ptr[0] == '|') { #ifdef HAVE_FORK /* create write pipe and spawn process */ - + int to_log_fds[2]; pid_t pid; - + if (pipe(to_log_fds)) { log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed: ", strerror(errno)); return HANDLER_ERROR; } - + /* fork, execve */ switch (pid = fork()) { - case 0: + case 0: /* child */ - + close(STDIN_FILENO); dup2(to_log_fds[0], STDIN_FILENO); close(to_log_fds[0]); /* not needed */ close(to_log_fds[1]); - + /* we don't need the client socket */ for (i = 3; i < 256; i++) { close(i); } - - /* exec the log-process (skip the | ) - * + + /* exec the log-process (skip the | ) + * */ - + execl("/bin/sh", "sh", "-c", s->access_logfile->ptr + 1, NULL); - log_error_write(srv, __FILE__, __LINE__, "sss", - "spawning log-process failed: ", strerror(errno), + log_error_write(srv, __FILE__, __LINE__, "sss", + "spawning log-process failed: ", strerror(errno), s->access_logfile->ptr + 1); - + exit(-1); break; case -1: @@ -500,27 +500,27 @@ SETDEFAULTS_FUNC(log_access_open) { break; default: close(to_log_fds[0]); - + s->log_access_fd = to_log_fds[1]; - + break; } #else return -1; #endif - } else if (-1 == (s->log_access_fd = + } else if (-1 == (s->log_access_fd = open(s->access_logfile->ptr, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) { - - log_error_write(srv, __FILE__, __LINE__, "ssb", - "opening access-log failed:", + + log_error_write(srv, __FILE__, __LINE__, "ssb", + "opening access-log failed:", strerror(errno), s->access_logfile); - + return HANDLER_ERROR; } fcntl(s->log_access_fd, F_SETFD, FD_CLOEXEC); - + } - + return HANDLER_GO_ON; } @@ -529,7 +529,7 @@ SIGHUP_FUNC(log_access_cycle) { size_t i; if (!p->config_storage) return HANDLER_GO_ON; - + for (i = 0; i < srv->config_context->used; i++) { plugin_config *s = p->config_storage[i]; @@ -544,26 +544,26 @@ SIGHUP_FUNC(log_access_cycle) { } else if (s->log_access_fd != -1) { write(s->log_access_fd, s->access_logbuffer->ptr, s->access_logbuffer->used - 1); } - + buffer_reset(s->access_logbuffer); } - + if (s->use_syslog == 0 && !buffer_is_empty(s->access_logfile) && s->access_logfile->ptr[0] != '|') { - + close(s->log_access_fd); - - if (-1 == (s->log_access_fd = + + if (-1 == (s->log_access_fd = open(s->access_logfile->ptr, O_APPEND | O_WRONLY | O_CREAT | O_LARGEFILE, 0644))) { - + log_error_write(srv, __FILE__, __LINE__, "ss", "cycling access-log failed:", strerror(errno)); - + return HANDLER_ERROR; } } } - + return HANDLER_GO_ON; } @@ -572,7 +572,7 @@ SIGHUP_FUNC(log_access_cycle) { static int mod_accesslog_patch_connection(server *srv, connection *con, plugin_data *p) { size_t i, j; plugin_config *s = p->config_storage[0]; - + PATCH(access_logfile); PATCH(format); PATCH(log_access_fd); @@ -581,19 +581,19 @@ static int mod_accesslog_patch_connection(server *srv, connection *con, plugin_d PATCH(ts_accesslog_str); PATCH(parsed_format); PATCH(use_syslog); - + /* 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("accesslog.filename"))) { PATCH(access_logfile); PATCH(log_access_fd); @@ -608,7 +608,7 @@ static int mod_accesslog_patch_connection(server *srv, connection *con, plugin_d } } } - + return 0; } #undef PATCH @@ -617,17 +617,17 @@ REQUESTDONE_FUNC(log_access_write) { plugin_data *p = p_d; buffer *b; size_t j; - + int newts = 0; data_string *ds; - + mod_accesslog_patch_connection(srv, con, p); - + b = p->conf.access_logbuffer; if (b->used == 0) { buffer_copy_string(b, ""); } - + for (j = 0; j < p->conf.parsed_format->used; j++) { switch(p->conf.parsed_format->ptr[j]->type) { case FIELD_STRING: @@ -636,14 +636,14 @@ REQUESTDONE_FUNC(log_access_write) { case FIELD_FORMAT: switch(p->conf.parsed_format->ptr[j]->field) { case FORMAT_TIMESTAMP: - + /* cache the generated timestamp */ if (srv->cur_ts != *(p->conf.last_generated_accesslog_ts_ptr)) { struct tm tm; #if defined(HAVE_STRUCT_TM_GMTOFF) long scd, hrs, min; #endif - + buffer_prepare_copy(p->conf.ts_accesslog_str, 255); #if defined(HAVE_STRUCT_TM_GMTOFF) # ifdef HAVE_LOCALTIME_R @@ -653,17 +653,17 @@ REQUESTDONE_FUNC(log_access_write) { strftime(p->conf.ts_accesslog_str->ptr, p->conf.ts_accesslog_str->size - 1, "[%d/%b/%Y:%H:%M:%S ", localtime_r(&(srv->cur_ts))); # endif p->conf.ts_accesslog_str->used = strlen(p->conf.ts_accesslog_str->ptr) + 1; - + buffer_append_string(p->conf.ts_accesslog_str, tm.tm_gmtoff >= 0 ? "+" : "-"); - + scd = abs(tm.tm_gmtoff); hrs = scd / 3600; min = (scd % 3600) / 60; - + /* hours */ if (hrs < 10) buffer_append_string(p->conf.ts_accesslog_str, "0"); buffer_append_long(p->conf.ts_accesslog_str, hrs); - + if (min < 10) buffer_append_string(p->conf.ts_accesslog_str, "0"); buffer_append_long(p->conf.ts_accesslog_str, min); BUFFER_APPEND_STRING_CONST(p->conf.ts_accesslog_str, "]"); @@ -676,20 +676,20 @@ REQUESTDONE_FUNC(log_access_write) { #endif p->conf.ts_accesslog_str->used = strlen(p->conf.ts_accesslog_str->ptr) + 1; #endif - + *(p->conf.last_generated_accesslog_ts_ptr) = srv->cur_ts; newts = 1; } - + buffer_append_string_buffer(b, p->conf.ts_accesslog_str); - + break; case FORMAT_REMOTE_HOST: - + /* handle inet_ntop cache */ - + buffer_append_string(b, inet_ntop_cache_get_ip(srv, &(con->dst_addr))); - + break; case FORMAT_REMOTE_IDENT: /* ident */ @@ -710,10 +710,10 @@ REQUESTDONE_FUNC(log_access_write) { case FORMAT_STATUS: buffer_append_long(b, con->http_status); break; - + case FORMAT_BYTES_OUT_NO_HEADER: if (con->bytes_written > 0) { - buffer_append_off_t(b, + buffer_append_off_t(b, con->bytes_written - con->bytes_header <= 0 ? 0 : con->bytes_written - con->bytes_header); } else { BUFFER_APPEND_STRING_CONST(b, "-"); @@ -772,7 +772,7 @@ REQUESTDONE_FUNC(log_access_write) { } break; case FORMAT_REQUEST_PROTOCOL: - buffer_append_string(b, + buffer_append_string(b, con->request.http_version == HTTP_VERSION_1_1 ? "HTTP/1.1" : "HTTP/1.0"); break; case FORMAT_REQUEST_METHOD: @@ -801,7 +801,7 @@ REQUESTDONE_FUNC(log_access_write) { { 'D', FORMAT_TIME_USED_MS }, { 'e', FORMAT_ENV }, */ - + break; } break; @@ -809,7 +809,7 @@ REQUESTDONE_FUNC(log_access_write) { break; } } - + BUFFER_APPEND_STRING_CONST(b, "\n"); if (p->conf.use_syslog || /* syslog doesn't cache */ @@ -828,7 +828,7 @@ REQUESTDONE_FUNC(log_access_write) { } buffer_reset(b); } - + return HANDLER_GO_ON; } @@ -836,15 +836,15 @@ REQUESTDONE_FUNC(log_access_write) { int mod_accesslog_plugin_init(plugin *p) { p->version = LIGHTTPD_VERSION_ID; p->name = buffer_init_string("accesslog"); - + p->init = mod_accesslog_init; p->set_defaults= log_access_open; p->cleanup = mod_accesslog_free; - + p->handle_request_done = log_access_write; p->handle_sighup = log_access_cycle; - + p->data = NULL; - + return 0; } diff --git a/src/mod_alias.c b/src/mod_alias.c index f56afeb..43b11c2 100644 --- a/src/mod_alias.c +++ b/src/mod_alias.c @@ -16,44 +16,44 @@ typedef struct { typedef struct { PLUGIN_DATA; - + plugin_config **config_storage; - - plugin_config conf; + + plugin_config conf; } plugin_data; /* init the plugin data */ INIT_FUNC(mod_alias_init) { plugin_data *p; - + p = calloc(1, sizeof(*p)); - - - + + + return p; } /* detroy the plugin data */ FREE_FUNC(mod_alias_free) { plugin_data *p = p_d; - + 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]; - + array_free(s->alias); - + free(s); } free(p->config_storage); } - + free(p); - + return HANDLER_GO_ON; } @@ -62,25 +62,25 @@ FREE_FUNC(mod_alias_free) { SETDEFAULTS_FUNC(mod_alias_set_defaults) { plugin_data *p = p_d; size_t i = 0; - - config_values_t cv[] = { + + config_values_t cv[] = { { "alias.url", 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)); - s->alias = array_init(); + s->alias = array_init(); cv[0].destination = s->alias; - + p->config_storage[i] = s; - + if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) { return HANDLER_ERROR; } @@ -110,7 +110,7 @@ SETDEFAULTS_FUNC(mod_alias_set_defaults) { } } } - + return HANDLER_GO_ON; } @@ -119,27 +119,27 @@ SETDEFAULTS_FUNC(mod_alias_set_defaults) { static int mod_alias_patch_connection(server *srv, connection *con, plugin_data *p) { size_t i, j; plugin_config *s = p->config_storage[0]; - + PATCH(alias); - + /* 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("alias.url"))) { PATCH(alias); } } } - + return 0; } #undef PATCH @@ -149,37 +149,37 @@ PHYSICALPATH_FUNC(mod_alias_physical_handler) { int uri_len, basedir_len; char *uri_ptr; size_t k; - + if (con->physical.path->used == 0) return HANDLER_GO_ON; - + mod_alias_patch_connection(srv, con, p); - + /* not to include the tailing slash */ basedir_len = (con->physical.basedir->used - 1) - 1; uri_len = con->physical.path->used - 1 - basedir_len; uri_ptr = con->physical.path->ptr + basedir_len; - + for (k = 0; k < p->conf.alias->used; k++) { data_string *ds = (data_string *)p->conf.alias->data[k]; int alias_len = ds->key->used - 1; - + if (alias_len > uri_len) continue; if (ds->key->used == 0) continue; - + if (0 == (con->conf.force_lowercase_filenames ? strncasecmp(uri_ptr, ds->key->ptr, alias_len) : strncmp(uri_ptr, ds->key->ptr, alias_len))) { /* matched */ - + buffer_copy_string_buffer(con->physical.basedir, ds->value); buffer_copy_string_buffer(srv->tmp_buf, ds->value); buffer_append_string(srv->tmp_buf, uri_ptr + alias_len); buffer_copy_string_buffer(con->physical.path, srv->tmp_buf); - + return HANDLER_GO_ON; } } - + /* not found */ return HANDLER_GO_ON; } @@ -189,13 +189,13 @@ PHYSICALPATH_FUNC(mod_alias_physical_handler) { int mod_alias_plugin_init(plugin *p) { p->version = LIGHTTPD_VERSION_ID; p->name = buffer_init_string("alias"); - + p->init = mod_alias_init; p->handle_physical= mod_alias_physical_handler; p->set_defaults = mod_alias_set_defaults; p->cleanup = mod_alias_free; - + p->data = NULL; - + return 0; } diff --git a/src/mod_auth.c b/src/mod_auth.c index b075a2b..d7e8276 100644 --- a/src/mod_auth.c +++ b/src/mod_auth.c @@ -17,79 +17,79 @@ handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s); /** * the basic and digest auth framework - * + * * - config handling * - protocol handling - * - * http_auth.c - * http_auth_digest.c - * + * + * http_auth.c + * http_auth_digest.c + * * do the real work */ INIT_FUNC(mod_auth_init) { mod_auth_plugin_data *p; - + p = calloc(1, sizeof(*p)); - + p->tmp_buf = buffer_init(); - + p->auth_user = buffer_init(); #ifdef USE_LDAP p->ldap_filter = buffer_init(); #endif - + return p; } FREE_FUNC(mod_auth_free) { mod_auth_plugin_data *p = p_d; - + UNUSED(srv); if (!p) return HANDLER_GO_ON; - + buffer_free(p->tmp_buf); buffer_free(p->auth_user); #ifdef USE_LDAP buffer_free(p->ldap_filter); #endif - + if (p->config_storage) { size_t i; for (i = 0; i < srv->config_context->used; i++) { mod_auth_plugin_config *s = p->config_storage[i]; - + if (!s) continue; - + array_free(s->auth_require); buffer_free(s->auth_plain_groupfile); buffer_free(s->auth_plain_userfile); buffer_free(s->auth_htdigest_userfile); buffer_free(s->auth_htpasswd_userfile); buffer_free(s->auth_backend_conf); - + buffer_free(s->auth_ldap_hostname); buffer_free(s->auth_ldap_basedn); buffer_free(s->auth_ldap_binddn); buffer_free(s->auth_ldap_bindpw); buffer_free(s->auth_ldap_filter); buffer_free(s->auth_ldap_cafile); - + #ifdef USE_LDAP buffer_free(s->ldap_filter_pre); buffer_free(s->ldap_filter_post); - + if (s->ldap) ldap_unbind_s(s->ldap); #endif - + free(s); } free(p->config_storage); } - + free(p); - + return HANDLER_GO_ON; } @@ -118,19 +118,19 @@ static int mod_auth_patch_connection(server *srv, connection *con, mod_auth_plug PATCH(ldap_filter_pre); PATCH(ldap_filter_post); #endif - + /* 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("auth.backend"))) { PATCH(auth_backend); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.plain.groupfile"))) { @@ -163,7 +163,7 @@ static int mod_auth_patch_connection(server *srv, connection *con, mod_auth_plug } } } - + return 0; } #undef PATCH @@ -175,22 +175,22 @@ static handler_t mod_auth_uri_handler(server *srv, connection *con, void *p_d) { data_string *ds; mod_auth_plugin_data *p = p_d; array *req; - + /* select the right config */ mod_auth_patch_connection(srv, con, p); - + if (p->conf.auth_require == NULL) return HANDLER_GO_ON; - + /* * AUTH - * + * */ - + /* do we have to ask for auth ? */ - + auth_required = 0; auth_satisfied = 0; - + /* search auth-directives for path */ for (k = 0; k < p->conf.auth_require->used; k++) { buffer *require = p->conf.auth_require->data[k]->key; @@ -212,31 +212,31 @@ static handler_t mod_auth_uri_handler(server *srv, connection *con, void *p_d) { } } } - + /* nothing to do for us */ if (auth_required == 0) return HANDLER_GO_ON; - + req = ((data_array *)(p->conf.auth_require->data[k]))->value; - + /* try to get Authorization-header */ - + if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Authorization"))) { http_authorization = ds->value->ptr; } - + if (ds && ds->value && ds->value->used) { char *auth_realm; data_string *method; - + method = (data_string *)array_get_element(req, "method"); - + /* parse auth-header */ if (NULL != (auth_realm = strchr(http_authorization, ' '))) { int auth_type_len = auth_realm - http_authorization; - + if ((auth_type_len == 5) && (0 == strncmp(http_authorization, "Basic", auth_type_len))) { - + if (0 == strcmp(method->value->ptr, "basic")) { auth_satisfied = http_auth_basic_check(srv, con, p, req, con->uri.path, auth_realm+1); } @@ -245,43 +245,43 @@ static handler_t mod_auth_uri_handler(server *srv, connection *con, void *p_d) { if (0 == strcmp(method->value->ptr, "digest")) { if (-1 == (auth_satisfied = http_auth_digest_check(srv, con, p, req, con->uri.path, auth_realm+1))) { con->http_status = 400; - + /* a field was missing */ - + return HANDLER_FINISHED; } } } else { - log_error_write(srv, __FILE__, __LINE__, "ss", + log_error_write(srv, __FILE__, __LINE__, "ss", "unknown authentification type:", http_authorization); } } } - + if (!auth_satisfied) { data_string *method, *realm; method = (data_string *)array_get_element(req, "method"); realm = (data_string *)array_get_element(req, "realm"); - + con->http_status = 401; - + if (0 == strcmp(method->value->ptr, "basic")) { buffer_copy_string(p->tmp_buf, "Basic realm=\""); buffer_append_string_buffer(p->tmp_buf, realm->value); buffer_append_string(p->tmp_buf, "\""); - + response_header_insert(srv, con, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(p->tmp_buf)); } else if (0 == strcmp(method->value->ptr, "digest")) { char hh[33]; http_auth_digest_generate_nonce(srv, p, srv->tmp_buf, hh); - + buffer_copy_string(p->tmp_buf, "Digest realm=\""); buffer_append_string_buffer(p->tmp_buf, realm->value); buffer_append_string(p->tmp_buf, "\", nonce=\""); buffer_append_string(p->tmp_buf, hh); buffer_append_string(p->tmp_buf, "\", qop=\"auth\""); - + response_header_insert(srv, con, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(p->tmp_buf)); } else { /* evil */ @@ -289,18 +289,18 @@ static handler_t mod_auth_uri_handler(server *srv, connection *con, void *p_d) { return HANDLER_FINISHED; } else { /* the REMOTE_USER header */ - + buffer_copy_string_buffer(con->authed_user, p->auth_user); } - + return HANDLER_GO_ON; } SETDEFAULTS_FUNC(mod_auth_set_defaults) { mod_auth_plugin_data *p = p_d; size_t i; - - config_values_t cv[] = { + + config_values_t cv[] = { { "auth.backend", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ { "auth.backend.plain.groupfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, { "auth.backend.plain.userfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, @@ -317,7 +317,7 @@ SETDEFAULTS_FUNC(mod_auth_set_defaults) { { "auth.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 13 */ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } }; - + p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *)); for (i = 0; i < srv->config_context->used; i++) { @@ -325,14 +325,14 @@ SETDEFAULTS_FUNC(mod_auth_set_defaults) { size_t n; data_array *da; array *ca; - + s = calloc(1, sizeof(mod_auth_plugin_config)); s->auth_plain_groupfile = buffer_init(); s->auth_plain_userfile = buffer_init(); s->auth_htdigest_userfile = buffer_init(); s->auth_htpasswd_userfile = buffer_init(); s->auth_backend_conf = buffer_init(); - + s->auth_ldap_hostname = buffer_init(); s->auth_ldap_basedn = buffer_init(); s->auth_ldap_binddn = buffer_init(); @@ -341,15 +341,15 @@ SETDEFAULTS_FUNC(mod_auth_set_defaults) { s->auth_ldap_cafile = buffer_init(); s->auth_ldap_starttls = 0; s->auth_debug = 0; - + s->auth_require = array_init(); - + #ifdef USE_LDAP s->ldap_filter_pre = buffer_init(); s->ldap_filter_post = buffer_init(); s->ldap = NULL; #endif - + cv[0].destination = s->auth_backend_conf; cv[1].destination = s->auth_plain_groupfile; cv[2].destination = s->auth_plain_userfile; @@ -364,14 +364,14 @@ SETDEFAULTS_FUNC(mod_auth_set_defaults) { cv[11].destination = s->auth_htdigest_userfile; cv[12].destination = s->auth_htpasswd_userfile; cv[13].destination = &(s->auth_debug); - + 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; } - + if (s->auth_backend_conf->used) { if (0 == strcmp(s->auth_backend_conf->ptr, "htpasswd")) { s->auth_backend = AUTH_BACKEND_HTPASSWD; @@ -383,31 +383,31 @@ SETDEFAULTS_FUNC(mod_auth_set_defaults) { s->auth_backend = AUTH_BACKEND_LDAP; } else { log_error_write(srv, __FILE__, __LINE__, "sb", "auth.backend not supported:", s->auth_backend_conf); - + return HANDLER_ERROR; } } /* no auth.require for this section */ if (NULL == (da = (data_array *)array_get_element(ca, "auth.require"))) continue; - + if (da->type != TYPE_ARRAY) continue; - + for (n = 0; n < da->value->used; n++) { size_t m; data_array *da_file = (data_array *)da->value->data[n]; const char *method, *realm, *require; - + if (da->value->data[n]->type != TYPE_ARRAY) { - log_error_write(srv, __FILE__, __LINE__, "ss", - "auth.require should contain an array as in:", + log_error_write(srv, __FILE__, __LINE__, "ss", + "auth.require should contain an array as in:", "auth.require = ( \"...\" => ( ..., ...) )"); return HANDLER_ERROR; } - + method = realm = require = NULL; - + for (m = 0; m < da_file->value->used; m++) { if (da_file->value->data[m]->type == TYPE_STRING) { if (0 == strcmp(da_file->value->data[m]->key->ptr, "method")) { @@ -417,8 +417,8 @@ SETDEFAULTS_FUNC(mod_auth_set_defaults) { } else if (0 == strcmp(da_file->value->data[m]->key->ptr, "require")) { require = ((data_string *)(da_file->value->data[m]))->value->ptr; } else { - log_error_write(srv, __FILE__, __LINE__, "ssbs", - "the field is unknown in:", + log_error_write(srv, __FILE__, __LINE__, "ssbs", + "the field is unknown in:", "auth.require = ( \"...\" => ( ..., -> \"", da_file->value->data[m]->key, "\" <- => \"...\" ) )"); @@ -426,19 +426,19 @@ SETDEFAULTS_FUNC(mod_auth_set_defaults) { return HANDLER_ERROR; } } else { - log_error_write(srv, __FILE__, __LINE__, "ssbs", - "a string was expected for:", + log_error_write(srv, __FILE__, __LINE__, "ssbs", + "a string was expected for:", "auth.require = ( \"...\" => ( ..., -> \"", da_file->value->data[m]->key, "\" <- => \"...\" ) )"); - + return HANDLER_ERROR; } } - + if (method == NULL) { - log_error_write(srv, __FILE__, __LINE__, "ss", - "the require field is missing in:", + log_error_write(srv, __FILE__, __LINE__, "ss", + "the require field is missing in:", "auth.require = ( \"...\" => ( ..., \"method\" => \"...\" ) )"); return HANDLER_ERROR; } else { @@ -450,60 +450,60 @@ SETDEFAULTS_FUNC(mod_auth_set_defaults) { return HANDLER_ERROR; } } - + if (realm == NULL) { - log_error_write(srv, __FILE__, __LINE__, "ss", - "the require field is missing in:", + log_error_write(srv, __FILE__, __LINE__, "ss", + "the require field is missing in:", "auth.require = ( \"...\" => ( ..., \"realm\" => \"...\" ) )"); return HANDLER_ERROR; } - + if (require == NULL) { - log_error_write(srv, __FILE__, __LINE__, "ss", - "the require field is missing in:", + log_error_write(srv, __FILE__, __LINE__, "ss", + "the require field is missing in:", "auth.require = ( \"...\" => ( ..., \"require\" => \"...\" ) )"); return HANDLER_ERROR; } - + if (method && realm && require) { data_string *ds; data_array *a; - + a = data_array_init(); buffer_copy_string_buffer(a->key, da_file->key); - + ds = data_string_init(); - + buffer_copy_string(ds->key, "method"); buffer_copy_string(ds->value, method); - + array_insert_unique(a->value, (data_unset *)ds); - + ds = data_string_init(); - + buffer_copy_string(ds->key, "realm"); buffer_copy_string(ds->value, realm); - + array_insert_unique(a->value, (data_unset *)ds); - + ds = data_string_init(); - + buffer_copy_string(ds->key, "require"); buffer_copy_string(ds->value, require); - + array_insert_unique(a->value, (data_unset *)ds); - + array_insert_unique(s->auth_require, (data_unset *)a); } } - + switch(s->auth_backend) { case AUTH_BACKEND_PLAIN: if (s->auth_plain_userfile->used) { int fd; /* try to read */ if (-1 == (fd = open(s->auth_plain_userfile->ptr, O_RDONLY))) { - log_error_write(srv, __FILE__, __LINE__, "sbss", + log_error_write(srv, __FILE__, __LINE__, "sbss", "opening auth.backend.plain.userfile:", s->auth_plain_userfile, "failed:", strerror(errno)); return HANDLER_ERROR; @@ -516,7 +516,7 @@ SETDEFAULTS_FUNC(mod_auth_set_defaults) { int fd; /* try to read */ if (-1 == (fd = open(s->auth_htpasswd_userfile->ptr, O_RDONLY))) { - log_error_write(srv, __FILE__, __LINE__, "sbss", + log_error_write(srv, __FILE__, __LINE__, "sbss", "opening auth.backend.htpasswd.userfile:", s->auth_htpasswd_userfile, "failed:", strerror(errno)); return HANDLER_ERROR; @@ -529,7 +529,7 @@ SETDEFAULTS_FUNC(mod_auth_set_defaults) { int fd; /* try to read */ if (-1 == (fd = open(s->auth_htdigest_userfile->ptr, O_RDONLY))) { - log_error_write(srv, __FILE__, __LINE__, "sbss", + log_error_write(srv, __FILE__, __LINE__, "sbss", "opening auth.backend.htdigest.userfile:", s->auth_htdigest_userfile, "failed:", strerror(errno)); return HANDLER_ERROR; @@ -554,75 +554,75 @@ SETDEFAULTS_FUNC(mod_auth_set_defaults) { handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s) { #ifdef USE_LDAP int ret; -#if 0 +#if 0 if (s->auth_ldap_basedn->used == 0) { log_error_write(srv, __FILE__, __LINE__, "s", "ldap: auth.backend.ldap.base-dn has to be set"); - + return HANDLER_ERROR; } #endif - + if (s->auth_ldap_filter->used) { char *dollar; - + /* parse filter */ - + if (NULL == (dollar = strchr(s->auth_ldap_filter->ptr, '$'))) { log_error_write(srv, __FILE__, __LINE__, "s", "ldap: auth.backend.ldap.filter is missing a replace-operator '$'"); - + return HANDLER_ERROR; } - + buffer_copy_string_len(s->ldap_filter_pre, s->auth_ldap_filter->ptr, dollar - s->auth_ldap_filter->ptr); buffer_copy_string(s->ldap_filter_post, dollar+1); } - + if (s->auth_ldap_hostname->used) { if (NULL == (s->ldap = ldap_init(s->auth_ldap_hostname->ptr, LDAP_PORT))) { log_error_write(srv, __FILE__, __LINE__, "ss", "ldap ...", strerror(errno)); - + return HANDLER_ERROR; } - + ret = LDAP_VERSION3; if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(s->ldap, LDAP_OPT_PROTOCOL_VERSION, &ret))) { log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret)); - + return HANDLER_ERROR; } if (s->auth_ldap_starttls) { - /* if no CA file is given, it is ok, as we will use encryption + /* if no CA file is given, it is ok, as we will use encryption * if the server requires a CAfile it will tell us */ if (!buffer_is_empty(s->auth_ldap_cafile)) { - if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, + if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, s->auth_ldap_cafile->ptr))) { - log_error_write(srv, __FILE__, __LINE__, "ss", + log_error_write(srv, __FILE__, __LINE__, "ss", "Loading CA certificate failed:", ldap_err2string(ret)); - + return HANDLER_ERROR; } } - + if (LDAP_OPT_SUCCESS != (ret = ldap_start_tls_s(s->ldap, NULL, NULL))) { log_error_write(srv, __FILE__, __LINE__, "ss", "ldap startTLS failed:", ldap_err2string(ret)); - + return HANDLER_ERROR; } } - - + + /* 1. */ if (s->auth_ldap_binddn->used) { if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(s->ldap, s->auth_ldap_binddn->ptr, s->auth_ldap_bindpw->ptr))) { log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret)); - + return HANDLER_ERROR; } } else { if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(s->ldap, NULL, NULL))) { log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret)); - + return HANDLER_ERROR; } } @@ -641,8 +641,8 @@ int mod_auth_plugin_init(plugin *p) { p->set_defaults = mod_auth_set_defaults; p->handle_uri_clean = mod_auth_uri_handler; p->cleanup = mod_auth_free; - + p->data = NULL; - + return 0; } diff --git a/src/mod_cgi.c b/src/mod_cgi.c index 15aca3c..a6f8756 100644 --- a/src/mod_cgi.c +++ b/src/mod_cgi.c @@ -40,7 +40,7 @@ enum {EOL_UNSET, EOL_N, EOL_RN}; typedef struct { char **ptr; - + size_t size; size_t used; } char_array; @@ -58,23 +58,23 @@ typedef struct { 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 +83,17 @@ static handler_ctx * cgi_handler_ctx_init() { 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 +101,14 @@ enum {FDEVENT_HANDLED_UNSET, FDEVENT_HANDLED_FINISHED, FDEVENT_HANDLED_NOT_FINIS 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 +116,62 @@ INIT_FUNC(mod_cgi_init) { 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 +180,13 @@ static int cgi_pid_add(server *srv, plugin_data *p, pid_t pid) { 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 +194,31 @@ static int cgi_pid_add(server *srv, plugin_data *p, pid_t pid) { 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 +226,32 @@ static int cgi_response_parse(server *srv, connection *con, plugin_data *p, buff 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 +260,27 @@ static int cgi_response_parse(server *srv, connection *con, plugin_data *p, buff } } } else { - + key = s; if (NULL == (value = strchr(s, ':'))) { /* we expect: "<key>: <value>\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 +315,13 @@ static int cgi_response_parse(server *srv, connection *con, plugin_data *p, buff } } } - + /* 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 +329,10 @@ static int cgi_response_parse(server *srv, connection *con, plugin_data *p, buff 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 +343,125 @@ static int cgi_demux_response(server *srv, handler_ctx *hctx) { 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,42 +470,42 @@ static handler_t cgi_connection_close(server *srv, handler_ctx *hctx) { 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 - + /* 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 */ @@ -519,19 +519,19 @@ static handler_t cgi_connection_close(server *srv, handler_ctx *hctx) { 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 +541,13 @@ static handler_t cgi_connection_close(server *srv, handler_ctx *hctx) { 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 +555,20 @@ static handler_t cgi_connection_close(server *srv, handler_ctx *hctx) { return HANDLER_GO_ON; } } - - + + kill(pid, SIGTERM); - + /* 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 +577,43 @@ static handler_t cgi_handle_fdevent(void *s, void *ctx, int revents) { 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 +623,54 @@ static handler_t cgi_handle_fdevent(void *s, void *ctx, int revents) { 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 +678,45 @@ static int cgi_env_add(char_array *env, const char *key, size_t key_len, const c 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 +730,22 @@ static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer * 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 +754,20 @@ static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer * 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 +779,10 @@ static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer * 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 +790,10 @@ static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer * #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); @@ -815,11 +815,11 @@ static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer * 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 +828,7 @@ static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer * #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 +836,19 @@ static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer * #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 +863,24 @@ static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer * 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 +893,46 @@ static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer * 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 +942,7 @@ static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer * /* 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 +954,12 @@ static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer * 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 +974,11 @@ static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer * 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 +993,16 @@ static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer * 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 +1012,7 @@ static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer * close(c->file.fd); c->file.fd = -1; - + /* chunk_reset() or chunk_free() will cleanup for us */ } @@ -1020,7 +1020,7 @@ static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer * switch(errno) { case ENOSPC: con->http_status = 507; - + break; default: con->http_status = 403; @@ -1033,7 +1033,7 @@ static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer * switch(errno) { case ENOSPC: con->http_status = 507; - + break; default: con->http_status = 403; @@ -1056,45 +1056,45 @@ static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer * } 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; @@ -1106,27 +1106,27 @@ static int cgi_create_env(server *srv, connection *con, plugin_data *p, buffer * 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); - + /* 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); } } } - + return 0; } #undef PATCH @@ -1135,24 +1135,24 @@ 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 +1160,7 @@ URIHANDLER_FUNC(cgi_is_handled) { break; } } - + return HANDLER_GO_ON; } @@ -1172,7 +1172,7 @@ TRIGGER_FUNC(cgi_trigger) { 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 +1182,7 @@ TRIGGER_FUNC(cgi_trigger) { break; case -1: log_error_write(srv, __FILE__, __LINE__, "ss", "waitpid failed: ", strerror(errno)); - + return HANDLER_ERROR; default: @@ -1193,16 +1193,16 @@ TRIGGER_FUNC(cgi_trigger) { } 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 +1210,15 @@ SUBREQUEST_FUNC(mod_cgi_handle_subrequest) { 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 +1228,61 @@ SUBREQUEST_FUNC(mod_cgi_handle_subrequest) { 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 +1306,8 @@ int mod_cgi_plugin_init(plugin *p) { p->init = mod_cgi_init; p->cleanup = mod_cgi_free; p->set_defaults = mod_fastcgi_set_defaults; - + p->data = NULL; - + return 0; } diff --git a/src/mod_cml.c b/src/mod_cml.c index f5b1768..2221368 100644 --- a/src/mod_cml.c +++ b/src/mod_cml.c @@ -20,50 +20,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 +72,22 @@ FREE_FUNC(mod_cml_free) { 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,42 +96,42 @@ SETDEFAULTS_FUNC(mod_cml_set_defaults) { #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; } @@ -140,26 +140,26 @@ SETDEFAULTS_FUNC(mod_cml_set_defaults) { 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); #if defined(HAVE_MEMCACHE_H) PATCH(mc); #endif PATCH(mc_namespace); PATCH(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); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("cml.memcache-hosts"))) { @@ -173,7 +173,7 @@ static int mod_cml_patch_connection(server *srv, connection *con, plugin_data *p } } } - + return 0; } #undef PATCH @@ -181,63 +181,60 @@ static int mod_cml_patch_connection(server *srv, connection *con, plugin_data *p int cache_call_lua(server *srv, connection *con, plugin_data *p, buffer *cml_file) { buffer *b; char *c; - int ret; /* cleanup basedir */ 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 +263,20 @@ URIHANDLER_FUNC(mod_cml_power_magnet) { 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 +308,15 @@ URIHANDLER_FUNC(mod_cml_is_handled) { 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; } diff --git a/src/mod_cml.h b/src/mod_cml.h index 992af68..1afd708 100644 --- a/src/mod_cml.h +++ b/src/mod_cml.h @@ -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 { 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); diff --git a/src/mod_cml_funcs.c b/src/mod_cml_funcs.c index 46a1f16..07c7673 100644 --- a/src/mod_cml_funcs.c +++ b/src/mod_cml_funcs.c @@ -30,7 +30,7 @@ typedef char HASHHEX[HASHHEXLEN+1]; #ifdef USE_OPENSSL #define IN const #else -#define IN +#define IN #endif #define OUT @@ -42,29 +42,29 @@ int f_crypto_md5(lua_State *L) { buffer b; char hex[33]; int n = lua_gettop(L); - + b.ptr = hex; b.used = 0; b.size = sizeof(hex); - + if (n != 1) { lua_pushstring(L, "md5: expected one argument"); lua_error(L); } - + if (!lua_isstring(L, 1)) { lua_pushstring(L, "md5: argument has to be a string"); lua_error(L); } - + MD5_Init(&Md5Ctx); MD5_Update(&Md5Ctx, (unsigned char *)lua_tostring(L, 1), lua_strlen(L, 1)); MD5_Final(HA1, &Md5Ctx); - + buffer_copy_string_hex(&b, (char *)HA1, 16); - + lua_pushstring(L, b.ptr); - + return 1; } @@ -72,37 +72,37 @@ int f_crypto_md5(lua_State *L) { int f_file_mtime(lua_State *L) { struct stat st; int n = lua_gettop(L); - + if (n != 1) { lua_pushstring(L, "file_mtime: expected one argument"); lua_error(L); } - + if (!lua_isstring(L, 1)) { lua_pushstring(L, "file_mtime: argument has to be a string"); lua_error(L); } - + if (-1 == stat(lua_tostring(L, 1), &st)) { lua_pushnil(L); return 1; } - + lua_pushnumber(L, st.st_mtime); - + return 1; } int f_dir_files_iter(lua_State *L) { DIR *d; struct dirent *de; - + d = lua_touserdata(L, lua_upvalueindex(1)); - + if (NULL == (de = readdir(d))) { /* EOF */ closedir(d); - + return 0; } else { lua_pushstring(L, de->d_name); @@ -113,75 +113,75 @@ int f_dir_files_iter(lua_State *L) { int f_dir_files(lua_State *L) { DIR *d; int n = lua_gettop(L); - + if (n != 1) { lua_pushstring(L, "dir_files: expected one argument"); lua_error(L); } - + if (!lua_isstring(L, 1)) { lua_pushstring(L, "dir_files: argument has to be a string"); lua_error(L); } - - /* check if there is a valid DIR handle on the stack */ + + /* check if there is a valid DIR handle on the stack */ if (NULL == (d = opendir(lua_tostring(L, 1)))) { lua_pushnil(L); return 1; } - + /* push d into registry */ lua_pushlightuserdata(L, d); lua_pushcclosure(L, f_dir_files_iter, 1); - + return 1; } int f_file_isreg(lua_State *L) { struct stat st; int n = lua_gettop(L); - + if (n != 1) { lua_pushstring(L, "file_isreg: expected one argument"); lua_error(L); } - + if (!lua_isstring(L, 1)) { lua_pushstring(L, "file_isreg: argument has to be a string"); lua_error(L); } - + if (-1 == stat(lua_tostring(L, 1), &st)) { lua_pushnil(L); return 1; } - + lua_pushnumber(L, S_ISREG(st.st_mode)); - + return 1; } int f_file_isdir(lua_State *L) { struct stat st; int n = lua_gettop(L); - + if (n != 1) { lua_pushstring(L, "file_isreg: expected one argument"); lua_error(L); } - + if (!lua_isstring(L, 1)) { lua_pushstring(L, "file_isreg: argument has to be a string"); lua_error(L); } - + if (-1 == stat(lua_tostring(L, 1), &st)) { lua_pushnil(L); return 1; } - + lua_pushnumber(L, S_ISDIR(st.st_mode)); - + return 1; } @@ -192,33 +192,33 @@ int f_memcache_exists(lua_State *L) { char *r; int n = lua_gettop(L); struct memcache *mc; - + if (!lua_islightuserdata(L, lua_upvalueindex(1))) { lua_pushstring(L, "where is my userdata ?"); lua_error(L); } - + mc = lua_touserdata(L, lua_upvalueindex(1)); - + if (n != 1) { lua_pushstring(L, "expected one argument"); lua_error(L); } - + if (!lua_isstring(L, 1)) { lua_pushstring(L, "argument has to be a string"); lua_error(L); } - - if (NULL == (r = mc_aget(mc, + + if (NULL == (r = mc_aget(mc, lua_tostring(L, 1), lua_strlen(L, 1)))) { - + lua_pushboolean(L, 0); return 1; } - + free(r); - + lua_pushboolean(L, 1); return 1; } @@ -226,74 +226,74 @@ int f_memcache_exists(lua_State *L) { int f_memcache_get_string(lua_State *L) { char *r; int n = lua_gettop(L); - + struct memcache *mc; - + if (!lua_islightuserdata(L, lua_upvalueindex(1))) { lua_pushstring(L, "where is my userdata ?"); lua_error(L); } - + mc = lua_touserdata(L, lua_upvalueindex(1)); - - + + if (n != 1) { lua_pushstring(L, "expected one argument"); lua_error(L); } - + if (!lua_isstring(L, 1)) { lua_pushstring(L, "argument has to be a string"); lua_error(L); } - - if (NULL == (r = mc_aget(mc, + + if (NULL == (r = mc_aget(mc, lua_tostring(L, 1), lua_strlen(L, 1)))) { lua_pushnil(L); return 1; } - + lua_pushstring(L, r); - + free(r); - + return 1; } int f_memcache_get_long(lua_State *L) { char *r; int n = lua_gettop(L); - + struct memcache *mc; - + if (!lua_islightuserdata(L, lua_upvalueindex(1))) { lua_pushstring(L, "where is my userdata ?"); lua_error(L); } - + mc = lua_touserdata(L, lua_upvalueindex(1)); - - + + if (n != 1) { lua_pushstring(L, "expected one argument"); lua_error(L); } - + if (!lua_isstring(L, 1)) { lua_pushstring(L, "argument has to be a string"); lua_error(L); } - - if (NULL == (r = mc_aget(mc, + + if (NULL == (r = mc_aget(mc, lua_tostring(L, 1), lua_strlen(L, 1)))) { lua_pushnil(L); return 1; } - + lua_pushnumber(L, strtol(r, NULL, 10)); - + free(r); - + return 1; } #endif diff --git a/src/mod_cml_lua.c b/src/mod_cml_lua.c index ded53b8..8bfb1ab 100644 --- a/src/mod_cml_lua.c +++ b/src/mod_cml_lua.c @@ -23,7 +23,7 @@ typedef char HASHHEX[HASHHEXLEN+1]; #ifdef USE_OPENSSL #define IN const #else -#define IN +#define IN #endif #define OUT @@ -40,11 +40,11 @@ typedef struct { static const char * load_file(lua_State *L, void *data, size_t *size) { readme *rm = data; - + UNUSED(L); - + if (rm->done) return 0; - + *size = rm->st.size; rm->done = 1; return rm->st.start; @@ -52,47 +52,47 @@ static const char * load_file(lua_State *L, void *data, size_t *size) { static int lua_to_c_get_string(lua_State *L, const char *varname, buffer *b) { int curelem; - + lua_pushstring(L, varname); - + curelem = lua_gettop(L); lua_gettable(L, LUA_GLOBALSINDEX); - + /* it should be a table */ if (!lua_isstring(L, curelem)) { lua_settop(L, curelem - 1); - + return -1; } - + buffer_copy_string(b, lua_tostring(L, curelem)); - + lua_pop(L, 1); - + assert(curelem - 1 == lua_gettop(L)); - + return 0; } static int lua_to_c_is_table(lua_State *L, const char *varname) { int curelem; - + lua_pushstring(L, varname); - + curelem = lua_gettop(L); lua_gettable(L, LUA_GLOBALSINDEX); - + /* it should be a table */ if (!lua_istable(L, curelem)) { lua_settop(L, curelem - 1); - + return 0; } - + lua_settop(L, curelem - 1); - + assert(curelem - 1 == lua_gettop(L)); - + return 1; } @@ -100,7 +100,7 @@ static int c_to_lua_push(lua_State *L, int tbl, const char *key, size_t key_len, lua_pushlstring(L, key, key_len); lua_pushlstring(L, val, val_len); lua_settable(L, tbl); - + return 0; } @@ -109,21 +109,21 @@ int cache_export_get_params(lua_State *L, int tbl, buffer *qrystr) { size_t is_key = 1; size_t i; char *key = NULL, *val = NULL; - + key = qrystr->ptr; - + /* we need the \0 */ for (i = 0; i < qrystr->used; i++) { switch(qrystr->ptr[i]) { case '=': if (is_key) { val = qrystr->ptr + i + 1; - + qrystr->ptr[i] = '\0'; - + is_key = 0; } - + break; case '&': case '\0': /* fin symbol */ @@ -132,19 +132,19 @@ int cache_export_get_params(lua_State *L, int tbl, buffer *qrystr) { /* terminate the value */ qrystr->ptr[i] = '\0'; - - c_to_lua_push(L, tbl, + + c_to_lua_push(L, tbl, key, strlen(key), val, strlen(val)); } - + key = qrystr->ptr + i + 1; val = NULL; is_key = 1; break; } } - + return 0; } #if 0 @@ -152,21 +152,21 @@ int cache_export_cookie_params(server *srv, connection *con, plugin_data *p) { data_unset *d; UNUSED(srv); - + if (NULL != (d = array_get_element(con->request.headers, "Cookie"))) { data_string *ds = (data_string *)d; size_t key = 0, value = 0; size_t is_key = 1, is_sid = 0; size_t i; - + /* found COOKIE */ if (!DATA_IS_STRING(d)) return -1; if (ds->value->used == 0) return -1; - + if (ds->value->ptr[0] == '\0' || ds->value->ptr[0] == '=' || ds->value->ptr[0] == ';') return -1; - + buffer_reset(p->session_id); for (i = 0; i < ds->value->used; i++) { switch(ds->value->ptr[i]) { @@ -177,16 +177,16 @@ int cache_export_cookie_params(server *srv, connection *con, plugin_data *p) { is_sid = 1; } value = i + 1; - + is_key = 0; } - + break; case ';': if (is_sid) { buffer_copy_string_len(p->session_id, ds->value->ptr + value, i - value); } - + is_sid = 0; key = i + 1; value = 0; @@ -205,21 +205,21 @@ int cache_export_cookie_params(server *srv, connection *con, plugin_data *p) { } } } - + return 0; } #endif int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn) { - lua_State *L; + lua_State *L; readme rm; int ret = -1; buffer *b = buffer_init(); int header_tbl = 0; - + rm.done = 0; stream_open(&rm.st, fn); - + /* push the lua file to the interpreter and see what happends */ L = luaL_newstate(); luaL_openlibs(L); @@ -230,18 +230,18 @@ int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn) { lua_register(L, "file_isreg", f_file_isreg); lua_register(L, "file_isdir", f_file_isreg); lua_register(L, "dir_files", f_dir_files); - + #ifdef HAVE_MEMCACHE_H lua_pushliteral(L, "memcache_get_long"); lua_pushlightuserdata(L, p->conf.mc); lua_pushcclosure(L, f_memcache_get_long, 1); lua_settable(L, LUA_GLOBALSINDEX); - + lua_pushliteral(L, "memcache_get_string"); lua_pushlightuserdata(L, p->conf.mc); lua_pushcclosure(L, f_memcache_get_string, 1); lua_settable(L, LUA_GLOBALSINDEX); - + lua_pushliteral(L, "memcache_exists"); lua_pushlightuserdata(L, p->conf.mc); lua_pushcclosure(L, f_memcache_exists, 1); @@ -251,11 +251,11 @@ int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn) { lua_pushliteral(L, "request"); lua_newtable(L); lua_settable(L, LUA_GLOBALSINDEX); - + lua_pushliteral(L, "request"); header_tbl = lua_gettop(L); lua_gettable(L, LUA_GLOBALSINDEX); - + c_to_lua_push(L, header_tbl, CONST_STR_LEN("REQUEST_URI"), CONST_BUF_LEN(con->request.orig_uri)); c_to_lua_push(L, header_tbl, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path)); c_to_lua_push(L, header_tbl, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(con->physical.path)); @@ -263,84 +263,84 @@ int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn) { if (!buffer_is_empty(con->request.pathinfo)) { c_to_lua_push(L, header_tbl, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo)); } - + c_to_lua_push(L, header_tbl, CONST_STR_LEN("CWD"), CONST_BUF_LEN(p->basedir)); c_to_lua_push(L, header_tbl, CONST_STR_LEN("BASEURL"), CONST_BUF_LEN(p->baseurl)); - + /* register GET parameter */ lua_pushliteral(L, "get"); lua_newtable(L); lua_settable(L, LUA_GLOBALSINDEX); - + lua_pushliteral(L, "get"); header_tbl = lua_gettop(L); lua_gettable(L, LUA_GLOBALSINDEX); - + buffer_copy_string_buffer(b, con->uri.query); cache_export_get_params(L, header_tbl, b); buffer_reset(b); - /* 2 default constants */ + /* 2 default constants */ lua_pushliteral(L, "CACHE_HIT"); lua_pushboolean(L, 0); lua_settable(L, LUA_GLOBALSINDEX); - + lua_pushliteral(L, "CACHE_MISS"); lua_pushboolean(L, 1); lua_settable(L, LUA_GLOBALSINDEX); - + /* load lua program */ if (lua_load(L, load_file, &rm, fn->ptr) || lua_pcall(L,0,1,0)) { log_error_write(srv, __FILE__, __LINE__, "s", lua_tostring(L,-1)); - + goto error; } - + /* get return value */ ret = (int)lua_tonumber(L, -1); lua_pop(L, 1); - - /* fetch the data from lua */ + + /* fetch the data from lua */ lua_to_c_get_string(L, "trigger_handler", p->trigger_handler); - + if (0 == lua_to_c_get_string(L, "output_contenttype", b)) { response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(b)); } - + if (ret == 0) { /* up to now it is a cache-hit, check if all files exist */ - + int curelem; time_t mtime = 0; - + if (!lua_to_c_is_table(L, "output_include")) { log_error_write(srv, __FILE__, __LINE__, "s", "output_include is missing or not a table"); ret = -1; - + goto error; } - + lua_pushstring(L, "output_include"); - + curelem = lua_gettop(L); lua_gettable(L, LUA_GLOBALSINDEX); /* HOW-TO build a etag ? - * as we don't just have one file we have to take the stat() + * as we don't just have one file we have to take the stat() * from all base files, merge them and build the etag from * it later. - * + * * The mtime of the content is the mtime of the freshest base file - * + * * */ - + lua_pushnil(L); /* first key */ while (lua_next(L, curelem) != 0) { stat_cache_entry *sce = NULL; /* key' is at index -2 and value' at index -1 */ - + if (lua_isstring(L, -1)) { const char *s = lua_tostring(L, -1); @@ -360,18 +360,18 @@ int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn) { /* a file is missing, call the handler to generate it */ if (!buffer_is_empty(p->trigger_handler)) { ret = 1; /* cache-miss */ - + log_error_write(srv, __FILE__, __LINE__, "s", "a file is missing, calling handler"); - + break; } else { /* handler not set -> 500 */ ret = -1; - + log_error_write(srv, __FILE__, __LINE__, "s", "a file missing and no handler set"); - + break; } break; @@ -389,12 +389,12 @@ int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn) { "not a string"); break; } - + lua_pop(L, 1); /* removes value'; keeps key' for next iteration */ } - + lua_settop(L, curelem - 1); - + if (ret == 0) { data_string *ds; char timebuf[sizeof("Sat, 23 Jul 2005 21:20:01 GMT")]; @@ -406,9 +406,9 @@ int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn) { /* no Last-Modified specified */ if ((mtime) && (NULL == ds)) { - + strftime(timebuf, sizeof(timebuf), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&mtime)); - + response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), timebuf, sizeof(timebuf) - 1); @@ -424,9 +424,9 @@ int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn) { tbuf.used = 0; tbuf.ptr = NULL; } - + if (HANDLER_FINISHED == http_response_handle_cachable(srv, con, &tbuf)) { - /* ok, the client already has our content, + /* ok, the client already has our content, * no need to send it again */ chunkqueue_reset(con->write_queue); @@ -436,28 +436,32 @@ int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn) { chunkqueue_reset(con->write_queue); } } - + if (ret == 1 && !buffer_is_empty(p->trigger_handler)) { /* cache-miss */ buffer_copy_string_buffer(con->uri.path, p->baseurl); buffer_append_string_buffer(con->uri.path, p->trigger_handler); - + buffer_copy_string_buffer(con->physical.path, p->basedir); buffer_append_string_buffer(con->physical.path, p->trigger_handler); - + chunkqueue_reset(con->write_queue); } - + error: lua_close(L); - + stream_close(&rm.st); buffer_free(b); - + return ret /* cache-error */; } #else int cache_parse_lua(server *srv, connection *con, plugin_data *p, buffer *fn) { + UNUSED(srv); + UNUSED(con); + UNUSED(p); + UNUSED(fn); /* error */ return -1; } diff --git a/src/mod_compress.c b/src/mod_compress.c index fc78220..b528ebf 100644 --- a/src/mod_compress.c +++ b/src/mod_compress.c @@ -55,97 +55,97 @@ typedef struct { PLUGIN_DATA; buffer *ofn; buffer *b; - + plugin_config **config_storage; - plugin_config conf; + plugin_config conf; } plugin_data; INIT_FUNC(mod_compress_init) { plugin_data *p; - + p = calloc(1, sizeof(*p)); - + p->ofn = buffer_init(); p->b = buffer_init(); - + return p; } FREE_FUNC(mod_compress_free) { plugin_data *p = p_d; - + UNUSED(srv); if (!p) return HANDLER_GO_ON; - + buffer_free(p->ofn); buffer_free(p->b); - + if (p->config_storage) { size_t i; for (i = 0; i < srv->config_context->used; i++) { plugin_config *s = p->config_storage[i]; if (!s) continue; - + array_free(s->compress); buffer_free(s->compress_cache_dir); - + free(s); } free(p->config_storage); } - - + + free(p); - + return HANDLER_GO_ON; } SETDEFAULTS_FUNC(mod_compress_setdefaults) { plugin_data *p = p_d; size_t i = 0; - - config_values_t cv[] = { + + config_values_t cv[] = { { "compress.cache-dir", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, { "compress.filetype", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, { "compress.max-filesize", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } }; - + 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->compress_cache_dir = buffer_init(); s->compress = array_init(); s->compress_max_filesize = 0; - + cv[0].destination = s->compress_cache_dir; cv[1].destination = s->compress; cv[2].destination = &(s->compress_max_filesize); - + 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 (!buffer_is_empty(s->compress_cache_dir)) { struct stat st; if (0 != stat(s->compress_cache_dir->ptr, &st)) { - log_error_write(srv, __FILE__, __LINE__, "sbs", "can't stat compress.cache-dir", + log_error_write(srv, __FILE__, __LINE__, "sbs", "can't stat compress.cache-dir", s->compress_cache_dir, strerror(errno)); - + return HANDLER_ERROR; } } } - + return HANDLER_GO_ON; - + } #ifdef USE_ZLIB @@ -153,32 +153,32 @@ static int deflate_file_to_buffer_gzip(server *srv, connection *con, plugin_data unsigned char *c; unsigned long crc; z_stream z; - + UNUSED(srv); UNUSED(con); z.zalloc = Z_NULL; z.zfree = Z_NULL; z.opaque = Z_NULL; - - if (Z_OK != deflateInit2(&z, + + if (Z_OK != deflateInit2(&z, Z_DEFAULT_COMPRESSION, - Z_DEFLATED, + Z_DEFLATED, -MAX_WBITS, /* supress zlib-header */ 8, Z_DEFAULT_STRATEGY)) { return -1; } - + z.next_in = (unsigned char *)start; z.avail_in = st_size; z.total_in = 0; - - + + buffer_prepare_copy(p->b, (z.avail_in * 1.1) + 12 + 18); - + /* write gzip header */ - + c = (unsigned char *)p->b->ptr; c[0] = 0x1f; c[1] = 0x8b; @@ -190,24 +190,24 @@ static int deflate_file_to_buffer_gzip(server *srv, connection *con, plugin_data c[7] = (mtime >> 24) & 0xff; c[8] = 0x00; /* extra flags */ c[9] = 0x03; /* UNIX */ - + p->b->used = 10; z.next_out = (unsigned char *)p->b->ptr + p->b->used; z.avail_out = p->b->size - p->b->used - 8; z.total_out = 0; - + if (Z_STREAM_END != deflate(&z, Z_FINISH)) { deflateEnd(&z); return -1; } - + /* trailer */ p->b->used += z.total_out; - + crc = generate_crc32c(start, st_size); - + c = (unsigned char *)p->b->ptr + p->b->used; - + c[0] = (crc >> 0) & 0xff; c[1] = (crc >> 8) & 0xff; c[2] = (crc >> 16) & 0xff; @@ -221,51 +221,51 @@ static int deflate_file_to_buffer_gzip(server *srv, connection *con, plugin_data if (Z_OK != deflateEnd(&z)) { return -1; } - + return 0; } static int deflate_file_to_buffer_deflate(server *srv, connection *con, plugin_data *p, unsigned char *start, off_t st_size) { z_stream z; - + UNUSED(srv); UNUSED(con); z.zalloc = Z_NULL; z.zfree = Z_NULL; z.opaque = Z_NULL; - - if (Z_OK != deflateInit2(&z, + + if (Z_OK != deflateInit2(&z, Z_DEFAULT_COMPRESSION, - Z_DEFLATED, + Z_DEFLATED, -MAX_WBITS, /* supress zlib-header */ 8, Z_DEFAULT_STRATEGY)) { return -1; } - + z.next_in = start; z.avail_in = st_size; z.total_in = 0; - + buffer_prepare_copy(p->b, (z.avail_in * 1.1) + 12); - + z.next_out = (unsigned char *)p->b->ptr; z.avail_out = p->b->size; z.total_out = 0; - + if (Z_STREAM_END != deflate(&z, Z_FINISH)) { deflateEnd(&z); return -1; } - + /* trailer */ p->b->used += z.total_out; - + if (Z_OK != deflateEnd(&z)) { return -1; } - + return 0; } @@ -274,48 +274,48 @@ static int deflate_file_to_buffer_deflate(server *srv, connection *con, plugin_d #ifdef USE_BZ2LIB static int deflate_file_to_buffer_bzip2(server *srv, connection *con, plugin_data *p, unsigned char *start, off_t st_size) { bz_stream bz; - + UNUSED(srv); UNUSED(con); bz.bzalloc = NULL; bz.bzfree = NULL; bz.opaque = NULL; - - if (BZ_OK != BZ2_bzCompressInit(&bz, + + if (BZ_OK != BZ2_bzCompressInit(&bz, 9, /* blocksize = 900k */ 0, /* no output */ 0)) { /* workFactor: default */ return -1; } - + bz.next_in = (char *)start; bz.avail_in = st_size; bz.total_in_lo32 = 0; bz.total_in_hi32 = 0; - + buffer_prepare_copy(p->b, (bz.avail_in * 1.1) + 12); - + bz.next_out = p->b->ptr; bz.avail_out = p->b->size; bz.total_out_lo32 = 0; bz.total_out_hi32 = 0; - + if (BZ_STREAM_END != BZ2_bzCompress(&bz, BZ_FINISH)) { BZ2_bzCompressEnd(&bz); return -1; } - + /* file is too large for now */ if (bz.total_out_hi32) return -1; - + /* trailer */ p->b->used = bz.total_out_lo32; - + if (BZ_OK != BZ2_bzCompressEnd(&bz)) { return -1; } - + return 0; } #endif @@ -326,47 +326,47 @@ static int deflate_file_to_file(server *srv, connection *con, plugin_data *p, bu void *start; const char *filename = fn->ptr; ssize_t r; - + /* overflow */ if ((off_t)(sce->st.st_size * 1.1) < sce->st.st_size) return -1; - - /* don't mmap files > 128Mb - * + + /* don't mmap files > 128Mb + * * we could use a sliding window, but currently there is no need for it */ - + if (sce->st.st_size > 128 * 1024 * 1024) return -1; - + buffer_reset(p->ofn); buffer_copy_string_buffer(p->ofn, p->conf.compress_cache_dir); BUFFER_APPEND_SLASH(p->ofn); - + if (0 == strncmp(con->physical.path->ptr, con->physical.doc_root->ptr, con->physical.doc_root->used-1)) { size_t offset = p->ofn->used - 1; char *dir, *nextdir; - + buffer_append_string(p->ofn, con->physical.path->ptr + con->physical.doc_root->used - 1); - + buffer_copy_string_buffer(p->b, p->ofn); - + /* mkdir -p ... */ for (dir = p->b->ptr + offset; NULL != (nextdir = strchr(dir, '/')); dir = nextdir + 1) { *nextdir = '\0'; - + if (-1 == mkdir(p->b->ptr, 0700)) { if (errno != EEXIST) { log_error_write(srv, __FILE__, __LINE__, "sbss", "creating cache-directory", p->b, "failed", strerror(errno)); - + return -1; } } - + *nextdir = '/'; } } else { buffer_append_string_buffer(p->ofn, con->uri.path); } - + switch(type) { case HTTP_ACCEPT_ENCODING_GZIP: buffer_append_string(p->ofn, "-gzip-"); @@ -381,9 +381,9 @@ static int deflate_file_to_file(server *srv, connection *con, plugin_data *p, bu log_error_write(srv, __FILE__, __LINE__, "sd", "unknown compression type", type); return -1; } - + buffer_append_string_buffer(p->ofn, sce->etag); - + if (-1 == (ofd = open(p->ofn->ptr, O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0600))) { if (errno == EEXIST) { /* cache-entry exists */ @@ -391,45 +391,45 @@ static int deflate_file_to_file(server *srv, connection *con, plugin_data *p, bu log_error_write(srv, __FILE__, __LINE__, "bs", p->ofn, "compress-cache hit"); #endif buffer_copy_string_buffer(con->physical.path, p->ofn); - + return 0; } - + log_error_write(srv, __FILE__, __LINE__, "sbss", "creating cachefile", p->ofn, "failed", strerror(errno)); - + return -1; } #if 0 log_error_write(srv, __FILE__, __LINE__, "bs", p->ofn, "compress-cache miss"); -#endif +#endif if (-1 == (ifd = open(filename, O_RDONLY | O_BINARY))) { log_error_write(srv, __FILE__, __LINE__, "sbss", "opening plain-file", fn, "failed", strerror(errno)); - + close(ofd); - + return -1; } - - + + if (MAP_FAILED == (start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) { log_error_write(srv, __FILE__, __LINE__, "sbss", "mmaping", fn, "failed", strerror(errno)); - + close(ofd); close(ifd); return -1; } - + switch(type) { #ifdef USE_ZLIB - case HTTP_ACCEPT_ENCODING_GZIP: + case HTTP_ACCEPT_ENCODING_GZIP: ret = deflate_file_to_buffer_gzip(srv, con, p, start, sce->st.st_size, sce->st.st_mtime); break; - case HTTP_ACCEPT_ENCODING_DEFLATE: + case HTTP_ACCEPT_ENCODING_DEFLATE: ret = deflate_file_to_buffer_deflate(srv, con, p, start, sce->st.st_size); break; #endif #ifdef USE_BZ2LIB - case HTTP_ACCEPT_ENCODING_BZIP2: + case HTTP_ACCEPT_ENCODING_BZIP2: ret = deflate_file_to_buffer_bzip2(srv, con, p, start, sce->st.st_size); break; #endif @@ -437,26 +437,26 @@ static int deflate_file_to_file(server *srv, connection *con, plugin_data *p, bu ret = -1; break; } - + if (-1 == (r = write(ofd, p->b->ptr, p->b->used))) { - munmap(start, sce->st.st_size); + munmap(start, sce->st.st_size); close(ofd); close(ifd); return -1; } - + if ((size_t)r != p->b->used) { - + } - + munmap(start, sce->st.st_size); close(ofd); close(ifd); - + if (ret != 0) return -1; - + buffer_copy_string_buffer(con->physical.path, p->ofn); - + return 0; } @@ -465,43 +465,43 @@ static int deflate_file_to_buffer(server *srv, connection *con, plugin_data *p, int ret = -1; void *start; buffer *b; - + /* overflow */ if ((off_t)(sce->st.st_size * 1.1) < sce->st.st_size) return -1; - + /* don't mmap files > 128M - * + * * we could use a sliding window, but currently there is no need for it */ - + if (sce->st.st_size > 128 * 1024 * 1024) return -1; - - + + if (-1 == (ifd = open(fn->ptr, O_RDONLY | O_BINARY))) { log_error_write(srv, __FILE__, __LINE__, "sbss", "opening plain-file", fn, "failed", strerror(errno)); - + return -1; } - - + + if (MAP_FAILED == (start = mmap(NULL, sce->st.st_size, PROT_READ, MAP_SHARED, ifd, 0))) { log_error_write(srv, __FILE__, __LINE__, "sbss", "mmaping", fn, "failed", strerror(errno)); - + close(ifd); return -1; } - + switch(type) { #ifdef USE_ZLIB - case HTTP_ACCEPT_ENCODING_GZIP: + case HTTP_ACCEPT_ENCODING_GZIP: ret = deflate_file_to_buffer_gzip(srv, con, p, start, sce->st.st_size, sce->st.st_mtime); break; - case HTTP_ACCEPT_ENCODING_DEFLATE: + case HTTP_ACCEPT_ENCODING_DEFLATE: ret = deflate_file_to_buffer_deflate(srv, con, p, start, sce->st.st_size); break; #endif #ifdef USE_BZ2LIB - case HTTP_ACCEPT_ENCODING_BZIP2: + case HTTP_ACCEPT_ENCODING_BZIP2: ret = deflate_file_to_buffer_bzip2(srv, con, p, start, sce->st.st_size); break; #endif @@ -509,21 +509,21 @@ static int deflate_file_to_buffer(server *srv, connection *con, plugin_data *p, ret = -1; break; } - + munmap(start, sce->st.st_size); close(ifd); - + if (ret != 0) return -1; - + chunkqueue_reset(con->write_queue); b = chunkqueue_get_append_buffer(con->write_queue); buffer_copy_memory(b, p->b->ptr, p->b->used + 1); - + buffer_reset(con->physical.path); - + con->file_finished = 1; con->file_started = 1; - + return 0; } @@ -537,19 +537,19 @@ static int mod_compress_patch_connection(server *srv, connection *con, plugin_da PATCH(compress_cache_dir); PATCH(compress); PATCH(compress_max_filesize); - + /* 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("compress.cache-dir"))) { PATCH(compress_cache_dir); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("compress.filetype"))) { @@ -559,7 +559,7 @@ static int mod_compress_patch_connection(server *srv, connection *con, plugin_da } } } - + return 0; } #undef PATCH @@ -569,9 +569,9 @@ PHYSICALPATH_FUNC(mod_compress_physical) { size_t m; off_t max_fsize; stat_cache_entry *sce = NULL; - + /* only GET and POST can get compressed */ - if (con->request.http_method != HTTP_METHOD_GET && + if (con->request.http_method != HTTP_METHOD_GET && con->request.http_method != HTTP_METHOD_POST) { return HANDLER_GO_ON; } @@ -579,46 +579,46 @@ PHYSICALPATH_FUNC(mod_compress_physical) { if (buffer_is_empty(con->physical.path)) { return HANDLER_GO_ON; } - + mod_compress_patch_connection(srv, con, p); - + max_fsize = p->conf.compress_max_filesize; stat_cache_get_entry(srv, con, con->physical.path, &sce); /* don't compress files that are too large as we need to much time to handle them */ if (max_fsize && (sce->st.st_size >> 10) > max_fsize) return HANDLER_GO_ON; - + /* check if mimetype is in compress-config */ for (m = 0; m < p->conf.compress->used; m++) { data_string *compress_ds = (data_string *)p->conf.compress->data[m]; - + if (!compress_ds) { log_error_write(srv, __FILE__, __LINE__, "sbb", "evil", con->physical.path, con->uri.path); - + return HANDLER_GO_ON; } - + if (buffer_is_equal(compress_ds->value, sce->content_type)) { /* mimetype found */ data_string *ds; - + /* the response might change according to Accept-Encoding */ response_header_insert(srv, con, CONST_STR_LEN("Vary"), CONST_STR_LEN("Accept-Encoding")); - + if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Accept-Encoding"))) { int accept_encoding = 0; char *value = ds->value->ptr; int srv_encodings = 0; int matched_encodings = 0; - + /* get client side support encodings */ if (NULL != strstr(value, "gzip")) accept_encoding |= HTTP_ACCEPT_ENCODING_GZIP; if (NULL != strstr(value, "deflate")) accept_encoding |= HTTP_ACCEPT_ENCODING_DEFLATE; if (NULL != strstr(value, "compress")) accept_encoding |= HTTP_ACCEPT_ENCODING_COMPRESS; if (NULL != strstr(value, "bzip2")) accept_encoding |= HTTP_ACCEPT_ENCODING_BZIP2; if (NULL != strstr(value, "identity")) accept_encoding |= HTTP_ACCEPT_ENCODING_IDENTITY; - + /* get server side supported ones */ #ifdef USE_BZ2LIB srv_encodings |= HTTP_ACCEPT_ENCODING_BZIP2; @@ -627,18 +627,18 @@ PHYSICALPATH_FUNC(mod_compress_physical) { srv_encodings |= HTTP_ACCEPT_ENCODING_GZIP; srv_encodings |= HTTP_ACCEPT_ENCODING_DEFLATE; #endif - + /* find matching entries */ matched_encodings = accept_encoding & srv_encodings; - + if (matched_encodings) { const char *dflt_gzip = "gzip"; const char *dflt_deflate = "deflate"; const char *dflt_bzip2 = "bzip2"; - + const char *compression_name = NULL; int compression_type = 0; - + /* select best matching encoding */ if (matched_encodings & HTTP_ACCEPT_ENCODING_BZIP2) { compression_type = HTTP_ACCEPT_ENCODING_BZIP2; @@ -650,15 +650,15 @@ PHYSICALPATH_FUNC(mod_compress_physical) { compression_type = HTTP_ACCEPT_ENCODING_DEFLATE; compression_name = dflt_deflate; } - + /* deflate it */ if (p->conf.compress_cache_dir->used) { if (0 == deflate_file_to_file(srv, con, p, con->physical.path, sce, compression_type)) { buffer *mtime; - + response_header_overwrite(srv, con, CONST_STR_LEN("Content-Encoding"), compression_name, strlen(compression_name)); - + mtime = strftime_cache_get(srv, sce->st.st_mtime); response_header_overwrite(srv, con, CONST_STR_LEN("Last-Modified"), CONST_BUF_LEN(mtime)); @@ -671,10 +671,10 @@ PHYSICALPATH_FUNC(mod_compress_physical) { } } else if (0 == deflate_file_to_buffer(srv, con, p, con->physical.path, sce, compression_type)) { - + response_header_overwrite(srv, con, CONST_STR_LEN("Content-Encoding"), compression_name, strlen(compression_name)); response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type)); - + return HANDLER_FINISHED; } break; @@ -682,20 +682,20 @@ PHYSICALPATH_FUNC(mod_compress_physical) { } } } - + return HANDLER_GO_ON; } int mod_compress_plugin_init(plugin *p) { p->version = LIGHTTPD_VERSION_ID; p->name = buffer_init_string("compress"); - + p->init = mod_compress_init; p->set_defaults = mod_compress_setdefaults; p->handle_subrequest_start = mod_compress_physical; p->cleanup = mod_compress_free; - + p->data = NULL; - + return 0; } diff --git a/src/mod_dirlisting.c b/src/mod_dirlisting.c index 69eb1e9..165699b 100644 --- a/src/mod_dirlisting.c +++ b/src/mod_dirlisting.c @@ -54,7 +54,7 @@ typedef struct { unsigned short hide_readme_file; unsigned short show_header; unsigned short hide_header_file; - + excludes_buffer *excludes; buffer *external_css; @@ -63,13 +63,13 @@ typedef struct { typedef struct { PLUGIN_DATA; - + buffer *tmp_buf; buffer *content_charset; - + plugin_config **config_storage; - - plugin_config conf; + + plugin_config conf; } plugin_data; excludes_buffer *excludes_buffer_init(void) { @@ -146,44 +146,44 @@ void excludes_buffer_free(excludes_buffer *exb) { /* init the plugin data */ INIT_FUNC(mod_dirlisting_init) { plugin_data *p; - + p = calloc(1, sizeof(*p)); p->tmp_buf = buffer_init(); p->content_charset = buffer_init(); - + return p; } /* detroy the plugin data */ FREE_FUNC(mod_dirlisting_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]; - + if (!s) continue; - + excludes_buffer_free(s->excludes); buffer_free(s->external_css); buffer_free(s->encoding); - + free(s); } free(p->config_storage); } - + buffer_free(p->tmp_buf); buffer_free(p->content_charset); - + free(p); - + return HANDLER_GO_ON; } @@ -215,10 +215,10 @@ static int parse_config_entry(server *srv, plugin_config *s, array *ca, const ch if (0 != excludes_buffer_append(s->excludes, ((data_string *)(da->value->data[j]))->value)) { #ifdef HAVE_PCRE_H - log_error_write(srv, __FILE__, __LINE__, "sb", + log_error_write(srv, __FILE__, __LINE__, "sb", "pcre-compile failed for", ((data_string *)(da->value->data[j]))->value); #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 } @@ -233,8 +233,8 @@ static int parse_config_entry(server *srv, plugin_config *s, array *ca, const ch SETDEFAULTS_FUNC(mod_dirlisting_set_defaults) { plugin_data *p = p_d; size_t i = 0; - - config_values_t cv[] = { + + config_values_t cv[] = { { "dir-listing.exclude", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ { "dir-listing.activate", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 1 */ { "dir-listing.hide-dotfiles", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 2 */ @@ -245,18 +245,18 @@ SETDEFAULTS_FUNC(mod_dirlisting_set_defaults) { { "dir-listing.show-header", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 7 */ { "dir-listing.hide-header-file", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 8 */ { "server.dir-listing", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 9 */ - + { 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; array *ca; - + s = calloc(1, sizeof(plugin_config)); s->excludes = excludes_buffer_init(); s->dir_listing = 0; @@ -267,7 +267,7 @@ SETDEFAULTS_FUNC(mod_dirlisting_set_defaults) { s->show_header = 0; s->hide_header_file = 0; s->encoding = buffer_init(); - + cv[0].destination = s->excludes; cv[1].destination = &(s->dir_listing); cv[2].destination = &(s->hide_dot_files); @@ -307,19 +307,19 @@ static int mod_dirlisting_patch_connection(server *srv, connection *con, plugin_ PATCH(show_header); PATCH(hide_header_file); PATCH(excludes); - + /* 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("dir-listing.activate")) || buffer_is_equal_string(du->key, CONST_STR_LEN("server.dir-listing"))) { PATCH(dir_listing); @@ -342,7 +342,7 @@ static int mod_dirlisting_patch_connection(server *srv, connection *con, plugin_ } } } - + return 0; } #undef PATCH @@ -432,7 +432,7 @@ static int http_list_directory_sizefmt(char *buf, off_t size) { static void http_list_directory_header(server *srv, connection *con, plugin_data *p, buffer *out) { UNUSED(srv); - + BUFFER_APPEND_STRING_CONST(out, "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n" "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\">\n" @@ -492,11 +492,11 @@ static void http_list_directory_header(server *srv, connection *con, plugin_data if (p->conf.show_header) { stream s; /* if we have a HEADER file, display it in <pre class="header"></pre> */ - + buffer_copy_string_buffer(p->tmp_buf, con->physical.path); BUFFER_APPEND_SLASH(p->tmp_buf); BUFFER_APPEND_STRING_CONST(p->tmp_buf, "HEADER.txt"); - + if (-1 != stream_open(&s, p->tmp_buf)) { BUFFER_APPEND_STRING_CONST(out, "<pre class=\"header\">"); buffer_append_string_encoded(out, s.start, s.size, ENCODING_MINIMAL_XML); @@ -510,7 +510,7 @@ static void http_list_directory_header(server *srv, connection *con, plugin_data BUFFER_APPEND_STRING_CONST(out, "</h2>\n" "<div class=\"list\">\n" - "<table cellpadding=\"0\" cellspacing=\"0\">\n" + "<table summary=\"Directory Listing\" cellpadding=\"0\" cellspacing=\"0\">\n" "<thead>" "<tr>" "<th class=\"n\">Name</th>" @@ -531,21 +531,21 @@ static void http_list_directory_header(server *srv, connection *con, plugin_data static void http_list_directory_footer(server *srv, connection *con, plugin_data *p, buffer *out) { UNUSED(srv); - + BUFFER_APPEND_STRING_CONST(out, "</tbody>\n" "</table>\n" "</div>\n" ); - + if (p->conf.show_readme) { stream s; /* if we have a README file, display it in <pre class="readme"></pre> */ - + buffer_copy_string_buffer(p->tmp_buf, con->physical.path); BUFFER_APPEND_SLASH(p->tmp_buf); BUFFER_APPEND_STRING_CONST(p->tmp_buf, "README.txt"); - + if (-1 != stream_open(&s, p->tmp_buf)) { BUFFER_APPEND_STRING_CONST(out, "<pre class=\"readme\">"); buffer_append_string_encoded(out, s.start, s.size, ENCODING_MINIMAL_XML); @@ -553,7 +553,7 @@ static void http_list_directory_footer(server *srv, connection *con, plugin_data } stream_close(&s); } - + BUFFER_APPEND_STRING_CONST(out, "<div class=\"foot\">" ); @@ -595,7 +595,7 @@ static int http_list_directory(server *srv, connection *con, plugin_data *p, buf #endif if (dir->used == 0) return -1; - + i = dir->used - 1; #ifdef HAVE_PATHCONF @@ -611,14 +611,14 @@ static int http_list_directory(server *srv, connection *con, plugin_data *p, buf #else name_max = NAME_MAX; #endif - + path = malloc(dir->used + name_max); assert(path); strcpy(path, dir->ptr); path_file = path + i; if (NULL == (dp = opendir(path))) { - log_error_write(srv, __FILE__, __LINE__, "sbs", + log_error_write(srv, __FILE__, __LINE__, "sbs", "opendir failed:", dir, strerror(errno)); free(path); @@ -633,7 +633,7 @@ static int http_list_directory(server *srv, connection *con, plugin_data *p, buf assert(files.ent); files.size = DIRLIST_BLOB_SIZE; files.used = 0; - + while ((dent = readdir(dp)) != NULL) { unsigned short exclude_match = 0; @@ -686,12 +686,12 @@ static int http_list_directory(server *srv, connection *con, plugin_data *p, buf #endif i = strlen(dent->d_name); - + /* NOTE: the manual says, d_name is never more than NAME_MAX * so this should actually not be a buffer-overflow-risk */ if (i > (size_t)name_max) continue; - + memcpy(path_file, dent->d_name, i + 1); if (stat(path, &st) != 0) continue; @@ -740,7 +740,7 @@ static int http_list_directory(server *srv, connection *con, plugin_data *p, buf #else strftime(datebuf, sizeof(datebuf), "%Y-%b-%d %H:%M:%S", localtime(&(tmp->mtime))); #endif - + BUFFER_APPEND_STRING_CONST(out, "<tr><td class=\"n\"><a href=\""); buffer_append_string_encoded(out, DIRLIST_ENT_NAME(tmp), tmp->namelen, ENCODING_REL_URI_PART); BUFFER_APPEND_STRING_CONST(out, "/\">"); @@ -758,7 +758,7 @@ static int http_list_directory(server *srv, connection *con, plugin_data *p, buf content_type = NULL; #ifdef HAVE_XATTR - + if (con->conf.use_xattr) { memcpy(path_file, DIRLIST_ENT_NAME(tmp), tmp->namelen + 1); attrlen = sizeof(attrval) - 1; @@ -768,7 +768,7 @@ static int http_list_directory(server *srv, connection *con, plugin_data *p, buf } } #endif - + if (content_type == NULL) { content_type = "application/octet-stream"; for (k = 0; k < con->conf.mimetypes->used; k++) { @@ -788,7 +788,7 @@ static int http_list_directory(server *srv, connection *con, plugin_data *p, buf } } } - + #ifdef HAVE_LOCALTIME_R localtime_r(&(tmp->mtime), &tm); strftime(datebuf, sizeof(datebuf), "%Y-%b-%d %H:%M:%S", &tm); @@ -837,36 +837,36 @@ static int http_list_directory(server *srv, connection *con, plugin_data *p, buf URIHANDLER_FUNC(mod_dirlisting_subrequest) { plugin_data *p = p_d; stat_cache_entry *sce = NULL; - + UNUSED(srv); - + if (con->physical.path->used == 0) return HANDLER_GO_ON; if (con->uri.path->used == 0) return HANDLER_GO_ON; if (con->uri.path->ptr[con->uri.path->used - 2] != '/') return HANDLER_GO_ON; - + mod_dirlisting_patch_connection(srv, con, p); if (!p->conf.dir_listing) return HANDLER_GO_ON; - + if (con->conf.log_request_handling) { log_error_write(srv, __FILE__, __LINE__, "s", "-- handling the request as Dir-Listing"); log_error_write(srv, __FILE__, __LINE__, "sb", "URI :", con->uri.path); } - + if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) { fprintf(stderr, "%s.%d: %s\n", __FILE__, __LINE__, con->physical.path->ptr); SEGFAULT(); } - + if (!S_ISDIR(sce->st.st_mode)) return HANDLER_GO_ON; - + if (http_list_directory(srv, con, p, con->physical.path)) { /* dirlisting failed */ con->http_status = 403; } - + buffer_reset(con->physical.path); - + /* not found */ return HANDLER_FINISHED; } @@ -876,13 +876,13 @@ URIHANDLER_FUNC(mod_dirlisting_subrequest) { int mod_dirlisting_plugin_init(plugin *p) { p->version = LIGHTTPD_VERSION_ID; p->name = buffer_init_string("dirlisting"); - + p->init = mod_dirlisting_init; p->handle_subrequest_start = mod_dirlisting_subrequest; p->set_defaults = mod_dirlisting_set_defaults; p->cleanup = mod_dirlisting_free; - + p->data = NULL; - + return 0; } diff --git a/src/mod_evasive.c b/src/mod_evasive.c index b9d19ca..3415953 100644 --- a/src/mod_evasive.c +++ b/src/mod_evasive.c @@ -31,68 +31,68 @@ typedef struct { typedef struct { PLUGIN_DATA; - + plugin_config **config_storage; - - plugin_config conf; + + plugin_config conf; } plugin_data; INIT_FUNC(mod_evasive_init) { plugin_data *p; - + p = calloc(1, sizeof(*p)); - + return p; } FREE_FUNC(mod_evasive_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]; - + free(s); } free(p->config_storage); } - + free(p); - + return HANDLER_GO_ON; } SETDEFAULTS_FUNC(mod_evasive_set_defaults) { plugin_data *p = p_d; size_t i = 0; - - config_values_t cv[] = { + + config_values_t cv[] = { { "evasive.max-conns-per-ip", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } }; - + 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->max_conns = 0; - + cv[0].destination = &(s->max_conns); - + 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; } @@ -103,25 +103,25 @@ static int mod_evasive_patch_connection(server *srv, connection *con, plugin_dat plugin_config *s = p->config_storage[0]; PATCH(max_conns); - + /* 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("evasive.max-conns-per-ip"))) { PATCH(max_conns); } } } - + return 0; } #undef PATCH @@ -132,10 +132,10 @@ URIHANDLER_FUNC(mod_evasive_uri_handler) { size_t j; if (con->uri.path->used == 0) return HANDLER_GO_ON; - + mod_evasive_patch_connection(srv, con, p); - - /* no limit set, nothing to block */ + + /* no limit set, nothing to block */ if (p->conf.max_conns == 0) return HANDLER_GO_ON; for (j = 0; j < srv->conns->used; j++) { @@ -147,7 +147,7 @@ URIHANDLER_FUNC(mod_evasive_uri_handler) { if (c->dst_addr.ipv4.sin_addr.s_addr == con->dst_addr.ipv4.sin_addr.s_addr && c->state > CON_STATE_REQUEST_END) { conns_by_ip++; - + if (conns_by_ip > p->conf.max_conns) { log_error_write(srv, __FILE__, __LINE__, "ss", inet_ntop_cache_get_ip(srv, &(con->dst_addr)), @@ -158,7 +158,7 @@ URIHANDLER_FUNC(mod_evasive_uri_handler) { } } } - + return HANDLER_GO_ON; } @@ -166,13 +166,13 @@ URIHANDLER_FUNC(mod_evasive_uri_handler) { int mod_evasive_plugin_init(plugin *p) { p->version = LIGHTTPD_VERSION_ID; p->name = buffer_init_string("evasive"); - + p->init = mod_evasive_init; p->set_defaults = mod_evasive_set_defaults; p->handle_uri_clean = mod_evasive_uri_handler; p->cleanup = mod_evasive_free; - + p->data = NULL; - + return 0; } diff --git a/src/mod_evhost.c b/src/mod_evhost.c index bc8adb6..daf4494 100644 --- a/src/mod_evhost.c +++ b/src/mod_evhost.c @@ -10,7 +10,7 @@ typedef struct { /* unparsed pieces */ buffer *path_pieces_raw; - + /* pieces for path creation */ size_t len; buffer **path_pieces; @@ -21,14 +21,14 @@ typedef struct { buffer *tmp_buf; plugin_config **config_storage; - plugin_config conf; + plugin_config conf; } plugin_data; INIT_FUNC(mod_evhost_init) { plugin_data *p; - + p = calloc(1, sizeof(*p)); - + p->tmp_buf = buffer_init(); return p; @@ -36,34 +36,34 @@ INIT_FUNC(mod_evhost_init) { FREE_FUNC(mod_evhost_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]; if (!s) continue; - + if(s->path_pieces) { size_t j; for (j = 0; j < s->len; j++) { buffer_free(s->path_pieces[j]); } - + free(s->path_pieces); } - + buffer_free(s->path_pieces_raw); - + free(s); } free(p->config_storage); } - + buffer_free(p->tmp_buf); free(p); @@ -73,30 +73,30 @@ FREE_FUNC(mod_evhost_free) { static void mod_evhost_parse_pattern(plugin_config *s) { char *ptr = s->path_pieces_raw->ptr,*pos; - + s->path_pieces = NULL; - + for(pos=ptr;*ptr;ptr++) { if(*ptr == '%') { s->path_pieces = realloc(s->path_pieces,(s->len+2) * sizeof(*s->path_pieces)); s->path_pieces[s->len] = buffer_init(); s->path_pieces[s->len+1] = buffer_init(); - + buffer_copy_string_len(s->path_pieces[s->len],pos,ptr-pos); pos = ptr + 2; - + buffer_copy_string_len(s->path_pieces[s->len+1],ptr++,2); - + s->len += 2; } } - + if(*pos != '\0') { s->path_pieces = realloc(s->path_pieces,(s->len+1) * sizeof(*s->path_pieces)); s->path_pieces[s->len] = buffer_init(); - + buffer_append_memory(s->path_pieces[s->len],pos,ptr-pos); - + s->len += 1; } } @@ -104,9 +104,9 @@ static void mod_evhost_parse_pattern(plugin_config *s) { SETDEFAULTS_FUNC(mod_evhost_set_defaults) { plugin_data *p = p_d; size_t i; - + /** - * + * * # * # define a pattern for the host url finding * # %% => % sign @@ -117,39 +117,39 @@ SETDEFAULTS_FUNC(mod_evhost_set_defaults) { * # %4 => subdomain 2 name * # * evhost.path-pattern = "/home/ckruse/dev/www/%3/htdocs/" - * + * */ - - config_values_t cv[] = { + + config_values_t cv[] = { { "evhost.path-pattern", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, { 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->path_pieces_raw = buffer_init(); s->path_pieces = NULL; s->len = 0; - + cv[0].destination = s->path_pieces_raw; - + 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->path_pieces_raw->used != 0) { mod_evhost_parse_pattern(s); } } - + return HANDLER_GO_ON; } @@ -158,7 +158,7 @@ SETDEFAULTS_FUNC(mod_evhost_set_defaults) { * - %0 - full hostname (authority w/o port) * - %1 - tld * - %2 - domain.tld - * - %3 - + * - %3 - */ static int mod_evhost_parse_host(connection *con,array *host) { @@ -168,7 +168,7 @@ static int mod_evhost_parse_host(connection *con,array *host) { int first = 1; data_string *ds; int i; - + /* first, find the domain + tld */ for(;ptr > con->uri.authority->ptr;ptr--) { if(*ptr == '.') { @@ -179,18 +179,18 @@ static int mod_evhost_parse_host(connection *con,array *host) { first = 1; } } - + ds = data_string_init(); buffer_copy_string(ds->key,"%0"); - + /* if we stopped at a dot, skip the dot */ if (*ptr == '.') ptr++; buffer_copy_string_len(ds->value, ptr, colon-ptr); - + array_insert_unique(host,(data_unset *)ds); - + /* if the : is not the start of the authority, go on parsing the hostname */ - + if (colon != con->uri.authority->ptr) { for(ptr = colon - 1, i = 1; ptr > con->uri.authority->ptr; ptr--) { if(*ptr == '.') { @@ -200,24 +200,24 @@ static int mod_evhost_parse_host(connection *con,array *host) { buffer_copy_string(ds->key,"%"); buffer_append_long(ds->key, i++); buffer_copy_string_len(ds->value,ptr+1,colon-ptr-1); - + array_insert_unique(host,(data_unset *)ds); } colon = ptr; } } - + /* if the . is not the first charactor of the hostname */ if (colon != ptr) { ds = data_string_init(); buffer_copy_string(ds->key,"%"); buffer_append_long(ds->key, i++); buffer_copy_string_len(ds->value,ptr,colon-ptr); - + array_insert_unique(host,(data_unset *)ds); } } - + return 0; } @@ -226,29 +226,29 @@ static int mod_evhost_parse_host(connection *con,array *host) { static int mod_evhost_patch_connection(server *srv, connection *con, plugin_data *p) { size_t i, j; plugin_config *s = p->config_storage[0]; - + PATCH(path_pieces); PATCH(len); - + /* 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("evhost.path-pattern"))) { PATCH(path_pieces); PATCH(len); } } } - + return 0; } #undef PATCH @@ -261,29 +261,29 @@ static handler_t mod_evhost_uri_handler(server *srv, connection *con, void *p_d) register char *ptr; int not_good = 0; stat_cache_entry *sce = NULL; - + /* not authority set */ if (con->uri.authority->used == 0) return HANDLER_GO_ON; - + mod_evhost_patch_connection(srv, con, p); - + /* missing even default(global) conf */ if (0 == p->conf.len) { return HANDLER_GO_ON; } parsed_host = array_init(); - + mod_evhost_parse_host(con, parsed_host); - + /* build document-root */ buffer_reset(p->tmp_buf); - + for (i = 0; i < p->conf.len; i++) { ptr = p->conf.path_pieces[i]->ptr; if (*ptr == '%') { data_string *ds; - + if (*(ptr+1) == '%') { /* %% */ BUFFER_APPEND_STRING_CONST(p->tmp_buf,"%"); @@ -298,11 +298,11 @@ static handler_t mod_evhost_uri_handler(server *srv, connection *con, void *p_d) buffer_append_string_buffer(p->tmp_buf,p->conf.path_pieces[i]); } } - + BUFFER_APPEND_SLASH(p->tmp_buf); - + array_free(parsed_host); - + if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->tmp_buf, &sce)) { log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), p->tmp_buf); not_good = 1; @@ -310,11 +310,11 @@ static handler_t mod_evhost_uri_handler(server *srv, connection *con, void *p_d) log_error_write(srv, __FILE__, __LINE__, "sb", "not a directory:", p->tmp_buf); not_good = 1; } - + if (!not_good) { buffer_copy_string_buffer(con->physical.doc_root, p->tmp_buf); } - + return HANDLER_GO_ON; } @@ -325,9 +325,9 @@ int mod_evhost_plugin_init(plugin *p) { p->set_defaults = mod_evhost_set_defaults; p->handle_docroot = mod_evhost_uri_handler; p->cleanup = mod_evhost_free; - + p->data = NULL; - + return 0; } diff --git a/src/mod_expire.c b/src/mod_expire.c index 619b542..037e21a 100644 --- a/src/mod_expire.c +++ b/src/mod_expire.c @@ -12,8 +12,8 @@ #include "stat_cache.h" /** - * this is a expire module for a lighttpd - * + * this is a expire module for a lighttpd + * * set 'Expires:' HTTP Headers on demand */ @@ -27,51 +27,51 @@ typedef struct { typedef struct { PLUGIN_DATA; - + buffer *expire_tstmp; - + plugin_config **config_storage; - - plugin_config conf; + + plugin_config conf; } plugin_data; /* init the plugin data */ INIT_FUNC(mod_expire_init) { plugin_data *p; - + p = calloc(1, sizeof(*p)); - + p->expire_tstmp = buffer_init(); - + buffer_prepare_copy(p->expire_tstmp, 255); - + return p; } /* detroy the plugin data */ FREE_FUNC(mod_expire_free) { plugin_data *p = p_d; - + UNUSED(srv); if (!p) return HANDLER_GO_ON; - + buffer_free(p->expire_tstmp); - + 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->expire_url); - + free(s); } free(p->config_storage); } - + free(p); - + return HANDLER_GO_ON; } @@ -79,25 +79,25 @@ static int mod_expire_get_offset(server *srv, plugin_data *p, buffer *expire, in char *ts; int type = -1; int retts = 0; - + UNUSED(p); - /* + /* * parse - * + * * '(access|modification) [plus] {<num> <type>}*' - * + * * e.g. 'access 1 years' */ - + if (expire->used == 0) { - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "empty:"); return -1; } - + ts = expire->ptr; - + if (0 == strncmp(ts, "access ", 7)) { type = 0; ts += 7; @@ -110,39 +110,39 @@ static int mod_expire_get_offset(server *srv, plugin_data *p, buffer *expire, in "invalid <base>:", ts); return -1; } - + if (0 == strncmp(ts, "plus ", 5)) { /* skip the optional plus */ ts += 5; } - + /* the rest is just <number> (years|months|days|hours|minutes|seconds) */ while (1) { char *space, *err; int num; - + if (NULL == (space = strchr(ts, ' '))) { - log_error_write(srv, __FILE__, __LINE__, "ss", + log_error_write(srv, __FILE__, __LINE__, "ss", "missing space after <num>:", ts); return -1; } - + num = strtol(ts, &err, 10); if (*err != ' ') { - log_error_write(srv, __FILE__, __LINE__, "ss", + log_error_write(srv, __FILE__, __LINE__, "ss", "missing <type> after <num>:", ts); return -1; } - + ts = space + 1; - + if (NULL != (space = strchr(ts, ' '))) { int slen; /* */ - + slen = space - ts; - - if (slen == 5 && + + if (slen == 5 && 0 == strncmp(ts, "years", slen)) { num *= 60 * 60 * 24 * 30 * 12; } else if (slen == 6 && @@ -161,13 +161,13 @@ static int mod_expire_get_offset(server *srv, plugin_data *p, buffer *expire, in 0 == strncmp(ts, "seconds", slen)) { num *= 1; } else { - log_error_write(srv, __FILE__, __LINE__, "ss", + log_error_write(srv, __FILE__, __LINE__, "ss", "unknown type:", ts); return -1; } - + retts += num; - + ts = space + 1; } else { if (0 == strcmp(ts, "years")) { @@ -183,19 +183,19 @@ static int mod_expire_get_offset(server *srv, plugin_data *p, buffer *expire, in } else if (0 == strcmp(ts, "seconds")) { num *= 1; } else { - log_error_write(srv, __FILE__, __LINE__, "ss", + log_error_write(srv, __FILE__, __LINE__, "ss", "unknown type:", ts); return -1; } - + retts += num; - + break; } } - + if (offset != NULL) *offset = retts; - + return type; } @@ -205,43 +205,43 @@ static int mod_expire_get_offset(server *srv, plugin_data *p, buffer *expire, in SETDEFAULTS_FUNC(mod_expire_set_defaults) { plugin_data *p = p_d; size_t i = 0, k; - - config_values_t cv[] = { + + config_values_t cv[] = { { "expire.url", 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)); s->expire_url = array_init(); - + cv[0].destination = s->expire_url; - + p->config_storage[i] = s; - + if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) { return HANDLER_ERROR; } - + for (k = 0; k < s->expire_url->used; k++) { data_string *ds = (data_string *)s->expire_url->data[k]; - + /* parse lines */ if (-1 == mod_expire_get_offset(srv, p, ds->value, NULL)) { - log_error_write(srv, __FILE__, __LINE__, "sb", + log_error_write(srv, __FILE__, __LINE__, "sb", "parsing expire.url failed:", ds->value); return HANDLER_ERROR; } } } - - + + return HANDLER_GO_ON; } @@ -250,27 +250,27 @@ SETDEFAULTS_FUNC(mod_expire_set_defaults) { static int mod_expire_patch_connection(server *srv, connection *con, plugin_data *p) { size_t i, j; plugin_config *s = p->config_storage[0]; - + PATCH(expire_url); - + /* 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("expire.url"))) { PATCH(expire_url); } } } - + return 0; } #undef PATCH @@ -279,28 +279,28 @@ URIHANDLER_FUNC(mod_expire_path_handler) { plugin_data *p = p_d; int s_len; size_t k; - + if (con->uri.path->used == 0) return HANDLER_GO_ON; - + mod_expire_patch_connection(srv, con, p); - + s_len = con->uri.path->used - 1; - + for (k = 0; k < p->conf.expire_url->used; k++) { data_string *ds = (data_string *)p->conf.expire_url->data[k]; int ct_len = ds->key->used - 1; - + if (ct_len > s_len) continue; if (ds->key->used == 0) continue; - + if (0 == strncmp(con->uri.path->ptr, ds->key->ptr, ct_len)) { int ts; time_t t; size_t len; stat_cache_entry *sce = NULL; - + stat_cache_get_entry(srv, con, con->physical.path, &sce); - + switch(mod_expire_get_offset(srv, p, ds->value, &ts)) { case 0: /* access */ @@ -308,38 +308,38 @@ URIHANDLER_FUNC(mod_expire_path_handler) { break; case 1: /* modification */ - + t = (ts + sce->st.st_mtime); break; default: /* -1 is handled at parse-time */ break; } - - - if (0 == (len = strftime(p->expire_tstmp->ptr, p->expire_tstmp->size - 1, + + + if (0 == (len = strftime(p->expire_tstmp->ptr, p->expire_tstmp->size - 1, "%a, %d %b %Y %H:%M:%S GMT", gmtime(&(t))))) { /* could not set expire header, out of mem */ - + return HANDLER_GO_ON; - + } - + p->expire_tstmp->used = len + 1; - - /* HTTP/1.0 */ + + /* HTTP/1.0 */ response_header_overwrite(srv, con, CONST_STR_LEN("Expires"), CONST_BUF_LEN(p->expire_tstmp)); - /* HTTP/1.1 */ + /* HTTP/1.1 */ buffer_copy_string(p->expire_tstmp, "max-age="); buffer_append_long(p->expire_tstmp, ts); - + response_header_overwrite(srv, con, CONST_STR_LEN("Cache-Control"), CONST_BUF_LEN(p->expire_tstmp)); - + return HANDLER_GO_ON; } } - + /* not found */ return HANDLER_GO_ON; } @@ -349,13 +349,13 @@ URIHANDLER_FUNC(mod_expire_path_handler) { int mod_expire_plugin_init(plugin *p) { p->version = LIGHTTPD_VERSION_ID; p->name = buffer_init_string("expire"); - + p->init = mod_expire_init; p->handle_subrequest_start = mod_expire_path_handler; p->set_defaults = mod_expire_set_defaults; p->cleanup = mod_expire_free; - + p->data = NULL; - + return 0; } diff --git a/src/mod_fastcgi.c b/src/mod_fastcgi.c index 4f7260b..bd30179 100644 --- a/src/mod_fastcgi.c +++ b/src/mod_fastcgi.c @@ -25,7 +25,15 @@ #include "stat_cache.h" #include "status_counter.h" +#ifdef HAVE_FASTCGI_FASTCGI_H +#include <fastcgi/fastcgi.h> +#else +#ifdef HAVE_FASTCGI_H #include <fastcgi.h> +#else +#include "fastcgi.h" +#endif +#endif /* HAVE_FASTCGI_FASTCGI_H */ #include <stdio.h> #ifdef HAVE_SYS_FILIO_H @@ -48,12 +56,12 @@ /* - * + * * TODO: - * + * * - add timeout for a connect to a non-fastcgi process * (use state_timestamp + state) - * + * */ typedef struct fcgi_proc { @@ -62,7 +70,7 @@ typedef struct fcgi_proc { unsigned port; /* config.port + pno */ buffer *connection_name; /* either tcp:<host>:<port> or unix:<socket> for debuggin purposes */ - + pid_t pid; /* PID of the spawned process (0 if not spawned locally) */ @@ -71,20 +79,20 @@ typedef struct fcgi_proc { time_t last_used; /* see idle_timeout */ size_t requests; /* see max_requests */ struct fcgi_proc *prev, *next; /* see first */ - + time_t disabled_until; /* this proc is disabled until, use something else until than */ - + int is_local; - enum { + enum { PROC_STATE_UNSET, /* init-phase */ PROC_STATE_RUNNING, /* alive */ - PROC_STATE_OVERLOADED, /* listen-queue is full, + PROC_STATE_OVERLOADED, /* listen-queue is full, don't send something to this proc for the next 2 seconds */ PROC_STATE_DIED_WAIT_FOR_PID, /* */ PROC_STATE_DIED, /* marked as dead, should be restarted */ PROC_STATE_KILLED /* was killed as we don't have the load anymore */ - } state; + } state; } fcgi_proc; typedef struct { @@ -95,20 +103,20 @@ typedef struct { * sorted by lowest load * * whenever a job is done move it up in the list - * until it is sorted, move it down as soon as the + * until it is sorted, move it down as soon as the * job is started */ - fcgi_proc *first; - fcgi_proc *unused_procs; + fcgi_proc *first; + fcgi_proc *unused_procs; - /* + /* * spawn at least min_procs, at max_procs. * - * as soon as the load of the first entry + * as soon as the load of the first entry * is max_load_per_proc we spawn a new one - * and add it to the first entry and give it + * and add it to the first entry and give it * the load - * + * */ unsigned short min_procs; @@ -120,44 +128,44 @@ typedef struct { /* * kick the process from the list if it was not - * used for idle_timeout until min_procs is + * used for idle_timeout until min_procs is * reached. this helps to get the processlist * small again we had a small peak load. * */ - + unsigned short idle_timeout; - + /* * time after a disabled remote connection is tried to be re-enabled - * - * + * + * */ - + unsigned short disable_time; /* * same fastcgi processes get a little bit larger - * than wanted. max_requests_per_proc kills a + * than wanted. max_requests_per_proc kills a * process after a number of handled requests. * */ size_t max_requests_per_proc; - + /* config */ - /* - * host:port + /* + * host:port * - * if host is one of the local IP adresses the + * if host is one of the local IP adresses the * whole connection is local * * if tcp/ip should be used host AND port have - * to be specified - * - */ - buffer *host; + * to be specified + * + */ + buffer *host; unsigned short port; /* @@ -170,7 +178,7 @@ typedef struct { */ buffer *unixsocket; - /* if socket is local we can start the fastcgi + /* if socket is local we can start the fastcgi * process ourself * * bin-path is the path to the binary @@ -178,19 +186,19 @@ typedef struct { * check min_procs and max_procs for the number * of process to start-up */ - buffer *bin_path; - - /* bin-path is set bin-environment is taken to + buffer *bin_path; + + /* bin-path is set bin-environment is taken to * create the environement before starting the * FastCGI process - * + * */ array *bin_env; - + array *bin_env_copy; - + /* - * docroot-translation between URL->phys and the + * docroot-translation between URL->phys and the * remote host * * reasons: @@ -209,7 +217,7 @@ typedef struct { unsigned short mode; /* - * check_local tell you if the phys file is stat()ed + * check_local tell you if the phys file is stat()ed * or not. FastCGI doesn't care if the service is * remote. If the web-server side doesn't contain * the fastcgi-files we should not stat() for them @@ -219,11 +227,11 @@ typedef struct { /* * append PATH_INFO to SCRIPT_FILENAME - * + * * php needs this if cgi.fix_pathinfo is provied - * + * */ - + unsigned short break_scriptfilename_for_php; /* @@ -232,12 +240,12 @@ typedef struct { * */ unsigned short allow_xsendfile; - + ssize_t load; /* replace by host->load */ size_t max_id; /* corresponds most of the time to num_procs. - + only if a process is killed max_id waits for the process itself to die and decrements its afterwards */ @@ -246,17 +254,17 @@ typedef struct { /* * one extension can have multiple hosts assigned - * one host can spawn additional processes on the same + * one host can spawn additional processes on the same * socket (if we control it) * * ext -> host -> procs * 1:n 1:n * - * if the fastcgi process is remote that whole goes down + * if the fastcgi process is remote that whole goes down * to * * ext -> host -> procs - * 1:n 1:1 + * 1:n 1:1 * * in case of PHP and FCGI_CHILDREN we have again a procs * but we don't control it directly. @@ -269,7 +277,7 @@ typedef struct { int note_is_sent; fcgi_extension_host **hosts; - + size_t used; size_t size; } fcgi_extension; @@ -283,10 +291,10 @@ typedef struct { typedef struct { - fcgi_exts *exts; + fcgi_exts *exts; array *ext_mapping; - + int debug; } plugin_config; @@ -298,7 +306,7 @@ typedef struct { typedef struct { char **ptr; - + size_t size; size_t used; } char_array; @@ -307,44 +315,44 @@ typedef struct { typedef struct { PLUGIN_DATA; buffer_uint fcgi_request_id; - + buffer *fcgi_env; - + buffer *path; buffer *parse_response; buffer *statuskey; - + plugin_config **config_storage; - + plugin_config conf; /* this is only used as long as no handler_ctx is setup */ } plugin_data; /* connection specific data */ -typedef enum { +typedef enum { FCGI_STATE_UNSET, - FCGI_STATE_INIT, - FCGI_STATE_CONNECT_DELAYED, - FCGI_STATE_PREPARE_WRITE, - FCGI_STATE_WRITE, - FCGI_STATE_READ + FCGI_STATE_INIT, + FCGI_STATE_CONNECT_DELAYED, + FCGI_STATE_PREPARE_WRITE, + FCGI_STATE_WRITE, + FCGI_STATE_READ } fcgi_connection_state_t; typedef struct { fcgi_proc *proc; fcgi_extension_host *host; fcgi_extension *ext; - + fcgi_connection_state_t state; time_t state_timestamp; - + int reconnects; /* number of reconnect attempts */ - + chunkqueue *rb; /* read queue */ chunkqueue *wb; /* write queue */ - + buffer *response_header; - + size_t request_id; int fd; /* fd to the fastcgi process */ int fde_ndx; /* index into the fd-event buffer */ @@ -353,9 +361,9 @@ typedef struct { int got_proc; int send_content_body; - + plugin_config conf; - + connection *remote_conn; /* dumb pointer */ plugin_data *plugin_data; /* dumb pointer */ } handler_ctx; @@ -387,7 +395,7 @@ int fastcgi_status_init(server *srv, buffer *b, fcgi_extension_host *host, fcgi_ CLEAN(".connected"); CLEAN(".load"); -#undef CLEAN +#undef CLEAN #define CLEAN(x) \ fastcgi_status_copy_procname(b, host, NULL); \ @@ -396,33 +404,33 @@ int fastcgi_status_init(server *srv, buffer *b, fcgi_extension_host *host, fcgi_ CLEAN(".load"); -#undef CLEAN +#undef CLEAN return 0; } static handler_ctx * handler_ctx_init() { handler_ctx * hctx; - + hctx = calloc(1, sizeof(*hctx)); assert(hctx); - + hctx->fde_ndx = -1; - + hctx->response_header = buffer_init(); - + hctx->request_id = 0; hctx->state = FCGI_STATE_INIT; hctx->proc = NULL; - + hctx->fd = -1; - + hctx->reconnects = 0; hctx->send_content_body = 1; hctx->rb = chunkqueue_init(); hctx->wb = chunkqueue_init(); - + return hctx; } @@ -431,7 +439,7 @@ static void handler_ctx_free(handler_ctx *hctx) { hctx->host->load--; hctx->host = NULL; } - + buffer_free(hctx->response_header); chunkqueue_free(hctx->rb); @@ -446,21 +454,21 @@ fcgi_proc *fastcgi_process_init() { f = calloc(1, sizeof(*f)); f->unixsocket = buffer_init(); f->connection_name = buffer_init(); - + f->prev = NULL; f->next = NULL; - + return f; } void fastcgi_process_free(fcgi_proc *f) { if (!f) return; - + fastcgi_process_free(f->next); - + buffer_free(f->unixsocket); buffer_free(f->connection_name); - + free(f); } @@ -477,13 +485,13 @@ fcgi_extension_host *fastcgi_host_init() { f->bin_env = array_init(); f->bin_env_copy = array_init(); f->strip_request_uri = buffer_init(); - + return f; } void fastcgi_host_free(fcgi_extension_host *h) { if (!h) return; - + buffer_free(h->id); buffer_free(h->host); buffer_free(h->unixsocket); @@ -492,49 +500,49 @@ void fastcgi_host_free(fcgi_extension_host *h) { buffer_free(h->strip_request_uri); array_free(h->bin_env); array_free(h->bin_env_copy); - + fastcgi_process_free(h->first); fastcgi_process_free(h->unused_procs); - + free(h); - + } fcgi_exts *fastcgi_extensions_init() { fcgi_exts *f; f = calloc(1, sizeof(*f)); - + return f; } void fastcgi_extensions_free(fcgi_exts *f) { size_t i; - + if (!f) return; - + for (i = 0; i < f->used; i++) { fcgi_extension *fe; size_t j; - + fe = f->exts[i]; - + for (j = 0; j < fe->used; j++) { fcgi_extension_host *h; - + h = fe->hosts[j]; - + fastcgi_host_free(h); } - + buffer_free(fe->key); free(fe->hosts); - + free(fe); } - + free(f->exts); - + free(f); } @@ -583,24 +591,24 @@ int fastcgi_extension_insert(fcgi_exts *ext, buffer *key, fcgi_extension_host *f assert(fe->hosts); } - fe->hosts[fe->used++] = fh; + fe->hosts[fe->used++] = fh; return 0; - + } INIT_FUNC(mod_fastcgi_init) { plugin_data *p; - + p = calloc(1, sizeof(*p)); - + p->fcgi_env = buffer_init(); - + p->path = buffer_init(); p->parse_response = buffer_init(); p->statuskey = buffer_init(); - + return p; } @@ -608,81 +616,81 @@ INIT_FUNC(mod_fastcgi_init) { FREE_FUNC(mod_fastcgi_free) { plugin_data *p = p_d; buffer_uint *r = &(p->fcgi_request_id); - + UNUSED(srv); if (r->ptr) free(r->ptr); - + buffer_free(p->fcgi_env); buffer_free(p->path); buffer_free(p->parse_response); buffer_free(p->statuskey); - + if (p->config_storage) { size_t i, j, n; for (i = 0; i < srv->config_context->used; i++) { plugin_config *s = p->config_storage[i]; fcgi_exts *exts; - + if (!s) continue; - + exts = s->exts; for (j = 0; j < exts->used; j++) { fcgi_extension *ex; - + ex = exts->exts[j]; - + for (n = 0; n < ex->used; n++) { fcgi_proc *proc; fcgi_extension_host *host; - + host = ex->hosts[n]; - + for (proc = host->first; proc; proc = proc->next) { if (proc->pid != 0) kill(proc->pid, SIGTERM); - - if (proc->is_local && + + if (proc->is_local && !buffer_is_empty(proc->unixsocket)) { unlink(proc->unixsocket->ptr); } } - + for (proc = host->unused_procs; proc; proc = proc->next) { if (proc->pid != 0) kill(proc->pid, SIGTERM); - - if (proc->is_local && + + if (proc->is_local && !buffer_is_empty(proc->unixsocket)) { unlink(proc->unixsocket->ptr); } } } } - + fastcgi_extensions_free(s->exts); array_free(s->ext_mapping); - + free(s); } free(p->config_storage); } - + free(p); - + return HANDLER_GO_ON; } static int 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)); @@ -690,9 +698,9 @@ static int env_add(char_array *env, const char *key, size_t key_len, const char env->size += 16; env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr)); } - + env->ptr[env->used++] = dst; - + return 0; } @@ -711,15 +719,15 @@ static int parse_binpath(char_array *env, buffer *b) { if (env->size == 0) { env->size = 16; env->ptr = malloc(env->size * sizeof(*env->ptr)); - } else if (env->size == env->used) { + } else if (env->size == env->used) { env->size += 16; env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr)); } - + b->ptr[i] = '\0'; env->ptr[env->used++] = start; - + start = b->ptr + i + 1; break; default: @@ -752,7 +760,7 @@ static int parse_binpath(char_array *env, buffer *b) { return 0; } -static int fcgi_spawn_connection(server *srv, +static int fcgi_spawn_connection(server *srv, plugin_data *p, fcgi_extension_host *host, fcgi_proc *proc) { @@ -764,25 +772,25 @@ static int fcgi_spawn_connection(server *srv, #endif struct sockaddr_in fcgi_addr_in; struct sockaddr *fcgi_addr; - + socklen_t servlen; - + #ifndef HAVE_FORK return -1; #endif - + if (p->conf.debug) { log_error_write(srv, __FILE__, __LINE__, "sdb", "new proc, socket:", proc->port, proc->unixsocket); } - + if (!buffer_is_empty(proc->unixsocket)) { memset(&fcgi_addr, 0, sizeof(fcgi_addr)); - + #ifdef HAVE_SYS_UN_H fcgi_addr_un.sun_family = AF_UNIX; strcpy(fcgi_addr_un.sun_path, proc->unixsocket->ptr); - + #ifdef SUN_LEN servlen = SUN_LEN(&fcgi_addr_un); #else @@ -802,108 +810,108 @@ static int fcgi_spawn_connection(server *srv, #endif } else { fcgi_addr_in.sin_family = AF_INET; - + if (buffer_is_empty(host->host)) { fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY); } else { struct hostent *he; - + /* set a usefull default */ fcgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY); - - + + if (NULL == (he = gethostbyname(host->host->ptr))) { - log_error_write(srv, __FILE__, __LINE__, - "sdb", "gethostbyname failed: ", + log_error_write(srv, __FILE__, __LINE__, + "sdb", "gethostbyname failed: ", h_errno, host->host); return -1; } - + if (he->h_addrtype != AF_INET) { log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype); return -1; } - + if (he->h_length != sizeof(struct in_addr)) { log_error_write(srv, __FILE__, __LINE__, "sd", "addr-length != sizeof(in_addr): ", he->h_length); return -1; } - + memcpy(&(fcgi_addr_in.sin_addr.s_addr), he->h_addr_list[0], he->h_length); - + } fcgi_addr_in.sin_port = htons(proc->port); servlen = sizeof(fcgi_addr_in); - + socket_type = AF_INET; fcgi_addr = (struct sockaddr *) &fcgi_addr_in; - + buffer_copy_string(proc->connection_name, "tcp:"); buffer_append_string_buffer(proc->connection_name, host->host); buffer_append_string(proc->connection_name, ":"); buffer_append_long(proc->connection_name, proc->port); } - + if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) { - log_error_write(srv, __FILE__, __LINE__, "ss", + log_error_write(srv, __FILE__, __LINE__, "ss", "failed:", strerror(errno)); return -1; } - + if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) { /* server is not up, spawn in */ pid_t child; int val; - - if (errno != ENOENT && + + if (errno != ENOENT && !buffer_is_empty(proc->unixsocket)) { unlink(proc->unixsocket->ptr); } - + close(fcgi_fd); - + /* reopen socket */ if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) { - log_error_write(srv, __FILE__, __LINE__, "ss", + log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno)); return -1; } - + val = 1; if (setsockopt(fcgi_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) { - log_error_write(srv, __FILE__, __LINE__, "ss", + log_error_write(srv, __FILE__, __LINE__, "ss", "socketsockopt failed:", strerror(errno)); return -1; } - + /* create socket */ if (-1 == bind(fcgi_fd, fcgi_addr, servlen)) { - log_error_write(srv, __FILE__, __LINE__, "sbs", - "bind failed for:", + log_error_write(srv, __FILE__, __LINE__, "sbs", + "bind failed for:", proc->connection_name, strerror(errno)); return -1; } - + if (-1 == listen(fcgi_fd, 1024)) { - log_error_write(srv, __FILE__, __LINE__, "ss", + log_error_write(srv, __FILE__, __LINE__, "ss", "listen failed:", strerror(errno)); return -1; } - -#ifdef HAVE_FORK + +#ifdef HAVE_FORK switch ((child = fork())) { case 0: { size_t i = 0; char *c; char_array env; char_array arg; - + /* create environment */ env.ptr = NULL; env.size = 0; env.used = 0; - + arg.ptr = NULL; arg.size = 0; arg.used = 0; @@ -913,18 +921,18 @@ static int fcgi_spawn_connection(server *srv, dup2(fcgi_fd, FCGI_LISTENSOCK_FILENO); close(fcgi_fd); } - + /* we don't need the client socket */ for (i = 3; i < 256; i++) { close(i); } - + /* build clean environment */ if (host->bin_env_copy->used) { for (i = 0; i < host->bin_env_copy->used; i++) { data_string *ds = (data_string *)host->bin_env_copy->data[i]; char *ge; - + if (NULL != (ge = getenv(ds->value->ptr))) { env_add(&env, CONST_BUF_LEN(ds->value), ge, strlen(ge)); } @@ -932,39 +940,39 @@ static int fcgi_spawn_connection(server *srv, } else { for (i = 0; environ[i]; i++) { char *eq; - + if (NULL != (eq = strchr(environ[i], '='))) { env_add(&env, environ[i], eq - environ[i], eq+1, strlen(eq+1)); } } } - + /* create environment */ for (i = 0; i < host->bin_env->used; i++) { data_string *ds = (data_string *)host->bin_env->data[i]; - + env_add(&env, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value)); } - + for (i = 0; i < env.used; i++) { /* search for PHP_FCGI_CHILDREN */ if (0 == strncmp(env.ptr[i], "PHP_FCGI_CHILDREN=", sizeof("PHP_FCGI_CHILDREN=") - 1)) break; } - + /* not found, add a default */ if (i == env.used) { env_add(&env, CONST_STR_LEN("PHP_FCGI_CHILDREN"), CONST_STR_LEN("1")); } - + env.ptr[env.used] = NULL; parse_binpath(&arg, host->bin_path); - + /* chdir into the base of the bin-path, * search for the last / */ if (NULL != (c = strrchr(arg.ptr[0], '/'))) { *c = '\0'; - + /* change to the physical directory */ if (-1 == chdir(arg.ptr[0])) { *c = '/'; @@ -976,12 +984,12 @@ static int fcgi_spawn_connection(server *srv, /* exec the cgi */ execve(arg.ptr[0], arg.ptr, env.ptr); - - log_error_write(srv, __FILE__, __LINE__, "sbs", + + log_error_write(srv, __FILE__, __LINE__, "sbs", "execve failed for:", host->bin_path, strerror(errno)); - + exit(errno); - + break; } case -1: @@ -989,17 +997,17 @@ static int fcgi_spawn_connection(server *srv, break; default: /* father */ - + /* wait */ select(0, NULL, NULL, NULL, &tv); - + switch (waitpid(child, &status, WNOHANG)) { case 0: /* child still running after timeout, good */ break; case -1: /* no PID found ? should never happen */ - log_error_write(srv, __FILE__, __LINE__, "ss", + log_error_write(srv, __FILE__, __LINE__, "ss", "pid not found:", strerror(errno)); return -1; default: @@ -1007,10 +1015,10 @@ static int fcgi_spawn_connection(server *srv, "the fastcgi-backend", host->bin_path, "failed to start:"); /* the child should not terminate at all */ if (WIFEXITED(status)) { - log_error_write(srv, __FILE__, __LINE__, "sdb", - "child exited with status", + log_error_write(srv, __FILE__, __LINE__, "sdb", + "child exited with status", WEXITSTATUS(status), host->bin_path); - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "if you try do run PHP as FastCGI backend make sure you use the FastCGI enabled version.\n" "You can find out if it is the right one by executing 'php -v' and it should display '(cgi-fcgi)' " "in the output, NOT (cgi) NOR (cli)\n" @@ -1018,8 +1026,8 @@ static int fcgi_spawn_connection(server *srv, log_error_write(srv, __FILE__, __LINE__, "s", "If this is PHP on Gentoo add fastcgi to the USE flags"); } else if (WIFSIGNALED(status)) { - log_error_write(srv, __FILE__, __LINE__, "sd", - "terminated by signal:", + log_error_write(srv, __FILE__, __LINE__, "sd", + "terminated by signal:", WTERMSIG(status)); if (WTERMSIG(status) == 11) { @@ -1029,8 +1037,8 @@ static int fcgi_spawn_connection(server *srv, "If this is PHP try to remove the byte-code caches for now and try again."); } } else { - log_error_write(srv, __FILE__, __LINE__, "sd", - "child died somehow:", + log_error_write(srv, __FILE__, __LINE__, "sd", + "child died somehow:", status); } return -1; @@ -1040,26 +1048,26 @@ static int fcgi_spawn_connection(server *srv, proc->pid = child; proc->last_used = srv->cur_ts; proc->is_local = 1; - + break; } #endif } else { proc->is_local = 0; proc->pid = 0; - + if (p->conf.debug) { log_error_write(srv, __FILE__, __LINE__, "sb", "(debug) socket is already used, won't spawn:", proc->connection_name); } } - + proc->state = PROC_STATE_RUNNING; host->active_procs++; - + close(fcgi_fd); - + return 0; } @@ -1069,93 +1077,93 @@ SETDEFAULTS_FUNC(mod_fastcgi_set_defaults) { data_unset *du; size_t i = 0; buffer *fcgi_mode = buffer_init(); - - config_values_t cv[] = { + + config_values_t cv[] = { { "fastcgi.server", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ { "fastcgi.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */ { "fastcgi.map-extensions", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 2 */ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } }; - + 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 = malloc(sizeof(plugin_config)); s->exts = fastcgi_extensions_init(); s->debug = 0; s->ext_mapping = array_init(); - + cv[0].destination = s->exts; cv[1].destination = &(s->debug); cv[2].destination = s->ext_mapping; - + 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; } - - /* + + /* * <key> = ( ... ) */ - + if (NULL != (du = array_get_element(ca, "fastcgi.server"))) { size_t j; data_array *da = (data_array *)du; - + if (du->type != TYPE_ARRAY) { - log_error_write(srv, __FILE__, __LINE__, "sss", + log_error_write(srv, __FILE__, __LINE__, "sss", "unexpected type for key: ", "fastcgi.server", "array of strings"); - + return HANDLER_ERROR; } - - - /* - * fastcgi.server = ( "<ext>" => ( ... ), + + + /* + * fastcgi.server = ( "<ext>" => ( ... ), * "<ext>" => ( ... ) ) */ - + for (j = 0; j < da->value->used; j++) { size_t n; data_array *da_ext = (data_array *)da->value->data[j]; - + if (da->value->data[j]->type != TYPE_ARRAY) { - log_error_write(srv, __FILE__, __LINE__, "sssbs", - "unexpected type for key: ", "fastcgi.server", + log_error_write(srv, __FILE__, __LINE__, "sssbs", + "unexpected type for key: ", "fastcgi.server", "[", da->value->data[j]->key, "](string)"); - + return HANDLER_ERROR; } - - /* - * da_ext->key == name of the extension + + /* + * da_ext->key == name of the extension */ - - /* - * fastcgi.server = ( "<ext>" => - * ( "<host>" => ( ... ), + + /* + * fastcgi.server = ( "<ext>" => + * ( "<host>" => ( ... ), * "<host>" => ( ... ) - * ), + * ), * "<ext>" => ... ) */ - + for (n = 0; n < da_ext->value->used; n++) { data_array *da_host = (data_array *)da_ext->value->data[n]; - + fcgi_extension_host *host; - - config_values_t fcv[] = { + + config_values_t fcv[] = { { "host", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ { "docroot", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 1 */ { "mode", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */ { "socket", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */ { "bin-path", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 4 */ - + { "check-local", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 5 */ { "port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 6 */ { "min-procs-not-working", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 7 this is broken for now */ @@ -1163,28 +1171,28 @@ SETDEFAULTS_FUNC(mod_fastcgi_set_defaults) { { "max-load-per-proc", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 9 */ { "idle-timeout", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 10 */ { "disable-time", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 11 */ - + { "bin-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 12 */ { "bin-copy-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 13 */ - + { "broken-scriptfilename", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 14 */ { "allow-x-send-file", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 15 */ { "strip-request-uri", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 16 */ - + { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } }; - + if (da_host->type != TYPE_ARRAY) { - log_error_write(srv, __FILE__, __LINE__, "ssSBS", - "unexpected type for key:", - "fastcgi.server", + log_error_write(srv, __FILE__, __LINE__, "ssSBS", + "unexpected type for key:", + "fastcgi.server", "[", da_host->key, "](string)"); - + return HANDLER_ERROR; } - + host = fastcgi_host_init(); - + buffer_copy_string_buffer(host->id, da_host->key); host->check_local = 1; @@ -1196,13 +1204,13 @@ SETDEFAULTS_FUNC(mod_fastcgi_set_defaults) { host->disable_time = 60; host->break_scriptfilename_for_php = 0; host->allow_xsendfile = 0; /* handle X-LIGHTTPD-send-file */ - + fcv[0].destination = host->host; fcv[1].destination = host->docroot; fcv[2].destination = fcgi_mode; fcv[3].destination = host->unixsocket; fcv[4].destination = host->bin_path; - + fcv[5].destination = &(host->check_local); fcv[6].destination = &(host->port); fcv[7].destination = &(host->min_procs); @@ -1210,35 +1218,35 @@ SETDEFAULTS_FUNC(mod_fastcgi_set_defaults) { fcv[9].destination = &(host->max_load_per_proc); fcv[10].destination = &(host->idle_timeout); fcv[11].destination = &(host->disable_time); - + fcv[12].destination = host->bin_env; fcv[13].destination = host->bin_env_copy; fcv[14].destination = &(host->break_scriptfilename_for_php); fcv[15].destination = &(host->allow_xsendfile); fcv[16].destination = host->strip_request_uri; - + if (0 != config_insert_values_internal(srv, da_host->value, fcv)) { return HANDLER_ERROR; } - - if ((!buffer_is_empty(host->host) || host->port) && + + if ((!buffer_is_empty(host->host) || host->port) && !buffer_is_empty(host->unixsocket)) { - log_error_write(srv, __FILE__, __LINE__, "sbsbsbs", + log_error_write(srv, __FILE__, __LINE__, "sbsbsbs", "either host/port or socket have to be set in:", - da->key, "= (", + da->key, "= (", da_ext->key, " => (", da_host->key, " ( ..."); return HANDLER_ERROR; } - + if (!buffer_is_empty(host->unixsocket)) { /* unix domain socket */ - + if (host->unixsocket->used > UNIX_PATH_MAX - 2) { - log_error_write(srv, __FILE__, __LINE__, "sbsbsbs", + log_error_write(srv, __FILE__, __LINE__, "sbsbsbs", "unixsocket is too long in:", - da->key, "= (", + da->key, "= (", da_ext->key, " => (", da_host->key, " ( ..."); @@ -1246,37 +1254,37 @@ SETDEFAULTS_FUNC(mod_fastcgi_set_defaults) { } } else { /* tcp/ip */ - - if (buffer_is_empty(host->host) && + + if (buffer_is_empty(host->host) && buffer_is_empty(host->bin_path)) { - log_error_write(srv, __FILE__, __LINE__, "sbsbsbs", + log_error_write(srv, __FILE__, __LINE__, "sbsbsbs", "host or binpath have to be set in:", - da->key, "= (", + da->key, "= (", da_ext->key, " => (", da_host->key, " ( ..."); - + return HANDLER_ERROR; } else if (host->port == 0) { - log_error_write(srv, __FILE__, __LINE__, "sbsbsbs", + log_error_write(srv, __FILE__, __LINE__, "sbsbsbs", "port has to be set in:", - da->key, "= (", + da->key, "= (", da_ext->key, " => (", da_host->key, " ( ..."); return HANDLER_ERROR; } } - - if (!buffer_is_empty(host->bin_path)) { + + if (!buffer_is_empty(host->bin_path)) { /* a local socket + self spawning */ size_t pno; /* HACK: just to make sure the adaptive spawing is disabled */ host->min_procs = host->max_procs; - + if (host->min_procs > host->max_procs) host->max_procs = host->min_procs; if (host->max_load_per_proc < 1) host->max_load_per_proc = 0; - + if (s->debug) { log_error_write(srv, __FILE__, __LINE__, "ssbsdsbsdsd", "--- fastcgi spawning local", @@ -1286,7 +1294,7 @@ SETDEFAULTS_FUNC(mod_fastcgi_set_defaults) { "\n\tmin-procs:", host->min_procs, "\n\tmax-procs:", host->max_procs); } - + for (pno = 0; pno < host->min_procs; pno++) { fcgi_proc *proc; @@ -1301,7 +1309,7 @@ SETDEFAULTS_FUNC(mod_fastcgi_set_defaults) { buffer_append_string(proc->unixsocket, "-"); buffer_append_long(proc->unixsocket, pno); } - + if (s->debug) { log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd", "--- fastcgi spawning", @@ -1309,7 +1317,7 @@ SETDEFAULTS_FUNC(mod_fastcgi_set_defaults) { "\n\tsocket", host->unixsocket, "\n\tcurrent:", pno, "/", host->min_procs); } - + if (fcgi_spawn_connection(srv, p, host, proc)) { log_error_write(srv, __FILE__, __LINE__, "s", "[ERROR]: spawning fcgi failed."); @@ -1317,35 +1325,35 @@ SETDEFAULTS_FUNC(mod_fastcgi_set_defaults) { } fastcgi_status_init(srv, p->statuskey, host, proc); - + proc->next = host->first; if (host->first) host->first->prev = proc; - + host->first = proc; } } else { fcgi_proc *proc; - + proc = fastcgi_process_init(); proc->id = host->num_procs++; host->max_id++; host->active_procs++; proc->state = PROC_STATE_RUNNING; - + if (buffer_is_empty(host->unixsocket)) { proc->port = host->port; } else { buffer_copy_string_buffer(proc->unixsocket, host->unixsocket); } - + fastcgi_status_init(srv, p->statuskey, host, proc); host->first = proc; - + host->min_procs = 1; host->max_procs = 1; } - + if (!buffer_is_empty(fcgi_mode)) { if (strcmp(fcgi_mode->ptr, "responder") == 0) { host->mode = FCGI_RESPONDER; @@ -1369,16 +1377,16 @@ SETDEFAULTS_FUNC(mod_fastcgi_set_defaults) { } } } - + buffer_free(fcgi_mode); - + return HANDLER_GO_ON; } static int fcgi_set_state(server *srv, handler_ctx *hctx, fcgi_connection_state_t state) { hctx->state = state; hctx->state_timestamp = srv->cur_ts; - + return 0; } @@ -1387,13 +1395,13 @@ static size_t fcgi_requestid_new(server *srv, plugin_data *p) { size_t m = 0; size_t i; buffer_uint *r = &(p->fcgi_request_id); - + 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); @@ -1401,54 +1409,54 @@ static size_t fcgi_requestid_new(server *srv, plugin_data *p) { r->size += 16; r->ptr = realloc(r->ptr, sizeof(*r->ptr) * r->size); } - + r->ptr[r->used++] = ++m; - + return m; } static int fcgi_requestid_del(server *srv, plugin_data *p, size_t request_id) { size_t i; buffer_uint *r = &(p->fcgi_request_id); - + UNUSED(srv); for (i = 0; i < r->used; i++) { if (r->ptr[i] == request_id) break; } - + if (i != r->used) { /* found */ - + if (i != r->used - 1) { r->ptr[i] = r->ptr[r->used - 1]; } r->used--; } - + return 0; } void fcgi_connection_close(server *srv, handler_ctx *hctx) { plugin_data *p; connection *con; - + if (NULL == hctx) return; - + p = hctx->plugin_data; con = hctx->remote_conn; - + if (con->mode != p->id) { WP(); return; } - + if (hctx->fd != -1) { fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); fdevent_unregister(srv->ev, hctx->fd); close(hctx->fd); srv->cur_fds--; } - + if (hctx->request_id != 0) { fcgi_requestid_del(srv, p, hctx->request_id); } @@ -1457,7 +1465,7 @@ void fcgi_connection_close(server *srv, handler_ctx *hctx) { if (hctx->got_proc) { /* after the connect the process gets a load */ hctx->proc->load--; - + status_counter_dec(srv, CONST_STR_LEN("fastcgi.active-requests")); fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc); @@ -1467,39 +1475,39 @@ void fcgi_connection_close(server *srv, handler_ctx *hctx) { if (p->conf.debug) { log_error_write(srv, __FILE__, __LINE__, "ssdsbsd", - "released proc:", - "pid:", hctx->proc->pid, - "socket:", hctx->proc->connection_name, + "released proc:", + "pid:", hctx->proc->pid, + "socket:", hctx->proc->connection_name, "load:", hctx->proc->load); } } } - + handler_ctx_free(hctx); - con->plugin_ctx[p->id] = NULL; + con->plugin_ctx[p->id] = NULL; } static int fcgi_reconnect(server *srv, handler_ctx *hctx) { plugin_data *p = hctx->plugin_data; - - /* child died - * - * 1. - * + + /* child died + * + * 1. + * * connect was ok, connection was accepted * but the php accept loop checks after the accept if it should die or not. - * - * if yes we can only detect it at a write() - * + * + * if yes we can only detect it at a write() + * * next step is resetting this attemp and setup a connection again - * + * * if we have more then 5 reconnects for the same request, die - * - * 2. - * + * + * 2. + * * we have a connection but the child died by some other reason - * + * */ if (hctx->fd != -1) { @@ -1509,59 +1517,59 @@ static int fcgi_reconnect(server *srv, handler_ctx *hctx) { srv->cur_fds--; hctx->fd = -1; } - + fcgi_requestid_del(srv, p, hctx->request_id); - + fcgi_set_state(srv, hctx, FCGI_STATE_INIT); - + hctx->request_id = 0; hctx->reconnects++; - + if (p->conf.debug > 2) { if (hctx->proc) { log_error_write(srv, __FILE__, __LINE__, "sdb", - "release proc for reconnect:", + "release proc for reconnect:", hctx->proc->pid, hctx->proc->connection_name); } else { log_error_write(srv, __FILE__, __LINE__, "sb", - "release proc for reconnect:", + "release proc for reconnect:", hctx->host->unixsocket); } } - if (hctx->proc && hctx->got_proc) { + if (hctx->proc && hctx->got_proc) { hctx->proc->load--; } /* perhaps another host gives us more luck */ hctx->host->load--; hctx->host = NULL; - + return 0; } static handler_t fcgi_connection_reset(server *srv, connection *con, void *p_d) { plugin_data *p = p_d; - + fcgi_connection_close(srv, con->plugin_ctx[p->id]); - + return HANDLER_GO_ON; } static int fcgi_env_add(buffer *env, const char *key, size_t key_len, const char *val, size_t val_len) { size_t len; - + if (!key || !val) return -1; - + len = key_len + val_len; - + len += key_len > 127 ? 4 : 1; len += val_len > 127 ? 4 : 1; - + buffer_prepare_append(env, len); - + if (key_len > 127) { env->ptr[env->used++] = ((key_len >> 24) & 0xff) | 0x80; env->ptr[env->used++] = (key_len >> 16) & 0xff; @@ -1570,7 +1578,7 @@ static int fcgi_env_add(buffer *env, const char *key, size_t key_len, const char } else { env->ptr[env->used++] = (key_len >> 0) & 0xff; } - + if (val_len > 127) { env->ptr[env->used++] = ((val_len >> 24) & 0xff) | 0x80; env->ptr[env->used++] = (val_len >> 16) & 0xff; @@ -1579,12 +1587,12 @@ static int fcgi_env_add(buffer *env, const char *key, size_t key_len, const char } else { env->ptr[env->used++] = (val_len >> 0) & 0xff; } - + memcpy(env->ptr + env->used, key, key_len); env->used += key_len; memcpy(env->ptr + env->used, val, val_len); env->used += val_len; - + return 0; } @@ -1597,11 +1605,11 @@ static int fcgi_header(FCGI_Header * header, unsigned char type, size_t request_ header->contentLengthB1 = (contentLength >> 8) & 0xff; header->paddingLength = paddingLength; header->reserved = 0; - + return 0; } /** - * + * * returns * -1 error * 0 connected @@ -1623,13 +1631,13 @@ static connection_result_t fcgi_establish_connection(server *srv, handler_ctx *h struct sockaddr_un fcgi_addr_un; #endif socklen_t servlen; - + fcgi_extension_host *host = hctx->host; fcgi_proc *proc = hctx->proc; int fcgi_fd = hctx->fd; - + memset(&fcgi_addr, 0, sizeof(fcgi_addr)); - + if (!buffer_is_empty(proc->unixsocket)) { #ifdef HAVE_SYS_UN_H /* use the unix domain socket */ @@ -1642,7 +1650,7 @@ static connection_result_t fcgi_establish_connection(server *srv, handler_ctx *h servlen = proc->unixsocket->used + sizeof(fcgi_addr_un.sun_family); #endif fcgi_addr = (struct sockaddr *) &fcgi_addr_un; - + if (buffer_is_empty(proc->connection_name)) { /* on remote spawing we have to set the connection-name now */ buffer_copy_string(proc->connection_name, "unix:"); @@ -1654,15 +1662,15 @@ static connection_result_t fcgi_establish_connection(server *srv, handler_ctx *h } else { fcgi_addr_in.sin_family = AF_INET; if (0 == inet_aton(host->host->ptr, &(fcgi_addr_in.sin_addr))) { - log_error_write(srv, __FILE__, __LINE__, "sbs", - "converting IP-adress failed for", host->host, + log_error_write(srv, __FILE__, __LINE__, "sbs", + "converting IP-adress failed for", host->host, "\nBe sure to specify an IP address here"); - + return -1; } fcgi_addr_in.sin_port = htons(proc->port); servlen = sizeof(fcgi_addr_in); - + fcgi_addr = (struct sockaddr *) &fcgi_addr_in; if (buffer_is_empty(proc->connection_name)) { @@ -1673,20 +1681,20 @@ static connection_result_t fcgi_establish_connection(server *srv, handler_ctx *h buffer_append_long(proc->connection_name, proc->port); } } - + if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) { - if (errno == EINPROGRESS || + if (errno == EINPROGRESS || errno == EALREADY || errno == EINTR) { if (hctx->conf.debug > 2) { - log_error_write(srv, __FILE__, __LINE__, "sb", + log_error_write(srv, __FILE__, __LINE__, "sb", "connect delayed, will continue later:", proc->connection_name); } - + return CONNECTION_DELAYED; } else if (errno == EAGAIN) { if (hctx->conf.debug) { - log_error_write(srv, __FILE__, __LINE__, "sbsd", + log_error_write(srv, __FILE__, __LINE__, "sbsd", "This means that the you have more incoming requests than your fastcgi-backend can handle in parallel. " "Perhaps it helps to spawn more fastcgi backend or php-children, if not decrease server.max-connections." "The load for this fastcgi backend", proc->connection_name, "is", proc->load); @@ -1694,8 +1702,8 @@ static connection_result_t fcgi_establish_connection(server *srv, handler_ctx *h return CONNECTION_OVERLOADED; } else { - log_error_write(srv, __FILE__, __LINE__, "sssb", - "connect failed:", + log_error_write(srv, __FILE__, __LINE__, "sssb", + "connect failed:", strerror(errno), "on", proc->connection_name); @@ -1705,7 +1713,7 @@ static connection_result_t fcgi_establish_connection(server *srv, handler_ctx *h hctx->reconnects = 0; if (hctx->conf.debug > 1) { - log_error_write(srv, __FILE__, __LINE__, "sd", + log_error_write(srv, __FILE__, __LINE__, "sd", "connect succeeded: ", fcgi_fd); } @@ -1714,21 +1722,21 @@ static connection_result_t fcgi_establish_connection(server *srv, handler_ctx *h static int fcgi_env_add_request_headers(server *srv, connection *con, plugin_data *p) { size_t i; - + for (i = 0; i < con->request.headers->used; i++) { data_string *ds; - + ds = (data_string *)con->request.headers->data[i]; - + if (ds->value->used && ds->key->used) { size_t j; buffer_reset(srv->tmp_buf); - + if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) { BUFFER_COPY_STRING_CONST(srv->tmp_buf, "HTTP_"); srv->tmp_buf->used--; } - + buffer_prepare_append(srv->tmp_buf, ds->key->used + 2); for (j = 0; j < ds->key->used - 1; j++) { char c = '_'; @@ -1742,20 +1750,20 @@ static int fcgi_env_add_request_headers(server *srv, connection *con, plugin_dat srv->tmp_buf->ptr[srv->tmp_buf->used++] = c; } srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0'; - + fcgi_env_add(p->fcgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value)); } } - + for (i = 0; i < con->environment->used; i++) { data_string *ds; - + ds = (data_string *)con->environment->data[i]; - + if (ds->value->used && ds->key->used) { size_t j; buffer_reset(srv->tmp_buf); - + buffer_prepare_append(srv->tmp_buf, ds->key->used + 2); for (j = 0; j < ds->key->used - 1; j++) { char c = '_'; @@ -1769,11 +1777,11 @@ static int fcgi_env_add_request_headers(server *srv, connection *con, plugin_dat srv->tmp_buf->ptr[srv->tmp_buf->used++] = c; } srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0'; - + fcgi_env_add(p->fcgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value)); } } - + return 0; } @@ -1782,24 +1790,24 @@ static int fcgi_create_env(server *srv, handler_ctx *hctx, size_t request_id) { FCGI_BeginRequestRecord beginRecord; FCGI_Header header; buffer *b; - + char buf[32]; const char *s; #ifdef HAVE_IPV6 char b2[INET6_ADDRSTRLEN + 1]; #endif - + plugin_data *p = hctx->plugin_data; fcgi_extension_host *host= hctx->host; connection *con = hctx->remote_conn; server_socket *srv_sock = con->srv_socket; - + sock_addr our_addr; socklen_t our_addr_len; - + /* send FCGI_BEGIN_REQUEST */ - + fcgi_header(&(beginRecord.header), FCGI_BEGIN_REQUEST, request_id, sizeof(beginRecord.body), 0); beginRecord.body.roleB0 = host->mode; beginRecord.body.roleB1 = 0; @@ -1807,21 +1815,21 @@ static int fcgi_create_env(server *srv, handler_ctx *hctx, size_t request_id) { memset(beginRecord.body.reserved, 0, sizeof(beginRecord.body.reserved)); b = chunkqueue_get_append_buffer(hctx->wb); - + buffer_copy_memory(b, (const char *)&beginRecord, sizeof(beginRecord)); - + /* send FCGI_PARAMS */ buffer_prepare_copy(p->fcgi_env, 1024); fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION)); - + if (con->server_name->used) { fcgi_env_add(p->fcgi_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); @@ -1830,50 +1838,50 @@ static int fcgi_create_env(server *srv, handler_ctx *hctx, size_t request_id) { #endif fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_NAME"), s, strlen(s)); } - + fcgi_env_add(p->fcgi_env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1")); - - ltostr(buf, + + ltostr(buf, #ifdef HAVE_IPV6 ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port) #else ntohs(srv_sock->addr.ipv4.sin_port) #endif ); - + fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf)); - + /* get the server-side of the connection to the client */ our_addr_len = sizeof(our_addr); - + if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) { s = inet_ntop_cache_get_ip(srv, &(srv_sock->addr)); } else { s = inet_ntop_cache_get_ip(srv, &(our_addr)); } fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_ADDR"), s, strlen(s)); - - ltostr(buf, + + ltostr(buf, #ifdef HAVE_IPV6 ntohs(con->dst_addr.plain.sa_family ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port) #else ntohs(con->dst_addr.ipv4.sin_port) #endif ); - + fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf)); - + s = inet_ntop_cache_get_ip(srv, &(con->dst_addr)); fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s)); - + if (!buffer_is_empty(con->authed_user)) { fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REMOTE_USER"), CONST_BUF_LEN(con->authed_user)); } - + if (con->request.content_length > 0 && host->mode != FCGI_AUTHORIZER) { /* CGI-SPEC 6.1.2 and FastCGI spec 6.3 */ - + /* request.content_length < SSIZE_MAX, see request.c */ ltostr(buf, con->request.content_length); fcgi_env_add(p->fcgi_env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf)); @@ -1888,12 +1896,12 @@ static int fcgi_create_env(server *srv, handler_ctx *hctx, size_t request_id) { */ fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path)); - + if (!buffer_is_empty(con->request.pathinfo)) { fcgi_env_add(p->fcgi_env, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo)); - + /* PATH_TRANSLATED is only defined if PATH_INFO is set */ - + if (!buffer_is_empty(host->docroot)) { buffer_copy_string_buffer(p->path, host->docroot); } else { @@ -1915,27 +1923,27 @@ static int fcgi_create_env(server *srv, handler_ctx *hctx, size_t request_id) { */ if (!buffer_is_empty(host->docroot)) { - /* - * rewrite SCRIPT_FILENAME - * + /* + * rewrite SCRIPT_FILENAME + * */ - + buffer_copy_string_buffer(p->path, host->docroot); buffer_append_string_buffer(p->path, con->uri.path); - + fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path)); fcgi_env_add(p->fcgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(host->docroot)); } else { buffer_copy_string_buffer(p->path, con->physical.path); - - /* cgi.fix_pathinfo need a broken SCRIPT_FILENAME to find out what PATH_INFO is itself - * + + /* cgi.fix_pathinfo need a broken SCRIPT_FILENAME to find out what PATH_INFO is itself + * * see src/sapi/cgi_main.c, init_request_info() */ if (host->break_scriptfilename_for_php) { buffer_append_string_buffer(p->path, con->request.pathinfo); } - + fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path)); fcgi_env_add(p->fcgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root)); } @@ -1945,7 +1953,7 @@ static int fcgi_create_env(server *srv, handler_ctx *hctx, size_t request_id) { /** * /app1/index/list * - * stripping /app1 or /app1/ should lead to + * stripping /app1 or /app1/ should lead to * * /index/list * @@ -1959,7 +1967,7 @@ static int fcgi_create_env(server *srv, handler_ctx *hctx, size_t request_id) { 0 == strncmp(con->request.orig_uri->ptr, host->strip_request_uri->ptr, host->strip_request_uri->used - 1)) { /* the left is the same */ - fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_URI"), + fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_URI"), con->request.orig_uri->ptr + (host->strip_request_uri->used - 2), con->request.orig_uri->used - (host->strip_request_uri->used - 2)); } else { @@ -1976,26 +1984,26 @@ static int fcgi_create_env(server *srv, handler_ctx *hctx, size_t request_id) { } else { fcgi_env_add(p->fcgi_env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN("")); } - + s = get_http_method_name(con->request.http_method); fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REQUEST_METHOD"), s, strlen(s)); fcgi_env_add(p->fcgi_env, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200")); /* if php is compiled with --force-redirect */ s = get_http_version_name(con->request.http_version); fcgi_env_add(p->fcgi_env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s)); - + #ifdef USE_OPENSSL if (srv_sock->is_ssl) { fcgi_env_add(p->fcgi_env, CONST_STR_LEN("HTTPS"), CONST_STR_LEN("on")); } #endif - - + + fcgi_env_add_request_headers(srv, con, p); - + fcgi_header(&(header), FCGI_PARAMS, request_id, p->fcgi_env->used, 0); buffer_append_memory(b, (const char *)&header, sizeof(header)); buffer_append_memory(b, (const char *)p->fcgi_env->ptr, p->fcgi_env->used); - + fcgi_header(&(header), FCGI_PARAMS, request_id, 0, 0); buffer_append_memory(b, (const char *)&header, sizeof(header)); @@ -2015,7 +2023,7 @@ static int fcgi_create_env(server *srv, handler_ctx *hctx, size_t request_id) { /* we announce toWrite octects * now take all the request_content chunk that we need to fill this request - * */ + * */ b = chunkqueue_get_append_buffer(hctx->wb); fcgi_header(&(header), FCGI_STDIN, request_id, weWant, 0); @@ -2038,16 +2046,16 @@ static int fcgi_create_env(server *srv, handler_ctx *hctx, size_t request_id) { if (weHave > weWant - written) weHave = weWant - written; if (p->conf.debug > 10) { - fprintf(stderr, "%s.%d: sending %lld bytes from (%lld / %lld) %s\n", - __FILE__, __LINE__, - weHave, - req_c->offset, - req_c->file.length, + fprintf(stderr, "%s.%d: sending %lld bytes from (%lld / %lld) %s\n", + __FILE__, __LINE__, + weHave, + req_c->offset, + req_c->file.length, req_c->file.name->ptr); } assert(weHave != 0); - + chunkqueue_append_file(hctx->wb, req_c->file.name, req_c->offset, weHave); req_c->offset += weHave; @@ -2062,7 +2070,7 @@ static int fcgi_create_env(server *srv, handler_ctx *hctx, size_t request_id) { * - we reference the tempfile from the request-content-queue several times * if the req_c is larger than FCGI_MAX_LENGTH * - we can't simply cleanup the request-content-queue as soon as possible - * as it would remove the tempfiles + * as it would remove the tempfiles * - the idea is to 'steal' the tempfiles and attach the is_temp flag to the last * referencing chunk of the fastcgi-write-queue * @@ -2099,7 +2107,7 @@ static int fcgi_create_env(server *srv, handler_ctx *hctx, size_t request_id) { req_c->offset += weHave; req_cq->bytes_out += weHave; written += weHave; - + hctx->wb->bytes_in += weHave; if (req_c->offset == req_c->mem->used - 1) { @@ -2113,12 +2121,12 @@ static int fcgi_create_env(server *srv, handler_ctx *hctx, size_t request_id) { break; } } - + b->used++; /* add virtual \0 */ offset += weWant; } } - + b = chunkqueue_get_append_buffer(hctx->wb); /* terminate STDIN */ fcgi_header(&(header), FCGI_STDIN, request_id, 0, 0); @@ -2133,59 +2141,59 @@ static int fcgi_create_env(server *srv, handler_ctx *hctx, size_t request_id) { if ((i+1) % 16 == 0) { size_t j; for (j = i-15; j <= i; j++) { - fprintf(stderr, "%c", + fprintf(stderr, "%c", isprint((unsigned char)hctx->write_buffer->ptr[j]) ? hctx->write_buffer->ptr[j] : '.'); } fprintf(stderr, "\n"); } } #endif - + return 0; } static int fcgi_response_parse(server *srv, connection *con, plugin_data *p, buffer *in) { char *s, *ns; - + handler_ctx *hctx = con->plugin_ctx[p->id]; fcgi_extension_host *host= hctx->host; - + UNUSED(srv); buffer_copy_string_buffer(p->parse_response, in); - + /* search for \n */ for (s = p->parse_response->ptr; NULL != (ns = strchr(s, '\n')); s = ns + 1) { char *key, *value; int key_len; data_string *ds; - + /* a good day. Someone has read the specs and is sending a \r\n to us */ - + if (ns > p->parse_response->ptr && *(ns-1) == '\r') { *(ns-1) = '\0'; } - + ns[0] = '\0'; - + key = s; if (NULL == (value = strchr(s, ':'))) { /* we expect: "<key>: <value>\n" */ continue; } - + key_len = value - key; - + value++; /* strip WS */ while (*value == ' ' || *value == '\t') value++; - + if (host->mode != FCGI_AUTHORIZER || !(con->http_status == 0 || con->http_status == 200)) { /* authorizers shouldn't affect the response headers sent back to the client */ - + /* don't forward Status: */ if (0 != strncasecmp(key, "Status", key_len)) { if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) { @@ -2193,11 +2201,11 @@ static int fcgi_response_parse(server *srv, connection *con, plugin_data *p, buf } 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)) { @@ -2225,7 +2233,7 @@ static int fcgi_response_parse(server *srv, connection *con, plugin_data *p, buf if (0 == strncasecmp(key, "Content-Length", key_len)) { con->response.content_length = strtol(value, NULL, 10); con->parsed_response |= HTTP_CONTENT_LENGTH; - + if (con->response.content_length < 0) con->response.content_length = 0; } break; @@ -2233,18 +2241,18 @@ static int fcgi_response_parse(server *srv, connection *con, plugin_data *p, buf break; } } - + /* 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; } typedef struct { - buffer *b; + buffer *b; size_t len; int type; int padding; @@ -2285,9 +2293,9 @@ static int fastcgi_get_packet(server *srv, handler_ctx *hctx, fastcgi_response_p return -1; } - /* we have at least a header, now check how much me have to fetch */ + /* we have at least a header, now check how much me have to fetch */ header = (FCGI_Header *)(packet->b->ptr); - + packet->len = (header->contentLengthB0 | (header->contentLengthB1 << 8)) + header->paddingLength; packet->request_id = (header->requestIdB0 | (header->requestIdB1 << 8)); packet->type = header->type; @@ -2306,7 +2314,7 @@ static int fastcgi_get_packet(server *srv, handler_ctx *hctx, fastcgi_response_p size_t weHave = c->mem->used - c->offset - offset - 1; if (weHave > weWant) weHave = weWant; - + buffer_append_string_len(packet->b, c->mem->ptr + c->offset + offset, weHave); /* we only skipped the first 8 bytes as they are the fcgi header */ @@ -2338,7 +2346,7 @@ static int fastcgi_get_packet(server *srv, handler_ctx *hctx, fastcgi_response_p } chunkqueue_remove_finished_chunks(hctx->rb); - + return 0; } @@ -2346,25 +2354,25 @@ static int fcgi_demux_response(server *srv, handler_ctx *hctx) { int fin = 0; int toread; ssize_t r; - + plugin_data *p = hctx->plugin_data; connection *con = hctx->remote_conn; int fcgi_fd = hctx->fd; fcgi_extension_host *host= hctx->host; fcgi_proc *proc = hctx->proc; - - /* - * check how much we have to read + + /* + * check how much we have to read */ if (ioctl(hctx->fd, FIONREAD, &toread)) { - log_error_write(srv, __FILE__, __LINE__, "sd", + log_error_write(srv, __FILE__, __LINE__, "sd", "unexpected end-of-file (perhaps the fastcgi process died):", fcgi_fd); return -1; } - + /* init read-buffer */ - + if (toread > 0) { buffer *b; @@ -2373,30 +2381,30 @@ static int fcgi_demux_response(server *srv, handler_ctx *hctx) { /* append to read-buffer */ if (-1 == (r = read(hctx->fd, b->ptr, toread))) { - log_error_write(srv, __FILE__, __LINE__, "sds", + log_error_write(srv, __FILE__, __LINE__, "sds", "unexpected end-of-file (perhaps the fastcgi process died):", fcgi_fd, strerror(errno)); return -1; } - + /* this should be catched by the b > 0 above */ assert(r); b->used = r + 1; /* one extra for the fake \0 */ b->ptr[b->used - 1] = '\0'; } else { - log_error_write(srv, __FILE__, __LINE__, "ssdsb", + log_error_write(srv, __FILE__, __LINE__, "ssdsb", "unexpected end-of-file (perhaps the fastcgi process died):", "pid:", proc->pid, "socket:", proc->connection_name); - + return -1; } /* * parse the fastcgi packets and forward the content to the write-queue * - */ + */ while (fin == 0) { fastcgi_response_packet packet; @@ -2415,9 +2423,9 @@ static int fcgi_demux_response(server *srv, handler_ctx *hctx) { char *c; size_t blen; data_string *ds; - - /* search for header terminator - * + + /* search for header terminator + * * if we start with \r\n check if last packet terminated with \r\n * if we start with \n check if last packet terminated with \n * search for \r\n\r\n @@ -2468,8 +2476,8 @@ static int fcgi_demux_response(server *srv, handler_ctx *hctx) { } } - - if (hctx->send_content_body && blen > 1) { + + if (hctx->send_content_body && blen > 1) { /* enable chunked-transfer-encoding */ if (con->request.http_version == HTTP_VERSION_1_1 && !(con->parsed_response & HTTP_CONTENT_LENGTH)) { @@ -2491,13 +2499,13 @@ static int fcgi_demux_response(server *srv, handler_ctx *hctx) { } break; case FCGI_STDERR: - log_error_write(srv, __FILE__, __LINE__, "sb", + log_error_write(srv, __FILE__, __LINE__, "sb", "FastCGI-stderr:", packet.b); - + break; case FCGI_END_REQUEST: con->file_finished = 1; - + if (host->mode != FCGI_AUTHORIZER || !(con->http_status == 0 || con->http_status == 200)) { @@ -2505,39 +2513,39 @@ static int fcgi_demux_response(server *srv, handler_ctx *hctx) { http_chunk_append_mem(srv, con, NULL, 0); joblist_append(srv, con); } - + fin = 1; break; default: - log_error_write(srv, __FILE__, __LINE__, "sd", + log_error_write(srv, __FILE__, __LINE__, "sd", "FastCGI: header.type not handled: ", packet.type); break; } buffer_free(packet.b); } - + return fin; } static int fcgi_restart_dead_procs(server *srv, plugin_data *p, fcgi_extension_host *host) { fcgi_proc *proc; - + for (proc = host->first; proc; proc = proc->next) { int status; if (p->conf.debug > 2) { - log_error_write(srv, __FILE__, __LINE__, "sbdddd", - "proc:", + log_error_write(srv, __FILE__, __LINE__, "sbdddd", + "proc:", proc->connection_name, proc->state, proc->is_local, proc->load, proc->pid); } - - /* + + /* * if the remote side is overloaded, we check back after <n> seconds - * + * */ switch (proc->state) { case PROC_STATE_KILLED: @@ -2550,13 +2558,13 @@ static int fcgi_restart_dead_procs(server *srv, plugin_data *p, fcgi_extension_h break; case PROC_STATE_OVERLOADED: if (srv->cur_ts <= proc->disabled_until) break; - + proc->state = PROC_STATE_RUNNING; host->active_procs++; - - log_error_write(srv, __FILE__, __LINE__, "sbdb", - "fcgi-server re-enabled:", - host->host, host->port, + + log_error_write(srv, __FILE__, __LINE__, "sbdb", + "fcgi-server re-enabled:", + host->host, host->port, host->unixsocket); break; case PROC_STATE_DIED_WAIT_FOR_PID: @@ -2564,7 +2572,7 @@ static int fcgi_restart_dead_procs(server *srv, plugin_data *p, fcgi_extension_h if (!proc->is_local) break; /* the child should not terminate at all */ - + switch(waitpid(proc->pid, &status, WNOHANG)) { case 0: /* child is still alive */ @@ -2574,20 +2582,20 @@ static int fcgi_restart_dead_procs(server *srv, plugin_data *p, fcgi_extension_h default: if (WIFEXITED(status)) { #if 0 - log_error_write(srv, __FILE__, __LINE__, "sdsd", + log_error_write(srv, __FILE__, __LINE__, "sdsd", "child exited, pid:", proc->pid, "status:", WEXITSTATUS(status)); #endif } else if (WIFSIGNALED(status)) { - log_error_write(srv, __FILE__, __LINE__, "sd", - "child signaled:", + log_error_write(srv, __FILE__, __LINE__, "sd", + "child signaled:", WTERMSIG(status)); } else { - log_error_write(srv, __FILE__, __LINE__, "sd", - "child died somehow:", + log_error_write(srv, __FILE__, __LINE__, "sd", + "child died somehow:", status); } - + proc->state = PROC_STATE_DIED; break; } @@ -2596,23 +2604,23 @@ static int fcgi_restart_dead_procs(server *srv, plugin_data *p, fcgi_extension_h if (proc->state != PROC_STATE_DIED) break; case PROC_STATE_DIED: - /* local proc get restarted by us, + /* local proc get restarted by us, * remote ones hopefully by the admin */ - + if (proc->is_local) { /* we still have connections bound to this proc, * let them terminate first */ if (proc->load != 0) break; - + /* restart the child */ - + if (p->conf.debug) { log_error_write(srv, __FILE__, __LINE__, "ssbsdsd", "--- fastcgi spawning", "\n\tsocket", proc->connection_name, "\n\tcurrent:", 1, "/", host->min_procs); } - + if (fcgi_spawn_connection(srv, p, host, proc)) { log_error_write(srv, __FILE__, __LINE__, "s", "ERROR: spawning fcgi failed."); @@ -2620,18 +2628,18 @@ static int fcgi_restart_dead_procs(server *srv, plugin_data *p, fcgi_extension_h } } else { if (srv->cur_ts <= proc->disabled_until) break; - + proc->state = PROC_STATE_RUNNING; host->active_procs++; - - log_error_write(srv, __FILE__, __LINE__, "sb", - "fcgi-server re-enabled:", + + log_error_write(srv, __FILE__, __LINE__, "sb", + "fcgi-server re-enabled:", proc->connection_name); } break; } } - + return 0; } @@ -2640,19 +2648,19 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) { fcgi_extension_host *host= hctx->host; connection *con = hctx->remote_conn; fcgi_proc *proc; - + int ret; - /* sanity check */ + /* sanity check */ if (!host || ((!host->host->used || !host->port) && !host->unixsocket->used)) { - log_error_write(srv, __FILE__, __LINE__, "sxddd", + log_error_write(srv, __FILE__, __LINE__, "sxddd", "write-req: error", host, host->host->used, host->port, host->unixsocket->used); - + hctx->proc->disabled_until = srv->cur_ts + 10; hctx->proc->state = PROC_STATE_DIED; @@ -2663,12 +2671,12 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) { if (hctx->state == FCGI_STATE_CONNECT_DELAYED) { int socket_error; socklen_t socket_error_len = sizeof(socket_error); - + /* try to finish the connect() */ if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) { - log_error_write(srv, __FILE__, __LINE__, "ss", + log_error_write(srv, __FILE__, __LINE__, "ss", "getsockopt failed:", strerror(errno)); - + hctx->proc->disabled_until = srv->cur_ts + 10; hctx->proc->state = PROC_STATE_DIED; @@ -2677,12 +2685,12 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) { if (socket_error != 0) { if (!hctx->proc->is_local || p->conf.debug) { /* local procs get restarted */ - + log_error_write(srv, __FILE__, __LINE__, "sssb", - "establishing connection failed:", strerror(socket_error), + "establishing connection failed:", strerror(socket_error), "socket:", hctx->proc->connection_name); } - + hctx->proc->disabled_until = srv->cur_ts + 5; if (hctx->proc->is_local) { @@ -2690,17 +2698,17 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) { } else { hctx->proc->state = PROC_STATE_DIED; } - + hctx->proc->state = PROC_STATE_DIED; - + fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc); buffer_append_string(p->statuskey, ".died"); status_counter_inc(srv, CONST_BUF_LEN(p->statuskey)); - + return HANDLER_ERROR; } - /* go on with preparing the request */ + /* go on with preparing the request */ hctx->state = FCGI_STATE_PREPARE_WRITE; } @@ -2713,14 +2721,14 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) { /* do we have a running process for this host (max-procs) ? */ hctx->proc = NULL; - for (proc = hctx->host->first; - proc && proc->state != PROC_STATE_RUNNING; + for (proc = hctx->host->first; + proc && proc->state != PROC_STATE_RUNNING; proc = proc->next); - + /* all childs are dead */ if (proc == NULL) { hctx->fde_ndx = -1; - + return HANDLER_ERROR; } @@ -2733,50 +2741,50 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) { } ret = host->unixsocket->used ? AF_UNIX : AF_INET; - + if (-1 == (hctx->fd = socket(ret, SOCK_STREAM, 0))) { if (errno == EMFILE || errno == EINTR) { - log_error_write(srv, __FILE__, __LINE__, "sd", + log_error_write(srv, __FILE__, __LINE__, "sd", "wait for fd at connection:", con->fd); - + return HANDLER_WAIT_FOR_FD; } - - log_error_write(srv, __FILE__, __LINE__, "ssdd", + + log_error_write(srv, __FILE__, __LINE__, "ssdd", "socket failed:", strerror(errno), srv->cur_fds, srv->max_fds); return HANDLER_ERROR; } hctx->fde_ndx = -1; - + srv->cur_fds++; - + fdevent_register(srv->ev, hctx->fd, fcgi_handle_fdevent, hctx); - + if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) { - log_error_write(srv, __FILE__, __LINE__, "ss", + log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed:", strerror(errno)); - + return HANDLER_ERROR; } - + if (hctx->proc->is_local) { hctx->pid = hctx->proc->pid; } - + switch (fcgi_establish_connection(srv, hctx)) { case CONNECTION_DELAYED: /* connection is in progress, wait for an event and call getsockopt() below */ - + fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); - + fcgi_set_state(srv, hctx, FCGI_STATE_CONNECT_DELAYED); return HANDLER_WAIT_FOR_EVENT; case CONNECTION_OVERLOADED: /* cool down the backend, it is overloaded * -> EAGAIN */ - log_error_write(srv, __FILE__, __LINE__, "ssdsd", + log_error_write(srv, __FILE__, __LINE__, "ssdsd", "backend is overloaded, we disable it for a 2 seconds and send the request to another backend instead:", "reconnects:", hctx->reconnects, "load:", host->load); @@ -2789,7 +2797,7 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) { buffer_append_string(p->statuskey, ".overloaded"); status_counter_inc(srv, CONST_BUF_LEN(p->statuskey)); - + return HANDLER_ERROR; case CONNECTION_DEAD: /* we got a hard error from the backend like @@ -2798,19 +2806,19 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) { * * for check if the host is back in 5 seconds * */ - + hctx->proc->disabled_until = srv->cur_ts + 5; if (hctx->proc->is_local) { hctx->proc->state = PROC_STATE_DIED_WAIT_FOR_PID; } else { hctx->proc->state = PROC_STATE_DIED; } - - log_error_write(srv, __FILE__, __LINE__, "ssdsd", + + log_error_write(srv, __FILE__, __LINE__, "ssdsd", "backend died, we disable it for a 5 seconds and send the request to another backend instead:", "reconnects:", hctx->reconnects, "load:", host->load); - + fastcgi_status_copy_procname(p->statuskey, hctx->host, hctx->proc); buffer_append_string(p->statuskey, ".died"); @@ -2821,19 +2829,19 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) { /* everything is ok, go on */ fcgi_set_state(srv, hctx, FCGI_STATE_PREPARE_WRITE); - + break; case CONNECTION_UNSET: break; } - + case FCGI_STATE_PREPARE_WRITE: /* ok, we have the connection */ - + hctx->proc->load++; hctx->proc->last_used = srv->cur_ts; hctx->got_proc = 1; - + status_counter_inc(srv, CONST_STR_LEN("fastcgi.requests")); status_counter_inc(srv, CONST_STR_LEN("fastcgi.active-requests")); @@ -2856,9 +2864,9 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) { if (p->conf.debug) { log_error_write(srv, __FILE__, __LINE__, "ssdsbsd", - "got proc:", - "pid:", hctx->proc->pid, - "socket:", hctx->proc->connection_name, + "got proc:", + "pid:", hctx->proc->pid, + "socket:", hctx->proc->connection_name, "load:", hctx->proc->load); } @@ -2866,62 +2874,62 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) { if (hctx->request_id == 0) { hctx->request_id = fcgi_requestid_new(srv, p); } else { - log_error_write(srv, __FILE__, __LINE__, "sd", + log_error_write(srv, __FILE__, __LINE__, "sd", "fcgi-request is already in use:", hctx->request_id); } - + /* fall through */ fcgi_create_env(srv, hctx, hctx->request_id); - + fcgi_set_state(srv, hctx, FCGI_STATE_WRITE); - + /* fall through */ case FCGI_STATE_WRITE: - ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb); + ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb); chunkqueue_remove_finished_chunks(hctx->wb); - + if (ret < 0) { switch(errno) { case ENOTCONN: - /* the connection got dropped after accept() - * - * this is most of the time a PHP which dies + /* the connection got dropped after accept() + * + * this is most of the time a PHP which dies * after PHP_FCGI_MAX_REQUESTS - * - */ + * + */ if (hctx->wb->bytes_out == 0 && hctx->reconnects < 5) { - usleep(10000); /* take away the load of the webserver - * to let the php a chance to restart + usleep(10000); /* take away the load of the webserver + * to let the php a chance to restart */ - + fcgi_reconnect(srv, hctx); - + return HANDLER_WAIT_FOR_FD; } - + /* not reconnected ... why - * + * * far@#lighttpd report this for FreeBSD - * + * */ - - log_error_write(srv, __FILE__, __LINE__, "ssdsd", + + log_error_write(srv, __FILE__, __LINE__, "ssdsd", "[REPORT ME] connection was dropped after accept(). reconnect() denied:", "write-offset:", hctx->wb->bytes_out, "reconnect attempts:", hctx->reconnects); - + return HANDLER_ERROR; case EAGAIN: case EINTR: fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); - + return HANDLER_WAIT_FOR_EVENT; default: - log_error_write(srv, __FILE__, __LINE__, "ssd", + log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), errno); - + return HANDLER_ERROR; } } @@ -2933,7 +2941,7 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) { fcgi_set_state(srv, hctx, FCGI_STATE_READ); } else { fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); - + return HANDLER_WAIT_FOR_EVENT; } @@ -2945,7 +2953,7 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) { log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state"); return HANDLER_ERROR; } - + return HANDLER_WAIT_FOR_EVENT; } @@ -2954,18 +2962,18 @@ static handler_t fcgi_write_request(server *srv, handler_ctx *hctx) { * */ SUBREQUEST_FUNC(mod_fastcgi_handle_subrequest) { plugin_data *p = p_d; - + handler_ctx *hctx = con->plugin_ctx[p->id]; fcgi_proc *proc; fcgi_extension_host *host; - + if (NULL == hctx) return HANDLER_GO_ON; - + /* not my job */ if (con->mode != p->id) return HANDLER_GO_ON; /* we don't have a host yet, choose one - * -> this happens in the first round + * -> this happens in the first round * and when the host died and we have to select a new one */ if (hctx->host == NULL) { size_t k; @@ -2974,23 +2982,23 @@ SUBREQUEST_FUNC(mod_fastcgi_handle_subrequest) { /* get best server */ for (k = 0, ndx = -1; k < hctx->ext->used; k++) { host = hctx->ext->hosts[k]; - + /* we should have at least one proc that can do something */ if (host->active_procs == 0) continue; if (used == -1 || host->load < used) { used = host->load; - + ndx = k; } } - + /* found a server */ if (ndx == -1) { /* all hosts are down */ fcgi_connection_close(srv, hctx); - + con->http_status = 500; con->mode = DIRECT; @@ -2998,16 +3006,16 @@ SUBREQUEST_FUNC(mod_fastcgi_handle_subrequest) { } host = hctx->ext->hosts[ndx]; - - /* - * if check-local is disabled, use the uri.path handler - * + + /* + * if check-local is disabled, use the uri.path handler + * */ - + /* init handler-context */ hctx->host = host; - /* we put a connection on this host, move the other new connections to other hosts + /* we put a connection on this host, move the other new connections to other hosts * * as soon as hctx->host is unassigned, decrease the load again */ hctx->host->load++; @@ -3021,7 +3029,7 @@ SUBREQUEST_FUNC(mod_fastcgi_handle_subrequest) { case HANDLER_ERROR: proc = hctx->proc; host = hctx->host; - + if (hctx->state == FCGI_STATE_INIT || hctx->state == FCGI_STATE_CONNECT_DELAYED) { if (proc) host->active_procs--; @@ -3036,7 +3044,7 @@ SUBREQUEST_FUNC(mod_fastcgi_handle_subrequest) { return HANDLER_WAIT_FOR_FD; } else { fcgi_connection_close(srv, hctx); - + buffer_reset(con->physical.path); con->mode = DIRECT; con->http_status = 500; @@ -3046,12 +3054,12 @@ SUBREQUEST_FUNC(mod_fastcgi_handle_subrequest) { } } else { fcgi_connection_close(srv, hctx); - + buffer_reset(con->physical.path); con->mode = DIRECT; con->http_status = 503; joblist_append(srv, con); /* really ? */ - + return HANDLER_FINISHED; } case HANDLER_WAIT_FOR_EVENT: @@ -3073,7 +3081,7 @@ static handler_t fcgi_handle_fdevent(void *s, void *ctx, int revents) { handler_ctx *hctx = ctx; connection *con = hctx->remote_conn; plugin_data *p = hctx->plugin_data; - + fcgi_proc *proc = hctx->proc; fcgi_extension_host *host= hctx->host; @@ -3083,8 +3091,8 @@ static handler_t fcgi_handle_fdevent(void *s, void *ctx, int revents) { case 0: break; case 1: - - if (host->mode == FCGI_AUTHORIZER && + + if (host->mode == FCGI_AUTHORIZER && (con->http_status == 200 || con->http_status == 0)) { /* @@ -3094,26 +3102,26 @@ static handler_t fcgi_handle_fdevent(void *s, void *ctx, int revents) { */ buffer_copy_string_buffer(con->physical.doc_root, host->docroot); - + buffer_copy_string_buffer(con->physical.path, host->docroot); buffer_append_string_buffer(con->physical.path, con->uri.path); fcgi_connection_close(srv, hctx); - + con->mode = DIRECT; con->file_started = 1; /* fcgi_extension won't touch the request afterwards */ } else { /* we are done */ fcgi_connection_close(srv, hctx); } - + joblist_append(srv, con); return HANDLER_FINISHED; case -1: if (proc->pid && proc->state != PROC_STATE_DIED) { int status; - + /* only fetch the zombie if it is not already done */ - + switch(waitpid(proc->pid, &status, WNOHANG)) { case 0: /* child is still alive */ @@ -3123,60 +3131,60 @@ static handler_t fcgi_handle_fdevent(void *s, void *ctx, int revents) { default: /* the child should not terminate at all */ if (WIFEXITED(status)) { - log_error_write(srv, __FILE__, __LINE__, "sdsd", + log_error_write(srv, __FILE__, __LINE__, "sdsd", "child exited, pid:", proc->pid, "status:", WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { - log_error_write(srv, __FILE__, __LINE__, "sd", - "child signaled:", + log_error_write(srv, __FILE__, __LINE__, "sd", + "child signaled:", WTERMSIG(status)); } else { - log_error_write(srv, __FILE__, __LINE__, "sd", - "child died somehow:", + log_error_write(srv, __FILE__, __LINE__, "sd", + "child died somehow:", status); } - + if (p->conf.debug) { log_error_write(srv, __FILE__, __LINE__, "ssbsdsd", "--- fastcgi spawning", "\n\tsocket", proc->connection_name, "\n\tcurrent:", 1, "/", host->min_procs); } - + if (fcgi_spawn_connection(srv, p, host, proc)) { /* respawning failed, retry later */ proc->state = PROC_STATE_DIED; - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "respawning failed, will retry later"); } - + break; } } if (con->file_started == 0) { /* nothing has been send out yet, try to use another child */ - + if (hctx->wb->bytes_out == 0 && hctx->reconnects < 5) { fcgi_reconnect(srv, hctx); - - log_error_write(srv, __FILE__, __LINE__, "ssbsbs", + + log_error_write(srv, __FILE__, __LINE__, "ssbsbs", "response not received, request not sent", - "on socket:", proc->connection_name, + "on socket:", proc->connection_name, "for", con->uri.path, ", reconnecting"); - + return HANDLER_WAIT_FOR_FD; } - - log_error_write(srv, __FILE__, __LINE__, "sosbsbs", + + log_error_write(srv, __FILE__, __LINE__, "sosbsbs", "response not received, request sent:", hctx->wb->bytes_out, - "on socket:", proc->connection_name, + "on socket:", proc->connection_name, "for", con->uri.path, ", closing connection"); - + fcgi_connection_close(srv, hctx); - + connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST); buffer_reset(con->physical.path); con->http_status = 500; @@ -3184,76 +3192,76 @@ static handler_t fcgi_handle_fdevent(void *s, void *ctx, int revents) { } else { /* response might have been already started, kill the connection */ fcgi_connection_close(srv, hctx); - - log_error_write(srv, __FILE__, __LINE__, "ssbsbs", + + log_error_write(srv, __FILE__, __LINE__, "ssbsbs", "response already sent out, but backend returned error", - "on socket:", proc->connection_name, + "on socket:", proc->connection_name, "for", con->uri.path, ", terminating connection"); - + connection_set_state(srv, con, CON_STATE_ERROR); } /* */ - - + + joblist_append(srv, con); return HANDLER_FINISHED; } } - + if (revents & FDEVENT_OUT) { if (hctx->state == FCGI_STATE_CONNECT_DELAYED || hctx->state == FCGI_STATE_WRITE) { /* we are allowed to send something out - * + * * 1. in a unfinished connect() call * 2. in a unfinished write() call (long POST request) */ return mod_fastcgi_handle_subrequest(srv, con, p); } else { - log_error_write(srv, __FILE__, __LINE__, "sd", - "got a FDEVENT_OUT and didn't know why:", + log_error_write(srv, __FILE__, __LINE__, "sd", + "got a FDEVENT_OUT and didn't know why:", hctx->state); } } - + /* perhaps this issue is already handled */ if (revents & FDEVENT_HUP) { if (hctx->state == FCGI_STATE_CONNECT_DELAYED) { /* getoptsock will catch this one (right ?) - * - * if we are in connect we might get a EINPROGRESS - * in the first call and a FDEVENT_HUP in the + * + * if we are in connect we might get a EINPROGRESS + * in the first call and a FDEVENT_HUP in the * second round - * + * * FIXME: as it is a bit ugly. - * + * */ return mod_fastcgi_handle_subrequest(srv, con, p); } else if (hctx->state == FCGI_STATE_READ && hctx->proc->port == 0) { /* FIXME: - * + * * ioctl says 8192 bytes to read from PHP and we receive directly a HUP for the socket * even if the FCGI_FIN packet is not received yet */ } else { - log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd", - "error: unexpected close of fastcgi connection for", + log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd", + "error: unexpected close of fastcgi connection for", con->uri.path, - "(no fastcgi process on host:", + "(no fastcgi process on host:", host->host, - ", port: ", + ", port: ", host->port, " ?)", hctx->state); - + connection_set_state(srv, con, CON_STATE_ERROR); fcgi_connection_close(srv, hctx); joblist_append(srv, con); } } else if (revents & FDEVENT_ERR) { - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "fcgi: got a FDEVENT_ERR. Don't know why."); /* kill all connections to the fastcgi process */ @@ -3262,7 +3270,7 @@ static handler_t fcgi_handle_fdevent(void *s, void *ctx, int revents) { fcgi_connection_close(srv, hctx); joblist_append(srv, con); } - + return HANDLER_FINISHED; } #define PATCH(x) \ @@ -3270,23 +3278,23 @@ static handler_t fcgi_handle_fdevent(void *s, void *ctx, int revents) { static int fcgi_patch_connection(server *srv, connection *con, plugin_data *p) { size_t i, j; plugin_config *s = p->config_storage[0]; - + PATCH(exts); PATCH(debug); PATCH(ext_mapping); - + /* 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("fastcgi.server"))) { PATCH(exts); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("fastcgi.debug"))) { @@ -3296,7 +3304,7 @@ static int fcgi_patch_connection(server *srv, connection *con, plugin_data *p) { } } } - + return 0; } #undef PATCH @@ -3309,16 +3317,16 @@ static handler_t fcgi_check_extension(server *srv, connection *con, void *p_d, i buffer *fn; fcgi_extension *extension = NULL; fcgi_extension_host *host = NULL; - + /* Possibly, we processed already this request */ if (con->file_started == 1) return HANDLER_GO_ON; fn = uri_path_handler ? con->uri.path : con->physical.path; if (buffer_is_empty(fn)) return HANDLER_GO_ON; - + s_len = fn->used - 1; - + fcgi_patch_connection(srv, con, p); /* fastcgi.map-extensions maps extensions to existing fastcgi.server entries @@ -3326,24 +3334,24 @@ static handler_t fcgi_check_extension(server *srv, connection *con, void *p_d, i * fastcgi.map-extensions = ( ".php3" => ".php" ) * * fastcgi.server = ( ".php" => ... ) - * + * * */ /* check if extension-mapping matches */ for (k = 0; k < p->conf.ext_mapping->used; k++) { data_string *ds = (data_string *)p->conf.ext_mapping->data[k]; size_t ct_len; /* length of the config entry */ - + if (ds->key->used == 0) continue; - + ct_len = ds->key->used - 1; - + if (s_len < ct_len) continue; - + /* found a mapping */ if (0 == strncmp(fn->ptr + s_len - ct_len, ds->key->ptr, ct_len)) { /* check if we know the extension */ - + /* we can reuse k here */ for (k = 0; k < p->conf.exts->used; k++) { extension = p->conf.exts->exts[k]; @@ -3365,15 +3373,15 @@ static handler_t fcgi_check_extension(server *srv, connection *con, void *p_d, i /* check if extension matches */ for (k = 0; k < p->conf.exts->used; k++) { size_t ct_len; /* length of the config entry */ - + extension = p->conf.exts->exts[k]; - + if (extension->key->used == 0) continue; - + ct_len = extension->key->used - 1; - + if (s_len < ct_len) continue; - + /* check extension in the form "/fcgi_pattern" */ if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) { break; @@ -3399,10 +3407,10 @@ static handler_t fcgi_check_extension(server *srv, connection *con, void *p_d, i continue; } - /* we found one host that is alive */ + /* we found one host that is alive */ break; } - + if (!host) { /* sorry, we don't have a server alive for this ext */ buffer_reset(con->physical.path); @@ -3417,72 +3425,72 @@ static handler_t fcgi_check_extension(server *srv, connection *con, void *p_d, i "on", extension->key, "are down."); } - + return HANDLER_FINISHED; } /* a note about no handler is not sent yey */ extension->note_is_sent = 0; - /* - * if check-local is disabled, use the uri.path handler - * + /* + * if check-local is disabled, use the uri.path handler + * */ - + /* init handler-context */ if (uri_path_handler) { if (host->check_local == 0) { handler_ctx *hctx; char *pathinfo; - + hctx = handler_ctx_init(); - + hctx->remote_conn = con; hctx->plugin_data = p; hctx->proc = NULL; hctx->ext = extension; - + hctx->conf.exts = p->conf.exts; hctx->conf.debug = p->conf.debug; - + con->plugin_ctx[p->id] = hctx; - + con->mode = p->id; - + if (con->conf.log_request_handling) { - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_fastcgi"); } - - /* the prefix is the SCRIPT_NAME, + + /* the prefix is the SCRIPT_NAME, * everthing from start to the next slash * this is important for check-local = "disable" - * + * * if prefix = /admin.fcgi - * + * * /admin.fcgi/foo/bar - * + * * SCRIPT_NAME = /admin.fcgi * PATH_INFO = /foo/bar - * + * * if prefix = /fcgi-bin/ - * + * * /fcgi-bin/foo/bar - * + * * SCRIPT_NAME = /fcgi-bin/foo * PATH_INFO = /bar - * + * */ - + /* the rewrite is only done for /prefix/? matches */ if (extension->key->ptr[0] == '/' && con->uri.path->used > extension->key->used && NULL != (pathinfo = strchr(con->uri.path->ptr + extension->key->used - 1, '/'))) { - /* rewrite uri.path and pathinfo */ - + /* rewrite uri.path and pathinfo */ + buffer_copy_string(con->request.pathinfo, pathinfo); - + con->uri.path->used -= con->request.pathinfo->used - 1; con->uri.path->ptr[con->uri.path->used - 1] = '\0'; } @@ -3490,19 +3498,19 @@ static handler_t fcgi_check_extension(server *srv, connection *con, void *p_d, i } else { handler_ctx *hctx; hctx = handler_ctx_init(); - + hctx->remote_conn = con; hctx->plugin_data = p; hctx->proc = NULL; hctx->ext = extension; - + hctx->conf.exts = p->conf.exts; hctx->conf.debug = p->conf.debug; - + con->plugin_ctx[p->id] = hctx; - + con->mode = p->id; - + if (con->conf.log_request_handling) { log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_fastcgi"); } @@ -3524,19 +3532,19 @@ static handler_t fcgi_check_extension_2(server *srv, connection *con, void *p_d) JOBLIST_FUNC(mod_fastcgi_handle_joblist) { plugin_data *p = p_d; handler_ctx *hctx = con->plugin_ctx[p->id]; - + if (hctx == NULL) return HANDLER_GO_ON; if (hctx->fd != -1) { switch (hctx->state) { case FCGI_STATE_READ: fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN); - + break; case FCGI_STATE_CONNECT_DELAYED: case FCGI_STATE_WRITE: fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); - + break; case FCGI_STATE_INIT: /* at reconnect */ @@ -3553,7 +3561,7 @@ JOBLIST_FUNC(mod_fastcgi_handle_joblist) { static handler_t fcgi_connection_close_callback(server *srv, connection *con, void *p_d) { plugin_data *p = p_d; - + fcgi_connection_close(srv, con->plugin_ctx[p->id]); return HANDLER_GO_ON; @@ -3562,14 +3570,14 @@ static handler_t fcgi_connection_close_callback(server *srv, connection *con, vo TRIGGER_FUNC(mod_fastcgi_handle_trigger) { plugin_data *p = p_d; size_t i, j, n; - - + + /* perhaps we should kill a connect attempt after 10-15 seconds - * + * * currently we wait for the TCP timeout which is on Linux 180 seconds - * - * - * + * + * + * */ /* check all childs if they are still up */ @@ -3586,45 +3594,45 @@ TRIGGER_FUNC(mod_fastcgi_handle_trigger) { fcgi_extension *ex; ex = exts->exts[j]; - + for (n = 0; n < ex->used; n++) { - + fcgi_proc *proc; unsigned long sum_load = 0; fcgi_extension_host *host; - + host = ex->hosts[n]; - + fcgi_restart_dead_procs(srv, p, host); - + for (proc = host->first; proc; proc = proc->next) { sum_load += proc->load; } - + if (host->num_procs && host->num_procs < host->max_procs && (sum_load / host->num_procs) > host->max_load_per_proc) { /* overload, spawn new child */ if (p->conf.debug) { - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "overload detected, spawning a new child"); } - + for (proc = host->unused_procs; proc && proc->pid != 0; proc = proc->next); - + if (proc) { if (proc == host->unused_procs) host->unused_procs = proc->next; - + if (proc->next) proc->next->prev = NULL; - + host->max_id++; } else { proc = fastcgi_process_init(); proc->id = host->max_id++; } - + host->num_procs++; - + if (buffer_is_empty(host->unixsocket)) { proc->port = host->port + proc->id; } else { @@ -3632,13 +3640,13 @@ TRIGGER_FUNC(mod_fastcgi_handle_trigger) { buffer_append_string(proc->unixsocket, "-"); buffer_append_long(proc->unixsocket, proc->id); } - + if (fcgi_spawn_connection(srv, p, host, proc)) { log_error_write(srv, __FILE__, __LINE__, "s", "ERROR: spawning fcgi failed."); return HANDLER_ERROR; } - + proc->prev = NULL; proc->next = host->first; if (host->first) { @@ -3646,56 +3654,56 @@ TRIGGER_FUNC(mod_fastcgi_handle_trigger) { } host->first = proc; } - + for (proc = host->first; proc; proc = proc->next) { if (proc->load != 0) break; if (host->num_procs <= host->min_procs) break; if (proc->pid == 0) continue; - + if (srv->cur_ts - proc->last_used > host->idle_timeout) { /* a proc is idling for a long time now, * terminated it */ - + if (p->conf.debug) { - log_error_write(srv, __FILE__, __LINE__, "ssbsd", - "idle-timeout reached, terminating child:", - "socket:", proc->connection_name, + log_error_write(srv, __FILE__, __LINE__, "ssbsd", + "idle-timeout reached, terminating child:", + "socket:", proc->connection_name, "pid", proc->pid); } - - + + if (proc->next) proc->next->prev = proc->prev; if (proc->prev) proc->prev->next = proc->next; - + if (proc->prev == NULL) host->first = proc->next; - + proc->prev = NULL; proc->next = host->unused_procs; - + if (host->unused_procs) host->unused_procs->prev = proc; host->unused_procs = proc; - + kill(proc->pid, SIGTERM); - + proc->state = PROC_STATE_KILLED; - - log_error_write(srv, __FILE__, __LINE__, "ssbsd", - "killed:", - "socket:", proc->connection_name, + + log_error_write(srv, __FILE__, __LINE__, "ssbsd", + "killed:", + "socket:", proc->connection_name, "pid", proc->pid); - + host->num_procs--; - + /* proc is now in unused, let the next second handle the next process */ break; - } + } } - + for (proc = host->unused_procs; proc; proc = proc->next) { int status; - + if (proc->pid == 0) continue; - + switch (waitpid(proc->pid, &status, WNOHANG)) { case 0: /* child still running after timeout, good */ @@ -3703,10 +3711,10 @@ TRIGGER_FUNC(mod_fastcgi_handle_trigger) { case -1: if (errno != EINTR) { /* no PID found ? should never happen */ - log_error_write(srv, __FILE__, __LINE__, "sddss", + log_error_write(srv, __FILE__, __LINE__, "sddss", "pid ", proc->pid, proc->state, "not found:", strerror(errno)); - + #if 0 if (errno == ECHILD) { /* someone else has cleaned up for us */ @@ -3720,19 +3728,19 @@ TRIGGER_FUNC(mod_fastcgi_handle_trigger) { /* the child should not terminate at all */ if (WIFEXITED(status)) { if (proc->state != PROC_STATE_KILLED) { - log_error_write(srv, __FILE__, __LINE__, "sdb", - "child exited:", + log_error_write(srv, __FILE__, __LINE__, "sdb", + "child exited:", WEXITSTATUS(status), proc->connection_name); } } else if (WIFSIGNALED(status)) { if (WTERMSIG(status) != SIGTERM) { - log_error_write(srv, __FILE__, __LINE__, "sd", - "child signaled:", + log_error_write(srv, __FILE__, __LINE__, "sd", + "child signaled:", WTERMSIG(status)); } } else { - log_error_write(srv, __FILE__, __LINE__, "sd", - "child died somehow:", + log_error_write(srv, __FILE__, __LINE__, "sd", + "child died somehow:", status); } proc->pid = 0; @@ -3762,8 +3770,8 @@ int mod_fastcgi_plugin_init(plugin *p) { p->handle_subrequest = mod_fastcgi_handle_subrequest; p->handle_joblist = mod_fastcgi_handle_joblist; p->handle_trigger = mod_fastcgi_handle_trigger; - + p->data = NULL; - + return 0; } diff --git a/src/mod_flv_streaming.c b/src/mod_flv_streaming.c index d1f467a..32f2369 100644 --- a/src/mod_flv_streaming.c +++ b/src/mod_flv_streaming.c @@ -23,35 +23,35 @@ typedef struct { typedef struct { PLUGIN_DATA; - + buffer *query_str; array *get_params; - + plugin_config **config_storage; - - plugin_config conf; + + plugin_config conf; } plugin_data; /* init the plugin data */ INIT_FUNC(mod_flv_streaming_init) { plugin_data *p; - + p = calloc(1, sizeof(*p)); - + p->query_str = buffer_init(); p->get_params = array_init(); - + return p; } /* detroy the plugin data */ FREE_FUNC(mod_flv_streaming_free) { plugin_data *p = p_d; - + UNUSED(srv); if (!p) return HANDLER_GO_ON; - + if (p->config_storage) { size_t i; @@ -59,19 +59,19 @@ FREE_FUNC(mod_flv_streaming_free) { plugin_config *s = p->config_storage[i]; if (!s) continue; - + array_free(s->extensions); - + free(s); } free(p->config_storage); } - + buffer_free(p->query_str); array_free(p->get_params); - + free(p); - + return HANDLER_GO_ON; } @@ -80,31 +80,31 @@ FREE_FUNC(mod_flv_streaming_free) { SETDEFAULTS_FUNC(mod_flv_streaming_set_defaults) { plugin_data *p = p_d; size_t i = 0; - - config_values_t cv[] = { + + config_values_t cv[] = { { "flv-streaming.extensions", 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)); s->extensions = array_init(); - + cv[0].destination = s->extensions; - + 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; } @@ -113,27 +113,27 @@ SETDEFAULTS_FUNC(mod_flv_streaming_set_defaults) { static int mod_flv_streaming_patch_connection(server *srv, connection *con, plugin_data *p) { size_t i, j; plugin_config *s = p->config_storage[0]; - + PATCH(extensions); - + /* 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("flv-streaming.extensions"))) { PATCH(extensions); } } } - + return 0; } #undef PATCH @@ -142,21 +142,21 @@ static int split_get_params(array *get_params, buffer *qrystr) { size_t is_key = 1; size_t i; char *key = NULL, *val = NULL; - + key = qrystr->ptr; - + /* we need the \0 */ for (i = 0; i < qrystr->used; i++) { switch(qrystr->ptr[i]) { case '=': if (is_key) { val = qrystr->ptr + i + 1; - + qrystr->ptr[i] = '\0'; - + is_key = 0; } - + break; case '&': case '\0': /* fin symbol */ @@ -175,14 +175,14 @@ static int split_get_params(array *get_params, buffer *qrystr) { array_insert_unique(get_params, (data_unset *)ds); } - + key = qrystr->ptr + i + 1; val = NULL; is_key = 1; break; } } - + return 0; } @@ -190,29 +190,29 @@ URIHANDLER_FUNC(mod_flv_streaming_path_handler) { plugin_data *p = p_d; int s_len; size_t k; - + UNUSED(srv); if (buffer_is_empty(con->physical.path)) return HANDLER_GO_ON; - + mod_flv_streaming_patch_connection(srv, con, p); s_len = con->physical.path->used - 1; - + for (k = 0; k < p->conf.extensions->used; k++) { data_string *ds = (data_string *)p->conf.extensions->data[k]; int ct_len = ds->value->used - 1; - + if (ct_len > s_len) continue; if (ds->value->used == 0) continue; - + if (0 == strncmp(con->physical.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) { data_string *get_param; stat_cache_entry *sce = NULL; buffer *b; int start; char *err = NULL; - /* if there is a start=[0-9]+ in the header use it as start, + /* if there is a start=[0-9]+ in the header use it as start, * otherwise send the full file */ array_reset(p->get_params); @@ -256,7 +256,7 @@ URIHANDLER_FUNC(mod_flv_streaming_path_handler) { return HANDLER_FINISHED; } } - + /* not found */ return HANDLER_GO_ON; } @@ -266,13 +266,13 @@ URIHANDLER_FUNC(mod_flv_streaming_path_handler) { int mod_flv_streaming_plugin_init(plugin *p) { p->version = LIGHTTPD_VERSION_ID; p->name = buffer_init_string("flv_streaming"); - + p->init = mod_flv_streaming_init; p->handle_physical = mod_flv_streaming_path_handler; p->set_defaults = mod_flv_streaming_set_defaults; p->cleanup = mod_flv_streaming_free; - + p->data = NULL; - + return 0; } diff --git a/src/mod_indexfile.c b/src/mod_indexfile.c index 4a784c6..d167424 100644 --- a/src/mod_indexfile.c +++ b/src/mod_indexfile.c @@ -20,51 +20,51 @@ typedef struct { typedef struct { PLUGIN_DATA; - + buffer *tmp_buf; - + plugin_config **config_storage; - - plugin_config conf; + + plugin_config conf; } plugin_data; /* init the plugin data */ INIT_FUNC(mod_indexfile_init) { plugin_data *p; - + p = calloc(1, sizeof(*p)); - + p->tmp_buf = buffer_init(); - + return p; } /* detroy the plugin data */ FREE_FUNC(mod_indexfile_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]; if (!s) continue; - + array_free(s->indexfiles); - + free(s); } free(p->config_storage); } - + buffer_free(p->tmp_buf); - + free(p); - + return HANDLER_GO_ON; } @@ -73,33 +73,33 @@ FREE_FUNC(mod_indexfile_free) { SETDEFAULTS_FUNC(mod_indexfile_set_defaults) { plugin_data *p = p_d; size_t i = 0; - - config_values_t cv[] = { + + config_values_t cv[] = { { "index-file.names", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ { "server.indexfiles", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */ { 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->indexfiles = array_init(); - + cv[0].destination = s->indexfiles; cv[1].destination = s->indexfiles; /* old name for [0] */ - + 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; } @@ -108,21 +108,21 @@ SETDEFAULTS_FUNC(mod_indexfile_set_defaults) { static int mod_indexfile_patch_connection(server *srv, connection *con, plugin_data *p) { size_t i, j; plugin_config *s = p->config_storage[0]; - + PATCH(indexfiles); - + /* 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("server.indexfiles"))) { PATCH(indexfiles); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("index-file.names"))) { @@ -130,7 +130,7 @@ static int mod_indexfile_patch_connection(server *srv, connection *con, plugin_d } } } - + return 0; } #undef PATCH @@ -139,65 +139,65 @@ URIHANDLER_FUNC(mod_indexfile_subrequest) { plugin_data *p = p_d; size_t k; stat_cache_entry *sce = NULL; - + if (con->uri.path->used == 0) return HANDLER_GO_ON; if (con->uri.path->ptr[con->uri.path->used - 2] != '/') return HANDLER_GO_ON; - + mod_indexfile_patch_connection(srv, con, p); - + if (con->conf.log_request_handling) { log_error_write(srv, __FILE__, __LINE__, "s", "-- handling the request as Indexfile"); log_error_write(srv, __FILE__, __LINE__, "sb", "URI :", con->uri.path); } - + /* indexfile */ for (k = 0; k < p->conf.indexfiles->used; k++) { data_string *ds = (data_string *)p->conf.indexfiles->data[k]; - + if (ds->value && ds->value->ptr[0] == '/') { - /* if the index-file starts with a prefix as use this file as + /* if the index-file starts with a prefix as use this file as * index-generator */ buffer_copy_string_buffer(p->tmp_buf, con->physical.doc_root); } else { buffer_copy_string_buffer(p->tmp_buf, con->physical.path); } buffer_append_string_buffer(p->tmp_buf, ds->value); - + if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->tmp_buf, &sce)) { if (errno == EACCES) { con->http_status = 403; buffer_reset(con->physical.path); - + return HANDLER_FINISHED; } - + if (errno != ENOENT && errno != ENOTDIR) { /* we have no idea what happend. let's tell the user so. */ - + con->http_status = 500; - + log_error_write(srv, __FILE__, __LINE__, "ssbsb", "file not found ... or so: ", strerror(errno), con->uri.path, "->", con->physical.path); - + buffer_reset(con->physical.path); - + return HANDLER_FINISHED; } continue; } - + /* rewrite uri.path to the real path (/ -> /index.php) */ buffer_append_string_buffer(con->uri.path, ds->value); buffer_copy_string_buffer(con->physical.path, p->tmp_buf); - + /* fce is already set up a few lines above */ - + return HANDLER_GO_ON; } - + /* not found */ return HANDLER_GO_ON; } @@ -207,13 +207,13 @@ URIHANDLER_FUNC(mod_indexfile_subrequest) { int mod_indexfile_plugin_init(plugin *p) { p->version = LIGHTTPD_VERSION_ID; p->name = buffer_init_string("indexfile"); - + p->init = mod_indexfile_init; p->handle_subrequest_start = mod_indexfile_subrequest; p->set_defaults = mod_indexfile_set_defaults; p->cleanup = mod_indexfile_free; - + p->data = NULL; - + return 0; } diff --git a/src/mod_magnet.c b/src/mod_magnet.c index a2f6185..4fd0795 100644 --- a/src/mod_magnet.c +++ b/src/mod_magnet.c @@ -14,6 +14,7 @@ #include "response.h" #include "stat_cache.h" #include "status_counter.h" +#include "etag.h" #ifdef HAVE_LUA_H #include <lua.h> @@ -34,36 +35,36 @@ typedef struct { typedef struct { PLUGIN_DATA; - + script_cache *cache; buffer *encode_buf; - + plugin_config **config_storage; - - plugin_config conf; + + plugin_config conf; } plugin_data; /* init the plugin data */ INIT_FUNC(mod_magnet_init) { plugin_data *p; - + p = calloc(1, sizeof(*p)); - + p->cache = script_cache_init(); p->encode_buf = buffer_init(); - + return p; } /* detroy the plugin data */ FREE_FUNC(mod_magnet_free) { plugin_data *p = p_d; - + UNUSED(srv); if (!p) return HANDLER_GO_ON; - + if (p->config_storage) { size_t i; @@ -71,20 +72,20 @@ FREE_FUNC(mod_magnet_free) { plugin_config *s = p->config_storage[i]; if (!s) continue; - + array_free(s->url_raw); array_free(s->physical_path); - + free(s); } free(p->config_storage); } - + script_cache_free(p->cache); buffer_free(p->encode_buf); - + free(p); - + return HANDLER_GO_ON; } @@ -93,34 +94,34 @@ FREE_FUNC(mod_magnet_free) { SETDEFAULTS_FUNC(mod_magnet_set_defaults) { plugin_data *p = p_d; size_t i = 0; - - config_values_t cv[] = { + + config_values_t cv[] = { { MAGNET_CONFIG_RAW_URL, NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ { MAGNET_CONFIG_PHYSICAL_PATH, NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */ { 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->url_raw = array_init(); s->physical_path = array_init(); - + cv[0].destination = s->url_raw; cv[1].destination = s->physical_path; - + 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; } @@ -129,22 +130,22 @@ SETDEFAULTS_FUNC(mod_magnet_set_defaults) { static int mod_magnet_patch_connection(server *srv, connection *con, plugin_data *p) { size_t i, j; plugin_config *s = p->config_storage[0]; - + PATCH(url_raw); PATCH(physical_path); - + /* 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(MAGNET_CONFIG_RAW_URL))) { PATCH(url_raw); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN(MAGNET_CONFIG_PHYSICAL_PATH))) { @@ -152,7 +153,7 @@ static int mod_magnet_patch_connection(server *srv, connection *con, plugin_data } } } - + return 0; } #undef PATCH @@ -166,12 +167,106 @@ static int magnet_print(lua_State *L) { srv = lua_touserdata(L, -1); lua_pop(L, 1); - log_error_write(srv, __FILE__, __LINE__, "ss", + log_error_write(srv, __FILE__, __LINE__, "ss", "(lua-print)", s); return 0; } +static int magnet_stat(lua_State *L) { + const char *s = luaL_checkstring(L, 1); + server *srv; + connection *con; + buffer sb; + stat_cache_entry *sce = NULL; + + lua_pushstring(L, "lighty.srv"); + lua_gettable(L, LUA_REGISTRYINDEX); + srv = lua_touserdata(L, -1); + lua_pop(L, 1); + + lua_pushstring(L, "lighty.con"); + lua_gettable(L, LUA_REGISTRYINDEX); + con = lua_touserdata(L, -1); + lua_pop(L, 1); + + sb.ptr = (char *)s; + sb.used = sb.size = strlen(s) + 1; + + if (HANDLER_GO_ON != stat_cache_get_entry(srv, con, &sb, &sce)) { + lua_pushnil(L); + + return 1; + } + + lua_newtable(L); + + lua_pushboolean(L, S_ISREG(sce->st.st_mode)); + lua_setfield(L, -2, "is_file"); + + lua_pushboolean(L, S_ISDIR(sce->st.st_mode)); + lua_setfield(L, -2, "is_dir"); + + lua_pushboolean(L, S_ISCHR(sce->st.st_mode)); + lua_setfield(L, -2, "is_char"); + + lua_pushboolean(L, S_ISBLK(sce->st.st_mode)); + lua_setfield(L, -2, "is_block"); + + lua_pushboolean(L, S_ISSOCK(sce->st.st_mode)); + lua_setfield(L, -2, "is_socket"); + + lua_pushboolean(L, S_ISLNK(sce->st.st_mode)); + lua_setfield(L, -2, "is_link"); + + lua_pushboolean(L, S_ISFIFO(sce->st.st_mode)); + lua_setfield(L, -2, "is_fifo"); + + lua_pushinteger(L, sce->st.st_mtime); + lua_setfield(L, -2, "st_mtime"); + + lua_pushinteger(L, sce->st.st_ctime); + lua_setfield(L, -2, "st_ctime"); + + lua_pushinteger(L, sce->st.st_atime); + lua_setfield(L, -2, "st_atime"); + + lua_pushinteger(L, sce->st.st_uid); + lua_setfield(L, -2, "st_uid"); + + lua_pushinteger(L, sce->st.st_gid); + lua_setfield(L, -2, "st_gid"); + + lua_pushinteger(L, sce->st.st_size); + lua_setfield(L, -2, "st_size"); + + lua_pushinteger(L, sce->st.st_ino); + lua_setfield(L, -2, "st_ino"); + + + if (!buffer_is_empty(sce->etag)) { + /* we have to mutate the etag */ + buffer *b = buffer_init(); + etag_mutate(b, sce->etag); + + lua_pushlstring(L, b->ptr, b->used - 1); + buffer_free(b); + } else { + lua_pushnil(L); + } + lua_setfield(L, -2, "etag"); + + if (!buffer_is_empty(sce->content_type)) { + lua_pushlstring(L, sce->content_type->ptr, sce->content_type->used - 1); + } else { + lua_pushnil(L); + } + lua_setfield(L, -2, "content-type"); + + return 1; +} + + static int magnet_atpanic(lua_State *L) { const char *s = luaL_checkstring(L, 1); server *srv; @@ -181,9 +276,9 @@ static int magnet_atpanic(lua_State *L) { srv = lua_touserdata(L, -1); lua_pop(L, 1); - log_error_write(srv, __FILE__, __LINE__, "ss", + log_error_write(srv, __FILE__, __LINE__, "ss", "(lua-atpanic)", s); - + longjmp(exceptionjmp, 1); } @@ -254,7 +349,7 @@ static int magnet_status_set(lua_State *L) { typedef struct { const char *name; - enum { + enum { MAGNET_ENV_UNSET, MAGNET_ENV_PHYICAL_PATH, @@ -269,6 +364,7 @@ typedef struct { MAGNET_ENV_REQUEST_METHOD, MAGNET_ENV_REQUEST_URI, + MAGNET_ENV_REQUEST_ORIG_URI, MAGNET_ENV_REQUEST_PROTOCOL } type; } magnet_env_t; @@ -290,14 +386,16 @@ static buffer *magnet_env_get_buffer(server *srv, connection *con, const char *k { "request.method", MAGNET_ENV_REQUEST_METHOD }, { "request.uri", MAGNET_ENV_REQUEST_URI }, + { "request.orig-uri", MAGNET_ENV_REQUEST_ORIG_URI }, { "request.protocol", MAGNET_ENV_REQUEST_PROTOCOL }, - + { NULL, MAGNET_ENV_UNSET } }; + UNUSED(srv); /** - * map all internal variables to lua + * map all internal variables to lua * */ @@ -318,6 +416,7 @@ static buffer *magnet_env_get_buffer(server *srv, connection *con, const char *k case MAGNET_ENV_REQUEST_METHOD: break; case MAGNET_ENV_REQUEST_URI: dest = con->request.uri; break; + case MAGNET_ENV_REQUEST_ORIG_URI: dest = con->request.orig_uri; break; case MAGNET_ENV_REQUEST_PROTOCOL: break; case MAGNET_ENV_UNSET: break; @@ -385,6 +484,7 @@ static int magnet_env_set(lua_State *L) { static int magnet_copy_response_header(server *srv, connection *con, plugin_data *p, lua_State *L) { + UNUSED(p); /** * get the environment of the function */ @@ -414,7 +514,7 @@ static int magnet_copy_response_header(server *srv, connection *con, plugin_data lua_pop(L, 1); } - } + } lua_pop(L, 1); /* pop the header-table */ lua_pop(L, 1); /* pop the lighty-env */ @@ -424,15 +524,16 @@ static int magnet_copy_response_header(server *srv, connection *con, plugin_data } /** - * walk through the content array + * walk through the content array * - * content = { "<pre>", { file = "/content" } , "</pre>" } + * content = { "<pre>", { file = "/content" } , "</pre>" } * * header["Content-Type"] = "text/html" - * + * * return 200 */ static int magnet_attach_content(server *srv, connection *con, plugin_data *p, lua_State *L) { + UNUSED(p); /** * get the environment of the function */ @@ -489,7 +590,7 @@ static int magnet_attach_content(server *srv, connection *con, plugin_data *p, l if (len < off) { return luaL_error(L, "offset > length for '%s'", fn->ptr); } - + chunkqueue_append_file(con->write_queue, fn, off, len - off); } @@ -534,7 +635,7 @@ static handler_t magnet_attract(server *srv, connection *con, plugin_data *p, bu L = script_cache_get_script(srv, con, p->cache, name); if (lua_isstring(L, -1)) { - log_error_write(srv, __FILE__, __LINE__, + log_error_write(srv, __FILE__, __LINE__, "sbss", "loading script", name, @@ -542,7 +643,7 @@ static handler_t magnet_attract(server *srv, connection *con, plugin_data *p, bu lua_tostring(L, -1)); lua_pop(L, 1); - + assert(lua_gettop(L) == 0); /* only the function should be on the stack */ con->http_status = 500; @@ -550,25 +651,25 @@ static handler_t magnet_attract(server *srv, connection *con, plugin_data *p, bu return HANDLER_FINISHED; } - lua_pushstring(L, "lighty.srv"); + lua_pushstring(L, "lighty.srv"); lua_pushlightuserdata(L, srv); lua_settable(L, LUA_REGISTRYINDEX); /* registery[<id>] = srv */ - lua_pushstring(L, "lighty.con"); + lua_pushstring(L, "lighty.con"); lua_pushlightuserdata(L, con); lua_settable(L, LUA_REGISTRYINDEX); /* registery[<id>] = con */ lua_atpanic(L, magnet_atpanic); /** - * we want to create empty environment for our script - * + * we want to create empty environment for our script + * * setmetatable({}, {__index = _G}) - * - * if a function, symbol is not defined in our env, __index will lookup + * + * if a function, symbol is not defined in our env, __index will lookup * in the global env. * - * all variables created in the script-env will be thrown + * all variables created in the script-env will be thrown * away at the end of the script run. */ lua_newtable(L); /* my empty environment aka {} (sp += 1) */ @@ -578,8 +679,8 @@ static handler_t magnet_attract(server *srv, connection *con, plugin_data *p, bu lua_setfield(L, -2, "print"); /* -1 is the env we want to set(sp -= 1) */ /** - * lighty.request[] has the HTTP-request headers - * lighty.content[] is a table of string/file + * lighty.request[] has the HTTP-request headers + * lighty.content[] is a table of string/file * lighty.header[] is a array to set response headers */ @@ -588,25 +689,25 @@ static handler_t magnet_attract(server *srv, connection *con, plugin_data *p, bu lua_newtable(L); /* {} (sp += 1) */ lua_newtable(L); /* the meta-table for the request-table (sp += 1) */ lua_pushcfunction(L, magnet_reqhdr_get); /* (sp += 1) */ - lua_setfield(L, -2, "__index"); /* (sp -= 1) */ + lua_setfield(L, -2, "__index"); /* (sp -= 1) */ lua_setmetatable(L, -2); /* tie the metatable to request (sp -= 1) */ lua_setfield(L, -2, "request"); /* content = {} (sp -= 1) */ lua_newtable(L); /* {} (sp += 1) */ lua_newtable(L); /* the meta-table for the request-table (sp += 1) */ lua_pushcfunction(L, magnet_env_get); /* (sp += 1) */ - lua_setfield(L, -2, "__index"); /* (sp -= 1) */ + lua_setfield(L, -2, "__index"); /* (sp -= 1) */ lua_pushcfunction(L, magnet_env_set); /* (sp += 1) */ - lua_setfield(L, -2, "__newindex"); /* (sp -= 1) */ + lua_setfield(L, -2, "__newindex"); /* (sp -= 1) */ lua_setmetatable(L, -2); /* tie the metatable to request (sp -= 1) */ lua_setfield(L, -2, "env"); /* content = {} (sp -= 1) */ lua_newtable(L); /* {} (sp += 1) */ lua_newtable(L); /* the meta-table for the request-table (sp += 1) */ lua_pushcfunction(L, magnet_status_get); /* (sp += 1) */ - lua_setfield(L, -2, "__index"); /* (sp -= 1) */ + lua_setfield(L, -2, "__index"); /* (sp -= 1) */ lua_pushcfunction(L, magnet_status_set); /* (sp += 1) */ - lua_setfield(L, -2, "__newindex"); /* (sp -= 1) */ + lua_setfield(L, -2, "__newindex"); /* (sp -= 1) */ lua_setmetatable(L, -2); /* tie the metatable to request (sp -= 1) */ lua_setfield(L, -2, "status"); /* content = {} (sp -= 1) */ @@ -620,19 +721,22 @@ static handler_t magnet_attract(server *srv, connection *con, plugin_data *p, bu lua_pushinteger(L, MAGNET_RESTART_REQUEST); lua_setfield(L, -2, "RESTART_REQUEST"); + lua_pushcfunction(L, magnet_stat); /* (sp += 1) */ + lua_setfield(L, -2, "stat"); /* -1 is the env we want to set (sp -= 1) */ + lua_setfield(L, -2, "lighty"); /* lighty.* (sp -= 1) */ - + lua_newtable(L); /* the meta-table for the new env (sp += 1) */ lua_pushvalue(L, LUA_GLOBALSINDEX); /* (sp += 1) */ lua_setfield(L, -2, "__index"); /* { __index = _G } (sp -= 1) */ lua_setmetatable(L, -2); /* setmetatable({}, {__index = _G}) (sp -= 1) */ - + lua_setfenv(L, -2); /* on the stack should be a modified env (sp -= 1) */ if (lua_pcall(L, 0, 1, 0)) { - log_error_write(srv, __FILE__, __LINE__, - "ss", + log_error_write(srv, __FILE__, __LINE__, + "ss", "lua_pcall():", lua_tostring(L, -1)); lua_pop(L, 1); /* remove the error-msg and the function copy from the stack */ @@ -658,7 +762,7 @@ static handler_t magnet_attract(server *srv, connection *con, plugin_data *p, bu if (lua_return_value > 99) { con->http_status = lua_return_value; con->file_finished = 1; - + /* try { ...*/ if (0 == setjmp(exceptionjmp)) { magnet_attach_content(srv, con, p, L); @@ -666,7 +770,7 @@ static handler_t magnet_attract(server *srv, connection *con, plugin_data *p, bu /* } catch () { */ con->http_status = 500; } - + assert(lua_gettop(L) == 1); /* only the function should be on the stack */ /* we are finished */ @@ -677,7 +781,7 @@ static handler_t magnet_attract(server *srv, connection *con, plugin_data *p, bu return HANDLER_COMEBACK; } else { assert(lua_gettop(L) == 1); /* only the function should be on the stack */ - + return HANDLER_GO_ON; } } @@ -696,7 +800,7 @@ static handler_t magnet_attract_array(server *srv, connection *con, plugin_data handler_t ret; if (buffer_is_empty(ds->value)) continue; - + ret = magnet_attract(srv, con, p, ds->value); if (ret != HANDLER_GO_ON) return ret; @@ -707,7 +811,7 @@ static handler_t magnet_attract_array(server *srv, connection *con, plugin_data URIHANDLER_FUNC(mod_magnet_uri_handler) { plugin_data *p = p_d; - + mod_magnet_patch_connection(srv, con, p); return magnet_attract_array(srv, con, p, p->conf.url_raw); @@ -715,7 +819,7 @@ URIHANDLER_FUNC(mod_magnet_uri_handler) { URIHANDLER_FUNC(mod_magnet_physical) { plugin_data *p = p_d; - + mod_magnet_patch_connection(srv, con, p); return magnet_attract_array(srv, con, p, p->conf.physical_path); @@ -727,20 +831,21 @@ URIHANDLER_FUNC(mod_magnet_physical) { int mod_magnet_plugin_init(plugin *p) { p->version = LIGHTTPD_VERSION_ID; p->name = buffer_init_string("magnet"); - + p->init = mod_magnet_init; p->handle_uri_clean = mod_magnet_uri_handler; p->handle_physical = mod_magnet_physical; p->set_defaults = mod_magnet_set_defaults; p->cleanup = mod_magnet_free; - + p->data = NULL; - + return 0; } #else int mod_magnet_plugin_init(plugin *p) { + UNUSED(p); return -1; } #endif diff --git a/src/mod_magnet_cache.c b/src/mod_magnet_cache.c index e2f5d84..3756bd1 100644 --- a/src/mod_magnet_cache.c +++ b/src/mod_magnet_cache.c @@ -34,7 +34,7 @@ void script_free(script *sc) { script_cache *script_cache_init() { script_cache *p; - + p = calloc(1, sizeof(*p)); return p; @@ -89,7 +89,7 @@ lua_State *script_cache_get_script(server *srv, connection *con, script_cache *c sc = NULL; } - /* if the script was script already loaded but either got changed or + /* if the script was script already loaded but either got changed or * failed to load last time */ if (sc == NULL) { sc = script_init(); @@ -103,7 +103,7 @@ lua_State *script_cache_get_script(server *srv, connection *con, script_cache *c } cache->ptr[cache->used++] = sc; - + buffer_copy_string_buffer(sc->name, name); sc->L = luaL_newstate(); diff --git a/src/mod_mysql_vhost.c b/src/mod_mysql_vhost.c index 524071e..a33eecb 100644 --- a/src/mod_mysql_vhost.c +++ b/src/mod_mysql_vhost.c @@ -21,12 +21,12 @@ #endif /* - * Plugin for lighttpd to use MySQL + * Plugin for lighttpd to use MySQL * for domain to directory lookups, * i.e virtual hosts (vhosts). - * - * Optionally sets fcgi_offset and fcgi_arg - * in preparation for fcgi.c to handle + * + * Optionally sets fcgi_offset and fcgi_arg + * in preparation for fcgi.c to handle * per-user fcgi chroot jails. * * /ada@riksnet.se 2004-12-06 @@ -35,15 +35,15 @@ #ifdef HAVE_MYSQL typedef struct { MYSQL *mysql; - + buffer *mydb; buffer *myuser; buffer *mypass; buffer *mysock; - + buffer *hostname; unsigned short port; - + buffer *mysql_pre; buffer *mysql_post; } plugin_config; @@ -51,12 +51,12 @@ typedef struct { /* global plugin data */ typedef struct { PLUGIN_DATA; - + buffer *tmp_buf; - + plugin_config **config_storage; - - plugin_config conf; + + plugin_config conf; } plugin_data; /* per connection plugin data */ @@ -70,7 +70,7 @@ typedef struct { /* init the plugin data */ INIT_FUNC(mod_mysql_vhost_init) { plugin_data *p; - + p = calloc(1, sizeof(*p)); p->tmp_buf = buffer_init(); @@ -83,22 +83,22 @@ SERVER_FUNC(mod_mysql_vhost_cleanup) { plugin_data *p = p_d; UNUSED(srv); - + #ifdef DEBUG - log_error_write(srv, __FILE__, __LINE__, "ss", + log_error_write(srv, __FILE__, __LINE__, "ss", "mod_mysql_vhost_cleanup", p ? "yes" : "NO"); #endif 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]; if (!s) continue; - + mysql_close(s->mysql); - + buffer_free(s->mydb); buffer_free(s->myuser); buffer_free(s->mypass); @@ -106,13 +106,13 @@ SERVER_FUNC(mod_mysql_vhost_cleanup) { buffer_free(s->mysql_pre); buffer_free(s->mysql_post); buffer_free(s->hostname); - + free(s); } free(p->config_storage); } buffer_free(p->tmp_buf); - + free(p); return HANDLER_GO_ON; @@ -127,7 +127,7 @@ static void* mod_mysql_vhost_connection_data(server *srv, connection *con, void UNUSED(srv); #ifdef DEBUG - log_error_write(srv, __FILE__, __LINE__, "ss", + log_error_write(srv, __FILE__, __LINE__, "ss", "mod_mysql_connection_data", c ? "old" : "NEW"); #endif @@ -150,10 +150,10 @@ CONNECTION_FUNC(mod_mysql_vhost_handle_connection_close) { UNUSED(srv); #ifdef DEBUG - log_error_write(srv, __FILE__, __LINE__, "ss", + log_error_write(srv, __FILE__, __LINE__, "ss", "mod_mysql_vhost_handle_connection_close", c ? "yes" : "NO"); #endif - + if (!c) return HANDLER_GO_ON; buffer_free(c->server_name); @@ -184,14 +184,14 @@ SERVER_FUNC(mod_mysql_vhost_set_defaults) { { "mysql-vhost.port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } }; - + p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *)); - + for (i = 0; i < srv->config_context->used; i++) { plugin_config *s; buffer *sel; - - + + s = calloc(1, sizeof(plugin_config)); s->mydb = buffer_init(); s->myuser = buffer_init(); @@ -201,10 +201,10 @@ SERVER_FUNC(mod_mysql_vhost_set_defaults) { s->port = 0; /* default port for mysql */ sel = buffer_init(); s->mysql = NULL; - + s->mysql_pre = buffer_init(); s->mysql_post = buffer_init(); - + cv[0].destination = s->mydb; cv[1].destination = s->myuser; cv[2].destination = s->mypass; @@ -212,16 +212,16 @@ SERVER_FUNC(mod_mysql_vhost_set_defaults) { cv[4].destination = sel; cv[5].destination = s->hostname; cv[6].destination = &(s->port); - + p->config_storage[i] = s; - - if (config_insert_values_global(srv, + + if (config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) return HANDLER_ERROR; - + s->mysql_pre = buffer_init(); s->mysql_post = buffer_init(); - + if (sel->used && (qmark = index(sel->ptr, '?'))) { *qmark = '\0'; buffer_copy_string(s->mysql_pre, sel->ptr); @@ -229,35 +229,35 @@ SERVER_FUNC(mod_mysql_vhost_set_defaults) { } else { buffer_copy_string_buffer(s->mysql_pre, sel); } - + /* required: * - username - * - database - * + * - database + * * optional: * - password, default: empty * - socket, default: mysql default * - hostname, if set overrides socket * - port, default: 3306 */ - + /* all have to be set */ if (!(buffer_is_empty(s->myuser) || buffer_is_empty(s->mydb))) { int fd; - + if (NULL == (s->mysql = mysql_init(NULL))) { log_error_write(srv, __FILE__, __LINE__, "s", "mysql_init() failed, exiting..."); - + return HANDLER_ERROR; } #define FOO(x) (s->x->used ? s->x->ptr : NULL) - - if (!mysql_real_connect(s->mysql, FOO(hostname), FOO(myuser), FOO(mypass), + + if (!mysql_real_connect(s->mysql, FOO(hostname), FOO(myuser), FOO(mypass), FOO(mydb), s->port, FOO(mysock), 0)) { log_error_write(srv, __FILE__, __LINE__, "s", mysql_error(s->mysql)); - + return HANDLER_ERROR; } #undef FOO @@ -266,12 +266,12 @@ SERVER_FUNC(mod_mysql_vhost_set_defaults) { /* otherwise we cannot be sure that mysql is fd i-1 */ if (-1 == (fd = open("/dev/null", 0))) { close(fd); - fcntl(fd-1, F_SETFD, FD_CLOEXEC); + fcntl(fd-1, F_SETFD, FD_CLOEXEC); } } } - - + + return HANDLER_GO_ON; } @@ -281,36 +281,36 @@ SERVER_FUNC(mod_mysql_vhost_set_defaults) { static int mod_mysql_vhost_patch_connection(server *srv, connection *con, plugin_data *p) { size_t i, j; plugin_config *s = p->config_storage[0]; - + PATCH(mysql_pre); PATCH(mysql_post); #ifdef HAVE_MYSQL PATCH(mysql); #endif - + /* 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("mysql-vhost.sql"))) { PATCH(mysql_pre); PATCH(mysql_post); } } - + if (s->mysql) { PATCH(mysql); } } - + return 0; } #undef PATCH @@ -379,7 +379,7 @@ CONNECTION_FUNC(mod_mysql_vhost_handle_docroot) { /* fcgi_offset and fcgi_arg are optional */ if (cols > 1 && row[1]) { c->fcgi_offset = atoi(row[1]); - + if (cols > 2 && row[2]) { buffer_copy_string(c->fcgi_arg, row[2]); } else { @@ -395,12 +395,12 @@ GO_ON: buffer_copy_string_buffer(con->server_name, c->server_name); buffer_copy_string_buffer(con->physical.doc_root, c->document_root); #ifdef DEBUG - log_error_write(srv, __FILE__, __LINE__, "sbbdb", - result ? "NOT CACHED" : "cached", + log_error_write(srv, __FILE__, __LINE__, "sbbdb", + result ? "NOT CACHED" : "cached", con->server_name, con->physical.doc_root, c->fcgi_offset, c->fcgi_arg); #endif - return HANDLER_GO_ON; + return HANDLER_GO_ON; ERR500: if (result) mysql_free_result(result); con->http_status = 500; /* Internal Error */ @@ -418,7 +418,7 @@ int mod_mysql_vhost_plugin_init(plugin *p) { p->set_defaults = mod_mysql_vhost_set_defaults; p->handle_docroot = mod_mysql_vhost_handle_docroot; - + return 0; } #else diff --git a/src/mod_proxy.c b/src/mod_proxy.c index 572de62..9a28f4f 100644 --- a/src/mod_proxy.c +++ b/src/mod_proxy.c @@ -38,16 +38,16 @@ #define PROXY_RETRY_TIMEOUT 60 /** - * - * the proxy module is based on the fastcgi module - * + * + * the proxy module is based on the fastcgi module + * * 28.06.2004 Jan Kneschke The first release * 01.07.2004 Evgeny Rodichev Several bugfixes and cleanups * - co-ordinate up- and downstream flows correctly (proxy_demux_response * and proxy_handle_fdevent) * - correctly transfer upstream http_response_status; * - some unused structures removed. - * + * * TODO: - delay upstream read if write_queue is too large * (to prevent memory eating, like in apache). Shoud be * configurable). @@ -70,22 +70,22 @@ typedef struct { typedef struct { PLUGIN_DATA; - + buffer *parse_response; buffer *balance_buf; - + plugin_config **config_storage; - + plugin_config conf; } plugin_data; -typedef enum { - PROXY_STATE_INIT, - PROXY_STATE_CONNECT, - PROXY_STATE_PREPARE_WRITE, - PROXY_STATE_WRITE, - PROXY_STATE_READ, - PROXY_STATE_ERROR +typedef enum { + PROXY_STATE_INIT, + PROXY_STATE_CONNECT, + PROXY_STATE_PREPARE_WRITE, + PROXY_STATE_WRITE, + PROXY_STATE_READ, + PROXY_STATE_ERROR } proxy_connection_state_t; enum { PROXY_STDOUT, PROXY_END_REQUEST }; @@ -93,19 +93,19 @@ enum { PROXY_STDOUT, PROXY_END_REQUEST }; typedef struct { proxy_connection_state_t state; time_t state_timestamp; - + data_proxy *host; - + buffer *response; buffer *response_header; chunkqueue *wb; - + int fd; /* fd to the proxy process */ int fde_ndx; /* index into the fd-event buffer */ size_t path_info_offset; /* start of path_info in uri.path */ - + connection *remote_conn; /* dump pointer */ plugin_data *plugin_data; /* dump pointer */ } handler_ctx; @@ -116,13 +116,13 @@ static handler_t proxy_handle_fdevent(void *s, void *ctx, int revents); static handler_ctx * handler_ctx_init() { handler_ctx * hctx; - + hctx = calloc(1, sizeof(*hctx)); - + hctx->state = PROXY_STATE_INIT; hctx->host = NULL; - + hctx->response = buffer_init(); hctx->response_header = buffer_init(); @@ -130,7 +130,7 @@ static handler_ctx * handler_ctx_init() { hctx->fd = -1; hctx->fde_ndx = -1; - + return hctx; } @@ -138,47 +138,47 @@ static void handler_ctx_free(handler_ctx *hctx) { buffer_free(hctx->response); buffer_free(hctx->response_header); chunkqueue_free(hctx->wb); - + free(hctx); } INIT_FUNC(mod_proxy_init) { plugin_data *p; - + p = calloc(1, sizeof(*p)); - + p->parse_response = buffer_init(); p->balance_buf = buffer_init(); - + return p; } FREE_FUNC(mod_proxy_free) { plugin_data *p = p_d; - + UNUSED(srv); buffer_free(p->parse_response); buffer_free(p->balance_buf); - + if (p->config_storage) { size_t i; for (i = 0; i < srv->config_context->used; i++) { plugin_config *s = p->config_storage[i]; - + if (s) { - + array_free(s->extensions); - + free(s); } } free(p->config_storage); } - + free(p); - + return HANDLER_GO_ON; } @@ -186,37 +186,37 @@ SETDEFAULTS_FUNC(mod_proxy_set_defaults) { plugin_data *p = p_d; data_unset *du; size_t i = 0; - - config_values_t cv[] = { + + config_values_t cv[] = { { "proxy.server", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ { "proxy.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */ { "proxy.balance", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } }; - + 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 = malloc(sizeof(plugin_config)); s->extensions = array_init(); s->debug = 0; - + cv[0].destination = s->extensions; cv[1].destination = &(s->debug); cv[2].destination = p->balance_buf; buffer_reset(p->balance_buf); - + 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; } - + if (buffer_is_empty(p->balance_buf)) { s->balance = PROXY_BALANCE_FAIR; } else if (buffer_is_equal_string(p->balance_buf, CONST_STR_LEN("fair"))) { @@ -226,7 +226,7 @@ SETDEFAULTS_FUNC(mod_proxy_set_defaults) { } else if (buffer_is_equal_string(p->balance_buf, CONST_STR_LEN("hash"))) { s->balance = PROXY_BALANCE_HASH; } else { - log_error_write(srv, __FILE__, __LINE__, "sb", + log_error_write(srv, __FILE__, __LINE__, "sb", "proxy.balance has to be one of: fair, round-robin, hash, but not:", p->balance_buf); return HANDLER_ERROR; } @@ -234,91 +234,91 @@ SETDEFAULTS_FUNC(mod_proxy_set_defaults) { if (NULL != (du = array_get_element(ca, "proxy.server"))) { size_t j; data_array *da = (data_array *)du; - + if (du->type != TYPE_ARRAY) { - log_error_write(srv, __FILE__, __LINE__, "sss", + log_error_write(srv, __FILE__, __LINE__, "sss", "unexpected type for key: ", "proxy.server", "array of strings"); - + return HANDLER_ERROR; } - - /* + + /* * proxy.server = ( "<ext>" => ..., * "<ext>" => ... ) */ - + for (j = 0; j < da->value->used; j++) { data_array *da_ext = (data_array *)da->value->data[j]; size_t n; - + if (da_ext->type != TYPE_ARRAY) { - log_error_write(srv, __FILE__, __LINE__, "sssbs", - "unexpected type for key: ", "proxy.server", + log_error_write(srv, __FILE__, __LINE__, "sssbs", + "unexpected type for key: ", "proxy.server", "[", da->value->data[j]->key, "](string)"); - + return HANDLER_ERROR; } - - /* - * proxy.server = ( "<ext>" => - * ( "<host>" => ( ... ), + + /* + * proxy.server = ( "<ext>" => + * ( "<host>" => ( ... ), * "<host>" => ( ... ) - * ), + * ), * "<ext>" => ... ) */ - + for (n = 0; n < da_ext->value->used; n++) { data_array *da_host = (data_array *)da_ext->value->data[n]; - + data_proxy *df; data_array *dfa; - - config_values_t pcv[] = { + + config_values_t pcv[] = { { "host", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ { "port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } }; - + if (da_host->type != TYPE_ARRAY) { - log_error_write(srv, __FILE__, __LINE__, "ssSBS", - "unexpected type for key:", - "proxy.server", + log_error_write(srv, __FILE__, __LINE__, "ssSBS", + "unexpected type for key:", + "proxy.server", "[", da_ext->value->data[n]->key, "](string)"); - + return HANDLER_ERROR; } - + df = data_proxy_init(); - + df->port = 80; - + buffer_copy_string_buffer(df->key, da_host->key); - + pcv[0].destination = df->host; pcv[1].destination = &(df->port); - + if (0 != config_insert_values_internal(srv, da_host->value, pcv)) { return HANDLER_ERROR; } - + if (buffer_is_empty(df->host)) { - log_error_write(srv, __FILE__, __LINE__, "sbbbs", - "missing key (string):", + log_error_write(srv, __FILE__, __LINE__, "sbbbs", + "missing key (string):", da->key, da_ext->key, da_host->key, "host"); - + return HANDLER_ERROR; } - + /* if extension already exists, take it */ - + if (NULL == (dfa = (data_array *)array_get_element(s->extensions, da_ext->key->ptr))) { dfa = data_array_init(); - + buffer_copy_string_buffer(dfa->key, da_ext->key); - + array_insert_unique(dfa->value, (data_unset *)df); array_insert_unique(s->extensions, (data_unset *)dfa); } else { @@ -328,19 +328,19 @@ SETDEFAULTS_FUNC(mod_proxy_set_defaults) { } } } - + return HANDLER_GO_ON; } void proxy_connection_close(server *srv, handler_ctx *hctx) { plugin_data *p; connection *con; - + if (NULL == hctx) return; - + p = hctx->plugin_data; con = hctx->remote_conn; - + if (hctx->fd != -1) { fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); fdevent_unregister(srv->ev, hctx->fd); @@ -348,47 +348,47 @@ void proxy_connection_close(server *srv, handler_ctx *hctx) { close(hctx->fd); srv->cur_fds--; } - + handler_ctx_free(hctx); - con->plugin_ctx[p->id] = NULL; + con->plugin_ctx[p->id] = NULL; } static int proxy_establish_connection(server *srv, handler_ctx *hctx) { struct sockaddr *proxy_addr; struct sockaddr_in proxy_addr_in; socklen_t servlen; - + plugin_data *p = hctx->plugin_data; data_proxy *host= hctx->host; int proxy_fd = hctx->fd; - + memset(&proxy_addr, 0, sizeof(proxy_addr)); - + proxy_addr_in.sin_family = AF_INET; proxy_addr_in.sin_addr.s_addr = inet_addr(host->host->ptr); proxy_addr_in.sin_port = htons(host->port); servlen = sizeof(proxy_addr_in); - + proxy_addr = (struct sockaddr *) &proxy_addr_in; - + if (-1 == connect(proxy_fd, proxy_addr, servlen)) { if (errno == EINPROGRESS || errno == EALREADY) { if (p->conf.debug) { - log_error_write(srv, __FILE__, __LINE__, "sd", + log_error_write(srv, __FILE__, __LINE__, "sd", "connect delayed:", proxy_fd); } - + return 1; } else { - - log_error_write(srv, __FILE__, __LINE__, "sdsd", + + log_error_write(srv, __FILE__, __LINE__, "sdsd", "connect failed:", proxy_fd, strerror(errno), errno); - + return -1; } } if (p->conf.debug) { - log_error_write(srv, __FILE__, __LINE__, "sd", + log_error_write(srv, __FILE__, __LINE__, "sd", "connect succeeded: ", proxy_fd); } @@ -422,25 +422,25 @@ void proxy_append_header(connection *con, const char *key, const char *value) { static int proxy_create_env(server *srv, handler_ctx *hctx) { size_t i; - + connection *con = hctx->remote_conn; buffer *b; - + /* build header */ b = chunkqueue_get_append_buffer(hctx->wb); - + /* request line */ buffer_copy_string(b, get_http_method_name(con->request.http_method)); BUFFER_APPEND_STRING_CONST(b, " "); - + buffer_append_string_buffer(b, con->request.uri); BUFFER_APPEND_STRING_CONST(b, " HTTP/1.0\r\n"); proxy_append_header(con, "X-Forwarded-For", (char *)inet_ntop_cache_get_ip(srv, &(con->dst_addr))); - /* http_host is NOT is just a pointer to a buffer + /* http_host is NOT is just a pointer to a buffer * which is NULL if it is not set */ - if (con->request.http_host && + if (con->request.http_host && !buffer_is_empty(con->request.http_host)) { proxy_set_header(con, "X-Host", con->request.http_host->ptr); } @@ -449,24 +449,24 @@ static int proxy_create_env(server *srv, handler_ctx *hctx) { /* request header */ for (i = 0; i < con->request.headers->used; i++) { data_string *ds; - + ds = (data_string *)con->request.headers->data[i]; - + if (ds->value->used && ds->key->used) { if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Connection"))) continue; - + buffer_append_string_buffer(b, ds->key); BUFFER_APPEND_STRING_CONST(b, ": "); buffer_append_string_buffer(b, ds->value); BUFFER_APPEND_STRING_CONST(b, "\r\n"); } } - + BUFFER_APPEND_STRING_CONST(b, "\r\n"); - + hctx->wb->bytes_in += b->used - 1; /* body */ - + if (con->request.content_length) { chunkqueue *req_cq = con->request_content_queue; chunk *req_c; @@ -479,7 +479,7 @@ static int proxy_create_env(server *srv, handler_ctx *hctx) { /* we announce toWrite octects * now take all the request_content chunk that we need to fill this request - * */ + * */ switch (req_c->type) { case FILE_CHUNK: @@ -507,26 +507,26 @@ static int proxy_create_env(server *srv, handler_ctx *hctx) { req_c->offset += weHave; req_cq->bytes_out += weHave; - + hctx->wb->bytes_in += weHave; break; default: break; } - + offset += weHave; } } - + return 0; } static int proxy_set_state(server *srv, handler_ctx *hctx, proxy_connection_state_t state) { hctx->state = state; hctx->state_timestamp = srv->cur_ts; - + return 0; } @@ -534,19 +534,19 @@ static int proxy_set_state(server *srv, handler_ctx *hctx, proxy_connection_stat static int proxy_response_parse(server *srv, connection *con, plugin_data *p, buffer *in) { char *s, *ns; int http_response_status = -1; - + UNUSED(srv); /* \r\n -> \0\0 */ - + buffer_copy_string_buffer(p->parse_response, in); - + for (s = p->parse_response->ptr; NULL != (ns = strstr(s, "\r\n")); s = ns + 2) { char *key, *value; int key_len; data_string *ds; int copy_header; - + ns[0] = '\0'; ns[1] = '\0'; @@ -566,7 +566,7 @@ static int proxy_response_parse(server *srv, connection *con, plugin_data *p, bu con->parsed_response |= HTTP_STATUS; continue; } - + if (NULL == (value = strchr(s, ':'))) { /* now we expect: "<key>: <value>\n" */ @@ -575,13 +575,13 @@ static int proxy_response_parse(server *srv, connection *con, plugin_data *p, bu key = s; key_len = value - key; - + value++; /* strip WS */ while (*value == ' ' || *value == '\t') value++; - + copy_header = 1; - + switch(key_len) { case 4: if (0 == strncasecmp(key, "Date", key_len)) { @@ -614,11 +614,11 @@ static int proxy_response_parse(server *srv, connection *con, plugin_data *p, bu } buffer_copy_string_len(ds->key, key, key_len); buffer_copy_string(ds->value, value); - + array_insert_unique(con->response.headers, (data_unset *)ds); } } - + return 0; } @@ -627,14 +627,14 @@ static int proxy_demux_response(server *srv, handler_ctx *hctx) { int fin = 0; int b; ssize_t r; - + plugin_data *p = hctx->plugin_data; connection *con = hctx->remote_conn; int proxy_fd = hctx->fd; - + /* check how much we have to read */ if (ioctl(hctx->fd, FIONREAD, &b)) { - log_error_write(srv, __FILE__, __LINE__, "sd", + log_error_write(srv, __FILE__, __LINE__, "sd", "ioctl failed: ", proxy_fd); return -1; @@ -654,22 +654,22 @@ static int proxy_demux_response(server *srv, handler_ctx *hctx) { } else { buffer_prepare_append(hctx->response, hctx->response->used + b); } - + if (-1 == (r = read(hctx->fd, hctx->response->ptr + hctx->response->used - 1, b))) { - log_error_write(srv, __FILE__, __LINE__, "sds", + log_error_write(srv, __FILE__, __LINE__, "sds", "unexpected end-of-file (perhaps the proxy process died):", proxy_fd, strerror(errno)); return -1; } - + /* this should be catched by the b > 0 above */ assert(r); - + hctx->response->used += r; hctx->response->ptr[hctx->response->used - 1] = '\0'; #if 0 - log_error_write(srv, __FILE__, __LINE__, "sdsbs", + log_error_write(srv, __FILE__, __LINE__, "sdsbs", "demux: Response buffer len", hctx->response->used, ":", hctx->response, ":"); #endif @@ -677,29 +677,29 @@ static int proxy_demux_response(server *srv, handler_ctx *hctx) { con->got_response = 1; buffer_prepare_copy(hctx->response_header, 128); } - + if (0 == con->file_started) { char *c; - + /* search for the \r\n\r\n in the string */ if (NULL != (c = buffer_search_string_len(hctx->response, "\r\n\r\n", 4))) { size_t hlen = c - hctx->response->ptr + 4; size_t blen = hctx->response->used - hlen - 1; /* found */ - + buffer_append_string_len(hctx->response_header, hctx->response->ptr, c - hctx->response->ptr + 4); #if 0 log_error_write(srv, __FILE__, __LINE__, "sb", "Header:", hctx->response_header); #endif /* parse the response header */ proxy_response_parse(srv, con, p, hctx->response_header); - + /* 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; } - + con->file_started = 1; if (blen) { http_chunk_append_mem(srv, con, c + 4, blen + 1); @@ -712,17 +712,17 @@ static int proxy_demux_response(server *srv, handler_ctx *hctx) { joblist_append(srv, con); hctx->response->used = 0; } - + } else { /* reading from upstream done */ con->file_finished = 1; - + http_chunk_append_mem(srv, con, NULL, 0); joblist_append(srv, con); - + fin = 1; } - + return fin; } @@ -731,12 +731,12 @@ static handler_t proxy_write_request(server *srv, handler_ctx *hctx) { data_proxy *host= hctx->host; plugin_data *p = hctx->plugin_data; connection *con = hctx->remote_conn; - + int ret; - - if (!host || + + if (!host || (!host->host->used || !host->port)) return -1; - + switch(hctx->state) { case PROXY_STATE_INIT: if (-1 == (hctx->fd = socket(AF_INET, SOCK_STREAM, 0))) { @@ -744,19 +744,19 @@ static handler_t proxy_write_request(server *srv, handler_ctx *hctx) { return HANDLER_ERROR; } hctx->fde_ndx = -1; - + srv->cur_fds++; - + fdevent_register(srv->ev, hctx->fd, proxy_handle_fdevent, hctx); - + if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) { log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno)); - + return HANDLER_ERROR; } - + /* fall through */ - + case PROXY_STATE_CONNECT: /* try to finish the connect() */ if (hctx->state == PROXY_STATE_INIT) { @@ -764,16 +764,16 @@ static handler_t proxy_write_request(server *srv, handler_ctx *hctx) { switch (proxy_establish_connection(srv, hctx)) { case 1: proxy_set_state(srv, hctx, PROXY_STATE_CONNECT); - + /* connection is in progress, wait for an event and call getsockopt() below */ - + fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); - + return HANDLER_WAIT_FOR_EVENT; case -1: /* if ECONNREFUSED choose another connection -> FIXME */ hctx->fde_ndx = -1; - + return HANDLER_ERROR; default: /* everything is ok, go on */ @@ -782,39 +782,39 @@ static handler_t proxy_write_request(server *srv, handler_ctx *hctx) { } else { int socket_error; socklen_t socket_error_len = sizeof(socket_error); - - /* we don't need it anymore */ + + /* we don't need it anymore */ fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); /* try to finish the connect() */ if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) { - log_error_write(srv, __FILE__, __LINE__, "ss", + log_error_write(srv, __FILE__, __LINE__, "ss", "getsockopt failed:", strerror(errno)); - + return HANDLER_ERROR; } if (socket_error != 0) { log_error_write(srv, __FILE__, __LINE__, "ss", - "establishing connection failed:", strerror(socket_error), + "establishing connection failed:", strerror(socket_error), "port:", hctx->host->port); - + return HANDLER_ERROR; } if (p->conf.debug) { - log_error_write(srv, __FILE__, __LINE__, "s", "proxy - connect - delayed success"); + log_error_write(srv, __FILE__, __LINE__, "s", "proxy - connect - delayed success"); } } - + proxy_set_state(srv, hctx, PROXY_STATE_PREPARE_WRITE); /* fall through */ case PROXY_STATE_PREPARE_WRITE: proxy_create_env(srv, hctx); - + proxy_set_state(srv, hctx, PROXY_STATE_WRITE); - + /* fall through */ case PROXY_STATE_WRITE:; - ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb); + ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb); chunkqueue_remove_finished_chunks(hctx->wb); @@ -822,7 +822,7 @@ static handler_t proxy_write_request(server *srv, handler_ctx *hctx) { if (errno != EAGAIN && errno != EINTR) { log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), errno); - + return HANDLER_ERROR; } else { fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); @@ -838,10 +838,10 @@ static handler_t proxy_write_request(server *srv, handler_ctx *hctx) { fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN); } else { fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); - + return HANDLER_WAIT_FOR_EVENT; } - + return HANDLER_WAIT_FOR_EVENT; case PROXY_STATE_READ: /* waiting for a response */ @@ -850,7 +850,7 @@ static handler_t proxy_write_request(server *srv, handler_ctx *hctx) { log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state"); return HANDLER_ERROR; } - + return HANDLER_GO_ON; } @@ -859,23 +859,23 @@ static handler_t proxy_write_request(server *srv, handler_ctx *hctx) { static int mod_proxy_patch_connection(server *srv, connection *con, plugin_data *p) { size_t i, j; plugin_config *s = p->config_storage[0]; - + PATCH(extensions); PATCH(debug); PATCH(balance); - + /* 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("proxy.server"))) { PATCH(extensions); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("proxy.debug"))) { @@ -885,49 +885,49 @@ static int mod_proxy_patch_connection(server *srv, connection *con, plugin_data } } } - + return 0; } #undef PATCH SUBREQUEST_FUNC(mod_proxy_handle_subrequest) { plugin_data *p = p_d; - + handler_ctx *hctx = con->plugin_ctx[p->id]; data_proxy *host; - + if (NULL == hctx) return HANDLER_GO_ON; mod_proxy_patch_connection(srv, con, p); - + host = hctx->host; - + /* not my job */ if (con->mode != p->id) return HANDLER_GO_ON; - + /* ok, create the request */ switch(proxy_write_request(srv, hctx)) { case HANDLER_ERROR: - log_error_write(srv, __FILE__, __LINE__, "sbdd", "proxy-server disabled:", + log_error_write(srv, __FILE__, __LINE__, "sbdd", "proxy-server disabled:", host->host, host->port, hctx->fd); - + /* disable this server */ host->is_disabled = 1; host->disable_ts = srv->cur_ts; - + proxy_connection_close(srv, hctx); - - /* reset the enviroment and restart the sub-request */ + + /* reset the enviroment and restart the sub-request */ buffer_reset(con->physical.path); con->mode = DIRECT; joblist_append(srv, con); - /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop - * and hope that the childs will be restarted - * + /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop + * and hope that the childs will be restarted + * */ return HANDLER_WAIT_FOR_FD; @@ -938,7 +938,7 @@ SUBREQUEST_FUNC(mod_proxy_handle_subrequest) { default: break; } - + if (con->file_started == 1) { return HANDLER_FINISHED; } else { @@ -951,13 +951,13 @@ static handler_t proxy_handle_fdevent(void *s, void *ctx, int revents) { handler_ctx *hctx = ctx; connection *con = hctx->remote_conn; plugin_data *p = hctx->plugin_data; - - + + if ((revents & FDEVENT_IN) && hctx->state == PROXY_STATE_READ) { if (p->conf.debug) { - log_error_write(srv, __FILE__, __LINE__, "sd", + log_error_write(srv, __FILE__, __LINE__, "sd", "proxy: fdevent-in", hctx->state); } @@ -966,10 +966,10 @@ static handler_t proxy_handle_fdevent(void *s, void *ctx, int revents) { break; case 1: hctx->host->usage--; - + /* we are done */ proxy_connection_close(srv, hctx); - + joblist_append(srv, con); return HANDLER_FINISHED; case -1: @@ -982,53 +982,53 @@ static handler_t proxy_handle_fdevent(void *s, void *ctx, int revents) { /* response might have been already started, kill the connection */ connection_set_state(srv, con, CON_STATE_ERROR); } - + joblist_append(srv, con); return HANDLER_FINISHED; } } - + if (revents & FDEVENT_OUT) { if (p->conf.debug) { - log_error_write(srv, __FILE__, __LINE__, "sd", + log_error_write(srv, __FILE__, __LINE__, "sd", "proxy: fdevent-out", hctx->state); } if (hctx->state == PROXY_STATE_CONNECT || hctx->state == PROXY_STATE_WRITE) { /* we are allowed to send something out - * + * * 1. in a unfinished connect() call * 2. in a unfinished write() call (long POST request) */ return mod_proxy_handle_subrequest(srv, con, p); } else { - log_error_write(srv, __FILE__, __LINE__, "sd", + log_error_write(srv, __FILE__, __LINE__, "sd", "proxy: out", hctx->state); } } - + /* perhaps this issue is already handled */ if (revents & FDEVENT_HUP) { if (p->conf.debug) { - log_error_write(srv, __FILE__, __LINE__, "sd", + log_error_write(srv, __FILE__, __LINE__, "sd", "proxy: fdevent-hup", hctx->state); } - + if (hctx->state == PROXY_STATE_CONNECT) { /* connect() -> EINPROGRESS -> HUP */ - + /** - * what is proxy is doing if it can't reach the next hop ? - * + * what is proxy is doing if it can't reach the next hop ? + * */ - + proxy_connection_close(srv, hctx); joblist_append(srv, con); - + con->http_status = 503; con->mode = DIRECT; - + return HANDLER_FINISHED; } @@ -1038,13 +1038,13 @@ static handler_t proxy_handle_fdevent(void *s, void *ctx, int revents) { joblist_append(srv, con); } else if (revents & FDEVENT_ERR) { /* kill all connections to the proxy process */ - + log_error_write(srv, __FILE__, __LINE__, "sd", "proxy-FDEVENT_ERR, but no HUP", revents); joblist_append(srv, con); proxy_connection_close(srv, hctx); } - + return HANDLER_FINISHED; } @@ -1058,44 +1058,44 @@ static handler_t mod_proxy_check_extension(server *srv, connection *con, void *p buffer *fn; data_array *extension = NULL; size_t path_info_offset; - + /* Possibly, we processed already this request */ if (con->file_started == 1) return HANDLER_GO_ON; - + mod_proxy_patch_connection(srv, con, p); - + fn = con->uri.path; if (fn->used == 0) { return HANDLER_ERROR; } - + s_len = fn->used - 1; - - + + path_info_offset = 0; - if (p->conf.debug) { + if (p->conf.debug) { log_error_write(srv, __FILE__, __LINE__, "s", "proxy - start"); } /* check if extension matches */ for (k = 0; k < p->conf.extensions->used; k++) { size_t ct_len; - + extension = (data_array *)p->conf.extensions->data[k]; - + if (extension->key->used == 0) continue; - + ct_len = extension->key->used - 1; - + if (s_len < ct_len) continue; - + /* check extension in the form "/proxy_pattern" */ if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) { if (s_len > ct_len + 1) { char *pi_offset; - + if (0 != (pi_offset = strchr(fn->ptr + ct_len + 1, '/'))) { path_info_offset = pi_offset - fn->ptr; } @@ -1106,12 +1106,12 @@ static handler_t mod_proxy_check_extension(server *srv, connection *con, void *p break; } } - + if (k == p->conf.extensions->used) { return HANDLER_GO_ON; } - if (p->conf.debug) { + if (p->conf.debug) { log_error_write(srv, __FILE__, __LINE__, "s", "proxy - ext found"); } @@ -1120,7 +1120,7 @@ static handler_t mod_proxy_check_extension(server *srv, connection *con, void *p /* hash balancing */ if (p->conf.debug) { - log_error_write(srv, __FILE__, __LINE__, "sd", + log_error_write(srv, __FILE__, __LINE__, "sd", "proxy - used hash balancing, hosts:", extension->value->used); } @@ -1129,13 +1129,13 @@ static handler_t mod_proxy_check_extension(server *srv, connection *con, void *p unsigned long cur_max; if (host->is_disabled) continue; - + cur_max = generate_crc32c(CONST_BUF_LEN(con->uri.path)) + generate_crc32c(CONST_BUF_LEN(host->host)) + /* we can cache this */ generate_crc32c(CONST_BUF_LEN(con->uri.authority)); - + if (p->conf.debug) { - log_error_write(srv, __FILE__, __LINE__, "sbbbd", + log_error_write(srv, __FILE__, __LINE__, "sbbbd", "proxy - election:", con->uri.path, host->host, @@ -1155,18 +1155,18 @@ static handler_t mod_proxy_check_extension(server *srv, connection *con, void *p case PROXY_BALANCE_FAIR: /* fair balancing */ if (p->conf.debug) { - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "proxy - used fair balancing"); } for (k = 0, ndx = -1, max_usage = INT_MAX; k < extension->value->used; k++) { data_proxy *host = (data_proxy *)extension->value->data[k]; - + if (host->is_disabled) continue; if (host->usage < max_usage) { max_usage = host->usage; - + ndx = k; } } @@ -1175,16 +1175,16 @@ static handler_t mod_proxy_check_extension(server *srv, connection *con, void *p case PROXY_BALANCE_RR: /* round robin */ if (p->conf.debug) { - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "proxy - used round-robin balancing"); } /* just to be sure */ assert(extension->value->used < INT_MAX); - + for (k = 0, ndx = -1, max_usage = INT_MAX; k < extension->value->used; k++) { data_proxy *host = (data_proxy *)extension->value->data[k]; - + if (host->is_disabled) continue; /* first usable ndx */ @@ -1200,7 +1200,7 @@ static handler_t mod_proxy_check_extension(server *srv, connection *con, void *p break; } } - + /* didn't found a higher id, wrap to the start */ if (ndx != -1 && max_usage != INT_MAX) { ndx = max_usage; @@ -1210,33 +1210,33 @@ static handler_t mod_proxy_check_extension(server *srv, connection *con, void *p default: break; } - + /* found a server */ if (ndx != -1) { data_proxy *host = (data_proxy *)extension->value->data[ndx]; - - /* - * if check-local is disabled, use the uri.path handler - * + + /* + * if check-local is disabled, use the uri.path handler + * */ - + /* init handler-context */ handler_ctx *hctx; hctx = handler_ctx_init(); - + hctx->path_info_offset = path_info_offset; hctx->remote_conn = con; hctx->plugin_data = p; hctx->host = host; - + con->plugin_ctx[p->id] = hctx; - + host->usage++; - + con->mode = p->id; - + if (p->conf.debug) { - log_error_write(srv, __FILE__, __LINE__, "sbd", + log_error_write(srv, __FILE__, __LINE__, "sbd", "proxy - found a host", host->host, host->port); } @@ -1245,11 +1245,11 @@ static handler_t mod_proxy_check_extension(server *srv, connection *con, void *p } else { /* no handler found */ con->http_status = 500; - - log_error_write(srv, __FILE__, __LINE__, "sb", - "no proxy-handler found for:", + + log_error_write(srv, __FILE__, __LINE__, "sb", + "no proxy-handler found for:", fn); - + return HANDLER_FINISHED; } return HANDLER_GO_ON; @@ -1257,7 +1257,7 @@ static handler_t mod_proxy_check_extension(server *srv, connection *con, void *p static handler_t mod_proxy_connection_close_callback(server *srv, connection *con, void *p_d) { plugin_data *p = p_d; - + proxy_connection_close(srv, con->plugin_ctx[p->id]); return HANDLER_GO_ON; @@ -1276,11 +1276,11 @@ TRIGGER_FUNC(mod_proxy_trigger) { size_t i, n, k; for (i = 0; i < srv->config_context->used; i++) { plugin_config *s = p->config_storage[i]; - - if (!s) continue; + + if (!s) continue; /* get the extensions for all configs */ - + for (k = 0; k < s->extensions->used; k++) { data_array *extension = (data_array *)s->extensions->data[k]; @@ -1290,8 +1290,8 @@ TRIGGER_FUNC(mod_proxy_trigger) { if (!host->is_disabled || srv->cur_ts - host->disable_ts < 5) continue; - - log_error_write(srv, __FILE__, __LINE__, "sbd", + + log_error_write(srv, __FILE__, __LINE__, "sbd", "proxy - re-enabled:", host->host, host->port); @@ -1317,8 +1317,8 @@ int mod_proxy_plugin_init(plugin *p) { p->handle_uri_clean = mod_proxy_check_extension; p->handle_subrequest = mod_proxy_handle_subrequest; p->handle_trigger = mod_proxy_trigger; - + p->data = NULL; - + return 0; } diff --git a/src/mod_redirect.c b/src/mod_redirect.c index 079e756..7a4f3eb 100644 --- a/src/mod_redirect.c +++ b/src/mod_redirect.c @@ -22,35 +22,35 @@ typedef struct { PLUGIN_DATA; buffer *match_buf; buffer *location; - + plugin_config **config_storage; - - plugin_config conf; + + plugin_config conf; } plugin_data; INIT_FUNC(mod_redirect_init) { plugin_data *p; - + p = calloc(1, sizeof(*p)); - + p->match_buf = buffer_init(); p->location = buffer_init(); - + return p; } FREE_FUNC(mod_redirect_free) { plugin_data *p = p_d; - + 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]; - + pcre_keyvalue_buffer_free(s->redirect); - + free(s); } free(p->config_storage); @@ -59,9 +59,9 @@ FREE_FUNC(mod_redirect_free) { buffer_free(p->match_buf); buffer_free(p->location); - + free(p); - + return HANDLER_GO_ON; } @@ -69,97 +69,97 @@ SETDEFAULTS_FUNC(mod_redirect_set_defaults) { plugin_data *p = p_d; data_unset *du; size_t i = 0; - - config_values_t cv[] = { + + config_values_t cv[] = { { "url.redirect", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ { 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; size_t j; array *ca; data_array *da = (data_array *)du; - + s = calloc(1, sizeof(plugin_config)); s->redirect = pcre_keyvalue_buffer_init(); - + cv[0].destination = s->redirect; - + 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; } - + if (NULL == (du = array_get_element(ca, "url.redirect"))) { /* no url.redirect defined */ continue; } - + if (du->type != TYPE_ARRAY) { - log_error_write(srv, __FILE__, __LINE__, "sss", + log_error_write(srv, __FILE__, __LINE__, "sss", "unexpected type for key: ", "url.redirect", "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: ", - "url.redirect", + log_error_write(srv, __FILE__, __LINE__, "sssbs", + "unexpected type for key: ", + "url.redirect", "[", da->value->data[j]->key, "](string)"); - + return HANDLER_ERROR; } - - if (0 != pcre_keyvalue_buffer_append(s->redirect, + + if (0 != pcre_keyvalue_buffer_append(s->redirect, ((data_string *)(da->value->data[j]))->key->ptr, ((data_string *)(da->value->data[j]))->value->ptr)) { - - log_error_write(srv, __FILE__, __LINE__, "sb", + + log_error_write(srv, __FILE__, __LINE__, "sb", "pcre-compile failed for", da->value->data[j]->key); } } } - + return HANDLER_GO_ON; } #ifdef HAVE_PCRE_H static int mod_redirect_patch_connection(server *srv, connection *con, plugin_data *p) { size_t i, j; plugin_config *s = p->config_storage[0]; - + p->conf.redirect = s->redirect; - + /* 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 (0 == strcmp(du->key->ptr, "url.redirect")) { p->conf.redirect = s->redirect; p->conf.context = dc; } } } - + return 0; } #endif @@ -168,17 +168,17 @@ static handler_t mod_redirect_uri_handler(server *srv, connection *con, void *p_ plugin_data *p = p_data; size_t i; - /* + /* * REWRITE URL - * + * * e.g. redirect /base/ to /index.php?section=base - * + * */ - + mod_redirect_patch_connection(srv, con, p); - + buffer_copy_string_buffer(p->match_buf, con->request.uri); - + for (i = 0; i < p->conf.redirect->used; i++) { pcre *match; pcre_extra *extra; @@ -188,12 +188,12 @@ static handler_t mod_redirect_uri_handler(server *srv, connection *con, void *p_ pcre_keyvalue *kv = p->conf.redirect->kv[i]; # define N 10 int ovec[N * 3]; - + match = kv->key; extra = kv->key_extra; pattern = kv->value->ptr; pattern_len = kv->value->used - 1; - + if ((n = pcre_exec(match, extra, 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", @@ -204,26 +204,26 @@ static handler_t mod_redirect_uri_handler(server *srv, connection *con, void *p_ 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(p->location); - + 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(p->location, pattern + start, end - start); - + if (pattern[k] == '$') { /* n is always > 0 */ if (num < (size_t)n) { @@ -232,32 +232,32 @@ static handler_t mod_redirect_uri_handler(server *srv, connection *con, void *p_ } else { config_append_cond_match_buffer(con, p->conf.context, p->location, num); } - + k++; start = k + 1; - } + } } - + buffer_append_string_len(p->location, pattern + start, pattern_len - start); - + pcre_free(list); - + response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->location)); - + con->http_status = 301; con->file_finished = 1; - + return HANDLER_FINISHED; } } #undef N - + #else UNUSED(srv); UNUSED(con); UNUSED(p_data); #endif - + return HANDLER_GO_ON; } @@ -265,13 +265,13 @@ static handler_t mod_redirect_uri_handler(server *srv, connection *con, void *p_ int mod_redirect_plugin_init(plugin *p) { p->version = LIGHTTPD_VERSION_ID; p->name = buffer_init_string("redirect"); - + p->init = mod_redirect_init; p->handle_uri_clean = mod_redirect_uri_handler; p->set_defaults = mod_redirect_set_defaults; p->cleanup = mod_redirect_free; - + p->data = NULL; - + return 0; } diff --git a/src/mod_rewrite.c b/src/mod_rewrite.c index ff152a9..4a9d3ea 100644 --- a/src/mod_rewrite.c +++ b/src/mod_rewrite.c @@ -16,15 +16,15 @@ 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; @@ -42,20 +42,20 @@ typedef struct { 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; } @@ -65,9 +65,9 @@ static void handler_ctx_free(handler_ctx *hctx) { rewrite_rule_buffer *rewrite_rule_buffer_init(void) { rewrite_rule_buffer *kvb; - + kvb = calloc(1, sizeof(*kvb)); - + return kvb; } @@ -76,40 +76,40 @@ int rewrite_rule_buffer_append(rewrite_rule_buffer *kvb, buffer *key, buffer *va 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); @@ -130,140 +130,140 @@ void rewrite_rule_buffer_free(rewrite_rule_buffer *kvb) { 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); - + 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, + + if (0 != rewrite_rule_buffer_append(s->rewrite, ((data_string *)(da->value->data[j]))->key, ((data_string *)(da->value->data[j]))->value, once)) { #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 } } } - + 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; - + 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,21 +271,21 @@ static int mod_rewrite_patch_connection(server *srv, connection *con, plugin_dat size_t i, j; plugin_config *s = p->config_storage[0]; p->conf.rewrite = s->rewrite; - + /* 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.context = dc; @@ -301,20 +301,20 @@ static int mod_rewrite_patch_connection(server *srv, connection *con, plugin_dat } } } - + 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; } @@ -324,32 +324,32 @@ URIHANDLER_FUNC(mod_rewrite_uri_handler) { size_t 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; @@ -358,11 +358,11 @@ URIHANDLER_FUNC(mod_rewrite_uri_handler) { 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", @@ -373,26 +373,26 @@ URIHANDLER_FUNC(mod_rewrite_uri_handler) { 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) { @@ -401,27 +401,27 @@ URIHANDLER_FUNC(mod_rewrite_uri_handler) { } 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; } } #undef N - + #else UNUSED(srv); UNUSED(con); @@ -434,17 +434,17 @@ URIHANDLER_FUNC(mod_rewrite_uri_handler) { 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; } diff --git a/src/mod_rrdtool.c b/src/mod_rrdtool.c index c7b897a..28003c4 100644 --- a/src/mod_rrdtool.c +++ b/src/mod_rrdtool.c @@ -23,7 +23,7 @@ typedef struct { buffer *path_rrdtool_bin; buffer *path_rrd; - + double requests, *requests_ptr; double bytes_written, *bytes_written_ptr; double bytes_read, *bytes_read_ptr; @@ -31,84 +31,84 @@ typedef struct { typedef struct { PLUGIN_DATA; - + buffer *cmd; buffer *resp; - + int read_fd, write_fd; pid_t rrdtool_pid; - + int rrdtool_running; - + plugin_config **config_storage; plugin_config conf; } plugin_data; INIT_FUNC(mod_rrd_init) { plugin_data *p; - + p = calloc(1, sizeof(*p)); - + p->resp = buffer_init(); p->cmd = buffer_init(); - + return p; } FREE_FUNC(mod_rrd_free) { plugin_data *p = p_d; size_t i; - + if (!p) return HANDLER_GO_ON; - + if (p->config_storage) { for (i = 0; i < srv->config_context->used; i++) { plugin_config *s = p->config_storage[i]; - + buffer_free(s->path_rrdtool_bin); buffer_free(s->path_rrd); - + free(s); } } buffer_free(p->cmd); buffer_free(p->resp); - + free(p->config_storage); - + if (p->rrdtool_pid) { int status; close(p->read_fd); close(p->write_fd); -#ifdef HAVE_FORK +#ifdef HAVE_FORK /* collect status */ waitpid(p->rrdtool_pid, &status, 0); #endif } - + free(p); - + return HANDLER_GO_ON; } int mod_rrd_create_pipe(server *srv, plugin_data *p) { pid_t pid; - + int to_rrdtool_fds[2]; int from_rrdtool_fds[2]; -#ifdef HAVE_FORK +#ifdef HAVE_FORK if (pipe(to_rrdtool_fds)) { - log_error_write(srv, __FILE__, __LINE__, "ss", + log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed: ", strerror(errno)); return -1; } - + if (pipe(from_rrdtool_fds)) { - log_error_write(srv, __FILE__, __LINE__, "ss", + log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed: ", strerror(errno)); return -1; } - + /* fork, execve */ switch (pid = fork()) { case 0: { @@ -117,33 +117,33 @@ int mod_rrd_create_pipe(server *srv, plugin_data *p) { int argc; int i = 0; char *dash = "-"; - + /* move stdout to from_rrdtool_fd[1] */ close(STDOUT_FILENO); dup2(from_rrdtool_fds[1], STDOUT_FILENO); close(from_rrdtool_fds[1]); /* not needed */ close(from_rrdtool_fds[0]); - + /* move the stdin to to_rrdtool_fd[0] */ close(STDIN_FILENO); dup2(to_rrdtool_fds[0], STDIN_FILENO); close(to_rrdtool_fds[0]); /* not needed */ close(to_rrdtool_fds[1]); - + close(STDERR_FILENO); - + if (srv->errorlog_mode == ERRORLOG_FILE) { dup2(srv->errorlog_fd, STDERR_FILENO); close(srv->errorlog_fd); } - + /* set up args */ argc = 3; args = malloc(sizeof(*args) * argc); i = 0; - + args[i++] = p->conf.path_rrdtool_bin->ptr; args[i++] = dash; args[i++] = NULL; @@ -152,12 +152,12 @@ int mod_rrd_create_pipe(server *srv, plugin_data *p) { for (i = 3; i < 256; i++) { close(i); } - + /* exec the cgi */ execv(args[0], args); - + log_error_write(srv, __FILE__, __LINE__, "sss", "spawing rrdtool failed: ", strerror(errno), args[0]); - + /* */ SEGFAULT(); break; @@ -168,19 +168,19 @@ int mod_rrd_create_pipe(server *srv, plugin_data *p) { break; default: { /* father */ - + close(from_rrdtool_fds[1]); close(to_rrdtool_fds[0]); - + /* register PID and wait for them asyncronously */ p->write_fd = to_rrdtool_fds[1]; p->read_fd = from_rrdtool_fds[0]; p->rrdtool_pid = pid; - + break; } } - + return 0; #else return -1; @@ -189,19 +189,19 @@ int mod_rrd_create_pipe(server *srv, plugin_data *p) { static int mod_rrdtool_create_rrd(server *srv, plugin_data *p, plugin_config *s) { struct stat st; - + /* check if DB already exists */ if (0 == stat(s->path_rrd->ptr, &st)) { /* check if it is plain file */ if (!S_ISREG(st.st_mode)) { - log_error_write(srv, __FILE__, __LINE__, "sb", + log_error_write(srv, __FILE__, __LINE__, "sb", "not a regular file:", s->path_rrd); return HANDLER_ERROR; } } else { int r ; /* create a new one */ - + BUFFER_COPY_STRING_CONST(p->cmd, "create "); buffer_append_string_buffer(p->cmd, s->path_rrd); buffer_append_string(p->cmd, " --step 60 "); @@ -220,33 +220,33 @@ static int mod_rrdtool_create_rrd(server *srv, plugin_data *p, plugin_config *s) buffer_append_string(p->cmd, "RRA:MIN:0.5:6:700 "); buffer_append_string(p->cmd, "RRA:MIN:0.5:24:775 "); buffer_append_string(p->cmd, "RRA:MIN:0.5:288:797\n"); - + if (-1 == (r = write(p->write_fd, p->cmd->ptr, p->cmd->used - 1))) { - log_error_write(srv, __FILE__, __LINE__, "ss", + log_error_write(srv, __FILE__, __LINE__, "ss", "rrdtool-write: failed", strerror(errno)); - + return HANDLER_ERROR; } - + buffer_prepare_copy(p->resp, 4096); if (-1 == (r = read(p->read_fd, p->resp->ptr, p->resp->size))) { - log_error_write(srv, __FILE__, __LINE__, "ss", + log_error_write(srv, __FILE__, __LINE__, "ss", "rrdtool-read: failed", strerror(errno)); - + return HANDLER_ERROR; } - + p->resp->used = r; - + if (p->resp->ptr[0] != 'O' || p->resp->ptr[1] != 'K') { - log_error_write(srv, __FILE__, __LINE__, "sbb", + log_error_write(srv, __FILE__, __LINE__, "sbb", "rrdtool-response:", p->cmd, p->resp); - + return HANDLER_ERROR; } } - + return HANDLER_GO_ON; } @@ -255,37 +255,37 @@ static int mod_rrdtool_create_rrd(server *srv, plugin_data *p, plugin_config *s) static int mod_rrd_patch_connection(server *srv, connection *con, plugin_data *p) { size_t i, j; plugin_config *s = p->config_storage[0]; - + PATCH(path_rrdtool_bin); PATCH(path_rrd); - + p->conf.bytes_written_ptr = &(s->bytes_written); p->conf.bytes_read_ptr = &(s->bytes_read); p->conf.requests_ptr = &(s->requests); - + /* 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("rrdtool.db-name"))) { PATCH(path_rrd); /* get pointers to double values */ - + p->conf.bytes_written_ptr = &(s->bytes_written); p->conf.bytes_read_ptr = &(s->bytes_read); p->conf.requests_ptr = &(s->requests); } } } - + return 0; } #undef PATCH @@ -293,85 +293,85 @@ static int mod_rrd_patch_connection(server *srv, connection *con, plugin_data *p SETDEFAULTS_FUNC(mod_rrd_set_defaults) { plugin_data *p = p_d; size_t i; - - config_values_t cv[] = { + + config_values_t cv[] = { { "rrdtool.binary", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, { "rrdtool.db-name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, { 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->path_rrdtool_bin = buffer_init(); s->path_rrd = buffer_init(); s->requests = 0; s->bytes_written = 0; s->bytes_read = 0; - + cv[0].destination = s->path_rrdtool_bin; cv[1].destination = s->path_rrd; - + 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 (i > 0 && !buffer_is_empty(s->path_rrdtool_bin)) { /* path_rrdtool_bin is a global option */ - - log_error_write(srv, __FILE__, __LINE__, "s", + + log_error_write(srv, __FILE__, __LINE__, "s", "rrdtool.binary can only be set as a global option."); - + return HANDLER_ERROR; } - + } - + p->conf.path_rrdtool_bin = p->config_storage[0]->path_rrdtool_bin; p->rrdtool_running = 0; - + /* check for dir */ - + if (buffer_is_empty(p->conf.path_rrdtool_bin)) { - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "rrdtool.binary has to be set"); return HANDLER_ERROR; } - + /* open the pipe to rrdtool */ if (mod_rrd_create_pipe(srv, p)) { return HANDLER_ERROR; } - + p->rrdtool_running = 1; - + return HANDLER_GO_ON; } TRIGGER_FUNC(mod_rrd_trigger) { plugin_data *p = p_d; size_t i; - + if (!p->rrdtool_running) return HANDLER_GO_ON; if ((srv->cur_ts % 60) != 0) return HANDLER_GO_ON; - + for (i = 0; i < srv->config_context->used; i++) { plugin_config *s = p->config_storage[i]; int r; - + if (buffer_is_empty(s->path_rrd)) continue; - + /* write the data down every minute */ - + if (HANDLER_GO_ON != mod_rrdtool_create_rrd(srv, p, s)) return HANDLER_ERROR; - + BUFFER_COPY_STRING_CONST(p->cmd, "update "); buffer_append_string_buffer(p->cmd, s->path_rrd); BUFFER_APPEND_STRING_CONST(p->cmd, " N:"); @@ -381,69 +381,69 @@ TRIGGER_FUNC(mod_rrd_trigger) { BUFFER_APPEND_STRING_CONST(p->cmd, ":"); buffer_append_long(p->cmd, s->requests); BUFFER_APPEND_STRING_CONST(p->cmd, "\n"); - + if (-1 == (r = write(p->write_fd, p->cmd->ptr, p->cmd->used - 1))) { p->rrdtool_running = 0; - - log_error_write(srv, __FILE__, __LINE__, "ss", + + log_error_write(srv, __FILE__, __LINE__, "ss", "rrdtool-write: failed", strerror(errno)); - + return HANDLER_ERROR; } - + buffer_prepare_copy(p->resp, 4096); if (-1 == (r = read(p->read_fd, p->resp->ptr, p->resp->size))) { p->rrdtool_running = 0; - - log_error_write(srv, __FILE__, __LINE__, "ss", + + log_error_write(srv, __FILE__, __LINE__, "ss", "rrdtool-read: failed", strerror(errno)); - + return HANDLER_ERROR; } - + p->resp->used = r; - + if (p->resp->ptr[0] != 'O' || p->resp->ptr[1] != 'K') { p->rrdtool_running = 0; - - log_error_write(srv, __FILE__, __LINE__, "sbb", + + log_error_write(srv, __FILE__, __LINE__, "sbb", "rrdtool-response:", p->cmd, p->resp); - + return HANDLER_ERROR; } s->requests = 0; s->bytes_written = 0; s->bytes_read = 0; } - + return HANDLER_GO_ON; } REQUESTDONE_FUNC(mod_rrd_account) { plugin_data *p = p_d; - + mod_rrd_patch_connection(srv, con, p); - + *(p->conf.requests_ptr) += 1; *(p->conf.bytes_written_ptr) += con->bytes_written; *(p->conf.bytes_read_ptr) += con->bytes_read; - + return HANDLER_GO_ON; } int mod_rrdtool_plugin_init(plugin *p) { p->version = LIGHTTPD_VERSION_ID; p->name = buffer_init_string("rrd"); - + p->init = mod_rrd_init; p->cleanup = mod_rrd_free; p->set_defaults= mod_rrd_set_defaults; - + p->handle_trigger = mod_rrd_trigger; p->handle_request_done = mod_rrd_account; - + p->data = NULL; - + return 0; } diff --git a/src/mod_scgi.c b/src/mod_scgi.c index 88c80eb..2db0308 100644 --- a/src/mod_scgi.c +++ b/src/mod_scgi.c @@ -46,19 +46,19 @@ enum {EOL_UNSET, EOL_N, EOL_RN}; /* - * + * * TODO: - * + * * - add timeout for a connect to a non-scgi process * (use state_timestamp + state) - * + * */ typedef struct scgi_proc { size_t id; /* id will be between 1 and max_procs */ buffer *socket; /* config.socket + "-" + id */ unsigned port; /* config.port + pno */ - + pid_t pid; /* PID of the spawned process (0 if not spawned locally) */ @@ -67,9 +67,9 @@ typedef struct scgi_proc { time_t last_used; /* see idle_timeout */ size_t requests; /* see max_requests */ struct scgi_proc *prev, *next; /* see first */ - + time_t disable_ts; /* replace by host->something */ - + int is_local; enum { PROC_STATE_UNSET, /* init-phase */ @@ -78,7 +78,7 @@ typedef struct scgi_proc { PROC_STATE_KILLED, /* was killed as we don't have the load anymore */ PROC_STATE_DIED, /* marked as dead, should be restarted */ PROC_STATE_DISABLED /* proc disabled as it resulted in an error */ - } state; + } state; } scgi_proc; typedef struct { @@ -86,20 +86,20 @@ typedef struct { * sorted by lowest load * * whenever a job is done move it up in the list - * until it is sorted, move it down as soon as the + * until it is sorted, move it down as soon as the * job is started */ - scgi_proc *first; - scgi_proc *unused_procs; + scgi_proc *first; + scgi_proc *unused_procs; - /* + /* * spawn at least min_procs, at max_procs. * - * as soon as the load of the first entry + * as soon as the load of the first entry * is max_load_per_proc we spawn a new one - * and add it to the first entry and give it + * and add it to the first entry and give it * the load - * + * */ unsigned short min_procs; @@ -111,44 +111,44 @@ typedef struct { /* * kick the process from the list if it was not - * used for idle_timeout until min_procs is + * used for idle_timeout until min_procs is * reached. this helps to get the processlist * small again we had a small peak load. * */ - + unsigned short idle_timeout; - + /* * time after a disabled remote connection is tried to be re-enabled - * - * + * + * */ - + unsigned short disable_time; /* * same scgi processes get a little bit larger - * than wanted. max_requests_per_proc kills a + * than wanted. max_requests_per_proc kills a * process after a number of handled requests. * */ size_t max_requests_per_proc; - + /* config */ - /* - * host:port + /* + * host:port * - * if host is one of the local IP adresses the + * if host is one of the local IP adresses the * whole connection is local * * if tcp/ip should be used host AND port have - * to be specified - * - */ - buffer *host; + * to be specified + * + */ + buffer *host; unsigned short port; /* @@ -161,7 +161,7 @@ typedef struct { */ buffer *unixsocket; - /* if socket is local we can start the scgi + /* if socket is local we can start the scgi * process ourself * * bin-path is the path to the binary @@ -169,19 +169,19 @@ typedef struct { * check min_procs and max_procs for the number * of process to start-up */ - buffer *bin_path; - - /* bin-path is set bin-environment is taken to + buffer *bin_path; + + /* bin-path is set bin-environment is taken to * create the environement before starting the * FastCGI process - * + * */ array *bin_env; - + array *bin_env_copy; - + /* - * docroot-translation between URL->phys and the + * docroot-translation between URL->phys and the * remote host * * reasons: @@ -192,7 +192,7 @@ typedef struct { buffer *docroot; /* - * check_local tell you if the phys file is stat()ed + * check_local tell you if the phys file is stat()ed * or not. FastCGI doesn't care if the service is * remote. If the web-server side doesn't contain * the scgi-files we should not stat() for them @@ -202,33 +202,33 @@ typedef struct { /* * append PATH_INFO to SCRIPT_FILENAME - * + * * php needs this if cgi.fix_pathinfo is provied - * + * */ - + ssize_t load; /* replace by host->load */ size_t max_id; /* corresponds most of the time to num_procs. - + only if a process is killed max_id waits for the process itself to die and decrements its afterwards */ } scgi_extension_host; /* * one extension can have multiple hosts assigned - * one host can spawn additional processes on the same + * one host can spawn additional processes on the same * socket (if we control it) * * ext -> host -> procs * 1:n 1:n * - * if the scgi process is remote that whole goes down + * if the scgi process is remote that whole goes down * to * * ext -> host -> procs - * 1:n 1:1 + * 1:n 1:1 * * in case of PHP and FCGI_CHILDREN we have again a procs * but we don't control it directly. @@ -239,7 +239,7 @@ typedef struct { buffer *key; /* like .php */ scgi_extension_host **hosts; - + size_t used; size_t size; } scgi_extension; @@ -253,14 +253,14 @@ typedef struct { typedef struct { - scgi_exts *exts; - + scgi_exts *exts; + int debug; } plugin_config; typedef struct { char **ptr; - + size_t size; size_t used; } char_array; @@ -268,52 +268,52 @@ typedef struct { /* generic plugin data, shared between all connections */ typedef struct { PLUGIN_DATA; - + buffer *scgi_env; - + buffer *path; buffer *parse_response; - + plugin_config **config_storage; - + plugin_config conf; /* this is only used as long as no handler_ctx is setup */ } plugin_data; /* connection specific data */ -typedef enum { FCGI_STATE_INIT, FCGI_STATE_CONNECT, FCGI_STATE_PREPARE_WRITE, - FCGI_STATE_WRITE, FCGI_STATE_READ +typedef enum { FCGI_STATE_INIT, FCGI_STATE_CONNECT, FCGI_STATE_PREPARE_WRITE, + FCGI_STATE_WRITE, FCGI_STATE_READ } scgi_connection_state_t; typedef struct { - buffer *response; + buffer *response; size_t response_len; int response_type; int response_padding; - + scgi_proc *proc; scgi_extension_host *host; - + scgi_connection_state_t state; time_t state_timestamp; - + int reconnects; /* number of reconnect attempts */ - + read_buffer *rb; chunkqueue *wb; - + buffer *response_header; - + int delayed; /* flag to mark that the connect() is delayed */ - + size_t request_id; int fd; /* fd to the scgi process */ int fde_ndx; /* index into the fd-event buffer */ pid_t pid; int got_proc; - + plugin_config conf; - + connection *remote_conn; /* dumb pointer */ plugin_data *plugin_data; /* dumb pointer */ } handler_ctx; @@ -328,28 +328,28 @@ int scgi_proclist_sort_down(server *srv, scgi_extension_host *host, scgi_proc *p static handler_ctx * handler_ctx_init() { handler_ctx * hctx; - + hctx = calloc(1, sizeof(*hctx)); assert(hctx); - + hctx->fde_ndx = -1; - + hctx->response = buffer_init(); hctx->response_header = buffer_init(); - + hctx->request_id = 0; hctx->state = FCGI_STATE_INIT; hctx->proc = NULL; - + hctx->response_len = 0; hctx->response_type = 0; hctx->response_padding = 0; hctx->fd = -1; - + hctx->reconnects = 0; hctx->wb = chunkqueue_init(); - + return hctx; } @@ -358,12 +358,12 @@ static void handler_ctx_free(handler_ctx *hctx) { buffer_free(hctx->response_header); chunkqueue_free(hctx->wb); - + if (hctx->rb) { if (hctx->rb->ptr) free(hctx->rb->ptr); free(hctx->rb); } - + free(hctx); } @@ -372,20 +372,20 @@ scgi_proc *scgi_process_init() { f = calloc(1, sizeof(*f)); f->socket = buffer_init(); - + f->prev = NULL; f->next = NULL; - + return f; } void scgi_process_free(scgi_proc *f) { if (!f) return; - + scgi_process_free(f->next); - + buffer_free(f->socket); - + free(f); } @@ -400,62 +400,62 @@ scgi_extension_host *scgi_host_init() { f->bin_path = buffer_init(); f->bin_env = array_init(); f->bin_env_copy = array_init(); - + return f; } void scgi_host_free(scgi_extension_host *h) { if (!h) return; - + buffer_free(h->host); buffer_free(h->unixsocket); buffer_free(h->docroot); buffer_free(h->bin_path); array_free(h->bin_env); array_free(h->bin_env_copy); - + scgi_process_free(h->first); scgi_process_free(h->unused_procs); - + free(h); - + } scgi_exts *scgi_extensions_init() { scgi_exts *f; f = calloc(1, sizeof(*f)); - + return f; } void scgi_extensions_free(scgi_exts *f) { size_t i; - + if (!f) return; - + for (i = 0; i < f->used; i++) { scgi_extension *fe; size_t j; - + fe = f->exts[i]; - + for (j = 0; j < fe->used; j++) { scgi_extension_host *h; - + h = fe->hosts[j]; - + scgi_host_free(h); } - + buffer_free(fe->key); free(fe->hosts); - + free(fe); } - + free(f->exts); - + free(f); } @@ -504,99 +504,99 @@ int scgi_extension_insert(scgi_exts *ext, buffer *key, scgi_extension_host *fh) assert(fe->hosts); } - fe->hosts[fe->used++] = fh; + fe->hosts[fe->used++] = fh; return 0; - + } INIT_FUNC(mod_scgi_init) { plugin_data *p; - + p = calloc(1, sizeof(*p)); - + p->scgi_env = buffer_init(); - + p->path = buffer_init(); p->parse_response = buffer_init(); - + return p; } FREE_FUNC(mod_scgi_free) { plugin_data *p = p_d; - + UNUSED(srv); buffer_free(p->scgi_env); buffer_free(p->path); buffer_free(p->parse_response); - + if (p->config_storage) { size_t i, j, n; for (i = 0; i < srv->config_context->used; i++) { plugin_config *s = p->config_storage[i]; scgi_exts *exts; - + if (!s) continue; - + exts = s->exts; for (j = 0; j < exts->used; j++) { scgi_extension *ex; - + ex = exts->exts[j]; - + for (n = 0; n < ex->used; n++) { scgi_proc *proc; scgi_extension_host *host; - + host = ex->hosts[n]; - + for (proc = host->first; proc; proc = proc->next) { if (proc->pid != 0) kill(proc->pid, SIGTERM); - - if (proc->is_local && + + if (proc->is_local && !buffer_is_empty(proc->socket)) { unlink(proc->socket->ptr); } } - + for (proc = host->unused_procs; proc; proc = proc->next) { if (proc->pid != 0) kill(proc->pid, SIGTERM); - - if (proc->is_local && + + if (proc->is_local && !buffer_is_empty(proc->socket)) { unlink(proc->socket->ptr); } } } } - + scgi_extensions_free(s->exts); - + free(s); } free(p->config_storage); } - + free(p); - + return HANDLER_GO_ON; } static int 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)); @@ -604,13 +604,13 @@ static int env_add(char_array *env, const char *key, size_t key_len, const char env->size += 16; env->ptr = realloc(env->ptr, env->size * sizeof(*env->ptr)); } - + env->ptr[env->used++] = dst; - + return 0; } -static int scgi_spawn_connection(server *srv, +static int scgi_spawn_connection(server *srv, plugin_data *p, scgi_extension_host *host, scgi_proc *proc) { @@ -622,25 +622,25 @@ static int scgi_spawn_connection(server *srv, #endif struct sockaddr_in scgi_addr_in; struct sockaddr *scgi_addr; - + socklen_t servlen; - + #ifndef HAVE_FORK return -1; #endif - + if (p->conf.debug) { log_error_write(srv, __FILE__, __LINE__, "sdb", "new proc, socket:", proc->port, proc->socket); } - + if (!buffer_is_empty(proc->socket)) { memset(&scgi_addr, 0, sizeof(scgi_addr)); - + #ifdef HAVE_SYS_UN_H scgi_addr_un.sun_family = AF_UNIX; strcpy(scgi_addr_un.sun_path, proc->socket->ptr); - + #ifdef SUN_LEN servlen = SUN_LEN(&scgi_addr_un); #else @@ -656,115 +656,115 @@ static int scgi_spawn_connection(server *srv, #endif } else { scgi_addr_in.sin_family = AF_INET; - + if (buffer_is_empty(host->host)) { scgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY); } else { struct hostent *he; - + /* set a usefull default */ scgi_addr_in.sin_addr.s_addr = htonl(INADDR_ANY); - - + + if (NULL == (he = gethostbyname(host->host->ptr))) { - log_error_write(srv, __FILE__, __LINE__, - "sdb", "gethostbyname failed: ", + log_error_write(srv, __FILE__, __LINE__, + "sdb", "gethostbyname failed: ", h_errno, host->host); return -1; } - + if (he->h_addrtype != AF_INET) { log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype); return -1; } - + if (he->h_length != sizeof(struct in_addr)) { log_error_write(srv, __FILE__, __LINE__, "sd", "addr-length != sizeof(in_addr): ", he->h_length); return -1; } - + memcpy(&(scgi_addr_in.sin_addr.s_addr), he->h_addr_list[0], he->h_length); - + } scgi_addr_in.sin_port = htons(proc->port); servlen = sizeof(scgi_addr_in); - + socket_type = AF_INET; scgi_addr = (struct sockaddr *) &scgi_addr_in; } - + if (-1 == (scgi_fd = socket(socket_type, SOCK_STREAM, 0))) { - log_error_write(srv, __FILE__, __LINE__, "ss", + log_error_write(srv, __FILE__, __LINE__, "ss", "failed:", strerror(errno)); return -1; } - + if (-1 == connect(scgi_fd, scgi_addr, servlen)) { /* server is not up, spawn in */ pid_t child; int val; - + if (!buffer_is_empty(proc->socket)) { unlink(proc->socket->ptr); } - + close(scgi_fd); - + /* reopen socket */ if (-1 == (scgi_fd = socket(socket_type, SOCK_STREAM, 0))) { - log_error_write(srv, __FILE__, __LINE__, "ss", + log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno)); return -1; } - + val = 1; if (setsockopt(scgi_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) { - log_error_write(srv, __FILE__, __LINE__, "ss", + log_error_write(srv, __FILE__, __LINE__, "ss", "socketsockopt failed:", strerror(errno)); return -1; } - + /* create socket */ if (-1 == bind(scgi_fd, scgi_addr, servlen)) { - log_error_write(srv, __FILE__, __LINE__, "sbds", - "bind failed for:", - proc->socket, - proc->port, + log_error_write(srv, __FILE__, __LINE__, "sbds", + "bind failed for:", + proc->socket, + proc->port, strerror(errno)); return -1; } - + if (-1 == listen(scgi_fd, 1024)) { - log_error_write(srv, __FILE__, __LINE__, "ss", + log_error_write(srv, __FILE__, __LINE__, "ss", "listen failed:", strerror(errno)); return -1; } - -#ifdef HAVE_FORK + +#ifdef HAVE_FORK switch ((child = fork())) { case 0: { buffer *b; size_t i = 0; int fd = 0; char_array env; - - + + /* create environment */ env.ptr = NULL; env.size = 0; env.used = 0; - + /* we don't need the client socket */ for (fd = 3; fd < 256; fd++) { if (fd != 2 && fd != scgi_fd) close(fd); } - + /* build clean environment */ if (host->bin_env_copy->used) { for (i = 0; i < host->bin_env_copy->used; i++) { data_string *ds = (data_string *)host->bin_env_copy->data[i]; char *ge; - + if (NULL != (ge = getenv(ds->value->ptr))) { env_add(&env, CONST_BUF_LEN(ds->value), ge, strlen(ge)); } @@ -772,44 +772,44 @@ static int scgi_spawn_connection(server *srv, } else { for (i = 0; environ[i]; i++) { char *eq; - + if (NULL != (eq = strchr(environ[i], '='))) { env_add(&env, environ[i], eq - environ[i], eq+1, strlen(eq+1)); } } } - + /* create environment */ for (i = 0; i < host->bin_env->used; i++) { data_string *ds = (data_string *)host->bin_env->data[i]; - + env_add(&env, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value)); } - + for (i = 0; i < env.used; i++) { /* search for PHP_FCGI_CHILDREN */ if (0 == strncmp(env.ptr[i], "PHP_FCGI_CHILDREN=", sizeof("PHP_FCGI_CHILDREN=") - 1)) break; } - + /* not found, add a default */ if (i == env.used) { env_add(&env, CONST_STR_LEN("PHP_FCGI_CHILDREN"), CONST_STR_LEN("1")); } - + env.ptr[env.used] = NULL; - + b = buffer_init(); buffer_copy_string(b, "exec "); buffer_append_string_buffer(b, host->bin_path); - + /* exec the cgi */ execle("/bin/sh", "sh", "-c", b->ptr, NULL, env.ptr); - - log_error_write(srv, __FILE__, __LINE__, "sbs", + + log_error_write(srv, __FILE__, __LINE__, "sbs", "execl failed for:", host->bin_path, strerror(errno)); - + exit(errno); - + break; } case -1: @@ -817,32 +817,32 @@ static int scgi_spawn_connection(server *srv, break; default: /* father */ - + /* wait */ select(0, NULL, NULL, NULL, &tv); - + switch (waitpid(child, &status, WNOHANG)) { case 0: /* child still running after timeout, good */ break; case -1: /* no PID found ? should never happen */ - log_error_write(srv, __FILE__, __LINE__, "ss", + log_error_write(srv, __FILE__, __LINE__, "ss", "pid not found:", strerror(errno)); return -1; default: /* the child should not terminate at all */ if (WIFEXITED(status)) { - log_error_write(srv, __FILE__, __LINE__, "sd", - "child exited (is this a SCGI binary ?):", + log_error_write(srv, __FILE__, __LINE__, "sd", + "child exited (is this a SCGI binary ?):", WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { - log_error_write(srv, __FILE__, __LINE__, "sd", - "child signaled:", + log_error_write(srv, __FILE__, __LINE__, "sd", + "child signaled:", WTERMSIG(status)); } else { - log_error_write(srv, __FILE__, __LINE__, "sd", - "child died somehow:", + log_error_write(srv, __FILE__, __LINE__, "sd", + "child died somehow:", status); } return -1; @@ -852,26 +852,26 @@ static int scgi_spawn_connection(server *srv, proc->pid = child; proc->last_used = srv->cur_ts; proc->is_local = 1; - + break; } #endif } else { proc->is_local = 0; proc->pid = 0; - + if (p->conf.debug) { log_error_write(srv, __FILE__, __LINE__, "sb", "(debug) socket is already used, won't spawn:", proc->socket); } } - + proc->state = PROC_STATE_RUNNING; host->active_procs++; - + close(scgi_fd); - + return 0; } @@ -880,89 +880,89 @@ SETDEFAULTS_FUNC(mod_scgi_set_defaults) { plugin_data *p = p_d; data_unset *du; size_t i = 0; - - config_values_t cv[] = { + + config_values_t cv[] = { { "scgi.server", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ { "scgi.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } }; - + 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 = malloc(sizeof(plugin_config)); s->exts = scgi_extensions_init(); s->debug = 0; - + cv[0].destination = s->exts; cv[1].destination = &(s->debug); - + 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; } - - /* + + /* * <key> = ( ... ) */ - + if (NULL != (du = array_get_element(ca, "scgi.server"))) { size_t j; data_array *da = (data_array *)du; - + if (du->type != TYPE_ARRAY) { - log_error_write(srv, __FILE__, __LINE__, "sss", + log_error_write(srv, __FILE__, __LINE__, "sss", "unexpected type for key: ", "scgi.server", "array of strings"); - + return HANDLER_ERROR; } - - - /* - * scgi.server = ( "<ext>" => ( ... ), + + + /* + * scgi.server = ( "<ext>" => ( ... ), * "<ext>" => ( ... ) ) */ - + for (j = 0; j < da->value->used; j++) { size_t n; data_array *da_ext = (data_array *)da->value->data[j]; - + if (da->value->data[j]->type != TYPE_ARRAY) { - log_error_write(srv, __FILE__, __LINE__, "sssbs", - "unexpected type for key: ", "scgi.server", + log_error_write(srv, __FILE__, __LINE__, "sssbs", + "unexpected type for key: ", "scgi.server", "[", da->value->data[j]->key, "](string)"); - + return HANDLER_ERROR; } - - /* - * da_ext->key == name of the extension + + /* + * da_ext->key == name of the extension */ - - /* - * scgi.server = ( "<ext>" => - * ( "<host>" => ( ... ), + + /* + * scgi.server = ( "<ext>" => + * ( "<host>" => ( ... ), * "<host>" => ( ... ) - * ), + * ), * "<ext>" => ... ) */ - + for (n = 0; n < da_ext->value->used; n++) { data_array *da_host = (data_array *)da_ext->value->data[n]; - + scgi_extension_host *df; - - config_values_t fcv[] = { + + config_values_t fcv[] = { { "host", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ { "docroot", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 1 */ { "socket", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */ { "bin-path", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 3 */ - + { "check-local", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 4 */ { "port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 5 */ { "min-procs-not-working", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 7 this is broken for now */ @@ -970,37 +970,37 @@ SETDEFAULTS_FUNC(mod_scgi_set_defaults) { { "max-load-per-proc", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 8 */ { "idle-timeout", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 9 */ { "disable-time", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 10 */ - + { "bin-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 11 */ { "bin-copy-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 12 */ - - + + { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } }; - + if (da_host->type != TYPE_ARRAY) { - log_error_write(srv, __FILE__, __LINE__, "ssSBS", - "unexpected type for key:", - "scgi.server", + log_error_write(srv, __FILE__, __LINE__, "ssSBS", + "unexpected type for key:", + "scgi.server", "[", da_host->key, "](string)"); - + return HANDLER_ERROR; } - + df = scgi_host_init(); - + df->check_local = 1; df->min_procs = 4; df->max_procs = 4; df->max_load_per_proc = 1; df->idle_timeout = 60; df->disable_time = 60; - + fcv[0].destination = df->host; fcv[1].destination = df->docroot; fcv[2].destination = df->unixsocket; fcv[3].destination = df->bin_path; - + fcv[4].destination = &(df->check_local); fcv[5].destination = &(df->port); fcv[6].destination = &(df->min_procs); @@ -1008,47 +1008,47 @@ SETDEFAULTS_FUNC(mod_scgi_set_defaults) { fcv[8].destination = &(df->max_load_per_proc); fcv[9].destination = &(df->idle_timeout); fcv[10].destination = &(df->disable_time); - + fcv[11].destination = df->bin_env; fcv[12].destination = df->bin_env_copy; - - + + if (0 != config_insert_values_internal(srv, da_host->value, fcv)) { return HANDLER_ERROR; } - - if ((!buffer_is_empty(df->host) || df->port) && + + if ((!buffer_is_empty(df->host) || df->port) && !buffer_is_empty(df->unixsocket)) { - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "either host+port or socket"); - + return HANDLER_ERROR; } - + if (!buffer_is_empty(df->unixsocket)) { /* unix domain socket */ - + if (df->unixsocket->used > UNIX_PATH_MAX - 2) { - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "path of the unixdomain socket is too large"); return HANDLER_ERROR; } } else { /* tcp/ip */ - - if (buffer_is_empty(df->host) && + + if (buffer_is_empty(df->host) && buffer_is_empty(df->bin_path)) { - log_error_write(srv, __FILE__, __LINE__, "sbbbs", - "missing key (string):", + log_error_write(srv, __FILE__, __LINE__, "sbbbs", + "missing key (string):", da->key, da_ext->key, da_host->key, "host"); - + return HANDLER_ERROR; } else if (df->port == 0) { - log_error_write(srv, __FILE__, __LINE__, "sbbbs", - "missing key (short):", + log_error_write(srv, __FILE__, __LINE__, "sbbbs", + "missing key (short):", da->key, da_ext->key, da_host->key, @@ -1056,14 +1056,14 @@ SETDEFAULTS_FUNC(mod_scgi_set_defaults) { return HANDLER_ERROR; } } - - if (!buffer_is_empty(df->bin_path)) { + + if (!buffer_is_empty(df->bin_path)) { /* a local socket + self spawning */ size_t pno; - + if (df->min_procs > df->max_procs) df->max_procs = df->min_procs; if (df->max_load_per_proc < 1) df->max_load_per_proc = 0; - + if (s->debug) { log_error_write(srv, __FILE__, __LINE__, "ssbsdsbsdsd", "--- scgi spawning local", @@ -1073,7 +1073,7 @@ SETDEFAULTS_FUNC(mod_scgi_set_defaults) { "\n\tmin-procs:", df->min_procs, "\n\tmax-procs:", df->max_procs); } - + for (pno = 0; pno < df->min_procs; pno++) { scgi_proc *proc; @@ -1088,7 +1088,7 @@ SETDEFAULTS_FUNC(mod_scgi_set_defaults) { buffer_append_string(proc->socket, "-"); buffer_append_long(proc->socket, pno); } - + if (s->debug) { log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd", "--- scgi spawning", @@ -1096,53 +1096,53 @@ SETDEFAULTS_FUNC(mod_scgi_set_defaults) { "\n\tsocket", df->unixsocket, "\n\tcurrent:", pno, "/", df->min_procs); } - + if (scgi_spawn_connection(srv, p, df, proc)) { log_error_write(srv, __FILE__, __LINE__, "s", "[ERROR]: spawning fcgi failed."); return HANDLER_ERROR; } - + proc->next = df->first; if (df->first) df->first->prev = proc; - + df->first = proc; } } else { scgi_proc *fp; - + fp = scgi_process_init(); fp->id = df->num_procs++; df->max_id++; df->active_procs++; fp->state = PROC_STATE_RUNNING; - + if (buffer_is_empty(df->unixsocket)) { fp->port = df->port; } else { buffer_copy_string_buffer(fp->socket, df->unixsocket); } - + df->first = fp; - + df->min_procs = 1; df->max_procs = 1; } - + /* if extension already exists, take it */ scgi_extension_insert(s->exts, da_ext->key, df); } } } } - + return HANDLER_GO_ON; } static int scgi_set_state(server *srv, handler_ctx *hctx, scgi_connection_state_t state) { hctx->state = state; hctx->state_timestamp = srv->cur_ts; - + return 0; } @@ -1150,34 +1150,34 @@ static int scgi_set_state(server *srv, handler_ctx *hctx, scgi_connection_state_ void scgi_connection_cleanup(server *srv, handler_ctx *hctx) { plugin_data *p; connection *con; - + if (NULL == hctx) return; - + p = hctx->plugin_data; con = hctx->remote_conn; - + if (con->mode != p->id) { WP(); return; } - + if (hctx->fd != -1) { fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); fdevent_unregister(srv->ev, hctx->fd); close(hctx->fd); srv->cur_fds--; } - + if (hctx->host && hctx->proc) { hctx->host->load--; - + if (hctx->got_proc) { /* after the connect the process gets a load */ hctx->proc->load--; - + if (p->conf.debug) { log_error_write(srv, __FILE__, __LINE__, "sddb", - "release proc:", + "release proc:", hctx->fd, hctx->proc->pid, hctx->proc->socket); } @@ -1186,87 +1186,87 @@ void scgi_connection_cleanup(server *srv, handler_ctx *hctx) { scgi_proclist_sort_down(srv, hctx->host, hctx->proc); } - + handler_ctx_free(hctx); - con->plugin_ctx[p->id] = NULL; + con->plugin_ctx[p->id] = NULL; } static int scgi_reconnect(server *srv, handler_ctx *hctx) { plugin_data *p = hctx->plugin_data; - - /* child died - * - * 1. - * + + /* child died + * + * 1. + * * connect was ok, connection was accepted * but the php accept loop checks after the accept if it should die or not. - * - * if yes we can only detect it at a write() - * + * + * if yes we can only detect it at a write() + * * next step is resetting this attemp and setup a connection again - * + * * if we have more then 5 reconnects for the same request, die - * - * 2. - * + * + * 2. + * * we have a connection but the child died by some other reason - * + * */ - + fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); fdevent_unregister(srv->ev, hctx->fd); close(hctx->fd); srv->cur_fds--; - + scgi_set_state(srv, hctx, FCGI_STATE_INIT); - + hctx->request_id = 0; hctx->reconnects++; - + if (p->conf.debug) { log_error_write(srv, __FILE__, __LINE__, "sddb", - "release proc:", + "release proc:", hctx->fd, hctx->proc->pid, hctx->proc->socket); } - + hctx->proc->load--; scgi_proclist_sort_down(srv, hctx->host, hctx->proc); - + return 0; } static handler_t scgi_connection_reset(server *srv, connection *con, void *p_d) { plugin_data *p = p_d; - + scgi_connection_cleanup(srv, con->plugin_ctx[p->id]); - + return HANDLER_GO_ON; } static int scgi_env_add(buffer *env, const char *key, size_t key_len, const char *val, size_t val_len) { size_t len; - + if (!key || !val) return -1; - + len = key_len + val_len + 2; - + buffer_prepare_append(env, len); - /* include the NUL */ + /* include the NUL */ memcpy(env->ptr + env->used, key, key_len + 1); env->used += key_len + 1; memcpy(env->ptr + env->used, val, val_len + 1); env->used += val_len + 1; - + return 0; } /** - * + * * returns * -1 error * 0 connected @@ -1280,13 +1280,13 @@ static int scgi_establish_connection(server *srv, handler_ctx *hctx) { struct sockaddr_un scgi_addr_un; #endif socklen_t servlen; - + scgi_extension_host *host = hctx->host; scgi_proc *proc = hctx->proc; int scgi_fd = hctx->fd; - + memset(&scgi_addr, 0, sizeof(scgi_addr)); - + if (!buffer_is_empty(proc->socket)) { #ifdef HAVE_SYS_UN_H /* use the unix domain socket */ @@ -1305,105 +1305,105 @@ static int scgi_establish_connection(server *srv, handler_ctx *hctx) { } else { scgi_addr_in.sin_family = AF_INET; if (0 == inet_aton(host->host->ptr, &(scgi_addr_in.sin_addr))) { - log_error_write(srv, __FILE__, __LINE__, "sbs", - "converting IP-adress failed for", host->host, + log_error_write(srv, __FILE__, __LINE__, "sbs", + "converting IP-adress failed for", host->host, "\nBe sure to specify an IP address here"); - + return -1; } scgi_addr_in.sin_port = htons(proc->port); servlen = sizeof(scgi_addr_in); - + scgi_addr = (struct sockaddr *) &scgi_addr_in; } - + if (-1 == connect(scgi_fd, scgi_addr, servlen)) { - if (errno == EINPROGRESS || + if (errno == EINPROGRESS || errno == EALREADY || errno == EINTR) { if (hctx->conf.debug) { - log_error_write(srv, __FILE__, __LINE__, "sd", + log_error_write(srv, __FILE__, __LINE__, "sd", "connect delayed, will continue later:", scgi_fd); } - + return 1; } else { - log_error_write(srv, __FILE__, __LINE__, "sdsddb", - "connect failed:", scgi_fd, + log_error_write(srv, __FILE__, __LINE__, "sdsddb", + "connect failed:", scgi_fd, strerror(errno), errno, proc->port, proc->socket); if (errno == EAGAIN) { /* this is Linux only */ - - log_error_write(srv, __FILE__, __LINE__, "s", + + log_error_write(srv, __FILE__, __LINE__, "s", "If this happend on Linux: You have been run out of local ports. " "Check the manual, section Performance how to handle this."); - } - + } + return -1; } } if (hctx->conf.debug > 1) { - log_error_write(srv, __FILE__, __LINE__, "sd", + log_error_write(srv, __FILE__, __LINE__, "sd", "connect succeeded: ", scgi_fd); } - + return 0; } static int scgi_env_add_request_headers(server *srv, connection *con, plugin_data *p) { size_t i; - + for (i = 0; i < con->request.headers->used; i++) { data_string *ds; - + ds = (data_string *)con->request.headers->data[i]; - + if (ds->value->used && ds->key->used) { size_t j; buffer_reset(srv->tmp_buf); - + if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) { BUFFER_COPY_STRING_CONST(srv->tmp_buf, "HTTP_"); srv->tmp_buf->used--; } - + buffer_prepare_append(srv->tmp_buf, ds->key->used + 2); for (j = 0; j < ds->key->used - 1; j++) { - srv->tmp_buf->ptr[srv->tmp_buf->used++] = - light_isalpha(ds->key->ptr[j]) ? + srv->tmp_buf->ptr[srv->tmp_buf->used++] = + light_isalpha(ds->key->ptr[j]) ? ds->key->ptr[j] & ~32 : '_'; } srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0'; - + scgi_env_add(p->scgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value)); } } - + for (i = 0; i < con->environment->used; i++) { data_string *ds; - + ds = (data_string *)con->environment->data[i]; - + if (ds->value->used && ds->key->used) { size_t j; buffer_reset(srv->tmp_buf); - + buffer_prepare_append(srv->tmp_buf, ds->key->used + 2); for (j = 0; j < ds->key->used - 1; j++) { - srv->tmp_buf->ptr[srv->tmp_buf->used++] = - isalpha((unsigned char)ds->key->ptr[j]) ? + srv->tmp_buf->ptr[srv->tmp_buf->used++] = + isalpha((unsigned char)ds->key->ptr[j]) ? toupper((unsigned char)ds->key->ptr[j]) : '_'; } srv->tmp_buf->ptr[srv->tmp_buf->used++] = '\0'; - + scgi_env_add(p->scgi_env, CONST_BUF_LEN(srv->tmp_buf), CONST_BUF_LEN(ds->value)); } } - + return 0; } @@ -1415,20 +1415,20 @@ static int scgi_create_env(server *srv, handler_ctx *hctx) { char b2[INET6_ADDRSTRLEN + 1]; #endif buffer *b; - + plugin_data *p = hctx->plugin_data; scgi_extension_host *host= hctx->host; connection *con = hctx->remote_conn; server_socket *srv_sock = con->srv_socket; - + sock_addr our_addr; socklen_t our_addr_len; - + buffer_prepare_copy(p->scgi_env, 1024); /* CGI-SPEC 6.1.2, FastCGI spec 6.3 and SCGI spec */ - + /* request.content_length < SSIZE_MAX, see request.c */ ltostr(buf, con->request.content_length); scgi_env_add(p->scgi_env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf)); @@ -1436,13 +1436,13 @@ static int scgi_create_env(server *srv, handler_ctx *hctx) { scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_SOFTWARE"), CONST_STR_LEN(PACKAGE_NAME"/"PACKAGE_VERSION)); - + if (con->server_name->used) { scgi_env_add(p->scgi_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); @@ -1451,47 +1451,47 @@ static int scgi_create_env(server *srv, handler_ctx *hctx) { #endif scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_NAME"), s, strlen(s)); } - + scgi_env_add(p->scgi_env, CONST_STR_LEN("GATEWAY_INTERFACE"), CONST_STR_LEN("CGI/1.1")); - - ltostr(buf, + + ltostr(buf, #ifdef HAVE_IPV6 ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port) #else ntohs(srv_sock->addr.ipv4.sin_port) #endif ); - + scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_PORT"), buf, strlen(buf)); - + /* get the server-side of the connection to the client */ our_addr_len = sizeof(our_addr); - + if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) { s = inet_ntop_cache_get_ip(srv, &(srv_sock->addr)); } else { s = inet_ntop_cache_get_ip(srv, &(our_addr)); } scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_ADDR"), s, strlen(s)); - - ltostr(buf, + + ltostr(buf, #ifdef HAVE_IPV6 ntohs(con->dst_addr.plain.sa_family ? con->dst_addr.ipv6.sin6_port : con->dst_addr.ipv4.sin_port) #else ntohs(con->dst_addr.ipv4.sin_port) #endif ); - + scgi_env_add(p->scgi_env, CONST_STR_LEN("REMOTE_PORT"), buf, strlen(buf)); - + s = inet_ntop_cache_get_ip(srv, &(con->dst_addr)); scgi_env_add(p->scgi_env, CONST_STR_LEN("REMOTE_ADDR"), s, strlen(s)); - + if (!buffer_is_empty(con->authed_user)) { scgi_env_add(p->scgi_env, CONST_STR_LEN("REMOTE_USER"), CONST_BUF_LEN(con->authed_user)); } - + /* * SCRIPT_NAME, PATH_INFO and PATH_TRANSLATED according to @@ -1500,12 +1500,12 @@ static int scgi_create_env(server *srv, handler_ctx *hctx) { */ scgi_env_add(p->scgi_env, CONST_STR_LEN("SCRIPT_NAME"), CONST_BUF_LEN(con->uri.path)); - + if (!buffer_is_empty(con->request.pathinfo)) { scgi_env_add(p->scgi_env, CONST_STR_LEN("PATH_INFO"), CONST_BUF_LEN(con->request.pathinfo)); - + /* PATH_TRANSLATED is only defined if PATH_INFO is set */ - + if (!buffer_is_empty(host->docroot)) { buffer_copy_string_buffer(p->path, host->docroot); } else { @@ -1526,19 +1526,19 @@ static int scgi_create_env(server *srv, handler_ctx *hctx) { */ if (!buffer_is_empty(host->docroot)) { - /* - * rewrite SCRIPT_FILENAME - * + /* + * rewrite SCRIPT_FILENAME + * */ - + buffer_copy_string_buffer(p->path, host->docroot); buffer_append_string_buffer(p->path, con->uri.path); - + scgi_env_add(p->scgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path)); scgi_env_add(p->scgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(host->docroot)); } else { buffer_copy_string_buffer(p->path, con->physical.path); - + scgi_env_add(p->scgi_env, CONST_STR_LEN("SCRIPT_FILENAME"), CONST_BUF_LEN(p->path)); scgi_env_add(p->scgi_env, CONST_STR_LEN("DOCUMENT_ROOT"), CONST_BUF_LEN(con->physical.doc_root)); } @@ -1551,30 +1551,30 @@ static int scgi_create_env(server *srv, handler_ctx *hctx) { } else { scgi_env_add(p->scgi_env, CONST_STR_LEN("QUERY_STRING"), CONST_STR_LEN("")); } - + s = get_http_method_name(con->request.http_method); scgi_env_add(p->scgi_env, CONST_STR_LEN("REQUEST_METHOD"), s, strlen(s)); scgi_env_add(p->scgi_env, CONST_STR_LEN("REDIRECT_STATUS"), CONST_STR_LEN("200")); /* if php is compiled with --force-redirect */ s = get_http_version_name(con->request.http_version); scgi_env_add(p->scgi_env, CONST_STR_LEN("SERVER_PROTOCOL"), s, strlen(s)); - + #ifdef USE_OPENSSL if (srv_sock->is_ssl) { scgi_env_add(p->scgi_env, CONST_STR_LEN("HTTPS"), CONST_STR_LEN("on")); } #endif - + scgi_env_add_request_headers(srv, con, p); b = chunkqueue_get_append_buffer(hctx->wb); - + buffer_append_long(b, p->scgi_env->used); buffer_append_string_len(b, CONST_STR_LEN(":")); buffer_append_string_len(b, (const char *)p->scgi_env->ptr, p->scgi_env->used); buffer_append_string_len(b, CONST_STR_LEN(",")); hctx->wb->bytes_in += b->used - 1; - + if (con->request.content_length) { chunkqueue *req_cq = con->request_content_queue; chunk *req_c; @@ -1587,7 +1587,7 @@ static int scgi_create_env(server *srv, handler_ctx *hctx) { /* we announce toWrite octects * now take all the request_content chunk that we need to fill this request - * */ + * */ switch (req_c->type) { case FILE_CHUNK: @@ -1615,32 +1615,32 @@ static int scgi_create_env(server *srv, handler_ctx *hctx) { req_c->offset += weHave; req_cq->bytes_out += weHave; - + hctx->wb->bytes_in += weHave; break; default: break; } - + offset += weHave; } } - + #if 0 for (i = 0; i < hctx->write_buffer->used; i++) { fprintf(stderr, "%02x ", hctx->write_buffer->ptr[i]); if ((i+1) % 16 == 0) { size_t j; for (j = i-15; j <= i; j++) { - fprintf(stderr, "%c", + fprintf(stderr, "%c", isprint((unsigned char)hctx->write_buffer->ptr[j]) ? hctx->write_buffer->ptr[j] : '.'); } fprintf(stderr, "\n"); } } #endif - + return 0; } @@ -1648,32 +1648,32 @@ static int scgi_response_parse(server *srv, connection *con, plugin_data *p, buf 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 */ @@ -1682,27 +1682,27 @@ static int scgi_response_parse(server *srv, connection *con, plugin_data *p, buf } } } else { - + key = s; if (NULL == (value = strchr(s, ':'))) { /* we expect: "<key>: <value>\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)) { @@ -1737,13 +1737,13 @@ static int scgi_response_parse(server *srv, connection *con, plugin_data *p, buf } } } - + /* 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; } @@ -1751,10 +1751,10 @@ static int scgi_response_parse(server *srv, connection *con, plugin_data *p, buf static int scgi_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) { @@ -1765,143 +1765,143 @@ static int scgi_demux_response(server *srv, handler_ctx *hctx) { log_error_write(srv, __FILE__, __LINE__, "sdd", strerror(errno), con->fd, hctx->fd); return -1; } - + 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 1; } - + 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 */ scgi_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 0; } int scgi_proclist_sort_up(server *srv, scgi_extension_host *host, scgi_proc *proc) { scgi_proc *p; - + UNUSED(srv); - - /* we have been the smallest of the current list - * and we want to insert the node sorted as soon + + /* we have been the smallest of the current list + * and we want to insert the node sorted as soon * possible * - * 1 0 0 0 1 1 1 - * | ^ + * 1 0 0 0 1 1 1 + * | ^ * | | * +------+ - * + * */ /* nothing to sort, only one element */ @@ -1909,9 +1909,9 @@ int scgi_proclist_sort_up(server *srv, scgi_extension_host *host, scgi_proc *pro for (p = proc; p->next && p->next->load < proc->load; p = p->next); - /* no need to move something + /* no need to move something * - * 1 2 2 2 3 3 3 + * 1 2 2 2 3 3 3 * ^ * | * + @@ -1930,16 +1930,16 @@ int scgi_proclist_sort_up(server *srv, scgi_extension_host *host, scgi_proc *pro if (proc->prev) proc->prev->next = proc->next; if (proc->next) proc->next->prev = proc->prev; - + /* proc should be right of p */ - + proc->next = p->next; proc->prev = p; if (p->next) p->next->prev = proc; p->next = proc; #if 0 for(p = host->first; p; p = p->next) { - log_error_write(srv, __FILE__, __LINE__, "dd", + log_error_write(srv, __FILE__, __LINE__, "dd", p->pid, p->load); } #else @@ -1951,21 +1951,21 @@ int scgi_proclist_sort_up(server *srv, scgi_extension_host *host, scgi_proc *pro int scgi_proclist_sort_down(server *srv, scgi_extension_host *host, scgi_proc *proc) { scgi_proc *p; - + UNUSED(srv); - - /* we have been the smallest of the current list - * and we want to insert the node sorted as soon + + /* we have been the smallest of the current list + * and we want to insert the node sorted as soon * possible * - * 0 0 0 0 1 0 1 + * 0 0 0 0 1 0 1 * ^ | * | | * +----------+ * * * the basic is idea is: - * - the last active scgi process should be still + * - the last active scgi process should be still * in ram and is not swapped out yet * - processes that are not reused will be killed * after some time by the trigger-handler @@ -1975,7 +1975,7 @@ int scgi_proclist_sort_down(server *srv, scgi_extension_host *host, scgi_proc *p * ice-cold processes are propably unused since more * than 'unused-timeout', are swaped out and won't be * reused in the next seconds anyway. - * + * */ /* nothing to sort, only one element */ @@ -1984,16 +1984,16 @@ int scgi_proclist_sort_down(server *srv, scgi_extension_host *host, scgi_proc *p for (p = host->first; p != proc && p->load < proc->load; p = p->next); - /* no need to move something + /* no need to move something * - * 1 2 2 2 3 3 3 + * 1 2 2 2 3 3 3 * ^ * | * + * */ if (p == proc) return 0; - + /* we have to move left. If we are already the first element * we are done */ if (host->first == proc) return 0; @@ -2009,9 +2009,9 @@ int scgi_proclist_sort_down(server *srv, scgi_extension_host *host, scgi_proc *p p->prev = proc; if (proc->prev == NULL) host->first = proc; -#if 0 +#if 0 for(p = host->first; p; p = p->next) { - log_error_write(srv, __FILE__, __LINE__, "dd", + log_error_write(srv, __FILE__, __LINE__, "dd", p->pid, p->load); } #else @@ -2023,40 +2023,40 @@ int scgi_proclist_sort_down(server *srv, scgi_extension_host *host, scgi_proc *p static int scgi_restart_dead_procs(server *srv, plugin_data *p, scgi_extension_host *host) { scgi_proc *proc; - + for (proc = host->first; proc; proc = proc->next) { if (p->conf.debug) { - log_error_write(srv, __FILE__, __LINE__, "sbdbdddd", - "proc:", - host->host, proc->port, + log_error_write(srv, __FILE__, __LINE__, "sbdbdddd", + "proc:", + host->host, proc->port, proc->socket, proc->state, proc->is_local, proc->load, proc->pid); } - + if (0 == proc->is_local) { - /* - * external servers might get disabled - * - * enable the server again, perhaps it is back again + /* + * external servers might get disabled + * + * enable the server again, perhaps it is back again */ - + if ((proc->state == PROC_STATE_DISABLED) && (srv->cur_ts - proc->disable_ts > host->disable_time)) { proc->state = PROC_STATE_RUNNING; host->active_procs++; - - log_error_write(srv, __FILE__, __LINE__, "sbdb", - "fcgi-server re-enabled:", - host->host, host->port, + + log_error_write(srv, __FILE__, __LINE__, "sbdb", + "fcgi-server re-enabled:", + host->host, host->port, host->unixsocket); } } else { /* the child should not terminate at all */ int status; - + if (proc->state == PROC_STATE_DIED_WAIT_FOR_PID) { switch(waitpid(proc->pid, &status, WNOHANG)) { case 0: @@ -2067,33 +2067,33 @@ static int scgi_restart_dead_procs(server *srv, plugin_data *p, scgi_extension_h default: if (WIFEXITED(status)) { #if 0 - log_error_write(srv, __FILE__, __LINE__, "sdsd", + log_error_write(srv, __FILE__, __LINE__, "sdsd", "child exited, pid:", proc->pid, "status:", WEXITSTATUS(status)); #endif } else if (WIFSIGNALED(status)) { - log_error_write(srv, __FILE__, __LINE__, "sd", - "child signaled:", + log_error_write(srv, __FILE__, __LINE__, "sd", + "child signaled:", WTERMSIG(status)); } else { - log_error_write(srv, __FILE__, __LINE__, "sd", - "child died somehow:", + log_error_write(srv, __FILE__, __LINE__, "sd", + "child died somehow:", status); } - + proc->state = PROC_STATE_DIED; break; } } - - /* + + /* * local servers might died, but we restart them - * + * */ if (proc->state == PROC_STATE_DIED && proc->load == 0) { /* restart the child */ - + if (p->conf.debug) { log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd", "--- scgi spawning", @@ -2101,18 +2101,18 @@ static int scgi_restart_dead_procs(server *srv, plugin_data *p, scgi_extension_h "\n\tsocket", host->unixsocket, "\n\tcurrent:", 1, "/", host->min_procs); } - + if (scgi_spawn_connection(srv, p, host, proc)) { log_error_write(srv, __FILE__, __LINE__, "s", "ERROR: spawning fcgi failed."); return HANDLER_ERROR; } - + scgi_proclist_sort_down(srv, host, proc); } } } - + return 0; } @@ -2121,13 +2121,13 @@ static handler_t scgi_write_request(server *srv, handler_ctx *hctx) { plugin_data *p = hctx->plugin_data; scgi_extension_host *host= hctx->host; connection *con = hctx->remote_conn; - + int ret; - /* sanity check */ + /* sanity check */ if (!host || ((!host->host->used || !host->port) && !host->unixsocket->used)) { - log_error_write(srv, __FILE__, __LINE__, "sxddd", + log_error_write(srv, __FILE__, __LINE__, "sxddd", "write-req: error", host, host->host->used, @@ -2135,179 +2135,179 @@ static handler_t scgi_write_request(server *srv, handler_ctx *hctx) { host->unixsocket->used); return HANDLER_ERROR; } - + switch(hctx->state) { case FCGI_STATE_INIT: ret = host->unixsocket->used ? AF_UNIX : AF_INET; - + if (-1 == (hctx->fd = socket(ret, SOCK_STREAM, 0))) { if (errno == EMFILE || errno == EINTR) { - log_error_write(srv, __FILE__, __LINE__, "sd", + log_error_write(srv, __FILE__, __LINE__, "sd", "wait for fd at connection:", con->fd); - + return HANDLER_WAIT_FOR_FD; } - - log_error_write(srv, __FILE__, __LINE__, "ssdd", + + log_error_write(srv, __FILE__, __LINE__, "ssdd", "socket failed:", strerror(errno), srv->cur_fds, srv->max_fds); return HANDLER_ERROR; } hctx->fde_ndx = -1; - + srv->cur_fds++; - + fdevent_register(srv->ev, hctx->fd, scgi_handle_fdevent, hctx); - + if (-1 == fdevent_fcntl_set(srv->ev, hctx->fd)) { - log_error_write(srv, __FILE__, __LINE__, "ss", + log_error_write(srv, __FILE__, __LINE__, "ss", "fcntl failed: ", strerror(errno)); - + return HANDLER_ERROR; } - + /* fall through */ case FCGI_STATE_CONNECT: if (hctx->state == FCGI_STATE_INIT) { - for (hctx->proc = hctx->host->first; - hctx->proc && hctx->proc->state != PROC_STATE_RUNNING; + for (hctx->proc = hctx->host->first; + hctx->proc && hctx->proc->state != PROC_STATE_RUNNING; hctx->proc = hctx->proc->next); - + /* all childs are dead */ if (hctx->proc == NULL) { hctx->fde_ndx = -1; - + return HANDLER_ERROR; } - + if (hctx->proc->is_local) { hctx->pid = hctx->proc->pid; } - + switch (scgi_establish_connection(srv, hctx)) { case 1: scgi_set_state(srv, hctx, FCGI_STATE_CONNECT); - + /* connection is in progress, wait for an event and call getsockopt() below */ - + fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); - + return HANDLER_WAIT_FOR_EVENT; case -1: /* if ECONNREFUSED choose another connection -> FIXME */ hctx->fde_ndx = -1; - + return HANDLER_ERROR; default: /* everything is ok, go on */ break; } - + } else { int socket_error; socklen_t socket_error_len = sizeof(socket_error); - + /* try to finish the connect() */ if (0 != getsockopt(hctx->fd, SOL_SOCKET, SO_ERROR, &socket_error, &socket_error_len)) { - log_error_write(srv, __FILE__, __LINE__, "ss", + log_error_write(srv, __FILE__, __LINE__, "ss", "getsockopt failed:", strerror(errno)); - + return HANDLER_ERROR; } if (socket_error != 0) { if (!hctx->proc->is_local || p->conf.debug) { /* local procs get restarted */ - + log_error_write(srv, __FILE__, __LINE__, "ss", - "establishing connection failed:", strerror(socket_error), + "establishing connection failed:", strerror(socket_error), "port:", hctx->proc->port); } - + return HANDLER_ERROR; } } - + /* ok, we have the connection */ - + hctx->proc->load++; hctx->proc->last_used = srv->cur_ts; hctx->got_proc = 1; - + if (p->conf.debug) { log_error_write(srv, __FILE__, __LINE__, "sddbdd", - "got proc:", + "got proc:", hctx->fd, - hctx->proc->pid, - hctx->proc->socket, + hctx->proc->pid, + hctx->proc->socket, hctx->proc->port, hctx->proc->load); } /* move the proc-list entry down the list */ scgi_proclist_sort_up(srv, hctx->host, hctx->proc); - + scgi_set_state(srv, hctx, FCGI_STATE_PREPARE_WRITE); /* fall through */ case FCGI_STATE_PREPARE_WRITE: scgi_create_env(srv, hctx); - + scgi_set_state(srv, hctx, FCGI_STATE_WRITE); - + /* fall through */ case FCGI_STATE_WRITE: - ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb); + ret = srv->network_backend_write(srv, con, hctx->fd, hctx->wb); chunkqueue_remove_finished_chunks(hctx->wb); - + if (-1 == ret) { if (errno == ENOTCONN) { - /* the connection got dropped after accept() - * - * this is most of the time a PHP which dies + /* the connection got dropped after accept() + * + * this is most of the time a PHP which dies * after PHP_FCGI_MAX_REQUESTS - * - */ + * + */ if (hctx->wb->bytes_out == 0 && hctx->reconnects < 5) { - usleep(10000); /* take away the load of the webserver - * to let the php a chance to restart + usleep(10000); /* take away the load of the webserver + * to let the php a chance to restart */ - + scgi_reconnect(srv, hctx); - + return HANDLER_WAIT_FOR_FD; } - + /* not reconnected ... why - * + * * far@#lighttpd report this for FreeBSD - * + * */ - - log_error_write(srv, __FILE__, __LINE__, "ssdsd", + + log_error_write(srv, __FILE__, __LINE__, "ssdsd", "[REPORT ME] connection was dropped after accept(). reconnect() denied:", "write-offset:", hctx->wb->bytes_out, "reconnect attempts:", hctx->reconnects); - + return HANDLER_ERROR; } - + if ((errno != EAGAIN) && (errno != EINTR)) { - - log_error_write(srv, __FILE__, __LINE__, "ssd", + + log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), errno); - + return HANDLER_ERROR; } else { fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); - + return HANDLER_WAIT_FOR_EVENT; } } - + if (hctx->wb->bytes_out == hctx->wb->bytes_in) { /* we don't need the out event anymore */ fdevent_event_del(srv->ev, &(hctx->fde_ndx), hctx->fd); @@ -2315,10 +2315,10 @@ static handler_t scgi_write_request(server *srv, handler_ctx *hctx) { scgi_set_state(srv, hctx, FCGI_STATE_READ); } else { fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); - + return HANDLER_WAIT_FOR_EVENT; } - + break; case FCGI_STATE_READ: /* waiting for a response */ @@ -2327,67 +2327,67 @@ static handler_t scgi_write_request(server *srv, handler_ctx *hctx) { log_error_write(srv, __FILE__, __LINE__, "s", "(debug) unknown state"); return HANDLER_ERROR; } - + return HANDLER_WAIT_FOR_EVENT; } SUBREQUEST_FUNC(mod_scgi_handle_subrequest) { plugin_data *p = p_d; - + handler_ctx *hctx = con->plugin_ctx[p->id]; scgi_proc *proc; scgi_extension_host *host; - + if (NULL == hctx) return HANDLER_GO_ON; - + /* not my job */ if (con->mode != p->id) return HANDLER_GO_ON; - + /* ok, create the request */ switch(scgi_write_request(srv, hctx)) { case HANDLER_ERROR: proc = hctx->proc; host = hctx->host; - - if (proc && + + if (proc && 0 == proc->is_local && proc->state != PROC_STATE_DISABLED) { /* only disable remote servers as we don't manage them*/ - - log_error_write(srv, __FILE__, __LINE__, "sbdb", "fcgi-server disabled:", + + log_error_write(srv, __FILE__, __LINE__, "sbdb", "fcgi-server disabled:", host->host, proc->port, proc->socket); - + /* disable this server */ proc->disable_ts = srv->cur_ts; proc->state = PROC_STATE_DISABLED; host->active_procs--; } - + if (hctx->state == FCGI_STATE_INIT || hctx->state == FCGI_STATE_CONNECT) { - /* connect() or getsockopt() failed, - * restart the request-handling + /* connect() or getsockopt() failed, + * restart the request-handling */ if (proc && proc->is_local) { if (p->conf.debug) { - log_error_write(srv, __FILE__, __LINE__, "sbdb", "connect() to scgi failed, restarting the request-handling:", + log_error_write(srv, __FILE__, __LINE__, "sbdb", "connect() to scgi failed, restarting the request-handling:", host->host, proc->port, proc->socket); } - /* + /* * several hctx might reference the same proc - * + * * Only one of them should mark the proc as dead all the other * ones should just take a new one. - * + * * If a new proc was started with the old struct this might lead * the mark a perfect proc as dead otherwise - * + * */ if (proc->state == PROC_STATE_RUNNING && hctx->pid == proc->pid) { @@ -2395,25 +2395,25 @@ SUBREQUEST_FUNC(mod_scgi_handle_subrequest) { } } scgi_restart_dead_procs(srv, p, host); - + scgi_connection_cleanup(srv, hctx); - + buffer_reset(con->physical.path); con->mode = DIRECT; joblist_append(srv, con); - - /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop - * and hope that the childs will be restarted - * + + /* mis-using HANDLER_WAIT_FOR_FD to break out of the loop + * and hope that the childs will be restarted + * */ return HANDLER_WAIT_FOR_FD; } else { scgi_connection_cleanup(srv, hctx); - + buffer_reset(con->physical.path); con->mode = DIRECT; con->http_status = 503; - + return HANDLER_FINISHED; } case HANDLER_WAIT_FOR_EVENT: @@ -2433,23 +2433,23 @@ SUBREQUEST_FUNC(mod_scgi_handle_subrequest) { static handler_t scgi_connection_close(server *srv, handler_ctx *hctx) { 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; - - log_error_write(srv, __FILE__, __LINE__, "ssdsd", - "emergency exit: scgi:", + + log_error_write(srv, __FILE__, __LINE__, "ssdsd", + "emergency exit: scgi:", "connection-fd:", con->fd, "fcgi-fd:", hctx->fd); - - - + + + scgi_connection_cleanup(srv, hctx); - + return HANDLER_FINISHED; } @@ -2459,7 +2459,7 @@ static handler_t scgi_handle_fdevent(void *s, void *ctx, int revents) { handler_ctx *hctx = ctx; connection *con = hctx->remote_conn; plugin_data *p = hctx->plugin_data; - + scgi_proc *proc = hctx->proc; scgi_extension_host *host= hctx->host; @@ -2471,15 +2471,15 @@ static handler_t scgi_handle_fdevent(void *s, void *ctx, int revents) { case 1: /* we are done */ scgi_connection_cleanup(srv, hctx); - + joblist_append(srv, con); return HANDLER_FINISHED; case -1: if (proc->pid && proc->state != PROC_STATE_DIED) { int status; - + /* only fetch the zombie if it is not already done */ - + switch(waitpid(proc->pid, &status, WNOHANG)) { case 0: /* child is still alive */ @@ -2489,19 +2489,19 @@ static handler_t scgi_handle_fdevent(void *s, void *ctx, int revents) { default: /* the child should not terminate at all */ if (WIFEXITED(status)) { - log_error_write(srv, __FILE__, __LINE__, "sdsd", + log_error_write(srv, __FILE__, __LINE__, "sdsd", "child exited, pid:", proc->pid, "status:", WEXITSTATUS(status)); } else if (WIFSIGNALED(status)) { - log_error_write(srv, __FILE__, __LINE__, "sd", - "child signaled:", + log_error_write(srv, __FILE__, __LINE__, "sd", + "child signaled:", WTERMSIG(status)); } else { - log_error_write(srv, __FILE__, __LINE__, "sd", - "child died somehow:", + log_error_write(srv, __FILE__, __LINE__, "sd", + "child died somehow:", status); } - + if (p->conf.debug) { log_error_write(srv, __FILE__, __LINE__, "ssdsbsdsd", "--- scgi spawning", @@ -2509,40 +2509,40 @@ static handler_t scgi_handle_fdevent(void *s, void *ctx, int revents) { "\n\tsocket", host->unixsocket, "\n\tcurrent:", 1, "/", host->min_procs); } - + if (scgi_spawn_connection(srv, p, host, proc)) { /* child died */ proc->state = PROC_STATE_DIED; } else { scgi_proclist_sort_down(srv, host, proc); } - + break; } } if (con->file_started == 0) { /* nothing has been send out yet, try to use another child */ - + if (hctx->wb->bytes_out == 0 && hctx->reconnects < 5) { scgi_reconnect(srv, hctx); - - log_error_write(srv, __FILE__, __LINE__, "sdsdsd", + + log_error_write(srv, __FILE__, __LINE__, "sdsdsd", "response not sent, request not sent, reconnection.", "connection-fd:", con->fd, "fcgi-fd:", hctx->fd); - + return HANDLER_WAIT_FOR_FD; } - - log_error_write(srv, __FILE__, __LINE__, "sdsdsd", + + log_error_write(srv, __FILE__, __LINE__, "sdsdsd", "response not sent, request sent:", hctx->wb->bytes_out, "connection-fd:", con->fd, "fcgi-fd:", hctx->fd); - + scgi_connection_cleanup(srv, hctx); - + connection_set_state(srv, con, CON_STATE_HANDLE_REQUEST); buffer_reset(con->physical.path); con->http_status = 500; @@ -2550,76 +2550,76 @@ static handler_t scgi_handle_fdevent(void *s, void *ctx, int revents) { } else { /* response might have been already started, kill the connection */ scgi_connection_cleanup(srv, hctx); - - log_error_write(srv, __FILE__, __LINE__, "ssdsd", + + log_error_write(srv, __FILE__, __LINE__, "ssdsd", "response already sent out, termination connection", "connection-fd:", con->fd, "fcgi-fd:", hctx->fd); - + connection_set_state(srv, con, CON_STATE_ERROR); } /* */ - - + + joblist_append(srv, con); return HANDLER_FINISHED; } } - + if (revents & FDEVENT_OUT) { if (hctx->state == FCGI_STATE_CONNECT || hctx->state == FCGI_STATE_WRITE) { /* we are allowed to send something out - * + * * 1. in a unfinished connect() call * 2. in a unfinished write() call (long POST request) */ return mod_scgi_handle_subrequest(srv, con, p); } else { - log_error_write(srv, __FILE__, __LINE__, "sd", - "got a FDEVENT_OUT and didn't know why:", + log_error_write(srv, __FILE__, __LINE__, "sd", + "got a FDEVENT_OUT and didn't know why:", hctx->state); } } - + /* perhaps this issue is already handled */ if (revents & FDEVENT_HUP) { if (hctx->state == FCGI_STATE_CONNECT) { /* getoptsock will catch this one (right ?) - * - * if we are in connect we might get a EINPROGRESS - * in the first call and a FDEVENT_HUP in the + * + * if we are in connect we might get a EINPROGRESS + * in the first call and a FDEVENT_HUP in the * second round - * + * * FIXME: as it is a bit ugly. - * + * */ return mod_scgi_handle_subrequest(srv, con, p); } else if (hctx->state == FCGI_STATE_READ && hctx->proc->port == 0) { /* FIXME: - * + * * ioctl says 8192 bytes to read from PHP and we receive directly a HUP for the socket * even if the FCGI_FIN packet is not received yet */ } else { - log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd", - "error: unexpected close of scgi connection for", + log_error_write(srv, __FILE__, __LINE__, "sbSBSDSd", + "error: unexpected close of scgi connection for", con->uri.path, - "(no scgi process on host: ", + "(no scgi process on host: ", host->host, - ", port: ", + ", port: ", host->port, " ?)", hctx->state); - + connection_set_state(srv, con, CON_STATE_ERROR); scgi_connection_close(srv, hctx); joblist_append(srv, con); } } else if (revents & FDEVENT_ERR) { - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "fcgi: got a FDEVENT_ERR. Don't know why."); /* kill all connections to the scgi process */ @@ -2628,7 +2628,7 @@ static handler_t scgi_handle_fdevent(void *s, void *ctx, int revents) { scgi_connection_close(srv, hctx); joblist_append(srv, con); } - + return HANDLER_FINISHED; } #define PATCH(x) \ @@ -2636,22 +2636,22 @@ static handler_t scgi_handle_fdevent(void *s, void *ctx, int revents) { static int scgi_patch_connection(server *srv, connection *con, plugin_data *p) { size_t i, j; plugin_config *s = p->config_storage[0]; - + PATCH(exts); PATCH(debug); - + /* 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("scgi.server"))) { PATCH(exts); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("scgi.debug"))) { @@ -2659,7 +2659,7 @@ static int scgi_patch_connection(server *srv, connection *con, plugin_data *p) { } } } - + return 0; } #undef PATCH @@ -2673,30 +2673,30 @@ static handler_t scgi_check_extension(server *srv, connection *con, void *p_d, i size_t k; buffer *fn; scgi_extension *extension = NULL; - + /* Possibly, we processed already this request */ if (con->file_started == 1) return HANDLER_GO_ON; - + fn = uri_path_handler ? con->uri.path : con->physical.path; if (buffer_is_empty(fn)) return HANDLER_GO_ON; s_len = fn->used - 1; - + scgi_patch_connection(srv, con, p); /* check if extension matches */ for (k = 0; k < p->conf.exts->used; k++) { size_t ct_len; - + extension = p->conf.exts->exts[k]; - + if (extension->key->used == 0) continue; - + ct_len = extension->key->used - 1; - + if (s_len < ct_len) continue; - + /* check extension in the form "/scgi_pattern" */ if (*(extension->key->ptr) == '/' && strncmp(fn->ptr, extension->key->ptr, ct_len) == 0) { break; @@ -2710,17 +2710,17 @@ static handler_t scgi_check_extension(server *srv, connection *con, void *p_d, i if (k == p->conf.exts->used) { return HANDLER_GO_ON; } - + /* get best server */ for (k = 0, ndx = -1; k < extension->used; k++) { scgi_extension_host *host = extension->hosts[k]; - + /* we should have at least one proc that can do somthing */ if (host->active_procs == 0) continue; if (used == -1 || host->load < used) { used = host->load; - + ndx = k; } } @@ -2728,12 +2728,12 @@ static handler_t scgi_check_extension(server *srv, connection *con, void *p_d, i /* found a server */ if (ndx != -1) { scgi_extension_host *host = extension->hosts[ndx]; - - /* - * if check-local is disabled, use the uri.path handler - * + + /* + * if check-local is disabled, use the uri.path handler + * */ - + /* init handler-context */ if (uri_path_handler) { if (host->check_local == 0) { @@ -2741,7 +2741,7 @@ static handler_t scgi_check_extension(server *srv, connection *con, void *p_d, i char *pathinfo; hctx = handler_ctx_init(); - + hctx->remote_conn = con; hctx->plugin_data = p; hctx->host = host; @@ -2749,45 +2749,45 @@ static handler_t scgi_check_extension(server *srv, connection *con, void *p_d, i hctx->conf.exts = p->conf.exts; hctx->conf.debug = p->conf.debug; - + con->plugin_ctx[p->id] = hctx; - + host->load++; - + con->mode = p->id; if (con->conf.log_request_handling) { log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_scgi"); } - /* the prefix is the SCRIPT_NAME, + /* the prefix is the SCRIPT_NAME, * everthing from start to the next slash * this is important for check-local = "disable" - * + * * if prefix = /admin.fcgi - * + * * /admin.fcgi/foo/bar - * + * * SCRIPT_NAME = /admin.fcgi * PATH_INFO = /foo/bar - * + * * if prefix = /fcgi-bin/ - * + * * /fcgi-bin/foo/bar - * + * * SCRIPT_NAME = /fcgi-bin/foo * PATH_INFO = /bar - * + * */ - + /* the rewrite is only done for /prefix/? matches */ if (extension->key->ptr[0] == '/' && con->uri.path->used > extension->key->used && NULL != (pathinfo = strchr(con->uri.path->ptr + extension->key->used - 1, '/'))) { - /* rewrite uri.path and pathinfo */ - + /* rewrite uri.path and pathinfo */ + buffer_copy_string(con->request.pathinfo, pathinfo); - + con->uri.path->used -= con->request.pathinfo->used - 1; con->uri.path->ptr[con->uri.path->used - 1] = '\0'; } @@ -2796,21 +2796,21 @@ static handler_t scgi_check_extension(server *srv, connection *con, void *p_d, i } else { handler_ctx *hctx; hctx = handler_ctx_init(); - + hctx->remote_conn = con; hctx->plugin_data = p; hctx->host = host; hctx->proc = NULL; - + hctx->conf.exts = p->conf.exts; hctx->conf.debug = p->conf.debug; - + con->plugin_ctx[p->id] = hctx; - + host->load++; - + con->mode = p->id; - + if (con->conf.log_request_handling) { log_error_write(srv, __FILE__, __LINE__, "s", "handling it in mod_fastcgi"); } @@ -2821,11 +2821,11 @@ static handler_t scgi_check_extension(server *srv, connection *con, void *p_d, i /* no handler found */ buffer_reset(con->physical.path); con->http_status = 500; - - log_error_write(srv, __FILE__, __LINE__, "sb", - "no fcgi-handler found for:", + + log_error_write(srv, __FILE__, __LINE__, "sb", + "no fcgi-handler found for:", fn); - + return HANDLER_FINISHED; } return HANDLER_GO_ON; @@ -2844,19 +2844,19 @@ static handler_t scgi_check_extension_2(server *srv, connection *con, void *p_d) JOBLIST_FUNC(mod_scgi_handle_joblist) { plugin_data *p = p_d; handler_ctx *hctx = con->plugin_ctx[p->id]; - + if (hctx == NULL) return HANDLER_GO_ON; if (hctx->fd != -1) { switch (hctx->state) { case FCGI_STATE_READ: fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_IN); - + break; case FCGI_STATE_CONNECT: case FCGI_STATE_WRITE: fdevent_event_add(srv->ev, &(hctx->fde_ndx), hctx->fd, FDEVENT_OUT); - + break; case FCGI_STATE_INIT: /* at reconnect */ @@ -2873,21 +2873,21 @@ JOBLIST_FUNC(mod_scgi_handle_joblist) { static handler_t scgi_connection_close_callback(server *srv, connection *con, void *p_d) { plugin_data *p = p_d; - + return scgi_connection_close(srv, con->plugin_ctx[p->id]); } TRIGGER_FUNC(mod_scgi_handle_trigger) { plugin_data *p = p_d; size_t i, j, n; - - + + /* perhaps we should kill a connect attempt after 10-15 seconds - * + * * currently we wait for the TCP timeout which is on Linux 180 seconds - * - * - * + * + * + * */ /* check all childs if they are still up */ @@ -2904,47 +2904,47 @@ TRIGGER_FUNC(mod_scgi_handle_trigger) { scgi_extension *ex; ex = exts->exts[j]; - + for (n = 0; n < ex->used; n++) { - + scgi_proc *proc; unsigned long sum_load = 0; scgi_extension_host *host; - + host = ex->hosts[n]; - + scgi_restart_dead_procs(srv, p, host); - + for (proc = host->first; proc; proc = proc->next) { sum_load += proc->load; } - + if (host->num_procs && host->num_procs < host->max_procs && (sum_load / host->num_procs) > host->max_load_per_proc) { /* overload, spawn new child */ scgi_proc *fp = NULL; - + if (p->conf.debug) { - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "overload detected, spawning a new child"); } - + for (fp = host->unused_procs; fp && fp->pid != 0; fp = fp->next); - + if (fp) { if (fp == host->unused_procs) host->unused_procs = fp->next; - + if (fp->next) fp->next->prev = NULL; - + host->max_id++; } else { fp = scgi_process_init(); fp->id = host->max_id++; } - + host->num_procs++; - + if (buffer_is_empty(host->unixsocket)) { fp->port = host->port + fp->id; } else { @@ -2952,13 +2952,13 @@ TRIGGER_FUNC(mod_scgi_handle_trigger) { buffer_append_string(fp->socket, "-"); buffer_append_long(fp->socket, fp->id); } - + if (scgi_spawn_connection(srv, p, host, fp)) { log_error_write(srv, __FILE__, __LINE__, "s", "ERROR: spawning fcgi failed."); return HANDLER_ERROR; } - + fp->prev = NULL; fp->next = host->first; if (host->first) { @@ -2966,56 +2966,56 @@ TRIGGER_FUNC(mod_scgi_handle_trigger) { } host->first = fp; } - + for (proc = host->first; proc; proc = proc->next) { if (proc->load != 0) break; if (host->num_procs <= host->min_procs) break; if (proc->pid == 0) continue; - + if (srv->cur_ts - proc->last_used > host->idle_timeout) { /* a proc is idling for a long time now, * terminated it */ - + if (p->conf.debug) { - log_error_write(srv, __FILE__, __LINE__, "ssbsd", - "idle-timeout reached, terminating child:", - "socket:", proc->socket, + log_error_write(srv, __FILE__, __LINE__, "ssbsd", + "idle-timeout reached, terminating child:", + "socket:", proc->socket, "pid", proc->pid); } - - + + if (proc->next) proc->next->prev = proc->prev; if (proc->prev) proc->prev->next = proc->next; - + if (proc->prev == NULL) host->first = proc->next; - + proc->prev = NULL; proc->next = host->unused_procs; - + if (host->unused_procs) host->unused_procs->prev = proc; host->unused_procs = proc; - + kill(proc->pid, SIGTERM); - + proc->state = PROC_STATE_KILLED; - - log_error_write(srv, __FILE__, __LINE__, "ssbsd", - "killed:", - "socket:", proc->socket, + + log_error_write(srv, __FILE__, __LINE__, "ssbsd", + "killed:", + "socket:", proc->socket, "pid", proc->pid); - + host->num_procs--; - + /* proc is now in unused, let the next second handle the next process */ break; - } + } } - + for (proc = host->unused_procs; proc; proc = proc->next) { int status; - + if (proc->pid == 0) continue; - + switch (waitpid(proc->pid, &status, WNOHANG)) { case 0: /* child still running after timeout, good */ @@ -3023,10 +3023,10 @@ TRIGGER_FUNC(mod_scgi_handle_trigger) { case -1: if (errno != EINTR) { /* no PID found ? should never happen */ - log_error_write(srv, __FILE__, __LINE__, "sddss", + log_error_write(srv, __FILE__, __LINE__, "sddss", "pid ", proc->pid, proc->state, "not found:", strerror(errno)); - + #if 0 if (errno == ECHILD) { /* someone else has cleaned up for us */ @@ -3040,19 +3040,19 @@ TRIGGER_FUNC(mod_scgi_handle_trigger) { /* the child should not terminate at all */ if (WIFEXITED(status)) { if (proc->state != PROC_STATE_KILLED) { - log_error_write(srv, __FILE__, __LINE__, "sdb", - "child exited:", + log_error_write(srv, __FILE__, __LINE__, "sdb", + "child exited:", WEXITSTATUS(status), proc->socket); } } else if (WIFSIGNALED(status)) { if (WTERMSIG(status) != SIGTERM) { - log_error_write(srv, __FILE__, __LINE__, "sd", - "child signaled:", + log_error_write(srv, __FILE__, __LINE__, "sd", + "child signaled:", WTERMSIG(status)); } } else { - log_error_write(srv, __FILE__, __LINE__, "sd", - "child died somehow:", + log_error_write(srv, __FILE__, __LINE__, "sd", + "child died somehow:", status); } proc->pid = 0; @@ -3082,8 +3082,8 @@ int mod_scgi_plugin_init(plugin *p) { p->handle_subrequest = mod_scgi_handle_subrequest; p->handle_joblist = mod_scgi_handle_joblist; p->handle_trigger = mod_scgi_handle_trigger; - + p->data = NULL; - + return 0; } diff --git a/src/mod_secure_download.c b/src/mod_secure_download.c index 1ea5a50..08a0554 100644 --- a/src/mod_secure_download.c +++ b/src/mod_secure_download.c @@ -25,7 +25,7 @@ typedef char HASHHEX[HASHHEXLEN+1]; #ifdef USE_OPENSSL #define IN const #else -#define IN +#define IN #endif #define OUT @@ -36,28 +36,28 @@ typedef struct { 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 @@ INIT_FUNC(mod_secdownload_init) { 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,65 +94,65 @@ FREE_FUNC(mod_secdownload_free) { 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; } @@ -161,24 +161,24 @@ int is_hex_len(const char *str, size_t len) { 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); - + /* 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); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("secdownload.document-root"))) { @@ -190,7 +190,7 @@ static int mod_secdownload_patch_connection(server *srv, connection *con, plugin } } } - + return 0; } #undef PATCH @@ -203,88 +203,88 @@ URIHANDLER_FUNC(mod_secdownload_uri_handler) { 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; } - - /* + + /* * /<uri-prefix>[a-f0-9]{32}/[a-f0-9]{8}/<rel-path> */ - + 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 + * * <secret><rel-path><timestamp-hex> */ - + 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 +293,13 @@ URIHANDLER_FUNC(mod_secdownload_uri_handler) { 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; } diff --git a/src/mod_setenv.c b/src/mod_setenv.c index 9501554..88ce45a 100644 --- a/src/mod_setenv.c +++ b/src/mod_setenv.c @@ -18,25 +18,25 @@ typedef struct { typedef struct { array *request_header; array *response_header; - + array *environment; } plugin_config; typedef struct { PLUGIN_DATA; - + 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->handled = 0; - + return hctx; } @@ -48,36 +48,36 @@ static void handler_ctx_free(handler_ctx *hctx) { /* init the plugin data */ INIT_FUNC(mod_setenv_init) { plugin_data *p; - + p = calloc(1, sizeof(*p)); - + return p; } /* detroy the plugin data */ FREE_FUNC(mod_setenv_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]; - + array_free(s->request_header); array_free(s->response_header); array_free(s->environment); - + free(s); } free(p->config_storage); } - + free(p); - + return HANDLER_GO_ON; } @@ -86,37 +86,37 @@ FREE_FUNC(mod_setenv_free) { SETDEFAULTS_FUNC(mod_setenv_set_defaults) { plugin_data *p = p_d; size_t i = 0; - - config_values_t cv[] = { + + config_values_t cv[] = { { "setenv.add-request-header", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ { "setenv.add-response-header", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */ { "setenv.add-environment", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 2 */ { 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->request_header = array_init(); s->response_header = array_init(); s->environment = array_init(); - + cv[0].destination = s->request_header; cv[1].destination = s->response_header; cv[2].destination = s->environment; - + 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; } @@ -125,23 +125,23 @@ SETDEFAULTS_FUNC(mod_setenv_set_defaults) { static int mod_setenv_patch_connection(server *srv, connection *con, plugin_data *p) { size_t i, j; plugin_config *s = p->config_storage[0]; - + PATCH(request_header); PATCH(response_header); PATCH(environment); - + /* 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("setenv.add-request-header"))) { PATCH(request_header); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("setenv.add-response-header"))) { @@ -151,7 +151,7 @@ static int mod_setenv_patch_connection(server *srv, connection *con, plugin_data } } } - + return 0; } #undef PATCH @@ -160,12 +160,12 @@ URIHANDLER_FUNC(mod_setenv_uri_handler) { plugin_data *p = p_d; size_t k; handler_ctx *hctx; - + if (con->plugin_ctx[p->id]) { hctx = con->plugin_ctx[p->id]; } else { hctx = handler_ctx_init(); - + con->plugin_ctx[p->id] = hctx; } @@ -180,52 +180,52 @@ URIHANDLER_FUNC(mod_setenv_uri_handler) { for (k = 0; k < p->conf.request_header->used; k++) { data_string *ds = (data_string *)p->conf.request_header->data[k]; data_string *ds_dst; - + if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) { ds_dst = data_string_init(); } - + buffer_copy_string_buffer(ds_dst->key, ds->key); buffer_copy_string_buffer(ds_dst->value, ds->value); - + array_insert_unique(con->request.headers, (data_unset *)ds_dst); } - + for (k = 0; k < p->conf.environment->used; k++) { data_string *ds = (data_string *)p->conf.environment->data[k]; data_string *ds_dst; - + if (NULL == (ds_dst = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) { ds_dst = data_string_init(); } - + buffer_copy_string_buffer(ds_dst->key, ds->key); buffer_copy_string_buffer(ds_dst->value, ds->value); - + array_insert_unique(con->environment, (data_unset *)ds_dst); } - + for (k = 0; k < p->conf.response_header->used; k++) { data_string *ds = (data_string *)p->conf.response_header->data[k]; - + response_header_insert(srv, con, CONST_BUF_LEN(ds->key), CONST_BUF_LEN(ds->value)); } - + /* not found */ return HANDLER_GO_ON; } REQUESTDONE_FUNC(mod_setenv_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; + return HANDLER_GO_ON; } /* this function is called at dlopen() time and inits the callbacks */ @@ -233,15 +233,15 @@ REQUESTDONE_FUNC(mod_setenv_reset) { int mod_setenv_plugin_init(plugin *p) { p->version = LIGHTTPD_VERSION_ID; p->name = buffer_init_string("setenv"); - + p->init = mod_setenv_init; p->handle_uri_clean = mod_setenv_uri_handler; p->set_defaults = mod_setenv_set_defaults; p->cleanup = mod_setenv_free; - + p->handle_request_done = mod_setenv_reset; p->data = NULL; - + return 0; } diff --git a/src/mod_simple_vhost.c b/src/mod_simple_vhost.c index 8f81384..d55cfed 100644 --- a/src/mod_simple_vhost.c +++ b/src/mod_simple_vhost.c @@ -18,7 +18,7 @@ typedef struct { buffer *server_root; buffer *default_host; buffer *document_root; - + buffer *docroot_cache_key; buffer *docroot_cache_value; buffer *docroot_cache_servername; @@ -28,119 +28,119 @@ typedef struct { typedef struct { PLUGIN_DATA; - + buffer *doc_root; - + plugin_config **config_storage; - plugin_config conf; + plugin_config conf; } plugin_data; INIT_FUNC(mod_simple_vhost_init) { plugin_data *p; - + p = calloc(1, sizeof(*p)); - + p->doc_root = buffer_init(); - + return p; } FREE_FUNC(mod_simple_vhost_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->document_root); buffer_free(s->default_host); buffer_free(s->server_root); - + buffer_free(s->docroot_cache_key); buffer_free(s->docroot_cache_value); buffer_free(s->docroot_cache_servername); - + free(s); } - + free(p->config_storage); } - + buffer_free(p->doc_root); - + free(p); - + return HANDLER_GO_ON; } SETDEFAULTS_FUNC(mod_simple_vhost_set_defaults) { plugin_data *p = p_d; size_t i; - - config_values_t cv[] = { + + config_values_t cv[] = { { "simple-vhost.server-root", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, { "simple-vhost.default-host", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, { "simple-vhost.document-root", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, { "simple-vhost.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, { 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->server_root = buffer_init(); s->default_host = buffer_init(); s->document_root = buffer_init(); - + s->docroot_cache_key = buffer_init(); s->docroot_cache_value = buffer_init(); s->docroot_cache_servername = buffer_init(); s->debug = 0; - + cv[0].destination = s->server_root; cv[1].destination = s->default_host; cv[2].destination = s->document_root; cv[3].destination = &(s->debug); - - + + 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; } static int build_doc_root(server *srv, connection *con, plugin_data *p, buffer *out, buffer *host) { stat_cache_entry *sce = NULL; - + buffer_prepare_copy(out, 128); if (p->conf.server_root->used) { buffer_copy_string_buffer(out, p->conf.server_root); - + if (host->used) { /* a hostname has to start with a alpha-numerical character * and must not contain a slash "/" */ char *dp; - + BUFFER_APPEND_SLASH(out); - + if (NULL == (dp = strchr(host->ptr, ':'))) { buffer_append_string_buffer(out, host); } else { @@ -148,7 +148,7 @@ static int build_doc_root(server *srv, connection *con, plugin_data *p, buffer * } } BUFFER_APPEND_SLASH(out); - + if (p->conf.document_root->used > 2 && p->conf.document_root->ptr[0] == '/') { buffer_append_string_len(out, p->conf.document_root->ptr + 1, p->conf.document_root->used - 2); } else { @@ -159,7 +159,7 @@ static int build_doc_root(server *srv, connection *con, plugin_data *p, buffer * buffer_copy_string_buffer(out, con->conf.document_root); BUFFER_APPEND_SLASH(out); } - + if (HANDLER_ERROR == stat_cache_get_entry(srv, con, out, &sce)) { if (p->conf.debug) { log_error_write(srv, __FILE__, __LINE__, "sb", @@ -169,7 +169,7 @@ static int build_doc_root(server *srv, connection *con, plugin_data *p, buffer * } else if (!S_ISDIR(sce->st.st_mode)) { return -1; } - + return 0; } @@ -179,29 +179,29 @@ static int build_doc_root(server *srv, connection *con, plugin_data *p, buffer * static int mod_simple_vhost_patch_connection(server *srv, connection *con, plugin_data *p) { size_t i, j; plugin_config *s = p->config_storage[0]; - + PATCH(server_root); PATCH(default_host); PATCH(document_root); - + PATCH(docroot_cache_key); PATCH(docroot_cache_value); PATCH(docroot_cache_servername); PATCH(debug); - + /* 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("simple-vhost.server-root"))) { PATCH(server_root); PATCH(docroot_cache_key); @@ -216,7 +216,7 @@ static int mod_simple_vhost_patch_connection(server *srv, connection *con, plugi } } } - + return 0; } #undef PATCH @@ -227,12 +227,12 @@ static handler_t mod_simple_vhost_docroot(server *srv, connection *con, void *p_ /* * cache the last successfull translation from hostname (authority) to docroot * - this saves us a stat() call - * + * */ - + mod_simple_vhost_patch_connection(srv, con, p); - - if (p->conf.docroot_cache_key->used && + + if (p->conf.docroot_cache_key->used && con->uri.authority->used && buffer_is_equal(p->conf.docroot_cache_key, con->uri.authority)) { /* cache hit */ @@ -243,8 +243,8 @@ static handler_t mod_simple_vhost_docroot(server *srv, connection *con, void *p_ if ((con->uri.authority->used == 0) || build_doc_root(srv, con, p, p->doc_root, con->uri.authority)) { /* not found, fallback the default-host */ - if (build_doc_root(srv, con, p, - p->doc_root, + if (build_doc_root(srv, con, p, + p->doc_root, p->conf.default_host)) { return HANDLER_GO_ON; } else { @@ -253,15 +253,15 @@ static handler_t mod_simple_vhost_docroot(server *srv, connection *con, void *p_ } else { buffer_copy_string_buffer(con->server_name, con->uri.authority); } - + /* copy to cache */ buffer_copy_string_buffer(p->conf.docroot_cache_key, con->uri.authority); buffer_copy_string_buffer(p->conf.docroot_cache_value, p->doc_root); buffer_copy_string_buffer(p->conf.docroot_cache_servername, con->server_name); - + buffer_copy_string_buffer(con->physical.doc_root, p->doc_root); } - + return HANDLER_GO_ON; } @@ -269,13 +269,13 @@ static handler_t mod_simple_vhost_docroot(server *srv, connection *con, void *p_ int mod_simple_vhost_plugin_init(plugin *p) { p->version = LIGHTTPD_VERSION_ID; p->name = buffer_init_string("simple_vhost"); - + p->init = mod_simple_vhost_init; p->set_defaults = mod_simple_vhost_set_defaults; p->handle_docroot = mod_simple_vhost_docroot; p->cleanup = mod_simple_vhost_free; - + p->data = NULL; - + return 0; } diff --git a/src/mod_skeleton.c b/src/mod_skeleton.c index a3fa186..9cea92c 100644 --- a/src/mod_skeleton.c +++ b/src/mod_skeleton.c @@ -14,13 +14,13 @@ /** * this is a skeleton for a lighttpd plugin - * + * * just replaces every occurance of 'skeleton' by your plugin name - * + * * e.g. in vim: - * + * * :%s/skeleton/myhandler/ - * + * */ @@ -33,12 +33,12 @@ typedef struct { typedef struct { PLUGIN_DATA; - + buffer *match_buf; - + plugin_config **config_storage; - - plugin_config conf; + + plugin_config conf; } plugin_data; typedef struct { @@ -47,36 +47,36 @@ typedef struct { static handler_ctx * handler_ctx_init() { handler_ctx * hctx; - + hctx = calloc(1, sizeof(*hctx)); - + return hctx; } static void handler_ctx_free(handler_ctx *hctx) { - + free(hctx); } /* init the plugin data */ INIT_FUNC(mod_skeleton_init) { plugin_data *p; - + p = calloc(1, sizeof(*p)); - + p->match_buf = buffer_init(); - + return p; } /* detroy the plugin data */ FREE_FUNC(mod_skeleton_free) { plugin_data *p = p_d; - + UNUSED(srv); if (!p) return HANDLER_GO_ON; - + if (p->config_storage) { size_t i; @@ -84,18 +84,18 @@ FREE_FUNC(mod_skeleton_free) { plugin_config *s = p->config_storage[i]; if (!s) continue; - + array_free(s->match); - + free(s); } free(p->config_storage); } - + buffer_free(p->match_buf); - + free(p); - + return HANDLER_GO_ON; } @@ -104,31 +104,31 @@ FREE_FUNC(mod_skeleton_free) { SETDEFAULTS_FUNC(mod_skeleton_set_defaults) { plugin_data *p = p_d; size_t i = 0; - - config_values_t cv[] = { + + config_values_t cv[] = { { "skeleton.array", 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)); s->match = array_init(); - + cv[0].destination = s->match; - + 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; } @@ -137,27 +137,27 @@ SETDEFAULTS_FUNC(mod_skeleton_set_defaults) { static int mod_skeleton_patch_connection(server *srv, connection *con, plugin_data *p) { size_t i, j; plugin_config *s = p->config_storage[0]; - + PATCH(match); - + /* 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("skeleton.array"))) { PATCH(match); } } } - + return 0; } #undef PATCH @@ -166,29 +166,29 @@ URIHANDLER_FUNC(mod_skeleton_uri_handler) { plugin_data *p = p_d; int s_len; size_t k, i; - + UNUSED(srv); if (con->uri.path->used == 0) return HANDLER_GO_ON; - + mod_skeleton_patch_connection(srv, con, p); s_len = con->uri.path->used - 1; - + for (k = 0; k < p->conf.match->used; k++) { data_string *ds = (data_string *)p->conf.match->data[k]; int ct_len = ds->value->used - 1; - + if (ct_len > s_len) continue; if (ds->value->used == 0) continue; - + if (0 == strncmp(con->uri.path->ptr + s_len - ct_len, ds->value->ptr, ct_len)) { con->http_status = 403; - + return HANDLER_FINISHED; } } - + /* not found */ return HANDLER_GO_ON; } @@ -198,13 +198,13 @@ URIHANDLER_FUNC(mod_skeleton_uri_handler) { int mod_skeleton_plugin_init(plugin *p) { p->version = LIGHTTPD_VERSION_ID; p->name = buffer_init_string("skeleton"); - + p->init = mod_skeleton_init; p->handle_uri_clean = mod_skeleton_uri_handler; p->set_defaults = mod_skeleton_set_defaults; p->cleanup = mod_skeleton_free; - + p->data = NULL; - + return 0; } diff --git a/src/mod_ssi.c b/src/mod_ssi.c index 4fdae2f..e66a6fc 100644 --- a/src/mod_ssi.c +++ b/src/mod_ssi.c @@ -39,15 +39,15 @@ /* init the plugin data */ INIT_FUNC(mod_ssi_init) { plugin_data *p; - + p = calloc(1, sizeof(*p)); - + p->timefmt = buffer_init(); p->stat_fn = buffer_init(); - + p->ssi_vars = array_init(); p->ssi_cgi_env = array_init(); - + return p; } @@ -55,21 +55,21 @@ INIT_FUNC(mod_ssi_init) { FREE_FUNC(mod_ssi_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]; - + array_free(s->ssi_extension); - + free(s); } free(p->config_storage); } - + array_free(p->ssi_vars); array_free(p->ssi_cgi_env); #ifdef HAVE_PCRE_H @@ -77,9 +77,9 @@ FREE_FUNC(mod_ssi_free) { #endif buffer_free(p->timefmt); buffer_free(p->stat_fn); - + free(p); - + return HANDLER_GO_ON; } @@ -92,36 +92,36 @@ SETDEFAULTS_FUNC(mod_ssi_set_defaults) { const char *errptr; int erroff; #endif - - config_values_t cv[] = { + + config_values_t cv[] = { { "ssi.extension", 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)); s->ssi_extension = array_init(); - + cv[0].destination = s->ssi_extension; - + p->config_storage[i] = s; - + if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) { return HANDLER_ERROR; } } - + #ifdef HAVE_PCRE_H /* allow 2 params */ if (NULL == (p->ssi_regex = pcre_compile("<!--#([a-z]+)\\s+(?:([a-z]+)=\"(.*?)(?<!\\\\)\"\\s*)?(?:([a-z]+)=\"(.*?)(?<!\\\\)\"\\s*)?-->", 0, &errptr, &erroff, NULL))) { log_error_write(srv, __FILE__, __LINE__, "sds", - "ssi: pcre ", + "ssi: pcre ", erroff, errptr); return HANDLER_ERROR; } @@ -130,52 +130,52 @@ SETDEFAULTS_FUNC(mod_ssi_set_defaults) { "mod_ssi: pcre support is missing, please recompile with pcre support or remove mod_ssi from the list of modules"); return HANDLER_ERROR; #endif - + return HANDLER_GO_ON; } int ssi_env_add(array *env, const char *key, const char *val) { data_string *ds; - + if (NULL == (ds = (data_string *)array_get_unused_element(env, TYPE_STRING))) { ds = data_string_init(); } buffer_copy_string(ds->key, key); buffer_copy_string(ds->value, val); - + array_insert_unique(env, (data_unset *)ds); - + return 0; } /** * * the next two functions are take from fcgi.c - * + * */ static int ssi_env_add_request_headers(server *srv, connection *con, plugin_data *p) { size_t i; - + for (i = 0; i < con->request.headers->used; i++) { data_string *ds; - + ds = (data_string *)con->request.headers->data[i]; - + if (ds->value->used && ds->key->used) { size_t j; buffer_reset(srv->tmp_buf); - + /* don't forward the Authorization: Header */ if (0 == strcasecmp(ds->key->ptr, "AUTHORIZATION")) { continue; } - + if (0 != strcasecmp(ds->key->ptr, "CONTENT-TYPE")) { buffer_copy_string(srv->tmp_buf, "HTTP_"); srv->tmp_buf->used--; } - + buffer_prepare_append(srv->tmp_buf, ds->key->used + 2); for (j = 0; j < ds->key->used - 1; j++) { char c = '_'; @@ -189,33 +189,33 @@ static int ssi_env_add_request_headers(server *srv, connection *con, plugin_data srv->tmp_buf->ptr[srv->tmp_buf->used++] = c; } srv->tmp_buf->ptr[srv->tmp_buf->used] = '\0'; - + ssi_env_add(p->ssi_cgi_env, srv->tmp_buf->ptr, ds->value->ptr); } } - + return 0; } static int build_ssi_cgi_vars(server *srv, connection *con, plugin_data *p) { char buf[32]; - + server_socket *srv_sock = con->srv_socket; - + #ifdef HAVE_IPV6 char b2[INET6_ADDRSTRLEN + 1]; #endif #define CONST_STRING(x) \ x - + array_reset(p->ssi_cgi_env); - + ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_SOFTWARE"), PACKAGE_NAME"/"PACKAGE_VERSION); ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_NAME"), #ifdef HAVE_IPV6 - inet_ntop(srv_sock->addr.plain.sa_family, - srv_sock->addr.plain.sa_family == AF_INET6 ? + 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) @@ -224,28 +224,28 @@ static int build_ssi_cgi_vars(server *srv, connection *con, plugin_data *p) { #endif ); ssi_env_add(p->ssi_cgi_env, CONST_STRING("GATEWAY_INTERFACE"), "CGI/1.1"); - - ltostr(buf, + + ltostr(buf, #ifdef HAVE_IPV6 ntohs(srv_sock->addr.plain.sa_family ? srv_sock->addr.ipv6.sin6_port : srv_sock->addr.ipv4.sin_port) #else ntohs(srv_sock->addr.ipv4.sin_port) #endif ); - + ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_PORT"), buf); - + ssi_env_add(p->ssi_cgi_env, CONST_STRING("REMOTE_ADDR"), inet_ntop_cache_get_ip(srv, &(con->dst_addr))); - + if (con->authed_user->used) { ssi_env_add(p->ssi_cgi_env, CONST_STRING("REMOTE_USER"), con->authed_user->ptr); } - + if (con->request.content_length > 0) { /* CGI-SPEC 6.1.2 and FastCGI spec 6.3 */ - + /* request.content_length < SSIZE_MAX, see request.c */ ltostr(buf, con->request.content_length); ssi_env_add(p->ssi_cgi_env, CONST_STRING("CONTENT_LENGTH"), buf); @@ -271,30 +271,30 @@ static int build_ssi_cgi_vars(server *srv, connection *con, plugin_data *p) { if (con->request.pathinfo->used) { ssi_env_add(p->ssi_cgi_env, CONST_STRING("PATH_INFO"), con->request.pathinfo->ptr); } - + ssi_env_add(p->ssi_cgi_env, CONST_STRING("SCRIPT_FILENAME"), con->physical.path->ptr); ssi_env_add(p->ssi_cgi_env, CONST_STRING("DOCUMENT_ROOT"), con->physical.doc_root->ptr); - + ssi_env_add(p->ssi_cgi_env, CONST_STRING("REQUEST_URI"), con->request.uri->ptr); ssi_env_add(p->ssi_cgi_env, CONST_STRING("QUERY_STRING"), con->uri.query->used ? con->uri.query->ptr : ""); ssi_env_add(p->ssi_cgi_env, CONST_STRING("REQUEST_METHOD"), get_http_method_name(con->request.http_method)); ssi_env_add(p->ssi_cgi_env, CONST_STRING("REDIRECT_STATUS"), "200"); ssi_env_add(p->ssi_cgi_env, CONST_STRING("SERVER_PROTOCOL"), get_http_version_name(con->request.http_version)); - + ssi_env_add_request_headers(srv, con, p); - + return 0; } -static int process_ssi_stmt(server *srv, connection *con, plugin_data *p, +static int process_ssi_stmt(server *srv, connection *con, plugin_data *p, const char **l, size_t n) { size_t i, ssicmd = 0; char buf[255]; buffer *b = NULL; - - struct { + + struct { const char *var; - enum { SSI_UNSET, SSI_ECHO, SSI_FSIZE, SSI_INCLUDE, SSI_FLASTMOD, + enum { SSI_UNSET, SSI_ECHO, SSI_FSIZE, SSI_INCLUDE, SSI_FLASTMOD, SSI_CONFIG, SSI_PRINTENV, SSI_SET, SSI_IF, SSI_ELIF, SSI_ELSE, SSI_ENDIF, SSI_EXEC } type; } ssicmds[] = { @@ -310,27 +310,27 @@ static int process_ssi_stmt(server *srv, connection *con, plugin_data *p, { "endif", SSI_ENDIF }, { "else", SSI_ELSE }, { "exec", SSI_EXEC }, - + { NULL, SSI_UNSET } }; - + for (i = 0; ssicmds[i].var; i++) { if (0 == strcmp(l[1], ssicmds[i].var)) { ssicmd = ssicmds[i].type; break; } } - + switch(ssicmd) { case SSI_ECHO: { /* echo */ int var = 0, enc = 0; const char *var_val = NULL; stat_cache_entry *sce = NULL; - - struct { + + struct { const char *var; - enum { SSI_ECHO_UNSET, SSI_ECHO_DATE_GMT, SSI_ECHO_DATE_LOCAL, SSI_ECHO_DOCUMENT_NAME, SSI_ECHO_DOCUMENT_URI, + enum { SSI_ECHO_UNSET, SSI_ECHO_DATE_GMT, SSI_ECHO_DATE_LOCAL, SSI_ECHO_DOCUMENT_NAME, SSI_ECHO_DOCUMENT_URI, SSI_ECHO_LAST_MODIFIED, SSI_ECHO_USER_NAME } type; } echovars[] = { { "DATE_GMT", SSI_ECHO_DATE_GMT }, @@ -339,27 +339,27 @@ static int process_ssi_stmt(server *srv, connection *con, plugin_data *p, { "DOCUMENT_URI", SSI_ECHO_DOCUMENT_URI }, { "LAST_MODIFIED", SSI_ECHO_LAST_MODIFIED }, { "USER_NAME", SSI_ECHO_USER_NAME }, - + { NULL, SSI_ECHO_UNSET } }; - - struct { + + struct { const char *var; enum { SSI_ENC_UNSET, SSI_ENC_URL, SSI_ENC_NONE, SSI_ENC_ENTITY } type; } encvars[] = { { "url", SSI_ENC_URL }, { "none", SSI_ENC_NONE }, { "entity", SSI_ENC_ENTITY }, - + { NULL, SSI_ENC_UNSET } }; - + for (i = 2; i < n; i += 2) { if (0 == strcmp(l[i], "var")) { int j; - + var_val = l[i+1]; - + for (j = 0; echovars[j].var; j++) { if (0 == strcmp(l[i+1], echovars[j].var)) { var = echovars[j].type; @@ -368,7 +368,7 @@ static int process_ssi_stmt(server *srv, connection *con, plugin_data *p, } } else if (0 == strcmp(l[i], "encoding")) { int j; - + for (j = 0; encvars[j].var; j++) { if (0 == strcmp(l[i+1], encvars[j].var)) { enc = encvars[j].type; @@ -377,26 +377,26 @@ static int process_ssi_stmt(server *srv, connection *con, plugin_data *p, } } else { log_error_write(srv, __FILE__, __LINE__, "sss", - "ssi: unknow attribute for ", + "ssi: unknow attribute for ", l[1], l[i]); } } - + if (p->if_is_false) break; - + if (!var_val) { log_error_write(srv, __FILE__, __LINE__, "sss", - "ssi: ", + "ssi: ", l[1], "var is missing"); break; } stat_cache_get_entry(srv, con, con->physical.path, &sce); - + switch(var) { case SSI_ECHO_USER_NAME: { struct passwd *pw; - + b = chunkqueue_get_append_buffer(con->write_queue); #ifdef HAVE_PWD_H if (NULL == (pw = getpwuid(sce->st.st_uid))) { @@ -411,7 +411,7 @@ static int process_ssi_stmt(server *srv, connection *con, plugin_data *p, } case SSI_ECHO_LAST_MODIFIED: { time_t t = sce->st.st_mtime; - + b = chunkqueue_get_append_buffer(con->write_queue); if (0 == strftime(buf, sizeof(buf), p->timefmt->ptr, localtime(&t))) { buffer_copy_string(b, "(none)"); @@ -422,7 +422,7 @@ static int process_ssi_stmt(server *srv, connection *con, plugin_data *p, } case SSI_ECHO_DATE_LOCAL: { time_t t = time(NULL); - + b = chunkqueue_get_append_buffer(con->write_queue); if (0 == strftime(buf, sizeof(buf), p->timefmt->ptr, localtime(&t))) { buffer_copy_string(b, "(none)"); @@ -433,7 +433,7 @@ static int process_ssi_stmt(server *srv, connection *con, plugin_data *p, } case SSI_ECHO_DATE_GMT: { time_t t = time(NULL); - + b = chunkqueue_get_append_buffer(con->write_queue); if (0 == strftime(buf, sizeof(buf), p->timefmt->ptr, gmtime(&t))) { buffer_copy_string(b, "(none)"); @@ -444,7 +444,7 @@ static int process_ssi_stmt(server *srv, connection *con, plugin_data *p, } case SSI_ECHO_DOCUMENT_NAME: { char *sl; - + b = chunkqueue_get_append_buffer(con->write_queue); if (NULL == (sl = strrchr(con->physical.path->ptr, '/'))) { buffer_copy_string_buffer(b, con->physical.path); @@ -461,15 +461,15 @@ static int process_ssi_stmt(server *srv, connection *con, plugin_data *p, default: { data_string *ds; /* check if it is a cgi-var */ - + b = chunkqueue_get_append_buffer(con->write_queue); - + if (NULL != (ds = (data_string *)array_get_element(p->ssi_cgi_env, var_val))) { buffer_copy_string_buffer(b, ds->value); } else { buffer_copy_string(b, "(none)"); } - + break; } } @@ -481,7 +481,7 @@ static int process_ssi_stmt(server *srv, connection *con, plugin_data *p, const char * file_path = NULL, *virt_path = NULL; struct stat st; char *sl; - + for (i = 2; i < n; i += 2) { if (0 == strcmp(l[i], "file")) { file_path = l[i+1]; @@ -489,28 +489,28 @@ static int process_ssi_stmt(server *srv, connection *con, plugin_data *p, virt_path = l[i+1]; } else { log_error_write(srv, __FILE__, __LINE__, "sss", - "ssi: unknow attribute for ", + "ssi: unknow attribute for ", l[1], l[i]); } } - + if (!file_path && !virt_path) { log_error_write(srv, __FILE__, __LINE__, "sss", - "ssi: ", + "ssi: ", l[1], "file or virtual are missing"); break; } - + if (file_path && virt_path) { log_error_write(srv, __FILE__, __LINE__, "sss", - "ssi: ", + "ssi: ", l[1], "only one of file and virtual is allowed here"); break; } - - + + if (p->if_is_false) break; - + if (file_path) { /* current doc-root */ if (NULL == (sl = strrchr(con->physical.path->ptr, '/'))) { @@ -519,46 +519,46 @@ static int process_ssi_stmt(server *srv, connection *con, plugin_data *p, buffer_copy_string_len(p->stat_fn, con->physical.path->ptr, sl - con->physical.path->ptr + 1); } - buffer_copy_string(srv->tmp_buf, file_path); + buffer_copy_string(srv->tmp_buf, file_path); buffer_urldecode_path(srv->tmp_buf); - buffer_path_simplify(srv->tmp_buf, srv->tmp_buf); - buffer_append_string_buffer(p->stat_fn, srv->tmp_buf); + buffer_path_simplify(srv->tmp_buf, srv->tmp_buf); + buffer_append_string_buffer(p->stat_fn, srv->tmp_buf); } else { /* virtual */ - + if (virt_path[0] == '/') { buffer_copy_string(p->stat_fn, virt_path); } else { /* there is always a / */ sl = strrchr(con->uri.path->ptr, '/'); - + buffer_copy_string_len(p->stat_fn, con->uri.path->ptr, sl - con->uri.path->ptr + 1); buffer_append_string(p->stat_fn, virt_path); } - + buffer_urldecode_path(p->stat_fn); buffer_path_simplify(srv->tmp_buf, p->stat_fn); - + /* we have an uri */ - + buffer_copy_string_buffer(p->stat_fn, con->physical.doc_root); buffer_append_string_buffer(p->stat_fn, srv->tmp_buf); } - + if (0 == stat(p->stat_fn->ptr, &st)) { time_t t = st.st_mtime; - + switch (ssicmd) { case SSI_FSIZE: b = chunkqueue_get_append_buffer(con->write_queue); if (p->sizefmt) { int j = 0; const char *abr[] = { " B", " kB", " MB", " GB", " TB", NULL }; - + off_t s = st.st_size; - + for (j = 0; s > 1024 && abr[j+1]; s /= 1024, j++); - + buffer_copy_off_t(b, s); buffer_append_string(b, abr[j]); } else { @@ -579,7 +579,7 @@ static int process_ssi_stmt(server *srv, connection *con, plugin_data *p, } } else { log_error_write(srv, __FILE__, __LINE__, "sbs", - "ssi: stating failed ", + "ssi: stating failed ", p->stat_fn, strerror(errno)); } break; @@ -593,33 +593,33 @@ static int process_ssi_stmt(server *srv, connection *con, plugin_data *p, val = l[i+1]; } else { log_error_write(srv, __FILE__, __LINE__, "sss", - "ssi: unknow attribute for ", + "ssi: unknow attribute for ", l[1], l[i]); } } - + if (p->if_is_false) break; - + if (key && val) { data_string *ds; - + if (NULL == (ds = (data_string *)array_get_unused_element(p->ssi_vars, TYPE_STRING))) { ds = data_string_init(); } buffer_copy_string(ds->key, key); buffer_copy_string(ds->value, val); - + array_insert_unique(p->ssi_vars, (data_unset *)ds); } else { log_error_write(srv, __FILE__, __LINE__, "sss", - "ssi: var and value have to be set in", + "ssi: var and value have to be set in", l[0], l[1]); } break; } - case SSI_CONFIG: + case SSI_CONFIG: if (p->if_is_false) break; - + for (i = 2; i < n; i += 2) { if (0 == strcmp(l[i], "timefmt")) { buffer_copy_string(p->timefmt, l[i+1]); @@ -632,63 +632,63 @@ static int process_ssi_stmt(server *srv, connection *con, plugin_data *p, log_error_write(srv, __FILE__, __LINE__, "sssss", "ssi: unknow value for attribute '", l[i], - "' for ", + "' for ", l[1], l[i+1]); } } else { log_error_write(srv, __FILE__, __LINE__, "sss", - "ssi: unknow attribute for ", + "ssi: unknow attribute for ", l[1], l[i]); } } break; case SSI_PRINTENV: if (p->if_is_false) break; - + b = chunkqueue_get_append_buffer(con->write_queue); buffer_copy_string(b, "<pre>"); for (i = 0; i < p->ssi_vars->used; i++) { data_string *ds = (data_string *)p->ssi_vars->data[p->ssi_vars->sorted[i]]; - + buffer_append_string_buffer(b, ds->key); buffer_append_string(b, ": "); buffer_append_string_buffer(b, ds->value); buffer_append_string(b, "<br />"); - + } buffer_append_string(b, "</pre>"); - + break; case SSI_EXEC: { const char *cmd = NULL; pid_t pid; int from_exec_fds[2]; - + for (i = 2; i < n; i += 2) { if (0 == strcmp(l[i], "cmd")) { cmd = l[i+1]; } else { log_error_write(srv, __FILE__, __LINE__, "sss", - "ssi: unknow attribute for ", + "ssi: unknow attribute for ", l[1], l[i]); } } - + if (p->if_is_false) break; - + /* create a return pipe and send output to the html-page - * - * as exec is assumed evil it is implemented synchronously + * + * as exec is assumed evil it is implemented synchronously */ - + if (!cmd) break; -#ifdef HAVE_FORK +#ifdef HAVE_FORK if (pipe(from_exec_fds)) { - log_error_write(srv, __FILE__, __LINE__, "ss", + log_error_write(srv, __FILE__, __LINE__, "ss", "pipe failed: ", strerror(errno)); return -1; } - + /* fork, execve */ switch (pid = fork()) { case 0: { @@ -698,14 +698,14 @@ static int process_ssi_stmt(server *srv, connection *con, plugin_data *p, close(from_exec_fds[1]); /* not needed */ close(from_exec_fds[0]); - + /* close stdin */ close(STDIN_FILENO); - + execl("/bin/sh", "sh", "-c", cmd, NULL); - + log_error_write(srv, __FILE__, __LINE__, "sss", "spawing exec failed:", strerror(errno), cmd); - + /* */ SEGFAULT(); break; @@ -718,16 +718,16 @@ static int process_ssi_stmt(server *srv, connection *con, plugin_data *p, /* father */ int status; ssize_t r; - + close(from_exec_fds[1]); - + /* wait for the client to end */ /* * FIXME: if we get interrupted by a SIGCHILD we count this as error * * for now it only happened on OpenBSD. - * + * * that leads to zombies and missing output */ if (-1 == waitpid(pid, &status, 0)) { @@ -738,7 +738,7 @@ static int process_ssi_stmt(server *srv, connection *con, plugin_data *p, while(1) { if (ioctl(from_exec_fds[0], FIONREAD, &toread)) { - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "unexpected end-of-file (perhaps the ssi-exec process died)"); return -1; } @@ -746,10 +746,10 @@ static int process_ssi_stmt(server *srv, connection *con, plugin_data *p, if (toread > 0) { b = chunkqueue_get_append_buffer(con->write_queue); - buffer_prepare_copy(b, toread + 1); + buffer_prepare_copy(b, toread + 1); if ((r = read(from_exec_fds[0], b->ptr, b->size - 1)) < 0) { - /* read failed */ + /* read failed */ break; } else { b->used = r; @@ -763,7 +763,7 @@ static int process_ssi_stmt(server *srv, connection *con, plugin_data *p, log_error_write(srv, __FILE__, __LINE__, "s", "process exited abnormally"); } close(from_exec_fds[0]); - + break; } } @@ -771,51 +771,51 @@ static int process_ssi_stmt(server *srv, connection *con, plugin_data *p, return -1; #endif - + break; } case SSI_IF: { const char *expr = NULL; - + for (i = 2; i < n; i += 2) { if (0 == strcmp(l[i], "expr")) { expr = l[i+1]; } else { log_error_write(srv, __FILE__, __LINE__, "sss", - "ssi: unknow attribute for ", + "ssi: unknow attribute for ", l[1], l[i]); } } - + if (!expr) { log_error_write(srv, __FILE__, __LINE__, "sss", - "ssi: ", + "ssi: ", l[1], "expr missing"); break; } - + if ((!p->if_is_false) && - ((p->if_is_false_level == 0) || + ((p->if_is_false_level == 0) || (p->if_level < p->if_is_false_level))) { switch (ssi_eval_expr(srv, con, p, expr)) { case -1: - case 0: - p->if_is_false = 1; + case 0: + p->if_is_false = 1; p->if_is_false_level = p->if_level; break; - case 1: - p->if_is_false = 0; + case 1: + p->if_is_false = 0; break; } } - + p->if_level++; - + break; } case SSI_ELSE: p->if_level--; - + if (p->if_is_false) { if ((p->if_level == p->if_is_false_level) && (p->if_is_false_endif == 0)) { @@ -823,11 +823,11 @@ static int process_ssi_stmt(server *srv, connection *con, plugin_data *p, } } else { p->if_is_false = 1; - + p->if_is_false_level = p->if_level; } p->if_level++; - + break; case SSI_ELIF: { const char *expr = NULL; @@ -836,52 +836,52 @@ static int process_ssi_stmt(server *srv, connection *con, plugin_data *p, expr = l[i+1]; } else { log_error_write(srv, __FILE__, __LINE__, "sss", - "ssi: unknow attribute for ", + "ssi: unknow attribute for ", l[1], l[i]); } } - + if (!expr) { log_error_write(srv, __FILE__, __LINE__, "sss", - "ssi: ", + "ssi: ", l[1], "expr missing"); break; } - + p->if_level--; - + if (p->if_level == p->if_is_false_level) { if ((p->if_is_false) && (p->if_is_false_endif == 0)) { switch (ssi_eval_expr(srv, con, p, expr)) { case -1: - case 0: - p->if_is_false = 1; + case 0: + p->if_is_false = 1; p->if_is_false_level = p->if_level; break; - case 1: - p->if_is_false = 0; + case 1: + p->if_is_false = 0; break; } } else { - p->if_is_false = 1; + p->if_is_false = 1; p->if_is_false_level = p->if_level; p->if_is_false_endif = 1; } } - + p->if_level++; - + break; } case SSI_ENDIF: p->if_level--; - + if (p->if_level == p->if_is_false_level) { p->if_is_false = 0; p->if_is_false_endif = 0; } - + break; default: log_error_write(srv, __FILE__, __LINE__, "ss", @@ -889,41 +889,41 @@ static int process_ssi_stmt(server *srv, connection *con, plugin_data *p, l[1]); break; } - + return 0; - + } static int mod_ssi_handle_request(server *srv, connection *con, plugin_data *p) { stream s; #ifdef HAVE_PCRE_H int i, n; - + #define N 10 int ovec[N * 3]; #endif - + /* get a stream to the file */ - + array_reset(p->ssi_vars); array_reset(p->ssi_cgi_env); buffer_copy_string(p->timefmt, "%a, %d %b %Y %H:%M:%S %Z"); p->sizefmt = 0; build_ssi_cgi_vars(srv, con, p); p->if_is_false = 0; - + if (-1 == stream_open(&s, con->physical.path)) { log_error_write(srv, __FILE__, __LINE__, "sb", "stream-open: ", con->physical.path); return -1; } - - + + /** - * <!--#element attribute=value attribute=value ... --> - * + * <!--#element attribute=value attribute=value ... --> + * * config DONE - * errmsg -- missing + * errmsg -- missing * sizefmt DONE * timefmt DONE * echo DONE @@ -945,13 +945,13 @@ static int mod_ssi_handle_request(server *srv, connection *con, plugin_data *p) * set DONE * var DONE * value DONE - * + * * if DONE * elif DONE * else DONE * endif DONE - * - * + * + * * expressions * AND, OR DONE * comp DONE @@ -959,60 +959,60 @@ static int mod_ssi_handle_request(server *srv, connection *con, plugin_data *p) * $... DONE * '...' DONE * ( ... ) DONE - * - * - * + * + * + * * ** all DONE ** - * DATE_GMT - * The current date in Greenwich Mean Time. - * DATE_LOCAL - * The current date in the local time zone. - * DOCUMENT_NAME - * The filename (excluding directories) of the document requested by the user. - * DOCUMENT_URI - * The (%-decoded) URL path of the document requested by the user. Note that in the case of nested include files, this is not then URL for the current document. - * LAST_MODIFIED - * The last modification date of the document requested by the user. - * USER_NAME + * DATE_GMT + * The current date in Greenwich Mean Time. + * DATE_LOCAL + * The current date in the local time zone. + * DOCUMENT_NAME + * The filename (excluding directories) of the document requested by the user. + * DOCUMENT_URI + * The (%-decoded) URL path of the document requested by the user. Note that in the case of nested include files, this is not then URL for the current document. + * LAST_MODIFIED + * The last modification date of the document requested by the user. + * USER_NAME * Contains the owner of the file which included it. - * + * */ -#ifdef HAVE_PCRE_H +#ifdef HAVE_PCRE_H for (i = 0; (n = pcre_exec(p->ssi_regex, NULL, s.start, s.size, i, 0, ovec, N * 3)) > 0; i = ovec[1]) { const char **l; /* take everything from last offset to current match pos */ - + if (!p->if_is_false) chunkqueue_append_file(con->write_queue, con->physical.path, i, ovec[0] - i); - + pcre_get_substring_list(s.start, ovec, n, &l); process_ssi_stmt(srv, con, p, l, n); pcre_free_substring_list(l); } - + switch(n) { case PCRE_ERROR_NOMATCH: /* copy everything/the rest */ chunkqueue_append_file(con->write_queue, con->physical.path, i, s.size - i); - + break; default: log_error_write(srv, __FILE__, __LINE__, "sd", "execution error while matching: ", n); break; } -#endif - - +#endif + + stream_close(&s); - + con->file_started = 1; con->file_finished = 1; - + response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html")); - + /* reset physical.path */ buffer_reset(con->physical.path); - + return 0; } @@ -1021,27 +1021,27 @@ static int mod_ssi_handle_request(server *srv, connection *con, plugin_data *p) static int mod_ssi_patch_connection(server *srv, connection *con, plugin_data *p) { size_t i, j; plugin_config *s = p->config_storage[0]; - + PATCH(ssi_extension); - + /* 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("ssi.extension"))) { PATCH(ssi_extension); } } } - + return 0; } #undef PATCH @@ -1049,28 +1049,28 @@ static int mod_ssi_patch_connection(server *srv, connection *con, plugin_data *p URIHANDLER_FUNC(mod_ssi_physical_path) { plugin_data *p = p_d; size_t k; - + if (con->physical.path->used == 0) return HANDLER_GO_ON; - + mod_ssi_patch_connection(srv, con, p); - + for (k = 0; k < p->conf.ssi_extension->used; k++) { data_string *ds = (data_string *)p->conf.ssi_extension->data[k]; - + if (ds->value->used == 0) continue; - + if (buffer_is_equal_right_len(con->physical.path, ds->value, ds->value->used - 1)) { /* handle ssi-request */ - + if (mod_ssi_handle_request(srv, con, p)) { /* on error */ con->http_status = 500; } - + return HANDLER_FINISHED; } } - + /* not found */ return HANDLER_GO_ON; } @@ -1080,13 +1080,13 @@ URIHANDLER_FUNC(mod_ssi_physical_path) { int mod_ssi_plugin_init(plugin *p) { p->version = LIGHTTPD_VERSION_ID; p->name = buffer_init_string("ssi"); - + p->init = mod_ssi_init; p->handle_subrequest_start = mod_ssi_physical_path; p->set_defaults = mod_ssi_set_defaults; p->cleanup = mod_ssi_free; - + p->data = NULL; - + return 0; } diff --git a/src/mod_ssi.h b/src/mod_ssi.h index 80f03ed..4d2214b 100644 --- a/src/mod_ssi.h +++ b/src/mod_ssi.h @@ -19,23 +19,23 @@ typedef struct { typedef struct { PLUGIN_DATA; - -#ifdef HAVE_PCRE_H + +#ifdef HAVE_PCRE_H pcre *ssi_regex; -#endif +#endif buffer *timefmt; int sizefmt; - + buffer *stat_fn; - + array *ssi_vars; array *ssi_cgi_env; - + int if_level, if_is_false_level, if_is_false, if_is_false_endif; - + plugin_config **config_storage; - - plugin_config conf; + + plugin_config conf; } plugin_data; int ssi_eval_expr(server *srv, connection *con, plugin_data *p, const char *expr); diff --git a/src/mod_ssi_expr.c b/src/mod_ssi_expr.c index 98959ab..fc6e4cb 100644 --- a/src/mod_ssi_expr.c +++ b/src/mod_ssi_expr.c @@ -11,9 +11,9 @@ typedef struct { const char *input; size_t offset; size_t size; - + int line_pos; - + int in_key; int in_brace; int in_cond; @@ -21,15 +21,15 @@ typedef struct { ssi_val_t *ssi_val_init() { ssi_val_t *s; - + s = calloc(1, sizeof(*s)); - + return s; } void ssi_val_free(ssi_val_t *s) { if (s->str) buffer_free(s->str); - + free(s); } @@ -45,175 +45,175 @@ static int ssi_expr_tokenizer(server *srv, connection *con, plugin_data *p, ssi_tokenizer_t *t, int *token_id, buffer *token) { int tid = 0; size_t i; - + UNUSED(con); for (tid = 0; tid == 0 && t->offset < t->size && t->input[t->offset] ; ) { char c = t->input[t->offset]; data_string *ds; - + switch (c) { - case '=': + case '=': tid = TK_EQ; - + t->offset++; t->line_pos++; - + buffer_copy_string(token, "(=)"); - + break; case '>': if (t->input[t->offset + 1] == '=') { t->offset += 2; t->line_pos += 2; - + tid = TK_GE; - + buffer_copy_string(token, "(>=)"); } else { t->offset += 1; t->line_pos += 1; - + tid = TK_GT; - + buffer_copy_string(token, "(>)"); } - + break; case '<': if (t->input[t->offset + 1] == '=') { t->offset += 2; t->line_pos += 2; - + tid = TK_LE; - + buffer_copy_string(token, "(<=)"); } else { t->offset += 1; t->line_pos += 1; - + tid = TK_LT; - + buffer_copy_string(token, "(<)"); } - + break; - + case '!': if (t->input[t->offset + 1] == '=') { t->offset += 2; t->line_pos += 2; - + tid = TK_NE; - + buffer_copy_string(token, "(!=)"); } else { t->offset += 1; t->line_pos += 1; - + tid = TK_NOT; - + buffer_copy_string(token, "(!)"); } - + break; case '&': if (t->input[t->offset + 1] == '&') { t->offset += 2; t->line_pos += 2; - + tid = TK_AND; - + buffer_copy_string(token, "(&&)"); } else { - log_error_write(srv, __FILE__, __LINE__, "sds", - "pos:", t->line_pos, + log_error_write(srv, __FILE__, __LINE__, "sds", + "pos:", t->line_pos, "missing second &"); return -1; } - + break; case '|': if (t->input[t->offset + 1] == '|') { t->offset += 2; t->line_pos += 2; - + tid = TK_OR; - + buffer_copy_string(token, "(||)"); } else { - log_error_write(srv, __FILE__, __LINE__, "sds", - "pos:", t->line_pos, + log_error_write(srv, __FILE__, __LINE__, "sds", + "pos:", t->line_pos, "missing second |"); return -1; } - + break; case '\t': case ' ': t->offset++; t->line_pos++; break; - + case '\'': /* search for the terminating " */ for (i = 1; t->input[t->offset + i] && t->input[t->offset + i] != '\''; i++); - + if (t->input[t->offset + i]) { tid = TK_VALUE; - + buffer_copy_string_len(token, t->input + t->offset + 1, i-1); - + t->offset += i + 1; t->line_pos += i + 1; } else { /* ERROR */ - - log_error_write(srv, __FILE__, __LINE__, "sds", - "pos:", t->line_pos, + + log_error_write(srv, __FILE__, __LINE__, "sds", + "pos:", t->line_pos, "missing closing quote"); - + return -1; } - + break; case '(': t->offset++; t->in_brace++; - + tid = TK_LPARAN; - + buffer_copy_string(token, "("); break; case ')': t->offset++; t->in_brace--; - + tid = TK_RPARAN; - + buffer_copy_string(token, ")"); break; case '$': if (t->input[t->offset + 1] == '{') { for (i = 2; t->input[t->offset + i] && t->input[t->offset + i] != '}'; i++); - + if (t->input[t->offset + i] != '}') { - log_error_write(srv, __FILE__, __LINE__, "sds", - "pos:", t->line_pos, + log_error_write(srv, __FILE__, __LINE__, "sds", + "pos:", t->line_pos, "missing closing quote"); - + return -1; } - + buffer_copy_string_len(token, t->input + t->offset + 2, i-3); } else { for (i = 1; isalpha(t->input[t->offset + i]) || t->input[t->offset + i] == '_'; i++); - + buffer_copy_string_len(token, t->input + t->offset + 1, i-1); } - + tid = TK_VALUE; - + if (NULL != (ds = (data_string *)array_get_element(p->ssi_cgi_env, token->ptr))) { buffer_copy_string_buffer(token, ds->value); } else if (NULL != (ds = (data_string *)array_get_element(p->ssi_vars, token->ptr))) { @@ -221,16 +221,16 @@ static int ssi_expr_tokenizer(server *srv, connection *con, plugin_data *p, } else { buffer_copy_string(token, ""); } - + t->offset += i; t->line_pos += i; - + break; default: for (i = 0; isgraph(t->input[t->offset + i]); i++) { char d = t->input[t->offset + i]; switch(d) { - case ' ': + case ' ': case '\t': case ')': case '(': @@ -244,25 +244,25 @@ static int ssi_expr_tokenizer(server *srv, connection *con, plugin_data *p, break; } } - + tid = TK_VALUE; - + buffer_copy_string_len(token, t->input + t->offset, i); - + t->offset += i; t->line_pos += i; - + break; } } - + if (tid) { *token_id = tid; - + return 1; } else if (t->offset < t->size) { - log_error_write(srv, __FILE__, __LINE__, "sds", - "pos:", t->line_pos, + log_error_write(srv, __FILE__, __LINE__, "sds", + "pos:", t->line_pos, "foobar"); } return 0; @@ -275,50 +275,50 @@ int ssi_eval_expr(server *srv, connection *con, plugin_data *p, const char *expr buffer *token; ssi_ctx_t context; int ret; - + t.input = expr; t.offset = 0; t.size = strlen(expr); t.line_pos = 1; - + t.in_key = 1; t.in_brace = 0; t.in_cond = 0; - + context.ok = 1; context.srv = srv; - + /* default context */ - + pParser = ssiexprparserAlloc( malloc ); token = buffer_init(); while((1 == (ret = ssi_expr_tokenizer(srv, con, p, &t, &token_id, token))) && context.ok) { ssiexprparser(pParser, token_id, token, &context); - + token = buffer_init(); } ssiexprparser(pParser, 0, token, &context); ssiexprparserFree(pParser, free ); - + buffer_free(token); - + if (ret == -1) { - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "expr parser failed"); return -1; } - + if (context.ok == 0) { - log_error_write(srv, __FILE__, __LINE__, "sds", - "pos:", t.line_pos, + log_error_write(srv, __FILE__, __LINE__, "sds", + "pos:", t.line_pos, "parser failed somehow near here"); return -1; } #if 0 - log_error_write(srv, __FILE__, __LINE__, "ssd", + log_error_write(srv, __FILE__, __LINE__, "ssd", "expr: ", expr, context.val.bo); -#endif +#endif return context.val.bo; } diff --git a/src/mod_ssi_expr.h b/src/mod_ssi_expr.h index b484f78..2d3ae8b 100644 --- a/src/mod_ssi_expr.h +++ b/src/mod_ssi_expr.h @@ -5,16 +5,16 @@ typedef struct { enum { SSI_TYPE_UNSET, SSI_TYPE_BOOL, SSI_TYPE_STRING } type; - + buffer *str; int bo; } ssi_val_t; typedef struct { int ok; - + ssi_val_t val; - + void *srv; } ssi_ctx_t; diff --git a/src/mod_ssi_exprparser.c b/src/mod_ssi_exprparser.c index 65ec4dc..d049e9a 100644 --- a/src/mod_ssi_exprparser.c +++ b/src/mod_ssi_exprparser.c @@ -18,10 +18,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. */ @@ -38,7 +38,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 @@ -47,7 +47,7 @@ ** and nonterminal numbers. "unsigned char" is ** used if there are fewer than 250 rules and ** states combined. "int" is used otherwise. -** ssiexprparserTOKENTYPE is the data type used for minor tokens given +** ssiexprparserTOKENTYPE 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 @@ -91,7 +91,7 @@ typedef union { /* 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 @@ -116,7 +116,7 @@ typedef union { ** 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 @@ -168,7 +168,7 @@ static YYACTIONTYPE yy_default[] = { /* 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, @@ -219,10 +219,10 @@ static char *yyTracePrompt = 0; #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: ** <ul> @@ -247,7 +247,7 @@ void ssiexprparserTrace(FILE *TraceFILE, char *zTracePrompt){ #ifndef NDEBUG /* For tracing shifts, the names of all terminals and nonterminals ** are required. The following table supplies these names */ -static const char *yyTokenName[] = { +static const char *yyTokenName[] = { "$", "AND", "OR", "EQ", "NE", "GT", "GE", "LT", "LE", "NOT", "LPARAN", "RPARAN", @@ -295,7 +295,7 @@ const char *ssiexprparserTokenName(int tokenType){ #endif } -/* +/* ** This function allocates a new parser. ** The only argument is a pointer to a function which works like ** malloc. @@ -326,7 +326,7 @@ static void yy_destructor(YYCODETYPE yymajor, YYMINORTYPE *yypminor){ /* Here is inserted the actions which take place when a ** terminal or non-terminal is destroyed. This can happen ** when the symbol is popped from the stack during a - ** reduce or during error processing or when a parser is + ** reduce or during error processing or when a parser is ** being destroyed before it is finished parsing. ** ** Note: during a reduce, the only symbols destroyed are those @@ -379,7 +379,7 @@ static int yy_pop_parser_stack(yyParser *pParser){ return yymajor; } -/* +/* ** Deallocate and destroy a parser. Destructors are all called for ** all stack elements before shutting the parser down. ** @@ -415,7 +415,7 @@ static int yy_find_shift_action( ){ int i; int stateno = pParser->yystack[pParser->yyidx].stateno; - + /* if( pParser->yyidx<0 ) return YY_NO_ACTION; */ i = yy_shift_ofst[stateno]; if( i==YY_SHIFT_USE_DFLT ){ @@ -459,7 +459,7 @@ static int yy_find_reduce_action( ){ int i; int stateno = pParser->yystack[pParser->yyidx].stateno; - + i = yy_reduce_ofst[stateno]; if( i==YY_REDUCE_USE_DFLT ){ return yy_default[stateno]; @@ -559,7 +559,7 @@ static void yy_reduce( ssiexprparserARG_FETCH; yymsp = &yypParser->yystack[yypParser->yyidx]; #ifndef NDEBUG - if( yyTraceFILE && yyruleno>=0 + if( yyTraceFILE && yyruleno>=0 && yyruleno<sizeof(yyRuleName)/sizeof(yyRuleName[0]) ){ fprintf(yyTraceFILE, "%sReduce [%s].\n", yyTracePrompt, yyRuleName[yyruleno]); @@ -580,7 +580,7 @@ static void yy_reduce( { ctx->val.bo = ssi_val_tobool(yymsp[0].minor.yy29); ctx->val.type = SSI_TYPE_BOOL; - + ssi_val_free(yymsp[0].minor.yy29); } #line 586 "mod_ssi_exprparser.c" @@ -589,16 +589,16 @@ static void yy_reduce( #line 38 "./mod_ssi_exprparser.y" { int cmp; - - if (yymsp[-2].minor.yy29->type == SSI_TYPE_STRING && + + if (yymsp[-2].minor.yy29->type == SSI_TYPE_STRING && yymsp[0].minor.yy29->type == SSI_TYPE_STRING) { cmp = strcmp(yymsp[-2].minor.yy29->str->ptr, yymsp[0].minor.yy29->str->ptr); } else { cmp = ssi_val_tobool(yymsp[-2].minor.yy29) - ssi_val_tobool(yymsp[0].minor.yy29); } - + yygotominor.yy29 = yymsp[-2].minor.yy29; - + switch(yymsp[-1].minor.yy8) { case SSI_COND_EQ: yygotominor.yy29->bo = (cmp == 0) ? 1 : 0; break; case SSI_COND_NE: yygotominor.yy29->bo = (cmp != 0) ? 1 : 0; break; @@ -607,9 +607,9 @@ static void yy_reduce( case SSI_COND_LE: yygotominor.yy29->bo = (cmp <= 0) ? 1 : 0; break; case SSI_COND_LT: yygotominor.yy29->bo = (cmp < 0) ? 1 : 0; break; } - + yygotominor.yy29->type = SSI_TYPE_BOOL; - + ssi_val_free(yymsp[0].minor.yy29); } #line 615 "mod_ssi_exprparser.c" @@ -625,9 +625,9 @@ static void yy_reduce( #line 66 "./mod_ssi_exprparser.y" { int e; - + e = ssi_val_tobool(yymsp[-2].minor.yy29) && ssi_val_tobool(yymsp[0].minor.yy29); - + yygotominor.yy29 = yymsp[-2].minor.yy29; yygotominor.yy29->bo = e; yygotominor.yy29->type = SSI_TYPE_BOOL; @@ -640,9 +640,9 @@ static void yy_reduce( #line 77 "./mod_ssi_exprparser.y" { int e; - + e = ssi_val_tobool(yymsp[-2].minor.yy29) || ssi_val_tobool(yymsp[0].minor.yy29); - + yygotominor.yy29 = yymsp[-2].minor.yy29; yygotominor.yy29->bo = e; yygotominor.yy29->type = SSI_TYPE_BOOL; @@ -655,9 +655,9 @@ static void yy_reduce( #line 88 "./mod_ssi_exprparser.y" { int e; - + e = !ssi_val_tobool(yymsp[0].minor.yy29); - + yygotominor.yy29 = yymsp[0].minor.yy29; yygotominor.yy29->bo = e; yygotominor.yy29->type = SSI_TYPE_BOOL; @@ -872,7 +872,7 @@ void ssiexprparser( #ifdef YYERRORSYMBOL /* A syntax error has occurred. ** The response to an error depends upon whether or not the - ** grammar defines an error token "ERROR". + ** grammar defines an error token "ERROR". ** ** This is what we do if the grammar does define ERROR: ** diff --git a/src/mod_ssi_exprparser.y b/src/mod_ssi_exprparser.y index c123941..ac993d7 100644 --- a/src/mod_ssi_exprparser.y +++ b/src/mod_ssi_exprparser.y @@ -31,22 +31,22 @@ input ::= exprline(B). { ctx->val.bo = ssi_val_tobool(B); ctx->val.type = SSI_TYPE_BOOL; - + ssi_val_free(B); } exprline(A) ::= expr(B) cond(C) expr(D). { int cmp; - - if (B->type == SSI_TYPE_STRING && + + if (B->type == SSI_TYPE_STRING && D->type == SSI_TYPE_STRING) { cmp = strcmp(B->str->ptr, D->str->ptr); } else { cmp = ssi_val_tobool(B) - ssi_val_tobool(D); } - + A = B; - + switch(C) { case SSI_COND_EQ: A->bo = (cmp == 0) ? 1 : 0; break; case SSI_COND_NE: A->bo = (cmp != 0) ? 1 : 0; break; @@ -55,9 +55,9 @@ exprline(A) ::= expr(B) cond(C) expr(D). { case SSI_COND_LE: A->bo = (cmp <= 0) ? 1 : 0; break; case SSI_COND_LT: A->bo = (cmp < 0) ? 1 : 0; break; } - + A->type = SSI_TYPE_BOOL; - + ssi_val_free(D); } exprline(A) ::= expr(B). { @@ -65,9 +65,9 @@ exprline(A) ::= expr(B). { } expr(A) ::= expr(B) AND expr(C). { int e; - + e = ssi_val_tobool(B) && ssi_val_tobool(C); - + A = B; A->bo = e; A->type = SSI_TYPE_BOOL; @@ -76,9 +76,9 @@ expr(A) ::= expr(B) AND expr(C). { expr(A) ::= expr(B) OR expr(C). { int e; - + e = ssi_val_tobool(B) || ssi_val_tobool(C); - + A = B; A->bo = e; A->type = SSI_TYPE_BOOL; @@ -87,9 +87,9 @@ expr(A) ::= expr(B) OR expr(C). { expr(A) ::= NOT expr(B). { int e; - + e = !ssi_val_tobool(B); - + A = B; A->bo = e; A->type = SSI_TYPE_BOOL; diff --git a/src/mod_staticfile.c b/src/mod_staticfile.c index f5308cd..35dd279 100644 --- a/src/mod_staticfile.c +++ b/src/mod_staticfile.c @@ -16,7 +16,7 @@ /** * this is a staticfile for a lighttpd plugin - * + * */ @@ -29,48 +29,48 @@ typedef struct { typedef struct { PLUGIN_DATA; - + buffer *range_buf; - + plugin_config **config_storage; - - plugin_config conf; + + plugin_config conf; } plugin_data; /* init the plugin data */ INIT_FUNC(mod_staticfile_init) { plugin_data *p; - + p = calloc(1, sizeof(*p)); - + p->range_buf = buffer_init(); - + return p; } /* detroy the plugin data */ FREE_FUNC(mod_staticfile_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]; - + array_free(s->exclude_ext); - + free(s); } free(p->config_storage); } buffer_free(p->range_buf); - + free(p); - + return HANDLER_GO_ON; } @@ -79,31 +79,31 @@ FREE_FUNC(mod_staticfile_free) { SETDEFAULTS_FUNC(mod_staticfile_set_defaults) { plugin_data *p = p_d; size_t i = 0; - - config_values_t cv[] = { + + config_values_t cv[] = { { "static-file.exclude-extensions", 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)); s->exclude_ext = array_init(); - + cv[0].destination = s->exclude_ext; - + 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; } @@ -112,27 +112,27 @@ SETDEFAULTS_FUNC(mod_staticfile_set_defaults) { static int mod_staticfile_patch_connection(server *srv, connection *con, plugin_data *p) { size_t i, j; plugin_config *s = p->config_storage[0]; - + PATCH(exclude_ext); - + /* 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("static-file.exclude-extensions"))) { PATCH(exclude_ext); } } } - + return 0; } #undef PATCH @@ -146,69 +146,69 @@ static int http_response_parse_range(server *srv, connection *con, plugin_data * data_string *ds; stat_cache_entry *sce = NULL; buffer *content_type = NULL; - + if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) { SEGFAULT(); } - + start = 0; end = sce->st.st_size - 1; - + con->response.content_length = 0; - + if (NULL != (ds = (data_string *)array_get_element(con->response.headers, "Content-Type"))) { content_type = ds->value; } - + for (s = con->request.http_range, error = 0; !error && *s && NULL != (minus = strchr(s, '-')); ) { char *err; off_t la, le; - + if (s == minus) { /* -<stop> */ - + le = strtoll(s, &err, 10); - + if (le == 0) { /* RFC 2616 - 14.35.1 */ - + con->http_status = 416; error = 1; } else if (*err == '\0') { /* end */ s = err; - + end = sce->st.st_size - 1; start = sce->st.st_size + le; } else if (*err == ',') { multipart = 1; s = err + 1; - + end = sce->st.st_size - 1; start = sce->st.st_size + le; } else { error = 1; } - + } else if (*(minus+1) == '\0' || *(minus+1) == ',') { /* <start>- */ - + la = strtoll(s, &err, 10); - + if (err == minus) { /* ok */ - + if (*(err + 1) == '\0') { s = err + 1; - + end = sce->st.st_size - 1; start = la; - + } else if (*(err + 1) == ',') { multipart = 1; s = err + 2; - + end = sce->st.st_size - 1; start = la; } else { @@ -220,64 +220,64 @@ static int http_response_parse_range(server *srv, connection *con, plugin_data * } } else { /* <start>-<stop> */ - + la = strtoll(s, &err, 10); - + if (err == minus) { le = strtoll(minus+1, &err, 10); - + /* RFC 2616 - 14.35.1 */ if (la > le) { error = 1; } - + if (*err == '\0') { /* ok, end*/ s = err; - + end = le; start = la; } else if (*err == ',') { multipart = 1; s = err + 1; - + end = le; start = la; } else { /* error */ - + error = 1; } } else { /* error */ - + error = 1; } } - + if (!error) { if (start < 0) start = 0; - + /* RFC 2616 - 14.35.1 */ if (end > sce->st.st_size - 1) end = sce->st.st_size - 1; - + if (start > sce->st.st_size - 1) { error = 1; - + con->http_status = 416; } } - + if (!error) { if (multipart) { /* write boundary-header */ buffer *b; - + b = chunkqueue_get_append_buffer(con->write_queue); - + buffer_copy_string(b, "\r\n--"); buffer_append_string(b, boundary); - + /* write Content-Range */ buffer_append_string(b, "\r\nContent-Range: bytes "); buffer_append_off_t(b, start); @@ -285,54 +285,54 @@ static int http_response_parse_range(server *srv, connection *con, plugin_data * buffer_append_off_t(b, end); buffer_append_string(b, "/"); buffer_append_off_t(b, sce->st.st_size); - + buffer_append_string(b, "\r\nContent-Type: "); buffer_append_string_buffer(b, content_type); - + /* write END-OF-HEADER */ buffer_append_string(b, "\r\n\r\n"); - + con->response.content_length += b->used - 1; - + } - + chunkqueue_append_file(con->write_queue, con->physical.path, start, end - start + 1); con->response.content_length += end - start + 1; } } - + /* something went wrong */ if (error) return -1; - + if (multipart) { /* add boundary end */ buffer *b; - + b = chunkqueue_get_append_buffer(con->write_queue); - + buffer_copy_string_len(b, "\r\n--", 4); buffer_append_string(b, boundary); buffer_append_string_len(b, "--\r\n", 4); - + con->response.content_length += b->used - 1; - + /* set header-fields */ - + buffer_copy_string(p->range_buf, "multipart/byteranges; boundary="); buffer_append_string(p->range_buf, boundary); - + /* overwrite content-type */ response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(p->range_buf)); } else { /* add Content-Range-header */ - + buffer_copy_string(p->range_buf, "bytes "); buffer_append_off_t(p->range_buf, start); buffer_append_string(p->range_buf, "-"); buffer_append_off_t(p->range_buf, end); buffer_append_string(p->range_buf, "/"); buffer_append_off_t(p->range_buf, sce->st.st_size); - + response_header_insert(srv, con, CONST_STR_LEN("Content-Range"), CONST_BUF_LEN(p->range_buf)); } @@ -347,12 +347,12 @@ URIHANDLER_FUNC(mod_staticfile_subrequest) { stat_cache_entry *sce = NULL; buffer *mtime; data_string *ds; - + /* someone else has done a decision for us */ if (con->http_status != 0) return HANDLER_GO_ON; if (con->uri.path->used == 0) return HANDLER_GO_ON; if (con->physical.path->used == 0) return HANDLER_GO_ON; - + /* someone else has handled this request */ if (con->mode != DIRECT) return HANDLER_GO_ON; @@ -365,42 +365,42 @@ URIHANDLER_FUNC(mod_staticfile_subrequest) { default: return HANDLER_GO_ON; } - + mod_staticfile_patch_connection(srv, con, p); - + s_len = con->uri.path->used - 1; - + /* ignore certain extensions */ for (k = 0; k < p->conf.exclude_ext->used; k++) { - ds = (data_string *)p->conf.exclude_ext->data[k]; - + ds = (data_string *)p->conf.exclude_ext->data[k]; + if (ds->value->used == 0) continue; if (buffer_is_equal_right_len(con->physical.path, ds->value, ds->value->used - 1)) { return HANDLER_GO_ON; } } - + if (con->conf.log_request_handling) { log_error_write(srv, __FILE__, __LINE__, "s", "-- handling file as static file"); } - + if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) { con->http_status = 403; - + log_error_write(srv, __FILE__, __LINE__, "sbsb", "not a regular file:", con->uri.path, "->", con->physical.path); - + return HANDLER_FINISHED; } - + /* we only handline regular files */ #ifdef HAVE_LSTAT if ((sce->is_symlink == 1) && !con->conf.follow_symlink) { con->http_status = 403; - + if (con->conf.log_request_handling) { log_error_write(srv, __FILE__, __LINE__, "s", "-- access denied due symlink restriction"); log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path); @@ -412,18 +412,18 @@ URIHANDLER_FUNC(mod_staticfile_subrequest) { #endif if (!S_ISREG(sce->st.st_mode)) { con->http_status = 404; - + if (con->conf.log_file_not_found) { log_error_write(srv, __FILE__, __LINE__, "sbsb", "not a regular file:", con->uri.path, "->", sce->name); } - + return HANDLER_FINISHED; } /* mod_compress might set several data directly, don't overwrite them */ - + /* set response content-type, if not set already */ if (NULL == array_get_element(con->response.headers, "Content-Type")) { @@ -433,15 +433,15 @@ URIHANDLER_FUNC(mod_staticfile_subrequest) { response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(sce->content_type)); } } - + if (NULL == array_get_element(con->response.headers, "ETag")) { /* generate e-tag */ etag_mutate(con->physical.etag, sce->etag); - + response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag)); } response_header_overwrite(srv, con, CONST_STR_LEN("Accept-Ranges"), CONST_STR_LEN("bytes")); - + /* prepare header */ if (NULL == (ds = (data_string *)array_get_element(con->response.headers, "Last-Modified"))) { mtime = strftime_cache_get(srv, sce->st.st_mtime); @@ -457,34 +457,34 @@ URIHANDLER_FUNC(mod_staticfile_subrequest) { /* check if we have a conditional GET */ if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If-Range"))) { - /* if the value is the same as our ETag, we do a Range-request, + /* if the value is the same as our ETag, we do a Range-request, * otherwise a full 200 */ if (!buffer_is_equal(ds->value, con->physical.etag)) { do_range_request = 0; } } - + if (do_range_request) { /* content prepared, I'm done */ con->file_finished = 1; - + if (0 == http_response_parse_range(srv, con, p)) { con->http_status = 206; } return HANDLER_FINISHED; } } - + /* if we are still here, prepare body */ - - /* we add it here for all requests - * the HEAD request will drop it afterwards again + + /* we add it here for all requests + * the HEAD request will drop it afterwards again */ http_chunk_append_file(srv, con, con->physical.path, 0, sce->st.st_size); - + con->file_finished = 1; - + return HANDLER_FINISHED; } @@ -493,13 +493,13 @@ URIHANDLER_FUNC(mod_staticfile_subrequest) { int mod_staticfile_plugin_init(plugin *p) { p->version = LIGHTTPD_VERSION_ID; p->name = buffer_init_string("staticfile"); - + p->init = mod_staticfile_init; p->handle_subrequest_start = mod_staticfile_subrequest; p->set_defaults = mod_staticfile_set_defaults; p->cleanup = mod_staticfile_free; - + p->data = NULL; - + return 0; } diff --git a/src/mod_status.c b/src/mod_status.c index f5a35e9..2a4003a 100644 --- a/src/mod_status.c +++ b/src/mod_status.c @@ -29,114 +29,114 @@ typedef struct { typedef struct { PLUGIN_DATA; - + double traffic_out; double requests; - + double mod_5s_traffic_out[5]; double mod_5s_requests[5]; size_t mod_5s_ndx; - + double rel_traffic_out; double rel_requests; - + double abs_traffic_out; double abs_requests; - + double bytes_written; - + buffer *module_list; - + plugin_config **config_storage; - - plugin_config conf; + + plugin_config conf; } plugin_data; INIT_FUNC(mod_status_init) { plugin_data *p; size_t i; - + p = calloc(1, sizeof(*p)); - + p->traffic_out = p->requests = 0; p->rel_traffic_out = p->rel_requests = 0; p->abs_traffic_out = p->abs_requests = 0; p->bytes_written = 0; p->module_list = buffer_init(); - + for (i = 0; i < 5; i++) { p->mod_5s_traffic_out[i] = p->mod_5s_requests[i] = 0; } - + return p; } FREE_FUNC(mod_status_free) { plugin_data *p = p_d; - + UNUSED(srv); if (!p) return HANDLER_GO_ON; - + buffer_free(p->module_list); - + 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->status_url); buffer_free(s->statistics_url); buffer_free(s->config_url); - + free(s); } free(p->config_storage); } - - + + free(p); - + return HANDLER_GO_ON; } SETDEFAULTS_FUNC(mod_status_set_defaults) { plugin_data *p = p_d; size_t i; - - config_values_t cv[] = { + + config_values_t cv[] = { { "status.status-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, { "status.config-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, { "status.enable-sort", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, { "status.statistics-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, { 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->config_url = buffer_init(); s->status_url = buffer_init(); s->sort = 1; s->statistics_url = buffer_init(); - + cv[0].destination = s->status_url; cv[1].destination = s->config_url; cv[2].destination = &(s->sort); cv[3].destination = s->statistics_url; - + 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; } @@ -151,7 +151,7 @@ static int mod_status_row_append(buffer *b, const char *key, const char *value) buffer_append_string(b, value); BUFFER_APPEND_STRING_CONST(b, "</td>\n"); BUFFER_APPEND_STRING_CONST(b, " </tr>\n"); - + return 0; } @@ -161,29 +161,29 @@ static int mod_status_header_append(buffer *b, const char *key) { buffer_append_string(b, key); BUFFER_APPEND_STRING_CONST(b, "</th>\n"); BUFFER_APPEND_STRING_CONST(b, " </tr>\n"); - + return 0; } static int mod_status_header_append_sort(buffer *b, void *p_d, const char* key) { plugin_data *p = p_d; - + if (p->conf.sort) { BUFFER_APPEND_STRING_CONST(b, "<th class=\"status\"><a href=\"#\" class=\"sortheader\" onclick=\"resort(this);return false;\">"); buffer_append_string(b, key); - BUFFER_APPEND_STRING_CONST(b, "<span class=\"sortarrow\"></span></a></th>\n"); + BUFFER_APPEND_STRING_CONST(b, "<span class=\"sortarrow\">:</span></a></th>\n"); } else { BUFFER_APPEND_STRING_CONST(b, "<th class=\"status\">"); buffer_append_string(b, key); BUFFER_APPEND_STRING_CONST(b, "</th>\n"); } - + return 0; } static int mod_status_get_multiplier(double *avg, char *multiplier, int size) { *multiplier = ' '; - + if (*avg > size) { *avg /= size; *multiplier = 'k'; } if (*avg > size) { *avg /= size; *multiplier = 'M'; } if (*avg > size) { *avg /= size; *multiplier = 'G'; } @@ -204,19 +204,19 @@ static handler_t mod_status_handle_server_status_html(server *srv, connection *c char multiplier = '\0'; char buf[32]; time_t ts; - + int days, hours, mins, seconds; - + b = chunkqueue_get_append_buffer(con->write_queue); - BUFFER_COPY_STRING_CONST(b, + BUFFER_COPY_STRING_CONST(b, "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n" "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n" " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n" "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">\n" " <head>\n" " <title>Status</title>\n"); - + BUFFER_APPEND_STRING_CONST(b, " <style type=\"text/css\">\n" " table.status { border: black solid thin; }\n" @@ -226,14 +226,14 @@ static handler_t mod_status_handle_server_status_html(server *srv, connection *c " a.sortheader { background-color: black; color: white; font-weight: bold; text-decoration: none; display: block; }\n" " span.sortarrow { color: white; text-decoration: none; }\n" " </style>\n"); - + if (p->conf.sort) { BUFFER_APPEND_STRING_CONST(b, "<script type=\"text/javascript\">\n" "// <!--\n" "var sort_column;\n" "var prev_span = null;\n"); - + BUFFER_APPEND_STRING_CONST(b, "function get_inner_text(el) {\n" " if((typeof el == 'string')||(typeof el == 'undefined'))\n" @@ -251,7 +251,7 @@ static handler_t mod_status_handle_server_status_html(server *srv, connection *c " }\n" " return str;\n" "}\n"); - + BUFFER_APPEND_STRING_CONST(b, "function sortfn(a,b) {\n" " var at = get_inner_text(a.cells[sort_column]);\n" @@ -266,7 +266,7 @@ static handler_t mod_status_handle_server_status_html(server *srv, connection *c " else return 1;\n" " }\n" "}\n"); - + BUFFER_APPEND_STRING_CONST(b, "function resort(lnk) {\n" " var span = lnk.childNodes[1];\n" @@ -276,7 +276,7 @@ static handler_t mod_status_handle_server_status_html(server *srv, connection *c " rows[j-1] = table.rows[j];\n" " sort_column = lnk.parentNode.cellIndex;\n" " rows.sort(sortfn);\n"); - + BUFFER_APPEND_STRING_CONST(b, " if (prev_span != null) prev_span.innerHTML = '';\n" " if (span.getAttribute('sortdir')=='down') {\n" @@ -294,77 +294,77 @@ static handler_t mod_status_handle_server_status_html(server *srv, connection *c "// -->\n" "</script>\n"); } - - BUFFER_APPEND_STRING_CONST(b, + + BUFFER_APPEND_STRING_CONST(b, " </head>\n" " <body>\n"); - - - + + + /* connection listing */ BUFFER_APPEND_STRING_CONST(b, "<h1>Server-Status</h1>"); - - BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\">"); + + BUFFER_APPEND_STRING_CONST(b, "<table summary=\"status\" class=\"status\">"); BUFFER_APPEND_STRING_CONST(b, "<tr><td>Hostname</td><td class=\"string\">"); buffer_append_string_buffer(b, con->uri.authority); BUFFER_APPEND_STRING_CONST(b, " ("); buffer_append_string_buffer(b, con->server_name); BUFFER_APPEND_STRING_CONST(b, ")</td></tr>\n"); BUFFER_APPEND_STRING_CONST(b, "<tr><td>Uptime</td><td class=\"string\">"); - + ts = srv->cur_ts - srv->startup_ts; - + days = ts / (60 * 60 * 24); ts %= (60 * 60 * 24); - + hours = ts / (60 * 60); ts %= (60 * 60); - + mins = ts / (60); ts %= (60); - + seconds = ts; - + if (days) { buffer_append_long(b, days); BUFFER_APPEND_STRING_CONST(b, " days "); } - + if (hours) { buffer_append_long(b, hours); BUFFER_APPEND_STRING_CONST(b, " hours "); } - + if (mins) { buffer_append_long(b, mins); BUFFER_APPEND_STRING_CONST(b, " min "); } - + buffer_append_long(b, seconds); BUFFER_APPEND_STRING_CONST(b, " s"); - + BUFFER_APPEND_STRING_CONST(b, "</td></tr>\n"); BUFFER_APPEND_STRING_CONST(b, "<tr><td>Started at</td><td class=\"string\">"); - + ts = srv->startup_ts; - + strftime(buf, sizeof(buf) - 1, "%Y-%m-%d %H:%M:%S", localtime(&ts)); buffer_append_string(b, buf); BUFFER_APPEND_STRING_CONST(b, "</td></tr>\n"); - - + + BUFFER_APPEND_STRING_CONST(b, "<tr><th colspan=\"2\">absolute (since start)</th></tr>\n"); - + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\">"); avg = p->abs_requests; mod_status_get_multiplier(&avg, &multiplier, 1000); - + buffer_append_long(b, avg); BUFFER_APPEND_STRING_CONST(b, " "); if (multiplier) buffer_append_string_len(b, &multiplier, 1); BUFFER_APPEND_STRING_CONST(b, "req</td></tr>\n"); - + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\">"); avg = p->abs_traffic_out; @@ -379,7 +379,7 @@ static handler_t mod_status_handle_server_status_html(server *srv, connection *c BUFFER_APPEND_STRING_CONST(b, "<tr><th colspan=\"2\">average (since start)</th></tr>\n"); - + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\">"); avg = p->abs_requests / (srv->cur_ts - srv->startup_ts); @@ -389,7 +389,7 @@ static handler_t mod_status_handle_server_status_html(server *srv, connection *c BUFFER_APPEND_STRING_CONST(b, " "); if (multiplier) buffer_append_string_len(b, &multiplier, 1); BUFFER_APPEND_STRING_CONST(b, "req/s</td></tr>\n"); - + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\">"); avg = p->abs_traffic_out / (srv->cur_ts - srv->startup_ts); @@ -401,15 +401,15 @@ static handler_t mod_status_handle_server_status_html(server *srv, connection *c if (multiplier) buffer_append_string_len(b, &multiplier, 1); BUFFER_APPEND_STRING_CONST(b, "byte/s</td></tr>\n"); - - + + BUFFER_APPEND_STRING_CONST(b, "<tr><th colspan=\"2\">average (5s sliding average)</th></tr>\n"); for (j = 0, avg = 0; j < 5; j++) { avg += p->mod_5s_requests[j]; } - + avg /= 5; - + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Requests</td><td class=\"string\">"); mod_status_get_multiplier(&avg, &multiplier, 1000); @@ -417,15 +417,15 @@ static handler_t mod_status_handle_server_status_html(server *srv, connection *c buffer_append_long(b, avg); BUFFER_APPEND_STRING_CONST(b, " "); if (multiplier) buffer_append_string_len(b, &multiplier, 1); - + BUFFER_APPEND_STRING_CONST(b, "req/s</td></tr>\n"); - + for (j = 0, avg = 0; j < 5; j++) { avg += p->mod_5s_traffic_out[j]; } - + avg /= 5; - + BUFFER_APPEND_STRING_CONST(b, "<tr><td>Traffic</td><td class=\"string\">"); mod_status_get_multiplier(&avg, &multiplier, 1024); @@ -435,34 +435,34 @@ static handler_t mod_status_handle_server_status_html(server *srv, connection *c BUFFER_APPEND_STRING_CONST(b, " "); if (multiplier) buffer_append_string_len(b, &multiplier, 1); BUFFER_APPEND_STRING_CONST(b, "byte/s</td></tr>\n"); - + BUFFER_APPEND_STRING_CONST(b, "</table>\n"); - - + + BUFFER_APPEND_STRING_CONST(b, "<hr />\n<pre><b>legend</b>\n"); BUFFER_APPEND_STRING_CONST(b, ". = connect, C = close, E = hard error\n"); BUFFER_APPEND_STRING_CONST(b, "r = read, R = read-POST, W = write, h = handle-request\n"); BUFFER_APPEND_STRING_CONST(b, "q = request-start, Q = request-end\n"); BUFFER_APPEND_STRING_CONST(b, "s = response-start, S = response-end\n"); - + BUFFER_APPEND_STRING_CONST(b, "<b>"); buffer_append_long(b, srv->conns->used); BUFFER_APPEND_STRING_CONST(b, " connections</b>\n"); - + for (j = 0; j < srv->conns->used; j++) { connection *c = srv->conns->ptr[j]; const char *state = connection_get_short_state(c->state); - + buffer_append_string_len(b, state, 1); - + if (((j + 1) % 50) == 0) { BUFFER_APPEND_STRING_CONST(b, "\n"); } } - + BUFFER_APPEND_STRING_CONST(b, "\n</pre><hr />\n<h2>Connections</h2>\n"); - - BUFFER_APPEND_STRING_CONST(b, "<table class=\"status\">\n"); + + BUFFER_APPEND_STRING_CONST(b, "<table summary=\"status\" class=\"status\">\n"); BUFFER_APPEND_STRING_CONST(b, "<tr>"); mod_status_header_append_sort(b, p_d, "Client IP"); mod_status_header_append_sort(b, p_d, "Read"); @@ -473,16 +473,16 @@ static handler_t mod_status_handle_server_status_html(server *srv, connection *c mod_status_header_append_sort(b, p_d, "URI"); mod_status_header_append_sort(b, p_d, "File"); BUFFER_APPEND_STRING_CONST(b, "</tr>\n"); - + for (j = 0; j < srv->conns->used; j++) { connection *c = srv->conns->ptr[j]; - + BUFFER_APPEND_STRING_CONST(b, "<tr><td class=\"string\">"); - + buffer_append_string(b, inet_ntop_cache_get_ip(srv, &(c->dst_addr))); - + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int\">"); - + if (con->request.content_length) { buffer_append_long(b, c->request_content_queue->bytes_in); BUFFER_APPEND_STRING_CONST(b, "/"); @@ -490,55 +490,55 @@ static handler_t mod_status_handle_server_status_html(server *srv, connection *c } else { BUFFER_APPEND_STRING_CONST(b, "0/0"); } - + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int\">"); - + buffer_append_off_t(b, chunkqueue_written(c->write_queue)); BUFFER_APPEND_STRING_CONST(b, "/"); buffer_append_off_t(b, chunkqueue_length(c->write_queue)); - + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">"); - + buffer_append_string(b, connection_get_state(c->state)); - + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"int\">"); - + buffer_append_long(b, srv->cur_ts - c->request_start); - + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">"); - + if (buffer_is_empty(c->server_name)) { buffer_append_string_buffer(b, c->uri.authority); } else { buffer_append_string_buffer(b, c->server_name); } - + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">"); - + if (!buffer_is_empty(c->uri.path)) { buffer_append_string_encoded(b, CONST_BUF_LEN(c->uri.path), ENCODING_HTML); } - + BUFFER_APPEND_STRING_CONST(b, "</td><td class=\"string\">"); - + buffer_append_string_buffer(b, c->physical.path); - + BUFFER_APPEND_STRING_CONST(b, "</td></tr>\n"); } - - - BUFFER_APPEND_STRING_CONST(b, + + + BUFFER_APPEND_STRING_CONST(b, "</table>\n"); - - - BUFFER_APPEND_STRING_CONST(b, + + + BUFFER_APPEND_STRING_CONST(b, " </body>\n" "</html>\n" ); - + response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html")); - + return 0; } @@ -548,7 +548,7 @@ static handler_t mod_status_handle_server_status_text(server *srv, connection *c buffer *b; double avg; time_t ts; - + b = chunkqueue_get_append_buffer(con->write_queue); /* output total number of requests */ @@ -556,19 +556,19 @@ static handler_t mod_status_handle_server_status_text(server *srv, connection *c avg = p->abs_requests; buffer_append_long(b, avg); BUFFER_APPEND_STRING_CONST(b, "\n"); - + /* output total traffic out in kbytes */ BUFFER_APPEND_STRING_CONST(b, "Total kBytes: "); avg = p->abs_traffic_out / 1024; buffer_append_long(b, avg); BUFFER_APPEND_STRING_CONST(b, "\n"); - + /* output uptime */ BUFFER_APPEND_STRING_CONST(b, "Uptime: "); ts = srv->cur_ts - srv->startup_ts; buffer_append_long(b, ts); BUFFER_APPEND_STRING_CONST(b, "\n"); - + /* output busy servers */ BUFFER_APPEND_STRING_CONST(b, "BusyServers: "); buffer_append_long(b, srv->conns->used); @@ -577,13 +577,13 @@ static handler_t mod_status_handle_server_status_text(server *srv, connection *c /* set text/plain output */ response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/plain")); - + return 0; } static handler_t mod_status_handle_server_statistics(server *srv, connection *con, void *p_d) { plugin_data *p = p_d; - buffer *b, *m = p->module_list; + buffer *b = p->module_list; size_t i; array *st = srv->status; @@ -591,10 +591,10 @@ static handler_t mod_status_handle_server_statistics(server *srv, connection *co /* we have nothing to send */ con->http_status = 204; con->file_finished = 1; - + return HANDLER_FINISHED; } - + b = chunkqueue_get_append_buffer(con->write_queue); for (i = 0; i < st->used; i++) { @@ -605,27 +605,27 @@ static handler_t mod_status_handle_server_statistics(server *srv, connection *co buffer_append_long(b, ((data_integer *)(st->data[ndx]))->value); buffer_append_string(b, "\n"); } - + response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/plain")); - + con->http_status = 200; con->file_finished = 1; - + return HANDLER_FINISHED; } static handler_t mod_status_handle_server_status(server *srv, connection *con, void *p_d) { - + if (buffer_is_equal_string(con->uri.query, CONST_STR_LEN("auto"))) { mod_status_handle_server_status_text(srv, con, p_d); } else { mod_status_handle_server_status_html(srv, con, p_d); } - + con->http_status = 200; con->file_finished = 1; - + return HANDLER_FINISHED; } @@ -634,9 +634,9 @@ static handler_t mod_status_handle_server_config(server *srv, connection *con, v plugin_data *p = p_d; buffer *b, *m = p->module_list; size_t i; - - struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] = - { + + struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] = + { /* - poll is most reliable * - select works everywhere * - linux-* are experimental @@ -661,10 +661,10 @@ static handler_t mod_status_handle_server_config(server *srv, connection *con, v #endif { FDEVENT_HANDLER_UNSET, NULL } }; - + b = chunkqueue_get_append_buffer(con->write_queue); - - BUFFER_COPY_STRING_CONST(b, + + BUFFER_COPY_STRING_CONST(b, "<?xml version=\"1.0\" encoding=\"iso-8859-1\"?>\n" "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n" " \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n" @@ -674,8 +674,8 @@ static handler_t mod_status_handle_server_config(server *srv, connection *con, v " </head>\n" " <body>\n" " <h1>" PACKAGE_NAME " " PACKAGE_VERSION "</h1>\n" - " <table border=\"1\">\n"); - + " <table summary=\"status\" border=\"1\">\n"); + mod_status_header_append(b, "Server-Features"); #ifdef HAVE_PCRE_H mod_status_row_append(b, "RegEx Conditionals", "enabled"); @@ -683,21 +683,21 @@ static handler_t mod_status_handle_server_config(server *srv, connection *con, v mod_status_row_append(b, "RegEx Conditionals", "disabled - pcre missing"); #endif mod_status_header_append(b, "Network Engine"); - + for (i = 0; event_handlers[i].name; i++) { if (event_handlers[i].et == srv->event_handler) { mod_status_row_append(b, "fd-Event-Handler", event_handlers[i].name); break; } } - + mod_status_header_append(b, "Config-File-Settings"); - + for (i = 0; i < srv->plugins.used; i++) { plugin **ps = srv->plugins.ptr; - + plugin *pl = ps[i]; - + if (i == 0) { buffer_copy_string_buffer(m, pl->name); } else { @@ -705,21 +705,21 @@ static handler_t mod_status_handle_server_config(server *srv, connection *con, v buffer_append_string_buffer(m, pl->name); } } - + mod_status_row_append(b, "Loaded Modules", m->ptr); - + BUFFER_APPEND_STRING_CONST(b, " </table>\n"); - - BUFFER_APPEND_STRING_CONST(b, + + BUFFER_APPEND_STRING_CONST(b, " </body>\n" "</html>\n" ); - + response_header_overwrite(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html")); - + con->http_status = 200; con->file_finished = 1; - + return HANDLER_FINISHED; } @@ -728,24 +728,24 @@ static handler_t mod_status_handle_server_config(server *srv, connection *con, v static int mod_status_patch_connection(server *srv, connection *con, plugin_data *p) { size_t i, j; plugin_config *s = p->config_storage[0]; - + PATCH(status_url); PATCH(config_url); PATCH(sort); PATCH(statistics_url); - + /* 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("status.status-url"))) { PATCH(status_url); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.config-url"))) { @@ -754,88 +754,88 @@ static int mod_status_patch_connection(server *srv, connection *con, plugin_data PATCH(sort); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("status.statistics-url"))) { PATCH(statistics_url); - } + } } } - + return 0; } static handler_t mod_status_handler(server *srv, connection *con, void *p_d) { plugin_data *p = p_d; - + mod_status_patch_connection(srv, con, p); - - if (!buffer_is_empty(p->conf.status_url) && + + if (!buffer_is_empty(p->conf.status_url) && buffer_is_equal(p->conf.status_url, con->uri.path)) { return mod_status_handle_server_status(srv, con, p_d); - } else if (!buffer_is_empty(p->conf.config_url) && + } else if (!buffer_is_empty(p->conf.config_url) && buffer_is_equal(p->conf.config_url, con->uri.path)) { return mod_status_handle_server_config(srv, con, p_d); - } else if (!buffer_is_empty(p->conf.statistics_url) && + } else if (!buffer_is_empty(p->conf.statistics_url) && buffer_is_equal(p->conf.statistics_url, con->uri.path)) { return mod_status_handle_server_statistics(srv, con, p_d); } - + return HANDLER_GO_ON; } TRIGGER_FUNC(mod_status_trigger) { plugin_data *p = p_d; size_t i; - + /* check all connections */ for (i = 0; i < srv->conns->used; i++) { connection *c = srv->conns->ptr[i]; - + p->bytes_written += c->bytes_written_cur_second; } - + /* a sliding average */ p->mod_5s_traffic_out[p->mod_5s_ndx] = p->bytes_written; p->mod_5s_requests [p->mod_5s_ndx] = p->requests; - + p->mod_5s_ndx = (p->mod_5s_ndx+1) % 5; - + p->abs_traffic_out += p->bytes_written; p->rel_traffic_out += p->bytes_written; - + p->bytes_written = 0; - + /* reset storage - second */ p->traffic_out = 0; p->requests = 0; - + return HANDLER_GO_ON; } REQUESTDONE_FUNC(mod_status_account) { plugin_data *p = p_d; - + UNUSED(srv); p->requests++; p->rel_requests++; p->abs_requests++; - + p->bytes_written += con->bytes_written_cur_second; - + return HANDLER_GO_ON; } int mod_status_plugin_init(plugin *p) { p->version = LIGHTTPD_VERSION_ID; p->name = buffer_init_string("status"); - + p->init = mod_status_init; p->cleanup = mod_status_free; p->set_defaults= mod_status_set_defaults; - + p->handle_uri_clean = mod_status_handler; p->handle_trigger = mod_status_trigger; p->handle_request_done = mod_status_account; - + p->data = NULL; - + return 0; } diff --git a/src/mod_trigger_b4_dl.c b/src/mod_trigger_b4_dl.c index 8281ec0..bc49b1e 100644 --- a/src/mod_trigger_b4_dl.c +++ b/src/mod_trigger_b4_dl.c @@ -24,18 +24,18 @@ /** * this is a trigger_b4_dl for a lighttpd plugin - * + * */ /* plugin config for all request/connections */ typedef struct { buffer *db_filename; - + buffer *trigger_url; buffer *download_url; buffer *deny_url; - + array *mc_hosts; buffer *mc_namespace; #if defined(HAVE_PCRE_H) @@ -46,58 +46,58 @@ typedef struct { GDBM_FILE db; #endif -#if defined(HAVE_MEMCACHE_H) +#if defined(HAVE_MEMCACHE_H) struct memcache *mc; #endif - + unsigned short trigger_timeout; unsigned short debug; } plugin_config; typedef struct { PLUGIN_DATA; - + buffer *tmp_buf; - + plugin_config **config_storage; - - plugin_config conf; + + plugin_config conf; } plugin_data; /* init the plugin data */ INIT_FUNC(mod_trigger_b4_dl_init) { plugin_data *p; - + p = calloc(1, sizeof(*p)); - + p->tmp_buf = buffer_init(); - + return p; } /* detroy the plugin data */ FREE_FUNC(mod_trigger_b4_dl_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]; if (!s) continue; - + buffer_free(s->db_filename); buffer_free(s->download_url); buffer_free(s->trigger_url); buffer_free(s->deny_url); - + buffer_free(s->mc_namespace); array_free(s->mc_hosts); - + #if defined(HAVE_PCRE_H) if (s->trigger_regex) pcre_free(s->trigger_regex); if (s->download_regex) pcre_free(s->download_regex); @@ -108,16 +108,16 @@ FREE_FUNC(mod_trigger_b4_dl_free) { #if defined(HAVE_MEMCACHE_H) if (s->mc) mc_free(s->mc); #endif - + free(s); } free(p->config_storage); } - + buffer_free(p->tmp_buf); - + free(p); - + return HANDLER_GO_ON; } @@ -126,9 +126,9 @@ FREE_FUNC(mod_trigger_b4_dl_free) { SETDEFAULTS_FUNC(mod_trigger_b4_dl_set_defaults) { plugin_data *p = p_d; size_t i = 0; - - - config_values_t cv[] = { + + + config_values_t cv[] = { { "trigger-before-download.gdbm-filename", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ { "trigger-before-download.trigger-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 1 */ { "trigger-before-download.download-url", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */ @@ -139,18 +139,18 @@ SETDEFAULTS_FUNC(mod_trigger_b4_dl_set_defaults) { { "trigger-before-download.debug", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 7 */ { 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; #if defined(HAVE_PCRE_H) const char *errptr; int erroff; #endif - + s = calloc(1, sizeof(plugin_config)); s->db_filename = buffer_init(); s->download_url = buffer_init(); @@ -158,7 +158,7 @@ SETDEFAULTS_FUNC(mod_trigger_b4_dl_set_defaults) { s->deny_url = buffer_init(); s->mc_hosts = array_init(); s->mc_namespace = buffer_init(); - + cv[0].destination = s->db_filename; cv[1].destination = s->trigger_url; cv[2].destination = s->download_url; @@ -167,41 +167,41 @@ SETDEFAULTS_FUNC(mod_trigger_b4_dl_set_defaults) { cv[5].destination = s->mc_hosts; cv[6].destination = s->mc_namespace; cv[7].destination = &(s->debug); - + 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 defined(HAVE_GDBM_H) if (!buffer_is_empty(s->db_filename)) { if (NULL == (s->db = gdbm_open(s->db_filename->ptr, 4096, GDBM_WRCREAT | GDBM_NOLOCK, S_IRUSR | S_IWUSR, 0))) { - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "gdbm-open failed"); return HANDLER_ERROR; } } #endif -#if defined(HAVE_PCRE_H) +#if defined(HAVE_PCRE_H) if (!buffer_is_empty(s->download_url)) { if (NULL == (s->download_regex = pcre_compile(s->download_url->ptr, 0, &errptr, &erroff, NULL))) { - - log_error_write(srv, __FILE__, __LINE__, "sbss", - "compiling regex for download-url failed:", + + log_error_write(srv, __FILE__, __LINE__, "sbss", + "compiling regex for download-url failed:", s->download_url, "pos:", erroff); return HANDLER_ERROR; } } - + if (!buffer_is_empty(s->trigger_url)) { if (NULL == (s->trigger_regex = pcre_compile(s->trigger_url->ptr, 0, &errptr, &erroff, NULL))) { - - log_error_write(srv, __FILE__, __LINE__, "sbss", - "compiling regex for trigger-url failed:", + + log_error_write(srv, __FILE__, __LINE__, "sbss", + "compiling regex for trigger-url failed:", s->trigger_url, "pos:", erroff); - + return HANDLER_ERROR; } } @@ -211,33 +211,33 @@ SETDEFAULTS_FUNC(mod_trigger_b4_dl_set_defaults) { #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 trigger-before-download.memcache-hosts is set, aborting"); return HANDLER_ERROR; #endif } - + #if (!defined(HAVE_GDBM_H) && !defined(HAVE_MEMCACHE_H)) || !defined(HAVE_PCRE_H) - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "(either gdbm or libmemcache) and pcre are require, but were not found, aborting"); return HANDLER_ERROR; #endif } - + return HANDLER_GO_ON; } @@ -246,14 +246,14 @@ SETDEFAULTS_FUNC(mod_trigger_b4_dl_set_defaults) { static int mod_trigger_b4_dl_patch_connection(server *srv, connection *con, plugin_data *p) { size_t i, j; plugin_config *s = p->config_storage[0]; - + #if defined(HAVE_GDBM) PATCH(db); -#endif +#endif #if defined(HAVE_PCRE_H) PATCH(download_regex); PATCH(trigger_regex); -#endif +#endif PATCH(trigger_timeout); PATCH(deny_url); PATCH(mc_namespace); @@ -261,15 +261,15 @@ static int mod_trigger_b4_dl_patch_connection(server *srv, connection *con, plug #if defined(HAVE_MEMCACHE_H) PATCH(mc); #endif - + /* 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]; @@ -301,7 +301,7 @@ static int mod_trigger_b4_dl_patch_connection(server *srv, connection *con, plug } } } - + return 0; } #undef PATCH @@ -315,20 +315,20 @@ URIHANDLER_FUNC(mod_trigger_b4_dl_uri_handler) { int n; # define N 10 int ovec[N * 3]; - + if (con->uri.path->used == 0) return HANDLER_GO_ON; - + mod_trigger_b4_dl_patch_connection(srv, con, p); - + if (!p->conf.trigger_regex || !p->conf.download_regex) return HANDLER_GO_ON; - + # if !defined(HAVE_GDBM_H) && !defined(HAVE_MEMCACHE_H) return HANDLER_GO_ON; # elif defined(HAVE_GDBM_H) && defined(HAVE_MEMCACHE_H) if (!p->conf.db && !p->conf.mc) return HANDLER_GO_ON; if (p->conf.db && p->conf.mc) { /* can't decide which one */ - + return HANDLER_GO_ON; } # elif defined(HAVE_GDBM_H) @@ -336,12 +336,12 @@ URIHANDLER_FUNC(mod_trigger_b4_dl_uri_handler) { # else if (!p->conf.mc) return HANDLER_GO_ON; # endif - + if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "X-Forwarded-For"))) { /* X-Forwarded-For contains the ip behind the proxy */ - + remote_ip = ds->value->ptr; - + /* memcache can't handle spaces */ } else { remote_ip = inet_ntop_cache_get_ip(srv, &(con->dst_addr)); @@ -350,13 +350,13 @@ URIHANDLER_FUNC(mod_trigger_b4_dl_uri_handler) { if (p->conf.debug) { log_error_write(srv, __FILE__, __LINE__, "ss", "(debug) remote-ip:", remote_ip); } - + /* check if URL is a trigger -> insert IP into DB */ if ((n = pcre_exec(p->conf.trigger_regex, NULL, con->uri.path->ptr, con->uri.path->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 { @@ -364,34 +364,34 @@ URIHANDLER_FUNC(mod_trigger_b4_dl_uri_handler) { if (p->conf.db) { /* the trigger matched */ datum key, val; - + key.dptr = (char *)remote_ip; key.dsize = strlen(remote_ip); - + val.dptr = (char *)&(srv->cur_ts); val.dsize = sizeof(srv->cur_ts); - + if (0 != gdbm_store(p->conf.db, key, val, GDBM_REPLACE)) { log_error_write(srv, __FILE__, __LINE__, "s", "insert failed"); } } # endif -# if defined(HAVE_MEMCACHE_H) +# if defined(HAVE_MEMCACHE_H) if (p->conf.mc) { size_t i; buffer_copy_string_buffer(p->tmp_buf, p->conf.mc_namespace); buffer_append_string(p->tmp_buf, remote_ip); - + for (i = 0; i < p->tmp_buf->used - 1; i++) { if (p->tmp_buf->ptr[i] == ' ') p->tmp_buf->ptr[i] = '-'; } - + if (p->conf.debug) { log_error_write(srv, __FILE__, __LINE__, "sb", "(debug) triggered IP:", p->tmp_buf); } - if (0 != mc_set(p->conf.mc, + if (0 != mc_set(p->conf.mc, CONST_BUF_LEN(p->tmp_buf), (char *)&(srv->cur_ts), sizeof(srv->cur_ts), p->conf.trigger_timeout, 0)) { @@ -401,7 +401,7 @@ URIHANDLER_FUNC(mod_trigger_b4_dl_uri_handler) { } # endif } - + /* check if URL is a download -> check IP in DB, update timestamp */ if ((n = pcre_exec(p->conf.download_regex, NULL, con->uri.path->ptr, con->uri.path->used - 1, 0, 0, ovec, 3 * N)) < 0) { if (n != PCRE_ERROR_NOMATCH) { @@ -411,93 +411,93 @@ URIHANDLER_FUNC(mod_trigger_b4_dl_uri_handler) { } } else { /* the download uri matched */ -# if defined(HAVE_GDBM_H) +# if defined(HAVE_GDBM_H) if (p->conf.db) { datum key, val; time_t last_hit; - + key.dptr = (char *)remote_ip; key.dsize = strlen(remote_ip); - + val = gdbm_fetch(p->conf.db, key); - + if (val.dptr == NULL) { /* not found, redirect */ - + response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->conf.deny_url)); - + con->http_status = 307; - + return HANDLER_FINISHED; } - + last_hit = *(time_t *)(val.dptr); - + free(val.dptr); - + if (srv->cur_ts - last_hit > p->conf.trigger_timeout) { /* found, but timeout, redirect */ - + response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->conf.deny_url)); con->http_status = 307; - + if (p->conf.db) { if (0 != gdbm_delete(p->conf.db, key)) { log_error_write(srv, __FILE__, __LINE__, "s", "delete failed"); } } - + return HANDLER_FINISHED; } - + val.dptr = (char *)&(srv->cur_ts); val.dsize = sizeof(srv->cur_ts); - + if (0 != gdbm_store(p->conf.db, key, val, GDBM_REPLACE)) { log_error_write(srv, __FILE__, __LINE__, "s", "insert failed"); } } # endif - -# if defined(HAVE_MEMCACHE_H) + +# if defined(HAVE_MEMCACHE_H) if (p->conf.mc) { void *r; size_t i; - + buffer_copy_string_buffer(p->tmp_buf, p->conf.mc_namespace); buffer_append_string(p->tmp_buf, remote_ip); - + for (i = 0; i < p->tmp_buf->used - 1; i++) { if (p->tmp_buf->ptr[i] == ' ') p->tmp_buf->ptr[i] = '-'; } - + if (p->conf.debug) { log_error_write(srv, __FILE__, __LINE__, "sb", "(debug) checking IP:", p->tmp_buf); } /** - * + * * memcached is do expiration for us, as long as we can fetch it every thing is ok - * and the timestamp is updated - * + * and the timestamp is updated + * */ - if (NULL == (r = mc_aget(p->conf.mc, + if (NULL == (r = mc_aget(p->conf.mc, CONST_BUF_LEN(p->tmp_buf) ))) { - + response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(p->conf.deny_url)); - + con->http_status = 307; - + return HANDLER_FINISHED; } - + free(r); - + /* set a new timeout */ - if (0 != mc_set(p->conf.mc, + if (0 != mc_set(p->conf.mc, CONST_BUF_LEN(p->tmp_buf), (char *)&(srv->cur_ts), sizeof(srv->cur_ts), p->conf.trigger_timeout, 0)) { @@ -507,13 +507,13 @@ URIHANDLER_FUNC(mod_trigger_b4_dl_uri_handler) { } # endif } - + #else UNUSED(srv); UNUSED(con); UNUSED(p_d); #endif - + return HANDLER_GO_ON; } @@ -521,21 +521,21 @@ URIHANDLER_FUNC(mod_trigger_b4_dl_uri_handler) { TRIGGER_FUNC(mod_trigger_b4_dl_handle_trigger) { plugin_data *p = p_d; size_t i; - + /* check DB each minute */ if (srv->cur_ts % 60 != 0) return HANDLER_GO_ON; - + /* cleanup */ for (i = 0; i < srv->config_context->used; i++) { plugin_config *s = p->config_storage[i]; datum key, val, okey; - + if (!s->db) continue; - + okey.dptr = NULL; - - /* according to the manual this loop + delete does delete all entries on its way - * + + /* according to the manual this loop + delete does delete all entries on its way + * * we don't care as the next round will remove them. We don't have to perfect here. */ for (key = gdbm_firstkey(s->db); key.dptr; key = gdbm_nextkey(s->db, okey)) { @@ -544,21 +544,21 @@ TRIGGER_FUNC(mod_trigger_b4_dl_handle_trigger) { free(okey.dptr); okey.dptr = NULL; } - + val = gdbm_fetch(s->db, key); - + last_hit = *(time_t *)(val.dptr); - + free(val.dptr); - + if (srv->cur_ts - last_hit > s->trigger_timeout) { gdbm_delete(s->db, key); } - + okey = key; } if (okey.dptr) free(okey.dptr); - + /* reorg once a day */ if ((srv->cur_ts % (60 * 60 * 24) != 0)) gdbm_reorganize(s->db); } @@ -571,7 +571,7 @@ TRIGGER_FUNC(mod_trigger_b4_dl_handle_trigger) { int mod_trigger_b4_dl_plugin_init(plugin *p) { p->version = LIGHTTPD_VERSION_ID; p->name = buffer_init_string("trigger_b4_dl"); - + p->init = mod_trigger_b4_dl_init; p->handle_uri_clean = mod_trigger_b4_dl_uri_handler; p->set_defaults = mod_trigger_b4_dl_set_defaults; @@ -579,8 +579,8 @@ int mod_trigger_b4_dl_plugin_init(plugin *p) { p->handle_trigger = mod_trigger_b4_dl_handle_trigger; #endif p->cleanup = mod_trigger_b4_dl_free; - + p->data = NULL; - + return 0; } diff --git a/src/mod_userdir.c b/src/mod_userdir.c index 9612fa8..2fef0f2 100644 --- a/src/mod_userdir.c +++ b/src/mod_userdir.c @@ -25,54 +25,54 @@ typedef struct { typedef struct { PLUGIN_DATA; - + buffer *username; buffer *temp_path; - + plugin_config **config_storage; - - plugin_config conf; + + plugin_config conf; } plugin_data; /* init the plugin data */ INIT_FUNC(mod_userdir_init) { plugin_data *p; - + p = calloc(1, sizeof(*p)); - + p->username = buffer_init(); p->temp_path = buffer_init(); - + return p; } /* detroy the plugin data */ FREE_FUNC(mod_userdir_free) { plugin_data *p = p_d; - + 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]; - + array_free(s->include_user); array_free(s->exclude_user); buffer_free(s->path); buffer_free(s->basepath); - + free(s); } free(p->config_storage); } - + buffer_free(p->username); buffer_free(p->temp_path); - + free(p); - + return HANDLER_GO_ON; } @@ -81,40 +81,40 @@ FREE_FUNC(mod_userdir_free) { SETDEFAULTS_FUNC(mod_userdir_set_defaults) { plugin_data *p = p_d; size_t i; - - config_values_t cv[] = { + + config_values_t cv[] = { { "userdir.path", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ { "userdir.exclude-user", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 1 */ { "userdir.include-user", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 2 */ { "userdir.basepath", 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 = 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->exclude_user = array_init(); s->include_user = array_init(); s->path = buffer_init(); s->basepath = buffer_init(); - + cv[0].destination = s->path; cv[1].destination = s->exclude_user; cv[2].destination = s->include_user; cv[3].destination = s->basepath; - + 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; } @@ -123,24 +123,24 @@ SETDEFAULTS_FUNC(mod_userdir_set_defaults) { static int mod_userdir_patch_connection(server *srv, connection *con, plugin_data *p) { size_t i, j; plugin_config *s = p->config_storage[0]; - + PATCH(path); PATCH(exclude_user); PATCH(include_user); PATCH(basepath); - + /* 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("userdir.path"))) { PATCH(path); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("userdir.exclude-user"))) { @@ -152,7 +152,7 @@ static int mod_userdir_patch_connection(server *srv, connection *con, plugin_dat } } } - + return 0; } #undef PATCH @@ -169,18 +169,18 @@ URIHANDLER_FUNC(mod_userdir_docroot_handler) { if (con->uri.path->used == 0) return HANDLER_GO_ON; mod_userdir_patch_connection(srv, con, p); - + uri_len = con->uri.path->used - 1; - + /* /~user/foo.html -> /home/user/public_html/foo.html */ - + if (con->uri.path->ptr[0] != '/' || con->uri.path->ptr[1] != '~') return HANDLER_GO_ON; - + if (NULL == (rel_url = strchr(con->uri.path->ptr + 2, '/'))) { /* / is missing -> redirect to .../ as we are a user - DIRECTORY ! :) */ http_response_redirect_to_directory(srv, con); - + return HANDLER_FINISHED; } @@ -188,10 +188,10 @@ URIHANDLER_FUNC(mod_userdir_docroot_handler) { if (0 == rel_url - (con->uri.path->ptr + 2)) { return HANDLER_GO_ON; } - + buffer_copy_string_len(p->username, con->uri.path->ptr + 2, rel_url - (con->uri.path->ptr + 2)); - - if (buffer_is_empty(p->conf.basepath) + + if (buffer_is_empty(p->conf.basepath) #ifdef HAVE_PWD_H && NULL == (pwd = getpwnam(p->username->ptr)) #endif @@ -200,31 +200,31 @@ URIHANDLER_FUNC(mod_userdir_docroot_handler) { return HANDLER_GO_ON; } - + for (k = 0; k < p->conf.exclude_user->used; k++) { data_string *ds = (data_string *)p->conf.exclude_user->data[k]; - + if (buffer_is_equal(ds->value, p->username)) { /* user in exclude list */ return HANDLER_GO_ON; } } - + if (p->conf.include_user->used) { int found_user = 0; for (k = 0; k < p->conf.include_user->used; k++) { data_string *ds = (data_string *)p->conf.include_user->data[k]; - + if (buffer_is_equal(ds->value, p->username)) { /* user in include list */ found_user = 1; break; } } - + if (!found_user) return HANDLER_GO_ON; } - + /* we build the physical path */ if (buffer_is_empty(p->conf.basepath)) { @@ -256,16 +256,16 @@ URIHANDLER_FUNC(mod_userdir_docroot_handler) { buffer_append_string_buffer(p->temp_path, p->username); } BUFFER_APPEND_SLASH(p->temp_path); - buffer_append_string_buffer(p->temp_path, p->conf.path); + buffer_append_string_buffer(p->temp_path, p->conf.path); if (buffer_is_empty(p->conf.basepath)) { struct stat st; int ret; - + ret = stat(p->temp_path->ptr, &st); if (ret < 0 || S_ISDIR(st.st_mode) != 1) { return HANDLER_GO_ON; - } + } } BUFFER_APPEND_SLASH(p->temp_path); @@ -282,13 +282,13 @@ URIHANDLER_FUNC(mod_userdir_docroot_handler) { int mod_userdir_plugin_init(plugin *p) { p->version = LIGHTTPD_VERSION_ID; p->name = buffer_init_string("userdir"); - + p->init = mod_userdir_init; p->handle_physical = mod_userdir_docroot_handler; p->set_defaults = mod_userdir_set_defaults; p->cleanup = mod_userdir_free; - + p->data = NULL; - + return 0; } diff --git a/src/mod_usertrack.c b/src/mod_usertrack.c index d3314c2..fb1839d 100644 --- a/src/mod_usertrack.c +++ b/src/mod_usertrack.c @@ -24,44 +24,44 @@ typedef struct { typedef struct { PLUGIN_DATA; - + plugin_config **config_storage; - - plugin_config conf; + + plugin_config conf; } plugin_data; /* init the plugin data */ INIT_FUNC(mod_usertrack_init) { plugin_data *p; - + p = calloc(1, sizeof(*p)); - + return p; } /* detroy the plugin data */ FREE_FUNC(mod_usertrack_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->cookie_name); buffer_free(s->cookie_domain); - + free(s); } free(p->config_storage); } - + free(p); - + return HANDLER_GO_ON; } @@ -70,38 +70,38 @@ FREE_FUNC(mod_usertrack_free) { SETDEFAULTS_FUNC(mod_usertrack_set_defaults) { plugin_data *p = p_d; size_t i = 0; - - config_values_t cv[] = { + + config_values_t cv[] = { { "usertrack.cookie-name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ { "usertrack.cookie-max-age", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */ { "usertrack.cookie-domain", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */ - - { "usertrack.cookiename", NULL, T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_CONNECTION }, + + { "usertrack.cookiename", NULL, T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_CONNECTION }, { 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->cookie_name = buffer_init(); s->cookie_domain = buffer_init(); s->cookie_max_age = 0; - + cv[0].destination = s->cookie_name; cv[1].destination = &(s->cookie_max_age); cv[2].destination = s->cookie_domain; - + 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 (buffer_is_empty(s->cookie_name)) { buffer_copy_string(s->cookie_name, "TRACKID"); } else { @@ -109,30 +109,30 @@ SETDEFAULTS_FUNC(mod_usertrack_set_defaults) { for (j = 0; j < s->cookie_name->used - 1; j++) { char c = s->cookie_name->ptr[j] | 32; if (c < 'a' || c > 'z') { - log_error_write(srv, __FILE__, __LINE__, "sb", - "invalid character in usertrack.cookie-name:", + log_error_write(srv, __FILE__, __LINE__, "sb", + "invalid character in usertrack.cookie-name:", s->cookie_name); - + return HANDLER_ERROR; } } } - + if (!buffer_is_empty(s->cookie_domain)) { size_t j; for (j = 0; j < s->cookie_domain->used - 1; j++) { char c = s->cookie_domain->ptr[j]; if (c <= 32 || c >= 127 || c == '"' || c == '\\') { - log_error_write(srv, __FILE__, __LINE__, "sb", - "invalid character in usertrack.cookie-domain:", + log_error_write(srv, __FILE__, __LINE__, "sb", + "invalid character in usertrack.cookie-domain:", s->cookie_domain); - + return HANDLER_ERROR; } } } } - + return HANDLER_GO_ON; } @@ -141,23 +141,23 @@ SETDEFAULTS_FUNC(mod_usertrack_set_defaults) { static int mod_usertrack_patch_connection(server *srv, connection *con, plugin_data *p) { size_t i, j; plugin_config *s = p->config_storage[0]; - + PATCH(cookie_name); PATCH(cookie_domain); PATCH(cookie_max_age); - + /* 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("usertrack.cookie-name"))) { PATCH(cookie_name); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("usertrack.cookie-max-age"))) { @@ -167,7 +167,7 @@ static int mod_usertrack_patch_connection(server *srv, connection *con, plugin_d } } } - + return 0; } #undef PATCH @@ -178,38 +178,38 @@ URIHANDLER_FUNC(mod_usertrack_uri_handler) { unsigned char h[16]; MD5_CTX Md5Ctx; char hh[32]; - + if (con->uri.path->used == 0) return HANDLER_GO_ON; - + mod_usertrack_patch_connection(srv, con, p); - + if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Cookie"))) { char *g; /* we have a cookie, does it contain a valid name ? */ - - /* parse the cookie - * + + /* parse the cookie + * * check for cookiename + (WS | '=') - * + * */ - + if (NULL != (g = strstr(ds->value->ptr, p->conf.cookie_name->ptr))) { char *nc; - + /* skip WS */ for (nc = g + p->conf.cookie_name->used-1; *nc == ' ' || *nc == '\t'; nc++); - + if (*nc == '=') { /* ok, found the key of our own cookie */ - + if (strlen(nc) > 32) { /* i'm lazy */ return HANDLER_GO_ON; } } } - } - + } + /* set a cookie */ if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) { ds = data_response_init(); @@ -217,39 +217,39 @@ URIHANDLER_FUNC(mod_usertrack_uri_handler) { buffer_copy_string(ds->key, "Set-Cookie"); buffer_copy_string_buffer(ds->value, p->conf.cookie_name); buffer_append_string(ds->value, "="); - + /* taken from mod_auth.c */ - + /* generate shared-secret */ MD5_Init(&Md5Ctx); MD5_Update(&Md5Ctx, (unsigned char *)con->uri.path->ptr, con->uri.path->used - 1); MD5_Update(&Md5Ctx, (unsigned char *)"+", 1); - + /* we assume sizeof(time_t) == 4 here, but if not it ain't a problem at all */ ltostr(hh, srv->cur_ts); MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh)); ltostr(hh, rand()); MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh)); - + MD5_Final(h, &Md5Ctx); - + buffer_append_string_encoded(ds->value, (char *)h, 16, ENCODING_HEX); buffer_append_string(ds->value, "; Path=/"); buffer_append_string(ds->value, "; Version=1"); - + if (!buffer_is_empty(p->conf.cookie_domain)) { buffer_append_string(ds->value, "; Domain="); buffer_append_string_encoded(ds->value, CONST_BUF_LEN(p->conf.cookie_domain), ENCODING_REL_URI); } - + if (p->conf.cookie_max_age) { buffer_append_string(ds->value, "; max-age="); buffer_append_long(ds->value, p->conf.cookie_max_age); } - + array_insert_unique(con->response.headers, (data_unset *)ds); - + return HANDLER_GO_ON; } @@ -258,13 +258,13 @@ URIHANDLER_FUNC(mod_usertrack_uri_handler) { int mod_usertrack_plugin_init(plugin *p) { p->version = LIGHTTPD_VERSION_ID; p->name = buffer_init_string("usertrack"); - + p->init = mod_usertrack_init; p->handle_uri_clean = mod_usertrack_uri_handler; p->set_defaults = mod_usertrack_set_defaults; p->cleanup = mod_usertrack_free; - + p->data = NULL; - + return 0; } diff --git a/src/mod_webdav.c b/src/mod_webdav.c index 3fd021f..572a7b6 100644 --- a/src/mod_webdav.c +++ b/src/mod_webdav.c @@ -23,7 +23,7 @@ #include <sqlite3.h> #endif -#if defined(HAVE_LIBXML_H) && defined(HAVE_SQLITE3_H) && defined(HAVE_UUID_H) +#if defined(HAVE_LIBXML_H) && defined(HAVE_SQLITE3_H) && defined(HAVE_UUID_UUID_H) #define USE_LOCKS #include <uuid/uuid.h> #endif @@ -48,7 +48,8 @@ * */ - +#define WEBDAV_FILE_MODE S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH +#define WEBDAV_DIR_MODE S_IRWXU | S_IRWXG | S_IRWXO /* plugin config for all request/connections */ @@ -207,7 +208,9 @@ SETDEFAULTS_FUNC(mod_webdav_set_defaults) { char *err; if (SQLITE_OK != sqlite3_open(s->sqlite_db_name->ptr, &(s->sql))) { - log_error_write(srv, __FILE__, __LINE__, "s", "sqlite3_open failed"); + log_error_write(srv, __FILE__, __LINE__, "sbs", "sqlite3_open failed for", + s->sqlite_db_name, + sqlite3_errmsg(s->sql)); return HANDLER_ERROR; } @@ -661,14 +664,14 @@ static int webdav_delete_dir(server *srv, connection *con, plugin_data *p, physi static int webdav_copy_file(server *srv, connection *con, plugin_data *p, physical *src, physical *dst, int overwrite) { stream s; int status = 0, ofd; - + UNUSED(srv); UNUSED(con); if (stream_open(&s, src->path)) { return 403; } - if (-1 == (ofd = open(dst->path->ptr, O_WRONLY|O_TRUNC|O_CREAT|(overwrite ? 0 : O_EXCL), S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH))) { + if (-1 == (ofd = open(dst->path->ptr, O_WRONLY|O_TRUNC|O_CREAT|(overwrite ? 0 : O_EXCL), WEBDAV_FILE_MODE))) { /* opening the destination failed for some reason */ switch(errno) { case EEXIST: @@ -773,7 +776,7 @@ static int webdav_copy_dir(server *srv, connection *con, plugin_data *p, physica /* why ? */ } else if (S_ISDIR(st.st_mode)) { /* a directory */ - if (-1 == mkdir(d.path->ptr, 0700) && + if (-1 == mkdir(d.path->ptr, WEBDAV_DIR_MODE) && errno != EEXIST) { /* WTH ? */ } else { @@ -1148,31 +1151,32 @@ int webdav_lockdiscovery(server *srv, connection *con, * */ int webdav_has_lock(server *srv, connection *con, plugin_data *p, buffer *uri) { + UNUSED(srv); int has_lock = 1; #ifdef USE_LOCKS data_string *ds; /** - * If can have - * - <lock-token> - * - [etag] - * - * there is NOT, AND and OR - * and a list can be tagged - * - * (<lock-token>) is untagged - * <tag> (<lock-token>) is tagged - * - * as long as we don't handle collections it is simple. :) + * This implementation is more fake than real + * we need a parser for the If: header to really handle the full scope * * X-Litmus: locks: 11 (owner_modify) * If: <http://127.0.0.1:1025/dav/litmus/lockme> (<opaquelocktoken:2165478d-0611-49c4-be92-e790d68a38f1>) + * - a tagged check: + * if http://127.0.0.1:1025/dav/litmus/lockme is locked with + * opaquelocktoken:2165478d-0611-49c4-be92-e790d68a38f1, go on * * X-Litmus: locks: 16 (fail_cond_put) * If: (<DAV:no-lock> ["-1622396671"]) + * - untagged: + * go on if the resource has the etag [...] and the lock */ if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If"))) { + /* Ooh, ooh. A if tag, now the fun begins. + * + * this can only work with a real parser + **/ } else { /* we didn't provided a lock-token -> */ /* if the resource is locked -> 423 */ @@ -1493,7 +1497,7 @@ URIHANDLER_FUNC(mod_webdav_subrequest_handler) { /* let's create the directory */ - if (-1 == mkdir(con->physical.path->ptr, 0700)) { + if (-1 == mkdir(con->physical.path->ptr, WEBDAV_DIR_MODE)) { switch(errno) { case EPERM: con->http_status = 403; @@ -1651,7 +1655,7 @@ URIHANDLER_FUNC(mod_webdav_subrequest_handler) { return HANDLER_FINISHED; } - if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH))) { + if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY, WEBDAV_FILE_MODE))) { switch (errno) { case ENOENT: con->http_status = 404; /* not found */ @@ -1675,9 +1679,9 @@ URIHANDLER_FUNC(mod_webdav_subrequest_handler) { /* take what we have in the request-body and write it to a file */ /* if the file doesn't exist, create it */ - if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH))) { + if (-1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_TRUNC, WEBDAV_FILE_MODE))) { if (errno == ENOENT && - -1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH))) { + -1 == (fd = open(con->physical.path->ptr, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, WEBDAV_FILE_MODE))) { /* we can't open the file */ con->http_status = 403; @@ -1883,7 +1887,7 @@ URIHANDLER_FUNC(mod_webdav_subrequest_handler) { /* src is a directory */ if (-1 == stat(p->physical.path->ptr, &st)) { - if (-1 == mkdir(p->physical.path->ptr, 0700)) { + if (-1 == mkdir(p->physical.path->ptr, WEBDAV_DIR_MODE)) { con->http_status = 403; return HANDLER_FINISHED; } @@ -1894,7 +1898,7 @@ URIHANDLER_FUNC(mod_webdav_subrequest_handler) { return HANDLER_FINISHED; } else { unlink(p->physical.path->ptr); - if (-1 == mkdir(p->physical.path->ptr, 0700)) { + if (-1 == mkdir(p->physical.path->ptr, WEBDAV_DIR_MODE)) { con->http_status = 403; return HANDLER_FINISHED; } @@ -2202,7 +2206,7 @@ propmatch_cleanup: if (0 == xmlStrcmp(rootnode->name, BAD_CAST "lockinfo")) { xmlNode *lockinfo; - const xmlChar *lockscope = NULL, *locktype = NULL, *owner = NULL; + const xmlChar *lockscope = NULL, *locktype = NULL; /* TODO: compiler says unused: *owner = NULL; */ for (lockinfo = rootnode->children; lockinfo; lockinfo = lockinfo->next) { if (0 == xmlStrcmp(lockinfo->name, BAD_CAST "lockscope")) { @@ -2306,12 +2310,12 @@ propmatch_cleanup: SQLITE_TRANSIENT); sqlite3_bind_text(stmt, 3, - lockscope, + (const char *)lockscope, xmlStrlen(lockscope), SQLITE_TRANSIENT); sqlite3_bind_text(stmt, 4, - locktype, + (const char *)locktype, xmlStrlen(locktype), SQLITE_TRANSIENT); @@ -2332,7 +2336,7 @@ propmatch_cleanup: } /* looks like we survived */ - webdav_lockdiscovery(srv, con, p->tmp_buf, lockscope, locktype, depth); + webdav_lockdiscovery(srv, con, p->tmp_buf, (const char *)lockscope, (const char *)locktype, depth); con->http_status = 201; con->file_finished = 1; diff --git a/src/network.c b/src/network.c index 5b21b83..ba024aa 100644 --- a/src/network.c +++ b/src/network.c @@ -21,9 +21,9 @@ #include "sys-socket.h" #ifdef USE_OPENSSL -# include <openssl/ssl.h> -# include <openssl/err.h> -# include <openssl/rand.h> +# include <openssl/ssl.h> +# include <openssl/err.h> +# include <openssl/rand.h> #endif handler_t network_server_handle_fdevent(void *s, void *context, int revents) { @@ -31,11 +31,11 @@ handler_t network_server_handle_fdevent(void *s, void *context, int revents) { server_socket *srv_socket = (server_socket *)context; connection *con; int loops = 0; - + UNUSED(context); - + if (revents != FDEVENT_IN) { - log_error_write(srv, __FILE__, __LINE__, "sdd", + log_error_write(srv, __FILE__, __LINE__, "sdd", "strange event for server socket", srv_socket->fd, revents); @@ -44,12 +44,12 @@ handler_t network_server_handle_fdevent(void *s, void *context, int revents) { /* accept()s at most 100 connections directly * - * we jump out after 100 to give the waiting connections a chance */ + * we jump out after 100 to give the waiting connections a chance */ for (loops = 0; loops < 100 && NULL != (con = connection_accept(srv, srv_socket)); loops++) { handler_t r; - + connection_state_machine(srv, con); - + switch(r = plugins_call_handle_joblist(srv, con)) { case HANDLER_FINISHED: case HANDLER_GO_ON: @@ -72,7 +72,7 @@ int network_server_init(server *srv, buffer *host_token, specific_config *s) { buffer *b; int is_unix_domain_socket = 0; int fd; - + #ifdef SO_ACCEPTFILTER struct accept_filter_arg afa; #endif @@ -81,9 +81,9 @@ int network_server_init(server *srv, buffer *host_token, specific_config *s) { WORD wVersionRequested; WSADATA wsaData; int err; - + wVersionRequested = MAKEWORD( 2, 2 ); - + err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { /* Tell the user that we could not find a usable */ @@ -91,37 +91,37 @@ int network_server_init(server *srv, buffer *host_token, specific_config *s) { return -1; } #endif - + srv_socket = calloc(1, sizeof(*srv_socket)); srv_socket->fd = -1; - + srv_socket->srv_token = buffer_init(); buffer_copy_string_buffer(srv_socket->srv_token, host_token); - + b = buffer_init(); buffer_copy_string_buffer(b, host_token); - - /* ipv4:port + + /* ipv4:port * [ipv6]:port */ if (NULL == (sp = strrchr(b->ptr, ':'))) { log_error_write(srv, __FILE__, __LINE__, "sb", "value of $SERVER[\"socket\"] has to be \"ip:port\".", b); - + return -1; } - + host = b->ptr; - + /* check for [ and ] */ if (b->ptr[0] == '[' && *(sp-1) == ']') { *(sp-1) = '\0'; host++; - + s->use_ipv6 = 1; } - + *(sp++) = '\0'; - + port = strtol(sp, NULL, 10); if (host[0] == '/') { @@ -129,17 +129,17 @@ int network_server_init(server *srv, buffer *host_token, specific_config *s) { is_unix_domain_socket = 1; } else if (port == 0 || port > 65535) { log_error_write(srv, __FILE__, __LINE__, "sd", "port out of range:", port); - + return -1; } - + if (*host == '\0') host = NULL; if (is_unix_domain_socket) { #ifdef HAVE_SYS_UN_H srv_socket->addr.plain.sa_family = AF_UNIX; - + if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, 0))) { log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno)); return -1; @@ -154,7 +154,7 @@ int network_server_init(server *srv, buffer *host_token, specific_config *s) { #ifdef HAVE_IPV6 if (s->use_ipv6) { srv_socket->addr.plain.sa_family = AF_INET6; - + if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) { log_error_write(srv, __FILE__, __LINE__, "ss", "socket failed:", strerror(errno)); return -1; @@ -162,7 +162,7 @@ int network_server_init(server *srv, buffer *host_token, specific_config *s) { srv_socket->use_ipv6 = 1; } #endif - + if (srv_socket->fd == -1) { srv_socket->addr.plain.sa_family = AF_INET; if (-1 == (srv_socket->fd = socket(srv_socket->addr.plain.sa_family, SOCK_STREAM, IPPROTO_TCP))) { @@ -170,16 +170,16 @@ int network_server_init(server *srv, buffer *host_token, specific_config *s) { return -1; } } - + /* */ srv->cur_fds = srv_socket->fd; - + val = 1; if (setsockopt(srv_socket->fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) { log_error_write(srv, __FILE__, __LINE__, "ss", "socketsockopt failed:", strerror(errno)); return -1; } - + switch(srv_socket->addr.plain.sa_family) { #ifdef HAVE_IPV6 case AF_INET6: @@ -190,23 +190,23 @@ int network_server_init(server *srv, buffer *host_token, specific_config *s) { } else { struct addrinfo hints, *res; int r; - + memset(&hints, 0, sizeof(hints)); - + hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; - + if (0 != (r = getaddrinfo(host, NULL, &hints, &res))) { - log_error_write(srv, __FILE__, __LINE__, - "sssss", "getaddrinfo failed: ", + log_error_write(srv, __FILE__, __LINE__, + "sssss", "getaddrinfo failed: ", gai_strerror(r), "'", host, "'"); - + return -1; } - + memcpy(&(srv_socket->addr), res->ai_addr, res->ai_addrlen); - + freeaddrinfo(res); } srv_socket->addr.ipv6.sin6_port = htons(port); @@ -221,33 +221,33 @@ int network_server_init(server *srv, buffer *host_token, specific_config *s) { } else { struct hostent *he; if (NULL == (he = gethostbyname(host))) { - log_error_write(srv, __FILE__, __LINE__, - "sds", "gethostbyname failed: ", + log_error_write(srv, __FILE__, __LINE__, + "sds", "gethostbyname failed: ", h_errno, host); return -1; } - + if (he->h_addrtype != AF_INET) { log_error_write(srv, __FILE__, __LINE__, "sd", "addr-type != AF_INET: ", he->h_addrtype); return -1; } - + if (he->h_length != sizeof(struct in_addr)) { log_error_write(srv, __FILE__, __LINE__, "sd", "addr-length != sizeof(in_addr): ", he->h_length); return -1; } - + memcpy(&(srv_socket->addr.ipv4.sin_addr.s_addr), he->h_addr_list[0], he->h_length); } srv_socket->addr.ipv4.sin_port = htons(port); - + addr_len = sizeof(struct sockaddr_in); - + break; case AF_UNIX: srv_socket->addr.un.sun_family = AF_UNIX; strcpy(srv_socket->addr.un.sun_path, host); - + #ifdef SUN_LEN addr_len = SUN_LEN(&srv_socket->addr.un); #else @@ -259,8 +259,8 @@ int network_server_init(server *srv, buffer *host_token, specific_config *s) { if (-1 != (fd = connect(srv_socket->fd, (struct sockaddr *) &(srv_socket->addr), addr_len))) { close(fd); - log_error_write(srv, __FILE__, __LINE__, "ss", - "server socket is still in use:", + log_error_write(srv, __FILE__, __LINE__, "ss", + "server socket is still in use:", host); @@ -275,8 +275,8 @@ int network_server_init(server *srv, buffer *host_token, specific_config *s) { case ENOENT: break; default: - log_error_write(srv, __FILE__, __LINE__, "sds", - "testing socket failed:", + log_error_write(srv, __FILE__, __LINE__, "sds", + "testing socket failed:", host, strerror(errno)); return -1; @@ -285,47 +285,47 @@ int network_server_init(server *srv, buffer *host_token, specific_config *s) { break; default: addr_len = 0; - + return -1; } - + if (0 != bind(srv_socket->fd, (struct sockaddr *) &(srv_socket->addr), addr_len)) { switch(srv_socket->addr.plain.sa_family) { case AF_UNIX: - log_error_write(srv, __FILE__, __LINE__, "sds", - "can't bind to socket:", + log_error_write(srv, __FILE__, __LINE__, "sds", + "can't bind to socket:", host, strerror(errno)); break; default: - log_error_write(srv, __FILE__, __LINE__, "ssds", - "can't bind to port:", + log_error_write(srv, __FILE__, __LINE__, "ssds", + "can't bind to port:", host, port, strerror(errno)); break; } return -1; } - + if (-1 == listen(srv_socket->fd, 128 * 8)) { log_error_write(srv, __FILE__, __LINE__, "ss", "listen failed: ", strerror(errno)); return -1; } - + if (s->is_ssl) { #ifdef USE_OPENSSL if (srv->ssl_is_init == 0) { SSL_load_error_strings(); SSL_library_init(); srv->ssl_is_init = 1; - + if (0 == RAND_status()) { - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", "not enough entropy in the pool"); return -1; } } - + if (NULL == (s->ssl_ctx = SSL_CTX_new(SSLv23_server_method()))) { - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", ERR_error_string(ERR_get_error(), NULL)); return -1; } @@ -347,34 +347,34 @@ int network_server_init(server *srv, buffer *host_token, specific_config *s) { return -1; } } - + if (buffer_is_empty(s->ssl_pemfile)) { log_error_write(srv, __FILE__, __LINE__, "s", "ssl.pemfile has to be set"); return -1; } - + if (!buffer_is_empty(s->ssl_ca_file)) { if (1 != SSL_CTX_load_verify_locations(s->ssl_ctx, s->ssl_ca_file->ptr, NULL)) { - log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", + log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", ERR_error_string(ERR_get_error(), NULL), s->ssl_ca_file); return -1; } } - + if (SSL_CTX_use_certificate_file(s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) { - log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", + log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile); return -1; } - + if (SSL_CTX_use_PrivateKey_file (s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) { - log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", + log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:", ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile); return -1; } - + if (SSL_CTX_check_private_key(s->ssl_ctx) != 1) { - log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:", + log_error_write(srv, __FILE__, __LINE__, "sssb", "SSL:", "Private key does not match the certificate public key, reason:", ERR_error_string(ERR_get_error(), NULL), s->ssl_pemfile); @@ -385,15 +385,15 @@ int network_server_init(server *srv, buffer *host_token, specific_config *s) { srv_socket->ssl_ctx = s->ssl_ctx; #else - + buffer_free(srv_socket->srv_token); free(srv_socket); - + buffer_free(b); - - log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", + + log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:", "ssl requested but openssl support is not compiled in"); - + return -1; #endif } else { @@ -411,10 +411,10 @@ int network_server_init(server *srv, buffer *host_token, specific_config *s) { } #endif } - + srv_socket->is_ssl = s->is_ssl; srv_socket->fde_ndx = -1; - + if (srv->srv_sockets.size == 0) { srv->srv_sockets.size = 4; srv->srv_sockets.used = 0; @@ -423,11 +423,11 @@ int network_server_init(server *srv, buffer *host_token, specific_config *s) { srv->srv_sockets.size += 4; srv->srv_sockets.ptr = realloc(srv->srv_sockets.ptr, srv->srv_sockets.size * sizeof(server_socket)); } - + srv->srv_sockets.ptr[srv->srv_sockets.used++] = srv_socket; - + buffer_free(b); - + return 0; } @@ -435,24 +435,24 @@ int network_close(server *srv) { size_t i; for (i = 0; i < srv->srv_sockets.used; i++) { server_socket *srv_socket = srv->srv_sockets.ptr[i]; - + if (srv_socket->fd != -1) { /* check if server fd are already registered */ if (srv_socket->fde_ndx != -1) { fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd); fdevent_unregister(srv->ev, srv_socket->fd); } - + close(srv_socket->fd); } - + buffer_free(srv_socket->srv_token); - + free(srv_socket); } - + free(srv->srv_sockets.ptr); - + return 0; } @@ -469,11 +469,11 @@ int network_init(server *srv) { buffer *b; size_t i; network_backend_t backend; - - struct nb_map { - network_backend_t nb; - const char *name; - } network_backends[] = { + + struct nb_map { + network_backend_t nb; + const char *name; + } network_backends[] = { /* lowest id wins */ #if defined USE_LINUX_SENDFILE { NETWORK_BACKEND_LINUX_SENDFILE, "linux-sendfile" }, @@ -490,18 +490,18 @@ int network_init(server *srv) { { NETWORK_BACKEND_WRITE, "write" }, { NETWORK_BACKEND_UNSET, NULL } }; - + b = buffer_init(); - + buffer_copy_string_buffer(b, srv->srvconf.bindhost); buffer_append_string(b, ":"); buffer_append_long(b, srv->srvconf.port); - + if (0 != network_server_init(srv, b, srv->config_storage[0])) { return -1; } buffer_free(b); - + #ifdef USE_OPENSSL srv->network_ssl_backend_write = network_write_chunkqueue_openssl; #endif @@ -521,8 +521,8 @@ int network_init(server *srv) { if (NULL == network_backends[i].name) { /* we don't know it */ - log_error_write(srv, __FILE__, __LINE__, "sb", - "server.network-backend has a unknown value:", + log_error_write(srv, __FILE__, __LINE__, "sb", + "server.network-backend has a unknown value:", srv->srvconf.network_backend); return -1; @@ -540,17 +540,17 @@ int network_init(server *srv) { #endif #ifdef USE_LINUX_SENDFILE case NETWORK_BACKEND_LINUX_SENDFILE: - srv->network_backend_write = network_write_chunkqueue_linuxsendfile; + srv->network_backend_write = network_write_chunkqueue_linuxsendfile; break; #endif #ifdef USE_FREEBSD_SENDFILE case NETWORK_BACKEND_FREEBSD_SENDFILE: - srv->network_backend_write = network_write_chunkqueue_freebsdsendfile; + srv->network_backend_write = network_write_chunkqueue_freebsdsendfile; break; #endif #ifdef USE_SOLARIS_SENDFILEV case NETWORK_BACKEND_SOLARIS_SENDFILEV: - srv->network_backend_write = network_write_chunkqueue_solarissendfilev; + srv->network_backend_write = network_write_chunkqueue_solarissendfilev; break; #endif default: @@ -562,13 +562,13 @@ int network_init(server *srv) { data_config *dc = (data_config *)srv->config_context->data[i]; specific_config *s = srv->config_storage[i]; size_t j; - + /* not our stage */ if (COMP_SERVER_SOCKET != dc->comp) continue; - + if (dc->cond != CONFIG_COND_EQ) { log_error_write(srv, __FILE__, __LINE__, "s", "only == is allowed for $SERVER[\"socket\"]."); - + return -1; } @@ -579,26 +579,26 @@ int network_init(server *srv) { break; } } - + if (j == srv->srv_sockets.used) { if (0 != network_server_init(srv, dc->string, s)) return -1; } } - + return 0; } int network_register_fdevents(server *srv) { size_t i; - + if (-1 == fdevent_reset(srv->ev)) { return -1; } - + /* register fdevents after reset */ for (i = 0; i < srv->srv_sockets.used; i++) { server_socket *srv_socket = srv->srv_sockets.ptr[i]; - + fdevent_register(srv->ev, srv_socket->fd, network_server_handle_fdevent, srv_socket); fdevent_event_add(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN); } @@ -608,7 +608,7 @@ int network_register_fdevents(server *srv) { int network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq) { int ret = -1; off_t written = 0; -#ifdef TCP_CORK +#ifdef TCP_CORK int corked = 0; #endif server_socket *srv_socket = con->srv_socket; @@ -621,11 +621,11 @@ int network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq) { joblist_append(srv, con); return 1; - } + } written = cq->bytes_out; -#ifdef TCP_CORK +#ifdef TCP_CORK /* Linux: put a cork into the socket as we want to combine the write() calls * but only if we really have multiple chunks */ @@ -634,7 +634,7 @@ int network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq) { setsockopt(con->fd, IPPROTO_TCP, TCP_CORK, &corked, sizeof(corked)); } #endif - + if (srv_socket->is_ssl) { #ifdef USE_OPENSSL ret = srv->network_ssl_backend_write(srv, con, con->ssl, cq); @@ -642,12 +642,12 @@ int network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq) { } else { ret = srv->network_backend_write(srv, con, con->fd, cq); } - + if (ret >= 0) { chunkqueue_remove_finished_chunks(cq); ret = chunkqueue_is_empty(cq) ? 0 : 1; } - + #ifdef TCP_CORK if (corked) { corked = 0; @@ -660,13 +660,13 @@ int network_write_chunkqueue(server *srv, connection *con, chunkqueue *cq) { con->bytes_written_cur_second += written; *(con->conf.global_bytes_per_second_cnt_ptr) += written; - + if (con->conf.kbytes_per_second && (con->bytes_written_cur_second > con->conf.kbytes_per_second * 1024)) { /* we reached the traffic limit */ con->traffic_limit_reached = 1; joblist_append(srv, con); - } + } return ret; } diff --git a/src/network_freebsd_sendfile.c b/src/network_freebsd_sendfile.c index f6f4d82..819d16f 100644 --- a/src/network_freebsd_sendfile.c +++ b/src/network_freebsd_sendfile.c @@ -26,7 +26,7 @@ #ifndef UIO_MAXIOV # ifdef __FreeBSD__ -/* FreeBSD 4.7, 4.9 defined it in sys/uio.h only if _KERNEL is specified */ +/* FreeBSD 4.7, 4.9 defined it in sys/uio.h only if _KERNEL is specified */ # define UIO_MAXIOV 1024 # endif #endif @@ -34,30 +34,30 @@ int network_write_chunkqueue_freebsdsendfile(server *srv, connection *con, int fd, chunkqueue *cq) { chunk *c; size_t chunks_written = 0; - + for(c = cq->first; c; c = c->next, chunks_written++) { int chunk_finished = 0; - + switch(c->type) { case MEM_CHUNK: { char * offset; size_t toSend; ssize_t r; - + size_t num_chunks, i; struct iovec chunks[UIO_MAXIOV]; chunk *tc; size_t num_bytes = 0; - + /* we can't send more then SSIZE_MAX bytes in one chunk */ - - /* build writev list - * + + /* build writev list + * * 1. limit: num_chunks < UIO_MAXIOV * 2. limit: num_bytes < SSIZE_MAX */ for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next); - + for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) { if (tc->mem->used == 0) { chunks[i].iov_base = tc->mem->ptr; @@ -65,24 +65,24 @@ int network_write_chunkqueue_freebsdsendfile(server *srv, connection *con, int f } else { offset = tc->mem->ptr + tc->offset; toSend = tc->mem->used - 1 - tc->offset; - + chunks[i].iov_base = offset; - + /* protect the return value of writev() */ if (toSend > SSIZE_MAX || num_bytes + toSend > SSIZE_MAX) { chunks[i].iov_len = SSIZE_MAX - num_bytes; - + num_chunks = i + 1; break; } else { chunks[i].iov_len = toSend; } - + num_bytes += toSend; } } - + if ((r = writev(fd, chunks, num_chunks)) < 0) { switch (errno) { case EAGAIN: @@ -94,24 +94,24 @@ int network_write_chunkqueue_freebsdsendfile(server *srv, connection *con, int f case ECONNRESET: return -2; default: - log_error_write(srv, __FILE__, __LINE__, "ssd", + log_error_write(srv, __FILE__, __LINE__, "ssd", "writev failed:", strerror(errno), fd); - + return -1; } r = 0; } - + /* check which chunks have been written */ cq->bytes_out += r; - + for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) { if (r >= (ssize_t)chunks[i].iov_len) { /* written */ r -= chunks[i].iov_len; tc->offset += chunks[i].iov_len; - + if (chunk_finished) { /* skip the chunks from further touches */ chunks_written++; @@ -122,14 +122,14 @@ int network_write_chunkqueue_freebsdsendfile(server *srv, connection *con, int f } } else { /* partially written */ - + tc->offset += r; chunk_finished = 0; - + break; } } - + break; } case FILE_CHUNK: { @@ -137,32 +137,32 @@ int network_write_chunkqueue_freebsdsendfile(server *srv, connection *con, int f 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; } - + offset = c->file.start + c->offset; /* limit the toSend to 2^31-1 bytes in a chunk */ - toSend = c->file.length - c->offset > ((1 << 30) - 1) ? + toSend = c->file.length - c->offset > ((1 << 30) - 1) ? ((1 << 30) - 1) : 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; } - + if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) { log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno)); - + return -1; } - + r = 0; - + /* FreeBSD sendfile() */ if (-1 == sendfile(ifd, fd, offset, toSend, NULL, &r, 0)) { switch(errno) { @@ -178,26 +178,26 @@ int network_write_chunkqueue_freebsdsendfile(server *srv, connection *con, int f } } close(ifd); - + 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; } - + if (!chunk_finished) { /* not finished yet */ - + break; } } diff --git a/src/network_linux_sendfile.c b/src/network_linux_sendfile.c index 580ba87..6586efb 100644 --- a/src/network_linux_sendfile.c +++ b/src/network_linux_sendfile.c @@ -29,32 +29,32 @@ int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd, chunkqueue *cq) { chunk *c; size_t chunks_written = 0; - + for(c = cq->first; c; c = c->next, chunks_written++) { int chunk_finished = 0; - + switch(c->type) { case MEM_CHUNK: { char * offset; size_t toSend; ssize_t r; - + size_t num_chunks, i; struct iovec chunks[UIO_MAXIOV]; chunk *tc; size_t num_bytes = 0; - + /* we can't send more then SSIZE_MAX bytes in one chunk */ - - /* build writev list - * + + /* build writev list + * * 1. limit: num_chunks < UIO_MAXIOV * 2. limit: num_bytes < SSIZE_MAX */ - for (num_chunks = 0, tc = c; - tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; + for (num_chunks = 0, tc = c; + tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; tc = tc->next, num_chunks++); - + for (tc = c, i = 0; i < num_chunks; tc = tc->next, i++) { if (tc->mem->used == 0) { chunks[i].iov_base = tc->mem->ptr; @@ -62,24 +62,24 @@ int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd, } else { offset = tc->mem->ptr + tc->offset; toSend = tc->mem->used - 1 - tc->offset; - + chunks[i].iov_base = offset; - + /* protect the return value of writev() */ if (toSend > SSIZE_MAX || num_bytes + toSend > SSIZE_MAX) { chunks[i].iov_len = SSIZE_MAX - num_bytes; - + num_chunks = i + 1; break; } else { chunks[i].iov_len = toSend; } - + num_bytes += toSend; } } - + if ((r = writev(fd, chunks, num_chunks)) < 0) { switch (errno) { case EAGAIN: @@ -90,13 +90,13 @@ int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd, case ECONNRESET: return -2; default: - log_error_write(srv, __FILE__, __LINE__, "ssd", + log_error_write(srv, __FILE__, __LINE__, "ssd", "writev failed:", strerror(errno), fd); - + return -1; } } - + /* check which chunks have been written */ cq->bytes_out += r; @@ -105,7 +105,7 @@ int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd, /* written */ r -= chunks[i].iov_len; tc->offset += chunks[i].iov_len; - + if (chunk_finished) { /* skip the chunks from further touches */ chunks_written++; @@ -116,14 +116,14 @@ int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd, } } else { /* partially written */ - + tc->offset += r; chunk_finished = 0; - + break; } } - + break; } case FILE_CHUNK: { @@ -131,17 +131,17 @@ int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd, off_t offset; size_t toSend; stat_cache_entry *sce = NULL; - + offset = c->file.start + c->offset; /* limit the toSend to 2^31-1 bytes in a chunk */ - toSend = c->file.length - c->offset > ((1 << 30) - 1) ? + toSend = c->file.length - c->offset > ((1 << 30) - 1) ? ((1 << 30) - 1) : c->file.length - c->offset; - - /* open file if not already opened */ + + /* open file if not already opened */ if (-1 == c->file.fd) { if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) { log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno)); - + return -1; } #ifdef FD_CLOEXEC @@ -151,7 +151,7 @@ int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd, /* tell the kernel that we want to stream the file */ if (-1 == posix_fadvise(c->file.fd, 0, 0, POSIX_FADV_SEQUENTIAL)) { if (ENOSYS != errno) { - log_error_write(srv, __FILE__, __LINE__, "ssd", + log_error_write(srv, __FILE__, __LINE__, "ssd", "posix_fadvise failed:", strerror(errno), c->file.fd); } } @@ -168,18 +168,19 @@ int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd, case ECONNRESET: return -2; default: - log_error_write(srv, __FILE__, __LINE__, "ssd", + log_error_write(srv, __FILE__, __LINE__, "ssd", "sendfile failed:", strerror(errno), fd); return -1; } } if (r == 0) { + int oerrno = errno; /* We got an event to write but we wrote nothing * * - the file shrinked -> error * - the remote side closed inbetween -> remote-close */ - + if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) { /* file is gone ? */ return -1; @@ -187,31 +188,34 @@ int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd, if (offset > sce->st.st_size) { /* file shrinked, close the connection */ + errno = oerrno; + return -1; } + errno = oerrno; return -2; } #ifdef HAVE_POSIX_FADVISE #if 0 #define K * 1024 -#define M * 1024 K +#define M * 1024 K #define READ_AHEAD 4 M /* check if we need a new chunk */ if ((c->offset & ~(READ_AHEAD - 1)) != ((c->offset + r) & ~(READ_AHEAD - 1))) { /* tell the kernel that we want to stream the file */ if (-1 == posix_fadvise(c->file.fd, (c->offset + r) & ~(READ_AHEAD - 1), READ_AHEAD, POSIX_FADV_NOREUSE)) { - log_error_write(srv, __FILE__, __LINE__, "ssd", + log_error_write(srv, __FILE__, __LINE__, "ssd", "posix_fadvise failed:", strerror(errno), c->file.fd); } } #endif #endif - + c->offset += r; cq->bytes_out += r; - + if (c->offset == c->file.length) { chunk_finished = 1; @@ -222,19 +226,19 @@ int network_write_chunkqueue_linuxsendfile(server *srv, connection *con, int fd, c->file.fd = -1; } } - + break; } default: - + log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known"); - + return -1; } - + if (!chunk_finished) { /* not finished yet */ - + break; } } diff --git a/src/network_openssl.c b/src/network_openssl.c index 86043fa..e6df35e 100644 --- a/src/network_openssl.c +++ b/src/network_openssl.c @@ -23,8 +23,8 @@ #include "log.h" #include "stat_cache.h" -# include <openssl/ssl.h> -# include <openssl/err.h> +# include <openssl/ssl.h> +# include <openssl/err.h> int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chunkqueue *cq) { int ssl_r; @@ -33,7 +33,7 @@ int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chu /* this is a 64k sendbuffer * - * it has to stay at the same location all the time to satisfy the needs + * it has to stay at the same location all the time to satisfy the needs * of SSL_write to pass the SAME parameter in case of a _WANT_WRITE * * the buffer is allocated once, is NOT realloced and is NOT freed at shutdown @@ -43,14 +43,14 @@ int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chu * In reality we would like to use mmap() but we don't have a guarantee that * we get the same mmap() address for each call. On openbsd the mmap() address * even randomized. - * That means either we keep the mmap() open or we do a read() into a - * constant buffer + * That means either we keep the mmap() open or we do a read() into a + * constant buffer * */ #define LOCAL_SEND_BUFSIZE (64 * 1024) static char *local_send_buffer = NULL; /* the remote side closed the connection before without shutdown request - * - IE + * - IE * - wget * if keep-alive is disabled */ @@ -85,31 +85,31 @@ int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chu 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 || c->mem->used == 1) { chunk_finished = 1; break; } - + offset = c->mem->ptr + c->offset; toSend = c->mem->used - 1 - c->offset; - + /** * SSL_write man-page - * + * * WARNING * When an SSL_write() operation has to be repeated because of * SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, it must be * repeated with the same arguments. - * + * */ - + if ((r = SSL_write(ssl, offset, toSend)) <= 0) { unsigned long err; @@ -120,7 +120,7 @@ int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chu /* perhaps we have error waiting in our error-queue */ if (0 != (err = ERR_get_error())) { do { - log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:", + log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:", ssl_r, r, ERR_error_string(err, NULL)); } while((err = ERR_get_error())); @@ -130,43 +130,43 @@ int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chu case EPIPE: return -2; default: - log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:", + log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:", ssl_r, r, errno, strerror(errno)); break; } } else { /* neither error-queue nor errno ? */ - log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):", + log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):", ssl_r, r, errno, strerror(errno)); } - + return -1; case SSL_ERROR_ZERO_RETURN: /* clean shutdown on the remote side */ - + if (r == 0) return -2; - + /* fall through */ default: while((err = ERR_get_error())) { - log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:", + log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:", ssl_r, r, ERR_error_string(err, NULL)); } - + return -1; } } else { c->offset += r; cq->bytes_out += r; } - + if (c->offset == (off_t)c->mem->used - 1) { chunk_finished = 1; } - + break; } case FILE_CHUNK: { @@ -175,7 +175,7 @@ int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chu stat_cache_entry *sce = NULL; int ifd; int write_wait = 0; - + 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); @@ -189,13 +189,13 @@ int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chu do { off_t offset = c->file.start + c->offset; - off_t toSend = c->file.length - c->offset; + off_t toSend = c->file.length - c->offset; if (toSend > LOCAL_SEND_BUFSIZE) toSend = LOCAL_SEND_BUFSIZE; - + if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) { log_error_write(srv, __FILE__, __LINE__, "ss", "open failed:", strerror(errno)); - + return -1; } @@ -208,9 +208,9 @@ int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chu } s = local_send_buffer; - + close(ifd); - + if ((r = SSL_write(ssl, s, toSend)) <= 0) { unsigned long err; @@ -222,7 +222,7 @@ int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chu /* perhaps we have error waiting in our error-queue */ if (0 != (err = ERR_get_error())) { do { - log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:", + log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:", ssl_r, r, ERR_error_string(err, NULL)); } while((err = ERR_get_error())); @@ -232,58 +232,58 @@ int network_write_chunkqueue_openssl(server *srv, connection *con, SSL *ssl, chu case EPIPE: return -2; default: - log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:", + log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL:", ssl_r, r, errno, strerror(errno)); break; } } else { /* neither error-queue nor errno ? */ - log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):", + log_error_write(srv, __FILE__, __LINE__, "sddds", "SSL (error):", ssl_r, r, errno, strerror(errno)); } - + return -1; case SSL_ERROR_ZERO_RETURN: /* clean shutdown on the remote side */ - + if (r == 0) return -2; - + /* fall thourgh */ default: while((err = ERR_get_error())) { - log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:", + log_error_write(srv, __FILE__, __LINE__, "sdds", "SSL:", ssl_r, r, ERR_error_string(err, NULL)); } - + return -1; } } else { c->offset += r; cq->bytes_out += r; } - + if (c->offset == c->file.length) { chunk_finished = 1; } } while(!chunk_finished && !write_wait); - + break; } default: log_error_write(srv, __FILE__, __LINE__, "s", "type not known"); - + return -1; } - + if (!chunk_finished) { /* not finished yet */ - + break; } - + chunks_written++; } diff --git a/src/network_solaris_sendfilev.c b/src/network_solaris_sendfilev.c index 0ab669f..fcb7d10 100644 --- a/src/network_solaris_sendfilev.c +++ b/src/network_solaris_sendfilev.c @@ -29,11 +29,11 @@ #endif /** - * a very simple sendfilev() interface for solaris which can be optimised a lot more + * a very simple sendfilev() interface for solaris which can be optimised a lot more * as solaris sendfilev() supports 'sending everythin in one syscall()' - * - * If you want such an interface and need the performance, just give me an account on - * a solaris box. + * + * If you want such an interface and need the performance, just give me an account on + * a solaris box. * - jan@kneschke.de */ @@ -41,31 +41,31 @@ int network_write_chunkqueue_solarissendfilev(server *srv, connection *con, int fd, chunkqueue *cq) { chunk *c; size_t chunks_written = 0; - + for(c = cq->first; c; c = c->next, chunks_written++) { int chunk_finished = 0; - + switch(c->type) { case MEM_CHUNK: { char * offset; size_t toSend; ssize_t r; - + size_t num_chunks, i; struct iovec chunks[UIO_MAXIOV]; chunk *tc; - + size_t num_bytes = 0; - + /* we can't send more then SSIZE_MAX bytes in one chunk */ - - /* build writev list - * + + /* build writev list + * * 1. limit: num_chunks < UIO_MAXIOV * 2. limit: num_bytes < SSIZE_MAX */ for(num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < UIO_MAXIOV; num_chunks++, tc = tc->next); - + for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) { if (tc->mem->used == 0) { chunks[i].iov_base = tc->mem->ptr; @@ -73,24 +73,24 @@ int network_write_chunkqueue_solarissendfilev(server *srv, connection *con, int } else { offset = tc->mem->ptr + tc->offset; toSend = tc->mem->used - 1 - tc->offset; - + chunks[i].iov_base = offset; - + /* protect the return value of writev() */ if (toSend > SSIZE_MAX || num_bytes + toSend > SSIZE_MAX) { chunks[i].iov_len = SSIZE_MAX - num_bytes; - + num_chunks = i + 1; break; } else { chunks[i].iov_len = toSend; } - + num_bytes += toSend; } } - + if ((r = writev(fd, chunks, num_chunks)) < 0) { switch (errno) { case EAGAIN: @@ -101,22 +101,22 @@ int network_write_chunkqueue_solarissendfilev(server *srv, connection *con, int case ECONNRESET: return -2; default: - log_error_write(srv, __FILE__, __LINE__, "ssd", + log_error_write(srv, __FILE__, __LINE__, "ssd", "writev failed:", strerror(errno), fd); - + return -1; } } - + /* check which chunks have been written */ cq->bytes_out += r; - + for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) { if (r >= (ssize_t)chunks[i].iov_len) { /* written */ r -= chunks[i].iov_len; tc->offset += chunks[i].iov_len; - + if (chunk_finished) { /* skip the chunks from further touches */ chunks_written++; @@ -127,14 +127,14 @@ int network_write_chunkqueue_solarissendfilev(server *srv, connection *con, int } } else { /* partially written */ - + tc->offset += r; chunk_finished = 0; - + break; } } - + break; } case FILE_CHUNK: { @@ -144,25 +144,25 @@ int network_write_chunkqueue_solarissendfilev(server *srv, connection *con, int sendfilevec_t fvec; 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; } - + 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; } if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) { log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno)); - + return -1; } @@ -170,39 +170,39 @@ int network_write_chunkqueue_solarissendfilev(server *srv, connection *con, int fvec.sfv_flag = 0; fvec.sfv_off = offset; fvec.sfv_len = toSend; - + /* Solaris sendfilev() */ if (-1 == (r = sendfilev(fd, &fvec, 1, &written))) { if (errno != EAGAIN) { log_error_write(srv, __FILE__, __LINE__, "ssd", "sendfile: ", strerror(errno), errno); - + close(ifd); return -1; } - + r = 0; } - + close(ifd); c->offset += written; cq->bytes_out += written; - + if (c->offset == c->file.length) { chunk_finished = 1; } - + break; } default: - + log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known"); - + return -1; } - + if (!chunk_finished) { /* not finished yet */ - + break; } } diff --git a/src/network_write.c b/src/network_write.c index 90fc2ac..7fb52cb 100644 --- a/src/network_write.c +++ b/src/network_write.c @@ -27,44 +27,44 @@ int network_write_chunkqueue_write(server *srv, connection *con, int fd, chunkqueue *cq) { 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 +#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; } #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,34 +76,34 @@ int network_write_chunkqueue_write(server *srv, connection *con, int fd, chunkqu 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; } - + 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; } if (-1 == (ifd = open(c->file.name->ptr, O_RDONLY))) { log_error_write(srv, __FILE__, __LINE__, "ss", "open failed: ", strerror(errno)); - + return -1; } - + #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; } close(ifd); @@ -113,48 +113,48 @@ int network_write_chunkqueue_write(server *srv, connection *con, int fd, chunkqu munmap(p, sce->st.st_size); return -1; } - + 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; } 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; } #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; } - + if (!chunk_finished) { /* not finished yet */ - + break; } - + chunks_written++; } diff --git a/src/network_writev.c b/src/network_writev.c index 5fdec8c..d628f75 100644 --- a/src/network_writev.c +++ b/src/network_writev.c @@ -33,16 +33,16 @@ int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkqueue *cq) { 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; - + size_t num_chunks, i; struct iovec *chunks; chunk *tc; @@ -55,21 +55,23 @@ int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkq const size_t max_chunks = MAX_IOVEC; #elif defined(UIO_MAXIOV) /* Linux x86 (glibc-2.2.5-233) */ const size_t max_chunks = UIO_MAXIOV; +#elif (defined(__FreeBSD__) && __FreeBSD_version < 500000) /* FreeBSD 4.x */ + const size_t max_chunks = 1024; /* UIO_MAXIOV value from sys/uio.h */ #else #error "sysconf() doesnt return _SC_IOV_MAX ..., check the output of 'man writev' for the EINVAL error and send the output to jan@kneschke.de" #endif /* we can't send more then SSIZE_MAX bytes in one chunk */ - - /* build writev list - * + + /* build writev list + * * 1. limit: num_chunks < max_chunks * 2. limit: num_bytes < SSIZE_MAX */ for (num_chunks = 0, tc = c; tc && tc->type == MEM_CHUNK && num_chunks < max_chunks; num_chunks++, tc = tc->next); chunks = calloc(num_chunks, sizeof(*chunks)); - + for(tc = c, i = 0; i < num_chunks; tc = tc->next, i++) { if (tc->mem->used == 0) { chunks[i].iov_base = tc->mem->ptr; @@ -77,24 +79,24 @@ int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkq } else { offset = tc->mem->ptr + tc->offset; toSend = tc->mem->used - 1 - tc->offset; - + chunks[i].iov_base = offset; - + /* protect the return value of writev() */ if (toSend > SSIZE_MAX || num_bytes + toSend > SSIZE_MAX) { chunks[i].iov_len = SSIZE_MAX - num_bytes; - + num_chunks = i + 1; break; } else { chunks[i].iov_len = toSend; } - + num_bytes += toSend; } } - + if ((r = writev(fd, chunks, num_chunks)) < 0) { switch (errno) { case EAGAIN: @@ -106,24 +108,24 @@ int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkq free(chunks); return -2; default: - log_error_write(srv, __FILE__, __LINE__, "ssd", + log_error_write(srv, __FILE__, __LINE__, "ssd", "writev failed:", strerror(errno), fd); - + free(chunks); return -1; } } - + cq->bytes_out += r; /* check which chunks have been written */ - + for(i = 0, tc = c; i < num_chunks; i++, tc = tc->next) { if (r >= (ssize_t)chunks[i].iov_len) { /* written */ r -= chunks[i].iov_len; tc->offset += chunks[i].iov_len; - + if (chunk_finished) { /* skip the chunks from further touches */ chunks_written++; @@ -134,7 +136,7 @@ int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkq } } else { /* partially written */ - + tc->offset += r; chunk_finished = 0; @@ -142,7 +144,7 @@ int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkq } } free(chunks); - + break; } case FILE_CHUNK: { @@ -154,7 +156,7 @@ int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkq #define KByte * 1024 #define MByte * 1024 KByte #define GByte * 1024 MByte - const off_t we_want_to_mmap = 512 KByte; + const off_t we_want_to_mmap = 512 KByte; char *start = NULL; if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) { @@ -164,16 +166,16 @@ int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkq } abs_offset = c->file.start + c->offset; - + if (abs_offset > sce->st.st_size) { - log_error_write(srv, __FILE__, __LINE__, "sb", + log_error_write(srv, __FILE__, __LINE__, "sb", "file was shrinked:", c->file.name); - + return -1; } - /* mmap the buffer - * - first mmap + /* mmap the buffer + * - first mmap * - new mmap as the we are at the end of the last one */ if (c->file.mmap.start == MAP_FAILED || abs_offset == (off_t)(c->file.mmap.offset + c->file.mmap.length)) { @@ -183,7 +185,7 @@ int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkq * adaptive mem-mapping * the problem: * we mmap() the whole file. If someone has alot large files and 32bit - * machine the virtual address area will be unrun and we will have a failing + * machine the virtual address area will be unrun and we will have a failing * mmap() call. * solution: * only mmap 16M in one chunk and move the window as soon as we have finished @@ -229,7 +231,7 @@ int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkq if (-1 == c->file.fd) { /* open the file if not already open */ if (-1 == (c->file.fd = open(c->file.name->ptr, O_RDONLY))) { log_error_write(srv, __FILE__, __LINE__, "sbs", "open failed for:", c->file.name, strerror(errno)); - + return -1; } #ifdef FD_CLOEXEC @@ -240,7 +242,7 @@ int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkq if (MAP_FAILED == (c->file.mmap.start = mmap(0, to_mmap, PROT_READ, MAP_SHARED, c->file.fd, c->file.mmap.offset))) { /* close it here, otherwise we'd have to set FD_CLOEXEC */ - 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); return -1; @@ -253,7 +255,7 @@ int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkq #ifdef HAVE_MADVISE /* don't advise files < 64Kb */ if (c->file.mmap.length > (64 KByte)) { - /* darwin 7 is returning EINVAL all the time and I don't know how to + /* darwin 7 is returning EINVAL all the time and I don't know how to * detect this at runtime.i * * ignore the return value for now */ @@ -269,12 +271,12 @@ int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkq toSend = (c->file.mmap.offset + c->file.mmap.length) - (abs_offset); if (toSend < 0) { - log_error_write(srv, __FILE__, __LINE__, "soooo", + log_error_write(srv, __FILE__, __LINE__, "soooo", "toSend is negative:", toSend, c->file.mmap.length, abs_offset, - c->file.mmap.offset); + c->file.mmap.offset); assert(toSend < 0); } @@ -294,16 +296,16 @@ int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkq case ECONNRESET: return -2; default: - log_error_write(srv, __FILE__, __LINE__, "ssd", + log_error_write(srv, __FILE__, __LINE__, "ssd", "write failed:", strerror(errno), fd); - + return -1; } } - + c->offset += r; cq->bytes_out += r; - + if (c->offset == c->file.length) { chunk_finished = 1; @@ -313,22 +315,22 @@ int network_write_chunkqueue_writev(server *srv, connection *con, int fd, chunkq c->file.mmap.start = MAP_FAILED; } } - + break; } default: - + log_error_write(srv, __FILE__, __LINE__, "ds", c, "type not known"); - + return -1; } - + if (!chunk_finished) { /* not finished yet */ - + break; } - + chunks_written++; } diff --git a/src/plugin.c b/src/plugin.c index e74d8b0..faf5520 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -17,23 +17,23 @@ #include <dlfcn.h> #endif /* - * + * * if you change this enum to add a new callback, be sure * - that PLUGIN_FUNC_SIZEOF is the last entry * - that you add PLUGIN_TO_SLOT twice: - * 1. as callback-dispatcher + * 1. as callback-dispatcher * 2. in plugins_call_init() - * + * */ typedef struct { PLUGIN_DATA; } plugin_data; -typedef enum { +typedef enum { PLUGIN_FUNC_UNSET, - PLUGIN_FUNC_HANDLE_URI_CLEAN, - PLUGIN_FUNC_HANDLE_URI_RAW, + PLUGIN_FUNC_HANDLE_URI_CLEAN, + PLUGIN_FUNC_HANDLE_URI_RAW, PLUGIN_FUNC_HANDLE_REQUEST_DONE, PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE, PLUGIN_FUNC_HANDLE_TRIGGER, @@ -44,18 +44,18 @@ typedef enum { PLUGIN_FUNC_HANDLE_DOCROOT, PLUGIN_FUNC_HANDLE_PHYSICAL, PLUGIN_FUNC_CONNECTION_RESET, - PLUGIN_FUNC_INIT, + PLUGIN_FUNC_INIT, PLUGIN_FUNC_CLEANUP, PLUGIN_FUNC_SET_DEFAULTS, - + PLUGIN_FUNC_SIZEOF } plugin_t; static plugin *plugin_init(void) { plugin *p; - + p = calloc(1, sizeof(*p)); - + return p; } @@ -67,7 +67,7 @@ static void plugin_free(plugin *p) { #endif #ifndef LIGHTTPD_STATIC - if (use_dlclose && p->lib) { + if (use_dlclose && p->lib) { #ifdef __WIN32 FreeLibrary(p->lib); #else @@ -75,7 +75,7 @@ static void plugin_free(plugin *p) { #endif } #endif - + free(p); } @@ -89,17 +89,17 @@ static int plugins_register(server *srv, plugin *p) { srv->plugins.size += 4; srv->plugins.ptr = realloc(srv->plugins.ptr, srv->plugins.size * sizeof(*ps)); } - + ps = srv->plugins.ptr; ps[srv->plugins.used++] = p; - + return 0; } /** - * - * - * + * + * + * */ #ifdef LIGHTTPD_STATIC @@ -124,11 +124,11 @@ int plugins_load(server *srv) { int (*init)(plugin *pl); const char *error; size_t i; - + for (i = 0; i < srv->srvconf.modules->used; i++) { data_string *d = (data_string *)srv->srvconf.modules->data[i]; char *modules = d->value->ptr; - + buffer_copy_string_buffer(srv->tmp_buf, srv->srvconf.modules_dir); buffer_append_string(srv->tmp_buf, "/"); @@ -138,13 +138,13 @@ int plugins_load(server *srv) { #else buffer_append_string(srv->tmp_buf, ".so"); #endif - + p = plugin_init(); #ifdef __WIN32 if (NULL == (p->lib = LoadLibrary(srv->tmp_buf->ptr))) { LPVOID lpMsgBuf; FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), @@ -152,24 +152,24 @@ int plugins_load(server *srv) { (LPTSTR) &lpMsgBuf, 0, NULL ); - log_error_write(srv, __FILE__, __LINE__, "ssb", "LoadLibrary() failed", + log_error_write(srv, __FILE__, __LINE__, "ssb", "LoadLibrary() failed", lpMsgBuf, srv->tmp_buf); - + plugin_free(p); - + return -1; } -#else - if (NULL == (p->lib = dlopen(srv->tmp_buf->ptr, RTLD_LAZY))) { - log_error_write(srv, __FILE__, __LINE__, "sbs", "dlopen() failed for:", +#else + if (NULL == (p->lib = dlopen(srv->tmp_buf->ptr, RTLD_NOW|RTLD_GLOBAL))) { + log_error_write(srv, __FILE__, __LINE__, "sbs", "dlopen() failed for:", srv->tmp_buf, dlerror()); - + plugin_free(p); - + return -1; } - + #endif buffer_reset(srv->tmp_buf); buffer_copy_string(srv->tmp_buf, modules); @@ -181,7 +181,7 @@ int plugins_load(server *srv) { if (init == NULL) { LPVOID lpMsgBuf; FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), @@ -190,7 +190,7 @@ int plugins_load(server *srv) { 0, NULL ); log_error_write(srv, __FILE__, __LINE__, "sbs", "getprocaddress failed:", srv->tmp_buf, lpMsgBuf); - + plugin_free(p); return -1; } @@ -203,15 +203,15 @@ int plugins_load(server *srv) { #endif if ((error = dlerror()) != NULL) { log_error_write(srv, __FILE__, __LINE__, "s", error); - + plugin_free(p); return -1; } - + #endif if ((*init)(p)) { log_error_write(srv, __FILE__, __LINE__, "ss", modules, "plugin init failed" ); - + plugin_free(p); return -1; } @@ -220,7 +220,7 @@ int plugins_load(server *srv) { #endif plugins_register(srv, p); } - + return 0; } #endif @@ -253,8 +253,8 @@ int plugins_load(server *srv) { } /** - * plugins that use - * + * plugins that use + * * - server *srv * - connection *con * - void *p_d (plugin_data *) @@ -301,12 +301,12 @@ PLUGIN_TO_SLOT(PLUGIN_FUNC_CONNECTION_RESET, connection_reset) } /** - * plugins that use - * + * plugins that use + * * - server *srv * - void *p_d (plugin_data *) */ - + PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_TRIGGER, handle_trigger) PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_SIGHUP, handle_sighup) PLUGIN_TO_SLOT(PLUGIN_FUNC_CLEANUP, cleanup) @@ -314,18 +314,18 @@ PLUGIN_TO_SLOT(PLUGIN_FUNC_SET_DEFAULTS, set_defaults) #undef PLUGIN_TO_SLOT -#if 0 +#if 0 /** - * + * * special handler - * + * */ handler_t plugins_call_handle_fdevent(server *srv, const fd_conn *fdc) { size_t i; plugin **ps; - + ps = srv->plugins.ptr; - + for (i = 0; i < srv->plugins.used; i++) { plugin *p = ps[i]; if (p->handle_fdevent) { @@ -344,34 +344,34 @@ handler_t plugins_call_handle_fdevent(server *srv, const fd_conn *fdc) { } } } - + return HANDLER_GO_ON; } #endif /** - * + * * - call init function of all plugins to init the plugin-internals * - added each plugin that supports has callback to the corresponding slot - * + * * - is only called once. */ handler_t plugins_call_init(server *srv) { size_t i; plugin **ps; - + ps = srv->plugins.ptr; - + /* fill slots */ - + srv->plugin_slots = calloc(PLUGIN_FUNC_SIZEOF, sizeof(ps)); - + for (i = 0; i < srv->plugins.used; i++) { size_t j; /* check which calls are supported */ - + plugin *p = ps[i]; - + #define PLUGIN_TO_SLOT(x, y) \ if (p->y) { \ plugin **slot = ((plugin ***)(srv->plugin_slots))[x]; \ @@ -384,11 +384,11 @@ handler_t plugins_call_init(server *srv) { slot[j] = p;\ break;\ }\ - } - - - PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_CLEAN, handle_uri_clean); - PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_RAW, handle_uri_raw); + } + + + PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_CLEAN, handle_uri_clean); + PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_URI_RAW, handle_uri_raw); PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_REQUEST_DONE, handle_request_done); PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_CONNECTION_CLOSE, handle_connection_close); PLUGIN_TO_SLOT(PLUGIN_FUNC_HANDLE_TRIGGER, handle_trigger); @@ -402,19 +402,19 @@ handler_t plugins_call_init(server *srv) { PLUGIN_TO_SLOT(PLUGIN_FUNC_CLEANUP, cleanup); PLUGIN_TO_SLOT(PLUGIN_FUNC_SET_DEFAULTS, set_defaults); #undef PLUGIN_TO_SLOT - + if (p->init) { if (NULL == (p->data = p->init())) { - log_error_write(srv, __FILE__, __LINE__, "sb", + log_error_write(srv, __FILE__, __LINE__, "sb", "plugin-init failed for module", p->name); return HANDLER_ERROR; } - + /* used for con->mode, DIRECT == 0, plugins above that */ ((plugin_data *)(p->data))->id = i + 1; - + if (p->version != LIGHTTPD_VERSION_ID) { - log_error_write(srv, __FILE__, __LINE__, "sb", + log_error_write(srv, __FILE__, __LINE__, "sb", "plugin-version doesn't match lighttpd-version for", p->name); return HANDLER_ERROR; } @@ -422,29 +422,29 @@ handler_t plugins_call_init(server *srv) { p->data = NULL; } } - + return HANDLER_GO_ON; } void plugins_free(server *srv) { size_t i; plugins_call_cleanup(srv); - + for (i = 0; i < srv->plugins.used; i++) { plugin *p = ((plugin **)srv->plugins.ptr)[i]; - + plugin_free(p); } - + for (i = 0; srv->plugin_slots && i < PLUGIN_FUNC_SIZEOF; i++) { plugin **slot = ((plugin ***)(srv->plugin_slots))[i]; - + if (slot) free(slot); } - + free(srv->plugin_slots); srv->plugin_slots = NULL; - + free(srv->plugins.ptr); srv->plugins.ptr = NULL; srv->plugins.used = 0; diff --git a/src/plugin.h b/src/plugin.h index b43129a..aa64bee 100644 --- a/src/plugin.h +++ b/src/plugin.h @@ -25,19 +25,19 @@ #define URIHANDLER_FUNC CONNECTION_FUNC #define PLUGIN_DATA size_t id - + typedef struct { size_t version; - + buffer *name; /* name of the plugin */ - + void *(* init) (); handler_t (* set_defaults) (server *srv, void *p_d); handler_t (* cleanup) (server *srv, void *p_d); /* is called ... */ handler_t (* handle_trigger) (server *srv, void *p_d); /* once a second */ handler_t (* handle_sighup) (server *srv, void *p_d); /* at a signup */ - + handler_t (* handle_uri_raw) (server *srv, connection *con, void *p_d); /* after uri_raw is set */ handler_t (* handle_uri_clean) (server *srv, connection *con, void *p_d); /* after uri is set */ handler_t (* handle_docroot) (server *srv, connection *con, void *p_d); /* getting the document-root */ @@ -45,18 +45,18 @@ typedef struct { handler_t (* handle_request_done) (server *srv, connection *con, void *p_d); /* at the end of a request */ handler_t (* handle_connection_close)(server *srv, connection *con, void *p_d); /* at the end of a connection */ handler_t (* handle_joblist) (server *srv, connection *con, void *p_d); /* after all events are handled */ - - - - handler_t (* handle_subrequest_start)(server *srv, connection *con, void *p_d); - - /* when a handler for the request + + + + handler_t (* handle_subrequest_start)(server *srv, connection *con, void *p_d); + + /* when a handler for the request * has to be found */ handler_t (* handle_subrequest) (server *srv, connection *con, void *p_d); /* */ handler_t (* connection_reset) (server *srv, connection *con, void *p_d); /* */ void *data; - + /* dlopen handle */ void *lib; } plugin; diff --git a/src/request.c b/src/request.c index f539c80..eb35332 100644 --- a/src/request.c +++ b/src/request.c @@ -16,9 +16,9 @@ static int request_check_hostname(server *srv, connection *con, buffer *host) { int label_len = 0; size_t host_len; char *colon; - int is_ip = -1; /* -1 don't know yet, 0 no, 1 yes */ + int is_ip = -1; /* -1 don't know yet, 0 no, 1 yes */ int level = 0; - + UNUSED(srv); UNUSED(con); @@ -32,17 +32,17 @@ static int request_check_hostname(server *srv, connection *con, buffer *host) { * IPv6address = "[" ... "]" * port = *digit */ - + /* no Host: */ if (!host || host->used == 0) return 0; - + host_len = host->used - 1; - + /* IPv6 adress */ if (host->ptr[0] == '[') { char *c = host->ptr + 1; int colon_cnt = 0; - + /* check portnumber */ for (; *c && *c != ']'; c++) { if (*c == ':') { @@ -53,12 +53,12 @@ static int request_check_hostname(server *srv, connection *con, buffer *host) { return -1; } } - + /* missing ] */ if (!*c) { return -1; } - + /* check port */ if (*(c+1) == ':') { for (c += 2; *c; c++) { @@ -69,39 +69,39 @@ static int request_check_hostname(server *srv, connection *con, buffer *host) { } return 0; } - + if (NULL != (colon = memchr(host->ptr, ':', host_len))) { char *c = colon + 1; - + /* check portnumber */ for (; *c; c++) { if (!light_isdigit(*c)) return -1; } - + /* remove the port from the host-len */ host_len = colon - host->ptr; } - + /* Host is empty */ if (host_len == 0) return -1; - + /* scan from the right and skip the \0 */ for (i = host_len - 1; i + 1 > 0; i--) { const char c = host->ptr[i]; switch (stage) { - case TOPLABEL: + case TOPLABEL: if (c == '.') { /* only switch stage, if this is not the last character */ if (i != host_len - 1) { if (label_len == 0) { return -1; } - + /* check the first character at right of the dot */ if (is_ip == 0) { if (!light_isalpha(host->ptr[i+1])) { - return -1; + return -1; } } else if (!light_isdigit(host->ptr[i+1])) { is_ip = 0; @@ -111,9 +111,9 @@ static int request_check_hostname(server *srv, connection *con, buffer *host) { /* just digits */ is_ip = 1; } - + stage = DOMAINLABEL; - + label_len = 0; level++; } else if (i == 0) { @@ -135,7 +135,7 @@ static int request_check_hostname(server *srv, connection *con, buffer *host) { } label_len++; } - + break; case DOMAINLABEL: if (is_ip == 1) { @@ -143,7 +143,7 @@ static int request_check_hostname(server *srv, connection *con, buffer *host) { if (label_len == 0) { return -1; } - + label_len = 0; level++; } else if (!light_isdigit(c)) { @@ -156,12 +156,12 @@ static int request_check_hostname(server *srv, connection *con, buffer *host) { if (label_len == 0) { return -1; } - + /* c is either - or alphanum here */ if ('-' == host->ptr[i+1]) { return -1; } - + label_len = 0; level++; } else if (i == 0) { @@ -176,20 +176,20 @@ static int request_check_hostname(server *srv, connection *con, buffer *host) { label_len++; } } - + break; } } - + /* a IP has to consist of 4 parts */ if (is_ip == 1 && level != 3) { return -1; } - + if (label_len == 0) { return -1; } - + return 0; } @@ -201,53 +201,53 @@ int http_request_split_value(array *vals, buffer *b) { char *s; size_t i; int state = 0; - /* - * parse - * + /* + * parse + * * val1, val2, val3, val4 - * + * * into a array (more or less a explode() incl. striping of whitespaces */ - + if (b->used == 0) return 0; - + s = b->ptr; - + for (i =0; i < b->used - 1; ) { char *start = NULL, *end = NULL; data_string *ds; - + switch (state) { case 0: /* ws */ - + /* skip ws */ for (; (*s == ' ' || *s == '\t') && i < b->used - 1; i++, s++); - - + + state = 1; break; case 1: /* value */ start = s; - + for (; *s != ',' && i < b->used - 1; i++, s++); end = s - 1; - + for (; (*end == ' ' || *end == '\t') && end > start; end--); - + if (NULL == (ds = (data_string *)array_get_unused_element(vals, TYPE_STRING))) { ds = data_string_init(); } buffer_copy_string_len(ds->value, start, end-start+1); array_insert_unique(vals, (data_unset *)ds); - + if (*s == ',') { state = 0; i++; s++; } else { /* end of string */ - + state = 2; } break; @@ -263,7 +263,7 @@ int request_uri_is_valid_char(unsigned char c) { if (c <= 32) return 0; if (c == 127) return 0; if (c == 255) return 0; - + return 1; } @@ -271,28 +271,28 @@ int http_request_parse(server *srv, connection *con) { char *uri = NULL, *proto = NULL, *method = NULL, con_length_set; int is_key = 1, key_len = 0, is_ws_after_key = 0, in_folding; char *value = NULL, *key = NULL; - + enum { HTTP_CONNECTION_UNSET, HTTP_CONNECTION_KEEPALIVE, HTTP_CONNECTION_CLOSE } keep_alive_set = HTTP_CONNECTION_UNSET; - + int line = 0; - + int request_line_stage = 0; size_t i, first; - + int done = 0; - + data_string *ds = NULL; - - /* - * Request: "^(GET|POST|HEAD) ([^ ]+(\\?[^ ]+|)) (HTTP/1\\.[01])$" - * Option : "^([-a-zA-Z]+): (.+)$" + + /* + * Request: "^(GET|POST|HEAD) ([^ ]+(\\?[^ ]+|)) (HTTP/1\\.[01])$" + * Option : "^([-a-zA-Z]+): (.+)$" * End : "^$" */ if (con->conf.log_request_header) { - log_error_write(srv, __FILE__, __LINE__, "sdsdSb", - "fd:", con->fd, - "request-len:", con->request.request->used, + log_error_write(srv, __FILE__, __LINE__, "sdsdSb", + "fd:", con->fd, + "request-len:", con->request.request->used, "\n", con->request.request); } @@ -300,13 +300,13 @@ int http_request_parse(server *srv, connection *con) { con->request.request->ptr[0] == '\r' && con->request.request->ptr[1] == '\n') { /* we are in keep-alive and might get \r\n after a previous POST request.*/ - + buffer_copy_string_len(con->parse_request, con->request.request->ptr + 2, con->request.request->used - 1 - 2); } else { /* fill the local request buffer */ buffer_copy_string_buffer(con->parse_request, con->request.request); } - + keep_alive_set = 0; con_length_set = 0; @@ -318,25 +318,25 @@ int http_request_parse(server *srv, connection *con) { * */ for (i = 0, first = 0; i < con->parse_request->used && line == 0; i++) { char *cur = con->parse_request->ptr + i; - + switch(*cur) { - case '\r': + case '\r': if (con->parse_request->ptr[i+1] == '\n') { http_method_t r; char *nuri = NULL; size_t j; - + /* \r\n -> \0\0 */ con->parse_request->ptr[i] = '\0'; con->parse_request->ptr[i+1] = '\0'; - + buffer_copy_string_len(con->request.request_line, con->parse_request->ptr, i); - + if (request_line_stage != 2) { con->http_status = 400; con->response.keep_alive = 0; con->keep_alive = 0; - + if (srv->srvconf.log_request_header_on_error) { log_error_write(srv, __FILE__, __LINE__, "s", "incomplete request line -> 400"); log_error_write(srv, __FILE__, __LINE__, "Sb", @@ -345,36 +345,36 @@ int http_request_parse(server *srv, connection *con) { } return 0; } - + proto = con->parse_request->ptr + first; - + *(uri - 1) = '\0'; *(proto - 1) = '\0'; - + /* we got the first one :) */ if (-1 == (r = get_http_method_key(method))) { con->http_status = 501; con->response.keep_alive = 0; con->keep_alive = 0; - + if (srv->srvconf.log_request_header_on_error) { log_error_write(srv, __FILE__, __LINE__, "s", "unknown http-method -> 501"); log_error_write(srv, __FILE__, __LINE__, "Sb", "request-header:\n", con->request.request); } - + return 0; } - + con->request.http_method = r; - - /* + + /* * RFC2616 says: * * HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT * - * */ + * */ if (0 == strncmp(proto, "HTTP/", sizeof("HTTP/") - 1)) { char * major = proto + sizeof("HTTP/") - 1; char * minor = strchr(major, '.'); @@ -416,7 +416,7 @@ int http_request_parse(server *srv, connection *con) { con->request.http_version = con->conf.allow_http11 ? HTTP_VERSION_1_1 : HTTP_VERSION_1_0; } else if (major_num == 1 && minor_num == 0) { con->request.http_version = HTTP_VERSION_1_0; - } else { + } else { con->http_status = 505; if (srv->srvconf.log_request_header_on_error) { @@ -439,30 +439,30 @@ int http_request_parse(server *srv, connection *con) { } return 0; } - + if (0 == strncmp(uri, "http://", 7) && NULL != (nuri = strchr(uri + 7, '/'))) { /* ignore the host-part */ - + buffer_copy_string_len(con->request.uri, nuri, proto - nuri - 1); } else { /* everything looks good so far */ buffer_copy_string_len(con->request.uri, uri, proto - uri - 1); } - + /* check uri for invalid characters */ for (j = 0; j < con->request.uri->used - 1; j++) { if (!request_uri_is_valid_char(con->request.uri->ptr[j])) { unsigned char buf[2]; con->http_status = 400; con->keep_alive = 0; - + if (srv->srvconf.log_request_header_on_error) { buf[0] = con->request.uri->ptr[j]; buf[1] = '\0'; - + if (con->request.uri->ptr[j] > 32 && - con->request.uri->ptr[j] != 127) { + con->request.uri->ptr[j] != 127) { /* the character is printable -> print it */ log_error_write(srv, __FILE__, __LINE__, "ss", "invalid character in URI -> 400", @@ -473,20 +473,20 @@ int http_request_parse(server *srv, connection *con) { "invalid character in URI -> 400", con->request.uri->ptr[j]); } - + log_error_write(srv, __FILE__, __LINE__, "Sb", "request-header:\n", con->request.request); } - + return 0; } } - + buffer_copy_string_buffer(con->request.orig_uri, con->request.uri); - + con->http_status = 0; - + i++; line++; first = i+1; @@ -494,14 +494,14 @@ int http_request_parse(server *srv, connection *con) { break; case ' ': switch(request_line_stage) { - case 0: + case 0: /* GET|POST|... */ - method = con->parse_request->ptr + first; + method = con->parse_request->ptr + first; first = i + 1; break; case 1: /* /foobar/... */ - uri = con->parse_request->ptr + first; + uri = con->parse_request->ptr + first; first = i + 1; break; default: @@ -509,7 +509,7 @@ int http_request_parse(server *srv, connection *con) { con->http_status = 400; con->response.keep_alive = 0; con->keep_alive = 0; - + if (srv->srvconf.log_request_header_on_error) { log_error_write(srv, __FILE__, __LINE__, "s", "overlong request line -> 400"); log_error_write(srv, __FILE__, __LINE__, "Sb", @@ -518,12 +518,12 @@ int http_request_parse(server *srv, connection *con) { } return 0; } - + request_line_stage++; break; } } - + in_folding = 0; if (con->request.uri->used == 1) { @@ -540,30 +540,30 @@ int http_request_parse(server *srv, connection *con) { return 0; } - + for (; i < con->parse_request->used && !done; i++) { char *cur = con->parse_request->ptr + i; - + if (is_key) { size_t j; int got_colon = 0; - + /** * 1*<any CHAR except CTLs or separators> * CTLs == 0-31 + 127 - * + * */ switch(*cur) { case ':': is_key = 0; - + value = cur + 1; - + if (is_ws_after_key == 0) { key_len = i - first; } is_ws_after_key = 0; - + break; case '(': case ')': @@ -584,8 +584,8 @@ int http_request_parse(server *srv, connection *con) { con->http_status = 400; con->keep_alive = 0; con->response.keep_alive = 0; - - log_error_write(srv, __FILE__, __LINE__, "sbsds", + + log_error_write(srv, __FILE__, __LINE__, "sbsds", "invalid character in key", con->request.request, cur, *cur, "-> 400"); return 0; case ' ': @@ -594,13 +594,13 @@ int http_request_parse(server *srv, connection *con) { is_key = 0; in_folding = 1; value = cur; - + break; } - - + + key_len = i - first; - + /* skip every thing up to the : */ for (j = 1; !got_colon; j++) { switch(con->parse_request->ptr[j + i]) { @@ -610,40 +610,40 @@ int http_request_parse(server *srv, connection *con) { continue; case ':': /* ok, done */ - + i += j - 1; got_colon = 1; - + break; default: /* error */ - + if (srv->srvconf.log_request_header_on_error) { log_error_write(srv, __FILE__, __LINE__, "s", "WS character in key -> 400"); log_error_write(srv, __FILE__, __LINE__, "Sb", "request-header:\n", con->request.request); } - + con->http_status = 400; con->response.keep_alive = 0; con->keep_alive = 0; - + return 0; } } - + break; case '\r': if (con->parse_request->ptr[i+1] == '\n' && i == first) { /* End of Header */ con->parse_request->ptr[i] = '\0'; con->parse_request->ptr[i+1] = '\0'; - + i++; - + done = 1; - + break; } else { if (srv->srvconf.log_request_header_on_error) { @@ -652,7 +652,7 @@ int http_request_parse(server *srv, connection *con) { "request-header:\n", con->request.request); } - + con->http_status = 400; con->keep_alive = 0; con->response.keep_alive = 0; @@ -693,16 +693,16 @@ int http_request_parse(server *srv, connection *con) { con->http_status = 400; con->keep_alive = 0; con->response.keep_alive = 0; - + if (srv->srvconf.log_request_header_on_error) { - log_error_write(srv, __FILE__, __LINE__, "sbsds", + log_error_write(srv, __FILE__, __LINE__, "sbsds", "CTL character in key", con->request.request, cur, *cur, "-> 400"); log_error_write(srv, __FILE__, __LINE__, "Sb", "request-header:\n", con->request.request); } - + return 0; default: /* ok */ @@ -710,25 +710,25 @@ int http_request_parse(server *srv, connection *con) { } } else { switch(*cur) { - case '\r': + case '\r': if (con->parse_request->ptr[i+1] == '\n') { /* End of Headerline */ con->parse_request->ptr[i] = '\0'; con->parse_request->ptr[i+1] = '\0'; - + if (in_folding) { if (!ds) { /* 400 */ - + if (srv->srvconf.log_request_header_on_error) { log_error_write(srv, __FILE__, __LINE__, "s", "WS at the start of first line -> 400"); - + log_error_write(srv, __FILE__, __LINE__, "Sb", "request-header:\n", con->request.request); } - + con->http_status = 400; con->keep_alive = 0; con->response.keep_alive = 0; @@ -738,9 +738,9 @@ int http_request_parse(server *srv, connection *con) { } else { int s_len; key = con->parse_request->ptr + first; - + s_len = cur - value; - + if (s_len > 0) { int cmp = 0; if (NULL == (ds = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) { @@ -748,50 +748,50 @@ int http_request_parse(server *srv, connection *con) { } buffer_copy_string_len(ds->key, key, key_len); buffer_copy_string_len(ds->value, value, s_len); - - /* retreive values - * - * + + /* retreive values + * + * * the list of options is sorted to simplify the search */ - + if (0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Connection")))) { array *vals; size_t vi; - + /* split on , */ - + vals = srv->split_vals; array_reset(vals); - + http_request_split_value(vals, ds->value); - + for (vi = 0; vi < vals->used; vi++) { data_string *dsv = (data_string *)vals->data[vi]; - + if (0 == buffer_caseless_compare(CONST_BUF_LEN(dsv->value), CONST_STR_LEN("keep-alive"))) { keep_alive_set = HTTP_CONNECTION_KEEPALIVE; - + break; } else if (0 == buffer_caseless_compare(CONST_BUF_LEN(dsv->value), CONST_STR_LEN("close"))) { keep_alive_set = HTTP_CONNECTION_CLOSE; - + break; } } - + } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Content-Length")))) { char *err; unsigned long int r; size_t j; - + if (con_length_set) { con->http_status = 400; con->keep_alive = 0; - + if (srv->srvconf.log_request_header_on_error) { - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "duplicate Content-Length-header -> 400"); log_error_write(srv, __FILE__, __LINE__, "Sb", "request-header:\n", @@ -799,35 +799,35 @@ int http_request_parse(server *srv, connection *con) { } return 0; } - + if (ds->value->used == 0) SEGFAULT(); - + for (j = 0; j < ds->value->used - 1; j++) { char c = ds->value->ptr[j]; if (!isdigit((unsigned char)c)) { - log_error_write(srv, __FILE__, __LINE__, "sbs", + log_error_write(srv, __FILE__, __LINE__, "sbs", "content-length broken:", ds->value, "-> 400"); - + con->http_status = 400; con->keep_alive = 0; - + array_insert_unique(con->request.headers, (data_unset *)ds); return 0; } } - + r = strtoul(ds->value->ptr, &err, 10); - + if (*err == '\0') { con_length_set = 1; con->request.content_length = r; } else { - log_error_write(srv, __FILE__, __LINE__, "sbs", + log_error_write(srv, __FILE__, __LINE__, "sbs", "content-length broken:", ds->value, "-> 400"); - + con->http_status = 400; con->keep_alive = 0; - + array_insert_unique(con->request.headers, (data_unset *)ds); return 0; } @@ -838,9 +838,9 @@ int http_request_parse(server *srv, connection *con) { } else { con->http_status = 400; con->keep_alive = 0; - + if (srv->srvconf.log_request_header_on_error) { - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "duplicate Content-Type-header -> 400"); log_error_write(srv, __FILE__, __LINE__, "Sb", "request-header:\n", @@ -849,12 +849,12 @@ int http_request_parse(server *srv, connection *con) { return 0; } } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Expect")))) { - /* HTTP 2616 8.2.3 + /* HTTP 2616 8.2.3 * Expect: 100-continue - * + * * -> (10.1.1) 100 (read content, process request, send final status-code) * -> (10.4.18) 417 (close) - * + * * (not handled at all yet, we always send 417 here) * * What has to be added ? @@ -863,10 +863,10 @@ int http_request_parse(server *srv, connection *con) { * header * */ - + con->http_status = 417; con->keep_alive = 0; - + array_insert_unique(con->request.headers, (data_unset *)ds); return 0; } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Host")))) { @@ -875,9 +875,9 @@ int http_request_parse(server *srv, connection *con) { } else { con->http_status = 400; con->keep_alive = 0; - + if (srv->srvconf.log_request_header_on_error) { - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "duplicate Host-header -> 400"); log_error_write(srv, __FILE__, __LINE__, "Sb", "request-header:\n", @@ -897,9 +897,9 @@ int http_request_parse(server *srv, connection *con) { } else { con->http_status = 400; con->keep_alive = 0; - + if (srv->srvconf.log_request_header_on_error) { - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "duplicate If-Modified-Since header -> 400"); log_error_write(srv, __FILE__, __LINE__, "Sb", "request-header:\n", @@ -914,9 +914,9 @@ int http_request_parse(server *srv, connection *con) { } else { con->http_status = 400; con->keep_alive = 0; - + if (srv->srvconf.log_request_header_on_error) { - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "duplicate If-None-Match-header -> 400"); log_error_write(srv, __FILE__, __LINE__, "Sb", "request-header:\n", @@ -927,19 +927,19 @@ int http_request_parse(server *srv, connection *con) { } else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Range")))) { if (!con->request.http_range) { /* bytes=.*-.* */ - + if (0 == strncasecmp(ds->value->ptr, "bytes=", 6) && NULL != strchr(ds->value->ptr+6, '-')) { - + /* if dup, only the first one will survive */ con->request.http_range = ds->value->ptr + 6; } } else { con->http_status = 400; con->keep_alive = 0; - + if (srv->srvconf.log_request_header_on_error) { - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "duplicate Range-header -> 400"); log_error_write(srv, __FILE__, __LINE__, "Sb", "request-header:\n", @@ -948,13 +948,13 @@ int http_request_parse(server *srv, connection *con) { return 0; } } - + array_insert_unique(con->request.headers, (data_unset *)ds); } else { /* empty header-fields are not allowed by HTTP-RFC, we just ignore them */ } } - + i++; first = i+1; is_key = 1; @@ -963,10 +963,10 @@ int http_request_parse(server *srv, connection *con) { in_folding = 0; } else { if (srv->srvconf.log_request_header_on_error) { - log_error_write(srv, __FILE__, __LINE__, "sbs", + log_error_write(srv, __FILE__, __LINE__, "sbs", "CR without LF", con->request.request, "-> 400"); } - + con->http_status = 400; con->keep_alive = 0; con->response.keep_alive = 0; @@ -982,28 +982,28 @@ int http_request_parse(server *srv, connection *con) { } } } - + con->header_len = i; - + /* do some post-processing */ if (con->request.http_version == HTTP_VERSION_1_1) { if (keep_alive_set != HTTP_CONNECTION_CLOSE) { /* no Connection-Header sent */ - + /* HTTP/1.1 -> keep-alive default TRUE */ con->keep_alive = 1; } else { con->keep_alive = 0; } - + /* RFC 2616, 14.23 */ if (con->request.http_host == NULL || buffer_is_empty(con->request.http_host)) { con->http_status = 400; con->response.keep_alive = 0; con->keep_alive = 0; - + if (srv->srvconf.log_request_header_on_error) { log_error_write(srv, __FILE__, __LINE__, "s", "HTTP/1.1 but Host missing -> 400"); log_error_write(srv, __FILE__, __LINE__, "Sb", @@ -1015,18 +1015,18 @@ int http_request_parse(server *srv, connection *con) { } else { if (keep_alive_set == HTTP_CONNECTION_KEEPALIVE) { /* no Connection-Header sent */ - + /* HTTP/1.0 -> keep-alive default FALSE */ con->keep_alive = 1; } else { con->keep_alive = 0; } } - + /* check hostname field if it is set */ if (NULL != con->request.http_host && 0 != request_check_hostname(srv, con, con->request.http_host)) { - + if (srv->srvconf.log_request_header_on_error) { log_error_write(srv, __FILE__, __LINE__, "s", "Invalid Hostname -> 400"); @@ -1038,7 +1038,7 @@ int http_request_parse(server *srv, connection *con) { con->http_status = 400; con->response.keep_alive = 0; con->keep_alive = 0; - + return 0; } @@ -1048,7 +1048,7 @@ int http_request_parse(server *srv, connection *con) { /* content-length is forbidden for those */ if (con_length_set && con->request.content_length != 0) { /* content-length is missing */ - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "GET/HEAD with content-length -> 400"); con->keep_alive = 0; @@ -1060,7 +1060,7 @@ int http_request_parse(server *srv, connection *con) { /* content-length is required for them */ if (!con_length_set) { /* content-length is missing */ - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "POST-request, but content-length missing -> 411"); con->keep_alive = 0; @@ -1073,16 +1073,16 @@ int http_request_parse(server *srv, connection *con) { /* the may have a content-length */ break; } - - + + /* check if we have read post data */ if (con_length_set) { /* don't handle more the SSIZE_MAX bytes in content-length */ if (con->request.content_length > SSIZE_MAX) { - con->http_status = 413; + con->http_status = 413; con->keep_alive = 0; - log_error_write(srv, __FILE__, __LINE__, "sds", + log_error_write(srv, __FILE__, __LINE__, "sds", "request-size too long:", con->request.content_length, "-> 413"); return 0; } @@ -1090,25 +1090,25 @@ int http_request_parse(server *srv, connection *con) { /* divide by 1024 as srvconf.max_request_size is in kBytes */ if (srv->srvconf.max_request_size != 0 && (con->request.content_length >> 10) > srv->srvconf.max_request_size) { - /* the request body itself is larger then + /* the request body itself is larger then * our our max_request_size */ - + con->http_status = 413; con->keep_alive = 0; - - log_error_write(srv, __FILE__, __LINE__, "sds", + + log_error_write(srv, __FILE__, __LINE__, "sds", "request-size too long:", con->request.content_length, "-> 413"); return 0; } - - + + /* we have content */ if (con->request.content_length != 0) { return 1; } } - + return 0; } @@ -1116,9 +1116,9 @@ int http_request_header_finished(server *srv, connection *con) { UNUSED(srv); if (con->request.request->used < 5) return 0; - + if (0 == memcmp(con->request.request->ptr + con->request.request->used - 5, "\r\n\r\n", 4)) return 1; if (NULL != strstr(con->request.request->ptr, "\r\n\r\n")) return 1; - + return 0; } diff --git a/src/response.c b/src/response.c index 45a1782..5f72a9b 100644 --- a/src/response.c +++ b/src/response.c @@ -30,9 +30,9 @@ int http_response_write_header(server *srv, connection *con) { size_t i; int have_date = 0; int have_server = 0; - + b = chunkqueue_get_prepend_buffer(con->write_queue); - + if (con->request.http_version == HTTP_VERSION_1_1) { BUFFER_COPY_STRING_CONST(b, "HTTP/1.1 "); } else { @@ -41,23 +41,23 @@ int http_response_write_header(server *srv, connection *con) { buffer_append_long(b, con->http_status); BUFFER_APPEND_STRING_CONST(b, " "); buffer_append_string(b, get_http_status_name(con->http_status)); - + if (con->request.http_version != HTTP_VERSION_1_1 || con->keep_alive == 0) { BUFFER_APPEND_STRING_CONST(b, "\r\nConnection: "); buffer_append_string(b, con->keep_alive ? "keep-alive" : "close"); } - + if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) { BUFFER_APPEND_STRING_CONST(b, "\r\nTransfer-Encoding: chunked"); } - - + + /* add all headers */ for (i = 0; i < con->response.headers->used; i++) { data_string *ds; - + ds = (data_string *)con->response.headers->data[i]; - + if (ds->value->used && ds->key->used && 0 != strncmp(ds->key->ptr, "X-LIGHTTPD-", sizeof("X-LIGHTTPD-") - 1)) { if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Date"))) have_date = 1; @@ -68,28 +68,28 @@ int http_response_write_header(server *srv, connection *con) { BUFFER_APPEND_STRING_CONST(b, ": "); buffer_append_string_buffer(b, ds->value); #if 0 - log_error_write(srv, __FILE__, __LINE__, "bb", + log_error_write(srv, __FILE__, __LINE__, "bb", ds->key, ds->value); #endif } } - + if (!have_date) { /* HTTP/1.1 requires a Date: header */ BUFFER_APPEND_STRING_CONST(b, "\r\nDate: "); - + /* cache the generated timestamp */ if (srv->cur_ts != srv->last_generated_date_ts) { buffer_prepare_copy(srv->ts_date_str, 255); - - strftime(srv->ts_date_str->ptr, srv->ts_date_str->size - 1, + + strftime(srv->ts_date_str->ptr, srv->ts_date_str->size - 1, "%a, %d %b %Y %H:%M:%S GMT", gmtime(&(srv->cur_ts))); - + srv->ts_date_str->used = strlen(srv->ts_date_str->ptr) + 1; - + srv->last_generated_date_ts = srv->cur_ts; } - + buffer_append_string_buffer(b, srv->ts_date_str); } @@ -101,16 +101,16 @@ int http_response_write_header(server *srv, connection *con) { buffer_append_string_buffer(b, con->conf.server_tag); } } - + BUFFER_APPEND_STRING_CONST(b, "\r\n\r\n"); - - + + con->bytes_header = b->used - 1; - + if (con->conf.log_response_header) { log_error_write(srv, __FILE__, __LINE__, "sSb", "Response-Header:", "\n", b); } - + return 0; } @@ -118,71 +118,77 @@ int http_response_write_header(server *srv, connection *con) { handler_t http_response_prepare(server *srv, connection *con) { handler_t r; - + /* looks like someone has already done a decision */ - if (con->mode == DIRECT && + if (con->mode == DIRECT && (con->http_status != 0 && con->http_status != 200)) { /* remove a packets in the queue */ if (con->file_finished == 0) { chunkqueue_reset(con->write_queue); } - + return HANDLER_FINISHED; } - + /* no decision yet, build conf->filename */ if (con->mode == DIRECT && con->physical.path->used == 0) { char *qstr; /* we only come here when we have the parse the full request again - * - * a HANDLER_COMEBACK from mod_rewrite and mod_fastcgi might be a + * + * a HANDLER_COMEBACK from mod_rewrite and mod_fastcgi might be a * problem here as mod_setenv might get called multiple times * * fastcgi-auth might lead to a COMEBACK too * fastcgi again dead server too * * mod_compress might add headers twice too - * + * * */ - + if (con->conf.log_condition_handling) { log_error_write(srv, __FILE__, __LINE__, "s", "run condition"); } config_patch_connection(srv, con, COMP_SERVER_SOCKET); /* SERVERsocket */ - + /** * prepare strings - * - * - uri.path_raw + * + * - uri.path_raw * - uri.path (secure) * - uri.query - * + * */ - - /** + + /** * Name according to RFC 2396 - * + * * - scheme * - authority * - path * - query - * - * (scheme)://(authority)(path)?(query) - * - * + * + * (scheme)://(authority)(path)?(query)#fragment + * + * */ - + buffer_copy_string(con->uri.scheme, con->conf.is_ssl ? "https" : "http"); buffer_copy_string_buffer(con->uri.authority, con->request.http_host); buffer_to_lower(con->uri.authority); - + config_patch_connection(srv, con, COMP_HTTP_HOST); /* Host: */ config_patch_connection(srv, con, COMP_HTTP_REMOTEIP); /* Client-IP */ config_patch_connection(srv, con, COMP_HTTP_REFERER); /* Referer: */ config_patch_connection(srv, con, COMP_HTTP_USERAGENT); /* User-Agent: */ config_patch_connection(srv, con, COMP_HTTP_COOKIE); /* Cookie: */ - + + /** their might be a fragment which has to be cut away */ + if (NULL != (qstr = strchr(con->request.uri->ptr, '#'))) { + con->request.uri->used = qstr - con->request.uri->ptr; + con->request.uri->ptr[con->request.uri->used++] = '\0'; + } + /** extract query string from request.uri */ if (NULL != (qstr = strchr(con->request.uri->ptr, '?'))) { buffer_copy_string (con->uri.query, qstr + 1); @@ -200,22 +206,22 @@ handler_t http_response_prepare(server *srv, connection *con) { log_error_write(srv, __FILE__, __LINE__, "sb", "URI-path : ", con->uri.path_raw); log_error_write(srv, __FILE__, __LINE__, "sb", "URI-query : ", con->uri.query); } - + /* disable keep-alive if requested */ - + if (con->request_count > con->conf.max_keep_alive_requests) { con->keep_alive = 0; } - - + + /** - * - * call plugins - * + * + * call plugins + * * - based on the raw URL - * + * */ - + switch(r = plugins_call_handle_uri_raw(srv, con)) { case HANDLER_GO_ON: break; @@ -229,14 +235,14 @@ handler_t http_response_prepare(server *srv, connection *con) { break; } - /* build filename + /* build filename * * - decode url-encodings (e.g. %20 -> ' ') * - remove path-modifiers (e.g. /../) */ - - - + + + if (con->request.http_method == HTTP_METHOD_OPTIONS && con->uri.path_raw->ptr[0] == '*' && con->uri.path_raw->ptr[1] == '\0') { /* OPTIONS * ... */ @@ -253,13 +259,13 @@ handler_t http_response_prepare(server *srv, connection *con) { } /** - * - * call plugins - * + * + * call plugins + * * - based on the clean URL - * + * */ - + config_patch_connection(srv, con, COMP_HTTP_URL); /* HTTPurl */ config_patch_connection(srv, con, COMP_HTTP_QUERYSTRING); /* HTTPqs */ @@ -280,11 +286,11 @@ handler_t http_response_prepare(server *srv, connection *con) { log_error_write(srv, __FILE__, __LINE__, ""); break; } - + if (con->request.http_method == HTTP_METHOD_OPTIONS && con->uri.path->ptr[0] == '*' && con->uri.path_raw->ptr[1] == '\0') { /* option requests are handled directly without checking of the path */ - + response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("OPTIONS, GET, HEAD, POST")); con->http_status = 200; @@ -294,38 +300,38 @@ handler_t http_response_prepare(server *srv, connection *con) { } /*** - * - * border - * + * + * border + * * logical filename (URI) becomes a physical filename here - * - * - * + * + * + * */ - - - - + + + + /* 1. stat() * ... ISREG() -> ok, go on * ... ISDIR() -> index-file -> redirect - * - * 2. pathinfo() + * + * 2. pathinfo() * ... ISREG() - * + * * 3. -> 404 - * + * */ - + /* * SEARCH DOCUMENT ROOT */ - + /* set a default */ - + buffer_copy_string_buffer(con->physical.doc_root, con->conf.document_root); buffer_copy_string_buffer(con->physical.rel_path, con->uri.path); - + #if defined(__WIN32) || defined(__CYGWIN__) /* strip dots from the end and spaces * @@ -383,9 +389,9 @@ handler_t http_response_prepare(server *srv, connection *con) { log_error_write(srv, __FILE__, __LINE__, ""); break; } - - /* MacOS X and Windows can't distiguish between upper and lower-case - * + + /* MacOS X and Windows can't distiguish between upper and lower-case + * * convert to lower-case */ if (con->conf.force_lowercase_filenames) { @@ -396,13 +402,13 @@ handler_t http_response_prepare(server *srv, connection *con) { if (buffer_is_empty(con->server_name)) { buffer_copy_string_buffer(con->server_name, con->uri.authority); } - - /** - * create physical filename + + /** + * create physical filename * -> physical.path = docroot + rel_path - * + * */ - + buffer_copy_string_buffer(con->physical.path, con->physical.doc_root); BUFFER_APPEND_SLASH(con->physical.path); buffer_copy_string_buffer(con->physical.basedir, con->physical.path); @@ -432,7 +438,7 @@ handler_t http_response_prepare(server *srv, connection *con) { log_error_write(srv, __FILE__, __LINE__, ""); break; } - + if (con->conf.log_request_handling) { log_error_write(srv, __FILE__, __LINE__, "s", "-- logical -> physical"); log_error_write(srv, __FILE__, __LINE__, "sb", "Doc-Root :", con->physical.doc_root); @@ -440,19 +446,19 @@ handler_t http_response_prepare(server *srv, connection *con) { log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path); } } - - /* + + /* * Noone catched away the file from normal path of execution yet (like mod_access) - * + * * Go on and check of the file exists at all */ - + if (con->mode == DIRECT) { char *slash = NULL; char *pathinfo = NULL; int found = 0; stat_cache_entry *sce = NULL; - + if (con->conf.log_request_handling) { log_error_write(srv, __FILE__, __LINE__, "s", "-- handling physical path"); log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path); @@ -460,7 +466,7 @@ handler_t http_response_prepare(server *srv, connection *con) { if (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) { /* file exists */ - + if (con->conf.log_request_handling) { log_error_write(srv, __FILE__, __LINE__, "s", "-- file found"); log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path); @@ -481,9 +487,9 @@ handler_t http_response_prepare(server *srv, connection *con) { if (S_ISDIR(sce->st.st_mode)) { if (con->physical.path->ptr[con->physical.path->used - 2] != '/') { /* redirect to .../ */ - + http_response_redirect_to_directory(srv, con); - + return HANDLER_FINISHED; } #ifdef HAVE_LSTAT @@ -499,12 +505,12 @@ handler_t http_response_prepare(server *srv, connection *con) { switch (errno) { case EACCES: con->http_status = 403; - + if (con->conf.log_request_handling) { log_error_write(srv, __FILE__, __LINE__, "s", "-- access denied"); log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path); } - + buffer_reset(con->physical.path); return HANDLER_FINISHED; case ENOENT: @@ -524,74 +530,74 @@ handler_t http_response_prepare(server *srv, connection *con) { /* we have no idea what happend. let's tell the user so. */ con->http_status = 500; buffer_reset(con->physical.path); - + log_error_write(srv, __FILE__, __LINE__, "ssbsb", "file not found ... or so: ", strerror(errno), con->uri.path, "->", con->physical.path); - + return HANDLER_FINISHED; } - + /* not found, perhaps PATHINFO */ - + buffer_copy_string_buffer(srv->tmp_buf, con->physical.path); - + do { struct stat st; - + if (slash) { buffer_copy_string_len(con->physical.path, srv->tmp_buf->ptr, slash - srv->tmp_buf->ptr); } else { buffer_copy_string_buffer(con->physical.path, srv->tmp_buf); } - + if (0 == stat(con->physical.path->ptr, &(st)) && S_ISREG(st.st_mode)) { found = 1; break; } - + if (pathinfo != NULL) { *pathinfo = '\0'; } slash = strrchr(srv->tmp_buf->ptr, '/'); - + if (pathinfo != NULL) { /* restore '/' */ *pathinfo = '/'; } - + if (slash) pathinfo = slash; - } while ((found == 0) && (slash != NULL) && (slash - srv->tmp_buf->ptr > con->physical.basedir->used - 2)); - + } while ((found == 0) && (slash != NULL) && ((size_t)(slash - srv->tmp_buf->ptr) > (con->physical.basedir->used - 2))); + if (found == 0) { /* no it really doesn't exists */ con->http_status = 404; - + if (con->conf.log_file_not_found) { log_error_write(srv, __FILE__, __LINE__, "sbsb", "file not found:", con->uri.path, "->", con->physical.path); } - + buffer_reset(con->physical.path); - + return HANDLER_FINISHED; } - + /* we have a PATHINFO */ if (pathinfo) { buffer_copy_string(con->request.pathinfo, pathinfo); - + /* * shorten uri.path */ - + con->uri.path->used -= strlen(pathinfo); con->uri.path->ptr[con->uri.path->used - 1] = '\0'; } - + if (con->conf.log_request_handling) { log_error_write(srv, __FILE__, __LINE__, "s", "-- after pathinfo check"); log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path); @@ -599,12 +605,12 @@ handler_t http_response_prepare(server *srv, connection *con) { log_error_write(srv, __FILE__, __LINE__, "sb", "Pathinfo :", con->request.pathinfo); } } - + if (con->conf.log_request_handling) { log_error_write(srv, __FILE__, __LINE__, "s", "-- handling subrequest"); log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path); } - + /* call the handlers */ switch(r = plugins_call_handle_subrequest_start(srv, con)) { case HANDLER_GO_ON: @@ -615,21 +621,21 @@ handler_t http_response_prepare(server *srv, connection *con) { if (con->conf.log_request_handling) { log_error_write(srv, __FILE__, __LINE__, "s", "-- subrequest finished"); } - + /* something strange happend */ return r; } - + /* if we are still here, no one wanted the file, status 403 is ok I think */ - + if (con->mode == DIRECT) { con->http_status = 403; - + return HANDLER_FINISHED; } - + } - + switch(r = plugins_call_handle_subrequest(srv, con)) { case HANDLER_GO_ON: /* request was not handled, looks like we are done */ @@ -640,7 +646,7 @@ handler_t http_response_prepare(server *srv, connection *con) { /* something strange happend */ return r; } - + /* can't happen */ return HANDLER_COMEBACK; } diff --git a/src/server.c b/src/server.c index 0222a22..f0e9ee1 100644 --- a/src/server.c +++ b/src/server.c @@ -55,6 +55,10 @@ #include <sys/prctl.h> #endif +#ifdef USE_OPENSSL +# include <openssl/err.h> +#endif + #ifndef __sgi /* IRIX doesn't like the alarm based time() optimization */ /* #define USE_ALARM */ @@ -72,9 +76,9 @@ static void sigaction_handler(int sig, siginfo_t *si, void *context) { switch (sig) { case SIGTERM: srv_shutdown = 1; break; - case SIGINT: + case SIGINT: if (graceful_shutdown) srv_shutdown = 1; - else graceful_shutdown = 1; + else graceful_shutdown = 1; break; case SIGALRM: handle_sig_alarm = 1; break; @@ -86,9 +90,9 @@ static void sigaction_handler(int sig, siginfo_t *si, void *context) { static void signal_handler(int sig) { switch (sig) { case SIGTERM: srv_shutdown = 1; break; - case SIGINT: + case SIGINT: if (graceful_shutdown) srv_shutdown = 1; - else graceful_shutdown = 1; + else graceful_shutdown = 1; break; case SIGALRM: handle_sig_alarm = 1; break; @@ -110,25 +114,25 @@ static void daemonize(void) { signal(SIGTSTP, SIG_IGN); #endif if (0 != fork()) exit(0); - + if (-1 == setsid()) exit(0); signal(SIGHUP, SIG_IGN); if (0 != fork()) exit(0); - + if (0 != chdir("/")) exit(0); } #endif static server *server_init(void) { int i; - + server *srv = calloc(1, sizeof(*srv)); assert(srv); #define CLEAN(x) \ srv->x = buffer_init(); - + CLEAN(response_header); CLEAN(parse_full_path); CLEAN(ts_debug_str); @@ -138,7 +142,7 @@ static server *server_init(void) { CLEAN(tmp_buf); srv->empty_string = buffer_init_string(""); CLEAN(cond_check_buf); - + CLEAN(srvconf.errorlog_file); CLEAN(srvconf.groupname); CLEAN(srvconf.username); @@ -146,58 +150,58 @@ static server *server_init(void) { CLEAN(srvconf.bindhost); CLEAN(srvconf.event_handler); CLEAN(srvconf.pid_file); - + CLEAN(tmp_chunk_len); #undef CLEAN - + #define CLEAN(x) \ srv->x = array_init(); - + CLEAN(config_context); CLEAN(config_touched); CLEAN(status); #undef CLEAN - + for (i = 0; i < FILE_CACHE_MAX; i++) { srv->mtime_cache[i].str = buffer_init(); } - + srv->cur_ts = time(NULL); srv->startup_ts = srv->cur_ts; - + srv->conns = calloc(1, sizeof(*srv->conns)); assert(srv->conns); - + srv->joblist = calloc(1, sizeof(*srv->joblist)); assert(srv->joblist); - + srv->fdwaitqueue = calloc(1, sizeof(*srv->fdwaitqueue)); assert(srv->fdwaitqueue); - + srv->srvconf.modules = array_init(); srv->srvconf.modules_dir = buffer_init_string(LIBRARY_DIR); srv->srvconf.network_backend = buffer_init(); srv->srvconf.upload_tempdirs = array_init(); - + /* use syslog */ srv->errorlog_fd = -1; srv->errorlog_mode = ERRORLOG_STDERR; srv->split_vals = array_init(); - + return srv; } static void server_free(server *srv) { size_t i; - + for (i = 0; i < FILE_CACHE_MAX; i++) { buffer_free(srv->mtime_cache[i].str); } - + #define CLEAN(x) \ buffer_free(srv->x); - + CLEAN(response_header); CLEAN(parse_full_path); CLEAN(ts_debug_str); @@ -207,7 +211,7 @@ static void server_free(server *srv) { CLEAN(tmp_buf); CLEAN(empty_string); CLEAN(cond_check_buf); - + CLEAN(srvconf.errorlog_file); CLEAN(srvconf.groupname); CLEAN(srvconf.username); @@ -217,7 +221,7 @@ static void server_free(server *srv) { CLEAN(srvconf.pid_file); CLEAN(srvconf.modules_dir); CLEAN(srvconf.network_backend); - + CLEAN(tmp_chunk_len); #undef CLEAN @@ -225,49 +229,61 @@ static void server_free(server *srv) { fdevent_unregister(srv->ev, srv->fd); #endif fdevent_free(srv->ev); - + free(srv->conns); - + if (srv->config_storage) { for (i = 0; i < srv->config_context->used; i++) { specific_config *s = srv->config_storage[i]; if (!s) continue; - + buffer_free(s->document_root); buffer_free(s->server_name); buffer_free(s->server_tag); buffer_free(s->ssl_pemfile); buffer_free(s->ssl_ca_file); + buffer_free(s->ssl_cipher_list); buffer_free(s->error_handler); buffer_free(s->errorfile_prefix); array_free(s->mimetypes); - +#ifdef USE_OPENSSL + SSL_CTX_free(s->ssl_ctx); +#endif free(s); } free(srv->config_storage); srv->config_storage = NULL; } - + #define CLEAN(x) \ array_free(srv->x); - + CLEAN(config_context); CLEAN(config_touched); CLEAN(status); CLEAN(srvconf.upload_tempdirs); #undef CLEAN - + joblist_free(srv, srv->joblist); fdwaitqueue_free(srv, srv->fdwaitqueue); - + if (srv->stat_cache) { stat_cache_free(srv->stat_cache); } array_free(srv->srvconf.modules); array_free(srv->split_vals); - + +#ifdef USE_OPENSSL + if (srv->ssl_is_init) { + CRYPTO_cleanup_all_ex_data(); + ERR_free_strings(); + ERR_remove_state(0); + EVP_cleanup(); + } +#endif + free(srv); } @@ -281,7 +297,7 @@ static void show_version (void) { " - a light and fast webserver\n" \ "Build-Date: " __DATE__ " " __TIME__ "\n"; ; -#undef TEXT_SSL +#undef TEXT_SSL write(STDOUT_FILENO, b, strlen(b)); } @@ -427,7 +443,7 @@ static void show_help (void) { " -h show this help\n" \ "\n" ; -#undef TEXT_SSL +#undef TEXT_SSL #undef TEXT_IPV6 write(STDOUT_FILENO, b, strlen(b)); } @@ -447,27 +463,27 @@ int main (int argc, char **argv) { #ifdef HAVE_GETRLIMIT struct rlimit rlim; #endif - + #ifdef USE_ALARM struct itimerval interval; - + interval.it_interval.tv_sec = 1; interval.it_interval.tv_usec = 0; interval.it_value.tv_sec = 1; interval.it_value.tv_usec = 0; #endif - - + + /* for nice %b handling in strfime() */ setlocale(LC_TIME, "C"); - + if (NULL == (srv = server_init())) { fprintf(stderr, "did this really happen?\n"); return -1; } - + /* init structs done */ - + srv->srvconf.port = 0; #ifdef HAVE_GETUID i_am_root = (getuid() == 0); @@ -475,11 +491,11 @@ int main (int argc, char **argv) { i_am_root = 0; #endif srv->srvconf.dont_daemonize = 0; - + while(-1 != (o = getopt(argc, argv, "f:m:hvVDpt"))) { switch(o) { - case 'f': - if (config_read(srv, optarg)) { + case 'f': + if (config_read(srv, optarg)) { server_free(srv); return -1; } @@ -491,23 +507,23 @@ int main (int argc, char **argv) { case 't': test_config = 1; break; case 'D': srv->srvconf.dont_daemonize = 1; break; case 'v': show_version(); return 0; - case 'V': show_features(); return 0; + case 'V': show_features(); return 0; case 'h': show_help(); return 0; - default: + default: show_help(); server_free(srv); return -1; } } - + if (!srv->config_storage) { log_error_write(srv, __FILE__, __LINE__, "s", "No configuration available. Try using -f option."); - + server_free(srv); return -1; } - + if (print_config) { data_unset *dc = srv->config_context->data[0]; if (dc) { @@ -527,7 +543,7 @@ int main (int argc, char **argv) { server_free(srv); return 0; } - + /* close stdin and stdout, as they are not needed */ /* move stdin to /dev/null */ if (-1 != (fd = open("/dev/null", O_RDONLY))) { @@ -535,54 +551,54 @@ int main (int argc, char **argv) { dup2(fd, STDIN_FILENO); close(fd); } - + /* move stdout to /dev/null */ if (-1 != (fd = open("/dev/null", O_WRONLY))) { close(STDOUT_FILENO); dup2(fd, STDOUT_FILENO); close(fd); } - + if (0 != config_set_defaults(srv)) { - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "setting default values failed"); server_free(srv); return -1; } - + /* UID handling */ #ifdef HAVE_GETUID if (!i_am_root && (geteuid() == 0 || getegid() == 0)) { /* we are setuid-root */ - - log_error_write(srv, __FILE__, __LINE__, "s", + + log_error_write(srv, __FILE__, __LINE__, "s", "Are you nuts ? Don't apply a SUID bit to this binary"); - + server_free(srv); return -1; } #endif - + /* check document-root */ if (srv->config_storage[0]->document_root->used <= 1) { - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "document-root is not set\n"); - + server_free(srv); - + return -1; } - + if (plugins_load(srv)) { log_error_write(srv, __FILE__, __LINE__, "s", "loading plugins finally failed"); - + plugins_free(srv); server_free(srv); - + return -1; } - + /* open pid file BEFORE chroot */ if (srv->srvconf.pid_file->used) { if (-1 == (pid_fd = open(srv->srvconf.pid_file->ptr, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) { @@ -592,18 +608,18 @@ int main (int argc, char **argv) { "opening pid-file failed:", srv->srvconf.pid_file, strerror(errno)); return -1; } - + if (0 != stat(srv->srvconf.pid_file->ptr, &st)) { log_error_write(srv, __FILE__, __LINE__, "sbs", "stating existing pid-file failed:", srv->srvconf.pid_file, strerror(errno)); } - + if (!S_ISREG(st.st_mode)) { log_error_write(srv, __FILE__, __LINE__, "sb", "pid-file exists and isn't regular file:", srv->srvconf.pid_file); return -1; } - + if (-1 == (pid_fd = open(srv->srvconf.pid_file->ptr, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) { log_error_write(srv, __FILE__, __LINE__, "sbs", "opening pid-file failed:", srv->srvconf.pid_file, strerror(errno)); @@ -630,7 +646,7 @@ int main (int argc, char **argv) { #ifdef HAVE_VALGRIND_VALGRIND_H if (RUNNING_ON_VALGRIND) use_rlimit = 0; #endif - + #ifdef HAVE_GETRLIMIT if (0 != getrlimit(RLIMIT_NOFILE, &rlim)) { log_error_write(srv, __FILE__, __LINE__, @@ -638,13 +654,13 @@ int main (int argc, char **argv) { strerror(errno)); return -1; } - + if (use_rlimit && srv->srvconf.max_fds) { /* set rlimits */ - + rlim.rlim_cur = srv->srvconf.max_fds; rlim.rlim_max = srv->srvconf.max_fds; - + if (0 != setrlimit(RLIMIT_NOFILE, &rlim)) { log_error_write(srv, __FILE__, __LINE__, "ss", "couldn't set 'max filedescriptors'", @@ -653,7 +669,7 @@ int main (int argc, char **argv) { } } - /* #372: solaris need some fds extra for devpoll */ + /* #372: solaris need some fds extra for devpoll */ if (rlim.rlim_cur > 10) rlim.rlim_cur -= 10; if (srv->event_handler == FDEVENT_HANDLER_SELECT) { @@ -671,33 +687,33 @@ int main (int argc, char **argv) { if (srv->event_handler == FDEVENT_HANDLER_SELECT) { /* don't raise the limit above FD_SET_SIZE */ if (srv->max_fds > FD_SETSIZE - 200) { - log_error_write(srv, __FILE__, __LINE__, "sd", + log_error_write(srv, __FILE__, __LINE__, "sd", "can't raise max filedescriptors above", FD_SETSIZE - 200, "if event-handler is 'select'. Use 'poll' or something else or reduce server.max-fds."); return -1; } } - + #ifdef HAVE_PWD_H /* set user and group */ if (srv->srvconf.username->used) { if (NULL == (pwd = getpwnam(srv->srvconf.username->ptr))) { - log_error_write(srv, __FILE__, __LINE__, "sb", + log_error_write(srv, __FILE__, __LINE__, "sb", "can't find username", srv->srvconf.username); return -1; } - + if (pwd->pw_uid == 0) { log_error_write(srv, __FILE__, __LINE__, "s", "I will not set uid to 0\n"); return -1; } } - + if (srv->srvconf.groupname->used) { if (NULL == (grp = getgrnam(srv->srvconf.groupname->ptr))) { - log_error_write(srv, __FILE__, __LINE__, "sb", + log_error_write(srv, __FILE__, __LINE__, "sb", "can't find groupname", srv->srvconf.groupname); return -1; } @@ -707,15 +723,15 @@ int main (int argc, char **argv) { return -1; } } -#endif +#endif /* we need root-perms for port < 1024 */ if (0 != network_init(srv)) { plugins_free(srv); server_free(srv); - + return -1; } -#ifdef HAVE_CHROOT +#ifdef HAVE_CHROOT if (srv->srvconf.changeroot->used) { tzset(); @@ -735,9 +751,13 @@ int main (int argc, char **argv) { setgid(grp->gr_gid); setgroups(0, NULL); } - if (srv->srvconf.username->used && srv->srvconf.groupname->used) - initgroups(srv->srvconf.username->ptr, grp->gr_gid); - if (srv->srvconf.username->used) setuid(pwd->pw_uid); + + if (srv->srvconf.username->used) { + if (srv->srvconf.groupname->used) { + initgroups(srv->srvconf.username->ptr, grp->gr_gid); + } + setuid(pwd->pw_uid); + } #endif #ifdef HAVE_PRCTL if (srv->srvconf.enable_cores) { @@ -770,17 +790,17 @@ int main (int argc, char **argv) { if (srv->event_handler == FDEVENT_HANDLER_SELECT) { /* don't raise the limit above FD_SET_SIZE */ if (srv->max_fds > FD_SETSIZE - 200) { - log_error_write(srv, __FILE__, __LINE__, "sd", + log_error_write(srv, __FILE__, __LINE__, "sd", "can't raise max filedescriptors above", FD_SETSIZE - 200, "if event-handler is 'select'. Use 'poll' or something else or reduce server.max-fds."); return -1; } } - + if (0 != network_init(srv)) { plugins_free(srv); server_free(srv); - + return -1; } } @@ -796,25 +816,25 @@ int main (int argc, char **argv) { /* or use the default */ srv->max_conns = srv->max_fds; } - + if (HANDLER_GO_ON != plugins_call_init(srv)) { log_error_write(srv, __FILE__, __LINE__, "s", "Initialization of plugins failed. Going down."); - + plugins_free(srv); network_close(srv); server_free(srv); - + return -1; } -#ifdef HAVE_FORK +#ifdef HAVE_FORK /* network is up, let's deamonize ourself */ if (srv->srvconf.dont_daemonize == 0) daemonize(); #endif srv->gid = getgid(); srv->uid = getuid(); - + /* write pid file */ if (pid_fd != -1) { buffer_copy_long(srv->tmp_buf, getpid()); @@ -823,17 +843,17 @@ int main (int argc, char **argv) { close(pid_fd); pid_fd = -1; } - + if (HANDLER_GO_ON != plugins_call_set_defaults(srv)) { log_error_write(srv, __FILE__, __LINE__, "s", "Configuration of plugins failed. Going down."); - + plugins_free(srv); network_close(srv); server_free(srv); - + return -1; } - + /* dump unused config-keys */ for (i = 0; i < srv->config_context->used; i++) { array *config = ((data_config *)srv->config_context->data[i])->value; @@ -841,14 +861,14 @@ int main (int argc, char **argv) { for (j = 0; config && j < config->used; j++) { data_unset *du = config->data[j]; - + /* all var.* is known as user defined variable */ if (strncmp(du->key->ptr, "var.", sizeof("var.") - 1) == 0) { continue; } if (NULL == array_get_element(srv->config_touched, du->key->ptr)) { - log_error_write(srv, __FILE__, __LINE__, "sbs", + log_error_write(srv, __FILE__, __LINE__, "sbs", "WARNING: unknown config-key:", du->key, "(ignored)"); @@ -857,12 +877,12 @@ int main (int argc, char **argv) { } if (srv->config_unsupported) { - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "Configuration contains unsupported keys. Going down."); } if (srv->config_deprecated) { - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "Configuration contains deprecated keys. Going down."); } @@ -875,7 +895,7 @@ int main (int argc, char **argv) { } if (-1 == log_error_open(srv)) { - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "opening errorlog failed, dying"); plugins_free(srv); @@ -883,8 +903,8 @@ int main (int argc, char **argv) { server_free(srv); return -1; } - - + + #ifdef HAVE_SIGACTION memset(&act, 0, sizeof(act)); act.sa_handler = SIG_IGN; @@ -904,7 +924,7 @@ int main (int argc, char **argv) { sigaction(SIGHUP, &act, NULL); sigaction(SIGALRM, &act, NULL); sigaction(SIGCHLD, &act, NULL); - + #elif defined(HAVE_SIGNAL) /* ignore the SIGPIPE from sendfile() */ signal(SIGPIPE, SIG_IGN); @@ -915,20 +935,20 @@ int main (int argc, char **argv) { signal(SIGCHLD, signal_handler); signal(SIGINT, signal_handler); #endif - + #ifdef USE_ALARM signal(SIGALRM, signal_handler); - + /* setup periodic timer (1 second) */ if (setitimer(ITIMER_REAL, &interval, NULL)) { log_error_write(srv, __FILE__, __LINE__, "s", "setting timer failed"); return -1; } - + getitimer(ITIMER_REAL, &interval); #endif -#ifdef HAVE_FORK +#ifdef HAVE_FORK /* start watcher and workers */ num_childs = srv->srvconf.max_worker; if (num_childs > 0) { @@ -964,8 +984,8 @@ int main (int argc, char **argv) { "s", "fdevent_init failed"); return -1; } - /* - * kqueue() is called here, select resets its internals, + /* + * kqueue() is called here, select resets its internals, * all server sockets get their handlers * * */ @@ -973,7 +993,7 @@ int main (int argc, char **argv) { plugins_free(srv); network_close(srv); server_free(srv); - + return -1; } @@ -988,7 +1008,7 @@ int main (int argc, char **argv) { /* setup FAM */ if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_FAM) { if (0 != FAMOpen2(srv->stat_cache->fam, "lighttpd")) { - log_error_write(srv, __FILE__, __LINE__, "s", + log_error_write(srv, __FILE__, __LINE__, "s", "could not open a fam connection, dieing."); return -1; } @@ -1020,16 +1040,16 @@ int main (int argc, char **argv) { int n; size_t ndx; time_t min_ts; - + if (handle_sig_hup) { handler_t r; - + /* reset notification */ handle_sig_hup = 0; - - + + /* cycle logfiles */ - + switch(r = plugins_call_handle_sighup(srv)) { case HANDLER_GO_ON: break; @@ -1037,30 +1057,30 @@ int main (int argc, char **argv) { log_error_write(srv, __FILE__, __LINE__, "sd", "sighup-handler return with an error", r); break; } - + if (-1 == log_error_cycle(srv)) { log_error_write(srv, __FILE__, __LINE__, "s", "cycling errorlog failed, dying"); - + return -1; } } - + if (handle_sig_alarm) { /* a new second */ - + #ifdef USE_ALARM /* reset notification */ handle_sig_alarm = 0; #endif - + /* get current time */ min_ts = time(NULL); - + if (min_ts != srv->cur_ts) { int cs = 0; connections *conns = srv->conns; handler_t r; - + switch(r = plugins_call_handle_trigger(srv)) { case HANDLER_GO_ON: break; @@ -1071,21 +1091,21 @@ int main (int argc, char **argv) { log_error_write(srv, __FILE__, __LINE__, "d", r); break; } - + /* trigger waitpid */ srv->cur_ts = min_ts; - - /* cleanup stat-cache */ + + /* cleanup stat-cache */ stat_cache_trigger_cleanup(srv); /** - * check all connections for timeouts - * + * check all connections for timeouts + * */ for (ndx = 0; ndx < conns->used; ndx++) { int changed = 0; connection *con; int t_diff; - + con = conns->ptr[ndx]; if (con->state == CON_STATE_READ || @@ -1094,7 +1114,7 @@ int main (int argc, char **argv) { if (srv->cur_ts - con->read_idle_ts > con->conf.max_read_idle) { /* time - out */ #if 0 - log_error_write(srv, __FILE__, __LINE__, "sd", + log_error_write(srv, __FILE__, __LINE__, "sd", "connection closed - read-timeout:", con->fd); #endif connection_set_state(srv, con, CON_STATE_ERROR); @@ -1104,7 +1124,7 @@ int main (int argc, char **argv) { if (srv->cur_ts - con->read_idle_ts > con->conf.max_keep_alive_idle) { /* time - out */ #if 0 - log_error_write(srv, __FILE__, __LINE__, "sd", + log_error_write(srv, __FILE__, __LINE__, "sd", "connection closed - read-timeout:", con->fd); #endif connection_set_state(srv, con, CON_STATE_ERROR); @@ -1112,20 +1132,20 @@ int main (int argc, char **argv) { } } } - + if ((con->state == CON_STATE_WRITE) && - (con->write_request_ts != 0)) { + (con->write_request_ts != 0)) { #if 0 if (srv->cur_ts - con->write_request_ts > 60) { - log_error_write(srv, __FILE__, __LINE__, "sdd", + log_error_write(srv, __FILE__, __LINE__, "sdd", "connection closed - pre-write-request-timeout:", con->fd, srv->cur_ts - con->write_request_ts); } #endif - + if (srv->cur_ts - con->write_request_ts > con->conf.max_write_idle) { /* time - out */ #if 1 - log_error_write(srv, __FILE__, __LINE__, "sbsosds", + log_error_write(srv, __FILE__, __LINE__, "sbsosds", "NOTE: a request for", con->request.uri, "timed out after writing", @@ -1140,35 +1160,35 @@ int main (int argc, char **argv) { } /* we don't like div by zero */ if (0 == (t_diff = srv->cur_ts - con->connection_start)) t_diff = 1; - - if (con->traffic_limit_reached && - (con->conf.kbytes_per_second == 0 || + + if (con->traffic_limit_reached && + (con->conf.kbytes_per_second == 0 || ((con->bytes_written / t_diff) < con->conf.kbytes_per_second * 1024))) { /* enable connection again */ con->traffic_limit_reached = 0; - + changed = 1; } - + if (changed) { connection_state_machine(srv, con); } con->bytes_written_cur_second = 0; *(con->conf.global_bytes_per_second_cnt_ptr) = 0; - + #if 0 if (cs == 0) { fprintf(stderr, "connection-state: "); cs = 1; } - + fprintf(stderr, "c[%d,%d]: %s ", con->fd, con->fcgi.fd, connection_get_state(con->state)); #endif } - + if (cs == 1) fprintf(stderr, "\n"); } } @@ -1183,18 +1203,18 @@ int main (int argc, char **argv) { server_socket *srv_socket = srv->srv_sockets.ptr[i]; fdevent_event_add(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd, FDEVENT_IN); } - + log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets enabled again"); - + srv->sockets_disabled = 0; } } else { if ((srv->cur_fds + srv->want_fds > srv->max_fds * 0.9) || /* out of fds */ (srv->conns->used > srv->max_conns) || /* out of connections */ - (graceful_shutdown)) { /* graceful_shutdown */ + (graceful_shutdown)) { /* graceful_shutdown */ /* disable server-fds */ - + for (i = 0; i < srv->srv_sockets.used; i++) { server_socket *srv_socket = srv->srv_sockets.ptr[i]; fdevent_event_del(srv->ev, &(srv_socket->fde_ndx), srv_socket->fd); @@ -1213,7 +1233,7 @@ int main (int argc, char **argv) { /* network_close() will cleanup after us */ } } - + if (graceful_shutdown) { log_error_write(srv, __FILE__, __LINE__, "s", "[note] graceful shutdown started"); } else if (srv->conns->used > srv->max_conns) { @@ -1221,7 +1241,7 @@ int main (int argc, char **argv) { } else { log_error_write(srv, __FILE__, __LINE__, "s", "[note] sockets disabled, out-of-fds"); } - + srv->sockets_disabled = 1; } } @@ -1231,16 +1251,16 @@ int main (int argc, char **argv) { * we are ready to terminate without harming anyone */ srv_shutdown = 1; } - + /* we still have some fds to share */ - if (srv->want_fds) { + if (srv->want_fds) { /* check the fdwaitqueue for waiting fds */ int free_fds = srv->max_fds - srv->cur_fds - 16; connection *con; - + for (; free_fds > 0 && NULL != (con = fdwaitqueue_unshift(srv, srv->fdwaitqueue)); free_fds--) { connection_state_machine(srv, con); - + srv->want_fds--; } } @@ -1251,27 +1271,27 @@ int main (int argc, char **argv) { int fd_ndx; #if 0 if (n > 0) { - log_error_write(srv, __FILE__, __LINE__, "sd", + log_error_write(srv, __FILE__, __LINE__, "sd", "polls:", n); } -#endif +#endif fd_ndx = -1; do { fdevent_handler handler; void *context; handler_t r; - + fd_ndx = fdevent_event_next_fdndx (srv->ev, fd_ndx); revents = fdevent_event_get_revent (srv->ev, fd_ndx); fd = fdevent_event_get_fd (srv->ev, fd_ndx); handler = fdevent_get_handler(srv->ev, fd); context = fdevent_get_context(srv->ev, fd); - + /* connection_handle_fdevent needs a joblist_append */ #if 0 - log_error_write(srv, __FILE__, __LINE__, "sdd", + log_error_write(srv, __FILE__, __LINE__, "sdd", "event for", fd, revents); -#endif +#endif switch (r = (*handler)(srv, context, revents)) { case HANDLER_FINISHED: case HANDLER_GO_ON: @@ -1288,17 +1308,17 @@ int main (int argc, char **argv) { } } while (--n > 0); } else if (n < 0 && errno != EINTR) { - log_error_write(srv, __FILE__, __LINE__, "ss", - "fdevent_poll failed:", + log_error_write(srv, __FILE__, __LINE__, "ss", + "fdevent_poll failed:", strerror(errno)); } - + for (ndx = 0; ndx < srv->joblist->used; ndx++) { connection *con = srv->joblist->ptr[ndx]; handler_t r; - + connection_state_machine(srv, con); - + switch(r = plugins_call_handle_joblist(srv, con)) { case HANDLER_FINISHED: case HANDLER_GO_ON: @@ -1307,32 +1327,32 @@ int main (int argc, char **argv) { log_error_write(srv, __FILE__, __LINE__, "d", r); break; } - + con->in_joblist = 0; } - + srv->joblist->used = 0; } - + if (srv->srvconf.pid_file->used && srv->srvconf.changeroot->used == 0) { if (0 != unlink(srv->srvconf.pid_file->ptr)) { if (errno != EACCES && errno != EPERM) { - log_error_write(srv, __FILE__, __LINE__, "sbds", - "unlink failed for:", + log_error_write(srv, __FILE__, __LINE__, "sbds", + "unlink failed for:", srv->srvconf.pid_file, errno, strerror(errno)); } } } - + /* clean-up */ log_error_close(srv); network_close(srv); connections_free(srv); plugins_free(srv); server_free(srv); - + return 0; } diff --git a/src/settings.h b/src/settings.h index f0c6354..349fc20 100644 --- a/src/settings.h +++ b/src/settings.h @@ -9,24 +9,24 @@ /** * max size of a buffer which will just be reset * to ->used = 0 instead of really freeing the buffer - * + * * 64kB (no real reason, just a guess) */ #define BUFFER_MAX_REUSE_SIZE (4 * 1024) /** * max size of the HTTP request header - * + * * 32k should be enough for everything (just a guess) - * + * */ #define MAX_HTTP_REQUEST_HEADER (32 * 1024) -typedef enum { HANDLER_UNSET, - HANDLER_GO_ON, +typedef enum { HANDLER_UNSET, + HANDLER_GO_ON, HANDLER_FINISHED, - HANDLER_COMEBACK, - HANDLER_WAIT_FOR_EVENT, + HANDLER_COMEBACK, + HANDLER_WAIT_FOR_EVENT, HANDLER_ERROR, HANDLER_WAIT_FOR_FD } handler_t; diff --git a/src/spawn-fcgi.c b/src/spawn-fcgi.c index fd869a2..c40d8f9 100644 --- a/src/spawn-fcgi.c +++ b/src/spawn-fcgi.c @@ -45,28 +45,28 @@ int fcgi_spawn_connection(char *appPath, char *addr, unsigned short port, const int fcgi_fd; int socket_type, status; struct timeval tv = { 0, 100 * 1000 }; - + struct sockaddr_un fcgi_addr_un; struct sockaddr_in fcgi_addr_in; struct sockaddr *fcgi_addr; - + socklen_t servlen; - + if (child_count < 2) { child_count = 5; } - + if (child_count > 256) { child_count = 256; } - - + + if (unixsocket) { memset(&fcgi_addr, 0, sizeof(fcgi_addr)); - + fcgi_addr_un.sun_family = AF_UNIX; strcpy(fcgi_addr_un.sun_path, unixsocket); - + #ifdef SUN_LEN servlen = SUN_LEN(&fcgi_addr_un); #else @@ -84,50 +84,50 @@ int fcgi_spawn_connection(char *appPath, char *addr, unsigned short port, const } fcgi_addr_in.sin_port = htons(port); servlen = sizeof(fcgi_addr_in); - + socket_type = AF_INET; fcgi_addr = (struct sockaddr *) &fcgi_addr_in; } - + if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) { - fprintf(stderr, "%s.%d\n", + fprintf(stderr, "%s.%d\n", __FILE__, __LINE__); return -1; } - + if (-1 == connect(fcgi_fd, fcgi_addr, servlen)) { /* server is not up, spawn in */ pid_t child; int val; - + if (unixsocket) unlink(unixsocket); - + close(fcgi_fd); - + /* reopen socket */ if (-1 == (fcgi_fd = socket(socket_type, SOCK_STREAM, 0))) { - fprintf(stderr, "%s.%d\n", + fprintf(stderr, "%s.%d\n", __FILE__, __LINE__); return -1; } val = 1; if (setsockopt(fcgi_fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) { - fprintf(stderr, "%s.%d\n", + fprintf(stderr, "%s.%d\n", __FILE__, __LINE__); return -1; } /* create socket */ if (-1 == bind(fcgi_fd, fcgi_addr, servlen)) { - fprintf(stderr, "%s.%d: bind failed: %s\n", + fprintf(stderr, "%s.%d: bind failed: %s\n", __FILE__, __LINE__, strerror(errno)); return -1; } - + if (-1 == listen(fcgi_fd, 1024)) { - fprintf(stderr, "%s.%d: fd = -1\n", + fprintf(stderr, "%s.%d: fd = -1\n", __FILE__, __LINE__); return -1; } @@ -137,42 +137,42 @@ int fcgi_spawn_connection(char *appPath, char *addr, unsigned short port, const } else { child = 0; } - + switch (child) { case 0: { char cgi_childs[64]; char *b; - + int i = 0; - + /* is save as we limit to 256 childs */ sprintf(cgi_childs, "PHP_FCGI_CHILDREN=%d", child_count); - + if(fcgi_fd != FCGI_LISTENSOCK_FILENO) { close(FCGI_LISTENSOCK_FILENO); dup2(fcgi_fd, FCGI_LISTENSOCK_FILENO); close(fcgi_fd); } - + /* we don't need the client socket */ for (i = 3; i < 256; i++) { close(i); } - + /* create environment */ - + putenv(cgi_childs); - + /* fork and replace shell */ b = malloc(strlen("exec ") + strlen(appPath) + 1); strcpy(b, "exec "); strcat(b, appPath); - + /* exec the cgi */ execl("/bin/sh", "sh", "-c", b, NULL); - + exit(errno); - + break; } case -1: @@ -180,47 +180,47 @@ int fcgi_spawn_connection(char *appPath, char *addr, unsigned short port, const break; default: /* father */ - + /* wait */ select(0, NULL, NULL, NULL, &tv); - + switch (waitpid(child, &status, WNOHANG)) { case 0: - fprintf(stderr, "%s.%d: child spawned successfully: PID: %d\n", + fprintf(stderr, "%s.%d: child spawned successfully: PID: %d\n", __FILE__, __LINE__, child); - + /* write pid file */ if (pid_fd != -1) { /* assume a 32bit pid_t */ char pidbuf[12]; - + snprintf(pidbuf, sizeof(pidbuf) - 1, "%d", child); - + write(pid_fd, pidbuf, strlen(pidbuf)); close(pid_fd); pid_fd = -1; } - + break; case -1: break; default: if (WIFEXITED(status)) { - fprintf(stderr, "%s.%d: child exited with: %d, %s\n", + fprintf(stderr, "%s.%d: child exited with: %d, %s\n", __FILE__, __LINE__, WEXITSTATUS(status), strerror(WEXITSTATUS(status))); } else if (WIFSIGNALED(status)) { - fprintf(stderr, "%s.%d: child signaled: %d\n", + fprintf(stderr, "%s.%d: child signaled: %d\n", __FILE__, __LINE__, WTERMSIG(status)); } else { - fprintf(stderr, "%s.%d: child died somehow: %d\n", + fprintf(stderr, "%s.%d: child died somehow: %d\n", __FILE__, __LINE__, status); } } - + break; } } else { @@ -228,16 +228,16 @@ int fcgi_spawn_connection(char *appPath, char *addr, unsigned short port, const __FILE__, __LINE__); return -1; } - + close(fcgi_fd); - + return 0; } void show_version () { char *b = "spawn-fcgi" "-" PACKAGE_VERSION \ -" - spawns fastcgi processes\n" +" - spawns fastcgi processes\n" ; write(1, b, strlen(b)); } @@ -265,7 +265,7 @@ void show_help () { int main(int argc, char **argv) { - char *fcgi_app = NULL, *changeroot = NULL, *username = NULL, + char *fcgi_app = NULL, *changeroot = NULL, *username = NULL, *groupname = NULL, *unixsocket = NULL, *pid_file = NULL, *addr = NULL; unsigned short port = 0; @@ -273,9 +273,9 @@ int main(int argc, char **argv) { int i_am_root, o; int pid_fd = -1; int nofork = 0; - + i_am_root = (getuid() == 0); - + while(-1 != (o = getopt(argc, argv, "c:f:g:hna:p:u:vC:s:P:"))) { switch(o) { case 'f': fcgi_app = optarg; break; @@ -290,145 +290,149 @@ int main(int argc, char **argv) { case 'P': pid_file = optarg; /* PID file */ break; case 'v': show_version(); return 0; case 'h': show_help(); return 0; - default: + default: show_help(); return -1; } } - + if (fcgi_app == NULL || (port == 0 && unixsocket == NULL)) { show_help(); return -1; } - + if (unixsocket && port) { - fprintf(stderr, "%s.%d: %s\n", + fprintf(stderr, "%s.%d: %s\n", __FILE__, __LINE__, "either a unix domain socket or a tcp-port, but not both\n"); - + return -1; } - + if (unixsocket && strlen(unixsocket) > UNIX_PATH_MAX - 1) { - fprintf(stderr, "%s.%d: %s\n", + fprintf(stderr, "%s.%d: %s\n", __FILE__, __LINE__, "path of the unix socket is too long\n"); - + return -1; } /* UID handling */ if (!i_am_root && (geteuid() == 0 || getegid() == 0)) { /* we are setuid-root */ - - fprintf(stderr, "%s.%d: %s\n", + + fprintf(stderr, "%s.%d: %s\n", __FILE__, __LINE__, "Are you nuts ? Don't apply a SUID bit to this binary\n"); - + return -1; } - - if (pid_file && + + if (pid_file && (-1 == (pid_fd = open(pid_file, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)))) { struct stat st; if (errno != EEXIST) { - fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n", + fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n", __FILE__, __LINE__, pid_file, strerror(errno)); - + return -1; } - + /* ok, file exists */ - + if (0 != stat(pid_file, &st)) { - fprintf(stderr, "%s.%d: stating pid-file '%s' failed: %s\n", + fprintf(stderr, "%s.%d: stating pid-file '%s' failed: %s\n", __FILE__, __LINE__, pid_file, strerror(errno)); - + return -1; } - + /* is it a regular file ? */ - + if (!S_ISREG(st.st_mode)) { - fprintf(stderr, "%s.%d: pid-file exists and isn't regular file: '%s'\n", + fprintf(stderr, "%s.%d: pid-file exists and isn't regular file: '%s'\n", __FILE__, __LINE__, pid_file); - + return -1; } - + if (-1 == (pid_fd = open(pid_file, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH))) { - fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n", + fprintf(stderr, "%s.%d: opening pid-file '%s' failed: %s\n", __FILE__, __LINE__, pid_file, strerror(errno)); - + return -1; } } - + if (i_am_root) { struct group *grp = NULL; struct passwd *pwd = NULL; - + /* set user and group */ - + if (username) { if (NULL == (pwd = getpwnam(username))) { - fprintf(stderr, "%s.%d: %s, %s\n", + fprintf(stderr, "%s.%d: %s, %s\n", __FILE__, __LINE__, "can't find username", username); return -1; } - + if (pwd->pw_uid == 0) { - fprintf(stderr, "%s.%d: %s\n", + fprintf(stderr, "%s.%d: %s\n", __FILE__, __LINE__, "I will not set uid to 0\n"); return -1; } } - + if (groupname) { if (NULL == (grp = getgrnam(groupname))) { - fprintf(stderr, "%s.%d: %s %s\n", + fprintf(stderr, "%s.%d: %s %s\n", __FILE__, __LINE__, - "can't find groupname", + "can't find groupname", groupname); return -1; } if (grp->gr_gid == 0) { - fprintf(stderr, "%s.%d: %s\n", + fprintf(stderr, "%s.%d: %s\n", __FILE__, __LINE__, "I will not set gid to 0\n"); return -1; } } - + if (changeroot) { if (-1 == chroot(changeroot)) { - fprintf(stderr, "%s.%d: %s %s\n", + fprintf(stderr, "%s.%d: %s %s\n", __FILE__, __LINE__, "chroot failed: ", strerror(errno)); return -1; } if (-1 == chdir("/")) { - fprintf(stderr, "%s.%d: %s %s\n", + fprintf(stderr, "%s.%d: %s %s\n", __FILE__, __LINE__, "chdir failed: ", strerror(errno)); return -1; } } - + /* drop root privs */ if (groupname) { setgid(grp->gr_gid); - setgroups(0, NULL); } - if (username) setuid(pwd->pw_uid); + if (username) { + if (groupname) { + initgroups(username, grp->gr_gid); + } + setuid(pwd->pw_uid); + } } - + return fcgi_spawn_connection(fcgi_app, addr, port, unixsocket, child_count, pid_fd, nofork); } #else diff --git a/src/splaytree.c b/src/splaytree.c index 3a80910..5d6a2b4 100644 --- a/src/splaytree.c +++ b/src/splaytree.c @@ -56,19 +56,19 @@ #define node_size splaytree_size -/* Splay using the key i (which may or may not be in the tree.) - * The starting root is t, and the tree used is defined by rat +/* Splay using the key i (which may or may not be in the tree.) + * The starting root is t, and the tree used is defined by rat * size fields are maintained */ splay_tree * splaytree_splay (splay_tree *t, int i) { splay_tree N, *l, *r, *y; int comp, root_size, l_size, r_size; - + if (t == NULL) return t; N.left = N.right = NULL; l = r = &N; root_size = node_size(t); l_size = r_size = 0; - + for (;;) { comp = compare(i, t->key); if (comp < 0) { @@ -120,7 +120,7 @@ splay_tree * splaytree_splay (splay_tree *t, int i) { y->size = r_size; r_size -= 1+node_size(y->right); } - + l->right = t->left; /* assemble */ r->left = t->right; t->left = N.right; diff --git a/src/splaytree.h b/src/splaytree.h index 98e4234..4be1523 100644 --- a/src/splaytree.h +++ b/src/splaytree.h @@ -19,6 +19,6 @@ splay_tree * splaytree_size(splay_tree *t); /* This macro returns the size of a node. Unlike "x->size", */ /* it works even if x=NULL. The test could be avoided by using */ /* a special version of NULL which was a real node with size 0. */ - + #endif diff --git a/src/stat_cache.c b/src/stat_cache.c index a4f31a4..283ead9 100644 --- a/src/stat_cache.c +++ b/src/stat_cache.c @@ -52,8 +52,8 @@ * * if we get a change-event from FAM, we increment the version in the FAM->dir mapping * - * if the stat()-cache is queried we check if the version id for the directory is the - * same and return immediatly. + * if the stat()-cache is queried we check if the version id for the directory is the + * same and return immediatly. * * * What we need: @@ -62,17 +62,17 @@ * - for each FAMRequest we have to find the version in the directory cache (index as userdata) * * stat <<-> directory <-> FAMRequest - * - * if file is deleted, directory is dirty, file is rechecked ... + * + * if file is deleted, directory is dirty, file is rechecked ... * if directory is deleted, directory mapping is removed - * + * * */ #ifdef HAVE_FAM_H typedef struct { FAMRequest *req; FAMConnection *fc; - + buffer *name; int version; @@ -83,16 +83,16 @@ typedef struct { * - we need a hash * - the hash-key is used as sorting criteria for a tree * - a splay-tree is used as we can use the caching effect of it - */ + */ /* we want to cleanup the stat-cache every few seconds, let's say 10 * * - remove entries which are outdated since 30s * - remove entries which are fresh but havn't been used since 60s * - if we don't have a stat-cache entry for a directory, release it from the monitor - */ + */ -#ifdef DEBUG_STAT_CACHE +#ifdef DEBUG_STAT_CACHE typedef struct { int *ptr; @@ -105,16 +105,16 @@ static fake_keys ctrl; stat_cache *stat_cache_init(void) { stat_cache *fc = NULL; - + fc = calloc(1, sizeof(*fc)); - + fc->dir_name = buffer_init(); fc->hash_key = buffer_init(); #ifdef HAVE_FAM_H fc->fam = calloc(1, sizeof(*fc->fam)); #endif -#ifdef DEBUG_STAT_CACHE +#ifdef DEBUG_STAT_CACHE ctrl.size = 0; #endif @@ -123,24 +123,24 @@ stat_cache *stat_cache_init(void) { static stat_cache_entry * stat_cache_entry_init(void) { stat_cache_entry *sce = NULL; - + sce = calloc(1, sizeof(*sce)); - + sce->name = buffer_init(); sce->etag = buffer_init(); sce->content_type = buffer_init(); - + return sce; } static void stat_cache_entry_free(void *data) { stat_cache_entry *sce = data; if (!sce) return; - + buffer_free(sce->etag); buffer_free(sce->name); buffer_free(sce->content_type); - + free(sce); } @@ -149,22 +149,22 @@ static fam_dir_entry * fam_dir_entry_init(void) { fam_dir_entry *fam_dir = NULL; fam_dir = calloc(1, sizeof(*fam_dir)); - + fam_dir->name = buffer_init(); - + return fam_dir; } static void fam_dir_entry_free(void *data) { fam_dir_entry *fam_dir = data; - + if (!fam_dir) return; - + FAMCancelMonitor(fam_dir->fc, fam_dir->req); - + buffer_free(fam_dir->name); free(fam_dir->req); - + free(fam_dir); } #endif @@ -175,7 +175,7 @@ void stat_cache_free(stat_cache *sc) { splay_tree *node = sc->files; osize = sc->files->size; - + stat_cache_entry_free(node->data); sc->files = splaytree_delete(sc->files, node->key); @@ -189,12 +189,12 @@ void stat_cache_free(stat_cache *sc) { while (sc->dirs) { int osize; splay_tree *node = sc->dirs; - + osize = sc->dirs->size; fam_dir_entry_free(node->data); sc->dirs = splaytree_delete(sc->dirs, node->key); - + if (osize == 1) { assert(NULL == sc->dirs); } else { @@ -214,7 +214,7 @@ void stat_cache_free(stat_cache *sc) { static int stat_cache_attr_get(buffer *buf, char *name) { int attrlen; int ret; - + attrlen = 1024; buffer_prepare_copy(buf, attrlen); attrlen--; @@ -253,15 +253,15 @@ handler_t stat_cache_handle_fdevent(void *_srv, void *_fce, int revent) { sc->fam) { events = FAMPending(sc->fam); - + for (i = 0; i < events; i++) { FAMEvent fe; fam_dir_entry *fam_dir; splay_tree *node; int ndx, j; - + FAMNextEvent(sc->fam, &fe); - + /* handle event */ switch(fe.code) { @@ -286,13 +286,13 @@ handler_t stat_cache_handle_fdevent(void *_srv, void *_fce, int revent) { sc->dirs = splaytree_splay(sc->dirs, ndx); node = sc->dirs; - + if (node && (node->key == ndx)) { int osize = splaytree_size(sc->dirs); - + fam_dir_entry_free(node->data); sc->dirs = splaytree_delete(sc->dirs, ndx); - + assert(osize - 1 == splaytree_size(sc->dirs)); } } @@ -315,7 +315,7 @@ handler_t stat_cache_handle_fdevent(void *_srv, void *_fce, int revent) { sc->fam = NULL; } - + return HANDLER_GO_ON; } @@ -353,7 +353,7 @@ static int stat_cache_lstat(server *srv, buffer *dname, struct stat *lst) { * * * - * returns: + * returns: * - HANDLER_FINISHED on cache-miss (don't forget to reopen the file) * - HANDLER_ERROR on stat() failed -> see errno for problem */ @@ -370,16 +370,16 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_ size_t k; int fd; struct stat lst; -#ifdef DEBUG_STAT_CACHE +#ifdef DEBUG_STAT_CACHE size_t i; #endif int file_ndx; splay_tree *file_node = NULL; - *ret_sce = NULL; + *ret_sce = NULL; - /* + /* * check if the directory for this file has changed */ @@ -391,23 +391,23 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_ file_ndx = hashme(sc->hash_key); sc->files = splaytree_splay(sc->files, file_ndx); -#ifdef DEBUG_STAT_CACHE +#ifdef DEBUG_STAT_CACHE for (i = 0; i < ctrl.used; i++) { if (ctrl.ptr[i] == file_ndx) break; } #endif if (sc->files && (sc->files->key == file_ndx)) { -#ifdef DEBUG_STAT_CACHE +#ifdef DEBUG_STAT_CACHE /* it was in the cache */ assert(i < ctrl.used); #endif - - /* we have seen this file already and + + /* we have seen this file already and * don't stat() it again in the same second */ file_node = sc->files; - + sce = file_node->data; /* check if the name is the same, we might have a collision */ @@ -415,7 +415,7 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_ if (buffer_is_equal(name, sce->name)) { if (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_SIMPLE) { if (sce->stat_ts == srv->cur_ts) { - *ret_sce = sce; + *ret_sce = sce; return HANDLER_GO_ON; } } @@ -425,15 +425,15 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_ * file_node is used by the FAM check below to see if we know this file * and if we can save a stat(). * - * BUT, the sce is not reset here as the entry into the cache is ok, we + * BUT, the sce is not reset here as the entry into the cache is ok, we * it is just not pointing to our requested file. - * + * * */ file_node = NULL; } } else { -#ifdef DEBUG_STAT_CACHE +#ifdef DEBUG_STAT_CACHE if (i != ctrl.used) { fprintf(stderr, "%s.%d: %08x was already inserted but not found in cache, %s\n", __FILE__, __LINE__, file_ndx, name->ptr); } @@ -447,28 +447,28 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_ if (0 != buffer_copy_dirname(sc->dir_name, name)) { SEGFAULT(); } - + buffer_copy_string_buffer(sc->hash_key, sc->dir_name); buffer_append_long(sc->hash_key, con->conf.follow_symlink); dir_ndx = hashme(sc->hash_key); - + sc->dirs = splaytree_splay(sc->dirs, dir_ndx); - + if (sc->dirs && (sc->dirs->key == dir_ndx)) { dir_node = sc->dirs; } - + if (dir_node && file_node) { /* we found a file */ - + sce = file_node->data; fam_dir = dir_node->data; - + if (fam_dir->version == sce->dir_version) { /* the stat()-cache entry is still ok */ - - *ret_sce = sce; + + *ret_sce = sce; return HANDLER_GO_ON; } } @@ -476,7 +476,7 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_ #endif /* - * *lol* + * *lol* * - open() + fstat() on a named-pipe results in a (intended) hang. * - stat() if regular file + open() to see if we can read from it is better * @@ -496,16 +496,16 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_ if (NULL == sce) { int osize = 0; - + if (sc->files) { osize = sc->files->size; } sce = stat_cache_entry_init(); buffer_copy_string_buffer(sce->name, name); - - sc->files = splaytree_insert(sc->files, file_ndx, sce); -#ifdef DEBUG_STAT_CACHE + + sc->files = splaytree_insert(sc->files, file_ndx, sce); +#ifdef DEBUG_STAT_CACHE if (ctrl.size == 0) { ctrl.size = 16; ctrl.used = 0; @@ -526,22 +526,22 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_ sce->st = st; sce->stat_ts = srv->cur_ts; - /* catch the obvious symlinks + /* catch the obvious symlinks * * this is not a secure check as we still have a race-condition between - * the stat() and the open. We can only solve this by + * the stat() and the open. We can only solve this by * 1. open() the file * 2. fstat() the fd * * and keeping the file open for the rest of the time. But this can * only be done at network level. - * + * * per default it is not a symlink * */ #ifdef HAVE_LSTAT sce->is_symlink = 0; - /* we want to only check for symlinks if we should block symlinks. + /* we want to only check for symlinks if we should block symlinks. */ if (!con->conf.follow_symlink) { if (stat_cache_lstat(srv, name, &lst) == 0) { @@ -590,14 +590,14 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_ }; #endif - if (S_ISREG(st.st_mode)) { + if (S_ISREG(st.st_mode)) { /* determine mimetype */ buffer_reset(sce->content_type); - + for (k = 0; k < con->conf.mimetypes->used; k++) { data_string *ds = (data_string *)con->conf.mimetypes->data[k]; buffer *type = ds->key; - + if (type->used == 0) continue; /* check if the right side is the same */ @@ -617,7 +617,7 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_ } else if (S_ISDIR(st.st_mode)) { etag_create(sce->etag, &(sce->st)); } - + #ifdef HAVE_FAM_H if (sc->fam && (srv->srvconf.stat_cache_engine == STAT_CACHE_ENGINE_FAM)) { @@ -627,19 +627,19 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_ fam_dir->fc = sc->fam; buffer_copy_string_buffer(fam_dir->name, sc->dir_name); - + fam_dir->version = 1; - + fam_dir->req = calloc(1, sizeof(FAMRequest)); - - if (0 != FAMMonitorDirectory(sc->fam, fam_dir->name->ptr, + + if (0 != FAMMonitorDirectory(sc->fam, fam_dir->name->ptr, fam_dir->req, fam_dir)) { - - log_error_write(srv, __FILE__, __LINE__, "sbs", - "monitoring dir failed:", - fam_dir->name, + + log_error_write(srv, __FILE__, __LINE__, "sbs", + "monitoring dir failed:", + fam_dir->name, FamErrlist[FAMErrno]); - + fam_dir_entry_free(fam_dir); } else { int osize = 0; @@ -648,7 +648,7 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_ osize = sc->dirs->size; } - sc->dirs = splaytree_insert(sc->dirs, dir_ndx, fam_dir); + sc->dirs = splaytree_insert(sc->dirs, dir_ndx, fam_dir); assert(sc->dirs); assert(sc->dirs->data == fam_dir); assert(osize == (sc->dirs->size - 1)); @@ -656,9 +656,9 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_ } else { fam_dir = dir_node->data; } - + /* bind the fam_fc to the stat() cache entry */ - + if (fam_dir) { sce->dir_version = fam_dir->version; sce->dir_ndx = dir_ndx; @@ -672,11 +672,11 @@ handler_t stat_cache_get_entry(server *srv, connection *con, buffer *name, stat_ } /** - * remove stat() from cache which havn't been stat()ed for + * remove stat() from cache which havn't been stat()ed for * more than 10 seconds - * * - * walk though the stat-cache, collect the ids which are too old + * + * walk though the stat-cache, collect the ids which are too old * and remove them in a second loop */ @@ -717,9 +717,9 @@ int stat_cache_trigger_cleanup(server *srv) { sc->files = splaytree_splay(sc->files, ndx); node = sc->files; - + if (node && (node->key == ndx)) { -#ifdef DEBUG_STAT_CACHE +#ifdef DEBUG_STAT_CACHE size_t j; int osize = splaytree_size(sc->files); stat_cache_entry *sce = node->data; @@ -727,7 +727,7 @@ int stat_cache_trigger_cleanup(server *srv) { stat_cache_entry_free(node->data); sc->files = splaytree_delete(sc->files, ndx); -#ifdef DEBUG_STAT_CACHE +#ifdef DEBUG_STAT_CACHE for (j = 0; j < ctrl.used; j++) { if (ctrl.ptr[j] == ndx) { ctrl.ptr[j] = ctrl.ptr[--ctrl.used]; diff --git a/src/status_counter.c b/src/status_counter.c index 3b345cd..eaf9251 100644 --- a/src/status_counter.c +++ b/src/status_counter.c @@ -32,7 +32,7 @@ data_integer *status_counter_get_counter(server *srv, const char *s, size_t len) return di; } -/* dummies of the statistic framework functions +/* dummies of the statistic framework functions * they will be moved to a statistics.c later */ int status_counter_inc(server *srv, const char *s, size_t len) { data_integer *di = status_counter_get_counter(srv, s, len); diff --git a/src/status_counter.h b/src/status_counter.h index 431bd9c..210fe85 100644 --- a/src/status_counter.h +++ b/src/status_counter.h @@ -11,4 +11,4 @@ int status_counter_inc(server *srv, const char *s, size_t len); int status_counter_dec(server *srv, const char *s, size_t len); int status_counter_set(server *srv, const char *s, size_t len, int val); -#endif +#endif diff --git a/src/stream.c b/src/stream.c index ecaadc1..aac6cf7 100644 --- a/src/stream.c +++ b/src/stream.c @@ -1,7 +1,7 @@ #include <sys/types.h> #include <sys/stat.h> -#include <unistd.h> +#include <unistd.h> #include <fcntl.h> #include "stream.h" @@ -25,33 +25,33 @@ int stream_open(stream *f, buffer *fn) { #endif f->start = NULL; - + if (-1 == stat(fn->ptr, &st)) { return -1; } - + f->size = st.st_size; #ifdef HAVE_MMAP if (-1 == (fd = open(fn->ptr, O_RDONLY | O_BINARY))) { return -1; } - + f->start = mmap(0, f->size, PROT_READ, MAP_SHARED, fd, 0); - + close(fd); - + if (MAP_FAILED == f->start) { return -1; } #elif defined __WIN32 - fh = CreateFile(fn->ptr, - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_READONLY, + fh = CreateFile(fn->ptr, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_READONLY, NULL); if (!fh) return -1; @@ -66,7 +66,7 @@ int stream_open(stream *f, buffer *fn) { if (!mh) { LPVOID lpMsgBuf; FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), @@ -76,7 +76,7 @@ int stream_open(stream *f, buffer *fn) { return -1; } - + p = MapViewOfFile(mh, FILE_MAP_READ, 0, @@ -87,9 +87,9 @@ int stream_open(stream *f, buffer *fn) { f->start = p; #else -# error no mmap found +# error no mmap found #endif - + return 0; } |