changeset 50:72eb30262aac NGINX_0_1_25

nginx 0.1.25 *) Bugfix: nginx did run on Linux parisc. *) Feature: nginx now does not start under FreeBSD if the sysctl kern.ipc.somaxconn value is too big. *) Bugfix: if a request was internally redirected by the ngx_http_index_module module to the ngx_http_proxy_module or ngx_http_fastcgi_module modules, then the index file was not closed after request completion. *) Feature: the "proxy_pass" can be used in location with regular expression. *) Feature: the ngx_http_rewrite_filter_module module supports the condition like "if ($HTTP_USER_AGENT ~ MSIE)". *) Bugfix: nginx started too slow if the large number of addresses and text values were used in the "geo" directive. *) Change: a variable name must be declared as "$name" in the "geo" directive. The previous variant without "$" is still supported, but will be removed soon. *) Feature: the "%{VARIABLE}v" logging parameter. *) Feature: the "set $name value" directive. *) Bugfix: gcc 4.0 compatibility. *) Feature: the --with-openssl-opt=OPTIONS autoconfiguration directive.
author Igor Sysoev <http://sysoev.ru>
date Sat, 19 Mar 2005 00:00:00 +0300
parents 93dabbc9efb9
children 43f383e47efc
files CHANGES CHANGES.ru auto/cc/gcc auto/cc/icc auto/lib/openssl/make auto/options auto/sources auto/summary src/core/nginx.c src/core/nginx.h src/core/ngx_array.c src/core/ngx_array.h src/core/ngx_buf.c src/core/ngx_buf.h src/core/ngx_conf_file.c src/core/ngx_connection.c src/core/ngx_cycle.c src/core/ngx_file.c src/core/ngx_file.h src/core/ngx_garbage_collector.c src/core/ngx_inet.c src/core/ngx_list.c src/core/ngx_list.h src/core/ngx_log.c src/core/ngx_output_chain.c src/core/ngx_palloc.c src/core/ngx_palloc.h src/core/ngx_radix_tree.c src/core/ngx_regex.c src/core/ngx_regex.h src/core/ngx_string.c src/core/ngx_string.h src/core/ngx_times.c src/core/ngx_unix_domain.c src/event/modules/ngx_devpoll_module.c src/event/modules/ngx_epoll_module.c src/event/modules/ngx_kqueue_module.c src/event/modules/ngx_poll_module.c src/event/modules/ngx_rtsig_module.c src/event/modules/ngx_select_module.c src/event/ngx_event.c src/event/ngx_event_accept.c src/event/ngx_event_openssl.c src/event/ngx_event_pipe.c src/event/ngx_event_posted.c src/event/ngx_event_timer.c src/event/ngx_event_timer.h src/http/modules/ngx_http_access_handler.c src/http/modules/ngx_http_access_module.c src/http/modules/ngx_http_autoindex_handler.c src/http/modules/ngx_http_autoindex_module.c src/http/modules/ngx_http_charset_filter.c src/http/modules/ngx_http_charset_filter_module.c src/http/modules/ngx_http_chunked_filter.c src/http/modules/ngx_http_chunked_filter_module.c src/http/modules/ngx_http_fastcgi_handler.c src/http/modules/ngx_http_fastcgi_module.c src/http/modules/ngx_http_geo_module.c src/http/modules/ngx_http_gzip_filter.c src/http/modules/ngx_http_gzip_filter_module.c src/http/modules/ngx_http_headers_filter.c src/http/modules/ngx_http_headers_filter_module.c src/http/modules/ngx_http_index_handler.c src/http/modules/ngx_http_index_module.c src/http/modules/ngx_http_not_modified_filter.c src/http/modules/ngx_http_not_modified_filter_module.c src/http/modules/ngx_http_range_filter.c src/http/modules/ngx_http_range_filter_module.c src/http/modules/ngx_http_rewrite_handler.c src/http/modules/ngx_http_rewrite_module.c src/http/modules/ngx_http_ssi_filter.c src/http/modules/ngx_http_ssi_filter_module.c src/http/modules/ngx_http_ssl_module.c src/http/modules/ngx_http_ssl_module.h src/http/modules/ngx_http_static_handler.c src/http/modules/ngx_http_static_module.c src/http/modules/ngx_http_stub_status_module.c src/http/modules/ngx_http_userid_filter.c src/http/modules/ngx_http_userid_filter_module.c src/http/modules/proxy/ngx_http_proxy_handler.c src/http/modules/proxy/ngx_http_proxy_header.c src/http/modules/proxy/ngx_http_proxy_upstream.c src/http/ngx_http.c src/http/ngx_http.h src/http/ngx_http_busy_lock.c src/http/ngx_http_config.h src/http/ngx_http_copy_filter.c src/http/ngx_http_copy_filter_module.c src/http/ngx_http_core_module.c src/http/ngx_http_header_filter.c src/http/ngx_http_header_filter_module.c src/http/ngx_http_log_handler.c src/http/ngx_http_log_handler.h src/http/ngx_http_log_module.c src/http/ngx_http_log_module.h src/http/ngx_http_parse.c src/http/ngx_http_parse_time.c src/http/ngx_http_request.c src/http/ngx_http_request.h src/http/ngx_http_request_body.c src/http/ngx_http_special_response.c src/http/ngx_http_upstream.c src/http/ngx_http_variables.c src/http/ngx_http_variables.h src/http/ngx_http_write_filter.c src/http/ngx_http_write_filter_module.c src/os/unix/ngx_aio_read_chain.c src/os/unix/ngx_aio_write_chain.c src/os/unix/ngx_alloc.c src/os/unix/ngx_errno.c src/os/unix/ngx_errno.h src/os/unix/ngx_files.c src/os/unix/ngx_freebsd_init.c src/os/unix/ngx_freebsd_rfork_thread.c src/os/unix/ngx_freebsd_rfork_thread.h src/os/unix/ngx_freebsd_sendfile_chain.c src/os/unix/ngx_linux_sendfile_chain.c src/os/unix/ngx_posix_init.c src/os/unix/ngx_process.c src/os/unix/ngx_process_cycle.c src/os/unix/ngx_pthread_thread.c src/os/unix/ngx_readv_chain.c src/os/unix/ngx_setproctitle.c src/os/unix/ngx_socket.c src/os/unix/ngx_solaris_sendfilev_chain.c src/os/unix/ngx_writev_chain.c
diffstat 123 files changed, 12586 insertions(+), 11283 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,37 @@
+
+Changes with nginx 0.1.25                                        19 Mar 2005
+
+    *) Bugfix: nginx did run on Linux parisc.
+
+    *) Feature: nginx now does not start under FreeBSD if the sysctl 
+       kern.ipc.somaxconn value is too big.
+
+    *) Bugfix: if a request was internally redirected by the 
+       ngx_http_index_module module to the ngx_http_proxy_module or 
+       ngx_http_fastcgi_module modules, then the index file was not closed 
+       after request completion.
+
+    *) Feature: the "proxy_pass" can be used in location with regular 
+       expression.
+
+    *) Feature: the ngx_http_rewrite_filter_module module supports the 
+       condition like "if ($HTTP_USER_AGENT ~ MSIE)".
+
+    *) Bugfix: nginx started too slow if the large number of addresses and 
+       text values were used in the "geo" directive.
+
+    *) Change: a variable name must be declared as "$name" in the "geo" 
+       directive. The previous variant without "$" is still supported, but 
+       will be removed soon.
+
+    *) Feature: the "%{VARIABLE}v" logging parameter.
+
+    *) Feature: the "set $name value" directive.
+
+    *) Bugfix: gcc 4.0 compatibility.
+
+    *) Feature: the --with-openssl-opt=OPTIONS autoconfiguration directive.
+
 
 Changes with nginx 0.1.24                                        04 Mar 2005
 
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,3 +1,36 @@
+
+éÚÍÅÎÅÎÉÑ × nginx 0.1.25                                          19.03.2005
+
+    *) éÓÐÒÁ×ÌÅÎÉÅ: nginx ÎÅ ÒÁÂÏÔÁÌ ÎÁ Linux parisc.
+
+    *) äÏÂÁ×ÌÅÎÉÅ: nginx ÔÅÐÅÒØ ÎÅ ÚÁÐÕÓËÁÅÔÓÑ ÐÏÄ FreeBSD, ÅÓÌÉ ÚÎÁÞÅÎÉÅ 
+       sysctl kern.ipc.somaxconn ÓÌÉÛËÏÍ ÂÏÌØÛÏÅ.
+
+    *) éÓÐÒÁ×ÌÅÎÉÅ: ÅÓÌÉ ÍÏÄÕÌØ ngx_http_index_module ÄÅÌÁÌ ×ÎÕÔÒÅÎÎÅÅ 
+       ÐÅÒÅÎÁÐÒÁ×ÌÅÎÉÅ ÚÁÐÒÏÓÁ × ÍÏÄÕÌÉ ngx_http_proxy_module ÉÌÉ 
+       ngx_http_fastcgi_module, ÔÏ ÆÁÊÌ ÉÎÄÅËÓÁ ÎÅ ÚÁËÒÙ×ÁÌÓÑ ÐÏÓÌÅ 
+       ÏÂÓÌÕÖÉ×ÁÎÉÑ ÚÁÐÒÏÓÁ.
+
+    *) äÏÂÁ×ÌÅÎÉÅ: ÄÉÒÅËÔÉ×Á proxy_pass ÍÏÖÅÔ ÉÓÐÏÌØÚÏ×ÁÔØÓÑ × location, 
+       ÚÁÄÁÎÎÙÈ ÒÅÇÕÌÑÒÎÙÍ ×ÙÒÁÖÅÎÉÅÍ.
+
+    *) äÏÂÁ×ÌÅÎÉÅ: ÍÏÄÕÌØ ngx_http_rewrite_filter_module ÐÏÄÄÅÒÖÉ×ÁÅÔ 
+       ÕÓÌÏ×ÉÑ ×ÉÄÁ "if ($HTTP_USER_AGENT ~ MSIE)".
+
+    *) éÓÐÒÁ×ÌÅÎÉÅ: nginx ÏÞÅÎØ ÍÅÄÌÅÎÎÏ ÚÁÐÕÓËÁÌÓÑ ÐÒÉ ÂÏÌØÛÏÍ ËÏÌÉÞÅÓÔ×Å 
+       ÁÄÒÅÓÏ× É ÉÓÐÏÌØÚÏ×ÁÎÉÉ ÔÅËÓÔÏ×ÙÈ ÚÎÁÞÅÎÉÊ × ÄÉÒÅËÔÉ×Å geo.
+
+    *) éÚÍÅÎÅÎÉÅ: ÉÍÑ ÐÅÒÅÍÅÎÎÏÊ × ÄÉÒÅËÔÉ×Å geo ÎÕÖÎÏ ÕËÁÚÙ×ÁÔØ, ËÁË 
+       $name. ðÒÅÖÎÉÊ ×ÁÒÉÁÎÔ ÂÅÚ "$" ÐÏËÁ ÒÁÂÏÔÁÅÔ, ÎÏ ×ÓËÏÒÅ ÂÕÄÅÔ ÕÂÒÁÎ.
+
+    *) äÏÂÁ×ÌÅÎÉÅ: ÐÁÒÁÍÅÔÒ ÌÏÇÁ "%{VARIABLE}v".
+
+    *) äÏÂÁ×ÌÅÎÉÅ: ÄÉÒÅËÔÉ×Á "set $name value".
+
+    *) éÓÐÒÁ×ÌÅÎÉÅ: ÓÏ×ÍÅÓÔÉÍÏÓÔØ Ó gcc 4.0.
+
+    *) äÏÂÁ×ÌÅÎÉÅ: ÐÁÒÁÍÅÔÒ Á×ÔÏËÏÎÆÉÇÕÒÁÃÉÉ --with-openssl-opt=OPTIONS.
+
 
 éÚÍÅÎÅÎÉÑ × nginx 0.1.24                                          04.03.2005
 
--- a/auto/cc/gcc
+++ b/auto/cc/gcc
@@ -2,8 +2,15 @@
 # Copyright (C) Igor Sysoev
 
 
-# gcc 2.7.2.3, 2.8.1, 2.95.4,
+# gcc 2.7.2.3, 2.8.1, 2.95.4, egcs-1.1.2
 #     3.0.4, 3.1.1, 3.2.3, 3.3.2, 3.3.3, 3.3.4, 3.4.0, 3.4.2
+#     4.0.0
+
+
+NGX_GCC_VER=`$CC -v 2>&1 | grep 'gcc version' 2>&1 \
+                         | sed -e 's/^.* version \(.*\)/\1/'`
+
+echo " + gcc version: $NGX_GCC_VER"
 
 
 # Solaris 7's /usr/ccs/bin/as does not support "-pipe"
@@ -24,7 +31,6 @@ if [ $ngx_found = yes ]; then
     PIPE="-pipe"
 fi
 
-
 # optimizations
 
 #NGX_GCC_OPT="-O2"
@@ -61,8 +67,12 @@ case $CPU in
 esac
 
 
-# STUB for batch builds
-if [ $CC = gcc27 ]; then CPU_OPT=; fi
+case "$NGX_GCC_VER" in
+    2.7*)
+        # batch build
+        CPU_OPT=
+    ;;
+esac
 
 
 CFLAGS="$CFLAGS $PIPE $CPU_OPT"
@@ -95,8 +105,21 @@ CFLAGS="$CFLAGS -Wall -Wpointer-arith"
 #CFLAGS="$CFLAGS -Wconversion" 
 #CFLAGS="$CFLAGS -Winline"
 
-# we have a lot of the unused function arguments
-CFLAGS="$CFLAGS -Wno-unused"
+
+case "$NGX_GCC_VER" in
+    3.* | 4.* )
+        # we have a lot of the unused function arguments
+        CFLAGS="$CFLAGS -Wno-unused-parameter"
+        CFLAGS="$CFLAGS -Wno-unused-function"
+        #CFLAGS="$CFLAGS -Wunreachable-code"
+    ;;
+
+    *)
+        # we have a lot of the unused function arguments
+        CFLAGS="$CFLAGS -Wno-unused"
+    ;;
+esac
+
 
 # stop on warning
 CFLAGS="$CFLAGS -Werror"
--- a/auto/cc/icc
+++ b/auto/cc/icc
@@ -7,7 +7,7 @@
 # optimizations
 
 CFLAGS="$CFLAGS -O"
-# inline functions declared with __inline
+# inline the functions declared with __inline
 #CFLAGS="$CFLAGS -Ob1"
 # inline any function, at the compiler's discretion
 CFLAGS="$CFLAGS -Ob2"
@@ -54,14 +54,34 @@ fi
 
 # warnings
 
-CFLAGS="$CFLAGS -w1"
-#CFLAGS="$CFLAGS -w2"
+CFLAGS="$CFLAGS -w2"
+
+# disable some warnings
 
-# disable the ICC 8.1 errors:
-#    error #181: argument is incompatible with corresponding format
-#                string conversion
-#    error #269: invalid format string conversion
-CFLAGS="$CFLAGS -wd181 -wd269"
+# invalid type conversion: "int" to "char *"
+CFLAGS="$CFLAGS -wd171"
+# argument is incompatible with corresponding format string conversion
+CFLAGS="$CFLAGS -wd181"
+# zero used for undefined preprocessing identifier
+CFLAGS="$CFLAGS -wd193"
+# invalid format string conversion
+CFLAGS="$CFLAGS -wd269"
+# conversion from "long long" to "size_t" may lose significant bits
+CFLAGS="$CFLAGS -wd810"
+# parameter was never referenced
+CFLAGS="$CFLAGS -wd869"
+
+# STUB
+# enumerated type mixed with another type
+CFLAGS="$CFLAGS -wd188"
+# controlling expression is constant
+CFLAGS="$CFLAGS -wd279"
+# operands are evaluated in unspecified order
+CFLAGS="$CFLAGS -wd981"
+# external definition with no prior declaration
+CFLAGS="$CFLAGS -wd1418"
+# external declaration in primary source file
+CFLAGS="$CFLAGS -wd1419"
 
 # stop on warning
 CFLAGS="$CFLAGS -Werror"
--- a/auto/lib/openssl/make
+++ b/auto/lib/openssl/make
@@ -1,17 +1,28 @@
 
 # Copyright (C) Igor Sysoev
 
+if test -n "$OPENSSL_OPT"; then
+    NGX_OPENSSL_CONFIG="./Configure \"$OPENSSL_OPT\""
+else
+    NGX_OPENSSL_CONFIG="./config"
+fi
+
+if test -n "$USE_THREADS"; then
+    NGX_OPENSSL_CONFIG="$NGX_OPENSSL_CONFIG threads"
+fi
 
 case "$NGX_PLATFORM" in
     *)
-        echo "$OPENSSL/libssl.a:"                                 >> $MAKEFILE
-        echo "	cd $OPENSSL \\"                                   >> $MAKEFILE
-        echo "	&& \$(MAKE) clean \\"                             >> $MAKEFILE
-        echo "	&& CC=\"\$(CC)\" \\"                              >> $MAKEFILE
-        echo "	./config threads no-shared \\"                    >> $MAKEFILE
-        echo "	&& \$(MAKE)"                                      >> $MAKEFILE
+        cat << END                                            >> $NGX_MAKEFILE
+
+$OPENSSL/libssl.a:
+	cd $OPENSSL \\
+	&& \$(MAKE) clean \\
+	&& $NGX_OPENSSL_CONFIG no-shared \\
+	&& \$(MAKE)
+
+END
+
     ;;
 
 esac
-
-echo                                                              >> $MAKEFILE
--- a/auto/options
+++ b/auto/options
@@ -153,6 +153,7 @@ do
         --with-pcre-opt=*)               PCRE_OPT="$value"          ;;
 
         --with-openssl=*)                OPENSSL="$value"           ;;
+        --with-openssl-opt=*)            OPENSSL_OPT="$value"       ;;
 
         --with-md5=*)                    MD5="$value"               ;;
         --with-md5-opt=*)                MD5_OPT="$value"           ;;
@@ -203,6 +204,7 @@ cat << END
   --with-http_ssl_module             enable ngx_http_ssl_module
   --without-http_charset_module      disable ngx_http_charset_module
   --without-http_gzip_module         disable ngx_http_gzip_module
+  --without-http_ssi_module          disable ngx_http_ssi_module
   --without-http_userid_module       disable ngx_http_userid_module
   --without-http_access_module       disable ngx_http_access_module
   --without-http_autoindex_module    disable ngx_http_autoindex_module
@@ -241,6 +243,7 @@ cat << END
                                      pentium, pentiumpro
 
   --with-openssl=DIR                 set path to OpenSSL library sources
+  --with-openssl-opt=OPTIONS         set additional options for OpenSSL building
 
   --with-debug                       enable the debugging logging
 
--- a/auto/sources
+++ b/auto/sources
@@ -241,27 +241,27 @@ HTTP_DEPS="src/http/ngx_http.h \
            src/http/ngx_http_variables.h \
            src/http/ngx_http_upstream.h \
            src/http/ngx_http_busy_lock.h \
-           src/http/ngx_http_log_handler.h"
+           src/http/ngx_http_log_module.h"
 
 HTTP_SRCS="src/http/ngx_http.c \
            src/http/ngx_http_core_module.c \
            src/http/ngx_http_special_response.c \
            src/http/ngx_http_request.c \
            src/http/ngx_http_parse.c \
-           src/http/ngx_http_header_filter.c \
-           src/http/ngx_http_write_filter.c \
-           src/http/ngx_http_copy_filter.c \
-           src/http/ngx_http_log_handler.c \
+           src/http/ngx_http_header_filter_module.c \
+           src/http/ngx_http_write_filter_module.c \
+           src/http/ngx_http_copy_filter_module.c \
+           src/http/ngx_http_log_module.c \
            src/http/ngx_http_request_body.c \
            src/http/ngx_http_variables.c \
            src/http/ngx_http_upstream.c \
            src/http/ngx_http_parse_time.c \
-           src/http/modules/ngx_http_static_handler.c \
-           src/http/modules/ngx_http_index_handler.c \
-           src/http/modules/ngx_http_chunked_filter.c \
-           src/http/modules/ngx_http_range_filter.c \
-           src/http/modules/ngx_http_headers_filter.c \
-           src/http/modules/ngx_http_not_modified_filter.c"
+           src/http/modules/ngx_http_static_module.c \
+           src/http/modules/ngx_http_index_module.c \
+           src/http/modules/ngx_http_chunked_filter_module.c \
+           src/http/modules/ngx_http_range_filter_module.c \
+           src/http/modules/ngx_http_headers_filter_module.c \
+           src/http/modules/ngx_http_not_modified_filter_module.c"
 
 # STUB
 HTTP_SRCS="$HTTP_SRCS src/http/ngx_http_busy_lock.c"
@@ -271,31 +271,31 @@ HTPP_FILE_CACHE_SRCS=src/http/ngx_http_f
 
 
 HTTP_CHARSET_FILTER_MODULE=ngx_http_charset_filter_module
-HTTP_CHARSET_SRCS=src/http/modules/ngx_http_charset_filter.c
+HTTP_CHARSET_SRCS=src/http/modules/ngx_http_charset_filter_module.c
 
 
 HTTP_GZIP_FILTER_MODULE=ngx_http_gzip_filter_module
-HTTP_GZIP_SRCS=src/http/modules/ngx_http_gzip_filter.c
+HTTP_GZIP_SRCS=src/http/modules/ngx_http_gzip_filter_module.c
 
 
 HTTP_SSI_FILTER_MODULE=ngx_http_ssi_filter_module
-HTTP_SSI_SRCS=src/http/modules/ngx_http_ssi_filter.c
+HTTP_SSI_SRCS=src/http/modules/ngx_http_ssi_filter_module.c
 
 
 HTTP_USERID_FILTER_MODULE=ngx_http_userid_filter_module
-HTTP_USERID_SRCS=src/http/modules/ngx_http_userid_filter.c
+HTTP_USERID_SRCS=src/http/modules/ngx_http_userid_filter_module.c
 
 
 HTTP_ACCESS_MODULE=ngx_http_access_module
-HTTP_ACCESS_SRCS=src/http/modules/ngx_http_access_handler.c
+HTTP_ACCESS_SRCS=src/http/modules/ngx_http_access_module.c
 
 
 HTTP_AUTOINDEX_MODULE=ngx_http_autoindex_module
-HTTP_AUTOINDEX_SRCS=src/http/modules/ngx_http_autoindex_handler.c
+HTTP_AUTOINDEX_SRCS=src/http/modules/ngx_http_autoindex_module.c
 
 
 HTTP_STATUS_MODULE=ngx_http_status_module
-HTTP_STATUS_SRCS=src/http/modules/ngx_http_status_handler.c
+HTTP_STATUS_SRCS=src/http/modules/ngx_http_status_module.c
 
 
 HTTP_GEO_MODULE=ngx_http_geo_module
@@ -303,7 +303,7 @@ HTTP_GEO_SRCS=src/http/modules/ngx_http_
 
 
 HTTP_REWRITE_MODULE=ngx_http_rewrite_module
-HTTP_REWRITE_SRCS=src/http/modules/ngx_http_rewrite_handler.c
+HTTP_REWRITE_SRCS=src/http/modules/ngx_http_rewrite_module.c
 
 
 HTTP_SSL_MODULE=ngx_http_ssl_module
@@ -324,7 +324,7 @@ HTTP_PROXY_SRCS="src/http/modules/proxy/
 
 
 HTTP_FASTCGI_MODULE=ngx_http_fastcgi_module
-HTTP_FASTCGI_SRCS=src/http/modules/ngx_http_fastcgi_handler.c
+HTTP_FASTCGI_SRCS=src/http/modules/ngx_http_fastcgi_module.c
 
 
 IMAP_INCS="src/imap"
--- a/auto/summary
+++ b/auto/summary
@@ -17,7 +17,7 @@ case $USE_THREADS in
 esac
 
 if [ $USE_PCRE = DISABLED ]; then
-    echo " + PCRE library is disabled"
+    echo "  + PCRE library is disabled"
 
 else
     case $PCRE in
--- a/src/core/nginx.c
+++ b/src/core/nginx.c
@@ -141,7 +141,8 @@ main(int argc, char *const *argv)
 
     ngx_pid = ngx_getpid();
 
-    if (!(log = ngx_log_init())) {
+    log = ngx_log_init();
+    if (log == NULL) {
         return 1;
     }
 
@@ -155,7 +156,8 @@ main(int argc, char *const *argv)
     init_cycle.log = log;
     ngx_cycle = &init_cycle;
 
-    if (!(init_cycle.pool = ngx_create_pool(1024, log))) {
+    init_cycle.pool = ngx_create_pool(1024, log);
+    if (init_cycle.pool == NULL) {
         return 1;
     }
 
@@ -255,9 +257,9 @@ main(int argc, char *const *argv)
 static ngx_int_t
 ngx_add_inherited_sockets(ngx_cycle_t *cycle)
 {
-    u_char              *p, *v, *inherited;
-    ngx_socket_t         s;
-    ngx_listening_t     *ls;
+    u_char           *p, *v, *inherited;
+    ngx_int_t         s;
+    ngx_listening_t  *ls;
 
     inherited = (u_char *) getenv(NGINX_VAR);
 
@@ -287,11 +289,12 @@ ngx_add_inherited_sockets(ngx_cycle_t *c
 
             v = p + 1;
 
-            if (!(ls = ngx_array_push(&cycle->listening))) {
+            ls = ngx_array_push(&cycle->listening);
+            if (ls == NULL) {
                 return NGX_ERROR;
             }
 
-            ls->fd = s;
+            ls->fd = (ngx_socket_t) s;
         }
     }
 
@@ -315,7 +318,7 @@ ngx_pid_t ngx_exec_new_binary(ngx_cycle_
     ctx.argv = argv;
 
     var = ngx_alloc(sizeof(NGINX_VAR)
-                            + cycle->listening.nelts * (NGX_INT32_LEN + 1) + 2,
+                    + cycle->listening.nelts * (NGX_INT32_LEN + 1) + 2,
                     cycle->log);
 
     p = ngx_cpymem(var, NGINX_VAR "=", sizeof(NGINX_VAR));
@@ -411,27 +414,29 @@ static ngx_int_t ngx_getopt(ngx_cycle_t 
 static ngx_int_t
 ngx_save_argv(ngx_cycle_t *cycle, int argc, char *const *argv)
 {
+#if (NGX_FREEBSD)
+
+    ngx_os_argv = (char **) argv;
+    ngx_argc = argc;
+    ngx_argv = (char **) argv;
+
+#else
     size_t     len;
     ngx_int_t  i;
 
     ngx_os_argv = (char **) argv;
-
     ngx_argc = argc;
 
-#if (NGX_FREEBSD)
-
-    ngx_argv = (char **) argv;
-
-#else
-
-    if (!(ngx_argv = ngx_alloc((argc + 1) * sizeof(char *), cycle->log))) {
+    ngx_argv = ngx_alloc((argc + 1) * sizeof(char *), cycle->log);
+    if (ngx_argv == NULL) {
         return NGX_ERROR;
     }
 
     for (i = 0; i < argc; i++) {
         len = ngx_strlen(argv[i]) + 1;
 
-        if (!(ngx_argv[i] = ngx_alloc(len, cycle->log))) {
+        ngx_argv[i] = ngx_alloc(len, cycle->log);
+        if (ngx_argv[i] == NULL) {
             return NGX_ERROR;
         }
 
@@ -451,7 +456,8 @@ ngx_core_module_create_conf(ngx_cycle_t 
 {
     ngx_core_conf_t  *ccf;
 
-    if (!(ccf = ngx_pcalloc(cycle->pool, sizeof(ngx_core_conf_t)))) {
+    ccf = ngx_pcalloc(cycle->pool, sizeof(ngx_core_conf_t));
+    if (ccf == NULL) {
         return NULL;
     }
 
@@ -534,7 +540,8 @@ ngx_core_module_init_conf(ngx_cycle_t *c
 
     ccf->newpid.len = ccf->pid.len + sizeof(NGX_NEWPID_EXT);
 
-    if (!(ccf->newpid.data = ngx_palloc(cycle->pool, ccf->newpid.len))) {
+    ccf->newpid.data = ngx_palloc(cycle->pool, ccf->newpid.len);
+    if (ccf->newpid.data == NULL) {
         return NGX_CONF_ERROR;
     }
 
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define NGINX_VER          "nginx/0.1.24"
+#define NGINX_VER          "nginx/0.1.25"
 
 #define NGINX_VAR          "NGINX"
 #define NGX_NEWPID_EXT     ".newbin"
--- a/src/core/ngx_array.c
+++ b/src/core/ngx_array.c
@@ -12,11 +12,13 @@ ngx_array_t *ngx_array_create(ngx_pool_t
 {
     ngx_array_t *a;
 
-    if (!(a = ngx_palloc(p, sizeof(ngx_array_t)))) {
+    a = ngx_palloc(p, sizeof(ngx_array_t));
+    if (a == NULL) {
         return NULL;
     }
 
-    if (!(a->elts = ngx_palloc(p, n * size))) {
+    a->elts = ngx_palloc(p, n * size);
+    if (a->elts == NULL) {
         return NULL;
     }
 
@@ -72,7 +74,8 @@ void *ngx_array_push(ngx_array_t *a)
         } else {
             /* allocate a new array */
 
-            if (!(new = ngx_palloc(p, 2 * size))) {
+            new = ngx_palloc(p, 2 * size);
+            if (new == NULL) {
                 return NULL;
             }
 
@@ -120,7 +123,8 @@ void *ngx_array_push_n(ngx_array_t *a, n
 
             nalloc = 2 * ((n >= a->nalloc) ? n : a->nalloc);
 
-            if (!(new = ngx_palloc(p, nalloc * a->size))) {
+            new = ngx_palloc(p, nalloc * a->size);
+            if (new == NULL) {
                 return NULL;
             }
 
--- a/src/core/ngx_array.h
+++ b/src/core/ngx_array.h
@@ -27,10 +27,11 @@ void *ngx_array_push(ngx_array_t *a);
 void *ngx_array_push_n(ngx_array_t *a, ngx_uint_t n);
 
 
-static ngx_inline ngx_int_t ngx_array_init(ngx_array_t *array, ngx_pool_t *pool,
-                                           ngx_uint_t n, size_t size)
+static ngx_inline ngx_int_t
+ngx_array_init(ngx_array_t *array, ngx_pool_t *pool, ngx_uint_t n, size_t size)
 {
-    if (!(array->elts = ngx_palloc(pool, n * size))) {
+    array->elts = ngx_palloc(pool, n * size);
+    if (array->elts == NULL) {
         return NGX_ERROR;
     }
 
@@ -43,14 +44,4 @@ static ngx_inline ngx_int_t ngx_array_in
 }
 
 
-/* STUB */
-#define ngx_init_array(a, p, n, s, rc)                                       \
-    ngx_test_null(a.elts, ngx_palloc(p, n * s), rc);                         \
-    a.nelts = 0; a.size = s; a.nalloc = n; a.pool = p;
-
-#define ngx_create_array  ngx_array_create
-#define ngx_push_array    ngx_array_push
-/**/
-
-
 #endif /* _NGX_ARRAY_H_INCLUDED_ */
--- a/src/core/ngx_buf.c
+++ b/src/core/ngx_buf.c
@@ -13,11 +13,13 @@ ngx_create_temp_buf(ngx_pool_t *pool, si
 {
     ngx_buf_t *b;
 
-    if (!(b = ngx_calloc_buf(pool))) {
+    b = ngx_calloc_buf(pool);
+    if (b == NULL) {
         return NULL;
     }
 
-    if (!(b->start = ngx_palloc(pool, size))) {
+    b->start = ngx_palloc(pool, size);
+    if (b->start == NULL) {
         return NULL;
     }
 
@@ -49,14 +51,17 @@ ngx_create_chain_of_bufs(ngx_pool_t *poo
     ngx_buf_t    *b;
     ngx_chain_t  *chain, *cl, **ll;
 
-    if (!(p = ngx_palloc(pool, bufs->num * bufs->size))) {
+    p = ngx_palloc(pool, bufs->num * bufs->size);
+    if (p == NULL) {
         return NULL;
     }
 
     ll = &chain;
 
     for (i = 0; i < bufs->num; i++) {
-        if (!(b = ngx_calloc_buf(pool))) {
+
+        b = ngx_calloc_buf(pool);
+        if (b == NULL) {
             return NULL;
         }
 
@@ -79,7 +84,8 @@ ngx_create_chain_of_bufs(ngx_pool_t *poo
         p += bufs->size;
         b->end = p;
 
-        if (!(cl = ngx_alloc_chain_link(pool))) {
+        cl = ngx_alloc_chain_link(pool);
+        if (cl == NULL) {
             return NULL;
         }
 
@@ -106,7 +112,10 @@ ngx_chain_add_copy(ngx_pool_t *pool, ngx
     }
 
     while (in) {
-        ngx_test_null(cl, ngx_alloc_chain_link(pool), NGX_ERROR);
+        cl = ngx_alloc_chain_link(pool);
+        if (cl == NULL) {
+            return NGX_ERROR;
+        }
 
         cl->buf = in->buf;
         *ll = cl;
--- a/src/core/ngx_buf.h
+++ b/src/core/ngx_buf.h
@@ -119,27 +119,9 @@ ngx_chain_t *ngx_create_chain_of_bufs(ng
 #define ngx_alloc_buf(pool)  ngx_palloc(pool, sizeof(ngx_buf_t))
 #define ngx_calloc_buf(pool) ngx_pcalloc(pool, sizeof(ngx_buf_t))
 
-
 #define ngx_alloc_chain_link(pool) ngx_palloc(pool, sizeof(ngx_chain_t))
 
 
-#define ngx_alloc_link_and_set_buf(chain, b, pool, error)                    \
-    do {                                                                     \
-        ngx_test_null(chain, ngx_alloc_chain_link(pool), error);             \
-        chain->buf = b;                                                      \
-        chain->next = NULL;                                                  \
-    } while (0);
-
-
-#define ngx_chain_add_link(chain, last, cl)                                  \
-    if (chain) {                                                             \
-        *last = cl;                                                          \
-    } else {                                                                 \
-        chain = cl;                                                          \
-    }                                                                        \
-    last = &cl->next
-
-
 ngx_int_t ngx_output_chain(ngx_output_chain_ctx_t *ctx, ngx_chain_t *in);
 ngx_int_t ngx_chain_writer(void *ctx, ngx_chain_t *in);
 
--- a/src/core/ngx_conf_file.c
+++ b/src/core/ngx_conf_file.c
@@ -8,6 +8,7 @@
 #include <ngx_core.h>
 
 
+static ngx_int_t ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last);
 static char *ngx_conf_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
 
 
@@ -53,13 +54,10 @@ static ngx_int_t ngx_conf_read_token(ngx
 
 char *ngx_conf_parse(ngx_conf_t *cf, ngx_str_t *filename)
 {
-    int               m, rc, found, valid;
     char             *rv;
-    void             *conf, **confp;
     ngx_fd_t          fd;
-    ngx_str_t        *name;
+    ngx_int_t         rc;
     ngx_conf_file_t  *prev;
-    ngx_command_t    *cmd;
 
 #if (NGX_SUPPRESS_WARN)
     fd = NGX_INVALID_FILE;
@@ -78,7 +76,9 @@ char *ngx_conf_parse(ngx_conf_t *cf, ngx
         }
 
         prev = cf->conf_file;
-        if (!(cf->conf_file = ngx_palloc(cf->pool, sizeof(ngx_conf_file_t)))) {
+
+        cf->conf_file = ngx_palloc(cf->pool, sizeof(ngx_conf_file_t));
+        if (cf->conf_file == NULL) {
             return NGX_CONF_ERROR;
         }
 
@@ -130,194 +130,30 @@ char *ngx_conf_parse(ngx_conf_t *cf, ngx
             rv = (*cf->handler)(cf, NULL, cf->handler_conf);
             if (rv == NGX_CONF_OK) {
                 continue;
-
-            } else if (rv == NGX_CONF_ERROR) {
-                rc = NGX_ERROR;
-                break;
+            }
 
-            } else {
-                ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
-                             "%s in %s:%d",
-                             rv,
-                             cf->conf_file->file.name.data,
-                             cf->conf_file->line);
+            if (rv == NGX_CONF_ERROR) {
                 rc = NGX_ERROR;
                 break;
             }
-        }
 
-        name = (ngx_str_t *) cf->args->elts;
-        found = 0;
-
-        for (m = 0; rc != NGX_ERROR && !found && ngx_modules[m]; m++) {
-
-            /* look up the directive in the appropriate modules */
-
-            if (ngx_modules[m]->type != NGX_CONF_MODULE
-                && ngx_modules[m]->type != cf->module_type)
-            {
-                continue;
-            }
-
-            cmd = ngx_modules[m]->commands;
-            if (cmd == NULL) {
-                continue;
-            }
-
-            while (cmd->name.len) {
-                if (name->len == cmd->name.len
-                    && ngx_strcmp(name->data, cmd->name.data) == 0)
-                {
-
-                    found = 1;
-
-                    /* is the directive's location right ? */
-
-                    if ((cmd->type & cf->cmd_type) == 0) {
-                        ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
-                                      "directive \"%s\" in %s:%d "
-                                      "is not allowed here",
-                                      name->data,
-                                      cf->conf_file->file.name.data,
-                                      cf->conf_file->line);
-                        rc = NGX_ERROR;
-                        break;
-                    }
-
-                    if (!(cmd->type & NGX_CONF_BLOCK) && rc != NGX_OK)
-                    {
-                        ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
-                                      "directive \"%s\" in %s:%d "
-                                      "is not terminated by \";\"",
-                                      name->data,
-                                      cf->conf_file->file.name.data,
-                                      cf->conf_file->line);
-                        rc = NGX_ERROR;
-                        break;
-                    }
-
-                    if ((cmd->type & NGX_CONF_BLOCK)
-                        && rc != NGX_CONF_BLOCK_START)
-                    {
-                        ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
-                                      "directive \"%s\" in %s:%d "
-                                      "has not the opening \"{\"",
-                                      name->data,
-                                      cf->conf_file->file.name.data,
-                                      cf->conf_file->line);
-                        rc = NGX_ERROR;
-                        break;
-                    }
-
-                    /* is the directive's argument count right ? */
-
-                    if (cmd->type & NGX_CONF_ANY) {
-                        valid = 1;
-
-                    } else if (cmd->type & NGX_CONF_FLAG) {
-
-                        if (cf->args->nelts == 2) {
-                            valid = 1;
-                        } else {
-                            valid = 0;
-                        }
-
-                    } else if (cmd->type & NGX_CONF_1MORE) {
-
-                        if (cf->args->nelts > 1) {
-                            valid = 1;
-                        } else {
-                            valid = 0;
-                        }
-
-                    } else if (cmd->type & NGX_CONF_2MORE) {
-
-                        if (cf->args->nelts > 2) {
-                            valid = 1;
-                        } else {
-                            valid = 0;
-                        }
-
-                    } else if (cf->args->nelts <= 10
-                               && (cmd->type
-                                   & argument_number[cf->args->nelts - 1]))
-                    {
-                        valid = 1;
-
-                    } else {
-                        valid = 0;
-                    }
-
-                    if (!valid) {
-                        ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
-                                      "invalid number arguments in "
-                                      "directive \"%s\" in %s:%d",
-                                      name->data,
-                                      cf->conf_file->file.name.data,
-                                      cf->conf_file->line);
-                        rc = NGX_ERROR;
-                        break;
-                    }
-
-                    /* set up the directive's configuration context */
-
-                    conf = NULL;
-
-                    if (cmd->type & NGX_DIRECT_CONF) {
-                        conf = ((void **) cf->ctx)[ngx_modules[m]->index];
-
-                    } else if (cmd->type & NGX_MAIN_CONF) {
-                        conf = &(((void **) cf->ctx)[ngx_modules[m]->index]);
-
-                    } else if (cf->ctx) {
-                        confp = *(void **) ((char *) cf->ctx + cmd->conf);
-
-                        if (confp) {
-                            conf = confp[ngx_modules[m]->ctx_index];
-                        }
-                    }
-
-                    rv = cmd->set(cf, cmd, conf);
-
-                    if (rv == NGX_CONF_OK) {
-                        break;
-
-                    } else if (rv == NGX_CONF_ERROR) {
-                        rc = NGX_ERROR;
-                        break;
-
-                    } else {
-                        ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
-                                      "the \"%s\" directive %s in %s:%d",
-                                      name->data, rv,
-                                      cf->conf_file->file.name.data,
-                                      cf->conf_file->line);
-
-                        rc = NGX_ERROR;
-                        break;
-                    }
-                }
-
-                cmd++;
-            }
-        }
-
-        if (!found) {
             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
-                          "unknown directive \"%s\" in %s:%d",
-                          name->data,
-                          cf->conf_file->file.name.data,
-                          cf->conf_file->line);
-
+                         "%s in %s:%d",
+                         rv, cf->conf_file->file.name.data,
+                         cf->conf_file->line);
             rc = NGX_ERROR;
             break;
         }
 
+
+        rc = ngx_conf_handler(cf, rc);
+
         if (rc == NGX_ERROR) {
             break;
         }
     }
 
+
     if (filename) {
         cf->conf_file = prev;
 
@@ -337,6 +173,164 @@ char *ngx_conf_parse(ngx_conf_t *cf, ngx
 }
 
 
+static ngx_int_t ngx_conf_handler(ngx_conf_t *cf, ngx_int_t last)
+{
+    char           *rv;
+    void           *conf, **confp;
+    ngx_uint_t      i, valid;
+    ngx_str_t      *name;
+    ngx_command_t  *cmd;
+
+    name = cf->args->elts;
+
+    for (i = 0; ngx_modules[i]; i++) {
+
+        /* look up the directive in the appropriate modules */
+
+        if (ngx_modules[i]->type != NGX_CONF_MODULE
+            && ngx_modules[i]->type != cf->module_type)
+        {
+            continue;
+        }
+
+        cmd = ngx_modules[i]->commands;
+        if (cmd == NULL) {
+            continue;
+        }
+
+        while (cmd->name.len) {
+
+            if (name->len == cmd->name.len
+                && ngx_strcmp(name->data, cmd->name.data) == 0)
+            {
+                /* is the directive's location right ? */
+
+                if (!(cmd->type & cf->cmd_type)) {
+                    ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+                                  "directive \"%s\" in %s:%d "
+                                  "is not allowed here",
+                                  name->data, cf->conf_file->file.name.data,
+                                  cf->conf_file->line);
+                    return NGX_ERROR;
+                }
+
+                if (!(cmd->type & NGX_CONF_BLOCK) && last != NGX_OK) {
+                    ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+                                  "directive \"%s\" in %s:%d "
+                                  "is not terminated by \";\"",
+                                  name->data, cf->conf_file->file.name.data,
+                                  cf->conf_file->line);
+                    return NGX_ERROR;
+                }
+
+                if ((cmd->type & NGX_CONF_BLOCK)
+                    && last != NGX_CONF_BLOCK_START)
+                {
+                    ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+                                  "directive \"%s\" in %s:%d "
+                                  "has not the opening \"{\"",
+                                  name->data, cf->conf_file->file.name.data,
+                                  cf->conf_file->line);
+                    return NGX_ERROR;
+                }
+
+                /* is the directive's argument count right ? */
+
+                if (cmd->type & NGX_CONF_ANY) {
+                    valid = 1;
+
+                } else if (cmd->type & NGX_CONF_FLAG) {
+
+                    if (cf->args->nelts == 2) {
+                        valid = 1;
+                    } else {
+                        valid = 0;
+                    }
+
+                } else if (cmd->type & NGX_CONF_1MORE) {
+
+                    if (cf->args->nelts > 1) {
+                        valid = 1;
+                    } else {
+                        valid = 0;
+                    }
+
+                } else if (cmd->type & NGX_CONF_2MORE) {
+
+                    if (cf->args->nelts > 2) {
+                        valid = 1;
+                    } else {
+                        valid = 0;
+                    }
+
+                } else if (cf->args->nelts <= 10
+                           && (cmd->type
+                               & argument_number[cf->args->nelts - 1]))
+                {
+                    valid = 1;
+
+                } else {
+                    valid = 0;
+                }
+
+                if (!valid) {
+                    ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+                                  "invalid number arguments in "
+                                  "directive \"%s\" in %s:%d",
+                                  name->data, cf->conf_file->file.name.data,
+                                  cf->conf_file->line);
+                    return NGX_ERROR;
+                }
+
+                /* set up the directive's configuration context */
+
+                conf = NULL;
+
+                if (cmd->type & NGX_DIRECT_CONF) {
+                    conf = ((void **) cf->ctx)[ngx_modules[i]->index];
+
+                } else if (cmd->type & NGX_MAIN_CONF) {
+                    conf = &(((void **) cf->ctx)[ngx_modules[i]->index]);
+
+                } else if (cf->ctx) {
+                    confp = *(void **) ((char *) cf->ctx + cmd->conf);
+
+                    if (confp) {
+                        conf = confp[ngx_modules[i]->ctx_index];
+                    }
+                }
+
+                rv = cmd->set(cf, cmd, conf);
+
+                if (rv == NGX_CONF_OK) {
+                    return NGX_OK;
+                }
+
+                if (rv == NGX_CONF_ERROR) {
+                    return NGX_ERROR;
+                }
+
+                ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+                              "the \"%s\" directive %s in %s:%d",
+                              name->data, rv, cf->conf_file->file.name.data,
+                              cf->conf_file->line);
+
+                return NGX_ERROR;
+            }
+
+            cmd++;
+        }
+    }
+
+    ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+                  "unknown directive \"%s\" in %s:%d",
+                  name->data, cf->conf_file->file.name.data,
+                  cf->conf_file->line);
+
+    return NGX_ERROR;
+}
+
+
 static ngx_int_t ngx_conf_read_token(ngx_conf_t *cf)
 {
     u_char      *start, ch, *src, *dst;
@@ -523,11 +517,13 @@ static ngx_int_t ngx_conf_read_token(ngx
             }
 
             if (found) {
-                if (!(word = ngx_push_array(cf->args))) {
+                word = ngx_array_push(cf->args);
+                if (word == NULL) {
                     return NGX_ERROR;
                 }
 
-                if (!(word->data = ngx_palloc(cf->pool, b->pos - start + 1))) {
+                word->data = ngx_palloc(cf->pool, b->pos - start + 1);
+                if (word->data == NULL) {
                     return NGX_ERROR;
                 }
 
@@ -623,7 +619,8 @@ ngx_int_t ngx_conf_full_name(ngx_cycle_t
     name->len = cycle->root.len + old.len;
 
     if (cycle->connections) {
-        if (!(name->data = ngx_palloc(cycle->pool, name->len + 1))) {
+        name->data = ngx_palloc(cycle->pool, name->len + 1);
+        if (name->data == NULL) {
             return  NGX_ERROR;
         }
 
@@ -631,7 +628,8 @@ ngx_int_t ngx_conf_full_name(ngx_cycle_t
 
         /* the init_cycle */
 
-        if (!(name->data = ngx_alloc(name->len + 1, cycle->log))) {
+        name->data = ngx_alloc(name->len + 1, cycle->log);
+        if (name->data == NULL) {
             return  NGX_ERROR;
         }
     }
@@ -686,7 +684,8 @@ ngx_open_file_t *ngx_conf_open_file(ngx_
         }
     }
 
-    if (!(file = ngx_list_push(&cycle->open_files))) {
+    file = ngx_list_push(&cycle->open_files);
+    if (file == NULL) {
         return NULL;
     }
 
--- a/src/core/ngx_connection.c
+++ b/src/core/ngx_connection.c
@@ -20,13 +20,15 @@ ngx_listening_t *ngx_listening_inet_stre
     ngx_listening_t     *ls;
     struct sockaddr_in  *sin;
 
-    if (!(ls = ngx_array_push(&cf->cycle->listening))) {
+    ls = ngx_array_push(&cf->cycle->listening);
+    if (ls == NULL) {
         return NULL;
     }
 
     ngx_memzero(ls, sizeof(ngx_listening_t));
 
-    if (!(sin = ngx_pcalloc(cf->pool, sizeof(struct sockaddr_in)))) {
+    sin = ngx_pcalloc(cf->pool, sizeof(struct sockaddr_in));
+    if (sin == NULL) {
         return NULL;
     }
 
@@ -46,7 +48,6 @@ ngx_listening_t *ngx_listening_inet_stre
     ls->addr_text.len = ngx_sprintf(ls->addr_text.data + len, ":%d", port)
                         - ls->addr_text.data;
 
-
     ls->fd = (ngx_socket_t) -1;
     ls->family = AF_INET;
     ls->type = SOCK_STREAM;
--- a/src/core/ngx_cycle.c
+++ b/src/core/ngx_cycle.c
@@ -54,15 +54,18 @@ ngx_cycle_t *ngx_init_cycle(ngx_cycle_t 
 
     log = old_cycle->log;
 
-    if (!(pool = ngx_create_pool(16 * 1024, log))) {
+    pool = ngx_create_pool(16 * 1024, log);
+    if (pool == NULL) {
         return NULL;
     }
     pool->log = log;
 
-    if (!(cycle = ngx_pcalloc(pool, sizeof(ngx_cycle_t)))) {
+    cycle = ngx_pcalloc(pool, sizeof(ngx_cycle_t));
+    if (cycle == NULL) {
         ngx_destroy_pool(pool);
         return NULL;
     }
+
     cycle->pool = pool;
     cycle->log = log;
     cycle->old_cycle = old_cycle;
@@ -72,10 +75,13 @@ ngx_cycle_t *ngx_init_cycle(ngx_cycle_t 
 
 
     n = old_cycle->pathes.nelts ? old_cycle->pathes.nelts : 10;
-    if (!(cycle->pathes.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *)))) {
+
+    cycle->pathes.elts = ngx_pcalloc(pool, n * sizeof(ngx_path_t *));
+    if (cycle->pathes.elts == NULL) {
         ngx_destroy_pool(pool);
         return NULL;
     }
+
     cycle->pathes.nelts = 0;
     cycle->pathes.size = sizeof(ngx_path_t *);
     cycle->pathes.nalloc = n;
@@ -100,7 +106,8 @@ ngx_cycle_t *ngx_init_cycle(ngx_cycle_t 
     }
 
 
-    if (!(cycle->new_log = ngx_log_create_errlog(cycle, NULL))) {
+    cycle->new_log = ngx_log_create_errlog(cycle, NULL);
+    if (cycle->new_log == NULL) {
         ngx_destroy_pool(pool);
         return NULL;
     }
@@ -109,11 +116,13 @@ ngx_cycle_t *ngx_init_cycle(ngx_cycle_t 
 
 
     n = old_cycle->listening.nelts ? old_cycle->listening.nelts : 10;
+
     cycle->listening.elts = ngx_pcalloc(pool, n * sizeof(ngx_listening_t));
     if (cycle->listening.elts == NULL) {
         ngx_destroy_pool(pool);
         return NULL;
     }
+
     cycle->listening.nelts = 0;
     cycle->listening.size = sizeof(ngx_listening_t);
     cycle->listening.nalloc = n;
@@ -147,7 +156,7 @@ ngx_cycle_t *ngx_init_cycle(ngx_cycle_t 
 
     ngx_memzero(&conf, sizeof(ngx_conf_t));
     /* STUB: init array ? */
-    conf.args = ngx_create_array(pool, 10, sizeof(ngx_str_t));
+    conf.args = ngx_array_create(pool, 10, sizeof(ngx_str_t));
     if (conf.args == NULL) {
         ngx_destroy_pool(pool);
         return NULL;
@@ -516,7 +525,7 @@ ngx_cycle_t *ngx_init_cycle(ngx_cycle_t 
 
     ngx_temp_pool->log = cycle->log;
 
-    old = ngx_push_array(&ngx_old_cycles);
+    old = ngx_array_push(&ngx_old_cycles);
     if (old == NULL) {
         exit(1);
     }
@@ -562,7 +571,7 @@ ngx_int_t ngx_create_pidfile(ngx_cycle_t
 {
     ngx_uint_t        trunc;
     size_t            len;
-    u_char           *name, pid[NGX_INT64_LEN];
+    u_char            pid[NGX_INT64_LEN];
     ngx_file_t        file;
     ngx_core_conf_t  *ccf, *old_ccf;
 
--- a/src/core/ngx_file.c
+++ b/src/core/ngx_file.c
@@ -43,7 +43,8 @@ ngx_create_temp_file(ngx_file_t *file, n
 
     file->name.len = path->name.len + 1 + path->len + NGX_ATOMIC_T_LEN;
 
-    if (!(file->name.data = ngx_palloc(pool, file->name.len + 1))) {
+    file->name.data = ngx_palloc(pool, file->name.len + 1);
+    if (file->name.data == NULL) {
         return NGX_ERROR;
     }
 
@@ -203,7 +204,8 @@ ngx_conf_set_path_slot(ngx_conf_t *cf, n
         return "is duplicate";
     }
 
-    if (!(path = ngx_pcalloc(cf->pool, sizeof(ngx_path_t)))) {
+    path = ngx_pcalloc(cf->pool, sizeof(ngx_path_t));
+    if (path == NULL) {
         return NGX_CONF_ERROR;
     }
 
@@ -292,7 +294,8 @@ ngx_add_path(ngx_conf_t *cf, ngx_path_t 
         }
     }
 
-    if (!(p = ngx_array_push(&cf->cycle->pathes))) {
+    p = ngx_array_push(&cf->cycle->pathes);
+    if (p == NULL) {
         return NGX_ERROR;
     }
 
--- a/src/core/ngx_file.h
+++ b/src/core/ngx_file.h
@@ -70,7 +70,8 @@ char *ngx_conf_set_path_slot(ngx_conf_t 
 #define ngx_conf_merge_path_value(curr, prev, path, l1, l2, l3, clean, cf)    \
     if (curr == NULL) {                                                       \
         if (prev == NULL) {                                                   \
-            if (!(curr = ngx_palloc(cf->pool, sizeof(ngx_path_t)))) {         \
+            curr = ngx_palloc(cf->pool, sizeof(ngx_path_t));                  \
+            if (curr == NULL) {                                               \
                 return NGX_CONF_ERROR;                                        \
             }                                                                 \
                                                                               \
--- a/src/core/ngx_garbage_collector.c
+++ b/src/core/ngx_garbage_collector.c
@@ -77,7 +77,8 @@ ngx_int_t ngx_collect_garbage(ngx_gc_t *
 
             buf.len = dname->len + 1 + len + NGX_DIR_MASK_LEN;
 
-            if (!(buf.data = ngx_alloc(buf.len + 1, ctx->log))) {
+            buf.data = ngx_alloc(buf.len + 1, ctx->log);
+            if (buf.data == NULL) {
                 return NGX_ABORT;
             }
         }
--- a/src/core/ngx_inet.c
+++ b/src/core/ngx_inet.c
@@ -244,7 +244,8 @@ ngx_peers_t *ngx_inet_upstream_parse(ngx
 
         u->port = u->default_port_value;
 
-        if (!(u->port_text.data = ngx_palloc(cf->pool, sizeof("65536") - 1))) {
+        u->port_text.data = ngx_palloc(cf->pool, sizeof("65536") - 1);
+        if (u->port_text.data == NULL) {
             return NULL;
         }
 
@@ -271,7 +272,8 @@ ngx_peers_t *ngx_inet_upstream_parse(ngx
 
     u->port = htons(u->port);
 
-    if (!(host = ngx_palloc(cf->pool, u->host.len + 1))) {
+    host = ngx_palloc(cf->pool, u->host.len + 1);
+    if (host == NULL) {
         return NULL;
     }
 
@@ -297,7 +299,6 @@ ngx_peers_t *ngx_inet_upstream_parse(ngx
 
         peers = ngx_pcalloc(cf->pool,
                             sizeof(ngx_peers_t) + sizeof(ngx_peer_t) * (i - 1));
-
         if (peers == NULL) {
             return NULL;
         }
@@ -307,7 +308,8 @@ ngx_peers_t *ngx_inet_upstream_parse(ngx
 
         for (i = 0; h->h_addr_list[i] != NULL; i++) {
 
-            if (!(sin = ngx_pcalloc(cf->pool, sizeof(struct sockaddr_in)))) {
+            sin = ngx_pcalloc(cf->pool, sizeof(struct sockaddr_in));
+            if (sin == NULL) {
                 return NULL;
             }
 
@@ -320,7 +322,8 @@ ngx_peers_t *ngx_inet_upstream_parse(ngx
 
             len = INET_ADDRSTRLEN - 1 + 1 + u->port_text.len;
     
-            if (!(peers->peer[i].name.data = ngx_palloc(cf->pool, len))) {
+            peers->peer[i].name.data = ngx_palloc(cf->pool, len);
+            if (peers->peer[i].name.data == NULL) {
                 return NULL;
             }
 
@@ -345,11 +348,13 @@ ngx_peers_t *ngx_inet_upstream_parse(ngx
 
         /* MP: ngx_shared_palloc() */
 
-        if (!(peers = ngx_pcalloc(cf->pool, sizeof(ngx_peers_t)))) {
+        peers = ngx_pcalloc(cf->pool, sizeof(ngx_peers_t));
+        if (peers == NULL) {
             return NULL;
         }
 
-        if (!(sin = ngx_pcalloc(cf->pool, sizeof(struct sockaddr_in)))) {
+        sin = ngx_pcalloc(cf->pool, sizeof(struct sockaddr_in));
+        if (sin == NULL) {
             return NULL;
         }
 
@@ -366,7 +371,8 @@ ngx_peers_t *ngx_inet_upstream_parse(ngx
 
         peers->peer[0].name.len = len;
 
-        if (!(peers->peer[0].name.data = ngx_palloc(cf->pool, len))) {
+        peers->peer[0].name.data = ngx_palloc(cf->pool, len);
+        if (peers->peer[0].name.data == NULL) {
             return NULL;
         }
 
--- a/src/core/ngx_list.c
+++ b/src/core/ngx_list.c
@@ -19,11 +19,13 @@ void *ngx_list_push(ngx_list_t *l)
 
         /* the last part is full, allocate a new list part */
 
-        if (!(last = ngx_palloc(l->pool, sizeof(ngx_list_part_t)))) {
+        last = ngx_palloc(l->pool, sizeof(ngx_list_part_t));
+        if (last == NULL) {
             return NULL;
         }
 
-        if (!(last->elts = ngx_palloc(l->pool, l->nalloc * l->size))) {
+        last->elts = ngx_palloc(l->pool, l->nalloc * l->size);
+        if (last->elts == NULL) {
             return NULL;
         }
 
--- a/src/core/ngx_list.h
+++ b/src/core/ngx_list.h
@@ -30,10 +30,12 @@ typedef struct {
 } ngx_list_t;
 
 
-static ngx_inline ngx_int_t ngx_list_init(ngx_list_t *list, ngx_pool_t *pool,
-                                          ngx_uint_t n, size_t size)
+static ngx_inline
+ngx_int_t ngx_list_init(ngx_list_t *list, ngx_pool_t *pool, ngx_uint_t n,
+    size_t size)
 {
-    if (!(list->part.elts = ngx_palloc(pool, n * size))) {
+    list->part.elts = ngx_palloc(pool, n * size);
+    if (list->part.elts == NULL) {
         return NGX_ERROR;
     }
 
--- a/src/core/ngx_log.c
+++ b/src/core/ngx_log.c
@@ -253,11 +253,13 @@ ngx_log_t *ngx_log_create_errlog(ngx_cyc
         name = NULL;
     }
 
-    if (!(log = ngx_pcalloc(cycle->pool, sizeof(ngx_log_t)))) {
+    log = ngx_pcalloc(cycle->pool, sizeof(ngx_log_t));
+    if (log == NULL) {
         return NULL;
     }
 
-    if (!(log->file = ngx_conf_open_file(cycle, name))) {
+    log->file = ngx_conf_open_file(cycle, name);
+    if (log->file == NULL) {
         return NULL;
     }
 
--- a/src/core/ngx_output_chain.c
+++ b/src/core/ngx_output_chain.c
@@ -155,7 +155,8 @@ ngx_output_chain(ngx_output_chain_ctx_t 
                         }
                     }
 
-                    if (!(ctx->buf = ngx_create_temp_buf(ctx->pool, size))) {
+                    ctx->buf = ngx_create_temp_buf(ctx->pool, size);
+                    if (ctx->buf == NULL) {
                         return NGX_ERROR;
                     }
 
@@ -186,9 +187,11 @@ ngx_output_chain(ngx_output_chain_ctx_t 
                 ctx->in = ctx->in->next;
             }
 
-            if (!(cl = ngx_alloc_chain_link(ctx->pool))) {
+            cl = ngx_alloc_chain_link(ctx->pool);
+            if (cl == NULL) {
                 return NGX_ERROR;
             }
+
             cl->buf = ctx->buf;
             cl->next = NULL;
             *last_out = cl;
@@ -269,7 +272,8 @@ ngx_output_chain_add_copy(ngx_pool_t *po
 
     while (in) {
 
-        if (!(cl = ngx_alloc_chain_link(pool))) {
+        cl = ngx_alloc_chain_link(pool);
+        if (cl == NULL) {
             return NGX_ERROR;
         }
 
@@ -281,7 +285,8 @@ ngx_output_chain_add_copy(ngx_pool_t *po
             && buf->file_pos < NGX_SENDFILE_LIMIT
             && buf->file_last > NGX_SENDFILE_LIMIT)
         {
-            if (!(b = ngx_calloc_buf(pool))) {
+            b = ngx_calloc_buf(pool);
+            if (b == NULL) {
                 return NGX_ERROR;
             }
 
@@ -431,9 +436,11 @@ ngx_chain_writer(void *data, ngx_chain_t
         ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->connection->log, 0,
                        "chain writer buf size: %uz", ngx_buf_size(in->buf));
 
-        if (!(cl = ngx_alloc_chain_link(ctx->pool))) {
+        cl = ngx_alloc_chain_link(ctx->pool);
+        if (cl == NULL) {
             return NGX_ERROR;
         }
+
         cl->buf = in->buf;
         cl->next = NULL;
         *ctx->last = cl;
--- a/src/core/ngx_palloc.c
+++ b/src/core/ngx_palloc.c
@@ -8,11 +8,13 @@
 #include <ngx_core.h>
 
 
-ngx_pool_t *ngx_create_pool(size_t size, ngx_log_t *log)
+ngx_pool_t *
+ngx_create_pool(size_t size, ngx_log_t *log)
 {
     ngx_pool_t  *p;
 
-    if (!(p = ngx_alloc(size, log))) {
+    p = ngx_alloc(size, log);
+    if (p == NULL) {
        return NULL;
     }
 
@@ -26,7 +28,8 @@ ngx_pool_t *ngx_create_pool(size_t size,
 }
 
 
-void ngx_destroy_pool(ngx_pool_t *pool)
+void
+ngx_destroy_pool(ngx_pool_t *pool)
 {
     ngx_pool_t        *p, *n;
     ngx_pool_large_t  *l;
@@ -68,7 +71,8 @@ void ngx_destroy_pool(ngx_pool_t *pool)
 }
 
 
-void *ngx_palloc(ngx_pool_t *pool, size_t size)
+void *
+ngx_palloc(ngx_pool_t *pool, size_t size)
 {
     u_char            *m;
     ngx_pool_t        *p, *n;
@@ -94,7 +98,8 @@ void *ngx_palloc(ngx_pool_t *pool, size_
 
         /* allocate a new pool block */
 
-        if (!(n = ngx_create_pool((size_t) (p->end - (u_char *) p), p->log))) {
+        n = ngx_create_pool((size_t) (p->end - (u_char *) p), p->log);
+        if (n == NULL) {
             return NULL;
         }
 
@@ -125,7 +130,8 @@ void *ngx_palloc(ngx_pool_t *pool, size_
     }
 
     if (large == NULL) {
-        if (!(large = ngx_palloc(pool, sizeof(ngx_pool_large_t)))) {
+        large = ngx_palloc(pool, sizeof(ngx_pool_large_t));
+        if (large == NULL) {
             return NULL;
         }
 
@@ -133,11 +139,13 @@ void *ngx_palloc(ngx_pool_t *pool, size_
     }
 
 #if 0
-    if (!(p = ngx_memalign(ngx_pagesize, size, pool->log))) {
+    p = ngx_memalign(ngx_pagesize, size, pool->log);
+    if (p == NULL) {
         return NULL;
     }
 #else
-    if (!(p = ngx_alloc(size, pool->log))) {
+    p = ngx_alloc(size, pool->log);
+    if (p == NULL) {
         return NULL;
     }
 #endif
@@ -155,7 +163,8 @@ void *ngx_palloc(ngx_pool_t *pool, size_
 }
 
 
-ngx_int_t ngx_pfree(ngx_pool_t *pool, void *p)
+ngx_int_t
+ngx_pfree(ngx_pool_t *pool, void *p)
 {
     ngx_pool_large_t  *l;
 
@@ -174,7 +183,8 @@ ngx_int_t ngx_pfree(ngx_pool_t *pool, vo
 }
 
 
-void *ngx_pcalloc(ngx_pool_t *pool, size_t size)
+void *
+ngx_pcalloc(ngx_pool_t *pool, size_t size)
 {
     void *p;
 
@@ -188,7 +198,8 @@ void *ngx_pcalloc(ngx_pool_t *pool, size
 
 #if 0
 
-static void *ngx_get_cached_block(size_t size)
+static void *
+ngx_get_cached_block(size_t size)
 {
     void                     *p;
     ngx_cached_block_slot_t  *slot;
--- a/src/core/ngx_palloc.h
+++ b/src/core/ngx_palloc.h
@@ -21,8 +21,6 @@
 
 #define NGX_DEFAULT_POOL_SIZE   (16 * 1024)
 
-#define ngx_test_null(p, alloc, rc)  if ((p = alloc) == NULL) { return rc; }
-
 
 typedef struct ngx_pool_large_s  ngx_pool_large_t;
 
--- a/src/core/ngx_radix_tree.c
+++ b/src/core/ngx_radix_tree.c
@@ -17,7 +17,8 @@ ngx_radix_tree_create(ngx_pool_t *pool, 
     uint32_t           key, mask, inc;
     ngx_radix_tree_t  *tree;
 
-    if (!(tree = ngx_palloc(pool, sizeof(ngx_radix_tree_t)))) {
+    tree = ngx_palloc(pool, sizeof(ngx_radix_tree_t));
+    if (tree == NULL) {
         return NULL;
     }
 
@@ -26,7 +27,8 @@ ngx_radix_tree_create(ngx_pool_t *pool, 
     tree->start = NULL;
     tree->size = 0;
 
-    if (!(tree->root = ngx_radix_alloc(tree))) {
+    tree->root = ngx_radix_alloc(tree);
+    if (tree->root == NULL) {
         return NULL;
     }
 
@@ -140,7 +142,8 @@ ngx_radix32tree_insert(ngx_radix_tree_t 
     }
 
     while (bit & mask) {
-        if (!(next = ngx_radix_alloc(tree))) {
+        next = ngx_radix_alloc(tree);
+        if (next == NULL) {
             return NGX_ERROR;
         }
 
@@ -266,7 +269,8 @@ ngx_radix_alloc(ngx_radix_tree_t *tree)
     }
 
     if (tree->size < sizeof(ngx_radix_node_t)) {
-        if (!(tree->start = ngx_palloc(tree->pool, ngx_pagesize))) {
+        tree->start = ngx_palloc(tree->pool, ngx_pagesize);
+        if (tree->start == NULL) {
             return NULL;
         }
 
--- a/src/core/ngx_regex.c
+++ b/src/core/ngx_regex.c
@@ -79,7 +79,7 @@ ngx_regex_t *ngx_regex_compile(ngx_str_t
 }
 
 
-ngx_uint_t ngx_regex_capture_count(ngx_regex_t *re)
+ngx_int_t ngx_regex_capture_count(ngx_regex_t *re)
 {
     int  rc, n;
 
@@ -87,7 +87,11 @@ ngx_uint_t ngx_regex_capture_count(ngx_r
 
     rc = pcre_fullinfo(re, NULL, PCRE_INFO_CAPTURECOUNT, &n);
 
-    return (ngx_uint_t) n;
+    if (rc < 0) {
+        return (ngx_int_t) rc;
+    }
+
+    return (ngx_int_t) n;
 }
 
 
--- a/src/core/ngx_regex.h
+++ b/src/core/ngx_regex.h
@@ -23,11 +23,12 @@ typedef pcre  ngx_regex_t;
 void ngx_regex_init(void);
 ngx_regex_t *ngx_regex_compile(ngx_str_t *pattern, ngx_int_t options,
                                ngx_pool_t *pool, ngx_str_t *err);
-ngx_uint_t ngx_regex_capture_count(ngx_regex_t *re);
+ngx_int_t ngx_regex_capture_count(ngx_regex_t *re);
 ngx_int_t ngx_regex_exec(ngx_regex_t *re, ngx_str_t *s,
                          int *captures, ngx_int_t size);
 
-#define ngx_regex_exec_n  "pcre_exec()"
+#define ngx_regex_exec_n           "pcre_exec()"
+#define ngx_regex_capture_count_n  "pcre_fullinfo()"
 
 
 #endif /* _NGX_REGEX_H_INCLUDED_ */
--- a/src/core/ngx_string.c
+++ b/src/core/ngx_string.c
@@ -34,7 +34,8 @@ ngx_pstrdup(ngx_pool_t *pool, ngx_str_t 
 {
     u_char  *dst;
 
-    if (!(dst = ngx_palloc(pool, src->len))) {
+    dst = ngx_palloc(pool, src->len);
+    if (dst == NULL) {
         return NULL;
     }
 
@@ -489,6 +490,84 @@ ngx_atoi(u_char *line, size_t n)
 }
 
 
+ssize_t
+ngx_atosz(u_char *line, size_t n)
+{
+    ssize_t  value;
+
+    if (n == 0) {
+        return NGX_ERROR;
+    }
+
+    for (value = 0; n--; line++) {
+        if (*line < '0' || *line > '9') {
+            return NGX_ERROR;
+        }
+
+        value = value * 10 + (*line - '0');
+    }
+
+    if (value < 0) {
+        return NGX_ERROR;
+
+    } else {
+        return value;
+    }
+}
+
+
+off_t
+ngx_atoof(u_char *line, size_t n)
+{
+    off_t  value;
+
+    if (n == 0) {
+        return NGX_ERROR;
+    }
+
+    for (value = 0; n--; line++) {
+        if (*line < '0' || *line > '9') {
+            return NGX_ERROR;
+        }
+
+        value = value * 10 + (*line - '0');
+    }
+
+    if (value < 0) {
+        return NGX_ERROR;
+
+    } else {
+        return value;
+    }
+}
+
+
+time_t
+ngx_atotm(u_char *line, size_t n)
+{
+    time_t  value;
+
+    if (n == 0) {
+        return NGX_ERROR;
+    }
+
+    for (value = 0; n--; line++) {
+        if (*line < '0' || *line > '9') {
+            return NGX_ERROR;
+        }
+
+        value = value * 10 + (*line - '0');
+    }
+
+    if (value < 0) {
+        return NGX_ERROR;
+
+    } else {
+        return value;
+    }
+}
+
+
 ngx_int_t
 ngx_hextoi(u_char *line, size_t n)
 {
--- a/src/core/ngx_string.h
+++ b/src/core/ngx_string.h
@@ -23,6 +23,7 @@ typedef struct {
 
 
 #define ngx_tolower(c)     (u_char) ((c >= 'A' && c <= 'Z') ? (c | 0x20) : c)
+#define ngx_toupper(c)     (u_char) ((c >= 'a' && c <= 'z') ? (c & ~0x20) : c)
 
 
 #if (NGX_WIN32)
@@ -81,6 +82,9 @@ ngx_int_t ngx_rstrncmp(u_char *s1, u_cha
 ngx_int_t ngx_rstrncasecmp(u_char *s1, u_char *s2, size_t n);
 
 ngx_int_t ngx_atoi(u_char *line, size_t n);
+ssize_t ngx_atosz(u_char *line, size_t n);
+off_t ngx_atoof(u_char *line, size_t n);
+time_t ngx_atotm(u_char *line, size_t n);
 ngx_int_t ngx_hextoi(u_char *line, size_t n);
 
 void ngx_md5_text(u_char *text, u_char *md5);
--- a/src/core/ngx_times.c
+++ b/src/core/ngx_times.c
@@ -70,8 +70,8 @@ static char  *week[] = { "Sun", "Mon", "
 static char  *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
                            "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
 
-
-void ngx_time_init(void)
+void
+ngx_time_init(void)
 {
     struct timeval  tv;
 
@@ -104,9 +104,12 @@ void ngx_time_init(void)
 
 #if (NGX_THREADS)
 
-ngx_int_t ngx_time_mutex_init(ngx_log_t *log)
+ngx_int_t
+ngx_time_mutex_init(ngx_log_t *log)
 {
-    if (!(ngx_time_mutex = ngx_mutex_init(log, NGX_MUTEX_LIGHT))) {
+    ngx_time_mutex = ngx_mutex_init(log, NGX_MUTEX_LIGHT);
+
+    if (ngx_time_mutex == NULL) {
         return NGX_ERROR;
     }
 
@@ -116,7 +119,8 @@ ngx_int_t ngx_time_mutex_init(ngx_log_t 
 #endif
 
 
-void ngx_time_update(time_t s)
+void
+ngx_time_update(time_t s)
 {
     u_char    *p;
     ngx_tm_t   tm;
@@ -209,7 +213,8 @@ void ngx_time_update(time_t s)
 }
 
 
-u_char *ngx_http_time(u_char *buf, time_t t)
+u_char *
+ngx_http_time(u_char *buf, time_t t)
 {
     ngx_tm_t  tm;
 
@@ -226,7 +231,8 @@ u_char *ngx_http_time(u_char *buf, time_
 }
 
 
-u_char *ngx_http_cookie_time(u_char *buf, time_t t)
+u_char *
+ngx_http_cookie_time(u_char *buf, time_t t)
 {
     ngx_tm_t  tm;
 
@@ -252,7 +258,8 @@ u_char *ngx_http_cookie_time(u_char *buf
 }
 
 
-void ngx_gmtime(time_t t, ngx_tm_t *tp)
+void
+ngx_gmtime(time_t t, ngx_tm_t *tp)
 {
     ngx_int_t  sec, min, hour, mday, mon, year, wday, yday, days;
 
--- a/src/core/ngx_unix_domain.c
+++ b/src/core/ngx_unix_domain.c
@@ -59,11 +59,13 @@ ngx_peers_t *ngx_unix_upstream_parse(ngx
 
     /* MP: ngx_shared_palloc() */
 
-    if (!(peers = ngx_pcalloc(cf->pool, sizeof(ngx_peers_t)))) {
+    peers = ngx_pcalloc(cf->pool, sizeof(ngx_peers_t));
+    if (peers == NULL) {
         return NULL;
     }
 
-    if (!(sun = ngx_pcalloc(cf->pool, sizeof(struct sockaddr_un)))) {
+    sun = ngx_pcalloc(cf->pool, sizeof(struct sockaddr_un));
+    if (sun == NULL) {
         return NULL;
     }
 
--- a/src/event/modules/ngx_devpoll_module.c
+++ b/src/event/modules/ngx_devpoll_module.c
@@ -134,19 +134,21 @@ ngx_devpoll_init(ngx_cycle_t *cycle)
             ngx_free(change_list);
         }
 
-        ngx_test_null(change_list,
-                      ngx_alloc(sizeof(struct pollfd) * dpcf->changes,
-                                cycle->log),
-                      NGX_ERROR);
+        change_list = ngx_alloc(sizeof(struct pollfd) * dpcf->changes,
+                                cycle->log);
+        if (change_list == NULL) {
+            return NGX_ERROR;
+        }
 
         if (change_index) {
             ngx_free(change_index);
         }
 
-        ngx_test_null(change_index,
-                      ngx_alloc(sizeof(ngx_event_t *) * dpcf->changes,
-                                cycle->log),
-                      NGX_ERROR);
+        change_index = ngx_alloc(sizeof(ngx_event_t *) * dpcf->changes,
+                                 cycle->log);
+        if (change_index == NULL) {
+            return NGX_ERROR;
+        }
     }
 
     max_changes = dpcf->changes;
@@ -156,10 +158,11 @@ ngx_devpoll_init(ngx_cycle_t *cycle)
             ngx_free(event_list);
         }
 
-        ngx_test_null(event_list,
-                      ngx_alloc(sizeof(struct pollfd) * dpcf->events,
-                                cycle->log),
-                      NGX_ERROR);
+        event_list = ngx_alloc(sizeof(struct pollfd) * dpcf->events,
+                               cycle->log);
+        if (event_list == NULL) {
+            return NGX_ERROR;
+        }
     }
 
     nevents = dpcf->events;
@@ -318,11 +321,13 @@ ngx_devpoll_process_events(ngx_cycle_t *
 {
     int                 events, revents;
     ngx_int_t           i;
-    ngx_uint_t          j, lock, accept_lock, expire;
+    ngx_uint_t          lock, accept_lock, expire;
     size_t              n;
     ngx_msec_t          timer;
     ngx_err_t           err;
+#if 0
     ngx_cycle_t       **old_cycle;
+#endif
     ngx_event_t        *rev, *wev;
     ngx_connection_t   *c;
     ngx_epoch_msec_t    delta;
@@ -580,8 +585,10 @@ ngx_devpoll_create_conf(ngx_cycle_t *cyc
 {
     ngx_devpoll_conf_t  *dpcf;
 
-    ngx_test_null(dpcf, ngx_palloc(cycle->pool, sizeof(ngx_devpoll_conf_t)),
-                  NGX_CONF_ERROR);
+    dpcf = ngx_palloc(cycle->pool, sizeof(ngx_devpoll_conf_t));
+    if (dpcf == NULL) {
+        return NGX_CONF_ERROR;
+    }
 
     dpcf->changes = NGX_CONF_UNSET;
     dpcf->events = NGX_CONF_UNSET;
--- a/src/event/modules/ngx_epoll_module.c
+++ b/src/event/modules/ngx_epoll_module.c
@@ -133,7 +133,6 @@ ngx_module_t  ngx_epoll_module = {
 static ngx_int_t
 ngx_epoll_init(ngx_cycle_t *cycle)
 {
-    size_t             n;
     ngx_event_conf_t  *ecf;
     ngx_epoll_conf_t  *epcf;
 
@@ -380,7 +379,6 @@ static ngx_int_t
 ngx_epoll_process_events(ngx_cycle_t *cycle)
 {
     int                events;
-    size_t             n;
     uint32_t           revents;
     ngx_int_t          instance, i;
     ngx_uint_t         lock, accept_lock, expire;
@@ -663,8 +661,10 @@ ngx_epoll_create_conf(ngx_cycle_t *cycle
 {
     ngx_epoll_conf_t  *epcf;
 
-    ngx_test_null(epcf, ngx_palloc(cycle->pool, sizeof(ngx_epoll_conf_t)),
-                  NGX_CONF_ERROR);
+    epcf = ngx_palloc(cycle->pool, sizeof(ngx_epoll_conf_t));
+    if (epcf == NULL) {
+        return NGX_CONF_ERROR;
+    }
 
     epcf->events = NGX_CONF_UNSET;
 
--- a/src/event/modules/ngx_kqueue_module.c
+++ b/src/event/modules/ngx_kqueue_module.c
@@ -123,11 +123,13 @@ ngx_kqueue_init(ngx_cycle_t *cycle)
 
 #if (NGX_THREADS)
 
-        if (!(list_mutex = ngx_mutex_init(cycle->log, 0))) {
+        list_mutex = ngx_mutex_init(cycle->log, 0);
+        if (list_mutex == NULL) {
             return NGX_ERROR;
         }
 
-        if (!(kevent_mutex = ngx_mutex_init(cycle->log, 0))) {
+        kevent_mutex = ngx_mutex_init(cycle->log, 0);
+        if (kevent_mutex == NULL) {
             return NGX_ERROR;
         }
 
@@ -797,8 +799,10 @@ ngx_kqueue_create_conf(ngx_cycle_t *cycl
 {
     ngx_kqueue_conf_t  *kcf;
 
-    ngx_test_null(kcf, ngx_palloc(cycle->pool, sizeof(ngx_kqueue_conf_t)),
-                  NGX_CONF_ERROR);
+    kcf = ngx_palloc(cycle->pool, sizeof(ngx_kqueue_conf_t));
+    if (kcf == NULL) {
+        return NGX_CONF_ERROR;
+    }
 
     kcf->changes = NGX_CONF_UNSET;
     kcf->events = NGX_CONF_UNSET;
--- a/src/event/modules/ngx_poll_module.c
+++ b/src/event/modules/ngx_poll_module.c
@@ -73,10 +73,11 @@ ngx_poll_init(ngx_cycle_t *cycle)
         || cycle->old_cycle == NULL
         || cycle->old_cycle->connection_n < cycle->connection_n)
     {
-        ngx_test_null(list,
-                      ngx_alloc(sizeof(struct pollfd) * cycle->connection_n,
-                                cycle->log),
-                      NGX_ERROR);
+        list = ngx_alloc(sizeof(struct pollfd) * cycle->connection_n,
+                         cycle->log);
+        if (list == NULL) {
+            return NGX_ERROR;
+        }
 
         if (event_list) {
             ngx_memcpy(list, event_list, sizeof(ngx_event_t *) * nevents);
@@ -90,10 +91,11 @@ ngx_poll_init(ngx_cycle_t *cycle)
             ngx_free(ready_index);
         }
 
-        ngx_test_null(ready_index,
-                      ngx_alloc(sizeof(ngx_event_t *) * 2 * cycle->connection_n,
-                                cycle->log),
-                      NGX_ERROR);
+        ready_index = ngx_alloc(sizeof(ngx_event_t *) * 2 * cycle->connection_n,
+                                cycle->log);
+        if (ready_index == NULL) {
+            return NGX_ERROR;
+        }
 #endif
     }
 
--- a/src/event/modules/ngx_rtsig_module.c
+++ b/src/event/modules/ngx_rtsig_module.c
@@ -274,9 +274,8 @@ static ngx_int_t
 ngx_rtsig_process_events(ngx_cycle_t *cycle)
 {
     int                 signo;
-    ngx_int_t           instance, i;
+    ngx_int_t           instance;
     ngx_uint_t          expire;
-    size_t              n;
     ngx_msec_t          timer;
     ngx_err_t           err;
     siginfo_t           si;
@@ -777,8 +776,10 @@ ngx_rtsig_create_conf(ngx_cycle_t *cycle
 {
     ngx_rtsig_conf_t  *rtscf;
 
-    ngx_test_null(rtscf, ngx_palloc(cycle->pool, sizeof(ngx_rtsig_conf_t)),
-                  NGX_CONF_ERROR);
+    rtscf = ngx_palloc(cycle->pool, sizeof(ngx_rtsig_conf_t));
+    if (rtscf == NULL) {
+        return NGX_CONF_ERROR;
+    }
 
     rtscf->signo = NGX_CONF_UNSET;
     rtscf->overflow_events = NGX_CONF_UNSET;
--- a/src/event/modules/ngx_select_module.c
+++ b/src/event/modules/ngx_select_module.c
@@ -72,7 +72,8 @@ ngx_module_t  ngx_select_module = {
 };
 
 
-static ngx_int_t ngx_select_init(ngx_cycle_t *cycle)
+static ngx_int_t
+ngx_select_init(ngx_cycle_t *cycle)
 {
     ngx_event_t  **index;
 
@@ -86,10 +87,11 @@ static ngx_int_t ngx_select_init(ngx_cyc
         || cycle->old_cycle == NULL
         || cycle->old_cycle->connection_n < cycle->connection_n)
     {
-        ngx_test_null(index,
-                      ngx_alloc(sizeof(ngx_event_t *) * 2 * cycle->connection_n,
-                                cycle->log),
-                      NGX_ERROR);
+        index = ngx_alloc(sizeof(ngx_event_t *) * 2 * cycle->connection_n,
+                          cycle->log);
+        if (index == NULL) {
+            return NGX_ERROR;
+        }
 
         if (event_index) {
             ngx_memcpy(index, event_index, sizeof(ngx_event_t *) * nevents);
@@ -101,10 +103,12 @@ static ngx_int_t ngx_select_init(ngx_cyc
         if (ready_index) {
             ngx_free(ready_index);
         }
-        ngx_test_null(ready_index,
-                      ngx_alloc(sizeof(ngx_event_t *) * 2 * cycle->connection_n,
-                      cycle->log),
-                      NGX_ERROR);
+
+        ready_index = ngx_alloc(sizeof(ngx_event_t *) * 2 * cycle->connection_n,
+                                cycle->log);
+        if (ready_index == NULL) {
+            return NGX_ERROR;
+        }
 #endif
     }
 
@@ -124,7 +128,8 @@ static ngx_int_t ngx_select_init(ngx_cyc
 }
 
 
-static void ngx_select_done(ngx_cycle_t *cycle)
+static void
+ngx_select_done(ngx_cycle_t *cycle)
 {
     ngx_free(event_index);
 #if 0
@@ -135,7 +140,8 @@ static void ngx_select_done(ngx_cycle_t 
 }
 
 
-static ngx_int_t ngx_select_add_event(ngx_event_t *ev, int event, u_int flags)
+static ngx_int_t
+ngx_select_add_event(ngx_event_t *ev, int event, u_int flags)
 {
     ngx_connection_t  *c;
 
@@ -196,7 +202,8 @@ static ngx_int_t ngx_select_add_event(ng
 }
 
 
-static ngx_int_t ngx_select_del_event(ngx_event_t *ev, int event, u_int flags)
+static ngx_int_t
+ngx_select_del_event(ngx_event_t *ev, int event, u_int flags)
 {
     ngx_connection_t  *c;
 
@@ -248,7 +255,8 @@ static ngx_int_t ngx_select_del_event(ng
 }
 
 
-static ngx_int_t ngx_select_process_events(ngx_cycle_t *cycle)
+static ngx_int_t
+ngx_select_process_events(ngx_cycle_t *cycle)
 {
     int                       ready, nready;
     ngx_uint_t                i, found, lock, expire;
@@ -592,7 +600,8 @@ static ngx_int_t ngx_select_process_even
 }
 
 
-static char *ngx_select_init_conf(ngx_cycle_t *cycle, void *conf)
+static char *
+ngx_select_init_conf(ngx_cycle_t *cycle, void *conf)
 {
     ngx_event_conf_t  *ecf;
 
--- a/src/event/ngx_event.c
+++ b/src/event/ngx_event.c
@@ -219,7 +219,8 @@ static ngx_int_t ngx_event_module_init(n
 
 #endif
 
-    if (!(shared = ngx_create_shared_memory(size, cycle->log))) {
+    shared = ngx_create_shared_memory(size, cycle->log);
+    if (shared == NULL) {
         return NGX_ERROR;
     }
 
@@ -272,7 +273,8 @@ static ngx_int_t ngx_event_process_init(
     }
 
 #if (NGX_THREADS)
-    if (!(ngx_posted_events_mutex = ngx_mutex_init(cycle->log, 0))) {
+    ngx_posted_events_mutex = ngx_mutex_init(cycle->log, 0);
+    if (ngx_posted_events_mutex == NULL) {
         return NGX_ERROR;
     }
 #endif
@@ -497,42 +499,47 @@ ngx_int_t ngx_send_lowat(ngx_connection_
 
 static char *ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
-    int                    m;
-    char                  *rv;
+    char                 *rv;
     void               ***ctx;
+    ngx_uint_t            i;
     ngx_conf_t            pcf;
-    ngx_event_module_t   *module;
+    ngx_event_module_t   *m;
 
     /* count the number of the event modules and set up their indices */
 
     ngx_event_max_module = 0;
-    for (m = 0; ngx_modules[m]; m++) {
-        if (ngx_modules[m]->type != NGX_EVENT_MODULE) {
+    for (i = 0; ngx_modules[i]; i++) {
+        if (ngx_modules[i]->type != NGX_EVENT_MODULE) {
             continue;
         }
 
-        ngx_modules[m]->ctx_index = ngx_event_max_module++;
+        ngx_modules[i]->ctx_index = ngx_event_max_module++;
     }
 
-    ngx_test_null(ctx, ngx_pcalloc(cf->pool, sizeof(void *)), NGX_CONF_ERROR);
+    ctx = ngx_pcalloc(cf->pool, sizeof(void *));
+    if (ctx == NULL) {
+        return NGX_CONF_ERROR;
+    }
 
-    ngx_test_null(*ctx,
-                  ngx_pcalloc(cf->pool, ngx_event_max_module * sizeof(void *)),
-                  NGX_CONF_ERROR);
+    *ctx = ngx_pcalloc(cf->pool, ngx_event_max_module * sizeof(void *));
+    if (*ctx == NULL) {
+        return NGX_CONF_ERROR;
+    }
 
     *(void **) conf = ctx;
 
-    for (m = 0; ngx_modules[m]; m++) {
-        if (ngx_modules[m]->type != NGX_EVENT_MODULE) {
+    for (i = 0; ngx_modules[i]; i++) {
+        if (ngx_modules[i]->type != NGX_EVENT_MODULE) {
             continue;
         }
 
-        module = ngx_modules[m]->ctx;
+        m = ngx_modules[i]->ctx;
 
-        if (module->create_conf) {
-            ngx_test_null((*ctx)[ngx_modules[m]->ctx_index],
-                          module->create_conf(cf->cycle),
-                          NGX_CONF_ERROR);
+        if (m->create_conf) {
+            (*ctx)[ngx_modules[i]->ctx_index] = m->create_conf(cf->cycle);
+            if ((*ctx)[ngx_modules[i]->ctx_index] == NULL) {
+                return NGX_CONF_ERROR;
+            }
         }
     }
 
@@ -540,22 +547,23 @@ static char *ngx_events_block(ngx_conf_t
     cf->ctx = ctx;
     cf->module_type = NGX_EVENT_MODULE;
     cf->cmd_type = NGX_EVENT_CONF;
+
     rv = ngx_conf_parse(cf, NULL);
+
     *cf = pcf;
 
     if (rv != NGX_CONF_OK)
         return rv;
 
-    for (m = 0; ngx_modules[m]; m++) {
-        if (ngx_modules[m]->type != NGX_EVENT_MODULE) {
+    for (i = 0; ngx_modules[i]; i++) {
+        if (ngx_modules[i]->type != NGX_EVENT_MODULE) {
             continue;
         }
 
-        module = ngx_modules[m]->ctx;
+        m = ngx_modules[i]->ctx;
 
-        if (module->init_conf) {
-            rv = module->init_conf(cf->cycle,
-                                   (*ctx)[ngx_modules[m]->ctx_index]);
+        if (m->init_conf) {
+            rv = m->init_conf(cf->cycle, (*ctx)[ngx_modules[i]->ctx_index]);
             if (rv != NGX_CONF_OK) {
                 return rv;
             }
@@ -668,7 +676,8 @@ static char *ngx_event_debug_connection(
 
     /* AF_INET only */
 
-    if (!(addr = ngx_push_array(&ecf->debug_connection))) {
+    addr = ngx_array_push(&ecf->debug_connection);
+    if (addr == NULL) {
         return NGX_CONF_ERROR;
     }
 
@@ -704,8 +713,10 @@ static void *ngx_event_create_conf(ngx_c
 {
     ngx_event_conf_t  *ecf;
 
-    ngx_test_null(ecf, ngx_palloc(cycle->pool, sizeof(ngx_event_conf_t)),
-                  NGX_CONF_ERROR);
+    ecf = ngx_palloc(cycle->pool, sizeof(ngx_event_conf_t));
+    if (ecf == NULL) {
+        return NGX_CONF_ERROR;
+    }
 
     ecf->connections = NGX_CONF_UNSET_UINT;
     ecf->use = NGX_CONF_UNSET_UINT;
@@ -715,8 +726,13 @@ static void *ngx_event_create_conf(ngx_c
     ecf->name = (void *) NGX_CONF_UNSET;
 
 #if (NGX_DEBUG)
-    ngx_init_array(ecf->debug_connection, cycle->pool, 4, sizeof(in_addr_t),
-                   NGX_CONF_ERROR);
+
+    if (ngx_array_init(&ecf->debug_connection, cycle->pool, 4,
+                       sizeof(in_addr_t)) == NGX_ERROR)
+    {
+        return NGX_CONF_ERROR;
+    }
+
 #endif
 
     return ecf;
@@ -727,7 +743,12 @@ static char *ngx_event_init_conf(ngx_cyc
 {
     ngx_event_conf_t  *ecf = conf;
 
-    int                  fd, rtsig;
+#if (NGX_HAVE_EPOLL) && !(NGX_TEST_BUILD_EPOLL)
+    int                  fd;
+#endif
+#if (NGX_HAVE_RTSIG)
+    ngx_uint_t           rtsig;
+#endif
     ngx_int_t            i, connections;
     ngx_module_t        *module;
     ngx_core_conf_t     *ccf;
@@ -735,8 +756,6 @@ static char *ngx_event_init_conf(ngx_cyc
 
     connections = NGX_CONF_UNSET_UINT;
     module = NULL;
-    rtsig = 0;
-    fd = 0;
 
 #if (NGX_HAVE_EPOLL) && !(NGX_TEST_BUILD_EPOLL)
 
@@ -760,6 +779,9 @@ static char *ngx_event_init_conf(ngx_cyc
         connections = DEFAULT_CONNECTIONS;
         module = &ngx_rtsig_module;
         rtsig = 1;
+
+    } else {
+        rtsig = 0;
     }
 
 #endif
@@ -782,11 +804,10 @@ static char *ngx_event_init_conf(ngx_cyc
 
     if (module == NULL) {
 
-#if (NGX_WIN32)
+#if (NGX_WIN32 || FD_SETSIZE >= DEFAULT_CONNECTIONS)
         connections = DEFAULT_CONNECTIONS;
 #else
-        connections = FD_SETSIZE < DEFAULT_CONNECTIONS ? FD_SETSIZE:
-                                                         DEFAULT_CONNECTIONS;
+        connections = FD_SETSIZE;
 #endif
         module = &ngx_select_module;
     }
@@ -828,7 +849,15 @@ static char *ngx_event_init_conf(ngx_cyc
     ngx_conf_init_msec_value(ecf->accept_mutex_delay, 500);
 
 
-    if (!rtsig || ecf->accept_mutex) {
+#if (NGX_HAVE_RTSIG)
+
+    if (!rtsig) {
+        return NGX_CONF_OK;
+    }
+
+#endif
+
+    if (ecf->accept_mutex) {
         return NGX_CONF_OK;
     }
 
--- a/src/event/ngx_event_accept.c
+++ b/src/event/ngx_event_accept.c
@@ -16,7 +16,10 @@ static u_char *ngx_accept_log_error(ngx_
 void
 ngx_event_accept(ngx_event_t *ev)
 {
-    ngx_uint_t         instance, accepted;
+    ngx_uint_t         instance;
+#if 0
+    ngx_uint_t         accepted;
+#endif
     socklen_t          len;
     struct sockaddr   *sa;
     ngx_err_t          err;
@@ -43,8 +46,10 @@ ngx_event_accept(ngx_event_t *ev)
                    &ls->listening->addr_text, ev->available);
 
     ev->ready = 0;
+    pool = NULL;
+#if 0
     accepted = 0;
-    pool = NULL;
+#endif
 
     do {
 
@@ -56,17 +61,20 @@ ngx_event_accept(ngx_event_t *ev)
              * case and besides the pool can be got from the free pool list.
              */
 
-            if (!(pool = ngx_create_pool(ls->listening->pool_size, ev->log))) {
+            pool = ngx_create_pool(ls->listening->pool_size, ev->log);
+            if (pool == NULL) {
                 return;
             }
         }
 
-        if (!(sa = ngx_palloc(pool, ls->listening->socklen))) {
+        sa = ngx_palloc(pool, ls->listening->socklen);
+        if (sa == NULL) {
             ngx_destroy_pool(pool);
             return;
         }
 
-        if (!(log = ngx_palloc(pool, sizeof(ngx_log_t)))) {
+        log = ngx_palloc(pool, sizeof(ngx_log_t));
+        if (log == NULL) {
             ngx_destroy_pool(pool);
             return;
         }
@@ -331,7 +339,9 @@ ngx_event_accept(ngx_event_t *ev)
             ev->available--;
         }
 
+#if 0
         accepted++;
+#endif
 
     } while (ev->available);
 }
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -20,8 +20,6 @@ static void ngx_ssl_read_handler(ngx_eve
 ngx_int_t
 ngx_ssl_init(ngx_log_t *log)
 {
-    ENGINE  *engine;
-
     SSL_library_init();
     SSL_load_error_strings();
     ENGINE_load_builtin_engines();
@@ -36,11 +34,13 @@ ngx_ssl_create_session(ngx_ssl_ctx_t *ss
 {   
     ngx_ssl_t  *ssl;
 
-    if (!(ssl = ngx_pcalloc(c->pool, sizeof(ngx_ssl_t)))) {
+    ssl = ngx_pcalloc(c->pool, sizeof(ngx_ssl_t));
+    if (ssl == NULL) {
         return NGX_ERROR;
     }
 
-    if (!(ssl->buf = ngx_create_temp_buf(c->pool, NGX_SSL_BUFSIZE))) {
+    ssl->buf = ngx_create_temp_buf(c->pool, NGX_SSL_BUFSIZE);
+    if (ssl->buf == NULL) {
         return NGX_ERROR;
     }
 
@@ -586,7 +586,7 @@ ngx_ssl_error(ngx_uint_t level, ngx_log_
     p = ngx_vsnprintf(errstr, sizeof(errstr) - 1, fmt, args);
     va_end(args);
 
-    p = ngx_cpystrn(p, " (SSL: ", last - p);
+    p = ngx_cpystrn(p, (u_char *) " (SSL: ", last - p);
 
     ERR_error_string_n(ERR_get_error(), (char *) p, last - p);
 
--- a/src/event/ngx_event_pipe.c
+++ b/src/event/ngx_event_pipe.c
@@ -165,13 +165,15 @@ static ngx_int_t ngx_event_pipe_read_ups
 
                 /* allocate a new buf if it's still allowed */
 
-                if (!(b = ngx_create_temp_buf(p->pool, p->bufs.size))) {
+                b = ngx_create_temp_buf(p->pool, p->bufs.size);
+                if (b == NULL) {
                     return NGX_ABORT;
                 }
 
                 p->allocated++;
 
-                if (!(chain = ngx_alloc_chain_link(p->pool))) {
+                chain = ngx_alloc_chain_link(p->pool);
+                if (chain == NULL) {
                     return NGX_ABORT;
                 }
 
@@ -495,7 +497,13 @@ static ngx_int_t ngx_event_pipe_write_to
             }
 
             cl->next = NULL;
-            ngx_chain_add_link(out, ll, cl);
+
+            if (out) {
+                *ll = cl;
+            } else {
+                out = cl;
+            }
+            ll = &cl->next;
         }
 
         ngx_log_debug2(NGX_LOG_DEBUG_EVENT, p->log, 0,
@@ -635,11 +643,17 @@ static ngx_int_t ngx_event_pipe_write_ch
         b->in_file = 1;
         b->temp_file = 1;
 
-        ngx_chain_add_link(p->out, p->last_out, cl);
+        if (p->out) {
+            *p->last_out = cl;
+        } else {
+            p->out = cl;
+        }
+        p->last_out = &cl->next;
 
         if (b->last_shadow) {
 
-            if (!(tl = ngx_alloc_chain_link(p->pool))) {
+            tl = ngx_alloc_chain_link(p->pool);
+            if (tl == NULL) {
                 return NGX_ABORT;
             }
 
@@ -676,7 +690,8 @@ ngx_int_t ngx_event_pipe_copy_input_filt
         p->free = p->free->next;
 
     } else {
-        if (!(b = ngx_alloc_buf(p->pool))) {
+        b = ngx_alloc_buf(p->pool);
+        if (b == NULL) {
             return NGX_ERROR;
         }
     }
@@ -688,7 +703,8 @@ ngx_int_t ngx_event_pipe_copy_input_filt
     b->recycled = 1;
     buf->shadow = b;
 
-    if (!(cl = ngx_alloc_chain_link(p->pool))) {
+    cl = ngx_alloc_chain_link(p->pool);
+    if (cl == NULL) {
         return NGX_ERROR;
     }
 
@@ -697,7 +713,12 @@ ngx_int_t ngx_event_pipe_copy_input_filt
 
     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0, "input buf #%d", b->num);
 
-    ngx_chain_add_link(p->in, p->last_in, cl);
+    if (p->in) {
+        *p->last_in = cl;
+    } else {
+        p->in = cl;
+    }
+    p->last_in = &cl->next;
 
     return NGX_OK;
 }
@@ -766,7 +787,8 @@ ngx_int_t ngx_event_pipe_add_free_buf(ng
 {
     ngx_chain_t  *cl;
 
-    if (!(cl = ngx_alloc_chain_link(p->pool))) {
+    cl = ngx_alloc_chain_link(p->pool);
+    if (cl == NULL) {
         return NGX_ERROR;
     }
 
--- a/src/event/ngx_event_posted.c
+++ b/src/event/ngx_event_posted.c
@@ -43,10 +43,10 @@ void ngx_event_process_posted(ngx_cycle_
 void ngx_wakeup_worker_thread(ngx_cycle_t *cycle)
 {
     ngx_int_t     i;
+#if 0
     ngx_uint_t    busy;
     ngx_event_t  *ev;
 
-#if 0
     busy = 1;
 
     if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
--- a/src/event/ngx_event_timer.c
+++ b/src/event/ngx_event_timer.c
@@ -31,7 +31,8 @@ ngx_event_timer_init(ngx_log_t *log)
     ngx_event_timer_rbtree = &ngx_event_timer_sentinel;
 
 #if (NGX_THREADS)
-    if (!(ngx_event_timer_mutex = ngx_mutex_init(log, 0))) {
+    ngx_event_timer_mutex = ngx_mutex_init(log, 0);
+    if (ngx_event_timer_mutex == NULL) {
         return NGX_ERROR;
     }
 #endif
--- a/src/event/ngx_event_timer.h
+++ b/src/event/ngx_event_timer.h
@@ -13,8 +13,8 @@
 #include <ngx_event.h>
 
 
-#define NGX_TIMER_INFINITE  -1
-#define NGX_TIMER_ERROR     -2
+#define NGX_TIMER_INFINITE  (ngx_msec_t) -1
+#define NGX_TIMER_ERROR     (ngx_msec_t) -2
 
 
 /*
deleted file mode 100644
--- a/src/http/modules/ngx_http_access_handler.c
+++ /dev/null
@@ -1,214 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-/* AF_INET only */
-
-typedef struct {
-    in_addr_t     mask;
-    in_addr_t     addr;
-    unsigned      deny;
-} ngx_http_access_rule_t;
-
-
-typedef struct {
-    ngx_array_t  *rules;     /* array of ngx_http_access_rule_t */
-} ngx_http_access_loc_conf_t;
-
-
-static ngx_int_t ngx_http_access_handler(ngx_http_request_t *r);
-static char *ngx_http_access_rule(ngx_conf_t *cf, ngx_command_t *cmd,
-                                  void *conf);
-static void *ngx_http_access_create_loc_conf(ngx_conf_t *cf);
-static char *ngx_http_access_merge_loc_conf(ngx_conf_t *cf,
-                                            void *parent, void *child);
-static ngx_int_t ngx_http_access_init(ngx_cycle_t *cycle);
-
-
-static ngx_command_t  ngx_http_access_commands[] = {
-
-    { ngx_string("allow"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
-      ngx_http_access_rule,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      0,
-      NULL },
-
-    { ngx_string("deny"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
-      ngx_http_access_rule,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      0,
-      NULL },
-
-      ngx_null_command
-};
-
-
-
-ngx_http_module_t  ngx_http_access_module_ctx = {
-    NULL,                                  /* pre conf */
-
-    NULL,                                  /* create main configuration */
-    NULL,                                  /* init main configuration */
-
-    NULL,                                  /* create server configuration */
-    NULL,                                  /* merge server configuration */
-
-    ngx_http_access_create_loc_conf,       /* create location configuration */
-    ngx_http_access_merge_loc_conf         /* merge location configuration */
-};
-
-
-ngx_module_t  ngx_http_access_module = {
-    NGX_MODULE,
-    &ngx_http_access_module_ctx,           /* module context */
-    ngx_http_access_commands,              /* module directives */
-    NGX_HTTP_MODULE,                       /* module type */
-    ngx_http_access_init,                  /* init module */
-    NULL                                   /* init process */
-};
-
-
-static ngx_int_t ngx_http_access_handler(ngx_http_request_t *r)
-{
-    ngx_uint_t                   i;
-    struct sockaddr_in          *sin;
-    ngx_http_access_rule_t      *rule;
-    ngx_http_access_loc_conf_t  *alcf;
-
-    alcf = ngx_http_get_module_loc_conf(r, ngx_http_access_module);
-
-    if (alcf->rules == NULL) {
-        return NGX_OK;
-    }
-
-    /* AF_INET only */
-
-    sin = (struct sockaddr_in *) r->connection->sockaddr;
-
-    rule = alcf->rules->elts;
-    for (i = 0; i < alcf->rules->nelts; i++) {
-
-        ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                       "%08XD %08XD %08XD",
-                       sin->sin_addr.s_addr, rule[i].mask, rule[i].addr);
-
-        if ((sin->sin_addr.s_addr & rule[i].mask) == rule[i].addr) {
-            if (rule[i].deny) {
-                ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
-                              "access forbidden by rule");
-
-                return NGX_HTTP_FORBIDDEN;
-            }
-
-            return NGX_OK;
-        }
-    }
-
-    return NGX_OK;
-}
-
-
-static char *ngx_http_access_rule(ngx_conf_t *cf, ngx_command_t *cmd,
-                                  void *conf)
-{
-    ngx_http_access_loc_conf_t *alcf = conf;
-
-    ngx_str_t               *value;
-    ngx_inet_cidr_t          in_cidr;
-    ngx_http_access_rule_t  *rule;
-
-    if (alcf->rules == NULL) {
-        alcf->rules = ngx_create_array(cf->pool, 4,
-                                       sizeof(ngx_http_access_rule_t));
-        if (alcf->rules == NULL) {
-            return NGX_CONF_ERROR;
-        }
-    }
-
-    if (!(rule = ngx_push_array(alcf->rules))) {
-        return NGX_CONF_ERROR;
-    }
-
-    value = cf->args->elts;
-
-    rule->deny = (value[0].data[0] == 'd') ? 1 : 0;
-
-    if (value[1].len == 3 && ngx_strcmp(value[1].data, "all") == 0) {
-        rule->mask = 0;
-        rule->addr = 0;
-
-        return NGX_CONF_OK;
-    }
-
-    rule->addr = inet_addr((char *) value[1].data);
-
-    if (rule->addr != INADDR_NONE) {
-        rule->mask = 0xffffffff;
-
-        return NGX_CONF_OK;
-    }
-
-    if (ngx_ptocidr(&value[1], &in_cidr) == NGX_ERROR) {
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"",
-                           &value[1]);
-        return NGX_CONF_ERROR;
-    }
-
-    rule->mask = in_cidr.mask;
-    rule->addr = in_cidr.addr;
-
-    return NGX_CONF_OK;
-}
-
-
-static void *ngx_http_access_create_loc_conf(ngx_conf_t *cf)
-{
-    ngx_http_access_loc_conf_t  *conf;
-
-    if (!(conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_access_loc_conf_t)))) {
-        return NGX_CONF_ERROR;
-    }
-
-    return conf;
-}
-
-
-static char *ngx_http_access_merge_loc_conf(ngx_conf_t *cf,
-                                            void *parent, void *child)
-{
-    ngx_http_access_loc_conf_t  *prev = parent;
-    ngx_http_access_loc_conf_t  *conf = child;
-
-    if (conf->rules == NULL) {
-        conf->rules = prev->rules;
-    }
-
-    return NGX_CONF_OK;
-}
-
-
-static ngx_int_t ngx_http_access_init(ngx_cycle_t *cycle)
-{
-    ngx_http_handler_pt        *h;
-    ngx_http_core_main_conf_t  *cmcf;
-
-    cmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_core_module);
-
-    h = ngx_push_array(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers);
-    if (h == NULL) {
-        return NGX_ERROR;
-    }
-
-    *h = ngx_http_access_handler;
-
-    return NGX_OK;
-}
new file mode 100644
--- /dev/null
+++ b/src/http/modules/ngx_http_access_module.c
@@ -0,0 +1,219 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+
+
+/* AF_INET only */
+
+typedef struct {
+    in_addr_t     mask;
+    in_addr_t     addr;
+    unsigned      deny;
+} ngx_http_access_rule_t;
+
+
+typedef struct {
+    ngx_array_t  *rules;     /* array of ngx_http_access_rule_t */
+} ngx_http_access_loc_conf_t;
+
+
+static ngx_int_t ngx_http_access_handler(ngx_http_request_t *r);
+static char *ngx_http_access_rule(ngx_conf_t *cf, ngx_command_t *cmd,
+    void *conf);
+static void *ngx_http_access_create_loc_conf(ngx_conf_t *cf);
+static char *ngx_http_access_merge_loc_conf(ngx_conf_t *cf,
+    void *parent, void *child);
+static ngx_int_t ngx_http_access_init(ngx_cycle_t *cycle);
+
+
+static ngx_command_t  ngx_http_access_commands[] = {
+
+    { ngx_string("allow"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_http_access_rule,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      0,
+      NULL },
+
+    { ngx_string("deny"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_http_access_rule,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      0,
+      NULL },
+
+      ngx_null_command
+};
+
+
+
+ngx_http_module_t  ngx_http_access_module_ctx = {
+    NULL,                                  /* pre conf */
+
+    NULL,                                  /* create main configuration */
+    NULL,                                  /* init main configuration */
+
+    NULL,                                  /* create server configuration */
+    NULL,                                  /* merge server configuration */
+
+    ngx_http_access_create_loc_conf,       /* create location configuration */
+    ngx_http_access_merge_loc_conf         /* merge location configuration */
+};
+
+
+ngx_module_t  ngx_http_access_module = {
+    NGX_MODULE,
+    &ngx_http_access_module_ctx,           /* module context */
+    ngx_http_access_commands,              /* module directives */
+    NGX_HTTP_MODULE,                       /* module type */
+    ngx_http_access_init,                  /* init module */
+    NULL                                   /* init process */
+};
+
+
+static ngx_int_t
+ngx_http_access_handler(ngx_http_request_t *r)
+{
+    ngx_uint_t                   i;
+    struct sockaddr_in          *sin;
+    ngx_http_access_rule_t      *rule;
+    ngx_http_access_loc_conf_t  *alcf;
+
+    alcf = ngx_http_get_module_loc_conf(r, ngx_http_access_module);
+
+    if (alcf->rules == NULL) {
+        return NGX_OK;
+    }
+
+    /* AF_INET only */
+
+    sin = (struct sockaddr_in *) r->connection->sockaddr;
+
+    rule = alcf->rules->elts;
+    for (i = 0; i < alcf->rules->nelts; i++) {
+
+        ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                       "%08XD %08XD %08XD",
+                       sin->sin_addr.s_addr, rule[i].mask, rule[i].addr);
+
+        if ((sin->sin_addr.s_addr & rule[i].mask) == rule[i].addr) {
+            if (rule[i].deny) {
+                ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                              "access forbidden by rule");
+
+                return NGX_HTTP_FORBIDDEN;
+            }
+
+            return NGX_OK;
+        }
+    }
+
+    return NGX_OK;
+}
+
+
+static char *
+ngx_http_access_rule(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+    ngx_http_access_loc_conf_t *alcf = conf;
+
+    ngx_str_t               *value;
+    ngx_inet_cidr_t          in_cidr;
+    ngx_http_access_rule_t  *rule;
+
+    if (alcf->rules == NULL) {
+        alcf->rules = ngx_array_create(cf->pool, 4,
+                                       sizeof(ngx_http_access_rule_t));
+        if (alcf->rules == NULL) {
+            return NGX_CONF_ERROR;
+        }
+    }
+
+    rule = ngx_array_push(alcf->rules);
+    if (rule == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    value = cf->args->elts;
+
+    rule->deny = (value[0].data[0] == 'd') ? 1 : 0;
+
+    if (value[1].len == 3 && ngx_strcmp(value[1].data, "all") == 0) {
+        rule->mask = 0;
+        rule->addr = 0;
+
+        return NGX_CONF_OK;
+    }
+
+    rule->addr = inet_addr((char *) value[1].data);
+
+    if (rule->addr != INADDR_NONE) {
+        rule->mask = 0xffffffff;
+
+        return NGX_CONF_OK;
+    }
+
+    if (ngx_ptocidr(&value[1], &in_cidr) == NGX_ERROR) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"",
+                           &value[1]);
+        return NGX_CONF_ERROR;
+    }
+
+    rule->mask = in_cidr.mask;
+    rule->addr = in_cidr.addr;
+
+    return NGX_CONF_OK;
+}
+
+
+static void *
+ngx_http_access_create_loc_conf(ngx_conf_t *cf)
+{
+    ngx_http_access_loc_conf_t  *conf;
+
+    conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_access_loc_conf_t));
+    if (conf == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    return conf;
+}
+
+
+static char *
+ngx_http_access_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
+{
+    ngx_http_access_loc_conf_t  *prev = parent;
+    ngx_http_access_loc_conf_t  *conf = child;
+
+    if (conf->rules == NULL) {
+        conf->rules = prev->rules;
+    }
+
+    return NGX_CONF_OK;
+}
+
+
+static ngx_int_t
+ngx_http_access_init(ngx_cycle_t *cycle)
+{
+    ngx_http_handler_pt        *h;
+    ngx_http_core_main_conf_t  *cmcf;
+
+    cmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_core_module);
+
+    h = ngx_array_push(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers);
+    if (h == NULL) {
+        return NGX_ERROR;
+    }
+
+    *h = ngx_http_access_handler;
+
+    return NGX_OK;
+}
deleted file mode 100644
--- a/src/http/modules/ngx_http_autoindex_handler.c
+++ /dev/null
@@ -1,560 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-#if 0
-
-typedef struct {
-    ngx_buf_t     *buf;
-    size_t         size;
-    ngx_pool_t    *pool;
-    size_t         alloc_size;
-    ngx_chain_t  **last_out;
-} ngx_http_autoindex_ctx_t;
-
-#endif
-
-
-typedef struct {
-    ngx_str_t      name;
-    ngx_uint_t     escape;
-    ngx_uint_t     dir;
-    time_t         mtime;
-    off_t          size;
-} ngx_http_autoindex_entry_t;
-
-
-typedef struct {
-    ngx_flag_t     enable;
-} ngx_http_autoindex_loc_conf_t;
-
-
-#define NGX_HTTP_AUTOINDEX_NAME_LEN  50
-
-
-static int ngx_http_autoindex_cmp_entries(const void *one, const void *two);
-static ngx_int_t ngx_http_autoindex_error(ngx_http_request_t *r,
-    ngx_dir_t *dir, u_char *name);
-static ngx_int_t ngx_http_autoindex_init(ngx_cycle_t *cycle);
-static void *ngx_http_autoindex_create_loc_conf(ngx_conf_t *cf);
-static char *ngx_http_autoindex_merge_loc_conf(ngx_conf_t *cf,
-    void *parent, void *child);
-
-
-static ngx_command_t  ngx_http_autoindex_commands[] = {
-
-    { ngx_string("autoindex"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
-      ngx_conf_set_flag_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_autoindex_loc_conf_t, enable),
-      NULL },
-
-      ngx_null_command
-};
-
-
-ngx_http_module_t  ngx_http_autoindex_module_ctx = {
-    NULL,                                  /* pre conf */
-
-    NULL,                                  /* create main configuration */
-    NULL,                                  /* init main configuration */
-
-    NULL,                                  /* create server configuration */
-    NULL,                                  /* merge server configuration */
-
-    ngx_http_autoindex_create_loc_conf,    /* create location configration */
-    ngx_http_autoindex_merge_loc_conf      /* merge location configration */
-};
-
-
-ngx_module_t  ngx_http_autoindex_module = {
-    NGX_MODULE,
-    &ngx_http_autoindex_module_ctx,        /* module context */ 
-    ngx_http_autoindex_commands,           /* module directives */
-    NGX_HTTP_MODULE,                       /* module type */
-    ngx_http_autoindex_init,               /* init module */
-    NULL                                   /* init process */
-};
-
-
-static u_char title[] =
-"<html>" CRLF
-"<head><title>Index of "
-;
-
-
-static u_char header[] =
-"</title></head>" CRLF
-"<body bgcolor=\"white\">" CRLF
-"<h1>Index of "
-;
-
-static u_char tail[] =
-"</body>" CRLF
-"</html>" CRLF
-;
-
-
-static ngx_int_t
-ngx_http_autoindex_handler(ngx_http_request_t *r)
-{
-    u_char                         *last;
-    size_t                          len;
-    ngx_tm_t                        tm;
-    ngx_int_t                       rc;
-    ngx_uint_t                      i, level;
-    ngx_err_t                       err;
-    ngx_buf_t                      *b;
-    ngx_chain_t                     out;
-    ngx_str_t                       dname, fname;
-    ngx_dir_t                       dir;
-    ngx_pool_t                     *pool;
-    ngx_array_t                     entries;
-    ngx_http_core_loc_conf_t       *clcf;
-    ngx_http_autoindex_entry_t     *entry;
-    ngx_http_autoindex_loc_conf_t  *alcf;
-
-    static char  *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
-                               "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
-
-    if (r->uri.data[r->uri.len - 1] != '/') {
-        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) {
-        return NGX_DECLINED;
-    }
-
-    /* TODO: pool should be temporary pool */
-    pool = r->pool;
-
-    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-
-    if (clcf->alias) {
-        dname.data = ngx_palloc(pool, clcf->root.len + r->uri.len
-                                                     + NGX_DIR_MASK_LEN + 1
-                                                     - clcf->name.len);
-        if (dname.data == NULL) {
-            return NGX_HTTP_INTERNAL_SERVER_ERROR;
-        }
-    
-        last = ngx_cpymem(dname.data, clcf->root.data, clcf->root.len);
-        last = ngx_cpystrn(last, r->uri.data + clcf->name.len,
-                           r->uri.len - clcf->name.len + 1);
-
-    } else {
-        dname.data = ngx_palloc(pool, clcf->root.len + r->uri.len
-                                                     + NGX_DIR_MASK_LEN);
-        if (dname.data == NULL) {
-            return NGX_HTTP_INTERNAL_SERVER_ERROR;
-        }
-
-        last = ngx_cpymem(dname.data, clcf->root.data, clcf->root.len);
-        last = ngx_cpystrn(last, r->uri.data, r->uri.len);
-    }
-
-    dname.len = last - dname.data;
-
-    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                   "http autoindex: \"%s\"", dname.data);
-
-
-    if (ngx_open_dir(&dname, &dir) == NGX_ERROR) {
-        err = ngx_errno;
-
-        if (err == NGX_ENOENT || err == NGX_ENOTDIR) {
-            level = NGX_LOG_ERR;
-            rc = NGX_HTTP_NOT_FOUND;
-
-        } else if (err == NGX_EACCES) {
-            level = NGX_LOG_ERR;
-            rc = NGX_HTTP_FORBIDDEN;
-
-        } else {
-            level = NGX_LOG_CRIT;
-            rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
-        }
-
-        ngx_log_error(level, r->connection->log, err,
-                      ngx_open_dir_n " \"%s\" failed", dname.data);
-
-        return rc;
-    }
-
-#if (NGX_SUPPRESS_WARN)
-    /* MSVC thinks 'entries' may be used without having been initialized */
-    ngx_memzero(&entries, sizeof(ngx_array_t));
-#endif
-
-    if (ngx_array_init(&entries, pool, 50, sizeof(ngx_http_autoindex_entry_t))
-                                                                  == NGX_ERROR)
-    {
-        return ngx_http_autoindex_error(r, &dir, dname.data);
-    }
-
-    fname.len = 0;
-#if (NGX_SUPPRESS_WARN)
-    fname.data = NULL;
-#endif
-
-    for ( ;; ) {
-        ngx_set_errno(0);
-
-        if (ngx_read_dir(&dir) == NGX_ERROR) {
-            err = ngx_errno;
-
-            if (err == NGX_ENOMOREFILES) {
-                rc = NGX_OK;
-
-            } else {
-                ngx_log_error(NGX_LOG_CRIT, r->connection->log, err,
-                              ngx_read_dir_n " \"%s\" failed", dname.data);
-                return ngx_http_autoindex_error(r, &dir, dname.data);
-            }
-
-            break; 
-        }
-
-        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                       "http autoindex file: \"%s\"", ngx_de_name(&dir));
-
-        len = ngx_de_namelen(&dir);
-
-        if (len == 1 && ngx_de_name(&dir)[0] == '.') {
-            continue;
-        }
-
-        if (len == 2
-            && ngx_de_name(&dir)[0] == '.'
-            && ngx_de_name(&dir)[1] == '.')
-        {
-            continue;
-        }
-
-        if (!dir.valid_info) {
-
-            if (dname.len + 1 + len > fname.len) {
-                fname.len = dname.len + 1 + len + 32;
-
-                if (!(fname.data = ngx_palloc(pool, fname.len))) {
-                    return ngx_http_autoindex_error(r, &dir, dname.data);
-                }
-
-                last = ngx_cpystrn(fname.data, dname.data,
-                                   dname.len + 1);
-                *last++ = '/';
-            }
-
-            ngx_cpystrn(last, ngx_de_name(&dir), len + 1);
-
-            if (ngx_de_info(fname.data, &dir) == NGX_FILE_ERROR) {
-                err = ngx_errno;
-
-                if (err != NGX_ENOENT) {
-                    ngx_log_error(NGX_LOG_CRIT, r->connection->log, err,
-                                  ngx_de_info_n " \"%s\" failed", fname.data);
-                    return ngx_http_autoindex_error(r, &dir, dname.data);
-                }
-
-                if (ngx_de_link_info(fname.data, &dir) == NGX_FILE_ERROR) {
-                    ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
-                                  ngx_de_link_info_n " \"%s\" failed",
-                                  fname.data);
-                    return ngx_http_autoindex_error(r, &dir, dname.data);
-                }
-            }
-        }
-
-        if (!(entry = ngx_array_push(&entries))) {
-            return ngx_http_autoindex_error(r, &dir, dname.data);
-        }
-
-        entry->name.len = len;        
-        entry->escape = 2 * ngx_escape_uri(NULL, ngx_de_name(&dir), len,
-                                           NGX_ESCAPE_HTML);
-
-        if (!(entry->name.data = ngx_palloc(pool, len + entry->escape + 1))) {
-            return ngx_http_autoindex_error(r, &dir, dname.data);
-        }
-
-        ngx_cpystrn(entry->name.data, ngx_de_name(&dir), len + 1);
-
-        entry->dir = ngx_de_is_dir(&dir);
-        entry->mtime = ngx_de_mtime(&dir);
-        entry->size = ngx_de_size(&dir);
-    }
-
-    if (ngx_close_dir(&dir) == NGX_ERROR) {
-        ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
-                      ngx_close_dir_n " \"%s\" failed", dname.data);
-    }
-
-    len = sizeof(title) - 1
-          + r->uri.len
-          + sizeof(header) - 1
-          + r->uri.len
-          + sizeof("</h1>") - 1
-          + sizeof("<hr><pre><a href=\"../\">../</a>" CRLF) - 1
-          + sizeof("</pre><hr>") - 1
-          + sizeof(tail) - 1;
-
-    entry = entries.elts;
-    for (i = 0; i < entries.nelts; i++) {
-        len += sizeof("<a href=\"") - 1
-               + 1                                          /* 1 is for "/" */
-               + entry[i].name.len + entry[i].escape
-               + sizeof("\">") - 1
-               + NGX_HTTP_AUTOINDEX_NAME_LEN + sizeof("&gt;") - 2
-               + sizeof("</a>") - 1
-               + sizeof(" 28-Sep-1970 12:00 ") - 1
-               + 19
-               + 2;
-    }
-
-    if (!(b = ngx_create_temp_buf(r->pool, len))) {
-        return NGX_HTTP_INTERNAL_SERVER_ERROR;
-    }
-
-    if (entries.nelts > 1) {
-        ngx_qsort(entry, (size_t) entries.nelts,
-                  sizeof(ngx_http_autoindex_entry_t),
-                  ngx_http_autoindex_cmp_entries);
-    }
-
-    b->last = ngx_cpymem(b->last, title, sizeof(title) - 1);
-    b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len);
-    b->last = ngx_cpymem(b->last, header, sizeof(header) - 1);
-    b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len);
-    b->last = ngx_cpymem(b->last, "</h1>", sizeof("</h1>") - 1);
-
-    b->last = ngx_cpymem(b->last, "<hr><pre><a href=\"../\">../</a>" CRLF,
-                         sizeof("<hr><pre><a href=\"../\">../</a>" CRLF) - 1);
-
-    for (i = 0; i < entries.nelts; i++) {
-        b->last = ngx_cpymem(b->last, "<a href=\"", sizeof("<a href=\"") - 1);
-
-        if (entry[i].escape) {
-            ngx_escape_uri(b->last, entry[i].name.data, entry[i].name.len,
-                           NGX_ESCAPE_HTML);
-
-            b->last += entry[i].name.len + entry[i].escape;
-
-        } else {
-            b->last = ngx_cpymem(b->last, entry[i].name.data,
-                                 entry[i].name.len);
-        }
-
-        if (entry[i].dir) {
-            *b->last++ = '/';
-        }
-
-        *b->last++ = '"';
-        *b->last++ = '>';
-
-        b->last = ngx_cpystrn(b->last, entry[i].name.data,
-                              NGX_HTTP_AUTOINDEX_NAME_LEN + 1);
-
-        len = entry[i].name.len;
-
-        if (len > NGX_HTTP_AUTOINDEX_NAME_LEN) {
-            b->last = ngx_cpymem(b->last - 3, "..&gt;</a>",
-                                 sizeof("..&gt;</a>") - 1);
-
-        } else {
-            if (entry[i].dir && NGX_HTTP_AUTOINDEX_NAME_LEN - len > 0) {
-                *b->last++ = '/';
-                len++;
-            }
-
-            b->last = ngx_cpymem(b->last, "</a>", sizeof("</a>") - 1);
-            ngx_memset(b->last, ' ', NGX_HTTP_AUTOINDEX_NAME_LEN - len);
-            b->last += NGX_HTTP_AUTOINDEX_NAME_LEN - len;
-        }
-
-        *b->last++ = ' ';
-
-        ngx_gmtime(entry[i].mtime, &tm);
-
-        b->last = ngx_sprintf(b->last, "%02d-%s-%d %02d:%02d ",
-                              tm.ngx_tm_mday,
-                              months[tm.ngx_tm_mon - 1],
-                              tm.ngx_tm_year,
-                              tm.ngx_tm_hour,
-                              tm.ngx_tm_min);
-
-        if (entry[i].dir) {
-            b->last = ngx_cpymem(b->last,  "                  -",
-                                 sizeof("                  -") - 1);
-
-        } else {
-            b->last = ngx_sprintf(b->last, "%19O", entry[i].size);
-        }
-
-        *b->last++ = CR;
-        *b->last++ = LF;
-    }
-
-    /* TODO: free temporary pool */
-
-    b->last = ngx_cpymem(b->last, "</pre><hr>", sizeof("</pre><hr>") - 1);
-
-    b->last = ngx_cpymem(b->last, tail, sizeof(tail) - 1);
-
-    r->headers_out.status = NGX_HTTP_OK;
-    r->headers_out.content_length_n = b->last - b->pos;
-
-    r->headers_out.content_type = ngx_list_push(&r->headers_out.headers);
-    if (r->headers_out.content_type == NULL) {
-        return NGX_HTTP_INTERNAL_SERVER_ERROR;
-    }
-
-    r->headers_out.content_type->key.len = 0;
-    r->headers_out.content_type->key.data = NULL;
-    r->headers_out.content_type->value.len = sizeof("text/html") - 1;
-    r->headers_out.content_type->value.data = (u_char *) "text/html";
-
-    rc = ngx_http_send_header(r);
-
-    if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
-        return rc;
-    }
-
-    if (!r->main) {
-        b->last_buf = 1;
-    }
-
-    out.buf = b;
-    out.next = NULL;
-
-    return ngx_http_output_filter(r, &out);
-}
-
-
-static int
-ngx_http_autoindex_cmp_entries(const void *one, const void *two)
-{
-    ngx_http_autoindex_entry_t *first = (ngx_http_autoindex_entry_t *) one;
-    ngx_http_autoindex_entry_t *second = (ngx_http_autoindex_entry_t *) two;
-
-    if (first->dir && !second->dir) {
-        /* move the directories to the start */
-        return -1;
-    }
-
-    if (!first->dir && second->dir) {
-        /* move the directories to the start */
-        return 1;
-    }
-
-    return (int) ngx_strcmp(first->name.data, second->name.data);
-}
-
-
-#if 0
-
-static ngx_buf_t *
-ngx_http_autoindex_alloc(ngx_http_autoindex_ctx_t *ctx, size_t size)
-{
-    ngx_chain_t  *cl;
-
-    if (ctx->buf) {
-
-        if ((size_t) (ctx->buf->end - ctx->buf->last) >= size) {
-            return ctx->buf;
-        }
-
-        ctx->size += ctx->buf->last - ctx->buf->pos;
-    }
-
-    if (!(ctx->buf = ngx_create_temp_buf(ctx->pool, ctx->alloc_size))) {
-        return NULL;
-    }
-
-    if (!(cl = ngx_alloc_chain_link(ctx->pool))) {
-        return NULL;
-    }
-
-    cl->buf = ctx->buf;
-    cl->next = NULL;
-
-    *ctx->last_out = cl;
-    ctx->last_out = &cl->next;
-
-    return ctx->buf;
-}
-
-#endif
-
-
-static ngx_int_t
-ngx_http_autoindex_error(ngx_http_request_t *r, ngx_dir_t *dir, u_char *name)
-{
-    if (ngx_close_dir(dir) == NGX_ERROR) {
-        ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
-                      ngx_close_dir_n " \"%s\" failed", name);
-    }
-
-    return NGX_HTTP_INTERNAL_SERVER_ERROR;
-}
-
-
-static ngx_int_t
-ngx_http_autoindex_init(ngx_cycle_t *cycle)
-{
-    ngx_http_handler_pt        *h;
-    ngx_http_core_main_conf_t  *cmcf;
-
-    cmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_core_module);
-
-    h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers);
-    if (h == NULL) {
-        return NGX_ERROR;
-    }
-
-    *h = ngx_http_autoindex_handler;
-
-    return NGX_OK;
-}
-
-
-static void *
-ngx_http_autoindex_create_loc_conf(ngx_conf_t *cf)
-{
-    ngx_http_autoindex_loc_conf_t  *conf;
-
-    conf = ngx_palloc(cf->pool, sizeof(ngx_http_autoindex_loc_conf_t));
-    if (conf == NULL) {
-        return NGX_CONF_ERROR;
-    }
-
-    conf->enable = NGX_CONF_UNSET;
-
-    return conf;
-}
-
-
-static char *
-ngx_http_autoindex_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
-{
-    ngx_http_autoindex_loc_conf_t *prev = parent;
-    ngx_http_autoindex_loc_conf_t *conf = child;
-
-    ngx_conf_merge_value(conf->enable, prev->enable, 0);
-
-    return NGX_CONF_OK;
-}
new file mode 100644
--- /dev/null
+++ b/src/http/modules/ngx_http_autoindex_module.c
@@ -0,0 +1,563 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+
+
+#if 0
+
+typedef struct {
+    ngx_buf_t     *buf;
+    size_t         size;
+    ngx_pool_t    *pool;
+    size_t         alloc_size;
+    ngx_chain_t  **last_out;
+} ngx_http_autoindex_ctx_t;
+
+#endif
+
+
+typedef struct {
+    ngx_str_t      name;
+    ngx_uint_t     escape;
+    ngx_uint_t     dir;
+    time_t         mtime;
+    off_t          size;
+} ngx_http_autoindex_entry_t;
+
+
+typedef struct {
+    ngx_flag_t     enable;
+} ngx_http_autoindex_loc_conf_t;
+
+
+#define NGX_HTTP_AUTOINDEX_NAME_LEN  50
+
+
+static int ngx_http_autoindex_cmp_entries(const void *one, const void *two);
+static ngx_int_t ngx_http_autoindex_error(ngx_http_request_t *r,
+    ngx_dir_t *dir, u_char *name);
+static ngx_int_t ngx_http_autoindex_init(ngx_cycle_t *cycle);
+static void *ngx_http_autoindex_create_loc_conf(ngx_conf_t *cf);
+static char *ngx_http_autoindex_merge_loc_conf(ngx_conf_t *cf,
+    void *parent, void *child);
+
+
+static ngx_command_t  ngx_http_autoindex_commands[] = {
+
+    { ngx_string("autoindex"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      ngx_conf_set_flag_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_autoindex_loc_conf_t, enable),
+      NULL },
+
+      ngx_null_command
+};
+
+
+ngx_http_module_t  ngx_http_autoindex_module_ctx = {
+    NULL,                                  /* pre conf */
+
+    NULL,                                  /* create main configuration */
+    NULL,                                  /* init main configuration */
+
+    NULL,                                  /* create server configuration */
+    NULL,                                  /* merge server configuration */
+
+    ngx_http_autoindex_create_loc_conf,    /* create location configration */
+    ngx_http_autoindex_merge_loc_conf      /* merge location configration */
+};
+
+
+ngx_module_t  ngx_http_autoindex_module = {
+    NGX_MODULE,
+    &ngx_http_autoindex_module_ctx,        /* module context */ 
+    ngx_http_autoindex_commands,           /* module directives */
+    NGX_HTTP_MODULE,                       /* module type */
+    ngx_http_autoindex_init,               /* init module */
+    NULL                                   /* init process */
+};
+
+
+static u_char title[] =
+"<html>" CRLF
+"<head><title>Index of "
+;
+
+
+static u_char header[] =
+"</title></head>" CRLF
+"<body bgcolor=\"white\">" CRLF
+"<h1>Index of "
+;
+
+static u_char tail[] =
+"</body>" CRLF
+"</html>" CRLF
+;
+
+
+static ngx_int_t
+ngx_http_autoindex_handler(ngx_http_request_t *r)
+{
+    u_char                         *last;
+    size_t                          len;
+    ngx_tm_t                        tm;
+    ngx_int_t                       rc;
+    ngx_uint_t                      i, level;
+    ngx_err_t                       err;
+    ngx_buf_t                      *b;
+    ngx_chain_t                     out;
+    ngx_str_t                       dname, fname;
+    ngx_dir_t                       dir;
+    ngx_pool_t                     *pool;
+    ngx_array_t                     entries;
+    ngx_http_core_loc_conf_t       *clcf;
+    ngx_http_autoindex_entry_t     *entry;
+    ngx_http_autoindex_loc_conf_t  *alcf;
+
+    static char  *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+                               "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+
+    if (r->uri.data[r->uri.len - 1] != '/') {
+        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) {
+        return NGX_DECLINED;
+    }
+
+    /* TODO: pool should be temporary pool */
+    pool = r->pool;
+
+    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+    if (clcf->alias) {
+        dname.data = ngx_palloc(pool, clcf->root.len + r->uri.len
+                                                     + NGX_DIR_MASK_LEN + 1
+                                                     - clcf->name.len);
+        if (dname.data == NULL) {
+            return NGX_HTTP_INTERNAL_SERVER_ERROR;
+        }
+    
+        last = ngx_cpymem(dname.data, clcf->root.data, clcf->root.len);
+        last = ngx_cpystrn(last, r->uri.data + clcf->name.len,
+                           r->uri.len - clcf->name.len + 1);
+
+    } else {
+        dname.data = ngx_palloc(pool, clcf->root.len + r->uri.len
+                                                     + NGX_DIR_MASK_LEN);
+        if (dname.data == NULL) {
+            return NGX_HTTP_INTERNAL_SERVER_ERROR;
+        }
+
+        last = ngx_cpymem(dname.data, clcf->root.data, clcf->root.len);
+        last = ngx_cpystrn(last, r->uri.data, r->uri.len);
+    }
+
+    dname.len = last - dname.data;
+
+    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                   "http autoindex: \"%s\"", dname.data);
+
+
+    if (ngx_open_dir(&dname, &dir) == NGX_ERROR) {
+        err = ngx_errno;
+
+        if (err == NGX_ENOENT || err == NGX_ENOTDIR) {
+            level = NGX_LOG_ERR;
+            rc = NGX_HTTP_NOT_FOUND;
+
+        } else if (err == NGX_EACCES) {
+            level = NGX_LOG_ERR;
+            rc = NGX_HTTP_FORBIDDEN;
+
+        } else {
+            level = NGX_LOG_CRIT;
+            rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
+        }
+
+        ngx_log_error(level, r->connection->log, err,
+                      ngx_open_dir_n " \"%s\" failed", dname.data);
+
+        return rc;
+    }
+
+#if (NGX_SUPPRESS_WARN)
+    /* MSVC thinks 'entries' may be used without having been initialized */
+    ngx_memzero(&entries, sizeof(ngx_array_t));
+#endif
+
+    if (ngx_array_init(&entries, pool, 50, sizeof(ngx_http_autoindex_entry_t))
+                                                                  == NGX_ERROR)
+    {
+        return ngx_http_autoindex_error(r, &dir, dname.data);
+    }
+
+    fname.len = 0;
+#if (NGX_SUPPRESS_WARN)
+    fname.data = NULL;
+#endif
+
+    for ( ;; ) {
+        ngx_set_errno(0);
+
+        if (ngx_read_dir(&dir) == NGX_ERROR) {
+            err = ngx_errno;
+
+            if (err != NGX_ENOMOREFILES) {
+                ngx_log_error(NGX_LOG_CRIT, r->connection->log, err,
+                              ngx_read_dir_n " \"%s\" failed", dname.data);
+                return ngx_http_autoindex_error(r, &dir, dname.data);
+            }
+
+            break; 
+        }
+
+        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                       "http autoindex file: \"%s\"", ngx_de_name(&dir));
+
+        len = ngx_de_namelen(&dir);
+
+        if (len == 1 && ngx_de_name(&dir)[0] == '.') {
+            continue;
+        }
+
+        if (len == 2
+            && ngx_de_name(&dir)[0] == '.'
+            && ngx_de_name(&dir)[1] == '.')
+        {
+            continue;
+        }
+
+        if (!dir.valid_info) {
+
+            if (dname.len + 1 + len > fname.len) {
+                fname.len = dname.len + 1 + len + 32;
+
+                fname.data = ngx_palloc(pool, fname.len);
+                if (fname.data == NULL) {
+                    return ngx_http_autoindex_error(r, &dir, dname.data);
+                }
+
+                last = ngx_cpystrn(fname.data, dname.data,
+                                   dname.len + 1);
+                *last++ = '/';
+            }
+
+            ngx_cpystrn(last, ngx_de_name(&dir), len + 1);
+
+            if (ngx_de_info(fname.data, &dir) == NGX_FILE_ERROR) {
+                err = ngx_errno;
+
+                if (err != NGX_ENOENT) {
+                    ngx_log_error(NGX_LOG_CRIT, r->connection->log, err,
+                                  ngx_de_info_n " \"%s\" failed", fname.data);
+                    return ngx_http_autoindex_error(r, &dir, dname.data);
+                }
+
+                if (ngx_de_link_info(fname.data, &dir) == NGX_FILE_ERROR) {
+                    ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
+                                  ngx_de_link_info_n " \"%s\" failed",
+                                  fname.data);
+                    return ngx_http_autoindex_error(r, &dir, dname.data);
+                }
+            }
+        }
+
+        entry = ngx_array_push(&entries);
+        if (entry == NULL) {
+            return ngx_http_autoindex_error(r, &dir, dname.data);
+        }
+
+        entry->name.len = len;        
+        entry->escape = 2 * ngx_escape_uri(NULL, ngx_de_name(&dir), len,
+                                           NGX_ESCAPE_HTML);
+
+        entry->name.data = ngx_palloc(pool, len + entry->escape + 1);
+        if (entry->name.data == NULL) {
+            return ngx_http_autoindex_error(r, &dir, dname.data);
+        }
+
+        ngx_cpystrn(entry->name.data, ngx_de_name(&dir), len + 1);
+
+        entry->dir = ngx_de_is_dir(&dir);
+        entry->mtime = ngx_de_mtime(&dir);
+        entry->size = ngx_de_size(&dir);
+    }
+
+    if (ngx_close_dir(&dir) == NGX_ERROR) {
+        ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
+                      ngx_close_dir_n " \"%s\" failed", dname.data);
+    }
+
+    len = sizeof(title) - 1
+          + r->uri.len
+          + sizeof(header) - 1
+          + r->uri.len
+          + sizeof("</h1>") - 1
+          + sizeof("<hr><pre><a href=\"../\">../</a>" CRLF) - 1
+          + sizeof("</pre><hr>") - 1
+          + sizeof(tail) - 1;
+
+    entry = entries.elts;
+    for (i = 0; i < entries.nelts; i++) {
+        len += sizeof("<a href=\"") - 1
+               + 1                                          /* 1 is for "/" */
+               + entry[i].name.len + entry[i].escape
+               + sizeof("\">") - 1
+               + NGX_HTTP_AUTOINDEX_NAME_LEN + sizeof("&gt;") - 2
+               + sizeof("</a>") - 1
+               + sizeof(" 28-Sep-1970 12:00 ") - 1
+               + 19
+               + 2;
+    }
+
+    b = ngx_create_temp_buf(r->pool, len);
+    if (b == NULL) {
+        return NGX_HTTP_INTERNAL_SERVER_ERROR;
+    }
+
+    if (entries.nelts > 1) {
+        ngx_qsort(entry, (size_t) entries.nelts,
+                  sizeof(ngx_http_autoindex_entry_t),
+                  ngx_http_autoindex_cmp_entries);
+    }
+
+    b->last = ngx_cpymem(b->last, title, sizeof(title) - 1);
+    b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len);
+    b->last = ngx_cpymem(b->last, header, sizeof(header) - 1);
+    b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len);
+    b->last = ngx_cpymem(b->last, "</h1>", sizeof("</h1>") - 1);
+
+    b->last = ngx_cpymem(b->last, "<hr><pre><a href=\"../\">../</a>" CRLF,
+                         sizeof("<hr><pre><a href=\"../\">../</a>" CRLF) - 1);
+
+    for (i = 0; i < entries.nelts; i++) {
+        b->last = ngx_cpymem(b->last, "<a href=\"", sizeof("<a href=\"") - 1);
+
+        if (entry[i].escape) {
+            ngx_escape_uri(b->last, entry[i].name.data, entry[i].name.len,
+                           NGX_ESCAPE_HTML);
+
+            b->last += entry[i].name.len + entry[i].escape;
+
+        } else {
+            b->last = ngx_cpymem(b->last, entry[i].name.data,
+                                 entry[i].name.len);
+        }
+
+        if (entry[i].dir) {
+            *b->last++ = '/';
+        }
+
+        *b->last++ = '"';
+        *b->last++ = '>';
+
+        b->last = ngx_cpystrn(b->last, entry[i].name.data,
+                              NGX_HTTP_AUTOINDEX_NAME_LEN + 1);
+
+        len = entry[i].name.len;
+
+        if (len > NGX_HTTP_AUTOINDEX_NAME_LEN) {
+            b->last = ngx_cpymem(b->last - 3, "..&gt;</a>",
+                                 sizeof("..&gt;</a>") - 1);
+
+        } else {
+            if (entry[i].dir && NGX_HTTP_AUTOINDEX_NAME_LEN - len > 0) {
+                *b->last++ = '/';
+                len++;
+            }
+
+            b->last = ngx_cpymem(b->last, "</a>", sizeof("</a>") - 1);
+            ngx_memset(b->last, ' ', NGX_HTTP_AUTOINDEX_NAME_LEN - len);
+            b->last += NGX_HTTP_AUTOINDEX_NAME_LEN - len;
+        }
+
+        *b->last++ = ' ';
+
+        ngx_gmtime(entry[i].mtime, &tm);
+
+        b->last = ngx_sprintf(b->last, "%02d-%s-%d %02d:%02d ",
+                              tm.ngx_tm_mday,
+                              months[tm.ngx_tm_mon - 1],
+                              tm.ngx_tm_year,
+                              tm.ngx_tm_hour,
+                              tm.ngx_tm_min);
+
+        if (entry[i].dir) {
+            b->last = ngx_cpymem(b->last,  "                  -",
+                                 sizeof("                  -") - 1);
+
+        } else {
+            b->last = ngx_sprintf(b->last, "%19O", entry[i].size);
+        }
+
+        *b->last++ = CR;
+        *b->last++ = LF;
+    }
+
+    /* TODO: free temporary pool */
+
+    b->last = ngx_cpymem(b->last, "</pre><hr>", sizeof("</pre><hr>") - 1);
+
+    b->last = ngx_cpymem(b->last, tail, sizeof(tail) - 1);
+
+    r->headers_out.status = NGX_HTTP_OK;
+    r->headers_out.content_length_n = b->last - b->pos;
+
+    r->headers_out.content_type = ngx_list_push(&r->headers_out.headers);
+    if (r->headers_out.content_type == NULL) {
+        return NGX_HTTP_INTERNAL_SERVER_ERROR;
+    }
+
+    r->headers_out.content_type->key.len = 0;
+    r->headers_out.content_type->key.data = NULL;
+    r->headers_out.content_type->value.len = sizeof("text/html") - 1;
+    r->headers_out.content_type->value.data = (u_char *) "text/html";
+
+    rc = ngx_http_send_header(r);
+
+    if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
+        return rc;
+    }
+
+    if (!r->main) {
+        b->last_buf = 1;
+    }
+
+    out.buf = b;
+    out.next = NULL;
+
+    return ngx_http_output_filter(r, &out);
+}
+
+
+static int
+ngx_http_autoindex_cmp_entries(const void *one, const void *two)
+{
+    ngx_http_autoindex_entry_t *first = (ngx_http_autoindex_entry_t *) one;
+    ngx_http_autoindex_entry_t *second = (ngx_http_autoindex_entry_t *) two;
+
+    if (first->dir && !second->dir) {
+        /* move the directories to the start */
+        return -1;
+    }
+
+    if (!first->dir && second->dir) {
+        /* move the directories to the start */
+        return 1;
+    }
+
+    return (int) ngx_strcmp(first->name.data, second->name.data);
+}
+
+
+#if 0
+
+static ngx_buf_t *
+ngx_http_autoindex_alloc(ngx_http_autoindex_ctx_t *ctx, size_t size)
+{
+    ngx_chain_t  *cl;
+
+    if (ctx->buf) {
+
+        if ((size_t) (ctx->buf->end - ctx->buf->last) >= size) {
+            return ctx->buf;
+        }
+
+        ctx->size += ctx->buf->last - ctx->buf->pos;
+    }
+
+    ctx->buf = ngx_create_temp_buf(ctx->pool, ctx->alloc_size);
+    if (ctx->buf == NULL) {
+        return NULL;
+    }
+
+    cl = ngx_alloc_chain_link(ctx->pool);
+    if (cl == NULL) {
+        return NULL;
+    }
+
+    cl->buf = ctx->buf;
+    cl->next = NULL;
+
+    *ctx->last_out = cl;
+    ctx->last_out = &cl->next;
+
+    return ctx->buf;
+}
+
+#endif
+
+
+static ngx_int_t
+ngx_http_autoindex_error(ngx_http_request_t *r, ngx_dir_t *dir, u_char *name)
+{
+    if (ngx_close_dir(dir) == NGX_ERROR) {
+        ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
+                      ngx_close_dir_n " \"%s\" failed", name);
+    }
+
+    return NGX_HTTP_INTERNAL_SERVER_ERROR;
+}
+
+
+static ngx_int_t
+ngx_http_autoindex_init(ngx_cycle_t *cycle)
+{
+    ngx_http_handler_pt        *h;
+    ngx_http_core_main_conf_t  *cmcf;
+
+    cmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_core_module);
+
+    h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers);
+    if (h == NULL) {
+        return NGX_ERROR;
+    }
+
+    *h = ngx_http_autoindex_handler;
+
+    return NGX_OK;
+}
+
+
+static void *
+ngx_http_autoindex_create_loc_conf(ngx_conf_t *cf)
+{
+    ngx_http_autoindex_loc_conf_t  *conf;
+
+    conf = ngx_palloc(cf->pool, sizeof(ngx_http_autoindex_loc_conf_t));
+    if (conf == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    conf->enable = NGX_CONF_UNSET;
+
+    return conf;
+}
+
+
+static char *
+ngx_http_autoindex_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
+{
+    ngx_http_autoindex_loc_conf_t *prev = parent;
+    ngx_http_autoindex_loc_conf_t *conf = child;
+
+    ngx_conf_merge_value(conf->enable, prev->enable, 0);
+
+    return NGX_CONF_OK;
+}
deleted file mode 100644
--- a/src/http/modules/ngx_http_charset_filter.c
+++ /dev/null
@@ -1,588 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-typedef struct {
-    char       **tables;
-    ngx_str_t    name;
-    ngx_uint_t   server;  /* unsigned     server:1; */
-} ngx_http_charset_t;
-
-
-typedef struct {
-    ngx_int_t   src;
-    ngx_int_t   dst;
-    char       *src2dst;
-    char       *dst2src;
-} ngx_http_charset_tables_t;
-
-
-typedef struct {
-    ngx_array_t  charsets;               /* ngx_http_charset_t */
-    ngx_array_t  tables;                 /* ngx_http_charset_tables_t */
-} ngx_http_charset_main_conf_t;
-
-
-typedef struct {
-    ngx_flag_t  enable;
-    ngx_flag_t  autodetect;
-
-    ngx_int_t   default_charset;
-    ngx_int_t   source_charset;
-} ngx_http_charset_loc_conf_t;
-
-
-typedef struct {
-    ngx_int_t   server;
-    ngx_int_t   client;
-} ngx_http_charset_ctx_t;
-
-
-static ngx_uint_t ngx_charset_recode(ngx_buf_t *b, char *table);
-
-static char *ngx_charset_map_block(ngx_conf_t *cf, ngx_command_t *cmd,
-                                   void *conf);
-static char *ngx_charset_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf);
-
-static char *ngx_http_set_charset_slot(ngx_conf_t *cf, ngx_command_t *cmd,
-                                       void *conf);
-static ngx_int_t ngx_http_add_charset(ngx_array_t *charsets, ngx_str_t *name);
-
-static ngx_int_t ngx_http_charset_filter_init(ngx_cycle_t *cycle);
-
-static void *ngx_http_charset_create_main_conf(ngx_conf_t *cf);
-static char *ngx_http_charset_init_main_conf(ngx_conf_t *cf, void *conf);
-static void *ngx_http_charset_create_loc_conf(ngx_conf_t *cf);
-static char *ngx_http_charset_merge_loc_conf(ngx_conf_t *cf,
-                                             void *parent, void *child);
-
-
-static ngx_command_t  ngx_http_charset_filter_commands[] = {
-
-    { ngx_string("charset_map"),
-      NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE2,
-      ngx_charset_map_block,
-      NGX_HTTP_MAIN_CONF_OFFSET,
-      0,
-      NULL },
-
-    { ngx_string("default_charset"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
-      ngx_http_set_charset_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_charset_loc_conf_t, default_charset),
-      NULL },
-
-    { ngx_string("source_charset"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
-      ngx_http_set_charset_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_charset_loc_conf_t, source_charset),
-      NULL },
-
-    { ngx_string("charset"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
-      ngx_conf_set_flag_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_charset_loc_conf_t, enable),
-      NULL },
-
-    { ngx_string("autodetect_charset"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
-      ngx_conf_set_flag_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_charset_loc_conf_t, autodetect),
-      NULL },
-
-      ngx_null_command
-};
-
-
-static ngx_http_module_t  ngx_http_charset_filter_module_ctx = {
-    NULL,                                  /* pre conf */
-
-    ngx_http_charset_create_main_conf,     /* create main configuration */
-    ngx_http_charset_init_main_conf,       /* init main configuration */
-
-    NULL,                                  /* create server configuration */
-    NULL,                                  /* merge server configuration */
-
-    ngx_http_charset_create_loc_conf,      /* create location configuration */
-    ngx_http_charset_merge_loc_conf        /* merge location configuration */
-};
-
-
-ngx_module_t  ngx_http_charset_filter_module = {
-    NGX_MODULE,
-    &ngx_http_charset_filter_module_ctx,   /* module context */
-    ngx_http_charset_filter_commands,      /* module directives */
-    NGX_HTTP_MODULE,                       /* module type */
-    ngx_http_charset_filter_init,          /* init module */
-    NULL                                   /* init process */
-};
-
-
-static ngx_http_output_header_filter_pt  ngx_http_next_header_filter;
-static ngx_http_output_body_filter_pt    ngx_http_next_body_filter;
-
-
-static ngx_int_t ngx_http_charset_header_filter(ngx_http_request_t *r)
-{
-    ngx_http_charset_t            *charsets;
-    ngx_http_charset_ctx_t        *ctx;
-    ngx_http_charset_loc_conf_t   *lcf;
-    ngx_http_charset_main_conf_t  *mcf;
-
-    mcf = ngx_http_get_module_main_conf(r, ngx_http_charset_filter_module);
-    lcf = ngx_http_get_module_loc_conf(r, ngx_http_charset_filter_module);
-
-    if (lcf->enable == 0) {
-        return ngx_http_next_header_filter(r);
-    }
-
-    if (r->headers_out.content_type == NULL) {
-        return ngx_http_next_header_filter(r);
-    }
-
-    if (ngx_strncasecmp(r->headers_out.content_type->value.data,
-                                                              "text/", 5) != 0
-        && ngx_strncasecmp(r->headers_out.content_type->value.data,
-                                          "application/x-javascript", 24) != 0)
-    {
-        return ngx_http_next_header_filter(r);
-    }
-
-    if (ngx_strstr(r->headers_out.content_type->value.data, "charset") != NULL)
-    {
-        return ngx_http_next_header_filter(r);
-    }
-
-    if (r->headers_out.status == NGX_HTTP_MOVED_PERMANENTLY
-        && r->headers_out.status == NGX_HTTP_MOVED_TEMPORARILY)
-    {
-        /*
-         * do not set charset for the redirect because NN 4.x uses this
-         * charset instead of the next page charset
-         */
-
-        r->headers_out.charset.len = 0;
-        return ngx_http_next_header_filter(r);
-    }
-
-    if (r->headers_out.charset.len) {
-        return ngx_http_next_header_filter(r);
-    }
-
-    charsets = mcf->charsets.elts;
-    r->headers_out.charset = charsets[lcf->default_charset].name;
-
-    if (lcf->default_charset == lcf->source_charset) {
-        return ngx_http_next_header_filter(r);
-    }
-
-    ngx_http_create_ctx(r, ctx, ngx_http_charset_filter_module,
-                        sizeof(ngx_http_charset_ctx_t), NGX_ERROR);
-
-    r->filter_need_in_memory = 1;
-
-    return ngx_http_next_header_filter(r);
-}
-
-
-static ngx_int_t ngx_http_charset_body_filter(ngx_http_request_t *r,
-                                              ngx_chain_t *in)
-{
-    char                          *table;
-    ngx_chain_t                   *cl;
-    ngx_http_charset_t            *charsets;
-    ngx_http_charset_ctx_t        *ctx;
-    ngx_http_charset_loc_conf_t   *lcf;
-    ngx_http_charset_main_conf_t  *mcf;
-
-    ctx = ngx_http_get_module_ctx(r, ngx_http_charset_filter_module);
-
-    if (ctx == NULL) {
-        return ngx_http_next_body_filter(r, in);
-    }
-
-    mcf = ngx_http_get_module_main_conf(r, ngx_http_charset_filter_module);
-    lcf = ngx_http_get_module_loc_conf(r, ngx_http_charset_filter_module);
-
-    charsets = mcf->charsets.elts;
-    table = charsets[lcf->source_charset].tables[lcf->default_charset];
-
-    for (cl = in; cl; cl = cl->next) {
-        ngx_charset_recode(cl->buf, table);
-    }
-
-    return ngx_http_next_body_filter(r, in);
-}
-
-
-static ngx_uint_t ngx_charset_recode(ngx_buf_t *b, char *table)
-{
-    u_char      *p;
-    ngx_uint_t   change;
-
-    change = 0;
-
-    for (p = b->pos; p < b->last; p++) {
-        if (*p != table[*p]) {
-            change = 1;
-            break;
-        }
-    }
-
-    if (change) {
-
-        while (p < b->last) {
-            *p = table[*p];
-            p++;
-        }
-
-        b->in_file = 0;
-    }
-
-    return change;
-}
-
-
-static char *ngx_charset_map_block(ngx_conf_t *cf, ngx_command_t *cmd,
-                                   void *conf)
-{
-    ngx_http_charset_main_conf_t  *mcf = conf;
-
-    char                       *rv;
-    ngx_int_t                   src, dst;
-    ngx_uint_t                  i;
-    ngx_str_t                  *value;
-    ngx_conf_t                  pvcf;
-    ngx_http_charset_tables_t  *table;
-
-    value = cf->args->elts;
-
-    src = ngx_http_add_charset(&mcf->charsets, &value[1]);
-    if (src == NGX_ERROR) {
-        return NGX_CONF_ERROR;
-    }
-
-    dst = ngx_http_add_charset(&mcf->charsets, &value[2]);
-    if (dst == NGX_ERROR) {
-        return NGX_CONF_ERROR;
-    }
-
-    if (src == dst) {
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                           "\"charset_map\" between the same charsets "
-                           "\"%V\" and \"%V\"", &value[1], &value[2]);
-        return NGX_CONF_ERROR;
-    }
-
-    table = mcf->tables.elts;
-    for (i = 0; i < mcf->tables.nelts; i++) {
-        if ((src == table->src && dst == table->dst)
-             || (src == table->dst && dst == table->src))
-        {
-            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                               "duplicate \"charset_map\" between "
-                               "\"%V\" and \"%V\"", &value[1], &value[2]);
-            return NGX_CONF_ERROR;
-        }
-    }
-
-    if (!(table = ngx_push_array(&mcf->tables))) {
-        return NGX_CONF_ERROR;
-    }
-
-    table->src = src;
-    table->dst = dst;
-
-    if (!(table->src2dst = ngx_palloc(cf->pool, 256))) {
-        return NGX_CONF_ERROR;
-    }
-
-    if (!(table->dst2src = ngx_palloc(cf->pool, 256))) {
-        return NGX_CONF_ERROR;
-    }
-
-    for (i = 0; i < 128; i++) {
-        table->src2dst[i] = (char) i;
-        table->dst2src[i] = (char) i;
-    }
-
-    for (/* void */; i < 256; i++) {
-        table->src2dst[i] = '?';
-        table->dst2src[i] = '?';
-    }
-
-    pvcf = *cf;
-    cf->ctx = table;
-    cf->handler = ngx_charset_map;
-    cf->handler_conf = conf;
-    rv = ngx_conf_parse(cf, NULL);
-    *cf = pvcf;
-
-    return rv;
-}
-
-
-static char *ngx_charset_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
-{
-    ngx_int_t                   src, dst;
-    ngx_str_t                  *value;
-    ngx_http_charset_tables_t  *table;
-
-    if (cf->args->nelts != 2) {
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameters number");
-        return NGX_CONF_ERROR;
-    }
-
-    value = cf->args->elts;
-
-    src = ngx_hextoi(value[0].data, value[0].len);
-    if (src == NGX_ERROR || src > 255) {
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                           "invalid value \"%V\"", &value[0]);
-        return NGX_CONF_ERROR;
-    }
-
-    dst = ngx_hextoi(value[1].data, value[1].len);
-    if (dst == NGX_ERROR || dst > 255) {
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                           "invalid value \"%V\"", &value[1]);
-        return NGX_CONF_ERROR;
-    }
-
-    table = cf->ctx;
-
-    table->src2dst[src] = (char) dst;
-    table->dst2src[dst] = (char) src;
-
-    return NGX_CONF_OK;
-}
-
-
-static char *ngx_http_set_charset_slot(ngx_conf_t *cf, ngx_command_t *cmd,
-                                       void *conf)
-{
-    char  *p = conf;
-
-    ngx_int_t                     *cp;
-    ngx_str_t                     *value;
-    ngx_http_charset_t            *charset;
-    ngx_http_charset_main_conf_t  *mcf;
-
-    cp = (ngx_int_t *) (p + cmd->offset);
-
-    if (*cp != NGX_CONF_UNSET) {
-        return "is duplicate";
-    }
-
-    mcf = ngx_http_conf_get_module_main_conf(cf,
-                                             ngx_http_charset_filter_module);
-
-    value = cf->args->elts;
-
-    *cp = ngx_http_add_charset(&mcf->charsets, &value[1]);
-    if (*cp == NGX_ERROR) {
-        return NGX_CONF_ERROR;
-    }
-
-    if (cmd->offset == offsetof(ngx_http_charset_loc_conf_t, source_charset)) {
-        charset = mcf->charsets.elts;
-        charset[*cp].server = 1;
-    }
-
-    return NGX_CONF_OK;
-}
-
-
-static ngx_int_t ngx_http_add_charset(ngx_array_t *charsets, ngx_str_t *name)
-{
-    ngx_uint_t           i;
-    ngx_http_charset_t  *c;
-
-    c = charsets->elts;
-    for (i = 0; i < charsets->nelts; i++) {
-        if (name->len != c[i].name.len) {
-            continue;
-        }
-
-        if (ngx_strcasecmp(name->data, c[i].name.data) == 0) {
-            break;
-        }
-    }
-
-    if (i < charsets->nelts) {
-        return i;
-    }
-
-    if (!(c = ngx_push_array(charsets))) {
-        return NGX_ERROR;
-    }
-
-    c->tables = NULL;
-    c->name = *name;
-    c->server = 0;
-
-    return i;
-}
-
-
-static ngx_int_t ngx_http_charset_filter_init(ngx_cycle_t *cycle)
-{
-    ngx_http_next_header_filter = ngx_http_top_header_filter;
-    ngx_http_top_header_filter = ngx_http_charset_header_filter;
-
-    ngx_http_next_body_filter = ngx_http_top_body_filter;
-    ngx_http_top_body_filter = ngx_http_charset_body_filter;
-
-    return NGX_OK;
-}
-
-
-static void *ngx_http_charset_create_main_conf(ngx_conf_t *cf)
-{
-    ngx_http_charset_main_conf_t  *mcf;
-
-    if (!(mcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_charset_main_conf_t)))) {
-        return NGX_CONF_ERROR;
-    }
-
-    ngx_init_array(mcf->charsets, cf->pool, 2, sizeof(ngx_http_charset_t),
-                   NGX_CONF_ERROR);
-
-    ngx_init_array(mcf->tables, cf->pool, 4, sizeof(ngx_http_charset_tables_t),
-                   NGX_CONF_ERROR);
-
-    return mcf;
-}
-
-
-static char *ngx_http_charset_init_main_conf(ngx_conf_t *cf, void *conf)
-{
-    ngx_http_charset_main_conf_t *mcf = conf;
-
-    ngx_uint_t                  i, n;
-    ngx_http_charset_t         *charset;
-    ngx_http_charset_tables_t  *tables;
-
-    tables = mcf->tables.elts;
-    charset = mcf->charsets.elts;
-
-    for (i = 0; i < mcf->charsets.nelts; i++) {
-        if (!charset[i].server) {
-            continue;
-        }
-
-        charset[i].tables = ngx_pcalloc(cf->pool,
-                                        sizeof(char *) * mcf->charsets.nelts);
-
-        if (charset[i].tables == NULL) {
-            return NGX_CONF_ERROR;
-        }
-
-        for (n = 0; n < mcf->tables.nelts; n++) {
-            if ((ngx_int_t) i == tables[n].src) {
-                charset[i].tables[tables[n].dst] = tables[n].src2dst;
-                continue;
-            }
-
-            if ((ngx_int_t) i == tables[n].dst) {
-                charset[i].tables[tables[n].src] = tables[n].dst2src;
-            }
-        }
-    }
-
-    for (i = 0; i < mcf->charsets.nelts; i++) {
-        if (!charset[i].server) {
-            continue;
-        }
-
-        for (n = 0; n < mcf->charsets.nelts; n++) {
-            if (i == n) {
-                continue;
-            }
-
-            if (charset[i].tables[n]) {
-                continue;
-            }
-
-            ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
-                          " no \"charset_map\" between the charsets "
-                          "\"%V\" and \"%V\"",
-                          &charset[i].name, &charset[n].name);
-            return NGX_CONF_ERROR;
-        }
-    }
-
-    return NGX_CONF_OK;
-}
-
-
-static void *ngx_http_charset_create_loc_conf(ngx_conf_t *cf)
-{
-    ngx_http_charset_loc_conf_t  *lcf;
-
-    if (!(lcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_charset_loc_conf_t)))) {
-        return NGX_CONF_ERROR;
-    }
-
-    lcf->enable = NGX_CONF_UNSET;
-    lcf->autodetect = NGX_CONF_UNSET;
-    lcf->default_charset = NGX_CONF_UNSET;
-    lcf->source_charset = NGX_CONF_UNSET;
-
-    return lcf;
-}
-
-
-static char *ngx_http_charset_merge_loc_conf(ngx_conf_t *cf,
-                                             void *parent, void *child)
-{
-    ngx_http_charset_loc_conf_t *prev = parent;
-    ngx_http_charset_loc_conf_t *conf = child;
-
-    ngx_conf_merge_value(conf->enable, prev->enable, 0);
-    ngx_conf_merge_value(conf->autodetect, prev->autodetect, 0);
-
-
-    if (conf->default_charset == NGX_CONF_UNSET) {
-        conf->default_charset = prev->default_charset;
-    }
-
-    if (conf->source_charset == NGX_CONF_UNSET) {
-        conf->source_charset = prev->source_charset;
-    }
-
-    if (conf->default_charset == NGX_CONF_UNSET
-        && conf->source_charset != NGX_CONF_UNSET)
-    {
-        conf->default_charset = conf->source_charset;
-    }
-
-    if (conf->source_charset == NGX_CONF_UNSET
-        && conf->default_charset != NGX_CONF_UNSET)
-    {
-        conf->source_charset = conf->default_charset;
-    }
-
-    if (conf->enable
-        && (conf->default_charset == NGX_CONF_UNSET
-            || conf->source_charset == NGX_CONF_UNSET))
-    {
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                           "the \"source_charset\" or \"default_charset\" "
-                           "must be specified when \"charset\" is on");
-        return NGX_CONF_ERROR;
-    }
-
-    return NGX_CONF_OK;
-}
new file mode 100644
--- /dev/null
+++ b/src/http/modules/ngx_http_charset_filter_module.c
@@ -0,0 +1,615 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+
+
+typedef struct {
+    char       **tables;
+    ngx_str_t    name;
+    ngx_uint_t   server;  /* unsigned     server:1; */
+} ngx_http_charset_t;
+
+
+typedef struct {
+    ngx_int_t   src;
+    ngx_int_t   dst;
+    char       *src2dst;
+    char       *dst2src;
+} ngx_http_charset_tables_t;
+
+
+typedef struct {
+    ngx_array_t  charsets;               /* ngx_http_charset_t */
+    ngx_array_t  tables;                 /* ngx_http_charset_tables_t */
+} ngx_http_charset_main_conf_t;
+
+
+typedef struct {
+    ngx_flag_t  enable;
+    ngx_flag_t  autodetect;
+
+    ngx_int_t   default_charset;
+    ngx_int_t   source_charset;
+} ngx_http_charset_loc_conf_t;
+
+
+typedef struct {
+    ngx_int_t   server;
+    ngx_int_t   client;
+} ngx_http_charset_ctx_t;
+
+
+static ngx_uint_t ngx_charset_recode(ngx_buf_t *b, char *table);
+
+static char *ngx_charset_map_block(ngx_conf_t *cf, ngx_command_t *cmd,
+    void *conf);
+static char *ngx_charset_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf);
+
+static char *ngx_http_set_charset_slot(ngx_conf_t *cf, ngx_command_t *cmd,
+    void *conf);
+static ngx_int_t ngx_http_add_charset(ngx_array_t *charsets, ngx_str_t *name);
+
+static ngx_int_t ngx_http_charset_filter_init(ngx_cycle_t *cycle);
+
+static void *ngx_http_charset_create_main_conf(ngx_conf_t *cf);
+static char *ngx_http_charset_init_main_conf(ngx_conf_t *cf, void *conf);
+static void *ngx_http_charset_create_loc_conf(ngx_conf_t *cf);
+static char *ngx_http_charset_merge_loc_conf(ngx_conf_t *cf,
+    void *parent, void *child);
+
+
+static ngx_command_t  ngx_http_charset_filter_commands[] = {
+
+    { ngx_string("charset_map"),
+      NGX_HTTP_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE2,
+      ngx_charset_map_block,
+      NGX_HTTP_MAIN_CONF_OFFSET,
+      0,
+      NULL },
+
+    { ngx_string("default_charset"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_http_set_charset_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_charset_loc_conf_t, default_charset),
+      NULL },
+
+    { ngx_string("source_charset"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_http_set_charset_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_charset_loc_conf_t, source_charset),
+      NULL },
+
+    { ngx_string("charset"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      ngx_conf_set_flag_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_charset_loc_conf_t, enable),
+      NULL },
+
+    { ngx_string("autodetect_charset"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      ngx_conf_set_flag_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_charset_loc_conf_t, autodetect),
+      NULL },
+
+      ngx_null_command
+};
+
+
+static ngx_http_module_t  ngx_http_charset_filter_module_ctx = {
+    NULL,                                  /* pre conf */
+
+    ngx_http_charset_create_main_conf,     /* create main configuration */
+    ngx_http_charset_init_main_conf,       /* init main configuration */
+
+    NULL,                                  /* create server configuration */
+    NULL,                                  /* merge server configuration */
+
+    ngx_http_charset_create_loc_conf,      /* create location configuration */
+    ngx_http_charset_merge_loc_conf        /* merge location configuration */
+};
+
+
+ngx_module_t  ngx_http_charset_filter_module = {
+    NGX_MODULE,
+    &ngx_http_charset_filter_module_ctx,   /* module context */
+    ngx_http_charset_filter_commands,      /* module directives */
+    NGX_HTTP_MODULE,                       /* module type */
+    ngx_http_charset_filter_init,          /* init module */
+    NULL                                   /* init process */
+};
+
+
+static ngx_http_output_header_filter_pt  ngx_http_next_header_filter;
+static ngx_http_output_body_filter_pt    ngx_http_next_body_filter;
+
+
+static ngx_int_t
+ngx_http_charset_header_filter(ngx_http_request_t *r)
+{
+    ngx_http_charset_t            *charsets;
+    ngx_http_charset_ctx_t        *ctx;
+    ngx_http_charset_loc_conf_t   *lcf;
+    ngx_http_charset_main_conf_t  *mcf;
+
+    mcf = ngx_http_get_module_main_conf(r, ngx_http_charset_filter_module);
+    lcf = ngx_http_get_module_loc_conf(r, ngx_http_charset_filter_module);
+
+    if (lcf->enable == 0) {
+        return ngx_http_next_header_filter(r);
+    }
+
+    if (r->headers_out.content_type == NULL) {
+        return ngx_http_next_header_filter(r);
+    }
+
+    if (ngx_strncasecmp(r->headers_out.content_type->value.data,
+                                                              "text/", 5) != 0
+        && ngx_strncasecmp(r->headers_out.content_type->value.data,
+                                          "application/x-javascript", 24) != 0)
+    {
+        return ngx_http_next_header_filter(r);
+    }
+
+    if (ngx_strstr(r->headers_out.content_type->value.data, "charset") != NULL)
+    {
+        return ngx_http_next_header_filter(r);
+    }
+
+    if (r->headers_out.status == NGX_HTTP_MOVED_PERMANENTLY
+        || r->headers_out.status == NGX_HTTP_MOVED_TEMPORARILY)
+    {
+        /*
+         * do not set charset for the redirect because NN 4.x uses this
+         * charset instead of the next page charset
+         */
+
+        r->headers_out.charset.len = 0;
+        return ngx_http_next_header_filter(r);
+    }
+
+    if (r->headers_out.charset.len) {
+        return ngx_http_next_header_filter(r);
+    }
+
+    charsets = mcf->charsets.elts;
+    r->headers_out.charset = charsets[lcf->default_charset].name;
+
+    if (lcf->default_charset == lcf->source_charset) {
+        return ngx_http_next_header_filter(r);
+    }
+
+
+    ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_charset_ctx_t));
+    if (ctx == NULL) {
+        return NGX_ERROR;
+    }
+
+    ngx_http_set_ctx(r, ctx, ngx_http_charset_filter_module);
+
+
+    r->filter_need_in_memory = 1;
+
+    return ngx_http_next_header_filter(r);
+}
+
+
+static ngx_int_t
+ngx_http_charset_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
+{
+    char                          *table;
+    ngx_chain_t                   *cl;
+    ngx_http_charset_t            *charsets;
+    ngx_http_charset_ctx_t        *ctx;
+    ngx_http_charset_loc_conf_t   *lcf;
+    ngx_http_charset_main_conf_t  *mcf;
+
+    ctx = ngx_http_get_module_ctx(r, ngx_http_charset_filter_module);
+
+    if (ctx == NULL) {
+        return ngx_http_next_body_filter(r, in);
+    }
+
+    mcf = ngx_http_get_module_main_conf(r, ngx_http_charset_filter_module);
+    lcf = ngx_http_get_module_loc_conf(r, ngx_http_charset_filter_module);
+
+    charsets = mcf->charsets.elts;
+    table = charsets[lcf->source_charset].tables[lcf->default_charset];
+
+    for (cl = in; cl; cl = cl->next) {
+        ngx_charset_recode(cl->buf, table);
+    }
+
+    return ngx_http_next_body_filter(r, in);
+}
+
+
+static ngx_uint_t
+ngx_charset_recode(ngx_buf_t *b, char *table)
+{
+    u_char      *p;
+    ngx_uint_t   change;
+
+    change = 0;
+
+    for (p = b->pos; p < b->last; p++) {
+        if (*p != table[*p]) {
+            change = 1;
+            break;
+        }
+    }
+
+    if (change) {
+
+        while (p < b->last) {
+            *p = table[*p];
+            p++;
+        }
+
+        b->in_file = 0;
+    }
+
+    return change;
+}
+
+
+static char *
+ngx_charset_map_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+    ngx_http_charset_main_conf_t  *mcf = conf;
+
+    char                       *rv;
+    ngx_int_t                   src, dst;
+    ngx_uint_t                  i;
+    ngx_str_t                  *value;
+    ngx_conf_t                  pvcf;
+    ngx_http_charset_tables_t  *table;
+
+    value = cf->args->elts;
+
+    src = ngx_http_add_charset(&mcf->charsets, &value[1]);
+    if (src == NGX_ERROR) {
+        return NGX_CONF_ERROR;
+    }
+
+    dst = ngx_http_add_charset(&mcf->charsets, &value[2]);
+    if (dst == NGX_ERROR) {
+        return NGX_CONF_ERROR;
+    }
+
+    if (src == dst) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                           "\"charset_map\" between the same charsets "
+                           "\"%V\" and \"%V\"", &value[1], &value[2]);
+        return NGX_CONF_ERROR;
+    }
+
+    table = mcf->tables.elts;
+    for (i = 0; i < mcf->tables.nelts; i++) {
+        if ((src == table->src && dst == table->dst)
+             || (src == table->dst && dst == table->src))
+        {
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                               "duplicate \"charset_map\" between "
+                               "\"%V\" and \"%V\"", &value[1], &value[2]);
+            return NGX_CONF_ERROR;
+        }
+    }
+
+    table = ngx_array_push(&mcf->tables);
+    if (table == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    table->src = src;
+    table->dst = dst;
+
+    table->src2dst = ngx_palloc(cf->pool, 256);
+    if (table->src2dst == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    table->dst2src = ngx_palloc(cf->pool, 256);
+    if (table->dst2src == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    for (i = 0; i < 128; i++) {
+        table->src2dst[i] = (char) i;
+        table->dst2src[i] = (char) i;
+    }
+
+    for (/* void */; i < 256; i++) {
+        table->src2dst[i] = '?';
+        table->dst2src[i] = '?';
+    }
+
+    pvcf = *cf;
+    cf->ctx = table;
+    cf->handler = ngx_charset_map;
+    cf->handler_conf = conf;
+
+    rv = ngx_conf_parse(cf, NULL);
+
+    *cf = pvcf;
+
+    return rv;
+}
+
+
+static char *
+ngx_charset_map(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
+{
+    ngx_int_t                   src, dst;
+    ngx_str_t                  *value;
+    ngx_http_charset_tables_t  *table;
+
+    if (cf->args->nelts != 2) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameters number");
+        return NGX_CONF_ERROR;
+    }
+
+    value = cf->args->elts;
+
+    src = ngx_hextoi(value[0].data, value[0].len);
+    if (src == NGX_ERROR || src > 255) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                           "invalid value \"%V\"", &value[0]);
+        return NGX_CONF_ERROR;
+    }
+
+    dst = ngx_hextoi(value[1].data, value[1].len);
+    if (dst == NGX_ERROR || dst > 255) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                           "invalid value \"%V\"", &value[1]);
+        return NGX_CONF_ERROR;
+    }
+
+    table = cf->ctx;
+
+    table->src2dst[src] = (char) dst;
+    table->dst2src[dst] = (char) src;
+
+    return NGX_CONF_OK;
+}
+
+
+static char *
+ngx_http_set_charset_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+    char  *p = conf;
+
+    ngx_int_t                     *cp;
+    ngx_str_t                     *value;
+    ngx_http_charset_t            *charset;
+    ngx_http_charset_main_conf_t  *mcf;
+
+    cp = (ngx_int_t *) (p + cmd->offset);
+
+    if (*cp != NGX_CONF_UNSET) {
+        return "is duplicate";
+    }
+
+    mcf = ngx_http_conf_get_module_main_conf(cf,
+                                             ngx_http_charset_filter_module);
+
+    value = cf->args->elts;
+
+    *cp = ngx_http_add_charset(&mcf->charsets, &value[1]);
+    if (*cp == NGX_ERROR) {
+        return NGX_CONF_ERROR;
+    }
+
+    if (cmd->offset == offsetof(ngx_http_charset_loc_conf_t, source_charset)) {
+        charset = mcf->charsets.elts;
+        charset[*cp].server = 1;
+    }
+
+    return NGX_CONF_OK;
+}
+
+
+static ngx_int_t
+ngx_http_add_charset(ngx_array_t *charsets, ngx_str_t *name)
+{
+    ngx_uint_t           i;
+    ngx_http_charset_t  *c;
+
+    c = charsets->elts;
+    for (i = 0; i < charsets->nelts; i++) {
+        if (name->len != c[i].name.len) {
+            continue;
+        }
+
+        if (ngx_strcasecmp(name->data, c[i].name.data) == 0) {
+            break;
+        }
+    }
+
+    if (i < charsets->nelts) {
+        return i;
+    }
+
+    c = ngx_array_push(charsets);
+    if (c == NULL) {
+        return NGX_ERROR;
+    }
+
+    c->tables = NULL;
+    c->name = *name;
+    c->server = 0;
+
+    return i;
+}
+
+
+static ngx_int_t
+ngx_http_charset_filter_init(ngx_cycle_t *cycle)
+{
+    ngx_http_next_header_filter = ngx_http_top_header_filter;
+    ngx_http_top_header_filter = ngx_http_charset_header_filter;
+
+    ngx_http_next_body_filter = ngx_http_top_body_filter;
+    ngx_http_top_body_filter = ngx_http_charset_body_filter;
+
+    return NGX_OK;
+}
+
+
+static void *
+ngx_http_charset_create_main_conf(ngx_conf_t *cf)
+{
+    ngx_http_charset_main_conf_t  *mcf;
+
+    mcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_charset_main_conf_t));
+    if (mcf == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    if (ngx_array_init(&mcf->charsets, cf->pool, 2, sizeof(ngx_http_charset_t))
+                                                                  == NGX_ERROR)
+    {
+        return NGX_CONF_ERROR;
+    }
+
+    if (ngx_array_init(&mcf->tables, cf->pool, 4,
+                       sizeof(ngx_http_charset_tables_t)) == NGX_ERROR)
+    {
+        return NGX_CONF_ERROR;
+    }
+
+    return mcf;
+}
+
+
+static char *
+ngx_http_charset_init_main_conf(ngx_conf_t *cf, void *conf)
+{
+    ngx_http_charset_main_conf_t *mcf = conf;
+
+    ngx_uint_t                  i, n;
+    ngx_http_charset_t         *charset;
+    ngx_http_charset_tables_t  *tables;
+
+    tables = mcf->tables.elts;
+    charset = mcf->charsets.elts;
+
+    for (i = 0; i < mcf->charsets.nelts; i++) {
+        if (!charset[i].server) {
+            continue;
+        }
+
+        charset[i].tables = ngx_pcalloc(cf->pool,
+                                        sizeof(char *) * mcf->charsets.nelts);
+        if (charset[i].tables == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+        for (n = 0; n < mcf->tables.nelts; n++) {
+            if ((ngx_int_t) i == tables[n].src) {
+                charset[i].tables[tables[n].dst] = tables[n].src2dst;
+                continue;
+            }
+
+            if ((ngx_int_t) i == tables[n].dst) {
+                charset[i].tables[tables[n].src] = tables[n].dst2src;
+            }
+        }
+    }
+
+    for (i = 0; i < mcf->charsets.nelts; i++) {
+        if (!charset[i].server) {
+            continue;
+        }
+
+        for (n = 0; n < mcf->charsets.nelts; n++) {
+            if (i == n) {
+                continue;
+            }
+
+            if (charset[i].tables[n]) {
+                continue;
+            }
+
+            ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+                          " no \"charset_map\" between the charsets "
+                          "\"%V\" and \"%V\"",
+                          &charset[i].name, &charset[n].name);
+            return NGX_CONF_ERROR;
+        }
+    }
+
+    return NGX_CONF_OK;
+}
+
+
+static void *
+ngx_http_charset_create_loc_conf(ngx_conf_t *cf)
+{
+    ngx_http_charset_loc_conf_t  *lcf;
+
+    lcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_charset_loc_conf_t));
+    if (lcf == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    lcf->enable = NGX_CONF_UNSET;
+    lcf->autodetect = NGX_CONF_UNSET;
+    lcf->default_charset = NGX_CONF_UNSET;
+    lcf->source_charset = NGX_CONF_UNSET;
+
+    return lcf;
+}
+
+
+static char *
+ngx_http_charset_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
+{
+    ngx_http_charset_loc_conf_t *prev = parent;
+    ngx_http_charset_loc_conf_t *conf = child;
+
+    ngx_conf_merge_value(conf->enable, prev->enable, 0);
+    ngx_conf_merge_value(conf->autodetect, prev->autodetect, 0);
+
+
+    if (conf->default_charset == NGX_CONF_UNSET) {
+        conf->default_charset = prev->default_charset;
+    }
+
+    if (conf->source_charset == NGX_CONF_UNSET) {
+        conf->source_charset = prev->source_charset;
+    }
+
+    if (conf->default_charset == NGX_CONF_UNSET
+        && conf->source_charset != NGX_CONF_UNSET)
+    {
+        conf->default_charset = conf->source_charset;
+    }
+
+    if (conf->source_charset == NGX_CONF_UNSET
+        && conf->default_charset != NGX_CONF_UNSET)
+    {
+        conf->source_charset = conf->default_charset;
+    }
+
+    if (conf->enable
+        && (conf->default_charset == NGX_CONF_UNSET
+            || conf->source_charset == NGX_CONF_UNSET))
+    {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                           "the \"source_charset\" or \"default_charset\" "
+                           "must be specified when \"charset\" is on");
+        return NGX_CONF_ERROR;
+    }
+
+    return NGX_CONF_OK;
+}
deleted file mode 100644
--- a/src/http/modules/ngx_http_chunked_filter.c
+++ /dev/null
@@ -1,173 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-static ngx_int_t ngx_http_chunked_filter_init(ngx_cycle_t *cycle);
-
-
-static ngx_http_module_t  ngx_http_chunked_filter_module_ctx = {
-    NULL,                                  /* pre conf */
-
-    NULL,                                  /* create main configuration */
-    NULL,                                  /* init main configuration */
-
-    NULL,                                  /* create server configuration */
-    NULL,                                  /* merge server configuration */
-
-    NULL,                                  /* create location configuration */
-    NULL,                                  /* merge location configuration */
-};
-
-
-ngx_module_t  ngx_http_chunked_filter_module = {
-    NGX_MODULE,
-    &ngx_http_chunked_filter_module_ctx,   /* module context */
-    NULL,                                  /* module directives */
-    NGX_HTTP_MODULE,                       /* module type */
-    ngx_http_chunked_filter_init,          /* init module */
-    NULL                                   /* init process */
-};
-
-
-static ngx_http_output_header_filter_pt  ngx_http_next_header_filter;
-static ngx_http_output_body_filter_pt    ngx_http_next_body_filter;
-
-
-static ngx_int_t ngx_http_chunked_header_filter(ngx_http_request_t *r)
-{
-    if (r->headers_out.status == NGX_HTTP_NOT_MODIFIED) {
-        return ngx_http_next_header_filter(r);
-    }
-
-    if (r->headers_out.content_length_n == -1) {
-        if (r->http_version < NGX_HTTP_VERSION_11) {
-            r->keepalive = 0;
-
-        } else {
-            r->chunked = 1;
-        }
-    }
-
-    return ngx_http_next_header_filter(r);
-}
-
-
-static ngx_int_t ngx_http_chunked_body_filter(ngx_http_request_t *r,
-                                              ngx_chain_t *in)
-{
-    u_char       *chunk;
-    off_t         size;
-    ngx_buf_t    *b;
-    ngx_chain_t   out, tail, *cl, *tl, **ll;
-
-    if (in == NULL || !r->chunked || r->header_only) {
-        return ngx_http_next_body_filter(r, in);
-    }
-
-    out.buf = NULL;
-    ll = &out.next;
-
-    size = 0;
-    cl = in;
-
-    for ( ;; ) {
-        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                       "http chunk: %d", ngx_buf_size(cl->buf));
-
-        size += ngx_buf_size(cl->buf);
-
-        if (cl->buf->flush || ngx_buf_in_memory(cl->buf) || cl->buf->in_file) {
-
-            if (!(tl = ngx_alloc_chain_link(r->pool))) {
-                return NGX_ERROR;
-            }
-
-            tl->buf = cl->buf;
-            *ll = tl;
-            ll = &tl->next;
-        }
-
-        if (cl->next == NULL) {
-            break;
-        }
-
-        cl = cl->next;
-    }
-
-    if (size) {
-        if (!(b = ngx_calloc_buf(r->pool))) {
-            return NGX_ERROR;
-        }
-
-        chunk = ngx_palloc(r->pool, sizeof("0000000000000000" CRLF) - 1);
-        if (chunk == NULL) {
-            return NGX_ERROR;
-        }
-
-        b->temporary = 1;
-        b->pos = chunk;
-        b->last = ngx_sprintf(chunk, "%xO" CRLF, size);
-
-        out.buf = b;
-    }
-
-    if (cl->buf->last_buf) {
-        if (!(b = ngx_calloc_buf(r->pool))) {
-            return NGX_ERROR;
-        }
-
-        b->memory = 1;
-        b->last_buf = 1;
-        b->pos = (u_char *) CRLF "0" CRLF CRLF;
-        b->last = b->pos + 7;
-
-        cl->buf->last_buf = 0;
-
-        if (size == 0) {
-            b->pos += 2;
-            out.buf = b;
-            out.next = NULL;
-
-            return ngx_http_next_body_filter(r, &out);
-        }
-
-    } else {
-        if (size == 0) {
-            *ll = NULL;
-            return ngx_http_next_body_filter(r, out.next);
-        }
-
-        if (!(b = ngx_calloc_buf(r->pool))) {
-            return NGX_ERROR;
-        }
-
-        b->memory = 1;
-        b->pos = (u_char *) CRLF;
-        b->last = b->pos + 2;
-    }
-
-    tail.buf = b;
-    tail.next = NULL;
-    *ll = &tail;
-
-    return ngx_http_next_body_filter(r, &out);
-}
-
-
-static ngx_int_t ngx_http_chunked_filter_init(ngx_cycle_t *cycle)
-{
-    ngx_http_next_header_filter = ngx_http_top_header_filter;
-    ngx_http_top_header_filter = ngx_http_chunked_header_filter;
-
-    ngx_http_next_body_filter = ngx_http_top_body_filter;
-    ngx_http_top_body_filter = ngx_http_chunked_body_filter;
-
-    return NGX_OK;
-}
new file mode 100644
--- /dev/null
+++ b/src/http/modules/ngx_http_chunked_filter_module.c
@@ -0,0 +1,181 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+
+
+static ngx_int_t ngx_http_chunked_filter_init(ngx_cycle_t *cycle);
+
+
+static ngx_http_module_t  ngx_http_chunked_filter_module_ctx = {
+    NULL,                                  /* pre conf */
+
+    NULL,                                  /* create main configuration */
+    NULL,                                  /* init main configuration */
+
+    NULL,                                  /* create server configuration */
+    NULL,                                  /* merge server configuration */
+
+    NULL,                                  /* create location configuration */
+    NULL,                                  /* merge location configuration */
+};
+
+
+ngx_module_t  ngx_http_chunked_filter_module = {
+    NGX_MODULE,
+    &ngx_http_chunked_filter_module_ctx,   /* module context */
+    NULL,                                  /* module directives */
+    NGX_HTTP_MODULE,                       /* module type */
+    ngx_http_chunked_filter_init,          /* init module */
+    NULL                                   /* init process */
+};
+
+
+static ngx_http_output_header_filter_pt  ngx_http_next_header_filter;
+static ngx_http_output_body_filter_pt    ngx_http_next_body_filter;
+
+
+static ngx_int_t
+ngx_http_chunked_header_filter(ngx_http_request_t *r)
+{
+    if (r->headers_out.status == NGX_HTTP_NOT_MODIFIED) {
+        return ngx_http_next_header_filter(r);
+    }
+
+    if (r->headers_out.content_length_n == -1) {
+        if (r->http_version < NGX_HTTP_VERSION_11) {
+            r->keepalive = 0;
+
+        } else {
+            r->chunked = 1;
+        }
+    }
+
+    return ngx_http_next_header_filter(r);
+}
+
+
+static ngx_int_t
+ngx_http_chunked_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
+{
+    u_char       *chunk;
+    off_t         size;
+    ngx_buf_t    *b;
+    ngx_chain_t   out, tail, *cl, *tl, **ll;
+
+    if (in == NULL || !r->chunked || r->header_only) {
+        return ngx_http_next_body_filter(r, in);
+    }
+
+    out.buf = NULL;
+    ll = &out.next;
+
+    size = 0;
+    cl = in;
+
+    for ( ;; ) {
+        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                       "http chunk: %d", ngx_buf_size(cl->buf));
+
+        size += ngx_buf_size(cl->buf);
+
+        if (cl->buf->flush || ngx_buf_in_memory(cl->buf) || cl->buf->in_file) {
+
+            tl = ngx_alloc_chain_link(r->pool);
+            if (tl == NULL) {
+                return NGX_ERROR;
+            }
+
+            tl->buf = cl->buf;
+            *ll = tl;
+            ll = &tl->next;
+        }
+
+        if (cl->next == NULL) {
+            break;
+        }
+
+        cl = cl->next;
+    }
+
+    if (size) {
+        b = ngx_calloc_buf(r->pool);
+        if (b == NULL) {
+            return NGX_ERROR;
+        }
+
+        /* the "0000000000000000" is 64-bit hexadimal string */
+
+        chunk = ngx_palloc(r->pool, sizeof("0000000000000000" CRLF) - 1);
+        if (chunk == NULL) {
+            return NGX_ERROR;
+        }
+
+        b->temporary = 1;
+        b->pos = chunk;
+        b->last = ngx_sprintf(chunk, "%xO" CRLF, size);
+
+        out.buf = b;
+    }
+
+    if (cl->buf->last_buf) {
+        b = ngx_calloc_buf(r->pool);
+        if (b == NULL) {
+            return NGX_ERROR;
+        }
+
+        b->memory = 1;
+        b->last_buf = 1;
+        b->pos = (u_char *) CRLF "0" CRLF CRLF;
+        b->last = b->pos + 7;
+
+        cl->buf->last_buf = 0;
+
+        if (size == 0) {
+            b->pos += 2;
+            out.buf = b;
+            out.next = NULL;
+
+            return ngx_http_next_body_filter(r, &out);
+        }
+
+    } else {
+        if (size == 0) {
+            *ll = NULL;
+            return ngx_http_next_body_filter(r, out.next);
+        }
+
+        b = ngx_calloc_buf(r->pool);
+        if (b == NULL) {
+            return NGX_ERROR;
+        }
+
+        b->memory = 1;
+        b->pos = (u_char *) CRLF;
+        b->last = b->pos + 2;
+    }
+
+    tail.buf = b;
+    tail.next = NULL;
+    *ll = &tail;
+
+    return ngx_http_next_body_filter(r, &out);
+}
+
+
+static ngx_int_t
+ngx_http_chunked_filter_init(ngx_cycle_t *cycle)
+{
+    ngx_http_next_header_filter = ngx_http_top_header_filter;
+    ngx_http_top_header_filter = ngx_http_chunked_header_filter;
+
+    ngx_http_next_body_filter = ngx_http_top_body_filter;
+    ngx_http_top_body_filter = ngx_http_chunked_body_filter;
+
+    return NGX_OK;
+}
deleted file mode 100644
--- a/src/http/modules/ngx_http_fastcgi_handler.c
+++ /dev/null
@@ -1,2272 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-#include <nginx.h>
-
-
-typedef struct {
-    ngx_http_upstream_conf_t        upstream;
-
-    ngx_peers_t                    *peers;
-
-    ngx_uint_t                      params;
-
-    ngx_str_t                       root;
-    ngx_str_t                       index;
-
-    ngx_array_t                    *vars;
-
-    ngx_str_t                      *location;
-} ngx_http_fastcgi_loc_conf_t;
-
-
-typedef struct {
-    ngx_list_t                      headers;
-
-    ngx_table_elt_t                *status;
-
-    ngx_table_elt_t                *content_type;
-    ngx_table_elt_t                *content_length;
-    ngx_table_elt_t                *x_powered_by;
-
-#if (NGX_HTTP_GZIP)
-    ngx_table_elt_t                *content_encoding;
-#endif
-} ngx_http_fastcgi_headers_in_t;
-
-
-typedef struct {
-    ngx_http_fastcgi_headers_in_t   headers_in;
-} ngx_http_fastcgi_upstream_t;
-
-
-typedef enum {
-    ngx_http_fastcgi_st_version = 0,
-    ngx_http_fastcgi_st_type,
-    ngx_http_fastcgi_st_request_id_hi,
-    ngx_http_fastcgi_st_request_id_lo,
-    ngx_http_fastcgi_st_content_length_hi,
-    ngx_http_fastcgi_st_content_length_lo,
-    ngx_http_fastcgi_st_padding_length,
-    ngx_http_fastcgi_st_reserved,
-    ngx_http_fastcgi_st_data,
-    ngx_http_fastcgi_st_padding,
-} ngx_http_fastcgi_state_e;
-
-
-typedef struct {
-    ngx_http_fastcgi_state_e      state;
-    u_char                       *pos;
-    u_char                       *last;
-    ngx_uint_t                    type;
-    size_t                        length;
-    size_t                        padding;
-
-    ngx_uint_t                    header;
-
-    ngx_http_fastcgi_upstream_t  *upstream;
-} ngx_http_fastcgi_ctx_t;
-
-
-#define NGX_HTTP_FASTCGI_REMOTE_ADDR          0x00000002
-#define NGX_HTTP_FASTCGI_REMOTE_USER          0x00000004
-#define NGX_HTTP_FASTCGI_SERVER_NAME          0x00000008
-#define NGX_HTTP_FASTCGI_SERVER_ADDR          0x00000010
-#define NGX_HTTP_FASTCGI_SERVER_PORT          0x00000020
-#define NGX_HTTP_FASTCGI_SCRIPT_NAME          0x00000040
-#define NGX_HTTP_FASTCGI_AUTH_TYPE            0x00000080
-#define NGX_HTTP_FASTCGI_SERVER_PROTOCOL      0x00000100
-#define NGX_HTTP_FASTCGI_SERVER_SOFTWARE      0x00000200
-#define NGX_HTTP_FASTCGI_GATEWAY_INTERFACE    0x00000400
-#define NGX_HTTP_FASTCGI_REQUEST_URI          0x00000800
-#define NGX_HTTP_FASTCGI_REDIRECT_STATUS      0x00001000
-#define NGX_HTTP_FASTCGI_DOCUMENT_ROOT        0x00002000
-#define NGX_HTTP_FASTCGI_SCRIPT_FILENAME      0x00004000
-#define NGX_HTTP_FASTCGI_REMOTE_PORT          0x00008000
-
-
-#define NGX_HTTP_FASTCGI_RESPONDER      1
-
-#define NGX_HTTP_FASTCGI_BEGIN_REQUEST  1
-#define NGX_HTTP_FASTCGI_ABORT_REQUEST  2
-#define NGX_HTTP_FASTCGI_END_REQUEST    3
-#define NGX_HTTP_FASTCGI_PARAMS         4
-#define NGX_HTTP_FASTCGI_STDIN          5
-#define NGX_HTTP_FASTCGI_STDOUT         6
-#define NGX_HTTP_FASTCGI_STDERR         7
-#define NGX_HTTP_FASTCGI_DATA           8
-
-
-typedef struct {
-    u_char  version;
-    u_char  type;
-    u_char  request_id_hi;
-    u_char  request_id_lo;
-    u_char  content_length_hi;
-    u_char  content_length_lo;
-    u_char  padding_length;
-    u_char  reserved;
-} ngx_http_fastcgi_header_t;
-
-
-typedef struct {
-    u_char  role_hi;
-    u_char  role_lo;
-    u_char  flags;
-    u_char  reserved[5];
-} ngx_http_fastcgi_begin_request_t;
-
-
-static ngx_int_t ngx_http_fastcgi_create_request(ngx_http_request_t *r);
-static ngx_int_t ngx_http_fastcgi_reinit_request(ngx_http_request_t *r);
-static ngx_int_t ngx_http_fastcgi_process_header(ngx_http_request_t *r);
-static ngx_int_t ngx_http_fastcgi_send_header(ngx_http_request_t *r);
-static ngx_int_t ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p,
-    ngx_buf_t *buf);
-static ngx_int_t ngx_http_fastcgi_process_record(ngx_http_request_t *r,
-    ngx_http_fastcgi_ctx_t *f);
-static void ngx_http_fastcgi_abort_request(ngx_http_request_t *r);
-static void ngx_http_fastcgi_finalize_request(ngx_http_request_t *r,
-    ngx_int_t rc);
-
-static char *ngx_http_fastcgi_pass(ngx_conf_t *cf, ngx_command_t *cmd,
-    void *conf);
-static char *ngx_http_fastcgi_set_var(ngx_conf_t *cf, ngx_command_t *cmd,
-    void *conf);
-static char *ngx_http_fastcgi_lowat_check(ngx_conf_t *cf, void *post,
-    void *data);
-static void *ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf);
-static char *ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf,
-    void *parent, void *child);
-
-
-static ngx_str_t ngx_http_fastcgi_methods[] = {
-    ngx_string("GET"),
-    ngx_string("HEAD"),
-    ngx_string("POST")
-};
-
-
-static ngx_str_t ngx_http_fastcgi_uri = ngx_string("/");
-
-
-static ngx_http_header_t ngx_http_fastcgi_headers_in[] = {
-    { ngx_string("Status"), offsetof(ngx_http_fastcgi_headers_in_t, status) },
-
-    { ngx_string("Content-Type"),
-                 offsetof(ngx_http_fastcgi_headers_in_t, content_type) },
-
-    { ngx_string("Content-Length"),
-                 offsetof(ngx_http_fastcgi_headers_in_t, content_length) },
-
-    { ngx_string("X-Powered-By"),
-                 offsetof(ngx_http_fastcgi_headers_in_t, x_powered_by) },
-
-#if (NGX_HTTP_GZIP)
-    { ngx_string("Content-Encoding"),
-                 offsetof(ngx_http_fastcgi_headers_in_t, content_encoding) },
-#endif
-
-    { ngx_null_string, 0 }
-};
-
-
-static ngx_conf_post_t  ngx_http_fastcgi_lowat_post =
-                                              { ngx_http_fastcgi_lowat_check };
-
-static ngx_conf_bitmask_t  ngx_http_fastcgi_next_upstream_masks[] = {
-    { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR },
-    { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT },
-    { ngx_string("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER },
-    { ngx_string("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500 },
-    { ngx_string("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404 },
-    { ngx_null_string, 0 }
-};
-
-
-static ngx_conf_bitmask_t  ngx_http_fastcgi_params_masks[] = {
-    { ngx_string("remote_addr"), NGX_HTTP_FASTCGI_REMOTE_ADDR },
-    { ngx_string("server_port"), NGX_HTTP_FASTCGI_SERVER_PORT },
-    { ngx_string("server_addr"), NGX_HTTP_FASTCGI_SERVER_ADDR },
-    { ngx_string("server_name"), NGX_HTTP_FASTCGI_SERVER_NAME },
-    { ngx_string("script_name"), NGX_HTTP_FASTCGI_SCRIPT_NAME },
-
-    { ngx_string("server_protocol"), NGX_HTTP_FASTCGI_SERVER_PROTOCOL },
-    { ngx_string("server_software"), NGX_HTTP_FASTCGI_SERVER_SOFTWARE },
-    { ngx_string("gateway_interface"), NGX_HTTP_FASTCGI_GATEWAY_INTERFACE },
-
-    { ngx_string("redirect_status"), NGX_HTTP_FASTCGI_REDIRECT_STATUS },
-    { ngx_string("request_uri"), NGX_HTTP_FASTCGI_REQUEST_URI },
-
-    { ngx_string("document_root"), NGX_HTTP_FASTCGI_DOCUMENT_ROOT },
-    { ngx_string("script_filename"), NGX_HTTP_FASTCGI_SCRIPT_FILENAME },
-    { ngx_string("remote_port"), NGX_HTTP_FASTCGI_REMOTE_PORT },
-
-    { ngx_null_string, 0 }
-};
-
-
-static ngx_command_t  ngx_http_fastcgi_commands[] = {
-
-    { ngx_string("fastcgi_pass"),
-      NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
-      ngx_http_fastcgi_pass,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      0,
-      NULL },
-
-    { ngx_string("fastcgi_root"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
-      ngx_conf_set_str_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_fastcgi_loc_conf_t, root),
-      NULL },
-
-    { ngx_string("fastcgi_index"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
-      ngx_conf_set_str_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_fastcgi_loc_conf_t, index),
-      NULL },
-
-    { ngx_string("fastcgi_connect_timeout"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
-      ngx_conf_set_msec_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.connect_timeout),
-      NULL },
-
-    { ngx_string("fastcgi_send_timeout"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
-      ngx_conf_set_msec_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.send_timeout),
-      NULL },
-
-    { ngx_string("fastcgi_send_lowat"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
-      ngx_conf_set_size_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.send_lowat),
-      &ngx_http_fastcgi_lowat_post },
-
-    { ngx_string("fastcgi_header_buffer_size"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
-      ngx_conf_set_size_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.header_buffer_size),
-      NULL },
-
-    { ngx_string("fastcgi_redirect_errors"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
-      ngx_conf_set_flag_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.redirect_errors),
-      NULL },
-
-    { ngx_string("fastcgi_x_powered_by"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
-      ngx_conf_set_flag_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.x_powered_by),
-      NULL },
-
-    { ngx_string("fastcgi_read_timeout"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
-      ngx_conf_set_msec_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.read_timeout),
-      NULL },
-
-    { ngx_string("fastcgi_buffers"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
-      ngx_conf_set_bufs_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.bufs),
-      NULL },
-
-    { ngx_string("fastcgi_busy_buffers_size"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
-      ngx_conf_set_size_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.busy_buffers_size),
-      NULL },
-
-    { ngx_string("fastcgi_temp_path"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234,
-      ngx_conf_set_path_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.temp_path),
-      (void *) ngx_garbage_collector_temp_handler },
-
-    { ngx_string("fastcgi_max_temp_file_size"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
-      ngx_conf_set_size_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.max_temp_file_size),
-      NULL },
-
-    { ngx_string("fastcgi_temp_file_write_size"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
-      ngx_conf_set_size_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.temp_file_write_size),
-      NULL },
-
-    { ngx_string("fastcgi_next_upstream"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_ANY,
-      ngx_conf_set_bitmask_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.next_upstream),
-      &ngx_http_fastcgi_next_upstream_masks },
-
-    { ngx_string("fastcgi_set_var"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
-      ngx_http_fastcgi_set_var,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      0,
-      NULL },
-
-    { ngx_string("fastcgi_params"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_ANY,
-      ngx_conf_set_bitmask_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_fastcgi_loc_conf_t, params),
-      &ngx_http_fastcgi_params_masks },
-
-      ngx_null_command
-};
-
-
-ngx_http_module_t  ngx_http_fastcgi_module_ctx = {
-    NULL,                                  /* pre conf */
-
-    NULL,                                  /* create main configuration */
-    NULL,                                  /* init main configuration */
-
-    NULL,                                  /* create server configuration */
-    NULL,                                  /* merge server configuration */
-
-    ngx_http_fastcgi_create_loc_conf,      /* create location configuration */
-    ngx_http_fastcgi_merge_loc_conf        /* merge location configuration */
-};
-
-
-ngx_module_t  ngx_http_fastcgi_module = {
-    NGX_MODULE,
-    &ngx_http_fastcgi_module_ctx,          /* module context */
-    ngx_http_fastcgi_commands,             /* module directives */
-    NGX_HTTP_MODULE,                       /* module type */
-    NULL,                                  /* init module */
-    NULL                                   /* init process */
-};
-
-
-static ngx_int_t
-ngx_http_fastcgi_handler(ngx_http_request_t *r)
-{
-    ngx_int_t                     rc;
-    ngx_http_upstream_t          *u;
-    ngx_http_fastcgi_loc_conf_t  *flcf;
-
-    flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
-
-    if (!(u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t)))) {
-        return NGX_HTTP_INTERNAL_SERVER_ERROR;
-    }
-
-    u->peer.log = r->connection->log;
-    u->peer.log_error = NGX_ERROR_ERR;
-    u->peer.peers = flcf->peers;
-    u->peer.tries = flcf->peers->number;
-#if (NGX_THREADS)
-    u->peer.lock = &r->connection->lock;
-#endif
-
-    u->output.tag = (ngx_buf_tag_t) &ngx_http_fastcgi_module;
-
-    u->conf = &flcf->upstream;
-
-    u->location = flcf->location;
-
-    u->create_request = ngx_http_fastcgi_create_request;
-    u->reinit_request = ngx_http_fastcgi_reinit_request;
-    u->process_header = ngx_http_fastcgi_process_header;
-    u->send_header = ngx_http_fastcgi_send_header;
-    u->abort_request = ngx_http_fastcgi_abort_request;
-    u->finalize_request = ngx_http_fastcgi_finalize_request;
-
-    u->pipe.input_filter = ngx_http_fastcgi_input_filter;
-    u->pipe.input_ctx = r;
-
-    u->log_ctx = r->connection->log->data;
-    u->log_handler = ngx_http_upstream_log_error;
-
-    u->schema.len = sizeof("fastcgi://") - 1;
-    u->schema.data = (u_char *) "fastcgi://";
-    u->uri.len = sizeof("/") - 1;
-    u->uri.data = (u_char *) "/";
-
-    r->upstream = u;
-
-    rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);
-
-    if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
-        return rc;
-    }
-
-    return NGX_DONE;
-}
-
-
-static ngx_int_t
-ngx_http_fastcgi_create_request(ngx_http_request_t *r)
-{
-    u_char                             ch, *pos, addr_text[INET_ADDRSTRLEN],
-                                       port_text[sizeof("65535") - 1];
-    size_t                             size, len, index, padding,
-                                       addr_len, port_len;
-    off_t                              file_pos;
-    ngx_buf_t                         *b;
-    socklen_t                          slen;
-    ngx_chain_t                       *cl, *body;
-    ngx_uint_t                         i, n, next, *vindex, port;
-    ngx_list_part_t                   *part;
-    ngx_table_elt_t                   *header;
-    struct sockaddr_in                 sin, *sinp;
-    ngx_http_variable_t               *var;
-    ngx_http_variable_value_t         *value;
-    ngx_http_core_loc_conf_t          *clcf;
-    ngx_http_core_main_conf_t         *cmcf;
-    ngx_http_fastcgi_header_t         *h;
-    ngx_http_fastcgi_loc_conf_t       *flcf;
-    ngx_http_fastcgi_begin_request_t  *br;
-
-
-    flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
-
-    if ((flcf->params & NGX_HTTP_FASTCGI_SERVER_ADDR) && r->in_addr == 0) {
-
-        slen = sizeof(struct sockaddr_in);
-        if (getsockname(r->connection->fd,
-                        (struct sockaddr *) &sin, &slen) == -1)
-        {
-            ngx_log_error(NGX_LOG_CRIT, r->connection->log,
-                          ngx_socket_errno, "getsockname() failed");
-            return NGX_ERROR;
-        }
-
-        r->in_addr = sin.sin_addr.s_addr;
-    }
-
-    addr_len = ngx_inet_ntop(r->connection->listening->family, &r->in_addr,
-                             addr_text, INET_ADDRSTRLEN);
-    if (addr_len == 0) {
-        return NGX_ERROR;
-    }
-
-#if (NGX_SUPPRESS_WARN)
-    clcf = NULL;
-    var = NULL;
-    vindex = NULL;
-#endif
-
-
-    if (r->upstream->method) {
-        len = 1 + 1 + sizeof("REQUEST_METHOD") - 1
-                + ngx_http_fastcgi_methods[r->upstream->method - 1].len;
-    
-    } else {
-        len = 1 + ((r->method_name.len - 1 > 127) ? 4 : 1)
-                                            + sizeof("REQUEST_METHOD") - 1
-                                            + r->method_name.len - 1;
-    }
-
-
-    index = (r->uri.data[r->uri.len - 1] == '/') ? flcf->index.len : 0;
-
-    len += 1 + ((flcf->root.len + r->uri.len + index > 127) ? 4 : 1)
-             + sizeof("PATH_TRANSLATED") - 1
-             + flcf->root.len + r->uri.len + index;
-
-    if (r->args.len) {
-        len += 1 + ((r->args.len > 127) ? 4 : 1) + sizeof("QUERY_STRING") - 1
-                                                 + r->args.len;
-    }
-
-    if (r->headers_in.content_length_n > 0) {
-        len += 1 + ((r->headers_in.content_length->value.len > 127) ? 4 : 1)
-                 + sizeof("CONTENT_LENGTH") - 1
-                 + r->headers_in.content_length->value.len;
-    }
-
-
-    if (r->headers_in.content_type) {
-        len += 1 + ((r->headers_in.content_type->value.len > 127) ? 4 : 1)
-                 + sizeof("CONTENT_TYPE") - 1
-                 + r->headers_in.content_type->value.len;
-    }
-
-
-    if (flcf->params & NGX_HTTP_FASTCGI_REDIRECT_STATUS) {
-        len += 1 + 1 + sizeof("REDIRECT_STATUS200") - 1;
-    }
-
-    if (flcf->params & NGX_HTTP_FASTCGI_REQUEST_URI) {
-        len += 1 + ((r->unparsed_uri.len > 127) ? 4 : 1)
-                 + sizeof("REQUEST_URI") - 1 + r->unparsed_uri.len;
-    }
-
-    if (flcf->params & NGX_HTTP_FASTCGI_DOCUMENT_ROOT) {
-        clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-        len += 1 + ((clcf->root.len > 127) ? 4 : 1)
-                 + sizeof("DOCUMENT_ROOT") - 1 + clcf->root.len;
-    }
-
-    if (flcf->params & NGX_HTTP_FASTCGI_SCRIPT_FILENAME) {
-        len += 1 + ((flcf->root.len + r->uri.len + index > 127) ? 4 : 1)
-                 + sizeof("SCRIPT_FILENAME") - 1
-                 + flcf->root.len + r->uri.len + index;
-    }
-
-    if (flcf->params & NGX_HTTP_FASTCGI_SCRIPT_NAME) {
-        len += 1 + ((r->uri.len + index > 127) ? 4 : 1)
-                 + sizeof("SCRIPT_NAME") - 1 + r->uri.len + index ;
-    }
-
-    if (flcf->params & NGX_HTTP_FASTCGI_REMOTE_ADDR) {
-        len += 1 + 1 + sizeof("REMOTE_ADDR") - 1 + r->connection->addr_text.len;
-    }
-
-    port_len = 0;
-
-    if (flcf->params & NGX_HTTP_FASTCGI_REMOTE_PORT) {
-
-        /* AF_INET only */
-
-        if (r->connection->sockaddr->sa_family == AF_INET) {
-            sinp = (struct sockaddr_in *) r->connection->sockaddr;
-
-            port = ntohs(sinp->sin_port);
-
-            if (port > 0 && port < 65536) {
-                port_len = ngx_sprintf(port_text, "%ui", port) - port_text;
-            }
-
-            len += 1 + 1 + sizeof("REMOTE_PORT") - 1 + port_len;
-        }
-    }
-
-    if (flcf->params & NGX_HTTP_FASTCGI_SERVER_NAME) {
-        len += 1 + 1 + sizeof("SERVER_NAME") - 1 + r->server_name.len;
-    }
-
-    if (flcf->params & NGX_HTTP_FASTCGI_SERVER_PORT) {
-        len += 1 + 1 + sizeof("SERVER_PORT") - 1 + r->port_text->len - 1;
-    }
-
-    if (flcf->params & NGX_HTTP_FASTCGI_SERVER_ADDR) {
-        len += 1 + 1 + sizeof("SERVER_ADDR") - 1 + addr_len;
-    }
-
-    if (flcf->params & NGX_HTTP_FASTCGI_SERVER_PROTOCOL
-        && r->http_protocol.len)
-    {
-        len += 1 + ((r->http_protocol.len > 127) ? 4 : 1)
-                 + sizeof("SERVER_PROTOCOL") - 1 + r->http_protocol.len;
-    }
-
-    if (flcf->params & NGX_HTTP_FASTCGI_SERVER_SOFTWARE) {
-        len += 1 + 1 + sizeof("SERVER_SOFTWARE") - 1 + sizeof(NGINX_VER) - 1;
-    }
-
-    if (flcf->params & NGX_HTTP_FASTCGI_GATEWAY_INTERFACE) {
-        len += 1 + 1 + sizeof("GATEWAY_INTERFACE") - 1 + sizeof("CGI/1.1") - 1;
-    }
-
-
-    if (flcf->vars) {
-        cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
-
-        var = cmcf->variables.elts;
-        vindex = flcf->vars->elts;
-
-        for (i = 0; i < flcf->vars->nelts; i++) {
-
-            if (!(value = ngx_http_get_indexed_variable(r, vindex[i]))) {
-                continue;
-            }
-
-            if (value->text.len) {
-                len += 1 + 1 + var[vindex[i]].name.len + value->text.len;
-            }
-        }
-    }
-
-
-    part = &r->headers_in.headers.part;
-    header = part->elts;
-
-    for (i = 0; /* void */; i++) {
-
-        if (i >= part->nelts) {
-            if (part->next == NULL) {
-                break;
-            }
-
-            part = part->next;
-            header = part->elts;
-            i = 0;
-        }
-
-        len += ((header[i].key.len > 127) ? 4 : 1)
-               + ((header[i].value.len > 127) ? 4 : 1)
-               + 5 + header[i].key.len + header[i].value.len;
-    }
-
-
-    if (len > 65535) {
-        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
-                      "fastcgi: the request record is too big");
-        return NGX_ERROR;
-    }
-
-
-    padding = 8 - len % 8;
-    padding = (padding == 8) ? 0 : padding;
-
-
-    size = sizeof(ngx_http_fastcgi_header_t)
-           + sizeof(ngx_http_fastcgi_begin_request_t)
-
-           + sizeof(ngx_http_fastcgi_header_t)  /* NGX_HTTP_FASTCGI_PARAMS */
-           + len + padding
-           + sizeof(ngx_http_fastcgi_header_t)  /* NGX_HTTP_FASTCGI_PARAMS */
-
-           + sizeof(ngx_http_fastcgi_header_t); /* NGX_HTTP_FASTCGI_STDIN */
-
-
-    if (!(b = ngx_create_temp_buf(r->pool, size))) {
-        return NGX_ERROR;
-    }
-
-    if (!(cl = ngx_alloc_chain_link(r->pool))) {
-        return NGX_ERROR;
-    }
-
-    cl->buf = b;
-
-    h = (ngx_http_fastcgi_header_t *) b->pos;
-
-    h->version = 1;
-    h->type = NGX_HTTP_FASTCGI_BEGIN_REQUEST;
-    h->request_id_hi = 0;
-    h->request_id_lo = 1;
-    h->content_length_hi = 0;
-    h->content_length_lo = sizeof(ngx_http_fastcgi_begin_request_t);
-    h->padding_length = 0;
-    h->reserved = 0;
-
-    br = (ngx_http_fastcgi_begin_request_t *)
-                                  (b->pos + sizeof(ngx_http_fastcgi_header_t));
-    br->role_hi = 0;
-    br->role_lo = NGX_HTTP_FASTCGI_RESPONDER;
-    br->flags = 0; /* NGX_HTTP_FASTCGI_KEEP_CONN */
-    br->reserved[0] = 0;
-    br->reserved[1] = 0;
-    br->reserved[2] = 0;
-    br->reserved[3] = 0;
-    br->reserved[4] = 0;
-
-    h = (ngx_http_fastcgi_header_t *)
-             (b->pos + sizeof(ngx_http_fastcgi_header_t)
-                     + sizeof(ngx_http_fastcgi_begin_request_t));
-
-    h->version = 1;
-    h->type = NGX_HTTP_FASTCGI_PARAMS;
-    h->request_id_hi = 0;
-    h->request_id_lo = 1;
-    h->content_length_hi = (u_char) ((len >> 8) & 0xff);
-    h->content_length_lo = (u_char) (len & 0xff);
-    h->padding_length = (u_char) padding;
-    h->reserved = 0;
-
-    b->last = b->pos + sizeof(ngx_http_fastcgi_header_t)
-                     + sizeof(ngx_http_fastcgi_begin_request_t)
-                     + sizeof(ngx_http_fastcgi_header_t);
-
-
-    *b->last++ = sizeof("PATH_TRANSLATED") - 1;
-
-    len = flcf->root.len + r->uri.len + index;
-    if (len > 127) {
-        *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
-        *b->last++ = (u_char) ((len >> 16) & 0xff);
-        *b->last++ = (u_char) ((len >> 8) & 0xff);
-        *b->last++ = (u_char) (len & 0xff);
-
-    } else {
-        *b->last++ = (u_char) len;
-    }
-
-    b->last = ngx_cpymem(b->last, "PATH_TRANSLATED",
-                         sizeof("PATH_TRANSLATED") - 1);
-    b->last = ngx_cpymem(b->last, flcf->root.data, flcf->root.len);
-    b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len);
-
-    if (index) {
-        b->last = ngx_cpymem(b->last, flcf->index.data, index);
-    }
-
-
-    *b->last++ = sizeof("REQUEST_METHOD") - 1;
-
-    if (r->upstream->method) {
-        *b->last++ = (u_char)
-                         ngx_http_fastcgi_methods[r->upstream->method - 1].len;
-
-        b->last = ngx_cpymem(b->last, "REQUEST_METHOD",
-                             sizeof("REQUEST_METHOD") - 1);
-
-        b->last = ngx_cpymem(b->last,
-                        ngx_http_fastcgi_methods[r->upstream->method - 1].data,
-                        ngx_http_fastcgi_methods[r->upstream->method - 1].len);
-
-    } else {
-        len = r->method_name.len - 1;
-        if (len > 127) {
-            *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
-            *b->last++ = (u_char) ((len >> 16) & 0xff);
-            *b->last++ = (u_char) ((len >> 8) & 0xff);
-            *b->last++ = (u_char) (len & 0xff);
-
-        } else {
-            *b->last++ = (u_char) len;
-        }
-
-        b->last = ngx_cpymem(b->last, "REQUEST_METHOD",
-                             sizeof("REQUEST_METHOD") - 1);
-        b->last = ngx_cpymem(b->last, r->method_name.data, len);
-    }
-
-
-    if (r->args.len) {
-        *b->last++ = sizeof("QUERY_STRING") - 1;
-
-        len = r->args.len;
-        if (len > 127) {
-            *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
-            *b->last++ = (u_char) ((len >> 16) & 0xff);
-            *b->last++ = (u_char) ((len >> 8) & 0xff);
-            *b->last++ = (u_char) (len & 0xff);
-
-        } else {
-            *b->last++ = (u_char) len;
-        }
-
-        b->last = ngx_cpymem(b->last, "QUERY_STRING",
-                             sizeof("QUERY_STRING") - 1);
-        b->last = ngx_cpymem(b->last, r->args.data, len);
-    }
-
-
-    if (r->headers_in.content_length_n > 0) {
-        *b->last++ = sizeof("CONTENT_LENGTH") - 1;
-
-        len = r->headers_in.content_length->value.len;
-        if (len > 127) {
-            *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
-            *b->last++ = (u_char) ((len >> 16) & 0xff);
-            *b->last++ = (u_char) ((len >> 8) & 0xff);
-            *b->last++ = (u_char) (len & 0xff);
-
-        } else {
-            *b->last++ = (u_char) len;
-        }
-
-        b->last = ngx_cpymem(b->last, "CONTENT_LENGTH",
-                             sizeof("CONTENT_LENGTH") - 1);
-        b->last = ngx_cpymem(b->last, r->headers_in.content_length->value.data,
-                             len);
-    }
-
-
-    if (r->headers_in.content_type) {
-        *b->last++ = sizeof("CONTENT_TYPE") - 1;
-
-        len = r->headers_in.content_type->value.len;
-        if (len > 127) {
-            *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
-            *b->last++ = (u_char) ((len >> 16) & 0xff);
-            *b->last++ = (u_char) ((len >> 8) & 0xff);
-            *b->last++ = (u_char) (len & 0xff);
-
-        } else {
-            *b->last++ = (u_char) len;
-        }
-
-        b->last = ngx_cpymem(b->last, "CONTENT_TYPE",
-                             sizeof("CONTENT_TYPE") - 1);
-        b->last = ngx_cpymem(b->last, r->headers_in.content_type->value.data,
-                             len);
-    }
-
-
-    if (flcf->params & NGX_HTTP_FASTCGI_REDIRECT_STATUS) {
-        *b->last++ = sizeof("REDIRECT_STATUS") - 1;
-        *b->last++ = sizeof("200") - 1;
-        b->last = ngx_cpymem(b->last, "REDIRECT_STATUS200",
-                             sizeof("REDIRECT_STATUS200") - 1);
-    }
-
-
-    if (flcf->params & NGX_HTTP_FASTCGI_REQUEST_URI) {
-        *b->last++ = sizeof("REQUEST_URI") - 1;
-
-        len = r->unparsed_uri.len;
-        if (len > 127) {
-            *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
-            *b->last++ = (u_char) ((len >> 16) & 0xff);
-            *b->last++ = (u_char) ((len >> 8) & 0xff);
-            *b->last++ = (u_char) (len & 0xff);
-
-        } else {
-            *b->last++ = (u_char) len;
-        }
-
-        b->last = ngx_cpymem(b->last, "REQUEST_URI", sizeof("REQUEST_URI") - 1);
-        b->last = ngx_cpymem(b->last, r->unparsed_uri.data, len);
-    }
-
-
-    if (flcf->params & NGX_HTTP_FASTCGI_DOCUMENT_ROOT) {
-        *b->last++ = sizeof("DOCUMENT_ROOT") - 1;
-
-        len = clcf->root.len;
-        if (len > 127) {
-            *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
-            *b->last++ = (u_char) ((len >> 16) & 0xff);
-            *b->last++ = (u_char) ((len >> 8) & 0xff);
-            *b->last++ = (u_char) (len & 0xff);
-
-        } else {
-            *b->last++ = (u_char) len;
-        }
-
-        b->last = ngx_cpymem(b->last, "DOCUMENT_ROOT",
-                             sizeof("DOCUMENT_ROOT") - 1);
-        b->last = ngx_cpymem(b->last, clcf->root.data, len);
-    }
-
-
-    if (flcf->params & NGX_HTTP_FASTCGI_SCRIPT_FILENAME) {
-        *b->last++ = sizeof("SCRIPT_FILENAME") - 1;
-
-        len = flcf->root.len + r->uri.len + index;
-        if (len > 127) {
-            *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
-            *b->last++ = (u_char) ((len >> 16) & 0xff);
-            *b->last++ = (u_char) ((len >> 8) & 0xff);
-            *b->last++ = (u_char) (len & 0xff);
-
-        } else {
-            *b->last++ = (u_char) len;
-        }
-
-        b->last = ngx_cpymem(b->last, "SCRIPT_FILENAME",
-                             sizeof("SCRIPT_FILENAME") - 1);
-        b->last = ngx_cpymem(b->last, flcf->root.data, flcf->root.len);
-        b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len);
-
-        if (index) {
-            b->last = ngx_cpymem(b->last, flcf->index.data, index);
-        }
-    }
-
-
-    if (flcf->params & NGX_HTTP_FASTCGI_SCRIPT_NAME) {
-        *b->last++ = sizeof("SCRIPT_NAME") - 1;
-
-        len = r->uri.len + index;
-        if (len > 127) {
-            *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
-            *b->last++ = (u_char) ((len >> 16) & 0xff);
-            *b->last++ = (u_char) ((len >> 8) & 0xff);
-            *b->last++ = (u_char) (len & 0xff);
-
-        } else {
-            *b->last++ = (u_char) len;
-        }
-
-        b->last = ngx_cpymem(b->last, "SCRIPT_NAME", sizeof("SCRIPT_NAME") - 1);
-        b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len);
-
-        if (index) {
-            b->last = ngx_cpymem(b->last, flcf->index.data, index);
-        }
-    }
-
-
-    if (flcf->params & NGX_HTTP_FASTCGI_REMOTE_ADDR) {
-        *b->last++ = sizeof("REMOTE_ADDR") - 1;
-        *b->last++ = (u_char) (r->connection->addr_text.len);
-        b->last = ngx_cpymem(b->last, "REMOTE_ADDR", sizeof("REMOTE_ADDR") - 1);
-        b->last = ngx_cpymem(b->last, r->connection->addr_text.data,
-                             r->connection->addr_text.len);
-    }
-
-
-    if (port_len) {
-        *b->last++ = sizeof("REMOTE_PORT") - 1;
-        *b->last++ = (u_char) port_len;
-        b->last = ngx_cpymem(b->last, "REMOTE_PORT", sizeof("REMOTE_PORT") - 1);
-        b->last = ngx_cpymem(b->last, port_text, port_len);
-    }
-
-
-    if (flcf->params & NGX_HTTP_FASTCGI_SERVER_NAME) {
-        *b->last++ = sizeof("SERVER_NAME") - 1;
-        *b->last++ = (u_char) r->server_name.len;
-        b->last = ngx_cpymem(b->last, "SERVER_NAME", sizeof("SERVER_NAME") - 1);
-        b->last = ngx_cpymem(b->last, r->server_name.data, r->server_name.len);
-    }
-
-
-    if (flcf->params & NGX_HTTP_FASTCGI_SERVER_PORT) {
-        *b->last++ = sizeof("SERVER_PORT") - 1;
-        *b->last++ = (u_char) (r->port_text->len - 1);
-        b->last = ngx_cpymem(b->last, "SERVER_PORT", sizeof("SERVER_PORT") - 1);
-        b->last = ngx_cpymem(b->last, r->port_text->data + 1,
-                             r->port_text->len - 1);
-    }
-
-
-    if (flcf->params & NGX_HTTP_FASTCGI_SERVER_ADDR) {
-        *b->last++ = sizeof("SERVER_ADDR") - 1;
-        *b->last++ = (u_char) addr_len;
-        b->last = ngx_cpymem(b->last, "SERVER_ADDR", sizeof("SERVER_ADDR") - 1);
-        b->last = ngx_cpymem(b->last, addr_text, addr_len);
-    }
-
-
-    if (flcf->params & NGX_HTTP_FASTCGI_SERVER_PROTOCOL
-        && r->http_protocol.len)
-    {
-        *b->last++ = sizeof("SERVER_PROTOCOL") - 1;
-
-        len = r->http_protocol.len;
-        if (len > 127) {
-            *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
-            *b->last++ = (u_char) ((len >> 16) & 0xff);
-            *b->last++ = (u_char) ((len >> 8) & 0xff);
-            *b->last++ = (u_char) (len & 0xff);
-
-        } else {
-            *b->last++ = (u_char) len;
-        }
-
-        b->last = ngx_cpymem(b->last, "SERVER_PROTOCOL",
-                             sizeof("SERVER_PROTOCOL") - 1);
-        b->last = ngx_cpymem(b->last, r->http_protocol.data, len);
-    }
-
-
-    if (flcf->params & NGX_HTTP_FASTCGI_SERVER_SOFTWARE) {
-        *b->last++ = sizeof("SERVER_SOFTWARE") - 1;
-        *b->last++ = (u_char) (sizeof(NGINX_VER) - 1);
-        b->last = ngx_cpymem(b->last, "SERVER_SOFTWARE",
-                             sizeof("SERVER_SOFTWARE") - 1);
-        b->last = ngx_cpymem(b->last, NGINX_VER, sizeof(NGINX_VER) - 1);
-    }
-
-
-    if (flcf->params & NGX_HTTP_FASTCGI_GATEWAY_INTERFACE) {
-        *b->last++ = sizeof("GATEWAY_INTERFACE") - 1;
-        *b->last++ = (u_char) (sizeof("CGI/1.1") - 1);
-        b->last = ngx_cpymem(b->last, "GATEWAY_INTERFACE",
-                             sizeof("GATEWAY_INTERFACE") - 1);
-        b->last = ngx_cpymem(b->last, "CGI/1.1", sizeof("CGI/1.1") - 1);
-    }
-
-
-    if (flcf->vars) {
-        for (i = 0; i < flcf->vars->nelts; i++) {
-
-            if (!(value = ngx_http_get_indexed_variable(r, vindex[i]))) {
-                continue;
-            }
-
-            if (value->text.len == 0) {
-                continue;
-            }
-
-            *b->last++ = (u_char) var[vindex[i]].name.len;
-            *b->last++ = (u_char) value->text.len;
-
-            b->last = ngx_cpymem(b->last, var[vindex[i]].name.data,
-                                 var[vindex[i]].name.len);
-
-            b->last = ngx_cpymem(b->last, value->text.data, value->text.len);
-        }
-    }
-
-
-    part = &r->headers_in.headers.part;
-    header = part->elts;
-
-    for (i = 0; /* void */; i++) {
-
-        if (i >= part->nelts) {
-            if (part->next == NULL) {
-                break;
-            }
-
-            part = part->next;
-            header = part->elts;
-            i = 0;
-        }
-
-        len = 5 + header[i].key.len;
-        if (len > 127) {
-            *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
-            *b->last++ = (u_char) ((len >> 16) & 0xff);
-            *b->last++ = (u_char) ((len >> 8) & 0xff);
-            *b->last++ = (u_char) (len & 0xff);
-
-        } else {
-            *b->last++ = (u_char) len;
-        }
-
-        len = header[i].value.len;
-        if (len > 127) {
-            *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
-            *b->last++ = (u_char) ((len >> 16) & 0xff);
-            *b->last++ = (u_char) ((len >> 8) & 0xff);
-            *b->last++ = (u_char) (len & 0xff);
-
-        } else {
-            *b->last++ = (u_char) len;
-        }
-
-        b->last = ngx_cpymem(b->last, "HTTP_", sizeof("HTTP_") - 1);
-
-        for (n = 0; n < header[i].key.len; n++) {
-            ch = header[i].key.data[n];
-
-            if (ch >= 'a' && ch <= 'z') {
-                ch &= ~0x20;
-
-            } else if (ch == '-') {
-                ch = '_';
-            }
-
-            *b->last++ = ch;
-        }
-
-        b->last = ngx_cpymem(b->last, header[i].value.data,
-                             header[i].value.len);
-    }
-
-
-    if (padding) {
-        ngx_memzero(b->last, padding);
-        b->last += padding;
-    }
-
-
-    h = (ngx_http_fastcgi_header_t *) b->last;
-    b->last += sizeof(ngx_http_fastcgi_header_t);
-
-    h->version = 1;
-    h->type = NGX_HTTP_FASTCGI_PARAMS;
-    h->request_id_hi = 0;
-    h->request_id_lo = 1;
-    h->content_length_hi = 0;
-    h->content_length_lo = 0;
-    h->padding_length = 0;
-    h->reserved = 0;
-
-    h = (ngx_http_fastcgi_header_t *) b->last;
-    b->last += sizeof(ngx_http_fastcgi_header_t);
-
-    body = r->request_body->bufs;
-    r->request_body->bufs = cl;
-
-#if (NGX_SUPPRESS_WARN)
-    file_pos = 0;
-    pos = NULL;
-#endif
-
-    while (body) {
-
-        if (body->buf->in_file) {
-            file_pos = body->buf->file_pos;
-
-        } else {
-            pos = body->buf->pos;
-        }
-
-        next = 0;
-
-        do {
-            if (!(b = ngx_alloc_buf(r->pool))) {
-                return NGX_ERROR;
-            }
-
-            ngx_memcpy(b, body->buf, sizeof(ngx_buf_t));
-
-            if (body->buf->in_file) {
-                b->file_pos = file_pos;
-                file_pos += 32 * 1024;
-
-                if (file_pos > body->buf->file_last) {
-                    file_pos = body->buf->file_last;
-                    next = 1;
-                }
-
-                b->file_last = file_pos;
-                len = (ngx_uint_t) (file_pos - b->file_pos);
-
-            } else {
-                b->pos = pos;
-                pos += 32 * 1024;
-
-                if (pos > body->buf->last) {
-                    pos = body->buf->last;
-                    next = 1;
-                }
-
-                b->last = pos;
-                len = (ngx_uint_t) (pos - b->pos);
-            }
-
-            padding = 8 - len % 8;
-            padding = (padding == 8) ? 0 : padding;
-
-            h->version = 1;
-            h->type = NGX_HTTP_FASTCGI_STDIN;
-            h->request_id_hi = 0;
-            h->request_id_lo = 1;
-            h->content_length_hi = (u_char) ((len >> 8) & 0xff);
-            h->content_length_lo = (u_char) (len & 0xff);
-            h->padding_length = (u_char) padding;
-            h->reserved = 0;
-
-            if (!(cl->next = ngx_alloc_chain_link(r->pool))) {
-                return NGX_ERROR;
-            }
-
-            cl = cl->next;
-            cl->buf = b;
-
-            b = ngx_create_temp_buf(r->pool, sizeof(ngx_http_fastcgi_header_t)
-                                             + padding);
-            if (b == NULL) {
-                return NGX_ERROR;
-            }
-
-            if (padding) {
-                ngx_memzero(b->last, padding);
-                b->last += padding;
-            }
-
-            h = (ngx_http_fastcgi_header_t *) b->last;
-            b->last += sizeof(ngx_http_fastcgi_header_t);
-
-            if (!(cl->next = ngx_alloc_chain_link(r->pool))) {
-                return NGX_ERROR;
-            }
-
-            cl = cl->next;
-            cl->buf = b;
-
-        } while (!next);
-
-        body = body->next;
-    }
-
-    h->version = 1;
-    h->type = NGX_HTTP_FASTCGI_STDIN;
-    h->request_id_hi = 0;
-    h->request_id_lo = 1;
-    h->content_length_hi = 0;
-    h->content_length_lo = 0;
-    h->padding_length = 0;
-    h->reserved = 0;
-
-    cl->next = NULL;
-
-    return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_fastcgi_reinit_request(ngx_http_request_t *r)
-{
-    ngx_http_fastcgi_ctx_t  *f;
-
-    f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
-
-    if (f == NULL) {
-        return NGX_OK;
-    }
-
-    f->state = ngx_http_fastcgi_st_version;
-    f->header = 0;
-
-    ngx_memzero(&f->upstream->headers_in,
-                sizeof(ngx_http_fastcgi_headers_in_t));
-
-    if (f->upstream->headers_in.headers.part.elts) {
-        if (ngx_list_init(&f->upstream->headers_in.headers, r->pool, 8,
-                                         sizeof(ngx_table_elt_t)) == NGX_ERROR)
-        {
-            return NGX_ERROR;
-        }
-    }
-
-    return NGX_OK;
-}
-
-
-static ngx_int_t ngx_http_fastcgi_process_header(ngx_http_request_t *r)
-{
-    u_char                  *start, *last;
-    ngx_str_t               *status_line, line;
-    ngx_int_t                rc, status;
-    ngx_uint_t               i;
-    ngx_table_elt_t         *h;
-    ngx_http_upstream_t     *u;
-    ngx_http_fastcgi_ctx_t  *f;
-
-    f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
-
-    if (f == NULL) {
-        if (!(f = ngx_pcalloc(r->pool, sizeof(ngx_http_fastcgi_ctx_t)))) {
-            return NGX_HTTP_INTERNAL_SERVER_ERROR;
-        }
-
-        ngx_http_set_ctx(r, f, ngx_http_fastcgi_module);
-
-        f->upstream = ngx_pcalloc(r->pool, sizeof(ngx_http_fastcgi_upstream_t));
-        if (f->upstream == NULL) {
-            return NGX_HTTP_INTERNAL_SERVER_ERROR;
-        }
-
-        if (ngx_list_init(&f->upstream->headers_in.headers, r->pool, 8,
-                                         sizeof(ngx_table_elt_t)) == NGX_ERROR)
-        {
-            return NGX_HTTP_INTERNAL_SERVER_ERROR;
-        }
-    }
-
-    u = r->upstream;
-
-    for ( ;; ) {
-
-        if (f->state < ngx_http_fastcgi_st_data) {
-
-            f->pos = u->header_in.pos;
-            f->last = u->header_in.last;
-
-            rc = ngx_http_fastcgi_process_record(r, f);
-
-            u->header_in.pos = f->pos;
-            u->header_in.last = f->last;
-
-            if (rc == NGX_AGAIN) {
-                return NGX_AGAIN;
-            }
-
-            if (rc == NGX_ERROR) {
-                return NGX_HTTP_UPSTREAM_INVALID_HEADER;
-            }
-
-            if (f->type != NGX_HTTP_FASTCGI_STDOUT
-                && f->type != NGX_HTTP_FASTCGI_STDERR)
-            {
-                ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
-                              "upstream sent unexpected FastCGI record: %d",
-                              f->type);
-
-                return NGX_HTTP_UPSTREAM_INVALID_HEADER;
-            }
-
-            if (f->type == NGX_HTTP_FASTCGI_STDOUT && f->length == 0) {
-                ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
-                              "upstream closed prematurely FastCGI stdout");
-
-                return NGX_HTTP_UPSTREAM_INVALID_HEADER;
-            }
-        }
-
-        if (f->state == ngx_http_fastcgi_st_padding) {
-
-            if (u->header_in.pos + f->padding < u->header_in.last) {
-                f->state = ngx_http_fastcgi_st_version;
-                u->header_in.pos += f->padding;
-
-                continue;
-            }
-
-            if (u->header_in.pos + f->padding == u->header_in.last) {
-                f->state = ngx_http_fastcgi_st_version;
-                u->header_in.pos = u->header_in.last;
-
-                return NGX_AGAIN;
-            }
-
-            f->padding -= u->header_in.last - u->header_in.pos;
-            u->header_in.pos = u->header_in.last;
-
-            return NGX_AGAIN;
-        }
-
-
-        /* f->state == ngx_http_fastcgi_st_data */
-
-        if (f->type == NGX_HTTP_FASTCGI_STDERR) {
-
-            if (f->header) {
-                ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
-                              "upstream split a header in FastCGI records");
-
-                return NGX_HTTP_UPSTREAM_INVALID_HEADER;
-            }
-
-            if (f->length) {
-                line.data = u->header_in.pos;
-
-                if (u->header_in.pos + f->length <= u->header_in.last) {
-                    line.len = f->length;
-                    u->header_in.pos += f->length;
-                    f->length = 0;
-                    f->state = ngx_http_fastcgi_st_padding;
-
-                } else { 
-                    line.len = u->header_in.last - u->header_in.pos;
-                    f->length -= u->header_in.last - u->header_in.pos;
-                    u->header_in.pos = u->header_in.last;
-                }
-
-                while (line.data[line.len - 1] == LF
-                       || line.data[line.len - 1] == CR
-                       || line.data[line.len - 1] == '.'
-                       || line.data[line.len - 1] == ' ')
-                {
-                    line.len--;
-                }
-
-                ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
-                              "FastCGI sent in stderr: \"%V\"", &line);
-
-                if (u->header_in.pos == u->header_in.last) {
-                    return NGX_AGAIN;
-                }
-
-            } else {
-                f->state = ngx_http_fastcgi_st_version;
-            }
-
-            continue;
-        }
-
-
-        /* f->type == NGX_HTTP_FASTCGI_STDOUT */
-
-        start = u->header_in.pos;
-
-        if (u->header_in.pos + f->length < u->header_in.last) {
-
-            /*
-             * set u->header_in.last to the end of the FastCGI record data
-             * for ngx_http_parse_header_line()
-             */
-
-            last = u->header_in.last;
-            u->header_in.last = u->header_in.pos + f->length;
-
-        } else {
-            last = NULL;
-        }
-
-        f->header = 1;
-
-        for ( ;; ) {
-
-            rc = ngx_http_parse_header_line(r, &u->header_in);
-
-            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                           "http fastcgi parser: %d", rc);
-
-            if (rc == NGX_AGAIN) {
-                break;
-            }
-
-            if (rc == NGX_OK) {
-
-                /* a header line has been parsed successfully */
-
-                if (!(h = ngx_list_push(&f->upstream->headers_in.headers))) {
-                    return NGX_HTTP_INTERNAL_SERVER_ERROR;
-                }
-
-                h->key.len = r->header_name_end - r->header_name_start;
-                h->value.len = r->header_end - r->header_start;
-
-                h->key.data = ngx_palloc(r->pool,
-                                         h->key.len + 1 + h->value.len + 1);
-                if (h->key.data == NULL) {
-                    return NGX_HTTP_INTERNAL_SERVER_ERROR;
-                }
-
-                h->value.data = h->key.data + h->key.len + 1;
-
-                ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1);
-                ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1);
-
-                for (i = 0; ngx_http_fastcgi_headers_in[i].name.len != 0; i++) {
-                    if (ngx_http_fastcgi_headers_in[i].name.len != h->key.len) {
-                        continue;
-                    }
-
-                    if (ngx_strcasecmp(ngx_http_fastcgi_headers_in[i].name.data,
-                                                             h->key.data) == 0)
-                    {
-                        *((ngx_table_elt_t **)
-                                 ((char *) &f->upstream->headers_in
-                                 + ngx_http_fastcgi_headers_in[i].offset)) = h;
-                        break;
-                    }
-                }
-
-                ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                               "http fastcgi header: \"%V: %V\"",
-                               &h->key, &h->value);
-
-                continue;
-            }
-
-            if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
-
-                /* a whole header has been parsed successfully */
-
-                ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                               "http fastcgi header done");
-
-                if (f->upstream->headers_in.status) {
-                    status_line = &f->upstream->headers_in.status->value;
-
-                    status = ngx_atoi(status_line->data, 3);
-
-                    if (status == NGX_ERROR) {
-                        return NGX_HTTP_INTERNAL_SERVER_ERROR;
-                    }
-
-                    r->headers_out.status = status;
-                    r->headers_out.status_line = *status_line;
-
-                } else {
-                    r->headers_out.status = 200;
-                    r->headers_out.status_line.len = sizeof("200 OK") - 1;
-                    r->headers_out.status_line.data = (u_char *) "200 OK";
-                }
-
-                u->state->status = r->headers_out.status;
-#if 0
-                if (u->cachable) {
-                    u->cachable = ngx_http_upstream_is_cachable(r);
-                }
-#endif
-
-                break;
-            }
-
-            /* there was error while a header line parsing */
-
-            ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
-                          ngx_http_upstream_header_errors[rc
-                                                - NGX_HTTP_PARSE_HEADER_ERROR]);
-
-            return NGX_HTTP_UPSTREAM_INVALID_HEADER;
-
-        }
-
-        if (last) {
-            u->header_in.last = last;
-        }
-
-        f->length -= u->header_in.pos - start;
-
-        if (rc == NGX_AGAIN) {
-            if (u->header_in.pos == u->header_in.last) {
-                return NGX_AGAIN;
-            }
-
-            ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
-                          "upstream split a header in FastCGI records");
-
-            return NGX_HTTP_UPSTREAM_INVALID_HEADER;
-        }
-
-        if (f->length == 0) {
-            if (f->padding) {
-                f->state = ngx_http_fastcgi_st_padding;
-            } else {
-                f->state = ngx_http_fastcgi_st_version;
-            }
-        }
-
-        return NGX_OK;
-    }
-}
-
-
-static ngx_int_t
-ngx_http_fastcgi_send_header(ngx_http_request_t *r)
-{
-    ngx_uint_t                      i;
-    ngx_list_part_t                *part;
-    ngx_table_elt_t                *ho, *h;
-    ngx_http_fastcgi_ctx_t         *f;
-    ngx_http_fastcgi_headers_in_t  *headers_in;
-
-    f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
-
-    headers_in = &f->upstream->headers_in;
-    part = &headers_in->headers.part;
-    h = part->elts;
-
-    for (i = 0; /* void */; i++) {
-
-        if (i >= part->nelts) {
-            if (part->next == NULL) {
-                break;
-            }
-
-            part = part->next;
-            h = part->elts;
-            i = 0;
-        }
-
-        /* ignore some headers */
-
-        if (&h[i] == headers_in->status) {
-            continue;
-        }
-
-
-        if (&h[i] == headers_in->x_powered_by
-            && !r->upstream->conf->x_powered_by)
-        {
-            continue;
-        }
-
-
-        /* "Content-Type" is handled specially */
-
-        if (&h[i] == headers_in->content_type) {
-            r->headers_out.content_type = &h[i];
-            r->headers_out.content_type->key.len = 0;
-            continue;
-        }
-
-
-        /* copy some header pointers and set up r->headers_out */
-
-        if (!(ho = ngx_list_push(&r->headers_out.headers))) {
-            return NGX_HTTP_INTERNAL_SERVER_ERROR;
-        }
-
-        *ho = h[i];
-
-#if (NGX_HTTP_GZIP)
-        if (&h[i] == headers_in->content_encoding) {
-            r->headers_out.content_encoding = ho;
-            continue;
-        }
-#endif
-
-        if (&h[i] == headers_in->content_length) {
-            r->headers_out.content_length = ho;
-            r->headers_out.content_length_n = ngx_atoi(ho->value.data,
-                                                       ho->value.len);
-            continue;
-        }
-    }
-
-    return ngx_http_send_header(r);
-}
-
-
-static ngx_int_t
-ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
-{
-    ngx_int_t                rc;
-    ngx_buf_t               *b, **prev;
-    ngx_str_t                line;
-    ngx_chain_t             *cl;
-    ngx_http_request_t      *r;
-    ngx_http_fastcgi_ctx_t  *f;
-
-    if (buf->pos == buf->last) {
-        return NGX_OK;
-    }
-
-    r = p->input_ctx;
-    f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
-
-    b = NULL;
-    prev = &buf->shadow;
-
-    f->pos = buf->pos;
-    f->last = buf->last;
-
-    for ( ;; ) {
-        if (f->state < ngx_http_fastcgi_st_data) {
-
-            rc = ngx_http_fastcgi_process_record(r, f);
-
-            if (rc == NGX_AGAIN) {
-                break;
-            }
-
-            if (rc == NGX_ERROR) {
-                return NGX_ERROR;
-            }
-
-            if (f->type == NGX_HTTP_FASTCGI_STDOUT && f->length == 0) {
-                f->state = ngx_http_fastcgi_st_version;
-                p->upstream_done = 1;
-
-                ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
-                               "http fastcgi closed stdout");
-
-                continue;
-            }
-
-            if (f->type == NGX_HTTP_FASTCGI_END_REQUEST) {
-                f->state = ngx_http_fastcgi_st_version;
-                p->upstream_done = 1;
-
-                ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
-                               "http fastcgi sent end request");
-
-                break;
-            }
-        }
-
-
-        if (f->state == ngx_http_fastcgi_st_padding) {
-
-            if (f->pos + f->padding < f->last) {
-                f->state = ngx_http_fastcgi_st_version;
-                f->pos += f->padding;
-
-                continue;
-            }
-
-            if (f->pos + f->padding == f->last) {
-                f->state = ngx_http_fastcgi_st_version;
-
-                break;
-            }
-
-            f->padding -= f->last - f->pos;
-
-            break;
-        }
-
-
-        /* f->state == ngx_http_fastcgi_st_data */
-
-        if (f->type == NGX_HTTP_FASTCGI_STDERR) {
-
-            if (f->length) {
-                line.data = f->pos;
-
-                if (f->pos + f->length <= f->last) {
-                    line.len = f->length;
-                    f->pos += f->length;
-                    f->length = 0;
-                    f->state = ngx_http_fastcgi_st_padding;
-
-                } else { 
-                    line.len = f->last - f->pos;
-                    f->length -= f->last - f->pos;
-                    f->pos = f->last;
-                }
-
-                while (line.data[line.len - 1] == LF
-                       || line.data[line.len - 1] == CR
-                       || line.data[line.len - 1] == '.'
-                       || line.data[line.len - 1] == ' ')
-                {
-                    line.len--;
-                }
-
-                ngx_log_error(NGX_LOG_ERR, p->log, 0,
-                              "FastCGI sent in stderr: \"%V\"", &line);
-
-                if (f->pos == f->last) {
-                    break;
-                }
-
-            } else {
-                f->state = ngx_http_fastcgi_st_version;
-            }
-
-            continue;
-        }
-
-
-        /* f->type == NGX_HTTP_FASTCGI_STDOUT */
-
-        if (p->free) {
-            b = p->free->buf;
-            p->free = p->free->next;
-
-        } else {
-            if (!(b = ngx_alloc_buf(p->pool))) {
-                return NGX_ERROR;
-            }
-        }
-
-        ngx_memzero(b, sizeof(ngx_buf_t));
-
-        b->pos = f->pos;
-        b->start = buf->start;
-        b->end = buf->end;
-        b->tag = p->tag;
-        b->temporary = 1;
-        b->recycled = 1;
-
-        *prev = b;
-        prev = &b->shadow;
-
-        if (!(cl = ngx_alloc_chain_link(p->pool))) {
-            return NGX_ERROR;
-        }
-
-        cl->buf = b;
-        cl->next = NULL;
-
-        /* STUB */ b->num = buf->num;
-
-        ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0, "input buf #%d", b->num);
-
-        ngx_chain_add_link(p->in, p->last_in, cl);
-
-        if (f->pos + f->length < f->last) {
-
-            if (f->padding) {
-                f->state = ngx_http_fastcgi_st_padding;
-            } else {
-                f->state = ngx_http_fastcgi_st_version;
-            }
-
-            f->pos += f->length;
-            b->last = f->pos;
-
-            continue;
-        }
-
-        if (f->pos + f->length == f->last) {
-
-            if (f->padding) {
-                f->state = ngx_http_fastcgi_st_padding;
-            } else {
-                f->state = ngx_http_fastcgi_st_version;
-            }
-
-            b->last = f->last;
-
-            break;
-        }
-
-        f->length -= f->last - f->pos;
-
-        b->last = f->last;
-
-        break;
-
-    }
-
-    if (b) {
-        b->shadow = buf;
-        b->last_shadow = 1;
-
-        return NGX_OK;
-    }
-
-    /* there is no data record in the buf, add it to free chain */
-
-    if (ngx_event_pipe_add_free_buf(p, buf) != NGX_OK) {
-        return NGX_ERROR;
-    }
-
-    return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_fastcgi_process_record(ngx_http_request_t *r,
-    ngx_http_fastcgi_ctx_t *f)
-{
-    u_char                     ch, *p;
-    ngx_http_upstream_t       *u;
-    ngx_http_fastcgi_state_e   state;
-
-    u = r->upstream;
-
-    state = f->state;
-
-    for (p = f->pos; p < f->last; p++) {
-
-        ch = *p;
-
-        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                       "http fastcgi record byte: %02Xd", ch);
-
-        switch (state) {
-
-        case ngx_http_fastcgi_st_version:
-            if (ch != 1) {
-                ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
-                              "upstream sent unsupported FastCGI "
-                              "protocol version: %d", ch);
-                return NGX_ERROR;
-            }
-            state = ngx_http_fastcgi_st_type;
-            break;
-
-        case ngx_http_fastcgi_st_type:
-            switch (ch) {
-            case NGX_HTTP_FASTCGI_STDOUT:
-            case NGX_HTTP_FASTCGI_STDERR:
-            case NGX_HTTP_FASTCGI_END_REQUEST:
-                 f->type = (ngx_uint_t) ch;
-                 break;
-            default:
-                ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
-                              "upstream sent invalid FastCGI "
-                              "record type: %d", ch);
-                return NGX_ERROR;
-
-            }
-            state = ngx_http_fastcgi_st_request_id_hi;
-            break;
-
-        /* we support the single request per connection */
-
-        case ngx_http_fastcgi_st_request_id_hi:
-            if (ch != 0) {
-                ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
-                              "upstream sent unexpected FastCGI "
-                              "request id high byte: %d", ch);
-                return NGX_ERROR;
-            }
-            state = ngx_http_fastcgi_st_request_id_lo;
-            break;
-
-        case ngx_http_fastcgi_st_request_id_lo:
-            if (ch != 1) {
-                ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
-                              "upstream sent unexpected FastCGI "
-                              "request id low byte: %d", ch);
-                return NGX_ERROR;
-            }
-            state = ngx_http_fastcgi_st_content_length_hi;
-            break;
-
-        case ngx_http_fastcgi_st_content_length_hi:
-            f->length = ch << 8;
-            state = ngx_http_fastcgi_st_content_length_lo;
-            break;
-
-        case ngx_http_fastcgi_st_content_length_lo:
-            f->length |= (size_t) ch;
-            state = ngx_http_fastcgi_st_padding_length;
-            break;
-
-        case ngx_http_fastcgi_st_padding_length:
-            f->padding = (size_t) ch;
-            state = ngx_http_fastcgi_st_reserved;
-            break;
-
-        case ngx_http_fastcgi_st_reserved:
-            state = ngx_http_fastcgi_st_data;
-
-            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                           "http fastcgi record length: %z", f->length);
-
-            f->pos = p + 1;
-            f->state = state;
-
-            return NGX_OK;
-
-        /* suppress warning */
-        case ngx_http_fastcgi_st_data:
-        case ngx_http_fastcgi_st_padding:
-            break;
-        }
-    }
-
-    f->pos = p + 1;
-    f->state = state;
-
-    return NGX_AGAIN;
-}
-
-
-static void
-ngx_http_fastcgi_abort_request(ngx_http_request_t *r)
-{
-    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                   "abort http fastcgi request");
-
-    return;
-}
-
-
-static void
-ngx_http_fastcgi_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
-{
-    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                   "finalize http fastcgi request");
-
-    return;
-}
-
-
-static char *
-ngx_http_fastcgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
-    ngx_http_fastcgi_loc_conf_t *lcf = conf;
-
-    ngx_str_t                   *value;
-    ngx_inet_upstream_t          inet_upstream;
-    ngx_http_core_loc_conf_t    *clcf;
-#if (NGX_HAVE_UNIX_DOMAIN)
-    ngx_unix_domain_upstream_t   unix_upstream;
-#endif
-
-    value = cf->args->elts;
-
-    if (ngx_strncasecmp(value[1].data, "unix:", 5) == 0) {
-
-#if (NGX_HAVE_UNIX_DOMAIN)
-
-        ngx_memzero(&unix_upstream, sizeof(ngx_unix_domain_upstream_t));
-
-        unix_upstream.name = value[1];
-        unix_upstream.url = value[1];
-
-        if (!(lcf->peers = ngx_unix_upstream_parse(cf, &unix_upstream))) {
-            return NGX_CONF_ERROR;
-        }
-
-#else
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                           "the unix domain sockets are not supported "
-                           "on this platform");
-        return NGX_CONF_ERROR;
-
-#endif
-
-    } else {
-        ngx_memzero(&inet_upstream, sizeof(ngx_inet_upstream_t));
-
-        inet_upstream.name = value[1];
-        inet_upstream.url = value[1];
-    
-        if (!(lcf->peers = ngx_inet_upstream_parse(cf, &inet_upstream))) {
-            return NGX_CONF_ERROR;
-        }
-    }
-
-    clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
-
-    clcf->handler = ngx_http_fastcgi_handler;
-
-#if (NGX_PCRE)
-    lcf->location = clcf->regex ? &ngx_http_fastcgi_uri: &clcf->name;
-#else
-    lcf->location = &clcf->name;
-#endif
-
-    if (clcf->name.data[clcf->name.len - 1] == '/') {
-        clcf->auto_redirect = 1;
-    }
-
-    return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_fastcgi_set_var(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
-    ngx_http_fastcgi_loc_conf_t *lcf = conf;
-
-    ngx_uint_t                  i, *index;
-    ngx_str_t                  *value;
-    ngx_http_variable_t        *var;
-    ngx_http_core_main_conf_t  *cmcf;
-
-    if (lcf->vars == NULL) {
-        lcf->vars = ngx_array_create(cf->pool, 4,
-                                     sizeof(ngx_http_variable_t *));
-        if (lcf->vars == NULL) {
-            return NGX_CONF_ERROR;
-        }
-    }
-
-    cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
-
-    value = cf->args->elts;
-
-    var = cmcf->variables.elts;
-    for (i = 0; i < cmcf->variables.nelts; i++) {
-        if (ngx_strcasecmp(var[i].name.data, value[1].data) == 0) {
-
-            if (!(index = ngx_array_push(lcf->vars))) {
-                return NGX_CONF_ERROR;
-            }
-
-            *index = var[i].index;
-            return NGX_CONF_OK;
-        }
-    }
-
-    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                       "unknown variable name \"%V\"", &value[1]);
-    return NGX_CONF_ERROR;
-}
-
-
-static char *
-ngx_http_fastcgi_lowat_check(ngx_conf_t *cf, void *post, void *data)
-{
-#if (NGX_FREEBSD)
-    ssize_t *np = data;
-
-    if (*np >= ngx_freebsd_net_inet_tcp_sendspace) {
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                           "\"fastcgi_send_lowat\" must be less than %d "
-                           "(sysctl net.inet.tcp.sendspace)",
-                           ngx_freebsd_net_inet_tcp_sendspace);
-
-        return NGX_CONF_ERROR;
-    }
-
-#elif !(NGX_HAVE_SO_SNDLOWAT)
-    ssize_t *np = data;
-
-    ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
-                       "\"fastcgi_send_lowat\" is not supported, ignored");
-
-    *np = 0;
-
-#endif
-
-    return NGX_CONF_OK;
-}
-
-
-static void *
-ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf)
-{
-    ngx_http_fastcgi_loc_conf_t  *conf;
-
-    if (!(conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_fastcgi_loc_conf_t)))) {
-        return NGX_CONF_ERROR;
-    }
-
-    /*
-     * set by ngx_pcalloc():
-     *
-     *     conf->upstream.bufs.num = 0;
-     *     conf->upstream.path = NULL;
-     *     conf->upstream.next_upstream = 0;
-     *     conf->upstream.temp_path = NULL;
-     *     conf->params = 0;
-     *     conf->root.len = 0;
-     *     conf->root.data = NULL;
-     *     conf->index.len = 0;
-     *     conf->index.data = NULL;
-     *     conf->location = NULL;
-     */
-
-    conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC;
-    conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC;
-    conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE;
-
-    conf->upstream.header_buffer_size = NGX_CONF_UNSET_SIZE;
-    conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC;
-    conf->upstream.busy_buffers_size = NGX_CONF_UNSET_SIZE;
-
-    conf->upstream.max_temp_file_size = NGX_CONF_UNSET_SIZE; 
-    conf->upstream.temp_file_write_size = NGX_CONF_UNSET_SIZE;
-    
-    conf->upstream.redirect_errors = NGX_CONF_UNSET;
-    conf->upstream.x_powered_by = NGX_CONF_UNSET;
-
-    /* "fastcgi_cyclic_temp_file" is disabled */
-    conf->upstream.cyclic_temp_file = 0;
-
-    return conf;
-}
-
-
-static char *
-ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
-{
-    ngx_http_fastcgi_loc_conf_t *prev = parent;
-    ngx_http_fastcgi_loc_conf_t *conf = child;
-
-    size_t  size;
-
-    ngx_conf_merge_msec_value(conf->upstream.connect_timeout,
-                              prev->upstream.connect_timeout, 60000);
-    ngx_conf_merge_msec_value(conf->upstream.send_timeout,
-                              prev->upstream.send_timeout, 60000);
-    ngx_conf_merge_size_value(conf->upstream.send_lowat,
-                              prev->upstream.send_lowat, 0);
-
-    ngx_conf_merge_msec_value(conf->upstream.read_timeout,
-                              prev->upstream.read_timeout, 60000);
-
-    ngx_conf_merge_msec_value(conf->upstream.redirect_errors,
-                              prev->upstream.redirect_errors, 0);
-
-    ngx_conf_merge_msec_value(conf->upstream.x_powered_by,
-                              prev->upstream.x_powered_by, 1);
-
-
-    ngx_conf_merge_size_value(conf->upstream.header_buffer_size, 
-                              prev->upstream.header_buffer_size,
-                              (size_t) ngx_pagesize);
-
-    ngx_conf_merge_bufs_value(conf->upstream.bufs, prev->upstream.bufs,
-                              8, ngx_pagesize);
-
-    if (conf->upstream.bufs.num < 2) {
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                           "there must be at least 2 \"fastcgi_buffers\"");
-        return NGX_CONF_ERROR;
-    }
-
-
-    size = conf->upstream.header_buffer_size;
-    if (size < conf->upstream.bufs.size) {
-        size = conf->upstream.bufs.size;
-    }
-
-
-    ngx_conf_merge_size_value(conf->upstream.busy_buffers_size, 
-                              prev->upstream.busy_buffers_size,
-                              NGX_CONF_UNSET_SIZE);
-
-    if (conf->upstream.busy_buffers_size == NGX_CONF_UNSET_SIZE) {
-        conf->upstream.busy_buffers_size = 2 * size;
-
-    } else if (conf->upstream.busy_buffers_size < size) {
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-             "\"fastcgi_busy_buffers_size\" must be equal or bigger than "
-             "maximum of the value of \"fastcgi_header_buffer_size\" and "
-             "one of the \"fastcgi_buffers\"");
-
-        return NGX_CONF_ERROR;
-
-    } else if (conf->upstream.busy_buffers_size
-               > (conf->upstream.bufs.num - 1) * conf->upstream.bufs.size)
-    {
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-             "\"fastcgi_busy_buffers_size\" must be less than "
-             "the size of all \"fastcgi_buffers\" minus one buffer");
-
-        return NGX_CONF_ERROR;
-    }
-
-
-    ngx_conf_merge_size_value(conf->upstream.temp_file_write_size, 
-                              prev->upstream.temp_file_write_size,
-                              NGX_CONF_UNSET_SIZE);
-
-    if (conf->upstream.temp_file_write_size == NGX_CONF_UNSET_SIZE) {
-        conf->upstream.temp_file_write_size = 2 * size;
-
-    } else if (conf->upstream.temp_file_write_size < size) {
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-             "\"fastcgi_temp_file_write_size\" must be equal or bigger than "
-             "maximum of the value of \"fastcgi_header_buffer_size\" and "
-             "one of the \"fastcgi_buffers\"");
-
-        return NGX_CONF_ERROR;
-    }
-
-
-    ngx_conf_merge_size_value(conf->upstream.max_temp_file_size,
-                              prev->upstream.max_temp_file_size,
-                              NGX_CONF_UNSET_SIZE);
-
-    if (conf->upstream.max_temp_file_size == NGX_CONF_UNSET_SIZE) {
-
-        conf->upstream.max_temp_file_size = 1024 * 1024 * 1024;
-
-    } else if (conf->upstream.max_temp_file_size != 0
-               && conf->upstream.max_temp_file_size < size)
-    {
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-             "\"fastcgi_max_temp_file_size\" must be equal to zero to disable "
-             "the temporary files usage or must be equal or bigger than "
-             "maximum of the value of \"fastcgi_header_buffer_size\" and "
-             "one of the \"fastcgi_buffers\"");
-
-        return NGX_CONF_ERROR;
-    }
-
-
-    ngx_conf_merge_bitmask_value(conf->upstream.next_upstream,
-                              prev->upstream.next_upstream,
-                              (NGX_CONF_BITMASK_SET
-                               |NGX_HTTP_UPSTREAM_FT_ERROR
-                               |NGX_HTTP_UPSTREAM_FT_TIMEOUT));
-
-    ngx_conf_merge_path_value(conf->upstream.temp_path,
-                              prev->upstream.temp_path,
-                              NGX_HTTP_FASTCGI_TEMP_PATH, 1, 2, 0,
-                              ngx_garbage_collector_temp_handler, cf);
-
-
-    ngx_conf_merge_bitmask_value(conf->params, prev->params,
-                              (NGX_CONF_BITMASK_SET
-                               |NGX_HTTP_FASTCGI_REMOTE_ADDR
-                               |NGX_HTTP_FASTCGI_REMOTE_USER
-                               |NGX_HTTP_FASTCGI_SERVER_NAME
-                               |NGX_HTTP_FASTCGI_SERVER_PORT
-                               |NGX_HTTP_FASTCGI_SCRIPT_NAME
-                               |NGX_HTTP_FASTCGI_AUTH_TYPE
-                               |NGX_HTTP_FASTCGI_REQUEST_URI
-                               |NGX_HTTP_FASTCGI_REDIRECT_STATUS));
-
-    ngx_conf_merge_str_value(conf->root, prev->root, "");
-
-    if (conf->root.len && conf->root.data[conf->root.len - 1] == '/') {
-        conf->root.len--;
-    }
-
-    ngx_conf_merge_str_value(conf->index, prev->index, "");
-
-    if (conf->vars == NULL) {
-        conf->vars = prev->vars;
-    }
-
-    return NGX_CONF_OK;
-}
new file mode 100644
--- /dev/null
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -0,0 +1,2292 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+#include <nginx.h>
+
+
+typedef struct {
+    ngx_http_upstream_conf_t        upstream;
+
+    ngx_peers_t                    *peers;
+
+    ngx_uint_t                      params;
+
+    ngx_str_t                       root;
+    ngx_str_t                       index;
+
+    ngx_array_t                    *vars;
+
+    ngx_str_t                      *location;
+} ngx_http_fastcgi_loc_conf_t;
+
+
+typedef struct {
+    ngx_list_t                      headers;
+
+    ngx_table_elt_t                *status;
+
+    ngx_table_elt_t                *content_type;
+    ngx_table_elt_t                *content_length;
+    ngx_table_elt_t                *x_powered_by;
+
+#if (NGX_HTTP_GZIP)
+    ngx_table_elt_t                *content_encoding;
+#endif
+} ngx_http_fastcgi_headers_in_t;
+
+
+typedef struct {
+    ngx_http_fastcgi_headers_in_t   headers_in;
+} ngx_http_fastcgi_upstream_t;
+
+
+typedef enum {
+    ngx_http_fastcgi_st_version = 0,
+    ngx_http_fastcgi_st_type,
+    ngx_http_fastcgi_st_request_id_hi,
+    ngx_http_fastcgi_st_request_id_lo,
+    ngx_http_fastcgi_st_content_length_hi,
+    ngx_http_fastcgi_st_content_length_lo,
+    ngx_http_fastcgi_st_padding_length,
+    ngx_http_fastcgi_st_reserved,
+    ngx_http_fastcgi_st_data,
+    ngx_http_fastcgi_st_padding,
+} ngx_http_fastcgi_state_e;
+
+
+typedef struct {
+    ngx_http_fastcgi_state_e      state;
+    u_char                       *pos;
+    u_char                       *last;
+    ngx_uint_t                    type;
+    size_t                        length;
+    size_t                        padding;
+
+    ngx_uint_t                    header;
+
+    ngx_http_fastcgi_upstream_t  *upstream;
+} ngx_http_fastcgi_ctx_t;
+
+
+#define NGX_HTTP_FASTCGI_REMOTE_ADDR          0x00000002
+#define NGX_HTTP_FASTCGI_REMOTE_USER          0x00000004
+#define NGX_HTTP_FASTCGI_SERVER_NAME          0x00000008
+#define NGX_HTTP_FASTCGI_SERVER_ADDR          0x00000010
+#define NGX_HTTP_FASTCGI_SERVER_PORT          0x00000020
+#define NGX_HTTP_FASTCGI_SCRIPT_NAME          0x00000040
+#define NGX_HTTP_FASTCGI_AUTH_TYPE            0x00000080
+#define NGX_HTTP_FASTCGI_SERVER_PROTOCOL      0x00000100
+#define NGX_HTTP_FASTCGI_SERVER_SOFTWARE      0x00000200
+#define NGX_HTTP_FASTCGI_GATEWAY_INTERFACE    0x00000400
+#define NGX_HTTP_FASTCGI_REQUEST_URI          0x00000800
+#define NGX_HTTP_FASTCGI_REDIRECT_STATUS      0x00001000
+#define NGX_HTTP_FASTCGI_DOCUMENT_ROOT        0x00002000
+#define NGX_HTTP_FASTCGI_SCRIPT_FILENAME      0x00004000
+#define NGX_HTTP_FASTCGI_REMOTE_PORT          0x00008000
+
+
+#define NGX_HTTP_FASTCGI_RESPONDER      1
+
+#define NGX_HTTP_FASTCGI_BEGIN_REQUEST  1
+#define NGX_HTTP_FASTCGI_ABORT_REQUEST  2
+#define NGX_HTTP_FASTCGI_END_REQUEST    3
+#define NGX_HTTP_FASTCGI_PARAMS         4
+#define NGX_HTTP_FASTCGI_STDIN          5
+#define NGX_HTTP_FASTCGI_STDOUT         6
+#define NGX_HTTP_FASTCGI_STDERR         7
+#define NGX_HTTP_FASTCGI_DATA           8
+
+
+typedef struct {
+    u_char  version;
+    u_char  type;
+    u_char  request_id_hi;
+    u_char  request_id_lo;
+    u_char  content_length_hi;
+    u_char  content_length_lo;
+    u_char  padding_length;
+    u_char  reserved;
+} ngx_http_fastcgi_header_t;
+
+
+typedef struct {
+    u_char  role_hi;
+    u_char  role_lo;
+    u_char  flags;
+    u_char  reserved[5];
+} ngx_http_fastcgi_begin_request_t;
+
+
+static ngx_int_t ngx_http_fastcgi_create_request(ngx_http_request_t *r);
+static ngx_int_t ngx_http_fastcgi_reinit_request(ngx_http_request_t *r);
+static ngx_int_t ngx_http_fastcgi_process_header(ngx_http_request_t *r);
+static ngx_int_t ngx_http_fastcgi_send_header(ngx_http_request_t *r);
+static ngx_int_t ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p,
+    ngx_buf_t *buf);
+static ngx_int_t ngx_http_fastcgi_process_record(ngx_http_request_t *r,
+    ngx_http_fastcgi_ctx_t *f);
+static void ngx_http_fastcgi_abort_request(ngx_http_request_t *r);
+static void ngx_http_fastcgi_finalize_request(ngx_http_request_t *r,
+    ngx_int_t rc);
+
+static char *ngx_http_fastcgi_pass(ngx_conf_t *cf, ngx_command_t *cmd,
+    void *conf);
+static char *ngx_http_fastcgi_set_var(ngx_conf_t *cf, ngx_command_t *cmd,
+    void *conf);
+static char *ngx_http_fastcgi_lowat_check(ngx_conf_t *cf, void *post,
+    void *data);
+static void *ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf);
+static char *ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf,
+    void *parent, void *child);
+
+
+static ngx_str_t ngx_http_fastcgi_methods[] = {
+    ngx_string("GET"),
+    ngx_string("HEAD"),
+    ngx_string("POST")
+};
+
+
+static ngx_str_t ngx_http_fastcgi_uri = ngx_string("/");
+
+
+static ngx_http_header_t ngx_http_fastcgi_headers_in[] = {
+    { ngx_string("Status"), offsetof(ngx_http_fastcgi_headers_in_t, status) },
+
+    { ngx_string("Content-Type"),
+                 offsetof(ngx_http_fastcgi_headers_in_t, content_type) },
+
+    { ngx_string("Content-Length"),
+                 offsetof(ngx_http_fastcgi_headers_in_t, content_length) },
+
+    { ngx_string("X-Powered-By"),
+                 offsetof(ngx_http_fastcgi_headers_in_t, x_powered_by) },
+
+#if (NGX_HTTP_GZIP)
+    { ngx_string("Content-Encoding"),
+                 offsetof(ngx_http_fastcgi_headers_in_t, content_encoding) },
+#endif
+
+    { ngx_null_string, 0 }
+};
+
+
+static ngx_conf_post_t  ngx_http_fastcgi_lowat_post =
+                                              { ngx_http_fastcgi_lowat_check };
+
+static ngx_conf_bitmask_t  ngx_http_fastcgi_next_upstream_masks[] = {
+    { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR },
+    { ngx_string("timeout"), NGX_HTTP_UPSTREAM_FT_TIMEOUT },
+    { ngx_string("invalid_header"), NGX_HTTP_UPSTREAM_FT_INVALID_HEADER },
+    { ngx_string("http_500"), NGX_HTTP_UPSTREAM_FT_HTTP_500 },
+    { ngx_string("http_404"), NGX_HTTP_UPSTREAM_FT_HTTP_404 },
+    { ngx_null_string, 0 }
+};
+
+
+static ngx_conf_bitmask_t  ngx_http_fastcgi_params_masks[] = {
+    { ngx_string("remote_addr"), NGX_HTTP_FASTCGI_REMOTE_ADDR },
+    { ngx_string("server_port"), NGX_HTTP_FASTCGI_SERVER_PORT },
+    { ngx_string("server_addr"), NGX_HTTP_FASTCGI_SERVER_ADDR },
+    { ngx_string("server_name"), NGX_HTTP_FASTCGI_SERVER_NAME },
+    { ngx_string("script_name"), NGX_HTTP_FASTCGI_SCRIPT_NAME },
+
+    { ngx_string("server_protocol"), NGX_HTTP_FASTCGI_SERVER_PROTOCOL },
+    { ngx_string("server_software"), NGX_HTTP_FASTCGI_SERVER_SOFTWARE },
+    { ngx_string("gateway_interface"), NGX_HTTP_FASTCGI_GATEWAY_INTERFACE },
+
+    { ngx_string("redirect_status"), NGX_HTTP_FASTCGI_REDIRECT_STATUS },
+    { ngx_string("request_uri"), NGX_HTTP_FASTCGI_REQUEST_URI },
+
+    { ngx_string("document_root"), NGX_HTTP_FASTCGI_DOCUMENT_ROOT },
+    { ngx_string("script_filename"), NGX_HTTP_FASTCGI_SCRIPT_FILENAME },
+    { ngx_string("remote_port"), NGX_HTTP_FASTCGI_REMOTE_PORT },
+
+    { ngx_null_string, 0 }
+};
+
+
+static ngx_command_t  ngx_http_fastcgi_commands[] = {
+
+    { ngx_string("fastcgi_pass"),
+      NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_http_fastcgi_pass,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      0,
+      NULL },
+
+    { ngx_string("fastcgi_root"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_str_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_fastcgi_loc_conf_t, root),
+      NULL },
+
+    { ngx_string("fastcgi_index"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_str_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_fastcgi_loc_conf_t, index),
+      NULL },
+
+    { ngx_string("fastcgi_connect_timeout"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_msec_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.connect_timeout),
+      NULL },
+
+    { ngx_string("fastcgi_send_timeout"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_msec_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.send_timeout),
+      NULL },
+
+    { ngx_string("fastcgi_send_lowat"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_size_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.send_lowat),
+      &ngx_http_fastcgi_lowat_post },
+
+    { ngx_string("fastcgi_header_buffer_size"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_size_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.header_buffer_size),
+      NULL },
+
+    { ngx_string("fastcgi_redirect_errors"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      ngx_conf_set_flag_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.redirect_errors),
+      NULL },
+
+    { ngx_string("fastcgi_x_powered_by"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      ngx_conf_set_flag_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.x_powered_by),
+      NULL },
+
+    { ngx_string("fastcgi_read_timeout"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_msec_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.read_timeout),
+      NULL },
+
+    { ngx_string("fastcgi_buffers"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
+      ngx_conf_set_bufs_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.bufs),
+      NULL },
+
+    { ngx_string("fastcgi_busy_buffers_size"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_size_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.busy_buffers_size),
+      NULL },
+
+    { ngx_string("fastcgi_temp_path"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1234,
+      ngx_conf_set_path_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.temp_path),
+      (void *) ngx_garbage_collector_temp_handler },
+
+    { ngx_string("fastcgi_max_temp_file_size"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_size_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.max_temp_file_size),
+      NULL },
+
+    { ngx_string("fastcgi_temp_file_write_size"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_size_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.temp_file_write_size),
+      NULL },
+
+    { ngx_string("fastcgi_next_upstream"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_ANY,
+      ngx_conf_set_bitmask_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.next_upstream),
+      &ngx_http_fastcgi_next_upstream_masks },
+
+    { ngx_string("fastcgi_set_var"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_http_fastcgi_set_var,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      0,
+      NULL },
+
+    { ngx_string("fastcgi_params"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_ANY,
+      ngx_conf_set_bitmask_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_fastcgi_loc_conf_t, params),
+      &ngx_http_fastcgi_params_masks },
+
+      ngx_null_command
+};
+
+
+ngx_http_module_t  ngx_http_fastcgi_module_ctx = {
+    NULL,                                  /* pre conf */
+
+    NULL,                                  /* create main configuration */
+    NULL,                                  /* init main configuration */
+
+    NULL,                                  /* create server configuration */
+    NULL,                                  /* merge server configuration */
+
+    ngx_http_fastcgi_create_loc_conf,      /* create location configuration */
+    ngx_http_fastcgi_merge_loc_conf        /* merge location configuration */
+};
+
+
+ngx_module_t  ngx_http_fastcgi_module = {
+    NGX_MODULE,
+    &ngx_http_fastcgi_module_ctx,          /* module context */
+    ngx_http_fastcgi_commands,             /* module directives */
+    NGX_HTTP_MODULE,                       /* module type */
+    NULL,                                  /* init module */
+    NULL                                   /* init process */
+};
+
+
+static ngx_int_t
+ngx_http_fastcgi_handler(ngx_http_request_t *r)
+{
+    ngx_int_t                     rc;
+    ngx_http_upstream_t          *u;
+    ngx_http_fastcgi_loc_conf_t  *flcf;
+
+    flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
+
+    u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t));
+    if (u == NULL) {
+        return NGX_HTTP_INTERNAL_SERVER_ERROR;
+    }
+
+    u->peer.log = r->connection->log;
+    u->peer.log_error = NGX_ERROR_ERR;
+    u->peer.peers = flcf->peers;
+    u->peer.tries = flcf->peers->number;
+#if (NGX_THREADS)
+    u->peer.lock = &r->connection->lock;
+#endif
+
+    u->output.tag = (ngx_buf_tag_t) &ngx_http_fastcgi_module;
+
+    u->conf = &flcf->upstream;
+
+    u->location = flcf->location;
+
+    u->create_request = ngx_http_fastcgi_create_request;
+    u->reinit_request = ngx_http_fastcgi_reinit_request;
+    u->process_header = ngx_http_fastcgi_process_header;
+    u->send_header = ngx_http_fastcgi_send_header;
+    u->abort_request = ngx_http_fastcgi_abort_request;
+    u->finalize_request = ngx_http_fastcgi_finalize_request;
+
+    u->pipe.input_filter = ngx_http_fastcgi_input_filter;
+    u->pipe.input_ctx = r;
+
+    u->log_ctx = r->connection->log->data;
+    u->log_handler = ngx_http_upstream_log_error;
+
+    u->schema.len = sizeof("fastcgi://") - 1;
+    u->schema.data = (u_char *) "fastcgi://";
+    u->uri.len = sizeof("/") - 1;
+    u->uri.data = (u_char *) "/";
+
+    r->upstream = u;
+
+    rc = ngx_http_read_client_request_body(r, ngx_http_upstream_init);
+
+    if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
+        return rc;
+    }
+
+    return NGX_DONE;
+}
+
+
+static ngx_int_t
+ngx_http_fastcgi_create_request(ngx_http_request_t *r)
+{
+    u_char                             ch, *pos, addr_text[INET_ADDRSTRLEN],
+                                       port_text[sizeof("65535") - 1];
+    size_t                             size, len, index, padding,
+                                       addr_len, port_len;
+    off_t                              file_pos;
+    ngx_buf_t                         *b;
+    socklen_t                          slen;
+    ngx_chain_t                       *cl, *body;
+    ngx_uint_t                         i, n, next, *vindex, port;
+    ngx_list_part_t                   *part;
+    ngx_table_elt_t                   *header;
+    struct sockaddr_in                 sin, *sinp;
+    ngx_http_variable_t               *var;
+    ngx_http_variable_value_t         *value;
+    ngx_http_core_loc_conf_t          *clcf;
+    ngx_http_core_main_conf_t         *cmcf;
+    ngx_http_fastcgi_header_t         *h;
+    ngx_http_fastcgi_loc_conf_t       *flcf;
+    ngx_http_fastcgi_begin_request_t  *br;
+
+
+    flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
+
+    if ((flcf->params & NGX_HTTP_FASTCGI_SERVER_ADDR) && r->in_addr == 0) {
+
+        slen = sizeof(struct sockaddr_in);
+        if (getsockname(r->connection->fd,
+                        (struct sockaddr *) &sin, &slen) == -1)
+        {
+            ngx_log_error(NGX_LOG_CRIT, r->connection->log,
+                          ngx_socket_errno, "getsockname() failed");
+            return NGX_ERROR;
+        }
+
+        r->in_addr = sin.sin_addr.s_addr;
+    }
+
+    addr_len = ngx_inet_ntop(r->connection->listening->family, &r->in_addr,
+                             addr_text, INET_ADDRSTRLEN);
+    if (addr_len == 0) {
+        return NGX_ERROR;
+    }
+
+#if (NGX_SUPPRESS_WARN)
+    clcf = NULL;
+    var = NULL;
+    vindex = NULL;
+#endif
+
+
+    if (r->upstream->method) {
+        len = 1 + 1 + sizeof("REQUEST_METHOD") - 1
+                + ngx_http_fastcgi_methods[r->upstream->method - 1].len;
+    
+    } else {
+        len = 1 + ((r->method_name.len - 1 > 127) ? 4 : 1)
+                                            + sizeof("REQUEST_METHOD") - 1
+                                            + r->method_name.len - 1;
+    }
+
+
+    index = (r->uri.data[r->uri.len - 1] == '/') ? flcf->index.len : 0;
+
+    len += 1 + ((flcf->root.len + r->uri.len + index > 127) ? 4 : 1)
+        + sizeof("PATH_TRANSLATED") - 1 + flcf->root.len + r->uri.len + index;
+
+    if (r->args.len) {
+        len += 1 + ((r->args.len > 127) ? 4 : 1) + sizeof("QUERY_STRING") - 1
+            + r->args.len;
+    }
+
+    if (r->headers_in.content_length_n > 0) {
+        len += 1 + ((r->headers_in.content_length->value.len > 127) ? 4 : 1)
+            + sizeof("CONTENT_LENGTH") - 1
+            + r->headers_in.content_length->value.len;
+    }
+
+
+    if (r->headers_in.content_type) {
+        len += 1 + ((r->headers_in.content_type->value.len > 127) ? 4 : 1)
+            + sizeof("CONTENT_TYPE") - 1
+            + r->headers_in.content_type->value.len;
+    }
+
+
+    if (flcf->params & NGX_HTTP_FASTCGI_REDIRECT_STATUS) {
+        len += 1 + 1 + sizeof("REDIRECT_STATUS200") - 1;
+    }
+
+    if (flcf->params & NGX_HTTP_FASTCGI_REQUEST_URI) {
+        len += 1 + ((r->unparsed_uri.len > 127) ? 4 : 1)
+            + sizeof("REQUEST_URI") - 1 + r->unparsed_uri.len;
+    }
+
+    if (flcf->params & NGX_HTTP_FASTCGI_DOCUMENT_ROOT) {
+        clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+        len += 1 + ((clcf->root.len > 127) ? 4 : 1)
+            + sizeof("DOCUMENT_ROOT") - 1 + clcf->root.len;
+    }
+
+    if (flcf->params & NGX_HTTP_FASTCGI_SCRIPT_FILENAME) {
+        len += 1 + ((flcf->root.len + r->uri.len + index > 127) ? 4 : 1)
+            + sizeof("SCRIPT_FILENAME") - 1
+            + flcf->root.len + r->uri.len + index;
+    }
+
+    if (flcf->params & NGX_HTTP_FASTCGI_SCRIPT_NAME) {
+        len += 1 + ((r->uri.len + index > 127) ? 4 : 1)
+            + sizeof("SCRIPT_NAME") - 1 + r->uri.len + index ;
+    }
+
+    if (flcf->params & NGX_HTTP_FASTCGI_REMOTE_ADDR) {
+        len += 1 + 1 + sizeof("REMOTE_ADDR") - 1 + r->connection->addr_text.len;
+    }
+
+    port_len = 0;
+
+    if (flcf->params & NGX_HTTP_FASTCGI_REMOTE_PORT) {
+
+        /* AF_INET only */
+
+        if (r->connection->sockaddr->sa_family == AF_INET) {
+            sinp = (struct sockaddr_in *) r->connection->sockaddr;
+
+            port = ntohs(sinp->sin_port);
+
+            if (port > 0 && port < 65536) {
+                port_len = ngx_sprintf(port_text, "%ui", port) - port_text;
+            }
+
+            len += 1 + 1 + sizeof("REMOTE_PORT") - 1 + port_len;
+        }
+    }
+
+    if (flcf->params & NGX_HTTP_FASTCGI_SERVER_NAME) {
+        len += 1 + 1 + sizeof("SERVER_NAME") - 1 + r->server_name.len;
+    }
+
+    if (flcf->params & NGX_HTTP_FASTCGI_SERVER_PORT) {
+        len += 1 + 1 + sizeof("SERVER_PORT") - 1 + r->port_text->len - 1;
+    }
+
+    if (flcf->params & NGX_HTTP_FASTCGI_SERVER_ADDR) {
+        len += 1 + 1 + sizeof("SERVER_ADDR") - 1 + addr_len;
+    }
+
+    if (flcf->params & NGX_HTTP_FASTCGI_SERVER_PROTOCOL
+        && r->http_protocol.len)
+    {
+        len += 1 + ((r->http_protocol.len > 127) ? 4 : 1)
+            + sizeof("SERVER_PROTOCOL") - 1 + r->http_protocol.len;
+    }
+
+    if (flcf->params & NGX_HTTP_FASTCGI_SERVER_SOFTWARE) {
+        len += 1 + 1 + sizeof("SERVER_SOFTWARE") - 1 + sizeof(NGINX_VER) - 1;
+    }
+
+    if (flcf->params & NGX_HTTP_FASTCGI_GATEWAY_INTERFACE) {
+        len += 1 + 1 + sizeof("GATEWAY_INTERFACE") - 1 + sizeof("CGI/1.1") - 1;
+    }
+
+
+    if (flcf->vars) {
+        cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
+
+        var = cmcf->variables.elts;
+        vindex = flcf->vars->elts;
+
+        for (i = 0; i < flcf->vars->nelts; i++) {
+
+            value = ngx_http_get_indexed_variable(r, vindex[i]);
+            if (value == NULL) {
+                continue;
+            }
+
+            if (value->text.len) {
+                len += 1 + 1 + var[vindex[i]].name.len + value->text.len;
+            }
+        }
+    }
+
+
+    part = &r->headers_in.headers.part;
+    header = part->elts;
+
+    for (i = 0; /* void */; i++) {
+
+        if (i >= part->nelts) {
+            if (part->next == NULL) {
+                break;
+            }
+
+            part = part->next;
+            header = part->elts;
+            i = 0;
+        }
+
+        len += ((header[i].key.len > 127) ? 4 : 1)
+            + ((header[i].value.len > 127) ? 4 : 1)
+            + 5 + header[i].key.len + header[i].value.len;
+    }
+
+
+    if (len > 65535) {
+        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+                      "fastcgi: the request record is too big");
+        return NGX_ERROR;
+    }
+
+
+    padding = 8 - len % 8;
+    padding = (padding == 8) ? 0 : padding;
+
+
+    size = sizeof(ngx_http_fastcgi_header_t)
+           + sizeof(ngx_http_fastcgi_begin_request_t)
+
+           + sizeof(ngx_http_fastcgi_header_t)  /* NGX_HTTP_FASTCGI_PARAMS */
+           + len + padding
+           + sizeof(ngx_http_fastcgi_header_t)  /* NGX_HTTP_FASTCGI_PARAMS */
+
+           + sizeof(ngx_http_fastcgi_header_t); /* NGX_HTTP_FASTCGI_STDIN */
+
+
+    b = ngx_create_temp_buf(r->pool, size);
+    if (b == NULL) {
+        return NGX_ERROR;
+    }
+
+    cl = ngx_alloc_chain_link(r->pool);
+    if (cl == NULL) {
+        return NGX_ERROR;
+    }
+
+    cl->buf = b;
+
+    h = (ngx_http_fastcgi_header_t *) b->pos;
+
+    h->version = 1;
+    h->type = NGX_HTTP_FASTCGI_BEGIN_REQUEST;
+    h->request_id_hi = 0;
+    h->request_id_lo = 1;
+    h->content_length_hi = 0;
+    h->content_length_lo = sizeof(ngx_http_fastcgi_begin_request_t);
+    h->padding_length = 0;
+    h->reserved = 0;
+
+    br = (ngx_http_fastcgi_begin_request_t *)
+                                  (b->pos + sizeof(ngx_http_fastcgi_header_t));
+    br->role_hi = 0;
+    br->role_lo = NGX_HTTP_FASTCGI_RESPONDER;
+    br->flags = 0; /* NGX_HTTP_FASTCGI_KEEP_CONN */
+    br->reserved[0] = 0;
+    br->reserved[1] = 0;
+    br->reserved[2] = 0;
+    br->reserved[3] = 0;
+    br->reserved[4] = 0;
+
+    h = (ngx_http_fastcgi_header_t *)
+             (b->pos + sizeof(ngx_http_fastcgi_header_t)
+                     + sizeof(ngx_http_fastcgi_begin_request_t));
+
+    h->version = 1;
+    h->type = NGX_HTTP_FASTCGI_PARAMS;
+    h->request_id_hi = 0;
+    h->request_id_lo = 1;
+    h->content_length_hi = (u_char) ((len >> 8) & 0xff);
+    h->content_length_lo = (u_char) (len & 0xff);
+    h->padding_length = (u_char) padding;
+    h->reserved = 0;
+
+    b->last = b->pos + sizeof(ngx_http_fastcgi_header_t)
+                     + sizeof(ngx_http_fastcgi_begin_request_t)
+                     + sizeof(ngx_http_fastcgi_header_t);
+
+
+    *b->last++ = sizeof("PATH_TRANSLATED") - 1;
+
+    len = flcf->root.len + r->uri.len + index;
+    if (len > 127) {
+        *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
+        *b->last++ = (u_char) ((len >> 16) & 0xff);
+        *b->last++ = (u_char) ((len >> 8) & 0xff);
+        *b->last++ = (u_char) (len & 0xff);
+
+    } else {
+        *b->last++ = (u_char) len;
+    }
+
+    b->last = ngx_cpymem(b->last, "PATH_TRANSLATED",
+                         sizeof("PATH_TRANSLATED") - 1);
+    b->last = ngx_cpymem(b->last, flcf->root.data, flcf->root.len);
+    b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len);
+
+    if (index) {
+        b->last = ngx_cpymem(b->last, flcf->index.data, index);
+    }
+
+
+    *b->last++ = sizeof("REQUEST_METHOD") - 1;
+
+    if (r->upstream->method) {
+        *b->last++ = (u_char)
+                         ngx_http_fastcgi_methods[r->upstream->method - 1].len;
+
+        b->last = ngx_cpymem(b->last, "REQUEST_METHOD",
+                             sizeof("REQUEST_METHOD") - 1);
+
+        b->last = ngx_cpymem(b->last,
+                        ngx_http_fastcgi_methods[r->upstream->method - 1].data,
+                        ngx_http_fastcgi_methods[r->upstream->method - 1].len);
+
+    } else {
+        len = r->method_name.len - 1;
+        if (len > 127) {
+            *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
+            *b->last++ = (u_char) ((len >> 16) & 0xff);
+            *b->last++ = (u_char) ((len >> 8) & 0xff);
+            *b->last++ = (u_char) (len & 0xff);
+
+        } else {
+            *b->last++ = (u_char) len;
+        }
+
+        b->last = ngx_cpymem(b->last, "REQUEST_METHOD",
+                             sizeof("REQUEST_METHOD") - 1);
+        b->last = ngx_cpymem(b->last, r->method_name.data, len);
+    }
+
+
+    if (r->args.len) {
+        *b->last++ = sizeof("QUERY_STRING") - 1;
+
+        len = r->args.len;
+        if (len > 127) {
+            *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
+            *b->last++ = (u_char) ((len >> 16) & 0xff);
+            *b->last++ = (u_char) ((len >> 8) & 0xff);
+            *b->last++ = (u_char) (len & 0xff);
+
+        } else {
+            *b->last++ = (u_char) len;
+        }
+
+        b->last = ngx_cpymem(b->last, "QUERY_STRING",
+                             sizeof("QUERY_STRING") - 1);
+        b->last = ngx_cpymem(b->last, r->args.data, len);
+    }
+
+
+    if (r->headers_in.content_length_n > 0) {
+        *b->last++ = sizeof("CONTENT_LENGTH") - 1;
+
+        len = r->headers_in.content_length->value.len;
+        if (len > 127) {
+            *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
+            *b->last++ = (u_char) ((len >> 16) & 0xff);
+            *b->last++ = (u_char) ((len >> 8) & 0xff);
+            *b->last++ = (u_char) (len & 0xff);
+
+        } else {
+            *b->last++ = (u_char) len;
+        }
+
+        b->last = ngx_cpymem(b->last, "CONTENT_LENGTH",
+                             sizeof("CONTENT_LENGTH") - 1);
+        b->last = ngx_cpymem(b->last, r->headers_in.content_length->value.data,
+                             len);
+    }
+
+
+    if (r->headers_in.content_type) {
+        *b->last++ = sizeof("CONTENT_TYPE") - 1;
+
+        len = r->headers_in.content_type->value.len;
+        if (len > 127) {
+            *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
+            *b->last++ = (u_char) ((len >> 16) & 0xff);
+            *b->last++ = (u_char) ((len >> 8) & 0xff);
+            *b->last++ = (u_char) (len & 0xff);
+
+        } else {
+            *b->last++ = (u_char) len;
+        }
+
+        b->last = ngx_cpymem(b->last, "CONTENT_TYPE",
+                             sizeof("CONTENT_TYPE") - 1);
+        b->last = ngx_cpymem(b->last, r->headers_in.content_type->value.data,
+                             len);
+    }
+
+
+    if (flcf->params & NGX_HTTP_FASTCGI_REDIRECT_STATUS) {
+        *b->last++ = sizeof("REDIRECT_STATUS") - 1;
+        *b->last++ = sizeof("200") - 1;
+        b->last = ngx_cpymem(b->last, "REDIRECT_STATUS200",
+                             sizeof("REDIRECT_STATUS200") - 1);
+    }
+
+
+    if (flcf->params & NGX_HTTP_FASTCGI_REQUEST_URI) {
+        *b->last++ = sizeof("REQUEST_URI") - 1;
+
+        len = r->unparsed_uri.len;
+        if (len > 127) {
+            *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
+            *b->last++ = (u_char) ((len >> 16) & 0xff);
+            *b->last++ = (u_char) ((len >> 8) & 0xff);
+            *b->last++ = (u_char) (len & 0xff);
+
+        } else {
+            *b->last++ = (u_char) len;
+        }
+
+        b->last = ngx_cpymem(b->last, "REQUEST_URI", sizeof("REQUEST_URI") - 1);
+        b->last = ngx_cpymem(b->last, r->unparsed_uri.data, len);
+    }
+
+
+    if (flcf->params & NGX_HTTP_FASTCGI_DOCUMENT_ROOT) {
+        *b->last++ = sizeof("DOCUMENT_ROOT") - 1;
+
+        len = clcf->root.len;
+        if (len > 127) {
+            *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
+            *b->last++ = (u_char) ((len >> 16) & 0xff);
+            *b->last++ = (u_char) ((len >> 8) & 0xff);
+            *b->last++ = (u_char) (len & 0xff);
+
+        } else {
+            *b->last++ = (u_char) len;
+        }
+
+        b->last = ngx_cpymem(b->last, "DOCUMENT_ROOT",
+                             sizeof("DOCUMENT_ROOT") - 1);
+        b->last = ngx_cpymem(b->last, clcf->root.data, len);
+    }
+
+
+    if (flcf->params & NGX_HTTP_FASTCGI_SCRIPT_FILENAME) {
+        *b->last++ = sizeof("SCRIPT_FILENAME") - 1;
+
+        len = flcf->root.len + r->uri.len + index;
+        if (len > 127) {
+            *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
+            *b->last++ = (u_char) ((len >> 16) & 0xff);
+            *b->last++ = (u_char) ((len >> 8) & 0xff);
+            *b->last++ = (u_char) (len & 0xff);
+
+        } else {
+            *b->last++ = (u_char) len;
+        }
+
+        b->last = ngx_cpymem(b->last, "SCRIPT_FILENAME",
+                             sizeof("SCRIPT_FILENAME") - 1);
+        b->last = ngx_cpymem(b->last, flcf->root.data, flcf->root.len);
+        b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len);
+
+        if (index) {
+            b->last = ngx_cpymem(b->last, flcf->index.data, index);
+        }
+    }
+
+
+    if (flcf->params & NGX_HTTP_FASTCGI_SCRIPT_NAME) {
+        *b->last++ = sizeof("SCRIPT_NAME") - 1;
+
+        len = r->uri.len + index;
+        if (len > 127) {
+            *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
+            *b->last++ = (u_char) ((len >> 16) & 0xff);
+            *b->last++ = (u_char) ((len >> 8) & 0xff);
+            *b->last++ = (u_char) (len & 0xff);
+
+        } else {
+            *b->last++ = (u_char) len;
+        }
+
+        b->last = ngx_cpymem(b->last, "SCRIPT_NAME", sizeof("SCRIPT_NAME") - 1);
+        b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len);
+
+        if (index) {
+            b->last = ngx_cpymem(b->last, flcf->index.data, index);
+        }
+    }
+
+
+    if (flcf->params & NGX_HTTP_FASTCGI_REMOTE_ADDR) {
+        *b->last++ = sizeof("REMOTE_ADDR") - 1;
+        *b->last++ = (u_char) (r->connection->addr_text.len);
+        b->last = ngx_cpymem(b->last, "REMOTE_ADDR", sizeof("REMOTE_ADDR") - 1);
+        b->last = ngx_cpymem(b->last, r->connection->addr_text.data,
+                             r->connection->addr_text.len);
+    }
+
+
+    if (port_len) {
+        *b->last++ = sizeof("REMOTE_PORT") - 1;
+        *b->last++ = (u_char) port_len;
+        b->last = ngx_cpymem(b->last, "REMOTE_PORT", sizeof("REMOTE_PORT") - 1);
+        b->last = ngx_cpymem(b->last, port_text, port_len);
+    }
+
+
+    if (flcf->params & NGX_HTTP_FASTCGI_SERVER_NAME) {
+        *b->last++ = sizeof("SERVER_NAME") - 1;
+        *b->last++ = (u_char) r->server_name.len;
+        b->last = ngx_cpymem(b->last, "SERVER_NAME", sizeof("SERVER_NAME") - 1);
+        b->last = ngx_cpymem(b->last, r->server_name.data, r->server_name.len);
+    }
+
+
+    if (flcf->params & NGX_HTTP_FASTCGI_SERVER_PORT) {
+        *b->last++ = sizeof("SERVER_PORT") - 1;
+        *b->last++ = (u_char) (r->port_text->len - 1);
+        b->last = ngx_cpymem(b->last, "SERVER_PORT", sizeof("SERVER_PORT") - 1);
+        b->last = ngx_cpymem(b->last, r->port_text->data + 1,
+                             r->port_text->len - 1);
+    }
+
+
+    if (flcf->params & NGX_HTTP_FASTCGI_SERVER_ADDR) {
+        *b->last++ = sizeof("SERVER_ADDR") - 1;
+        *b->last++ = (u_char) addr_len;
+        b->last = ngx_cpymem(b->last, "SERVER_ADDR", sizeof("SERVER_ADDR") - 1);
+        b->last = ngx_cpymem(b->last, addr_text, addr_len);
+    }
+
+
+    if (flcf->params & NGX_HTTP_FASTCGI_SERVER_PROTOCOL
+        && r->http_protocol.len)
+    {
+        *b->last++ = sizeof("SERVER_PROTOCOL") - 1;
+
+        len = r->http_protocol.len;
+        if (len > 127) {
+            *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
+            *b->last++ = (u_char) ((len >> 16) & 0xff);
+            *b->last++ = (u_char) ((len >> 8) & 0xff);
+            *b->last++ = (u_char) (len & 0xff);
+
+        } else {
+            *b->last++ = (u_char) len;
+        }
+
+        b->last = ngx_cpymem(b->last, "SERVER_PROTOCOL",
+                             sizeof("SERVER_PROTOCOL") - 1);
+        b->last = ngx_cpymem(b->last, r->http_protocol.data, len);
+    }
+
+
+    if (flcf->params & NGX_HTTP_FASTCGI_SERVER_SOFTWARE) {
+        *b->last++ = sizeof("SERVER_SOFTWARE") - 1;
+        *b->last++ = (u_char) (sizeof(NGINX_VER) - 1);
+        b->last = ngx_cpymem(b->last, "SERVER_SOFTWARE",
+                             sizeof("SERVER_SOFTWARE") - 1);
+        b->last = ngx_cpymem(b->last, NGINX_VER, sizeof(NGINX_VER) - 1);
+    }
+
+
+    if (flcf->params & NGX_HTTP_FASTCGI_GATEWAY_INTERFACE) {
+        *b->last++ = sizeof("GATEWAY_INTERFACE") - 1;
+        *b->last++ = (u_char) (sizeof("CGI/1.1") - 1);
+        b->last = ngx_cpymem(b->last, "GATEWAY_INTERFACE",
+                             sizeof("GATEWAY_INTERFACE") - 1);
+        b->last = ngx_cpymem(b->last, "CGI/1.1", sizeof("CGI/1.1") - 1);
+    }
+
+
+    if (flcf->vars) {
+        for (i = 0; i < flcf->vars->nelts; i++) {
+
+            value = ngx_http_get_indexed_variable(r, vindex[i]);
+            if (value == NULL) {
+                continue;
+            }
+
+            if (value->text.len == 0) {
+                continue;
+            }
+
+            *b->last++ = (u_char) var[vindex[i]].name.len;
+            *b->last++ = (u_char) value->text.len;
+
+            b->last = ngx_cpymem(b->last, var[vindex[i]].name.data,
+                                 var[vindex[i]].name.len);
+
+            b->last = ngx_cpymem(b->last, value->text.data, value->text.len);
+        }
+    }
+
+
+    part = &r->headers_in.headers.part;
+    header = part->elts;
+
+    for (i = 0; /* void */; i++) {
+
+        if (i >= part->nelts) {
+            if (part->next == NULL) {
+                break;
+            }
+
+            part = part->next;
+            header = part->elts;
+            i = 0;
+        }
+
+        len = 5 + header[i].key.len;
+        if (len > 127) {
+            *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
+            *b->last++ = (u_char) ((len >> 16) & 0xff);
+            *b->last++ = (u_char) ((len >> 8) & 0xff);
+            *b->last++ = (u_char) (len & 0xff);
+
+        } else {
+            *b->last++ = (u_char) len;
+        }
+
+        len = header[i].value.len;
+        if (len > 127) {
+            *b->last++ = (u_char) (((len >> 24) & 0x7f) | 0x80);
+            *b->last++ = (u_char) ((len >> 16) & 0xff);
+            *b->last++ = (u_char) ((len >> 8) & 0xff);
+            *b->last++ = (u_char) (len & 0xff);
+
+        } else {
+            *b->last++ = (u_char) len;
+        }
+
+        b->last = ngx_cpymem(b->last, "HTTP_", sizeof("HTTP_") - 1);
+
+        for (n = 0; n < header[i].key.len; n++) {
+            ch = header[i].key.data[n];
+
+            if (ch >= 'a' && ch <= 'z') {
+                ch &= ~0x20;
+
+            } else if (ch == '-') {
+                ch = '_';
+            }
+
+            *b->last++ = ch;
+        }
+
+        b->last = ngx_cpymem(b->last, header[i].value.data,
+                             header[i].value.len);
+    }
+
+
+    if (padding) {
+        ngx_memzero(b->last, padding);
+        b->last += padding;
+    }
+
+
+    h = (ngx_http_fastcgi_header_t *) b->last;
+    b->last += sizeof(ngx_http_fastcgi_header_t);
+
+    h->version = 1;
+    h->type = NGX_HTTP_FASTCGI_PARAMS;
+    h->request_id_hi = 0;
+    h->request_id_lo = 1;
+    h->content_length_hi = 0;
+    h->content_length_lo = 0;
+    h->padding_length = 0;
+    h->reserved = 0;
+
+    h = (ngx_http_fastcgi_header_t *) b->last;
+    b->last += sizeof(ngx_http_fastcgi_header_t);
+
+    body = r->request_body->bufs;
+    r->request_body->bufs = cl;
+
+#if (NGX_SUPPRESS_WARN)
+    file_pos = 0;
+    pos = NULL;
+#endif
+
+    while (body) {
+
+        if (body->buf->in_file) {
+            file_pos = body->buf->file_pos;
+
+        } else {
+            pos = body->buf->pos;
+        }
+
+        next = 0;
+
+        do {
+            b = ngx_alloc_buf(r->pool);
+            if (b == NULL) {
+                return NGX_ERROR;
+            }
+
+            ngx_memcpy(b, body->buf, sizeof(ngx_buf_t));
+
+            if (body->buf->in_file) {
+                b->file_pos = file_pos;
+                file_pos += 32 * 1024;
+
+                if (file_pos > body->buf->file_last) {
+                    file_pos = body->buf->file_last;
+                    next = 1;
+                }
+
+                b->file_last = file_pos;
+                len = (ngx_uint_t) (file_pos - b->file_pos);
+
+            } else {
+                b->pos = pos;
+                pos += 32 * 1024;
+
+                if (pos > body->buf->last) {
+                    pos = body->buf->last;
+                    next = 1;
+                }
+
+                b->last = pos;
+                len = (ngx_uint_t) (pos - b->pos);
+            }
+
+            padding = 8 - len % 8;
+            padding = (padding == 8) ? 0 : padding;
+
+            h->version = 1;
+            h->type = NGX_HTTP_FASTCGI_STDIN;
+            h->request_id_hi = 0;
+            h->request_id_lo = 1;
+            h->content_length_hi = (u_char) ((len >> 8) & 0xff);
+            h->content_length_lo = (u_char) (len & 0xff);
+            h->padding_length = (u_char) padding;
+            h->reserved = 0;
+
+            cl->next = ngx_alloc_chain_link(r->pool);
+            if (cl->next == NULL) {
+                return NGX_ERROR;
+            }
+
+            cl = cl->next;
+            cl->buf = b;
+
+            b = ngx_create_temp_buf(r->pool, sizeof(ngx_http_fastcgi_header_t)
+                                             + padding);
+            if (b == NULL) {
+                return NGX_ERROR;
+            }
+
+            if (padding) {
+                ngx_memzero(b->last, padding);
+                b->last += padding;
+            }
+
+            h = (ngx_http_fastcgi_header_t *) b->last;
+            b->last += sizeof(ngx_http_fastcgi_header_t);
+
+            cl->next = ngx_alloc_chain_link(r->pool);
+            if (cl->next == NULL) {
+                return NGX_ERROR;
+            }
+
+            cl = cl->next;
+            cl->buf = b;
+
+        } while (!next);
+
+        body = body->next;
+    }
+
+    h->version = 1;
+    h->type = NGX_HTTP_FASTCGI_STDIN;
+    h->request_id_hi = 0;
+    h->request_id_lo = 1;
+    h->content_length_hi = 0;
+    h->content_length_lo = 0;
+    h->padding_length = 0;
+    h->reserved = 0;
+
+    cl->next = NULL;
+
+    return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_fastcgi_reinit_request(ngx_http_request_t *r)
+{
+    ngx_http_fastcgi_ctx_t  *f;
+
+    f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
+
+    if (f == NULL) {
+        return NGX_OK;
+    }
+
+    f->state = ngx_http_fastcgi_st_version;
+    f->header = 0;
+
+    ngx_memzero(&f->upstream->headers_in,
+                sizeof(ngx_http_fastcgi_headers_in_t));
+
+    if (f->upstream->headers_in.headers.part.elts) {
+        if (ngx_list_init(&f->upstream->headers_in.headers, r->pool, 8,
+                                         sizeof(ngx_table_elt_t)) == NGX_ERROR)
+        {
+            return NGX_ERROR;
+        }
+    }
+
+    return NGX_OK;
+}
+
+
+static ngx_int_t ngx_http_fastcgi_process_header(ngx_http_request_t *r)
+{
+    u_char                  *start, *last;
+    ngx_str_t               *status_line, line;
+    ngx_int_t                rc, status;
+    ngx_uint_t               i;
+    ngx_table_elt_t         *h;
+    ngx_http_upstream_t     *u;
+    ngx_http_fastcgi_ctx_t  *f;
+
+    f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
+
+    if (f == NULL) {
+        f = ngx_pcalloc(r->pool, sizeof(ngx_http_fastcgi_ctx_t));
+        if (f == NULL) {
+            return NGX_HTTP_INTERNAL_SERVER_ERROR;
+        }
+
+        ngx_http_set_ctx(r, f, ngx_http_fastcgi_module);
+
+        f->upstream = ngx_pcalloc(r->pool, sizeof(ngx_http_fastcgi_upstream_t));
+        if (f->upstream == NULL) {
+            return NGX_HTTP_INTERNAL_SERVER_ERROR;
+        }
+
+        if (ngx_list_init(&f->upstream->headers_in.headers, r->pool, 8,
+                                         sizeof(ngx_table_elt_t)) == NGX_ERROR)
+        {
+            return NGX_HTTP_INTERNAL_SERVER_ERROR;
+        }
+    }
+
+    u = r->upstream;
+
+    for ( ;; ) {
+
+        if (f->state < ngx_http_fastcgi_st_data) {
+
+            f->pos = u->header_in.pos;
+            f->last = u->header_in.last;
+
+            rc = ngx_http_fastcgi_process_record(r, f);
+
+            u->header_in.pos = f->pos;
+            u->header_in.last = f->last;
+
+            if (rc == NGX_AGAIN) {
+                return NGX_AGAIN;
+            }
+
+            if (rc == NGX_ERROR) {
+                return NGX_HTTP_UPSTREAM_INVALID_HEADER;
+            }
+
+            if (f->type != NGX_HTTP_FASTCGI_STDOUT
+                && f->type != NGX_HTTP_FASTCGI_STDERR)
+            {
+                ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                              "upstream sent unexpected FastCGI record: %d",
+                              f->type);
+
+                return NGX_HTTP_UPSTREAM_INVALID_HEADER;
+            }
+
+            if (f->type == NGX_HTTP_FASTCGI_STDOUT && f->length == 0) {
+                ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                              "upstream closed prematurely FastCGI stdout");
+
+                return NGX_HTTP_UPSTREAM_INVALID_HEADER;
+            }
+        }
+
+        if (f->state == ngx_http_fastcgi_st_padding) {
+
+            if (u->header_in.pos + f->padding < u->header_in.last) {
+                f->state = ngx_http_fastcgi_st_version;
+                u->header_in.pos += f->padding;
+
+                continue;
+            }
+
+            if (u->header_in.pos + f->padding == u->header_in.last) {
+                f->state = ngx_http_fastcgi_st_version;
+                u->header_in.pos = u->header_in.last;
+
+                return NGX_AGAIN;
+            }
+
+            f->padding -= u->header_in.last - u->header_in.pos;
+            u->header_in.pos = u->header_in.last;
+
+            return NGX_AGAIN;
+        }
+
+
+        /* f->state == ngx_http_fastcgi_st_data */
+
+        if (f->type == NGX_HTTP_FASTCGI_STDERR) {
+
+            if (f->header) {
+                ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+                              "upstream split a header in FastCGI records");
+
+                return NGX_HTTP_UPSTREAM_INVALID_HEADER;
+            }
+
+            if (f->length) {
+                line.data = u->header_in.pos;
+
+                if (u->header_in.pos + f->length <= u->header_in.last) {
+                    line.len = f->length;
+                    u->header_in.pos += f->length;
+                    f->length = 0;
+                    f->state = ngx_http_fastcgi_st_padding;
+
+                } else { 
+                    line.len = u->header_in.last - u->header_in.pos;
+                    f->length -= u->header_in.last - u->header_in.pos;
+                    u->header_in.pos = u->header_in.last;
+                }
+
+                while (line.data[line.len - 1] == LF
+                       || line.data[line.len - 1] == CR
+                       || line.data[line.len - 1] == '.'
+                       || line.data[line.len - 1] == ' ')
+                {
+                    line.len--;
+                }
+
+                ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                              "FastCGI sent in stderr: \"%V\"", &line);
+
+                if (u->header_in.pos == u->header_in.last) {
+                    return NGX_AGAIN;
+                }
+
+            } else {
+                f->state = ngx_http_fastcgi_st_version;
+            }
+
+            continue;
+        }
+
+
+        /* f->type == NGX_HTTP_FASTCGI_STDOUT */
+
+        start = u->header_in.pos;
+
+        if (u->header_in.pos + f->length < u->header_in.last) {
+
+            /*
+             * set u->header_in.last to the end of the FastCGI record data
+             * for ngx_http_parse_header_line()
+             */
+
+            last = u->header_in.last;
+            u->header_in.last = u->header_in.pos + f->length;
+
+        } else {
+            last = NULL;
+        }
+
+        f->header = 1;
+
+        for ( ;; ) {
+
+            rc = ngx_http_parse_header_line(r, &u->header_in);
+
+            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                           "http fastcgi parser: %d", rc);
+
+            if (rc == NGX_AGAIN) {
+                break;
+            }
+
+            if (rc == NGX_OK) {
+
+                /* a header line has been parsed successfully */
+
+                h = ngx_list_push(&f->upstream->headers_in.headers);
+                if (h == NULL) {
+                    return NGX_HTTP_INTERNAL_SERVER_ERROR;
+                }
+
+                h->key.len = r->header_name_end - r->header_name_start;
+                h->value.len = r->header_end - r->header_start;
+
+                h->key.data = ngx_palloc(r->pool,
+                                         h->key.len + 1 + h->value.len + 1);
+                if (h->key.data == NULL) {
+                    return NGX_HTTP_INTERNAL_SERVER_ERROR;
+                }
+
+                h->value.data = h->key.data + h->key.len + 1;
+
+                ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1);
+                ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1);
+
+                for (i = 0; ngx_http_fastcgi_headers_in[i].name.len != 0; i++) {
+                    if (ngx_http_fastcgi_headers_in[i].name.len != h->key.len) {
+                        continue;
+                    }
+
+                    if (ngx_strcasecmp(ngx_http_fastcgi_headers_in[i].name.data,
+                                                             h->key.data) == 0)
+                    {
+                        *((ngx_table_elt_t **)
+                                 ((char *) &f->upstream->headers_in
+                                 + ngx_http_fastcgi_headers_in[i].offset)) = h;
+                        break;
+                    }
+                }
+
+                ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                               "http fastcgi header: \"%V: %V\"",
+                               &h->key, &h->value);
+
+                continue;
+            }
+
+            if (rc == NGX_HTTP_PARSE_HEADER_DONE) {
+
+                /* a whole header has been parsed successfully */
+
+                ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                               "http fastcgi header done");
+
+                if (f->upstream->headers_in.status) {
+                    status_line = &f->upstream->headers_in.status->value;
+
+                    status = ngx_atoi(status_line->data, 3);
+
+                    if (status == NGX_ERROR) {
+                        return NGX_HTTP_INTERNAL_SERVER_ERROR;
+                    }
+
+                    r->headers_out.status = status;
+                    r->headers_out.status_line = *status_line;
+
+                } else {
+                    r->headers_out.status = 200;
+                    r->headers_out.status_line.len = sizeof("200 OK") - 1;
+                    r->headers_out.status_line.data = (u_char *) "200 OK";
+                }
+
+                u->state->status = r->headers_out.status;
+#if 0
+                if (u->cachable) {
+                    u->cachable = ngx_http_upstream_is_cachable(r);
+                }
+#endif
+
+                break;
+            }
+
+            /* there was error while a header line parsing */
+
+            ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                          ngx_http_upstream_header_errors[rc
+                                                - NGX_HTTP_PARSE_HEADER_ERROR]);
+
+            return NGX_HTTP_UPSTREAM_INVALID_HEADER;
+
+        }
+
+        if (last) {
+            u->header_in.last = last;
+        }
+
+        f->length -= u->header_in.pos - start;
+
+        if (rc == NGX_AGAIN) {
+            if (u->header_in.pos == u->header_in.last) {
+                return NGX_AGAIN;
+            }
+
+            ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+                          "upstream split a header in FastCGI records");
+
+            return NGX_HTTP_UPSTREAM_INVALID_HEADER;
+        }
+
+        if (f->length == 0) {
+            if (f->padding) {
+                f->state = ngx_http_fastcgi_st_padding;
+            } else {
+                f->state = ngx_http_fastcgi_st_version;
+            }
+        }
+
+        return NGX_OK;
+    }
+}
+
+
+static ngx_int_t
+ngx_http_fastcgi_send_header(ngx_http_request_t *r)
+{
+    ngx_uint_t                      i;
+    ngx_list_part_t                *part;
+    ngx_table_elt_t                *ho, *h;
+    ngx_http_fastcgi_ctx_t         *f;
+    ngx_http_fastcgi_headers_in_t  *headers_in;
+
+    f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
+
+    headers_in = &f->upstream->headers_in;
+    part = &headers_in->headers.part;
+    h = part->elts;
+
+    for (i = 0; /* void */; i++) {
+
+        if (i >= part->nelts) {
+            if (part->next == NULL) {
+                break;
+            }
+
+            part = part->next;
+            h = part->elts;
+            i = 0;
+        }
+
+        /* ignore some headers */
+
+        if (&h[i] == headers_in->status) {
+            continue;
+        }
+
+
+        if (&h[i] == headers_in->x_powered_by
+            && !r->upstream->conf->x_powered_by)
+        {
+            continue;
+        }
+
+
+        /* "Content-Type" is handled specially */
+
+        if (&h[i] == headers_in->content_type) {
+            r->headers_out.content_type = &h[i];
+            r->headers_out.content_type->key.len = 0;
+            continue;
+        }
+
+
+        /* copy some header pointers and set up r->headers_out */
+
+        ho = ngx_list_push(&r->headers_out.headers);
+        if (ho == NULL) {
+            return NGX_HTTP_INTERNAL_SERVER_ERROR;
+        }
+
+        *ho = h[i];
+
+#if (NGX_HTTP_GZIP)
+        if (&h[i] == headers_in->content_encoding) {
+            r->headers_out.content_encoding = ho;
+            continue;
+        }
+#endif
+
+        if (&h[i] == headers_in->content_length) {
+            r->headers_out.content_length = ho;
+            r->headers_out.content_length_n = ngx_atoi(ho->value.data,
+                                                       ho->value.len);
+            continue;
+        }
+    }
+
+    return ngx_http_send_header(r);
+}
+
+
+static ngx_int_t
+ngx_http_fastcgi_input_filter(ngx_event_pipe_t *p, ngx_buf_t *buf)
+{
+    ngx_int_t                rc;
+    ngx_buf_t               *b, **prev;
+    ngx_str_t                line;
+    ngx_chain_t             *cl;
+    ngx_http_request_t      *r;
+    ngx_http_fastcgi_ctx_t  *f;
+
+    if (buf->pos == buf->last) {
+        return NGX_OK;
+    }
+
+    r = p->input_ctx;
+    f = ngx_http_get_module_ctx(r, ngx_http_fastcgi_module);
+
+    b = NULL;
+    prev = &buf->shadow;
+
+    f->pos = buf->pos;
+    f->last = buf->last;
+
+    for ( ;; ) {
+        if (f->state < ngx_http_fastcgi_st_data) {
+
+            rc = ngx_http_fastcgi_process_record(r, f);
+
+            if (rc == NGX_AGAIN) {
+                break;
+            }
+
+            if (rc == NGX_ERROR) {
+                return NGX_ERROR;
+            }
+
+            if (f->type == NGX_HTTP_FASTCGI_STDOUT && f->length == 0) {
+                f->state = ngx_http_fastcgi_st_version;
+                p->upstream_done = 1;
+
+                ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
+                               "http fastcgi closed stdout");
+
+                continue;
+            }
+
+            if (f->type == NGX_HTTP_FASTCGI_END_REQUEST) {
+                f->state = ngx_http_fastcgi_st_version;
+                p->upstream_done = 1;
+
+                ngx_log_debug0(NGX_LOG_DEBUG_HTTP, p->log, 0,
+                               "http fastcgi sent end request");
+
+                break;
+            }
+        }
+
+
+        if (f->state == ngx_http_fastcgi_st_padding) {
+
+            if (f->pos + f->padding < f->last) {
+                f->state = ngx_http_fastcgi_st_version;
+                f->pos += f->padding;
+
+                continue;
+            }
+
+            if (f->pos + f->padding == f->last) {
+                f->state = ngx_http_fastcgi_st_version;
+
+                break;
+            }
+
+            f->padding -= f->last - f->pos;
+
+            break;
+        }
+
+
+        /* f->state == ngx_http_fastcgi_st_data */
+
+        if (f->type == NGX_HTTP_FASTCGI_STDERR) {
+
+            if (f->length) {
+                line.data = f->pos;
+
+                if (f->pos + f->length <= f->last) {
+                    line.len = f->length;
+                    f->pos += f->length;
+                    f->length = 0;
+                    f->state = ngx_http_fastcgi_st_padding;
+
+                } else { 
+                    line.len = f->last - f->pos;
+                    f->length -= f->last - f->pos;
+                    f->pos = f->last;
+                }
+
+                while (line.data[line.len - 1] == LF
+                       || line.data[line.len - 1] == CR
+                       || line.data[line.len - 1] == '.'
+                       || line.data[line.len - 1] == ' ')
+                {
+                    line.len--;
+                }
+
+                ngx_log_error(NGX_LOG_ERR, p->log, 0,
+                              "FastCGI sent in stderr: \"%V\"", &line);
+
+                if (f->pos == f->last) {
+                    break;
+                }
+
+            } else {
+                f->state = ngx_http_fastcgi_st_version;
+            }
+
+            continue;
+        }
+
+
+        /* f->type == NGX_HTTP_FASTCGI_STDOUT */
+
+        if (p->free) {
+            b = p->free->buf;
+            p->free = p->free->next;
+
+        } else {
+            b = ngx_alloc_buf(p->pool);
+            if (b == NULL) {
+                return NGX_ERROR;
+            }
+        }
+
+        ngx_memzero(b, sizeof(ngx_buf_t));
+
+        b->pos = f->pos;
+        b->start = buf->start;
+        b->end = buf->end;
+        b->tag = p->tag;
+        b->temporary = 1;
+        b->recycled = 1;
+
+        *prev = b;
+        prev = &b->shadow;
+
+        cl = ngx_alloc_chain_link(p->pool);
+        if (cl == NULL) {
+            return NGX_ERROR;
+        }
+
+        cl->buf = b;
+        cl->next = NULL;
+
+        if (p->in) {
+            *p->last_in = cl;
+        } else {
+            p->in = cl;
+        }
+        p->last_in = &cl->next;
+
+
+        /* STUB */ b->num = buf->num;
+
+        ngx_log_debug1(NGX_LOG_DEBUG_EVENT, p->log, 0, "input buf #%d", b->num);
+
+
+        if (f->pos + f->length < f->last) {
+
+            if (f->padding) {
+                f->state = ngx_http_fastcgi_st_padding;
+            } else {
+                f->state = ngx_http_fastcgi_st_version;
+            }
+
+            f->pos += f->length;
+            b->last = f->pos;
+
+            continue;
+        }
+
+        if (f->pos + f->length == f->last) {
+
+            if (f->padding) {
+                f->state = ngx_http_fastcgi_st_padding;
+            } else {
+                f->state = ngx_http_fastcgi_st_version;
+            }
+
+            b->last = f->last;
+
+            break;
+        }
+
+        f->length -= f->last - f->pos;
+
+        b->last = f->last;
+
+        break;
+
+    }
+
+    if (b) {
+        b->shadow = buf;
+        b->last_shadow = 1;
+
+        return NGX_OK;
+    }
+
+    /* there is no data record in the buf, add it to free chain */
+
+    if (ngx_event_pipe_add_free_buf(p, buf) != NGX_OK) {
+        return NGX_ERROR;
+    }
+
+    return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_fastcgi_process_record(ngx_http_request_t *r,
+    ngx_http_fastcgi_ctx_t *f)
+{
+    u_char                     ch, *p;
+    ngx_http_fastcgi_state_e   state;
+
+    state = f->state;
+
+    for (p = f->pos; p < f->last; p++) {
+
+        ch = *p;
+
+        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                       "http fastcgi record byte: %02Xd", ch);
+
+        switch (state) {
+
+        case ngx_http_fastcgi_st_version:
+            if (ch != 1) {
+                ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                              "upstream sent unsupported FastCGI "
+                              "protocol version: %d", ch);
+                return NGX_ERROR;
+            }
+            state = ngx_http_fastcgi_st_type;
+            break;
+
+        case ngx_http_fastcgi_st_type:
+            switch (ch) {
+            case NGX_HTTP_FASTCGI_STDOUT:
+            case NGX_HTTP_FASTCGI_STDERR:
+            case NGX_HTTP_FASTCGI_END_REQUEST:
+                 f->type = (ngx_uint_t) ch;
+                 break;
+            default:
+                ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                              "upstream sent invalid FastCGI "
+                              "record type: %d", ch);
+                return NGX_ERROR;
+
+            }
+            state = ngx_http_fastcgi_st_request_id_hi;
+            break;
+
+        /* we support the single request per connection */
+
+        case ngx_http_fastcgi_st_request_id_hi:
+            if (ch != 0) {
+                ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                              "upstream sent unexpected FastCGI "
+                              "request id high byte: %d", ch);
+                return NGX_ERROR;
+            }
+            state = ngx_http_fastcgi_st_request_id_lo;
+            break;
+
+        case ngx_http_fastcgi_st_request_id_lo:
+            if (ch != 1) {
+                ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                              "upstream sent unexpected FastCGI "
+                              "request id low byte: %d", ch);
+                return NGX_ERROR;
+            }
+            state = ngx_http_fastcgi_st_content_length_hi;
+            break;
+
+        case ngx_http_fastcgi_st_content_length_hi:
+            f->length = ch << 8;
+            state = ngx_http_fastcgi_st_content_length_lo;
+            break;
+
+        case ngx_http_fastcgi_st_content_length_lo:
+            f->length |= (size_t) ch;
+            state = ngx_http_fastcgi_st_padding_length;
+            break;
+
+        case ngx_http_fastcgi_st_padding_length:
+            f->padding = (size_t) ch;
+            state = ngx_http_fastcgi_st_reserved;
+            break;
+
+        case ngx_http_fastcgi_st_reserved:
+            state = ngx_http_fastcgi_st_data;
+
+            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                           "http fastcgi record length: %z", f->length);
+
+            f->pos = p + 1;
+            f->state = state;
+
+            return NGX_OK;
+
+        /* suppress warning */
+        case ngx_http_fastcgi_st_data:
+        case ngx_http_fastcgi_st_padding:
+            break;
+        }
+    }
+
+    f->pos = p + 1;
+    f->state = state;
+
+    return NGX_AGAIN;
+}
+
+
+static void
+ngx_http_fastcgi_abort_request(ngx_http_request_t *r)
+{
+    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                   "abort http fastcgi request");
+
+    return;
+}
+
+
+static void
+ngx_http_fastcgi_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
+{
+    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                   "finalize http fastcgi request");
+
+    return;
+}
+
+
+static char *
+ngx_http_fastcgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+    ngx_http_fastcgi_loc_conf_t *lcf = conf;
+
+    ngx_str_t                   *value;
+    ngx_inet_upstream_t          inet_upstream;
+    ngx_http_core_loc_conf_t    *clcf;
+#if (NGX_HAVE_UNIX_DOMAIN)
+    ngx_unix_domain_upstream_t   unix_upstream;
+#endif
+
+    value = cf->args->elts;
+
+    if (ngx_strncasecmp(value[1].data, "unix:", 5) == 0) {
+
+#if (NGX_HAVE_UNIX_DOMAIN)
+
+        ngx_memzero(&unix_upstream, sizeof(ngx_unix_domain_upstream_t));
+
+        unix_upstream.name = value[1];
+        unix_upstream.url = value[1];
+
+        lcf->peers = ngx_unix_upstream_parse(cf, &unix_upstream);
+        if (lcf->peers == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+#else
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                           "the unix domain sockets are not supported "
+                           "on this platform");
+        return NGX_CONF_ERROR;
+
+#endif
+
+    } else {
+        ngx_memzero(&inet_upstream, sizeof(ngx_inet_upstream_t));
+
+        inet_upstream.name = value[1];
+        inet_upstream.url = value[1];
+    
+        lcf->peers = ngx_inet_upstream_parse(cf, &inet_upstream);
+        if (lcf->peers == NULL) {
+            return NGX_CONF_ERROR;
+        }
+    }
+
+    clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
+
+    clcf->handler = ngx_http_fastcgi_handler;
+
+#if (NGX_PCRE)
+    lcf->location = clcf->regex ? &ngx_http_fastcgi_uri : &clcf->name;
+#else
+    lcf->location = &clcf->name;
+#endif
+
+    if (clcf->name.data[clcf->name.len - 1] == '/') {
+        clcf->auto_redirect = 1;
+    }
+
+    return NGX_CONF_OK;
+}
+
+
+static char *
+ngx_http_fastcgi_set_var(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+    ngx_http_fastcgi_loc_conf_t *lcf = conf;
+
+    ngx_uint_t                  i, *index;
+    ngx_str_t                  *value;
+    ngx_http_variable_t        *var;
+    ngx_http_core_main_conf_t  *cmcf;
+
+    if (lcf->vars == NULL) {
+        lcf->vars = ngx_array_create(cf->pool, 4,
+                                     sizeof(ngx_http_variable_t *));
+        if (lcf->vars == NULL) {
+            return NGX_CONF_ERROR;
+        }
+    }
+
+    cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
+
+    value = cf->args->elts;
+
+    var = cmcf->variables.elts;
+    for (i = 0; i < cmcf->variables.nelts; i++) {
+        if (ngx_strcasecmp(var[i].name.data, value[1].data) == 0) {
+
+            index = ngx_array_push(lcf->vars);
+            if (index == NULL) {
+                return NGX_CONF_ERROR;
+            }
+
+            *index = var[i].index;
+            return NGX_CONF_OK;
+        }
+    }
+
+    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                       "unknown variable name \"%V\"", &value[1]);
+    return NGX_CONF_ERROR;
+}
+
+
+static char *
+ngx_http_fastcgi_lowat_check(ngx_conf_t *cf, void *post, void *data)
+{
+#if (NGX_FREEBSD)
+    ssize_t *np = data;
+
+    if (*np >= ngx_freebsd_net_inet_tcp_sendspace) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                           "\"fastcgi_send_lowat\" must be less than %d "
+                           "(sysctl net.inet.tcp.sendspace)",
+                           ngx_freebsd_net_inet_tcp_sendspace);
+
+        return NGX_CONF_ERROR;
+    }
+
+#elif !(NGX_HAVE_SO_SNDLOWAT)
+    ssize_t *np = data;
+
+    ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+                       "\"fastcgi_send_lowat\" is not supported, ignored");
+
+    *np = 0;
+
+#endif
+
+    return NGX_CONF_OK;
+}
+
+
+static void *
+ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf)
+{
+    ngx_http_fastcgi_loc_conf_t  *conf;
+
+    conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_fastcgi_loc_conf_t));
+    if (conf == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    /*
+     * set by ngx_pcalloc():
+     *
+     *     conf->upstream.bufs.num = 0;
+     *     conf->upstream.path = NULL;
+     *     conf->upstream.next_upstream = 0;
+     *     conf->upstream.temp_path = NULL;
+     *     conf->params = 0;
+     *     conf->root.len = 0;
+     *     conf->root.data = NULL;
+     *     conf->index.len = 0;
+     *     conf->index.data = NULL;
+     *     conf->location = NULL;
+     */
+
+    conf->upstream.connect_timeout = NGX_CONF_UNSET_MSEC;
+    conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC;
+    conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE;
+
+    conf->upstream.header_buffer_size = NGX_CONF_UNSET_SIZE;
+    conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC;
+    conf->upstream.busy_buffers_size = NGX_CONF_UNSET_SIZE;
+
+    conf->upstream.max_temp_file_size = NGX_CONF_UNSET_SIZE; 
+    conf->upstream.temp_file_write_size = NGX_CONF_UNSET_SIZE;
+    
+    conf->upstream.redirect_errors = NGX_CONF_UNSET;
+    conf->upstream.x_powered_by = NGX_CONF_UNSET;
+
+    /* "fastcgi_cyclic_temp_file" is disabled */
+    conf->upstream.cyclic_temp_file = 0;
+
+    return conf;
+}
+
+
+static char *
+ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
+{
+    ngx_http_fastcgi_loc_conf_t *prev = parent;
+    ngx_http_fastcgi_loc_conf_t *conf = child;
+
+    size_t  size;
+
+    ngx_conf_merge_msec_value(conf->upstream.connect_timeout,
+                              prev->upstream.connect_timeout, 60000);
+    ngx_conf_merge_msec_value(conf->upstream.send_timeout,
+                              prev->upstream.send_timeout, 60000);
+    ngx_conf_merge_size_value(conf->upstream.send_lowat,
+                              prev->upstream.send_lowat, 0);
+
+    ngx_conf_merge_msec_value(conf->upstream.read_timeout,
+                              prev->upstream.read_timeout, 60000);
+
+    ngx_conf_merge_msec_value(conf->upstream.redirect_errors,
+                              prev->upstream.redirect_errors, 0);
+
+    ngx_conf_merge_msec_value(conf->upstream.x_powered_by,
+                              prev->upstream.x_powered_by, 1);
+
+
+    ngx_conf_merge_size_value(conf->upstream.header_buffer_size, 
+                              prev->upstream.header_buffer_size,
+                              (size_t) ngx_pagesize);
+
+    ngx_conf_merge_bufs_value(conf->upstream.bufs, prev->upstream.bufs,
+                              8, ngx_pagesize);
+
+    if (conf->upstream.bufs.num < 2) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                           "there must be at least 2 \"fastcgi_buffers\"");
+        return NGX_CONF_ERROR;
+    }
+
+
+    size = conf->upstream.header_buffer_size;
+    if (size < conf->upstream.bufs.size) {
+        size = conf->upstream.bufs.size;
+    }
+
+
+    ngx_conf_merge_size_value(conf->upstream.busy_buffers_size, 
+                              prev->upstream.busy_buffers_size,
+                              NGX_CONF_UNSET_SIZE);
+
+    if (conf->upstream.busy_buffers_size == NGX_CONF_UNSET_SIZE) {
+        conf->upstream.busy_buffers_size = 2 * size;
+
+    } else if (conf->upstream.busy_buffers_size < size) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+             "\"fastcgi_busy_buffers_size\" must be equal or bigger than "
+             "maximum of the value of \"fastcgi_header_buffer_size\" and "
+             "one of the \"fastcgi_buffers\"");
+
+        return NGX_CONF_ERROR;
+
+    } else if (conf->upstream.busy_buffers_size
+               > (conf->upstream.bufs.num - 1) * conf->upstream.bufs.size)
+    {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+             "\"fastcgi_busy_buffers_size\" must be less than "
+             "the size of all \"fastcgi_buffers\" minus one buffer");
+
+        return NGX_CONF_ERROR;
+    }
+
+
+    ngx_conf_merge_size_value(conf->upstream.temp_file_write_size, 
+                              prev->upstream.temp_file_write_size,
+                              NGX_CONF_UNSET_SIZE);
+
+    if (conf->upstream.temp_file_write_size == NGX_CONF_UNSET_SIZE) {
+        conf->upstream.temp_file_write_size = 2 * size;
+
+    } else if (conf->upstream.temp_file_write_size < size) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+             "\"fastcgi_temp_file_write_size\" must be equal or bigger than "
+             "maximum of the value of \"fastcgi_header_buffer_size\" and "
+             "one of the \"fastcgi_buffers\"");
+
+        return NGX_CONF_ERROR;
+    }
+
+
+    ngx_conf_merge_size_value(conf->upstream.max_temp_file_size,
+                              prev->upstream.max_temp_file_size,
+                              NGX_CONF_UNSET_SIZE);
+
+    if (conf->upstream.max_temp_file_size == NGX_CONF_UNSET_SIZE) {
+
+        conf->upstream.max_temp_file_size = 1024 * 1024 * 1024;
+
+    } else if (conf->upstream.max_temp_file_size != 0
+               && conf->upstream.max_temp_file_size < size)
+    {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+             "\"fastcgi_max_temp_file_size\" must be equal to zero to disable "
+             "the temporary files usage or must be equal or bigger than "
+             "maximum of the value of \"fastcgi_header_buffer_size\" and "
+             "one of the \"fastcgi_buffers\"");
+
+        return NGX_CONF_ERROR;
+    }
+
+
+    ngx_conf_merge_bitmask_value(conf->upstream.next_upstream,
+                              prev->upstream.next_upstream,
+                              (NGX_CONF_BITMASK_SET
+                               |NGX_HTTP_UPSTREAM_FT_ERROR
+                               |NGX_HTTP_UPSTREAM_FT_TIMEOUT));
+
+    ngx_conf_merge_path_value(conf->upstream.temp_path,
+                              prev->upstream.temp_path,
+                              NGX_HTTP_FASTCGI_TEMP_PATH, 1, 2, 0,
+                              ngx_garbage_collector_temp_handler, cf);
+
+
+    ngx_conf_merge_bitmask_value(conf->params, prev->params,
+                              (NGX_CONF_BITMASK_SET
+                               |NGX_HTTP_FASTCGI_REMOTE_ADDR
+                               |NGX_HTTP_FASTCGI_REMOTE_USER
+                               |NGX_HTTP_FASTCGI_SERVER_NAME
+                               |NGX_HTTP_FASTCGI_SERVER_PORT
+                               |NGX_HTTP_FASTCGI_SCRIPT_NAME
+                               |NGX_HTTP_FASTCGI_AUTH_TYPE
+                               |NGX_HTTP_FASTCGI_REQUEST_URI
+                               |NGX_HTTP_FASTCGI_REDIRECT_STATUS));
+
+    ngx_conf_merge_str_value(conf->root, prev->root, "");
+
+    if (conf->root.len && conf->root.data[conf->root.len - 1] == '/') {
+        conf->root.len--;
+    }
+
+    ngx_conf_merge_str_value(conf->index, prev->index, "");
+
+    if (conf->vars == NULL) {
+        conf->vars = prev->vars;
+    }
+
+    return NGX_CONF_OK;
+}
--- a/src/http/modules/ngx_http_geo_module.c
+++ b/src/http/modules/ngx_http_geo_module.c
@@ -64,9 +64,9 @@ 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)
+ngx_http_geo_variable(ngx_http_request_t *r, uintptr_t data)
 {
-    ngx_radix_tree_t *tree = data;
+    ngx_radix_tree_t *tree = (ngx_radix_tree_t *) data;
 
     struct sockaddr_in         *sin;
     ngx_http_variable_value_t  *var;
@@ -90,33 +90,46 @@ static char *
 ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
 {
     char                 *rv;
-    ngx_str_t            *value;
+    ngx_str_t            *value, name;
     ngx_conf_t            save;
     ngx_pool_t           *pool;
     ngx_radix_tree_t     *tree;
     ngx_http_geo_conf_t   geo;
     ngx_http_variable_t  *var;
 
-    if (!(var = ngx_http_add_variable(cf))) {
+    value = cf->args->elts;
+
+    name = value[1];
+
+    if (name.data[0] != '$') {
+        ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+                           "\"%V\" variable name should start with '$'",
+                           &value[1]);
+    } else {
+        name.len--;
+        name.data++;
+    }
+
+    var = ngx_http_add_variable(cf, &name, 1);
+    if (var == NULL) {
         return NGX_CONF_ERROR;
     }
 
-    if (!(tree = ngx_radix_tree_create(cf->pool, -1))) {
+    tree = ngx_radix_tree_create(cf->pool, -1);
+    if (tree == NULL) {
         return NGX_CONF_ERROR;
     }
 
-    value = cf->args->elts;
-
-    var->name = value[1];
     var->handler = ngx_http_geo_variable;
-    var->data = tree;
+    var->data = (uintptr_t) tree;
 
     /*
      * create the temporary pool of a huge initial size
      * to process quickly a large number of geo lines
      */
 
-    if (!(pool = ngx_create_pool(512 * 1024, cf->log))) {
+    pool = ngx_create_pool(512 * 1024, cf->log);
+    if (pool == NULL) {
         return NGX_CONF_ERROR;
     }
 
@@ -212,7 +225,12 @@ ngx_http_geo(ngx_conf_t *cf, ngx_command
 
     if (n == NGX_ERROR) {
         for (i = 0; i < geo->values.nelts; i++) {
-            if (ngx_strcmp(value[1].data, v[i]->text.data) == 0) {
+            if (v[i]->text.len != value[1].len) {
+                continue;
+            }
+
+            if (ngx_strncmp(value[1].data, v[i]->text.data, value[1].len) == 0)
+            {
                 var = v[i];
                 break;
             }
@@ -227,20 +245,22 @@ ngx_http_geo(ngx_conf_t *cf, ngx_command
         }
     }
 
-    if (i == geo->values.nelts) {
+    if (var == NULL) {
         var = ngx_palloc(geo->pool, sizeof(ngx_http_variable_value_t));
         if (var == NULL) {
             return NGX_CONF_ERROR;
         }
 
         var->text.len = value[1].len;
-        if (!(var->text.data = ngx_pstrdup(geo->pool, &value[1]))) {
+        var->text.data = ngx_pstrdup(geo->pool, &value[1]);
+        if (var->text.data == NULL) {
             return NGX_CONF_ERROR;
         }
 
         var->value = (n == NGX_ERROR) ? 0 : n;
 
-        if (!(v = ngx_array_push(&geo->values))) {
+        v = ngx_array_push(&geo->values);
+        if (v == NULL) {
             return NGX_CONF_ERROR;
         }
 
deleted file mode 100644
--- a/src/http/modules/ngx_http_gzip_filter.c
+++ /dev/null
@@ -1,1142 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-#include <zlib.h>
-
-
-typedef struct {
-    ngx_flag_t           enable;
-    ngx_flag_t           no_buffer;
-
-    ngx_array_t         *types;     /* array of ngx_http_gzip_type_t */
-
-    ngx_bufs_t           bufs;
-
-    ngx_uint_t           http_version;
-    ngx_uint_t           proxied;
-
-    int                  level;
-    size_t               wbits;
-    size_t               memlevel;
-    ssize_t              min_length;
-} ngx_http_gzip_conf_t;
-
-
-typedef struct {
-    ngx_str_t            name;
-    ngx_uint_t           enable;
-} ngx_http_gzip_type_t;
-
-
-#define NGX_HTTP_GZIP_PROXIED_OFF       0x0002
-#define NGX_HTTP_GZIP_PROXIED_EXPIRED   0x0004
-#define NGX_HTTP_GZIP_PROXIED_NO_CACHE  0x0008
-#define NGX_HTTP_GZIP_PROXIED_NO_STORE  0x0010
-#define NGX_HTTP_GZIP_PROXIED_PRIVATE   0x0020
-#define NGX_HTTP_GZIP_PROXIED_NO_LM     0x0040
-#define NGX_HTTP_GZIP_PROXIED_NO_ETAG   0x0080
-#define NGX_HTTP_GZIP_PROXIED_AUTH      0x0100
-#define NGX_HTTP_GZIP_PROXIED_ANY       0x0200
-
-
-typedef struct {
-    ngx_chain_t         *in;
-    ngx_chain_t         *free;
-    ngx_chain_t         *busy;
-    ngx_chain_t         *out;
-    ngx_chain_t        **last_out;
-    ngx_buf_t           *in_buf;
-    ngx_buf_t           *out_buf;
-    ngx_int_t            bufs;
-
-    off_t                length;
-
-    void                *preallocated;
-    char                *free_mem;
-    ngx_uint_t           allocated;
-
-    unsigned             flush:4;
-    unsigned             redo:1;
-    unsigned             done:1;
-
-    size_t               zin;
-    size_t               zout;
-
-    uint32_t             crc32;
-    z_stream             zstream;
-    ngx_http_request_t  *request;
-} ngx_http_gzip_ctx_t;
-
-
-static ngx_int_t ngx_http_gzip_proxied(ngx_http_request_t *r,
-    ngx_http_gzip_conf_t *conf);
-static void *ngx_http_gzip_filter_alloc(void *opaque, u_int items,
-    u_int size);
-static void ngx_http_gzip_filter_free(void *opaque, void *address);
-static void ngx_http_gzip_error(ngx_http_gzip_ctx_t *ctx);
-
-static u_char *ngx_http_gzip_log_ratio(ngx_http_request_t *r, u_char *buf,
-    ngx_http_log_op_t *op);
-
-static ngx_int_t ngx_http_gzip_add_log_formats(ngx_conf_t *cf);
-
-static ngx_int_t ngx_http_gzip_filter_init(ngx_cycle_t *cycle);
-static void *ngx_http_gzip_create_conf(ngx_conf_t *cf);
-static char *ngx_http_gzip_merge_conf(ngx_conf_t *cf,
-    void *parent, void *child);
-static char *ngx_http_gzip_set_types(ngx_conf_t *cf, ngx_command_t *cmd,
-    void *conf);
-static char *ngx_http_gzip_set_window(ngx_conf_t *cf, void *post, void *data);
-static char *ngx_http_gzip_set_hash(ngx_conf_t *cf, void *post, void *data);
-
-
-static ngx_conf_num_bounds_t  ngx_http_gzip_comp_level_bounds = {
-    ngx_conf_check_num_bounds, 1, 9
-};
-
-static ngx_conf_post_handler_pt  ngx_http_gzip_set_window_p =
-                                                      ngx_http_gzip_set_window;
-static ngx_conf_post_handler_pt  ngx_http_gzip_set_hash_p =
-                                                        ngx_http_gzip_set_hash;
-
-
-
-static ngx_conf_enum_t  ngx_http_gzip_http_version[] = {
-    { ngx_string("1.0"), NGX_HTTP_VERSION_10 },
-    { ngx_string("1.1"), NGX_HTTP_VERSION_11 },
-    { ngx_null_string, 0 }
-};
-
-
-static ngx_conf_bitmask_t  ngx_http_gzip_proxied_mask[] = {
-    { ngx_string("off"), NGX_HTTP_GZIP_PROXIED_OFF },
-    { ngx_string("expired"), NGX_HTTP_GZIP_PROXIED_EXPIRED },
-    { ngx_string("no-cache"), NGX_HTTP_GZIP_PROXIED_NO_CACHE },
-    { ngx_string("no-store"), NGX_HTTP_GZIP_PROXIED_NO_STORE },
-    { ngx_string("private"), NGX_HTTP_GZIP_PROXIED_PRIVATE },
-    { ngx_string("no_last_modified"), NGX_HTTP_GZIP_PROXIED_NO_LM },
-    { ngx_string("no_etag"), NGX_HTTP_GZIP_PROXIED_NO_ETAG },
-    { ngx_string("auth"), NGX_HTTP_GZIP_PROXIED_AUTH },
-    { ngx_string("any"), NGX_HTTP_GZIP_PROXIED_ANY },
-    { ngx_null_string, 0 }
-};
-
-
-static ngx_command_t  ngx_http_gzip_filter_commands[] = {
-
-    { ngx_string("gzip"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
-                        |NGX_CONF_FLAG,
-      ngx_conf_set_flag_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_gzip_conf_t, enable),
-      NULL },
-
-    { ngx_string("gzip_buffers"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
-      ngx_conf_set_bufs_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_gzip_conf_t, bufs),
-      NULL },
-
-    { ngx_string("gzip_types"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
-      ngx_http_gzip_set_types,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      0,
-      NULL },
-
-    { ngx_string("gzip_comp_level"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
-      ngx_conf_set_num_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_gzip_conf_t, level),
-      &ngx_http_gzip_comp_level_bounds },
-
-    { ngx_string("gzip_window"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
-      ngx_conf_set_size_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_gzip_conf_t, wbits),
-      &ngx_http_gzip_set_window_p },
-
-    { ngx_string("gzip_hash"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
-      ngx_conf_set_size_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_gzip_conf_t, memlevel),
-      &ngx_http_gzip_set_hash_p },
-
-    { ngx_string("gzip_no_buffer"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
-      ngx_conf_set_flag_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_gzip_conf_t, no_buffer),
-      NULL },
-
-    { ngx_string("gzip_http_version"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_ANY,
-      ngx_conf_set_enum_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_gzip_conf_t, http_version),
-      &ngx_http_gzip_http_version },
-
-    { ngx_string("gzip_proxied"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_ANY,
-      ngx_conf_set_bitmask_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_gzip_conf_t, proxied),
-      &ngx_http_gzip_proxied_mask },
-
-    { ngx_string("gzip_min_length"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
-      ngx_conf_set_size_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_gzip_conf_t, min_length),
-      NULL },
-
-      ngx_null_command
-};
-
-
-static ngx_http_module_t  ngx_http_gzip_filter_module_ctx = {
-    ngx_http_gzip_add_log_formats,         /* pre conf */
-
-    NULL,                                  /* create main configuration */
-    NULL,                                  /* init main configuration */
-
-    NULL,                                  /* create server configuration */
-    NULL,                                  /* merge server configuration */
-
-    ngx_http_gzip_create_conf,             /* create location configuration */
-    ngx_http_gzip_merge_conf               /* merge location configuration */
-};
-
-
-ngx_module_t  ngx_http_gzip_filter_module = {
-    NGX_MODULE,
-    &ngx_http_gzip_filter_module_ctx,      /* module context */
-    ngx_http_gzip_filter_commands,         /* module directives */
-    NGX_HTTP_MODULE,                       /* module type */
-    ngx_http_gzip_filter_init,             /* init module */
-    NULL                                   /* init process */
-};
-
-
-static ngx_http_log_op_name_t ngx_http_gzip_log_fmt_ops[] = {
-    { ngx_string("gzip_ratio"), NGX_INT32_LEN + 3,
-                                NULL, NULL, ngx_http_gzip_log_ratio },
-    { ngx_null_string, 0, NULL, NULL, NULL }
-};
-
-
-
-static u_char  gzheader[10] = { 0x1f, 0x8b, Z_DEFLATED, 0, 0, 0, 0, 0, 0, 3 };
-
-#if (NGX_HAVE_LITTLE_ENDIAN && NGX_HAVE_NONALIGNED)
-
-struct gztrailer {
-    uint32_t  crc32;
-    uint32_t  zlen;
-};
-
-#else /* NGX_HAVE_BIG_ENDIAN || !NGX_HAVE_NONALIGNED */
-
-struct gztrailer {
-    u_char  crc32[4];
-    u_char  zlen[4];
-};
-
-#endif
-
-
-static ngx_http_output_header_filter_pt  ngx_http_next_header_filter;
-static ngx_http_output_body_filter_pt    ngx_http_next_body_filter;
-
-
-static ngx_int_t
-ngx_http_gzip_header_filter(ngx_http_request_t *r)
-{
-    ngx_uint_t             i, found;
-    ngx_http_gzip_ctx_t   *ctx;
-    ngx_http_gzip_conf_t  *conf;
-    ngx_http_gzip_type_t  *type;
-
-    conf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_filter_module);
-
-    if (!conf->enable
-        || (r->headers_out.status != NGX_HTTP_OK
-            && r->headers_out.status != NGX_HTTP_FORBIDDEN
-            && r->headers_out.status != NGX_HTTP_NOT_FOUND)
-        || r->header_only
-        || r->http_version < conf->http_version
-        || r->headers_out.content_type == NULL
-        || (r->headers_out.content_encoding
-            && r->headers_out.content_encoding->value.len)
-        || r->headers_in.accept_encoding == NULL
-        || (r->headers_out.content_length_n != -1
-            && r->headers_out.content_length_n < conf->min_length)
-        || ngx_strstr(r->headers_in.accept_encoding->value.data, "gzip") == NULL
-       )
-    {
-        return ngx_http_next_header_filter(r);
-    }
-
-
-    found = 0;
-    type = conf->types->elts;
-
-    for (i = 0; i < conf->types->nelts; i++) {
-        if (r->headers_out.content_type->value.len >= type[i].name.len
-            && ngx_strncasecmp(r->headers_out.content_type->value.data, 
-                               type[i].name.data, type[i].name.len) == 0)
-        {
-            found = 1;
-            break;
-        }
-    }
-
-    if (!found) {
-        return ngx_http_next_header_filter(r);
-    }
-
-
-    if (r->headers_in.via) {
-        if (conf->proxied & NGX_HTTP_GZIP_PROXIED_OFF) {
-            return ngx_http_next_header_filter(r);
-        }
-
-        if (!(conf->proxied & NGX_HTTP_GZIP_PROXIED_ANY)
-            && ngx_http_gzip_proxied(r, conf) == NGX_DECLINED)
-        {
-            return ngx_http_next_header_filter(r);
-        }
-    }
-
-
-    /*
-     * if the URL (without the "http://" prefix) is longer than 253 bytes
-     * then MSIE 4.x can not handle the compressed stream - it waits too long,
-     * hangs up or crashes
-     */
-
-    if (r->headers_in.msie4 && r->unparsed_uri.len > 200) {
-        return ngx_http_next_header_filter(r);
-    }
-
-
-    ngx_http_create_ctx(r, ctx, ngx_http_gzip_filter_module,
-                        sizeof(ngx_http_gzip_ctx_t), NGX_ERROR);
-    ctx->request = r;
-
-    r->headers_out.content_encoding = ngx_list_push(&r->headers_out.headers);
-    if (r->headers_out.content_encoding == NULL) {
-        return NGX_ERROR;
-    }
-
-    r->headers_out.content_encoding->key.len = sizeof("Content-Encoding") - 1;
-    r->headers_out.content_encoding->key.data = (u_char *) "Content-Encoding";
-    r->headers_out.content_encoding->value.len = sizeof("gzip") - 1;
-    r->headers_out.content_encoding->value.data = (u_char *) "gzip";
-
-    ctx->length = r->headers_out.content_length_n;
-    r->headers_out.content_length_n = -1;
-    if (r->headers_out.content_length) {
-        r->headers_out.content_length->key.len = 0;
-        r->headers_out.content_length = NULL;
-    }
-    r->filter_need_in_memory = 1;
-
-    return ngx_http_next_header_filter(r);
-}
-
-
-static ngx_int_t
-ngx_http_gzip_proxied(ngx_http_request_t *r, ngx_http_gzip_conf_t *conf)
-{
-    time_t  date, expires;
-
-    if (r->headers_in.authorization
-        && (conf->proxied & NGX_HTTP_GZIP_PROXIED_AUTH))
-    {
-        return NGX_OK;
-    }
-
-    if (r->headers_out.expires) {
-
-        if (!(conf->proxied & NGX_HTTP_GZIP_PROXIED_EXPIRED)) {
-            return NGX_DECLINED;
-        }
-
-        expires = ngx_http_parse_time(r->headers_out.expires->value.data,
-                                      r->headers_out.expires->value.len);
-        if (expires == NGX_ERROR) {
-            return NGX_DECLINED;
-        }
-
-        if (r->headers_out.date) {
-            date = ngx_http_parse_time(r->headers_out.date->value.data,
-                                       r->headers_out.date->value.len);
-            if (date == NGX_ERROR) {
-                return NGX_DECLINED;
-            }
-
-        } else {
-            date = ngx_time();
-        }
-
-        if (expires < date) {
-            return NGX_OK;
-        }
-
-        return NGX_DECLINED;
-    }
-
-    if (r->headers_out.cache_control) {
-
-        if ((conf->proxied & NGX_HTTP_GZIP_PROXIED_NO_CACHE)
-            && ngx_strstr(r->headers_out.cache_control->value.data, "no-cache"))
-        {
-            return NGX_OK;
-        }
-
-        if ((conf->proxied & NGX_HTTP_GZIP_PROXIED_NO_STORE)
-            && ngx_strstr(r->headers_out.cache_control->value.data, "no-store"))
-        {
-            return NGX_OK;
-        }
-
-        if ((conf->proxied & NGX_HTTP_GZIP_PROXIED_PRIVATE)
-            && ngx_strstr(r->headers_out.cache_control->value.data, "private"))
-        {
-            return NGX_OK;
-        }
-
-        return NGX_DECLINED;
-    }
-
-    if ((conf->proxied & NGX_HTTP_GZIP_PROXIED_NO_LM)
-        && r->headers_out.last_modified)
-    {
-        return NGX_DECLINED;
-    }
-
-    if ((conf->proxied & NGX_HTTP_GZIP_PROXIED_NO_ETAG)
-        && r->headers_out.etag)
-    {
-        return NGX_DECLINED;
-    }
-
-    return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_gzip_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
-{
-    int                    rc, wbits, memlevel;
-    ngx_int_t              last;
-    struct gztrailer      *trailer;
-    ngx_buf_t             *b;
-    ngx_chain_t           *cl;
-    ngx_http_gzip_ctx_t   *ctx;
-    ngx_http_gzip_conf_t  *conf;
-
-    ctx = ngx_http_get_module_ctx(r, ngx_http_gzip_filter_module);
-
-    if (ctx == NULL || ctx->done) {
-        return ngx_http_next_body_filter(r, in);
-    }
-
-    conf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_filter_module);
-
-    if (ctx->preallocated == NULL) {
-        wbits = conf->wbits;
-        memlevel = conf->memlevel;
-
-        if (ctx->length > 0) {
-
-            /* the actual zlib window size is smaller by 262 bytes */
-
-            while (ctx->length < ((1 << (wbits - 1)) - 262)) {
-                wbits--;
-                memlevel--;
-            }
-        }
-
-        /*
-         * We preallocate a memory for zlib in one buffer (200K-400K), this
-         * decreases a number of malloc() and free() calls and also probably
-         * decreases a number of syscalls (sbrk() and so on).
-         * Besides we free this memory as soon as the gzipping will complete
-         * and do not wait while a whole response will be sent to a client.
-         *
-         * 8K is for zlib deflate_state, it takes
-         *  * 5816 bytes on x86 and sparc64 (32-bit mode)
-         *  * 5920 bytes on amd64 and sparc64
-         */
-
-        ctx->allocated = 8192 + (1 << (wbits + 2)) + (1 << (memlevel + 9));
-
-        if (!(ctx->preallocated = ngx_palloc(r->pool, ctx->allocated))) {
-            return NGX_ERROR;
-        }
-
-        ctx->free_mem = ctx->preallocated;
-
-        ctx->zstream.zalloc = ngx_http_gzip_filter_alloc;
-        ctx->zstream.zfree = ngx_http_gzip_filter_free;
-        ctx->zstream.opaque = ctx;
-
-        rc = deflateInit2(&ctx->zstream, conf->level, Z_DEFLATED,
-                          -wbits, memlevel, Z_DEFAULT_STRATEGY);
-
-        if (rc != Z_OK) {
-            ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
-                          "deflateInit2() failed: %d", rc);
-            ngx_http_gzip_error(ctx);
-            return NGX_ERROR;
-        }
-
-        if (!(b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)))) {
-            ngx_http_gzip_error(ctx);
-            return NGX_ERROR;
-        }
-
-        b->memory = 1;
-        b->pos = gzheader;
-        b->last = b->pos + 10;
-
-        if (!(cl = ngx_alloc_chain_link(r->pool))) {
-            ngx_http_gzip_error(ctx);
-            return NGX_ERROR;
-        }
-        cl->buf = b;
-        cl->next = NULL;
-
-        /*
-         * We pass the gzheader to the next filter now to avoid its linking
-         * to the ctx->busy chain.  zlib does not usually output the compressed
-         * data in the initial iterations, so the gzheader that was linked
-         * to the ctx->busy chain would be flushed by ngx_http_write_filter().
-         */
-
-        if (ngx_http_next_body_filter(r, cl) == NGX_ERROR) {
-            ngx_http_gzip_error(ctx);
-            return NGX_ERROR;
-        }
-
-        ctx->last_out = &ctx->out;
-
-        ctx->crc32 = crc32(0L, Z_NULL, 0);
-        ctx->flush = Z_NO_FLUSH;
-    }
-
-    if (in) {
-        if (ngx_chain_add_copy(r->pool, &ctx->in, in) == NGX_ERROR) {
-            ngx_http_gzip_error(ctx);
-            return NGX_ERROR;
-        }
-    }
-
-    last = NGX_NONE;
-
-    for ( ;; ) {
-
-        for ( ;; ) {
-
-            /* does zlib need a new data ? */
-
-            if (ctx->zstream.avail_in == 0
-                && ctx->flush == Z_NO_FLUSH
-                && !ctx->redo)
-            {
-                ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                               "gzip in: %p", ctx->in);
-
-                if (ctx->in == NULL) {
-                    break;
-                }
-
-                ctx->in_buf = ctx->in->buf;
-                ctx->in = ctx->in->next;
-
-                ctx->zstream.next_in = ctx->in_buf->pos;
-                ctx->zstream.avail_in = ctx->in_buf->last - ctx->in_buf->pos;
-
-                ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                               "gzip in_buf:%p ni:%p ai:%ud",
-                               ctx->in_buf,
-                               ctx->zstream.next_in, ctx->zstream.avail_in);
-
-                /* STUB */
-                if (ctx->in_buf->last < ctx->in_buf->pos) {
-                    ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
-                                  "zstream.avail_in is huge");
-                    ctx->done = 1;
-                    return NGX_ERROR;
-                }
-                /**/
-
-                if (ctx->in_buf->last_buf) {
-                    ctx->flush = Z_FINISH;
-
-                } else if (ctx->in_buf->flush) {
-                    ctx->flush = Z_SYNC_FLUSH;
-                }
-
-                if (ctx->zstream.avail_in == 0) {
-                    if (ctx->flush == Z_NO_FLUSH) {
-                        continue;
-                    }
-
-                } else {
-                    ctx->crc32 = crc32(ctx->crc32, ctx->zstream.next_in,
-                                       ctx->zstream.avail_in);
-                }
-            }
-
-
-            /* is there a space for the gzipped data ? */
-
-            if (ctx->zstream.avail_out == 0) {
-
-                if (ctx->free) {
-                    ctx->out_buf = ctx->free->buf;
-                    ctx->free = ctx->free->next;
-
-                } else if (ctx->bufs < conf->bufs.num) {
-                    ctx->out_buf = ngx_create_temp_buf(r->pool,
-                                                       conf->bufs.size);
-                    if (ctx->out_buf == NULL) {
-                        ngx_http_gzip_error(ctx);
-                        return NGX_ERROR;
-                    }
-
-                    ctx->out_buf->tag = (ngx_buf_tag_t)
-                                                  &ngx_http_gzip_filter_module;
-                    ctx->out_buf->recycled = 1;
-                    ctx->bufs++;
-
-                } else {
-                    break;
-                }
-
-                ctx->zstream.next_out = ctx->out_buf->pos;
-                ctx->zstream.avail_out = conf->bufs.size;
-            }
-
-            ngx_log_debug6(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                         "deflate in: ni:%p no:%p ai:%ud ao:%ud fl:%d redo:%d",
-                         ctx->zstream.next_in, ctx->zstream.next_out,
-                         ctx->zstream.avail_in, ctx->zstream.avail_out,
-                         ctx->flush, ctx->redo);
-
-            rc = deflate(&ctx->zstream, ctx->flush);
-
-            if (rc != Z_OK && rc != Z_STREAM_END) {
-                ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
-                              "deflate() failed: %d, %d", ctx->flush, rc);
-                ngx_http_gzip_error(ctx);
-                return NGX_ERROR;
-            }
-
-            ngx_log_debug5(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                           "deflate out: ni:%p no:%p ai:%ud ao:%ud rc:%d",
-                           ctx->zstream.next_in, ctx->zstream.next_out,
-                           ctx->zstream.avail_in, ctx->zstream.avail_out,
-                           rc);
-
-            ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                           "gzip in_buf:%p pos:%p",
-                           ctx->in_buf, ctx->in_buf->pos);
-
-
-            if (ctx->zstream.next_in) {
-                ctx->in_buf->pos = ctx->zstream.next_in;
-
-                if (ctx->zstream.avail_in == 0) {
-                    ctx->zstream.next_in = NULL;
-                }
-            }
-
-            ctx->out_buf->last = ctx->zstream.next_out;
-
-            if (ctx->zstream.avail_out == 0) {
-
-                /* zlib wants to output some more gzipped data */
-
-                if (!(cl = ngx_alloc_chain_link(r->pool))) {
-                    ngx_http_gzip_error(ctx);
-                    return NGX_ERROR;
-                }
-                cl->buf = ctx->out_buf;
-                cl->next = NULL;
-                *ctx->last_out = cl;
-                ctx->last_out = &cl->next;
-
-                ctx->redo = 1;
-
-                continue;
-            }
-
-            ctx->redo = 0;
-
-            if (ctx->flush == Z_SYNC_FLUSH) {
-
-                ctx->out_buf->flush = 0;
-                ctx->flush = Z_NO_FLUSH;
-
-                if (!(cl = ngx_alloc_chain_link(r->pool))) {
-                    ngx_http_gzip_error(ctx);
-                    return NGX_ERROR;
-                }
-                cl->buf = ctx->out_buf;
-                cl->next = NULL;
-                *ctx->last_out = cl;
-                ctx->last_out = &cl->next;
-
-                break;
-            }
-
-            if (rc == Z_STREAM_END) {
-
-                ctx->zin = ctx->zstream.total_in;
-                ctx->zout = 10 + ctx->zstream.total_out + 8;
-
-                rc = deflateEnd(&ctx->zstream);
-
-                if (rc != Z_OK) {
-                    ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
-                                  "deflateEnd() failed: %d", rc);
-                    ngx_http_gzip_error(ctx);
-                    return NGX_ERROR;
-                }
-
-                ngx_pfree(r->pool, ctx->preallocated);
-
-                if (!(cl = ngx_alloc_chain_link(r->pool))) {
-                    ngx_http_gzip_error(ctx);
-                    return NGX_ERROR;
-                }
-                cl->buf = ctx->out_buf;
-                cl->next = NULL;
-                *ctx->last_out = cl;
-                ctx->last_out = &cl->next;
-
-                if (ctx->zstream.avail_out >= 8) {
-                    trailer = (struct gztrailer *) ctx->out_buf->last;
-                    ctx->out_buf->last += 8;
-                    ctx->out_buf->last_buf = 1;
-
-                } else {
-                    if (!(b = ngx_create_temp_buf(r->pool, 8))) {
-                        ngx_http_gzip_error(ctx);
-                        return NGX_ERROR;
-                    }
-
-                    b->last_buf = 1;
-
-                    if (!(cl = ngx_alloc_chain_link(r->pool))) {
-                        ngx_http_gzip_error(ctx);
-                        return NGX_ERROR;
-                    }
-                    cl->buf = b;
-                    cl->next = NULL;
-                    *ctx->last_out = cl;
-                    ctx->last_out = &cl->next;
-                    trailer = (struct gztrailer *) b->pos;
-                    b->last += 8;
-                }
-
-#if (NGX_HAVE_LITTLE_ENDIAN && NGX_HAVE_NONALIGNED)
-
-                trailer->crc32 = ctx->crc32;
-                trailer->zlen = ctx->zin;
-
-#else
-                trailer->crc32[0] = (u_char) (ctx->crc32 & 0xff);
-                trailer->crc32[1] = (u_char) ((ctx->crc32 >> 8) & 0xff);
-                trailer->crc32[2] = (u_char) ((ctx->crc32 >> 16) & 0xff);
-                trailer->crc32[3] = (u_char) ((ctx->crc32 >> 24) & 0xff);
-
-                trailer->zlen[0] = (u_char) (ctx->zin & 0xff);
-                trailer->zlen[1] = (u_char) ((ctx->zin >> 8) & 0xff);
-                trailer->zlen[2] = (u_char) ((ctx->zin >> 16) & 0xff);
-                trailer->zlen[3] = (u_char) ((ctx->zin >> 24) & 0xff);
-#endif
-
-                ctx->zstream.avail_in = 0;
-                ctx->zstream.avail_out = 0;
-
-                ctx->done = 1;
-
-                break;
-            }
-
-            if (conf->no_buffer && ctx->in == NULL) {
-                if (!(cl = ngx_alloc_chain_link(r->pool))) {
-                    ngx_http_gzip_error(ctx);
-                    return NGX_ERROR;
-                }
-                cl->buf = ctx->out_buf;
-                cl->next = NULL;
-                *ctx->last_out = cl;
-                ctx->last_out = &cl->next;
-
-                break;
-            }
-        }
-
-        if (last == NGX_AGAIN && !ctx->done) {
-            return NGX_AGAIN;
-        }
-
-        if (ctx->out == NULL && ctx->busy == NULL) {
-            return NGX_OK;
-        }
-
-        last = ngx_http_next_body_filter(r, ctx->out);
-
-        /*
-         * we do not check NGX_AGAIN here because the downstream filters
-         * may free some buffers and zlib may compress some data into them
-         */
-
-        if (last == NGX_ERROR) {
-            ngx_http_gzip_error(ctx);
-            return NGX_ERROR;
-        }
-
-        ngx_chain_update_chains(&ctx->free, &ctx->busy, &ctx->out,
-                                 (ngx_buf_tag_t) &ngx_http_gzip_filter_module);
-        ctx->last_out = &ctx->out;
-
-        if (ctx->done) {
-            return last;
-        }
-    }
-}
-
-
-static void *
-ngx_http_gzip_filter_alloc(void *opaque, u_int items, u_int size)
-{
-    ngx_http_gzip_ctx_t *ctx = opaque;
-
-    void        *p;
-    ngx_uint_t   alloc;
-
-    alloc = items * size;
-
-    if (alloc % 512 != 0) {
-
-        /*
-         * The zlib deflate_state allocation, it takes about 6K,
-         * we allocate 8K.  Other allocations are divisible by 512.
-         */
-
-        alloc = (alloc + ngx_pagesize - 1) & ~(ngx_pagesize - 1);
-    }
-
-    if (alloc <= ctx->allocated) {
-        p = ctx->free_mem;
-        ctx->free_mem += alloc;
-        ctx->allocated -= alloc;
-
-        ngx_log_debug4(NGX_LOG_DEBUG_HTTP, ctx->request->connection->log, 0,
-                       "gzip alloc: n:%ud s:%ud a:%ud p:%p",
-                       items, size, alloc, p);
-
-        return p;
-    }
-
-    ngx_log_error(NGX_LOG_ALERT, ctx->request->connection->log, 0,
-                  "gzip filter failed to use preallocated memory: %ud of %ud",
-                  items * size, ctx->allocated);
-
-    p = ngx_palloc(ctx->request->pool, items * size);
-
-    return p;
-}
-
-
-static void
-ngx_http_gzip_filter_free(void *opaque, void *address)
-{
-#if 0
-    ngx_http_gzip_ctx_t *ctx = opaque;
-
-    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->request->connection->log, 0,
-                   "gzip free: %p", address);
-#endif
-}
-
-
-static u_char *
-ngx_http_gzip_log_ratio(ngx_http_request_t *r, u_char *buf,
-    ngx_http_log_op_t *op)
-{
-    ngx_uint_t            zint, zfrac;
-    ngx_http_gzip_ctx_t  *ctx;
-
-    ctx = ngx_http_get_module_ctx(r, ngx_http_gzip_filter_module);
-
-    if (ctx == NULL || ctx->zout == 0) {
-        *buf = '-';
-        return buf + 1;
-    }
-
-    zint = (ngx_uint_t) (ctx->zin / ctx->zout);
-    zfrac = (ngx_uint_t) ((ctx->zin * 100 / ctx->zout) % 100);
-
-    if ((ctx->zin * 1000 / ctx->zout) % 10 > 4) {
-
-        /* the rounding, e.g., 2.125 to 2.13 */
-
-        zfrac++;
-
-        if (zfrac > 99) {
-            zint++;
-            zfrac = 0;
-        }
-    }
-
-    return ngx_sprintf(buf, "%ui.%02ui", zint, zfrac);
-}
-
-
-static void
-ngx_http_gzip_error(ngx_http_gzip_ctx_t *ctx)
-{
-    deflateEnd(&ctx->zstream);
-
-    if (ctx->preallocated) {
-        ngx_pfree(ctx->request->pool, ctx->preallocated);
-    }
-
-    ctx->zstream.avail_in = 0;
-    ctx->zstream.avail_out = 0;
-
-    ctx->done = 1;
-
-    return;
-}
-
-
-static ngx_int_t
-ngx_http_gzip_add_log_formats(ngx_conf_t *cf)
-{
-    ngx_http_log_op_name_t  *op;
-
-    for (op = ngx_http_gzip_log_fmt_ops; op->name.len; op++) { /* void */ }
-    op->run = NULL;
-
-    for (op = ngx_http_log_fmt_ops; op->run; op++) {
-        if (op->name.len == 0) {
-            op = (ngx_http_log_op_name_t *) op->run;
-        }
-    }
-
-    op->run = (ngx_http_log_op_run_pt) ngx_http_gzip_log_fmt_ops;
-
-    return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_gzip_filter_init(ngx_cycle_t *cycle)
-{
-    ngx_http_next_header_filter = ngx_http_top_header_filter;
-    ngx_http_top_header_filter = ngx_http_gzip_header_filter;
-
-    ngx_http_next_body_filter = ngx_http_top_body_filter;
-    ngx_http_top_body_filter = ngx_http_gzip_body_filter;
-
-    return NGX_OK;
-}
-
-
-static void *
-ngx_http_gzip_create_conf(ngx_conf_t *cf)
-{
-    ngx_http_gzip_conf_t  *conf;
-
-    if (!(conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_gzip_conf_t)))) {
-        return NGX_CONF_ERROR;
-    }
-
-    /*
-     * set by ngx_pcalloc():
-     *
-     *     conf->bufs.num = 0;
-     *     conf->proxied = 0;
-     *     conf->types = NULL;
-     */
-
-    conf->enable = NGX_CONF_UNSET;
-    conf->no_buffer = NGX_CONF_UNSET;
-
-    conf->http_version = NGX_CONF_UNSET_UINT;
-
-    conf->level = NGX_CONF_UNSET;
-    conf->wbits = (size_t) NGX_CONF_UNSET;
-    conf->memlevel = (size_t) NGX_CONF_UNSET;
-    conf->min_length = NGX_CONF_UNSET;
-
-    return conf;
-}
-
-
-static char *
-ngx_http_gzip_merge_conf(ngx_conf_t *cf, void *parent, void *child)
-{
-    ngx_http_gzip_conf_t *prev = parent;
-    ngx_http_gzip_conf_t *conf = child;
-
-    ngx_http_gzip_type_t  *type;
-
-    ngx_conf_merge_value(conf->enable, prev->enable, 0);
-
-    ngx_conf_merge_bufs_value(conf->bufs, prev->bufs, 4, ngx_pagesize);
-
-    ngx_conf_merge_unsigned_value(conf->http_version, prev->http_version,
-                              NGX_HTTP_VERSION_11);
-    ngx_conf_merge_bitmask_value(conf->proxied, prev->proxied,
-                              (NGX_CONF_BITMASK_SET|NGX_HTTP_GZIP_PROXIED_OFF));
-
-    ngx_conf_merge_value(conf->level, prev->level, 1);
-    ngx_conf_merge_size_value(conf->wbits, prev->wbits, MAX_WBITS);
-    ngx_conf_merge_size_value(conf->memlevel, prev->memlevel,
-                              MAX_MEM_LEVEL - 1);
-    ngx_conf_merge_value(conf->min_length, prev->min_length, 0);
-    ngx_conf_merge_value(conf->no_buffer, prev->no_buffer, 0);
-
-    if (conf->types == NULL) {
-        if (prev->types == NULL) {
-            conf->types = ngx_array_create(cf->pool, 1,
-                                           sizeof(ngx_http_gzip_type_t));
-            if (conf->types == NULL) {
-                return NGX_CONF_ERROR;
-            }
-
-            if (!(type = ngx_array_push(conf->types))) {
-                return NGX_CONF_ERROR;
-            }
-
-            type->name.len = sizeof("text/html") - 1;
-            type->name.data = (u_char *) "text/html";
-            type->enable = 1;
-
-        } else {
-            conf->types = prev->types;
-        }
-    }
-
-    return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_gzip_set_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
-    ngx_http_gzip_conf_t *gcf = conf;
-
-    ngx_str_t             *value;
-    ngx_uint_t             i;
-    ngx_http_gzip_type_t  *type;
-
-    if (gcf->types == NULL) {
-        gcf->types = ngx_array_create(cf->pool, 4,
-                                       sizeof(ngx_http_gzip_type_t));
-        if (gcf->types == NULL) {
-            return NGX_CONF_ERROR;
-        }
-
-        if (!(type = ngx_array_push(gcf->types))) {
-            return NGX_CONF_ERROR;
-        }
-
-        type->name.len = sizeof("text/html") - 1;
-        type->name.data = (u_char *) "text/html";
-        type->enable = 1;
-    }
-
-    value = cf->args->elts;
-
-    for (i = 1; i < cf->args->nelts; i++) {
-
-        if (ngx_strcmp(value[i].data, "text/html") == 0) {
-            continue;
-        }
-
-        if (!(type = ngx_array_push(gcf->types))) {
-            return NGX_CONF_ERROR;
-        }
-
-        type->name.len = value[i].len;
-
-        if (!(type->name.data = ngx_palloc(cf->pool, type->name.len + 1))) {
-            return NGX_CONF_ERROR;
-        }
-
-        ngx_cpystrn(type->name.data, value[i].data, type->name.len + 1);
-    }
-
-    return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_gzip_set_window(ngx_conf_t *cf, void *post, void *data)
-{
-    int *np = data;
-
-    int  wbits, wsize;
-
-    wbits = 15;
-
-    for (wsize = 32 * 1024; wsize > 256; wsize >>= 1) {
-
-        if (wsize == *np) {
-            *np = wbits;
-
-            return NGX_CONF_OK;
-        }
-
-        wbits--;
-    }
-
-    return "must be 512, 1k, 2k, 4k, 8k, 16k, or 32k";
-}
-
-
-static char *
-ngx_http_gzip_set_hash(ngx_conf_t *cf, void *post, void *data)
-{
-    int *np = data;
-
-    int  memlevel, hsize;
-
-    memlevel = 9;
-
-    for (hsize = 128 * 1024; hsize > 256; hsize >>= 1) {
-
-        if (hsize == *np) {
-            *np = memlevel;
-
-            return NGX_CONF_OK;
-        }
-
-        memlevel--;
-    }
-
-    return "must be 512, 1k, 2k, 4k, 8k, 16k, 32k, 64k, or 128k";
-}
new file mode 100644
--- /dev/null
+++ b/src/http/modules/ngx_http_gzip_filter_module.c
@@ -0,0 +1,1162 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+
+#include <zlib.h>
+
+
+typedef struct {
+    ngx_flag_t           enable;
+    ngx_flag_t           no_buffer;
+
+    ngx_array_t         *types;     /* array of ngx_http_gzip_type_t */
+
+    ngx_bufs_t           bufs;
+
+    ngx_uint_t           http_version;
+    ngx_uint_t           proxied;
+
+    int                  level;
+    size_t               wbits;
+    size_t               memlevel;
+    ssize_t              min_length;
+} ngx_http_gzip_conf_t;
+
+
+typedef struct {
+    ngx_str_t            name;
+    ngx_uint_t           enable;
+} ngx_http_gzip_type_t;
+
+
+#define NGX_HTTP_GZIP_PROXIED_OFF       0x0002
+#define NGX_HTTP_GZIP_PROXIED_EXPIRED   0x0004
+#define NGX_HTTP_GZIP_PROXIED_NO_CACHE  0x0008
+#define NGX_HTTP_GZIP_PROXIED_NO_STORE  0x0010
+#define NGX_HTTP_GZIP_PROXIED_PRIVATE   0x0020
+#define NGX_HTTP_GZIP_PROXIED_NO_LM     0x0040
+#define NGX_HTTP_GZIP_PROXIED_NO_ETAG   0x0080
+#define NGX_HTTP_GZIP_PROXIED_AUTH      0x0100
+#define NGX_HTTP_GZIP_PROXIED_ANY       0x0200
+
+
+typedef struct {
+    ngx_chain_t         *in;
+    ngx_chain_t         *free;
+    ngx_chain_t         *busy;
+    ngx_chain_t         *out;
+    ngx_chain_t        **last_out;
+    ngx_buf_t           *in_buf;
+    ngx_buf_t           *out_buf;
+    ngx_int_t            bufs;
+
+    off_t                length;
+
+    void                *preallocated;
+    char                *free_mem;
+    ngx_uint_t           allocated;
+
+    unsigned             flush:4;
+    unsigned             redo:1;
+    unsigned             done:1;
+
+    size_t               zin;
+    size_t               zout;
+
+    uint32_t             crc32;
+    z_stream             zstream;
+    ngx_http_request_t  *request;
+} ngx_http_gzip_ctx_t;
+
+
+static ngx_int_t ngx_http_gzip_proxied(ngx_http_request_t *r,
+    ngx_http_gzip_conf_t *conf);
+static void *ngx_http_gzip_filter_alloc(void *opaque, u_int items,
+    u_int size);
+static void ngx_http_gzip_filter_free(void *opaque, void *address);
+static void ngx_http_gzip_error(ngx_http_gzip_ctx_t *ctx);
+
+static u_char *ngx_http_gzip_log_ratio(ngx_http_request_t *r, u_char *buf,
+    ngx_http_log_op_t *op);
+
+static ngx_int_t ngx_http_gzip_add_log_formats(ngx_conf_t *cf);
+
+static ngx_int_t ngx_http_gzip_filter_init(ngx_cycle_t *cycle);
+static void *ngx_http_gzip_create_conf(ngx_conf_t *cf);
+static char *ngx_http_gzip_merge_conf(ngx_conf_t *cf,
+    void *parent, void *child);
+static char *ngx_http_gzip_set_types(ngx_conf_t *cf, ngx_command_t *cmd,
+    void *conf);
+static char *ngx_http_gzip_set_window(ngx_conf_t *cf, void *post, void *data);
+static char *ngx_http_gzip_set_hash(ngx_conf_t *cf, void *post, void *data);
+
+
+static ngx_conf_num_bounds_t  ngx_http_gzip_comp_level_bounds = {
+    ngx_conf_check_num_bounds, 1, 9
+};
+
+static ngx_conf_post_handler_pt  ngx_http_gzip_set_window_p =
+                                                      ngx_http_gzip_set_window;
+static ngx_conf_post_handler_pt  ngx_http_gzip_set_hash_p =
+                                                        ngx_http_gzip_set_hash;
+
+
+
+static ngx_conf_enum_t  ngx_http_gzip_http_version[] = {
+    { ngx_string("1.0"), NGX_HTTP_VERSION_10 },
+    { ngx_string("1.1"), NGX_HTTP_VERSION_11 },
+    { ngx_null_string, 0 }
+};
+
+
+static ngx_conf_bitmask_t  ngx_http_gzip_proxied_mask[] = {
+    { ngx_string("off"), NGX_HTTP_GZIP_PROXIED_OFF },
+    { ngx_string("expired"), NGX_HTTP_GZIP_PROXIED_EXPIRED },
+    { ngx_string("no-cache"), NGX_HTTP_GZIP_PROXIED_NO_CACHE },
+    { ngx_string("no-store"), NGX_HTTP_GZIP_PROXIED_NO_STORE },
+    { ngx_string("private"), NGX_HTTP_GZIP_PROXIED_PRIVATE },
+    { ngx_string("no_last_modified"), NGX_HTTP_GZIP_PROXIED_NO_LM },
+    { ngx_string("no_etag"), NGX_HTTP_GZIP_PROXIED_NO_ETAG },
+    { ngx_string("auth"), NGX_HTTP_GZIP_PROXIED_AUTH },
+    { ngx_string("any"), NGX_HTTP_GZIP_PROXIED_ANY },
+    { ngx_null_string, 0 }
+};
+
+
+static ngx_command_t  ngx_http_gzip_filter_commands[] = {
+
+    { ngx_string("gzip"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
+                        |NGX_CONF_FLAG,
+      ngx_conf_set_flag_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_gzip_conf_t, enable),
+      NULL },
+
+    { ngx_string("gzip_buffers"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
+      ngx_conf_set_bufs_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_gzip_conf_t, bufs),
+      NULL },
+
+    { ngx_string("gzip_types"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
+      ngx_http_gzip_set_types,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      0,
+      NULL },
+
+    { ngx_string("gzip_comp_level"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_num_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_gzip_conf_t, level),
+      &ngx_http_gzip_comp_level_bounds },
+
+    { ngx_string("gzip_window"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_size_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_gzip_conf_t, wbits),
+      &ngx_http_gzip_set_window_p },
+
+    { ngx_string("gzip_hash"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_size_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_gzip_conf_t, memlevel),
+      &ngx_http_gzip_set_hash_p },
+
+    { ngx_string("gzip_no_buffer"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+      ngx_conf_set_flag_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_gzip_conf_t, no_buffer),
+      NULL },
+
+    { ngx_string("gzip_http_version"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_ANY,
+      ngx_conf_set_enum_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_gzip_conf_t, http_version),
+      &ngx_http_gzip_http_version },
+
+    { ngx_string("gzip_proxied"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_ANY,
+      ngx_conf_set_bitmask_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_gzip_conf_t, proxied),
+      &ngx_http_gzip_proxied_mask },
+
+    { ngx_string("gzip_min_length"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_size_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_gzip_conf_t, min_length),
+      NULL },
+
+      ngx_null_command
+};
+
+
+static ngx_http_module_t  ngx_http_gzip_filter_module_ctx = {
+    ngx_http_gzip_add_log_formats,         /* pre conf */
+
+    NULL,                                  /* create main configuration */
+    NULL,                                  /* init main configuration */
+
+    NULL,                                  /* create server configuration */
+    NULL,                                  /* merge server configuration */
+
+    ngx_http_gzip_create_conf,             /* create location configuration */
+    ngx_http_gzip_merge_conf               /* merge location configuration */
+};
+
+
+ngx_module_t  ngx_http_gzip_filter_module = {
+    NGX_MODULE,
+    &ngx_http_gzip_filter_module_ctx,      /* module context */
+    ngx_http_gzip_filter_commands,         /* module directives */
+    NGX_HTTP_MODULE,                       /* module type */
+    ngx_http_gzip_filter_init,             /* init module */
+    NULL                                   /* init process */
+};
+
+
+static ngx_http_log_op_name_t ngx_http_gzip_log_fmt_ops[] = {
+    { ngx_string("gzip_ratio"), NGX_INT32_LEN + 3,
+                                NULL, NULL, ngx_http_gzip_log_ratio },
+    { ngx_null_string, 0, NULL, NULL, NULL }
+};
+
+
+
+static u_char  gzheader[10] = { 0x1f, 0x8b, Z_DEFLATED, 0, 0, 0, 0, 0, 0, 3 };
+
+#if (NGX_HAVE_LITTLE_ENDIAN && NGX_HAVE_NONALIGNED)
+
+struct gztrailer {
+    uint32_t  crc32;
+    uint32_t  zlen;
+};
+
+#else /* NGX_HAVE_BIG_ENDIAN || !NGX_HAVE_NONALIGNED */
+
+struct gztrailer {
+    u_char  crc32[4];
+    u_char  zlen[4];
+};
+
+#endif
+
+
+static ngx_http_output_header_filter_pt  ngx_http_next_header_filter;
+static ngx_http_output_body_filter_pt    ngx_http_next_body_filter;
+
+
+static ngx_int_t
+ngx_http_gzip_header_filter(ngx_http_request_t *r)
+{
+    ngx_uint_t             i, found;
+    ngx_http_gzip_ctx_t   *ctx;
+    ngx_http_gzip_conf_t  *conf;
+    ngx_http_gzip_type_t  *type;
+
+    conf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_filter_module);
+
+    if (!conf->enable
+        || (r->headers_out.status != NGX_HTTP_OK
+            && r->headers_out.status != NGX_HTTP_FORBIDDEN
+            && r->headers_out.status != NGX_HTTP_NOT_FOUND)
+        || r->header_only
+        || r->http_version < conf->http_version
+        || r->headers_out.content_type == NULL
+        || (r->headers_out.content_encoding
+            && r->headers_out.content_encoding->value.len)
+        || r->headers_in.accept_encoding == NULL
+        || (r->headers_out.content_length_n != -1
+            && r->headers_out.content_length_n < conf->min_length)
+        || ngx_strstr(r->headers_in.accept_encoding->value.data, "gzip") == NULL
+       )
+    {
+        return ngx_http_next_header_filter(r);
+    }
+
+
+    found = 0;
+    type = conf->types->elts;
+
+    for (i = 0; i < conf->types->nelts; i++) {
+        if (r->headers_out.content_type->value.len >= type[i].name.len
+            && ngx_strncasecmp(r->headers_out.content_type->value.data, 
+                               type[i].name.data, type[i].name.len) == 0)
+        {
+            found = 1;
+            break;
+        }
+    }
+
+    if (!found) {
+        return ngx_http_next_header_filter(r);
+    }
+
+
+    if (r->headers_in.via) {
+        if (conf->proxied & NGX_HTTP_GZIP_PROXIED_OFF) {
+            return ngx_http_next_header_filter(r);
+        }
+
+        if (!(conf->proxied & NGX_HTTP_GZIP_PROXIED_ANY)
+            && ngx_http_gzip_proxied(r, conf) == NGX_DECLINED)
+        {
+            return ngx_http_next_header_filter(r);
+        }
+    }
+
+
+    /*
+     * if the URL (without the "http://" prefix) is longer than 253 bytes
+     * then MSIE 4.x can not handle the compressed stream - it waits too long,
+     * hangs up or crashes
+     */
+
+    if (r->headers_in.msie4 && r->unparsed_uri.len > 200) {
+        return ngx_http_next_header_filter(r);
+    }
+
+    ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_gzip_ctx_t));
+    if (ctx == NULL) {
+        return NGX_ERROR;
+    }
+
+    ngx_http_set_ctx(r, ctx, ngx_http_gzip_filter_module);
+
+
+    ctx->request = r;
+
+    r->headers_out.content_encoding = ngx_list_push(&r->headers_out.headers);
+    if (r->headers_out.content_encoding == NULL) {
+        return NGX_ERROR;
+    }
+
+    r->headers_out.content_encoding->key.len = sizeof("Content-Encoding") - 1;
+    r->headers_out.content_encoding->key.data = (u_char *) "Content-Encoding";
+    r->headers_out.content_encoding->value.len = sizeof("gzip") - 1;
+    r->headers_out.content_encoding->value.data = (u_char *) "gzip";
+
+    ctx->length = r->headers_out.content_length_n;
+    r->headers_out.content_length_n = -1;
+    if (r->headers_out.content_length) {
+        r->headers_out.content_length->key.len = 0;
+        r->headers_out.content_length = NULL;
+    }
+    r->filter_need_in_memory = 1;
+
+    return ngx_http_next_header_filter(r);
+}
+
+
+static ngx_int_t
+ngx_http_gzip_proxied(ngx_http_request_t *r, ngx_http_gzip_conf_t *conf)
+{
+    time_t  date, expires;
+
+    if (r->headers_in.authorization
+        && (conf->proxied & NGX_HTTP_GZIP_PROXIED_AUTH))
+    {
+        return NGX_OK;
+    }
+
+    if (r->headers_out.expires) {
+
+        if (!(conf->proxied & NGX_HTTP_GZIP_PROXIED_EXPIRED)) {
+            return NGX_DECLINED;
+        }
+
+        expires = ngx_http_parse_time(r->headers_out.expires->value.data,
+                                      r->headers_out.expires->value.len);
+        if (expires == NGX_ERROR) {
+            return NGX_DECLINED;
+        }
+
+        if (r->headers_out.date) {
+            date = ngx_http_parse_time(r->headers_out.date->value.data,
+                                       r->headers_out.date->value.len);
+            if (date == NGX_ERROR) {
+                return NGX_DECLINED;
+            }
+
+        } else {
+            date = ngx_time();
+        }
+
+        if (expires < date) {
+            return NGX_OK;
+        }
+
+        return NGX_DECLINED;
+    }
+
+    if (r->headers_out.cache_control) {
+
+        if ((conf->proxied & NGX_HTTP_GZIP_PROXIED_NO_CACHE)
+            && ngx_strstr(r->headers_out.cache_control->value.data, "no-cache"))
+        {
+            return NGX_OK;
+        }
+
+        if ((conf->proxied & NGX_HTTP_GZIP_PROXIED_NO_STORE)
+            && ngx_strstr(r->headers_out.cache_control->value.data, "no-store"))
+        {
+            return NGX_OK;
+        }
+
+        if ((conf->proxied & NGX_HTTP_GZIP_PROXIED_PRIVATE)
+            && ngx_strstr(r->headers_out.cache_control->value.data, "private"))
+        {
+            return NGX_OK;
+        }
+
+        return NGX_DECLINED;
+    }
+
+    if ((conf->proxied & NGX_HTTP_GZIP_PROXIED_NO_LM)
+        && r->headers_out.last_modified)
+    {
+        return NGX_DECLINED;
+    }
+
+    if ((conf->proxied & NGX_HTTP_GZIP_PROXIED_NO_ETAG)
+        && r->headers_out.etag)
+    {
+        return NGX_DECLINED;
+    }
+
+    return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_gzip_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
+{
+    int                    rc, wbits, memlevel;
+    ngx_int_t              last;
+    struct gztrailer      *trailer;
+    ngx_buf_t             *b;
+    ngx_chain_t           *cl, out;
+    ngx_http_gzip_ctx_t   *ctx;
+    ngx_http_gzip_conf_t  *conf;
+
+    ctx = ngx_http_get_module_ctx(r, ngx_http_gzip_filter_module);
+
+    if (ctx == NULL || ctx->done) {
+        return ngx_http_next_body_filter(r, in);
+    }
+
+    conf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_filter_module);
+
+    if (ctx->preallocated == NULL) {
+        wbits = conf->wbits;
+        memlevel = conf->memlevel;
+
+        if (ctx->length > 0) {
+
+            /* the actual zlib window size is smaller by 262 bytes */
+
+            while (ctx->length < ((1 << (wbits - 1)) - 262)) {
+                wbits--;
+                memlevel--;
+            }
+        }
+
+        /*
+         * We preallocate a memory for zlib in one buffer (200K-400K), this
+         * decreases a number of malloc() and free() calls and also probably
+         * decreases a number of syscalls (sbrk() and so on).
+         * Besides we free this memory as soon as the gzipping will complete
+         * and do not wait while a whole response will be sent to a client.
+         *
+         * 8K is for zlib deflate_state, it takes
+         *  * 5816 bytes on x86 and sparc64 (32-bit mode)
+         *  * 5920 bytes on amd64 and sparc64
+         */
+
+        ctx->allocated = 8192 + (1 << (wbits + 2)) + (1 << (memlevel + 9));
+
+        ctx->preallocated = ngx_palloc(r->pool, ctx->allocated);
+        if (ctx->preallocated == NULL) {
+            return NGX_ERROR;
+        }
+
+        ctx->free_mem = ctx->preallocated;
+
+        ctx->zstream.zalloc = ngx_http_gzip_filter_alloc;
+        ctx->zstream.zfree = ngx_http_gzip_filter_free;
+        ctx->zstream.opaque = ctx;
+
+        rc = deflateInit2(&ctx->zstream, conf->level, Z_DEFLATED,
+                          -wbits, memlevel, Z_DEFAULT_STRATEGY);
+
+        if (rc != Z_OK) {
+            ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+                          "deflateInit2() failed: %d", rc);
+            ngx_http_gzip_error(ctx);
+            return NGX_ERROR;
+        }
+
+        b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
+        if (b == NULL) {
+            ngx_http_gzip_error(ctx);
+            return NGX_ERROR;
+        }
+
+        b->memory = 1;
+        b->pos = gzheader;
+        b->last = b->pos + 10;
+
+        out.buf = b;
+        out.next = NULL;
+
+        /*
+         * We pass the gzheader to the next filter now to avoid its linking
+         * to the ctx->busy chain.  zlib does not usually output the compressed
+         * data in the initial iterations, so the gzheader that was linked
+         * to the ctx->busy chain would be flushed by ngx_http_write_filter().
+         */
+
+        if (ngx_http_next_body_filter(r, &out) == NGX_ERROR) {
+            ngx_http_gzip_error(ctx);
+            return NGX_ERROR;
+        }
+
+        ctx->last_out = &ctx->out;
+
+        ctx->crc32 = crc32(0L, Z_NULL, 0);
+        ctx->flush = Z_NO_FLUSH;
+    }
+
+    if (in) {
+        if (ngx_chain_add_copy(r->pool, &ctx->in, in) == NGX_ERROR) {
+            ngx_http_gzip_error(ctx);
+            return NGX_ERROR;
+        }
+    }
+
+    last = NGX_NONE;
+
+    for ( ;; ) {
+
+        for ( ;; ) {
+
+            /* does zlib need a new data ? */
+
+            if (ctx->zstream.avail_in == 0
+                && ctx->flush == Z_NO_FLUSH
+                && !ctx->redo)
+            {
+                ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                               "gzip in: %p", ctx->in);
+
+                if (ctx->in == NULL) {
+                    break;
+                }
+
+                ctx->in_buf = ctx->in->buf;
+                ctx->in = ctx->in->next;
+
+                ctx->zstream.next_in = ctx->in_buf->pos;
+                ctx->zstream.avail_in = ctx->in_buf->last - ctx->in_buf->pos;
+
+                ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                               "gzip in_buf:%p ni:%p ai:%ud",
+                               ctx->in_buf,
+                               ctx->zstream.next_in, ctx->zstream.avail_in);
+
+                /* STUB */
+                if (ctx->in_buf->last < ctx->in_buf->pos) {
+                    ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+                                  "zstream.avail_in is huge");
+                    ctx->done = 1;
+                    return NGX_ERROR;
+                }
+                /**/
+
+                if (ctx->in_buf->last_buf) {
+                    ctx->flush = Z_FINISH;
+
+                } else if (ctx->in_buf->flush) {
+                    ctx->flush = Z_SYNC_FLUSH;
+                }
+
+                if (ctx->zstream.avail_in == 0) {
+                    if (ctx->flush == Z_NO_FLUSH) {
+                        continue;
+                    }
+
+                } else {
+                    ctx->crc32 = crc32(ctx->crc32, ctx->zstream.next_in,
+                                       ctx->zstream.avail_in);
+                }
+            }
+
+
+            /* is there a space for the gzipped data ? */
+
+            if (ctx->zstream.avail_out == 0) {
+
+                if (ctx->free) {
+                    ctx->out_buf = ctx->free->buf;
+                    ctx->free = ctx->free->next;
+
+                } else if (ctx->bufs < conf->bufs.num) {
+                    ctx->out_buf = ngx_create_temp_buf(r->pool,
+                                                       conf->bufs.size);
+                    if (ctx->out_buf == NULL) {
+                        ngx_http_gzip_error(ctx);
+                        return NGX_ERROR;
+                    }
+
+                    ctx->out_buf->tag = (ngx_buf_tag_t)
+                                                  &ngx_http_gzip_filter_module;
+                    ctx->out_buf->recycled = 1;
+                    ctx->bufs++;
+
+                } else {
+                    break;
+                }
+
+                ctx->zstream.next_out = ctx->out_buf->pos;
+                ctx->zstream.avail_out = conf->bufs.size;
+            }
+
+            ngx_log_debug6(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                         "deflate in: ni:%p no:%p ai:%ud ao:%ud fl:%d redo:%d",
+                         ctx->zstream.next_in, ctx->zstream.next_out,
+                         ctx->zstream.avail_in, ctx->zstream.avail_out,
+                         ctx->flush, ctx->redo);
+
+            rc = deflate(&ctx->zstream, ctx->flush);
+
+            if (rc != Z_OK && rc != Z_STREAM_END) {
+                ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+                              "deflate() failed: %d, %d", ctx->flush, rc);
+                ngx_http_gzip_error(ctx);
+                return NGX_ERROR;
+            }
+
+            ngx_log_debug5(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                           "deflate out: ni:%p no:%p ai:%ud ao:%ud rc:%d",
+                           ctx->zstream.next_in, ctx->zstream.next_out,
+                           ctx->zstream.avail_in, ctx->zstream.avail_out,
+                           rc);
+
+            ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                           "gzip in_buf:%p pos:%p",
+                           ctx->in_buf, ctx->in_buf->pos);
+
+
+            if (ctx->zstream.next_in) {
+                ctx->in_buf->pos = ctx->zstream.next_in;
+
+                if (ctx->zstream.avail_in == 0) {
+                    ctx->zstream.next_in = NULL;
+                }
+            }
+
+            ctx->out_buf->last = ctx->zstream.next_out;
+
+            if (ctx->zstream.avail_out == 0) {
+
+                /* zlib wants to output some more gzipped data */
+
+                cl = ngx_alloc_chain_link(r->pool);
+                if (cl == NULL) {
+                    ngx_http_gzip_error(ctx);
+                    return NGX_ERROR;
+                }
+
+                cl->buf = ctx->out_buf;
+                cl->next = NULL;
+                *ctx->last_out = cl;
+                ctx->last_out = &cl->next;
+
+                ctx->redo = 1;
+
+                continue;
+            }
+
+            ctx->redo = 0;
+
+            if (ctx->flush == Z_SYNC_FLUSH) {
+
+                ctx->out_buf->flush = 0;
+                ctx->flush = Z_NO_FLUSH;
+
+                cl = ngx_alloc_chain_link(r->pool);
+                if (cl == NULL) {
+                    ngx_http_gzip_error(ctx);
+                    return NGX_ERROR;
+                }
+
+                cl->buf = ctx->out_buf;
+                cl->next = NULL;
+                *ctx->last_out = cl;
+                ctx->last_out = &cl->next;
+
+                break;
+            }
+
+            if (rc == Z_STREAM_END) {
+
+                ctx->zin = ctx->zstream.total_in;
+                ctx->zout = 10 + ctx->zstream.total_out + 8;
+
+                rc = deflateEnd(&ctx->zstream);
+
+                if (rc != Z_OK) {
+                    ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+                                  "deflateEnd() failed: %d", rc);
+                    ngx_http_gzip_error(ctx);
+                    return NGX_ERROR;
+                }
+
+                ngx_pfree(r->pool, ctx->preallocated);
+
+                cl = ngx_alloc_chain_link(r->pool);
+                if (cl == NULL) {
+                    ngx_http_gzip_error(ctx);
+                    return NGX_ERROR;
+                }
+
+                cl->buf = ctx->out_buf;
+                cl->next = NULL;
+                *ctx->last_out = cl;
+                ctx->last_out = &cl->next;
+
+                if (ctx->zstream.avail_out >= 8) {
+                    trailer = (struct gztrailer *) ctx->out_buf->last;
+                    ctx->out_buf->last += 8;
+                    ctx->out_buf->last_buf = 1;
+
+                } else {
+                    b = ngx_create_temp_buf(r->pool, 8);
+                    if (b == NULL) {
+                        ngx_http_gzip_error(ctx);
+                        return NGX_ERROR;
+                    }
+
+                    b->last_buf = 1;
+
+                    cl = ngx_alloc_chain_link(r->pool);
+                    if (cl == NULL) {
+                        ngx_http_gzip_error(ctx);
+                        return NGX_ERROR;
+                    }
+
+                    cl->buf = b;
+                    cl->next = NULL;
+                    *ctx->last_out = cl;
+                    ctx->last_out = &cl->next;
+                    trailer = (struct gztrailer *) b->pos;
+                    b->last += 8;
+                }
+
+#if (NGX_HAVE_LITTLE_ENDIAN && NGX_HAVE_NONALIGNED)
+
+                trailer->crc32 = ctx->crc32;
+                trailer->zlen = ctx->zin;
+
+#else
+                trailer->crc32[0] = (u_char) (ctx->crc32 & 0xff);
+                trailer->crc32[1] = (u_char) ((ctx->crc32 >> 8) & 0xff);
+                trailer->crc32[2] = (u_char) ((ctx->crc32 >> 16) & 0xff);
+                trailer->crc32[3] = (u_char) ((ctx->crc32 >> 24) & 0xff);
+
+                trailer->zlen[0] = (u_char) (ctx->zin & 0xff);
+                trailer->zlen[1] = (u_char) ((ctx->zin >> 8) & 0xff);
+                trailer->zlen[2] = (u_char) ((ctx->zin >> 16) & 0xff);
+                trailer->zlen[3] = (u_char) ((ctx->zin >> 24) & 0xff);
+#endif
+
+                ctx->zstream.avail_in = 0;
+                ctx->zstream.avail_out = 0;
+
+                ctx->done = 1;
+
+                break;
+            }
+
+            if (conf->no_buffer && ctx->in == NULL) {
+
+                cl = ngx_alloc_chain_link(r->pool);
+                if (cl == NULL) {
+                    ngx_http_gzip_error(ctx);
+                    return NGX_ERROR;
+                }
+
+                cl->buf = ctx->out_buf;
+                cl->next = NULL;
+                *ctx->last_out = cl;
+                ctx->last_out = &cl->next;
+
+                break;
+            }
+        }
+
+        if (last == NGX_AGAIN && !ctx->done) {
+            return NGX_AGAIN;
+        }
+
+        if (ctx->out == NULL && ctx->busy == NULL) {
+            return NGX_OK;
+        }
+
+        last = ngx_http_next_body_filter(r, ctx->out);
+
+        /*
+         * we do not check NGX_AGAIN here because the downstream filters
+         * may free some buffers and zlib may compress some data into them
+         */
+
+        if (last == NGX_ERROR) {
+            ngx_http_gzip_error(ctx);
+            return NGX_ERROR;
+        }
+
+        ngx_chain_update_chains(&ctx->free, &ctx->busy, &ctx->out,
+                                (ngx_buf_tag_t) &ngx_http_gzip_filter_module);
+        ctx->last_out = &ctx->out;
+
+        if (ctx->done) {
+            return last;
+        }
+    }
+}
+
+
+static void *
+ngx_http_gzip_filter_alloc(void *opaque, u_int items, u_int size)
+{
+    ngx_http_gzip_ctx_t *ctx = opaque;
+
+    void        *p;
+    ngx_uint_t   alloc;
+
+    alloc = items * size;
+
+    if (alloc % 512 != 0) {
+
+        /*
+         * The zlib deflate_state allocation, it takes about 6K,
+         * we allocate 8K.  Other allocations are divisible by 512.
+         */
+
+        alloc = (alloc + ngx_pagesize - 1) & ~(ngx_pagesize - 1);
+    }
+
+    if (alloc <= ctx->allocated) {
+        p = ctx->free_mem;
+        ctx->free_mem += alloc;
+        ctx->allocated -= alloc;
+
+        ngx_log_debug4(NGX_LOG_DEBUG_HTTP, ctx->request->connection->log, 0,
+                       "gzip alloc: n:%ud s:%ud a:%ud p:%p",
+                       items, size, alloc, p);
+
+        return p;
+    }
+
+    ngx_log_error(NGX_LOG_ALERT, ctx->request->connection->log, 0,
+                  "gzip filter failed to use preallocated memory: %ud of %ud",
+                  items * size, ctx->allocated);
+
+    p = ngx_palloc(ctx->request->pool, items * size);
+
+    return p;
+}
+
+
+static void
+ngx_http_gzip_filter_free(void *opaque, void *address)
+{
+#if 0
+    ngx_http_gzip_ctx_t *ctx = opaque;
+
+    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ctx->request->connection->log, 0,
+                   "gzip free: %p", address);
+#endif
+}
+
+
+static u_char *
+ngx_http_gzip_log_ratio(ngx_http_request_t *r, u_char *buf,
+    ngx_http_log_op_t *op)
+{
+    ngx_uint_t            zint, zfrac;
+    ngx_http_gzip_ctx_t  *ctx;
+
+    ctx = ngx_http_get_module_ctx(r, ngx_http_gzip_filter_module);
+
+    if (ctx == NULL || ctx->zout == 0) {
+        *buf = '-';
+        return buf + 1;
+    }
+
+    zint = (ngx_uint_t) (ctx->zin / ctx->zout);
+    zfrac = (ngx_uint_t) ((ctx->zin * 100 / ctx->zout) % 100);
+
+    if ((ctx->zin * 1000 / ctx->zout) % 10 > 4) {
+
+        /* the rounding, e.g., 2.125 to 2.13 */
+
+        zfrac++;
+
+        if (zfrac > 99) {
+            zint++;
+            zfrac = 0;
+        }
+    }
+
+    return ngx_sprintf(buf, "%ui.%02ui", zint, zfrac);
+}
+
+
+static void
+ngx_http_gzip_error(ngx_http_gzip_ctx_t *ctx)
+{
+    deflateEnd(&ctx->zstream);
+
+    if (ctx->preallocated) {
+        ngx_pfree(ctx->request->pool, ctx->preallocated);
+    }
+
+    ctx->zstream.avail_in = 0;
+    ctx->zstream.avail_out = 0;
+
+    ctx->done = 1;
+
+    return;
+}
+
+
+static ngx_int_t
+ngx_http_gzip_add_log_formats(ngx_conf_t *cf)
+{
+    ngx_http_log_op_name_t  *op;
+
+    for (op = ngx_http_gzip_log_fmt_ops; op->name.len; op++) { /* void */ }
+    op->run = NULL;
+
+    for (op = ngx_http_log_fmt_ops; op->run; op++) {
+        if (op->name.len == 0) {
+            op = (ngx_http_log_op_name_t *) op->run;
+        }
+    }
+
+    op->run = (ngx_http_log_op_run_pt) ngx_http_gzip_log_fmt_ops;
+
+    return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_gzip_filter_init(ngx_cycle_t *cycle)
+{
+    ngx_http_next_header_filter = ngx_http_top_header_filter;
+    ngx_http_top_header_filter = ngx_http_gzip_header_filter;
+
+    ngx_http_next_body_filter = ngx_http_top_body_filter;
+    ngx_http_top_body_filter = ngx_http_gzip_body_filter;
+
+    return NGX_OK;
+}
+
+
+static void *
+ngx_http_gzip_create_conf(ngx_conf_t *cf)
+{
+    ngx_http_gzip_conf_t  *conf;
+
+    conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_gzip_conf_t));
+    if (conf == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    /*
+     * set by ngx_pcalloc():
+     *
+     *     conf->bufs.num = 0;
+     *     conf->proxied = 0;
+     *     conf->types = NULL;
+     */
+
+    conf->enable = NGX_CONF_UNSET;
+    conf->no_buffer = NGX_CONF_UNSET;
+
+    conf->http_version = NGX_CONF_UNSET_UINT;
+
+    conf->level = NGX_CONF_UNSET;
+    conf->wbits = (size_t) NGX_CONF_UNSET;
+    conf->memlevel = (size_t) NGX_CONF_UNSET;
+    conf->min_length = NGX_CONF_UNSET;
+
+    return conf;
+}
+
+
+static char *
+ngx_http_gzip_merge_conf(ngx_conf_t *cf, void *parent, void *child)
+{
+    ngx_http_gzip_conf_t *prev = parent;
+    ngx_http_gzip_conf_t *conf = child;
+
+    ngx_http_gzip_type_t  *type;
+
+    ngx_conf_merge_value(conf->enable, prev->enable, 0);
+
+    ngx_conf_merge_bufs_value(conf->bufs, prev->bufs, 4, ngx_pagesize);
+
+    ngx_conf_merge_unsigned_value(conf->http_version, prev->http_version,
+                              NGX_HTTP_VERSION_11);
+    ngx_conf_merge_bitmask_value(conf->proxied, prev->proxied,
+                              (NGX_CONF_BITMASK_SET|NGX_HTTP_GZIP_PROXIED_OFF));
+
+    ngx_conf_merge_value(conf->level, prev->level, 1);
+    ngx_conf_merge_size_value(conf->wbits, prev->wbits, MAX_WBITS);
+    ngx_conf_merge_size_value(conf->memlevel, prev->memlevel,
+                              MAX_MEM_LEVEL - 1);
+    ngx_conf_merge_value(conf->min_length, prev->min_length, 0);
+    ngx_conf_merge_value(conf->no_buffer, prev->no_buffer, 0);
+
+    if (conf->types == NULL) {
+        if (prev->types == NULL) {
+            conf->types = ngx_array_create(cf->pool, 1,
+                                           sizeof(ngx_http_gzip_type_t));
+            if (conf->types == NULL) {
+                return NGX_CONF_ERROR;
+            }
+
+            type = ngx_array_push(conf->types);
+            if (type == NULL) {
+                return NGX_CONF_ERROR;
+            }
+
+            type->name.len = sizeof("text/html") - 1;
+            type->name.data = (u_char *) "text/html";
+            type->enable = 1;
+
+        } else {
+            conf->types = prev->types;
+        }
+    }
+
+    return NGX_CONF_OK;
+}
+
+
+static char *
+ngx_http_gzip_set_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+    ngx_http_gzip_conf_t *gcf = conf;
+
+    ngx_str_t             *value;
+    ngx_uint_t             i;
+    ngx_http_gzip_type_t  *type;
+
+    if (gcf->types == NULL) {
+        gcf->types = ngx_array_create(cf->pool, 4,
+                                      sizeof(ngx_http_gzip_type_t));
+        if (gcf->types == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+        type = ngx_array_push(gcf->types);
+        if (type == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+        type->name.len = sizeof("text/html") - 1;
+        type->name.data = (u_char *) "text/html";
+        type->enable = 1;
+    }
+
+    value = cf->args->elts;
+
+    for (i = 1; i < cf->args->nelts; i++) {
+
+        if (ngx_strcmp(value[i].data, "text/html") == 0) {
+            continue;
+        }
+
+        type = ngx_array_push(gcf->types);
+        if (type == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+        type->name.len = value[i].len;
+
+        type->name.data = ngx_palloc(cf->pool, type->name.len + 1);
+        if (type->name.data == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+        ngx_cpystrn(type->name.data, value[i].data, type->name.len + 1);
+    }
+
+    return NGX_CONF_OK;
+}
+
+
+static char *
+ngx_http_gzip_set_window(ngx_conf_t *cf, void *post, void *data)
+{
+    int *np = data;
+
+    int  wbits, wsize;
+
+    wbits = 15;
+
+    for (wsize = 32 * 1024; wsize > 256; wsize >>= 1) {
+
+        if (wsize == *np) {
+            *np = wbits;
+
+            return NGX_CONF_OK;
+        }
+
+        wbits--;
+    }
+
+    return "must be 512, 1k, 2k, 4k, 8k, 16k, or 32k";
+}
+
+
+static char *
+ngx_http_gzip_set_hash(ngx_conf_t *cf, void *post, void *data)
+{
+    int *np = data;
+
+    int  memlevel, hsize;
+
+    memlevel = 9;
+
+    for (hsize = 128 * 1024; hsize > 256; hsize >>= 1) {
+
+        if (hsize == *np) {
+            *np = memlevel;
+
+            return NGX_CONF_OK;
+        }
+
+        memlevel--;
+    }
+
+    return "must be 512, 1k, 2k, 4k, 8k, 16k, 32k, 64k, or 128k";
+}
deleted file mode 100644
--- a/src/http/modules/ngx_http_headers_filter.c
+++ /dev/null
@@ -1,239 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-typedef struct {
-    time_t  expires;
-} ngx_http_headers_conf_t;
-
-
-#define NGX_HTTP_EXPIRES_UNSET   -2147483647
-#define NGX_HTTP_EXPIRES_OFF     -2147483646
-#define NGX_HTTP_EXPIRES_EPOCH   -2147483645
-
-
-static ngx_int_t ngx_http_headers_filter_init(ngx_cycle_t *cycle);
-static void *ngx_http_headers_create_conf(ngx_conf_t *cf);
-static char *ngx_http_headers_merge_conf(ngx_conf_t *cf,
-                                         void *parent, void *child);
-char *ngx_http_headers_expires(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
-
-
-static ngx_command_t  ngx_http_headers_filter_commands[] = {
-
-    { ngx_string("expires"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
-      ngx_http_headers_expires,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      0,
-      NULL},
-
-      ngx_null_command
-};
-
-
-static ngx_http_module_t  ngx_http_headers_filter_module_ctx = {
-    NULL,                                  /* pre conf */
-
-    NULL,                                  /* create main configuration */
-    NULL,                                  /* init main configuration */
-
-    NULL,                                  /* create server configuration */
-    NULL,                                  /* merge server configuration */
-
-    ngx_http_headers_create_conf,          /* create location configuration */
-    ngx_http_headers_merge_conf            /* merge location configuration */
-};
-
-
-ngx_module_t  ngx_http_headers_filter_module = {
-    NGX_MODULE,
-    &ngx_http_headers_filter_module_ctx,   /* module context */
-    ngx_http_headers_filter_commands,      /* module directives */
-    NGX_HTTP_MODULE,                       /* module type */
-    ngx_http_headers_filter_init,          /* init module */
-    NULL                                   /* init process */
-};
-
-
-static ngx_http_output_header_filter_pt  ngx_http_next_header_filter;
-
-
-static ngx_int_t ngx_http_headers_filter(ngx_http_request_t *r)
-{
-    size_t                    len;
-    ngx_table_elt_t          *expires, *cc;
-    ngx_http_headers_conf_t  *conf;
-
-    if (r->headers_out.status != NGX_HTTP_OK) {
-        return ngx_http_next_header_filter(r);
-    }
-
-    conf = ngx_http_get_module_loc_conf(r, ngx_http_headers_filter_module);
-
-    if (conf->expires != NGX_HTTP_EXPIRES_OFF) {
-
-        if (!(expires = ngx_list_push(&r->headers_out.headers))) {
-            return NGX_ERROR;
-        }
-
-        r->headers_out.expires = expires;
-
-        if (!(cc = ngx_list_push(&r->headers_out.headers))) {
-            return NGX_ERROR;
-        }
-
-        r->headers_out.cache_control = cc;
-
-        len = sizeof("Mon, 28 Sep 1970 06:00:00 GMT");
-
-        expires->key.len = sizeof("Expires") - 1;
-        expires->key.data = (u_char *) "Expires";
-        expires->value.len = len - 1;
-
-        cc->key.len = sizeof("Cache-Control") - 1;
-        cc->key.data = (u_char *) "Cache-Control";
-
-        if (conf->expires == NGX_HTTP_EXPIRES_EPOCH) {
-            expires->value.data = (u_char *) "Thu, 01 Jan 1970 00:00:01 GMT";
-
-            cc->value.len = sizeof("no-cache") - 1;
-            cc->value.data = (u_char *) "no-cache";
-
-        } else {
-            expires->value.data = ngx_palloc(r->pool, len);
-            if (expires->value.data == NULL) {
-                return NGX_ERROR;
-            }
-
-            if (conf->expires == 0) {
-                ngx_memcpy(expires->value.data, ngx_cached_http_time.data,
-                           ngx_cached_http_time.len + 1);
-
-                cc->value.len = sizeof("max-age=0") - 1;
-                cc->value.data = (u_char *) "max-age=0";
-
-            } else {
-                ngx_http_time(expires->value.data, ngx_time() + conf->expires);
-
-                if (conf->expires < 0) {
-                    cc->value.len = sizeof("no-cache") - 1;
-                    cc->value.data = (u_char *) "no-cache";
-
-                } else {
-                    cc->value.data = ngx_palloc(r->pool, sizeof("max-age=")
-                                                         + NGX_TIME_T_LEN + 1);
-                    if (cc->value.data == NULL) {
-                        return NGX_ERROR;
-                    }
-
-                    cc->value.len = ngx_sprintf(cc->value.data, "max-age=%T",
-                                                conf->expires)
-                                    - cc->value.data;
-
-                }
-            }
-        }
-    }
-
-    return ngx_http_next_header_filter(r);
-}
-
-
-static ngx_int_t ngx_http_headers_filter_init(ngx_cycle_t *cycle)
-{
-    ngx_http_next_header_filter = ngx_http_top_header_filter;
-    ngx_http_top_header_filter = ngx_http_headers_filter;
-
-    return NGX_OK;
-}
-
-
-static void *ngx_http_headers_create_conf(ngx_conf_t *cf)
-{   
-    ngx_http_headers_conf_t  *conf;
-
-    if (!(conf = ngx_palloc(cf->pool, sizeof(ngx_http_headers_conf_t)))) {
-        return NGX_CONF_ERROR;
-    }
-
-    conf->expires = NGX_HTTP_EXPIRES_UNSET;
-
-    return conf;
-}
-
-
-static char *ngx_http_headers_merge_conf(ngx_conf_t *cf,
-                                         void *parent, void *child)
-{
-    ngx_http_headers_conf_t *prev = parent;
-    ngx_http_headers_conf_t *conf = child;
-
-    if (conf->expires == NGX_HTTP_EXPIRES_UNSET) {
-        conf->expires = (prev->expires == NGX_HTTP_EXPIRES_UNSET) ?
-                                          NGX_HTTP_EXPIRES_OFF : prev->expires;
-    }
-
-    return NGX_CONF_OK;
-}
-
-
-char *ngx_http_headers_expires(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
-    ngx_http_headers_conf_t *hcf = conf;
-
-    ngx_uint_t   minus;
-    ngx_str_t   *value;
-
-    if (hcf->expires != NGX_HTTP_EXPIRES_UNSET) {
-        return "is duplicate";
-    }
-
-    value = cf->args->elts;
-
-    if (ngx_strcmp(value[1].data, "epoch") == 0) {
-        hcf->expires = NGX_HTTP_EXPIRES_EPOCH;
-        return NGX_CONF_OK;
-    }
-
-    if (ngx_strcmp(value[1].data, "off") == 0) {
-        hcf->expires = NGX_HTTP_EXPIRES_OFF;
-        return NGX_CONF_OK;
-    }
-
-    if (value[1].data[0] == '+') {
-        value[1].data++;
-        value[1].len--;
-        minus = 0;
-
-    } else if (value[1].data[0] == '-') {
-        value[1].data++;
-        value[1].len--;
-        minus = 1;
-
-    } else {
-        minus = 0;
-    }
-
-    hcf->expires = ngx_parse_time(&value[1], 1);
-    if (hcf->expires == NGX_ERROR) {
-        return "invalid value";
-    }
-    
-    if (hcf->expires == NGX_PARSE_LARGE_TIME) {
-        return "value must be less than 68 years";
-    }
-
-    if (minus) {
-        hcf->expires = - hcf->expires;
-    }
-
-    return NGX_CONF_OK;
-}
new file mode 100644
--- /dev/null
+++ b/src/http/modules/ngx_http_headers_filter_module.c
@@ -0,0 +1,248 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+
+
+typedef struct {
+    time_t  expires;
+} ngx_http_headers_conf_t;
+
+
+#define NGX_HTTP_EXPIRES_UNSET   -2147483647
+#define NGX_HTTP_EXPIRES_OFF     -2147483646
+#define NGX_HTTP_EXPIRES_EPOCH   -2147483645
+
+
+static ngx_int_t ngx_http_headers_filter_init(ngx_cycle_t *cycle);
+static void *ngx_http_headers_create_conf(ngx_conf_t *cf);
+static char *ngx_http_headers_merge_conf(ngx_conf_t *cf,
+                                         void *parent, void *child);
+static char *ngx_http_headers_expires(ngx_conf_t *cf, ngx_command_t *cmd,
+    void *conf);
+
+
+static ngx_command_t  ngx_http_headers_filter_commands[] = {
+
+    { ngx_string("expires"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_http_headers_expires,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      0,
+      NULL},
+
+      ngx_null_command
+};
+
+
+static ngx_http_module_t  ngx_http_headers_filter_module_ctx = {
+    NULL,                                  /* pre conf */
+
+    NULL,                                  /* create main configuration */
+    NULL,                                  /* init main configuration */
+
+    NULL,                                  /* create server configuration */
+    NULL,                                  /* merge server configuration */
+
+    ngx_http_headers_create_conf,          /* create location configuration */
+    ngx_http_headers_merge_conf            /* merge location configuration */
+};
+
+
+ngx_module_t  ngx_http_headers_filter_module = {
+    NGX_MODULE,
+    &ngx_http_headers_filter_module_ctx,   /* module context */
+    ngx_http_headers_filter_commands,      /* module directives */
+    NGX_HTTP_MODULE,                       /* module type */
+    ngx_http_headers_filter_init,          /* init module */
+    NULL                                   /* init process */
+};
+
+
+static ngx_http_output_header_filter_pt  ngx_http_next_header_filter;
+
+
+static ngx_int_t
+ngx_http_headers_filter(ngx_http_request_t *r)
+{
+    size_t                    len;
+    ngx_table_elt_t          *expires, *cc;
+    ngx_http_headers_conf_t  *conf;
+
+    if (r->headers_out.status != NGX_HTTP_OK) {
+        return ngx_http_next_header_filter(r);
+    }
+
+    conf = ngx_http_get_module_loc_conf(r, ngx_http_headers_filter_module);
+
+    if (conf->expires != NGX_HTTP_EXPIRES_OFF) {
+
+        expires = ngx_list_push(&r->headers_out.headers);
+        if (expires == NULL) {
+            return NGX_ERROR;
+        }
+
+        r->headers_out.expires = expires;
+
+        cc = ngx_list_push(&r->headers_out.headers);
+        if (cc == NULL) {
+            return NGX_ERROR;
+        }
+
+        r->headers_out.cache_control = cc;
+
+        len = sizeof("Mon, 28 Sep 1970 06:00:00 GMT");
+
+        expires->key.len = sizeof("Expires") - 1;
+        expires->key.data = (u_char *) "Expires";
+        expires->value.len = len - 1;
+
+        cc->key.len = sizeof("Cache-Control") - 1;
+        cc->key.data = (u_char *) "Cache-Control";
+
+        if (conf->expires == NGX_HTTP_EXPIRES_EPOCH) {
+            expires->value.data = (u_char *) "Thu, 01 Jan 1970 00:00:01 GMT";
+
+            cc->value.len = sizeof("no-cache") - 1;
+            cc->value.data = (u_char *) "no-cache";
+
+        } else {
+            expires->value.data = ngx_palloc(r->pool, len);
+            if (expires->value.data == NULL) {
+                return NGX_ERROR;
+            }
+
+            if (conf->expires == 0) {
+                ngx_memcpy(expires->value.data, ngx_cached_http_time.data,
+                           ngx_cached_http_time.len + 1);
+
+                cc->value.len = sizeof("max-age=0") - 1;
+                cc->value.data = (u_char *) "max-age=0";
+
+            } else {
+                ngx_http_time(expires->value.data, ngx_time() + conf->expires);
+
+                if (conf->expires < 0) {
+                    cc->value.len = sizeof("no-cache") - 1;
+                    cc->value.data = (u_char *) "no-cache";
+
+                } else {
+                    cc->value.data = ngx_palloc(r->pool, sizeof("max-age=")
+                                                         + NGX_TIME_T_LEN + 1);
+                    if (cc->value.data == NULL) {
+                        return NGX_ERROR;
+                    }
+
+                    cc->value.len = ngx_sprintf(cc->value.data, "max-age=%T",
+                                                conf->expires)
+                                    - cc->value.data;
+
+                }
+            }
+        }
+    }
+
+    return ngx_http_next_header_filter(r);
+}
+
+
+static ngx_int_t
+ngx_http_headers_filter_init(ngx_cycle_t *cycle)
+{
+    ngx_http_next_header_filter = ngx_http_top_header_filter;
+    ngx_http_top_header_filter = ngx_http_headers_filter;
+
+    return NGX_OK;
+}
+
+
+static void *
+ngx_http_headers_create_conf(ngx_conf_t *cf)
+{   
+    ngx_http_headers_conf_t  *conf;
+
+    conf = ngx_palloc(cf->pool, sizeof(ngx_http_headers_conf_t));
+    if (conf == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    conf->expires = NGX_HTTP_EXPIRES_UNSET;
+
+    return conf;
+}
+
+
+static char *
+ngx_http_headers_merge_conf(ngx_conf_t *cf, void *parent, void *child)
+{
+    ngx_http_headers_conf_t *prev = parent;
+    ngx_http_headers_conf_t *conf = child;
+
+    if (conf->expires == NGX_HTTP_EXPIRES_UNSET) {
+        conf->expires = (prev->expires == NGX_HTTP_EXPIRES_UNSET) ?
+                                          NGX_HTTP_EXPIRES_OFF : prev->expires;
+    }
+
+    return NGX_CONF_OK;
+}
+
+
+static char *
+ngx_http_headers_expires(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+    ngx_http_headers_conf_t *hcf = conf;
+
+    ngx_uint_t   minus;
+    ngx_str_t   *value;
+
+    if (hcf->expires != NGX_HTTP_EXPIRES_UNSET) {
+        return "is duplicate";
+    }
+
+    value = cf->args->elts;
+
+    if (ngx_strcmp(value[1].data, "epoch") == 0) {
+        hcf->expires = NGX_HTTP_EXPIRES_EPOCH;
+        return NGX_CONF_OK;
+    }
+
+    if (ngx_strcmp(value[1].data, "off") == 0) {
+        hcf->expires = NGX_HTTP_EXPIRES_OFF;
+        return NGX_CONF_OK;
+    }
+
+    if (value[1].data[0] == '+') {
+        value[1].data++;
+        value[1].len--;
+        minus = 0;
+
+    } else if (value[1].data[0] == '-') {
+        value[1].data++;
+        value[1].len--;
+        minus = 1;
+
+    } else {
+        minus = 0;
+    }
+
+    hcf->expires = ngx_parse_time(&value[1], 1);
+
+    if (hcf->expires == NGX_ERROR) {
+        return "invalid value";
+    }
+    
+    if (hcf->expires == NGX_PARSE_LARGE_TIME) {
+        return "value must be less than 68 years";
+    }
+
+    if (minus) {
+        hcf->expires = - hcf->expires;
+    }
+
+    return NGX_CONF_OK;
+}
deleted file mode 100644
--- a/src/http/modules/ngx_http_index_handler.c
+++ /dev/null
@@ -1,537 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-typedef struct {
-    ngx_array_t              indices;
-    size_t                   max_index_len;
-    ngx_http_cache_hash_t   *index_cache;
-} ngx_http_index_loc_conf_t;
-
-
-typedef struct {
-    ngx_uint_t               index;
-    u_char                  *last;
-    ngx_str_t                path;
-    ngx_str_t                redirect;
-    ngx_http_cache_entry_t  *cache;
-    ngx_uint_t               tested; /* unsigned  tested:1 */
-} ngx_http_index_ctx_t;
-
-
-#define NGX_HTTP_DEFAULT_INDEX   "index.html"
-
-
-static ngx_int_t ngx_http_index_test_dir(ngx_http_request_t *r,
-                                         ngx_http_index_ctx_t *ctx);
-static ngx_int_t ngx_http_index_error(ngx_http_request_t *r,
-                                      ngx_http_index_ctx_t *ctx, ngx_err_t err);
-
-static ngx_int_t ngx_http_index_init(ngx_cycle_t *cycle);
-static void *ngx_http_index_create_loc_conf(ngx_conf_t *cf);
-static char *ngx_http_index_merge_loc_conf(ngx_conf_t *cf,
-                                       void *parent, void *child);
-static char *ngx_http_index_set_index(ngx_conf_t *cf, ngx_command_t *cmd,
-                                      void *conf);
-
-
-static ngx_command_t  ngx_http_index_commands[] = {
-
-    { ngx_string("index"),
-      NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
-      ngx_http_index_set_index,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      0,
-      NULL },
-
-#if (NGX_HTTP_CACHE)
-
-    { ngx_string("index_cache"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE3,
-      ngx_http_set_cache_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_index_loc_conf_t, index_cache),
-      NULL },
-
-#endif
-
-      ngx_null_command
-};
-
-
-ngx_http_module_t  ngx_http_index_module_ctx = {
-    NULL,                                  /* pre conf */
-
-    NULL,                                  /* create main configuration */
-    NULL,                                  /* init main configuration */
-
-    NULL,                                  /* create server configuration */
-    NULL,                                  /* merge server configuration */
-
-    ngx_http_index_create_loc_conf,        /* create location configration */
-    ngx_http_index_merge_loc_conf          /* merge location configration */
-};
-
-
-ngx_module_t  ngx_http_index_module = {
-    NGX_MODULE,
-    &ngx_http_index_module_ctx,            /* module context */
-    ngx_http_index_commands,               /* module directives */
-    NGX_HTTP_MODULE,                       /* module type */
-    ngx_http_index_init,                   /* init module */
-    NULL                                   /* init process */
-};
-
-
-/*
- * Try to open the first index file before the test of the directory existence
- * because the valid requests should be many more than invalid ones.
- * If open() failed then stat() should be more quickly because some data
- * is already cached in the kernel.
- * Besides Win32 has ERROR_PATH_NOT_FOUND (NGX_ENOTDIR).
- * Unix has ENOTDIR error, although it less helpfull - it shows only
- * that path contains the usual file in place of the directory.
- */
-
-static ngx_int_t ngx_http_index_handler(ngx_http_request_t *r)
-{
-    u_char                     *name;
-    ngx_fd_t                    fd;
-    ngx_int_t                   rc;
-    ngx_str_t                  *index;
-    ngx_err_t                   err;
-    ngx_log_t                  *log;
-    ngx_http_index_ctx_t       *ctx;
-    ngx_http_core_loc_conf_t   *clcf;
-    ngx_http_index_loc_conf_t  *ilcf;
-#if (NGX_HTTP_CACHE0)
-    /* crc must be in ctx !! */
-    uint32_t                    crc;
-#endif
-
-    if (r->uri.data[r->uri.len - 1] != '/') {
-        return NGX_DECLINED;
-    }
-
-    /* TODO: Win32 */
-    if (r->zero_in_uri) {
-        return NGX_DECLINED;
-    }
-
-    log = r->connection->log;
-
-    /*
-     * we use context because the handler supports an async file opening
-     * and thus can be called several times
-     */
-
-    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-    ilcf = ngx_http_get_module_loc_conf(r, ngx_http_index_module);
-
-    ctx = ngx_http_get_module_ctx(r, ngx_http_index_module);
-    if (ctx == NULL) {
-        ngx_http_create_ctx(r, ctx, ngx_http_index_module,
-                            sizeof(ngx_http_index_ctx_t),
-                            NGX_HTTP_INTERNAL_SERVER_ERROR);
-
-#if (NGX_HTTP_CACHE)
-
-        if (ilcf->index_cache) {
-            ctx->cache = ngx_http_cache_get(ilcf->index_cache, NULL,
-                                            &r->uri, &crc);
-
-            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
-                           "http index cache get: %p", ctx->cache);
-
-            if (ctx->cache && !ctx->cache->expired) {
-
-                ctx->cache->accessed = ngx_cached_time;
-
-                ctx->redirect.len = ctx->cache->data.value.len;
-                ctx->redirect.data = ngx_palloc(r->pool, ctx->redirect.len + 1);
-                if (ctx->redirect.data == NULL) {
-                    ngx_http_cache_unlock(ilcf->index_cache, ctx->cache, log);
-                    return NGX_HTTP_INTERNAL_SERVER_ERROR;
-                }
-
-                ngx_memcpy(ctx->redirect.data, ctx->cache->data.value.data,
-                           ctx->redirect.len + 1);
-                ngx_http_cache_unlock(ilcf->index_cache, ctx->cache, log);
-
-                return ngx_http_internal_redirect(r, &ctx->redirect, NULL);
-            }
-        }
-
-#endif
-
-#if 0
-        ctx->path.data = ngx_palloc(r->pool, clcf->root.len + r->uri.len
-                                             + ilcf->max_index_len
-                                             - clcf->alias * clcf->name.len);
-        if (ctx->path.data == NULL) {
-            return NGX_HTTP_INTERNAL_SERVER_ERROR;
-        }
-
-        ctx->redirect.data = ngx_cpymem(ctx->path.data, clcf->root.data,
-                                        clcf->root.len);
-#endif
-
-        if (clcf->alias) {
-            ctx->path.data = ngx_palloc(r->pool, clcf->root.len
-                                              + r->uri.len + 1 - clcf->name.len
-                                              + ilcf->max_index_len);
-            if (ctx->path.data == NULL) {
-                return NGX_HTTP_INTERNAL_SERVER_ERROR;
-            }
-
-            ctx->redirect.data = ngx_palloc(r->pool, r->uri.len
-                                            + ilcf->max_index_len);
-            if (ctx->redirect.data == NULL) {
-                return NGX_HTTP_INTERNAL_SERVER_ERROR;
-            }
-
-            ngx_memcpy(ctx->path.data, clcf->root.data, clcf->root.len);
-
-            ctx->last = ngx_cpystrn(ctx->path.data + clcf->root.len,
-                                    r->uri.data + clcf->name.len,
-                                    r->uri.len + 1 - clcf->name.len);
-
-#if 0
-            /*
-             * aliases usually have trailling "/",
-             * set it in the start of the possible redirect
-             */
-
-            if (*ctx->redirect.data != '/') {
-                ctx->redirect.data--; 
-            }
-#endif
-
-        } else {
-            ctx->path.data = ngx_palloc(r->pool, clcf->root.len + r->uri.len
-                                                 + ilcf->max_index_len);
-            if (ctx->path.data == NULL) {
-                return NGX_HTTP_INTERNAL_SERVER_ERROR;
-            }
-
-            ctx->redirect.data = ngx_cpymem(ctx->path.data, clcf->root.data,
-                                            clcf->root.len);
-
-            ctx->last = ngx_cpystrn(ctx->redirect.data, r->uri.data,
-                                    r->uri.len + 1);
-        }
-    }
-
-    ctx->path.len = ctx->last - ctx->path.data;
-
-    index = ilcf->indices.elts;
-    for (/* void */; ctx->index < ilcf->indices.nelts; ctx->index++) {
-
-        if (index[ctx->index].data[0] == '/') {
-            name = index[ctx->index].data;
-
-        } else {
-            ngx_memcpy(ctx->last, index[ctx->index].data,
-                       index[ctx->index].len + 1);
-            name = ctx->path.data;
-        }
-
-        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
-                       "open index \"%s\"", name);
-
-        fd = ngx_open_file(name, NGX_FILE_RDONLY, NGX_FILE_OPEN);
-
-        if (fd == (ngx_fd_t) NGX_AGAIN) {
-            return NGX_AGAIN;
-        }
-
-        if (fd == NGX_INVALID_FILE) {
-            err = ngx_errno;
-
-            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, err,
-                           ngx_open_file_n " \"%s\" failed", name);
-
-            if (err == NGX_ENOTDIR) {
-                return ngx_http_index_error(r, ctx, err);
-
-            } else if (err == NGX_EACCES) {
-                return ngx_http_index_error(r, ctx, err);
-            }
-
-            if (!ctx->tested) {
-                rc = ngx_http_index_test_dir(r, ctx);
-
-                if (rc != NGX_OK) {
-                    return rc;
-                }
-
-                ctx->tested = 1;
-            }
-
-            if (err == NGX_ENOENT) {
-                continue;
-            }
-
-            ngx_log_error(NGX_LOG_ERR, log, err,
-                          ngx_open_file_n " \"%s\" failed", name);
-
-            return NGX_HTTP_INTERNAL_SERVER_ERROR;
-        }
-
-
-        /* STUB: open file cache */
-
-        r->file.name.data = name;
-        r->file.fd = fd;
-
-        if (index[ctx->index].data[0] == '/') {
-            r->file.name.len = index[ctx->index].len;
-            ctx->redirect.len = index[ctx->index].len;
-            ctx->redirect.data = index[ctx->index].data;
-
-        } else {
-            if (clcf->alias) {
-                name = ngx_cpymem(ctx->redirect.data, r->uri.data, r->uri.len);
-                ngx_memcpy(name, index[ctx->index].data,
-                           index[ctx->index].len + 1);
-            }
-
-            ctx->redirect.len = r->uri.len + index[ctx->index].len;
-            r->file.name.len = clcf->root.len + r->uri.len
-                                                - clcf->alias * clcf->name.len
-                                                       + index[ctx->index].len;
-        }
-
-        /**/
-
-
-#if (NGX_HTTP_CACHE)
-
-        if (ilcf->index_cache) {
-
-            if (ctx->cache) {
-                if (ctx->redirect.len == ctx->cache->data.value.len
-                    && ngx_memcmp(ctx->cache->data.value.data,
-                                  ctx->redirect.data, ctx->redirect.len) == 0)
-                {
-                    ctx->cache->accessed = ngx_cached_time;
-                    ctx->cache->updated = ngx_cached_time;
-                    ngx_http_cache_unlock(ilcf->index_cache, ctx->cache, log);
-
-                    return ngx_http_internal_redirect(r, &ctx->redirect, NULL);
-                }
-            }
-
-            ctx->redirect.len++;
-            ctx->cache = ngx_http_cache_alloc(ilcf->index_cache, ctx->cache,
-                                              NULL, &r->uri, crc,
-                                              &ctx->redirect, log);
-            ctx->redirect.len--;
-
-            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
-                           "http index cache alloc: %p", ctx->cache);
-
-            if (ctx->cache) {
-                ctx->cache->fd = NGX_INVALID_FILE;
-                ctx->cache->accessed = ngx_cached_time;
-                ctx->cache->last_modified = 0;
-                ctx->cache->updated = ngx_cached_time;
-                ctx->cache->memory = 1;
-                ngx_http_cache_unlock(ilcf->index_cache, ctx->cache, log);
-            }
-        }
-
-#endif
-
-        return ngx_http_internal_redirect(r, &ctx->redirect, NULL);
-    }
-
-    return NGX_DECLINED;
-}
-
-
-static ngx_int_t ngx_http_index_test_dir(ngx_http_request_t *r,
-                                         ngx_http_index_ctx_t *ctx)
-{
-    ngx_err_t  err;
-
-    ctx->path.data[ctx->path.len - 1] = '\0';
-    ctx->path.data[ctx->path.len] = '\0';
-
-    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                   "http check dir: \"%s\"", ctx->path.data);
-
-    if (ngx_file_info(ctx->path.data, &r->file.info) == -1) {
-
-        err = ngx_errno;
-
-        if (err == NGX_ENOENT) {
-            ctx->path.data[ctx->path.len - 1] = '/';
-            return ngx_http_index_error(r, ctx, err);
-        }
-
-        ngx_log_error(NGX_LOG_CRIT, r->connection->log, err,
-                      ngx_file_info_n " \"%s\" failed", ctx->path.data);
-
-        return NGX_HTTP_INTERNAL_SERVER_ERROR;
-    }
-
-    ctx->path.data[ctx->path.len - 1] = '/';
-
-    if (ngx_is_dir(&r->file.info)) {
-        return NGX_OK;
-    }
-
-    /* THINK: not reached ??? */
-    return ngx_http_index_error(r, ctx, 0);
-}
-
-
-static ngx_int_t ngx_http_index_error(ngx_http_request_t *r,
-                                      ngx_http_index_ctx_t *ctx, ngx_err_t err)
-{
-    if (err == NGX_EACCES) {
-        ngx_log_error(NGX_LOG_ERR, r->connection->log, err,
-                      "\"%s\" is forbidden", ctx->path.data);
-    
-        return NGX_HTTP_FORBIDDEN;
-    }
-
-    ngx_log_error(NGX_LOG_ERR, r->connection->log, err,
-                  "\"%s\" is not found", ctx->path.data);
-    return NGX_HTTP_NOT_FOUND;
-}
-
-
-static ngx_int_t ngx_http_index_init(ngx_cycle_t *cycle)
-{
-    ngx_http_handler_pt        *h;
-    ngx_http_core_main_conf_t  *cmcf;
-
-    cmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_core_module);
-
-    h = ngx_push_array(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers);
-    if (h == NULL) {
-        return NGX_ERROR;
-    }
-
-    *h = ngx_http_index_handler;
-
-    return NGX_OK;
-}
-
-
-static void *ngx_http_index_create_loc_conf(ngx_conf_t *cf)
-{
-    ngx_http_index_loc_conf_t  *conf;
-
-    ngx_test_null(conf, ngx_palloc(cf->pool, sizeof(ngx_http_index_loc_conf_t)),
-                  NGX_CONF_ERROR);
-
-    ngx_init_array(conf->indices, cf->pool, 3, sizeof(ngx_str_t),
-                   NGX_CONF_ERROR);
-    conf->max_index_len = 0;
-
-    conf->index_cache = NULL;
-
-    return conf;
-}
-
-
-/* TODO: remove duplicate indices */
-
-static char *ngx_http_index_merge_loc_conf(ngx_conf_t *cf,
-                                           void *parent, void *child)
-{
-    ngx_http_index_loc_conf_t  *prev = parent;
-    ngx_http_index_loc_conf_t  *conf = child;
-
-    ngx_str_t  *index;
-
-    if (conf->max_index_len == 0) {
-        if (prev->max_index_len != 0) {
-            ngx_memcpy(conf, prev, sizeof(ngx_http_index_loc_conf_t));
-            return NGX_CONF_OK;
-        }
-
-        ngx_test_null(index, ngx_push_array(&conf->indices), NGX_CONF_ERROR);
-        index->len = sizeof(NGX_HTTP_DEFAULT_INDEX) - 1;
-        index->data = (u_char *) NGX_HTTP_DEFAULT_INDEX;
-        conf->max_index_len = sizeof(NGX_HTTP_DEFAULT_INDEX);
-
-        return NGX_CONF_OK;
-    }
-
-#if 0
-
-    if (prev->max_index_len != 0) {
-
-        prev_index = prev->indices.elts;
-        for (i = 0; i < prev->indices.nelts; i++) {
-            ngx_test_null(index, ngx_push_array(&conf->indices),
-                          NGX_CONF_ERROR);
-            index->len = prev_index[i].len;
-            index->data = prev_index[i].data;
-        }
-    }
-
-    if (conf->max_index_len < prev->max_index_len) {
-        conf->max_index_len = prev->max_index_len;
-    }
-
-#endif
-
-    if (conf->index_cache == NULL) {
-        conf->index_cache = prev->index_cache;
-    }
-
-    return NGX_CONF_OK;
-}
-
-
-/* TODO: warn about duplicate indices */
-
-static char *ngx_http_index_set_index(ngx_conf_t *cf, ngx_command_t *cmd,
-                                      void *conf)
-{
-    ngx_http_index_loc_conf_t *ilcf = conf;
-
-    ngx_uint_t  i;
-    ngx_str_t  *index, *value;
-
-    value = cf->args->elts;
-
-    if (value[1].data[0] == '/' && ilcf->indices.nelts == 0) {
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                           "first index \"%V\" in \"%V\" directive "
-                           "must not be absolute",
-                           &value[1], &cmd->name);
-        return NGX_CONF_ERROR;
-    }
-
-    for (i = 1; i < cf->args->nelts; i++) {
-        if (value[i].len == 0) {
-            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                               "index \"%V\" in \"%V\" directive is invalid",
-                               &value[1], &cmd->name);
-            return NGX_CONF_ERROR;
-        }
-
-        ngx_test_null(index, ngx_push_array(&ilcf->indices), NGX_CONF_ERROR);
-        index->len = value[i].len;
-        index->data = value[i].data;
-
-        if (ilcf->max_index_len < index->len + 1) {
-            ilcf->max_index_len = index->len + 1;
-        }
-    }
-
-    return NGX_CONF_OK;
-}
new file mode 100644
--- /dev/null
+++ b/src/http/modules/ngx_http_index_module.c
@@ -0,0 +1,558 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+
+
+typedef struct {
+    ngx_array_t              indices;
+    size_t                   max_index_len;
+    ngx_http_cache_hash_t   *index_cache;
+} ngx_http_index_loc_conf_t;
+
+
+typedef struct {
+    ngx_uint_t               index;
+    u_char                  *last;
+    ngx_str_t                path;
+    ngx_str_t                redirect;
+    ngx_http_cache_entry_t  *cache;
+    ngx_uint_t               tested; /* unsigned  tested:1 */
+} ngx_http_index_ctx_t;
+
+
+#define NGX_HTTP_DEFAULT_INDEX   "index.html"
+
+
+static ngx_int_t ngx_http_index_test_dir(ngx_http_request_t *r,
+                                         ngx_http_index_ctx_t *ctx);
+static ngx_int_t ngx_http_index_error(ngx_http_request_t *r,
+                                      ngx_http_index_ctx_t *ctx, ngx_err_t err);
+
+static ngx_int_t ngx_http_index_init(ngx_cycle_t *cycle);
+static void *ngx_http_index_create_loc_conf(ngx_conf_t *cf);
+static char *ngx_http_index_merge_loc_conf(ngx_conf_t *cf,
+                                       void *parent, void *child);
+static char *ngx_http_index_set_index(ngx_conf_t *cf, ngx_command_t *cmd,
+                                      void *conf);
+
+
+static ngx_command_t  ngx_http_index_commands[] = {
+
+    { ngx_string("index"),
+      NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
+      ngx_http_index_set_index,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      0,
+      NULL },
+
+#if (NGX_HTTP_CACHE)
+
+    { ngx_string("index_cache"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE3,
+      ngx_http_set_cache_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_index_loc_conf_t, index_cache),
+      NULL },
+
+#endif
+
+      ngx_null_command
+};
+
+
+ngx_http_module_t  ngx_http_index_module_ctx = {
+    NULL,                                  /* pre conf */
+
+    NULL,                                  /* create main configuration */
+    NULL,                                  /* init main configuration */
+
+    NULL,                                  /* create server configuration */
+    NULL,                                  /* merge server configuration */
+
+    ngx_http_index_create_loc_conf,        /* create location configration */
+    ngx_http_index_merge_loc_conf          /* merge location configration */
+};
+
+
+ngx_module_t  ngx_http_index_module = {
+    NGX_MODULE,
+    &ngx_http_index_module_ctx,            /* module context */
+    ngx_http_index_commands,               /* module directives */
+    NGX_HTTP_MODULE,                       /* module type */
+    ngx_http_index_init,                   /* init module */
+    NULL                                   /* init process */
+};
+
+
+/*
+ * Try to open the first index file before the test of the directory existence
+ * because the valid requests should be many more than invalid ones.
+ * If open() would fail, then stat() should be more quickly because some data
+ * is already cached in the kernel.
+ * Besides, Win32 has ERROR_PATH_NOT_FOUND (NGX_ENOTDIR).
+ * Unix has ENOTDIR error, although it less helpfull - it points only
+ * that path contains the usual file in place of the directory.
+ */
+
+static ngx_int_t ngx_http_index_handler(ngx_http_request_t *r)
+{
+    u_char                     *name;
+    ngx_fd_t                    fd;
+    ngx_int_t                   rc;
+    ngx_str_t                  *index;
+    ngx_err_t                   err;
+    ngx_log_t                  *log;
+    ngx_http_index_ctx_t       *ctx;
+    ngx_http_core_loc_conf_t   *clcf;
+    ngx_http_index_loc_conf_t  *ilcf;
+#if (NGX_HTTP_CACHE0)
+    /* crc must be in ctx !! */
+    uint32_t                    crc;
+#endif
+
+    if (r->uri.data[r->uri.len - 1] != '/') {
+        return NGX_DECLINED;
+    }
+
+    /* TODO: Win32 */
+    if (r->zero_in_uri) {
+        return NGX_DECLINED;
+    }
+
+    log = r->connection->log;
+
+    /*
+     * we use context because the handler supports an async file opening
+     * and thus can be called several times
+     */
+
+    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+    ilcf = ngx_http_get_module_loc_conf(r, ngx_http_index_module);
+
+    ctx = ngx_http_get_module_ctx(r, ngx_http_index_module);
+    if (ctx == NULL) {
+
+        ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_index_ctx_t));
+        if (ctx == NULL) {
+            return NGX_HTTP_INTERNAL_SERVER_ERROR;
+        }
+
+        ngx_http_set_ctx(r, ctx, ngx_http_index_module);
+
+#if (NGX_HTTP_CACHE)
+
+        if (ilcf->index_cache) {
+            ctx->cache = ngx_http_cache_get(ilcf->index_cache, NULL,
+                                            &r->uri, &crc);
+
+            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
+                           "http index cache get: %p", ctx->cache);
+
+            if (ctx->cache && !ctx->cache->expired) {
+
+                ctx->cache->accessed = ngx_cached_time;
+
+                ctx->redirect.len = ctx->cache->data.value.len;
+                ctx->redirect.data = ngx_palloc(r->pool, ctx->redirect.len + 1);
+                if (ctx->redirect.data == NULL) {
+                    ngx_http_cache_unlock(ilcf->index_cache, ctx->cache, log);
+                    return NGX_HTTP_INTERNAL_SERVER_ERROR;
+                }
+
+                ngx_memcpy(ctx->redirect.data, ctx->cache->data.value.data,
+                           ctx->redirect.len + 1);
+                ngx_http_cache_unlock(ilcf->index_cache, ctx->cache, log);
+
+                return ngx_http_internal_redirect(r, &ctx->redirect, NULL);
+            }
+        }
+
+#endif
+
+#if 0
+        ctx->path.data = ngx_palloc(r->pool, clcf->root.len + r->uri.len
+                                             + ilcf->max_index_len
+                                             - clcf->alias * clcf->name.len);
+        if (ctx->path.data == NULL) {
+            return NGX_HTTP_INTERNAL_SERVER_ERROR;
+        }
+
+        ctx->redirect.data = ngx_cpymem(ctx->path.data, clcf->root.data,
+                                        clcf->root.len);
+#endif
+
+        if (clcf->alias) {
+            ctx->path.data = ngx_palloc(r->pool, clcf->root.len
+                                              + r->uri.len + 1 - clcf->name.len
+                                              + ilcf->max_index_len);
+            if (ctx->path.data == NULL) {
+                return NGX_HTTP_INTERNAL_SERVER_ERROR;
+            }
+
+            ctx->redirect.data = ngx_palloc(r->pool, r->uri.len
+                                            + ilcf->max_index_len);
+            if (ctx->redirect.data == NULL) {
+                return NGX_HTTP_INTERNAL_SERVER_ERROR;
+            }
+
+            ngx_memcpy(ctx->path.data, clcf->root.data, clcf->root.len);
+
+            ctx->last = ngx_cpystrn(ctx->path.data + clcf->root.len,
+                                    r->uri.data + clcf->name.len,
+                                    r->uri.len + 1 - clcf->name.len);
+
+#if 0
+            /*
+             * aliases usually have trailling "/",
+             * set it in the start of the possible redirect
+             */
+
+            if (*ctx->redirect.data != '/') {
+                ctx->redirect.data--; 
+            }
+#endif
+
+        } else {
+            ctx->path.data = ngx_palloc(r->pool, clcf->root.len + r->uri.len
+                                                 + ilcf->max_index_len);
+            if (ctx->path.data == NULL) {
+                return NGX_HTTP_INTERNAL_SERVER_ERROR;
+            }
+
+            ctx->redirect.data = ngx_cpymem(ctx->path.data, clcf->root.data,
+                                            clcf->root.len);
+
+            ctx->last = ngx_cpystrn(ctx->redirect.data, r->uri.data,
+                                    r->uri.len + 1);
+        }
+    }
+
+    ctx->path.len = ctx->last - ctx->path.data;
+
+    index = ilcf->indices.elts;
+    for (/* void */; ctx->index < ilcf->indices.nelts; ctx->index++) {
+
+        if (index[ctx->index].data[0] == '/') {
+            name = index[ctx->index].data;
+
+        } else {
+            ngx_memcpy(ctx->last, index[ctx->index].data,
+                       index[ctx->index].len + 1);
+            name = ctx->path.data;
+        }
+
+        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
+                       "open index \"%s\"", name);
+
+        fd = ngx_open_file(name, NGX_FILE_RDONLY, NGX_FILE_OPEN);
+
+        if (fd == (ngx_fd_t) NGX_AGAIN) {
+            return NGX_AGAIN;
+        }
+
+        if (fd == NGX_INVALID_FILE) {
+            err = ngx_errno;
+
+            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, err,
+                           ngx_open_file_n " \"%s\" failed", name);
+
+            if (err == NGX_ENOTDIR) {
+                return ngx_http_index_error(r, ctx, err);
+
+            } else if (err == NGX_EACCES) {
+                return ngx_http_index_error(r, ctx, err);
+            }
+
+            if (!ctx->tested) {
+                rc = ngx_http_index_test_dir(r, ctx);
+
+                if (rc != NGX_OK) {
+                    return rc;
+                }
+
+                ctx->tested = 1;
+            }
+
+            if (err == NGX_ENOENT) {
+                continue;
+            }
+
+            ngx_log_error(NGX_LOG_ERR, log, err,
+                          ngx_open_file_n " \"%s\" failed", name);
+
+            return NGX_HTTP_INTERNAL_SERVER_ERROR;
+        }
+
+
+        /* STUB: open file cache */
+
+        r->file.name.data = name;
+        r->file.fd = fd;
+
+        if (index[ctx->index].data[0] == '/') {
+            r->file.name.len = index[ctx->index].len;
+            ctx->redirect.len = index[ctx->index].len;
+            ctx->redirect.data = index[ctx->index].data;
+
+        } else {
+            if (clcf->alias) {
+                name = ngx_cpymem(ctx->redirect.data, r->uri.data, r->uri.len);
+                ngx_memcpy(name, index[ctx->index].data,
+                           index[ctx->index].len + 1);
+            }
+
+            ctx->redirect.len = r->uri.len + index[ctx->index].len;
+            r->file.name.len = clcf->root.len + r->uri.len
+                                                - clcf->alias * clcf->name.len
+                                                       + index[ctx->index].len;
+        }
+
+        /**/
+
+
+#if (NGX_HTTP_CACHE)
+
+        if (ilcf->index_cache) {
+
+            if (ctx->cache) {
+                if (ctx->redirect.len == ctx->cache->data.value.len
+                    && ngx_memcmp(ctx->cache->data.value.data,
+                                  ctx->redirect.data, ctx->redirect.len) == 0)
+                {
+                    ctx->cache->accessed = ngx_cached_time;
+                    ctx->cache->updated = ngx_cached_time;
+                    ngx_http_cache_unlock(ilcf->index_cache, ctx->cache, log);
+
+                    return ngx_http_internal_redirect(r, &ctx->redirect, NULL);
+                }
+            }
+
+            ctx->redirect.len++;
+            ctx->cache = ngx_http_cache_alloc(ilcf->index_cache, ctx->cache,
+                                              NULL, &r->uri, crc,
+                                              &ctx->redirect, log);
+            ctx->redirect.len--;
+
+            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
+                           "http index cache alloc: %p", ctx->cache);
+
+            if (ctx->cache) {
+                ctx->cache->fd = NGX_INVALID_FILE;
+                ctx->cache->accessed = ngx_cached_time;
+                ctx->cache->last_modified = 0;
+                ctx->cache->updated = ngx_cached_time;
+                ctx->cache->memory = 1;
+                ngx_http_cache_unlock(ilcf->index_cache, ctx->cache, log);
+            }
+        }
+
+#endif
+
+        return ngx_http_internal_redirect(r, &ctx->redirect, NULL);
+    }
+
+    return NGX_DECLINED;
+}
+
+
+static ngx_int_t ngx_http_index_test_dir(ngx_http_request_t *r,
+                                         ngx_http_index_ctx_t *ctx)
+{
+    ngx_err_t  err;
+
+    ctx->path.data[ctx->path.len - 1] = '\0';
+    ctx->path.data[ctx->path.len] = '\0';
+
+    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                   "http check dir: \"%s\"", ctx->path.data);
+
+    if (ngx_file_info(ctx->path.data, &r->file.info) == -1) {
+
+        err = ngx_errno;
+
+        if (err == NGX_ENOENT) {
+            ctx->path.data[ctx->path.len - 1] = '/';
+            return ngx_http_index_error(r, ctx, err);
+        }
+
+        ngx_log_error(NGX_LOG_CRIT, r->connection->log, err,
+                      ngx_file_info_n " \"%s\" failed", ctx->path.data);
+
+        return NGX_HTTP_INTERNAL_SERVER_ERROR;
+    }
+
+    ctx->path.data[ctx->path.len - 1] = '/';
+
+    if (ngx_is_dir(&r->file.info)) {
+        return NGX_OK;
+    }
+
+    /* THINK: not reached ??? */
+    return ngx_http_index_error(r, ctx, 0);
+}
+
+
+static ngx_int_t ngx_http_index_error(ngx_http_request_t *r,
+                                      ngx_http_index_ctx_t *ctx, ngx_err_t err)
+{
+    if (err == NGX_EACCES) {
+        ngx_log_error(NGX_LOG_ERR, r->connection->log, err,
+                      "\"%s\" is forbidden", ctx->path.data);
+    
+        return NGX_HTTP_FORBIDDEN;
+    }
+
+    ngx_log_error(NGX_LOG_ERR, r->connection->log, err,
+                  "\"%s\" is not found", ctx->path.data);
+    return NGX_HTTP_NOT_FOUND;
+}
+
+
+static ngx_int_t ngx_http_index_init(ngx_cycle_t *cycle)
+{
+    ngx_http_handler_pt        *h;
+    ngx_http_core_main_conf_t  *cmcf;
+
+    cmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_core_module);
+
+    h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers);
+    if (h == NULL) {
+        return NGX_ERROR;
+    }
+
+    *h = ngx_http_index_handler;
+
+    return NGX_OK;
+}
+
+
+static void *ngx_http_index_create_loc_conf(ngx_conf_t *cf)
+{
+    ngx_http_index_loc_conf_t  *conf;
+
+    conf = ngx_palloc(cf->pool, sizeof(ngx_http_index_loc_conf_t));
+    if (conf == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    if (ngx_array_init(&conf->indices, cf->pool, 2, sizeof(ngx_str_t))
+                                                                  == NGX_ERROR)
+    {
+        return NGX_CONF_ERROR;
+    }
+
+    conf->max_index_len = 0;
+
+    conf->index_cache = NULL;
+
+    return conf;
+}
+
+
+/* TODO: remove duplicate indices */
+
+static char *ngx_http_index_merge_loc_conf(ngx_conf_t *cf,
+                                           void *parent, void *child)
+{
+    ngx_http_index_loc_conf_t  *prev = parent;
+    ngx_http_index_loc_conf_t  *conf = child;
+
+    ngx_str_t  *index;
+
+    if (conf->max_index_len == 0) {
+        if (prev->max_index_len != 0) {
+            ngx_memcpy(conf, prev, sizeof(ngx_http_index_loc_conf_t));
+            return NGX_CONF_OK;
+        }
+
+        index = ngx_array_push(&conf->indices);
+        if (index == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+        index->len = sizeof(NGX_HTTP_DEFAULT_INDEX) - 1;
+        index->data = (u_char *) NGX_HTTP_DEFAULT_INDEX;
+        conf->max_index_len = sizeof(NGX_HTTP_DEFAULT_INDEX);
+
+        return NGX_CONF_OK;
+    }
+
+#if 0
+
+    if (prev->max_index_len != 0) {
+
+        prev_index = prev->indices.elts;
+        for (i = 0; i < prev->indices.nelts; i++) {
+            index = ngx_array_push(&conf->indices);
+            if (index == NULL) {
+                return NGX_CONF_ERROR;
+            }
+
+            index->len = prev_index[i].len;
+            index->data = prev_index[i].data;
+        }
+    }
+
+    if (conf->max_index_len < prev->max_index_len) {
+        conf->max_index_len = prev->max_index_len;
+    }
+
+#endif
+
+    if (conf->index_cache == NULL) {
+        conf->index_cache = prev->index_cache;
+    }
+
+    return NGX_CONF_OK;
+}
+
+
+/* TODO: warn about duplicate indices */
+
+static char *ngx_http_index_set_index(ngx_conf_t *cf, ngx_command_t *cmd,
+                                      void *conf)
+{
+    ngx_http_index_loc_conf_t *ilcf = conf;
+
+    ngx_uint_t  i;
+    ngx_str_t  *index, *value;
+
+    value = cf->args->elts;
+
+    if (value[1].data[0] == '/' && ilcf->indices.nelts == 0) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                           "first index \"%V\" in \"%V\" directive "
+                           "must not be absolute",
+                           &value[1], &cmd->name);
+        return NGX_CONF_ERROR;
+    }
+
+    for (i = 1; i < cf->args->nelts; i++) {
+        if (value[i].len == 0) {
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                               "index \"%V\" in \"%V\" directive is invalid",
+                               &value[1], &cmd->name);
+            return NGX_CONF_ERROR;
+        }
+
+        index = ngx_array_push(&ilcf->indices);
+        if (index == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+        index->len = value[i].len;
+        index->data = value[i].data;
+
+        if (ilcf->max_index_len < index->len + 1) {
+            ilcf->max_index_len = index->len + 1;
+        }
+    }
+
+    return NGX_CONF_OK;
+}
rename from src/http/modules/ngx_http_not_modified_filter.c
rename to src/http/modules/ngx_http_not_modified_filter_module.c
deleted file mode 100644
--- a/src/http/modules/ngx_http_range_filter.c
+++ /dev/null
@@ -1,578 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-/*
- * the single part format:
- *
- * "HTTP/1.0 206 Partial Content" CRLF
- * ... header ...
- * "Content-Type: image/jpeg" CRLF
- * "Content-Length: SIZE" CRLF
- * "Content-Range: bytes START-END/SIZE" CRLF
- * CRLF
- * ... data ...
- *
- *
- * the mutlipart format:
- *
- * "HTTP/1.0 206 Partial Content" CRLF
- * ... header ...
- * "Content-Type: multipart/byteranges; boundary=0123456789" CRLF
- * CRLF
- * CRLF
- * "--0123456789" CRLF
- * "Content-Type: image/jpeg" CRLF
- * "Content-Range: bytes START0-END0/SIZE" CRLF
- * CRLF
- * ... data ...
- * CRLF
- * "--0123456789" CRLF
- * "Content-Type: image/jpeg" CRLF
- * "Content-Range: bytes START1-END1/SIZE" CRLF
- * CRLF
- * ... data ...
- * CRLF
- * "--0123456789--" CRLF
- */
-
-
-typedef struct {
-    ngx_str_t  boundary_header;
-} ngx_http_range_filter_ctx_t;
-
-
-static ngx_int_t ngx_http_range_header_filter_init(ngx_cycle_t *cycle);
-static ngx_int_t ngx_http_range_body_filter_init(ngx_cycle_t *cycle);
-
-
-static ngx_http_module_t  ngx_http_range_header_filter_module_ctx = {
-    NULL,                                  /* pre conf */
-
-    NULL,                                  /* create main configuration */
-    NULL,                                  /* init main configuration */
-
-    NULL,                                  /* create server configuration */
-    NULL,                                  /* merge server configuration */
-
-    NULL,                                  /* create location configuration */
-    NULL,                                  /* merge location configuration */
-};
-
-
-ngx_module_t  ngx_http_range_header_filter_module = {
-    NGX_MODULE,
-    &ngx_http_range_header_filter_module_ctx, /* module context */
-    NULL,                                  /* module directives */
-    NGX_HTTP_MODULE,                       /* module type */
-    ngx_http_range_header_filter_init,     /* init module */
-    NULL                                   /* init process */
-};
-
-
-static ngx_http_module_t  ngx_http_range_body_filter_module_ctx = {
-    NULL,                                  /* pre conf */
-
-    NULL,                                  /* create main configuration */
-    NULL,                                  /* init main configuration */
-
-    NULL,                                  /* create server configuration */
-    NULL,                                  /* merge server configuration */
-
-    NULL,                                  /* create location configuration */
-    NULL,                                  /* merge location configuration */
-};
-
-
-ngx_module_t  ngx_http_range_body_filter_module = {
-    NGX_MODULE,
-    &ngx_http_range_body_filter_module_ctx, /* module context */
-    NULL,                                  /* module directives */
-    NGX_HTTP_MODULE,                       /* module type */
-    ngx_http_range_body_filter_init,       /* init module */
-    NULL                                   /* init process */
-};
-
-
-static ngx_http_output_header_filter_pt  ngx_http_next_header_filter;
-static ngx_http_output_body_filter_pt    ngx_http_next_body_filter;
-
-
-static ngx_int_t
-ngx_http_range_header_filter(ngx_http_request_t *r)
-{
-    u_char                       *p;
-    size_t                        len;
-    off_t                         start, end;
-    ngx_int_t                     rc;
-    ngx_uint_t                    suffix, i;
-    ngx_atomic_uint_t             boundary;
-    ngx_table_elt_t              *content_range;
-    ngx_http_range_t             *range;
-    ngx_http_range_filter_ctx_t  *ctx;
-
-    if (r->http_version < NGX_HTTP_VERSION_10
-        || r->headers_out.status != NGX_HTTP_OK
-        || r->headers_out.content_length_n == -1
-        || !r->filter_allow_ranges)
-    {
-        return ngx_http_next_header_filter(r);
-    }
-
-    if (r->headers_in.range == NULL
-        || r->headers_in.range->value.len < 7
-        || ngx_strncasecmp(r->headers_in.range->value.data, "bytes=", 6) != 0)
-    {
-
-        r->headers_out.accept_ranges = ngx_list_push(&r->headers_out.headers);
-        if (r->headers_out.accept_ranges == NULL) {
-            return NGX_ERROR;
-        }
-
-        r->headers_out.accept_ranges->key.len = sizeof("Accept-Ranges") - 1;
-        r->headers_out.accept_ranges->key.data = (u_char *) "Accept-Ranges";
-        r->headers_out.accept_ranges->value.len = sizeof("bytes") - 1;
-        r->headers_out.accept_ranges->value.data = (u_char *) "bytes";
-
-        return ngx_http_next_header_filter(r);
-    }
-
-    if (ngx_array_init(&r->headers_out.ranges, r->pool, 2,
-                                        sizeof(ngx_http_range_t)) == NGX_ERROR)
-    {
-        return NGX_ERROR;
-    }
-
-    rc = 0;
-    range = NULL;
-    p = r->headers_in.range->value.data + 6;
-
-    for ( ;; ) {
-        start = 0;
-        end = 0;
-        suffix = 0;
-
-        while (*p == ' ') { p++; }
-
-        if (*p != '-') {
-            if (*p < '0' || *p > '9') {
-                rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;
-                break;
-            }
-
-            while (*p >= '0' && *p <= '9') {
-                start = start * 10 + *p++ - '0';
-            }
-
-            while (*p == ' ') { p++; }
-
-            if (*p++ != '-') {
-                rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;
-                break;
-            }
-
-            if (start >= r->headers_out.content_length_n) {
-                rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;
-                break;
-            }
-
-            while (*p == ' ') { p++; }
-
-            if (*p == ',' || *p == '\0') {
-                if (!(range = ngx_array_push(&r->headers_out.ranges))) {
-                    return NGX_ERROR;
-                }
-
-                range->start = start;
-                range->end = r->headers_out.content_length_n;
-
-                if (*p++ != ',') {
-                    break;
-                }
-
-                continue;
-            }
-
-        } else {
-            suffix = 1;
-            p++;
-        }
-
-        if (*p < '0' || *p > '9') {
-            rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;
-            break;
-        }
-
-        while (*p >= '0' && *p <= '9') {
-            end = end * 10 + *p++ - '0';
-        }
-
-        while (*p == ' ') { p++; }
-
-        if (*p != ',' && *p != '\0') {
-            rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;
-            break;
-        }
-
-        if (suffix) {
-           start = r->headers_out.content_length_n - end;
-           end = r->headers_out.content_length_n - 1;
-        }
-
-        if (start > end) {
-            rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;
-            break;
-        }
-
-        if (!(range = ngx_array_push(&r->headers_out.ranges))) {
-            return NGX_ERROR;
-        }
-
-        range->start = start;
-
-        if (end >= r->headers_out.content_length_n) {
-            /*
-             * Download Accelerator sends the last byte position
-             * that equals to the file length
-             */
-            range->end = r->headers_out.content_length_n;
-
-        } else {
-            range->end = end + 1;
-        }
-
-        if (*p++ != ',') {
-            break;
-        }
-    }
-
-    if (rc) {
-
-        /* rc == NGX_HTTP_RANGE_NOT_SATISFIABLE */
-
-        r->headers_out.status = rc;
-        r->headers_out.ranges.nelts = 0;
-
-        if (!(content_range = ngx_list_push(&r->headers_out.headers))) {
-            return NGX_ERROR;
-        }
-
-        r->headers_out.content_range = content_range;
-
-        content_range->key.len = sizeof("Content-Range") - 1;
-        content_range->key.data = (u_char *) "Content-Range";
-
-        content_range->value.data =
-                   ngx_palloc(r->pool, sizeof("bytes */") - 1 + NGX_OFF_T_LEN);
-
-        if (content_range->value.data == NULL) {
-            return NGX_ERROR;
-        }
-
-        content_range->value.len = ngx_sprintf(content_range->value.data,
-                                               "bytes */%O",
-                                               r->headers_out.content_length_n)
-                                   - content_range->value.data;
-
-        r->headers_out.content_length_n = -1;
-        if (r->headers_out.content_length) {
-            r->headers_out.content_length->key.len = 0;
-            r->headers_out.content_length = NULL;
-        }
-
-        return rc;
-    }
-
-    r->headers_out.status = NGX_HTTP_PARTIAL_CONTENT;
-
-    if (r->headers_out.ranges.nelts == 1) {
-
-        if (!(content_range = ngx_list_push(&r->headers_out.headers))) {
-            return NGX_ERROR;
-        }
-
-        r->headers_out.content_range = content_range;
-
-        content_range->key.len = sizeof("Content-Range") - 1;
-        content_range->key.data = (u_char *) "Content-Range";
-
-        content_range->value.data =
-               ngx_palloc(r->pool, sizeof("bytes -/") - 1 + 3 * NGX_OFF_T_LEN);
-        if (content_range->value.data == NULL) {
-            return NGX_ERROR;
-        }
-
-        /* "Content-Range: bytes SSSS-EEEE/TTTT" header */
-
-        content_range->value.len = ngx_sprintf(content_range->value.data,
-                                               "bytes %O-%O/%O",
-                                               range->start, range->end - 1,
-                                               r->headers_out.content_length_n)
-                                   - content_range->value.data;
-
-        r->headers_out.content_length_n = range->end - range->start;
-
-        return ngx_http_next_header_filter(r);
-    }
-
-
-    /* TODO: what if no content_type ?? */
-
-    ngx_http_create_ctx(r, ctx, ngx_http_range_body_filter_module,
-                        sizeof(ngx_http_range_filter_ctx_t), NGX_ERROR);
-
-
-    len = sizeof(CRLF "--") - 1 + NGX_ATOMIC_T_LEN
-          + sizeof(CRLF "Content-Type: ") - 1
-          + r->headers_out.content_type->value.len
-          + sizeof(CRLF "Content-Range: bytes ") - 1;
-
-    if (r->headers_out.charset.len) {
-        len += sizeof("; charset=") - 1 + r->headers_out.charset.len;
-    }
-
-    if (!(ctx->boundary_header.data = ngx_palloc(r->pool, len))) {
-        return NGX_ERROR;
-    }
-
-    boundary = ngx_next_temp_number(0);
-
-    /*
-     * The boundary header of the range:
-     * CRLF
-     * "--0123456789" CRLF
-     * "Content-Type: image/jpeg" CRLF
-     * "Content-Range: bytes "
-     */
-
-    if (r->headers_out.charset.len) {
-        ctx->boundary_header.len = ngx_sprintf(ctx->boundary_header.data,
-                                           CRLF "--%0muA" CRLF
-                                           "Content-Type: %V; charset=%V" CRLF
-                                           "Content-Range: bytes ",
-                                           boundary,
-                                           &r->headers_out.content_type->value,
-                                           &r->headers_out.charset)
-                                   - ctx->boundary_header.data;
-
-        r->headers_out.charset.len = 0;
-
-    } else {
-        ctx->boundary_header.len = ngx_sprintf(ctx->boundary_header.data,
-                                           CRLF "--%0muA" CRLF
-                                           "Content-Type: %V" CRLF
-                                           "Content-Range: bytes ",
-                                           boundary,
-                                           &r->headers_out.content_type->value)
-                                   - ctx->boundary_header.data;
-    }
-
-    r->headers_out.content_type->value.data =
-         ngx_palloc(r->pool,
-                    sizeof("Content-Type: multipart/byteranges; boundary=") - 1
-                    + NGX_ATOMIC_T_LEN);
-
-    if (r->headers_out.content_type->value.data == NULL) {
-        return NGX_ERROR;
-    }
-
-    /* "Content-Type: multipart/byteranges; boundary=0123456789" */
-
-    r->headers_out.content_type->value.len =
-                           ngx_sprintf(r->headers_out.content_type->value.data,
-                                       "multipart/byteranges; boundary=%0muA",
-                                       boundary)
-                           - r->headers_out.content_type->value.data;
-
-
-    /* the size of the last boundary CRLF "--0123456789--" CRLF */
-
-    len = sizeof(CRLF "--") - 1 + NGX_ATOMIC_T_LEN + sizeof("--" CRLF) - 1;
-
-    range = r->headers_out.ranges.elts;
-    for (i = 0; i < r->headers_out.ranges.nelts; i++) {
-
-        /* the size of the range: "SSSS-EEEE/TTTT" CRLF CRLF */
-
-        range[i].content_range.data =
-                                ngx_palloc(r->pool, 3 * NGX_OFF_T_LEN + 2 + 4);
-
-        if (range[i].content_range.data == NULL) {
-            return NGX_ERROR;
-        }
-
-        range[i].content_range.len = ngx_sprintf(range[i].content_range.data,
-                                               "%O-%O/%O" CRLF CRLF,
-                                               range[i].start, range[i].end - 1,
-                                               r->headers_out.content_length_n)
-                                     - range[i].content_range.data;
-
-        len += ctx->boundary_header.len + range[i].content_range.len
-                                    + (size_t) (range[i].end - range[i].start);
-    }
-
-    r->headers_out.content_length_n = len;
-    r->headers_out.content_length = NULL;
-
-    return ngx_http_next_header_filter(r);
-}
-
-
-static ngx_int_t
-ngx_http_range_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
-{
-    ngx_uint_t                    i;
-    ngx_buf_t                    *b;
-    ngx_chain_t                  *out, *hcl, *rcl, *dcl, **ll;
-    ngx_http_range_t             *range;
-    ngx_http_range_filter_ctx_t  *ctx;
-
-    if (r->headers_out.ranges.nelts == 0) {
-        return ngx_http_next_body_filter(r, in);
-    }
-
-    /*
-     * the optimized version for the static files only
-     * that are passed in the single file buf
-     */
-
-    if (in && in->buf->in_file && in->buf->last_buf) {
-        range = r->headers_out.ranges.elts;
-
-        if (r->headers_out.ranges.nelts == 1) {
-            in->buf->file_pos = range->start;
-            in->buf->file_last = range->end;
-
-            return ngx_http_next_body_filter(r, in);
-        }
-
-        ctx = ngx_http_get_module_ctx(r, ngx_http_range_body_filter_module);
-        ll = &out;
-
-        for (i = 0; i < r->headers_out.ranges.nelts; i++) {
-
-            /*
-             * The boundary header of the range:
-             * CRLF
-             * "--0123456789" CRLF
-             * "Content-Type: image/jpeg" CRLF
-             * "Content-Range: bytes "
-             */
-
-            if (!(b = ngx_calloc_buf(r->pool))) {
-                return NGX_ERROR;
-            }
-
-            b->memory = 1;
-            b->pos = ctx->boundary_header.data;
-            b->last = ctx->boundary_header.data + ctx->boundary_header.len;
-
-            if (!(hcl = ngx_alloc_chain_link(r->pool))) {
-                return NGX_ERROR;
-            }
-
-            hcl->buf = b;
-
-
-            /* "SSSS-EEEE/TTTT" CRLF CRLF */
-
-            if (!(b = ngx_calloc_buf(r->pool))) {
-                return NGX_ERROR;
-            }
-
-            b->temporary = 1;
-            b->pos = range[i].content_range.data;
-            b->last = range[i].content_range.data + range[i].content_range.len;
-
-            if (!(rcl = ngx_alloc_chain_link(r->pool))) {
-                return NGX_ERROR;
-            }
-
-            rcl->buf = b;
-
-
-            /* the range data */
-
-            if (!(b = ngx_calloc_buf(r->pool))) {
-                return NGX_ERROR;
-            }
-
-            b->in_file = 1;
-            b->file_pos = range[i].start;
-            b->file_last = range[i].end;
-            b->file = in->buf->file;
-
-            if (!(dcl = ngx_alloc_chain_link(r->pool))) {
-                return NGX_ERROR;
-            }
-
-            dcl->buf = b;
-
-            *ll = hcl;
-            hcl->next = rcl;
-            rcl->next = dcl;
-            ll = &dcl->next;
-        }
-
-        /* the last boundary CRLF "--0123456789--" CRLF  */
-
-        if (!(b = ngx_calloc_buf(r->pool))) {
-            return NGX_ERROR;
-        }
-
-        b->temporary = 1;
-        b->last_buf = 1;
-
-        b->pos = ngx_palloc(r->pool, sizeof(CRLF "--") - 1 + NGX_ATOMIC_T_LEN
-                                     + sizeof("--" CRLF) - 1);
-        if (b->pos == NULL) {
-            return NGX_ERROR;
-        }
-
-        b->last = ngx_cpymem(b->pos, ctx->boundary_header.data, 4 + 10);
-        *b->last++ = '-'; *b->last++ = '-';
-        *b->last++ = CR; *b->last++ = LF;
-
-        if (!(hcl = ngx_alloc_chain_link(r->pool))) {
-            return NGX_ERROR;
-        }
-
-        hcl->buf = b;
-        hcl->next = NULL;
-
-        *ll = hcl;
-
-        return ngx_http_next_body_filter(r, out);
-    }
-
-    /* TODO: alert */
-
-    return ngx_http_next_body_filter(r, in);
-}
-
-
-static ngx_int_t
-ngx_http_range_header_filter_init(ngx_cycle_t *cycle)
-{
-    ngx_http_next_header_filter = ngx_http_top_header_filter;
-    ngx_http_top_header_filter = ngx_http_range_header_filter;
-
-    return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_range_body_filter_init(ngx_cycle_t *cycle)
-{
-    ngx_http_next_body_filter = ngx_http_top_body_filter;
-    ngx_http_top_body_filter = ngx_http_range_body_filter;
-
-    return NGX_OK;
-}
new file mode 100644
--- /dev/null
+++ b/src/http/modules/ngx_http_range_filter_module.c
@@ -0,0 +1,594 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+
+
+/*
+ * the single part format:
+ *
+ * "HTTP/1.0 206 Partial Content" CRLF
+ * ... header ...
+ * "Content-Type: image/jpeg" CRLF
+ * "Content-Length: SIZE" CRLF
+ * "Content-Range: bytes START-END/SIZE" CRLF
+ * CRLF
+ * ... data ...
+ *
+ *
+ * the mutlipart format:
+ *
+ * "HTTP/1.0 206 Partial Content" CRLF
+ * ... header ...
+ * "Content-Type: multipart/byteranges; boundary=0123456789" CRLF
+ * CRLF
+ * CRLF
+ * "--0123456789" CRLF
+ * "Content-Type: image/jpeg" CRLF
+ * "Content-Range: bytes START0-END0/SIZE" CRLF
+ * CRLF
+ * ... data ...
+ * CRLF
+ * "--0123456789" CRLF
+ * "Content-Type: image/jpeg" CRLF
+ * "Content-Range: bytes START1-END1/SIZE" CRLF
+ * CRLF
+ * ... data ...
+ * CRLF
+ * "--0123456789--" CRLF
+ */
+
+
+typedef struct {
+    ngx_str_t  boundary_header;
+} ngx_http_range_filter_ctx_t;
+
+
+static ngx_int_t ngx_http_range_header_filter_init(ngx_cycle_t *cycle);
+static ngx_int_t ngx_http_range_body_filter_init(ngx_cycle_t *cycle);
+
+
+static ngx_http_module_t  ngx_http_range_header_filter_module_ctx = {
+    NULL,                                  /* pre conf */
+
+    NULL,                                  /* create main configuration */
+    NULL,                                  /* init main configuration */
+
+    NULL,                                  /* create server configuration */
+    NULL,                                  /* merge server configuration */
+
+    NULL,                                  /* create location configuration */
+    NULL,                                  /* merge location configuration */
+};
+
+
+ngx_module_t  ngx_http_range_header_filter_module = {
+    NGX_MODULE,
+    &ngx_http_range_header_filter_module_ctx, /* module context */
+    NULL,                                  /* module directives */
+    NGX_HTTP_MODULE,                       /* module type */
+    ngx_http_range_header_filter_init,     /* init module */
+    NULL                                   /* init process */
+};
+
+
+static ngx_http_module_t  ngx_http_range_body_filter_module_ctx = {
+    NULL,                                  /* pre conf */
+
+    NULL,                                  /* create main configuration */
+    NULL,                                  /* init main configuration */
+
+    NULL,                                  /* create server configuration */
+    NULL,                                  /* merge server configuration */
+
+    NULL,                                  /* create location configuration */
+    NULL,                                  /* merge location configuration */
+};
+
+
+ngx_module_t  ngx_http_range_body_filter_module = {
+    NGX_MODULE,
+    &ngx_http_range_body_filter_module_ctx, /* module context */
+    NULL,                                  /* module directives */
+    NGX_HTTP_MODULE,                       /* module type */
+    ngx_http_range_body_filter_init,       /* init module */
+    NULL                                   /* init process */
+};
+
+
+static ngx_http_output_header_filter_pt  ngx_http_next_header_filter;
+static ngx_http_output_body_filter_pt    ngx_http_next_body_filter;
+
+
+static ngx_int_t
+ngx_http_range_header_filter(ngx_http_request_t *r)
+{
+    u_char                       *p;
+    size_t                        len;
+    off_t                         start, end;
+    ngx_int_t                     rc;
+    ngx_uint_t                    suffix, i;
+    ngx_atomic_uint_t             boundary;
+    ngx_table_elt_t              *content_range;
+    ngx_http_range_t             *range;
+    ngx_http_range_filter_ctx_t  *ctx;
+
+    if (r->http_version < NGX_HTTP_VERSION_10
+        || r->headers_out.status != NGX_HTTP_OK
+        || r->headers_out.content_length_n == -1
+        || !r->filter_allow_ranges)
+    {
+        return ngx_http_next_header_filter(r);
+    }
+
+    if (r->headers_in.range == NULL
+        || r->headers_in.range->value.len < 7
+        || ngx_strncasecmp(r->headers_in.range->value.data, "bytes=", 6) != 0)
+    {
+
+        r->headers_out.accept_ranges = ngx_list_push(&r->headers_out.headers);
+        if (r->headers_out.accept_ranges == NULL) {
+            return NGX_ERROR;
+        }
+
+        r->headers_out.accept_ranges->key.len = sizeof("Accept-Ranges") - 1;
+        r->headers_out.accept_ranges->key.data = (u_char *) "Accept-Ranges";
+        r->headers_out.accept_ranges->value.len = sizeof("bytes") - 1;
+        r->headers_out.accept_ranges->value.data = (u_char *) "bytes";
+
+        return ngx_http_next_header_filter(r);
+    }
+
+    if (ngx_array_init(&r->headers_out.ranges, r->pool, 2,
+                                        sizeof(ngx_http_range_t)) == NGX_ERROR)
+    {
+        return NGX_ERROR;
+    }
+
+    rc = 0;
+    range = NULL;
+    p = r->headers_in.range->value.data + 6;
+
+    for ( ;; ) {
+        start = 0;
+        end = 0;
+        suffix = 0;
+
+        while (*p == ' ') { p++; }
+
+        if (*p != '-') {
+            if (*p < '0' || *p > '9') {
+                rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;
+                break;
+            }
+
+            while (*p >= '0' && *p <= '9') {
+                start = start * 10 + *p++ - '0';
+            }
+
+            while (*p == ' ') { p++; }
+
+            if (*p++ != '-') {
+                rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;
+                break;
+            }
+
+            if (start >= r->headers_out.content_length_n) {
+                rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;
+                break;
+            }
+
+            while (*p == ' ') { p++; }
+
+            if (*p == ',' || *p == '\0') {
+                range = ngx_array_push(&r->headers_out.ranges);
+                if (range == NULL) {
+                    return NGX_ERROR;
+                }
+
+                range->start = start;
+                range->end = r->headers_out.content_length_n;
+
+                if (*p++ != ',') {
+                    break;
+                }
+
+                continue;
+            }
+
+        } else {
+            suffix = 1;
+            p++;
+        }
+
+        if (*p < '0' || *p > '9') {
+            rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;
+            break;
+        }
+
+        while (*p >= '0' && *p <= '9') {
+            end = end * 10 + *p++ - '0';
+        }
+
+        while (*p == ' ') { p++; }
+
+        if (*p != ',' && *p != '\0') {
+            rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;
+            break;
+        }
+
+        if (suffix) {
+           start = r->headers_out.content_length_n - end;
+           end = r->headers_out.content_length_n - 1;
+        }
+
+        if (start > end) {
+            rc = NGX_HTTP_RANGE_NOT_SATISFIABLE;
+            break;
+        }
+
+        range = ngx_array_push(&r->headers_out.ranges);
+        if (range == NULL) {
+            return NGX_ERROR;
+        }
+
+        range->start = start;
+
+        if (end >= r->headers_out.content_length_n) {
+            /*
+             * Download Accelerator sends the last byte position
+             * that equals to the file length
+             */
+            range->end = r->headers_out.content_length_n;
+
+        } else {
+            range->end = end + 1;
+        }
+
+        if (*p++ != ',') {
+            break;
+        }
+    }
+
+    if (rc) {
+
+        /* rc == NGX_HTTP_RANGE_NOT_SATISFIABLE */
+
+        r->headers_out.status = rc;
+        r->headers_out.ranges.nelts = 0;
+
+        content_range = ngx_list_push(&r->headers_out.headers);
+        if (content_range == NULL) {
+            return NGX_ERROR;
+        }
+
+        r->headers_out.content_range = content_range;
+
+        content_range->key.len = sizeof("Content-Range") - 1;
+        content_range->key.data = (u_char *) "Content-Range";
+
+        content_range->value.data = ngx_palloc(r->pool,
+                                       sizeof("bytes */") - 1 + NGX_OFF_T_LEN);
+        if (content_range->value.data == NULL) {
+            return NGX_ERROR;
+        }
+
+        content_range->value.len = ngx_sprintf(content_range->value.data,
+                                               "bytes */%O",
+                                               r->headers_out.content_length_n)
+                                   - content_range->value.data;
+
+        r->headers_out.content_length_n = -1;
+        if (r->headers_out.content_length) {
+            r->headers_out.content_length->key.len = 0;
+            r->headers_out.content_length = NULL;
+        }
+
+        return rc;
+    }
+
+    r->headers_out.status = NGX_HTTP_PARTIAL_CONTENT;
+
+    if (r->headers_out.ranges.nelts == 1) {
+
+        content_range = ngx_list_push(&r->headers_out.headers);
+        if (content_range == NULL) {
+            return NGX_ERROR;
+        }
+
+        r->headers_out.content_range = content_range;
+
+        content_range->key.len = sizeof("Content-Range") - 1;
+        content_range->key.data = (u_char *) "Content-Range";
+
+        content_range->value.data =
+               ngx_palloc(r->pool, sizeof("bytes -/") - 1 + 3 * NGX_OFF_T_LEN);
+        if (content_range->value.data == NULL) {
+            return NGX_ERROR;
+        }
+
+        /* "Content-Range: bytes SSSS-EEEE/TTTT" header */
+
+        content_range->value.len = ngx_sprintf(content_range->value.data,
+                                               "bytes %O-%O/%O",
+                                               range->start, range->end - 1,
+                                               r->headers_out.content_length_n)
+                                   - content_range->value.data;
+
+        r->headers_out.content_length_n = range->end - range->start;
+
+        return ngx_http_next_header_filter(r);
+    }
+
+
+    /* TODO: what if no content_type ?? */
+
+    ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_range_filter_ctx_t));
+    if (ctx == NULL) {
+        return NGX_ERROR;
+    }
+    
+    ngx_http_set_ctx(r, ctx, ngx_http_range_body_filter_module);
+
+
+    len = sizeof(CRLF "--") - 1 + NGX_ATOMIC_T_LEN
+          + sizeof(CRLF "Content-Type: ") - 1
+          + r->headers_out.content_type->value.len
+          + sizeof(CRLF "Content-Range: bytes ") - 1;
+
+    if (r->headers_out.charset.len) {
+        len += sizeof("; charset=") - 1 + r->headers_out.charset.len;
+    }
+
+    ctx->boundary_header.data = ngx_palloc(r->pool, len);
+    if (ctx->boundary_header.data == NULL) {
+        return NGX_ERROR;
+    }
+
+    boundary = ngx_next_temp_number(0);
+
+    /*
+     * The boundary header of the range:
+     * CRLF
+     * "--0123456789" CRLF
+     * "Content-Type: image/jpeg" CRLF
+     * "Content-Range: bytes "
+     */
+
+    if (r->headers_out.charset.len) {
+        ctx->boundary_header.len = ngx_sprintf(ctx->boundary_header.data,
+                                           CRLF "--%0muA" CRLF
+                                           "Content-Type: %V; charset=%V" CRLF
+                                           "Content-Range: bytes ",
+                                           boundary,
+                                           &r->headers_out.content_type->value,
+                                           &r->headers_out.charset)
+                                   - ctx->boundary_header.data;
+
+        r->headers_out.charset.len = 0;
+
+    } else {
+        ctx->boundary_header.len = ngx_sprintf(ctx->boundary_header.data,
+                                           CRLF "--%0muA" CRLF
+                                           "Content-Type: %V" CRLF
+                                           "Content-Range: bytes ",
+                                           boundary,
+                                           &r->headers_out.content_type->value)
+                                   - ctx->boundary_header.data;
+    }
+
+    r->headers_out.content_type->value.data =
+         ngx_palloc(r->pool,
+                    sizeof("Content-Type: multipart/byteranges; boundary=") - 1
+                    + NGX_ATOMIC_T_LEN);
+
+    if (r->headers_out.content_type->value.data == NULL) {
+        return NGX_ERROR;
+    }
+
+    /* "Content-Type: multipart/byteranges; boundary=0123456789" */
+
+    r->headers_out.content_type->value.len =
+                           ngx_sprintf(r->headers_out.content_type->value.data,
+                                       "multipart/byteranges; boundary=%0muA",
+                                       boundary)
+                           - r->headers_out.content_type->value.data;
+
+
+    /* the size of the last boundary CRLF "--0123456789--" CRLF */
+
+    len = sizeof(CRLF "--") - 1 + NGX_ATOMIC_T_LEN + sizeof("--" CRLF) - 1;
+
+    range = r->headers_out.ranges.elts;
+    for (i = 0; i < r->headers_out.ranges.nelts; i++) {
+
+        /* the size of the range: "SSSS-EEEE/TTTT" CRLF CRLF */
+
+        range[i].content_range.data =
+                                ngx_palloc(r->pool, 3 * NGX_OFF_T_LEN + 2 + 4);
+
+        if (range[i].content_range.data == NULL) {
+            return NGX_ERROR;
+        }
+
+        range[i].content_range.len = ngx_sprintf(range[i].content_range.data,
+                                               "%O-%O/%O" CRLF CRLF,
+                                               range[i].start, range[i].end - 1,
+                                               r->headers_out.content_length_n)
+                                     - range[i].content_range.data;
+
+        len += ctx->boundary_header.len + range[i].content_range.len
+                                    + (size_t) (range[i].end - range[i].start);
+    }
+
+    r->headers_out.content_length_n = len;
+    r->headers_out.content_length = NULL;
+
+    return ngx_http_next_header_filter(r);
+}
+
+
+static ngx_int_t
+ngx_http_range_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
+{
+    ngx_uint_t                    i;
+    ngx_buf_t                    *b;
+    ngx_chain_t                  *out, *hcl, *rcl, *dcl, **ll;
+    ngx_http_range_t             *range;
+    ngx_http_range_filter_ctx_t  *ctx;
+
+    if (r->headers_out.ranges.nelts == 0) {
+        return ngx_http_next_body_filter(r, in);
+    }
+
+    /*
+     * the optimized version for the static files only
+     * that are passed in the single file buf
+     */
+
+    if (in && in->buf->in_file && in->buf->last_buf) {
+        range = r->headers_out.ranges.elts;
+
+        if (r->headers_out.ranges.nelts == 1) {
+            in->buf->file_pos = range->start;
+            in->buf->file_last = range->end;
+
+            return ngx_http_next_body_filter(r, in);
+        }
+
+        ctx = ngx_http_get_module_ctx(r, ngx_http_range_body_filter_module);
+        ll = &out;
+
+        for (i = 0; i < r->headers_out.ranges.nelts; i++) {
+
+            /*
+             * The boundary header of the range:
+             * CRLF
+             * "--0123456789" CRLF
+             * "Content-Type: image/jpeg" CRLF
+             * "Content-Range: bytes "
+             */
+
+            b = ngx_calloc_buf(r->pool);
+            if (b == NULL) {
+                return NGX_ERROR;
+            }
+
+            b->memory = 1;
+            b->pos = ctx->boundary_header.data;
+            b->last = ctx->boundary_header.data + ctx->boundary_header.len;
+
+            hcl = ngx_alloc_chain_link(r->pool);
+            if (hcl == NULL) {
+                return NGX_ERROR;
+            }
+
+            hcl->buf = b;
+
+
+            /* "SSSS-EEEE/TTTT" CRLF CRLF */
+
+            b = ngx_calloc_buf(r->pool);
+            if (b == NULL) {
+                return NGX_ERROR;
+            }
+
+            b->temporary = 1;
+            b->pos = range[i].content_range.data;
+            b->last = range[i].content_range.data + range[i].content_range.len;
+
+            rcl = ngx_alloc_chain_link(r->pool);
+            if (rcl == NULL) {
+                return NGX_ERROR;
+            }
+
+            rcl->buf = b;
+
+
+            /* the range data */
+
+            b = ngx_calloc_buf(r->pool);
+            if (b == NULL) {
+                return NGX_ERROR;
+            }
+
+            b->in_file = 1;
+            b->file_pos = range[i].start;
+            b->file_last = range[i].end;
+            b->file = in->buf->file;
+
+            dcl = ngx_alloc_chain_link(r->pool);
+            if (dcl == NULL) {
+                return NGX_ERROR;
+            }
+
+            dcl->buf = b;
+
+            *ll = hcl;
+            hcl->next = rcl;
+            rcl->next = dcl;
+            ll = &dcl->next;
+        }
+
+        /* the last boundary CRLF "--0123456789--" CRLF  */
+
+        b = ngx_calloc_buf(r->pool);
+        if (b == NULL) {
+            return NGX_ERROR;
+        }
+
+        b->temporary = 1;
+        b->last_buf = 1;
+
+        b->pos = ngx_palloc(r->pool, sizeof(CRLF "--") - 1 + NGX_ATOMIC_T_LEN
+                                     + sizeof("--" CRLF) - 1);
+        if (b->pos == NULL) {
+            return NGX_ERROR;
+        }
+
+        b->last = ngx_cpymem(b->pos, ctx->boundary_header.data, 4 + 10);
+        *b->last++ = '-'; *b->last++ = '-';
+        *b->last++ = CR; *b->last++ = LF;
+
+        hcl = ngx_alloc_chain_link(r->pool);
+        if (hcl == NULL) {
+            return NGX_ERROR;
+        }
+
+        hcl->buf = b;
+        hcl->next = NULL;
+
+        *ll = hcl;
+
+        return ngx_http_next_body_filter(r, out);
+    }
+
+    /* TODO: alert */
+
+    return ngx_http_next_body_filter(r, in);
+}
+
+
+static ngx_int_t
+ngx_http_range_header_filter_init(ngx_cycle_t *cycle)
+{
+    ngx_http_next_header_filter = ngx_http_top_header_filter;
+    ngx_http_top_header_filter = ngx_http_range_header_filter;
+
+    return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_range_body_filter_init(ngx_cycle_t *cycle)
+{
+    ngx_http_next_body_filter = ngx_http_top_body_filter;
+    ngx_http_top_body_filter = ngx_http_range_body_filter;
+
+    return NGX_OK;
+}
deleted file mode 100644
--- a/src/http/modules/ngx_http_rewrite_handler.c
+++ /dev/null
@@ -1,1313 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-typedef struct ngx_http_rewrite_engine_s  ngx_http_rewrite_engine_t;
-
-typedef void (*ngx_http_rewrite_code_pt) (ngx_http_rewrite_engine_t *e);
-
-
-typedef struct {
-    ngx_str_t                     name;
-    ngx_uint_t                    wildcard;
-} ngx_http_rewrite_referer_t;
-
-
-typedef struct {
-    ngx_array_t                  *codes;        /* uintptr_t */
-    ngx_array_t                  *referers;     /* ngx_http_rewrite_referer_t */
-
-    ngx_uint_t                    max_captures;
-    ngx_uint_t                    stack_size;
-
-    ngx_flag_t                    log;
-
-    ngx_flag_t                    no_referer;
-} ngx_http_rewrite_loc_conf_t;
-
-
-typedef struct {
-    ngx_http_rewrite_code_pt      code;
-    ngx_regex_t                  *regex;
-    uintptr_t                     size;
-    uintptr_t                     ncaptures;
-    uintptr_t                     status;
-    uintptr_t                     next;
-
-    uintptr_t                     uri:1;
-
-    /* add the r->args to the new arguments */
-    uintptr_t                     args:1;
-
-    uintptr_t                     redirect:1;
-    uintptr_t                     break_cycle:1;
-
-    ngx_str_t                     name;
-} ngx_http_rewrite_regex_code_t;
-
-
-typedef struct {
-    ngx_http_rewrite_code_pt      code;
-
-    uintptr_t                     uri:1;
-
-    /* add the r->args to the new arguments */
-    uintptr_t                     args:1;
-
-    uintptr_t                     redirect:1;
-} ngx_http_rewrite_regex_end_code_t;
-
-typedef struct {
-    ngx_http_rewrite_code_pt      code;
-    uintptr_t                     n;
-} ngx_http_rewrite_copy_capture_code_t;
-
-
-typedef struct {
-    ngx_http_rewrite_code_pt      code;
-    uintptr_t                     len;
-} ngx_http_rewrite_copy_code_t;
-
-
-typedef struct {
-    ngx_http_rewrite_code_pt      code;
-    uintptr_t                     status;
-    uintptr_t                     null;
-} ngx_http_rewrite_return_code_t;
-
-
-typedef struct {
-    ngx_http_rewrite_code_pt      code;
-    uintptr_t                     next;
-    void                        **loc_conf;
-} ngx_http_rewrite_if_code_t;
-
-
-typedef struct {
-    ngx_http_rewrite_code_pt      code;
-    uintptr_t                     index;
-} ngx_http_rewrite_var_code_t;
-
-
-struct ngx_http_rewrite_engine_s {
-    u_char                       *ip;
-    uintptr_t                    *sp;
-
-    ngx_str_t                     buf;
-    ngx_str_t                    *line;
-
-    u_char                       *pos;
-
-    /* the start of the rewritten arguments */
-    u_char                       *args;
-
-    unsigned                      quote:1;
-
-    ngx_int_t                     status;
-
-    int                          *captures;
-
-    ngx_http_request_t           *request;
-    ngx_http_rewrite_loc_conf_t  *conf;
-};
-
-
-static ngx_int_t ngx_http_rewrite_init(ngx_cycle_t *cycle);
-static void *ngx_http_rewrite_create_loc_conf(ngx_conf_t *cf);
-static char *ngx_http_rewrite_merge_loc_conf(ngx_conf_t *cf,
-    void *parent, void *child);
-static char *ngx_http_rewrite(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
-static char *ngx_http_rewrite_return(ngx_conf_t *cf, ngx_command_t *cmd,
-    void *conf);
-static char *ngx_http_rewrite_if(ngx_conf_t *cf, ngx_command_t *cmd,
-    void *conf);
-static char *ngx_http_rewrite_valid_referers(ngx_conf_t *cf,
-    ngx_command_t *cmd, void *conf);
-static void *ngx_http_rewrite_start_code(ngx_pool_t *pool,
-    ngx_array_t **codes, size_t size);
-static void *ngx_http_rewrite_add_code(ngx_array_t *codes, size_t size,
-    void *code);
-
-
-static ngx_command_t  ngx_http_rewrite_commands[] = {
-
-    { ngx_string("rewrite"),
-      NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
-                       |NGX_CONF_TAKE23,
-      ngx_http_rewrite,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      0,
-      NULL },
-
-    { ngx_string("return"),
-      NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
-                       |NGX_CONF_TAKE1,
-      ngx_http_rewrite_return,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      0,
-      NULL },
-
-    { ngx_string("if"),
-      NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_BLOCK|NGX_CONF_1MORE,
-      ngx_http_rewrite_if,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      0,
-      NULL },
-
-    { ngx_string("valid_referers"),
-      NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
-      ngx_http_rewrite_valid_referers,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      0,
-      NULL },
-
-    { ngx_string("rewrite_log"),
-      NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
-                       |NGX_CONF_TAKE1,
-      ngx_conf_set_flag_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_rewrite_loc_conf_t, log),
-      NULL },
-
-      ngx_null_command
-};
-
-
-ngx_http_module_t  ngx_http_rewrite_module_ctx = {
-    NULL,                                  /* pre conf */
-
-    NULL,                                  /* create main configuration */
-    NULL,                                  /* init main configuration */
-
-    NULL,                                  /* create server configuration */
-    NULL,                                  /* merge server configuration */
-
-    ngx_http_rewrite_create_loc_conf,      /* create location configration */
-    ngx_http_rewrite_merge_loc_conf        /* merge location configration */
-};
-
-
-ngx_module_t  ngx_http_rewrite_module = {
-    NGX_MODULE,
-    &ngx_http_rewrite_module_ctx,          /* module context */ 
-    ngx_http_rewrite_commands,             /* module directives */
-    NGX_HTTP_MODULE,                       /* module type */
-    ngx_http_rewrite_init,                 /* init module */
-    NULL                                   /* init process */
-};
-
-
-#define ngx_http_rewrite_exit  (u_char *) &ngx_http_rewrite_exit_code
-
-uintptr_t ngx_http_rewrite_exit_code = (uintptr_t) NULL;
-
-
-static ngx_int_t
-ngx_http_rewrite_handler(ngx_http_request_t *r)
-{
-    ngx_http_rewrite_code_pt      code;
-    ngx_http_rewrite_engine_t    *e;
-    ngx_http_rewrite_loc_conf_t  *cf;
-
-    cf = ngx_http_get_module_loc_conf(r, ngx_http_rewrite_module);
-
-    if (cf->codes == NULL) {
-        return NGX_DECLINED;
-    }
-
-    if (!(e = ngx_palloc(r->pool, sizeof(ngx_http_rewrite_engine_t)))) {
-        return NGX_HTTP_INTERNAL_SERVER_ERROR;
-    }
-
-    e->sp = ngx_palloc(r->pool, cf->stack_size * sizeof(ngx_int_t));
-    if (e->sp == NULL) {
-        return NGX_HTTP_INTERNAL_SERVER_ERROR;
-    }
-
-    if (cf->max_captures) {
-        e->captures = ngx_palloc(r->pool, cf->max_captures * sizeof(int));
-        if (e->captures == NULL) {
-            return NGX_HTTP_INTERNAL_SERVER_ERROR;
-        }
-
-    } else {
-        e->captures = NULL;
-    }
-
-    e->ip = cf->codes->elts;
-    e->buf.len = 0;
-    e->buf.data = NULL;
-    e->line = NULL;
-    e->pos = NULL;
-    e->args = NULL;
-    e->quote = 1;
-    e->status = NGX_DECLINED;
-    e->request = r;
-    e->conf = cf;
-
-    while (*(uintptr_t *) e->ip) {
-        code = *(ngx_http_rewrite_code_pt *) e->ip;
-        code(e);
-    }
-
-    return e->status;
-}
-
-
-static void
-ngx_http_rewrite_regex_start_code(ngx_http_rewrite_engine_t *e)
-{
-    ngx_int_t                       rc;
-    ngx_uint_t                      n;
-    ngx_http_request_t             *r;
-    ngx_http_rewrite_regex_code_t  *code;
-
-    code = (ngx_http_rewrite_regex_code_t *) e->ip;
-
-    r = e->request;
-
-    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                   "http rewrite start: \"%V\"", &code->name);
-
-    if (code->uri) {
-        e->line = &r->uri;
-    } else {
-        e->line = *(ngx_str_t **) e->sp--;
-    }
-
-    rc = ngx_regex_exec(code->regex, e->line, e->captures, code->ncaptures);
-
-    if (rc == NGX_REGEX_NO_MATCHED) {
-        if (e->conf->log) {
-            ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
-                          "\"%V\" does not match \"%V\"", &code->name, e->line);
-        }
-
-        e->ip += code->next;
-        return;
-    }
-
-    if (rc < 0) {
-        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
-                      ngx_regex_exec_n " failed: %d on \"%V\" using \"%V\"",
-                      rc, e->line, &code->name);
-
-        e->ip = ngx_http_rewrite_exit;
-        e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
-        return;
-    }
-
-    if (e->conf->log) {
-        ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
-                      "\"%V\" matches \"%V\"", &code->name, e->line);
-    }
-
-    if (code->status) {
-        e->status = code->status;
-
-        if (!code->redirect) {
-            e->ip = ngx_http_rewrite_exit;
-            return;
-        }
-    }
-
-    e->buf.len = code->size;
-
-    if (code->uri) {
-        if (!code->break_cycle) {
-            r->uri_changed = 1;
-        }
-
-        if (rc && (r->quoted_uri || r->plus_in_uri)) {
-            e->buf.len += 2 * ngx_escape_uri(NULL, r->uri.data, r->uri.len,
-                                             NGX_ESCAPE_ARGS);
-        }
-    }
-
-    for (n = 1; n < (ngx_uint_t) rc; n++) {
-        e->buf.len += e->captures[2 * n + 1] - e->captures[2 * n];
-    }
-
-    if (code->args && r->args.len) {
-        e->buf.len += r->args.len + 1;
-    }
-
-    if (!(e->buf.data = ngx_palloc(r->pool, e->buf.len))) {
-        e->ip = ngx_http_rewrite_exit;
-        e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
-        return;
-    }
-
-    e->quote = code->redirect;
-
-    e->pos = e->buf.data;
-
-    e->ip += sizeof(ngx_http_rewrite_regex_code_t);
-}
-
-
-static void
-ngx_http_rewrite_regex_end_code(ngx_http_rewrite_engine_t *e)
-{
-    ngx_http_request_t                 *r;
-    ngx_http_rewrite_regex_end_code_t  *code;
-
-    code = (ngx_http_rewrite_regex_end_code_t *) e->ip;
-
-    r = e->request;
-
-    e->quote = 0;
-
-    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                   "http rewrite end");
-
-    if (e->args) {
-        e->buf.len = e->args - e->buf.data;
-
-        if (code->args && r->args.len) {
-            *e->pos++ = '&';
-            e->pos = ngx_cpymem(e->pos, r->args.data, r->args.len);
-        }
-
-        r->args.len = e->pos - e->args;
-        r->args.data = e->args;
-
-        e->args = NULL;
-
-    } else {
-        if (code->args && r->args.len) {
-            *e->pos++ = '?';
-            e->pos = ngx_cpymem(e->pos, r->args.data, r->args.len);
-        }
-
-        e->buf.len = e->pos - e->buf.data;
-    }
-
-    if (!code->redirect) {
-        if (e->conf->log) {
-            ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
-                          "rewritten data: \"%V\", args: \"%V\"",
-                          &e->buf, &r->args);
-        }
-
-        if (code->uri) {
-            r->uri = e->buf;
-
-            if (ngx_http_set_exten(r) != NGX_OK) {
-                e->ip = ngx_http_rewrite_exit;
-                e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
-                return;
-            }
-        }
-
-        e->ip += sizeof(ngx_http_rewrite_regex_end_code_t);
-        return;
-    }
-
-    ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
-                  "rewritten redirect: \"%V\"", &e->buf);
-
-    if (!(r->headers_out.location = ngx_list_push(&r->headers_out.headers))) {
-        e->ip = ngx_http_rewrite_exit;
-        e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
-        return;
-    }
-
-    if (e->buf.data[0] != '/') {
-        r->headers_out.location->key.len = sizeof("Location") - 1;
-        r->headers_out.location->key.data = (u_char *) "Location";
-    }
-
-    r->headers_out.location->value = e->buf;
-
-    e->ip += sizeof(ngx_http_rewrite_regex_end_code_t);
-}
-
-
-static void
-ngx_http_rewrite_copy_capture_code(ngx_http_rewrite_engine_t *e)
-{
-    ngx_http_rewrite_copy_capture_code_t  *code;
-
-    code = (ngx_http_rewrite_copy_capture_code_t *) e->ip;
-
-    e->ip += sizeof(ngx_http_rewrite_copy_capture_code_t);
-
-    if ((e->args || e->quote)
-        && (e->request->quoted_uri || e->request->plus_in_uri))
-    {
-        e->pos = (u_char *) ngx_escape_uri(e->pos,
-                                &e->line->data[e->captures[code->n]],
-                                e->captures[code->n + 1] - e->captures[code->n],
-                                NGX_ESCAPE_ARGS);
-    } else {
-        e->pos = ngx_cpymem(e->pos, &e->line->data[e->captures[code->n]],
-                        e->captures[code->n + 1] - e->captures[code->n]);
-    }
-
-    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
-                   "http rewrite capture: \"%V\"", &e->buf);
-}
-
-
-static void
-ngx_http_rewrite_copy_code(ngx_http_rewrite_engine_t *e)
-{
-    ngx_http_rewrite_copy_code_t  *code;
-
-    code = (ngx_http_rewrite_copy_code_t *) e->ip;
-
-    e->pos = ngx_cpymem(e->pos, e->ip + sizeof(ngx_http_rewrite_copy_code_t),
-                        code->len);
-
-    e->ip += sizeof(ngx_http_rewrite_copy_code_t)
-             + ((code->len + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1));
-
-    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
-                   "http rewrite copy: \"%V\"", &e->buf);
-}
-
-
-static void
-ngx_http_rewrite_start_args_code(ngx_http_rewrite_engine_t *e)
-{
-    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
-                   "http rewrite args");
-
-    e->args = e->pos;
-    e->ip += sizeof(uintptr_t);
-}
-
-
-static void
-ngx_http_rewrite_return_code(ngx_http_rewrite_engine_t *e)
-{
-    ngx_http_rewrite_return_code_t  *code;
-
-    code = (ngx_http_rewrite_return_code_t *) e->ip;
-
-    e->status = code->status;
-
-    e->ip += sizeof(ngx_http_rewrite_return_code_t) - sizeof(uintptr_t);
-}
-
-
-static void
-ngx_http_rewrite_if_code(ngx_http_rewrite_engine_t *e)
-{
-    ngx_http_rewrite_if_code_t  *code;
-
-    code = (ngx_http_rewrite_if_code_t *) e->ip;
-
-    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
-                   "http rewrite if");
-
-    if (*e->sp--) {
-        if (code->loc_conf) {
-            e->request->loc_conf = code->loc_conf;
-        }
-
-        e->ip += sizeof(ngx_http_rewrite_if_code_t);
-        return;
-    }
-
-    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
-                   "http rewrite if false");
-
-    e->ip += code->next;
-}
-
-
-static void
-ngx_http_rewrite_var_code(ngx_http_rewrite_engine_t *e)
-{
-    ngx_http_variable_value_t    *value;
-    ngx_http_rewrite_var_code_t  *code;
-
-    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
-                   "http rewrite var");
-
-    code = (ngx_http_rewrite_var_code_t *) e->ip;
-
-    e->sp++;
-
-    e->ip += sizeof(ngx_http_rewrite_var_code_t);
-
-    if (!(value = ngx_http_get_indexed_variable(e->request, code->index))) {
-        *e->sp = (uintptr_t) 0;
-        return;
-    }
-
-    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
-                   "http rewrite var: %p", value->value);
-
-    *e->sp = value->value;
-}
-
-
-static void
-ngx_http_rewrite_invalid_referer_code(ngx_http_rewrite_engine_t *e)
-{
-    u_char                       *ref;
-    size_t                        len;
-    ngx_uint_t                    i, n;
-    ngx_http_request_t           *r;
-    ngx_http_rewrite_referer_t   *refs;
-    ngx_http_rewrite_loc_conf_t  *cf;
-
-    r = e->request;
-
-    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                   "http rewrite invalid referer");
-
-    cf = ngx_http_get_module_loc_conf(r, ngx_http_rewrite_module);
-
-    e->sp++;
-    e->ip += sizeof(uintptr_t);
-
-    if (cf->referers == NULL) {
-        *e->sp = (uintptr_t) 0;
-        return;
-    }
-
-    if (r->headers_in.referer == NULL) {
-        if (cf->no_referer) {
-            *e->sp = (uintptr_t) 0;
-            return;
-        } else {
-            *e->sp = (uintptr_t) 1;
-            return;
-        }
-    }
-
-    len = r->headers_in.referer->value.len;
-    ref = r->headers_in.referer->value.data;
-
-    if (len < sizeof("http://i.ru") - 1
-        || (ngx_strncasecmp(ref, "http://", 7) != 0))
-    {
-        *e->sp = (uintptr_t) 1;
-        return;
-    }
-
-    len -= 7;
-    ref += 7;
-
-    refs = cf->referers->elts;
-    for (i = 0; i < cf->referers->nelts; i++ ){
-
-        if (refs[i].name.len > len) {
-            continue;
-        }
-
-        if (refs[i].wildcard) {
-            for (n = 0; n < len; n++) {
-                if (ref[n] == '/' || ref[n] == ':') {
-                    break;
-                }
-
-                if (ref[n] != '.') {
-                    continue;
-                }
-
-                if (ngx_strncmp(&ref[n], refs[i].name.data,
-                                refs[i].name.len) == 0)
-                {
-                    *e->sp = (uintptr_t) 0;
-                    return;
-                }
-            }
-
-        } else {
-            if (ngx_strncasecmp(refs[i].name.data, ref, refs[i].name.len) == 0)
-            {
-                *e->sp = (uintptr_t) 0;
-                return;
-            }
-        }
-    }
-
-    *e->sp = (uintptr_t) 1;
-}
-
-
-static void
-ngx_http_rewrite_nop_code(ngx_http_rewrite_engine_t *e)
-{
-    e->ip += sizeof(uintptr_t);
-}
-
-
-static ngx_int_t
-ngx_http_rewrite_init(ngx_cycle_t *cycle)
-{   
-    ngx_http_handler_pt        *h;
-    ngx_http_core_main_conf_t  *cmcf;
-    
-    cmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_core_module);
-
-    h = ngx_push_array(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers);
-    if (h == NULL) {
-        return NGX_ERROR;
-    }
-    
-    *h = ngx_http_rewrite_handler;
-    
-    return NGX_OK;
-}   
-
-
-static void *
-ngx_http_rewrite_create_loc_conf(ngx_conf_t *cf)
-{
-    ngx_http_rewrite_loc_conf_t  *conf;
-
-    if (!(conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_rewrite_loc_conf_t)))) {
-        return NGX_CONF_ERROR;
-    }
-
-    conf->stack_size = NGX_CONF_UNSET_UINT;
-    conf->log = NGX_CONF_UNSET;
-    conf->no_referer = NGX_CONF_UNSET;
-
-    return conf;
-}
-
-
-static char *
-ngx_http_rewrite_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
-{
-    ngx_http_rewrite_loc_conf_t *prev = parent;
-    ngx_http_rewrite_loc_conf_t *conf = child;
-
-    uintptr_t                      *code, *last;
-    ngx_http_rewrite_regex_code_t  *regex;
-
-    ngx_conf_merge_value(conf->log, prev->log, 0);
-    ngx_conf_merge_unsigned_value(conf->stack_size, prev->stack_size, 10);
-
-    if (conf->referers == NULL) {
-        conf->referers = prev->referers;
-        ngx_conf_merge_value(conf->no_referer, prev->no_referer, 0);
-    }
-
-    if (conf->no_referer == NGX_CONF_UNSET) {
-        conf->no_referer = 0;
-    }
-
-    if (conf->codes == NULL) {
-        return NGX_CONF_OK;
-    }
-
-    if (conf->codes == prev->codes) {
-        return NGX_CONF_OK;
-    }
-
-    code = conf->codes->elts;
-    last = (uintptr_t *) ((u_char *) code + conf->codes->nelts);
-
-    while (code < last) {
-        if (*code == (uintptr_t) NULL) {
-            return NGX_CONF_OK;
-        }
-
-        if (*code == (uintptr_t) &ngx_http_rewrite_regex_start_code) {
-            regex = (ngx_http_rewrite_regex_code_t *) code;
-            if (conf->max_captures < regex->ncaptures) {
-                conf->max_captures = regex->ncaptures;
-            }
-            code = (uintptr_t *) ((u_char *) code + regex->next);
-        }
-
-        if (*code == (uintptr_t) &ngx_http_rewrite_if_code) {
-            code += sizeof(ngx_http_rewrite_if_code_t) / sizeof(uintptr_t);
-        }
-
-        if (*code == (uintptr_t) &ngx_http_rewrite_return_code) {
-            code += sizeof(ngx_http_rewrite_return_code_t) / sizeof(uintptr_t);
-        }
-
-        if (*code == (uintptr_t) &ngx_http_rewrite_var_code) {
-            code += sizeof(ngx_http_rewrite_var_code_t) / sizeof(uintptr_t);
-        }
-
-        if (*code == (uintptr_t) &ngx_http_rewrite_invalid_referer_code) {
-            code++;
-        }
-
-        if (*code == (uintptr_t) &ngx_http_rewrite_nop_code) {
-            code++;
-        }
-    }
-
-    if (!(code = ngx_array_push_n(conf->codes, sizeof(uintptr_t)))) {
-        return NGX_CONF_ERROR;
-    }
-
-    *code = (uintptr_t) NULL;
-
-    return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_rewrite(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
-    ngx_http_rewrite_loc_conf_t *lcf = conf;
-    
-    u_char                                *data;
-    size_t                                 len, size;
-    ngx_str_t                             *value, err;
-    ngx_uint_t                             i, n, last;
-    ngx_http_rewrite_code_pt              *code;
-    ngx_http_rewrite_copy_code_t          *copy;
-    ngx_http_rewrite_regex_code_t         *regex;
-    ngx_http_rewrite_regex_end_code_t     *regex_end;
-    ngx_http_rewrite_copy_capture_code_t  *copy_capture;
-    u_char                                 errstr[NGX_MAX_CONF_ERRSTR];
-
-    regex = ngx_http_rewrite_start_code(cf->pool, &lcf->codes,
-                                        sizeof(ngx_http_rewrite_regex_code_t));
-    if (regex == NULL) {
-        return NGX_CONF_ERROR;
-    }
-
-    value = cf->args->elts;
-
-    err.len = NGX_MAX_CONF_ERRSTR;
-    err.data = errstr;
-
-    /* TODO: NGX_REGEX_CASELESS */
-
-    regex->regex = ngx_regex_compile(&value[1], 0, cf->pool, &err);
-
-    if (regex->regex == NULL) {
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
-        return NGX_CONF_ERROR;
-    }
-
-    regex->code = ngx_http_rewrite_regex_start_code;
-    regex->size = 0;
-    regex->ncaptures = 0;
-    regex->status = 0;
-    regex->uri = 1;
-    regex->args = 1;
-    regex->redirect = 0;
-    regex->name = value[1];
-
-    last = 0;
-
-    if (ngx_strncmp(value[2].data, "http://", sizeof("http://") - 1) == 0) {
-        regex->status = NGX_HTTP_MOVED_TEMPORARILY;
-        regex->redirect = 1;
-        last = 1;
-    }
-
-    if (cf->args->nelts == 4) {
-        if (ngx_strcmp(value[3].data, "last") == 0) {
-            last = 1;
-
-        } else if (ngx_strcmp(value[3].data, "break") == 0) {
-            regex->break_cycle = 1;
-            last = 1;
-
-        } else if (ngx_strcmp(value[3].data, "redirect") == 0) {
-            regex->status = NGX_HTTP_MOVED_TEMPORARILY;
-            regex->redirect = 1;
-            last = 1;
-
-        } else if (ngx_strcmp(value[3].data, "permanent") == 0) {
-            regex->status = NGX_HTTP_MOVED_PERMANENTLY;
-            regex->redirect = 1;
-            last = 1;
-
-        } else {
-            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                               "invalid parameter \"%V\"", &value[3]);
-            return NGX_CONF_ERROR;
-        }
-    }
-
-    i = 0;
-
-    while (i < value[2].len) {
-
-        data = &value[2].data[i];
-
-        if (value[2].data[i] == '$' && i < value[2].len
-            && value[2].data[i + 1] >= '1' && value[2].data[i + 1] <= '9')
-        {
-
-            /* the "$1" - "$9" captures */
-
-            copy_capture = ngx_http_rewrite_add_code(lcf->codes,
-                                  sizeof(ngx_http_rewrite_copy_capture_code_t),
-                                  &regex);
-            if (copy_capture == NULL) {
-                return NGX_CONF_ERROR;
-            }
-
-            i++;
-
-            copy_capture->code = ngx_http_rewrite_copy_capture_code;
-            copy_capture->n = value[2].data[i] - '0';
-
-            if (regex->ncaptures < copy_capture->n) {
-                regex->ncaptures = copy_capture->n;
-            }
-
-            copy_capture->n *= 2;
-
-            i++;
-
-            continue;
-        }
-
-        if (value[2].data[i] == '?') {
-
-            /* the arguments */
-
-            if (i == value[2].len - 1) {
-                /* the last "?" drops the original arguments */
-                regex->args = 0;
-                break;
-            }
-
-            if (!regex->redirect) {
-                code = ngx_http_rewrite_add_code(lcf->codes, sizeof(uintptr_t),
-                                                 &regex);
-                if (code == NULL) {
-                    return NGX_CONF_ERROR;
-                }
-
-                *code = ngx_http_rewrite_start_args_code;
-
-                i++;
-
-                continue;
-            }
-        }
-
-        i++;
-
-        /* the substituion strings */
-
-        while (i < value[2].len && value[2].data[i] != '$') {
-
-            if (value[2].data[i] == '?') {
-
-                if (i == value[2].len - 1) {
-                    /*
-                     * the last "?" drops the original arguments,
-                     * and it should not be copied to a substituion
-                     */
-                    regex->args = 0;
-                    break;
-                }
-
-                if (!regex->redirect) {
-                    break;
-                }
-            }
-
-            i++;
-        }
-
-        len = &value[2].data[i] - data;
-
-        if (len == 0) {
-            continue;
-        }
-
-        regex->size += len;
-
-        size = (len + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1);
-
-        copy = ngx_http_rewrite_add_code(lcf->codes,
-                                   sizeof(ngx_http_rewrite_copy_code_t) + size,
-                                   &regex);
-        if (copy == NULL) {
-            return NGX_CONF_ERROR;
-        }
-
-        copy->code = ngx_http_rewrite_copy_code;
-        copy->len = len;
-
-        ngx_memcpy((u_char *) copy + sizeof(ngx_http_rewrite_copy_code_t),
-                   data, len);
-    }
-
-    n = ngx_regex_capture_count(regex->regex);
-
-    if (regex->ncaptures > n) {
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                           "pattern \"%V\" has less captures "
-                           "than referrenced in substitution \"%V\"",
-                           &value[1], &value[2]);
-        return NGX_CONF_ERROR;
-    }
-
-    if (regex->ncaptures < n) {
-        regex->ncaptures = n;
-    }
-
-    if (regex->ncaptures) {
-        regex->ncaptures = (regex->ncaptures + 1) * 3;
-    }
-
-    regex_end = ngx_http_rewrite_add_code(lcf->codes,
-                                     sizeof(ngx_http_rewrite_regex_end_code_t),
-                                     &regex);
-    if (regex_end == NULL) {
-        return NGX_CONF_ERROR;
-    }
-
-    regex_end->code = ngx_http_rewrite_regex_end_code;
-    regex_end->uri = regex->uri;
-    regex_end->args = regex->args;
-    regex_end->redirect = regex->redirect;
-
-    if (last) {
-        code = ngx_http_rewrite_add_code(lcf->codes, sizeof(uintptr_t),
-                                         &regex);
-        if (code == NULL) {
-            return NGX_CONF_ERROR;
-        }
-
-        *code = (uintptr_t) NULL;
-    }
-
-    regex->next = (u_char *) lcf->codes->elts + lcf->codes->nelts
-                                              - (u_char *) regex;
-
-    return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_rewrite_return(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
-    ngx_http_rewrite_loc_conf_t *lcf = conf;
-
-    ngx_str_t                       *value;
-    ngx_http_rewrite_return_code_t  *ret;
-
-    ret = ngx_http_rewrite_start_code(cf->pool, &lcf->codes,
-                                      sizeof(ngx_http_rewrite_return_code_t));
-    if (ret == NULL) {
-        return NGX_CONF_ERROR;
-    }
-
-    value = cf->args->elts;
-
-    ret->code = ngx_http_rewrite_return_code;
-    ret->null = (uintptr_t) NULL;
-
-    ret->status = ngx_atoi(value[1].data, value[1].len);
-
-    if (ret->status == (uintptr_t) NGX_ERROR) {
-        return NGX_CONF_ERROR;
-    }
-
-    return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_rewrite_if(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
-    ngx_http_rewrite_loc_conf_t *lcf = conf;
-
-    void                         *mconf;
-    char                         *rv;
-    u_char                       *elts;
-    ngx_str_t                    *value;
-    ngx_int_t                     index;
-    ngx_uint_t                    i;
-    ngx_conf_t                    save;
-    ngx_http_rewrite_code_pt     *code;
-    ngx_http_module_t            *module;
-    ngx_http_conf_ctx_t          *ctx, *pctx;
-    ngx_http_core_loc_conf_t     *clcf, *pclcf, **clcfp;
-    ngx_http_core_main_conf_t    *cmcf;
-    ngx_http_rewrite_if_code_t   *if_code;
-    ngx_http_rewrite_var_code_t  *var_code;
-    ngx_http_rewrite_loc_conf_t  *nlcf;
-
-    if (!(ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)))) {
-        return NGX_CONF_ERROR;
-    }
-
-    pctx = cf->ctx;
-    ctx->main_conf = pctx->main_conf;
-    ctx->srv_conf = pctx->srv_conf; 
-
-    ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
-    if (ctx->loc_conf == NULL) {
-        return NGX_CONF_ERROR;
-    }
-
-    for (i = 0; ngx_modules[i]; i++) {
-        if (ngx_modules[i]->type != NGX_HTTP_MODULE) {
-            continue;
-        }
-
-        module = ngx_modules[i]->ctx;
-    
-        if (module->create_loc_conf) {
-
-            if (!(mconf = module->create_loc_conf(cf))) {
-                 return NGX_CONF_ERROR;
-            }
-
-            ctx->loc_conf[ngx_modules[i]->ctx_index] = mconf;
-        }
-    }
-
-    pclcf = pctx->loc_conf[ngx_http_core_module.ctx_index];
-
-    clcf = ctx->loc_conf[ngx_http_core_module.ctx_index];
-    clcf->loc_conf = ctx->loc_conf;
-    clcf->name = pclcf->name;
-    clcf->noname = 1;
-
-    if (pclcf->locations.elts == NULL) {
-        if (ngx_array_init(&pclcf->locations, cf->pool, 4, sizeof(void *))
-                                                                  == NGX_ERROR)
-        {
-            return NGX_CONF_ERROR;
-        }
-    }
-
-    if (!(clcfp = ngx_push_array(&pclcf->locations))) {
-        return NGX_CONF_ERROR;
-    }
-
-    *clcfp = clcf;
-
-
-    /* STUB: "if ($var)" */
-
-    value = cf->args->elts;
-
-    if (value[1].len < 2
-        || value[1].data[0] != '('
-        || value[1].data[1] != '$'
-        || value[1].data[value[1].len - 1] != ')')
-    {
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                           "invalid condition \"%V\"", &value[1]);
-        return NGX_CONF_ERROR;
-    }
-
-    value[1].len -= 3;
-    value[1].data += 2;
-
-    if (value[1].len == sizeof("invalid_referer") - 1
-        && ngx_strncmp(value[1].data, "invalid_referer",
-                       sizeof("invalid_referer") - 1) == 0)
-    {
-        code = ngx_http_rewrite_start_code(cf->pool, &lcf->codes,
-                                           sizeof(ngx_http_rewrite_code_pt));
-        if (code == NULL) {
-            return NGX_CONF_ERROR;
-        }
-
-        *code = ngx_http_rewrite_invalid_referer_code;
-
-    } else {
-        cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
-
-        index = ngx_http_get_variable_index(cmcf, &value[1]);
-
-        if (index == -1) {
-            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                               "unknown variable name \"%V\"", &value[1]);
-            return NGX_CONF_ERROR;
-        }
-
-        var_code = ngx_http_rewrite_start_code(cf->pool, &lcf->codes,
-                                           sizeof(ngx_http_rewrite_var_code_t));
-        if (var_code == NULL) {
-            return NGX_CONF_ERROR;
-        }
-
-        var_code->code = ngx_http_rewrite_var_code;
-        var_code->index = index;
-    }
-
-    if_code = ngx_array_push_n(lcf->codes, sizeof(ngx_http_rewrite_if_code_t));
-    if (if_code == NULL) {
-        return NULL;
-    }
-
-    if_code->code = ngx_http_rewrite_if_code;
-
-    elts = lcf->codes->elts;
-
-
-    /* the inside directives must compile to the same code array */
-
-    nlcf = ctx->loc_conf[ngx_http_rewrite_module.ctx_index];
-    nlcf->codes = lcf->codes;
-
-
-    save = *cf;
-    cf->ctx = ctx;
-
-    if (pclcf->name.len == 0) {
-        if_code->loc_conf = NULL;
-        cf->cmd_type = NGX_HTTP_SIF_CONF;
-
-    } else {
-        if_code->loc_conf = ctx->loc_conf;
-        cf->cmd_type = NGX_HTTP_LIF_CONF;
-    }
-
-    rv = ngx_conf_parse(cf, NULL);
-
-    *cf = save;
-
-    if (rv != NGX_CONF_OK) {
-        return rv;
-    }
-
-
-    if (elts != lcf->codes->elts) {
-        if_code = (ngx_http_rewrite_if_code_t *)
-                   ((u_char *) if_code + ((u_char *) lcf->codes->elts - elts));
-    }
-
-    if_code->next = (u_char *) lcf->codes->elts + lcf->codes->nelts
-                                                - (u_char *) if_code;
-
-    return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_rewrite_valid_referers(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
-    ngx_http_rewrite_loc_conf_t *lcf = conf;
-
-    ngx_uint_t                   i, server_names;
-    ngx_str_t                   *value;
-    ngx_http_server_name_t      *sn;
-    ngx_http_core_srv_conf_t    *cscf;
-    ngx_http_rewrite_referer_t  *ref;
-
-    cscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_core_module);
-
-    if (lcf->referers == NULL) {
-        lcf->referers = ngx_array_create(cf->pool,
-                                    cf->args->nelts + cscf->server_names.nelts,
-                                    sizeof(ngx_http_rewrite_referer_t));
-        if (lcf->referers == NULL) {
-            return NGX_CONF_ERROR;
-        }
-    }
-
-    value = cf->args->elts;
-    server_names = 0;
-
-    for (i = 1; i < cf->args->nelts; i++) {
-        if (value[i].len == 0) {
-            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                               "invalid referer \"%V\"", &value[i]);
-            return NGX_CONF_ERROR;
-        }
-
-        if (ngx_strcmp(value[i].data, "none") == 0) {
-            lcf->no_referer = 1;
-            continue;
-        }
-
-        if (ngx_strcmp(value[i].data, "server_names") == 0) {
-            server_names = 1;
-            continue;
-        }
-
-        if (!(ref = ngx_array_push(lcf->referers))) {
-            return NGX_CONF_ERROR;
-        }
-
-        if (value[i].data[0] != '*') {
-            ref->name = value[i];
-            ref->wildcard = 0;
-            continue;
-        }
-
-        if (value[i].data[1] != '.') {
-            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                               "invalid wildcard referer \"%V\"", &value[i]);
-            return NGX_CONF_ERROR;
-        }
-
-        ref->name.len = value[i].len - 1;
-        ref->name.data = value[i].data + 1;
-        ref->wildcard = 1;
-    }
-
-    if (!server_names) {
-        return NGX_CONF_OK;
-    }
-
-    sn = cscf->server_names.elts;
-    for (i = 0; i < cscf->server_names.nelts; i++) {
-        if (!(ref = ngx_array_push(lcf->referers))) {
-            return NGX_CONF_ERROR;
-        }
-
-        ref->name.len = sn[i].name.len + 1;
-        if (!(ref->name.data = ngx_palloc(cf->pool, ref->name.len))) {
-            return NGX_CONF_ERROR;
-        }
-
-        ngx_memcpy(ref->name.data, sn[i].name.data, sn[i].name.len);
-        ref->name.data[sn[i].name.len] = '/';
-        ref->wildcard = sn[i].wildcard;
-    }
-
-    return NGX_CONF_OK;
-}
-
-
-static void *
-ngx_http_rewrite_start_code(ngx_pool_t *pool, ngx_array_t **codes, size_t size)
-{
-    if (*codes == NULL) {
-        if (!(*codes = ngx_array_create(pool, 256, 1))) {
-            return NULL;
-        }
-    }
-
-    return ngx_array_push_n(*codes, size);
-}
-
-
-static void *
-ngx_http_rewrite_add_code(ngx_array_t *codes, size_t size, void *code)
-{
-    u_char  *elts, **p;
-    void    *new;
-
-    elts = codes->elts;
-
-    if (!(new = ngx_array_push_n(codes, size))) {
-        return NGX_CONF_ERROR;
-    }
-
-    if (elts != codes->elts) {
-        p = code;
-        *p += (u_char *) codes->elts - elts;
-    }
-
-    return new;
-}
new file mode 100644
--- /dev/null
+++ b/src/http/modules/ngx_http_rewrite_module.c
@@ -0,0 +1,1689 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+
+
+typedef struct ngx_http_rewrite_engine_s  ngx_http_rewrite_engine_t;
+
+typedef void (*ngx_http_rewrite_code_pt) (ngx_http_rewrite_engine_t *e);
+
+
+typedef struct {
+    ngx_str_t                     name;
+    ngx_uint_t                    wildcard;
+} ngx_http_rewrite_referer_t;
+
+
+typedef struct {
+    ngx_str_t                    *name;
+    ngx_http_variable_value_t    *value;
+} ngx_http_rewrite_variable_t;
+
+
+typedef struct {
+    ngx_array_t                  *codes;        /* uintptr_t */
+    ngx_array_t                  *referers;     /* ngx_http_rewrite_referer_t */
+
+    ngx_uint_t                    max_captures;
+    ngx_uint_t                    stack_size;
+
+    ngx_flag_t                    log;
+
+    ngx_flag_t                    no_referer;
+} ngx_http_rewrite_loc_conf_t;
+
+
+typedef struct {
+    ngx_http_rewrite_code_pt      code;
+    ngx_regex_t                  *regex;
+    uintptr_t                     size;
+    uintptr_t                     ncaptures;
+    uintptr_t                     status;
+    uintptr_t                     next;
+
+    uintptr_t                     test:1;
+    uintptr_t                     uri:1;
+
+    /* add the r->args to the new arguments */
+    uintptr_t                     args:1;
+
+    uintptr_t                     redirect:1;
+    uintptr_t                     break_cycle:1;
+
+    ngx_str_t                     name;
+} ngx_http_rewrite_regex_code_t;
+
+
+typedef struct {
+    ngx_http_rewrite_code_pt      code;
+
+    uintptr_t                     uri:1;
+
+    /* add the r->args to the new arguments */
+    uintptr_t                     args:1;
+
+    uintptr_t                     redirect:1;
+} ngx_http_rewrite_regex_end_code_t;
+
+typedef struct {
+    ngx_http_rewrite_code_pt      code;
+    uintptr_t                     n;
+} ngx_http_rewrite_copy_capture_code_t;
+
+
+typedef struct {
+    ngx_http_rewrite_code_pt      code;
+    uintptr_t                     len;
+} ngx_http_rewrite_copy_code_t;
+
+
+typedef struct {
+    ngx_http_rewrite_code_pt      code;
+    uintptr_t                     status;
+    uintptr_t                     null;
+} ngx_http_rewrite_return_code_t;
+
+
+typedef struct {
+    ngx_http_rewrite_code_pt      code;
+    uintptr_t                     next;
+    void                        **loc_conf;
+} ngx_http_rewrite_if_code_t;
+
+
+typedef struct {
+    ngx_http_rewrite_code_pt      code;
+    uintptr_t                     value;
+    uintptr_t                     text_len;
+    uintptr_t                     text_data;
+} ngx_http_rewrite_value_code_t;
+
+
+typedef struct {
+    ngx_http_rewrite_code_pt      code;
+    uintptr_t                     index;
+} ngx_http_rewrite_var_code_t;
+
+
+struct ngx_http_rewrite_engine_s {
+    u_char                       *ip;
+    ngx_http_variable_value_t    *sp;
+
+    ngx_str_t                     buf;
+    ngx_str_t                    *line;
+
+    u_char                       *pos;
+
+    /* the start of the rewritten arguments */
+    u_char                       *args;
+
+    unsigned                      quote:1;
+
+    ngx_int_t                     status;
+
+    int                          *captures;
+
+    ngx_http_request_t           *request;
+    ngx_http_rewrite_loc_conf_t  *conf;
+};
+
+
+static ngx_int_t ngx_http_rewrite_init(ngx_cycle_t *cycle);
+static void *ngx_http_rewrite_create_loc_conf(ngx_conf_t *cf);
+static char *ngx_http_rewrite_merge_loc_conf(ngx_conf_t *cf,
+    void *parent, void *child);
+static char *ngx_http_rewrite(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
+static char *ngx_http_rewrite_return(ngx_conf_t *cf, ngx_command_t *cmd,
+    void *conf);
+static char *ngx_http_rewrite_if(ngx_conf_t *cf, ngx_command_t *cmd,
+    void *conf);
+static char * ngx_http_rewrite_if_condition(ngx_conf_t *cf,
+    ngx_http_rewrite_loc_conf_t *lcf);
+static char *ngx_http_rewrite_variable(ngx_conf_t *cf,
+    ngx_http_rewrite_loc_conf_t *lcf, ngx_str_t *value);
+static char *ngx_http_rewrite_valid_referers(ngx_conf_t *cf,
+    ngx_command_t *cmd, void *conf);
+static char * ngx_http_rewrite_set(ngx_conf_t *cf, ngx_command_t *cmd,
+    void *conf);
+static void *ngx_http_rewrite_start_code(ngx_pool_t *pool,
+    ngx_array_t **codes, size_t size);
+static void *ngx_http_rewrite_add_code(ngx_array_t *codes, size_t size,
+    void *code);
+
+
+static ngx_command_t  ngx_http_rewrite_commands[] = {
+
+    { ngx_string("rewrite"),
+      NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
+                       |NGX_CONF_TAKE23,
+      ngx_http_rewrite,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      0,
+      NULL },
+
+    { ngx_string("return"),
+      NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
+                       |NGX_CONF_TAKE1,
+      ngx_http_rewrite_return,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      0,
+      NULL },
+
+    { ngx_string("if"),
+      NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_BLOCK|NGX_CONF_1MORE,
+      ngx_http_rewrite_if,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      0,
+      NULL },
+
+    { ngx_string("valid_referers"),
+      NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
+      ngx_http_rewrite_valid_referers,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      0,
+      NULL },
+
+    { ngx_string("set"),
+      NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
+                       |NGX_CONF_TAKE2,
+      ngx_http_rewrite_set,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      0,
+      NULL },
+
+    { ngx_string("rewrite_log"),
+      NGX_HTTP_SRV_CONF|NGX_HTTP_SIF_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
+                       |NGX_CONF_TAKE1,
+      ngx_conf_set_flag_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_rewrite_loc_conf_t, log),
+      NULL },
+
+      ngx_null_command
+};
+
+
+ngx_http_module_t  ngx_http_rewrite_module_ctx = {
+    NULL,                                  /* pre conf */
+
+    NULL,                                  /* create main configuration */
+    NULL,                                  /* init main configuration */
+
+    NULL,                                  /* create server configuration */
+    NULL,                                  /* merge server configuration */
+
+    ngx_http_rewrite_create_loc_conf,      /* create location configration */
+    ngx_http_rewrite_merge_loc_conf        /* merge location configration */
+};
+
+
+ngx_module_t  ngx_http_rewrite_module = {
+    NGX_MODULE,
+    &ngx_http_rewrite_module_ctx,          /* module context */ 
+    ngx_http_rewrite_commands,             /* module directives */
+    NGX_HTTP_MODULE,                       /* module type */
+    ngx_http_rewrite_init,                 /* init module */
+    NULL                                   /* init process */
+};
+
+
+#define ngx_http_rewrite_exit  (u_char *) &ngx_http_rewrite_exit_code
+
+uintptr_t ngx_http_rewrite_exit_code = (uintptr_t) NULL;
+
+static ngx_http_variable_value_t  ngx_http_rewrite_null_value =
+                                                        { 0, ngx_string("") };
+
+
+static ngx_int_t
+ngx_http_rewrite_handler(ngx_http_request_t *r)
+{
+    ngx_http_rewrite_code_pt      code;
+    ngx_http_rewrite_engine_t    *e;
+    ngx_http_rewrite_loc_conf_t  *cf;
+
+    cf = ngx_http_get_module_loc_conf(r, ngx_http_rewrite_module);
+
+    if (cf->codes == NULL) {
+        return NGX_DECLINED;
+    }
+
+    e = ngx_palloc(r->pool, sizeof(ngx_http_rewrite_engine_t));
+    if (e == NULL) {
+        return NGX_HTTP_INTERNAL_SERVER_ERROR;
+    }
+
+    e->sp = ngx_palloc(r->pool,
+                       cf->stack_size * sizeof(ngx_http_variable_value_t));
+    if (e->sp == NULL) {
+        return NGX_HTTP_INTERNAL_SERVER_ERROR;
+    }
+
+    if (cf->max_captures) {
+        e->captures = ngx_palloc(r->pool, cf->max_captures * sizeof(int));
+        if (e->captures == NULL) {
+            return NGX_HTTP_INTERNAL_SERVER_ERROR;
+        }
+
+    } else {
+        e->captures = NULL;
+    }
+
+    e->ip = cf->codes->elts;
+    e->buf.len = 0;
+    e->buf.data = NULL;
+    e->line = NULL;
+    e->pos = NULL;
+    e->args = NULL;
+    e->quote = 1;
+    e->status = NGX_DECLINED;
+    e->request = r;
+    e->conf = cf;
+
+    while (*(uintptr_t *) e->ip) {
+        code = *(ngx_http_rewrite_code_pt *) e->ip;
+        code(e);
+    }
+
+    return e->status;
+}
+
+
+static void
+ngx_http_rewrite_regex_start_code(ngx_http_rewrite_engine_t *e)
+{
+    ngx_int_t                       rc;
+    ngx_uint_t                      n;
+    ngx_http_request_t             *r;
+    ngx_http_rewrite_regex_code_t  *code;
+
+    code = (ngx_http_rewrite_regex_code_t *) e->ip;
+
+    r = e->request;
+
+    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                   "http rewrite regex: \"%V\"", &code->name);
+
+    if (code->uri) {
+        e->line = &r->uri;
+    } else {
+        e->sp--;
+        e->line = &e->sp->text;
+    }
+
+    rc = ngx_regex_exec(code->regex, e->line, e->captures, code->ncaptures);
+
+    if (rc == NGX_REGEX_NO_MATCHED) {
+        if (e->conf->log) {
+            ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
+                          "\"%V\" does not match \"%V\"", &code->name, e->line);
+        }
+
+        if (code->test) {
+            e->sp->value = 0;
+            e->sp->text.len = 0;
+            e->sp->text.data = (u_char *) "";
+            e->sp++;
+
+            e->ip += sizeof(ngx_http_rewrite_regex_code_t);
+            return;
+        }
+
+        e->ip += code->next;
+        return;
+    }
+
+    if (rc < 0) {
+        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+                      ngx_regex_exec_n " failed: %d on \"%V\" using \"%V\"",
+                      rc, e->line, &code->name);
+
+        e->ip = ngx_http_rewrite_exit;
+        e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
+        return;
+    }
+
+    if (e->conf->log) {
+        ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
+                      "\"%V\" matches \"%V\"", &code->name, e->line);
+    }
+
+    if (code->test) {
+        e->sp->value = 1;
+        e->sp->text.len = 1;
+        e->sp->text.data = (u_char *) "1";
+        e->sp++;
+
+        e->ip += sizeof(ngx_http_rewrite_regex_code_t);
+        return;
+    }
+
+    if (code->status) {
+        e->status = code->status;
+
+        if (!code->redirect) {
+            e->ip = ngx_http_rewrite_exit;
+            return;
+        }
+    }
+
+    e->buf.len = code->size;
+
+    if (code->uri) {
+        if (!code->break_cycle) {
+            r->uri_changed = 1;
+        }
+
+        if (rc && (r->quoted_uri || r->plus_in_uri)) {
+            e->buf.len += 2 * ngx_escape_uri(NULL, r->uri.data, r->uri.len,
+                                             NGX_ESCAPE_ARGS);
+        }
+    }
+
+    for (n = 1; n < (ngx_uint_t) rc; n++) {
+        e->buf.len += e->captures[2 * n + 1] - e->captures[2 * n];
+    }
+
+    if (code->args && r->args.len) {
+        e->buf.len += r->args.len + 1;
+    }
+
+    e->buf.data = ngx_palloc(r->pool, e->buf.len);
+    if (e->buf.data == NULL) {
+        e->ip = ngx_http_rewrite_exit;
+        e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
+        return;
+    }
+
+    e->quote = code->redirect;
+
+    e->pos = e->buf.data;
+
+    e->ip += sizeof(ngx_http_rewrite_regex_code_t);
+}
+
+
+static void
+ngx_http_rewrite_regex_end_code(ngx_http_rewrite_engine_t *e)
+{
+    ngx_http_request_t                 *r;
+    ngx_http_rewrite_regex_end_code_t  *code;
+
+    code = (ngx_http_rewrite_regex_end_code_t *) e->ip;
+
+    r = e->request;
+
+    e->quote = 0;
+
+    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                   "http rewrite regex end");
+
+    if (e->args) {
+        e->buf.len = e->args - e->buf.data;
+
+        if (code->args && r->args.len) {
+            *e->pos++ = '&';
+            e->pos = ngx_cpymem(e->pos, r->args.data, r->args.len);
+        }
+
+        r->args.len = e->pos - e->args;
+        r->args.data = e->args;
+
+        e->args = NULL;
+
+    } else {
+        if (code->args && r->args.len) {
+            *e->pos++ = '?';
+            e->pos = ngx_cpymem(e->pos, r->args.data, r->args.len);
+        }
+
+        e->buf.len = e->pos - e->buf.data;
+    }
+
+    if (!code->redirect) {
+        if (e->conf->log) {
+            ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
+                          "rewritten data: \"%V\", args: \"%V\"",
+                          &e->buf, &r->args);
+        }
+
+        if (code->uri) {
+            r->uri = e->buf;
+
+            if (ngx_http_set_exten(r) != NGX_OK) {
+                e->ip = ngx_http_rewrite_exit;
+                e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
+                return;
+            }
+        }
+
+        e->ip += sizeof(ngx_http_rewrite_regex_end_code_t);
+        return;
+    }
+
+    ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0,
+                  "rewritten redirect: \"%V\"", &e->buf);
+
+    r->headers_out.location = ngx_list_push(&r->headers_out.headers);
+    if (r->headers_out.location == NULL) {
+        e->ip = ngx_http_rewrite_exit;
+        e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
+        return;
+    }
+
+    if (e->buf.data[0] != '/') {
+        r->headers_out.location->key.len = sizeof("Location") - 1;
+        r->headers_out.location->key.data = (u_char *) "Location";
+    }
+
+    r->headers_out.location->value = e->buf;
+
+    e->ip += sizeof(ngx_http_rewrite_regex_end_code_t);
+}
+
+
+static void
+ngx_http_rewrite_copy_capture_code(ngx_http_rewrite_engine_t *e)
+{
+    ngx_http_rewrite_copy_capture_code_t  *code;
+
+    code = (ngx_http_rewrite_copy_capture_code_t *) e->ip;
+
+    e->ip += sizeof(ngx_http_rewrite_copy_capture_code_t);
+
+    if ((e->args || e->quote)
+        && (e->request->quoted_uri || e->request->plus_in_uri))
+    {
+        e->pos = (u_char *) ngx_escape_uri(e->pos,
+                                &e->line->data[e->captures[code->n]],
+                                e->captures[code->n + 1] - e->captures[code->n],
+                                NGX_ESCAPE_ARGS);
+    } else {
+        e->pos = ngx_cpymem(e->pos, &e->line->data[e->captures[code->n]],
+                        e->captures[code->n + 1] - e->captures[code->n]);
+    }
+
+    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
+                   "http rewrite capture: \"%V\"", &e->buf);
+}
+
+
+static void
+ngx_http_rewrite_copy_code(ngx_http_rewrite_engine_t *e)
+{
+    ngx_http_rewrite_copy_code_t  *code;
+
+    code = (ngx_http_rewrite_copy_code_t *) e->ip;
+
+    e->pos = ngx_cpymem(e->pos, e->ip + sizeof(ngx_http_rewrite_copy_code_t),
+                        code->len);
+
+    e->ip += sizeof(ngx_http_rewrite_copy_code_t)
+          + ((code->len + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1));
+
+    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
+                   "http rewrite copy: \"%V\"", &e->buf);
+}
+
+
+static void
+ngx_http_rewrite_start_args_code(ngx_http_rewrite_engine_t *e)
+{
+    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
+                   "http rewrite args");
+
+    e->args = e->pos;
+    e->ip += sizeof(uintptr_t);
+}
+
+
+static void
+ngx_http_rewrite_return_code(ngx_http_rewrite_engine_t *e)
+{
+    ngx_http_rewrite_return_code_t  *code;
+
+    code = (ngx_http_rewrite_return_code_t *) e->ip;
+
+    e->status = code->status;
+
+    e->ip += sizeof(ngx_http_rewrite_return_code_t) - sizeof(uintptr_t);
+}
+
+
+static void
+ngx_http_rewrite_if_code(ngx_http_rewrite_engine_t *e)
+{
+    ngx_http_rewrite_if_code_t  *code;
+
+    code = (ngx_http_rewrite_if_code_t *) e->ip;
+
+    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
+                   "http rewrite if");
+
+    e->sp--;
+
+    if (e->sp->value) {
+        if (code->loc_conf) {
+            e->request->loc_conf = code->loc_conf;
+        }
+
+        e->ip += sizeof(ngx_http_rewrite_if_code_t);
+        return;
+    }
+
+    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
+                   "http rewrite if false");
+
+    e->ip += code->next;
+}
+
+
+static void
+ngx_http_rewrite_value_code(ngx_http_rewrite_engine_t *e)
+{
+    ngx_http_rewrite_value_code_t  *code;
+
+    code = (ngx_http_rewrite_value_code_t *) e->ip;
+
+    e->ip += sizeof(ngx_http_rewrite_value_code_t);
+
+    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
+                   "http rewrite value");
+
+    e->sp->value = (ngx_uint_t) code->value;
+    e->sp->text.len = (size_t) code->text_len;
+    e->sp->text.data = (u_char *) code->text_data;
+    e->sp++;
+}
+
+
+static void
+ngx_http_rewrite_set_var_code(ngx_http_rewrite_engine_t *e)
+{
+    ngx_http_request_t           *r;
+    ngx_http_variable_value_t    *value;
+    ngx_http_core_main_conf_t    *cmcf;
+    ngx_http_rewrite_var_code_t  *code;
+
+    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
+                   "http rewrite set var");
+
+    code = (ngx_http_rewrite_var_code_t *) e->ip;
+
+    e->ip += sizeof(ngx_http_rewrite_var_code_t);
+
+    r = e->request;
+
+    if (r->variables == NULL) {
+        cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
+
+        r->variables = ngx_pcalloc(r->pool, cmcf->variables.nelts
+                                        * sizeof(ngx_http_variable_value_t *));
+        if (r->variables == NULL) {
+            e->ip = ngx_http_rewrite_exit;
+            e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
+            return;
+        }
+    }
+
+    value = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
+    if (value == NULL) {
+        e->ip = ngx_http_rewrite_exit;
+        e->status = NGX_HTTP_INTERNAL_SERVER_ERROR;
+        return;
+    }
+
+    e->sp--;
+
+    *value = *e->sp;
+
+    r->variables[code->index] = value;
+}
+
+
+static void
+ngx_http_rewrite_var_code(ngx_http_rewrite_engine_t *e)
+{
+    ngx_http_variable_value_t    *value;
+    ngx_http_rewrite_var_code_t  *code;
+
+    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
+                   "http rewrite var");
+
+    code = (ngx_http_rewrite_var_code_t *) e->ip;
+
+    e->ip += sizeof(ngx_http_rewrite_var_code_t);
+
+    value = ngx_http_get_indexed_variable(e->request, code->index);
+
+    if (value == NULL || value == NGX_HTTP_VARIABLE_NOT_FOUND) {
+        e->sp->value = 0;
+        e->sp->text.len = 0;
+        e->sp->text.data = (u_char *) "";
+        e->sp++;
+
+        return;
+    }
+
+    ngx_log_debug2(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
+                   "http rewrite var: %ui, \"%V\"", value->value, &value->text);
+
+    *e->sp = *value;
+    e->sp++;
+}
+
+
+static void
+ngx_http_rewrite_invalid_referer_code(ngx_http_rewrite_engine_t *e)
+{
+    u_char                       *ref;
+    size_t                        len;
+    ngx_uint_t                    i, n;
+    ngx_http_request_t           *r;
+    ngx_http_rewrite_referer_t   *refs;
+    ngx_http_rewrite_loc_conf_t  *cf;
+
+    r = e->request;
+
+    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                   "http rewrite invalid referer");
+
+    cf = ngx_http_get_module_loc_conf(r, ngx_http_rewrite_module);
+
+    e->ip += sizeof(uintptr_t);
+
+    if (cf->referers == NULL) {
+        e->sp->value = 0;
+        e->sp->text.len = 0;
+        e->sp->text.data = (u_char *) "";
+        e->sp++;
+
+        return;
+    }
+
+    if (r->headers_in.referer == NULL) {
+        if (cf->no_referer) {
+            e->sp->value = 0;
+            e->sp->text.len = 0;
+            e->sp->text.data = (u_char *) "";
+            e->sp++;
+
+            return;
+        } else {
+            e->sp->value = 1;
+            e->sp->text.len = 1;
+            e->sp->text.data = (u_char *) "1";
+            e->sp++;
+
+            return;
+        }
+    }
+
+    len = r->headers_in.referer->value.len;
+    ref = r->headers_in.referer->value.data;
+
+    if (len < sizeof("http://i.ru") - 1
+        || (ngx_strncasecmp(ref, "http://", 7) != 0))
+    {
+        e->sp->value = 1;
+        e->sp->text.len = 1;
+        e->sp->text.data = (u_char *) "1";
+        e->sp++;
+
+        return;
+    }
+
+    len -= 7;
+    ref += 7;
+
+    refs = cf->referers->elts;
+    for (i = 0; i < cf->referers->nelts; i++ ){
+
+        if (refs[i].name.len > len) {
+            continue;
+        }
+
+        if (refs[i].wildcard) {
+            for (n = 0; n < len; n++) {
+                if (ref[n] == '/' || ref[n] == ':') {
+                    break;
+                }
+
+                if (ref[n] != '.') {
+                    continue;
+                }
+
+                if (ngx_strncmp(&ref[n], refs[i].name.data,
+                                refs[i].name.len) == 0)
+                {
+                    e->sp->value = 0;
+                    e->sp->text.len = 0;
+                    e->sp->text.data = (u_char *) "";
+                    e->sp++;
+
+                    return;
+                }
+            }
+
+        } else {
+            if (ngx_strncasecmp(refs[i].name.data, ref, refs[i].name.len) == 0)
+            {
+                e->sp->value = 0;
+                e->sp->text.len = 0;
+                e->sp->text.data = (u_char *) "";
+                e->sp++;
+
+                return;
+            }
+        }
+    }
+
+    e->sp->value = 1;
+    e->sp->text.len = 1;
+    e->sp->text.data = (u_char *) "1";
+    e->sp++;
+}
+
+
+static void
+ngx_http_rewrite_nop_code(ngx_http_rewrite_engine_t *e)
+{
+    e->ip += sizeof(uintptr_t);
+}
+
+
+static ngx_http_variable_value_t *
+ngx_http_rewrite_var(ngx_http_request_t *r, uintptr_t data)
+{
+    ngx_http_variable_t        *var;
+    ngx_http_core_main_conf_t  *cmcf;
+
+    cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
+
+    var = cmcf->variables.elts;
+
+    /*
+     * the ngx_http_rewrite_module sets variables directly in r->variables,
+     * and they should be handle by ngx_http_get_indexed_variable(),
+     * so the handler is called only if the variable is not initialized
+     */
+
+    ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+                  "using uninitialized \"%V\" variable", &var[data].name);
+
+    return &ngx_http_rewrite_null_value;
+}
+
+
+static ngx_int_t
+ngx_http_rewrite_init(ngx_cycle_t *cycle)
+{   
+    ngx_http_handler_pt        *h;
+    ngx_http_core_main_conf_t  *cmcf;
+    
+    cmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_core_module);
+
+    h = ngx_array_push(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers);
+    if (h == NULL) {
+        return NGX_ERROR;
+    }
+    
+    *h = ngx_http_rewrite_handler;
+    
+    return NGX_OK;
+}   
+
+
+static void *
+ngx_http_rewrite_create_loc_conf(ngx_conf_t *cf)
+{
+    ngx_http_rewrite_loc_conf_t  *conf;
+
+    conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_rewrite_loc_conf_t));
+    if (conf == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    conf->stack_size = NGX_CONF_UNSET_UINT;
+    conf->log = NGX_CONF_UNSET;
+    conf->no_referer = NGX_CONF_UNSET;
+
+    return conf;
+}
+
+
+static char *
+ngx_http_rewrite_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
+{
+    ngx_http_rewrite_loc_conf_t *prev = parent;
+    ngx_http_rewrite_loc_conf_t *conf = child;
+
+    uintptr_t                      *code, *last;
+    ngx_http_rewrite_regex_code_t  *regex;
+
+    ngx_conf_merge_value(conf->log, prev->log, 0);
+    ngx_conf_merge_unsigned_value(conf->stack_size, prev->stack_size, 10);
+
+    if (conf->referers == NULL) {
+        conf->referers = prev->referers;
+        ngx_conf_merge_value(conf->no_referer, prev->no_referer, 0);
+    }
+
+    if (conf->no_referer == NGX_CONF_UNSET) {
+        conf->no_referer = 0;
+    }
+
+    if (conf->codes == NULL) {
+        return NGX_CONF_OK;
+    }
+
+    if (conf->codes == prev->codes) {
+        return NGX_CONF_OK;
+    }
+
+    code = conf->codes->elts;
+    last = (uintptr_t *) ((u_char *) code + conf->codes->nelts);
+
+    while (code < last) {
+        if (*code == (uintptr_t) NULL) {
+            return NGX_CONF_OK;
+        }
+
+        if (*code == (uintptr_t) &ngx_http_rewrite_regex_start_code) {
+            regex = (ngx_http_rewrite_regex_code_t *) code;
+            if (conf->max_captures < regex->ncaptures) {
+                conf->max_captures = regex->ncaptures;
+            }
+            code = (uintptr_t *) ((u_char *) code + regex->next);
+            continue;
+        }
+
+        if (*code == (uintptr_t) &ngx_http_rewrite_if_code) {
+            code += sizeof(ngx_http_rewrite_if_code_t) / sizeof(uintptr_t);
+            continue;
+        }
+
+        if (*code == (uintptr_t) &ngx_http_rewrite_return_code) {
+            code += sizeof(ngx_http_rewrite_return_code_t) / sizeof(uintptr_t);
+            continue;
+        }
+
+        if (*code == (uintptr_t) &ngx_http_rewrite_set_var_code) {
+            code += sizeof(ngx_http_rewrite_var_code_t) / sizeof(uintptr_t);
+            continue;
+        }
+
+        if (*code == (uintptr_t) &ngx_http_rewrite_var_code) {
+            code += sizeof(ngx_http_rewrite_var_code_t) / sizeof(uintptr_t);
+            continue;
+        }
+
+        if (*code == (uintptr_t) &ngx_http_rewrite_value_code) {
+            code += sizeof(ngx_http_rewrite_value_code_t) / sizeof(uintptr_t);
+            continue;
+        }
+
+        if (*code == (uintptr_t) &ngx_http_rewrite_invalid_referer_code) {
+            code++;
+            continue;
+        }
+
+        if (*code == (uintptr_t) &ngx_http_rewrite_nop_code) {
+            code++;
+            continue;
+        }
+
+#if (NGX_DEBUG)
+        ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+                      "unknown rewrite code: %p", *code);
+        return NGX_CONF_ERROR;
+#endif
+    }
+
+    code = ngx_array_push_n(conf->codes, sizeof(uintptr_t));
+    if (code == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    *code = (uintptr_t) NULL;
+
+    return NGX_CONF_OK;
+}
+
+
+static char *
+ngx_http_rewrite(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+    ngx_http_rewrite_loc_conf_t *lcf = conf;
+    
+    u_char                                *data;
+    size_t                                 len, size;
+    ngx_str_t                             *value, err;
+    ngx_int_t                              n;
+    ngx_uint_t                             i, last;
+    ngx_http_rewrite_code_pt              *code;
+    ngx_http_rewrite_copy_code_t          *copy;
+    ngx_http_rewrite_regex_code_t         *regex;
+    ngx_http_rewrite_regex_end_code_t     *regex_end;
+    ngx_http_rewrite_copy_capture_code_t  *copy_capture;
+    u_char                                 errstr[NGX_MAX_CONF_ERRSTR];
+
+    regex = ngx_http_rewrite_start_code(cf->pool, &lcf->codes,
+                                        sizeof(ngx_http_rewrite_regex_code_t));
+    if (regex == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    value = cf->args->elts;
+
+    err.len = NGX_MAX_CONF_ERRSTR;
+    err.data = errstr;
+
+    /* TODO: NGX_REGEX_CASELESS */
+
+    regex->regex = ngx_regex_compile(&value[1], 0, cf->pool, &err);
+
+    if (regex->regex == NULL) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
+        return NGX_CONF_ERROR;
+    }
+
+    regex->code = ngx_http_rewrite_regex_start_code;
+    regex->size = 0;
+    regex->ncaptures = 0;
+    regex->status = 0;
+    regex->test = 0;
+    regex->uri = 1;
+    regex->args = 1;
+    regex->redirect = 0;
+    regex->name = value[1];
+
+    last = 0;
+
+    if (ngx_strncmp(value[2].data, "http://", sizeof("http://") - 1) == 0) {
+        regex->status = NGX_HTTP_MOVED_TEMPORARILY;
+        regex->redirect = 1;
+        last = 1;
+    }
+
+    if (cf->args->nelts == 4) {
+        if (ngx_strcmp(value[3].data, "last") == 0) {
+            last = 1;
+
+        } else if (ngx_strcmp(value[3].data, "break") == 0) {
+            regex->break_cycle = 1;
+            last = 1;
+
+        } else if (ngx_strcmp(value[3].data, "redirect") == 0) {
+            regex->status = NGX_HTTP_MOVED_TEMPORARILY;
+            regex->redirect = 1;
+            last = 1;
+
+        } else if (ngx_strcmp(value[3].data, "permanent") == 0) {
+            regex->status = NGX_HTTP_MOVED_PERMANENTLY;
+            regex->redirect = 1;
+            last = 1;
+
+        } else {
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                               "invalid parameter \"%V\"", &value[3]);
+            return NGX_CONF_ERROR;
+        }
+    }
+
+    i = 0;
+
+    while (i < value[2].len) {
+
+        data = &value[2].data[i];
+
+        if (value[2].data[i] == '$' && i < value[2].len
+            && value[2].data[i + 1] >= '1' && value[2].data[i + 1] <= '9')
+        {
+
+            /* the "$1" - "$9" captures */
+
+            copy_capture = ngx_http_rewrite_add_code(lcf->codes,
+                                  sizeof(ngx_http_rewrite_copy_capture_code_t),
+                                  &regex);
+            if (copy_capture == NULL) {
+                return NGX_CONF_ERROR;
+            }
+
+            i++;
+
+            copy_capture->code = ngx_http_rewrite_copy_capture_code;
+            copy_capture->n = value[2].data[i] - '0';
+
+            if (regex->ncaptures < copy_capture->n) {
+                regex->ncaptures = copy_capture->n;
+            }
+
+            copy_capture->n *= 2;
+
+            i++;
+
+            continue;
+        }
+
+        if (value[2].data[i] == '?') {
+
+            /* the arguments */
+
+            if (i == value[2].len - 1) {
+                /* the last "?" drops the original arguments */
+                regex->args = 0;
+                break;
+            }
+
+            if (!regex->redirect) {
+                code = ngx_http_rewrite_add_code(lcf->codes, sizeof(uintptr_t),
+                                                 &regex);
+                if (code == NULL) {
+                    return NGX_CONF_ERROR;
+                }
+
+                *code = ngx_http_rewrite_start_args_code;
+
+                i++;
+
+                continue;
+            }
+        }
+
+        i++;
+
+        /* the substituion strings */
+
+        while (i < value[2].len && value[2].data[i] != '$') {
+
+            if (value[2].data[i] == '?') {
+
+                if (i == value[2].len - 1) {
+                    /*
+                     * the last "?" drops the original arguments,
+                     * and it should not be copied to a substituion
+                     */
+                    regex->args = 0;
+                    break;
+                }
+
+                if (!regex->redirect) {
+                    break;
+                }
+            }
+
+            i++;
+        }
+
+        len = &value[2].data[i] - data;
+
+        if (len == 0) {
+            continue;
+        }
+
+        regex->size += len;
+
+        size = (len + sizeof(uintptr_t) - 1) & ~(sizeof(uintptr_t) - 1);
+
+        copy = ngx_http_rewrite_add_code(lcf->codes,
+                                   sizeof(ngx_http_rewrite_copy_code_t) + size,
+                                   &regex);
+        if (copy == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+        copy->code = ngx_http_rewrite_copy_code;
+        copy->len = len;
+
+        ngx_memcpy((u_char *) copy + sizeof(ngx_http_rewrite_copy_code_t),
+                   data, len);
+    }
+
+    n = ngx_regex_capture_count(regex->regex);
+
+    if (n < 0) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                           ngx_regex_capture_count_n " failed for "
+                           "pattern \"%V\"", &value[1]);
+        return NGX_CONF_ERROR;
+    }
+
+    if (regex->ncaptures > (ngx_uint_t) n) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                           "pattern \"%V\" has less captures "
+                           "than referrenced in substitution \"%V\"",
+                           &value[1], &value[2]);
+        return NGX_CONF_ERROR;
+    }
+
+    if (regex->ncaptures < (ngx_uint_t) n) {
+        regex->ncaptures = (ngx_uint_t) n;
+    }
+
+    if (regex->ncaptures) {
+        regex->ncaptures = (regex->ncaptures + 1) * 3;
+    }
+
+    regex_end = ngx_http_rewrite_add_code(lcf->codes,
+                                     sizeof(ngx_http_rewrite_regex_end_code_t),
+                                     &regex);
+    if (regex_end == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    regex_end->code = ngx_http_rewrite_regex_end_code;
+    regex_end->uri = regex->uri;
+    regex_end->args = regex->args;
+    regex_end->redirect = regex->redirect;
+
+    if (last) {
+        code = ngx_http_rewrite_add_code(lcf->codes, sizeof(uintptr_t),
+                                         &regex);
+        if (code == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+        *code = (uintptr_t) NULL;
+    }
+
+    regex->next = (u_char *) lcf->codes->elts + lcf->codes->nelts
+                                              - (u_char *) regex;
+
+    return NGX_CONF_OK;
+}
+
+
+static char *
+ngx_http_rewrite_return(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+    ngx_http_rewrite_loc_conf_t *lcf = conf;
+
+    ngx_str_t                       *value;
+    ngx_http_rewrite_return_code_t  *ret;
+
+    ret = ngx_http_rewrite_start_code(cf->pool, &lcf->codes,
+                                      sizeof(ngx_http_rewrite_return_code_t));
+    if (ret == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    value = cf->args->elts;
+
+    ret->code = ngx_http_rewrite_return_code;
+    ret->null = (uintptr_t) NULL;
+
+    ret->status = ngx_atoi(value[1].data, value[1].len);
+
+    if (ret->status == (uintptr_t) NGX_ERROR) {
+        return NGX_CONF_ERROR;
+    }
+
+    return NGX_CONF_OK;
+}
+
+
+static char *
+ngx_http_rewrite_if(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+    ngx_http_rewrite_loc_conf_t *lcf = conf;
+
+    void                         *mconf;
+    char                         *rv;
+    u_char                       *elts;
+    ngx_uint_t                    i;
+    ngx_conf_t                    save;
+    ngx_http_module_t            *module;
+    ngx_http_conf_ctx_t          *ctx, *pctx;
+    ngx_http_core_loc_conf_t     *clcf, *pclcf, **clcfp;
+    ngx_http_rewrite_if_code_t   *if_code;
+    ngx_http_rewrite_loc_conf_t  *nlcf;
+
+    ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
+    if (ctx == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    pctx = cf->ctx;
+    ctx->main_conf = pctx->main_conf;
+    ctx->srv_conf = pctx->srv_conf; 
+
+    ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
+    if (ctx->loc_conf == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    for (i = 0; ngx_modules[i]; i++) {
+        if (ngx_modules[i]->type != NGX_HTTP_MODULE) {
+            continue;
+        }
+
+        module = ngx_modules[i]->ctx;
+    
+        if (module->create_loc_conf) {
+
+            mconf = module->create_loc_conf(cf);
+            if (mconf == NULL) {
+                 return NGX_CONF_ERROR;
+            }
+
+            ctx->loc_conf[ngx_modules[i]->ctx_index] = mconf;
+        }
+    }
+
+    pclcf = pctx->loc_conf[ngx_http_core_module.ctx_index];
+
+    clcf = ctx->loc_conf[ngx_http_core_module.ctx_index];
+    clcf->loc_conf = ctx->loc_conf;
+    clcf->name = pclcf->name;
+    clcf->noname = 1;
+
+    if (pclcf->locations.elts == NULL) {
+        if (ngx_array_init(&pclcf->locations, cf->pool, 4, sizeof(void *))
+                                                                  == NGX_ERROR)
+        {
+            return NGX_CONF_ERROR;
+        }
+    }
+
+    clcfp = ngx_array_push(&pclcf->locations);
+    if (clcfp == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    *clcfp = clcf;
+
+
+    if (ngx_http_rewrite_if_condition(cf, lcf) != NGX_CONF_OK) {
+        return NGX_CONF_ERROR;
+    }
+
+    if_code = ngx_array_push_n(lcf->codes, sizeof(ngx_http_rewrite_if_code_t));
+    if (if_code == NULL) {
+        return NULL;
+    }
+
+    if_code->code = ngx_http_rewrite_if_code;
+
+    elts = lcf->codes->elts;
+
+
+    /* the inside directives must compile to the same code array */
+
+    nlcf = ctx->loc_conf[ngx_http_rewrite_module.ctx_index];
+    nlcf->codes = lcf->codes;
+
+
+    save = *cf;
+    cf->ctx = ctx;
+
+    if (pclcf->name.len == 0) {
+        if_code->loc_conf = NULL;
+        cf->cmd_type = NGX_HTTP_SIF_CONF;
+
+    } else {
+        if_code->loc_conf = ctx->loc_conf;
+        cf->cmd_type = NGX_HTTP_LIF_CONF;
+    }
+
+    rv = ngx_conf_parse(cf, NULL);
+
+    *cf = save;
+
+    if (rv != NGX_CONF_OK) {
+        return rv;
+    }
+
+
+    if (elts != lcf->codes->elts) {
+        if_code = (ngx_http_rewrite_if_code_t *)
+                   ((u_char *) if_code + ((u_char *) lcf->codes->elts - elts));
+    }
+
+    if_code->next = (u_char *) lcf->codes->elts + lcf->codes->nelts
+                                                - (u_char *) if_code;
+
+    return NGX_CONF_OK;
+}
+
+
+static char *
+ngx_http_rewrite_if_condition(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf)
+{
+    ngx_str_t                      *value, err;
+    ngx_uint_t                      cur, last;
+    ngx_http_rewrite_regex_code_t  *regex;
+    u_char                          errstr[NGX_MAX_CONF_ERRSTR];
+
+    value = cf->args->elts;
+    last = cf->args->nelts - 1;
+
+    if (value[1].len < 1 || value[1].data[0] != '(') {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                           "invalid condition \"%V\"", &value[1]);
+        return NGX_CONF_ERROR;
+    }
+
+    if (value[1].len == 1) {
+        cur = 2;
+
+    } else {
+        cur = 1;
+        value[1].len--;
+        value[1].data++;
+    }
+
+    if (value[last].len < 1 || value[last].data[value[last].len - 1] != ')') {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                           "invalid condition \"%V\"", &value[last]);
+        return NGX_CONF_ERROR;
+    }
+
+    if (value[last].len == 1) {
+        last--;
+
+    } else {
+        value[last].len--;
+        value[last].data[value[last].len] = '\0';
+    }
+
+    if (value[cur].len > 1 && value[cur].data[0] == '$') {
+
+        if (cur != last && cur + 2 != last) {
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                       "invalid condition \"%V\"", &value[cur]);
+            return NGX_CONF_ERROR;
+        }
+
+        if (ngx_http_rewrite_variable(cf, lcf, &value[cur])!= NGX_CONF_OK) {
+            return NGX_CONF_ERROR;
+        }
+
+        if (cur == last) {
+            return NGX_CONF_OK;
+        }
+
+        cur++;
+
+        if ((value[cur].len == 1 && value[cur].data[0] != '~')
+            || (value[cur].len == 2
+                && value[cur].data[0] != '~' && value[cur].data[1] != '*'))
+        {
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                               "unexpected \"%V\" in condition", &value[cur]);
+            return NGX_CONF_ERROR;
+        }
+
+        regex = ngx_http_rewrite_start_code(cf->pool, &lcf->codes,
+                                        sizeof(ngx_http_rewrite_regex_code_t));
+        if (regex == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+        err.len = NGX_MAX_CONF_ERRSTR;
+        err.data = errstr;
+
+        regex->regex = ngx_regex_compile(&value[last],
+                                (value[cur].len == 2) ? NGX_REGEX_CASELESS : 0,
+                                cf->pool, &err);
+
+        if (regex->regex == NULL) {
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
+            return NGX_CONF_ERROR;
+        }
+
+        regex->code = ngx_http_rewrite_regex_start_code;
+        regex->size = 0;
+        regex->ncaptures = 0;
+        regex->status = 0;
+        regex->next = sizeof(ngx_http_rewrite_regex_code_t);
+        regex->test = 1;
+        regex->uri = 0;
+        regex->args = 0;
+        regex->redirect = 0;
+        regex->name = value[last];
+
+        return NGX_CONF_OK;
+    }
+
+    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                       "invalid condition \"%V\"", &value[cur]);
+
+    return NGX_CONF_ERROR;
+}
+
+
+static char *
+ngx_http_rewrite_variable(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf,
+    ngx_str_t *value)
+{
+    ngx_http_variable_t          *var;
+    ngx_http_rewrite_code_pt     *code;
+    ngx_http_rewrite_var_code_t  *var_code;
+
+    value->len--;
+    value->data++;
+
+    if (value->len == sizeof("invalid_referer") - 1
+        && ngx_strncmp(value->data, "invalid_referer",
+                       sizeof("invalid_referer") - 1) == 0)
+    {
+        code = ngx_http_rewrite_start_code(cf->pool, &lcf->codes,
+                                           sizeof(ngx_http_rewrite_code_pt));
+        if (code == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+        *code = ngx_http_rewrite_invalid_referer_code;
+
+    } else {
+        var = ngx_http_add_variable(cf, value, 0);
+
+        if (var == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+        var_code = ngx_http_rewrite_start_code(cf->pool, &lcf->codes,
+                                           sizeof(ngx_http_rewrite_var_code_t));
+        if (var_code == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+        var_code->code = ngx_http_rewrite_var_code;
+        var_code->index = var->index;
+    }
+
+    return NGX_CONF_OK;
+}
+
+
+static char *
+ngx_http_rewrite_valid_referers(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+    ngx_http_rewrite_loc_conf_t *lcf = conf;
+
+    ngx_uint_t                   i, server_names;
+    ngx_str_t                   *value;
+    ngx_http_server_name_t      *sn;
+    ngx_http_core_srv_conf_t    *cscf;
+    ngx_http_rewrite_referer_t  *ref;
+
+    cscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_core_module);
+
+    if (lcf->referers == NULL) {
+        lcf->referers = ngx_array_create(cf->pool,
+                                    cf->args->nelts + cscf->server_names.nelts,
+                                    sizeof(ngx_http_rewrite_referer_t));
+        if (lcf->referers == NULL) {
+            return NGX_CONF_ERROR;
+        }
+    }
+
+    value = cf->args->elts;
+    server_names = 0;
+
+    for (i = 1; i < cf->args->nelts; i++) {
+        if (value[i].len == 0) {
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                               "invalid referer \"%V\"", &value[i]);
+            return NGX_CONF_ERROR;
+        }
+
+        if (ngx_strcmp(value[i].data, "none") == 0) {
+            lcf->no_referer = 1;
+            continue;
+        }
+
+        if (ngx_strcmp(value[i].data, "server_names") == 0) {
+            server_names = 1;
+            continue;
+        }
+
+        ref = ngx_array_push(lcf->referers);
+        if (ref == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+        if (value[i].data[0] != '*') {
+            ref->name = value[i];
+            ref->wildcard = 0;
+            continue;
+        }
+
+        if (value[i].data[1] != '.') {
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                               "invalid wildcard referer \"%V\"", &value[i]);
+            return NGX_CONF_ERROR;
+        }
+
+        ref->name.len = value[i].len - 1;
+        ref->name.data = value[i].data + 1;
+        ref->wildcard = 1;
+    }
+
+    if (!server_names) {
+        return NGX_CONF_OK;
+    }
+
+    sn = cscf->server_names.elts;
+    for (i = 0; i < cscf->server_names.nelts; i++) {
+        ref = ngx_array_push(lcf->referers);
+        if (ref == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+        ref->name.len = sn[i].name.len + 1;
+        ref->name.data = ngx_palloc(cf->pool, ref->name.len);
+        if (ref->name.data == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+        ngx_memcpy(ref->name.data, sn[i].name.data, sn[i].name.len);
+        ref->name.data[sn[i].name.len] = '/';
+        ref->wildcard = sn[i].wildcard;
+    }
+
+    return NGX_CONF_OK;
+}
+
+
+static char *
+ngx_http_rewrite_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+    ngx_http_rewrite_loc_conf_t *lcf = conf;
+
+    ngx_int_t                       n;
+    ngx_str_t                      *value;
+    ngx_http_variable_t            *v;
+    ngx_http_rewrite_var_code_t    *var;
+    ngx_http_rewrite_value_code_t  *val;
+
+    value = cf->args->elts;
+
+    if (value[1].data[0] != '$') {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                           "invalid variable name \"%V\"", &value[1]);
+        return NGX_CONF_ERROR;
+    }
+
+    value[1].len--;
+    value[1].data++;
+
+    v = ngx_http_add_variable(cf, &value[1], 1);
+    if (v == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    v->handler = ngx_http_rewrite_var;
+    v->data = v->index;
+
+    val = ngx_http_rewrite_start_code(cf->pool, &lcf->codes,
+                                      sizeof(ngx_http_rewrite_value_code_t));
+    if (val == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    n = ngx_atoi(value[2].data, value[2].len);
+
+    if (n == NGX_ERROR) {
+        n = 0;
+    }
+
+    val->code = ngx_http_rewrite_value_code;
+    val->value = (uintptr_t) n;
+    val->text_len = (uintptr_t) value[2].len;
+    val->text_data = (uintptr_t) value[2].data;
+
+    var = ngx_http_rewrite_start_code(cf->pool, &lcf->codes,
+                                      sizeof(ngx_http_rewrite_var_code_t));
+    if (var == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    var->code = ngx_http_rewrite_set_var_code;
+    var->index = (uintptr_t) v->index;
+
+    return NGX_CONF_OK;
+}
+
+
+static void *
+ngx_http_rewrite_start_code(ngx_pool_t *pool, ngx_array_t **codes, size_t size)
+{
+    if (*codes == NULL) {
+        *codes = ngx_array_create(pool, 256, 1);
+        if (*codes == NULL) {
+            return NULL;
+        }
+    }
+
+    return ngx_array_push_n(*codes, size);
+}
+
+
+static void *
+ngx_http_rewrite_add_code(ngx_array_t *codes, size_t size, void *code)
+{
+    u_char  *elts, **p;
+    void    *new;
+
+    elts = codes->elts;
+
+    new = ngx_array_push_n(codes, size);
+    if (new == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    if (elts != codes->elts) {
+        p = code;
+        *p += (u_char *) codes->elts - elts;
+    }
+
+    return new;
+}
rename from src/http/modules/ngx_http_ssi_filter.c
rename to src/http/modules/ngx_http_ssi_filter_module.c
--- a/src/http/modules/ngx_http_ssi_filter.c
+++ b/src/http/modules/ngx_http_ssi_filter_module.c
@@ -98,8 +98,6 @@ typedef enum {
 } ngx_http_ssi_state_e;
 
 
-static ngx_int_t ngx_http_ssi_error(ngx_http_request_t *r,
-    ngx_http_ssi_ctx_t *ctx);
 static ngx_int_t ngx_http_ssi_parse(ngx_http_request_t *r,
     ngx_http_ssi_ctx_t *ctx);
 
@@ -1147,21 +1145,25 @@ static ngx_int_t
 ngx_http_ssi_echo(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
     ngx_str_t **params)
 {
+    ngx_uint_t                  i;
     ngx_buf_t                  *b;
     ngx_str_t                  *var, *value;
     ngx_chain_t                *cl;
-    ngx_http_variable_value_t  *v;
+    ngx_http_variable_value_t  *vv;
 
     var = params[NGX_HTTP_SSI_ECHO_VAR];
-    value = NULL;
 
-    v = ngx_http_get_variable(r, var);
+    for (i = 0; i < var->len; i++) {
+        var->data[i] = ngx_toupper(var->data[i]);
+    }
 
-    if (v == NULL) {
+    vv = ngx_http_get_variable(r, var);
+
+    if (vv == NULL) {
         return NGX_HTTP_SSI_ERROR;
     }
 
-    if (v == NGX_HTTP_VARIABLE_NOT_FOUND) {
+    if (vv == NGX_HTTP_VARIABLE_NOT_FOUND) {
         value = params[NGX_HTTP_SSI_ECHO_DEFAULT];
 
         if (value == NULL) {
@@ -1172,7 +1174,7 @@ ngx_http_ssi_echo(ngx_http_request_t *r,
         }
 
     } else {
-        value = &v->text;
+        value = &vv->text;
 
         if (value->len == 0) {
             return NGX_OK;
--- a/src/http/modules/ngx_http_ssl_module.c
+++ b/src/http/modules/ngx_http_ssl_module.c
@@ -19,7 +19,7 @@ static void *ngx_http_ssl_create_main_co
 static char *ngx_http_ssl_init_main_conf(ngx_conf_t *cf, void *conf);
 static void *ngx_http_ssl_create_srv_conf(ngx_conf_t *cf);
 static char *ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf,
-                                         void *parent, void *child);
+    void *parent, void *child);
 
 
 static ngx_command_t  ngx_http_ssl_commands[] = {
@@ -87,11 +87,13 @@ ngx_module_t  ngx_http_ssl_module = {
 };
 
 
-static void *ngx_http_ssl_create_main_conf(ngx_conf_t *cf)
+static void *
+ngx_http_ssl_create_main_conf(ngx_conf_t *cf)
 {
     ngx_http_ssl_main_conf_t  *mcf;
 
-    if (!(mcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_ssl_main_conf_t)))) {
+    mcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_ssl_main_conf_t));
+    if (mcf == NULL) {
         return NGX_CONF_ERROR;
     }
 
@@ -106,7 +108,8 @@ static void *ngx_http_ssl_create_main_co
 }
 
 
-static char *ngx_http_ssl_init_main_conf(ngx_conf_t *cf, void *conf)
+static char *
+ngx_http_ssl_init_main_conf(ngx_conf_t *cf, void *conf)
 {
     ngx_http_ssl_main_conf_t *mcf = conf;
 
@@ -137,11 +140,13 @@ static char *ngx_http_ssl_init_main_conf
 }
 
 
-static void *ngx_http_ssl_create_srv_conf(ngx_conf_t *cf)
+static void *
+ngx_http_ssl_create_srv_conf(ngx_conf_t *cf)
 {
     ngx_http_ssl_srv_conf_t  *scf;
 
-    if (!(scf = ngx_pcalloc(cf->pool, sizeof(ngx_http_ssl_srv_conf_t)))) {
+    scf = ngx_pcalloc(cf->pool, sizeof(ngx_http_ssl_srv_conf_t));
+    if (scf == NULL) {
         return NGX_CONF_ERROR;
     }
 
@@ -162,8 +167,8 @@ static void *ngx_http_ssl_create_srv_con
 }
 
 
-static char *ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf,
-                                         void *parent, void *child)
+static char *
+ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child)
 {
     ngx_http_ssl_srv_conf_t *prev = parent;
     ngx_http_ssl_srv_conf_t *conf = child;
@@ -226,7 +231,8 @@ static char *ngx_http_ssl_merge_srv_conf
 
 #if 0
 
-static ngx_int_t ngx_http_ssl_init_process(ngx_cycle_t *cycle)
+static ngx_int_t
+ngx_http_ssl_init_process(ngx_cycle_t *cycle)
 {
     ngx_uint_t                   i;
     ngx_http_ssl_srv_conf_t     *sscf;
--- a/src/http/modules/ngx_http_ssl_module.h
+++ b/src/http/modules/ngx_http_ssl_module.h
@@ -32,7 +32,7 @@ typedef struct {
 ngx_int_t ngx_http_ssl_read(ngx_http_request_t *r, u_char *buf, size_t size);
 ngx_int_t ngx_http_ssl_shutdown(ngx_http_request_t *r);
 ngx_chain_t *ngx_http_ssl_write(ngx_connection_t *c, ngx_chain_t *in,
-                                off_t limit);
+    off_t limit);
 
 void ngx_http_ssl_close_connection(SSL *ssl, ngx_log_t *log);
 
deleted file mode 100644
--- a/src/http/modules/ngx_http_static_handler.c
+++ /dev/null
@@ -1,589 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-typedef struct {
-    ngx_http_cache_hash_t  *redirect_cache;
-} ngx_http_static_loc_conf_t;
-
-
-static ngx_int_t ngx_http_static_handler(ngx_http_request_t *r);
-static void *ngx_http_static_create_loc_conf(ngx_conf_t *cf);
-static char *ngx_http_static_merge_loc_conf(ngx_conf_t *cf,
-                                            void *parent, void *child);
-static ngx_int_t ngx_http_static_init(ngx_cycle_t *cycle);
-
-
-static ngx_command_t  ngx_http_static_commands[] = {
-
-#if (NGX_HTTP_CACHE)
-
-    { ngx_string("redirect_cache"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE3,
-      ngx_http_set_cache_slot,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      offsetof(ngx_http_static_loc_conf_t, redirect_cache),
-      NULL },
-
-#endif
-
-      ngx_null_command
-};
-
-
-
-ngx_http_module_t  ngx_http_static_module_ctx = {
-    NULL,                                  /* pre conf */
-
-    NULL,                                  /* create main configuration */
-    NULL,                                  /* init main configuration */
-    
-    NULL,                                  /* create server configuration */
-    NULL,                                  /* merge server configuration */
-    
-    ngx_http_static_create_loc_conf,       /* create location configuration */
-    ngx_http_static_merge_loc_conf         /* merge location configuration */
-};  
-
-
-ngx_module_t  ngx_http_static_module = {
-    NGX_MODULE,
-    &ngx_http_static_module_ctx,           /* module context */
-    ngx_http_static_commands,              /* module directives */
-    NGX_HTTP_MODULE,                       /* module type */
-    ngx_http_static_init,                  /* init module */
-    NULL                                   /* init process */
-};
-
-
-static ngx_int_t ngx_http_static_handler(ngx_http_request_t *r)
-{
-    u_char                      *last;
-    ngx_fd_t                     fd;
-    ngx_int_t                    rc;
-    ngx_uint_t                   level;
-    ngx_str_t                    name, location;
-    ngx_err_t                    err;
-    ngx_log_t                   *log;
-    ngx_buf_t                   *b;
-    ngx_chain_t                  out;
-    ngx_file_info_t              fi;
-    ngx_http_cleanup_t          *file_cleanup, *redirect_cleanup;
-    ngx_http_core_loc_conf_t    *clcf;
-    ngx_http_static_loc_conf_t  *slcf;
-#if (NGX_HTTP_CACHE)
-    uint32_t                     file_crc, redirect_crc;
-    ngx_http_cache_t            *file, *redirect;
-#endif
-
-    if (r->uri.data[r->uri.len - 1] == '/') {
-        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;
-    }
-
-    rc = ngx_http_discard_body(r);
-
-    if (rc != NGX_OK && rc != NGX_AGAIN) {
-        return rc;
-    }
-
-#if (NGX_HTTP_CACHE)
-
-    /*
-     * there is a valid cached open file, i.e by the index handler,
-     * and it should be already registered in r->cleanup
-     */
-
-    if (r->cache && !r->cache->expired) {
-        return ngx_http_send_cached(r);
-    }
-
-#endif
-
-    log = r->connection->log;
-
-    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-
-    /*
-     * make a file name, reserve 2 bytes for a trailing '/'
-     * in a possible redirect and for the last '\0'
-     */
-
-    if (clcf->alias) {
-        name.data = ngx_palloc(r->pool, clcf->root.len + r->uri.len + 2
-                                        - clcf->name.len);
-        if (name.data == NULL) {
-            return NGX_HTTP_INTERNAL_SERVER_ERROR;
-        }
-
-        last = ngx_cpymem(name.data, clcf->root.data, clcf->root.len);
-        last = ngx_cpystrn(last, r->uri.data + clcf->name.len,
-                           r->uri.len + 1 - clcf->name.len);
-
-        name.len = last - name.data;
-
-        location.data = ngx_palloc(r->pool, r->uri.len + 2);
-        if (location.data == NULL) {
-            return NGX_HTTP_INTERNAL_SERVER_ERROR;
-        }
-
-        last = ngx_cpystrn(location.data, r->uri.data, r->uri.len + 1);
-
-#if 0
-        /*
-         * aliases usually have trailling "/",
-         * set it in the start of the possible redirect
-         */
-
-        if (*location.data != '/') {
-            location.data--;
-        }
-#endif
-
-        location.len = last - location.data + 1;
-
-    } else {
-        name.data = ngx_palloc(r->pool, clcf->root.len + r->uri.len + 2);
-        if (name.data == NULL) {
-            return NGX_HTTP_INTERNAL_SERVER_ERROR;
-        }
-
-        location.data = ngx_cpymem(name.data, clcf->root.data, clcf->root.len);
-        last = ngx_cpystrn(location.data, r->uri.data, r->uri.len + 1);
-
-        name.len = last - name.data;
-        location.len = last - location.data + 1;
-    }
-
-    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
-                   "http filename: \"%s\"", name.data);
-
-
-    /* allocate cleanups */
-
-    if (!(file_cleanup = ngx_push_array(&r->cleanup))) {
-        return NGX_HTTP_INTERNAL_SERVER_ERROR;
-    }
-    file_cleanup->valid = 0;
-
-    slcf = ngx_http_get_module_loc_conf(r, ngx_http_static_module);
-    if (slcf->redirect_cache) {
-        if (!(redirect_cleanup = ngx_push_array(&r->cleanup))) {
-            return NGX_HTTP_INTERNAL_SERVER_ERROR;
-        }
-        redirect_cleanup->valid = 0;
-
-    } else {
-        redirect_cleanup = NULL;
-    }
-
-#if (NGX_HTTP_CACHE)
-
-    /* look up an open files cache */
-
-    if (clcf->open_files) {
-        file = ngx_http_cache_get(clcf->open_files, file_cleanup,
-                                  &name, &file_crc);
-
-        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
-                       "http open file cache get: %p", file);
-
-        if (file && !file->expired) {
-            r->cache = file;
-            return ngx_http_send_cached(r);
-        }
-
-    } else {
-        file = NULL;
-    }
-
-
-    /* look up an redirect cache */
-
-    if (slcf->redirect_cache) {
-        redirect = ngx_http_cache_get(slcf->redirect_cache, redirect_cleanup,
-                                      &name, &redirect_crc);
-
-        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
-                       "http redirect cache get: %p", redirect);
-
-        if (redirect && !redirect->expired) {
-
-            /*
-             * We do not copy a cached value so the cache entry is locked
-             * until the end of the request.  In a single threaded model
-             * the redirected request should complete before other event
-             * will be processed.  In a multithreaded model this locking
-             * should keep more popular redirects in cache.
-             */
-
-            if (!(r->headers_out.location =
-                   ngx_http_add_header(&r->headers_out, ngx_http_headers_out)))
-            {
-                return NGX_HTTP_INTERNAL_SERVER_ERROR;
-            }
-
-            r->headers_out.location->value = redirect->data.value;
-
-            return NGX_HTTP_MOVED_PERMANENTLY;
-        }
-
-    } else {
-        redirect = NULL;
-    }
-
-#endif
-
-    /* open file */
-
-#if (NGX_WIN9X)
-
-    /* TODO: redirect cache */
-
-    if (ngx_win32_version < NGX_WIN_NT) {
-
-        /*
-         * there is no way to open a file or a directory in Win9X with
-         * one syscall because Win9X has no FILE_FLAG_BACKUP_SEMANTICS flag
-         * so we need to check its type before the opening
-         */
-
-        if (ngx_file_info(name.data, &fi) == NGX_FILE_ERROR) {
-            err = ngx_errno;
-            ngx_log_error(NGX_LOG_ERR, log, err,
-                          ngx_file_info_n " \"%s\" failed", name.data);
-
-            if (err == NGX_ENOENT || err == NGX_ENOTDIR) {
-                return NGX_HTTP_NOT_FOUND;
-
-            } else if (err == NGX_EACCES) {
-                return NGX_HTTP_FORBIDDEN;
-
-            } else {
-                return NGX_HTTP_INTERNAL_SERVER_ERROR;
-            }
-        }
-
-        if (ngx_is_dir(&fi)) {
-            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
-                           "HTTP DIR: \"%s\"", name.data);
-
-            if (!(r->headers_out.location =
-                   ngx_http_add_header(&r->headers_out, ngx_http_headers_out)))
-            {
-                return NGX_HTTP_INTERNAL_SERVER_ERROR;
-            }
-
-            *last++ = '/';
-            *last = '\0';
-            r->headers_out.location->value.len = last - location;
-            r->headers_out.location->value.data = location;
-
-            return NGX_HTTP_MOVED_PERMANENTLY;
-        }
-    }
-
-#endif
-
-
-    fd = ngx_open_file(name.data, NGX_FILE_RDONLY, NGX_FILE_OPEN);
-
-    if (fd == NGX_INVALID_FILE) {
-        err = ngx_errno;
-
-        if (err == NGX_ENOENT || err == NGX_ENOTDIR) {
-            level = NGX_LOG_ERR;
-            rc = NGX_HTTP_NOT_FOUND;
-
-        } else if (err == NGX_EACCES) {
-            level = NGX_LOG_ERR;
-            rc = NGX_HTTP_FORBIDDEN;
-
-        } else {
-            level = NGX_LOG_CRIT;
-            rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
-        }
-
-        ngx_log_error(level, log, err,
-                      ngx_open_file_n " \"%s\" failed", name.data);
-
-        return rc;
-    }
-
-    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http static fd: %d", fd);
-
-    if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) {
-        ngx_log_error(NGX_LOG_CRIT, log, ngx_errno,
-                      ngx_fd_info_n " \"%s\" failed", name.data);
-
-        if (ngx_close_file(fd) == NGX_FILE_ERROR) {
-            ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
-                          ngx_close_file_n " \"%s\" failed", name.data);
-        }
-
-        return NGX_HTTP_INTERNAL_SERVER_ERROR;
-    }
-
-    if (ngx_is_dir(&fi)) {
-
-        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http dir");
-
-        if (ngx_close_file(fd) == NGX_FILE_ERROR) {
-            ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
-                          ngx_close_file_n " \"%s\" failed", name.data);
-        }
-
-        *last++ = '/';
-        *last = '\0';
-
-        r->headers_out.location = ngx_list_push(&r->headers_out.headers);
-        if (r->headers_out.location == NULL) {
-            return NGX_HTTP_INTERNAL_SERVER_ERROR;
-        }
-
-        r->headers_out.location->value = location;
-
-#if (NGX_HTTP_CACHE)
-
-        if (slcf->redirect_cache) {
-            if (redirect) {
-                if (location.len == redirect->data.value.len
-                    && ngx_memcmp(redirect->data.value.data, location.data,
-                                                            location.len) == 0)
-                {
-                    redirect->accessed = ngx_cached_time;
-                    redirect->updated = ngx_cached_time;
-
-                    /*
-                     * we can unlock the cache entry because
-                     * we have the local copy anyway
-                     */
-
-                    ngx_http_cache_unlock(slcf->redirect_cache, redirect, log);
-                    redirect_cleanup->valid = 0;
-
-                    return NGX_HTTP_MOVED_PERMANENTLY;
-                }
-            }
-
-            location.len++;
-            redirect = ngx_http_cache_alloc(slcf->redirect_cache, redirect,
-                                            redirect_cleanup,
-                                            &name, redirect_crc,
-                                            &location, log);
-            location.len--;
-
-            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
-                           "http redirect cache alloc: %p", redirect);
-
-            if (redirect) {
-                redirect->fd = NGX_INVALID_FILE;
-                redirect->accessed = ngx_cached_time;
-                redirect->last_modified = 0;
-                redirect->updated = ngx_cached_time;
-                redirect->memory = 1;
-                ngx_http_cache_unlock(slcf->redirect_cache, redirect, log);
-                redirect_cleanup->valid = 0;
-            }
-
-        }
-
-#endif
-
-        return NGX_HTTP_MOVED_PERMANENTLY;
-    }
-
-#if !(NGX_WIN32) /* the not regular files are probably Unix specific */
-
-    if (!ngx_is_file(&fi)) {
-        ngx_log_error(NGX_LOG_CRIT, log, ngx_errno,
-                      "\"%s\" is not a regular file", name.data);
-
-        if (ngx_close_file(fd) == NGX_FILE_ERROR) {
-            ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
-                          ngx_close_file_n " \"%s\" failed", name.data);
-        }
-
-        return NGX_HTTP_NOT_FOUND;
-    }
-
-#endif
-
-
-#if (NGX_HTTP_CACHE)
-
-    if (clcf->open_files) {
-
-#if (NGX_USE_HTTP_FILE_CACHE_UNIQ)
-
-        if (file && file->uniq == ngx_file_uniq(&fi)) {
-            if (ngx_close_file(fd) == NGX_FILE_ERROR) {
-                ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
-                              ngx_close_file_n " \"%s\" failed", name.data);
-            }
-            file->accessed = ngx_cached_time;
-            file->updated = ngx_cached_time;
-            file->expired = 0;
-            r->cache = file;
-
-            return ngx_http_send_cached(r);
-
-        } else {
-            if (file) {
-                ngx_http_cache_unlock(clcf->open_files, file, log);
-                file = NULL;
-            }
-
-            file = ngx_http_cache_alloc(clcf->open_files, file,
-                                        file_cleanup,
-                                        &name, file_crc, NULL, log);
-            if (file) {
-                file->uniq = ngx_file_uniq(&fi);
-            }
-        }
-
-#else
-        file = ngx_http_cache_alloc(clcf->open_files, file,
-                                    file_cleanup,
-                                    &name, file_crc, NULL, log);
-#endif
-
-        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
-                       "http open file cache alloc: %p", file);
-
-        if (file) {
-            file->fd = fd;
-            file->data.size = ngx_file_size(&fi);
-            file->accessed = ngx_cached_time;
-            file->last_modified = ngx_file_mtime(&fi);
-            file->updated = ngx_cached_time;
-            r->cache = file;
-        }
-
-        return ngx_http_send_cached(r);
-    }
-
-#endif
-
-    log->action = "sending response to client";
-
-    file_cleanup->data.file.fd = fd;
-    file_cleanup->data.file.name = name.data;
-    file_cleanup->valid = 1;
-    file_cleanup->cache = 0;
-
-    r->headers_out.status = NGX_HTTP_OK;
-    r->headers_out.content_length_n = ngx_file_size(&fi);
-    r->headers_out.last_modified_time = ngx_file_mtime(&fi);
-
-    if (r->headers_out.content_length_n == 0) {
-        r->header_only = 1;
-    }
-
-    if (ngx_http_set_content_type(r) != NGX_OK) {
-        return NGX_HTTP_INTERNAL_SERVER_ERROR;
-    }
-
-#if (NGX_SUPPRESS_WARN)
-    b = NULL;
-#endif
-
-    if (!r->header_only) {
-        /* we need to allocate all before the header would be sent */
-
-        if (!(b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)))) {
-            return NGX_HTTP_INTERNAL_SERVER_ERROR;
-        }
-
-        if (!(b->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t)))) {
-            return NGX_HTTP_INTERNAL_SERVER_ERROR;
-        }
-
-        r->filter_allow_ranges = 1;
-    }
-
-    rc = ngx_http_send_header(r);
-
-    if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
-        return rc;
-    }
-
-    b->in_file = 1;
-
-    if (!r->main) {
-        b->last_buf = 1;
-    }
-
-    b->file_pos = 0;
-    b->file_last = ngx_file_size(&fi);
-
-    b->file->fd = fd;
-    b->file->name = name;
-    b->file->log = log;
-
-    out.buf = b;
-    out.next = NULL;
-
-    return ngx_http_output_filter(r, &out);
-}
-
-
-static void *ngx_http_static_create_loc_conf(ngx_conf_t *cf)
-{
-    ngx_http_static_loc_conf_t  *conf;
-
-    if (!(conf = ngx_palloc(cf->pool, sizeof(ngx_http_static_loc_conf_t)))) {
-        return NGX_CONF_ERROR;
-    }
-
-    conf->redirect_cache = NULL;
-
-    return conf;
-}
-
-
-static char *ngx_http_static_merge_loc_conf(ngx_conf_t *cf,
-                                            void *parent, void *child)
-{
-    ngx_http_static_loc_conf_t  *prev = parent;
-    ngx_http_static_loc_conf_t  *conf = child;
-
-    if (conf->redirect_cache == NULL) {
-        conf->redirect_cache = prev->redirect_cache;
-    }
-
-    return NGX_CONF_OK;
-}
-
-
-static ngx_int_t ngx_http_static_init(ngx_cycle_t *cycle)
-{
-    ngx_http_handler_pt        *h;
-    ngx_http_core_main_conf_t  *cmcf;
-
-    cmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_core_module);
-    
-    h = ngx_push_array(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers);
-    if (h == NULL) {
-        return NGX_ERROR;
-    }
-
-    *h = ngx_http_static_handler;
-
-    return NGX_OK;
-}
new file mode 100644
--- /dev/null
+++ b/src/http/modules/ngx_http_static_module.c
@@ -0,0 +1,597 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+
+
+typedef struct {
+    ngx_http_cache_hash_t  *redirect_cache;
+} ngx_http_static_loc_conf_t;
+
+
+static ngx_int_t ngx_http_static_handler(ngx_http_request_t *r);
+static void *ngx_http_static_create_loc_conf(ngx_conf_t *cf);
+static char *ngx_http_static_merge_loc_conf(ngx_conf_t *cf,
+                                            void *parent, void *child);
+static ngx_int_t ngx_http_static_init(ngx_cycle_t *cycle);
+
+
+static ngx_command_t  ngx_http_static_commands[] = {
+
+#if (NGX_HTTP_CACHE)
+
+    { ngx_string("redirect_cache"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE3,
+      ngx_http_set_cache_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_static_loc_conf_t, redirect_cache),
+      NULL },
+
+#endif
+
+      ngx_null_command
+};
+
+
+
+ngx_http_module_t  ngx_http_static_module_ctx = {
+    NULL,                                  /* pre conf */
+
+    NULL,                                  /* create main configuration */
+    NULL,                                  /* init main configuration */
+    
+    NULL,                                  /* create server configuration */
+    NULL,                                  /* merge server configuration */
+    
+    ngx_http_static_create_loc_conf,       /* create location configuration */
+    ngx_http_static_merge_loc_conf         /* merge location configuration */
+};  
+
+
+ngx_module_t  ngx_http_static_module = {
+    NGX_MODULE,
+    &ngx_http_static_module_ctx,           /* module context */
+    ngx_http_static_commands,              /* module directives */
+    NGX_HTTP_MODULE,                       /* module type */
+    ngx_http_static_init,                  /* init module */
+    NULL                                   /* init process */
+};
+
+
+static ngx_int_t ngx_http_static_handler(ngx_http_request_t *r)
+{
+    u_char                      *last;
+    ngx_fd_t                     fd;
+    ngx_int_t                    rc;
+    ngx_uint_t                   level;
+    ngx_str_t                    name, location;
+    ngx_err_t                    err;
+    ngx_log_t                   *log;
+    ngx_buf_t                   *b;
+    ngx_chain_t                  out;
+    ngx_file_info_t              fi;
+    ngx_http_cleanup_t          *file_cleanup;
+#if (NGX_HTTP_CACHE)
+    ngx_http_cleanup_t          *redirect_cleanup;
+#endif
+    ngx_http_core_loc_conf_t    *clcf;
+#if (NGX_HTTP_CACHE)
+    ngx_http_static_loc_conf_t  *slcf;
+    uint32_t                     file_crc, redirect_crc;
+    ngx_http_cache_t            *file, *redirect;
+#endif
+
+    if (r->uri.data[r->uri.len - 1] == '/') {
+        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;
+    }
+
+    rc = ngx_http_discard_body(r);
+
+    if (rc != NGX_OK && rc != NGX_AGAIN) {
+        return rc;
+    }
+
+#if (NGX_HTTP_CACHE)
+
+    /*
+     * there is a valid cached open file, i.e by the index handler,
+     * and it should be already registered in r->cleanup
+     */
+
+    if (r->cache && !r->cache->expired) {
+        return ngx_http_send_cached(r);
+    }
+
+#endif
+
+    log = r->connection->log;
+
+    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+    /*
+     * make a file name, reserve 2 bytes for a trailing '/'
+     * in a possible redirect and for the last '\0'
+     */
+
+    if (clcf->alias) {
+        name.data = ngx_palloc(r->pool, clcf->root.len + r->uri.len + 2
+                                        - clcf->name.len);
+        if (name.data == NULL) {
+            return NGX_HTTP_INTERNAL_SERVER_ERROR;
+        }
+
+        last = ngx_cpymem(name.data, clcf->root.data, clcf->root.len);
+        last = ngx_cpystrn(last, r->uri.data + clcf->name.len,
+                           r->uri.len + 1 - clcf->name.len);
+
+        name.len = last - name.data;
+
+        location.data = ngx_palloc(r->pool, r->uri.len + 2);
+        if (location.data == NULL) {
+            return NGX_HTTP_INTERNAL_SERVER_ERROR;
+        }
+
+        last = ngx_cpystrn(location.data, r->uri.data, r->uri.len + 1);
+
+#if 0
+        /*
+         * aliases usually have trailling "/",
+         * set it in the start of the possible redirect
+         */
+
+        if (*location.data != '/') {
+            location.data--;
+        }
+#endif
+
+        location.len = last - location.data + 1;
+
+    } else {
+        name.data = ngx_palloc(r->pool, clcf->root.len + r->uri.len + 2);
+        if (name.data == NULL) {
+            return NGX_HTTP_INTERNAL_SERVER_ERROR;
+        }
+
+        location.data = ngx_cpymem(name.data, clcf->root.data, clcf->root.len);
+        last = ngx_cpystrn(location.data, r->uri.data, r->uri.len + 1);
+
+        name.len = last - name.data;
+        location.len = last - location.data + 1;
+    }
+
+    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
+                   "http filename: \"%s\"", name.data);
+
+
+    /* allocate cleanups */
+
+    file_cleanup = ngx_array_push(&r->cleanup);
+    if (file_cleanup == NULL) {
+        return NGX_HTTP_INTERNAL_SERVER_ERROR;
+    }
+    file_cleanup->valid = 0;
+
+#if (NGX_HTTP_CACHE)
+
+    slcf = ngx_http_get_module_loc_conf(r, ngx_http_static_module);
+    if (slcf->redirect_cache) {
+        redirect_cleanup = ngx_array_push(&r->cleanup);
+        if (redirect_cleanup == NULL) {
+            return NGX_HTTP_INTERNAL_SERVER_ERROR;
+        }
+        redirect_cleanup->valid = 0;
+
+    } else {
+        redirect_cleanup = NULL;
+    }
+
+    /* look up an open files cache */
+
+    if (clcf->open_files) {
+        file = ngx_http_cache_get(clcf->open_files, file_cleanup,
+                                  &name, &file_crc);
+
+        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
+                       "http open file cache get: %p", file);
+
+        if (file && !file->expired) {
+            r->cache = file;
+            return ngx_http_send_cached(r);
+        }
+
+    } else {
+        file = NULL;
+    }
+
+
+    /* look up an redirect cache */
+
+    if (slcf->redirect_cache) {
+        redirect = ngx_http_cache_get(slcf->redirect_cache, redirect_cleanup,
+                                      &name, &redirect_crc);
+
+        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
+                       "http redirect cache get: %p", redirect);
+
+        if (redirect && !redirect->expired) {
+
+            /*
+             * We do not copy a cached value so the cache entry is locked
+             * until the end of the request.  In a single threaded model
+             * the redirected request should complete before other event
+             * will be processed.  In a multithreaded model this locking
+             * should keep more popular redirects in cache.
+             */
+
+            r->headers_out.location = ngx_http_add_header(&r->headers_out,
+                                                          ngx_http_headers_out);
+            if (r->headers_out.location == NULL) {
+                return NGX_HTTP_INTERNAL_SERVER_ERROR;
+            }
+
+            r->headers_out.location->value = redirect->data.value;
+
+            return NGX_HTTP_MOVED_PERMANENTLY;
+        }
+
+    } else {
+        redirect = NULL;
+    }
+
+#endif
+
+    /* open file */
+
+#if (NGX_WIN9X)
+
+    /* TODO: redirect cache */
+
+    if (ngx_win32_version < NGX_WIN_NT) {
+
+        /*
+         * there is no way to open a file or a directory in Win9X with
+         * one syscall because Win9X has no FILE_FLAG_BACKUP_SEMANTICS flag
+         * so we need to check its type before the opening
+         */
+
+        if (ngx_file_info(name.data, &fi) == NGX_FILE_ERROR) {
+            err = ngx_errno;
+            ngx_log_error(NGX_LOG_ERR, log, err,
+                          ngx_file_info_n " \"%s\" failed", name.data);
+
+            if (err == NGX_ENOENT || err == NGX_ENOTDIR) {
+                return NGX_HTTP_NOT_FOUND;
+
+            } else if (err == NGX_EACCES) {
+                return NGX_HTTP_FORBIDDEN;
+
+            } else {
+                return NGX_HTTP_INTERNAL_SERVER_ERROR;
+            }
+        }
+
+        if (ngx_is_dir(&fi)) {
+            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
+                           "HTTP DIR: \"%s\"", name.data);
+
+            r->headers_out.location = ngx_http_add_header(&r->headers_out,
+                                                          ngx_http_headers_out);
+            if (r->headers_out.location == NULL) {
+                return NGX_HTTP_INTERNAL_SERVER_ERROR;
+            }
+
+            *last++ = '/';
+            *last = '\0';
+            r->headers_out.location->value.len = last - location;
+            r->headers_out.location->value.data = location;
+
+            return NGX_HTTP_MOVED_PERMANENTLY;
+        }
+    }
+
+#endif
+
+
+    fd = ngx_open_file(name.data, NGX_FILE_RDONLY, NGX_FILE_OPEN);
+
+    if (fd == NGX_INVALID_FILE) {
+        err = ngx_errno;
+
+        if (err == NGX_ENOENT || err == NGX_ENOTDIR) {
+            level = NGX_LOG_ERR;
+            rc = NGX_HTTP_NOT_FOUND;
+
+        } else if (err == NGX_EACCES) {
+            level = NGX_LOG_ERR;
+            rc = NGX_HTTP_FORBIDDEN;
+
+        } else {
+            level = NGX_LOG_CRIT;
+            rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
+        }
+
+        ngx_log_error(level, log, err,
+                      ngx_open_file_n " \"%s\" failed", name.data);
+
+        return rc;
+    }
+
+    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http static fd: %d", fd);
+
+    if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) {
+        ngx_log_error(NGX_LOG_CRIT, log, ngx_errno,
+                      ngx_fd_info_n " \"%s\" failed", name.data);
+
+        if (ngx_close_file(fd) == NGX_FILE_ERROR) {
+            ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+                          ngx_close_file_n " \"%s\" failed", name.data);
+        }
+
+        return NGX_HTTP_INTERNAL_SERVER_ERROR;
+    }
+
+    if (ngx_is_dir(&fi)) {
+
+        ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http dir");
+
+        if (ngx_close_file(fd) == NGX_FILE_ERROR) {
+            ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+                          ngx_close_file_n " \"%s\" failed", name.data);
+        }
+
+        *last++ = '/';
+        *last = '\0';
+
+        r->headers_out.location = ngx_list_push(&r->headers_out.headers);
+        if (r->headers_out.location == NULL) {
+            return NGX_HTTP_INTERNAL_SERVER_ERROR;
+        }
+
+        r->headers_out.location->value = location;
+
+#if (NGX_HTTP_CACHE)
+
+        if (slcf->redirect_cache) {
+            if (redirect) {
+                if (location.len == redirect->data.value.len
+                    && ngx_memcmp(redirect->data.value.data, location.data,
+                                                            location.len) == 0)
+                {
+                    redirect->accessed = ngx_cached_time;
+                    redirect->updated = ngx_cached_time;
+
+                    /*
+                     * we can unlock the cache entry because
+                     * we have the local copy anyway
+                     */
+
+                    ngx_http_cache_unlock(slcf->redirect_cache, redirect, log);
+                    redirect_cleanup->valid = 0;
+
+                    return NGX_HTTP_MOVED_PERMANENTLY;
+                }
+            }
+
+            location.len++;
+            redirect = ngx_http_cache_alloc(slcf->redirect_cache, redirect,
+                                            redirect_cleanup,
+                                            &name, redirect_crc,
+                                            &location, log);
+            location.len--;
+
+            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
+                           "http redirect cache alloc: %p", redirect);
+
+            if (redirect) {
+                redirect->fd = NGX_INVALID_FILE;
+                redirect->accessed = ngx_cached_time;
+                redirect->last_modified = 0;
+                redirect->updated = ngx_cached_time;
+                redirect->memory = 1;
+                ngx_http_cache_unlock(slcf->redirect_cache, redirect, log);
+                redirect_cleanup->valid = 0;
+            }
+
+        }
+
+#endif
+
+        return NGX_HTTP_MOVED_PERMANENTLY;
+    }
+
+#if !(NGX_WIN32) /* the not regular files are probably Unix specific */
+
+    if (!ngx_is_file(&fi)) {
+        ngx_log_error(NGX_LOG_CRIT, log, ngx_errno,
+                      "\"%s\" is not a regular file", name.data);
+
+        if (ngx_close_file(fd) == NGX_FILE_ERROR) {
+            ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+                          ngx_close_file_n " \"%s\" failed", name.data);
+        }
+
+        return NGX_HTTP_NOT_FOUND;
+    }
+
+#endif
+
+
+#if (NGX_HTTP_CACHE)
+
+    if (clcf->open_files) {
+
+#if (NGX_USE_HTTP_FILE_CACHE_UNIQ)
+
+        if (file && file->uniq == ngx_file_uniq(&fi)) {
+            if (ngx_close_file(fd) == NGX_FILE_ERROR) {
+                ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+                              ngx_close_file_n " \"%s\" failed", name.data);
+            }
+            file->accessed = ngx_cached_time;
+            file->updated = ngx_cached_time;
+            file->expired = 0;
+            r->cache = file;
+
+            return ngx_http_send_cached(r);
+
+        } else {
+            if (file) {
+                ngx_http_cache_unlock(clcf->open_files, file, log);
+                file = NULL;
+            }
+
+            file = ngx_http_cache_alloc(clcf->open_files, file,
+                                        file_cleanup,
+                                        &name, file_crc, NULL, log);
+            if (file) {
+                file->uniq = ngx_file_uniq(&fi);
+            }
+        }
+
+#else
+        file = ngx_http_cache_alloc(clcf->open_files, file,
+                                    file_cleanup,
+                                    &name, file_crc, NULL, log);
+#endif
+
+        ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0,
+                       "http open file cache alloc: %p", file);
+
+        if (file) {
+            file->fd = fd;
+            file->data.size = ngx_file_size(&fi);
+            file->accessed = ngx_cached_time;
+            file->last_modified = ngx_file_mtime(&fi);
+            file->updated = ngx_cached_time;
+            r->cache = file;
+        }
+
+        return ngx_http_send_cached(r);
+    }
+
+#endif
+
+    log->action = "sending response to client";
+
+    file_cleanup->data.file.fd = fd;
+    file_cleanup->data.file.name = name.data;
+    file_cleanup->valid = 1;
+    file_cleanup->cache = 0;
+
+    r->headers_out.status = NGX_HTTP_OK;
+    r->headers_out.content_length_n = ngx_file_size(&fi);
+    r->headers_out.last_modified_time = ngx_file_mtime(&fi);
+
+    if (r->headers_out.content_length_n == 0) {
+        r->header_only = 1;
+    }
+
+    if (ngx_http_set_content_type(r) != NGX_OK) {
+        return NGX_HTTP_INTERNAL_SERVER_ERROR;
+    }
+
+#if (NGX_SUPPRESS_WARN)
+    b = NULL;
+#endif
+
+    if (!r->header_only) {
+        /* we need to allocate all before the header would be sent */
+
+        b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
+        if (b == NULL) {
+            return NGX_HTTP_INTERNAL_SERVER_ERROR;
+        }
+
+        b->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t));
+        if (b->file == NULL) {
+            return NGX_HTTP_INTERNAL_SERVER_ERROR;
+        }
+
+        r->filter_allow_ranges = 1;
+    }
+
+    rc = ngx_http_send_header(r);
+
+    if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
+        return rc;
+    }
+
+    b->in_file = 1;
+
+    if (!r->main) {
+        b->last_buf = 1;
+    }
+
+    b->file_pos = 0;
+    b->file_last = ngx_file_size(&fi);
+
+    b->file->fd = fd;
+    b->file->name = name;
+    b->file->log = log;
+
+    out.buf = b;
+    out.next = NULL;
+
+    return ngx_http_output_filter(r, &out);
+}
+
+
+static void *ngx_http_static_create_loc_conf(ngx_conf_t *cf)
+{
+    ngx_http_static_loc_conf_t  *conf;
+
+    conf = ngx_palloc(cf->pool, sizeof(ngx_http_static_loc_conf_t));
+    if (conf == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    conf->redirect_cache = NULL;
+
+    return conf;
+}
+
+
+static char *ngx_http_static_merge_loc_conf(ngx_conf_t *cf,
+                                            void *parent, void *child)
+{
+    ngx_http_static_loc_conf_t  *prev = parent;
+    ngx_http_static_loc_conf_t  *conf = child;
+
+    if (conf->redirect_cache == NULL) {
+        conf->redirect_cache = prev->redirect_cache;
+    }
+
+    return NGX_CONF_OK;
+}
+
+
+static ngx_int_t ngx_http_static_init(ngx_cycle_t *cycle)
+{
+    ngx_http_handler_pt        *h;
+    ngx_http_core_main_conf_t  *cmcf;
+
+    cmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_core_module);
+    
+    h = ngx_array_push(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers);
+    if (h == NULL) {
+        return NGX_ERROR;
+    }
+
+    *h = ngx_http_static_handler;
+
+    return NGX_OK;
+}
--- a/src/http/modules/ngx_http_stub_status_module.c
+++ b/src/http/modules/ngx_http_stub_status_module.c
@@ -88,7 +88,8 @@ static ngx_int_t ngx_http_status_handler
            + 6 + 3 * NGX_ATOMIC_T_LEN
            + sizeof("Reading:  Writing:  Waiting:  \n") + 3 * NGX_ATOMIC_T_LEN;
 
-    if (!(b = ngx_create_temp_buf(r->pool, size))) {
+    b = ngx_create_temp_buf(r->pool, size);
+    if (b == NULL) {
         return NGX_HTTP_INTERNAL_SERVER_ERROR;
     }
 
rename from src/http/modules/ngx_http_userid_filter.c
rename to src/http/modules/ngx_http_userid_filter_module.c
--- a/src/http/modules/ngx_http_userid_filter.c
+++ b/src/http/modules/ngx_http_userid_filter_module.c
@@ -618,7 +618,7 @@ ngx_http_userid_domain(ngx_conf_t *cf, v
     }
 
     p = ngx_cpymem(new, "; domain=", sizeof("; domain=") - 1);
-    p = ngx_cpymem(p, domain->data, domain->len);
+    ngx_memcpy(p, domain->data, domain->len);
 
     domain->len += sizeof("; domain=") - 1;
     domain->data = new;
@@ -640,7 +640,7 @@ ngx_http_userid_path(ngx_conf_t *cf, voi
     }
 
     p = ngx_cpymem(new, "; path=", sizeof("; path=") - 1);
-    p = ngx_cpymem(p, path->data, path->len);
+    ngx_memcpy(p, path->data, path->len);
 
     path->len += sizeof("; path=") - 1;
     path->data = new;
--- a/src/http/modules/proxy/ngx_http_proxy_handler.c
+++ b/src/http/modules/proxy/ngx_http_proxy_handler.c
@@ -11,7 +11,9 @@
 
 
 static ngx_int_t ngx_http_proxy_handler(ngx_http_request_t *r);
+#if 0
 static ngx_int_t ngx_http_proxy_cache_get(ngx_http_proxy_ctx_t *p);
+#endif
 
 static size_t ngx_http_proxy_log_proxy_state_getlen(ngx_http_request_t *r,
                                                     uintptr_t data);
@@ -33,8 +35,6 @@ static char *ngx_http_proxy_merge_loc_co
 
 static char *ngx_http_proxy_set_pass(ngx_conf_t *cf, ngx_command_t *cmd,
                                      void *conf);
-static char *ngx_http_proxy_parse_upstream(ngx_str_t *url,
-                                           ngx_http_proxy_upstream_conf_t *u);
 
 static char *ngx_http_proxy_set_x_var(ngx_conf_t *cf, ngx_command_t *cmd,
                                       void *conf);
@@ -362,13 +362,20 @@ static ngx_str_t cache_reasons[] = {
 };
 
 
+static ngx_str_t ngx_http_proxy_uri = ngx_string("/");
+
+
 static ngx_int_t ngx_http_proxy_handler(ngx_http_request_t *r)
 {
     ngx_http_proxy_ctx_t  *p;
 
-    ngx_http_create_ctx(r, p, ngx_http_proxy_module,
-                        sizeof(ngx_http_proxy_ctx_t),
-                        NGX_HTTP_INTERNAL_SERVER_ERROR);
+    p = ngx_pcalloc(r->pool, sizeof(ngx_http_proxy_ctx_t));
+    if (p == NULL) {
+        return NGX_HTTP_INTERNAL_SERVER_ERROR;
+    }
+
+    ngx_http_set_ctx(r, p, ngx_http_proxy_module);
+
 
     p->lcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
     p->request = r;
@@ -382,7 +389,8 @@ static ngx_int_t ngx_http_proxy_handler(
         return NGX_HTTP_INTERNAL_SERVER_ERROR;
     }
 
-    if (!(p->state = ngx_array_push(&p->states))) {
+    p->state = ngx_array_push(&p->states);
+    if (p->state == NULL) {
         return NGX_HTTP_INTERNAL_SERVER_ERROR;
     }
 
@@ -439,7 +447,8 @@ static ngx_int_t ngx_http_proxy_cache_ge
     u = p->lcf->upstream;
 
     ctx.key.len = u->url.len + r->uri.len - u->location->len + r->args.len;
-    if (!(ctx.key.data = ngx_palloc(r->pool, ctx.key.len))) {
+    ctx.key.data = ngx_palloc(r->pool, ctx.key.len);
+    if (ctx.key.data == NULL) {
         return NGX_HTTP_INTERNAL_SERVER_ERROR;
     }
 
@@ -1072,7 +1081,8 @@ static void *ngx_http_proxy_create_loc_c
 {
     ngx_http_proxy_loc_conf_t  *conf;
 
-    if (!(conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_proxy_loc_conf_t)))) {
+    conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_proxy_loc_conf_t));
+    if (conf == NULL) {
         return NGX_CONF_ERROR;
     }
 
@@ -1332,7 +1342,8 @@ static char *ngx_http_proxy_set_pass(ngx
         unix_upstream.url.data = url->data + 7;
         unix_upstream.uri_part = 1;
 
-        if (!(lcf->peers = ngx_unix_upstream_parse(cf, &unix_upstream))) {
+        lcf->peers = ngx_unix_upstream_parse(cf, &unix_upstream);
+        if (lcf->peers == NULL) {
             return NGX_CONF_ERROR;
         }
 
@@ -1359,7 +1370,8 @@ static char *ngx_http_proxy_set_pass(ngx
         inet_upstream.default_port_value = 80;
         inet_upstream.uri_part = 1;
 
-        if (!(lcf->peers = ngx_inet_upstream_parse(cf, &inet_upstream))) {
+        lcf->peers = ngx_inet_upstream_parse(cf, &inet_upstream);
+        if (lcf->peers == NULL) {
             return NGX_CONF_ERROR;
         }
 
@@ -1372,8 +1384,13 @@ static char *ngx_http_proxy_set_pass(ngx
 
     clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
 
+    clcf->handler = ngx_http_proxy_handler;
+
+#if (NGX_PCRE)
+    lcf->upstream->location = clcf->regex ? &ngx_http_proxy_uri : &clcf->name;
+#else
     lcf->upstream->location = &clcf->name;
-    clcf->handler = ngx_http_proxy_handler;
+#endif
 
     if (clcf->name.data[clcf->name.len - 1] == '/') {
         clcf->auto_redirect = 1;
@@ -1409,7 +1426,8 @@ static char *ngx_http_proxy_set_x_var(ng
     for (i = 0; i < cmcf->variables.nelts; i++) {
         if (ngx_strcasecmp(var[i].name.data, value[1].data) == 0) {
 
-            if (!(index = ngx_array_push(lcf->x_vars))) {
+            index = ngx_array_push(lcf->x_vars);
+            if (index == NULL) {
                 return NGX_CONF_ERROR;
             }
 
--- a/src/http/modules/proxy/ngx_http_proxy_header.c
+++ b/src/http/modules/proxy/ngx_http_proxy_header.c
@@ -87,7 +87,8 @@ int ngx_http_proxy_copy_header(ngx_http_
 
         /* copy some header pointers and set up r->headers_out */
 
-        if (!(ho = ngx_list_push(&r->headers_out.headers))) {
+        ho = ngx_list_push(&r->headers_out.headers);
+        if (ho == NULL) {
             return NGX_ERROR;
         }
 
@@ -162,7 +163,8 @@ static int ngx_http_proxy_rewrite_locati
     r = p->request;
     uc = p->lcf->upstream;
 
-    if (!(location = ngx_list_push(&r->headers_out.headers))) {
+    location = ngx_list_push(&r->headers_out.headers);
+    if (location == NULL) {
         return NGX_ERROR;
     }
 
@@ -189,7 +191,8 @@ static int ngx_http_proxy_rewrite_locati
 
     location->value.len = uc->location->len
                                           + (loc->value.len - uc->url.len) + 1;
-    if (!(location->value.data = ngx_palloc(r->pool, location->value.len))) {
+    location->value.data = ngx_palloc(r->pool, location->value.len);
+    if (location->value.data == NULL) {
         return NGX_ERROR;
     }
 
--- a/src/http/modules/proxy/ngx_http_proxy_upstream.c
+++ b/src/http/modules/proxy/ngx_http_proxy_upstream.c
@@ -58,7 +58,8 @@ int ngx_http_proxy_request_upstream(ngx_
 
     r = p->request;
 
-    if (!(u = ngx_pcalloc(r->pool, sizeof(ngx_http_proxy_upstream_t)))) {
+    u = ngx_pcalloc(r->pool, sizeof(ngx_http_proxy_upstream_t));
+    if (u == NULL) {
         return NGX_HTTP_INTERNAL_SERVER_ERROR;
     }
 
@@ -85,7 +86,7 @@ int ngx_http_proxy_request_upstream(ngx_
 
 static ngx_chain_t *ngx_http_proxy_create_request(ngx_http_proxy_ctx_t *p)
 {
-    size_t                           len;
+    size_t                           len, loc_len;
     ngx_uint_t                       i, escape, *index;
     ngx_buf_t                       *b;
     ngx_chain_t                     *chain;
@@ -94,6 +95,7 @@ static ngx_chain_t *ngx_http_proxy_creat
     ngx_http_request_t              *r;
     ngx_http_variable_t             *var;
     ngx_http_variable_value_t       *value;
+    ngx_http_core_loc_conf_t        *clcf;
     ngx_http_core_main_conf_t       *cmcf;
     ngx_http_proxy_upstream_conf_t  *uc;
 
@@ -112,16 +114,23 @@ static ngx_chain_t *ngx_http_proxy_creat
         len = r->method_name.len;
     }
 
+    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+#if (NGX_PCRE)
+    loc_len = (clcf->regex) ? 1 : clcf->name.len;
+#else
+    loc_len = clcf->name.len;
+#endif
+
     if (r->quoted_uri) {
-        escape = 2 * ngx_escape_uri(NULL, r->uri.data + uc->location->len,
-                                    r->uri.len - uc->location->len,
-                                    NGX_ESCAPE_URI);
+        escape = 2 * ngx_escape_uri(NULL, r->uri.data + loc_len,
+                                    r->uri.len - loc_len, NGX_ESCAPE_URI);
     } else {
         escape = 0;
     }
 
     len += uc->uri.len
-        + r->uri.len - uc->location->len + escape
+        + r->uri.len - loc_len + escape
         + sizeof("?") - 1 + r->args.len
         + sizeof(http_version) - 1
         + sizeof(connection_close_header) - 1
@@ -190,7 +199,8 @@ static ngx_chain_t *ngx_http_proxy_creat
 
         for (i = 0; i < p->lcf->x_vars->nelts; i++) {
 
-            if (!(value = ngx_http_get_indexed_variable(r, index[i]))) {
+            value = ngx_http_get_indexed_variable(r, index[i]);
+            if (value == NULL) {
                 continue;
             }
 
@@ -233,11 +243,13 @@ static ngx_chain_t *ngx_http_proxy_creat
     len++;
 #endif
 
-    if (!(b = ngx_create_temp_buf(r->pool, len))) {
+    b = ngx_create_temp_buf(r->pool, len);
+    if (b == NULL) {
         return NULL;
     }
 
-    if (!(chain = ngx_alloc_chain_link(r->pool))) {
+    chain = ngx_alloc_chain_link(r->pool);
+    if (chain == NULL) {
         return NULL;
     }
 
@@ -258,14 +270,13 @@ static ngx_chain_t *ngx_http_proxy_creat
     b->last = ngx_cpymem(b->last, uc->uri.data, uc->uri.len);
 
     if (escape) {
-        ngx_escape_uri(b->last, r->uri.data + uc->location->len,
-                       r->uri.len - uc->location->len, NGX_ESCAPE_URI);
-        b->last += r->uri.len - uc->location->len + escape;
+        ngx_escape_uri(b->last, r->uri.data + loc_len,
+                       r->uri.len - loc_len, NGX_ESCAPE_URI);
+        b->last += r->uri.len - loc_len + escape;
 
     } else {
-        b->last = ngx_cpymem(b->last,
-                             r->uri.data + uc->location->len,
-                             r->uri.len - uc->location->len);
+        b->last = ngx_cpymem(b->last, r->uri.data + loc_len,
+                             r->uri.len - loc_len);
     }
 
     if (r->args.len > 0) {
@@ -379,7 +390,8 @@ static ngx_chain_t *ngx_http_proxy_creat
     if (p->lcf->x_vars) {
         for (i = 0; i < p->lcf->x_vars->nelts; i++) {
 
-            if (!(value = ngx_http_get_indexed_variable(r, index[i]))) {
+            value = ngx_http_get_indexed_variable(r, index[i]);
+            if (value == NULL) {
                 continue;
             }
 
@@ -506,7 +518,8 @@ static void ngx_http_proxy_init_upstream
     }
 
 
-    if (!(cl = ngx_http_proxy_create_request(p))) {
+    cl = ngx_http_proxy_create_request(p);
+    if (cl == NULL) {
         ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
         return;
     }
@@ -517,7 +530,8 @@ static void ngx_http_proxy_init_upstream
 
     r->request_body->bufs = cl;
 
-    if (!(ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_proxy_log_ctx_t)))) {
+    ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_proxy_log_ctx_t));
+    if (ctx == NULL) {
         ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
         return;
     }
@@ -531,7 +545,8 @@ static void ngx_http_proxy_init_upstream
     r->connection->log->handler = ngx_http_proxy_log_error;
     p->action = "connecting to upstream";
 
-    if (!(output = ngx_pcalloc(r->pool, sizeof(ngx_output_chain_ctx_t)))) {
+    output = ngx_pcalloc(r->pool, sizeof(ngx_output_chain_ctx_t));
+    if (output == NULL) {
         ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
         return;
     }
@@ -544,7 +559,8 @@ static void ngx_http_proxy_init_upstream
     output->tag = (ngx_buf_tag_t) &ngx_http_proxy_module;
     output->output_filter = ngx_chain_writer;
 
-    if (!(writer = ngx_palloc(r->pool, sizeof(ngx_chain_writer_ctx_t)))) {
+    writer = ngx_palloc(r->pool, sizeof(ngx_chain_writer_ctx_t));
+    if (writer == NULL) {
         ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
         return;
     }
@@ -603,7 +619,8 @@ static void ngx_http_proxy_reinit_upstre
 
     state = p->state->cache_state;
 
-    if (!(p->state = ngx_push_array(&p->states))) {
+    p->state = ngx_array_push(&p->states);
+    if (p->state == NULL) {
         ngx_http_proxy_finalize_request(p, NGX_HTTP_INTERNAL_SERVER_ERROR);
         return;
     }
@@ -775,7 +792,8 @@ static void ngx_http_proxy_connect(ngx_h
     if (r->request_body->buf) {
         if (r->request_body->temp_file) {
 
-            if (!(output->free = ngx_alloc_chain_link(r->pool))) {
+            output->free = ngx_alloc_chain_link(r->pool);
+            if (output->free == NULL) {
                 ngx_http_proxy_finalize_request(p,
                                                 NGX_HTTP_INTERNAL_SERVER_ERROR);
                 return;
@@ -1005,7 +1023,7 @@ static void ngx_http_proxy_process_upstr
     rc = ngx_http_proxy_parse_status_line(p);
 
     if (rc == NGX_AGAIN) {
-        if (p->header_in->pos == p->header_in->last) {
+        if (p->header_in->pos == p->header_in->end) {
             ngx_log_error(NGX_LOG_ERR, rev->log, 0,
                           "upstream sent too long status line");
             ngx_http_proxy_next_upstream(p, NGX_HTTP_PROXY_FT_INVALID_HEADER);
@@ -1158,7 +1176,8 @@ static void ngx_http_proxy_process_upstr
 
             /* a header line has been parsed successfully */
 
-            if (!(h = ngx_list_push(&p->upstream->headers_in.headers))) {
+            h = ngx_list_push(&p->upstream->headers_in.headers);
+            if (h == NULL) {
                 ngx_http_proxy_finalize_request(p,
                                                 NGX_HTTP_INTERNAL_SERVER_ERROR);
                 return;
@@ -1315,6 +1334,11 @@ static void ngx_http_proxy_send_response
 
     rc = ngx_http_send_header(r);
 
+    if (rc == NGX_ERROR || rc > NGX_OK) {
+        ngx_http_proxy_finalize_request(p, rc);
+        return;
+    }
+
     p->header_sent = 1;
 
     if (p->cache && p->cache->ctx.file.fd != NGX_INVALID_FILE) {
@@ -1361,7 +1385,8 @@ static void ngx_http_proxy_send_response
 
     ep->cachable = p->cachable;
 
-    if (!(ep->temp_file = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t)))) {
+    ep->temp_file = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t));
+    if (ep->temp_file == NULL) {
         ngx_http_proxy_finalize_request(p, 0);
         return;
     }
@@ -1381,7 +1406,8 @@ static void ngx_http_proxy_send_response
     ep->max_temp_file_size = p->lcf->max_temp_file_size;
     ep->temp_file_write_size = p->lcf->temp_file_write_size;
 
-    if (!(ep->preread_bufs = ngx_alloc_chain_link(r->pool))) {
+    ep->preread_bufs = ngx_alloc_chain_link(r->pool);
+    if (ep->preread_bufs == NULL) {
         ngx_http_proxy_finalize_request(p, 0);
         return;
     }
@@ -1467,7 +1493,6 @@ static void ngx_http_proxy_process_body(
         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ev->log, 0,
                        "http proxy process upstream");
         p = c->data;
-        r = p->request;
         p->action = "reading upstream body";
     }
 
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -92,7 +92,8 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma
 
     /* the main http context */
 
-    if (!(ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)))) {
+    ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
+    if (ctx == NULL) {
         return NGX_CONF_ERROR;
     }
 
@@ -162,19 +163,22 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma
         }
 
         if (module->create_main_conf) {
-            if (!(ctx->main_conf[mi] = module->create_main_conf(cf))) {
+            ctx->main_conf[mi] = module->create_main_conf(cf);
+            if (ctx->main_conf[mi] == NULL) {
                 return NGX_CONF_ERROR;
             }
         }
 
         if (module->create_srv_conf) {
-            if (!(ctx->srv_conf[mi] = module->create_srv_conf(cf))) {
+            ctx->srv_conf[mi] = module->create_srv_conf(cf);
+            if (ctx->srv_conf[mi] == NULL) {
                 return NGX_CONF_ERROR;
             }
         }
 
         if (module->create_loc_conf) {
-            if (!(ctx->loc_conf[mi] = module->create_loc_conf(cf))) {
+            ctx->loc_conf[mi] = module->create_loc_conf(cf);
+            if (ctx->loc_conf[mi] == NULL) {
                 return NGX_CONF_ERROR;
             }
         }
@@ -261,13 +265,14 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma
 
 
     /* we needed http{}'s cf->ctx while the merging configuration */
+
     *cf = pcf;
 
 
     /* init lists of the handlers */
 
     if (ngx_array_init(&cmcf->phases[NGX_HTTP_REWRITE_PHASE].handlers,
-                       cf->pool, 1, sizeof(ngx_http_handler_pt)) == NGX_ERROR)
+                       cf->pool, 1, sizeof(ngx_http_handler_pt)) != NGX_OK)
     {
         return NGX_CONF_ERROR;
     }
@@ -278,14 +283,14 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma
     /* the special find config phase for a single handler */
 
     if (ngx_array_init(&cmcf->phases[NGX_HTTP_FIND_CONFIG_PHASE].handlers,
-                       cf->pool, 1, sizeof(ngx_http_handler_pt)) == NGX_ERROR)
+                       cf->pool, 1, sizeof(ngx_http_handler_pt)) != NGX_OK)
     {
         return NGX_CONF_ERROR;
     }
 
     cmcf->phases[NGX_HTTP_FIND_CONFIG_PHASE].type = NGX_OK;
 
-    h = ngx_push_array(&cmcf->phases[NGX_HTTP_FIND_CONFIG_PHASE].handlers);
+    h = ngx_array_push(&cmcf->phases[NGX_HTTP_FIND_CONFIG_PHASE].handlers);
     if (h == NULL) {
         return NGX_CONF_ERROR;
     }
@@ -294,7 +299,7 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma
 
 
     if (ngx_array_init(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers,
-                       cf->pool, 1, sizeof(ngx_http_handler_pt)) == NGX_ERROR)
+                       cf->pool, 1, sizeof(ngx_http_handler_pt)) != NGX_OK)
     {
         return NGX_CONF_ERROR;
     }
@@ -303,7 +308,7 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma
 
 
     if (ngx_array_init(&cmcf->phases[NGX_HTTP_CONTENT_PHASE].handlers,
-                       cf->pool, 4, sizeof(ngx_http_handler_pt)) == NGX_ERROR)
+                       cf->pool, 4, sizeof(ngx_http_handler_pt)) != NGX_OK)
     {
         return NGX_CONF_ERROR;
     }
@@ -317,7 +322,7 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma
      */
 
     if (ngx_array_init(&in_ports, cf->pool, 10, sizeof(ngx_http_in_port_t))
-                                                                  == NGX_ERROR)
+        != NGX_OK)
     {
         return NGX_CONF_ERROR;
     }
@@ -354,7 +359,7 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma
                             /* the address is already in the address list */
 
                             if (ngx_http_add_names(cf, &in_addr[a], cscfp[s])
-                                                                  == NGX_ERROR)
+                                != NGX_OK)
                             {
                                 return NGX_CONF_ERROR;
                             }
@@ -386,7 +391,8 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma
 
                             /* the INADDR_ANY is always the last address */
 
-                            if (!(inaddr = ngx_array_push(&in_port[p].addrs))) {
+                            inaddr = ngx_array_push(&in_port[p].addrs);
+                            if (inaddr == NULL) {
                                 return NGX_CONF_ERROR;
                             }
 
@@ -407,7 +413,7 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma
                             in_addr[a].core_srv_conf = cscfp[s];
 
                             if (ngx_http_add_names(cf, &in_addr[a], cscfp[s])
-                                                                  == NGX_ERROR)
+                                != NGX_OK)
                             {
                                 return NGX_CONF_ERROR;
                             }
@@ -426,7 +432,7 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma
                          */
 
                         if (ngx_http_add_address(cf, &in_port[p], &lscf[l],
-                                                        cscfp[s]) == NGX_ERROR)
+                                                 cscfp[s]) != NGX_OK)
                         {
                             return NGX_CONF_ERROR;
                         }
@@ -438,14 +444,16 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma
 
                 /* add the port to the in_port list */
 
-                if (!(in_port = ngx_array_push(&in_ports))) {
+                in_port = ngx_array_push(&in_ports);
+                if (in_port == NULL) {
                     return NGX_CONF_ERROR;
                 }
 
                 in_port->port = lscf[l].port;
                 in_port->addrs.elts = NULL;
 
-                if (!(in_port->port_text.data = ngx_palloc(cf->pool, 7))) {
+                in_port->port_text.data = ngx_palloc(cf->pool, 7);
+                if (in_port->port_text.data == NULL) {
                     return NGX_CONF_ERROR;
                 }
 
@@ -454,7 +462,7 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma
                                          - in_port->port_text.data;
 
                 if (ngx_http_add_address(cf, in_port, &lscf[l], cscfp[s])
-                                                                  == NGX_ERROR)
+                    != NGX_OK)
                 {
                     return NGX_CONF_ERROR;
                 }
@@ -484,7 +492,7 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma
             for (n = 0; n < in_addr[a].names.nelts; n++) {
                 if (in_addr[a].core_srv_conf != name[n].core_srv_conf
                     || name[n].core_srv_conf->restrict_host_names
-                                                 != NGX_HTTP_RESTRICT_HOST_OFF)
+                       != NGX_HTTP_RESTRICT_HOST_OFF)
                 {
                     virtual_names = 1;
                     break;
@@ -496,7 +504,7 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma
                 for (n = 0; n < in_addr[a].wildcards.nelts; n++) {
                     if (in_addr[a].core_srv_conf != name[n].core_srv_conf
                         || name[n].core_srv_conf->restrict_host_names
-                                                 != NGX_HTTP_RESTRICT_HOST_OFF)
+                           != NGX_HTTP_RESTRICT_HOST_OFF)
                     {
                         virtual_names = 1;
                         break;
@@ -532,7 +540,7 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma
 
                 for (n = 0; n < cmcf->server_names_hash; n++) {
                     if (ngx_array_init(&in_addr[a].hash[n], cf->pool, 5,
-                                  sizeof(ngx_http_server_name_t)) == NGX_ERROR)
+                                     sizeof(ngx_http_server_name_t)) != NGX_OK)
                     {
                         return NGX_CONF_ERROR;
                     }
@@ -544,7 +552,8 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma
                                                    name[s].name.len,
                                                    cmcf->server_names_hash);
 
-                    if (!(s_name = ngx_array_push(&in_addr[a].hash[key]))) {
+                    s_name = ngx_array_push(&in_addr[a].hash[key]);
+                    if (s_name == NULL) {
                         return NGX_CONF_ERROR;
                     }
 
@@ -575,13 +584,7 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma
             }
 
             ls->backlog = -1;
-#if 0
-#if 0
-            ls->nonblocking = 1;
-#else
-            ls->nonblocking = 0;
-#endif
-#endif
+
             ls->addr_ntop = 1;
 
             ls->handler = ngx_http_init_connection;
@@ -612,19 +615,21 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma
                      * the separate ngx_http_in_port_t for the all bindings
                      */
 
-                    ngx_test_null(inport,
-                                  ngx_palloc(cf->pool,
-                                             sizeof(ngx_http_in_port_t)),
-                                  NGX_CONF_ERROR);
+                    inport = ngx_palloc(cf->pool, sizeof(ngx_http_in_port_t));
+                    if (inport == NULL) {
+                        return NGX_CONF_ERROR;
+                    }
 
                     inport->port = in_port[p].port;
                     inport->port_text = in_port[p].port_text;
 
                     /* init list of the addresses ... */
 
-                    ngx_init_array(inport->addrs, cf->pool, 1,
-                                   sizeof(ngx_http_in_addr_t),
-                                   NGX_CONF_ERROR);
+                    if (ngx_array_init(&inport->addrs, cf->pool, 1,
+                                       sizeof(ngx_http_in_addr_t)) != NGX_OK)
+                    {
+                        return NGX_CONF_ERROR;
+                    }
 
                     /* ... and set up it with the first address */
 
@@ -636,7 +641,7 @@ ngx_http_block(ngx_conf_t *cf, ngx_comma
                     /* prepare for the next cycle */
 
                     in_port[p].addrs.elts = (char *) in_port[p].addrs.elts
-                                                       + in_port[p].addrs.size;
+                                                      + in_port[p].addrs.size;
                     in_port[p].addrs.nelts--;
 
                     in_addr = (ngx_http_in_addr_t *) in_port[p].addrs.elts;
@@ -705,13 +710,14 @@ ngx_http_add_address(ngx_conf_t *cf, ngx
 
     if (in_port->addrs.elts == NULL) {
         if (ngx_array_init(&in_port->addrs, cf->pool, 10,
-                                      sizeof(ngx_http_in_addr_t)) == NGX_ERROR)
+                           sizeof(ngx_http_in_addr_t)) != NGX_OK)
         {
             return NGX_ERROR;
         }
     }
 
-    if (!(in_addr = ngx_array_push(&in_port->addrs))) {
+    in_addr = ngx_array_push(&in_port->addrs);
+    if (in_addr == NULL) {
         return NGX_ERROR;
     }
 
@@ -750,7 +756,7 @@ ngx_http_add_names(ngx_conf_t *cf, ngx_h
 
     if (in_addr->names.elts == NULL) {
         if (ngx_array_init(&in_addr->names, cf->pool, 10,
-                                  sizeof(ngx_http_server_name_t)) == NGX_ERROR)
+                           sizeof(ngx_http_server_name_t)) != NGX_OK)
         {
             return NGX_ERROR;
         }
@@ -758,7 +764,7 @@ ngx_http_add_names(ngx_conf_t *cf, ngx_h
 
     if (in_addr->wildcards.elts == NULL) {
         if (ngx_array_init(&in_addr->wildcards, cf->pool, 10,
-                                  sizeof(ngx_http_server_name_t)) == NGX_ERROR)
+                           sizeof(ngx_http_server_name_t)) != NGX_OK)
         {
             return NGX_ERROR;
         }
@@ -785,7 +791,8 @@ ngx_http_add_names(ngx_conf_t *cf, ngx_h
             array = &in_addr->names;
         }
 
-        if (!(name = ngx_array_push(array))) {
+        name = ngx_array_push(array);
+        if (name == NULL) {
             return NGX_ERROR;
         }
 
--- a/src/http/ngx_http.h
+++ b/src/http/ngx_http.h
@@ -16,6 +16,8 @@ typedef struct ngx_http_request_s  ngx_h
 typedef struct ngx_http_log_ctx_s  ngx_http_log_ctx_t;
 typedef struct ngx_http_cleanup_s  ngx_http_cleanup_t;
 typedef struct ngx_http_in_addr_s  ngx_http_in_addr_t;
+typedef struct ngx_http_variable_value_s  ngx_http_variable_value_t;
+
 
 #if (NGX_HTTP_CACHE)
 #include <ngx_http_cache.h>
@@ -27,7 +29,7 @@ typedef struct ngx_http_in_addr_s  ngx_h
 #include <ngx_http_request.h>
 #include <ngx_http_config.h>
 #include <ngx_http_busy_lock.h>
-#include <ngx_http_log_handler.h>
+#include <ngx_http_log_module.h>
 #include <ngx_http_core_module.h>
 #include <ngx_http_variables.h>
 
@@ -46,16 +48,7 @@ struct ngx_http_log_ctx_s {
 #define ngx_http_get_module_err_ctx(r, module)                                \
     ((r)->err_ctx ? (r)->err_ctx[module.ctx_index] : (r)->ctx[module.ctx_index])
 
-/* STUB */
-#define ngx_http_create_ctx(r, cx, module, size, error)                       \
-            do {                                                              \
-                ngx_test_null(cx, ngx_pcalloc(r->pool, size), error);         \
-                r->ctx[module.ctx_index] = cx;                                \
-            } while (0)
-/**/
-
 #define ngx_http_set_ctx(r, c, module)         r->ctx[module.ctx_index] = c;
-
 #define ngx_http_delete_ctx(r, module)         r->ctx[module.ctx_index] = NULL;
 
 
--- a/src/http/ngx_http_busy_lock.c
+++ b/src/http/ngx_http_busy_lock.c
@@ -205,13 +205,15 @@ char *ngx_http_set_busy_lock_slot(ngx_co
     }
 
     /* ngx_calloc_shared() */
-    if (!(bl = ngx_pcalloc(cf->pool, sizeof(ngx_http_busy_lock_t)))) {
+    bl = ngx_pcalloc(cf->pool, sizeof(ngx_http_busy_lock_t));
+    if (bl == NULL) {
         return NGX_CONF_ERROR;
     }
     *blp = bl;
 
     /* ngx_calloc_shared() */
-    if (!(bl->mutex = ngx_pcalloc(cf->pool, sizeof(ngx_event_mutex_t)))) {
+    bl->mutex = ngx_pcalloc(cf->pool, sizeof(ngx_event_mutex_t));
+    if (bl->mutex == NULL) {
         return NGX_CONF_ERROR;
     }
 
--- a/src/http/ngx_http_config.h
+++ b/src/http/ngx_http_config.h
@@ -59,15 +59,15 @@ typedef struct {
  */
 
 #define ngx_http_conf_get_module_main_conf(cf, module)                        \
-            ((ngx_http_conf_ctx_t *) cf->ctx)->main_conf[module.ctx_index]
+    ((ngx_http_conf_ctx_t *) cf->ctx)->main_conf[module.ctx_index]
 #define ngx_http_conf_get_module_srv_conf(cf, module)                         \
-            ((ngx_http_conf_ctx_t *) cf->ctx)->srv_conf[module.ctx_index]
+    ((ngx_http_conf_ctx_t *) cf->ctx)->srv_conf[module.ctx_index]
 #define ngx_http_conf_get_module_loc_conf(cf, module)                         \
-            ((ngx_http_conf_ctx_t *) cf->ctx)->loc_conf[module.ctx_index]
+    ((ngx_http_conf_ctx_t *) cf->ctx)->loc_conf[module.ctx_index]
 
 #define ngx_http_cycle_get_module_main_conf(cycle, module)                    \
-       ((ngx_http_conf_ctx_t *)                                               \
-           cycle->conf_ctx[ngx_http_module.index])->main_conf[module.ctx_index]
+    ((ngx_http_conf_ctx_t *)                                                  \
+         cycle->conf_ctx[ngx_http_module.index])->main_conf[module.ctx_index]
 
 
 
deleted file mode 100644
--- a/src/http/ngx_http_copy_filter.c
+++ /dev/null
@@ -1,132 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-typedef struct {
-    ngx_bufs_t  bufs;
-} ngx_http_copy_filter_conf_t;
-
-
-static void *ngx_http_copy_filter_create_conf(ngx_conf_t *cf);
-static char *ngx_http_copy_filter_merge_conf(ngx_conf_t *cf,
-                                             void *parent, void *child);
-static ngx_int_t ngx_http_copy_filter_init(ngx_cycle_t *cycle);
-
-
-static ngx_command_t  ngx_http_copy_filter_commands[] = {
-
-    {ngx_string("output_buffers"),
-     NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
-     ngx_conf_set_bufs_slot,
-     NGX_HTTP_LOC_CONF_OFFSET,
-     offsetof(ngx_http_copy_filter_conf_t, bufs),
-     NULL},
-
-    ngx_null_command
-};
-
-
-static ngx_http_module_t  ngx_http_copy_filter_module_ctx = {
-    NULL,                                  /* pre conf */
-
-    NULL,                                  /* create main configuration */
-    NULL,                                  /* init main configuration */
-
-    NULL,                                  /* create server configuration */
-    NULL,                                  /* merge server configuration */
-
-    ngx_http_copy_filter_create_conf,      /* create location configuration */
-    ngx_http_copy_filter_merge_conf        /* merge location configuration */
-};
-
-
-ngx_module_t  ngx_http_copy_filter_module = {
-    NGX_MODULE,
-    &ngx_http_copy_filter_module_ctx,      /* module context */
-    ngx_http_copy_filter_commands,         /* module directives */
-    NGX_HTTP_MODULE,                       /* module type */
-    ngx_http_copy_filter_init,             /* init module */
-    NULL                                   /* init process */
-};
-
-
-static ngx_http_output_body_filter_pt    ngx_http_next_filter;
-
-
-ngx_int_t ngx_http_copy_filter(ngx_http_request_t *r, ngx_chain_t *in)
-{
-    ngx_output_chain_ctx_t       *ctx;
-    ngx_http_copy_filter_conf_t  *conf;
-
-    if (r->connection->write->error) {
-        return NGX_ERROR;
-    }
-
-    ctx = ngx_http_get_module_ctx(r->main ? r->main : r,
-                                            ngx_http_copy_filter_module);
-
-    if (ctx == NULL) {
-        conf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
-                                            ngx_http_copy_filter_module);
-
-        ngx_http_create_ctx(r, ctx, ngx_http_copy_filter_module,
-                            sizeof(ngx_output_chain_ctx_t), NGX_ERROR);
-
-        ctx->sendfile = r->connection->sendfile;
-        ctx->need_in_memory = r->filter_need_in_memory;
-        ctx->need_in_temp = r->filter_need_temporary;
-
-        ctx->pool = r->pool;
-        ctx->bufs = conf->bufs;
-        ctx->tag = (ngx_buf_tag_t) &ngx_http_copy_filter_module;
-
-        ctx->output_filter = (ngx_output_chain_filter_pt) ngx_http_next_filter;
-        ctx->filter_ctx = r;
-
-    }
-
-    return ngx_output_chain(ctx, in);
-}
-
-
-static void *ngx_http_copy_filter_create_conf(ngx_conf_t *cf)
-{
-    ngx_http_copy_filter_conf_t *conf;
-
-    ngx_test_null(conf,
-                  ngx_palloc(cf->pool, sizeof(ngx_http_copy_filter_conf_t)),
-                  NULL);
-
-    conf->bufs.num = 0;
-
-    return conf;
-}
-
-
-static char *ngx_http_copy_filter_merge_conf(ngx_conf_t *cf,
-                                             void *parent, void *child)
-{
-    ngx_http_copy_filter_conf_t *prev = parent;
-    ngx_http_copy_filter_conf_t *conf = child;
-
-    ngx_conf_merge_bufs_value(conf->bufs, prev->bufs, 1, 32768);
-
-    return NULL;
-}
-
-
-static ngx_int_t ngx_http_copy_filter_init(ngx_cycle_t *cycle)
-{
-    ngx_http_next_filter = ngx_http_top_body_filter;
-    ngx_http_top_body_filter = ngx_http_copy_filter;
-
-    return NGX_OK;
-}
-
new file mode 100644
--- /dev/null
+++ b/src/http/ngx_http_copy_filter_module.c
@@ -0,0 +1,140 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+
+
+typedef struct {
+    ngx_bufs_t  bufs;
+} ngx_http_copy_filter_conf_t;
+
+
+static void *ngx_http_copy_filter_create_conf(ngx_conf_t *cf);
+static char *ngx_http_copy_filter_merge_conf(ngx_conf_t *cf,
+    void *parent, void *child);
+static ngx_int_t ngx_http_copy_filter_init(ngx_cycle_t *cycle);
+
+
+static ngx_command_t  ngx_http_copy_filter_commands[] = {
+
+    { ngx_string("output_buffers"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2,
+      ngx_conf_set_bufs_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_copy_filter_conf_t, bufs),
+      NULL },
+
+      ngx_null_command
+};
+
+
+static ngx_http_module_t  ngx_http_copy_filter_module_ctx = {
+    NULL,                                  /* pre conf */
+
+    NULL,                                  /* create main configuration */
+    NULL,                                  /* init main configuration */
+
+    NULL,                                  /* create server configuration */
+    NULL,                                  /* merge server configuration */
+
+    ngx_http_copy_filter_create_conf,      /* create location configuration */
+    ngx_http_copy_filter_merge_conf        /* merge location configuration */
+};
+
+
+ngx_module_t  ngx_http_copy_filter_module = {
+    NGX_MODULE,
+    &ngx_http_copy_filter_module_ctx,      /* module context */
+    ngx_http_copy_filter_commands,         /* module directives */
+    NGX_HTTP_MODULE,                       /* module type */
+    ngx_http_copy_filter_init,             /* init module */
+    NULL                                   /* init process */
+};
+
+
+static ngx_http_output_body_filter_pt    ngx_http_next_filter;
+
+
+static ngx_int_t
+ngx_http_copy_filter(ngx_http_request_t *r, ngx_chain_t *in)
+{
+    ngx_output_chain_ctx_t       *ctx;
+    ngx_http_copy_filter_conf_t  *conf;
+
+    if (r->connection->write->error) {
+        return NGX_ERROR;
+    }
+
+    ctx = ngx_http_get_module_ctx(r->main ? r->main : r,
+                                            ngx_http_copy_filter_module);
+
+    if (ctx == NULL) {
+        conf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
+                                            ngx_http_copy_filter_module);
+
+        ctx = ngx_pcalloc(r->pool, sizeof(ngx_output_chain_ctx_t));
+        if (ctx == NULL) {
+            return NGX_ERROR;
+        }
+
+        ngx_http_set_ctx(r, ctx, ngx_http_copy_filter_module);
+
+        ctx->sendfile = r->connection->sendfile;
+        ctx->need_in_memory = r->filter_need_in_memory;
+        ctx->need_in_temp = r->filter_need_temporary;
+
+        ctx->pool = r->pool;
+        ctx->bufs = conf->bufs;
+        ctx->tag = (ngx_buf_tag_t) &ngx_http_copy_filter_module;
+
+        ctx->output_filter = (ngx_output_chain_filter_pt) ngx_http_next_filter;
+        ctx->filter_ctx = r;
+
+    }
+
+    return ngx_output_chain(ctx, in);
+}
+
+
+static void *
+ngx_http_copy_filter_create_conf(ngx_conf_t *cf)
+{
+    ngx_http_copy_filter_conf_t *conf;
+
+    conf = ngx_palloc(cf->pool, sizeof(ngx_http_copy_filter_conf_t));
+    if (conf == NULL) {
+        return NULL;
+    }
+
+    conf->bufs.num = 0;
+
+    return conf;
+}
+
+
+static char *
+ngx_http_copy_filter_merge_conf(ngx_conf_t *cf, void *parent, void *child)
+{
+    ngx_http_copy_filter_conf_t *prev = parent;
+    ngx_http_copy_filter_conf_t *conf = child;
+
+    ngx_conf_merge_bufs_value(conf->bufs, prev->bufs, 1, 32768);
+
+    return NULL;
+}
+
+
+static ngx_int_t
+ngx_http_copy_filter_init(ngx_cycle_t *cycle)
+{
+    ngx_http_next_filter = ngx_http_top_body_filter;
+    ngx_http_top_body_filter = ngx_http_copy_filter;
+
+    return NGX_OK;
+}
+
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -785,7 +785,8 @@ ngx_http_set_content_type(ngx_http_reque
             }
 
             if (i < r->exten.len) {
-                if (!(p = ngx_palloc(r->pool, r->exten.len))) {
+                p = ngx_palloc(r->pool, r->exten.len);
+                if (p == NULL) {
                     return NGX_HTTP_INTERNAL_SERVER_ERROR;
                 }
 
@@ -897,7 +898,8 @@ ngx_http_set_exten(ngx_http_request_t *r
             r->exten.len = r->uri.len - i - 1;
 
             if (r->exten.len > 0) {
-                if (!(r->exten.data = ngx_palloc(r->pool, r->exten.len + 1))) {
+                r->exten.data = ngx_palloc(r->pool, r->exten.len + 1);
+                if (r->exten.data == NULL) {
                     return NGX_ERROR;
                 }
 
@@ -997,7 +999,8 @@ ngx_http_core_server(ngx_conf_t *cf, ngx
     ngx_http_core_srv_conf_t   *cscf, **cscfp;
     ngx_http_core_main_conf_t  *cmcf;
 
-    if (!(ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)))) {
+    ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
+    if (ctx == NULL) {
         return NGX_CONF_ERROR;
     }
 
@@ -1026,7 +1029,8 @@ ngx_http_core_server(ngx_conf_t *cf, ngx
         module = ngx_modules[m]->ctx;
 
         if (module->create_srv_conf) {
-            if (!(mconf = module->create_srv_conf(cf))) {
+            mconf = module->create_srv_conf(cf);
+            if (mconf == NULL) {
                 return NGX_CONF_ERROR;
             }
 
@@ -1034,7 +1038,8 @@ ngx_http_core_server(ngx_conf_t *cf, ngx
         }
 
         if (module->create_loc_conf) {
-            if (!(mconf = module->create_loc_conf(cf))) {
+            mconf = module->create_loc_conf(cf);
+            if (mconf == NULL) {
                 return NGX_CONF_ERROR;
             }
 
@@ -1051,7 +1056,8 @@ ngx_http_core_server(ngx_conf_t *cf, ngx
 
     cmcf = ctx->main_conf[ngx_http_core_module.ctx_index];
 
-    if (!(cscfp = ngx_array_push(&cmcf->servers))) {
+    cscfp = ngx_array_push(&cmcf->servers);
+    if (cscfp == NULL) {
         return NGX_CONF_ERROR;
     }
 
@@ -1095,7 +1101,8 @@ ngx_http_core_location(ngx_conf_t *cf, n
     u_char                     errstr[NGX_MAX_CONF_ERRSTR];
 #endif
 
-    if (!(ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t)))) {
+    ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
+    if (ctx == NULL) {
         return NGX_CONF_ERROR;
     }
 
@@ -1181,7 +1188,9 @@ ngx_http_core_location(ngx_conf_t *cf, n
 
     if (pclcf->name.len == 0) {
         cscf = ctx->srv_conf[ngx_http_core_module.ctx_index];
-        if (!(clcfp = ngx_array_push(&cscf->locations))) {
+
+        clcfp = ngx_array_push(&cscf->locations);
+        if (clcfp == NULL) {
             return NGX_CONF_ERROR;
         }
 
@@ -1214,11 +1223,15 @@ ngx_http_core_location(ngx_conf_t *cf, n
         }
 
         if (pclcf->locations.elts == NULL) {
-            ngx_init_array(pclcf->locations, cf->pool, 4, sizeof(void *),
-                           NGX_CONF_ERROR);
+            if (ngx_array_init(&pclcf->locations, cf->pool, 4, sizeof(void *))
+                != NGX_OK)
+            {
+                return NGX_CONF_ERROR;
+            }
         }
 
-        if (!(clcfp = ngx_push_array(&pclcf->locations))) {
+        clcfp = ngx_array_push(&pclcf->locations);
+        if (clcfp == NULL) {
             return NGX_CONF_ERROR;
         }
     }
@@ -1347,7 +1360,8 @@ ngx_http_core_type(ngx_conf_t *cf, ngx_c
     for (i = 1; i < cf->args->nelts; i++) {
         ngx_http_types_hash_key(key, value[i]);
 
-        if (!(type = ngx_array_push(&lcf->types[key]))) {
+        type = ngx_array_push(&lcf->types[key]);
+        if (type == NULL) {
             return NGX_CONF_ERROR;
         }
 
@@ -1364,7 +1378,8 @@ ngx_http_core_create_main_conf(ngx_conf_
 {
     ngx_http_core_main_conf_t  *cmcf;
 
-    if (!(cmcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_core_main_conf_t)))) {
+    cmcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_core_main_conf_t));
+    if (cmcf == NULL) {
         return NGX_CONF_ERROR;
     }
 
@@ -1403,7 +1418,8 @@ ngx_http_core_create_srv_conf(ngx_conf_t
 {
     ngx_http_core_srv_conf_t  *cscf;
 
-    if (!(cscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_core_srv_conf_t)))) {
+    cscf = ngx_pcalloc(cf->pool, sizeof(ngx_http_core_srv_conf_t));
+    if (cscf == NULL) {
         return NGX_CONF_ERROR;
     }
 
@@ -1455,7 +1471,8 @@ ngx_http_core_merge_srv_conf(ngx_conf_t 
     /* TODO: it does not merge, it inits only */
 
     if (conf->listen.nelts == 0) {
-        if (!(ls = ngx_array_push(&conf->listen))) {
+        ls = ngx_array_push(&conf->listen);
+        if (ls == NULL) {
             return NGX_CONF_ERROR;
         }
 
@@ -1470,11 +1487,13 @@ ngx_http_core_merge_srv_conf(ngx_conf_t 
     }
 
     if (conf->server_names.nelts == 0) {
-        if (!(sn = ngx_array_push(&conf->server_names))) {
+        sn = ngx_array_push(&conf->server_names);
+        if (sn == NULL) {
             return NGX_CONF_ERROR;
         }
 
-        if (!(sn->name.data = ngx_palloc(cf->pool, NGX_MAXHOSTNAMELEN))) {
+        sn->name.data = ngx_palloc(cf->pool, NGX_MAXHOSTNAMELEN);
+        if (sn->name.data == NULL) {
             return NGX_CONF_ERROR;
         }
 
@@ -1528,7 +1547,8 @@ ngx_http_core_create_loc_conf(ngx_conf_t
 {
     ngx_http_core_loc_conf_t  *lcf;
 
-    if (!(lcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_core_loc_conf_t)))) {
+    lcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_core_loc_conf_t));
+    if (lcf == NULL) {
         return NGX_CONF_ERROR;
     }
 
@@ -1618,7 +1638,8 @@ ngx_http_core_merge_loc_conf(ngx_conf_t 
                 ngx_http_types_hash_key(key,
                                         ngx_http_core_default_types[i].exten);
 
-                if (!(type = ngx_array_push(&conf->types[key]))) {
+                type = ngx_array_push(&conf->types[key]);
+                if (type == NULL) {
                     return NGX_CONF_ERROR;
                 }
 
@@ -1700,7 +1721,8 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx
      *       add resolved name to server names ???
      */
 
-    if (!(ls = ngx_array_push(&scf->listen))) {
+    ls = ngx_array_push(&scf->listen);
+    if (ls == NULL) {
         return NGX_CONF_ERROR;
     }
 
@@ -1796,7 +1818,8 @@ ngx_http_core_server_name(ngx_conf_t *cf
             return NGX_CONF_ERROR;
         }
 
-        if (!(sn = ngx_array_push(&scf->server_names))) {
+        sn = ngx_array_push(&scf->server_names);
+        if (sn == NULL) {
             return NGX_CONF_ERROR;
         }
 
@@ -1908,7 +1931,8 @@ ngx_http_core_error_page(ngx_conf_t *cf,
     }
 
     for (i = 1; i < cf->args->nelts - n; i++) {
-        if (!(err = ngx_array_push(lcf->error_pages))) {
+        err = ngx_array_push(lcf->error_pages);
+        if (err == NULL) {
             return NGX_CONF_ERROR;
         }
 
@@ -1981,7 +2005,8 @@ ngx_http_core_error_log(ngx_conf_t *cf, 
 {
     ngx_http_core_loc_conf_t *lcf = conf;
 
-    if (!(lcf->err_log = ngx_log_create_errlog(cf->cycle, cf->args))) {
+    lcf->err_log = ngx_log_create_errlog(cf->cycle, cf->args);
+    if (lcf->err_log == NULL) {
         return NGX_CONF_ERROR;
     }
 
@@ -2021,5 +2046,5 @@ ngx_http_core_lowat_check(ngx_conf_t *cf
 static ngx_int_t
 ngx_http_core_init(ngx_cycle_t *cycle)
 {
-    return ngx_http_core_variables_init(cycle);
+    return ngx_http_variables_init(cycle);
 }
deleted file mode 100644
--- a/src/http/ngx_http_header_filter.c
+++ /dev/null
@@ -1,481 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-#include <nginx.h>
-
-
-static ngx_int_t ngx_http_header_filter_init(ngx_cycle_t *cycle);
-static ngx_int_t ngx_http_header_filter(ngx_http_request_t *r);
-
-
-static ngx_http_module_t  ngx_http_header_filter_module_ctx = {
-    NULL,                                  /* pre conf */
-
-    NULL,                                  /* create main configuration */
-    NULL,                                  /* init main configuration */
-
-    NULL,                                  /* create server configuration */
-    NULL,                                  /* merge server configuration */
-
-    NULL,                                  /* create location configuration */
-    NULL,                                  /* merge location configuration */
-};
-
-
-ngx_module_t  ngx_http_header_filter_module = {
-    NGX_MODULE,
-    &ngx_http_header_filter_module_ctx,    /* module context */
-    NULL,                                  /* module directives */
-    NGX_HTTP_MODULE,                       /* module type */
-    ngx_http_header_filter_init,           /* init module */
-    NULL                                   /* init process */
-};
-
-
-static char server_string[] = "Server: " NGINX_VER CRLF;
-
-
-static ngx_str_t http_codes[] = {
-
-    ngx_string("200 OK"),
-    ngx_null_string,  /* "201 Created" */
-    ngx_null_string,  /* "202 Accepted" */
-    ngx_null_string,  /* "203 Non-Authoritative Information" */
-    ngx_null_string,  /* "204 No Content" */
-    ngx_null_string,  /* "205 Reset Content" */
-    ngx_string("206 Partial Content"),
-
-    /* ngx_null_string, */  /* "207 Multi-Status" */
-
-#define NGX_HTTP_LEVEL_200  7
-
-    /* ngx_null_string, */  /* "300 Multiple Choices" */
-
-    ngx_string("301 Moved Permanently"),
-    ngx_string("302 Moved Temporarily"),
-    ngx_null_string,  /* "303 See Other" */
-    ngx_string("304 Not Modified"),
-
-    /* ngx_null_string, */  /* "305 Use Proxy" */
-    /* ngx_null_string, */  /* "306 unused" */
-    /* ngx_null_string, */  /* "307 Temporary Redirect" */
-
-#define NGX_HTTP_LEVEL_300  4
-
-    ngx_string("400 Bad Request"),
-    ngx_string("401 Unauthorized"),
-    ngx_string("402 Payment Required"),
-    ngx_string("403 Forbidden"),
-    ngx_string("404 Not Found"),
-    ngx_string("405 Not Allowed"),
-    ngx_string("406 Not Acceptable"),
-    ngx_null_string,  /* "407 Proxy Authentication Required" */
-    ngx_string("408 Request Time-out"),
-    ngx_null_string,  /* "409 Conflict" */
-    ngx_string("410 Gone"),
-    ngx_string("411 Length Required"),
-    ngx_null_string,  /* "412 Precondition Failed" */
-    ngx_string("413 Request Entity Too Large"),
-    ngx_null_string,  /* "414 Request-URI Too Large", but we never send it
-                       * because we treat such requests as the HTTP/0.9
-                       * requests and send only a body without a header
-                       */
-    ngx_null_string,  /* "415 Unsupported Media Type" */
-    ngx_string("416 Requested Range Not Satisfiable"),
-
-    /* ngx_null_string, */  /* "417 Expectation Failed" */
-    /* ngx_null_string, */  /* "418 unused" */
-    /* ngx_null_string, */  /* "419 unused" */
-    /* ngx_null_string, */  /* "420 unused" */
-    /* ngx_null_string, */  /* "421 unused" */
-    /* ngx_null_string, */  /* "422 Unprocessable Entity" */
-    /* ngx_null_string, */  /* "423 Locked" */
-    /* ngx_null_string, */  /* "424 Failed Dependency" */
-
-#define NGX_HTTP_LEVEL_400  17
-
-    ngx_string("500 Internal Server Error"),
-    ngx_string("501 Method Not Implemented"),
-    ngx_string("502 Bad Gateway"),
-    ngx_string("503 Service Temporarily Unavailable"),
-    ngx_string("504 Gateway Time-out")
-
-    /* ngx_null_string, */  /* "505 HTTP Version Not Supported" */
-    /* ngx_null_string, */  /* "506 Variant Also Negotiates" */
-    /* ngx_null_string, */  /* "507 Insufficient Storage" */
-    /* ngx_null_string, */  /* "508 unused" */
-    /* ngx_null_string, */  /* "509 unused" */
-    /* ngx_null_string, */  /* "510 Not Extended" */
-};
-
-
-ngx_http_header_t  ngx_http_headers_out[] = {
-    { ngx_string("Server"), offsetof(ngx_http_headers_out_t, server) },
-    { ngx_string("Date"), offsetof(ngx_http_headers_out_t, date) },
-    { ngx_string("Content-Type"),
-                 offsetof(ngx_http_headers_out_t, content_type) },
-    { ngx_string("Content-Length"),
-                 offsetof(ngx_http_headers_out_t, content_length) },
-    { ngx_string("Content-Encoding"),
-                 offsetof(ngx_http_headers_out_t, content_encoding) },
-    { ngx_string("Location"), offsetof(ngx_http_headers_out_t, location) },
-    { ngx_string("Last-Modified"),
-                 offsetof(ngx_http_headers_out_t, last_modified) },
-    { ngx_string("Accept-Ranges"),
-                 offsetof(ngx_http_headers_out_t, accept_ranges) },
-    { ngx_string("Expires"), offsetof(ngx_http_headers_out_t, expires) },
-    { ngx_string("Cache-Control"),
-                 offsetof(ngx_http_headers_out_t, cache_control) },
-    { ngx_string("ETag"), offsetof(ngx_http_headers_out_t, etag) },
-
-    { ngx_null_string, 0 }
-};
-
-
-static ngx_int_t
-ngx_http_header_filter(ngx_http_request_t *r)
-{
-    u_char                    *p;
-    size_t                     len;
-    ngx_uint_t                 status, i;
-    ngx_buf_t                 *b;
-    ngx_chain_t               *ln;
-    ngx_list_part_t           *part;
-    ngx_table_elt_t           *header;
-    ngx_http_core_loc_conf_t  *clcf;
-
-    if (r->http_version < NGX_HTTP_VERSION_10) {
-        return NGX_OK;
-    }
-
-    if (r->method == NGX_HTTP_HEAD) {
-        r->header_only = 1;
-    }
-
-    if (r->headers_out.last_modified_time != -1) {
-        if (r->headers_out.status != NGX_HTTP_OK
-            && r->headers_out.status != NGX_HTTP_NOT_MODIFIED
-            && r->headers_out.status != NGX_HTTP_PARTIAL_CONTENT)
-        {
-            r->headers_out.last_modified_time = -1;
-            r->headers_out.last_modified = NULL;
-        }
-    }
-
-    len = sizeof("HTTP/1.x ") - 1 + sizeof(CRLF) - 1
-          /* the end of the header */
-          + sizeof(CRLF) - 1;
-
-    /* status line */
-
-    if (r->headers_out.status_line.len) {
-        len += r->headers_out.status_line.len;
-#if (NGX_SUPPRESS_WARN)
-        status = NGX_INVALID_ARRAY_INDEX;
-#endif
-
-    } else {
-
-        if (r->headers_out.status < NGX_HTTP_MOVED_PERMANENTLY) {
-            /* 2XX */
-            status = r->headers_out.status - NGX_HTTP_OK;
-
-        } else if (r->headers_out.status < NGX_HTTP_BAD_REQUEST) {
-            /* 3XX */
-            status = r->headers_out.status - NGX_HTTP_MOVED_PERMANENTLY
-                                           + NGX_HTTP_LEVEL_200;
-
-            if (r->headers_out.status == NGX_HTTP_NOT_MODIFIED) {
-                r->header_only = 1;
-            }
-
-        } else if (r->headers_out.status < NGX_HTTP_INTERNAL_SERVER_ERROR) {
-            /* 4XX */
-            status = r->headers_out.status - NGX_HTTP_BAD_REQUEST
-                                           + NGX_HTTP_LEVEL_200
-                                           + NGX_HTTP_LEVEL_300;
-
-        } else {
-            /* 5XX */
-            status = r->headers_out.status - NGX_HTTP_INTERNAL_SERVER_ERROR
-                                           + NGX_HTTP_LEVEL_200
-                                           + NGX_HTTP_LEVEL_300
-                                           + NGX_HTTP_LEVEL_400;
-        }
-
-        len += http_codes[status].len;
-    }
-
-    if (r->headers_out.server && r->headers_out.server->key.len) {
-        len += r->headers_out.server->key.len
-               + r->headers_out.server->value.len + 2;
-    } else {
-        len += sizeof(server_string) - 1;
-    }
-
-    if (r->headers_out.date && r->headers_out.date->key.len) {
-        len += r->headers_out.date->key.len
-               + r->headers_out.date->value.len + 2;
-    } else {
-        len += sizeof("Date: Mon, 28 Sep 1970 06:00:00 GMT" CRLF) - 1;
-    }
-
-    if (r->headers_out.content_length == NULL) {
-        if (r->headers_out.content_length_n >= 0) {
-            len += sizeof("Content-Length: ") - 1 + NGX_OFF_T_LEN + 2;
-        }
-    }
-
-    if (r->headers_out.content_type && r->headers_out.content_type->value.len) {
-        r->headers_out.content_type->key.len = 0;
-        len += sizeof("Content-Type: ") - 1
-               + r->headers_out.content_type->value.len + 2;
-
-        if (r->headers_out.charset.len) {
-            len += sizeof("; charset=") - 1 + r->headers_out.charset.len;
-        }
-    }
-
-    if (r->headers_out.location
-        && r->headers_out.location->value.len
-        && r->headers_out.location->value.data[0] == '/')
-    {
-        r->headers_out.location->key.len = 0;
-        len += sizeof("Location: http://") - 1
-               + r->server_name.len + r->headers_out.location->value.len + 2;
-
-        if (r->port != 80) {
-            len += r->port_text->len;
-        }
-    }
-
-    if (r->headers_out.last_modified && r->headers_out.last_modified->key.len) {
-        len += r->headers_out.last_modified->key.len
-               + r->headers_out.last_modified->value.len + 2;
-
-    } else if (r->headers_out.last_modified_time != -1) {
-        len += sizeof("Last-Modified: Mon, 28 Sep 1970 06:00:00 GMT" CRLF) - 1;
-    }
-
-    if (r->chunked) {
-        len += sizeof("Transfer-Encoding: chunked" CRLF) - 1;
-    }
-
-    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-
-    if (r->keepalive) {
-        len += sizeof("Connection: keep-alive" CRLF) - 1;
-
-        /*
-         * MSIE and Opera ignore the "Keep-Alive: timeout=<N>" header.
-         * MSIE keeps the connection alive for about 60-65 seconds.
-         * Opera keeps the connection alive very long.
-         * Mozilla keeps the connection alive for N plus about 1-10 seconds.
-         * Konqueror keeps the connection alive for about N seconds.
-         */
-
-        if (clcf->keepalive_header) {
-            len += sizeof("Keep-Alive: timeout=") - 1 + NGX_TIME_T_LEN + 2;
-        }
-
-    } else {
-        len += sizeof("Connection: closed" CRLF) - 1;
-    }
-
-    part = &r->headers_out.headers.part;
-    header = part->elts;
-
-    for (i = 0; /* void */; i++) {
-
-        if (i >= part->nelts) {
-            if (part->next == NULL) {
-                break;
-            }
-
-            part = part->next;
-            header = part->elts;
-            i = 0;
-        }
-
-        if (header[i].key.len == 0) {
-            continue;
-        }
-
-        len += header[i].key.len + sizeof(": ") - 1 + header[i].value.len
-               + sizeof(CRLF) - 1;
-    }
-
-    if (!(b = ngx_create_temp_buf(r->pool, len))) {
-        return NGX_ERROR;
-    }
-
-    /* "HTTP/1.x " */
-    b->last = ngx_cpymem(b->last, "HTTP/1.1 ", sizeof("HTTP/1.x ") - 1);
-
-    /* status line */
-    if (r->headers_out.status_line.len) {
-        b->last = ngx_cpymem(b->last, r->headers_out.status_line.data,
-                             r->headers_out.status_line.len);
-
-    } else {
-        b->last = ngx_cpymem(b->last, http_codes[status].data,
-                             http_codes[status].len);
-    }
-    *b->last++ = CR; *b->last++ = LF;
-
-    if (!(r->headers_out.server && r->headers_out.server->key.len)) {
-        b->last = ngx_cpymem(b->last, server_string, sizeof(server_string) - 1);
-    }
-
-    if (!(r->headers_out.date && r->headers_out.date->key.len)) {
-        b->last = ngx_cpymem(b->last, "Date: ", sizeof("Date: ") - 1);
-        b->last = ngx_cpymem(b->last, ngx_cached_http_time.data,
-                             ngx_cached_http_time.len);
-
-        *b->last++ = CR; *b->last++ = LF;
-    }
-
-    if (r->headers_out.content_length == NULL) {
-        if (r->headers_out.content_length_n >= 0) {
-            b->last = ngx_sprintf(b->last, "Content-Length: %O" CRLF,
-                                  r->headers_out.content_length_n);
-        }
-    }
-
-    if (r->headers_out.content_type && r->headers_out.content_type->value.len) {
-        b->last = ngx_cpymem(b->last, "Content-Type: ",
-                             sizeof("Content-Type: ") - 1);
-        p = b->last;
-        b->last = ngx_cpymem(b->last, r->headers_out.content_type->value.data,
-                             r->headers_out.content_type->value.len);
-
-        if (r->headers_out.charset.len) {
-            b->last = ngx_cpymem(b->last, "; charset=",
-                                 sizeof("; charset=") - 1);
-            b->last = ngx_cpymem(b->last, r->headers_out.charset.data,
-                                 r->headers_out.charset.len);
-
-            r->headers_out.content_type->value.len = b->last - p;
-            r->headers_out.content_type->value.data = p;
-        }
-
-        *b->last++ = CR; *b->last++ = LF;
-    }
-
-    if (r->headers_out.location
-        && r->headers_out.location->value.len
-        && r->headers_out.location->value.data[0] == '/')
-    {
-        p = b->last + sizeof("Location: ") - 1;
-        b->last = ngx_cpymem(b->last, "Location: http://",
-                             sizeof("Location: http://") - 1);
-        b->last = ngx_cpymem(b->last, r->server_name.data,
-                             r->server_name.len);
-        if (r->port != 80) {
-            b->last = ngx_cpymem(b->last, r->port_text->data,
-                                 r->port_text->len);
-        }
-
-        b->last = ngx_cpymem(b->last, r->headers_out.location->value.data,
-                             r->headers_out.location->value.len);
-
-        r->headers_out.location->value.len = b->last - p;
-        r->headers_out.location->value.data = p;
-
-        *b->last++ = CR; *b->last++ = LF;
-    }
-
-    if (!(r->headers_out.last_modified && r->headers_out.last_modified->key.len)
-        && r->headers_out.last_modified_time != -1)
-    {
-        b->last = ngx_cpymem(b->last, "Last-Modified: ",
-                             sizeof("Last-Modified: ") - 1);
-        b->last = ngx_http_time(b->last, r->headers_out.last_modified_time);
-
-        *b->last++ = CR; *b->last++ = LF;
-    }
-
-    if (r->chunked) {
-        b->last = ngx_cpymem(b->last, "Transfer-Encoding: chunked" CRLF,
-                             sizeof("Transfer-Encoding: chunked" CRLF) - 1);
-    }
-
-    if (r->keepalive) {
-        b->last = ngx_cpymem(b->last, "Connection: keep-alive" CRLF,
-                             sizeof("Connection: keep-alive" CRLF) - 1);
-
-        if (clcf->keepalive_header) {
-            b->last = ngx_sprintf(b->last, "Keep-Alive: timeout=%T" CRLF,
-                                  clcf->keepalive_header);
-        }
-
-    } else {
-        b->last = ngx_cpymem(b->last, "Connection: close" CRLF,
-                             sizeof("Connection: close" CRLF) - 1);
-    }
-
-    part = &r->headers_out.headers.part;
-    header = part->elts;
-
-    for (i = 0; /* void */; i++) {
-
-        if (i >= part->nelts) {
-            if (part->next == NULL) {
-                break;
-            }
-
-            part = part->next;
-            header = part->elts;
-            i = 0;
-        }
-
-        if (header[i].key.len == 0) {
-            continue;
-        }
-
-        b->last = ngx_cpymem(b->last, header[i].key.data, header[i].key.len);
-        *b->last++ = ':' ; *b->last++ = ' ' ;
-
-        b->last = ngx_cpymem(b->last, header[i].value.data,
-                             header[i].value.len);
-        *b->last++ = CR; *b->last++ = LF;
-    }
-
-#if (NGX_DEBUG)
-    *b->last = '\0';
-    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "%s\n", b->pos);
-#endif
-
-    /* the end of HTTP header */
-    *b->last++ = CR; *b->last++ = LF;
-
-    r->header_size = b->last - b->pos;
-
-    if (r->header_only) {
-        b->last_buf = 1;
-    }
-
-    if (!(ln = ngx_alloc_chain_link(r->pool))) {
-        return NGX_ERROR;
-    }
-
-    ln->buf = b;
-    ln->next = NULL;
-
-    return ngx_http_write_filter(r, ln);
-}
-
-
-static ngx_int_t
-ngx_http_header_filter_init(ngx_cycle_t *cycle)
-{
-    ngx_http_top_header_filter = ngx_http_header_filter;
-
-    return NGX_OK;
-}
new file mode 100644
--- /dev/null
+++ b/src/http/ngx_http_header_filter_module.c
@@ -0,0 +1,478 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+#include <nginx.h>
+
+
+static ngx_int_t ngx_http_header_filter_init(ngx_cycle_t *cycle);
+static ngx_int_t ngx_http_header_filter(ngx_http_request_t *r);
+
+
+static ngx_http_module_t  ngx_http_header_filter_module_ctx = {
+    NULL,                                  /* pre conf */
+
+    NULL,                                  /* create main configuration */
+    NULL,                                  /* init main configuration */
+
+    NULL,                                  /* create server configuration */
+    NULL,                                  /* merge server configuration */
+
+    NULL,                                  /* create location configuration */
+    NULL,                                  /* merge location configuration */
+};
+
+
+ngx_module_t  ngx_http_header_filter_module = {
+    NGX_MODULE,
+    &ngx_http_header_filter_module_ctx,    /* module context */
+    NULL,                                  /* module directives */
+    NGX_HTTP_MODULE,                       /* module type */
+    ngx_http_header_filter_init,           /* init module */
+    NULL                                   /* init process */
+};
+
+
+static char server_string[] = "Server: " NGINX_VER CRLF;
+
+
+static ngx_str_t http_codes[] = {
+
+    ngx_string("200 OK"),
+    ngx_null_string,  /* "201 Created" */
+    ngx_null_string,  /* "202 Accepted" */
+    ngx_null_string,  /* "203 Non-Authoritative Information" */
+    ngx_null_string,  /* "204 No Content" */
+    ngx_null_string,  /* "205 Reset Content" */
+    ngx_string("206 Partial Content"),
+
+    /* ngx_null_string, */  /* "207 Multi-Status" */
+
+#define NGX_HTTP_LEVEL_200  7
+
+    /* ngx_null_string, */  /* "300 Multiple Choices" */
+
+    ngx_string("301 Moved Permanently"),
+    ngx_string("302 Moved Temporarily"),
+    ngx_null_string,  /* "303 See Other" */
+    ngx_string("304 Not Modified"),
+
+    /* ngx_null_string, */  /* "305 Use Proxy" */
+    /* ngx_null_string, */  /* "306 unused" */
+    /* ngx_null_string, */  /* "307 Temporary Redirect" */
+
+#define NGX_HTTP_LEVEL_300  4
+
+    ngx_string("400 Bad Request"),
+    ngx_string("401 Unauthorized"),
+    ngx_string("402 Payment Required"),
+    ngx_string("403 Forbidden"),
+    ngx_string("404 Not Found"),
+    ngx_string("405 Not Allowed"),
+    ngx_string("406 Not Acceptable"),
+    ngx_null_string,  /* "407 Proxy Authentication Required" */
+    ngx_string("408 Request Time-out"),
+    ngx_null_string,  /* "409 Conflict" */
+    ngx_string("410 Gone"),
+    ngx_string("411 Length Required"),
+    ngx_null_string,  /* "412 Precondition Failed" */
+    ngx_string("413 Request Entity Too Large"),
+    ngx_null_string,  /* "414 Request-URI Too Large", but we never send it
+                       * because we treat such requests as the HTTP/0.9
+                       * requests and send only a body without a header
+                       */
+    ngx_null_string,  /* "415 Unsupported Media Type" */
+    ngx_string("416 Requested Range Not Satisfiable"),
+
+    /* ngx_null_string, */  /* "417 Expectation Failed" */
+    /* ngx_null_string, */  /* "418 unused" */
+    /* ngx_null_string, */  /* "419 unused" */
+    /* ngx_null_string, */  /* "420 unused" */
+    /* ngx_null_string, */  /* "421 unused" */
+    /* ngx_null_string, */  /* "422 Unprocessable Entity" */
+    /* ngx_null_string, */  /* "423 Locked" */
+    /* ngx_null_string, */  /* "424 Failed Dependency" */
+
+#define NGX_HTTP_LEVEL_400  17
+
+    ngx_string("500 Internal Server Error"),
+    ngx_string("501 Method Not Implemented"),
+    ngx_string("502 Bad Gateway"),
+    ngx_string("503 Service Temporarily Unavailable"),
+    ngx_string("504 Gateway Time-out")
+
+    /* ngx_null_string, */  /* "505 HTTP Version Not Supported" */
+    /* ngx_null_string, */  /* "506 Variant Also Negotiates" */
+    /* ngx_null_string, */  /* "507 Insufficient Storage" */
+    /* ngx_null_string, */  /* "508 unused" */
+    /* ngx_null_string, */  /* "509 unused" */
+    /* ngx_null_string, */  /* "510 Not Extended" */
+};
+
+
+ngx_http_header_t  ngx_http_headers_out[] = {
+    { ngx_string("Server"), offsetof(ngx_http_headers_out_t, server) },
+    { ngx_string("Date"), offsetof(ngx_http_headers_out_t, date) },
+    { ngx_string("Content-Type"),
+                 offsetof(ngx_http_headers_out_t, content_type) },
+    { ngx_string("Content-Length"),
+                 offsetof(ngx_http_headers_out_t, content_length) },
+    { ngx_string("Content-Encoding"),
+                 offsetof(ngx_http_headers_out_t, content_encoding) },
+    { ngx_string("Location"), offsetof(ngx_http_headers_out_t, location) },
+    { ngx_string("Last-Modified"),
+                 offsetof(ngx_http_headers_out_t, last_modified) },
+    { ngx_string("Accept-Ranges"),
+                 offsetof(ngx_http_headers_out_t, accept_ranges) },
+    { ngx_string("Expires"), offsetof(ngx_http_headers_out_t, expires) },
+    { ngx_string("Cache-Control"),
+                 offsetof(ngx_http_headers_out_t, cache_control) },
+    { ngx_string("ETag"), offsetof(ngx_http_headers_out_t, etag) },
+
+    { ngx_null_string, 0 }
+};
+
+
+static ngx_int_t
+ngx_http_header_filter(ngx_http_request_t *r)
+{
+    u_char                    *p;
+    size_t                     len;
+    ngx_uint_t                 status, i;
+    ngx_buf_t                 *b;
+    ngx_chain_t                out;
+    ngx_list_part_t           *part;
+    ngx_table_elt_t           *header;
+    ngx_http_core_loc_conf_t  *clcf;
+
+    if (r->http_version < NGX_HTTP_VERSION_10) {
+        return NGX_OK;
+    }
+
+    if (r->method == NGX_HTTP_HEAD) {
+        r->header_only = 1;
+    }
+
+    if (r->headers_out.last_modified_time != -1) {
+        if (r->headers_out.status != NGX_HTTP_OK
+            && r->headers_out.status != NGX_HTTP_NOT_MODIFIED
+            && r->headers_out.status != NGX_HTTP_PARTIAL_CONTENT)
+        {
+            r->headers_out.last_modified_time = -1;
+            r->headers_out.last_modified = NULL;
+        }
+    }
+
+    len = sizeof("HTTP/1.x ") - 1 + sizeof(CRLF) - 1
+          /* the end of the header */
+          + sizeof(CRLF) - 1;
+
+    /* status line */
+
+    if (r->headers_out.status_line.len) {
+        len += r->headers_out.status_line.len;
+#if (NGX_SUPPRESS_WARN)
+        status = NGX_INVALID_ARRAY_INDEX;
+#endif
+
+    } else {
+
+        if (r->headers_out.status < NGX_HTTP_MOVED_PERMANENTLY) {
+            /* 2XX */
+            status = r->headers_out.status - NGX_HTTP_OK;
+
+        } else if (r->headers_out.status < NGX_HTTP_BAD_REQUEST) {
+            /* 3XX */
+            status = r->headers_out.status - NGX_HTTP_MOVED_PERMANENTLY
+                                           + NGX_HTTP_LEVEL_200;
+
+            if (r->headers_out.status == NGX_HTTP_NOT_MODIFIED) {
+                r->header_only = 1;
+            }
+
+        } else if (r->headers_out.status < NGX_HTTP_INTERNAL_SERVER_ERROR) {
+            /* 4XX */
+            status = r->headers_out.status - NGX_HTTP_BAD_REQUEST
+                                           + NGX_HTTP_LEVEL_200
+                                           + NGX_HTTP_LEVEL_300;
+
+        } else {
+            /* 5XX */
+            status = r->headers_out.status - NGX_HTTP_INTERNAL_SERVER_ERROR
+                                           + NGX_HTTP_LEVEL_200
+                                           + NGX_HTTP_LEVEL_300
+                                           + NGX_HTTP_LEVEL_400;
+        }
+
+        len += http_codes[status].len;
+    }
+
+    if (r->headers_out.server && r->headers_out.server->key.len) {
+        len += r->headers_out.server->key.len
+               + r->headers_out.server->value.len + 2;
+    } else {
+        len += sizeof(server_string) - 1;
+    }
+
+    if (r->headers_out.date && r->headers_out.date->key.len) {
+        len += r->headers_out.date->key.len
+               + r->headers_out.date->value.len + 2;
+    } else {
+        len += sizeof("Date: Mon, 28 Sep 1970 06:00:00 GMT" CRLF) - 1;
+    }
+
+    if (r->headers_out.content_length == NULL) {
+        if (r->headers_out.content_length_n >= 0) {
+            len += sizeof("Content-Length: ") - 1 + NGX_OFF_T_LEN + 2;
+        }
+    }
+
+    if (r->headers_out.content_type && r->headers_out.content_type->value.len) {
+        r->headers_out.content_type->key.len = 0;
+        len += sizeof("Content-Type: ") - 1
+               + r->headers_out.content_type->value.len + 2;
+
+        if (r->headers_out.charset.len) {
+            len += sizeof("; charset=") - 1 + r->headers_out.charset.len;
+        }
+    }
+
+    if (r->headers_out.location
+        && r->headers_out.location->value.len
+        && r->headers_out.location->value.data[0] == '/')
+    {
+        r->headers_out.location->key.len = 0;
+        len += sizeof("Location: http://") - 1
+               + r->server_name.len + r->headers_out.location->value.len + 2;
+
+        if (r->port != 80) {
+            len += r->port_text->len;
+        }
+    }
+
+    if (r->headers_out.last_modified && r->headers_out.last_modified->key.len) {
+        len += r->headers_out.last_modified->key.len
+               + r->headers_out.last_modified->value.len + 2;
+
+    } else if (r->headers_out.last_modified_time != -1) {
+        len += sizeof("Last-Modified: Mon, 28 Sep 1970 06:00:00 GMT" CRLF) - 1;
+    }
+
+    if (r->chunked) {
+        len += sizeof("Transfer-Encoding: chunked" CRLF) - 1;
+    }
+
+    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+    if (r->keepalive) {
+        len += sizeof("Connection: keep-alive" CRLF) - 1;
+
+        /*
+         * MSIE and Opera ignore the "Keep-Alive: timeout=<N>" header.
+         * MSIE keeps the connection alive for about 60-65 seconds.
+         * Opera keeps the connection alive very long.
+         * Mozilla keeps the connection alive for N plus about 1-10 seconds.
+         * Konqueror keeps the connection alive for about N seconds.
+         */
+
+        if (clcf->keepalive_header) {
+            len += sizeof("Keep-Alive: timeout=") - 1 + NGX_TIME_T_LEN + 2;
+        }
+
+    } else {
+        len += sizeof("Connection: closed" CRLF) - 1;
+    }
+
+    part = &r->headers_out.headers.part;
+    header = part->elts;
+
+    for (i = 0; /* void */; i++) {
+
+        if (i >= part->nelts) {
+            if (part->next == NULL) {
+                break;
+            }
+
+            part = part->next;
+            header = part->elts;
+            i = 0;
+        }
+
+        if (header[i].key.len == 0) {
+            continue;
+        }
+
+        len += header[i].key.len + sizeof(": ") - 1 + header[i].value.len
+               + sizeof(CRLF) - 1;
+    }
+
+    b = ngx_create_temp_buf(r->pool, len);
+    if (b == NULL) {
+        return NGX_ERROR;
+    }
+
+    /* "HTTP/1.x " */
+    b->last = ngx_cpymem(b->last, "HTTP/1.1 ", sizeof("HTTP/1.x ") - 1);
+
+    /* status line */
+    if (r->headers_out.status_line.len) {
+        b->last = ngx_cpymem(b->last, r->headers_out.status_line.data,
+                             r->headers_out.status_line.len);
+
+    } else {
+        b->last = ngx_cpymem(b->last, http_codes[status].data,
+                             http_codes[status].len);
+    }
+    *b->last++ = CR; *b->last++ = LF;
+
+    if (!(r->headers_out.server && r->headers_out.server->key.len)) {
+        b->last = ngx_cpymem(b->last, server_string, sizeof(server_string) - 1);
+    }
+
+    if (!(r->headers_out.date && r->headers_out.date->key.len)) {
+        b->last = ngx_cpymem(b->last, "Date: ", sizeof("Date: ") - 1);
+        b->last = ngx_cpymem(b->last, ngx_cached_http_time.data,
+                             ngx_cached_http_time.len);
+
+        *b->last++ = CR; *b->last++ = LF;
+    }
+
+    if (r->headers_out.content_length == NULL) {
+        if (r->headers_out.content_length_n >= 0) {
+            b->last = ngx_sprintf(b->last, "Content-Length: %O" CRLF,
+                                  r->headers_out.content_length_n);
+        }
+    }
+
+    if (r->headers_out.content_type && r->headers_out.content_type->value.len) {
+        b->last = ngx_cpymem(b->last, "Content-Type: ",
+                             sizeof("Content-Type: ") - 1);
+        p = b->last;
+        b->last = ngx_cpymem(b->last, r->headers_out.content_type->value.data,
+                             r->headers_out.content_type->value.len);
+
+        if (r->headers_out.charset.len) {
+            b->last = ngx_cpymem(b->last, "; charset=",
+                                 sizeof("; charset=") - 1);
+            b->last = ngx_cpymem(b->last, r->headers_out.charset.data,
+                                 r->headers_out.charset.len);
+
+            r->headers_out.content_type->value.len = b->last - p;
+            r->headers_out.content_type->value.data = p;
+        }
+
+        *b->last++ = CR; *b->last++ = LF;
+    }
+
+    if (r->headers_out.location
+        && r->headers_out.location->value.len
+        && r->headers_out.location->value.data[0] == '/')
+    {
+        p = b->last + sizeof("Location: ") - 1;
+        b->last = ngx_cpymem(b->last, "Location: http://",
+                             sizeof("Location: http://") - 1);
+        b->last = ngx_cpymem(b->last, r->server_name.data,
+                             r->server_name.len);
+        if (r->port != 80) {
+            b->last = ngx_cpymem(b->last, r->port_text->data,
+                                 r->port_text->len);
+        }
+
+        b->last = ngx_cpymem(b->last, r->headers_out.location->value.data,
+                             r->headers_out.location->value.len);
+
+        r->headers_out.location->value.len = b->last - p;
+        r->headers_out.location->value.data = p;
+
+        *b->last++ = CR; *b->last++ = LF;
+    }
+
+    if (!(r->headers_out.last_modified && r->headers_out.last_modified->key.len)
+        && r->headers_out.last_modified_time != -1)
+    {
+        b->last = ngx_cpymem(b->last, "Last-Modified: ",
+                             sizeof("Last-Modified: ") - 1);
+        b->last = ngx_http_time(b->last, r->headers_out.last_modified_time);
+
+        *b->last++ = CR; *b->last++ = LF;
+    }
+
+    if (r->chunked) {
+        b->last = ngx_cpymem(b->last, "Transfer-Encoding: chunked" CRLF,
+                             sizeof("Transfer-Encoding: chunked" CRLF) - 1);
+    }
+
+    if (r->keepalive) {
+        b->last = ngx_cpymem(b->last, "Connection: keep-alive" CRLF,
+                             sizeof("Connection: keep-alive" CRLF) - 1);
+
+        if (clcf->keepalive_header) {
+            b->last = ngx_sprintf(b->last, "Keep-Alive: timeout=%T" CRLF,
+                                  clcf->keepalive_header);
+        }
+
+    } else {
+        b->last = ngx_cpymem(b->last, "Connection: close" CRLF,
+                             sizeof("Connection: close" CRLF) - 1);
+    }
+
+    part = &r->headers_out.headers.part;
+    header = part->elts;
+
+    for (i = 0; /* void */; i++) {
+
+        if (i >= part->nelts) {
+            if (part->next == NULL) {
+                break;
+            }
+
+            part = part->next;
+            header = part->elts;
+            i = 0;
+        }
+
+        if (header[i].key.len == 0) {
+            continue;
+        }
+
+        b->last = ngx_cpymem(b->last, header[i].key.data, header[i].key.len);
+        *b->last++ = ':' ; *b->last++ = ' ' ;
+
+        b->last = ngx_cpymem(b->last, header[i].value.data,
+                             header[i].value.len);
+        *b->last++ = CR; *b->last++ = LF;
+    }
+
+#if (NGX_DEBUG)
+    *b->last = '\0';
+    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "%s\n", b->pos);
+#endif
+
+    /* the end of HTTP header */
+    *b->last++ = CR; *b->last++ = LF;
+
+    r->header_size = b->last - b->pos;
+
+    if (r->header_only) {
+        b->last_buf = 1;
+    }
+
+    out.buf = b;
+    out.next = NULL;
+
+    return ngx_http_write_filter(r, &out);
+}
+
+
+static ngx_int_t
+ngx_http_header_filter_init(ngx_cycle_t *cycle)
+{
+    ngx_http_top_header_filter = ngx_http_header_filter;
+
+    return NGX_OK;
+}
deleted file mode 100644
--- a/src/http/ngx_http_log_handler.c
+++ /dev/null
@@ -1,1098 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-#include <nginx.h>
-
-
-static u_char *ngx_http_log_addr(ngx_http_request_t *r, u_char *buf,
-    ngx_http_log_op_t *op);
-static u_char *ngx_http_log_connection(ngx_http_request_t *r, u_char *buf,
-    ngx_http_log_op_t *op);
-static u_char *ngx_http_log_pipe(ngx_http_request_t *r, u_char *buf,
-    ngx_http_log_op_t *op);
-static u_char *ngx_http_log_time(ngx_http_request_t *r, u_char *buf,
-    ngx_http_log_op_t *op);
-static u_char *ngx_http_log_msec(ngx_http_request_t *r, u_char *buf,
-    ngx_http_log_op_t *op);
-static u_char *ngx_http_log_request_time(ngx_http_request_t *r, u_char *buf,
-    ngx_http_log_op_t *op);
-static u_char *ngx_http_log_status(ngx_http_request_t *r, u_char *buf,
-    ngx_http_log_op_t *op);
-static u_char *ngx_http_log_length(ngx_http_request_t *r, u_char *buf,
-    ngx_http_log_op_t *op);
-static u_char *ngx_http_log_apache_length(ngx_http_request_t *r, u_char *buf,
-    ngx_http_log_op_t *op);
-static u_char *ngx_http_log_request_length(ngx_http_request_t *r, u_char *buf,
-    ngx_http_log_op_t *op);
-
-static size_t ngx_http_log_request_getlen(ngx_http_request_t *r,
-    uintptr_t data);
-static u_char *ngx_http_log_request(ngx_http_request_t *r, u_char *buf,
-    ngx_http_log_op_t *op);
-
-static ngx_int_t ngx_http_log_header_in_compile(ngx_http_log_op_t *op,
-    ngx_str_t *value);
-static size_t ngx_http_log_header_in_getlen(ngx_http_request_t *r,
-    uintptr_t data);
-static u_char *ngx_http_log_header_in(ngx_http_request_t *r, u_char *buf,
-    ngx_http_log_op_t *op);
-static size_t ngx_http_log_unknown_header_in_getlen(ngx_http_request_t *r,
-    uintptr_t data);
-static u_char *ngx_http_log_unknown_header_in(ngx_http_request_t *r,
-    u_char *buf, ngx_http_log_op_t *op);
-
-static ngx_int_t ngx_http_log_header_out_compile(ngx_http_log_op_t *op,
-    ngx_str_t *value);
-static size_t ngx_http_log_header_out_getlen(ngx_http_request_t *r,
-    uintptr_t data);
-static u_char *ngx_http_log_header_out(ngx_http_request_t *r, u_char *buf,
-    ngx_http_log_op_t *op);
-static size_t ngx_http_log_unknown_header_out_getlen(ngx_http_request_t *r,
-    uintptr_t data);
-static u_char *ngx_http_log_unknown_header_out(ngx_http_request_t *r,
-    u_char *buf, ngx_http_log_op_t *op);
-
-static u_char *ngx_http_log_connection_header_out(ngx_http_request_t *r,
-    u_char *buf, ngx_http_log_op_t *op);
-static u_char *ngx_http_log_transfer_encoding_header_out(ngx_http_request_t *r,
-    u_char *buf, ngx_http_log_op_t *op);
-
-static ngx_table_elt_t *ngx_http_log_unknown_header(ngx_list_t *headers,
-    ngx_str_t *value);
-
-static ngx_int_t ngx_http_log_set_formats(ngx_conf_t *cf);
-static void *ngx_http_log_create_main_conf(ngx_conf_t *cf);
-static void *ngx_http_log_create_loc_conf(ngx_conf_t *cf);
-static char *ngx_http_log_merge_loc_conf(ngx_conf_t *cf, void *parent,
-    void *child);
-static char *ngx_http_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd,
-    void *conf);
-static char *ngx_http_log_set_format(ngx_conf_t *cf, ngx_command_t *cmd,
-    void *conf);
-static ngx_int_t ngx_http_log_parse_format(ngx_conf_t *cf, ngx_array_t *ops,
-    ngx_str_t *line);
-
-
-static ngx_command_t  ngx_http_log_commands[] = {
-
-    { ngx_string("log_format"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_2MORE,
-      ngx_http_log_set_format,
-      NGX_HTTP_MAIN_CONF_OFFSET,
-      0,
-      NULL },
-
-    { ngx_string("access_log"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
-      ngx_http_log_set_log,
-      NGX_HTTP_LOC_CONF_OFFSET,
-      0,
-      NULL },
-
-      ngx_null_command
-};
-
-
-ngx_http_module_t  ngx_http_log_module_ctx = {
-    ngx_http_log_set_formats,              /* pre conf */
-
-    ngx_http_log_create_main_conf,         /* create main configuration */
-    NULL,                                  /* init main configuration */
-
-    NULL,                                  /* create server configuration */
-    NULL,                                  /* merge server configuration */
-
-    ngx_http_log_create_loc_conf,          /* create location configration */
-    ngx_http_log_merge_loc_conf            /* merge location configration */
-};
-
-
-ngx_module_t  ngx_http_log_module = {
-    NGX_MODULE,
-    &ngx_http_log_module_ctx,              /* module context */
-    ngx_http_log_commands,                 /* module directives */
-    NGX_HTTP_MODULE,                       /* module type */
-    NULL,                                  /* init module */
-    NULL                                   /* init process */
-};
-
-
-static ngx_str_t http_access_log = ngx_string(NGX_HTTP_LOG_PATH);
-
-
-static ngx_str_t ngx_http_combined_fmt =
-    ngx_string("%addr - - [%time] \"%request\" %status %apache_length "
-               "\"%{Referer}i\" \"%{User-Agent}i\"");
-
-
-ngx_http_log_op_name_t ngx_http_log_fmt_ops[] = {
-    { ngx_string("addr"), INET_ADDRSTRLEN - 1, NULL, NULL, ngx_http_log_addr },
-    { ngx_string("conn"), NGX_ATOMIC_T_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 +0600") - 1,
-                          NULL, NULL, ngx_http_log_time },
-    { ngx_string("msec"), NGX_TIME_T_LEN + 4, NULL, NULL, ngx_http_log_msec },
-    { ngx_string("request_time"), NGX_TIME_T_LEN, NULL, NULL,
-                          ngx_http_log_request_time },
-    { ngx_string("status"), 3, NULL, NULL, ngx_http_log_status },
-    { ngx_string("length"), NGX_OFF_T_LEN, NULL, NULL, ngx_http_log_length },
-    { ngx_string("apache_length"), NGX_OFF_T_LEN,
-                          NULL, NULL, ngx_http_log_apache_length },
-    { ngx_string("request_length"), NGX_SIZE_T_LEN,
-                          NULL, NULL, ngx_http_log_request_length },
-
-    { ngx_string("request"), 0, NULL,
-                          ngx_http_log_request_getlen,
-                          ngx_http_log_request },
-
-    { ngx_string("i"), 0, ngx_http_log_header_in_compile,
-                          ngx_http_log_header_in_getlen,
-                          ngx_http_log_header_in },
-
-    { ngx_string("o"), 0, ngx_http_log_header_out_compile,
-                          ngx_http_log_header_out_getlen,
-                          ngx_http_log_header_out },
-
-    { ngx_null_string, 0, NULL, NULL, NULL }
-};
-
-
-ngx_int_t
-ngx_http_log_handler(ngx_http_request_t *r)
-{
-    ngx_uint_t                i, l;
-    u_char                   *line, *p;
-    size_t                    len;
-    ngx_http_log_t           *log;
-    ngx_http_log_op_t        *op;
-    ngx_http_log_loc_conf_t  *lcf;
-#if (NGX_WIN32)
-    u_long                    written;
-#endif
-
-    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                   "http log handler");
-
-    lcf = ngx_http_get_module_loc_conf(r, ngx_http_log_module);
-
-    if (lcf->off) {
-        return NGX_OK;
-    }
-
-    log = lcf->logs->elts;
-    for (l = 0; l < lcf->logs->nelts; l++) {
-
-        len = 0;
-        op = log[l].ops->elts;
-        for (i = 0; i < log[l].ops->nelts; i++) {
-            if (op[i].len == 0) {
-                len += op[i].getlen(r, op[i].data);
-
-            } else {
-                len += op[i].len;
-            }
-        }
-
-#if (NGX_WIN32)
-        len += 2;
-#else
-        len++;
-#endif
-
-        if (!(line = ngx_palloc(r->pool, len))) {
-            return NGX_ERROR;
-        }
-
-        p = line;
-
-        for (i = 0; i < log[l].ops->nelts; i++) {
-            p = op[i].run(r, p, &op[i]);
-        }
-
-#if (NGX_WIN32)
-        *p++ = CR; *p++ = LF;
-        WriteFile(log[l].file->fd, line, p - line, &written, NULL);
-#else
-        *p++ = LF;
-        write(log[l].file->fd, line, p - line);
-#endif
-    }
-
-    return NGX_OK;
-}
-
-
-static u_char *
-ngx_http_log_copy_short(ngx_http_request_t *r, u_char *buf,
-    ngx_http_log_op_t *op)
-{
-    size_t     len;
-    uintptr_t  data;
-
-    len = op->len;
-    data = op->data;
-
-    while (len--) {
-        *buf++ = (u_char) (data & 0xff);
-        data >>= 8;
-    }
-
-    return buf;
-}
-
-
-static u_char *
-ngx_http_log_copy_long(ngx_http_request_t *r, u_char *buf,
-    ngx_http_log_op_t *op)
-{
-    return ngx_cpymem(buf, (u_char *) op->data, op->len);
-}
-
-
-static u_char *
-ngx_http_log_addr(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
-{
-    return ngx_cpymem(buf, r->connection->addr_text.data,
-                      r->connection->addr_text.len);
-}
-
-
-static u_char *
-ngx_http_log_connection(ngx_http_request_t *r, u_char *buf,
-    ngx_http_log_op_t *op)
-{
-    return ngx_sprintf(buf, "%ui", r->connection->number);
-}
-
-
-static u_char *
-ngx_http_log_pipe(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
-{
-    if (r->pipeline) {
-        *buf = 'p';
-    } else {
-        *buf = '.';
-    }
-
-    return buf + 1;
-}
-
-
-static u_char *
-ngx_http_log_time(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
-{
-    return ngx_cpymem(buf, ngx_cached_http_log_time.data,
-                      ngx_cached_http_log_time.len);
-}
-
-
-static u_char *
-ngx_http_log_msec(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
-{
-    struct timeval  tv;
-
-    ngx_gettimeofday(&tv);
-
-    return ngx_sprintf(buf, "%l.%03l", tv.tv_sec, tv.tv_usec / 1000);
-}
-
-
-static u_char *
-ngx_http_log_request_time(ngx_http_request_t *r, u_char *buf,
-    ngx_http_log_op_t *op)
-{
-    time_t  elapsed;
-
-    elapsed = ngx_time() - r->start_time;
-
-    return ngx_sprintf(buf, "%T", elapsed);
-}
-
-
-static size_t
-ngx_http_log_request_getlen(ngx_http_request_t *r, uintptr_t data)
-{
-    return r->request_line.len;
-}
-
-
-static u_char *
-ngx_http_log_request(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
-{
-    return ngx_cpymem(buf, r->request_line.data, r->request_line.len);
-}
-
-
-static u_char *
-ngx_http_log_status(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
-{
-    return ngx_sprintf(buf, "%ui",
-                       r->err_status ? r->err_status : r->headers_out.status);
-}
-
-
-static u_char *
-ngx_http_log_length(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
-{
-    return ngx_sprintf(buf, "%O", r->connection->sent);
-}
-
-
-static u_char *
-ngx_http_log_apache_length(ngx_http_request_t *r, u_char *buf,
-    ngx_http_log_op_t *op)
-{
-    off_t  length;
-
-    length = r->connection->sent - r->header_size;
-
-    if (length > 0) {
-        return ngx_sprintf(buf, "%O", length);
-    }
-
-    *buf = '0';
-
-    return buf + 1;
-}
-
-
-static u_char *
-ngx_http_log_request_length(ngx_http_request_t *r, u_char *buf,
-    ngx_http_log_op_t *op)
-{
-    return ngx_sprintf(buf, "%z", r->request_length);
-}
-
-
-static ngx_int_t
-ngx_http_log_header_in_compile(ngx_http_log_op_t *op, ngx_str_t *value)
-{
-    ngx_uint_t  i;
-
-    op->len = 0;
-
-    for (i = 0; ngx_http_headers_in[i].name.len != 0; i++) {
-
-        if (ngx_http_headers_in[i].name.len != value->len) {
-            continue;
-        }
-
-        if (ngx_strncasecmp(ngx_http_headers_in[i].name.data, value->data,
-                                                              value->len) == 0)
-        {
-            op->getlen = ngx_http_log_header_in_getlen;
-            op->run = ngx_http_log_header_in;
-            op->data = ngx_http_headers_in[i].offset;
-
-            return NGX_OK;
-        }
-    }
-
-    op->getlen = ngx_http_log_unknown_header_in_getlen;
-    op->run = ngx_http_log_unknown_header_in;
-    op->data = (uintptr_t) value;
-
-    return NGX_OK;
-}
-
-
-static size_t
-ngx_http_log_header_in_getlen(ngx_http_request_t *r, uintptr_t data)
-{
-    ngx_table_elt_t  *h;
-
-    h = *(ngx_table_elt_t **) ((char *) &r->headers_in + data);
-
-    if (h) {
-        return h->value.len;
-    }
-
-    return 1;
-}
-
-
-static u_char *
-ngx_http_log_header_in(ngx_http_request_t *r, u_char *buf,
-    ngx_http_log_op_t *op)
-{
-    ngx_table_elt_t  *h;
-
-    h = *(ngx_table_elt_t **) ((char *) &r->headers_in + op->data);
-
-    if (h) {
-        return ngx_cpymem(buf, h->value.data, h->value.len);
-    }
-
-    *buf = '-';
-
-    return buf + 1;
-}
-
-
-static size_t
-ngx_http_log_unknown_header_in_getlen(ngx_http_request_t *r, uintptr_t data)
-{
-    ngx_table_elt_t  *h;
-
-    h = ngx_http_log_unknown_header(&r->headers_in.headers, (ngx_str_t *) data);
-
-    if (h) {
-        return h->value.len;
-    }
-
-    return 1;
-}
-
-
-static u_char *
-ngx_http_log_unknown_header_in(ngx_http_request_t *r, u_char *buf,
-    ngx_http_log_op_t *op)
-{
-    ngx_table_elt_t  *h;
-
-    h = ngx_http_log_unknown_header(&r->headers_in.headers,
-                                    (ngx_str_t *) op->data);
-
-    if (h) {
-        return ngx_cpymem(buf, h->value.data, h->value.len);
-    }
-
-    *buf = '-';
-
-    return buf + 1;
-}
-
-
-static ngx_int_t
-ngx_http_log_header_out_compile(ngx_http_log_op_t *op, ngx_str_t *value)
-{
-    ngx_uint_t  i;
-
-    op->len = 0;
-
-    for (i = 0; ngx_http_headers_out[i].name.len != 0; i++) {
-
-        if (ngx_http_headers_out[i].name.len != value->len) {
-            continue;
-        }
-
-        if (ngx_strncasecmp(ngx_http_headers_out[i].name.data, value->data,
-                            value->len) == 0)
-        {
-            op->getlen = ngx_http_log_header_out_getlen;
-            op->run = ngx_http_log_header_out;
-            op->data = ngx_http_headers_out[i].offset;
-
-            return NGX_OK;
-        }
-    }
-
-    if (value->len == sizeof("Connection") - 1
-        && ngx_strncasecmp(value->data, "Connection", value->len) == 0)
-    {
-        op->len = sizeof("keep-alive") - 1;
-        op->getlen = NULL;
-        op->run = ngx_http_log_connection_header_out;
-        op->data = 0;
-        return NGX_OK;
-    }
-
-    if (value->len == sizeof("Transfer-Encoding") - 1
-        && ngx_strncasecmp(value->data, "Transfer-Encoding", value->len) == 0)
-    {
-        op->len = sizeof("chunked") - 1;
-        op->getlen = NULL;
-        op->run = ngx_http_log_transfer_encoding_header_out;
-        op->data = 0;
-        return NGX_OK;
-    }
-
-    op->getlen = ngx_http_log_unknown_header_out_getlen;
-    op->run = ngx_http_log_unknown_header_out;
-    op->data = (uintptr_t) value;
-
-    return NGX_OK;
-}
-
-
-static size_t
-ngx_http_log_header_out_getlen(ngx_http_request_t *r, uintptr_t data)
-{
-    ngx_table_elt_t  *h;
-
-    h = *(ngx_table_elt_t **) ((char *) &r->headers_out + data);
-
-    if (h) {
-        return h->value.len;
-    }
-
-    /*
-     * No header pointer was found.
-     * However, some headers: "Date", "Server", "Content-Length",
-     * and "Last-Modified" have a special handling in the header filter
-     * but we do not set up their pointers in the filter because
-     * they are too seldom needed to be logged.
-     */
-
-    if (data == offsetof(ngx_http_headers_out_t, date)) {
-        return ngx_cached_http_time.len;
-    }
-
-    if (data == offsetof(ngx_http_headers_out_t, server)) {
-        return (sizeof(NGINX_VER) - 1);
-    }
-
-    if (data == offsetof(ngx_http_headers_out_t, content_length)) {
-        if (r->headers_out.content_length_n == -1) {
-            return 1;
-        }
-
-        return NGX_OFF_T_LEN;
-    }
-
-    if (data == offsetof(ngx_http_headers_out_t, last_modified)) {
-        if (r->headers_out.last_modified_time == -1) {
-            return 1;
-        }
-
-        return sizeof("Mon, 28 Sep 1970 06:00:00 GMT") - 1;
-    }
-
-    return 1;
-}
-
-
-static u_char *
-ngx_http_log_header_out(ngx_http_request_t *r, u_char *buf,
-    ngx_http_log_op_t *op)
-{
-    ngx_table_elt_t  *h;
-
-    h = *(ngx_table_elt_t **) ((char *) &r->headers_out + op->data);
-
-    if (h) {
-        return ngx_cpymem(buf, h->value.data, h->value.len);
-    }
-
-    /*
-     * No header pointer was found.
-     * However, some headers: "Date", "Server", "Content-Length",
-     * and "Last-Modified" have a special handling in the header filter
-     * but we do not set up their pointers in the filter because
-     * they are too seldom needed to be logged.
-     */
-
-    if (op->data == offsetof(ngx_http_headers_out_t, date)) {
-        return ngx_cpymem(buf, ngx_cached_http_time.data,
-                          ngx_cached_http_time.len);
-    }
-
-    if (op->data == offsetof(ngx_http_headers_out_t, server)) {
-        return ngx_cpymem(buf, NGINX_VER, sizeof(NGINX_VER) - 1);
-    }
-
-    if (op->data == offsetof(ngx_http_headers_out_t, content_length)) {
-        if (r->headers_out.content_length_n == -1) {
-            *buf = '-';
-
-            return buf + 1;
-        }
-
-        return ngx_sprintf(buf, "%O", r->headers_out.content_length_n);
-    }
-
-    if (op->data == offsetof(ngx_http_headers_out_t, last_modified)) {
-        if (r->headers_out.last_modified_time == -1) {
-            *buf = '-';
-
-            return buf + 1;
-        }
-
-        return ngx_http_time(buf, r->headers_out.last_modified_time);
-    }
-
-    *buf = '-';
-
-    return buf + 1;
-}
-
-
-static size_t
-ngx_http_log_unknown_header_out_getlen(ngx_http_request_t *r, uintptr_t data)
-{
-    ngx_table_elt_t  *h;
-
-    h = ngx_http_log_unknown_header(&r->headers_out.headers,
-                                    (ngx_str_t *) data);
-
-    if (h) {
-        return h->value.len;
-    }
-
-    return 1;
-}
-
-
-static u_char *
-ngx_http_log_unknown_header_out(ngx_http_request_t *r, u_char *buf,
-    ngx_http_log_op_t *op)
-{
-    ngx_table_elt_t  *h;
-
-    h = ngx_http_log_unknown_header(&r->headers_out.headers,
-                                    (ngx_str_t *) op->data);
-
-    if (h) {
-        return ngx_cpymem(buf, h->value.data, h->value.len);
-    }
-
-    *buf = '-';
-
-    return buf + 1;
-}
-
-
-static ngx_table_elt_t *
-ngx_http_log_unknown_header(ngx_list_t *headers, ngx_str_t *value)
-{
-    ngx_uint_t        i;
-    ngx_list_part_t  *part;
-    ngx_table_elt_t  *h;
-
-    part = &headers->part;
-    h = part->elts;
-
-    for (i = 0; /* void */; i++) {
-
-        if (i >= part->nelts) {
-            if (part->next == NULL) {
-                break;
-            }
-
-            part = part->next;
-            h = part->elts;
-            i = 0;
-        }
-
-        if (h[i].key.len != value->len) {
-            continue;
-        }
-
-        if (ngx_strncasecmp(h[i].key.data, value->data, value->len) == 0) {
-            return &h[i];
-        }
-    }
-
-    return NULL;
-}
-
-
-static u_char *
-ngx_http_log_connection_header_out(ngx_http_request_t *r, u_char *buf,
-    ngx_http_log_op_t *op)
-{
-    if (r->keepalive) {
-        return ngx_cpymem(buf, "keep-alive", sizeof("keep-alive") - 1);
-
-    } else {
-        return ngx_cpymem(buf, "close", sizeof("close") - 1);
-    }
-}
-
-
-static u_char *
-ngx_http_log_transfer_encoding_header_out(ngx_http_request_t *r, u_char *buf,
-    ngx_http_log_op_t *op)
-{
-    if (r->chunked) {
-        return ngx_cpymem(buf, "chunked", sizeof("chunked") - 1);
-    }
-
-    *buf = '-';
-
-    return buf + 1;
-}
-
-
-static ngx_int_t
-ngx_http_log_set_formats(ngx_conf_t *cf)
-{
-    ngx_http_log_op_name_t  *op;
-
-    for (op = ngx_http_log_fmt_ops; op->name.len; op++) { /* void */ }
-    op->run = NULL;
-
-    return NGX_OK;
-}
-
-
-static void *
-ngx_http_log_create_main_conf(ngx_conf_t *cf)
-{
-    ngx_http_log_main_conf_t  *conf;
-
-    char       *rc;
-    ngx_str_t  *value;
-
-    if (!(conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_log_main_conf_t)))) {
-        return NGX_CONF_ERROR;
-    }
-
-    if (ngx_array_init(&conf->formats, cf->pool, 4, sizeof(ngx_http_log_fmt_t))
-                                                                  == NGX_ERROR)
-    {
-        return NGX_CONF_ERROR;
-    }
-
-    cf->args->nelts = 0;
-
-    if (!(value = ngx_array_push(cf->args))) {
-        return NGX_CONF_ERROR;
-    }
-
-    if (!(value = ngx_array_push(cf->args))) {
-        return NGX_CONF_ERROR;
-    }
-
-    value->len = sizeof("combined") - 1;
-    value->data = (u_char *) "combined";
-
-    if (!(value = ngx_array_push(cf->args))) {
-        return NGX_CONF_ERROR;
-    }
-
-    *value = ngx_http_combined_fmt;
-
-    rc = ngx_http_log_set_format(cf, NULL, conf);
-    if (rc != NGX_CONF_OK) {
-        return NULL;
-    }
-
-    return conf;
-}
-
-
-static void *
-ngx_http_log_create_loc_conf(ngx_conf_t *cf)
-{
-    ngx_http_log_loc_conf_t  *conf;
-
-    if (!(conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_log_loc_conf_t)))) {
-        return NGX_CONF_ERROR;
-    }
-
-    return conf;
-}
-
-
-static char *
-ngx_http_log_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
-{
-    ngx_http_log_loc_conf_t *prev = parent;
-    ngx_http_log_loc_conf_t *conf = child;
-
-    ngx_http_log_t            *log;
-    ngx_http_log_fmt_t        *fmt;
-    ngx_http_log_main_conf_t  *lmcf;
-
-    if (conf->logs == NULL) {
-
-        if (conf->off) {
-            return NGX_CONF_OK;
-        }
-
-        if (prev->logs) {
-            conf->logs = prev->logs;
-
-        } else {
-
-            if (prev->off) {
-                conf->off = prev->off;
-                return NGX_CONF_OK;
-            }
-
-            conf->logs = ngx_array_create(cf->pool, 2, sizeof(ngx_http_log_t));
-            if (conf->logs == NULL) {
-                return NGX_CONF_ERROR;
-            }
-
-            if (!(log = ngx_array_push(conf->logs))) {
-                return NGX_CONF_ERROR;
-            }
-
-            log->file = ngx_conf_open_file(cf->cycle, &http_access_log);
-            if (log->file == NULL) {
-                return NGX_CONF_ERROR;
-            }
-
-            lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_log_module);
-            fmt = lmcf->formats.elts;
-
-            /* the default "combined" format */
-            log->ops = fmt[0].ops;
-        }
-    }
-
-    return NGX_CONF_OK;
-}
-
-
-static char *
-ngx_http_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
-    ngx_http_log_loc_conf_t *llcf = conf;
-
-    ngx_uint_t                 i;
-    ngx_str_t                 *value, name;
-    ngx_http_log_t            *log;
-    ngx_http_log_fmt_t        *fmt;
-    ngx_http_log_main_conf_t  *lmcf;
-
-    value = cf->args->elts;
-
-    if (ngx_strcmp(value[1].data, "off") == 0) {
-        llcf->off = 1;
-        return NGX_CONF_OK;
-    }
-
-    if (llcf->logs == NULL) {
-        llcf->logs = ngx_array_create(cf->pool, 2, sizeof(ngx_http_log_t));
-        if (llcf->logs == NULL) {
-            return NGX_CONF_ERROR;
-        }
-    }
-
-    lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_log_module);
-
-    if (!(log = ngx_array_push(llcf->logs))) {
-        return NGX_CONF_ERROR;
-    }
-
-    if (!(log->file = ngx_conf_open_file(cf->cycle, &value[1]))) {
-        return NGX_CONF_ERROR;
-    }
-
-    if (cf->args->nelts == 3) {
-        name = value[2];
-    } else {
-        name.len = sizeof("combined") - 1;
-        name.data = (u_char *) "combined";
-    }
-
-    fmt = lmcf->formats.elts;
-    for (i = 0; i < lmcf->formats.nelts; i++) {
-        if (fmt[i].name.len == name.len
-            && ngx_strcasecmp(fmt[i].name.data, name.data) == 0)
-        {
-            log->ops = fmt[i].ops;
-            return NGX_CONF_OK;
-        }
-    }
-
-    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                       "unknown log format \"%V\"", &name);
-
-    return NGX_CONF_ERROR;
-}
-
-
-static char *
-ngx_http_log_set_format(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
-{
-    ngx_http_log_main_conf_t *lmcf = conf;
-
-    ngx_uint_t                  s, f, invalid;
-    u_char                     *data, *p, *fname;
-    size_t                      i, len, fname_len;
-    ngx_str_t                  *value, arg, *a;
-    ngx_http_log_op_t          *op;
-    ngx_http_log_fmt_t         *fmt;
-    ngx_http_log_op_name_t     *name;
-
-    value = cf->args->elts;
-
-    fmt = lmcf->formats.elts;
-    for (f = 0; f < lmcf->formats.nelts; f++) {
-        if (fmt[f].name.len == value[1].len
-            && ngx_strcmp(fmt->name.data, value[1].data) == 0)
-        {
-            return "duplicate \"log_format\" name";
-        }
-    }
-
-    if (!(fmt = ngx_push_array(&lmcf->formats))) {
-        return NGX_CONF_ERROR;
-    }
-
-    fmt->name = value[1];
-
-    if (!(fmt->ops = ngx_array_create(cf->pool, 20, sizeof(ngx_http_log_op_t))))
-    {
-        return NGX_CONF_ERROR;
-    }
-
-    invalid = 0;
-    data = NULL;
-
-    for (s = 2; s < cf->args->nelts && !invalid; s++) {
-
-        i = 0;
-
-        while (i < value[s].len) {
-
-            if (!(op = ngx_push_array(fmt->ops))) {
-                return NGX_CONF_ERROR;
-            }
-
-            data = &value[s].data[i];
-
-            if (value[s].data[i] == '%') {
-                i++;
-
-                if (i == value[s].len) {
-                    invalid = 1;
-                    break;
-                }
-
-                if (value[s].data[i] == '{') {
-                    i++;
-
-                    arg.data = &value[s].data[i];
-
-                    while (i < value[s].len && value[s].data[i] != '}') {
-                        i++;
-                    }
-
-                    arg.len = &value[s].data[i] - arg.data;
-
-                    if (i == value[s].len || arg.len == 0) {
-                        invalid = 1;
-                        break;
-                    }
-
-                    i++;
-
-                } else {
-                    arg.len = 0;
-                }
-
-                fname = &value[s].data[i];
-
-                while (i < value[s].len
-                       && ((value[s].data[i] >= 'a' && value[s].data[i] <= 'z')
-                           || value[s].data[i] == '_'))
-                {
-                    i++;
-                }
-
-                fname_len = &value[s].data[i] - fname;
-
-                if (fname_len == 0) {
-                    invalid = 1;
-                    break;
-                }
-
-                for (name = ngx_http_log_fmt_ops; name->run; name++) {
-                    if (name->name.len == 0) {
-                        name = (ngx_http_log_op_name_t *) name->run;
-                    }
-
-                    if (name->name.len == fname_len
-                        && ngx_strncmp(name->name.data, fname, fname_len) == 0)
-                    {
-                        if (name->compile == NULL) {
-                            if (arg.len) {
-                                fname[fname_len] = '\0';
-                                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                                               "\"%s\" must not have argument",
-                                               data);
-                                return NGX_CONF_ERROR;
-                            }
-
-                            op->len = name->len;
-                            op->getlen = name->getlen;
-                            op->run = name->run;
-                            op->data = 0;
-
-                            break;
-                        }
-
-                        if (arg.len == 0) {
-                            fname[fname_len] = '\0';
-                            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                                               "\"%s\" requires argument", 
-                                               data);
-                            return NGX_CONF_ERROR;
-                        }
-
-                        if (!(a = ngx_palloc(cf->pool, sizeof(ngx_str_t)))) {
-                            return NGX_CONF_ERROR;
-                        }
-
-                        *a = arg;
-                        if (name->compile(op, a) == NGX_ERROR) {
-                            return NGX_CONF_ERROR;
-                        }
-
-                        break;
-                    }
-                }
-
-                if (name->name.len == 0) {
-                    invalid = 1;
-                    break;
-                }
-
-            } else {
-                i++;
-
-                while (i < value[s].len && value[s].data[i] != '%') {
-                    i++;
-                }
-
-                len = &value[s].data[i] - data;
-
-                if (len) {
-
-                    op->len = len;
-                    op->getlen = NULL;
-
-                    if (len <= sizeof(uintptr_t)) {
-                        op->run = ngx_http_log_copy_short;
-                        op->data = 0;
-
-                        while (len--) {
-                            op->data <<= 8;
-                            op->data |= data[len];
-                        }
-
-                    } else {
-                        op->run = ngx_http_log_copy_long;
-
-                        if (!(p = ngx_palloc(cf->pool, len))) {
-                            return NGX_CONF_ERROR;
-                        }
-
-                        ngx_memcpy(p, data, len);
-                        op->data = (uintptr_t) p;
-                    }
-                }
-            }
-        }
-    }
-
-    if (invalid) {
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                           "invalid parameter \"%s\"", data);
-        return NGX_CONF_ERROR;
-    }
-
-    return NGX_CONF_OK;
-}
deleted file mode 100644
--- a/src/http/ngx_http_log_handler.h
+++ /dev/null
@@ -1,70 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- */
-
-
-#ifndef _NGX_HTTP_LOG_HANDLER_H_INCLUDED_
-#define _NGX_HTTP_LOG_HANDLER_H_INCLUDED_
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-typedef struct ngx_http_log_op_s  ngx_http_log_op_t;
-
-typedef u_char *(*ngx_http_log_op_run_pt) (ngx_http_request_t *r, u_char *buf,
-                                           ngx_http_log_op_t *op);
-
-typedef size_t (*ngx_http_log_op_getlen_pt) (ngx_http_request_t *r,
-                                             uintptr_t data);
-
-typedef ngx_int_t (*ngx_http_log_op_compile_pt) (ngx_http_log_op_t *op,
-                                                 ngx_str_t *value);
-
-struct ngx_http_log_op_s {
-    size_t                      len;
-    ngx_http_log_op_getlen_pt   getlen;
-    ngx_http_log_op_run_pt      run;
-    uintptr_t                   data;
-};
-
-
-typedef struct {
-    ngx_str_t                   name;
-    ngx_array_t                *ops;        /* array of ngx_http_log_op_t */
-} ngx_http_log_fmt_t;
-
-
-typedef struct {
-    ngx_str_t                   name;
-    size_t                      len;
-    ngx_http_log_op_compile_pt  compile;
-    ngx_http_log_op_getlen_pt   getlen;
-    ngx_http_log_op_run_pt      run;
-} ngx_http_log_op_name_t;
-
-
-typedef struct {
-    ngx_array_t                 formats;    /* array of ngx_http_log_fmt_t */
-} ngx_http_log_main_conf_t;
-
-
-typedef struct {
-    ngx_open_file_t            *file;
-    ngx_array_t                *ops;        /* array of ngx_http_log_op_t */
-} ngx_http_log_t;
-
-
-typedef struct {
-    ngx_array_t                *logs;       /* array of ngx_http_log_t */
-    ngx_uint_t                  off;        /* unsigned  off:1 */
-} ngx_http_log_loc_conf_t;
-
-
-extern ngx_http_log_op_name_t ngx_http_log_fmt_ops[];
-
-
-#endif /* _NGX_HTTP_LOG_HANDLER_H_INCLUDED_ */
new file mode 100644
--- /dev/null
+++ b/src/http/ngx_http_log_module.c
@@ -0,0 +1,1181 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+#include <nginx.h>
+
+
+static u_char *ngx_http_log_addr(ngx_http_request_t *r, u_char *buf,
+    ngx_http_log_op_t *op);
+static u_char *ngx_http_log_connection(ngx_http_request_t *r, u_char *buf,
+    ngx_http_log_op_t *op);
+static u_char *ngx_http_log_pipe(ngx_http_request_t *r, u_char *buf,
+    ngx_http_log_op_t *op);
+static u_char *ngx_http_log_time(ngx_http_request_t *r, u_char *buf,
+    ngx_http_log_op_t *op);
+static u_char *ngx_http_log_msec(ngx_http_request_t *r, u_char *buf,
+    ngx_http_log_op_t *op);
+static u_char *ngx_http_log_request_time(ngx_http_request_t *r, u_char *buf,
+    ngx_http_log_op_t *op);
+static u_char *ngx_http_log_status(ngx_http_request_t *r, u_char *buf,
+    ngx_http_log_op_t *op);
+static u_char *ngx_http_log_length(ngx_http_request_t *r, u_char *buf,
+    ngx_http_log_op_t *op);
+static u_char *ngx_http_log_apache_length(ngx_http_request_t *r, u_char *buf,
+    ngx_http_log_op_t *op);
+static u_char *ngx_http_log_request_length(ngx_http_request_t *r, u_char *buf,
+    ngx_http_log_op_t *op);
+
+static size_t ngx_http_log_request_getlen(ngx_http_request_t *r,
+    uintptr_t data);
+static u_char *ngx_http_log_request(ngx_http_request_t *r, u_char *buf,
+    ngx_http_log_op_t *op);
+
+static ngx_int_t ngx_http_log_header_in_compile(ngx_conf_t *cf,
+    ngx_http_log_op_t *op, ngx_str_t *value);
+static size_t ngx_http_log_header_in_getlen(ngx_http_request_t *r,
+    uintptr_t data);
+static u_char *ngx_http_log_header_in(ngx_http_request_t *r, u_char *buf,
+    ngx_http_log_op_t *op);
+static size_t ngx_http_log_unknown_header_in_getlen(ngx_http_request_t *r,
+    uintptr_t data);
+static u_char *ngx_http_log_unknown_header_in(ngx_http_request_t *r,
+    u_char *buf, ngx_http_log_op_t *op);
+
+static ngx_int_t ngx_http_log_header_out_compile(ngx_conf_t *cf,
+    ngx_http_log_op_t *op, ngx_str_t *value);
+static size_t ngx_http_log_header_out_getlen(ngx_http_request_t *r,
+    uintptr_t data);
+static u_char *ngx_http_log_header_out(ngx_http_request_t *r, u_char *buf,
+    ngx_http_log_op_t *op);
+static size_t ngx_http_log_unknown_header_out_getlen(ngx_http_request_t *r,
+    uintptr_t data);
+static u_char *ngx_http_log_unknown_header_out(ngx_http_request_t *r,
+    u_char *buf, ngx_http_log_op_t *op);
+
+static u_char *ngx_http_log_connection_header_out(ngx_http_request_t *r,
+    u_char *buf, ngx_http_log_op_t *op);
+static u_char *ngx_http_log_transfer_encoding_header_out(ngx_http_request_t *r,
+    u_char *buf, ngx_http_log_op_t *op);
+
+static ngx_table_elt_t *ngx_http_log_unknown_header(ngx_list_t *headers,
+    ngx_str_t *value);
+
+static ngx_int_t ngx_http_log_variable_compile(ngx_conf_t *cf,
+    ngx_http_log_op_t *op, ngx_str_t *value);
+static size_t ngx_http_log_variable_getlen(ngx_http_request_t *r,
+    uintptr_t data);
+static u_char *ngx_http_log_variable(ngx_http_request_t *r, u_char *buf,
+    ngx_http_log_op_t *op);
+
+
+static ngx_int_t ngx_http_log_set_formats(ngx_conf_t *cf);
+static void *ngx_http_log_create_main_conf(ngx_conf_t *cf);
+static void *ngx_http_log_create_loc_conf(ngx_conf_t *cf);
+static char *ngx_http_log_merge_loc_conf(ngx_conf_t *cf, void *parent,
+    void *child);
+static char *ngx_http_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd,
+    void *conf);
+static char *ngx_http_log_set_format(ngx_conf_t *cf, ngx_command_t *cmd,
+    void *conf);
+
+
+static ngx_command_t  ngx_http_log_commands[] = {
+
+    { ngx_string("log_format"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_2MORE,
+      ngx_http_log_set_format,
+      NGX_HTTP_MAIN_CONF_OFFSET,
+      0,
+      NULL },
+
+    { ngx_string("access_log"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
+      ngx_http_log_set_log,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      0,
+      NULL },
+
+      ngx_null_command
+};
+
+
+ngx_http_module_t  ngx_http_log_module_ctx = {
+    ngx_http_log_set_formats,              /* pre conf */
+
+    ngx_http_log_create_main_conf,         /* create main configuration */
+    NULL,                                  /* init main configuration */
+
+    NULL,                                  /* create server configuration */
+    NULL,                                  /* merge server configuration */
+
+    ngx_http_log_create_loc_conf,          /* create location configration */
+    ngx_http_log_merge_loc_conf            /* merge location configration */
+};
+
+
+ngx_module_t  ngx_http_log_module = {
+    NGX_MODULE,
+    &ngx_http_log_module_ctx,              /* module context */
+    ngx_http_log_commands,                 /* module directives */
+    NGX_HTTP_MODULE,                       /* module type */
+    NULL,                                  /* init module */
+    NULL                                   /* init process */
+};
+
+
+static ngx_str_t http_access_log = ngx_string(NGX_HTTP_LOG_PATH);
+
+
+static ngx_str_t ngx_http_combined_fmt =
+    ngx_string("%addr - - [%time] \"%request\" %status %apache_length "
+               "\"%{Referer}i\" \"%{User-Agent}i\"");
+
+
+ngx_http_log_op_name_t ngx_http_log_fmt_ops[] = {
+    { ngx_string("addr"), INET_ADDRSTRLEN - 1, NULL, NULL, ngx_http_log_addr },
+    { ngx_string("conn"), NGX_ATOMIC_T_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 +0600") - 1,
+                          NULL, NULL, ngx_http_log_time },
+    { ngx_string("msec"), NGX_TIME_T_LEN + 4, NULL, NULL, ngx_http_log_msec },
+    { ngx_string("request_time"), NGX_TIME_T_LEN, NULL, NULL,
+                          ngx_http_log_request_time },
+    { ngx_string("status"), 3, NULL, NULL, ngx_http_log_status },
+    { ngx_string("length"), NGX_OFF_T_LEN, NULL, NULL, ngx_http_log_length },
+    { ngx_string("apache_length"), NGX_OFF_T_LEN,
+                          NULL, NULL, ngx_http_log_apache_length },
+    { ngx_string("request_length"), NGX_SIZE_T_LEN,
+                          NULL, NULL, ngx_http_log_request_length },
+
+    { ngx_string("request"), 0, NULL,
+                          ngx_http_log_request_getlen,
+                          ngx_http_log_request },
+
+    { ngx_string("i"), 0, ngx_http_log_header_in_compile, NULL,
+                          ngx_http_log_header_in },
+    { ngx_string("o"), 0, ngx_http_log_header_out_compile, NULL,
+                          ngx_http_log_header_out },
+    { ngx_string("v"), 0, ngx_http_log_variable_compile, NULL,
+                          ngx_http_log_variable },
+
+    { ngx_null_string, 0, NULL, NULL, NULL }
+};
+
+
+ngx_int_t
+ngx_http_log_handler(ngx_http_request_t *r)
+{
+    ngx_uint_t                i, l;
+    u_char                   *line, *p;
+    size_t                    len;
+    ngx_http_log_t           *log;
+    ngx_http_log_op_t        *op;
+    ngx_http_log_loc_conf_t  *lcf;
+#if (NGX_WIN32)
+    u_long                    written;
+#endif
+
+    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                   "http log handler");
+
+    lcf = ngx_http_get_module_loc_conf(r, ngx_http_log_module);
+
+    if (lcf->off) {
+        return NGX_OK;
+    }
+
+    log = lcf->logs->elts;
+    for (l = 0; l < lcf->logs->nelts; l++) {
+
+        len = 0;
+        op = log[l].ops->elts;
+        for (i = 0; i < log[l].ops->nelts; i++) {
+            if (op[i].len == 0) {
+                len += op[i].getlen(r, op[i].data);
+
+            } else {
+                len += op[i].len;
+            }
+        }
+
+#if (NGX_WIN32)
+        len += 2;
+#else
+        len++;
+#endif
+
+        line = ngx_palloc(r->pool, len);
+        if (line == NULL) {
+            return NGX_ERROR;
+        }
+
+        p = line;
+
+        for (i = 0; i < log[l].ops->nelts; i++) {
+            p = op[i].run(r, p, &op[i]);
+        }
+
+#if (NGX_WIN32)
+        *p++ = CR; *p++ = LF;
+        WriteFile(log[l].file->fd, line, p - line, &written, NULL);
+#else
+        *p++ = LF;
+        write(log[l].file->fd, line, p - line);
+#endif
+    }
+
+    return NGX_OK;
+}
+
+
+static u_char *
+ngx_http_log_copy_short(ngx_http_request_t *r, u_char *buf,
+    ngx_http_log_op_t *op)
+{
+    size_t     len;
+    uintptr_t  data;
+
+    len = op->len;
+    data = op->data;
+
+    while (len--) {
+        *buf++ = (u_char) (data & 0xff);
+        data >>= 8;
+    }
+
+    return buf;
+}
+
+
+static u_char *
+ngx_http_log_copy_long(ngx_http_request_t *r, u_char *buf,
+    ngx_http_log_op_t *op)
+{
+    return ngx_cpymem(buf, (u_char *) op->data, op->len);
+}
+
+
+static u_char *
+ngx_http_log_addr(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
+{
+    return ngx_cpymem(buf, r->connection->addr_text.data,
+                      r->connection->addr_text.len);
+}
+
+
+static u_char *
+ngx_http_log_connection(ngx_http_request_t *r, u_char *buf,
+    ngx_http_log_op_t *op)
+{
+    return ngx_sprintf(buf, "%ui", r->connection->number);
+}
+
+
+static u_char *
+ngx_http_log_pipe(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
+{
+    if (r->pipeline) {
+        *buf = 'p';
+    } else {
+        *buf = '.';
+    }
+
+    return buf + 1;
+}
+
+
+static u_char *
+ngx_http_log_time(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
+{
+    return ngx_cpymem(buf, ngx_cached_http_log_time.data,
+                      ngx_cached_http_log_time.len);
+}
+
+
+static u_char *
+ngx_http_log_msec(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
+{
+    struct timeval  tv;
+
+    ngx_gettimeofday(&tv);
+
+    return ngx_sprintf(buf, "%l.%03l", tv.tv_sec, tv.tv_usec / 1000);
+}
+
+
+static u_char *
+ngx_http_log_request_time(ngx_http_request_t *r, u_char *buf,
+    ngx_http_log_op_t *op)
+{
+    time_t  elapsed;
+
+    elapsed = ngx_time() - r->start_time;
+
+    return ngx_sprintf(buf, "%T", elapsed);
+}
+
+
+static size_t
+ngx_http_log_request_getlen(ngx_http_request_t *r, uintptr_t data)
+{
+    return r->request_line.len;
+}
+
+
+static u_char *
+ngx_http_log_request(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
+{
+    return ngx_cpymem(buf, r->request_line.data, r->request_line.len);
+}
+
+
+static u_char *
+ngx_http_log_status(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
+{
+    return ngx_sprintf(buf, "%ui",
+                       r->err_status ? r->err_status : r->headers_out.status);
+}
+
+
+static u_char *
+ngx_http_log_length(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
+{
+    return ngx_sprintf(buf, "%O", r->connection->sent);
+}
+
+
+static u_char *
+ngx_http_log_apache_length(ngx_http_request_t *r, u_char *buf,
+    ngx_http_log_op_t *op)
+{
+    off_t  length;
+
+    length = r->connection->sent - r->header_size;
+
+    if (length > 0) {
+        return ngx_sprintf(buf, "%O", length);
+    }
+
+    *buf = '0';
+
+    return buf + 1;
+}
+
+
+static u_char *
+ngx_http_log_request_length(ngx_http_request_t *r, u_char *buf,
+    ngx_http_log_op_t *op)
+{
+    return ngx_sprintf(buf, "%z", r->request_length);
+}
+
+
+static ngx_int_t
+ngx_http_log_header_in_compile(ngx_conf_t *cf, ngx_http_log_op_t *op,
+    ngx_str_t *value)
+{
+    ngx_uint_t  i;
+
+    op->len = 0;
+
+    for (i = 0; ngx_http_headers_in[i].name.len != 0; i++) {
+
+        if (ngx_http_headers_in[i].name.len != value->len) {
+            continue;
+        }
+
+        if (ngx_strncasecmp(ngx_http_headers_in[i].name.data, value->data,
+                            value->len) == 0)
+        {
+            op->getlen = ngx_http_log_header_in_getlen;
+            op->run = ngx_http_log_header_in;
+            op->data = ngx_http_headers_in[i].offset;
+
+            return NGX_OK;
+        }
+    }
+
+    op->getlen = ngx_http_log_unknown_header_in_getlen;
+    op->run = ngx_http_log_unknown_header_in;
+    op->data = (uintptr_t) value;
+
+    return NGX_OK;
+}
+
+
+static size_t
+ngx_http_log_header_in_getlen(ngx_http_request_t *r, uintptr_t data)
+{
+    ngx_table_elt_t  *h;
+
+    h = *(ngx_table_elt_t **) ((char *) &r->headers_in + data);
+
+    if (h) {
+        return h->value.len;
+    }
+
+    return 1;
+}
+
+
+static u_char *
+ngx_http_log_header_in(ngx_http_request_t *r, u_char *buf,
+    ngx_http_log_op_t *op)
+{
+    ngx_table_elt_t  *h;
+
+    h = *(ngx_table_elt_t **) ((char *) &r->headers_in + op->data);
+
+    if (h) {
+        return ngx_cpymem(buf, h->value.data, h->value.len);
+    }
+
+    *buf = '-';
+
+    return buf + 1;
+}
+
+
+static size_t
+ngx_http_log_unknown_header_in_getlen(ngx_http_request_t *r, uintptr_t data)
+{
+    ngx_table_elt_t  *h;
+
+    h = ngx_http_log_unknown_header(&r->headers_in.headers, (ngx_str_t *) data);
+
+    if (h) {
+        return h->value.len;
+    }
+
+    return 1;
+}
+
+
+static u_char *
+ngx_http_log_unknown_header_in(ngx_http_request_t *r, u_char *buf,
+    ngx_http_log_op_t *op)
+{
+    ngx_table_elt_t  *h;
+
+    h = ngx_http_log_unknown_header(&r->headers_in.headers,
+                                    (ngx_str_t *) op->data);
+
+    if (h) {
+        return ngx_cpymem(buf, h->value.data, h->value.len);
+    }
+
+    *buf = '-';
+
+    return buf + 1;
+}
+
+
+static ngx_int_t
+ngx_http_log_header_out_compile(ngx_conf_t *cf, ngx_http_log_op_t *op,
+    ngx_str_t *value)
+{
+    ngx_uint_t  i;
+
+    op->len = 0;
+
+    for (i = 0; ngx_http_headers_out[i].name.len != 0; i++) {
+
+        if (ngx_http_headers_out[i].name.len != value->len) {
+            continue;
+        }
+
+        if (ngx_strncasecmp(ngx_http_headers_out[i].name.data, value->data,
+                            value->len) == 0)
+        {
+            op->getlen = ngx_http_log_header_out_getlen;
+            op->run = ngx_http_log_header_out;
+            op->data = ngx_http_headers_out[i].offset;
+
+            return NGX_OK;
+        }
+    }
+
+    if (value->len == sizeof("Connection") - 1
+        && ngx_strncasecmp(value->data, "Connection", value->len) == 0)
+    {
+        op->len = sizeof("keep-alive") - 1;
+        op->getlen = NULL;
+        op->run = ngx_http_log_connection_header_out;
+        op->data = 0;
+        return NGX_OK;
+    }
+
+    if (value->len == sizeof("Transfer-Encoding") - 1
+        && ngx_strncasecmp(value->data, "Transfer-Encoding", value->len) == 0)
+    {
+        op->len = sizeof("chunked") - 1;
+        op->getlen = NULL;
+        op->run = ngx_http_log_transfer_encoding_header_out;
+        op->data = 0;
+        return NGX_OK;
+    }
+
+    op->getlen = ngx_http_log_unknown_header_out_getlen;
+    op->run = ngx_http_log_unknown_header_out;
+    op->data = (uintptr_t) value;
+
+    return NGX_OK;
+}
+
+
+static size_t
+ngx_http_log_header_out_getlen(ngx_http_request_t *r, uintptr_t data)
+{
+    ngx_table_elt_t  *h;
+
+    h = *(ngx_table_elt_t **) ((char *) &r->headers_out + data);
+
+    if (h) {
+        return h->value.len;
+    }
+
+    /*
+     * No header pointer was found.
+     * However, some headers: "Date", "Server", "Content-Length",
+     * and "Last-Modified" have a special handling in the header filter
+     * but we do not set up their pointers in the filter because
+     * they are too seldom needed to be logged.
+     */
+
+    if (data == offsetof(ngx_http_headers_out_t, date)) {
+        return ngx_cached_http_time.len;
+    }
+
+    if (data == offsetof(ngx_http_headers_out_t, server)) {
+        return (sizeof(NGINX_VER) - 1);
+    }
+
+    if (data == offsetof(ngx_http_headers_out_t, content_length)) {
+        if (r->headers_out.content_length_n == -1) {
+            return 1;
+        }
+
+        return NGX_OFF_T_LEN;
+    }
+
+    if (data == offsetof(ngx_http_headers_out_t, last_modified)) {
+        if (r->headers_out.last_modified_time == -1) {
+            return 1;
+        }
+
+        return sizeof("Mon, 28 Sep 1970 06:00:00 GMT") - 1;
+    }
+
+    return 1;
+}
+
+
+static u_char *
+ngx_http_log_header_out(ngx_http_request_t *r, u_char *buf,
+    ngx_http_log_op_t *op)
+{
+    ngx_table_elt_t  *h;
+
+    h = *(ngx_table_elt_t **) ((char *) &r->headers_out + op->data);
+
+    if (h) {
+        return ngx_cpymem(buf, h->value.data, h->value.len);
+    }
+
+    /*
+     * No header pointer was found.
+     * However, some headers: "Date", "Server", "Content-Length",
+     * and "Last-Modified" have a special handling in the header filter
+     * but we do not set up their pointers in the filter because
+     * they are too seldom needed to be logged.
+     */
+
+    if (op->data == offsetof(ngx_http_headers_out_t, date)) {
+        return ngx_cpymem(buf, ngx_cached_http_time.data,
+                          ngx_cached_http_time.len);
+    }
+
+    if (op->data == offsetof(ngx_http_headers_out_t, server)) {
+        return ngx_cpymem(buf, NGINX_VER, sizeof(NGINX_VER) - 1);
+    }
+
+    if (op->data == offsetof(ngx_http_headers_out_t, content_length)) {
+        if (r->headers_out.content_length_n == -1) {
+            *buf = '-';
+
+            return buf + 1;
+        }
+
+        return ngx_sprintf(buf, "%O", r->headers_out.content_length_n);
+    }
+
+    if (op->data == offsetof(ngx_http_headers_out_t, last_modified)) {
+        if (r->headers_out.last_modified_time == -1) {
+            *buf = '-';
+
+            return buf + 1;
+        }
+
+        return ngx_http_time(buf, r->headers_out.last_modified_time);
+    }
+
+    *buf = '-';
+
+    return buf + 1;
+}
+
+
+static size_t
+ngx_http_log_unknown_header_out_getlen(ngx_http_request_t *r, uintptr_t data)
+{
+    ngx_table_elt_t  *h;
+
+    h = ngx_http_log_unknown_header(&r->headers_out.headers,
+                                    (ngx_str_t *) data);
+
+    if (h) {
+        return h->value.len;
+    }
+
+    return 1;
+}
+
+
+static u_char *
+ngx_http_log_unknown_header_out(ngx_http_request_t *r, u_char *buf,
+    ngx_http_log_op_t *op)
+{
+    ngx_table_elt_t  *h;
+
+    h = ngx_http_log_unknown_header(&r->headers_out.headers,
+                                    (ngx_str_t *) op->data);
+
+    if (h) {
+        return ngx_cpymem(buf, h->value.data, h->value.len);
+    }
+
+    *buf = '-';
+
+    return buf + 1;
+}
+
+
+static ngx_table_elt_t *
+ngx_http_log_unknown_header(ngx_list_t *headers, ngx_str_t *value)
+{
+    ngx_uint_t        i;
+    ngx_list_part_t  *part;
+    ngx_table_elt_t  *h;
+
+    part = &headers->part;
+    h = part->elts;
+
+    for (i = 0; /* void */; i++) {
+
+        if (i >= part->nelts) {
+            if (part->next == NULL) {
+                break;
+            }
+
+            part = part->next;
+            h = part->elts;
+            i = 0;
+        }
+
+        if (h[i].key.len != value->len) {
+            continue;
+        }
+
+        if (ngx_strncasecmp(h[i].key.data, value->data, value->len) == 0) {
+            return &h[i];
+        }
+    }
+
+    return NULL;
+}
+
+
+static u_char *
+ngx_http_log_connection_header_out(ngx_http_request_t *r, u_char *buf,
+    ngx_http_log_op_t *op)
+{
+    if (r->keepalive) {
+        return ngx_cpymem(buf, "keep-alive", sizeof("keep-alive") - 1);
+
+    } else {
+        return ngx_cpymem(buf, "close", sizeof("close") - 1);
+    }
+}
+
+
+static u_char *
+ngx_http_log_transfer_encoding_header_out(ngx_http_request_t *r, u_char *buf,
+    ngx_http_log_op_t *op)
+{
+    if (r->chunked) {
+        return ngx_cpymem(buf, "chunked", sizeof("chunked") - 1);
+    }
+
+    *buf = '-';
+
+    return buf + 1;
+}
+
+
+static ngx_int_t 
+ngx_http_log_variable_compile(ngx_conf_t *cf, ngx_http_log_op_t *op,
+    ngx_str_t *value)
+{
+    ngx_uint_t            i;
+    ngx_http_variable_t  *var;
+
+    for (i = 0; i < value->len; i++) {
+        value->data[i] = ngx_toupper(value->data[i]);
+    }
+
+    var = ngx_http_add_variable(cf, value, 0);
+    if (var == NULL) {
+        return NGX_ERROR;
+    }
+
+    op->len = 0;
+    op->getlen = ngx_http_log_variable_getlen;
+    op->run = ngx_http_log_variable;
+    op->data = var->index;
+
+    return NGX_OK;
+}
+
+
+static size_t
+ngx_http_log_variable_getlen(ngx_http_request_t *r, uintptr_t data)
+{
+    ngx_http_variable_value_t  *value;
+
+    value = ngx_http_get_indexed_variable(r, data);
+
+    if (value == NULL
+        || value == NGX_HTTP_VARIABLE_NOT_FOUND
+        || value->text.len == 0)
+    {
+        return 1;
+    }
+
+    return value->text.len;
+}
+
+
+static u_char *
+ngx_http_log_variable(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op)
+{
+    ngx_http_variable_value_t  *value;
+
+    value = ngx_http_get_indexed_variable(r, op->data);
+
+    if (value == NULL
+        || value == NGX_HTTP_VARIABLE_NOT_FOUND
+        || value->text.len == 0)
+    {
+        *buf = '-';
+        return buf + 1;
+    }
+
+    return ngx_cpymem(buf, value->text.data, value->text.len);
+}
+
+
+static ngx_int_t
+ngx_http_log_set_formats(ngx_conf_t *cf)
+{
+    ngx_http_log_op_name_t  *op;
+
+    for (op = ngx_http_log_fmt_ops; op->name.len; op++) { /* void */ }
+    op->run = NULL;
+
+    return NGX_OK;
+}
+
+
+static void *
+ngx_http_log_create_main_conf(ngx_conf_t *cf)
+{
+    ngx_http_log_main_conf_t  *conf;
+
+    char       *rc;
+    ngx_str_t  *value;
+
+    conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_log_main_conf_t));
+    if (conf == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    if (ngx_array_init(&conf->formats, cf->pool, 4, sizeof(ngx_http_log_fmt_t))
+                                                                  == NGX_ERROR)
+    {
+        return NGX_CONF_ERROR;
+    }
+
+    cf->args->nelts = 0;
+
+    value = ngx_array_push(cf->args);
+    if (value == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    value = ngx_array_push(cf->args);
+    if (value == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    value->len = sizeof("combined") - 1;
+    value->data = (u_char *) "combined";
+
+    value = ngx_array_push(cf->args);
+    if (value == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    *value = ngx_http_combined_fmt;
+
+    rc = ngx_http_log_set_format(cf, NULL, conf);
+    if (rc != NGX_CONF_OK) {
+        return NULL;
+    }
+
+    return conf;
+}
+
+
+static void *
+ngx_http_log_create_loc_conf(ngx_conf_t *cf)
+{
+    ngx_http_log_loc_conf_t  *conf;
+
+    conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_log_loc_conf_t));
+    if (conf == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    return conf;
+}
+
+
+static char *
+ngx_http_log_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
+{
+    ngx_http_log_loc_conf_t *prev = parent;
+    ngx_http_log_loc_conf_t *conf = child;
+
+    ngx_http_log_t            *log;
+    ngx_http_log_fmt_t        *fmt;
+    ngx_http_log_main_conf_t  *lmcf;
+
+    if (conf->logs == NULL) {
+
+        if (conf->off) {
+            return NGX_CONF_OK;
+        }
+
+        if (prev->logs) {
+            conf->logs = prev->logs;
+
+        } else {
+
+            if (prev->off) {
+                conf->off = prev->off;
+                return NGX_CONF_OK;
+            }
+
+            conf->logs = ngx_array_create(cf->pool, 2, sizeof(ngx_http_log_t));
+            if (conf->logs == NULL) {
+                return NGX_CONF_ERROR;
+            }
+
+            log = ngx_array_push(conf->logs);
+            if (log == NULL) {
+                return NGX_CONF_ERROR;
+            }
+
+            log->file = ngx_conf_open_file(cf->cycle, &http_access_log);
+            if (log->file == NULL) {
+                return NGX_CONF_ERROR;
+            }
+
+            lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_log_module);
+            fmt = lmcf->formats.elts;
+
+            /* the default "combined" format */
+            log->ops = fmt[0].ops;
+        }
+    }
+
+    return NGX_CONF_OK;
+}
+
+
+static char *
+ngx_http_log_set_log(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+    ngx_http_log_loc_conf_t *llcf = conf;
+
+    ngx_uint_t                 i;
+    ngx_str_t                 *value, name;
+    ngx_http_log_t            *log;
+    ngx_http_log_fmt_t        *fmt;
+    ngx_http_log_main_conf_t  *lmcf;
+
+    value = cf->args->elts;
+
+    if (ngx_strcmp(value[1].data, "off") == 0) {
+        llcf->off = 1;
+        return NGX_CONF_OK;
+    }
+
+    if (llcf->logs == NULL) {
+        llcf->logs = ngx_array_create(cf->pool, 2, sizeof(ngx_http_log_t));
+        if (llcf->logs == NULL) {
+            return NGX_CONF_ERROR;
+        }
+    }
+
+    lmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_log_module);
+
+    log = ngx_array_push(llcf->logs);
+    if (log == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    log->file = ngx_conf_open_file(cf->cycle, &value[1]);
+    if (log->file == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    if (cf->args->nelts == 3) {
+        name = value[2];
+    } else {
+        name.len = sizeof("combined") - 1;
+        name.data = (u_char *) "combined";
+    }
+
+    fmt = lmcf->formats.elts;
+    for (i = 0; i < lmcf->formats.nelts; i++) {
+        if (fmt[i].name.len == name.len
+            && ngx_strcasecmp(fmt[i].name.data, name.data) == 0)
+        {
+            log->ops = fmt[i].ops;
+            return NGX_CONF_OK;
+        }
+    }
+
+    ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                       "unknown log format \"%V\"", &name);
+
+    return NGX_CONF_ERROR;
+}
+
+
+static char *
+ngx_http_log_set_format(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+    ngx_http_log_main_conf_t *lmcf = conf;
+
+    ngx_uint_t                  s, f, invalid;
+    u_char                     *data, *p, *fname;
+    size_t                      i, len, fname_len;
+    ngx_str_t                  *value, arg, *a;
+    ngx_http_log_op_t          *op;
+    ngx_http_log_fmt_t         *fmt;
+    ngx_http_log_op_name_t     *name;
+
+    value = cf->args->elts;
+
+    fmt = lmcf->formats.elts;
+    for (f = 0; f < lmcf->formats.nelts; f++) {
+        if (fmt[f].name.len == value[1].len
+            && ngx_strcmp(fmt->name.data, value[1].data) == 0)
+        {
+            return "duplicate \"log_format\" name";
+        }
+    }
+
+    fmt = ngx_array_push(&lmcf->formats);
+    if (fmt == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    fmt->name = value[1];
+
+    fmt->ops = ngx_array_create(cf->pool, 20, sizeof(ngx_http_log_op_t));
+    if (fmt->ops == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    invalid = 0;
+    data = NULL;
+    arg.data = NULL;
+
+    for (s = 2; s < cf->args->nelts && !invalid; s++) {
+
+        i = 0;
+
+        while (i < value[s].len) {
+
+            op = ngx_array_push(fmt->ops);
+            if (op == NULL) {
+                return NGX_CONF_ERROR;
+            }
+
+            data = &value[s].data[i];
+
+            if (value[s].data[i] == '%') {
+                i++;
+
+                if (i == value[s].len) {
+                    invalid = 1;
+                    break;
+                }
+
+                if (value[s].data[i] == '{') {
+                    i++;
+
+                    arg.data = &value[s].data[i];
+
+                    while (i < value[s].len && value[s].data[i] != '}') {
+                        i++;
+                    }
+
+                    arg.len = &value[s].data[i] - arg.data;
+
+                    if (i == value[s].len || arg.len == 0) {
+                        invalid = 1;
+                        break;
+                    }
+
+                    i++;
+
+                } else {
+                    arg.len = 0;
+                }
+
+                fname = &value[s].data[i];
+
+                while (i < value[s].len
+                       && ((value[s].data[i] >= 'a' && value[s].data[i] <= 'z')
+                           || value[s].data[i] == '_'))
+                {
+                    i++;
+                }
+
+                fname_len = &value[s].data[i] - fname;
+
+                if (fname_len == 0) {
+                    invalid = 1;
+                    break;
+                }
+
+                for (name = ngx_http_log_fmt_ops; name->run; name++) {
+                    if (name->name.len == 0) {
+                        name = (ngx_http_log_op_name_t *) name->run;
+                    }
+
+                    if (name->name.len == fname_len
+                        && ngx_strncmp(name->name.data, fname, fname_len) == 0)
+                    {
+                        if (name->compile == NULL) {
+                            if (arg.len) {
+                                fname[fname_len] = '\0';
+                                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                                               "\"%s\" must not have argument",
+                                               data);
+                                return NGX_CONF_ERROR;
+                            }
+
+                            op->len = name->len;
+                            op->getlen = name->getlen;
+                            op->run = name->run;
+                            op->data = 0;
+
+                            break;
+                        }
+
+                        if (arg.len == 0) {
+                            fname[fname_len] = '\0';
+                            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                                               "\"%s\" requires argument", 
+                                               data);
+                            return NGX_CONF_ERROR;
+                        }
+
+                        a = ngx_palloc(cf->pool, sizeof(ngx_str_t));
+                        if (a == NULL) {
+                            return NGX_CONF_ERROR;
+                        }
+
+                        *a = arg;
+                        if (name->compile(cf, op, a) == NGX_ERROR) {
+                            return NGX_CONF_ERROR;
+                        }
+
+                        break;
+                    }
+                }
+
+                if (name->name.len == 0) {
+                    invalid = 1;
+                    break;
+                }
+
+            } else {
+                i++;
+
+                while (i < value[s].len && value[s].data[i] != '%') {
+                    i++;
+                }
+
+                len = &value[s].data[i] - data;
+
+                if (len) {
+
+                    op->len = len;
+                    op->getlen = NULL;
+
+                    if (len <= sizeof(uintptr_t)) {
+                        op->run = ngx_http_log_copy_short;
+                        op->data = 0;
+
+                        while (len--) {
+                            op->data <<= 8;
+                            op->data |= data[len];
+                        }
+
+                    } else {
+                        op->run = ngx_http_log_copy_long;
+
+                        p = ngx_palloc(cf->pool, len);
+                        if (p == NULL) {
+                            return NGX_CONF_ERROR;
+                        }
+
+                        ngx_memcpy(p, data, len);
+                        op->data = (uintptr_t) p;
+                    }
+                }
+            }
+        }
+    }
+
+    if (invalid) {
+        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                           "invalid parameter \"%s\"", data);
+        return NGX_CONF_ERROR;
+    }
+
+    return NGX_CONF_OK;
+}
new file mode 100644
--- /dev/null
+++ b/src/http/ngx_http_log_module.h
@@ -0,0 +1,71 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#ifndef _NGX_HTTP_LOG_MODULE_H_INCLUDED_
+#define _NGX_HTTP_LOG_MODULE_H_INCLUDED_
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+
+
+typedef struct ngx_http_log_op_s  ngx_http_log_op_t;
+
+typedef u_char *(*ngx_http_log_op_run_pt) (ngx_http_request_t *r, u_char *buf,
+    ngx_http_log_op_t *op);
+
+typedef size_t (*ngx_http_log_op_getlen_pt) (ngx_http_request_t *r,
+    uintptr_t data);
+
+typedef ngx_int_t (*ngx_http_log_op_compile_pt) (ngx_conf_t *cf,
+    ngx_http_log_op_t *op, ngx_str_t *value);
+
+
+struct ngx_http_log_op_s {
+    size_t                      len;
+    ngx_http_log_op_getlen_pt   getlen;
+    ngx_http_log_op_run_pt      run;
+    uintptr_t                   data;
+};
+
+
+typedef struct {
+    ngx_str_t                   name;
+    ngx_array_t                *ops;        /* array of ngx_http_log_op_t */
+} ngx_http_log_fmt_t;
+
+
+typedef struct {
+    ngx_str_t                   name;
+    size_t                      len;
+    ngx_http_log_op_compile_pt  compile;
+    ngx_http_log_op_getlen_pt   getlen;
+    ngx_http_log_op_run_pt      run;
+} ngx_http_log_op_name_t;
+
+
+typedef struct {
+    ngx_array_t                 formats;    /* array of ngx_http_log_fmt_t */
+} ngx_http_log_main_conf_t;
+
+
+typedef struct {
+    ngx_open_file_t            *file;
+    ngx_array_t                *ops;        /* array of ngx_http_log_op_t */
+} ngx_http_log_t;
+
+
+typedef struct {
+    ngx_array_t                *logs;       /* array of ngx_http_log_t */
+    ngx_uint_t                  off;        /* unsigned  off:1 */
+} ngx_http_log_loc_conf_t;
+
+
+extern ngx_http_log_op_name_t ngx_http_log_fmt_ops[];
+
+
+#endif /* _NGX_HTTP_LOG_MODULE_H_INCLUDED_ */
--- a/src/http/ngx_http_parse.c
+++ b/src/http/ngx_http_parse.c
@@ -461,7 +461,6 @@ ngx_int_t ngx_http_parse_request_line(ng
             default:
                 return NGX_HTTP_PARSE_INVALID_REQUEST;
             }
-            break;
         }
     }
 
@@ -646,7 +645,6 @@ ngx_int_t ngx_http_parse_header_line(ngx
             default:
                 return NGX_HTTP_PARSE_INVALID_HEADER;
             }
-            break;
 
         /* end of header */
         case sw_header_almost_done:
@@ -656,7 +654,6 @@ ngx_int_t ngx_http_parse_header_line(ngx
             default:
                 return NGX_HTTP_PARSE_INVALID_HEADER;
             }
-            break;
         }
     }
 
--- a/src/http/ngx_http_parse_time.c
+++ b/src/http/ngx_http_parse_time.c
@@ -229,10 +229,14 @@ time_t ngx_http_parse_time(u_char *value
         return NGX_ERROR;
     }
 
-    if (sizeof(time_t) <= 4 && year >= 2038) {
+#if (NGX_TIME_T_SIZE <= 4)
+
+    if (year >= 2038) {
         return NGX_ERROR;
     }
 
+#endif
+
     /*
      * shift new year to March 1 and start months from 1 (not 0),
      * it is needed for Gauss's formula
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -18,7 +18,7 @@ static void ngx_http_process_request_lin
 static void ngx_http_process_request_headers(ngx_event_t *rev);
 static ssize_t ngx_http_read_request_header(ngx_http_request_t *r);
 static ngx_int_t ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
-                                                    ngx_uint_t request_line);
+    ngx_uint_t request_line);
 static ngx_int_t ngx_http_process_request_header(ngx_http_request_t *r);
 static ngx_int_t ngx_http_find_virtual_server(ngx_http_request_t *r);
 
@@ -34,7 +34,7 @@ static void ngx_http_set_lingering_close
 static void ngx_http_lingering_close_handler(ngx_event_t *ev);
 
 static void ngx_http_client_error(ngx_http_request_t *r,
-                                  int client_error, int error);
+    int client_error, int error);
 static u_char *ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len);
 
 
@@ -100,19 +100,22 @@ ngx_http_header_t  ngx_http_headers_in[]
 
 
 #if 0
-static void ngx_http_dummy(ngx_event_t *wev)
+static void
+ngx_http_dummy(ngx_event_t *wev)
 {
     return;
 }
 #endif
 
 
-void ngx_http_init_connection(ngx_connection_t *c)
+void
+ngx_http_init_connection(ngx_connection_t *c)
 {
     ngx_event_t         *rev;
     ngx_http_log_ctx_t  *ctx;
 
-    if (!(ctx = ngx_palloc(c->pool, sizeof(ngx_http_log_ctx_t)))) {
+    ctx = ngx_palloc(c->pool, sizeof(ngx_http_log_ctx_t));
+    if (ctx == NULL) {
         ngx_http_close_connection(c);
         return;
     }
@@ -186,7 +189,8 @@ void ngx_http_init_connection(ngx_connec
 }
 
 
-static void ngx_http_init_request(ngx_event_t *rev)
+static
+void ngx_http_init_request(ngx_event_t *rev)
 {
     ngx_uint_t                 i;
     socklen_t                  len;
@@ -225,7 +229,8 @@ static void ngx_http_init_request(ngx_ev
 #endif
 
     } else {
-        if (!(hc = ngx_pcalloc(c->pool, sizeof(ngx_http_connection_t)))) {
+        hc = ngx_pcalloc(c->pool, sizeof(ngx_http_connection_t));
+        if (hc == NULL) {
 
 #if (NGX_STAT_STUB)
             ngx_atomic_dec(ngx_stat_reading);
@@ -248,7 +253,8 @@ static void ngx_http_init_request(ngx_ev
         }
 
     } else {
-        if (!(r = ngx_pcalloc(c->pool, sizeof(ngx_http_request_t)))) {
+        r = ngx_pcalloc(c->pool, sizeof(ngx_http_request_t));
+        if (r == NULL) {
 
 #if (NGX_STAT_STUB)
             ngx_atomic_dec(ngx_stat_reading);
@@ -388,7 +394,8 @@ static void ngx_http_init_request(ngx_ev
         r->header_in = c->buffer;
     }
 
-    if (!(r->pool = ngx_create_pool(cscf->request_pool_size, c->log))) {
+    r->pool = ngx_create_pool(cscf->request_pool_size, c->log);
+    if (r->pool == NULL) {
         ngx_http_close_connection(c);
         return;
     }
@@ -444,7 +451,8 @@ static void ngx_http_init_request(ngx_ev
 
 #if (NGX_HTTP_SSL)
 
-static void ngx_http_ssl_handshake(ngx_event_t *rev)
+static void
+ngx_http_ssl_handshake(ngx_event_t *rev)
 {
     u_char               buf[1];
     ssize_t              n;
@@ -504,7 +512,8 @@ static void ngx_http_ssl_handshake(ngx_e
 #endif
 
 
-static void ngx_http_process_request_line(ngx_event_t *rev)
+static void
+ngx_http_process_request_line(ngx_event_t *rev)
 {
     ssize_t              n;
     ngx_int_t            rc, rv;
@@ -554,7 +563,8 @@ static void ngx_http_process_request_lin
 
             if (r->complex_uri || r->quoted_uri) {
 
-                if (!(r->uri.data = ngx_palloc(r->pool, r->uri.len + 1))) {
+                r->uri.data = ngx_palloc(r->pool, r->uri.len + 1);
+                if (r->uri.data == NULL) {
                     ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
                     ngx_http_close_connection(c);
                     return;
@@ -707,7 +717,8 @@ static void ngx_http_process_request_lin
 }
 
 
-static void ngx_http_process_request_headers(ngx_event_t *rev)
+static void
+ngx_http_process_request_headers(ngx_event_t *rev)
 {
     ssize_t              n;
     ngx_int_t            rc, rv, i;
@@ -764,7 +775,8 @@ static void ngx_http_process_request_hea
 
             r->headers_n++;
 
-            if (!(h = ngx_list_push(&r->headers_in.headers))) {
+            h = ngx_list_push(&r->headers_in.headers);
+            if (h == NULL) {
                 ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
                 ngx_http_close_connection(c);
                 return;
@@ -781,7 +793,8 @@ static void ngx_http_process_request_hea
             if (h->key.len == sizeof("Cookie") - 1
                 && ngx_strcasecmp(h->key.data, "Cookie") == 0)
             {
-                if (!(cookie = ngx_array_push(&r->headers_in.cookies))) {
+                cookie = ngx_array_push(&r->headers_in.cookies);
+                if (cookie == NULL) {
                     ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
                     ngx_http_close_connection(c);
                     return;
@@ -879,7 +892,8 @@ static void ngx_http_process_request_hea
 }
 
 
-static ssize_t ngx_http_read_request_header(ngx_http_request_t *r)
+static ssize_t
+ngx_http_read_request_header(ngx_http_request_t *r)
 {
     ssize_t                    n;
     ngx_event_t               *rev;
@@ -933,8 +947,9 @@ static ssize_t ngx_http_read_request_hea
 }
 
 
-static ngx_int_t ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
-                                                    ngx_uint_t request_line)
+static ngx_int_t
+ngx_http_alloc_large_header_buffer(ngx_http_request_t *r,
+    ngx_uint_t request_line)
 {
     u_char                    *old, *new;
     ngx_buf_t                 *b;
@@ -1076,7 +1091,8 @@ static ngx_int_t ngx_http_alloc_large_he
 }
 
 
-static ngx_int_t ngx_http_process_request_header(ngx_http_request_t *r)
+static ngx_int_t
+ngx_http_process_request_header(ngx_http_request_t *r)
 {
     u_char  *ua, *user_agent, ch;
     size_t   len;
@@ -1106,7 +1122,7 @@ static ngx_int_t ngx_http_process_reques
 
     if (r->headers_in.content_length) {
         r->headers_in.content_length_n =
-                             ngx_atoi(r->headers_in.content_length->value.data,
+                            ngx_atosz(r->headers_in.content_length->value.data,
                                       r->headers_in.content_length->value.len);
 
         if (r->headers_in.content_length_n == NGX_ERROR) {
@@ -1137,7 +1153,7 @@ static ngx_int_t ngx_http_process_reques
 
             if (r->headers_in.keep_alive) {
                 r->headers_in.keep_alive_n =
-                                 ngx_atoi(r->headers_in.keep_alive->value.data,
+                                ngx_atotm(r->headers_in.keep_alive->value.data,
                                           r->headers_in.keep_alive->value.len);
             }
         }
@@ -1191,7 +1207,8 @@ static ngx_int_t ngx_http_process_reques
 }
 
 
-static ngx_int_t ngx_http_find_virtual_server(ngx_http_request_t *r)
+static ngx_int_t
+ngx_http_find_virtual_server(ngx_http_request_t *r)
 {
     ngx_int_t                   rc;
     ngx_uint_t                  i, n, key, found;
@@ -1297,7 +1314,8 @@ static ngx_int_t ngx_http_find_virtual_s
 }
 
 
-void ngx_http_finalize_request(ngx_http_request_t *r, int rc)
+void
+ngx_http_finalize_request(ngx_http_request_t *r, int rc)
 {
     ngx_http_core_loc_conf_t  *clcf;
 
@@ -1380,7 +1398,8 @@ void ngx_http_finalize_request(ngx_http_
 }
 
 
-static void ngx_http_set_write_handler(ngx_http_request_t *r)
+static void
+ngx_http_set_write_handler(ngx_http_request_t *r)
 {
     ngx_event_t               *wev;
     ngx_http_core_loc_conf_t  *clcf;
@@ -1409,7 +1428,8 @@ static void ngx_http_set_write_handler(n
 }
 
 
-void ngx_http_writer(ngx_event_t *wev)
+void
+ngx_http_writer(ngx_event_t *wev)
 {
     int                        rc;
     ngx_connection_t          *c;
@@ -1486,7 +1506,8 @@ void ngx_http_writer(ngx_event_t *wev)
 }
 
 
-static void ngx_http_block_read(ngx_event_t *rev)
+static void
+ngx_http_block_read(ngx_event_t *rev)
 {
     ngx_connection_t          *c;
     ngx_http_request_t        *r;
@@ -1506,7 +1527,8 @@ static void ngx_http_block_read(ngx_even
 }
 
 
-ngx_int_t ngx_http_discard_body(ngx_http_request_t *r)
+ngx_int_t
+ngx_http_discard_body(ngx_http_request_t *r)
 {
     ssize_t       size;
     ngx_event_t  *rev;
@@ -1546,7 +1568,8 @@ ngx_int_t ngx_http_discard_body(ngx_http
 }
 
 
-static void ngx_http_read_discarded_body_event(ngx_event_t *rev)
+static void
+ngx_http_read_discarded_body_event(ngx_event_t *rev)
 {
     ngx_int_t            rc;
     ngx_connection_t    *c;
@@ -1572,7 +1595,8 @@ static void ngx_http_read_discarded_body
 }
 
 
-static ngx_int_t ngx_http_read_discarded_body(ngx_http_request_t *r)
+static ngx_int_t
+ngx_http_read_discarded_body(ngx_http_request_t *r)
 {
     ssize_t  size, n;
     u_char   buffer[NGX_HTTP_DISCARD_BUFFER_SIZE];
@@ -1615,7 +1639,8 @@ static ngx_int_t ngx_http_read_discarded
 }
 
 
-static void ngx_http_set_keepalive(ngx_http_request_t *r)
+static void
+ngx_http_set_keepalive(ngx_http_request_t *r)
 {
     int                        tcp_nodelay;
     ngx_int_t                  i;
@@ -1776,7 +1801,7 @@ static void ngx_http_set_keepalive(ngx_h
     c->log->action = "keepalive";
 
     if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
-        if (ngx_tcp_push(c->fd) == NGX_ERROR) {
+        if (ngx_tcp_push(c->fd) == -1) {
             ngx_connection_error(c, ngx_socket_errno, ngx_tcp_push_n " failed");
             ngx_http_close_connection(c);
             return;
@@ -1818,13 +1843,13 @@ static void ngx_http_set_keepalive(ngx_h
 }
 
 
-static void ngx_http_keepalive_handler(ngx_event_t *rev)
+static void
+ngx_http_keepalive_handler(ngx_event_t *rev)
 {
-    size_t                  size;
-    ssize_t                 n;
-    ngx_buf_t              *b;
-    ngx_connection_t       *c;
-    ngx_http_connection_t  *hc;
+    size_t             size;
+    ssize_t            n;
+    ngx_buf_t         *b;
+    ngx_connection_t  *c;
 
     c = rev->data;
 
@@ -1855,7 +1880,6 @@ static void ngx_http_keepalive_handler(n
 
 #endif
 
-    hc = c->data;
     b = c->buffer;
     size = b->end - b->start;
 
@@ -1867,7 +1891,8 @@ static void ngx_http_keepalive_handler(n
          * to keep the buffer size.
          */
 
-        if (!(b->pos = ngx_palloc(c->pool, size))) {
+        b->pos = ngx_palloc(c->pool, size);
+        if (b->pos == NULL) {
             ngx_http_close_connection(c);
             return;
         }
@@ -1919,7 +1944,8 @@ static void ngx_http_keepalive_handler(n
 }
 
 
-static void ngx_http_set_lingering_close(ngx_http_request_t *r)
+static void
+ngx_http_set_lingering_close(ngx_http_request_t *r)
 {   
     ngx_event_t               *rev, *wev;
     ngx_connection_t          *c;
@@ -1977,7 +2003,8 @@ static void ngx_http_set_lingering_close
 }
 
 
-static void ngx_http_lingering_close_handler(ngx_event_t *rev)
+static void
+ngx_http_lingering_close_handler(ngx_event_t *rev)
 {
     ssize_t                    n;
     ngx_msec_t                 timer;
@@ -2036,7 +2063,8 @@ static void ngx_http_lingering_close_han
 }
 
 
-void ngx_http_empty_handler(ngx_event_t *wev)
+void
+ngx_http_empty_handler(ngx_event_t *wev)
 {
     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0, "http empty handler");
 
@@ -2044,12 +2072,14 @@ void ngx_http_empty_handler(ngx_event_t 
 }
 
 
-ngx_int_t ngx_http_send_last(ngx_http_request_t *r)
+ngx_int_t
+ngx_http_send_last(ngx_http_request_t *r)
 {
     ngx_buf_t    *b;
     ngx_chain_t   out;
 
-    if (!(b = ngx_calloc_buf(r->pool))) {
+    b = ngx_calloc_buf(r->pool);
+    if (b == NULL) {
         return NGX_ERROR;
     }
 
@@ -2061,7 +2091,8 @@ ngx_int_t ngx_http_send_last(ngx_http_re
 }
 
 
-void ngx_http_close_request(ngx_http_request_t *r, int error)
+void
+ngx_http_close_request(ngx_http_request_t *r, int error)
 {
     ngx_uint_t                 i;
     ngx_log_t                 *log;
@@ -2171,7 +2202,8 @@ void ngx_http_close_request(ngx_http_req
 
 #if (NGX_HTTP_SSL)
 
-void ngx_ssl_close_handler(ngx_event_t *ev)
+void
+ngx_ssl_close_handler(ngx_event_t *ev)
 {
     ngx_connection_t  *c;
 
@@ -2189,7 +2221,8 @@ void ngx_ssl_close_handler(ngx_event_t *
 #endif
 
 
-void ngx_http_close_connection(ngx_connection_t *c)
+void
+ngx_http_close_connection(ngx_connection_t *c)
 {
     ngx_pool_t  *pool;
 
@@ -2216,12 +2249,12 @@ void ngx_http_close_connection(ngx_conne
 
     ngx_close_connection(c);
 
-    ngx_destroy_pool(c->pool);
+    ngx_destroy_pool(pool);
 }
 
 
-static void ngx_http_client_error(ngx_http_request_t *r,
-                                  int client_error, int error)
+static void
+ngx_http_client_error(ngx_http_request_t *r, int client_error, int error)
 {
     u_char                    *p;
     ngx_http_log_ctx_t        *ctx;
@@ -2315,7 +2348,8 @@ static void ngx_http_client_error(ngx_ht
 }
 
 
-static u_char *ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len)
+static u_char *
+ngx_http_log_error(ngx_log_t *log, u_char *buf, size_t len)
 {
     u_char              *p;
     ngx_http_log_ctx_t  *ctx;
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -119,91 +119,91 @@ typedef enum {
 
 
 typedef struct {
-    ngx_str_t         name;
-    ngx_uint_t        offset;
+    ngx_str_t                         name;
+    ngx_uint_t                        offset;
 } ngx_http_header_t;
 
 
 typedef struct {
-    ngx_list_t        headers;
+    ngx_list_t                        headers;
 
-    ngx_table_elt_t  *host;
-    ngx_table_elt_t  *connection;
-    ngx_table_elt_t  *if_modified_since;
-    ngx_table_elt_t  *user_agent;
-    ngx_table_elt_t  *referer;
-    ngx_table_elt_t  *content_length;
-    ngx_table_elt_t  *content_type;
+    ngx_table_elt_t                  *host;
+    ngx_table_elt_t                  *connection;
+    ngx_table_elt_t                  *if_modified_since;
+    ngx_table_elt_t                  *user_agent;
+    ngx_table_elt_t                  *referer;
+    ngx_table_elt_t                  *content_length;
+    ngx_table_elt_t                  *content_type;
 
-    ngx_table_elt_t  *range;
+    ngx_table_elt_t                  *range;
 
 #if (NGX_HTTP_GZIP)
-    ngx_table_elt_t  *accept_encoding;
-    ngx_table_elt_t  *via;
+    ngx_table_elt_t                  *accept_encoding;
+    ngx_table_elt_t                  *via;
 #endif
 
-    ngx_table_elt_t  *authorization;
+    ngx_table_elt_t                  *authorization;
 
-    ngx_table_elt_t  *keep_alive;
+    ngx_table_elt_t                  *keep_alive;
 
 #if (NGX_HTTP_PROXY)
-    ngx_table_elt_t  *x_forwarded_for;
-    ngx_table_elt_t  *x_real_ip;
-    ngx_table_elt_t  *x_url;
+    ngx_table_elt_t                  *x_forwarded_for;
+    ngx_table_elt_t                  *x_real_ip;
+    ngx_table_elt_t                  *x_url;
 #endif
 
 #if (NGX_HTTP_HEADERS)
-    ngx_table_elt_t  *accept;
-    ngx_table_elt_t  *accept_language;
+    ngx_table_elt_t                  *accept;
+    ngx_table_elt_t                  *accept_language;
 #endif
 
-    ngx_array_t       cookies;
+    ngx_array_t                       cookies;
+
+    size_t                            host_name_len;
+    ssize_t                           content_length_n;
+    time_t                            keep_alive_n;
 
-    size_t            host_name_len;
-    ssize_t           content_length_n;
-    size_t            connection_type;
-    ssize_t           keep_alive_n;
-
-    unsigned          msie:1;
-    unsigned          msie4:1;
-    unsigned          opera:1;
-    unsigned          gecko:1;
-    unsigned          konqueror:1;
+    unsigned                          connection_type:2;
+    unsigned                          msie:1;
+    unsigned                          msie4:1;
+    unsigned                          opera:1;
+    unsigned                          gecko:1;
+    unsigned                          konqueror:1;
 } ngx_http_headers_in_t;
 
 
 typedef struct {
-    off_t             start;
-    off_t             end;
-    ngx_str_t         content_range;
+    off_t                             start;
+    off_t                             end;
+    ngx_str_t                         content_range;
 } ngx_http_range_t;
 
 
 typedef struct {
-    ngx_list_t        headers;
+    ngx_list_t                        headers;
 
-    ngx_uint_t        status;
-    ngx_str_t         status_line;
+    ngx_uint_t                        status;
+    ngx_str_t                         status_line;
 
-    ngx_table_elt_t  *server;
-    ngx_table_elt_t  *date;
-    ngx_table_elt_t  *content_type;
-    ngx_table_elt_t  *content_length;
-    ngx_table_elt_t  *content_encoding;
-    ngx_table_elt_t  *location;
-    ngx_table_elt_t  *last_modified;
-    ngx_table_elt_t  *content_range;
-    ngx_table_elt_t  *accept_ranges;
-    ngx_table_elt_t  *expires;
-    ngx_table_elt_t  *cache_control;
-    ngx_table_elt_t  *etag;
+    ngx_table_elt_t                  *server;
+    ngx_table_elt_t                  *date;
+    ngx_table_elt_t                  *content_type;
+    ngx_table_elt_t                  *content_length;
+    ngx_table_elt_t                  *content_encoding;
+    ngx_table_elt_t                  *location;
+    ngx_table_elt_t                  *last_modified;
+    ngx_table_elt_t                  *content_range;
+    ngx_table_elt_t                  *accept_ranges;
+    ngx_table_elt_t                  *expires;
+    ngx_table_elt_t                  *cache_control;
+    ngx_table_elt_t                  *etag;
 
-    ngx_str_t         charset;
-    ngx_array_t       ranges;
+    ngx_str_t                         charset;
+    ngx_array_t                       ranges;
 
-    off_t             content_length_n;
-    time_t            date_time;
-    time_t            last_modified_time;
+    off_t                             content_length_n;
+    time_t                            date_time;
+    time_t                            last_modified_time;
 } ngx_http_headers_out_t;
 
 
@@ -221,172 +221,171 @@ typedef struct {
 struct ngx_http_cleanup_s {
     union {
         struct {
-            ngx_fd_t                 fd;
-            u_char                  *name;
+            ngx_fd_t                  fd;
+            u_char                   *name;
         } file;
 
         struct {
-            ngx_http_cache_hash_t   *hash;
-            ngx_http_cache_entry_t  *cache;
+            ngx_http_cache_hash_t    *hash;
+            ngx_http_cache_entry_t   *cache;
         } cache;
     } data;
 
-    unsigned                         valid:1;
-    unsigned                         cache:1;
+    unsigned                          valid:1;
+    unsigned                          cache:1;
 };
 
 
 typedef struct {
-    ngx_http_request_t   *request;
+    ngx_http_request_t               *request;
 
-    ngx_buf_t           **busy;
-    ngx_int_t             nbusy;
+    ngx_buf_t                       **busy;
+    ngx_int_t                         nbusy;
 
-    ngx_buf_t           **free;
-    ngx_int_t             nfree;
+    ngx_buf_t                       **free;
+    ngx_int_t                         nfree;
 
-    ngx_uint_t            pipeline;      /* unsigned  pipeline:1; */
+    ngx_uint_t                        pipeline;    /* unsigned  pipeline:1; */
 } ngx_http_connection_t;
 
 
 typedef ngx_int_t (*ngx_http_handler_pt)(ngx_http_request_t *r);
 
 struct ngx_http_request_s {
-    uint32_t                  signature;         /* "HTTP" */
+    uint32_t                          signature;         /* "HTTP" */
 
-    ngx_connection_t         *connection;
+    ngx_connection_t                 *connection;
 
-    void                    **ctx;
-    void                    **main_conf;
-    void                    **srv_conf;
-    void                    **loc_conf;
+    void                            **ctx;
+    void                            **main_conf;
+    void                            **srv_conf;
+    void                            **loc_conf;
 
-    ngx_http_cache_t         *cache;
+    ngx_http_cache_t                 *cache;
 
-    ngx_http_upstream_t      *upstream;
+    ngx_http_upstream_t              *upstream;
 
-    ngx_file_t                file;
+    ngx_file_t                        file;
 
-    ngx_pool_t               *pool;
-    ngx_buf_t                *header_in;
+    ngx_pool_t                       *pool;
+    ngx_buf_t                        *header_in;
 
-    ngx_http_headers_in_t     headers_in;
-    ngx_http_headers_out_t    headers_out;
+    ngx_http_headers_in_t             headers_in;
+    ngx_http_headers_out_t            headers_out;
 
-    ngx_http_request_body_t  *request_body;
+    ngx_http_request_body_t          *request_body;
 
-    time_t                    lingering_time;
-    time_t                    start_time;
+    time_t                            lingering_time;
+    time_t                            start_time;
 
-    ngx_uint_t           method;
-    ngx_uint_t           http_version;
-    ngx_uint_t           http_major;
-    ngx_uint_t           http_minor;
-
-    ngx_str_t            request_line;
-    ngx_str_t            uri;
-    ngx_str_t            args;
-    ngx_str_t            exten;
-    ngx_str_t            unparsed_uri;
-
-    ngx_str_t            method_name;
-    ngx_str_t            http_protocol;
+    ngx_uint_t                        method;
+    ngx_uint_t                        http_version;
+    ngx_uint_t                        http_major;
+    ngx_uint_t                        http_minor;
+ 
+    ngx_str_t                         request_line;
+    ngx_str_t                         uri;
+    ngx_str_t                         args;
+    ngx_str_t                         exten;
+    ngx_str_t                         unparsed_uri;
 
-    ngx_http_request_t  *main;
-
-    uint32_t             in_addr;
-    ngx_uint_t           port;
-    ngx_str_t           *port_text;    /* ":80" */
-    ngx_str_t            server_name;
-    ngx_http_in_addr_t  *virtual_names;
+    ngx_str_t                         method_name;
+    ngx_str_t                         http_protocol;
+ 
+    ngx_http_request_t               *main;
 
-    ngx_uint_t           phase;
-    ngx_int_t            phase_handler;
-    ngx_http_handler_pt  content_handler;
+    uint32_t                          in_addr;
+    ngx_uint_t                        port;
+    ngx_str_t                        *port_text;    /* ":80" */
+    ngx_str_t                         server_name;
+    ngx_http_in_addr_t               *virtual_names;
 
-    ngx_uint_t           nvariables;
-    void               **variables;
+    ngx_uint_t                        phase;
+    ngx_int_t                         phase_handler;
+    ngx_http_handler_pt               content_handler;
 
-    ngx_array_t          cleanup;
+    ngx_http_variable_value_t       **variables;
+
+    ngx_array_t                       cleanup;
 
     /* used to learn the Apache compatible response length without a header */
-    size_t               header_size;
+    size_t                            header_size;
 
-    size_t               request_length;
+    size_t                            request_length;
 
-    u_char              *discarded_buffer;
-    void               **err_ctx;
-    ngx_uint_t           err_status;
+    u_char                           *discarded_buffer;
+    void                            **err_ctx;
+    ngx_uint_t                        err_status;
 
-    ngx_http_connection_t  *http_connection;
+    ngx_http_connection_t            *http_connection;
 
-    unsigned             http_state:4;
+    unsigned                          http_state:4;
 
     /* URI with "/." and on Win32 with "//" */
-    unsigned             complex_uri:1;
+    unsigned                          complex_uri:1;
 
     /* URI with "%" */
-    unsigned             quoted_uri:1;
+    unsigned                          quoted_uri:1;
 
     /* URI with "+" */
-    unsigned             plus_in_uri:1;
+    unsigned                          plus_in_uri:1;
 
     /* URI with "\0" or "%00" */
-    unsigned             zero_in_uri:1;
+    unsigned                          zero_in_uri:1;
 
-    unsigned             uri_changed:1;
-    unsigned             uri_changes:4;
+    unsigned                          uri_changed:1;
+    unsigned                          uri_changes:4;
 
-    unsigned             low_case_exten:1;
-    unsigned             header_timeout_set:1;
+    unsigned                          low_case_exten:1;
+    unsigned                          header_timeout_set:1;
 
-    unsigned             proxy:1;
-    unsigned             bypass_cache:1;
-    unsigned             no_cache:1;
+    unsigned                          proxy:1;
+    unsigned                          bypass_cache:1;
+    unsigned                          no_cache:1;
 
 #if 0
-    unsigned             cachable:1;
+    unsigned                          cachable:1;
 #endif
-    unsigned             pipeline:1;
+    unsigned                          pipeline:1;
 
-    unsigned             plain_http:1;
-    unsigned             chunked:1;
-    unsigned             header_only:1;
-    unsigned             keepalive:1;
-    unsigned             lingering_close:1;
-    unsigned             closed:1;
+    unsigned                          plain_http:1;
+    unsigned                          chunked:1;
+    unsigned                          header_only:1;
+    unsigned                          keepalive:1;
+    unsigned                          lingering_close:1;
+    unsigned                          closed:1;
 
-    unsigned             filter_need_in_memory:1;
-    unsigned             filter_ssi_need_in_memory:1;
-    unsigned             filter_need_temporary:1;
-    unsigned             filter_allow_ranges:1;
+    unsigned                          filter_need_in_memory:1;
+    unsigned                          filter_ssi_need_in_memory:1;
+    unsigned                          filter_need_temporary:1;
+    unsigned                          filter_allow_ranges:1;
 
 #if (NGX_STAT_STUB)
-    unsigned             stat_reading:1;
-    unsigned             stat_writing:1;
+    unsigned                          stat_reading:1;
+    unsigned                          stat_writing:1;
 #endif
 
-    ngx_uint_t           headers_n;
+    ngx_uint_t                        headers_n;
 
     /* used to parse HTTP headers */
-    ngx_uint_t           state;
-    u_char              *uri_start;
-    u_char              *uri_end;
-    u_char              *uri_ext;
-    u_char              *args_start;
-    u_char              *request_start;
-    u_char              *request_end;
-    u_char              *method_end;
-    u_char              *schema_start;
-    u_char              *schema_end;
-    u_char              *host_start;
-    u_char              *host_end;
-    u_char              *port_start;
-    u_char              *port_end;
-    u_char              *header_name_start;
-    u_char              *header_name_end;
-    u_char              *header_start;
-    u_char              *header_end;
+    ngx_uint_t                        state;
+    u_char                           *uri_start;
+    u_char                           *uri_end;
+    u_char                           *uri_ext;
+    u_char                           *args_start;
+    u_char                           *request_start;
+    u_char                           *request_end;
+    u_char                           *method_end;
+    u_char                           *schema_start;
+    u_char                           *schema_end;
+    u_char                           *host_start;
+    u_char                           *host_end;
+    u_char                           *port_start;
+    u_char                           *port_end;
+    u_char                           *header_name_start;
+    u_char                           *header_name_end;
+    u_char                           *header_start;
+    u_char                           *header_end;
 };
 
 
--- a/src/http/ngx_http_request_body.c
+++ b/src/http/ngx_http_request_body.c
@@ -12,7 +12,7 @@
 
 static void ngx_http_read_client_request_body_handler(ngx_event_t *rev);
 static ngx_int_t ngx_http_do_read_client_request_body(ngx_http_request_t *r,
-                                                      ngx_connection_t *c);
+    ngx_connection_t *c);
 
 /*
  * on completion ngx_http_read_client_request_body() adds to
@@ -21,22 +21,35 @@ static ngx_int_t ngx_http_do_read_client
  *    *) one memory or file buf that contains the rest of the body
  */
 
-ngx_int_t ngx_http_read_client_request_body(ngx_http_request_t *r,
-                                  ngx_http_client_body_handler_pt post_handler)
+ngx_int_t
+ngx_http_read_client_request_body(ngx_http_request_t *r,
+    ngx_http_client_body_handler_pt post_handler)
 
 {
     ssize_t                    size;
     ngx_buf_t                 *b;
     ngx_chain_t               *cl;
+    ngx_connection_t          *c;
     ngx_http_request_body_t   *rb;
     ngx_http_core_loc_conf_t  *clcf;
 
-    if (!(rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t)))) {
+    rb = ngx_pcalloc(r->pool, sizeof(ngx_http_request_body_t));
+    if (rb == NULL) {
         return NGX_HTTP_INTERNAL_SERVER_ERROR;
     }
 
     r->request_body = rb;
 
+    /* STUB */
+    if (r->file.fd != NGX_INVALID_FILE) {
+        if (ngx_close_file(r->file.fd) == NGX_FILE_ERROR) {
+            ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno,
+                          ngx_close_file_n " \"%V\" failed", &r->file.name);
+        }
+        r->file.fd = NGX_INVALID_FILE;
+    }
+    /**/
+
     if (r->headers_in.content_length_n <= 0) {
         post_handler(r);
         return NGX_OK;
@@ -58,7 +71,8 @@ ngx_int_t ngx_http_read_client_request_b
 
         /* there is the pre-read part of the request body */
 
-        if (!(b = ngx_calloc_buf(r->pool))) {
+        b = ngx_calloc_buf(r->pool);
+        if (b == NULL) {
             return NGX_HTTP_INTERNAL_SERVER_ERROR;
         }
 
@@ -66,7 +80,8 @@ ngx_int_t ngx_http_read_client_request_b
         b->start = b->pos = r->header_in->pos;
         b->end = b->last = r->header_in->last;
 
-        if (!(rb->bufs = ngx_alloc_chain_link(r->pool))) {
+        rb->bufs = ngx_alloc_chain_link(r->pool);
+        if (rb->bufs == NULL) {
             return NGX_HTTP_INTERNAL_SERVER_ERROR;
         }
 
@@ -103,11 +118,13 @@ ngx_int_t ngx_http_read_client_request_b
         size = clcf->client_body_buffer_size;
     }
 
-    if (!(rb->buf = ngx_create_temp_buf(r->pool, size))) {
+    rb->buf = ngx_create_temp_buf(r->pool, size);
+    if (rb->buf == NULL) {
         return NGX_HTTP_INTERNAL_SERVER_ERROR;
     }
 
-    if (!(cl = ngx_alloc_chain_link(r->pool))) {
+    cl = ngx_alloc_chain_link(r->pool);
+    if (cl == NULL) {
         return NGX_HTTP_INTERNAL_SERVER_ERROR;
     }
 
@@ -121,14 +138,16 @@ ngx_int_t ngx_http_read_client_request_b
         rb->bufs = cl;
     }
 
-    r->connection->read->event_handler =
-                                     ngx_http_read_client_request_body_handler;
+    c = r->connection;
 
-    return ngx_http_do_read_client_request_body(r, r->connection);
+    c->read->event_handler = ngx_http_read_client_request_body_handler;
+
+    return ngx_http_do_read_client_request_body(r, c);
 }
 
 
-static void ngx_http_read_client_request_body_handler(ngx_event_t *rev)
+static void
+ngx_http_read_client_request_body_handler(ngx_event_t *rev)
 {
     ngx_int_t            rc;
     ngx_connection_t    *c;
@@ -150,8 +169,9 @@ static void ngx_http_read_client_request
 }
 
 
-static ngx_int_t ngx_http_do_read_client_request_body(ngx_http_request_t *r,
-                                                      ngx_connection_t *c)
+static ngx_int_t
+ngx_http_do_read_client_request_body(ngx_http_request_t *r,
+    ngx_connection_t *c)
 {
     size_t                     size;
     ssize_t                    n;
@@ -169,7 +189,8 @@ static ngx_int_t ngx_http_do_read_client
         if (rb->buf->last == rb->buf->end) {
 
             if (rb->temp_file == NULL) {
-                if (!(tf = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t)))) {
+                tf = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t));
+                if (tf == NULL) {
                     return NGX_ERROR;
                 }
 
@@ -268,7 +289,8 @@ static ngx_int_t ngx_http_do_read_client
             return NGX_HTTP_INTERNAL_SERVER_ERROR;
         }
 
-        if (!(b = ngx_calloc_buf(r->pool))) {
+        b = ngx_calloc_buf(r->pool);
+        if (b == NULL) {
             return NGX_HTTP_INTERNAL_SERVER_ERROR;
         }
 
--- a/src/http/ngx_http_special_response.c
+++ b/src/http/ngx_http_special_response.c
@@ -17,7 +17,7 @@ static u_char error_tail[] =
 ;
 
 
-static u_char msie_stub[] =
+static u_char ngx_http_msie_stub[] =
 "<!-- The padding to disable MSIE's friendly error page -->" CRLF
 "<!-- The padding to disable MSIE's friendly error page -->" CRLF
 "<!-- The padding to disable MSIE's friendly error page -->" CRLF
@@ -234,9 +234,9 @@ ngx_int_t
 ngx_http_special_response_handler(ngx_http_request_t *r, ngx_int_t error)
 {
     ngx_int_t                  rc;
-    ngx_uint_t                 err, i, msie_padding;
+    ngx_uint_t                 i, err, msie_padding;
     ngx_buf_t                 *b;
-    ngx_chain_t               *out, **ll, *cl;
+    ngx_chain_t               *out, *cl;
     ngx_http_err_page_t       *err_page;
     ngx_http_core_loc_conf_t  *clcf;
 
@@ -327,7 +327,7 @@ ngx_http_special_response_handler(ngx_ht
             && error >= NGX_HTTP_BAD_REQUEST
             && error != NGX_HTTP_REQUEST_URI_TOO_LARGE)
         {
-            r->headers_out.content_length_n += sizeof(msie_stub) - 1;
+            r->headers_out.content_length_n += sizeof(ngx_http_msie_stub) - 1;
             msie_padding = 1;
         }
 
@@ -360,43 +360,64 @@ ngx_http_special_response_handler(ngx_ht
         return NGX_OK;
     }
 
-    out = NULL;
-    ll = NULL;
 
-    if (!(b = ngx_calloc_buf(r->pool))) {
+    b = ngx_calloc_buf(r->pool);
+    if (b == NULL) {
         return NGX_ERROR;
     }
+
     b->memory = 1;
     b->pos = error_pages[err].data;
     b->last = error_pages[err].data + error_pages[err].len;
 
-    ngx_alloc_link_and_set_buf(cl, b, r->pool, NGX_ERROR);
-    ngx_chain_add_link(out, ll, cl);
+    cl = ngx_alloc_chain_link(r->pool);
+    if (cl == NULL) {
+        return NGX_ERROR;
+    }
+
+    cl->buf = b;
+    out = cl;
 
 
-    if (!(b = ngx_calloc_buf(r->pool))) {
+    b = ngx_calloc_buf(r->pool);
+    if (b == NULL) {
         return NGX_ERROR;
     }
+
     b->memory = 1;
     b->pos = error_tail;
     b->last = error_tail + sizeof(error_tail) - 1;
 
-    ngx_alloc_link_and_set_buf(cl, b, r->pool, NGX_ERROR);
-    ngx_chain_add_link(out, ll, cl);
+    cl->next = ngx_alloc_chain_link(r->pool);
+    if (cl->next == NULL) {
+        return NGX_ERROR;
+    }
+
+    cl = cl->next;
+    cl->buf = b;
 
     if (msie_padding) {
-        if (!(b = ngx_calloc_buf(r->pool))) {
+        b = ngx_calloc_buf(r->pool);
+        if (b == NULL) {
             return NGX_ERROR;
         }
+
         b->memory = 1;
-        b->pos = msie_stub;
-        b->last = msie_stub + sizeof(msie_stub) - 1;
+        b->pos = ngx_http_msie_stub;
+        b->last = ngx_http_msie_stub + sizeof(ngx_http_msie_stub) - 1;
 
-        ngx_alloc_link_and_set_buf(cl, b, r->pool, NGX_ERROR);
-        ngx_chain_add_link(out, ll, cl);
+        cl->next = ngx_alloc_chain_link(r->pool);
+        if (cl->next == NULL) {
+            return NGX_ERROR;
+        }
+
+        cl = cl->next;
+        cl->buf = b;
     }
 
     b->last_buf = 1;
 
+    cl->next = NULL;
+
     return ngx_http_output_filter(r, out);
 }
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -129,13 +129,14 @@ ngx_http_upstream_init(ngx_http_request_
     u->writer.pool = r->pool;
 
     if (ngx_array_init(&u->states, r->pool, u->peer.peers->number,
-                               sizeof(ngx_http_upstream_state_t)) == NGX_ERROR)
+                       sizeof(ngx_http_upstream_state_t)) != NGX_OK)
     {
         ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
         return;
     }
 
-    if (!(u->state = ngx_push_array(&u->states))) {
+    u->state = ngx_array_push(&u->states);
+    if (u->state == NULL) {
         ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
         return;
     }
@@ -317,7 +318,8 @@ ngx_http_upstream_connect(ngx_http_reque
     if (r->request_body->buf) {
         if (r->request_body->temp_file) {
 
-            if (!(u->output.free = ngx_alloc_chain_link(r->pool))) {
+            u->output.free = ngx_alloc_chain_link(r->pool);
+            if (u->output.free == NULL) {
                 ngx_http_upstream_finalize_request(r, u,
                                                 NGX_HTTP_INTERNAL_SERVER_ERROR);
                 return;
@@ -392,7 +394,8 @@ ngx_http_upstream_reinit(ngx_http_reques
 
     /* add one more state */
 
-    if (!(u->state = ngx_push_array(&u->states))) {
+    u->state = ngx_array_push(&u->states);
+    if (u->state == NULL) {
         ngx_http_upstream_finalize_request(r, u,
                                            NGX_HTTP_INTERNAL_SERVER_ERROR);
         return;
@@ -739,7 +742,8 @@ ngx_http_upstream_send_response(ngx_http
     
     p->cachable = u->cachable;
 
-    if (!(p->temp_file = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t)))) {
+    p->temp_file = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t));
+    if (p->temp_file == NULL) {
         ngx_http_upstream_finalize_request(r, u, 0);
         return;
     }
@@ -759,7 +763,8 @@ ngx_http_upstream_send_response(ngx_http
     p->max_temp_file_size = u->conf->max_temp_file_size;
     p->temp_file_write_size = u->conf->temp_file_write_size;
 
-    if (!(p->preread_bufs = ngx_alloc_chain_link(r->pool))) {
+    p->preread_bufs = ngx_alloc_chain_link(r->pool);
+    if (p->preread_bufs == NULL) {
         ngx_http_upstream_finalize_request(r, u, 0);
         return;
     }
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -25,7 +25,7 @@
 static ngx_http_variable_value_t *
     ngx_http_variable_header(ngx_http_request_t *r, uintptr_t data);
 static ngx_http_variable_value_t *
-    ngx_http_variable_unknown_header(ngx_http_request_t *r, ngx_str_t *var);
+    ngx_http_variable_unknown_header(ngx_http_request_t *r, uintptr_t data);
 static ngx_http_variable_value_t *
     ngx_http_variable_remote_addr(ngx_http_request_t *r, uintptr_t data);
 static ngx_http_variable_value_t *
@@ -69,39 +69,71 @@ static ngx_http_core_variable_t  ngx_htt
 
 
 ngx_http_variable_t *
-ngx_http_add_variable(ngx_conf_t *cf)
+ngx_http_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t set)
 {
-    ngx_http_variable_t        *var;
+    ngx_uint_t                  i;
+    ngx_http_variable_t        *v;
     ngx_http_core_main_conf_t  *cmcf;
 
     cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
 
-    if (cmcf->variables.elts == NULL) {
+    v = cmcf->variables.elts;
+
+    if (v == NULL) {
         if (ngx_array_init(&cmcf->variables, cf->pool, 4,
                            sizeof(ngx_http_variable_t)) == NGX_ERROR)
         {
             return NULL;
         }
+
+    } else {
+        for (i = 0; i < cmcf->variables.nelts; i++) {
+            if (name->len != v[i].name.len
+                || ngx_strncasecmp(name->data, v[i].name.data, name->len) != 0)
+            {
+                continue;
+            }
+
+            if (set && v[i].handler) {
+                ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                                   "the duplicate \"%V\" variable", name);
+                return NULL;
+            }
+
+            return &v[i];
+        }
     }
 
-    if (!(var = ngx_array_push(&cmcf->variables))) {
+    v = ngx_array_push(&cmcf->variables);
+    if (v == NULL) {
         return NULL;
     }
 
-    var->index = cmcf->variables.nelts - 1;
+    v->name.len = name->len;
+    v->name.data = ngx_palloc(cf->pool, name->len);
+    if (v->name.data == NULL) {
+        return NULL;
+    }
 
-    return var;
+    for (i = 0; i < name->len; i++) {
+        v->name.data[i] = ngx_toupper(name->data[i]);
+    }
+
+    v->index = cmcf->variables.nelts - 1;
+    v->handler = NULL;
+    v->data = 0;
+
+    return v;
 }
 
 
 ngx_http_variable_value_t *
 ngx_http_get_indexed_variable(ngx_http_request_t *r, ngx_uint_t index)
 {
-    ngx_http_variable_t        *var;
+    ngx_http_variable_t        *v;
+    ngx_http_variable_value_t  *vv;
     ngx_http_core_main_conf_t  *cmcf;
 
-    /* TODO: cached variables */
-
     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
 
     if (cmcf->variables.elts == NULL || cmcf->variables.nelts <= index) {
@@ -110,70 +142,70 @@ ngx_http_get_indexed_variable(ngx_http_r
         return NULL;
     }
 
-    var = cmcf->variables.elts;
+    if (r->variables && r->variables[index]) {
+        return r->variables[index];
+    }
 
-    return var[index].handler(r, var[index].data);
-}
-
+    v = cmcf->variables.elts;
 
-ngx_int_t
-ngx_http_get_variable_index(ngx_http_core_main_conf_t *cmcf, ngx_str_t *name)
-{
-    ngx_uint_t            i;
-    ngx_http_variable_t  *var;
+    vv = v[index].handler(r, v[index].data);
 
-    var = cmcf->variables.elts;
-    for (i = 0; i < cmcf->variables.nelts; i++) {
-        if (var[i].name.len != name->len) {
-            continue;
-        }
-
-        if (ngx_strncasecmp(var[i].name.data, name->data, name->len) == 0) {
-            return var[i].index;
+    if (r->variables == NULL) {
+        r->variables = ngx_pcalloc(r->pool, cmcf->variables.nelts
+                                        * sizeof(ngx_http_variable_value_t *));
+        if (r->variables == NULL) {
+            return NULL;
         }
     }
 
-    return -1;
+    r->variables[index] = vv;
+
+    return vv;
 }
 
 
 ngx_http_variable_value_t *
 ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name)
 {
-    ngx_int_t                   index;
     ngx_uint_t                  i, key;
-    ngx_http_core_variable_t   *var;
+    ngx_http_variable_t        *v;
+    ngx_http_core_variable_t   *cv;
     ngx_http_core_main_conf_t  *cmcf;
 
     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
 
-    index = ngx_http_get_variable_index(cmcf, name);
+    v = cmcf->variables.elts;
+    for (i = 0; i < cmcf->variables.nelts; i++) {
+        if (v[i].name.len != name->len) {
+            continue;
+        }
 
-    if (index != -1) {
-        return ngx_http_get_indexed_variable(r, index);
+        if (ngx_strncmp(v[i].name.data, name->data, name->len) == 0) {
+            return ngx_http_get_indexed_variable(r, v[i].index);
+        }
     }
 
     ngx_http_vars_hash_key(key, name);
 
-    var = ngx_http_core_variables_hash[key].elts;
+    cv = ngx_http_core_variables_hash[key].elts;
     for (i = 0; i < ngx_http_core_variables_hash[key].nelts; i++) {
-
-        if (var[i].name.len != name->len
-            || ngx_strncasecmp(var[i].name.data, name->data, name->len) != 0)
-        {
+        if (cv[i].name.len != name->len) {
             continue;
         }
 
-        return var[i].handler(r, var[i].data);
+        if (ngx_strncmp(cv[i].name.data, name->data, name->len) == 0) {
+            return cv[i].handler(r, cv[i].data);
+        }
     }
 
-    if (ngx_strncasecmp(name->data, "HTTP_", 5) != 0) {
-        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
-                      "unknown \"%V\" variable", name);
-        return NGX_HTTP_VARIABLE_NOT_FOUND;
+    if (ngx_strncmp(name->data, "HTTP_", 5) == 0) {
+        return ngx_http_variable_unknown_header(r, (uintptr_t) name);
     }
 
-    return ngx_http_variable_unknown_header(r, name);
+    ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                  "unknown \"%V\" variable", name);
+
+    return NGX_HTTP_VARIABLE_NOT_FOUND;
 }
 
 
@@ -181,7 +213,7 @@ static ngx_http_variable_value_t *
 ngx_http_variable_header(ngx_http_request_t *r, uintptr_t data)
 {
     ngx_table_elt_t            *h;
-    ngx_http_variable_value_t  *v;
+    ngx_http_variable_value_t  *vv;
 
     h = *(ngx_table_elt_t **) ((char *) &r->headers_in + data);
 
@@ -189,25 +221,28 @@ ngx_http_variable_header(ngx_http_reques
         return NGX_HTTP_VARIABLE_NOT_FOUND;
     }
 
-    if (!(v = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)))) {
+    vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
+    if (vv == NULL) {
         return NULL;
     }
 
-    v->value = 0;
-    v->text = h->value;
+    vv->value = 0;
+    vv->text = h->value;
 
-    return v;
+    return vv;
 }
 
 
 static ngx_http_variable_value_t *
-ngx_http_variable_unknown_header(ngx_http_request_t *r, ngx_str_t *var)
+ngx_http_variable_unknown_header(ngx_http_request_t *r, uintptr_t data)
 {
+    ngx_str_t  *var = (ngx_str_t *) data;
+
     u_char                      ch;
     ngx_uint_t                  i, n;
     ngx_list_part_t            *part;
     ngx_table_elt_t            *header;
-    ngx_http_variable_value_t  *v;
+    ngx_http_variable_value_t  *vv;
 
     part = &r->headers_in.headers.part;
     header = part->elts;
@@ -241,13 +276,14 @@ ngx_http_variable_unknown_header(ngx_htt
         }
 
         if (n + 5 == var->len) {
-            if (!(v = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)))) {
+            vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
+            if (vv == NULL) {
                 return NULL;
             }
 
-            v->value = 0;
-            v->text = header[i].value;
-            return v;
+            vv->value = 0;
+            vv->text = header[i].value;
+            return vv;
         }
     }
 
@@ -258,56 +294,61 @@ ngx_http_variable_unknown_header(ngx_htt
 static ngx_http_variable_value_t *
 ngx_http_variable_remote_addr(ngx_http_request_t *r, uintptr_t data)
 {
-    ngx_http_variable_value_t  *v;
+    ngx_http_variable_value_t  *vv;
 
-    if (!(v = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)))) {
+    vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
+    if (vv == NULL) {
         return NULL;
     }
 
-    v->value = 0;
-    v->text = r->connection->addr_text;
+    vv->value = 0;
+    vv->text = r->connection->addr_text;
 
-    return v;
+    return vv;
 }
 
 
 static ngx_http_variable_value_t *
 ngx_http_variable_uri(ngx_http_request_t *r, uintptr_t data)
 {
-    ngx_http_variable_value_t  *v;
+    ngx_http_variable_value_t  *vv;
 
-    if (!(v = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)))) {
+    vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
+    if (vv == NULL) {
         return NULL;
     }
 
-    v->value = 0;
-    v->text = r->uri;
+    vv->value = 0;
+    vv->text = r->uri;
 
-    return v;
+    return vv;
 }
 
 
 static ngx_http_variable_value_t *
 ngx_http_variable_query_string(ngx_http_request_t *r, uintptr_t data)
 {
-    ngx_http_variable_value_t  *v;
+    ngx_http_variable_value_t  *vv;
 
-    if (!(v = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)))) {
+    vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
+    if (vv == NULL) {
         return NULL;
     }
 
-    v->value = 0;
-    v->text = r->args;
+    vv->value = 0;
+    vv->text = r->args;
 
-    return v;
+    return vv;
 }
 
 
 ngx_int_t
-ngx_http_core_variables_init(ngx_cycle_t *cycle)
+ngx_http_variables_init(ngx_cycle_t *cycle)
 {
-    ngx_uint_t                 i, key;
-    ngx_http_core_variable_t  *var, *v;
+    ngx_uint_t                  i, j, key;
+    ngx_http_variable_t        *v;
+    ngx_http_core_variable_t   *cv, *vp;
+    ngx_http_core_main_conf_t  *cmcf;
 
     ngx_http_core_variables_hash = ngx_palloc(cycle->pool,
                                               NGX_HTTP_VARS_HASH_PRIME
@@ -324,14 +365,54 @@ ngx_http_core_variables_init(ngx_cycle_t
         }
     }
 
-    for (var = ngx_http_core_variables; var->name.len; var++) {
-        ngx_http_vars_hash_key(key, &var->name);
+    for (cv = ngx_http_core_variables; cv->name.len; cv++) {
+        ngx_http_vars_hash_key(key, &cv->name);
 
-        if (!(v = ngx_array_push(&ngx_http_core_variables_hash[key]))) {
+        vp = ngx_array_push(&ngx_http_core_variables_hash[key]);
+        if (vp == NULL) {
             return NGX_ERROR;
         }
 
-        *v = *var;
+        *vp = *cv;
+    }
+
+
+    cmcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_core_module);
+
+    v = cmcf->variables.elts;
+    for (i = 0; i < cmcf->variables.nelts; i++) {
+
+        if (v[i].handler) {
+            continue;
+        }
+
+        ngx_http_vars_hash_key(key, &v[i].name);
+
+        cv = ngx_http_core_variables_hash[key].elts;
+        for (j = 0; j < ngx_http_core_variables_hash[key].nelts; j++) {
+            if (cv[j].name.len != v[i].name.len) {
+                continue;
+            }
+
+            if (ngx_strncmp(cv[j].name.data, v[i].name.data, v[i].name.len)
+                == 0)
+            {
+                v[i].handler = cv[j].handler;
+                v[i].data = cv[j].data;
+                continue;
+            }
+        }
+
+        if (ngx_strncmp(v[i].name.data, "HTTP_", 5) == 0) {
+            v[i].handler = ngx_http_variable_unknown_header;
+            v[i].data = (uintptr_t) &v[i].name;
+            continue;
+        }
+
+        ngx_log_error(NGX_LOG_ERR, cycle->log, 0,
+                      "unknown \"%V\" variable", &v[i].name);
+
+        return NGX_ERROR;
     }
 
     return NGX_OK;
--- a/src/http/ngx_http_variables.h
+++ b/src/http/ngx_http_variables.h
@@ -17,45 +17,41 @@
 #define NGX_HTTP_VARIABLE_NOT_FOUND  (ngx_http_variable_value_t *) -1
 
 
-typedef struct {
+struct ngx_http_variable_value_s {
     ngx_uint_t                     value;
     ngx_str_t                      text;
-} ngx_http_variable_value_t;
-    
+};
 
 typedef struct ngx_http_variable_s  ngx_http_variable_t;
 
 typedef ngx_http_variable_value_t *
-                (*ngx_http_get_variable_pt) (ngx_http_request_t *r, void *var);
+    (*ngx_http_get_variable_pt) (ngx_http_request_t *r, uintptr_t data);
 
 
 struct ngx_http_variable_s {
-    ngx_str_t                      name;
-    ngx_uint_t                     index;
-    ngx_http_get_variable_pt       handler;
-    void                          *data;
-    ngx_uint_t                     uses;
+    ngx_str_t                  name;
+    ngx_uint_t                 index;
+    ngx_http_get_variable_pt   handler;
+    uintptr_t                  data;
 };
 
 
-typedef ngx_http_variable_value_t *
-    (*ngx_http_get_core_variable_pt) (ngx_http_request_t *r, uintptr_t data);
-
 typedef struct {
-    ngx_str_t                      name;
-    ngx_http_get_core_variable_pt  handler;
-    uintptr_t                      data;
+    ngx_str_t                  name;
+    ngx_http_get_variable_pt   handler;
+    uintptr_t                  data;
 } ngx_http_core_variable_t;
 
 
-ngx_http_variable_t *ngx_http_add_variable(ngx_conf_t *cf);
+ngx_http_variable_t *ngx_http_add_variable(ngx_conf_t *cf, ngx_str_t *name,
+    ngx_uint_t set);
 ngx_int_t ngx_http_get_variable_index(ngx_http_core_main_conf_t *cmcf,
     ngx_str_t *name);
 ngx_http_variable_value_t *ngx_http_get_indexed_variable(ngx_http_request_t *r,
     ngx_uint_t index);
 ngx_http_variable_value_t *ngx_http_get_variable(ngx_http_request_t *r,
     ngx_str_t *name);
-ngx_int_t ngx_http_core_variables_init(ngx_cycle_t *cycle);
+ngx_int_t ngx_http_variables_init(ngx_cycle_t *cycle);
 
 
 #endif /* _NGX_HTTP_VARIABLES_H_INCLUDED_ */
deleted file mode 100644
--- a/src/http/ngx_http_write_filter.c
+++ /dev/null
@@ -1,238 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_event.h>
-#include <ngx_http.h>
-
-
-typedef struct {
-    ngx_chain_t  *out;
-} ngx_http_write_filter_ctx_t;
-
-
-static ngx_int_t ngx_http_write_filter_init(ngx_cycle_t *cycle);
-
-
-ngx_http_module_t  ngx_http_write_filter_module_ctx = {
-    NULL,                                  /* pre conf */
-
-    NULL,                                  /* create main configuration */
-    NULL,                                  /* init main configuration */
-
-    NULL,                                  /* create server configuration */
-    NULL,                                  /* merge server configuration */
-
-    NULL,                                  /* create location configuration */
-    NULL,                                  /* merge location configuration */
-};
-
-
-ngx_module_t  ngx_http_write_filter_module = {
-    NGX_MODULE,
-    &ngx_http_write_filter_module_ctx,     /* module context */
-    NULL,                                  /* module directives */
-    NGX_HTTP_MODULE,                       /* module type */
-    ngx_http_write_filter_init,            /* init module */
-    NULL                                   /* init process */
-};
-
-
-ngx_int_t ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
-{
-    off_t                         size, sent;
-    ngx_uint_t                    last, flush;
-    ngx_chain_t                  *cl, *ln, **ll, *chain;
-    ngx_connection_t             *c;
-    ngx_http_core_loc_conf_t     *clcf;
-    ngx_http_write_filter_ctx_t  *ctx;
-
-    ctx = ngx_http_get_module_ctx(r->main ? r->main : r,
-                                  ngx_http_write_filter_module);
-
-    if (ctx == NULL) {
-        ngx_http_create_ctx(r, ctx, ngx_http_write_filter_module,
-                            sizeof(ngx_http_write_filter_ctx_t), NGX_ERROR);
-    }
-
-    size = 0;
-    flush = 0;
-    last = 0;
-    ll = &ctx->out;
-
-    /* find the size, the flush point and the last link of the saved chain */
-
-    for (cl = ctx->out; cl; cl = cl->next) {
-        ll = &cl->next;
-
-        ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0,
-                       "write old buf t:%d f:%d %p, pos %p, size: %z "
-                       "file: %O, size: %z",
-                       cl->buf->temporary, cl->buf->in_file,
-                       cl->buf->start, cl->buf->pos,
-                       cl->buf->last - cl->buf->pos,
-                       cl->buf->file_pos,
-                       cl->buf->file_last - cl->buf->file_pos);
-
-#if 1
-        if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) {
-            ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
-                          "zero size buf in writer "
-                          "t:%d r:%d f:%d %p %p-%p %p %O-%O",
-                          cl->buf->temporary,
-                          cl->buf->recycled,
-                          cl->buf->in_file,
-                          cl->buf->start,
-                          cl->buf->pos,
-                          cl->buf->last,
-                          cl->buf->file,
-                          cl->buf->file_pos,
-                          cl->buf->file_last);
-
-            ngx_debug_point();
-            return NGX_ERROR;
-        }
-#endif
-
-        size += ngx_buf_size(cl->buf);
-
-        if (cl->buf->flush || cl->buf->recycled) {
-            flush = 1;
-        }
-
-        if (cl->buf->last_buf) {
-            last = 1;
-        }
-    }
-
-    /* add the new chain to the existent one */
-
-    for (ln = in; ln; ln = ln->next) {
-        if (!(cl = ngx_alloc_chain_link(r->pool))) {
-            return NGX_ERROR;
-        }
-
-        cl->buf = ln->buf;
-        *ll = cl;
-        ll = &cl->next;
-
-        ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0,
-                       "write new buf t:%d f:%d %p, pos %p, size: %z "
-                       "file: %O, size: %z",
-                       cl->buf->temporary, cl->buf->in_file,
-                       cl->buf->start, cl->buf->pos,
-                       cl->buf->last - cl->buf->pos,
-                       cl->buf->file_pos,
-                       cl->buf->file_last - cl->buf->file_pos);
-
-#if 1
-        if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) {
-            ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
-                          "zero size buf in writer "
-                          "t:%d r:%d f:%d %p %p-%p %p %O-%O",
-                          cl->buf->temporary,
-                          cl->buf->recycled,
-                          cl->buf->in_file,
-                          cl->buf->start,
-                          cl->buf->pos,
-                          cl->buf->last,
-                          cl->buf->file,
-                          cl->buf->file_pos,
-                          cl->buf->file_last);
-
-            ngx_debug_point();
-            return NGX_ERROR;
-        }
-#endif
-
-        size += ngx_buf_size(cl->buf);
-
-        if (cl->buf->flush || cl->buf->recycled) {
-            flush = 1;
-        }
-
-        if (cl->buf->last_buf) {
-            last = 1;
-        }
-    }
-
-    *ll = NULL;
-
-    c = r->connection;
-
-    ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
-                   "http write filter: l:%d f:%d s:%O", last, flush, size);
-
-    clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
-                                        ngx_http_core_module);
-
-    /*
-     * avoid the output if there is no last buf, no flush point,
-     * there are the incoming bufs and the size of all bufs
-     * is smaller than "postpone_output" directive
-     */
-
-    if (!last && !flush && in && size < (off_t) clcf->postpone_output) {
-        return NGX_OK;
-    }
-
-    if (c->write->delayed) {
-        return NGX_AGAIN;
-    }
-
-    if (size == 0 && !c->buffered) {
-        if (last) {
-            return NGX_OK;
-        }
-
-        if (flush) {
-            while ((ctx->out = ctx->out->next)) { /* void */ }
-            return NGX_OK;
-        }
-
-        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
-                      "the http output chain is empty");
-
-        ngx_debug_point();
-
-        return NGX_ERROR;
-    }
-
-    sent = c->sent;
-
-    chain = c->send_chain(c, ctx->out, clcf->limit_rate);
-
-    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
-                   "http write filter %p", chain);
-
-    if (clcf->limit_rate) {
-        sent = c->sent - sent;
-        c->write->delayed = 1;
-        ngx_add_timer(r->connection->write,
-                      (ngx_msec_t) (sent * 1000 / clcf->limit_rate));
-    }
-
-    if (chain == NGX_CHAIN_ERROR) {
-        return NGX_ERROR;
-    }
-
-    ctx->out = chain;
-
-    if (chain || (last && c->buffered)) {
-        return NGX_AGAIN;
-    }
-
-    return NGX_OK;
-}
-
-
-static ngx_int_t ngx_http_write_filter_init(ngx_cycle_t *cycle)
-{
-    ngx_http_top_body_filter = ngx_http_write_filter;
-
-    return NGX_OK;
-}
new file mode 100644
--- /dev/null
+++ b/src/http/ngx_http_write_filter_module.c
@@ -0,0 +1,250 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_event.h>
+#include <ngx_http.h>
+
+
+typedef struct {
+    ngx_chain_t  *out;
+} ngx_http_write_filter_ctx_t;
+
+
+static ngx_int_t ngx_http_write_filter_init(ngx_cycle_t *cycle);
+
+
+ngx_http_module_t  ngx_http_write_filter_module_ctx = {
+    NULL,                                  /* pre conf */
+
+    NULL,                                  /* create main configuration */
+    NULL,                                  /* init main configuration */
+
+    NULL,                                  /* create server configuration */
+    NULL,                                  /* merge server configuration */
+
+    NULL,                                  /* create location configuration */
+    NULL,                                  /* merge location configuration */
+};
+
+
+ngx_module_t  ngx_http_write_filter_module = {
+    NGX_MODULE,
+    &ngx_http_write_filter_module_ctx,     /* module context */
+    NULL,                                  /* module directives */
+    NGX_HTTP_MODULE,                       /* module type */
+    ngx_http_write_filter_init,            /* init module */
+    NULL                                   /* init process */
+};
+
+
+ngx_int_t
+ngx_http_write_filter(ngx_http_request_t *r, ngx_chain_t *in)
+{
+    off_t                         size, sent;
+    ngx_uint_t                    last, flush;
+    ngx_chain_t                  *cl, *ln, **ll, *chain;
+    ngx_connection_t             *c;
+    ngx_http_core_loc_conf_t     *clcf;
+    ngx_http_write_filter_ctx_t  *ctx;
+
+    ctx = ngx_http_get_module_ctx(r->main ? r->main : r,
+                                  ngx_http_write_filter_module);
+
+    if (ctx == NULL) {
+
+        ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_write_filter_ctx_t));
+        if (ctx == NULL) {
+            return NGX_ERROR;
+        }
+
+        ngx_http_set_ctx(r, ctx, ngx_http_write_filter_module);
+    }
+
+    size = 0;
+    flush = 0;
+    last = 0;
+    ll = &ctx->out;
+
+    /* find the size, the flush point and the last link of the saved chain */
+
+    for (cl = ctx->out; cl; cl = cl->next) {
+        ll = &cl->next;
+
+        ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0,
+                       "write old buf t:%d f:%d %p, pos %p, size: %z "
+                       "file: %O, size: %z",
+                       cl->buf->temporary, cl->buf->in_file,
+                       cl->buf->start, cl->buf->pos,
+                       cl->buf->last - cl->buf->pos,
+                       cl->buf->file_pos,
+                       cl->buf->file_last - cl->buf->file_pos);
+
+#if 1
+        if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) {
+            ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+                          "zero size buf in writer "
+                          "t:%d r:%d f:%d %p %p-%p %p %O-%O",
+                          cl->buf->temporary,
+                          cl->buf->recycled,
+                          cl->buf->in_file,
+                          cl->buf->start,
+                          cl->buf->pos,
+                          cl->buf->last,
+                          cl->buf->file,
+                          cl->buf->file_pos,
+                          cl->buf->file_last);
+
+            ngx_debug_point();
+            return NGX_ERROR;
+        }
+#endif
+
+        size += ngx_buf_size(cl->buf);
+
+        if (cl->buf->flush || cl->buf->recycled) {
+            flush = 1;
+        }
+
+        if (cl->buf->last_buf) {
+            last = 1;
+        }
+    }
+
+    /* add the new chain to the existent one */
+
+    for (ln = in; ln; ln = ln->next) {
+        cl = ngx_alloc_chain_link(r->pool);
+        if (cl == NULL) {
+            return NGX_ERROR;
+        }
+
+        cl->buf = ln->buf;
+        *ll = cl;
+        ll = &cl->next;
+
+        ngx_log_debug7(NGX_LOG_DEBUG_EVENT, r->connection->log, 0,
+                       "write new buf t:%d f:%d %p, pos %p, size: %z "
+                       "file: %O, size: %z",
+                       cl->buf->temporary, cl->buf->in_file,
+                       cl->buf->start, cl->buf->pos,
+                       cl->buf->last - cl->buf->pos,
+                       cl->buf->file_pos,
+                       cl->buf->file_last - cl->buf->file_pos);
+
+#if 1
+        if (ngx_buf_size(cl->buf) == 0 && !ngx_buf_special(cl->buf)) {
+            ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+                          "zero size buf in writer "
+                          "t:%d r:%d f:%d %p %p-%p %p %O-%O",
+                          cl->buf->temporary,
+                          cl->buf->recycled,
+                          cl->buf->in_file,
+                          cl->buf->start,
+                          cl->buf->pos,
+                          cl->buf->last,
+                          cl->buf->file,
+                          cl->buf->file_pos,
+                          cl->buf->file_last);
+
+            ngx_debug_point();
+            return NGX_ERROR;
+        }
+#endif
+
+        size += ngx_buf_size(cl->buf);
+
+        if (cl->buf->flush || cl->buf->recycled) {
+            flush = 1;
+        }
+
+        if (cl->buf->last_buf) {
+            last = 1;
+        }
+    }
+
+    *ll = NULL;
+
+    c = r->connection;
+
+    ngx_log_debug3(NGX_LOG_DEBUG_HTTP, c->log, 0,
+                   "http write filter: l:%d f:%d s:%O", last, flush, size);
+
+    clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
+                                        ngx_http_core_module);
+
+    /*
+     * avoid the output if there is no last buf, no flush point,
+     * there are the incoming bufs and the size of all bufs
+     * is smaller than "postpone_output" directive
+     */
+
+    if (!last && !flush && in && size < (off_t) clcf->postpone_output) {
+        return NGX_OK;
+    }
+
+    if (c->write->delayed) {
+        return NGX_AGAIN;
+    }
+
+    if (size == 0 && !c->buffered) {
+        if (last) {
+            return NGX_OK;
+        }
+
+        if (flush) {
+            do {
+                ctx->out = ctx->out->next;
+            }
+            while (ctx->out);
+
+            return NGX_OK;
+        }
+
+        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+                      "the http output chain is empty");
+
+        ngx_debug_point();
+
+        return NGX_ERROR;
+    }
+
+    sent = c->sent;
+
+    chain = c->send_chain(c, ctx->out, clcf->limit_rate);
+
+    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
+                   "http write filter %p", chain);
+
+    if (clcf->limit_rate) {
+        sent = c->sent - sent;
+        c->write->delayed = 1;
+        ngx_add_timer(r->connection->write,
+                      (ngx_msec_t) (sent * 1000 / clcf->limit_rate));
+    }
+
+    if (chain == NGX_CHAIN_ERROR) {
+        return NGX_ERROR;
+    }
+
+    ctx->out = chain;
+
+    if (chain || (last && c->buffered)) {
+        return NGX_AGAIN;
+    }
+
+    return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_write_filter_init(ngx_cycle_t *cycle)
+{
+    ngx_http_top_body_filter = ngx_http_write_filter;
+
+    return NGX_OK;
+}
--- a/src/os/unix/ngx_aio_read_chain.c
+++ b/src/os/unix/ngx_aio_read_chain.c
@@ -16,7 +16,6 @@ ssize_t ngx_aio_read_chain(ngx_connectio
     u_char       *buf, *prev;
     size_t        size;
     ssize_t       total;
-    ngx_err_t     err;
 
     if (c->read->pending_eof) {
         c->read->ready = 0;
--- a/src/os/unix/ngx_aio_write_chain.c
+++ b/src/os/unix/ngx_aio_write_chain.c
@@ -17,7 +17,6 @@ ngx_chain_t *ngx_aio_write_chain(ngx_con
     off_t         send, sent;
     size_t        len;
     ssize_t       n, size;
-    ngx_err_t     err;
     ngx_chain_t  *cl;
 
     /* the maximum limit size is the maximum size_t value - the page size */
--- a/src/os/unix/ngx_alloc.c
+++ b/src/os/unix/ngx_alloc.c
@@ -11,11 +11,13 @@
 int ngx_pagesize;
 
 
-void *ngx_alloc(size_t size, ngx_log_t *log)
+void *
+ngx_alloc(size_t size, ngx_log_t *log)
 {
     void  *p;
 
-    if (!(p = malloc(size))) {
+    p = malloc(size);
+    if (p == NULL) {
         ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
                       "malloc() %uz bytes failed", size);
     }
@@ -26,7 +28,8 @@ void *ngx_alloc(size_t size, ngx_log_t *
 }
 
 
-void *ngx_calloc(size_t size, ngx_log_t *log)
+void *
+ngx_calloc(size_t size, ngx_log_t *log)
 {
     void  *p;
 
@@ -42,7 +45,8 @@ void *ngx_calloc(size_t size, ngx_log_t 
 
 #if (NGX_HAVE_POSIX_MEMALIGN)
 
-void *ngx_memalign(size_t alignment, size_t size, ngx_log_t *log)
+void *
+ngx_memalign(size_t alignment, size_t size, ngx_log_t *log)
 {
     void  *p;
 
@@ -60,11 +64,13 @@ void *ngx_memalign(size_t alignment, siz
 
 #elif (NGX_HAVE_MEMALIGN)
 
-void *ngx_memalign(size_t alignment, size_t size, ngx_log_t *log)
+void *
+ngx_memalign(size_t alignment, size_t size, ngx_log_t *log)
 {
     void  *p;
 
-    if (!(p = memalign(alignment, size))) {
+    p = memalign(alignment, size);
+    if (p == NULL) {
         ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
                       "memalign() %uz bytes aligned to %uz failed",
                       size, alignment);
--- a/src/os/unix/ngx_errno.c
+++ b/src/os/unix/ngx_errno.c
@@ -34,8 +34,7 @@ u_char *ngx_strerror_r(int err, u_char *
 
 u_char *ngx_strerror_r(int err, u_char *errstr, size_t size)
 {
-    char    *str;
-    size_t   len;
+    char  *str;
 
     if (size == 0) {
         return 0;
--- a/src/os/unix/ngx_errno.h
+++ b/src/os/unix/ngx_errno.h
@@ -25,7 +25,7 @@ typedef int               ngx_err_t;
 #define NGX_ENOTDIR       ENOTDIR
 #define NGX_EINVAL        EINVAL
 #define NGX_EPIPE         EPIPE
-#define NGX_EAGAIN        EWOULDBLOCK
+#define NGX_EAGAIN        EAGAIN
 #define NGX_EINPROGRESS   EINPROGRESS
 #define NGX_EADDRINUSE    EADDRINUSE
 #define NGX_ECONNABORTED  ECONNABORTED
@@ -52,10 +52,10 @@ u_char *ngx_strerror_r(int err, u_char *
 
 #else
 
-/* Solaris has threads-safe strerror() */
+/* Solaris has thread-safe strerror() */
 
 #define ngx_strerror_r(err, errstr, size)  \
-             ngx_cpystrn(errstr, (u_char *) strerror(err), size)
+    ngx_cpystrn(errstr, (u_char *) strerror(err), size)
 
 #endif
 
--- a/src/os/unix/ngx_files.c
+++ b/src/os/unix/ngx_files.c
@@ -131,7 +131,6 @@ ssize_t ngx_write_chain_to_file(ngx_file
     u_char        *prev;
     size_t         size;
     ssize_t        n;
-    ngx_err_t      err;
     ngx_array_t    vec;
     struct iovec  *iov, iovs[NGX_IOVS];
 
@@ -162,7 +161,8 @@ ssize_t ngx_write_chain_to_file(ngx_file
                 iov->iov_len += cl->buf->last - cl->buf->pos;
 
             } else {
-                if (!(iov = ngx_array_push(&vec))) {
+                iov = ngx_array_push(&vec);
+                if (iov == NULL) {
                     return NGX_ERROR;
                 }
 
--- a/src/os/unix/ngx_freebsd_init.c
+++ b/src/os/unix/ngx_freebsd_init.c
@@ -14,6 +14,7 @@ char ngx_freebsd_kern_osrelease[128];
 int ngx_freebsd_kern_osreldate;
 int ngx_freebsd_hw_ncpu;
 int ngx_freebsd_net_inet_tcp_sendspace;
+int ngx_freebsd_kern_ipc_somaxconn;
 
 /* FreeBSD 4.9 */
 int ngx_freebsd_machdep_hlt_logical_cpus;
@@ -61,6 +62,10 @@ sysctl_t sysctls[] = {
       &ngx_freebsd_net_inet_tcp_sendspace,
       sizeof(int), 0 },
 
+    { "kern.ipc.somaxconn",
+      &ngx_freebsd_kern_ipc_somaxconn,
+      sizeof(int), 0 },
+
     { "kern.ipc.zero_copy.send",
       &ngx_freebsd_kern_ipc_zero_copy_send,
       sizeof(int), 0 },
@@ -85,7 +90,7 @@ void ngx_debug_init()
 
 ngx_int_t ngx_os_init(ngx_log_t *log)
 {
-    int         version;
+    int         version, somaxconn;
     size_t      size;
     ngx_err_t   err;
     ngx_uint_t  i;
@@ -203,6 +208,18 @@ ngx_int_t ngx_os_init(ngx_log_t *log)
         ngx_ncpu = ngx_freebsd_hw_ncpu;
     }
 
+    if (version < 600008) {
+        somaxconn = 32767;
+    } else {
+        somaxconn = 65535;
+    }
+
+    if (ngx_freebsd_kern_ipc_somaxconn > somaxconn) {
+        ngx_log_error(NGX_LOG_ALERT, log, 0,
+                      "sysctl kern.ipc.somaxconn must be no more than %d",
+                      somaxconn);
+        return NGX_ERROR;
+    }
 
     ngx_tcp_nodelay_and_tcp_nopush = 1;
 
--- a/src/os/unix/ngx_freebsd_rfork_thread.c
+++ b/src/os/unix/ngx_freebsd_rfork_thread.c
@@ -227,13 +227,15 @@ ngx_int_t ngx_init_threads(int n, size_t
 
     /* create the thread errno' array */
 
-    if (!(errnos = ngx_calloc(n * sizeof(int), cycle->log))) {
+    errnos = ngx_calloc(n * sizeof(int), cycle->log);
+    if (errnos == NULL) {
         return NGX_ERROR;
     }
 
     /* create the thread tids array */
 
-    if (!(tids = ngx_calloc((n + 1) * sizeof(ngx_tid_t), cycle->log))) {
+    tids = ngx_calloc((n + 1) * sizeof(ngx_tid_t), cycle->log);
+    if (tids == NULL) {
         return NGX_ERROR;
     }
 
@@ -264,8 +266,7 @@ ngx_int_t ngx_init_threads(int n, size_t
 
 ngx_tid_t ngx_thread_self()
 {
-    int        tid;
-    ngx_tid_t  pid;
+    ngx_int_t  tid;
 
     tid = ngx_gettid();
 
@@ -305,7 +306,8 @@ ngx_mutex_t *ngx_mutex_init(ngx_log_t *l
     ngx_mutex_t  *m;
     union semun   op;
 
-    if (!(m = ngx_alloc(sizeof(ngx_mutex_t), log))) {
+    m = ngx_alloc(sizeof(ngx_mutex_t), log);
+    if (m == NULL) {
         return NULL;
     }
 
@@ -353,7 +355,7 @@ void ngx_mutex_destroy(ngx_mutex_t *m)
 
 ngx_int_t ngx_mutex_dolock(ngx_mutex_t *m, ngx_int_t try)
 {
-    uint32_t       lock, new, old;
+    uint32_t       lock, old;
     ngx_uint_t     tries;
     struct sembuf  op;
 
@@ -483,7 +485,7 @@ ngx_int_t ngx_mutex_dolock(ngx_mutex_t *
 
 ngx_int_t ngx_mutex_unlock(ngx_mutex_t *m)
 {
-    uint32_t       lock, new, old;
+    uint32_t       lock, old;
     struct sembuf  op;
 
     if (!ngx_threaded) {
@@ -576,7 +578,8 @@ ngx_cond_t *ngx_cond_init(ngx_log_t *log
 {
     ngx_cond_t  *cv;
 
-    if (!(cv = ngx_alloc(sizeof(ngx_cond_t), log))) {
+    cv = ngx_alloc(sizeof(ngx_cond_t), log);
+    if (cv == NULL) {
         return NULL;
     }
 
--- a/src/os/unix/ngx_freebsd_rfork_thread.h
+++ b/src/os/unix/ngx_freebsd_rfork_thread.h
@@ -56,7 +56,7 @@ extern char    *ngx_freebsd_kern_usrstac
 extern size_t   ngx_thread_stack_size;
 
 
-static inline int ngx_gettid()
+static ngx_inline ngx_int_t ngx_gettid()
 {
     char  *sp;
 
--- a/src/os/unix/ngx_freebsd_sendfile_chain.c
+++ b/src/os/unix/ngx_freebsd_sendfile_chain.c
@@ -21,19 +21,19 @@
  * to postpone the sending - it not only sends a header and the first part of
  * the file in one packet, but also sends the file pages in the full packets.
  *
- * But until FreeBSD 4.5 the turning TCP_NOPUSH off does not flush a pending
- * data that less than MSS so that data may be sent with 5 second delay.
- * So we do not use TCP_NOPUSH on FreeBSD prior to 4.5 although it can be used
+ * But until FreeBSD 4.5 turning TCP_NOPUSH off does not flush a pending
+ * data that less than MSS, so that data may be sent with 5 second delay.
+ * So we do not use TCP_NOPUSH on FreeBSD prior to 4.5, although it can be used
  * for non-keepalive HTTP connections.
  */
 
 
 #define NGX_HEADERS   8
-#define NGX_TRAILERS  4
+#define NGX_TRAILERS  8
 
 
-ngx_chain_t *ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in,
-                                        off_t limit)
+ngx_chain_t *
+ngx_freebsd_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
 {
     int              rc;
     u_char          *prev;
@@ -123,7 +123,8 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(
                 iov->iov_len += (size_t) size;
 
             } else {
-                if (!(iov = ngx_array_push(&header))) {
+                iov = ngx_array_push(&header);
+                if (iov == NULL) {
                     return NGX_CHAIN_ERROR;
                 }
 
@@ -197,7 +198,8 @@ ngx_chain_t *ngx_freebsd_sendfile_chain(
                     iov->iov_len += (size_t) size;
 
                 } else {
-                    if (!(iov = ngx_array_push(&trailer))) {
+                    iov = ngx_array_push(&trailer);
+                    if (iov == NULL) {
                         return NGX_CHAIN_ERROR;
                     }
 
--- a/src/os/unix/ngx_linux_sendfile_chain.c
+++ b/src/os/unix/ngx_linux_sendfile_chain.c
@@ -121,7 +121,8 @@ ngx_chain_t *ngx_linux_sendfile_chain(ng
                 iov->iov_len += (size_t) size;
 
             } else {
-                if (!(iov = ngx_array_push(&header))) {
+                iov = ngx_array_push(&header);
+                if (iov == NULL) {
                     return NGX_CHAIN_ERROR;
                 }
 
--- a/src/os/unix/ngx_posix_init.c
+++ b/src/os/unix/ngx_posix_init.c
@@ -182,7 +182,7 @@ void ngx_signal_handler(int signo)
 
         case ngx_signal_value(NGX_NOACCEPT_SIGNAL):
             ngx_noaccept = 1;
-            action = ", stop the accepting connections";
+            action = ", stop accepting connections";
             break;
 
         case ngx_signal_value(NGX_RECONFIGURE_SIGNAL):
--- a/src/os/unix/ngx_process.c
+++ b/src/os/unix/ngx_process.c
@@ -214,7 +214,6 @@ void ngx_process_get_status()
     ngx_err_t        err;
     ngx_int_t        i;
     ngx_uint_t       one;
-    struct timeval   tv;
 
     one = 0;
 
--- a/src/os/unix/ngx_process_cycle.c
+++ b/src/os/unix/ngx_process_cycle.c
@@ -11,7 +11,7 @@
 
 
 static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n,
-                                       ngx_int_t type);
+    ngx_int_t type);
 static void ngx_start_garbage_collector(ngx_cycle_t *cycle, ngx_int_t type);
 static void ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo);
 static ngx_uint_t ngx_reap_childs(ngx_cycle_t *cycle);
@@ -23,7 +23,9 @@ static void ngx_channel_handler(ngx_even
 static void ngx_wakeup_worker_threads(ngx_cycle_t *cycle);
 static void *ngx_worker_thread_cycle(void *data);
 #endif
+#if 0
 static void ngx_garbage_collector_cycle(ngx_cycle_t *cycle, void *data);
+#endif
 
 
 ngx_uint_t    ngx_process;
@@ -59,7 +61,8 @@ ngx_int_t              ngx_threads_n;
 u_char  master_process[] = "master process";
 
 
-void ngx_master_process_cycle(ngx_cycle_t *cycle)
+void
+ngx_master_process_cycle(ngx_cycle_t *cycle)
 {
     char              *title;
     u_char            *p;
@@ -254,7 +257,8 @@ void ngx_master_process_cycle(ngx_cycle_
 }
 
 
-void ngx_single_process_cycle(ngx_cycle_t *cycle)
+void
+ngx_single_process_cycle(ngx_cycle_t *cycle)
 {
     ngx_uint_t  i;
 
@@ -300,8 +304,8 @@ void ngx_single_process_cycle(ngx_cycle_
 }
 
 
-static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n,
-                                       ngx_int_t type)
+static void
+ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type)
 {
     ngx_int_t         i;
     ngx_channel_t     ch;
@@ -359,12 +363,12 @@ static void ngx_start_worker_processes(n
 }
 
 
-static void ngx_start_garbage_collector(ngx_cycle_t *cycle, ngx_int_t type)
+static void
+ngx_start_garbage_collector(ngx_cycle_t *cycle, ngx_int_t type)
 {
-    ngx_int_t         i;
-    ngx_channel_t     ch;
-
-    return;
+#if 0
+    ngx_int_t      i;
+    ngx_channel_t  ch;
 
     ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start garbage collector");
 
@@ -397,16 +401,17 @@ static void ngx_start_garbage_collector(
         ngx_write_channel(ngx_processes[i].channel[0],
                           &ch, sizeof(ngx_channel_t), cycle->log);
     }
+#endif
 }
 
 
-static void ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo)
+static void
+ngx_signal_worker_processes(ngx_cycle_t *cycle, int signo)
 {
     ngx_int_t      i;
     ngx_err_t      err;
     ngx_channel_t  ch;
 
-
     switch (signo) {
 
     case ngx_signal_value(NGX_SHUTDOWN_SIGNAL):
@@ -492,7 +497,8 @@ static void ngx_signal_worker_processes(
 }
 
 
-static ngx_uint_t ngx_reap_childs(ngx_cycle_t *cycle)
+static ngx_uint_t
+ngx_reap_childs(ngx_cycle_t *cycle)
 {
     ngx_int_t      i, n;
     ngx_uint_t     live;
@@ -619,7 +625,8 @@ static ngx_uint_t ngx_reap_childs(ngx_cy
 }
 
 
-static void ngx_master_exit(ngx_cycle_t *cycle)
+static void
+ngx_master_exit(ngx_cycle_t *cycle)
 {
     ngx_delete_pidfile(cycle);
 
@@ -631,11 +638,14 @@ static void ngx_master_exit(ngx_cycle_t 
 }
 
 
-static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
+static void
+ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
 {
+#if (NGX_THREADS)
     ngx_int_t          n;
     ngx_err_t          err;
     ngx_core_conf_t   *ccf;
+#endif
 
     ngx_worker_process_init(cycle, 1);
 
@@ -668,7 +678,9 @@ static void ngx_worker_process_cycle(ngx
 
         for (n = 0; n < ngx_threads_n; n++) {
 
-            if (!(ngx_threads[n].cv = ngx_cond_init(cycle->log))) {
+            ngx_threads[n].cv = ngx_cond_init(cycle->log);
+
+            if (ngx_threads[n].cv == NULL) {
                 /* fatal */
                 exit(2);
             }
@@ -748,7 +760,8 @@ static void ngx_worker_process_cycle(ngx
 }
 
 
-static void ngx_worker_process_init(ngx_cycle_t *cycle, ngx_uint_t priority)
+static void
+ngx_worker_process_init(ngx_cycle_t *cycle, ngx_uint_t priority)
 {
     sigset_t           set;
     ngx_int_t          n;
@@ -873,7 +886,8 @@ static void ngx_worker_process_init(ngx_
 }
 
 
-static void ngx_channel_handler(ngx_event_t *ev)
+static void
+ngx_channel_handler(ngx_event_t *ev)
 {
     ngx_int_t          n;
     ngx_channel_t      ch;
@@ -952,7 +966,8 @@ static void ngx_channel_handler(ngx_even
 
 #if (NGX_THREADS)
 
-static void ngx_wakeup_worker_threads(ngx_cycle_t *cycle)
+static void
+ngx_wakeup_worker_threads(ngx_cycle_t *cycle)
 {
     ngx_int_t   i;
     ngx_uint_t  live;
@@ -994,7 +1009,8 @@ static void ngx_wakeup_worker_threads(ng
 }
 
 
-static void *ngx_worker_thread_cycle(void *data)
+static void *
+ngx_worker_thread_cycle(void *data)
 {
     ngx_thread_t  *thr = data;
 
@@ -1022,7 +1038,8 @@ static void *ngx_worker_thread_cycle(voi
 
     ngx_setthrtitle("worker thread");
 
-    if (!(tls = ngx_calloc(sizeof(ngx_core_tls_t), cycle->log))) {
+    tls = ngx_calloc(sizeof(ngx_core_tls_t), cycle->log);
+    if (tls == NULL) {
         return (void *) 1;
     }
 
@@ -1077,7 +1094,10 @@ static void *ngx_worker_thread_cycle(voi
 #endif
 
 
-static void ngx_garbage_collector_cycle(ngx_cycle_t *cycle, void *data)
+#if 0
+
+static void
+ngx_garbage_collector_cycle(ngx_cycle_t *cycle, void *data)
 {
     ngx_uint_t         i;
     ngx_gc_t           ctx;
@@ -1123,3 +1143,5 @@ static void ngx_garbage_collector_cycle(
         ngx_process_events(cycle);
     }
 }
+
+#endif
--- a/src/os/unix/ngx_pthread_thread.c
+++ b/src/os/unix/ngx_pthread_thread.c
@@ -75,7 +75,8 @@ ngx_mutex_t *ngx_mutex_init(ngx_log_t *l
     int           err;
     ngx_mutex_t  *m;
 
-    if (!(m = ngx_alloc(sizeof(ngx_mutex_t), log))) {
+    m = ngx_alloc(sizeof(ngx_mutex_t), log);
+    if (m == NULL) {
         return NULL;
     }
     
@@ -189,7 +190,8 @@ ngx_cond_t *ngx_cond_init(ngx_log_t *log
     int          err;
     ngx_cond_t  *cv;
 
-    if (!(cv = ngx_alloc(sizeof(ngx_cond_t), log))) {
+    cv = ngx_alloc(sizeof(ngx_cond_t), log);
+    if (cv == NULL) {
         return NULL;
     }
     
--- a/src/os/unix/ngx_readv_chain.c
+++ b/src/os/unix/ngx_readv_chain.c
@@ -9,16 +9,20 @@
 #include <ngx_event.h>
 
 
+#define NGX_IOVS  16
+
+
 #if (NGX_HAVE_KQUEUE)
 
-ssize_t ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain)
+ssize_t
+ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain)
 {
     u_char        *prev;
     ssize_t        n, size;
     ngx_err_t      err;
-    ngx_array_t    io;
+    ngx_array_t    vec;
     ngx_event_t   *rev;
-    struct iovec  *iov;
+    struct iovec  *iov, iovs[NGX_IOVS];
 
     rev = c->read; 
 
@@ -53,7 +57,11 @@ ssize_t ngx_readv_chain(ngx_connection_t
     iov = NULL;
     size = 0;
 
-    ngx_init_array(io, c->pool, 10, sizeof(struct iovec), NGX_ERROR);
+    vec.elts = iovs;
+    vec.nelts = 0;
+    vec.size = sizeof(struct iovec);
+    vec.nalloc = NGX_IOVS;
+    vec.pool = c->pool;
 
     /* coalesce the neighbouring bufs */
 
@@ -62,7 +70,11 @@ ssize_t ngx_readv_chain(ngx_connection_t
             iov->iov_len += chain->buf->end - chain->buf->last;
 
         } else {
-            ngx_test_null(iov, ngx_push_array(&io), NGX_ERROR);
+            iov = ngx_array_push(&vec);
+            if (iov == NULL) {
+                return NGX_ERROR;
+            }
+
             iov->iov_base = (void *) chain->buf->last;
             iov->iov_len = chain->buf->end - chain->buf->last;
         }
@@ -73,12 +85,12 @@ ssize_t ngx_readv_chain(ngx_connection_t
     }
 
     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
-                   "readv: %d, last:%d", io.nelts, iov->iov_len);
+                   "readv: %d, last:%d", vec.nelts, iov->iov_len);
 
     rev = c->read;
 
     do {
-        n = readv(c->fd, (struct iovec *) io.elts, io.nelts);
+        n = readv(c->fd, (struct iovec *) vec.elts, vec.nelts);
 
         if (n >= 0) {
             if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) {
@@ -138,20 +150,25 @@ ssize_t ngx_readv_chain(ngx_connection_t
 
 #else /* ! NGX_HAVE_KQUEUE */
 
-ssize_t ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain)
+ssize_t
+ngx_readv_chain(ngx_connection_t *c, ngx_chain_t *chain)
 {
     u_char        *prev;
     ssize_t        n, size;
     ngx_err_t      err;
-    ngx_array_t    io;
+    ngx_array_t    vec;
     ngx_event_t   *rev;
-    struct iovec  *iov;
+    struct iovec  *iov, iovs[NGX_IOVS];
 
     prev = NULL;
     iov = NULL;
     size = 0;
 
-    ngx_init_array(io, c->pool, 10, sizeof(struct iovec), NGX_ERROR);
+    vec.elts = iovs;
+    vec.nelts = 0;
+    vec.size = sizeof(struct iovec);
+    vec.nalloc = NGX_IOVS;
+    vec.pool = c->pool;
 
     /* coalesce the neighbouring bufs */
 
@@ -160,7 +177,11 @@ ssize_t ngx_readv_chain(ngx_connection_t
             iov->iov_len += chain->buf->end - chain->buf->last;
 
         } else {
-            ngx_test_null(iov, ngx_push_array(&io), NGX_ERROR);
+            iov = ngx_array_push(&vec);
+            if (iov == NULL) {
+                return NGX_ERROR;
+            }
+
             iov->iov_base = chain->buf->last;
             iov->iov_len = chain->buf->end - chain->buf->last;
         }
@@ -171,12 +192,12 @@ ssize_t ngx_readv_chain(ngx_connection_t
     }
 
     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
-                   "readv: %d:%d", io.nelts, iov->iov_len);
+                   "readv: %d:%d", vec.nelts, iov->iov_len);
 
     rev = c->read;
 
     do {
-        n = readv(c->fd, (struct iovec *) io.elts, io.nelts);
+        n = readv(c->fd, (struct iovec *) vec.elts, vec.nelts);
 
         if (n == 0) {
             rev->ready = 0;
--- a/src/os/unix/ngx_setproctitle.c
+++ b/src/os/unix/ngx_setproctitle.c
@@ -43,7 +43,8 @@ ngx_init_setproctitle(ngx_log_t *log)
         size += ngx_strlen(environ[i]) + 1;
     }
 
-    if (!(p = ngx_alloc(size, log))) {
+    p = ngx_alloc(size, log);
+    if (p == NULL) {
         return NGX_ERROR;
     }
 
--- a/src/os/unix/ngx_socket.c
+++ b/src/os/unix/ngx_socket.c
@@ -22,7 +22,8 @@
 
 #if (NGX_HAVE_FIONBIO)
 
-int ngx_nonblocking(ngx_socket_t s)
+int
+ngx_nonblocking(ngx_socket_t s)
 {
     u_long  nb;
 
@@ -32,7 +33,8 @@ int ngx_nonblocking(ngx_socket_t s)
 }
 
 
-int ngx_blocking(ngx_socket_t s)
+int
+ngx_blocking(ngx_socket_t s)
 {
     u_long  nb;
 
@@ -46,7 +48,8 @@ int ngx_blocking(ngx_socket_t s)
 
 #if (NGX_FREEBSD)
 
-int ngx_tcp_nopush(ngx_socket_t s)
+int
+ngx_tcp_nopush(ngx_socket_t s)
 {
     int  tcp_nopush;
 
@@ -57,7 +60,8 @@ int ngx_tcp_nopush(ngx_socket_t s)
 }
 
 
-int ngx_tcp_push(ngx_socket_t s)
+int
+ngx_tcp_push(ngx_socket_t s)
 {
     int  tcp_nopush;
 
@@ -69,7 +73,8 @@ int ngx_tcp_push(ngx_socket_t s)
 
 #elif (NGX_LINUX)
 
-int ngx_tcp_nopush(ngx_socket_t s)
+int
+ngx_tcp_nopush(ngx_socket_t s)
 {
     int  cork;
 
@@ -79,7 +84,8 @@ int ngx_tcp_nopush(ngx_socket_t s)
                       (const void *) &cork, sizeof(int));
 }
 
-int ngx_tcp_push(ngx_socket_t s)
+int
+ngx_tcp_push(ngx_socket_t s)
 {
     int  cork;
 
@@ -91,14 +97,16 @@ int ngx_tcp_push(ngx_socket_t s)
 
 #else
 
-int ngx_tcp_nopush(ngx_socket_t s)
+int
+ngx_tcp_nopush(ngx_socket_t s)
 {
-    return NGX_OK;
+    return 0;
 }
 
-int ngx_tcp_push(ngx_socket_t s)
+int
+ngx_tcp_push(ngx_socket_t s)
 {
-    return NGX_OK;
+    return 0;
 }
 
 #endif
--- a/src/os/unix/ngx_solaris_sendfilev_chain.c
+++ b/src/os/unix/ngx_solaris_sendfilev_chain.c
@@ -47,7 +47,7 @@ ngx_chain_t *ngx_solaris_sendfilev_chain
     sendfilevec_t  *sfv, sfvs[NGX_SENDFILEVECS];
     ngx_array_t     vec;
     ngx_event_t    *wev;
-    ngx_chain_t    *cl, *tail;
+    ngx_chain_t    *cl;
 
     wev = c->write;
 
@@ -107,7 +107,8 @@ ngx_chain_t *ngx_solaris_sendfilev_chain
                     sfv->sfv_len += (size_t) size;
 
                 } else {
-                    if (!(sfv = ngx_array_push(&vec))) {
+                    sfv = ngx_array_push(&vec);
+                    if (sfv == NULL) {
                         return NGX_CHAIN_ERROR;
                     }
 
@@ -140,7 +141,8 @@ ngx_chain_t *ngx_solaris_sendfilev_chain
                     sfv->sfv_len += (size_t) size;
 
                 } else {
-                    if (!(sfv = ngx_array_push(&vec))) {
+                    sfv = ngx_array_push(&vec);
+                    if (sfv == NULL) {
                         return NGX_CHAIN_ERROR;
                     }
 
--- a/src/os/unix/ngx_writev_chain.c
+++ b/src/os/unix/ngx_writev_chain.c
@@ -12,7 +12,8 @@
 #define NGX_IOVS  16
 
 
-ngx_chain_t *ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
+ngx_chain_t *
+ngx_writev_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
 {
     u_char        *prev;
     ssize_t        n, size, sent;
@@ -88,7 +89,8 @@ ngx_chain_t *ngx_writev_chain(ngx_connec
                 iov->iov_len += size;
 
             } else {
-                if (!(iov = ngx_array_push(&vec))) {
+                iov = ngx_array_push(&vec);
+                if (iov == NULL) {
                     return NGX_CHAIN_ERROR;
                 }