Index: src/base.h =================================================================== --- src/base.h (.../tags/lighttpd-1.4.15) (revision 1880) +++ src/base.h (.../branches/lighttpd-1.4.x) (revision 1880) @@ -269,6 +269,9 @@ unsigned short use_ipv6; unsigned short is_ssl; unsigned short allow_http11; + unsigned short etag_use_inode; + unsigned short etag_use_mtime; + unsigned short etag_use_size; unsigned short force_lowercase_filenames; /* if the FS is case-insensitive, force all files to lower-case */ unsigned short max_request_size; Index: src/connections.c =================================================================== --- src/connections.c (.../tags/lighttpd-1.4.15) (revision 1880) +++ src/connections.c (.../branches/lighttpd-1.4.x) (revision 1880) @@ -1252,6 +1252,16 @@ socklen_t cnt_len; /* accept it and register the fd */ + /** + * check if we can still open a new connections + * + * see #1216 + */ + + if (srv->conns->used >= srv->max_conns) { + return NULL; + } + cnt_len = sizeof(cnt_addr); if (-1 == (cnt = accept(srv_socket->fd, (struct sockaddr *) &cnt_addr, &cnt_len))) { @@ -1265,6 +1275,9 @@ case ECONNABORTED: /* this is a FreeBSD thingy */ /* we were stopped _after_ we had a connection */ break; + case EMFILE: + /* out of fds */ + break; default: log_error_write(srv, __FILE__, __LINE__, "ssd", "accept failed:", strerror(errno), errno); } @@ -1432,6 +1445,7 @@ } else if (con->in_error_handler) { /* error-handler is back and has generated content */ /* if Status: was set, take it otherwise use 200 */ + con->http_status = con->error_handler_saved_status; } if (con->http_status == 0) con->http_status = 200; Index: src/mod_staticfile.c =================================================================== --- src/mod_staticfile.c (.../tags/lighttpd-1.4.15) (revision 1880) +++ src/mod_staticfile.c (.../branches/lighttpd-1.4.x) (revision 1880) @@ -25,6 +25,7 @@ typedef struct { array *exclude_ext; + unsigned short etags_used; } plugin_config; typedef struct { @@ -82,6 +83,7 @@ config_values_t cv[] = { { "static-file.exclude-extensions", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 0 */ + { "static-file.etags", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 1 */ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } }; @@ -94,8 +96,10 @@ s = calloc(1, sizeof(plugin_config)); s->exclude_ext = array_init(); + s->etags_used = 1; cv[0].destination = s->exclude_ext; + cv[1].destination = &(s->etags_used); p->config_storage[i] = s; @@ -114,6 +118,7 @@ plugin_config *s = p->config_storage[0]; PATCH(exclude_ext); + PATCH(etags_used); /* skip the first, the global context */ for (i = 1; i < srv->config_context->used; i++) { @@ -129,7 +134,9 @@ if (buffer_is_equal_string(du->key, CONST_STR_LEN("static-file.exclude-extensions"))) { PATCH(exclude_ext); - } + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("static-file.etags"))) { + PATCH(etags_used); + } } } @@ -446,11 +453,17 @@ response_header_overwrite(srv, con, CONST_STR_LEN("Accept-Ranges"), CONST_STR_LEN("bytes")); if (allow_caching) { - if (NULL == array_get_element(con->response.headers, "ETag")) { - /* generate e-tag */ - etag_mutate(con->physical.etag, sce->etag); + etag_flags_t flags; - response_header_overwrite(srv, con, CONST_STR_LEN("ETag"), CONST_BUF_LEN(con->physical.etag)); + flags = (con->conf.etag_use_mtime ? ETAG_USE_MTIME : 0) | (con->conf.etag_use_inode ? ETAG_USE_INODE : 0) | (con->conf.etag_use_size ? ETAG_USE_SIZE : 0); + + if (p->conf.etags_used && flags != 0 && !buffer_is_empty(sce->etag)) { + 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)); + } } /* prepare header */ Index: src/configfile.c =================================================================== --- src/configfile.c (.../tags/lighttpd-1.4.15) (revision 1880) +++ src/configfile.c (.../branches/lighttpd-1.4.x) (revision 1880) @@ -89,7 +89,9 @@ { "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 */ - + { "etag.use-inode", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 48 */ + { "etag.use-mtime", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 49 */ + { "etag.use-size", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 50 */ { "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 }, @@ -162,6 +164,9 @@ #endif s->kbytes_per_second = 0; s->allow_http11 = 1; + s->etag_use_inode = 1; + s->etag_use_mtime = 1; + s->etag_use_size = 1; s->range_requests = 1; s->force_lowercase_filenames = 0; s->global_kbytes_per_second = 0; @@ -206,6 +211,9 @@ cv[46].destination = s->ssl_cipher_list; cv[47].destination = &(s->ssl_use_sslv2); + cv[48].destination = &(s->etag_use_inode); + cv[49].destination = &(s->etag_use_mtime); + cv[50].destination = &(s->etag_use_size); srv->config_storage[i] = s; @@ -280,8 +288,10 @@ PATCH(ssl_ca_file); PATCH(ssl_cipher_list); PATCH(ssl_use_sslv2); - - + PATCH(etag_use_inode); + PATCH(etag_use_mtime); + PATCH(etag_use_size); + return 0; } @@ -323,6 +333,12 @@ PATCH(max_read_idle); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("mimetype.use-xattr"))) { PATCH(use_xattr); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("etag.use-inode"))) { + PATCH(etag_use_inode); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("etag.use-mtime"))) { + PATCH(etag_use_mtime); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("etag.use-size"))) { + PATCH(etag_use_size); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.pemfile"))) { PATCH(ssl_pemfile); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.ca-file"))) { Index: src/etag.c =================================================================== --- src/etag.c (.../tags/lighttpd-1.4.15) (revision 1880) +++ src/etag.c (.../branches/lighttpd-1.4.x) (revision 1880) @@ -8,13 +8,25 @@ return 0; } -int etag_create(buffer *etag, struct stat *st) { - buffer_copy_off_t(etag, st->st_ino); - buffer_append_string_len(etag, CONST_STR_LEN("-")); - buffer_append_off_t(etag, st->st_size); - buffer_append_string_len(etag, CONST_STR_LEN("-")); - buffer_append_long(etag, st->st_mtime); +int etag_create(buffer *etag, struct stat *st,etag_flags_t flags) { + if (0 == flags) return 0; + buffer_reset(etag); + + if (flags & ETAG_USE_INODE) { + buffer_append_off_t(etag, st->st_ino); + buffer_append_string_len(etag, CONST_STR_LEN("-")); + } + + if (flags & ETAG_USE_SIZE) { + buffer_append_off_t(etag, st->st_size); + buffer_append_string_len(etag, CONST_STR_LEN("-")); + } + + if (flags & ETAG_USE_MTIME) { + buffer_append_long(etag, st->st_mtime); + } + return 0; } Index: src/mod_scgi.c =================================================================== --- src/mod_scgi.c (.../tags/lighttpd-1.4.15) (revision 1880) +++ src/mod_scgi.c (.../branches/lighttpd-1.4.x) (revision 1880) @@ -803,7 +803,7 @@ buffer_append_string_buffer(b, host->bin_path); /* exec the cgi */ - execle("/bin/sh", "sh", "-c", b->ptr, NULL, env.ptr); + execle("/bin/sh", "sh", "-c", b->ptr, (char *)NULL, env.ptr); log_error_write(srv, __FILE__, __LINE__, "sbs", "execl failed for:", host->bin_path, strerror(errno)); Index: src/etag.h =================================================================== --- src/etag.h (.../tags/lighttpd-1.4.15) (revision 1880) +++ src/etag.h (.../branches/lighttpd-1.4.x) (revision 1880) @@ -7,8 +7,10 @@ #include "buffer.h" +typedef enum { ETAG_USE_INODE = 1, ETAG_USE_MTIME = 2, ETAG_USE_SIZE = 4 } etag_flags_t; + int etag_is_equal(buffer *etag, const char *matches); -int etag_create(buffer *etag, struct stat *st); +int etag_create(buffer *etag, struct stat *st, etag_flags_t flags); int etag_mutate(buffer *mut, buffer *etag); Index: src/request.c =================================================================== --- src/request.c (.../tags/lighttpd-1.4.15) (revision 1880) +++ src/request.c (.../branches/lighttpd-1.4.x) (revision 1880) @@ -284,8 +284,6 @@ int done = 0; - data_string *ds = NULL; - /* * Request: "^(GET|POST|HEAD) ([^ ]+(\\?[^ ]+|)) (HTTP/1\\.[01])$" * Option : "^([-a-zA-Z]+): (.+)$" @@ -715,12 +713,24 @@ switch(*cur) { case '\r': if (con->parse_request->ptr[i+1] == '\n') { + data_string *ds = NULL; + /* End of Headerline */ con->parse_request->ptr[i] = '\0'; con->parse_request->ptr[i+1] = '\0'; if (in_folding) { - if (!ds) { + buffer *key_b; + /** + * we use a evil hack to handle the line-folding + * + * As array_insert_unique() deletes 'ds' in the case of a duplicate + * ds points somewhere and we get a evil crash. As a solution we keep the old + * "key" and get the current value from the hash and append us + * + * */ + + if (!key || !key_len) { /* 400 */ if (srv->srvconf.log_request_header_on_error) { @@ -737,7 +747,15 @@ con->response.keep_alive = 0; return 0; } - buffer_append_string(ds->value, value); + + key_b = buffer_init(); + buffer_copy_string_len(key_b, key, key_len); + + if (NULL != (ds = (data_string *)array_get_element(con->request.headers, key_b->ptr))) { + buffer_append_string(ds->value, value); + } + + buffer_free(key_b); } else { int s_len; key = con->parse_request->ptr + first; @@ -969,7 +987,12 @@ first = i+1; is_key = 1; value = 0; - key_len = 0; +#if 0 + /** + * for Bug 1230 keep the key_len a live + */ + key_len = 0; +#endif in_folding = 0; } else { if (srv->srvconf.log_request_header_on_error) { Index: src/stat_cache.c =================================================================== --- src/stat_cache.c (.../tags/lighttpd-1.4.15) (revision 1880) +++ src/stat_cache.c (.../branches/lighttpd-1.4.x) (revision 1880) @@ -608,14 +608,16 @@ break; } } - etag_create(sce->etag, &(sce->st)); + etag_create(sce->etag, &(sce->st), + (con->conf.etag_use_mtime ? ETAG_USE_MTIME : 0) | (con->conf.etag_use_inode ? ETAG_USE_INODE : 0) | (con->conf.etag_use_size ? ETAG_USE_SIZE : 0)); #ifdef HAVE_XATTR - if (buffer_is_empty(sce->content_type)) { + if (con->conf.use_xattr && buffer_is_empty(sce->content_type)) { stat_cache_attr_get(sce->content_type, name->ptr); } #endif } else if (S_ISDIR(st.st_mode)) { - etag_create(sce->etag, &(sce->st)); + etag_create(sce->etag, &(sce->st), + (con->conf.etag_use_mtime ? ETAG_USE_MTIME : 0) | (con->conf.etag_use_inode ? ETAG_USE_INODE : 0) | (con->conf.etag_use_size ? ETAG_USE_SIZE : 0)); } #ifdef HAVE_FAM_H Index: src/http_auth.c =================================================================== --- src/http_auth.c (.../tags/lighttpd-1.4.15) (revision 1880) +++ src/http_auth.c (.../branches/lighttpd-1.4.x) (revision 1880) @@ -830,8 +830,14 @@ username = buffer_init(); - base64_decode(username, realm_str); + if (!base64_decode(username, realm_str)) { + buffer_free(username); + log_error_write(srv, __FILE__, __LINE__, "sb", "decodeing base64-string failed", username); + + return 0; + } + /* r2 == user:password */ if (NULL == (pw = strchr(username->ptr, ':'))) { buffer_free(username); @@ -967,7 +973,7 @@ for (c = b->ptr; *c; c++) { /* skip whitespaces */ while (*c == ' ' || *c == '\t') c++; - if (!c) break; + if (!*c) break; for (i = 0; dkv[i].key; i++) { if ((0 == strncmp(c, dkv[i].key, dkv[i].key_len))) { @@ -1016,9 +1022,24 @@ log_error_write(srv, __FILE__, __LINE__, "s", "digest: missing field"); + + buffer_free(b); return -1; } + /** + * protect the md5-sess against missing cnonce and nonce + */ + if (algorithm && + 0 == strcasecmp(algorithm, "md5-sess") && + (!nonce || !cnonce)) { + log_error_write(srv, __FILE__, __LINE__, "s", + "digest: (md5-sess: missing field"); + + buffer_free(b); + return -1; + } + m = get_http_method_name(con->request.http_method); /* password-string == HA1 */ Index: src/mod_status.c =================================================================== --- src/mod_status.c (.../tags/lighttpd-1.4.15) (revision 1880) +++ src/mod_status.c (.../branches/lighttpd-1.4.x) (revision 1880) @@ -220,6 +220,7 @@ BUFFER_APPEND_STRING_CONST(b, "