changeset 38:2879cd3a40cb NGINX_0_1_19

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.
author Igor Sysoev <http://sysoev.ru>
date Wed, 16 Feb 2005 00:00:00 +0300
parents 3376a7dea5d6
children 9a816ccfbf63
files CHANGES CHANGES.ru auto/make auto/modules auto/options auto/os/conf auto/os/freebsd src/core/nginx.h src/core/ngx_radix_tree.c src/core/ngx_radix_tree.h src/core/ngx_times.c src/event/modules/ngx_kqueue_module.c src/event/ngx_event_openssl.c src/event/ngx_event_openssl.h src/http/modules/ngx_http_autoindex_handler.c src/http/modules/ngx_http_geo_module.c src/http/modules/ngx_http_gzip_filter.c src/http/modules/ngx_http_index_handler.c src/http/modules/ngx_http_static_handler.c src/http/ngx_http_core_module.c src/http/ngx_http_core_module.h src/http/ngx_http_log_handler.c src/http/ngx_http_parse.c src/http/ngx_http_request.c src/http/ngx_http_request.h src/http/ngx_http_write_filter.c src/os/unix/ngx_linux_sendfile_chain.c
diffstat 27 files changed, 413 insertions(+), 135 deletions(-) [+]
line wrap: on
line diff
--- 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
 
--- 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
 
--- 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
--- 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
--- 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"               ;;
--- 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
--- a/auto/os/freebsd
+++ b/auto/os/freebsd
@@ -64,6 +64,7 @@ then
     EVENT_FOUND=YES
 fi
 
+
 NGX_KQUEUE_CHECKED=YES
 
 
--- 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"
--- 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;
 
--- 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,
--- 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++;
  *      }
  */
     }
--- 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
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -11,12 +11,14 @@
 #include <openssl/engine.h>
 
 
+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;
--- 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_ */
--- 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) {
--- 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;
--- 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 */
 };
 
 
--- 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;
 
     /*
--- 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;
     }
--- 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;
--- 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,
--- 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 },
--- 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;
             }
--- 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 }
 };
 
--- 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;
 
--- 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
 
--- 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