changeset 508:68c0ae0a4959 NGINX_0_7_66

nginx 0.7.66 *) Security: now nginx/Windows ignores default file stream name. Thanks to Jose Antonio Vazquez Gonzalez. *) Change: now the charset filter runs before the SSI filter. *) Change: now no message is written in an error log if a variable is not found by $r->variable() method. *) Change: now keepalive connections after POST requests are not disabled for MSIE 7.0+. Thanks to Adam Lounds. *) Feature: the "proxy_no_cache" and "fastcgi_no_cache" directives. *) Feature: now the "rewrite" directive does a redirect automatically if the $scheme variable is used. Thanks to Piotr Sikora. *) Feature: the "chunked_transfer_encoding" directive. *) Feature: the $geoip_city_continent_code, $geoip_latitude, and $geoip_longitude variables. Thanks to Arvind Sundararajan. *) Feature: now the ngx_http_image_filter_module deletes always EXIF and other application specific data if the data consume more than 5% of a JPEG file. *) Feature: now the "msie_padding" directive works for Chrome too. *) Workaround: now keepalive connections are disabled for Safari. Thanks to Joshua Sierles. *) Bugfix: nginx ignored the "private" and "no-store" values in the "Cache-Control" backend response header line. *) Bugfix: an "&" character was not escaped when it was copied in arguments part in a rewrite rule. *) Bugfix: nginx might be terminated abnormally while a signal processing or if the directive "timer_resolution" was used on platforms which do not support kqueue or eventport notification methods. Thanks to George Xie and Maxim Dounin. *) Bugfix: if temporary files and permanent storage area resided at different file systems, then permanent file modification times were incorrect. Thanks to Maxim Dounin. *) Bugfix: ngx_http_memcached_module might issue the error message "memcached sent invalid trailer". Thanks to Maxim Dounin. *) Bugfix: nginx could not built zlib-1.2.4 library using the library sources. Thanks to Maxim Dounin. *) Bugfix: values of the $query_string, $arg_..., etc. variables cached in main request were used by the SSI module in subrequests. *) Bugfix: nginx did not support HTTPS referrers. *) Bugfix: nginx/Windows might not find file if path in configuration was given in other character case; the bug had appeared in 0.7.65. *) Bugfix: the $date_local variable has an incorrect value, if the "%s" format was used. Thanks to Maxim Dounin. *) Bugfix: nginx did not support all ciphers and digests used in client certificates. Thanks to Innocenty Enikeew. *) Bugfix: if ssl_session_cache was not set or was set to "none", then during client certificate verify the error "session id context uninitialized" might occur; the bug had appeared in 0.7.1. *) Bugfix: OpenSSL-1.0.0 compatibility on 64-bit Linux. Thanks to Maxim Dounin. *) Bugfix: a geo range returned default value if the range included two or more /16 networks and did not begin at /16 network boundary. *) Bugfix: the $uid_got variable might not be used in the SSI and perl modules. *) Bugfix: a worker process hung if a FIFO file was requested. Thanks to Vicente Aguilar and Maxim Dounin. *) Bugfix: a variable value was repeatedly encoded after each an "echo" SSI-command output; the bug had appeared in 0.6.14. *) Bugfix: a "stub" parameter of an "include" SSI directive was not used, if empty response has 200 status code. *) Bugfix: a block used in a "stub" parameter of an "include" SSI directive was output with "text/plain" MIME type. *) Bugfix: if a proxied or FastCGI request was internally redirected to another proxied or FastCGI location, then a segmentation fault might occur in a worker process; the bug had appeared in 0.7.65. Thanks to Yichun Zhang. *) Bugfix: IMAP connections may hang until they timed out while talking to Zimbra server. Thanks to Alan Batie. *) Bugfix: nginx did not support chunked transfer encoding for 201 responses. Thanks to Julian Reich.
author Igor Sysoev <http://sysoev.ru>
date Mon, 07 Jun 2010 00:00:00 +0400
parents bfc170196f52
children b875e7d99b59
files CHANGES CHANGES.ru auto/cc/conf auto/cc/gcc auto/feature auto/lib/openssl/conf auto/lib/openssl/make auto/lib/openssl/makefile.bcc auto/lib/openssl/makefile.msvc auto/lib/zlib/make auto/modules auto/unix src/core/nginx.h src/core/ngx_cycle.c src/core/ngx_file.c src/core/ngx_open_file_cache.c src/core/ngx_string.c src/core/ngx_times.c src/core/ngx_times.h src/event/modules/ngx_devpoll_module.c src/event/modules/ngx_epoll_module.c src/event/modules/ngx_eventport_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/modules/ngx_win32_select_module.c src/event/ngx_event.c src/event/ngx_event_openssl.c src/event/ngx_event_openssl.h src/http/modules/ngx_http_autoindex_module.c src/http/modules/ngx_http_chunked_filter_module.c src/http/modules/ngx_http_dav_module.c src/http/modules/ngx_http_fastcgi_module.c src/http/modules/ngx_http_flv_module.c src/http/modules/ngx_http_geo_module.c src/http/modules/ngx_http_geoip_module.c src/http/modules/ngx_http_gzip_static_module.c src/http/modules/ngx_http_image_filter_module.c src/http/modules/ngx_http_index_module.c src/http/modules/ngx_http_memcached_module.c src/http/modules/ngx_http_proxy_module.c src/http/modules/ngx_http_random_index_module.c src/http/modules/ngx_http_referer_module.c src/http/modules/ngx_http_rewrite_module.c src/http/modules/ngx_http_ssi_filter_module.c src/http/modules/ngx_http_static_module.c src/http/modules/ngx_http_userid_filter_module.c src/http/modules/perl/nginx.pm src/http/modules/perl/nginx.xs src/http/modules/perl/ngx_http_perl_module.c src/http/ngx_http_cache.h src/http/ngx_http_copy_filter_module.c src/http/ngx_http_core_module.c src/http/ngx_http_core_module.h src/http/ngx_http_file_cache.c src/http/ngx_http_header_filter_module.c src/http/ngx_http_parse.c src/http/ngx_http_request.c src/http/ngx_http_request.h src/http/ngx_http_special_response.c src/http/ngx_http_upstream.c src/http/ngx_http_upstream.h src/http/ngx_http_variables.c src/http/ngx_http_variables.h src/mail/ngx_mail_pop3_handler.c src/mail/ngx_mail_proxy_module.c src/os/unix/ngx_errno.h src/os/unix/ngx_files.h src/os/unix/ngx_process.c src/os/unix/ngx_process_cycle.c
diffstat 71 files changed, 814 insertions(+), 305 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,119 @@
 
+Changes with nginx 0.7.66                                        07 Jun 2010
+
+    *) Security: now nginx/Windows ignores default file stream name.
+       Thanks to Jose Antonio Vazquez Gonzalez.
+
+    *) Change: now the charset filter runs before the SSI filter.
+
+    *) Change: now no message is written in an error log if a variable is 
+       not found by $r->variable() method.
+
+    *) Change: now keepalive connections after POST requests are not 
+       disabled for MSIE 7.0+.
+       Thanks to Adam Lounds.
+
+    *) Feature: the "proxy_no_cache" and "fastcgi_no_cache" directives.
+
+    *) Feature: now the "rewrite" directive does a redirect automatically 
+       if the $scheme variable is used.
+       Thanks to Piotr Sikora.
+
+    *) Feature: the "chunked_transfer_encoding" directive.
+
+    *) Feature: the $geoip_city_continent_code, $geoip_latitude, and 
+       $geoip_longitude variables.
+       Thanks to Arvind Sundararajan.
+
+    *) Feature: now the ngx_http_image_filter_module deletes always EXIF 
+       and other application specific data if the data consume more than 5% 
+       of a JPEG file.
+
+    *) Feature: now the "msie_padding" directive works for Chrome too.
+
+    *) Workaround: now keepalive connections are disabled for Safari.
+       Thanks to Joshua Sierles.
+
+    *) Bugfix: nginx ignored the "private" and "no-store" values in the 
+       "Cache-Control" backend response header line.
+
+    *) Bugfix: an "&" character was not escaped when it was copied in 
+       arguments part in a rewrite rule.
+
+    *) Bugfix: nginx might be terminated abnormally while a signal 
+       processing or if the directive "timer_resolution" was used on 
+       platforms which do not support kqueue or eventport notification 
+       methods.
+       Thanks to George Xie and Maxim Dounin.
+
+    *) Bugfix: if temporary files and permanent storage area resided at 
+       different file systems, then permanent file modification times were 
+       incorrect.
+       Thanks to Maxim Dounin.
+
+    *) Bugfix: ngx_http_memcached_module might issue the error message 
+       "memcached sent invalid trailer".
+       Thanks to Maxim Dounin.
+
+    *) Bugfix: nginx could not built zlib-1.2.4 library using the library 
+       sources.
+       Thanks to Maxim Dounin.
+
+    *) Bugfix: values of the $query_string, $arg_..., etc. variables cached 
+       in main request were used by the SSI module in subrequests.
+
+    *) Bugfix: nginx did not support HTTPS referrers.
+
+    *) Bugfix: nginx/Windows might not find file if path in configuration 
+       was given in other character case; the bug had appeared in 0.7.65.
+
+    *) Bugfix: the $date_local variable has an incorrect value, if the "%s" 
+       format was used.
+       Thanks to Maxim Dounin.
+
+    *) Bugfix: nginx did not support all ciphers and digests used in client 
+       certificates.
+       Thanks to Innocenty Enikeew.
+
+    *) Bugfix: if ssl_session_cache was not set or was set to "none", then 
+       during client certificate verify the error "session id context 
+       uninitialized" might occur; the bug had appeared in 0.7.1.
+
+    *) Bugfix: OpenSSL-1.0.0 compatibility on 64-bit Linux.
+       Thanks to Maxim Dounin.
+
+    *) Bugfix: a geo range returned default value if the range included two 
+       or more /16 networks and did not begin at /16 network boundary.
+
+    *) Bugfix: the $uid_got variable might not be used in the SSI and perl 
+       modules.
+
+    *) Bugfix: a worker process hung if a FIFO file was requested.
+       Thanks to Vicente Aguilar and Maxim Dounin.
+
+    *) Bugfix: a variable value was repeatedly encoded after each an "echo" 
+       SSI-command output; the bug had appeared in 0.6.14.
+
+    *) Bugfix: a "stub" parameter of an "include" SSI directive was not 
+       used, if empty response has 200 status code.
+
+    *) Bugfix: a block used in a "stub" parameter of an "include" SSI 
+       directive was output with "text/plain" MIME type.
+
+    *) Bugfix: if a proxied or FastCGI request was internally redirected to 
+       another proxied or FastCGI location, then a segmentation fault might 
+       occur in a worker process; the bug had appeared in 0.7.65.
+       Thanks to Yichun Zhang.
+
+    *) Bugfix: IMAP connections may hang until they timed out while talking 
+       to Zimbra server.
+       Thanks to Alan Batie.
+
+    *) Bugfix: nginx did not support chunked transfer encoding for 201 
+       responses.
+       Thanks to Julian Reich.
+
+
 Changes with nginx 0.7.65                                        01 Feb 2010
 
     *) Security: now nginx/Windows ignores trailing spaces in URI.
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,122 @@
 
+Изменения в nginx 0.7.66                                          07.06.2010
+
+    *) Безопасность: теперь nginx/Windows игнорирует имя потока файла по 
+       умолчанию.
+       Спасибо Jose Antonio Vazquez Gonzalez.
+
+    *) Изменение: теперь charset-фильтр работает до SSI-фильтра.
+
+    *) Изменение: теперь в лог ошибок не пишется сообщение, если переменная 
+       не найдена с помощью метода $r->variable().
+
+    *) Изменение: теперь keepalive соединения после запросов POST не 
+       запрещаются для MSIE 7.0+.
+       Спасибо Adam Lounds.
+
+    *) Добавление: директивы proxy_no_cache и fastcgi_no_cache.
+
+    *) Добавление: теперь при использовании переменной $scheme в директиве 
+       rewrite автоматически делается редирект.
+       Спасибо Piotr Sikora.
+
+    *) Добавление: директива chunked_transfer_encoding.
+
+    *) Добавление: переменные $geoip_city_continent_code, $geoip_latitude и 
+       $geoip_longitude.
+       Спасибо Arvind Sundararajan.
+
+    *) Добавление: модуль ngx_http_image_filter_module теперь всегда 
+       удаляет EXIF и другие данные, если они занимают больше 5% в 
+       JPEG-файле.
+
+    *) Добавление: теперь директива msie_padding работает и для Chrome.
+
+    *) Изменение: теперь keepalive соединения запрещены для Safari.
+       Спасибо Joshua Sierles.
+
+    *) Исправление: nginx игнорировал значения "private" и "no-store" в 
+       строке "Cache-Control" в заголовке ответа бэкенда.
+
+    *) Исправление: символ "&" при копировании в аргументы в правилах 
+       rewrite не экранировался.
+
+    *) Исправление: nginx мог завершаться аварийно во время обработки 
+       сигнала или при использовании директивы timer_resolution на 
+       платформах, не поддерживающих методы kqueue или eventport.
+       Спасибо George Xie и Максиму Дунину.
+
+    *) Исправление: если временные файлы и постоянное место хранения 
+       располагались на разных файловых системах, то у постоянных файлов 
+       время изменения было неверным.
+       Спасибо Максиму Дунину.
+
+    *) Исправление: модуль ngx_http_memcached_module мог выдавать ошибку 
+       "memcached sent invalid trailer".
+       Спасибо Максиму Дунину.
+
+    *) Исправление: nginx не мог собрать библиотеку zlib-1.2.4 из исходных 
+       текстов.
+       Спасибо Максиму Дунину.
+
+    *) Исправление: модуль SSI в подзапросах использовал закэшированные в 
+       основном запросе значения переменных $query_string, $arg_... и им 
+       подобных.
+
+    *) Исправление: nginx не поддерживал HTTPS-рефереры.
+
+    *) Исправление: nginx/Windows мог не находить файлы, если путь в 
+       конфигурации был задан в другом регистре; ошибка появилась в 0.7.65.
+
+    *) Исправление: переменная $date_local выдавала неверное время, если 
+       использовался формат "%s".
+       Спасибо Максиму Дунину.
+
+    *) Исправление: nginx не поддерживал все шифры, используемые в 
+       клиентских сертификатах.
+       Спасибо Иннокентию Еникееву.
+
+    *) Исправление: если ssl_session_cache не был установлен или установлен 
+       в none, то при проверке клиентского сертификаты могла происходить 
+       ошибка "session id context uninitialized"; ошибка появилась в 0.7.1.
+
+    *) Исправление: совместимость с OpenSSL-1.0.0 на 64-битном Linux.
+       Спасибо Максиму Дунину.
+
+    *) Исправление: geo-диапазон возвращал значение по умолчанию, если 
+       диапазон включал в себя одну и более сетей размером /16 и не 
+       начинался на границе сети размером /16.
+
+    *) Исправление: переменную $uid_got нельзя было использовать в SSI и 
+       перловом модулях.
+
+    *) Исправление: рабочий процесс зависал при запросе файла FIFO.
+       Спасибо Vicente Aguilar и Максиму Дунину.
+
+    *) Исправление: значение переменной повторно экранировалось после 
+       каждого вывода SSI-команды echo; ошибка появилась в 0.6.14.
+
+    *) Исправление: параметр stub в SSI-директиве include не использовался, 
+       если пустой ответ имел код 200.
+
+    *) Исправление: блок, используемый в параметре stub в SSI-директиве 
+       include, выводился с MIME-типом "text/plain".
+
+    *) Исправление: если проксированный или FastCGI запрос внутренне 
+       перенаправлялся в другой проксированный или FastCGI location, то в 
+       рабочем процессе мог произойти segmentation fault; ошибка появилась 
+       в 0.7.65.
+       Спасибо Yichun Zhang.
+
+    *) Исправление: соединения IMAP к серверу Zimbra могло зависнуть до 
+       таймаута.
+       Спасибо Alan Batie.
+
+    *) Исправление: nginx не поддерживал передачу chunk'ами для 201-ых 
+       ответов.
+       Спасибо Julian Reich.
+
+
 Изменения в nginx 0.7.65                                          01.02.2010
 
     *) Безопасность: теперь nginx/Windows игнорирует пробелы в конце URI. 
@@ -178,7 +296,7 @@
 
     *) Добавление: директивы limit_req_log_level и limit_conn_log_level.
 
-    *) Исправление: Теперь директива limit_req соответствует алгоритму 
+    *) Исправление: теперь директива limit_req соответствует алгоритму 
        leaky bucket.
        Спасибо Максиму Дунину.
 
@@ -1648,7 +1766,7 @@
        Спасибо Андрею Нигматулину.
 
     *) Исправление: ngx_http_memcached_module не устанавливал 
-       upstream_response_time.
+       $upstream_response_time.
        Спасибо Максиму Дунину.
 
     *) Исправление: рабочий процесс мог зациклиться при использовании 
--- a/auto/cc/conf
+++ b/auto/cc/conf
@@ -104,6 +104,7 @@ else
 fi
 
 CFLAGS="$CFLAGS $NGX_CC_OPT"
+NGX_TEST_LD_OPT="$NGX_LD_OPT"
 
 
 if [ "$NGX_PLATFORM" != win32 ]; then
--- a/auto/cc/gcc
+++ b/auto/cc/gcc
@@ -51,8 +51,6 @@ esac
 #NGX_GCC_OPT="-Os"
 NGX_GCC_OPT="-O"
 
-CFLAGS="$CFLAGS $NGX_GCC_OPT"
-
 #CFLAGS="$CFLAGS -fomit-frame-pointer"
 
 case $CPU in
--- a/auto/feature
+++ b/auto/feature
@@ -39,7 +39,7 @@ END
 
 
 ngx_test="$CC $CC_TEST_FLAGS $CC_AUX_FLAGS $ngx_feature_inc_path \
-          -o $NGX_AUTOTEST $NGX_AUTOTEST.c $NGX_LD_OPT $ngx_feature_libs"
+          -o $NGX_AUTOTEST $NGX_AUTOTEST.c $NGX_TEST_LD_OPT $ngx_feature_libs"
 
 ngx_feature_inc_path=
 
--- a/auto/lib/openssl/conf
+++ b/auto/lib/openssl/conf
@@ -19,6 +19,8 @@ if [ $OPENSSL != NONE ]; then
 
             # libeay32.lib requires gdi32.lib
             CORE_LIBS="$CORE_LIBS gdi32.lib"
+            # OpenSSL 1.0.0 requires crypt32.lib
+            CORE_LIBS="$CORE_LIBS crypt32.lib"
         ;;
 
         *)
--- a/auto/lib/openssl/make
+++ b/auto/lib/openssl/make
@@ -57,7 +57,7 @@ END
 	&& \$(MAKE) clean \\
 	&& ./config --prefix=$ngx_prefix no-shared $OPENSSL_OPT \\
 	&& \$(MAKE) \\
-	&& \$(MAKE) install
+	&& \$(MAKE) install LIBDIR=lib
 
 END
 
--- a/auto/lib/openssl/makefile.bcc
+++ b/auto/lib/openssl/makefile.bcc
@@ -5,8 +5,7 @@
 all:
 	cd $(OPENSSL)
 
-	perl Configure BC-32 no-shared --prefix=openssl -DNO_SYS_TYPES_H \
-		$(OPENSSL_OPT)
+	perl Configure BC-32 no-shared --prefix=openssl $(OPENSSL_OPT)
 
 	ms\do_nasm
 
--- a/auto/lib/openssl/makefile.msvc
+++ b/auto/lib/openssl/makefile.msvc
@@ -5,8 +5,7 @@
 all:
 	cd $(OPENSSL)
 
-	perl Configure VC-WIN32 no-shared --prefix=openssl -DNO_SYS_TYPES_H \
-		$(OPENSSL_OPT)
+	perl Configure VC-WIN32 no-shared --prefix=openssl $(OPENSSL_OPT)
 
 	ms\do_ms
 
--- a/auto/lib/zlib/make
+++ b/auto/lib/zlib/make
@@ -53,7 +53,7 @@ END
 
 $ZLIB/libz.a:	$NGX_MAKEFILE
 	cd $ZLIB \\
-	&& \$(MAKE) clean \\
+	&& \$(MAKE) distclean \\
 	&& cp contrib/asm586/match.S . \\
 	&& CFLAGS="$ZLIB_OPT -DASMV" CC="\$(CC)" \\
 		./configure \\
@@ -70,7 +70,7 @@ END
 
 $ZLIB/libz.a:	$NGX_MAKEFILE
 	cd $ZLIB \\
-	&& \$(MAKE) clean \\
+	&& \$(MAKE) distclean \\
 	&& cp contrib/asm686/match.S . \\
 	&& CFLAGS="$ZLIB_OPT -DASMV" CC="\$(CC)" \\
 		./configure \\
@@ -103,7 +103,7 @@ if [ $done = NO ]; then
 
 $ZLIB/libz.a:	$NGX_MAKEFILE
 	cd $ZLIB \\
-	&& \$(MAKE) clean \\
+	&& \$(MAKE) distclean \\
 	&& CFLAGS="$ZLIB_OPT" CC="\$(CC)" \\
 		./configure \\
 	&& \$(MAKE) libz.a
--- a/auto/modules
+++ b/auto/modules
@@ -101,8 +101,8 @@ fi
 #     ngx_http_range_header_filter
 #     ngx_http_gzip_filter
 #     ngx_http_postpone_filter
+#     ngx_http_ssi_filter
 #     ngx_http_charset_filter
-#     ngx_http_ssi_filter
 #         ngx_http_xslt_filter
 #         ngx_http_image_filter_filter
 #         ngx_http_sub_filter
@@ -130,12 +130,6 @@ if [ $HTTP_POSTPONE = YES ]; then
     HTTP_SRCS="$HTTP_SRCS $HTTP_POSTPONE_FILTER_SRCS"
 fi
 
-if [ $HTTP_CHARSET = YES ]; then
-    have=NGX_HTTP_CHARSET . auto/have
-    HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_CHARSET_FILTER_MODULE"
-    HTTP_SRCS="$HTTP_SRCS $HTTP_CHARSET_SRCS"
-fi
-
 if [ $HTTP_SSI = YES ]; then
     have=NGX_HTTP_SSI . auto/have
     HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_SSI_FILTER_MODULE"
@@ -143,6 +137,12 @@ if [ $HTTP_SSI = YES ]; then
     HTTP_SRCS="$HTTP_SRCS $HTTP_SSI_SRCS"
 fi
 
+if [ $HTTP_CHARSET = YES ]; then
+    have=NGX_HTTP_CHARSET . auto/have
+    HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_CHARSET_FILTER_MODULE"
+    HTTP_SRCS="$HTTP_SRCS $HTTP_CHARSET_SRCS"
+fi
+
 if [ $HTTP_XSLT = YES ]; then
     USE_LIBXSLT=YES
     HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_XSLT_FILTER_MODULE"
--- a/auto/unix
+++ b/auto/unix
@@ -133,6 +133,16 @@ ngx_feature_test="char buf[1024]; long n
 . auto/feature
 
 
+ngx_feature="sys_errlist[]"
+ngx_feature_name="NGX_HAVE_SYS_ERRLIST"
+ngx_feature_run=yes
+ngx_feature_incs="#include <stdio.h>"
+ngx_feature_path=
+ngx_feature_libs=
+ngx_feature_test="int n = sys_nerr; const char *p = sys_errlist[1];"
+. auto/feature
+
+
 ngx_feature="localtime_r()"
 ngx_feature_name="NGX_HAVE_LOCALTIME_R"
 ngx_feature_run=no
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,8 +8,8 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define nginx_version         7065
-#define NGINX_VERSION      "0.7.65"
+#define nginx_version         7066
+#define NGINX_VERSION      "0.7.66"
 #define NGINX_VER          "nginx/" NGINX_VERSION
 
 #define NGINX_VAR          "NGINX"
--- a/src/core/ngx_cycle.c
+++ b/src/core/ngx_cycle.c
@@ -63,7 +63,7 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
     tp = ngx_timeofday();
     tp->sec = 0;
 
-    ngx_time_update(0, 0);
+    ngx_time_update();
 
 
     log = old_cycle->log;
--- a/src/core/ngx_file.c
+++ b/src/core/ngx_file.c
@@ -762,10 +762,12 @@ ngx_copy_file(u_char *from, u_char *to, 
         size -= n;
     }
 
-    if (ngx_set_file_time(to, nfd, cf->time) != NGX_OK) {
-        ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
-                      ngx_set_file_time_n " \"%s\" failed", to);
-        goto failed;
+    if (cf->time != -1) {
+        if (ngx_set_file_time(to, nfd, cf->time) != NGX_OK) {
+            ngx_log_error(NGX_LOG_ALERT, cf->log, ngx_errno,
+                          ngx_set_file_time_n " \"%s\" failed", to);
+            goto failed;
+        }
     }
 
     rc = NGX_OK;
--- a/src/core/ngx_open_file_cache.c
+++ b/src/core/ngx_open_file_cache.c
@@ -487,7 +487,14 @@ ngx_open_and_stat_file(u_char *name, ngx
     }
 
     if (!of->log) {
-        fd = ngx_open_file(name, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);
+
+        /*
+         * Use non-blocking open() not to hang on FIFO files, etc.
+         * This flag has no effect on a regular files.
+         */
+
+        fd = ngx_open_file(name, NGX_FILE_RDONLY|NGX_FILE_NONBLOCK,
+                           NGX_FILE_OPEN, 0);
 
     } else {
         fd = ngx_open_file(name, NGX_FILE_APPEND, NGX_FILE_CREATE_OR_OPEN,
--- a/src/core/ngx_string.c
+++ b/src/core/ngx_string.c
@@ -1277,13 +1277,13 @@ ngx_escape_uri(u_char *dst, u_char *src,
         0xffffffff  /* 1111 1111 1111 1111  1111 1111 1111 1111 */
     };
 
-                    /* " ", "#", "%", "+", "?", %00-%1F, %7F-%FF */
+                    /* " ", "#", "%", "&", "+", "?", %00-%1F, %7F-%FF */
 
     static uint32_t   args[] = {
         0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
 
                     /* ?>=< ;:98 7654 3210  /.-, +*)( '&%$ #"!  */
-        0x80000829, /* 1000 0000 0000 0000  0000 1000 0010 1001 */
+        0x80000869, /* 1000 0000 0000 0000  0000 1000 0110 1001 */
 
                     /* _^]\ [ZYX WVUT SRQP  ONML KJIH GFED CBA@ */
         0x00000000, /* 0000 0000 0000 0000  0000 0000 0000 0000 */
--- a/src/core/ngx_times.c
+++ b/src/core/ngx_times.c
@@ -28,6 +28,17 @@ volatile ngx_str_t       ngx_cached_err_
 volatile ngx_str_t       ngx_cached_http_time;
 volatile ngx_str_t       ngx_cached_http_log_time;
 
+#if !(NGX_WIN32)
+
+/*
+ * locatime() and localtime_r() are not Async-Signal-Safe functions, therefore,
+ * they must not be called by a signal handler, so we use the cached
+ * GMT offset value. Fortunately the value is changed only two times a year.
+ */
+
+static ngx_int_t         cached_gmtoff;
+#endif
+
 static ngx_time_t        cached_time[NGX_TIME_SLOTS];
 static u_char            cached_err_log_time[NGX_TIME_SLOTS]
                                     [sizeof("1970/09/28 12:00:00")];
@@ -50,15 +61,17 @@ ngx_time_init(void)
 
     ngx_cached_time = &cached_time[0];
 
-    ngx_time_update(0, 0);
+    ngx_time_update();
 }
 
 
 void
-ngx_time_update(time_t sec, ngx_uint_t msec)
+ngx_time_update(void)
 {
     u_char          *p0, *p1, *p2;
     ngx_tm_t         tm, gmt;
+    time_t           sec;
+    ngx_uint_t       msec;
     ngx_time_t      *tp;
     struct timeval   tv;
 
@@ -66,12 +79,10 @@ ngx_time_update(time_t sec, ngx_uint_t m
         return;
     }
 
-    if (sec == 0) {
-        ngx_gettimeofday(&tv);
+    ngx_gettimeofday(&tv);
 
-        sec = tv.tv_sec;
-        msec = tv.tv_usec / 1000;
-    }
+    sec = tv.tv_sec;
+    msec = tv.tv_usec / 1000;
 
     ngx_current_msec = (ngx_msec_t) sec * 1000 + msec;
 
@@ -112,12 +123,14 @@ ngx_time_update(time_t sec, ngx_uint_t m
 #elif (NGX_HAVE_GMTOFF)
 
     ngx_localtime(sec, &tm);
-    tp->gmtoff = (ngx_int_t) (tm.ngx_tm_gmtoff / 60);
+    cached_gmtoff = (ngx_int_t) (tm.ngx_tm_gmtoff / 60);
+    tp->gmtoff = cached_gmtoff;
 
 #else
 
     ngx_localtime(sec, &tm);
-    tp->gmtoff = ngx_timezone(tm.ngx_tm_isdst);
+    cached_gmtoff = ngx_timezone(tm.ngx_tm_isdst);
+    tp->gmtoff = cached_gmtoff;
 
 #endif
 
@@ -151,6 +164,57 @@ ngx_time_update(time_t sec, ngx_uint_t m
 }
 
 
+#if !(NGX_WIN32)
+
+void
+ngx_time_sigsafe_update(void)
+{
+    u_char          *p;
+    ngx_tm_t         tm;
+    time_t           sec;
+    ngx_time_t      *tp;
+    struct timeval   tv;
+
+    if (!ngx_trylock(&ngx_time_lock)) {
+        return;
+    }
+
+    ngx_gettimeofday(&tv);
+
+    sec = tv.tv_sec;
+
+    tp = &cached_time[slot];
+
+    if (tp->sec == sec) {
+        ngx_unlock(&ngx_time_lock);
+        return;
+    }
+
+    if (slot == NGX_TIME_SLOTS - 1) {
+        slot = 0;
+    } else {
+        slot++;
+    }
+
+    ngx_gmtime(sec + cached_gmtoff * 60, &tm);
+
+    p = &cached_err_log_time[slot][0];
+
+    (void) ngx_sprintf(p, "%4d/%02d/%02d %02d:%02d:%02d",
+                       tm.ngx_tm_year, tm.ngx_tm_mon,
+                       tm.ngx_tm_mday, tm.ngx_tm_hour,
+                       tm.ngx_tm_min, tm.ngx_tm_sec);
+
+    ngx_memory_barrier();
+
+    ngx_cached_err_log_time.data = p;
+
+    ngx_unlock(&ngx_time_lock);
+}
+
+#endif
+
+
 u_char *
 ngx_http_time(u_char *buf, time_t t)
 {
--- a/src/core/ngx_times.h
+++ b/src/core/ngx_times.h
@@ -20,7 +20,8 @@ typedef struct {
 
 
 void ngx_time_init(void);
-void ngx_time_update(time_t sec, ngx_uint_t msec);
+void ngx_time_update(void);
+void ngx_time_sigsafe_update(void);
 u_char *ngx_http_time(u_char *buf, time_t t);
 u_char *ngx_http_cookie_time(u_char *buf, time_t t);
 void ngx_gmtime(time_t t, ngx_tm_t *tp);
--- a/src/event/modules/ngx_devpoll_module.c
+++ b/src/event/modules/ngx_devpoll_module.c
@@ -375,8 +375,8 @@ ngx_devpoll_process_events(ngx_cycle_t *
         err = 0;
     }
 
-    if (flags & NGX_UPDATE_TIME) {
-        ngx_time_update(0, 0);
+    if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
+        ngx_time_update();
     }
 
     if (err) {
--- a/src/event/modules/ngx_epoll_module.c
+++ b/src/event/modules/ngx_epoll_module.c
@@ -407,8 +407,8 @@ ngx_epoll_process_events(ngx_cycle_t *cy
         err = 0;
     }
 
-    if (flags & NGX_UPDATE_TIME) {
-        ngx_time_update(0, 0);
+    if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
+        ngx_time_update();
     }
 
     if (err) {
--- a/src/event/modules/ngx_eventport_module.c
+++ b/src/event/modules/ngx_eventport_module.c
@@ -405,7 +405,7 @@ ngx_eventport_process_events(ngx_cycle_t
     err = ngx_errno;
 
     if (flags & NGX_UPDATE_TIME) {
-        ngx_time_update(0, 0);
+        ngx_time_update();
     }
 
     if (n == -1) {
@@ -439,7 +439,7 @@ ngx_eventport_process_events(ngx_cycle_t
     for (i = 0; i < events; i++) {
 
         if (event_list[i].portev_source == PORT_SOURCE_TIMER) {
-            ngx_time_update(0, 0);
+            ngx_time_update();
             continue;
         }
 
--- a/src/event/modules/ngx_kqueue_module.c
+++ b/src/event/modules/ngx_kqueue_module.c
@@ -543,8 +543,8 @@ ngx_kqueue_process_events(ngx_cycle_t *c
         err = 0;
     }
 
-    if (flags & NGX_UPDATE_TIME) {
-        ngx_time_update(0, 0);
+    if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
+        ngx_time_update();
     }
 
     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
@@ -595,7 +595,7 @@ ngx_kqueue_process_events(ngx_cycle_t *c
 #if (NGX_HAVE_TIMER_EVENT)
 
         if (event_list[i].filter == EVFILT_TIMER) {
-            ngx_time_update(0, 0);
+            ngx_time_update();
             continue;
         }
 
--- a/src/event/modules/ngx_poll_module.c
+++ b/src/event/modules/ngx_poll_module.c
@@ -266,8 +266,8 @@ ngx_poll_process_events(ngx_cycle_t *cyc
         err = 0;
     }
 
-    if (flags & NGX_UPDATE_TIME) {
-        ngx_time_update(0, 0);
+    if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
+        ngx_time_update();
     }
 
     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
--- a/src/event/modules/ngx_rtsig_module.c
+++ b/src/event/modules/ngx_rtsig_module.c
@@ -323,7 +323,7 @@ ngx_rtsig_process_events(ngx_cycle_t *cy
                        "rtsig signo:%d", signo);
 
         if (flags & NGX_UPDATE_TIME) {
-            ngx_time_update(0, 0);
+            ngx_time_update();
         }
 
         if (err == NGX_EAGAIN) {
@@ -349,7 +349,7 @@ ngx_rtsig_process_events(ngx_cycle_t *cy
                    signo, si.si_fd, si.si_band);
 
     if (flags & NGX_UPDATE_TIME) {
-        ngx_time_update(0, 0);
+        ngx_time_update();
     }
 
     rtscf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_rtsig_module);
@@ -419,7 +419,7 @@ ngx_rtsig_process_events(ngx_cycle_t *cy
 
     } else if (signo == SIGALRM) {
 
-        ngx_time_update(0, 0);
+        ngx_time_update();
 
         return NGX_OK;
 
@@ -671,7 +671,7 @@ ngx_rtsig_process_overflow(ngx_cycle_t *
     }
 
     if (flags & NGX_UPDATE_TIME) {
-        ngx_time_update(0, 0);
+        ngx_time_update();
     }
 
     ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
--- a/src/event/modules/ngx_select_module.c
+++ b/src/event/modules/ngx_select_module.c
@@ -266,8 +266,8 @@ ngx_select_process_events(ngx_cycle_t *c
         err = 0;
     }
 
-    if (flags & NGX_UPDATE_TIME) {
-        ngx_time_update(0, 0);
+    if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
+        ngx_time_update();
     }
 
     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
--- a/src/event/modules/ngx_win32_select_module.c
+++ b/src/event/modules/ngx_win32_select_module.c
@@ -273,7 +273,7 @@ ngx_select_process_events(ngx_cycle_t *c
     }
 
     if (flags & NGX_UPDATE_TIME) {
-        ngx_time_update(0, 0);
+        ngx_time_update();
     }
 
     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
--- a/src/event/ngx_event.c
+++ b/src/event/ngx_event.c
@@ -562,8 +562,6 @@ ngx_timer_signal_handler(int signo)
 {
     ngx_event_timer_alarm = 1;
 
-    ngx_time_update(0, 0);
-
 #if 1
     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0, "timer signal");
 #endif
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -106,6 +106,8 @@ ngx_ssl_init(ngx_log_t *log)
 
     ENGINE_load_builtin_engines();
 
+    OpenSSL_add_all_algorithms();
+
     ngx_ssl_connection_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL);
 
     if (ngx_ssl_connection_index == -1) {
@@ -559,6 +561,9 @@ ngx_ssl_handshake(ngx_connection_t *c)
 #if (NGX_DEBUG)
         {
         char         buf[129], *s, *d;
+#if OPENSSL_VERSION_NUMBER >= 0x1000000fL
+        const
+#endif
         SSL_CIPHER  *cipher;
 
         cipher = SSL_get_current_cipher(c->ssl->connection);
@@ -1308,10 +1313,14 @@ ngx_ssl_connection_error(ngx_connection_
 
             /* handshake failures */
         if (n == SSL_R_DIGEST_CHECK_FAILED                           /*  149 */
+            || n == SSL_R_LENGTH_MISMATCH                            /*  159 */
             || n == SSL_R_NO_CIPHERS_PASSED                          /*  182 */
+            || n == SSL_R_NO_CIPHERS_SPECIFIED                       /*  183 */
             || n == SSL_R_NO_SHARED_CIPHER                           /*  193 */
+            || n == SSL_R_RECORD_LENGTH_MISMATCH                     /*  213 */
             || n == SSL_R_UNEXPECTED_MESSAGE                         /*  244 */
             || n == SSL_R_UNEXPECTED_RECORD                          /*  245 */
+            || n == SSL_R_UNKNOWN_ALERT_TYPE                         /*  246 */
             || n == SSL_R_UNKNOWN_PROTOCOL                           /*  252 */
             || n == SSL_R_WRONG_VERSION_NUMBER                       /*  267 */
             || n == SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC        /*  281 */
@@ -1424,6 +1433,8 @@ ngx_ssl_session_cache(ngx_ssl_t *ssl, ng
         return NGX_OK;
     }
 
+    SSL_CTX_set_session_id_context(ssl->ctx, sess_ctx->data, sess_ctx->len);
+
     if (builtin_session_cache == NGX_SSL_NONE_SCACHE) {
 
         /*
@@ -1455,8 +1466,6 @@ ngx_ssl_session_cache(ngx_ssl_t *ssl, ng
 
     SSL_CTX_set_session_cache_mode(ssl->ctx, cache_mode);
 
-    SSL_CTX_set_session_id_context(ssl->ctx, sess_ctx->data, sess_ctx->len);
-
     if (builtin_session_cache != NGX_SSL_NO_BUILTIN_SCACHE) {
 
         if (builtin_session_cache != NGX_SSL_DFLT_BUILTIN_SCACHE) {
@@ -2311,5 +2320,6 @@ ngx_openssl_engine(ngx_conf_t *cf, ngx_c
 static void
 ngx_openssl_exit(ngx_cycle_t *cycle)
 {
+    EVP_cleanup();
     ENGINE_cleanup();
 }
--- a/src/event/ngx_event_openssl.h
+++ b/src/event/ngx_event_openssl.h
@@ -15,6 +15,7 @@
 #include <openssl/err.h>
 #include <openssl/conf.h>
 #include <openssl/engine.h>
+#include <openssl/evp.h>
 
 #define NGX_SSL_NAME     "OpenSSL"
 
--- a/src/http/modules/ngx_http_autoindex_module.c
+++ b/src/http/modules/ngx_http_autoindex_module.c
@@ -160,10 +160,6 @@ ngx_http_autoindex_handler(ngx_http_requ
         return NGX_DECLINED;
     }
 
-    if (r->zero_in_uri) {
-        return NGX_DECLINED;
-    }
-
     if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) {
         return NGX_DECLINED;
     }
--- a/src/http/modules/ngx_http_chunked_filter_module.c
+++ b/src/http/modules/ngx_http_chunked_filter_module.c
@@ -50,9 +50,10 @@ static ngx_http_output_body_filter_pt   
 static ngx_int_t
 ngx_http_chunked_header_filter(ngx_http_request_t *r)
 {
+    ngx_http_core_loc_conf_t  *clcf;
+
     if (r->headers_out.status == NGX_HTTP_NOT_MODIFIED
         || r->headers_out.status == NGX_HTTP_NO_CONTENT
-        || r->headers_out.status == NGX_HTTP_CREATED
         || r != r->main
         || (r->method & NGX_HTTP_HEAD))
     {
@@ -64,7 +65,14 @@ ngx_http_chunked_header_filter(ngx_http_
             r->keepalive = 0;
 
         } else {
-            r->chunked = 1;
+            clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+            if (clcf->chunked_transfer_encoding) {
+                r->chunked = 1;
+
+            } else {
+                r->keepalive = 0;
+            }
         }
     }
 
--- a/src/http/modules/ngx_http_dav_module.c
+++ b/src/http/modules/ngx_http_dav_module.c
@@ -146,10 +146,6 @@ ngx_http_dav_handler(ngx_http_request_t 
     ngx_int_t                 rc;
     ngx_http_dav_loc_conf_t  *dlcf;
 
-    if (r->zero_in_uri) {
-        return NGX_DECLINED;
-    }
-
     dlcf = ngx_http_get_module_loc_conf(r, ngx_http_dav_module);
 
     if (!(r->method & dlcf->methods)) {
@@ -325,13 +321,13 @@ ok:
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    "http delete filename: \"%s\"", path.data);
 
-    if (ngx_file_info(path.data, &fi) == NGX_FILE_ERROR) {
+    if (ngx_link_info(path.data, &fi) == NGX_FILE_ERROR) {
         err = ngx_errno;
 
         rc = (err == NGX_ENOTDIR) ? NGX_HTTP_CONFLICT : NGX_HTTP_NOT_FOUND;
 
         return ngx_http_dav_error(r->connection->log, err,
-                                  rc, ngx_file_info_n, path.data);
+                                  rc, ngx_link_info_n, path.data);
     }
 
     if (ngx_is_dir(&fi)) {
@@ -358,7 +354,7 @@ ok:
 
         /*
          * we do not need to test (r->uri.data[r->uri.len - 1] == '/')
-         * because ngx_file_info("/file/") returned NGX_ENOTDIR above
+         * because ngx_link_info("/file/") returned NGX_ENOTDIR above
          */
 
         depth = ngx_http_dav_depth(r, 0);
@@ -685,12 +681,12 @@ overwrite_done:
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    "http copy to: \"%s\"", copy.path.data);
 
-    if (ngx_file_info(copy.path.data, &fi) == NGX_FILE_ERROR) {
+    if (ngx_link_info(copy.path.data, &fi) == NGX_FILE_ERROR) {
         err = ngx_errno;
 
         if (err != NGX_ENOENT) {
             return ngx_http_dav_error(r->connection->log, err,
-                                      NGX_HTTP_NOT_FOUND, ngx_file_info_n,
+                                      NGX_HTTP_NOT_FOUND, ngx_link_info_n,
                                       copy.path.data);
         }
 
@@ -719,9 +715,9 @@ overwrite_done:
         dir = ngx_is_dir(&fi);
     }
 
-    if (ngx_file_info(path.data, &fi) == NGX_FILE_ERROR) {
+    if (ngx_link_info(path.data, &fi) == NGX_FILE_ERROR) {
         return ngx_http_dav_error(r->connection->log, ngx_errno,
-                                  NGX_HTTP_NOT_FOUND, ngx_file_info_n,
+                                  NGX_HTTP_NOT_FOUND, ngx_link_info_n,
                                   path.data);
     }
 
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -333,6 +333,13 @@ static ngx_command_t  ngx_http_fastcgi_c
       0,
       &ngx_http_fastcgi_module },
 
+    { ngx_string("fastcgi_no_cache"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
+      ngx_http_no_cache_set_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_fastcgi_loc_conf_t, upstream.no_cache),
+      NULL },
+
     { ngx_string("fastcgi_cache_valid"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
       ngx_http_file_cache_valid_set_slot,
@@ -1890,6 +1897,7 @@ ngx_http_fastcgi_create_loc_conf(ngx_con
 #if (NGX_HTTP_CACHE)
     conf->upstream.cache = NGX_CONF_UNSET_PTR;
     conf->upstream.cache_min_uses = NGX_CONF_UNSET_UINT;
+    conf->upstream.no_cache = NGX_CONF_UNSET_PTR;
     conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
 #endif
 
@@ -2111,6 +2119,9 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf
 
     conf->upstream.cache_methods |= NGX_HTTP_GET|NGX_HTTP_HEAD;
 
+    ngx_conf_merge_ptr_value(conf->upstream.no_cache,
+                             prev->upstream.no_cache, NULL);
+
     ngx_conf_merge_ptr_value(conf->upstream.cache_valid,
                              prev->upstream.cache_valid, NULL);
 
--- a/src/http/modules/ngx_http_flv_module.c
+++ b/src/http/modules/ngx_http_flv_module.c
@@ -80,10 +80,6 @@ ngx_http_flv_handler(ngx_http_request_t 
         return NGX_DECLINED;
     }
 
-    if (r->zero_in_uri) {
-        return NGX_DECLINED;
-    }
-
     rc = ngx_http_discard_request_body(r);
 
     if (rc != NGX_OK) {
--- a/src/http/modules/ngx_http_geo_module.c
+++ b/src/http/modules/ngx_http_geo_module.c
@@ -589,7 +589,7 @@ ngx_http_geo_add_range(ngx_conf_t *cf, n
     ngx_array_t           *a;
     ngx_http_geo_range_t  *range;
 
-    for (n = start; n <= end; n += 0x10000) {
+    for (n = start; n <= end; n = (n + 0x10000) & 0xffff0000) {
 
         h = n >> 16;
 
--- a/src/http/modules/ngx_http_geoip_module.c
+++ b/src/http/modules/ngx_http_geoip_module.c
@@ -30,6 +30,9 @@ static ngx_int_t ngx_http_geoip_country_
     ngx_http_variable_value_t *v, uintptr_t data);
 static ngx_int_t ngx_http_geoip_city_variable(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data);
+static ngx_int_t ngx_http_geoip_city_float_variable(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data);
+static GeoIPRecord *ngx_http_geoip_get_city_record(ngx_http_request_t *r);
 
 static ngx_int_t ngx_http_geoip_add_variables(ngx_conf_t *cf);
 static void *ngx_http_geoip_create_conf(ngx_conf_t *cf);
@@ -93,23 +96,32 @@ ngx_module_t  ngx_http_geoip_module = {
 
 static ngx_http_variable_t  ngx_http_geoip_vars[] = {
 
-    { ngx_string("geoip_country_code"), NULL, ngx_http_geoip_country_variable,
+    { ngx_string("geoip_country_code"), NULL,
+      ngx_http_geoip_country_variable,
       (uintptr_t) GeoIP_country_code_by_ipnum, 0, 0 },
 
-    { ngx_string("geoip_country_code3"), NULL, ngx_http_geoip_country_variable,
+    { ngx_string("geoip_country_code3"), NULL,
+      ngx_http_geoip_country_variable,
       (uintptr_t) GeoIP_country_code3_by_ipnum, 0, 0 },
 
-    { ngx_string("geoip_country_name"), NULL, ngx_http_geoip_country_variable,
+    { ngx_string("geoip_country_name"), NULL,
+      ngx_http_geoip_country_variable,
       (uintptr_t) GeoIP_country_name_by_ipnum, 0, 0 },
 
-    { ngx_string("geoip_city_country_code"), NULL, ngx_http_geoip_city_variable,
+    { ngx_string("geoip_city_continent_code"), NULL,
+      ngx_http_geoip_city_variable,
+      offsetof(GeoIPRecord, continent_code), 0, 0 },
+
+    { ngx_string("geoip_city_country_code"), NULL,
+      ngx_http_geoip_city_variable,
       offsetof(GeoIPRecord, country_code), 0, 0 },
 
     { ngx_string("geoip_city_country_code3"), NULL,
       ngx_http_geoip_city_variable,
       offsetof(GeoIPRecord, country_code3), 0, 0 },
 
-    { ngx_string("geoip_city_country_name"), NULL, ngx_http_geoip_city_variable,
+    { ngx_string("geoip_city_country_name"), NULL,
+      ngx_http_geoip_city_variable,
       offsetof(GeoIPRecord, country_name), 0, 0 },
 
     { ngx_string("geoip_region"), NULL,
@@ -124,6 +136,14 @@ static ngx_http_variable_t  ngx_http_geo
       ngx_http_geoip_city_variable,
       offsetof(GeoIPRecord, postal_code), 0, 0 },
 
+    { ngx_string("geoip_latitude"), NULL,
+      ngx_http_geoip_city_float_variable,
+      offsetof(GeoIPRecord, latitude), 0, 0 },
+
+    { ngx_string("geoip_longitude"), NULL,
+      ngx_http_geoip_city_float_variable,
+      offsetof(GeoIPRecord, longitude), 0, 0 },
+
     { ngx_null_string, NULL, NULL, 0, 0, 0 }
 };
 
@@ -179,34 +199,16 @@ static ngx_int_t
 ngx_http_geoip_city_variable(ngx_http_request_t *r,
     ngx_http_variable_value_t *v, uintptr_t data)
 {
-    u_long                  addr;
-    char                   *val;
-    size_t                  len;
-    GeoIPRecord            *gr;
-    struct sockaddr_in     *sin;
-    ngx_http_geoip_conf_t  *gcf;
-
-    gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip_module);
+    char         *val;
+    size_t        len;
+    GeoIPRecord  *gr;
 
-    if (gcf->city == NULL) {
-        goto not_found;
-    }
-
-    if (r->connection->sockaddr->sa_family != AF_INET) {
-        goto not_found;
-    }
-
-    sin = (struct sockaddr_in *) r->connection->sockaddr;
-    addr = ntohl(sin->sin_addr.s_addr);
-
-    gr = GeoIP_record_by_ipnum(gcf->city, addr);
-
+    gr = ngx_http_geoip_get_city_record(r);
     if (gr == NULL) {
         goto not_found;
     }
 
     val = *(char **) ((char *) gr + data);
-
     if (val == NULL) {
         goto no_value;
     }
@@ -243,6 +245,56 @@ not_found:
 
 
 static ngx_int_t
+ngx_http_geoip_city_float_variable(ngx_http_request_t *r,
+    ngx_http_variable_value_t *v, uintptr_t data)
+{
+    float         val;
+    GeoIPRecord  *gr;
+
+    gr = ngx_http_geoip_get_city_record(r);
+    if (gr == NULL) {
+        v->not_found = 1;
+        return NGX_OK;
+    }
+
+    v->data = ngx_pnalloc(r->pool, NGX_INT64_LEN + 5);
+    if (v->data == NULL) {
+        GeoIPRecord_delete(gr);
+        return NGX_ERROR;
+    }
+
+    val = *(float *) ((char *) gr + data);
+
+    v->len = ngx_sprintf(v->data, "%.4f", val) - v->data;
+
+    GeoIPRecord_delete(gr);
+
+    return NGX_OK;
+}
+
+
+static GeoIPRecord *
+ngx_http_geoip_get_city_record(ngx_http_request_t *r)
+{
+    u_long                  addr;
+    struct sockaddr_in     *sin;
+    ngx_http_geoip_conf_t  *gcf;
+
+    gcf = ngx_http_get_module_main_conf(r, ngx_http_geoip_module);
+
+    if (gcf->city && r->connection->sockaddr->sa_family == AF_INET) {
+
+        sin = (struct sockaddr_in *) r->connection->sockaddr;
+        addr = ntohl(sin->sin_addr.s_addr);
+
+        return GeoIP_record_by_ipnum(gcf->city, addr);
+    }
+
+    return NULL;
+}
+
+
+static ngx_int_t
 ngx_http_geoip_add_variables(ngx_conf_t *cf)
 {
     ngx_http_variable_t  *var, *v;
--- a/src/http/modules/ngx_http_gzip_static_module.c
+++ b/src/http/modules/ngx_http_gzip_static_module.c
@@ -89,10 +89,6 @@ ngx_http_gzip_static_handler(ngx_http_re
         return NGX_DECLINED;
     }
 
-    if (r->zero_in_uri) {
-        return NGX_DECLINED;
-    }
-
     gzcf = ngx_http_get_module_loc_conf(r, ngx_http_gzip_static_module);
 
     if (!gzcf->enable) {
@@ -179,7 +175,7 @@ ngx_http_gzip_static_handler(ngx_http_re
 #if !(NGX_WIN32) /* the not regular files are probably Unix specific */
 
     if (!of.is_file) {
-        ngx_log_error(NGX_LOG_CRIT, log, ngx_errno,
+        ngx_log_error(NGX_LOG_CRIT, log, 0,
                       "\"%s\" is not a regular file", path.data);
 
         return NGX_HTTP_NOT_FOUND;
--- a/src/http/modules/ngx_http_image_filter_module.c
+++ b/src/http/modules/ngx_http_image_filter_module.c
@@ -63,6 +63,7 @@ typedef struct {
 
     ngx_uint_t                   phase;
     ngx_uint_t                   type;
+    ngx_uint_t                   force;
 } ngx_http_image_filter_ctx_t;
 
 
@@ -501,7 +502,8 @@ ngx_http_image_process(ngx_http_request_
 
     if (rc == NGX_OK
         && ctx->width <= ctx->max_width
-        && ctx->height <= ctx->max_height)
+        && ctx->height <= ctx->max_height
+        && !ctx->force)
     {
         return ngx_http_image_asis(r, ctx);
     }
@@ -601,6 +603,7 @@ static ngx_int_t
 ngx_http_image_size(ngx_http_request_t *r, ngx_http_image_filter_ctx_t *ctx)
 {
     u_char      *p, *last;
+    size_t       len, app;
     ngx_uint_t   width, height;
 
     p = ctx->image;
@@ -611,26 +614,38 @@ ngx_http_image_size(ngx_http_request_t *
 
         p += 2;
         last = ctx->image + ctx->length - 10;
+        width = 0;
+        height = 0;
+        app = 0;
 
         while (p < last) {
 
             if (p[0] == 0xff && p[1] != 0xff) {
 
                 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                               "JPEG: %02xd %02xd", *p, *(p + 1));
+                               "JPEG: %02xd %02xd", p[0], p[1]);
 
                 p++;
 
-                if (*p == 0xc0 || *p == 0xc1 || *p == 0xc2 || *p == 0xc3
-                    || *p == 0xc9 || *p == 0xca || *p == 0xcb)
+                if ((*p == 0xc0 || *p == 0xc1 || *p == 0xc2 || *p == 0xc3
+                     || *p == 0xc9 || *p == 0xca || *p == 0xcb)
+                    && (width == 0 || height == 0))
                 {
-                    goto found;
+                    width = p[6] * 256 + p[7];
+                    height = p[4] * 256 + p[5];
                 }
 
                 ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                                "JPEG: %02xd %02xd", p[1], p[2]);
 
-                p += p[1] * 256 + p[2];
+                len = p[1] * 256 + p[2];
+
+                if (*p >= 0xe1 && *p <= 0xef) {
+                    /* application data, e.g., EXIF, Adobe XMP, etc. */
+                    app += len;
+                }
+
+                p += len;
 
                 continue;
             }
@@ -638,12 +653,16 @@ ngx_http_image_size(ngx_http_request_t *
             p++;
         }
 
-        return NGX_DECLINED;
+        if (width == 0 || height == 0) {
+            return NGX_DECLINED;
+        }
 
-    found:
-
-        width = p[6] * 256 + p[7];
-        height = p[4] * 256 + p[5];
+        if (ctx->length / 20 < app) {
+            /* force conversion if application data consume more than 5% */
+            ctx->force = 1;
+            ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                           "app data size: %uz", app);
+        }
 
         break;
 
@@ -708,7 +727,8 @@ ngx_http_image_resize(ngx_http_request_t
 
     conf = ngx_http_get_module_loc_conf(r, ngx_http_image_filter_module);
 
-    if ((ngx_uint_t) sx <= ctx->max_width
+    if (!ctx->force
+        && (ngx_uint_t) sx <= ctx->max_width
         && (ngx_uint_t) sy <= ctx->max_height)
     {
         gdImageDestroy(src);
--- a/src/http/modules/ngx_http_index_module.c
+++ b/src/http/modules/ngx_http_index_module.c
@@ -116,10 +116,6 @@ ngx_http_index_handler(ngx_http_request_
         return NGX_DECLINED;
     }
 
-    if (r->zero_in_uri) {
-        return NGX_DECLINED;
-    }
-
     ilcf = ngx_http_get_module_loc_conf(r, ngx_http_index_module);
     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
 
--- a/src/http/modules/ngx_http_memcached_module.c
+++ b/src/http/modules/ngx_http_memcached_module.c
@@ -423,15 +423,20 @@ ngx_http_memcached_filter(void *data, ss
 
         if (ngx_strncmp(b->last,
                    ngx_http_memcached_end + NGX_HTTP_MEMCACHED_END - ctx->rest,
-                   ctx->rest)
+                   bytes)
             != 0)
         {
             ngx_log_error(NGX_LOG_ERR, ctx->request->connection->log, 0,
                           "memcached sent invalid trailer");
+
+            u->length = 0;
+            ctx->rest = 0;
+
+            return NGX_OK;
         }
 
-        u->length = 0;
-        ctx->rest = 0;
+        u->length -= bytes;
+        ctx->rest -= bytes;
 
         return NGX_OK;
     }
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -357,6 +357,13 @@ static ngx_command_t  ngx_http_proxy_com
       0,
       &ngx_http_proxy_module },
 
+    { ngx_string("proxy_no_cache"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
+      ngx_http_no_cache_set_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_proxy_loc_conf_t, upstream.no_cache),
+      NULL },
+
     { ngx_string("proxy_cache_valid"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE,
       ngx_http_file_cache_valid_set_slot,
@@ -630,6 +637,7 @@ ngx_http_proxy_handler(ngx_http_request_
     u->process_header = ngx_http_proxy_process_status_line;
     u->abort_request = ngx_http_proxy_abort_request;
     u->finalize_request = ngx_http_proxy_finalize_request;
+    r->state = 0;
 
     if (plcf->redirects) {
         u->rewrite_redirect = ngx_http_proxy_rewrite_redirect;
@@ -1191,6 +1199,7 @@ ngx_http_proxy_reinit_request(ngx_http_r
     ctx->status_end = NULL;
 
     r->upstream->process_header = ngx_http_proxy_process_status_line;
+    r->state = 0;
 
     return NGX_OK;
 }
@@ -1906,7 +1915,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_
      *     conf->body_set_len = NULL;
      *     conf->body_set = NULL;
      *     conf->body_source = { 0, NULL };
-     *     conf->rewrite_locations = NULL;
+     *     conf->redirects = NULL;
      */
 
     conf->upstream.store = NGX_CONF_UNSET;
@@ -1931,6 +1940,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_
 #if (NGX_HTTP_CACHE)
     conf->upstream.cache = NGX_CONF_UNSET_PTR;
     conf->upstream.cache_min_uses = NGX_CONF_UNSET_UINT;
+    conf->upstream.no_cache = NGX_CONF_UNSET_PTR;
     conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
 #endif
 
@@ -2155,6 +2165,9 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t
                                          |NGX_HTTP_UPSTREAM_FT_OFF;
     }
 
+    ngx_conf_merge_ptr_value(conf->upstream.no_cache,
+                             prev->upstream.no_cache, NULL);
+
     ngx_conf_merge_ptr_value(conf->upstream.cache_valid,
                              prev->upstream.cache_valid, NULL);
 
@@ -2747,9 +2760,16 @@ ngx_http_proxy_redirect(ngx_conf_t *cf, 
     }
 
     if (ngx_strcmp(value[1].data, "default") == 0) {
+        if (plcf->proxy_lengths) {
+            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+                               "\"proxy_redirect default\" may not be used "
+                               "with \"proxy_pass\" directive with variables");
+            return NGX_CONF_ERROR;
+        }
+
         if (plcf->url.data == NULL) {
             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                               "\"proxy_rewrite_location default\" must go "
+                               "\"proxy_redirect default\" must go "
                                "after the \"proxy_pass\" directive");
             return NGX_CONF_ERROR;
         }
--- a/src/http/modules/ngx_http_random_index_module.c
+++ b/src/http/modules/ngx_http_random_index_module.c
@@ -86,10 +86,6 @@ ngx_http_random_index_handler(ngx_http_r
         return NGX_DECLINED;
     }
 
-    if (r->zero_in_uri) {
-        return NGX_DECLINED;
-    }
-
     if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD|NGX_HTTP_POST))) {
         return NGX_DECLINED;
     }
--- a/src/http/modules/ngx_http_referer_module.c
+++ b/src/http/modules/ngx_http_referer_module.c
@@ -124,18 +124,27 @@ ngx_http_referer_variable(ngx_http_reque
     len = r->headers_in.referer->value.len;
     ref = r->headers_in.referer->value.data;
 
-    if (len < sizeof("http://i.ru") - 1
-        || (ngx_strncasecmp(ref, (u_char *) "http://", 7) != 0))
-    {
-        if (rlcf->blocked_referer) {
-            goto valid;
+    if (len >= sizeof("http://i.ru") - 1) {
+        last = ref + len;
+
+        if (ngx_strncasecmp(ref, (u_char *) "http://", 7) == 0) {
+            ref += 7;
+            goto valid_scheme;
+
+        } else if (ngx_strncasecmp(ref, (u_char *) "https://", 8) == 0) {
+            ref += 8;
+            goto valid_scheme;
         }
-
-        goto invalid;
     }
 
-    last = ref + len;
-    ref += 7;
+    if (rlcf->blocked_referer) {
+        goto valid;
+    }
+
+    goto invalid;
+
+valid_scheme:
+
     i = 0;
     key = 0;
 
--- a/src/http/modules/ngx_http_rewrite_module.c
+++ b/src/http/modules/ngx_http_rewrite_module.c
@@ -340,13 +340,10 @@ ngx_http_rewrite(ngx_conf_t *cf, ngx_com
 
     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 (ngx_strncmp(value[2].data, "https://", sizeof("https://") - 1) == 0) {
+    if (ngx_strncmp(value[2].data, "http://", sizeof("http://") - 1) == 0
+        || ngx_strncmp(value[2].data, "https://", sizeof("https://") - 1) == 0
+        || ngx_strncmp(value[2].data, "$scheme", sizeof("$scheme") - 1) == 0)
+    {
         regex->status = NGX_HTTP_MOVED_TEMPORARILY;
         regex->redirect = 1;
         last = 1;
--- a/src/http/modules/ngx_http_ssi_filter_module.c
+++ b/src/http/modules/ngx_http_ssi_filter_module.c
@@ -14,7 +14,6 @@
 
 #define NGX_HTTP_SSI_ADD_PREFIX     1
 #define NGX_HTTP_SSI_ADD_ZERO       2
-#define NGX_HTTP_SSI_EXPR_TEST      4
 
 
 typedef struct {
@@ -1701,8 +1700,7 @@ ngx_http_ssi_evaluate_string(ngx_http_re
             val = ngx_http_ssi_get_variable(r, &var, key);
 
             if (val == NULL) {
-                vv = ngx_http_get_variable(r, &var, key,
-                                           flags & NGX_HTTP_SSI_EXPR_TEST);
+                vv = ngx_http_get_variable(r, &var, key);
                 if (vv == NULL) {
                     return NGX_ERROR;
                 }
@@ -2061,9 +2059,9 @@ ngx_http_ssi_stub_output(ngx_http_reques
     out = data;
 
     if (!r->header_sent) {
-        if (ngx_http_set_content_type(r) != NGX_OK) {
-            return NGX_ERROR;
-        }
+        r->headers_out.content_type_len =
+                                      r->parent->headers_out.content_type_len;
+        r->headers_out.content_type = r->parent->headers_out.content_type;
 
         if (ngx_http_send_header(r) == NGX_ERROR) {
             return NGX_ERROR;
@@ -2110,7 +2108,7 @@ ngx_http_ssi_echo(ngx_http_request_t *r,
     value = ngx_http_ssi_get_variable(r, var, key);
 
     if (value == NULL) {
-        vv = ngx_http_get_variable(r, var, key, 1);
+        vv = ngx_http_get_variable(r, var, key);
 
         if (vv == NULL) {
             return NGX_HTTP_SSI_ERROR;
@@ -2161,11 +2159,10 @@ ngx_http_ssi_echo(ngx_http_request_t *r,
         }
     }
 
+    p = value->data;
+
     switch (ctx->encoding) {
 
-    case NGX_HTTP_SSI_NO_ENCODING:
-        break;
-
     case NGX_HTTP_SSI_URL_ENCODING:
         len = 2 * ngx_escape_uri(NULL, value->data, value->len,
                                  NGX_ESCAPE_HTML);
@@ -2177,11 +2174,9 @@ ngx_http_ssi_echo(ngx_http_request_t *r,
             }
 
             (void) ngx_escape_uri(p, value->data, value->len, NGX_ESCAPE_HTML);
-
-            value->len += len;
-            value->data = p;
         }
 
+        len += value->len;
         break;
 
     case NGX_HTTP_SSI_ENTITY_ENCODING:
@@ -2194,11 +2189,13 @@ ngx_http_ssi_echo(ngx_http_request_t *r,
             }
 
             (void) ngx_escape_html(p, value->data, value->len);
-
-            value->len += len;
-            value->data = p;
         }
 
+        len += value->len;
+        break;
+
+    default: /* NGX_HTTP_SSI_NO_ENCODING */
+        len = value->len;
         break;
     }
 
@@ -2213,8 +2210,8 @@ ngx_http_ssi_echo(ngx_http_request_t *r,
     }
 
     b->memory = 1;
-    b->pos = value->data;
-    b->last = value->data + value->len;
+    b->pos = p;
+    b->last = p + len;
 
     cl->buf = b;
     cl->next = NULL;
@@ -2362,7 +2359,7 @@ ngx_http_ssi_if(ngx_http_request_t *r, n
         p++;
     }
 
-    flags = (p == last) ? NGX_HTTP_SSI_EXPR_TEST : 0;
+    flags = 0;
 
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    "left: \"%V\"", &left);
@@ -2614,8 +2611,7 @@ ngx_http_ssi_date_gmt_local_variable(ngx
             return NGX_ERROR;
         }
 
-        v->len = ngx_sprintf(v->data, "%T", tp->sec + (gmt ? 0 : tp->gmtoff))
-                 - v->data;
+        v->len = ngx_sprintf(v->data, "%T", tp->sec) - v->data;
 
         return NGX_OK;
     }
--- a/src/http/modules/ngx_http_static_module.c
+++ b/src/http/modules/ngx_http_static_module.c
@@ -66,10 +66,6 @@ ngx_http_static_handler(ngx_http_request
         return NGX_DECLINED;
     }
 
-    if (r->zero_in_uri) {
-        return NGX_DECLINED;
-    }
-
     log = r->connection->log;
 
     /*
@@ -188,7 +184,7 @@ ngx_http_static_handler(ngx_http_request
 #if !(NGX_WIN32) /* the not regular files are probably Unix specific */
 
     if (!of.is_file) {
-        ngx_log_error(NGX_LOG_CRIT, log, ngx_errno,
+        ngx_log_error(NGX_LOG_CRIT, log, 0,
                       "\"%s\" is not a regular file", path.data);
 
         return NGX_HTTP_NOT_FOUND;
--- a/src/http/modules/ngx_http_userid_filter_module.c
+++ b/src/http/modules/ngx_http_userid_filter_module.c
@@ -545,7 +545,7 @@ ngx_http_userid_add_variables(ngx_conf_t
 {
     ngx_http_variable_t  *var;
 
-    var = ngx_http_add_variable(cf, &ngx_http_userid_got, NGX_HTTP_VAR_NOHASH);
+    var = ngx_http_add_variable(cf, &ngx_http_userid_got, 0);
     if (var == NULL) {
         return NGX_ERROR;
     }
--- a/src/http/modules/perl/nginx.pm
+++ b/src/http/modules/perl/nginx.pm
@@ -47,7 +47,7 @@ our @EXPORT = qw(
     HTTP_INSUFFICIENT_STORAGE
 );
 
-our $VERSION = '0.7.65';
+our $VERSION = '0.7.66';
 
 require XSLoader;
 XSLoader::load('nginx', $VERSION);
--- a/src/http/modules/perl/nginx.xs
+++ b/src/http/modules/perl/nginx.xs
@@ -847,7 +847,7 @@ variable(r, name, value = NULL)
 
     #endif
 
-    vv = ngx_http_get_variable(r, &var, hash, 1);
+    vv = ngx_http_get_variable(r, &var, hash);
     if (vv == NULL) {
         XSRETURN_UNDEF;
     }
@@ -901,9 +901,6 @@ variable(r, name, value = NULL)
             XSRETURN_UNDEF;
         }
 
-        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
-                      "variable \"%V\" not found", &var);
-
         XSRETURN_UNDEF;
     }
 
--- a/src/http/modules/perl/ngx_http_perl_module.c
+++ b/src/http/modules/perl/ngx_http_perl_module.c
@@ -30,12 +30,6 @@ typedef struct {
 } ngx_http_perl_variable_t;
 
 
-typedef struct {
-    SV                *sv;
-    PerlInterpreter   *perl;
-} ngx_http_perl_cleanup_t;
-
-
 #if (NGX_HTTP_SSI)
 static ngx_int_t ngx_http_perl_ssi(ngx_http_request_t *r,
     ngx_http_ssi_ctx_t *ssi_ctx, ngx_str_t **params);
@@ -174,10 +168,6 @@ ngx_http_perl_xs_init(pTHX)
 static ngx_int_t
 ngx_http_perl_handler(ngx_http_request_t *r)
 {
-    if (r->zero_in_uri) {
-        return NGX_HTTP_NOT_FOUND;
-    }
-
     ngx_http_perl_handle_request(r);
 
     return NGX_DONE;
--- a/src/http/ngx_http_cache.h
+++ b/src/http/ngx_http_cache.h
@@ -133,6 +133,11 @@ char *ngx_http_file_cache_set_slot(ngx_c
 char *ngx_http_file_cache_valid_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf);
 
+ngx_int_t ngx_http_cache(ngx_http_request_t *r, ngx_array_t *no_cache);
+char *ngx_http_no_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
+    void *conf);
+
+
 extern ngx_str_t  ngx_http_cache_status[];
 
 
--- a/src/http/ngx_http_copy_filter_module.c
+++ b/src/http/ngx_http_copy_filter_module.c
@@ -104,7 +104,9 @@ ngx_http_copy_filter(ngx_http_request_t 
         ctx->output_filter = (ngx_output_chain_filter_pt) ngx_http_next_filter;
         ctx->filter_ctx = r;
 
-        r->request_output = 1;
+        if (in && in->buf && ngx_buf_size(in->buf)) {
+            r->request_output = 1;
+        }
     }
 
     rc = ngx_output_chain(ctx, in);
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -560,6 +560,13 @@ static ngx_command_t  ngx_http_core_comm
       offsetof(ngx_http_core_loc_conf_t, if_modified_since),
       &ngx_http_core_if_modified_since },
 
+    { ngx_string("chunked_transfer_encoding"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+      ngx_conf_set_flag_slot,
+      NGX_HTTP_LOC_CONF_OFFSET,
+      offsetof(ngx_http_core_loc_conf_t, chunked_transfer_encoding),
+      NULL },
+
     { ngx_string("error_page"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
                         |NGX_CONF_2MORE,
@@ -744,14 +751,24 @@ ngx_http_handler(ngx_http_request_t *r)
             break;
         }
 
-        if (r->keepalive && r->headers_in.msie && r->method == NGX_HTTP_POST) {
-
-            /*
-             * MSIE may wait for some time if an response for
-             * a POST request was sent over a keepalive connection
-             */
-
-            r->keepalive = 0;
+        if (r->keepalive) {
+
+            if (r->headers_in.msie6) {
+                if (r->method == NGX_HTTP_POST) {
+                    /*
+                     * MSIE may wait for some time if an response for
+                     * a POST request was sent over a keepalive connection
+                     */
+                    r->keepalive = 0;
+                }
+
+            } else if (r->headers_in.safari) {
+                /*
+                 * Safari may send a POST request to a closed keepalive
+                 * connection and stalls for some time
+                 */
+                r->keepalive = 0;
+            }
         }
 
         if (r->headers_in.content_length_n > 0) {
@@ -1288,7 +1305,7 @@ ngx_http_core_content_phase(ngx_http_req
 
     /* no content handler was found */
 
-    if (r->uri.data[r->uri.len - 1] == '/' && !r->zero_in_uri) {
+    if (r->uri.data[r->uri.len - 1] == '/') {
 
         if (ngx_http_map_uri_to_path(r, &path, &root, 0) != NULL) {
             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
@@ -2076,7 +2093,6 @@ ngx_http_subrequest(ngx_http_request_t *
     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0,
                    "http subrequest \"%V?%V\"", uri, &sr->args);
 
-    sr->zero_in_uri = (flags & NGX_HTTP_ZERO_IN_URI) != 0;
     sr->subrequest_in_memory = (flags & NGX_HTTP_SUBREQUEST_IN_MEMORY) != 0;
     sr->waited = (flags & NGX_HTTP_SUBREQUEST_WAITED) != 0;
 
@@ -2944,6 +2960,7 @@ ngx_http_core_create_loc_conf(ngx_conf_t
     lcf->log_subrequest = NGX_CONF_UNSET;
     lcf->recursive_error_pages = NGX_CONF_UNSET;
     lcf->server_tokens = NGX_CONF_UNSET;
+    lcf->chunked_transfer_encoding = NGX_CONF_UNSET;
     lcf->types_hash_max_size = NGX_CONF_UNSET_UINT;
     lcf->types_hash_bucket_size = NGX_CONF_UNSET_UINT;
 
@@ -3181,6 +3198,8 @@ ngx_http_core_merge_loc_conf(ngx_conf_t 
     ngx_conf_merge_value(conf->recursive_error_pages,
                               prev->recursive_error_pages, 0);
     ngx_conf_merge_value(conf->server_tokens, prev->server_tokens, 1);
+    ngx_conf_merge_value(conf->chunked_transfer_encoding,
+                              prev->chunked_transfer_encoding, 1);
 
     ngx_conf_merge_ptr_value(conf->open_file_cache,
                               prev->open_file_cache, NULL);
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -358,6 +358,7 @@ struct ngx_http_core_loc_conf_s {
     ngx_flag_t    log_subrequest;          /* log_subrequest */
     ngx_flag_t    recursive_error_pages;   /* recursive_error_pages */
     ngx_flag_t    server_tokens;           /* server_tokens */
+    ngx_flag_t    chunked_transfer_encoding; /* chunked_transfer_encoding */
 
 #if (NGX_HTTP_GZIP)
     ngx_flag_t    gzip_vary;               /* gzip_vary */
--- a/src/http/ngx_http_file_cache.c
+++ b/src/http/ngx_http_file_cache.c
@@ -1128,7 +1128,7 @@ ngx_http_file_cache_manager_sleep(ngx_ht
 
     if (cache->files++ > 100) {
 
-        ngx_time_update(0, 0);
+        ngx_time_update();
 
         elapsed = ngx_abs((ngx_msec_int_t) (ngx_current_msec - cache->last));
 
@@ -1145,7 +1145,7 @@ ngx_http_file_cache_manager_sleep(ngx_ht
 
             ngx_msleep(200);
 
-            ngx_time_update(0, 0);
+            ngx_time_update();
         }
 
         cache->last = ngx_current_msec;
@@ -1604,3 +1604,69 @@ ngx_http_file_cache_valid_set_slot(ngx_c
 
     return NGX_CONF_OK;
 }
+
+
+ngx_int_t
+ngx_http_cache(ngx_http_request_t *r, ngx_array_t *no_cache)
+{
+    ngx_str_t                  val;
+    ngx_uint_t                 i;
+    ngx_http_complex_value_t  *cv;
+
+    cv = no_cache->elts;
+
+    for (i = 0; i < no_cache->nelts; i++) {
+        if (ngx_http_complex_value(r, &cv[i], &val) != NGX_OK) {
+            return NGX_ERROR;
+        }
+
+        if (val.len && val.data[0] != '0') {
+            return NGX_DECLINED;
+        }
+    }
+
+    return NGX_OK;
+}
+
+
+char *
+ngx_http_no_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+    char  *p = conf;
+
+    ngx_str_t                          *value;
+    ngx_uint_t                          i;
+    ngx_array_t                       **a;
+    ngx_http_complex_value_t           *cv;
+    ngx_http_compile_complex_value_t    ccv;
+
+    a = (ngx_array_t **) (p + cmd->offset);
+
+    if (*a == NGX_CONF_UNSET_PTR) {
+        *a = ngx_array_create(cf->pool, 1, sizeof(ngx_http_complex_value_t));
+        if (*a == NULL) {
+            return NGX_CONF_ERROR;
+        }
+    }
+
+    value = cf->args->elts;
+
+    for (i = 1; i < cf->args->nelts; i++) {
+        cv = ngx_array_push(*a);
+        if (cv == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+        ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
+
+        ccv.cf = cf;
+        ccv.value = &value[i];
+        ccv.complex_value = cv;
+
+        if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
+            return NGX_CONF_ERROR;
+        }
+    }
+
+    return NGX_CONF_OK;
+}
--- a/src/http/ngx_http_header_filter_module.c
+++ b/src/http/ngx_http_header_filter_module.c
@@ -538,8 +538,8 @@ ngx_http_header_filter(ngx_http_request_
 
         r->headers_out.location->value.len = b->last - p;
         r->headers_out.location->value.data = p;
-        r->headers_out.location->key.len = sizeof("Location: ") - 1;
-        r->headers_out.location->key.data = (u_char *) "Location: ";
+        r->headers_out.location->key.len = sizeof("Location") - 1;
+        r->headers_out.location->key.data = (u_char *) "Location";
 
         *b->last++ = CR; *b->last++ = LF;
     }
--- a/src/http/ngx_http_parse.c
+++ b/src/http/ngx_http_parse.c
@@ -438,8 +438,7 @@ ngx_http_parse_request_line(ngx_http_req
                 r->plus_in_uri = 1;
                 break;
             case '\0':
-                r->zero_in_uri = 1;
-                break;
+                return NGX_HTTP_PARSE_INVALID_REQUEST;
             default:
                 state = sw_check_uri;
                 break;
@@ -496,8 +495,7 @@ ngx_http_parse_request_line(ngx_http_req
                 r->plus_in_uri = 1;
                 break;
             case '\0':
-                r->zero_in_uri = 1;
-                break;
+                return NGX_HTTP_PARSE_INVALID_REQUEST;
             }
             break;
 
@@ -526,8 +524,7 @@ ngx_http_parse_request_line(ngx_http_req
                 r->complex_uri = 1;
                 break;
             case '\0':
-                r->zero_in_uri = 1;
-                break;
+                return NGX_HTTP_PARSE_INVALID_REQUEST;
             }
             break;
 
@@ -1202,7 +1199,7 @@ ngx_http_parse_complex_uri(ngx_http_requ
                     ch = *p++;
 
                 } else if (ch == '\0') {
-                    r->zero_in_uri = 1;
+                    return NGX_HTTP_PARSE_INVALID_REQUEST;
                 }
 
                 state = quoted_state;
@@ -1304,8 +1301,7 @@ ngx_http_parse_unsafe_uri(ngx_http_reque
         }
 
         if (ch == '\0') {
-            *flags |= NGX_HTTP_ZERO_IN_URI;
-            continue;
+            goto unsafe;
         }
 
         if (ngx_path_separator(ch) && len > 2) {
@@ -1449,34 +1445,19 @@ ngx_http_arg(ngx_http_request_t *r, u_ch
 void
 ngx_http_split_args(ngx_http_request_t *r, ngx_str_t *uri, ngx_str_t *args)
 {
-    u_char  ch, *p, *last;
-
-    p = uri->data;
-
-    last = p + uri->len;
+    u_char  *p, *last;
 
-    args->len = 0;
+    last = uri->data + uri->len;
 
-    while (p < last) {
-
-        ch = *p++;
+    p = ngx_strlchr(uri->data, last, '?');
 
-        if (ch == '?') {
-            args->len = last - p;
-            args->data = p;
-
-            uri->len = p - 1 - uri->data;
+    if (p) {
+        uri->len = p - uri->data;
+        p++;
+        args->len = last - p;
+        args->data = p;
 
-            if (ngx_strlchr(p, last, '\0') != NULL) {
-                r->zero_in_uri = 1;
-            }
-
-            return;
-        }
-
-        if (ch == '\0') {
-            r->zero_in_uri = 1;
-            continue;
-        }
+    } else {
+        args->len = 0;
     }
 }
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -784,16 +784,31 @@ ngx_http_process_request_line(ngx_event_
 
             p = r->uri.data + r->uri.len - 1;
 
-            if (*p == '.' || *p == ' ') {
-
-                while (--p > r->uri.data && (*p == '.' || *p == ' ')) {
-                    /* void */
+            while (p > r->uri.data) {
+
+                if (*p == ' ') {
+                    p--;
+                    continue;
+                }
+
+                if (*p == '.') {
+                    p--;
+                    continue;
                 }
 
+                if (ngx_strncasecmp(p - 6, (u_char *) "::$data", 7) == 0) {
+                    p -= 7;
+                    continue;
+                }
+
+                break;
+            }
+
+            if (p != r->uri.data + r->uri.len - 1) {
                 r->uri.len = p + 1 - r->uri.data;
-
                 ngx_http_set_exten(r);
             }
+
             }
 #endif
 
@@ -1443,6 +1458,12 @@ ngx_http_process_user_agent(ngx_http_req
         if (ngx_strstrn(user_agent, "Gecko/", 6 - 1)) {
             r->headers_in.gecko = 1;
 
+        } else if (ngx_strstrn(user_agent, "Chrome/", 7 - 1)) {
+            r->headers_in.chrome = 1;
+
+        } else if (ngx_strstrn(user_agent, "Safari/", 7 - 1)) {
+            r->headers_in.safari = 1;
+
         } else if (ngx_strstrn(user_agent, "Konqueror", 9 - 1)) {
             r->headers_in.konqueror = 1;
         }
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -57,7 +57,7 @@
 #define NGX_HTTP_PARSE_INVALID_HEADER      13
 
 
-#define NGX_HTTP_ZERO_IN_URI               1
+/* unused                                  1 */
 #define NGX_HTTP_SUBREQUEST_IN_MEMORY      2
 #define NGX_HTTP_SUBREQUEST_WAITED         4
 #define NGX_HTTP_LOG_UNSAFE                8
@@ -220,6 +220,8 @@ typedef struct {
     unsigned                          msie6:1;
     unsigned                          opera:1;
     unsigned                          gecko:1;
+    unsigned                          chrome:1;
+    unsigned                          safari:1;
     unsigned                          konqueror:1;
 } ngx_http_headers_in_t;
 
@@ -428,9 +430,6 @@ struct ngx_http_request_s {
     /* URI with "+" */
     unsigned                          plus_in_uri:1;
 
-    /* URI with "\0" or "%00" */
-    unsigned                          zero_in_uri:1;
-
     unsigned                          invalid_header:1;
 
     unsigned                          valid_location:1;
--- a/src/http/ngx_http_special_response.c
+++ b/src/http/ngx_http_special_response.c
@@ -31,13 +31,13 @@ static u_char ngx_http_error_tail[] =
 ;
 
 
-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
-"<!-- 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
+static u_char ngx_http_msie_padding[] =
+"<!-- a padding to disable MSIE and Chrome friendly error page -->" CRLF
+"<!-- a padding to disable MSIE and Chrome friendly error page -->" CRLF
+"<!-- a padding to disable MSIE and Chrome friendly error page -->" CRLF
+"<!-- a padding to disable MSIE and Chrome friendly error page -->" CRLF
+"<!-- a padding to disable MSIE and Chrome friendly error page -->" CRLF
+"<!-- a padding to disable MSIE and Chrome friendly error page -->" CRLF
 ;
 
 
@@ -517,8 +517,6 @@ ngx_http_send_error_page(ngx_http_reques
 
     r->err_status = overwrite;
 
-    r->zero_in_uri = 0;
-
     if (ngx_http_complex_value(r, &err_page->value, &uri) != NGX_OK) {
         return NGX_ERROR;
     }
@@ -598,12 +596,12 @@ ngx_http_send_special_response(ngx_http_
             r->headers_out.content_length_n = ngx_http_error_pages[err].len
                                               + len;
             if (clcf->msie_padding
-                && r->headers_in.msie
+                && (r->headers_in.msie || r->headers_in.chrome)
                 && r->http_version >= NGX_HTTP_VERSION_10
                 && err >= NGX_HTTP_LEVEL_300)
             {
                 r->headers_out.content_length_n +=
-                                                sizeof(ngx_http_msie_stub) - 1;
+                                             sizeof(ngx_http_msie_padding) - 1;
                 msie_padding = 1;
             }
 
@@ -671,8 +669,8 @@ ngx_http_send_special_response(ngx_http_
         }
 
         b->memory = 1;
-        b->pos = ngx_http_msie_stub;
-        b->last = ngx_http_msie_stub + sizeof(ngx_http_msie_stub) - 1;
+        b->pos = ngx_http_msie_padding;
+        b->last = ngx_http_msie_padding + sizeof(ngx_http_msie_padding) - 1;
 
         out[1].next = &out[2];
         out[2].buf = b;
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -363,8 +363,6 @@ ngx_http_upstream_create(ngx_http_reques
 
     if (u && u->cleanup) {
         ngx_http_upstream_cleanup(r);
-        *u->cleanup = NULL;
-        u->cleanup = NULL;
     }
 
     u = ngx_pcalloc(r->pool, sizeof(ngx_http_upstream_t));
@@ -587,6 +585,13 @@ ngx_http_upstream_cache(ngx_http_request
     ngx_int_t          rc;
     ngx_http_cache_t  *c;
 
+    if (u->conf->no_cache) {
+        rc = ngx_http_cache(r, u->conf->no_cache);
+        if (rc != NGX_OK) {
+            return rc;
+        }
+    }
+
     if (!(r->method & u->conf->cache_methods)) {
         return NGX_DECLINED;
     }
@@ -1775,10 +1780,6 @@ ngx_http_upstream_process_headers(ngx_ht
             return NGX_DONE;
         }
 
-        if (flags & NGX_HTTP_ZERO_IN_URI) {
-            r->zero_in_uri = 1;
-        }
-
         if (r->method != NGX_HTTP_HEAD) {
             r->method = NGX_HTTP_GET;
         }
@@ -3004,16 +3005,18 @@ ngx_http_upstream_process_cache_control(
         return NGX_OK;
     }
 
-    last = h->value.data + h->value.len;
-
-    if (ngx_strlcasestrn(h->value.data, last, (u_char *) "no-cache", 8 - 1)
-        != NULL)
+    p = h->value.data;
+    last = p + h->value.len;
+
+    if (ngx_strlcasestrn(p, last, (u_char *) "no-cache", 8 - 1) != NULL
+        || ngx_strlcasestrn(p, last, (u_char *) "no-store", 8 - 1) != NULL
+        || ngx_strlcasestrn(p, last, (u_char *) "private", 7 - 1) != NULL)
     {
         u->cacheable = 0;
         return NGX_OK;
     }
 
-    p = ngx_strlcasestrn(h->value.data, last, (u_char *) "max-age=", 8 - 1);
+    p = ngx_strlcasestrn(p, last, (u_char *) "max-age=", 8 - 1);
 
     if (p == NULL) {
         return NGX_OK;
--- a/src/http/ngx_http_upstream.h
+++ b/src/http/ngx_http_upstream.h
@@ -160,6 +160,7 @@ typedef struct {
     ngx_uint_t                       cache_methods;
 
     ngx_array_t                     *cache_valid;
+    ngx_array_t                     *no_cache; /* ngx_http_complex_value_t */
 #endif
 
     ngx_array_t                     *store_lengths;
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -196,7 +196,8 @@ static ngx_http_variable_t  ngx_http_cor
     { ngx_string("server_name"), NULL, ngx_http_variable_server_name, 0, 0, 0 },
 
     { ngx_string("request_method"), NULL,
-      ngx_http_variable_request_method, 0, 0, 0 },
+      ngx_http_variable_request_method, 0,
+      NGX_HTTP_VAR_NOCACHEABLE, 0 },
 
     { ngx_string("remote_user"), NULL, ngx_http_variable_remote_user, 0, 0, 0 },
 
@@ -440,8 +441,7 @@ ngx_http_get_flushed_variable(ngx_http_r
 
 
 ngx_http_variable_value_t *
-ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key,
-    ngx_uint_t nowarn)
+ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key)
 {
     ngx_http_variable_t        *v;
     ngx_http_variable_value_t  *vv;
@@ -453,7 +453,7 @@ ngx_http_get_variable(ngx_http_request_t
 
     if (v) {
         if (v->flags & NGX_HTTP_VAR_INDEXED) {
-            return ngx_http_get_indexed_variable(r, v->index);
+            return ngx_http_get_flushed_variable(r, v->index);
 
         } else {
 
@@ -494,7 +494,7 @@ ngx_http_get_variable(ngx_http_request_t
         return NULL;
     }
 
-    if (ngx_strncmp(name->data, "upstream_http_", 10) == 0) {
+    if (ngx_strncmp(name->data, "upstream_http_", 14) == 0) {
 
         if (ngx_http_upstream_header_variable(r, vv, (uintptr_t) name)
             == NGX_OK)
@@ -525,11 +525,6 @@ ngx_http_get_variable(ngx_http_request_t
 
     vv->not_found = 1;
 
-    if (nowarn == 0) {
-        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
-                      "unknown \"%V\" variable", name);
-    }
-
     return vv;
 }
 
@@ -1781,6 +1776,7 @@ ngx_http_variables_init_vars(ngx_conf_t 
         if (ngx_strncmp(v[i].name.data, "arg_", 4) == 0) {
             v[i].get_handler = ngx_http_variable_argument;
             v[i].data = (uintptr_t) &v[i].name;
+            v[i].flags = NGX_HTTP_VAR_NOCACHEABLE;
 
             continue;
         }
--- a/src/http/ngx_http_variables.h
+++ b/src/http/ngx_http_variables.h
@@ -50,7 +50,7 @@ ngx_http_variable_value_t *ngx_http_get_
     ngx_uint_t index);
 
 ngx_http_variable_value_t *ngx_http_get_variable(ngx_http_request_t *r,
-    ngx_str_t *name, ngx_uint_t key, ngx_uint_t nowarn);
+    ngx_str_t *name, ngx_uint_t key);
 
 ngx_int_t ngx_http_variable_unknown_header(ngx_http_variable_value_t *v,
     ngx_str_t *var, ngx_list_part_t *part, size_t prefix);
--- a/src/mail/ngx_mail_pop3_handler.c
+++ b/src/mail/ngx_mail_pop3_handler.c
@@ -188,7 +188,6 @@ ngx_mail_pop3_auth_state(ngx_event_t *re
 
             default:
                 rc = NGX_MAIL_PARSE_INVALID_COMMAND;
-                s->mail_state = ngx_pop3_start;
                 break;
             }
 
@@ -215,7 +214,6 @@ ngx_mail_pop3_auth_state(ngx_event_t *re
 
             default:
                 rc = NGX_MAIL_PARSE_INVALID_COMMAND;
-                s->mail_state = ngx_pop3_start;
                 break;
             }
 
--- a/src/mail/ngx_mail_proxy_module.c
+++ b/src/mail/ngx_mail_proxy_module.c
@@ -726,7 +726,7 @@ ngx_mail_proxy_read_response(ngx_mail_se
 
     b->last += n;
 
-    if (b->last - b->pos < 5) {
+    if (b->last - b->pos < 4) {
         return NGX_AGAIN;
     }
 
--- a/src/os/unix/ngx_errno.h
+++ b/src/os/unix/ngx_errno.h
@@ -64,10 +64,22 @@ u_char *ngx_strerror_r(int err, u_char *
 
 /* Solaris and Tru64 UNIX have thread-safe strerror() */
 
-#define ngx_strerror_r(err, errstr, size)  \
+#define ngx_strerror_r(err, errstr, size)                                    \
     ngx_cpystrn(errstr, (u_char *) strerror(err), size)
 
 #endif
 
 
+#if (NGX_HAVE_SYS_ERRLIST)
+
+#define ngx_sigsafe_strerror(err)                                            \
+    (err > 0 && err < sys_nerr) ? sys_errlist[err] : "Unknown error"
+
+#else
+
+#define ngx_sigsafe_strerror(err)  ""
+
+#endif
+
+
 #endif /* _NGX_ERRNO_H_INCLUDED_ */
--- a/src/os/unix/ngx_files.h
+++ b/src/os/unix/ngx_files.h
@@ -64,6 +64,7 @@ typedef struct {
 #define NGX_FILE_OPEN            0
 #define NGX_FILE_TRUNCATE        O_CREAT|O_TRUNC
 #define NGX_FILE_APPEND          O_WRONLY|O_APPEND
+#define NGX_FILE_NONBLOCK        O_NONBLOCK
 
 #define NGX_FILE_DEFAULT_ACCESS  0644
 #define NGX_FILE_OWNER_ACCESS    0600
@@ -138,6 +139,9 @@ ngx_int_t ngx_set_file_time(u_char *name
 #define ngx_fd_info(fd, sb)      fstat(fd, sb)
 #define ngx_fd_info_n            "fstat()"
 
+#define ngx_link_info(file, sb)  lstat((const char *) file, sb)
+#define ngx_link_info_n          "lstat()"
+
 #define ngx_is_dir(sb)           (S_ISDIR((sb)->st_mode))
 #define ngx_is_file(sb)          (S_ISREG((sb)->st_mode))
 #define ngx_is_link(sb)          (S_ISLNK((sb)->st_mode))
--- a/src/os/unix/ngx_process.c
+++ b/src/os/unix/ngx_process.c
@@ -315,7 +315,7 @@ ngx_signal_handler(int signo)
         }
     }
 
-    ngx_time_update(0, 0);
+    ngx_time_sigsafe_update();
 
     action = "";
 
@@ -476,16 +476,17 @@ ngx_process_get_status(void)
              */
 
             if (err == NGX_ECHILD) {
-                ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, errno,
-                              "waitpid() failed");
+                ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0,
+                              "waitpid() failed (%d: %s)",
+                              err, ngx_sigsafe_strerror(err));
                 return;
             }
 
 #endif
 
-            ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, errno,
-                          "waitpid() failed");
-
+            ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
+                          "waitpid() failed (%d: %s)",
+                          err, ngx_sigsafe_strerror(err));
             return;
         }
 
--- a/src/os/unix/ngx_process_cycle.c
+++ b/src/os/unix/ngx_process_cycle.c
@@ -168,7 +168,7 @@ ngx_master_process_cycle(ngx_cycle_t *cy
 
         sigsuspend(&set);
 
-        ngx_time_update(0, 0);
+        ngx_time_update();
 
         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                        "wake up, sigio %i", sigio);
@@ -1337,7 +1337,7 @@ ngx_cache_manager_process_handler(ngx_ev
 
             next = (n <= next) ? n : next;
 
-            ngx_time_update(0, 0);
+            ngx_time_update();
         }
     }
 
@@ -1367,7 +1367,7 @@ ngx_cache_loader_process_handler(ngx_eve
 
         if (path[i]->loader) {
             path[i]->loader(path[i]->data);
-            ngx_time_update(0, 0);
+            ngx_time_update();
         }
     }