# HG changeset patch # User Igor Sysoev # Date 1108501200 -10800 # Node ID 2879cd3a40cbc5df423cc87460c03caeb8e9ea4a # Parent 3376a7dea5d6d722d9351ea450ea47ea61e555fa nginx 0.1.19 *) Bugfix: now, if request contains the zero, then the 404 error is returned for the local requests. *) Bugfix: nginx could not be built on NetBSD 2.0. *) Bugfix: the timeout may occur while reading of the the client request body via SSL connections. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,14 @@ + +Changes with nginx 0.1.19 16 Feb 2005 + + *) Bugfix: now, if request contains the zero, then the 404 error is + returned for the local requests. + + *) Bugfix: nginx could not be built on NetBSD 2.0. + + *) Bugfix: the timeout may occur while reading of the the client + request body via SSL connections. + Changes with nginx 0.1.18 09 Feb 2005 diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,3 +1,14 @@ + +Изменения в nginx 0.1.19 16.02.2005 + + *) Исправление: если в запросе есть нуль, то для локальных запросов + теперь возвращается ошибка 404. + + *) Исправление: nginx не собирался под NetBSD 2.0. + + *) Исправление: во время чтения тела запроса клиента в SSL соединении + мог произойти таймаут. + Изменения в nginx 0.1.18 09.02.2005 diff --git a/auto/make b/auto/make --- a/auto/make +++ b/auto/make @@ -32,7 +32,7 @@ if [ "$CC" = wcl386 ]; then fi -# ALL_INCS, required by OpenWatcom C precompiled headers +# ALL_INCS, required by the addons and by OpenWatcom C precompiled headers ngx_incs=`echo $CORE_INCS $NGX_OBJS $HTTP_INCS $IMAP_INCS\ | sed -e "s/ *\([^ ][^ ]*\)/$ngx_regex_cont$ngx_include_opt\1/g" \ @@ -120,10 +120,32 @@ END fi +if test -n "$NGX_ADDON_SRCS"; then + +cat << END >> $NGX_MAKEFILE + +ADDON_DEPS = \$(CORE_DPES) $NGX_ADDON_DEPS + +END + +fi + + # nginx ngx_all_srcs=`echo $ngx_all_srcs | sed -e "s/\//$ngx_regex_dirsep/g"` -ngx_modules_c=`echo $NGX_MODULES_C | sed -e "s/\//$ngx_regex_dirsep/g"` + +for ngx_src in $NGX_ADDON_SRCS +do + ngx_obj="addon/`basename \`dirname $ngx_src\``" + + test -d $NGX_OBJS/$ngx_obj || mkdir -p $NGX_OBJS/$ngx_obj + + ngx_obj=`echo $ngx_obj/\`basename $ngx_src\` \ + | sed -e "s/\//$ngx_regex_dirsep/g"` + + ngx_all_srcs="$ngx_all_srcs $ngx_obj" +done ngx_all_objs=`echo $ngx_all_srcs \ | sed -e "s/\([^ ]*\.\)cpp/$NGX_OBJS\/\1$ngx_objext/g" \ @@ -131,6 +153,8 @@ ngx_all_objs=`echo $ngx_all_srcs \ -e "s/\([^ ]*\.\)c/$NGX_OBJS\/\1$ngx_objext/g" \ -e "s/\([^ ]*\.\)S/$NGX_OBJS\/\1$ngx_objext/g"` +ngx_modules_c=`echo $NGX_MODULES_C | sed -e "s/\//$ngx_regex_dirsep/g"` + ngx_modules_obj=`echo $ngx_modules_c | sed -e "s/\(.*\.\)c/\1$ngx_objext/"` @@ -185,7 +209,6 @@ END for ngx_src in $CORE_SRCS do - ngx_src=`echo $ngx_src | sed -e "s/\//$ngx_regex_dirsep/g"` ngx_obj=`echo $ngx_src \ | sed -e "s/^\(.*\.\)cpp$/$ngx_objs_dir\1$ngx_objext/g" \ @@ -215,7 +238,6 @@ if [ $HTTP = YES ]; then for ngx_src in $HTTP_SRCS do - ngx_src=`echo $ngx_src | sed -e "s/\//$ngx_regex_dirsep/g"` ngx_obj=`echo $ngx_src \ | sed -e "s/^\(.*\.\)cpp$/$ngx_objs_dir\1$ngx_objext/g" \ @@ -229,7 +251,6 @@ if [ $HTTP = YES ]; then $ngx_cc$ngx_tab$ngx_objout$ngx_obj$ngx_tab$ngx_src END - done fi @@ -247,7 +268,6 @@ if [ $IMAP = YES ]; then for ngx_src in $IMAP_SRCS do - ngx_src=`echo $ngx_src | sed -e "s/\//$ngx_regex_dirsep/g"` ngx_obj=`echo $ngx_src \ | sed -e "s/^\(.*\.\)cpp$/$ngx_objs_dir\1$ngx_objext/g" \ @@ -261,7 +281,38 @@ if [ $IMAP = YES ]; then $ngx_cc$ngx_tab$ngx_objout$ngx_obj$ngx_tab$ngx_src END + done +fi + + +# the addons sources + +if test -n "$NGX_ADDON_SRCS"; then + + ngx_cc="\$(CC) $ngx_compile_opt \$(CFLAGS) $ngx_use_pch \$(ALL_INCS)" + + for ngx_src in $NGX_ADDON_SRCS + do + ngx_obj="addon/`basename \`dirname $ngx_src\``" + + ngx_obj=`echo $ngx_obj/\`basename $ngx_src\` \ + | sed -e "s/\//$ngx_regex_dirsep/g"` + + ngx_obj=`echo $ngx_obj \ + | sed -e "s/^\(.*\.\)cpp$/$ngx_objs_dir\1$ngx_objext/g" \ + -e "s/^\(.*\.\)cc$/$ngx_objs_dir\1$ngx_objext/g" \ + -e "s/^\(.*\.\)c$/$ngx_objs_dir\1$ngx_objext/g" \ + -e "s/^\(.*\.\)S$/$ngx_objs_dir\1$ngx_objext/g"` + + ngx_src=`echo $ngx_src | sed -e "s/\//$ngx_regex_dirsep/g"` + + cat << END >> $NGX_MAKEFILE + +$ngx_obj: \$(ADDON_DEPS)$ngx_cont$ngx_src + $ngx_cc$ngx_tab$ngx_objout$ngx_obj$ngx_tab$ngx_src + +END done fi diff --git a/auto/modules b/auto/modules --- a/auto/modules +++ b/auto/modules @@ -162,10 +162,32 @@ if [ $HTTP_STUB_STATUS = YES ]; then HTTP_SRCS="$HTTP_SRCS src/http/modules/ngx_http_stub_status_module.c" fi -if [ -r $NGX_OBJS/auto ]; then - . $NGX_OBJS/auto +#if [ -r $NGX_OBJS/auto ]; then +# . $NGX_OBJS/auto +#fi + + +if test -n "$NGX_ADDONS"; then + + echo configuring additional modules + + for ngx_addon_dir in $NGX_ADDONS + do + echo "adding module in $ngx_addon_dir" + + if test -f $ngx_addon_dir/config; then + . $ngx_addon_dir/config + + echo " + $ngx_addon_name was configured" + + else + echo "$0: error: no $ngx_addon_dir/config was found" + exit 1 + fi + done fi + modules="$CORE_MODULES $EVENT_MODULES" if [ $HTTP = YES ]; then @@ -174,8 +196,11 @@ if [ $HTTP = YES ]; then $HTTP_COPY_FILTER_MODULE \ $HTTP_RANGE_BODY_FILTER_MODULE \ $HTTP_NOT_MODIFIED_FILTER_MODULE" + + NGX_ADDON_DEPS="$NGX_ADDON_DEPS \$(HTTP_DEPS)" fi + IMAP_MODULES=$IMAP_MODULE if [ $IMAP = YES ]; then diff --git a/auto/options b/auto/options --- a/auto/options +++ b/auto/options @@ -63,7 +63,7 @@ HTTP_STUB_STATUS=NO IMAP=NO -NGX_MODULES= +NGX_ADDONS= USE_PCRE=NO PCRE=NONE @@ -139,7 +139,7 @@ do --with-imap) IMAP=YES ;; - --with-module=*) NGX_MODULES="$NGX_MODULES $values" ;; + --add-module=*) NGX_ADDONS="$NGX_ADDONS $value" ;; --with-cc=*) CC="$value" ;; --with-cpp=*) CPP="$value" ;; diff --git a/auto/os/conf b/auto/os/conf --- a/auto/os/conf +++ b/auto/os/conf @@ -123,4 +123,15 @@ if [ $NGX_PLATFORM != win32 ]; then . auto/feature fi fi + + if [ NGX_SYSTEM != "NetBSD" ]; then + + # NetBSD 2.0 incompatibly defines kevent.udata as "intptr_t" + cat << END >> $NGX_AUTO_CONFIG_H + +#define NGX_KQUEUE_UDATA_T (void *) + +END + + fi fi diff --git a/auto/os/freebsd b/auto/os/freebsd --- a/auto/os/freebsd +++ b/auto/os/freebsd @@ -64,6 +64,7 @@ then EVENT_FOUND=YES fi + NGX_KQUEUE_CHECKED=YES diff --git a/src/core/nginx.h b/src/core/nginx.h --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -8,7 +8,7 @@ #define _NGINX_H_INCLUDED_ -#define NGINX_VER "nginx/0.1.18" +#define NGINX_VER "nginx/0.1.19" #define NGINX_VAR "NGINX" #define NGX_NEWPID_EXT ".newbin" diff --git a/src/core/ngx_radix_tree.c b/src/core/ngx_radix_tree.c --- a/src/core/ngx_radix_tree.c +++ b/src/core/ngx_radix_tree.c @@ -12,7 +12,7 @@ static void *ngx_radix_alloc(ngx_radix_t ngx_radix_tree_t * -ngx_radix_tree_create(ngx_pool_t *pool, ngx_uint_t preallocate) +ngx_radix_tree_create(ngx_pool_t *pool, ngx_int_t preallocate) { uint32_t key, mask, inc; ngx_radix_tree_t *tree; @@ -35,13 +35,46 @@ ngx_radix_tree_create(ngx_pool_t *pool, tree->root->parent = NULL; tree->root->value = NGX_RADIX_NO_VALUE; + if (preallocate == 0) { + return tree; + } + /* * We preallocate the first nodes: 0, 1, 00, 01, 10, 11, 000, 001, etc., * to increase the TLB hits even if for the first lookup iterations. * On the 32-bit platforms the 7 preallocated bits takes continuous 4K, - * 8 - 8K, 9 - 16K, etc. + * 8 - 8K, 9 - 16K, etc. On the 64-bit platforms the 6 preallocated bits + * takes continuous 4K, 7 - 8K, 8 - 16K, etc. There is no sense to + * to preallocate more than one page, because further preallocation + * distribute the only bit per page. Instead, the random insertion + * may distribute several bits per page. + * + * Thus, by default we preallocate maximum + * 6 bits on amd64 (64-bit platform and 4K pages) + * 7 bits on i386 (32-bit platform and 4K pages) + * 7 bits on sparc64 in 64-bit mode (8K pages) + * 8 bits on sparc64 in 32-bit mode (8K pages) */ + if (preallocate == -1) { + switch (ngx_pagesize / sizeof(ngx_radix_tree_t)) { + + /* amd64 */ + case 128: + preallocate = 6; + break; + + /* i386, sparc64 */ + case 256: + preallocate = 7; + break; + + /* sparc64 in 32-bit mode */ + default: + preallocate = 8; + } + } + mask = 0; inc = 0x80000000; diff --git a/src/core/ngx_radix_tree.h b/src/core/ngx_radix_tree.h --- a/src/core/ngx_radix_tree.h +++ b/src/core/ngx_radix_tree.h @@ -34,7 +34,7 @@ typedef struct { ngx_radix_tree_t *ngx_radix_tree_create(ngx_pool_t *pool, - ngx_uint_t preallocate); + ngx_int_t preallocate); ngx_int_t ngx_radix32tree_insert(ngx_radix_tree_t *tree, uint32_t key, uint32_t mask, uintptr_t value); ngx_int_t ngx_radix32tree_delete(ngx_radix_tree_t *tree, diff --git a/src/core/ngx_times.c b/src/core/ngx_times.c --- a/src/core/ngx_times.c +++ b/src/core/ngx_times.c @@ -308,7 +308,6 @@ void ngx_gmtime(time_t t, ngx_tm_t *tp) mday -= 28; } } - /* * there is no "yday" in Win32 SYSTEMTIME * @@ -316,7 +315,7 @@ void ngx_gmtime(time_t t, ngx_tm_t *tp) * yday += 31 + 28; * * if ((year % 4 == 0) && (year % 100 || (year % 400 == 0))) { - * yday++; + * yday++; * } */ } diff --git a/src/event/modules/ngx_kqueue_module.c b/src/event/modules/ngx_kqueue_module.c --- a/src/event/modules/ngx_kqueue_module.c +++ b/src/event/modules/ngx_kqueue_module.c @@ -390,7 +390,7 @@ static ngx_int_t ngx_kqueue_set_event(ng kev->ident = c->fd; kev->filter = filter; kev->flags = flags; - kev->udata = (void *) ((uintptr_t) ev | ev->instance); + kev->udata = NGX_KQUEUE_UDATA_T ((uintptr_t) ev | ev->instance); if (filter == EVFILT_VNODE) { kev->fflags = NOTE_DELETE|NOTE_WRITE|NOTE_EXTEND diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -11,12 +11,14 @@ #include +static ngx_int_t ngx_ssl_handle_recv(ngx_connection_t *c, int n); static void ngx_ssl_write_handler(ngx_event_t *wev); static ssize_t ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size); static void ngx_ssl_read_handler(ngx_event_t *rev); -ngx_int_t ngx_ssl_init(ngx_log_t *log) +ngx_int_t +ngx_ssl_init(ngx_log_t *log) { ENGINE *engine; @@ -28,8 +30,9 @@ ngx_int_t ngx_ssl_init(ngx_log_t *log) } -ngx_int_t ngx_ssl_create_session(ngx_ssl_ctx_t *ssl_ctx, ngx_connection_t *c, - ngx_uint_t flags) +ngx_int_t +ngx_ssl_create_session(ngx_ssl_ctx_t *ssl_ctx, ngx_connection_t *c, + ngx_uint_t flags) { ngx_ssl_t *ssl; @@ -65,58 +68,105 @@ ngx_int_t ngx_ssl_create_session(ngx_ssl } -ssize_t ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size) +ssize_t +ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size) { - int n, sslerr; - ngx_err_t err; - char *handshake; + int n, bytes; + + if (c->ssl->last == NGX_ERROR) { + return NGX_ERROR; + } + + bytes = 0; - n = SSL_read(c->ssl->ssl, buf, size); + /* + * SSL_read() may return data in parts, so try to read + * until SSL_read() would return no data + */ + + for ( ;; ) { - ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_read: %d", n); + n = SSL_read(c->ssl->ssl, buf, size); + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, "SSL_read: %d", n); - if (n > 0) { + if (n > 0) { + + bytes += n; #if (NGX_DEBUG) - if (!c->ssl->handshaked && SSL_is_init_finished(c->ssl->ssl)) { - char buf[129], *s, *d; - SSL_CIPHER *cipher; + if (!c->ssl->handshaked && SSL_is_init_finished(c->ssl->ssl)) { + char buf[129], *s, *d; + SSL_CIPHER *cipher; - c->ssl->handshaked = 1; + c->ssl->handshaked = 1; + + cipher = SSL_get_current_cipher(c->ssl->ssl); + + if (cipher) { + SSL_CIPHER_description(cipher, &buf[1], 128); - cipher = SSL_get_current_cipher(c->ssl->ssl); + for (s = &buf[1], d = buf; *s; s++) { + if (*s == ' ' && *d == ' ') { + continue; + } - if (cipher) { - SSL_CIPHER_description(cipher, &buf[1], 128); + if (*s == '\n' || *s == '\r') { + continue; + } - for (s = &buf[1], d = buf; *s; s++) { - if (*s == ' ' && *d == ' ') { - continue; + *++d = *s; } - if (*s == '\n' || *s == '\r') { - continue; + if (*d != ' ') { + d++; } - *++d = *s; - } + *d = '\0'; - if (*d != ' ') { - d++; + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, + "SSL cipher: \"%s\"", &buf[1]); + } else { + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, + "SSL no shared ciphers"); } + } +#endif - *d = '\0'; + } + + c->ssl->last = ngx_ssl_handle_recv(c, n); + + if (c->ssl->last != NGX_OK) { - ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0, - "SSL cipher: \"%s\"", &buf[1]); + if (bytes) { + return bytes; + } else { - ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, 0, - "SSL no shared ciphers"); + return c->ssl->last; } } -#endif + size -= n; + + if (size == 0) { + return bytes; + } + + buf += n; + } +} + + +static ngx_int_t +ngx_ssl_handle_recv(ngx_connection_t *c, int n) +{ + int sslerr; + ngx_err_t err; + char *handshake; + + if (n > 0) { if (c->ssl->saved_write_handler) { @@ -137,7 +187,7 @@ ssize_t ngx_ssl_recv(ngx_connection_t *c ngx_mutex_unlock(ngx_posted_events_mutex); } - return n; + return NGX_OK; } if (!SSL_is_init_finished(c->ssl->ssl)) { @@ -197,7 +247,8 @@ ssize_t ngx_ssl_recv(ngx_connection_t *c } -static void ngx_ssl_write_handler(ngx_event_t *wev) +static void +ngx_ssl_write_handler(ngx_event_t *wev) { ngx_connection_t *c; @@ -214,8 +265,8 @@ static void ngx_ssl_write_handler(ngx_ev * the output to decrease a SSL overhead some more. */ -ngx_chain_t *ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, - off_t limit) +ngx_chain_t * +ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) { int n; ngx_uint_t flush; @@ -338,7 +389,8 @@ ngx_chain_t *ngx_ssl_send_chain(ngx_conn } -static ssize_t ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size) +static ssize_t +ngx_ssl_write(ngx_connection_t *c, u_char *data, size_t size) { int n, sslerr; ngx_err_t err; @@ -424,7 +476,8 @@ static ssize_t ngx_ssl_write(ngx_connect } -static void ngx_ssl_read_handler(ngx_event_t *rev) +static void +ngx_ssl_read_handler(ngx_event_t *rev) { ngx_connection_t *c; @@ -433,7 +486,8 @@ static void ngx_ssl_read_handler(ngx_eve } -ngx_int_t ngx_ssl_shutdown(ngx_connection_t *c) +ngx_int_t +ngx_ssl_shutdown(ngx_connection_t *c) { int n, sslerr, mode; ngx_uint_t again; @@ -520,8 +574,8 @@ ngx_int_t ngx_ssl_shutdown(ngx_connectio } -void ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, - char *fmt, ...) +void +ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, char *fmt, ...) { u_char errstr[NGX_MAX_CONF_ERRSTR], *p, *last; va_list args; diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h --- a/src/event/ngx_event_openssl.h +++ b/src/event/ngx_event_openssl.h @@ -17,6 +17,7 @@ typedef struct { SSL *ssl; + ngx_int_t last; ngx_buf_t *buf; ngx_event_handler_pt saved_read_handler; ngx_event_handler_pt saved_write_handler; @@ -49,10 +50,10 @@ ngx_int_t ngx_ssl_create_session(ngx_ssl ssize_t ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size); ngx_chain_t *ngx_ssl_send_chain(ngx_connection_t *c, ngx_chain_t *in, - off_t limit); + off_t limit); ngx_int_t ngx_ssl_shutdown(ngx_connection_t *c); void ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, - char *fmt, ...); + char *fmt, ...); #endif /* _NGX_EVENT_OPENSSL_H_INCLUDED_ */ diff --git a/src/http/modules/ngx_http_autoindex_handler.c b/src/http/modules/ngx_http_autoindex_handler.c --- a/src/http/modules/ngx_http_autoindex_handler.c +++ b/src/http/modules/ngx_http_autoindex_handler.c @@ -128,6 +128,11 @@ static ngx_int_t ngx_http_autoindex_hand return NGX_DECLINED; } + /* TODO: Win32 */ + if (r->zero_in_uri) { + return NGX_DECLINED; + } + alcf = ngx_http_get_module_loc_conf(r, ngx_http_autoindex_module); if (!alcf->enable) { diff --git a/src/http/modules/ngx_http_geo_module.c b/src/http/modules/ngx_http_geo_module.c --- a/src/http/modules/ngx_http_geo_module.c +++ b/src/http/modules/ngx_http_geo_module.c @@ -10,9 +10,9 @@ typedef struct { - ngx_radix_tree_t *tree; - ngx_pool_t *pool; - ngx_array_t values; + ngx_radix_tree_t *tree; + ngx_pool_t *pool; + ngx_array_t values; } ngx_http_geo_conf_t; @@ -63,21 +63,31 @@ static ngx_http_variable_value_t ngx_ht /* AF_INET only */ -static ngx_http_variable_value_t *ngx_http_geo_variable(ngx_http_request_t *r, - void *data) +static ngx_http_variable_value_t * +ngx_http_geo_variable(ngx_http_request_t *r, void *data) { ngx_radix_tree_t *tree = data; - struct sockaddr_in *sin; + struct sockaddr_in *sin; + ngx_http_variable_value_t *var; sin = (struct sockaddr_in *) r->connection->sockaddr; - return (ngx_http_variable_value_t *) + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http geo started"); + + var = (ngx_http_variable_value_t *) ngx_radix32tree_find(tree, ntohl(sin->sin_addr.s_addr)); + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http geo: %V %V", &r->connection->addr_text, &var->text); + + return var; } -static char *ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +static char * +ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *rv; ngx_str_t *value; @@ -91,7 +101,7 @@ static char *ngx_http_geo_block(ngx_conf return NGX_CONF_ERROR; } - if (!(tree = ngx_radix_tree_create(cf->pool, 8))) { + if (!(tree = ngx_radix_tree_create(cf->pool, -1))) { return NGX_CONF_ERROR; } @@ -148,7 +158,8 @@ static char *ngx_http_geo_block(ngx_conf /* AF_INET only */ -static char *ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) +static char * +ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) { ngx_int_t rc, n; ngx_uint_t i; diff --git a/src/http/modules/ngx_http_gzip_filter.c b/src/http/modules/ngx_http_gzip_filter.c --- a/src/http/modules/ngx_http_gzip_filter.c +++ b/src/http/modules/ngx_http_gzip_filter.c @@ -216,7 +216,7 @@ static ngx_http_module_t ngx_http_gzip_ NULL, /* merge server configuration */ ngx_http_gzip_create_conf, /* create location configuration */ - ngx_http_gzip_merge_conf, /* merge location configuration */ + ngx_http_gzip_merge_conf /* merge location configuration */ }; diff --git a/src/http/modules/ngx_http_index_handler.c b/src/http/modules/ngx_http_index_handler.c --- a/src/http/modules/ngx_http_index_handler.c +++ b/src/http/modules/ngx_http_index_handler.c @@ -120,6 +120,11 @@ static ngx_int_t ngx_http_index_handler( return NGX_DECLINED; } + /* TODO: Win32 */ + if (r->zero_in_uri) { + return NGX_DECLINED; + } + log = r->connection->log; /* diff --git a/src/http/modules/ngx_http_static_handler.c b/src/http/modules/ngx_http_static_handler.c --- a/src/http/modules/ngx_http_static_handler.c +++ b/src/http/modules/ngx_http_static_handler.c @@ -87,6 +87,11 @@ static ngx_int_t ngx_http_static_handler return NGX_DECLINED; } + /* TODO: Win32 */ + if (r->zero_in_uri) { + return NGX_DECLINED; + } + if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) { return NGX_HTTP_NOT_ALLOWED; } diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -415,6 +415,8 @@ ngx_http_handler(ngx_http_request_t *r) r->uri_changed = 1; r->uri_changes = 11; + r->phase = NGX_HTTP_REWRITE_PHASE; + r->phase_handler = 0; ngx_http_core_run_phases(r); } @@ -447,11 +449,7 @@ ngx_http_core_run_phases(ngx_http_reques for (/* void */; r->phase < NGX_HTTP_LAST_PHASE; r->phase++) { - if (r->phase == NGX_HTTP_FIND_CONFIG_PHASE && !r->uri_changed) { - continue; - } - - if (r->phase == NGX_HTTP_FIND_CONFIG_PHASE + 1 && r->uri_changed) { + if (r->phase == NGX_HTTP_REWRITE_PHASE + 1 && r->uri_changed) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "uri changes: %d", r->uri_changes); @@ -472,8 +470,7 @@ ngx_http_core_run_phases(ngx_http_reques return; } - r->uri_changed = 0; - r->phase = NGX_HTTP_REWRITE_PHASE; + r->phase = NGX_HTTP_FIND_CONFIG_PHASE; } if (r->phase == NGX_HTTP_CONTENT_PHASE && r->content_handler) { @@ -525,7 +522,7 @@ ngx_http_core_run_phases(ngx_http_reques /* no content handler was found */ - if (r->uri.data[r->uri.len - 1] == '/') { + if (r->uri.data[r->uri.len - 1] == '/' && !r->zero_in_uri) { clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); @@ -550,6 +547,9 @@ ngx_http_find_location_config(ngx_http_r ngx_http_core_loc_conf_t *clcf; ngx_http_core_srv_conf_t *cscf; + r->content_handler = NULL; + r->uri_changed = 0; + cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); rc = ngx_http_core_find_location(r, &cscf->locations, 0); @@ -955,10 +955,6 @@ ngx_http_internal_redirect(ngx_http_requ cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); r->loc_conf = cscf->ctx->loc_conf; - r->phase = 0; - r->phase_handler = 0; - r->content_handler = NULL; - ngx_http_handler(r); return NGX_DONE; diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -25,9 +25,9 @@ typedef struct { typedef enum { - NGX_HTTP_REWRITE_PHASE = 0, + NGX_HTTP_FIND_CONFIG_PHASE = 0, - NGX_HTTP_FIND_CONFIG_PHASE, + NGX_HTTP_REWRITE_PHASE, NGX_HTTP_ACCESS_PHASE, NGX_HTTP_CONTENT_PHASE, diff --git a/src/http/ngx_http_log_handler.c b/src/http/ngx_http_log_handler.c --- a/src/http/ngx_http_log_handler.c +++ b/src/http/ngx_http_log_handler.c @@ -137,7 +137,7 @@ ngx_http_log_op_name_t ngx_http_log_fmt_ { ngx_string("addr"), INET_ADDRSTRLEN - 1, NULL, NULL, ngx_http_log_addr }, { ngx_string("conn"), NGX_INT32_LEN, NULL, NULL, ngx_http_log_connection }, { ngx_string("pipe"), 1, NULL, NULL, ngx_http_log_pipe }, - { ngx_string("time"), sizeof("28/Sep/1970:12:00:00") - 1, + { ngx_string("time"), sizeof("28/Sep/1970:12:00:00 +0600") - 1, NULL, NULL, ngx_http_log_time }, { ngx_string("msec"), NGX_TIME_T_LEN + 4, NULL, NULL, ngx_http_log_msec }, { ngx_string("status"), 3, NULL, NULL, ngx_http_log_status }, diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c --- a/src/http/ngx_http_parse.c +++ b/src/http/ngx_http_parse.c @@ -109,6 +109,12 @@ ngx_int_t ngx_http_parse_request_line(ng /* space* before URI */ case sw_spaces_before_uri: + if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) { + r->schema_start = p; + state = sw_schema; + break; + } + switch (ch) { case '/': r->uri_start = p; @@ -117,25 +123,21 @@ ngx_int_t ngx_http_parse_request_line(ng case ' ': break; default: - if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) { - r->schema_start = p; - state = sw_schema; - break; - } return NGX_HTTP_PARSE_INVALID_REQUEST; } break; case sw_schema: + if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) { + break; + } + switch (ch) { case ':': r->schema_end = p; state = sw_schema_slash; break; default: - if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) { - break; - } return NGX_HTTP_PARSE_INVALID_REQUEST; } break; @@ -162,6 +164,12 @@ ngx_int_t ngx_http_parse_request_line(ng break; case sw_host: + if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') + || (ch >= '0' && ch <= '9') || ch == '.' || ch == '-') + { + break; + } + switch (ch) { case ':': r->host_end = p; @@ -173,16 +181,15 @@ ngx_int_t ngx_http_parse_request_line(ng state = sw_after_slash_in_uri; break; default: - if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') - || (ch >= '0' && ch <= '9') || ch == '.' || ch == '-') - { - break; - } return NGX_HTTP_PARSE_INVALID_REQUEST; } break; case sw_port: + if (ch >= '0' && ch <= '9') { + break; + } + switch (ch) { case '/': r->port_end = p; @@ -190,16 +197,26 @@ ngx_int_t ngx_http_parse_request_line(ng state = sw_after_slash_in_uri; break; default: - if (ch < '0' && ch > '9') { - return NGX_HTTP_PARSE_INVALID_REQUEST; - } - break; + return NGX_HTTP_PARSE_INVALID_REQUEST; } break; /* check "/.", "//", "%", and "\" (Win32) in URI */ case sw_after_slash_in_uri: + + if ((ch >= 'a' && ch <= 'z') + || (ch >= 'A' && ch <= 'Z') + || (ch >= '0' && ch <= '9')) + { + state = sw_check_uri; + break; + } + switch (ch) { + case ' ': + r->uri_end = p; + state = sw_http_09; + break; case CR: r->uri_end = p; r->http_minor = 9; @@ -209,10 +226,6 @@ ngx_int_t ngx_http_parse_request_line(ng r->uri_end = p; r->http_minor = 9; goto done; - case ' ': - r->uri_end = p; - state = sw_http_09; - break; case '.': r->complex_uri = 1; state = sw_uri; @@ -221,20 +234,25 @@ ngx_int_t ngx_http_parse_request_line(ng r->quoted_uri = 1; state = sw_uri; break; + case '/': + r->complex_uri = 1; + state = sw_uri; + break; #if (NGX_WIN32) case '\\': r->complex_uri = 1; + state = sw_uri; break; #endif - case '/': - r->complex_uri = 1; + case '?': + r->args_start = p + 1; + state = sw_uri; break; case '+': r->plus_in_uri = 1; break; - case '?': - r->args_start = p + 1; - state = sw_uri; + case '\0': + r->zero_in_uri = 1; break; default: state = sw_check_uri; @@ -244,7 +262,26 @@ ngx_int_t ngx_http_parse_request_line(ng /* check "/", "%" and "\" (Win32) in URI */ case sw_check_uri: + + if ((ch >= 'a' && ch <= 'z') + || (ch >= 'A' && ch <= 'Z') + || (ch >= '0' && ch <= '9')) + { + break; + } + switch (ch) { + case '/': + r->uri_ext = NULL; + state = sw_after_slash_in_uri; + break; + case '.': + r->uri_ext = p + 1; + break; + case ' ': + r->uri_end = p; + state = sw_http_09; + break; case CR: r->uri_end = p; r->http_minor = 9; @@ -254,40 +291,36 @@ ngx_int_t ngx_http_parse_request_line(ng r->uri_end = p; r->http_minor = 9; goto done; - case ' ': - r->uri_end = p; - state = sw_http_09; - break; - case '.': - r->uri_ext = p + 1; - break; #if (NGX_WIN32) case '\\': r->complex_uri = 1; state = sw_after_slash_in_uri; break; #endif - case '/': - r->uri_ext = NULL; - state = sw_after_slash_in_uri; + case '%': + r->quoted_uri = 1; + state = sw_uri; break; case '+': r->plus_in_uri = 1; break; - case '%': - r->quoted_uri = 1; - state = sw_uri; - break; case '?': r->args_start = p + 1; state = sw_uri; break; + case '\0': + r->zero_in_uri = 1; + break; } break; /* URI */ case sw_uri: switch (ch) { + case ' ': + r->uri_end = p; + state = sw_http_09; + break; case CR: r->uri_end = p; r->http_minor = 9; @@ -300,9 +333,8 @@ ngx_int_t ngx_http_parse_request_line(ng case '+': r->plus_in_uri = 1; break; - case ' ': - r->uri_end = p; - state = sw_http_09; + case '\0': + r->zero_in_uri = 1; break; } break; @@ -946,12 +978,20 @@ ngx_int_t ngx_http_parse_complex_uri(ngx case sw_quoted_second: if (ch >= '0' && ch <= '9') { ch = (u_char) ((decoded << 4) + ch - '0'); + if (ch == '%') { state = sw_usual; *u++ = ch; ch = *p++; break; } + + if (ch == '\0') { + r->zero_in_uri = 1; + *u++ = ch; + ch = *p++; + } + state = quoted_state; break; } diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -58,13 +58,13 @@ ngx_http_header_t ngx_http_headers_in[] { ngx_string("Host"), offsetof(ngx_http_headers_in_t, host) }, { ngx_string("Connection"), offsetof(ngx_http_headers_in_t, connection) }, { ngx_string("If-Modified-Since"), - offsetof(ngx_http_headers_in_t, if_modified_since) }, + offsetof(ngx_http_headers_in_t, if_modified_since) }, { ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent) }, { ngx_string("Referer"), offsetof(ngx_http_headers_in_t, referer) }, { ngx_string("Content-Length"), - offsetof(ngx_http_headers_in_t, content_length) }, + offsetof(ngx_http_headers_in_t, content_length) }, { ngx_string("Content-Type"), - offsetof(ngx_http_headers_in_t, content_type) }, + offsetof(ngx_http_headers_in_t, content_type) }, { ngx_string("Range"), offsetof(ngx_http_headers_in_t, range) }, #if 0 @@ -73,22 +73,29 @@ ngx_http_header_t ngx_http_headers_in[] #if (NGX_HTTP_GZIP) { ngx_string("Accept-Encoding"), - offsetof(ngx_http_headers_in_t, accept_encoding) }, + offsetof(ngx_http_headers_in_t, accept_encoding) }, { ngx_string("Via"), offsetof(ngx_http_headers_in_t, via) }, #endif { ngx_string("Authorization"), - offsetof(ngx_http_headers_in_t, authorization) }, + offsetof(ngx_http_headers_in_t, authorization) }, { ngx_string("Keep-Alive"), offsetof(ngx_http_headers_in_t, keep_alive) }, #if (NGX_HTTP_PROXY) { ngx_string("X-Forwarded-For"), - offsetof(ngx_http_headers_in_t, x_forwarded_for) }, + offsetof(ngx_http_headers_in_t, x_forwarded_for) }, { ngx_string("X-Real-IP"), offsetof(ngx_http_headers_in_t, x_real_ip) }, { ngx_string("X-URL"), offsetof(ngx_http_headers_in_t, x_url) }, #endif +#if (NGX_HTTP_HEADERS) + { ngx_string("Accept"), offsetof(ngx_http_headers_in_t, accept) }, + { ngx_string("Accept-Language"), + offsetof(ngx_http_headers_in_t, accept_language) }, + { ngx_string("Via"), offsetof(ngx_http_headers_in_t, via) }, +#endif + { ngx_null_string, 0 } }; diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -152,6 +152,11 @@ typedef struct { ngx_table_elt_t *x_url; #endif +#if (NGX_HTTP_HEADERS) + ngx_table_elt_t *accept; + ngx_table_elt_t *accept_language; +#endif + ngx_array_t cookies; size_t host_name_len; @@ -325,6 +330,9 @@ struct ngx_http_request_s { /* URI with "+" */ unsigned plus_in_uri:1; + /* URI with "\0" or "%00" */ + unsigned zero_in_uri:1; + unsigned uri_changed:1; unsigned uri_changes:4; diff --git a/src/http/ngx_http_write_filter.c b/src/http/ngx_http_write_filter.c --- a/src/http/ngx_http_write_filter.c +++ b/src/http/ngx_http_write_filter.c @@ -94,6 +94,7 @@ ngx_int_t ngx_http_write_filter(ngx_http cl->buf->file_last); ngx_debug_point(); + return NGX_ERROR; } #endif @@ -144,6 +145,7 @@ ngx_int_t ngx_http_write_filter(ngx_http cl->buf->file_last); ngx_debug_point(); + return NGX_ERROR; } #endif diff --git a/src/os/unix/ngx_linux_sendfile_chain.c b/src/os/unix/ngx_linux_sendfile_chain.c --- a/src/os/unix/ngx_linux_sendfile_chain.c +++ b/src/os/unix/ngx_linux_sendfile_chain.c @@ -102,6 +102,8 @@ ngx_chain_t *ngx_linux_sendfile_chain(ng cl->buf->file_last); ngx_debug_point(); + + return NGX_CHAIN_ERROR; } #endif