changeset 328:26ff8d6b618d NGINX_0_5_34

nginx 0.5.34 *) Change: now the full request line instead of URI only is written to error_log. *) Feature: Cygwin compatibility. Thanks to Vladimir Kutakov. *) Feature: the "merge_slashes" directive. *) Feature: the "gzip_vary" directive. *) Feature: the "server_tokens" directive. *) Feature: the "access_log" directive may be used inside the "limit_except" block. *) Bugfix: if the $server_protocol was used in FastCGI parameters and a request line length was near to the "client_header_buffer_size" directive value, then nginx issued an alert "fastcgi: the request record is too big". *) Bugfix: if a plain text HTTP/0.9 version request was made to HTTPS server, then nginx returned usual response. *) Bugfix: URL double escaping in a redirect of the "msie_refresh" directive; bug appeared in 0.5.28. *) Bugfix: a segmentation fault might occur in worker process if subrequests were used. *) Bugfix: the big responses may be transferred truncated if SSL and gzip were used. *) Bugfix: compatibility with mget. *) Bugfix: nginx did not unescape URI in the "include" SSI command. *) Bugfix: the segmentation fault was occurred on start or while reconfiguration if variable was used in the "charset" or "source_charset" directives. *) Bugfix: nginx returned the 400 response on requests like "GET http://www.domain.com HTTP/1.0". Thanks to James Oakley. *) Bugfix: a segmentation fault occurred in worker process if $date_local and $date_gmt were used outside the ngx_http_ssi_filter_module. *) Bugfix: a segmentation fault might occur in worker process if debug log was enabled. Thanks to Andrei Nigmatulin. *) Bugfix: ngx_http_memcached_module did not set $upstream_response_time. Thanks to Maxim Dounin. *) Bugfix: a worker process may got caught in an endless loop, if the memcached was used.
author Igor Sysoev <http://sysoev.ru>
date Thu, 13 Dec 2007 00:00:00 +0300
parents cb962a94cd7b
children d792b2cd78fe
files CHANGES CHANGES.ru auto/headers auto/sources src/core/nginx.h src/core/ngx_conf_file.c src/core/ngx_inet.c src/core/ngx_inet.h src/core/ngx_md5.h src/core/ngx_sha1.h src/core/ngx_string.c src/core/ngx_string.h src/event/ngx_event_busy_lock.c src/event/ngx_event_busy_lock.h src/event/ngx_event_pipe.c src/event/ngx_event_pipe.h src/http/modules/ngx_http_browser_module.c src/http/modules/ngx_http_charset_filter_module.c src/http/modules/ngx_http_fastcgi_module.c src/http/modules/ngx_http_geo_module.c src/http/modules/ngx_http_gzip_filter_module.c src/http/modules/ngx_http_log_module.c src/http/modules/ngx_http_map_module.c src/http/modules/ngx_http_memcached_module.c src/http/modules/ngx_http_proxy_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_ssl_module.c src/http/modules/ngx_http_stub_status_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.h src/http/ngx_http_busy_lock.c src/http/ngx_http_busy_lock.h src/http/ngx_http_core_module.c src/http/ngx_http_core_module.h src/http/ngx_http_header_filter_module.c 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_script.c src/http/ngx_http_script.h src/http/ngx_http_special_response.c src/http/ngx_http_upstream.c src/http/ngx_http_upstream.h src/http/ngx_http_upstream_round_robin.c src/http/ngx_http_variables.c src/http/ngx_http_variables.h src/mail/ngx_mail.h src/mail/ngx_mail_auth_http_module.c src/mail/ngx_mail_core_module.c src/os/unix/ngx_posix_config.h src/os/unix/ngx_process_cycle.c src/os/unix/ngx_recv.c src/os/unix/ngx_send.c src/os/unix/ngx_solaris_init.c
diffstat 60 files changed, 686 insertions(+), 313 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,66 @@
 
+Changes with nginx 0.5.34                                        13 Dec 2007
+
+    *) Change: now the full request line instead of URI only is written to 
+       error_log.
+
+    *) Feature: Cygwin compatibility.
+       Thanks to Vladimir Kutakov.
+
+    *) Feature: the "merge_slashes" directive.
+
+    *) Feature: the "gzip_vary" directive.
+
+    *) Feature: the "server_tokens" directive.
+
+    *) Feature: the "access_log" directive may be used inside the 
+       "limit_except" block.
+
+    *) Bugfix: if the $server_protocol was used in FastCGI parameters and a 
+       request line length was near to the "client_header_buffer_size" 
+       directive value, then nginx issued an alert "fastcgi: the request 
+       record is too big".
+
+    *) Bugfix: if a plain text HTTP/0.9 version request was made to HTTPS 
+       server, then nginx returned usual response.
+
+    *) Bugfix: URL double escaping in a redirect of the "msie_refresh" 
+       directive; bug appeared in 0.5.28.
+
+    *) Bugfix: a segmentation fault might occur in worker process if 
+       subrequests were used.
+
+    *) Bugfix: the big responses may be transferred truncated if SSL and 
+       gzip were used.
+
+    *) Bugfix: compatibility with mget.
+
+    *) Bugfix: nginx did not unescape URI in the "include" SSI command.
+
+    *) Bugfix: the segmentation fault was occurred on start or while 
+       reconfiguration if variable was used in the "charset" or 
+       "source_charset" directives.
+
+    *) Bugfix: nginx returned the 400 response on requests like 
+       "GET http://www.domain.com HTTP/1.0".
+       Thanks to James Oakley.
+
+    *) Bugfix: a segmentation fault occurred in worker process if 
+       $date_local and $date_gmt were used outside the 
+       ngx_http_ssi_filter_module.
+
+    *) Bugfix: a segmentation fault might occur in worker process if debug 
+       log was enabled.
+       Thanks to Andrei Nigmatulin.
+
+    *) Bugfix: ngx_http_memcached_module did not set 
+       $upstream_response_time.
+       Thanks to Maxim Dounin.
+
+    *) Bugfix: a worker process may got caught in an endless loop, if the 
+       memcached was used.
+
+
 Changes with nginx 0.5.33                                        07 Nov 2007
 
     *) Change: now by default the "echo" SSI command uses entity encoding.
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,66 @@
 
+Изменения в nginx 0.5.34                                          13.12.2007
+
+    *) Изменение: в error_log теперь записывается полная строка запроса 
+       вместо только URI.
+
+    *) Добавление: совместимость с Cygwin.
+       Спасибо Владимиру Кутакову.
+
+    *) Добавление: директива merge_slashes.
+
+    *) Добавление: директива gzip_vary.
+
+    *) Добавление: директива server_tokens.
+
+    *) Добавление: директиву access_log можно использовать внутри блока 
+       limit_except.
+
+    *) Исправление: При использовании переменной $server_protocol в 
+       FastCGI-параметрах и запросе, длина которого была близка к значению 
+       директивы client_header_buffer_size, nginx выдавал alert "fastcgi: 
+       the request record is too big".
+
+    *) Исправление: при обычном запросе версии HTTP/0.9 к HTTPS серверу 
+       nginx возвращал обычный ответ.
+
+    *) Исправление: при использовании директивы msie_refresh повторно 
+       экранировались уже экранированные символы; ошибка появилась в 0.5.28.
+
+    *) Исправление: при использовании подзапросов в рабочем процессе мог 
+       произойти segmentation fault.
+
+    *) Исправление: при использовании SSL и gzip большие ответы могли 
+       передаваться не полностью.
+
+    *) Исправление: совместимость с mget.
+
+    *) Исправление: nginx не раскодировал URI в команде SSI include.
+
+    *) Исправление: при использовании переменной в директивах charset или 
+       source_charset на старте или во время переконфигурации происходил 
+       segmentation fault,
+
+    *) Исправление: nginx возвращал ошибку 400 на запросы вида 
+       "GET http://www.domain.com HTTP/1.0".
+       Спасибо James Oakley.
+
+    *) Исправление: при использовании переменных $date_local и $date_gmt 
+       вне модуля ngx_http_ssi_filter_module в рабочем процессе происходил 
+       segmentation fault.
+
+    *) Исправление: при использовании включённом отладочном логе в рабочем 
+       процессе мог произойти segmentation fault.
+       Спасибо Андрею Нигматулину.
+
+    *) Исправление: ngx_http_memcached_module не устанавливал 
+       upstream_response_time.
+       Спасибо Максиму Дунину.
+
+    *) Исправление: рабочий процесс мог зациклиться при использовании 
+       memcached.
+
+
 Изменения в nginx 0.5.33                                          07.11.2007
 
     *) Изменение: теперь по умолчанию команда SSI echo использует 
--- a/auto/headers
+++ b/auto/headers
@@ -6,3 +6,5 @@ ngx_include="unistd.h";    . auto/includ
 ngx_include="inttypes.h";  . auto/include
 ngx_include="limits.h";    . auto/include
 ngx_include="sys/filio.h"; . auto/include
+ngx_include="crypt.h";     . auto/include
+ngx_include="malloc.h";    . auto/include
--- a/auto/sources
+++ b/auto/sources
@@ -21,6 +21,8 @@ CORE_DEPS="src/core/nginx.h \
            src/core/ngx_file.h \
            src/core/ngx_crc.h \
            src/core/ngx_crc32.h \
+           src/core/ngx_md5.h \
+           src/core/ngx_sha1.h \
            src/core/ngx_rbtree.h \
            src/core/ngx_radix_tree.h \
            src/core/ngx_slab.h \
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define NGINX_VERSION      "0.5.33"
+#define NGINX_VERSION      "0.5.34"
 #define NGINX_VER          "nginx/" NGINX_VERSION
 
 #define NGINX_VAR          "NGINX"
--- a/src/core/ngx_conf_file.c
+++ b/src/core/ngx_conf_file.c
@@ -117,7 +117,7 @@ ngx_conf_parse(ngx_conf_t *cf, ngx_str_t
         cf->conf_file->file.name.len = filename->len;
         cf->conf_file->file.name.data = filename->data;
         cf->conf_file->file.offset = 0;
-        cf->conf_file->file.log = cf->log;;
+        cf->conf_file->file.log = cf->log;
         cf->conf_file->line = 1;
 
         block = 0;
--- a/src/core/ngx_inet.c
+++ b/src/core/ngx_inet.c
@@ -225,7 +225,7 @@ ngx_ptocidr(ngx_str_t *text, void *cidr)
 
 
 ngx_int_t
-ngx_parse_url(ngx_conf_t *cf, ngx_url_t *u)
+ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u)
 {
     u_char              *p, *host, *port_start;
     size_t               len, port_len;
@@ -273,12 +273,12 @@ ngx_parse_url(ngx_conf_t *cf, ngx_url_t 
             return NGX_ERROR;
         }
 
-        u->addrs = ngx_pcalloc(cf->pool, sizeof(ngx_peer_addr_t));
+        u->addrs = ngx_pcalloc(pool, sizeof(ngx_peer_addr_t));
         if (u->addrs == NULL) {
             return NGX_ERROR;
         }
 
-        saun = ngx_pcalloc(cf->pool, sizeof(struct sockaddr_un));
+        saun = ngx_pcalloc(pool, sizeof(struct sockaddr_un));
         if (saun == NULL) {
             return NGX_ERROR;
         }
@@ -408,12 +408,12 @@ no_port:
 
         if (u->host.len) {
 
-           host = ngx_palloc(cf->temp_pool, u->host.len + 1);
-           if (host == NULL) {
-               return NGX_ERROR;
-           }
+            host = ngx_alloc(u->host.len + 1, pool->log);
+            if (host == NULL) {
+                return NGX_ERROR;
+            }
 
-           (void) ngx_cpystrn(host, u->host.data, u->host.len + 1);
+            (void) ngx_cpystrn(host, u->host.data, u->host.len + 1);
 
             u->addr.in_addr = inet_addr((const char *) host);
 
@@ -421,6 +421,7 @@ no_port:
                 h = gethostbyname((const char *) host);
 
                 if (h == NULL || h->h_addr_list[0] == NULL) {
+                    ngx_free(host);
                     u->err = "host not found";
                     return NGX_ERROR;
                 }
@@ -428,6 +429,8 @@ no_port:
                 u->addr.in_addr = *(in_addr_t *) (h->h_addr_list[0]);
             }
 
+            ngx_free(host);
+
         } else {
             u->addr.in_addr = INADDR_ANY;
         }
@@ -453,7 +456,7 @@ no_port:
         return NGX_ERROR;
     }
 
-    if (ngx_inet_resolve_host(cf, u) != NGX_OK) {
+    if (ngx_inet_resolve_host(pool, u) != NGX_OK) {
         return NGX_ERROR;
     }
 
@@ -462,7 +465,7 @@ no_port:
 
 
 ngx_int_t
-ngx_inet_resolve_host(ngx_conf_t *cf, ngx_url_t *u)
+ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
 {
     u_char              *p, *host;
     size_t               len;
@@ -471,7 +474,7 @@ ngx_inet_resolve_host(ngx_conf_t *cf, ng
     struct hostent      *h;
     struct sockaddr_in  *sin;
 
-    host = ngx_palloc(cf->temp_pool, u->host.len + 1);
+    host = ngx_alloc(u->host.len + 1, pool->log);
     if (host == NULL) {
         return NGX_ERROR;
     }
@@ -485,6 +488,8 @@ ngx_inet_resolve_host(ngx_conf_t *cf, ng
     if (in_addr == INADDR_NONE) {
         h = gethostbyname((char *) host);
 
+        ngx_free(host);
+
         if (h == NULL || h->h_addr_list[0] == NULL) {
             u->err = "host not found";
             return NGX_ERROR;
@@ -499,7 +504,7 @@ ngx_inet_resolve_host(ngx_conf_t *cf, ng
 
         /* MP: ngx_shared_palloc() */
 
-        u->addrs = ngx_pcalloc(cf->pool, i * sizeof(ngx_peer_addr_t));
+        u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_peer_addr_t));
         if (u->addrs == NULL) {
             return NGX_ERROR;
         }
@@ -508,7 +513,7 @@ ngx_inet_resolve_host(ngx_conf_t *cf, ng
 
         for (i = 0; h->h_addr_list[i] != NULL; i++) {
 
-            sin = ngx_pcalloc(cf->pool, sizeof(struct sockaddr_in));
+            sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
             if (sin == NULL) {
                 return NGX_ERROR;
             }
@@ -522,7 +527,7 @@ ngx_inet_resolve_host(ngx_conf_t *cf, ng
 
             len = INET_ADDRSTRLEN - 1 + 1 + sizeof(":65536") - 1;
 
-            p = ngx_palloc(cf->pool, len);
+            p = ngx_palloc(pool, len);
             if (p == NULL) {
                 return NGX_ERROR;
             }
@@ -535,14 +540,16 @@ ngx_inet_resolve_host(ngx_conf_t *cf, ng
 
     } else {
 
+        ngx_free(host);
+
         /* MP: ngx_shared_palloc() */
 
-        u->addrs = ngx_pcalloc(cf->pool, sizeof(ngx_peer_addr_t));
+        u->addrs = ngx_pcalloc(pool, sizeof(ngx_peer_addr_t));
         if (u->addrs == NULL) {
             return NGX_ERROR;
         }
 
-        sin = ngx_pcalloc(cf->pool, sizeof(struct sockaddr_in));
+        sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
         if (sin == NULL) {
             return NGX_ERROR;
         }
@@ -556,7 +563,7 @@ ngx_inet_resolve_host(ngx_conf_t *cf, ng
         u->addrs[0].sockaddr = (struct sockaddr *) sin;
         u->addrs[0].socklen = sizeof(struct sockaddr_in);
 
-        p = ngx_palloc(cf->pool, u->host.len + sizeof(":65536") - 1);
+        p = ngx_palloc(pool, u->host.len + sizeof(":65536") - 1);
         if (p == NULL) {
             return NGX_ERROR;
         }
--- a/src/core/ngx_inet.h
+++ b/src/core/ngx_inet.h
@@ -61,8 +61,8 @@ typedef struct {
 size_t ngx_sock_ntop(int family, struct sockaddr *sa, u_char *text, size_t len);
 size_t ngx_inet_ntop(int family, void *addr, u_char *text, size_t len);
 ngx_int_t ngx_ptocidr(ngx_str_t *text, void *cidr);
-ngx_int_t ngx_parse_url(ngx_conf_t *cf, ngx_url_t *u);
-ngx_int_t ngx_inet_resolve_host(ngx_conf_t *cf, ngx_url_t *u);
+ngx_int_t ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u);
+ngx_int_t ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u);
 
 
 
new file mode 100644
--- /dev/null
+++ b/src/core/ngx_md5.h
@@ -0,0 +1,40 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#ifndef _NGX_MD5_H_INCLUDED_
+#define _NGX_MD5_H_INCLUDED_
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+
+
+#if (NGX_HAVE_OPENSSL_MD5_H)
+#include <openssl/md5.h>
+#else
+#include <md5.h>
+#endif
+
+
+typedef MD5_CTX  ngx_md5_t;
+
+
+#if (NGX_OPENSSL_MD5)
+
+#define ngx_md5_init    MD5_Init
+#define ngx_md5_update  MD5_Update
+#define ngx_md5_final   MD5_Final
+
+#else
+
+#define ngx_md5_init    MD5Init
+#define ngx_md5_update  MD5Update
+#define ngx_md5_final   MD5Final
+
+#endif
+
+
+#endif /* _NGX_MD5_H_INCLUDED_ */
new file mode 100644
--- /dev/null
+++ b/src/core/ngx_sha1.h
@@ -0,0 +1,30 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#ifndef _NGX_SHA1_H_INCLUDED_
+#define _NGX_SHA1_H_INCLUDED_
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+
+
+#if (NGX_HAVE_OPENSSL_SHA1_H)
+#include <openssl/sha.h>
+#else
+#include <sha.h>
+#endif
+
+
+typedef SHA_CTX  ngx_sha1_t;
+
+
+#define ngx_sha1_init    SHA1_Init
+#define ngx_sha1_update  SHA1_Update
+#define ngx_sha1_final   SHA1_Final
+
+
+#endif /* _NGX_SHA1_H_INCLUDED_ */
--- a/src/core/ngx_string.c
+++ b/src/core/ngx_string.c
@@ -1147,7 +1147,7 @@ ngx_escape_uri(u_char *dst, u_char *src,
         0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
 
                     /* ?>=< ;:98 7654 3210  /.-, +*)( '&%$ #"!  */
-        0x000000a5, /* 0000 0000 0000 0000  0000 0000 1010 0101 */
+        0x00000085, /* 0000 0000 0000 0000  0000 0000 1000 0101 */
 
                     /* _^]\ [ZYX WVUT SRQP  ONML KJIH GFED CBA@ */
         0x00000000, /* 0000 0000 0000 0000  0000 0000 0000 0000 */
@@ -1243,7 +1243,9 @@ ngx_unescape_uri(u_char **dst, u_char **
 
         switch (state) {
         case sw_usual:
-            if (ch == '?' && type == NGX_UNESCAPE_URI) {
+            if (ch == '?'
+                && (type & (NGX_UNESCAPE_URI|NGX_UNESCAPE_REDIRECT)))
+            {
                 *d++ = ch;
                 goto done;
             }
@@ -1286,7 +1288,7 @@ ngx_unescape_uri(u_char **dst, u_char **
             if (ch >= '0' && ch <= '9') {
                 ch = (u_char) ((decoded << 4) + ch - '0');
 
-                if (type == NGX_UNESCAPE_URI) {
+                if (type & NGX_UNESCAPE_REDIRECT) {
                     if (ch > '%' && ch < 0x7f) {
                         *d++ = ch;
                         break;
@@ -1306,7 +1308,17 @@ ngx_unescape_uri(u_char **dst, u_char **
             if (c >= 'a' && c <= 'f') {
                 ch = (u_char) ((decoded << 4) + c - 'a' + 10);
 
-                if (type == NGX_UNESCAPE_URI) {
+                if (type & NGX_UNESCAPE_URI) {
+                    if (ch == '?') {
+                        *d++ = ch;
+                        goto done;
+                    }
+
+                    *d++ = ch;
+                    break;
+                }
+
+                if (type & NGX_UNESCAPE_REDIRECT) {
                     if (ch == '?') {
                         *d++ = ch;
                         goto done;
--- a/src/core/ngx_string.h
+++ b/src/core/ngx_string.h
@@ -28,7 +28,7 @@ typedef struct {
     unsigned    len:29;
 
     unsigned    valid:1;
-    unsigned    no_cachable:1;
+    unsigned    no_cacheable:1;
     unsigned    not_found:1;
 
     u_char     *data;
@@ -155,14 +155,15 @@ size_t ngx_utf_length(u_char *p, size_t 
 u_char *ngx_utf_cpystrn(u_char *dst, u_char *src, size_t n);
 
 
-#define NGX_ESCAPE_URI        0
-#define NGX_ESCAPE_ARGS       1
-#define NGX_ESCAPE_HTML       2
-#define NGX_ESCAPE_REFRESH    3
-#define NGX_ESCAPE_MEMCACHED  4
-#define NGX_ESCAPE_MAIL_AUTH  5
+#define NGX_ESCAPE_URI         0
+#define NGX_ESCAPE_ARGS        1
+#define NGX_ESCAPE_HTML        2
+#define NGX_ESCAPE_REFRESH     3
+#define NGX_ESCAPE_MEMCACHED   4
+#define NGX_ESCAPE_MAIL_AUTH   5
 
-#define NGX_UNESCAPE_URI      1
+#define NGX_UNESCAPE_URI       1
+#define NGX_UNESCAPE_REDIRECT  2
 
 uintptr_t ngx_escape_uri(u_char *dst, u_char *src, size_t size,
     ngx_uint_t type);
--- a/src/event/ngx_event_busy_lock.c
+++ b/src/event/ngx_event_busy_lock.c
@@ -9,7 +9,7 @@
 #include <ngx_event.h>
 
 
-static ngx_int_t ngx_event_busy_lock_look_cachable(ngx_event_busy_lock_t *bl,
+static ngx_int_t ngx_event_busy_lock_look_cacheable(ngx_event_busy_lock_t *bl,
     ngx_event_busy_lock_ctx_t *ctx);
 static void ngx_event_busy_lock_handler(ngx_event_t *ev);
 static void ngx_event_busy_lock_posted_handler(ngx_event_t *ev);
@@ -65,14 +65,14 @@ ngx_event_busy_lock(ngx_event_busy_lock_
 
 
 ngx_int_t
-ngx_event_busy_lock_cachable(ngx_event_busy_lock_t *bl,
+ngx_event_busy_lock_cacheable(ngx_event_busy_lock_t *bl,
     ngx_event_busy_lock_ctx_t *ctx)
 {
     ngx_int_t  rc;
 
     ngx_mutex_lock(bl->mutex);
 
-    rc = ngx_event_busy_lock_look_cachable(bl, ctx);
+    rc = ngx_event_busy_lock_look_cacheable(bl, ctx);
 
     ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ctx->event->log, 0,
                    "event busy lock: %d w:%d mw:%d",
@@ -201,14 +201,14 @@ ngx_event_busy_lock_cancel(ngx_event_bus
 
 
 static ngx_int_t
-ngx_event_busy_lock_look_cachable(ngx_event_busy_lock_t *bl,
+ngx_event_busy_lock_look_cacheable(ngx_event_busy_lock_t *bl,
     ngx_event_busy_lock_ctx_t *ctx)
 {
     ngx_int_t    free;
-    ngx_uint_t   i, bit, cachable, mask;
+    ngx_uint_t   i, bit, cacheable, mask;
 
     bit = 0;
-    cachable = 0;
+    cacheable = 0;
     free = -1;
 
 #if (NGX_SUPPRESS_WARN)
@@ -227,14 +227,14 @@ ngx_event_busy_lock_look_cachable(ngx_ev
                 ctx->slot = i;
                 return NGX_AGAIN;
             }
-            cachable++;
+            cacheable++;
 
         } else if (free == -1) {
             free = i;
         }
 
-        if (cachable == bl->cachable) {
-            if (free == -1 && cachable < bl->max_busy) {
+        if (cacheable == bl->cacheable) {
+            if (free == -1 && cacheable < bl->max_busy) {
                 free = i + 1;
             }
 
@@ -259,7 +259,7 @@ ngx_event_busy_lock_look_cachable(ngx_ev
     bl->md5_mask[free / 8] |= 1 << (free & 7);
     ctx->slot = free;
 
-    bl->cachable++;
+    bl->cacheable++;
     bl->busy++;
 
     return NGX_OK;
--- a/src/event/ngx_event_busy_lock.h
+++ b/src/event/ngx_event_busy_lock.h
@@ -34,7 +34,7 @@ struct ngx_event_busy_lock_ctx_s {
 typedef struct {
     u_char                     *md5_mask;
     char                       *md5;
-    ngx_uint_t                  cachable;
+    ngx_uint_t                  cacheable;
 
     ngx_uint_t                  busy;
     ngx_uint_t                  max_busy;
@@ -53,7 +53,7 @@ typedef struct {
 
 ngx_int_t ngx_event_busy_lock(ngx_event_busy_lock_t *bl,
     ngx_event_busy_lock_ctx_t *ctx);
-ngx_int_t ngx_event_busy_lock_cachable(ngx_event_busy_lock_t *bl,
+ngx_int_t ngx_event_busy_lock_cacheable(ngx_event_busy_lock_t *bl,
     ngx_event_busy_lock_ctx_t *ctx);
 void ngx_event_busy_unlock(ngx_event_busy_lock_t *bl,
     ngx_event_busy_lock_ctx_t *ctx);
--- a/src/event/ngx_event_pipe.c
+++ b/src/event/ngx_event_pipe.c
@@ -192,7 +192,7 @@ ngx_event_pipe_read_upstream(ngx_event_p
                 chain->buf = b;
                 chain->next = NULL;
 
-            } else if (!p->cachable
+            } else if (!p->cacheable
                        && p->downstream->data == p->output_ctx
                        && p->downstream->write->ready
                        && !p->downstream->write->delayed)
@@ -209,7 +209,7 @@ ngx_event_pipe_read_upstream(ngx_event_p
 
                 break;
 
-            } else if (p->cachable
+            } else if (p->cacheable
                        || p->temp_file->offset < p->max_temp_file_size)
             {
 
@@ -406,7 +406,7 @@ ngx_event_pipe_read_upstream(ngx_event_p
         }
     }
 
-    if (p->cachable && p->in) {
+    if (p->cacheable && p->in) {
         if (ngx_event_pipe_write_chain_to_temp_file(p) == NGX_ABORT) {
             return NGX_ABORT;
         }
@@ -421,6 +421,7 @@ ngx_event_pipe_write_to_downstream(ngx_e
 {
     u_char            *prev;
     size_t             bsize;
+    ngx_int_t          rc;
     ngx_uint_t         flush, prev_last_shadow;
     ngx_chain_t       *out, **ll, *cl;
     ngx_connection_t  *downstream;
@@ -451,7 +452,13 @@ ngx_event_pipe_write_to_downstream(ngx_e
                     cl->buf->recycled = 0;
                 }
 
-                if (p->output_filter(p->output_ctx, p->out) == NGX_ERROR) {
+                rc = p->output_filter(p->output_ctx, p->out);
+
+                if (downstream->destroyed) {
+                    return NGX_ABORT;
+                }
+
+                if (rc == NGX_ERROR) {
                     p->downstream_error = 1;
                     return ngx_event_pipe_drain_chains(p);
                 }
@@ -467,12 +474,13 @@ ngx_event_pipe_write_to_downstream(ngx_e
                     cl->buf->recycled = 0;
                 }
 
-                if (p->output_filter(p->output_ctx, p->in) == NGX_ERROR) {
+                rc = p->output_filter(p->output_ctx, p->in);
 
-                    if (downstream->destroyed) {
-                        return NGX_ABORT;
-                    }
+                if (downstream->destroyed) {
+                    return NGX_ABORT;
+                }
 
+                if (rc == NGX_ERROR) {
                     p->downstream_error = 1;
                     return ngx_event_pipe_drain_chains(p);
                 }
@@ -542,7 +550,7 @@ ngx_event_pipe_write_to_downstream(ngx_e
 
                 ngx_event_pipe_free_shadow_raw_buf(&p->free_raw_bufs, cl->buf);
 
-            } else if (!p->cachable && p->in) {
+            } else if (!p->cacheable && p->in) {
                 cl = p->in;
 
                 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, p->log, 0,
@@ -602,7 +610,13 @@ ngx_event_pipe_write_to_downstream(ngx_e
             break;
         }
 
-        if (p->output_filter(p->output_ctx, out) == NGX_ERROR) {
+        rc = p->output_filter(p->output_ctx, out);
+
+        if (downstream->destroyed) {
+            return NGX_ABORT;
+        }
+
+        if (rc == NGX_ERROR) {
             p->downstream_error = 1;
             return ngx_event_pipe_drain_chains(p);
         }
@@ -612,7 +626,7 @@ ngx_event_pipe_write_to_downstream(ngx_e
         for (cl = p->free; cl; cl = cl->next) {
 
             if (cl->buf->temp_file) {
-                if (p->cachable || !p->cyclic_temp_file) {
+                if (p->cacheable || !p->cyclic_temp_file) {
                     continue;
                 }
 
@@ -659,7 +673,7 @@ ngx_event_pipe_write_chain_to_temp_file(
         out = p->in;
     }
 
-    if (!p->cachable) {
+    if (!p->cacheable) {
 
         size = 0;
         cl = out;
--- a/src/event/ngx_event_pipe.h
+++ b/src/event/ngx_event_pipe.h
@@ -47,7 +47,7 @@ struct ngx_event_pipe_s {
     void                             *output_ctx;
 
     unsigned           read:1;
-    unsigned           cachable:1;
+    unsigned           cacheable:1;
     unsigned           single_buf:1;
     unsigned           free_bufs:1;
     unsigned           upstream_done:1;
--- a/src/http/modules/ngx_http_browser_module.c
+++ b/src/http/modules/ngx_http_browser_module.c
@@ -397,7 +397,7 @@ ngx_http_browser_add_variable(ngx_conf_t
 
     for (var = ngx_http_browsers; var->name.len; var++) {
 
-        v = ngx_http_add_variable(cf, &var->name, NGX_HTTP_VAR_CHANGABLE);
+        v = ngx_http_add_variable(cf, &var->name, NGX_HTTP_VAR_CHANGEABLE);
         if (v == NULL) {
             return NGX_ERROR;
         }
@@ -673,7 +673,7 @@ ngx_http_modern_browser_value(ngx_conf_t
 
     bcf->modern_browser_value->len = value[1].len;
     bcf->modern_browser_value->valid = 1;
-    bcf->modern_browser_value->no_cachable = 0;
+    bcf->modern_browser_value->no_cacheable = 0;
     bcf->modern_browser_value->not_found = 0;
     bcf->modern_browser_value->data = value[1].data;
 
@@ -698,7 +698,7 @@ ngx_http_ancient_browser_value(ngx_conf_
 
     bcf->ancient_browser_value->len = value[1].len;
     bcf->ancient_browser_value->valid = 1;
-    bcf->ancient_browser_value->no_cachable = 0;
+    bcf->ancient_browser_value->no_cacheable = 0;
     bcf->ancient_browser_value->not_found = 0;
     bcf->ancient_browser_value->data = value[1].data;
 
--- a/src/http/modules/ngx_http_charset_filter_module.c
+++ b/src/http/modules/ngx_http_charset_filter_module.c
@@ -366,8 +366,8 @@ ngx_http_charset_header_filter(ngx_http_
 no_charset_map:
 
     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
-                  "no \"charset_map\" between the charsets "
-                  "\"%V\" and \"%V\"", from, to);
+                  "no \"charset_map\" between the charsets \"%V\" and \"%V\"",
+                  from, to);
 
     return ngx_http_next_header_filter(r);
 }
@@ -1462,6 +1462,12 @@ ngx_http_charset_merge_loc_conf(ngx_conf
         return NGX_CONF_OK;
     }
 
+    if (conf->source_charset >= NGX_HTTP_CHARSET_VAR
+        || conf->charset >= NGX_HTTP_CHARSET_VAR)
+    {
+        return NGX_CONF_OK;
+    }
+
     mcf = ngx_http_conf_get_module_main_conf(cf,
                                              ngx_http_charset_filter_module);
     recode = mcf->recodes.elts;
@@ -1519,9 +1525,8 @@ ngx_http_charset_postconfiguration(ngx_c
         }
 
         ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
-                      " no \"charset_map\" between the charsets "
-                      "\"%V\" and \"%V\"",
-                      &charset[c].name, &charset[recode[i].dst].name);
+                   "no \"charset_map\" between the charsets \"%V\" and \"%V\"",
+                   &charset[c].name, &charset[recode[i].dst].name);
         return NGX_ERROR;
 
     next:
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -432,7 +432,7 @@ ngx_http_fastcgi_handler(ngx_http_reques
     if (r->subrequest_in_memory) {
         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
                       "ngx_http_fastcgi_module does not support "
-                      "subrequest in memeory");
+                      "subrequest in memory");
         return NGX_HTTP_INTERNAL_SERVER_ERROR;
     }
 
@@ -505,7 +505,7 @@ ngx_http_fastcgi_create_request(ngx_http
     if (flcf->params_len) {
         ngx_memzero(&le, sizeof(ngx_http_script_engine_t));
 
-        ngx_http_script_flush_no_cachable_variables(r, flcf->flushes);
+        ngx_http_script_flush_no_cacheable_variables(r, flcf->flushes);
         le.flushed = 1;
 
         le.ip = flcf->params_len->elts;
@@ -551,7 +551,7 @@ ngx_http_fastcgi_create_request(ngx_http
 
     if (len > 65535) {
         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
-                      "fastcgi: the request record is too big");
+                      "fastcgi request record is too big: %uz", len);
         return NGX_ERROR;
     }
 
@@ -1186,8 +1186,8 @@ ngx_http_fastcgi_process_header(ngx_http
 
                 u->state->status = u->headers_in.status_n;
 #if 0
-                if (u->cachable) {
-                    u->cachable = ngx_http_upstream_is_cachable(r);
+                if (u->cacheable) {
+                    u->cacheable = ngx_http_upstream_is_cacheable(r);
                 }
 #endif
 
@@ -1610,7 +1610,7 @@ ngx_http_fastcgi_add_variables(ngx_conf_
     ngx_http_variable_t  *var;
 
     var = ngx_http_add_variable(cf, &ngx_http_fastcgi_script_name,
-                                NGX_HTTP_VAR_NOHASH|NGX_HTTP_VAR_NOCACHABLE);
+                                NGX_HTTP_VAR_NOHASH|NGX_HTTP_VAR_NOCACHEABLE);
     if (var == NULL) {
         return NGX_ERROR;
     }
@@ -2104,7 +2104,7 @@ ngx_http_fastcgi_script_name_variable(ng
 
     if (r->uri.len) {
         v->valid = 1;
-        v->no_cachable = 0;
+        v->no_cacheable = 0;
         v->not_found = 0;
 
         flcf = ngx_http_get_module_loc_conf(r, ngx_http_fastcgi_module);
@@ -2128,7 +2128,7 @@ ngx_http_fastcgi_script_name_variable(ng
     } else {
         v->len = 0;
         v->valid = 1;
-        v->no_cachable = 0;
+        v->no_cacheable = 0;
         v->not_found = 0;
         v->data = NULL;
 
@@ -2215,7 +2215,7 @@ ngx_http_fastcgi_store(ngx_conf_t *cf, n
     sc.source = &value[1];
     sc.lengths = &flcf->upstream.store_lengths;
     sc.values = &flcf->upstream.store_values;
-    sc.variables = ngx_http_script_variables_count(&value[1]);;
+    sc.variables = ngx_http_script_variables_count(&value[1]);
     sc.complete_lengths = 1;
     sc.complete_values = 1;
 
--- a/src/http/modules/ngx_http_geo_module.c
+++ b/src/http/modules/ngx_http_geo_module.c
@@ -116,7 +116,7 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_c
         name.data++;
     }
 
-    var = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGABLE);
+    var = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGEABLE);
     if (var == NULL) {
         return NGX_CONF_ERROR;
     }
@@ -257,7 +257,7 @@ ngx_http_geo(ngx_conf_t *cf, ngx_command
         }
 
         var->valid = 1;
-        var->no_cachable = 0;
+        var->no_cacheable = 0;
         var->not_found = 0;
 
         v = ngx_array_push(&ctx->values);
--- a/src/http/modules/ngx_http_gzip_filter_module.c
+++ b/src/http/modules/ngx_http_gzip_filter_module.c
@@ -14,6 +14,7 @@
 typedef struct {
     ngx_flag_t           enable;
     ngx_flag_t           no_buffer;
+    ngx_flag_t           vary;
 
     ngx_array_t         *types;     /* array of ngx_str_t */
 
@@ -192,6 +193,13 @@ static ngx_command_t  ngx_http_gzip_filt
       offsetof(ngx_http_gzip_conf_t, min_length),
       NULL },
 
+    { ngx_string("gzip_vary"),
+      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, vary),
+      NULL },
+
       ngx_null_command
 };
 
@@ -261,6 +269,7 @@ ngx_http_gzip_header_filter(ngx_http_req
 {
     ngx_str_t             *type;
     ngx_uint_t             i;
+    ngx_table_elt_t       *header;
     ngx_http_gzip_ctx_t   *ctx;
     ngx_http_gzip_conf_t  *conf;
 
@@ -336,16 +345,31 @@ found:
 
     ctx->request = r;
 
-    r->headers_out.content_encoding = ngx_list_push(&r->headers_out.headers);
-    if (r->headers_out.content_encoding == NULL) {
+    header = ngx_list_push(&r->headers_out.headers);
+    if (header == NULL) {
         return NGX_ERROR;
     }
 
-    r->headers_out.content_encoding->hash = 1;
-    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";
+    header->hash = 1;
+    header->key.len = sizeof("Content-Encoding") - 1;
+    header->key.data = (u_char *) "Content-Encoding";
+    header->value.len = sizeof("gzip") - 1;
+    header->value.data = (u_char *) "gzip";
+
+    r->headers_out.content_encoding = header;
+
+    if (conf->vary) {
+        header = ngx_list_push(&r->headers_out.headers);
+        if (header == NULL) {
+            return NGX_ERROR;
+        }
+
+        header->hash = 1;
+        header->key.len = sizeof("Vary") - 1;
+        header->key.data = (u_char *) "Vary";
+        header->value.len = sizeof("Accept-Encoding") - 1;
+        header->value.data = (u_char *) "Accept-Encoding";
+    }
 
     ctx->length = r->headers_out.content_length_n;
 
@@ -813,12 +837,15 @@ ngx_http_gzip_body_filter(ngx_http_reque
             }
         }
 
-        if (last == NGX_AGAIN && !ctx->done) {
-            return NGX_AGAIN;
-        }
+        if (ctx->out == NULL) {
 
-        if (ctx->out == NULL && ctx->busy == NULL) {
-            return NGX_OK;
+            if (last == NGX_AGAIN) {
+                return NGX_AGAIN;
+            }
+
+            if (ctx->busy == NULL) {
+                return NGX_OK;
+            }
         }
 
         last = ngx_http_next_body_filter(r, ctx->out);
@@ -940,7 +967,7 @@ ngx_http_gzip_ratio_variable(ngx_http_re
     ngx_http_gzip_ctx_t  *ctx;
 
     v->valid = 1;
-    v->no_cachable = 0;
+    v->no_cacheable = 0;
     v->not_found = 0;
 
     ctx = ngx_http_get_module_ctx(r, ngx_http_gzip_filter_module);
@@ -996,6 +1023,7 @@ ngx_http_gzip_create_conf(ngx_conf_t *cf
 
     conf->enable = NGX_CONF_UNSET;
     conf->no_buffer = NGX_CONF_UNSET;
+    conf->vary = NGX_CONF_UNSET;
 
     conf->http_version = NGX_CONF_UNSET_UINT;
 
@@ -1031,6 +1059,7 @@ ngx_http_gzip_merge_conf(ngx_conf_t *cf,
                               MAX_MEM_LEVEL - 1);
     ngx_conf_merge_value(conf->min_length, prev->min_length, 20);
     ngx_conf_merge_value(conf->no_buffer, prev->no_buffer, 0);
+    ngx_conf_merge_value(conf->vary, prev->vary, 0);
 
     if (conf->types == NULL) {
         if (prev->types == NULL) {
--- a/src/http/modules/ngx_http_log_module.c
+++ b/src/http/modules/ngx_http_log_module.c
@@ -114,7 +114,7 @@ static ngx_command_t  ngx_http_log_comma
 
     { ngx_string("access_log"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
-                        |NGX_CONF_TAKE123,
+                        |NGX_HTTP_LMT_CONF|NGX_CONF_TAKE123,
       ngx_http_log_set_log,
       NGX_HTTP_LOC_CONF_OFFSET,
       0,
--- a/src/http/modules/ngx_http_map_module.c
+++ b/src/http/modules/ngx_http_map_module.c
@@ -221,7 +221,7 @@ ngx_http_map_block(ngx_conf_t *cf, ngx_c
     name.len--;
     name.data++;
 
-    var = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGABLE);
+    var = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGEABLE);
     if (var == NULL) {
         return NGX_CONF_ERROR;
     }
@@ -430,7 +430,7 @@ ngx_http_map(ngx_conf_t *cf, ngx_command
     }
 
     var->valid = 1;
-    var->no_cachable = 0;
+    var->no_cacheable = 0;
     var->not_found = 0;
 
     vp = ngx_array_push(&ctx->values_hash[key]);
--- a/src/http/modules/ngx_http_memcached_module.c
+++ b/src/http/modules/ngx_http_memcached_module.c
@@ -371,6 +371,7 @@ found:
         }
 
         u->headers_in.status_n = 200;
+        u->state->status = 200;
         u->buffer.pos = p + 1;
 
         return NGX_OK;
@@ -381,6 +382,7 @@ found:
                       "key: \"%V\" was not found by memcached", &ctx->key);
 
         u->headers_in.status_n = 404;
+        u->state->status = 404;
 
         return NGX_OK;
     }
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -420,10 +420,10 @@ static ngx_str_t  ngx_http_proxy_hide_he
 static ngx_http_variable_t  ngx_http_proxy_vars[] = {
 
     { ngx_string("proxy_host"), NULL, ngx_http_proxy_host_variable, 0,
-      NGX_HTTP_VAR_CHANGABLE|NGX_HTTP_VAR_NOHASH, 0 },
+      NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOHASH, 0 },
 
     { ngx_string("proxy_port"), NULL, ngx_http_proxy_port_variable, 0,
-      NGX_HTTP_VAR_CHANGABLE|NGX_HTTP_VAR_NOHASH, 0 },
+      NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOHASH, 0 },
 
     { ngx_string("proxy_add_x_forwarded_for"), NULL,
       ngx_http_proxy_add_x_forwarded_for_variable, 0, NGX_HTTP_VAR_NOHASH, 0 },
@@ -561,7 +561,7 @@ ngx_http_proxy_create_request(ngx_http_r
         len += r->uri.len - loc_len + escape + sizeof("?") - 1 + r->args.len;
     }
 
-    ngx_http_script_flush_no_cachable_variables(r, plcf->flushes);
+    ngx_http_script_flush_no_cacheable_variables(r, plcf->flushes);
 
     if (plcf->body_set_len) {
         le.ip = plcf->body_set_len->elts;
@@ -1249,7 +1249,7 @@ ngx_http_proxy_host_variable(ngx_http_re
 
     v->len = plcf->host_header.len;
     v->valid = 1;
-    v->no_cachable = 0;
+    v->no_cacheable = 0;
     v->not_found = 0;
     v->data = plcf->host_header.data;
 
@@ -1267,7 +1267,7 @@ ngx_http_proxy_port_variable(ngx_http_re
 
     v->len = plcf->port.len;
     v->valid = 1;
-    v->no_cachable = 0;
+    v->no_cacheable = 0;
     v->not_found = 0;
     v->data = plcf->port.data;
 
@@ -1282,7 +1282,7 @@ ngx_http_proxy_add_x_forwarded_for_varia
     u_char  *p;
 
     v->valid = 1;
-    v->no_cachable = 0;
+    v->no_cacheable = 0;
     v->not_found = 0;
 
     if (r->headers_in.x_forwarded_for == NULL) {
@@ -1326,7 +1326,7 @@ ngx_http_proxy_internal_body_length_vari
     }
 
     v->valid = 1;
-    v->no_cachable = 0;
+    v->no_cacheable = 0;
     v->not_found = 0;
 
     v->data = ngx_palloc(r->connection->pool, NGX_SIZE_T_LEN);
@@ -2429,7 +2429,7 @@ ngx_http_proxy_store(ngx_conf_t *cf, ngx
     sc.source = &value[1];
     sc.lengths = &plcf->upstream.store_lengths;
     sc.values = &plcf->upstream.store_values;
-    sc.variables = ngx_http_script_variables_count(&value[1]);;
+    sc.variables = ngx_http_script_variables_count(&value[1]);
     sc.complete_lengths = 1;
     sc.complete_values = 1;
 
--- a/src/http/modules/ngx_http_referer_module.c
+++ b/src/http/modules/ngx_http_referer_module.c
@@ -367,7 +367,7 @@ ngx_http_valid_referers(ngx_conf_t *cf, 
     name.data = (u_char *) "invalid_referer";
 
     var = ngx_http_add_variable(cf, &name,
-                                NGX_HTTP_VAR_CHANGABLE|NGX_HTTP_VAR_NOHASH);
+                                NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOHASH);
     if (var == NULL) {
         return NGX_CONF_ERROR;
     }
--- a/src/http/modules/ngx_http_rewrite_module.c
+++ b/src/http/modules/ngx_http_rewrite_module.c
@@ -924,7 +924,7 @@ ngx_http_rewrite_set(ngx_conf_t *cf, ngx
     value[1].len--;
     value[1].data++;
 
-    v = ngx_http_add_variable(cf, &value[1], NGX_HTTP_VAR_CHANGABLE);
+    v = ngx_http_add_variable(cf, &value[1], NGX_HTTP_VAR_CHANGEABLE);
     if (v == NULL) {
         return NGX_CONF_ERROR;
     }
--- a/src/http/modules/ngx_http_ssi_filter_module.c
+++ b/src/http/modules/ngx_http_ssi_filter_module.c
@@ -303,10 +303,10 @@ static ngx_http_ssi_command_t  ngx_http_
 static ngx_http_variable_t  ngx_http_ssi_vars[] = {
 
     { ngx_string("date_local"), NULL, ngx_http_ssi_date_gmt_local_variable, 0,
-      NGX_HTTP_VAR_NOCACHABLE, 0 },
+      NGX_HTTP_VAR_NOCACHEABLE, 0 },
 
     { ngx_string("date_gmt"), NULL, ngx_http_ssi_date_gmt_local_variable, 1,
-      NGX_HTTP_VAR_NOCACHABLE, 0 },
+      NGX_HTTP_VAR_NOCACHEABLE, 0 },
 
     { ngx_null_string, NULL, NULL, 0, 0, 0 }
 };
@@ -1858,6 +1858,8 @@ static ngx_int_t
 ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
     ngx_str_t **params)
 {
+    u_char                      *dst, *src;
+    size_t                       len;
     ngx_int_t                    rc, key;
     ngx_str_t                   *uri, *file, *wait, *set, *stub, args;
     ngx_buf_t                   *b;
@@ -1927,13 +1929,25 @@ ngx_http_ssi_include(ngx_http_request_t 
         return rc;
     }
 
+    dst = uri->data;
+    src = uri->data;
+
+    ngx_unescape_uri(&dst, &src, uri->len, NGX_UNESCAPE_URI);
+
+    len = (uri->data + uri->len) - src;
+    if (len) {
+        dst = ngx_copy(dst, src, len);
+    }
+
+    uri->len = dst - uri->data;
+
+    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                   "ssi include: \"%V\"", uri);
+
     args.len = 0;
     args.data = NULL;
     flags = 0;
 
-    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                   "ssi include: \"%V\"", uri);
-
     if (ngx_http_parse_unsafe_uri(r, uri, &args, &flags) != NGX_OK) {
         return NGX_HTTP_SSI_ERROR;
     }
@@ -2641,15 +2655,16 @@ ngx_http_ssi_date_gmt_local_variable(ngx
     char                 buf[NGX_HTTP_SSI_DATE_LEN];
 
     v->valid = 1;
-    v->no_cachable = 0;
+    v->no_cacheable = 0;
     v->not_found = 0;
 
     tp = ngx_timeofday();
 
     ctx = ngx_http_get_module_ctx(r, ngx_http_ssi_filter_module);
 
-    if (ctx->timefmt.len == sizeof("%s") - 1
-        && ctx->timefmt.data[0] == '%' && ctx->timefmt.data[1] == 's')
+    if (ctx == NULL
+        || (ctx->timefmt.len == sizeof("%s") - 1
+            && ctx->timefmt.data[0] == '%' && ctx->timefmt.data[1] == 's'))
     {
         v->data = ngx_palloc(r->pool, NGX_TIME_T_LEN);
         if (v->data == NULL) {
--- a/src/http/modules/ngx_http_ssl_module.c
+++ b/src/http/modules/ngx_http_ssl_module.c
@@ -170,19 +170,19 @@ ngx_module_t  ngx_http_ssl_module = {
 static ngx_http_variable_t  ngx_http_ssl_vars[] = {
 
     { ngx_string("ssl_protocol"), NULL, ngx_http_ssl_static_variable,
-      (uintptr_t) ngx_ssl_get_protocol, NGX_HTTP_VAR_CHANGABLE, 0 },
+      (uintptr_t) ngx_ssl_get_protocol, NGX_HTTP_VAR_CHANGEABLE, 0 },
 
     { ngx_string("ssl_cipher"), NULL, ngx_http_ssl_static_variable,
-      (uintptr_t) ngx_ssl_get_cipher_name, NGX_HTTP_VAR_CHANGABLE, 0 },
+      (uintptr_t) ngx_ssl_get_cipher_name, NGX_HTTP_VAR_CHANGEABLE, 0 },
 
     { ngx_string("ssl_client_s_dn"), NULL, ngx_http_ssl_variable,
-      (uintptr_t) ngx_ssl_get_subject_dn, NGX_HTTP_VAR_CHANGABLE, 0 },
+      (uintptr_t) ngx_ssl_get_subject_dn, NGX_HTTP_VAR_CHANGEABLE, 0 },
 
     { ngx_string("ssl_client_i_dn"), NULL, ngx_http_ssl_variable,
-      (uintptr_t) ngx_ssl_get_issuer_dn, NGX_HTTP_VAR_CHANGABLE, 0 },
+      (uintptr_t) ngx_ssl_get_issuer_dn, NGX_HTTP_VAR_CHANGEABLE, 0 },
 
     { ngx_string("ssl_client_serial"), NULL, ngx_http_ssl_variable,
-      (uintptr_t) ngx_ssl_get_serial_number, NGX_HTTP_VAR_CHANGABLE, 0 },
+      (uintptr_t) ngx_ssl_get_serial_number, NGX_HTTP_VAR_CHANGEABLE, 0 },
 
     { ngx_null_string, NULL, NULL, 0, 0, 0 }
 };
@@ -210,7 +210,7 @@ ngx_http_ssl_static_variable(ngx_http_re
 
         v->len = len;
         v->valid = 1;
-        v->no_cachable = 0;
+        v->no_cacheable = 0;
         v->not_found = 0;
 
         return NGX_OK;
@@ -241,7 +241,7 @@ ngx_http_ssl_variable(ngx_http_request_t
 
         if (v->len) {
             v->valid = 1;
-            v->no_cachable = 0;
+            v->no_cacheable = 0;
             v->not_found = 0;
 
             return NGX_OK;
--- a/src/http/modules/ngx_http_stub_status_module.c
+++ b/src/http/modules/ngx_http_stub_status_module.c
@@ -129,7 +129,7 @@ static ngx_int_t ngx_http_status_handler
         return rc;
     }
 
-    return ngx_http_output_filter(r, &out);;
+    return ngx_http_output_filter(r, &out);
 }
 
 
--- a/src/http/modules/ngx_http_userid_filter_module.c
+++ b/src/http/modules/ngx_http_userid_filter_module.c
@@ -493,7 +493,7 @@ ngx_http_userid_variable(ngx_http_reques
     }
 
     v->valid = 1;
-    v->no_cachable = 0;
+    v->no_cacheable = 0;
     v->not_found = 0;
 
     ngx_sprintf(v->data, "%V=%08XD%08XD%08XD%08XD",
--- 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.5.33';
+our $VERSION = '0.5.34';
 
 require XSLoader;
 XSLoader::load('nginx', $VERSION);
--- a/src/http/modules/perl/nginx.xs
+++ b/src/http/modules/perl/nginx.xs
@@ -912,7 +912,7 @@ variable(r, name, value = NULL)
     if (value) {
         vv->len = val.len;
         vv->valid = 1;
-        vv->no_cachable = 0;
+        vv->no_cacheable = 0;
         vv->not_found = 0;
         vv->data = val.data;
 
--- a/src/http/modules/perl/ngx_http_perl_module.c
+++ b/src/http/modules/perl/ngx_http_perl_module.c
@@ -336,7 +336,7 @@ ngx_http_perl_variable(ngx_http_request_
     if (value.data) {
         v->len = value.len;
         v->valid = 1;
-        v->no_cachable = 0;
+        v->no_cacheable = 0;
         v->not_found = 0;
         v->data = value.data;
 
@@ -954,7 +954,7 @@ ngx_http_perl_set(ngx_conf_t *cf, ngx_co
     value[1].len--;
     value[1].data++;
 
-    v = ngx_http_add_variable(cf, &value[1], NGX_HTTP_VAR_CHANGABLE);
+    v = ngx_http_add_variable(cf, &value[1], NGX_HTTP_VAR_CHANGEABLE);
     if (v == NULL) {
         return NGX_CONF_ERROR;
     }
--- a/src/http/ngx_http.h
+++ b/src/http/ngx_http.h
@@ -64,7 +64,8 @@ int ngx_http_ssl_servername(ngx_ssl_conn
 #endif
 
 ngx_int_t ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b);
-ngx_int_t ngx_http_parse_complex_uri(ngx_http_request_t *r);
+ngx_int_t ngx_http_parse_complex_uri(ngx_http_request_t *r,
+    ngx_uint_t merge_slashes);
 ngx_int_t ngx_http_parse_unsafe_uri(ngx_http_request_t *r, ngx_str_t *uri,
     ngx_str_t *args, ngx_uint_t *flags);
 ngx_int_t ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b);
@@ -112,9 +113,4 @@ extern ngx_http_output_header_filter_pt 
 extern ngx_http_output_body_filter_pt    ngx_http_top_body_filter;
 
 
-/* STUB */
-ngx_int_t ngx_http_log_handler(ngx_http_request_t *r);
-/**/
-
-
 #endif /* _NGX_HTTP_H_INCLUDED_ */
--- a/src/http/ngx_http_busy_lock.c
+++ b/src/http/ngx_http_busy_lock.c
@@ -10,9 +10,9 @@
 
 
 
-static int ngx_http_busy_lock_look_cachable(ngx_http_busy_lock_t *bl,
-                                            ngx_http_busy_lock_ctx_t *bc,
-                                            int lock);
+static int ngx_http_busy_lock_look_cacheable(ngx_http_busy_lock_t *bl,
+                                             ngx_http_busy_lock_ctx_t *bc,
+                                             int lock);
 
 
 int ngx_http_busy_lock(ngx_http_busy_lock_t *bl, ngx_http_busy_lock_ctx_t *bc)
@@ -60,12 +60,12 @@ int ngx_http_busy_lock(ngx_http_busy_loc
 }
 
 
-int ngx_http_busy_lock_cachable(ngx_http_busy_lock_t *bl,
-                                ngx_http_busy_lock_ctx_t *bc, int lock)
+int ngx_http_busy_lock_cacheable(ngx_http_busy_lock_t *bl,
+                                 ngx_http_busy_lock_ctx_t *bc, int lock)
 {
     int  rc;
 
-    rc = ngx_http_busy_lock_look_cachable(bl, bc, lock);
+    rc = ngx_http_busy_lock_look_cacheable(bl, bc, lock);
 
     ngx_log_debug3(NGX_LOG_DEBUG_HTTP, bc->event->log, 0,
                    "http busylock: %d w:%d mw::%d",
@@ -121,22 +121,22 @@ void ngx_http_busy_unlock(ngx_http_busy_
 
     if (bl->md5) {
         bl->md5_mask[bc->slot / 8] &= ~(1 << (bc->slot & 7));
-        bl->cachable--;
+        bl->cacheable--;
     }
 
     bl->busy--;
 }
 
 
-static int ngx_http_busy_lock_look_cachable(ngx_http_busy_lock_t *bl,
-                                            ngx_http_busy_lock_ctx_t *bc,
-                                            int lock)
+static int ngx_http_busy_lock_look_cacheable(ngx_http_busy_lock_t *bl,
+                                             ngx_http_busy_lock_ctx_t *bc,
+                                             int lock)
 {
-    int    i, b, cachable, free;
+    int    i, b, cacheable, free;
     u_int  mask;
 
     b = 0;
-    cachable = 0;
+    cacheable = 0;
     free = -1;
 
 #if (NGX_SUPPRESS_WARN)
@@ -153,15 +153,15 @@ static int ngx_http_busy_lock_look_cacha
             if (ngx_memcmp(&bl->md5[i * 16], bc->md5, 16) == 0) {
                 return NGX_AGAIN;
             }
-            cachable++;
+            cacheable++;
 
         } else if (free == -1) {
             free = i;
         }
 
 #if 1
-        if (cachable == bl->cachable) {
-            if (free == -1 && cachable < bl->max_busy) {
+        if (cacheable == bl->cacheable) {
+            if (free == -1 && cacheable < bl->max_busy) {
                 free = i + 1;
             }
 
@@ -186,7 +186,7 @@ static int ngx_http_busy_lock_look_cacha
         bl->md5_mask[free / 8] |= 1 << (free & 7);
         bc->slot = free;
 
-        bl->cachable++;
+        bl->cacheable++;
         bl->busy++;
     }
 
--- a/src/http/ngx_http_busy_lock.h
+++ b/src/http/ngx_http_busy_lock.h
@@ -17,7 +17,7 @@
 typedef struct {
     u_char             *md5_mask;
     char               *md5;
-    int                 cachable;
+    int                 cacheable;
 
     int                 busy;
     int                 max_busy;
@@ -41,8 +41,8 @@ typedef struct {
 
 
 int ngx_http_busy_lock(ngx_http_busy_lock_t *bl, ngx_http_busy_lock_ctx_t *bc);
-int ngx_http_busy_lock_cachable(ngx_http_busy_lock_t *bl,
-                                ngx_http_busy_lock_ctx_t *bc, int lock);
+int ngx_http_busy_lock_cacheable(ngx_http_busy_lock_t *bl,
+                                 ngx_http_busy_lock_ctx_t *bc, int lock);
 void ngx_http_busy_unlock(ngx_http_busy_lock_t *bl,
                           ngx_http_busy_lock_ctx_t *bc);
 
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -183,6 +183,13 @@ static ngx_command_t  ngx_http_core_comm
       offsetof(ngx_http_core_srv_conf_t, ignore_invalid_headers),
       NULL },
 
+    { ngx_string("merge_slashes"),
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
+      ngx_conf_set_flag_slot,
+      NGX_HTTP_SRV_CONF_OFFSET,
+      offsetof(ngx_http_core_srv_conf_t, merge_slashes),
+      NULL },
+
     { ngx_string("location"),
       NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE12,
       ngx_http_core_location,
@@ -425,6 +432,13 @@ static ngx_command_t  ngx_http_core_comm
       offsetof(ngx_http_core_loc_conf_t, recursive_error_pages),
       NULL },
 
+    { ngx_string("server_tokens"),
+      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_core_loc_conf_t, server_tokens),
+      NULL },
+
     { ngx_string("error_page"),
       NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
                         |NGX_CONF_2MORE,
@@ -662,7 +676,7 @@ ngx_http_core_find_config_phase(ngx_http
         && clcf->client_max_body_size < r->headers_in.content_length_n)
     {
         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
-                      "client intented to send too large body: %O bytes",
+                      "client intended to send too large body: %O bytes",
                       r->headers_in.content_length_n);
 
         ngx_http_finalize_request(r, NGX_HTTP_REQUEST_ENTITY_TOO_LARGE);
@@ -1578,7 +1592,7 @@ ngx_http_named_location(ngx_http_request
     }
 
     ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
-                  "could not find name location \"%V\"", name);
+                  "could not find named location \"%V\"", name);
 
     ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
     return NGX_DONE;
@@ -2213,6 +2227,7 @@ ngx_http_core_create_srv_conf(ngx_conf_t
     cscf->client_header_buffer_size = NGX_CONF_UNSET_SIZE;
     cscf->optimize_server_names = NGX_CONF_UNSET;
     cscf->ignore_invalid_headers = NGX_CONF_UNSET;
+    cscf->merge_slashes = NGX_CONF_UNSET;
 
     return cscf;
 }
@@ -2305,6 +2320,8 @@ ngx_http_core_merge_srv_conf(ngx_conf_t 
     ngx_conf_merge_value(conf->ignore_invalid_headers,
                               prev->ignore_invalid_headers, 1);
 
+    ngx_conf_merge_value(conf->merge_slashes, prev->merge_slashes, 1);
+
     return NGX_CONF_OK;
 }
 
@@ -2360,6 +2377,7 @@ ngx_http_core_create_loc_conf(ngx_conf_t
     lcf->msie_refresh = NGX_CONF_UNSET;
     lcf->log_not_found = NGX_CONF_UNSET;
     lcf->recursive_error_pages = NGX_CONF_UNSET;
+    lcf->server_tokens = NGX_CONF_UNSET;
     lcf->types_hash_max_size = NGX_CONF_UNSET_UINT;
     lcf->types_hash_bucket_size = NGX_CONF_UNSET_UINT;
 
@@ -2544,6 +2562,7 @@ ngx_http_core_merge_loc_conf(ngx_conf_t 
     ngx_conf_merge_value(conf->log_not_found, prev->log_not_found, 1);
     ngx_conf_merge_value(conf->recursive_error_pages,
                               prev->recursive_error_pages, 0);
+    ngx_conf_merge_value(conf->server_tokens, prev->server_tokens, 1);
 
     if (conf->open_files == NULL) {
         conf->open_files = prev->open_files;
@@ -2578,7 +2597,7 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx
     u.listen = 1;
     u.default_port = 80;
 
-    if (ngx_parse_url(cf, &u) != NGX_OK) {
+    if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
         if (u.err) {
             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                "%s in \"%V\" of the \"listen\" directive",
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -143,6 +143,7 @@ typedef struct {
 
     ngx_flag_t                 optimize_server_names;
     ngx_flag_t                 ignore_invalid_headers;
+    ngx_flag_t                 merge_slashes;
 } ngx_http_core_srv_conf_t;
 
 
@@ -284,6 +285,7 @@ struct ngx_http_core_loc_conf_s {
     ngx_flag_t    msie_refresh;            /* msie_refresh */
     ngx_flag_t    log_not_found;           /* log_not_found */
     ngx_flag_t    recursive_error_pages;   /* recursive_error_pages */
+    ngx_flag_t    server_tokens;           /* server_tokens */
 
     ngx_array_t  *error_pages;             /* error_page */
 
--- a/src/http/ngx_http_header_filter_module.c
+++ b/src/http/ngx_http_header_filter_module.c
@@ -45,7 +45,8 @@ ngx_module_t  ngx_http_header_filter_mod
 };
 
 
-static char ngx_http_server_string[] = "Server: " NGINX_VER CRLF;
+static char ngx_http_server_string[] = "Server: nginx" CRLF;
+static char ngx_http_server_full_string[] = "Server: " NGINX_VER CRLF;
 
 
 static ngx_str_t ngx_http_status_lines[] = {
@@ -237,8 +238,11 @@ ngx_http_header_filter(ngx_http_request_
         len += ngx_http_status_lines[status].len;
     }
 
+    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
     if (r->headers_out.server == NULL) {
-        len += sizeof(ngx_http_server_string) - 1;
+        len += clcf->server_tokens ? sizeof(ngx_http_server_full_string) - 1:
+                                     sizeof(ngx_http_server_string) - 1;
     }
 
     if (r->headers_out.date == NULL) {
@@ -268,8 +272,6 @@ ngx_http_header_filter(ngx_http_request_
         len += sizeof("Last-Modified: Mon, 28 Sep 1970 06:00:00 GMT" CRLF) - 1;
     }
 
-    clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-
     if (r->headers_out.location
         && r->headers_out.location->value.len
         && r->headers_out.location->value.data[0] == '/')
@@ -365,8 +367,16 @@ ngx_http_header_filter(ngx_http_request_
     *b->last++ = CR; *b->last++ = LF;
 
     if (r->headers_out.server == NULL) {
-        b->last = ngx_cpymem(b->last, ngx_http_server_string,
-                             sizeof(ngx_http_server_string) - 1);
+        if (clcf->server_tokens) {
+            p = (u_char *) ngx_http_server_full_string;
+            len = sizeof(ngx_http_server_full_string) - 1;
+
+        } else {
+            p = (u_char *) ngx_http_server_string;
+            len = sizeof(ngx_http_server_string) - 1;
+        }
+
+        b->last = ngx_cpymem(b->last, p, len);
     }
 
     if (r->headers_out.date == NULL) {
--- a/src/http/ngx_http_parse.c
+++ b/src/http/ngx_http_parse.c
@@ -124,6 +124,7 @@ ngx_http_parse_request_line(ngx_http_req
         sw_major_digit,
         sw_first_minor_digit,
         sw_minor_digit,
+        sw_spaces_after_digit,
         sw_almost_done
     } state;
 
@@ -335,18 +336,26 @@ ngx_http_parse_request_line(ngx_http_req
                 break;
             }
 
+            r->host_end = p;
+
             switch (ch) {
             case ':':
-                r->host_end = p;
                 state = sw_port;
                 break;
             case '/':
-                r->host_end = p;
                 r->uri_start = p;
                 state = sw_after_slash_in_uri;
                 break;
+            case ' ':
+                /*
+                 * use single "/" from request line to preserve pointers,
+                 * if request line will be copied to large client buffer
+                 */
+                r->uri_start = r->schema_end + 1;
+                r->uri_end = r->schema_end + 2;
+                state = sw_http_09;
+                break;
             default:
-                r->host_end = p;
                 return NGX_HTTP_PARSE_INVALID_REQUEST;
             }
             break;
@@ -362,6 +371,16 @@ ngx_http_parse_request_line(ngx_http_req
                 r->uri_start = p;
                 state = sw_after_slash_in_uri;
                 break;
+            case ' ':
+                r->port_end = p;
+                /*
+                 * use single "/" from request line to preserve pointers,
+                 * if request line will be copied to large client buffer
+                 */
+                r->uri_start = r->schema_end + 1;
+                r->uri_end = r->schema_end + 2;
+                state = sw_http_09;
+                break;
             default:
                 return NGX_HTTP_PARSE_INVALID_REQUEST;
             }
@@ -618,6 +637,11 @@ ngx_http_parse_request_line(ngx_http_req
                 goto done;
             }
 
+            if (ch == ' ') {
+                state = sw_spaces_after_digit;
+                break;
+            }
+
             if (ch < '0' || ch > '9') {
                 return NGX_HTTP_PARSE_INVALID_REQUEST;
             }
@@ -625,6 +649,20 @@ ngx_http_parse_request_line(ngx_http_req
             r->http_minor = r->http_minor * 10 + ch - '0';
             break;
 
+        case sw_spaces_after_digit:
+            switch (ch) {
+            case ' ':
+                break;
+            case CR:
+                state = sw_almost_done;
+                break;
+            case LF:
+                goto done;
+            default:
+                return NGX_HTTP_PARSE_INVALID_REQUEST;
+            }
+            break;
+
         /* end of request line */
         case sw_almost_done:
             r->request_end = p - 1;
@@ -890,7 +928,7 @@ header_done:
 
 
 ngx_int_t
-ngx_http_parse_complex_uri(ngx_http_request_t *r)
+ngx_http_parse_complex_uri(ngx_http_request_t *r, ngx_uint_t merge_slashes)
 {
     u_char  c, ch, decoded, *p, *u;
     enum {
@@ -998,8 +1036,12 @@ ngx_http_parse_complex_uri(ngx_http_requ
             switch(ch) {
 #if (NGX_WIN32)
             case '\\':
+                break;
 #endif
             case '/':
+                if (merge_slashes) {
+                    *u++ = ch;
+                }
                 break;
             case '.':
                 state = sw_dot;
--- a/src/http/ngx_http_parse_time.c
+++ b/src/http/ngx_http_parse_time.c
@@ -11,7 +11,8 @@
 
 static int mday[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
 
-time_t ngx_http_parse_time(u_char *value, size_t len)
+time_t
+ngx_http_parse_time(u_char *value, size_t len)
 {
     u_char  *p, *end;
     int      day, month, year, hour, min, sec;
@@ -247,7 +248,7 @@ time_t ngx_http_parse_time(u_char *value
         year -= 1;
     }
 
-    /* Gauss's formula for Grigorian days from 1 March 1 BC */
+    /* Gauss's formula for Grigorian days from March 1, 1 BC */
 
     return (365 * year + year / 4 - year / 100 + year / 400
             + 367 * month / 12 - 31
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -603,10 +603,11 @@ ngx_http_ssl_servername(ngx_ssl_conn_t *
 static void
 ngx_http_process_request_line(ngx_event_t *rev)
 {
-    ssize_t              n;
-    ngx_int_t            rc, rv;
-    ngx_connection_t    *c;
-    ngx_http_request_t  *r;
+    ssize_t                    n;
+    ngx_int_t                  rc, rv;
+    ngx_connection_t          *c;
+    ngx_http_request_t        *r;
+    ngx_http_core_srv_conf_t  *cscf;
 
     c = rev->data;
     r = c->data;
@@ -658,7 +659,9 @@ ngx_http_process_request_line(ngx_event_
                     return;
                 }
 
-                rc = ngx_http_parse_complex_uri(r);
+                cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
+
+                rc = ngx_http_parse_complex_uri(r, cscf->merge_slashes);
 
                 if (rc == NGX_HTTP_PARSE_INVALID_REQUEST) {
                     ngx_log_error(NGX_LOG_INFO, c->log, 0,
@@ -1148,6 +1151,10 @@ ngx_http_alloc_large_header_buffer(ngx_h
             r->args_start = new + (r->args_start - old);
         }
 
+        if (r->http_protocol.data) {
+            r->http_protocol.data = new + (r->http_protocol.data - old);
+        }
+
     } else {
         r->header_name_start = new;
         r->header_name_end = new + (r->header_name_end - old);
@@ -1329,13 +1336,6 @@ ngx_http_process_request_header(ngx_http
         return NGX_ERROR;
     }
 
-    if (r->plain_http) {
-        ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
-                      "client sent plain HTTP request to HTTPS port");
-        ngx_http_finalize_request(r, NGX_HTTP_TO_HTTPS);
-        return NGX_ERROR;
-    }
-
     if (r->headers_in.connection_type == NGX_HTTP_CONNECTION_KEEP_ALIVE) {
         if (r->headers_in.keep_alive) {
             r->headers_in.keep_alive_n =
@@ -1403,6 +1403,13 @@ ngx_http_process_request(ngx_http_reques
 
     c = r->connection;
 
+    if (r->plain_http) {
+        ngx_log_error(NGX_LOG_INFO, c->log, 0,
+                      "client sent plain HTTP request to HTTPS port");
+        ngx_http_finalize_request(r, NGX_HTTP_TO_HTTPS);
+        return;
+    }
+
 #if (NGX_HTTP_SSL)
 
     if (c->ssl) {
@@ -2596,28 +2603,21 @@ ngx_http_log_error_handler(ngx_http_requ
         buf = p;
     }
 
-    if (r->unparsed_uri.data) {
-        p = ngx_snprintf(buf, len, ", URL: \"%V\"", &r->unparsed_uri);
+    if (r->request_line.data == NULL && r->request_start) {
+        for (p = r->request_start; p < r->header_in->last; p++) {
+            if (*p == CR || *p == LF) {
+                break;
+            }
+        }
+
+        r->request_line.len = p - r->request_start;
+        r->request_line.data = r->request_start;
+    }
+
+    if (r->request_line.len) {
+        p = ngx_snprintf(buf, len, ", request: \"%V\"", &r->request_line);
         len -= p - buf;
         buf = p;
-
-    } else {
-        if (r->request_line.data == NULL && r->request_start) {
-            for (p = r->request_start; p < r->header_in->last; p++) {
-                if (*p == CR || *p == LF) {
-                    break;
-                }
-            }
-
-            r->request_line.len = p - r->request_start;
-            r->request_line.data = r->request_start;
-        }
-
-        if (r->request_line.len) {
-            p = ngx_snprintf(buf, len, ", request: \"%V\"", &r->request_line);
-            len -= p - buf;
-            buf = p;
-        }
     }
 
     if (r != sr) {
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -449,7 +449,7 @@ struct ngx_http_request_s {
     unsigned                          limit_zone_set:1;
 
 #if 0
-    unsigned                          cachable:1;
+    unsigned                          cacheable:1;
 #endif
 
     unsigned                          pipeline:1;
--- a/src/http/ngx_http_script.c
+++ b/src/http/ngx_http_script.c
@@ -314,7 +314,7 @@ ngx_http_script_run(ngx_http_request_t *
     cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
 
     for (i = 0; i < cmcf->variables.nelts; i++) {
-        if (r->variables[i].no_cachable) {
+        if (r->variables[i].no_cacheable) {
             r->variables[i].valid = 0;
             r->variables[i].not_found = 0;
         }
@@ -351,7 +351,7 @@ ngx_http_script_run(ngx_http_request_t *
 
 
 void
-ngx_http_script_flush_no_cachable_variables(ngx_http_request_t *r,
+ngx_http_script_flush_no_cacheable_variables(ngx_http_request_t *r,
     ngx_array_t *indices)
 {
     ngx_uint_t  n, *index;
@@ -359,7 +359,7 @@ ngx_http_script_flush_no_cachable_variab
     if (indices) {
         index = indices->elts;
         for (n = 0; n < indices->nelts; n++) {
-            if (r->variables[index[n]].no_cachable) {
+            if (r->variables[index[n]].no_cacheable) {
                 r->variables[index[n]].valid = 0;
                 r->variables[index[n]].not_found = 0;
             }
@@ -750,7 +750,8 @@ ngx_http_script_regex_end_code(ngx_http_
         dst = e->buf.data;
         src = e->buf.data;
 
-        ngx_unescape_uri(&dst, &src, e->pos - e->buf.data, NGX_UNESCAPE_URI);
+        ngx_unescape_uri(&dst, &src, e->pos - e->buf.data,
+                         NGX_UNESCAPE_REDIRECT);
 
         if (src < e->pos) {
             dst = ngx_copy(dst, src, e->pos - src);
@@ -1125,7 +1126,7 @@ ngx_http_script_value_code(ngx_http_scri
     e->sp->data = (u_char *) code->text_data;
 
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
-                   "http script value: \"%V\"", e->sp);
+                   "http script value: \"%v\"", e->sp);
 
     e->sp++;
 }
@@ -1150,7 +1151,7 @@ ngx_http_script_set_var_code(ngx_http_sc
 
     r->variables[code->index].len = e->sp->len;
     r->variables[code->index].valid = 1;
-    r->variables[code->index].no_cachable = 0;
+    r->variables[code->index].no_cacheable = 0;
     r->variables[code->index].not_found = 0;
     r->variables[code->index].data = e->sp->data;
 }
--- a/src/http/ngx_http_script.h
+++ b/src/http/ngx_http_script.h
@@ -181,7 +181,7 @@ ngx_uint_t ngx_http_script_variables_cou
 ngx_int_t ngx_http_script_compile(ngx_http_script_compile_t *sc);
 u_char *ngx_http_script_run(ngx_http_request_t *r, ngx_str_t *value,
     void *code_lengths, size_t reserved, void *code_values);
-void ngx_http_script_flush_no_cachable_variables(ngx_http_request_t *r,
+void ngx_http_script_flush_no_cacheable_variables(ngx_http_request_t *r,
     ngx_array_t *indices);
 
 void *ngx_http_script_start_code(ngx_pool_t *pool, ngx_array_t **codes,
--- a/src/http/ngx_http_special_response.c
+++ b/src/http/ngx_http_special_response.c
@@ -10,8 +10,15 @@
 #include <nginx.h>
 
 
+static u_char error_full_tail[] =
+"<hr><center>" NGINX_VER "</center>" CRLF
+"</body>" CRLF
+"</html>" CRLF
+;
+
+
 static u_char error_tail[] =
-"<hr><center>" NGINX_VER "</center>" CRLF
+"<hr><center>nginx</center>" CRLF
 "</body>" CRLF
 "</html>" CRLF
 ;
@@ -471,7 +478,8 @@ ngx_http_special_response_handler(ngx_ht
     if (!r->zero_body) {
         if (error_pages[err].len) {
             r->headers_out.content_length_n = error_pages[err].len
-                                              + sizeof(error_tail) - 1;
+                + (clcf->server_tokens ? sizeof(error_full_tail) - 1:
+                                         sizeof(error_tail) - 1);
 
             if (clcf->msie_padding
                 && r->headers_in.msie
@@ -568,8 +576,14 @@ ngx_http_special_response_handler(ngx_ht
         }
 
         b->memory = 1;
-        b->pos = error_tail;
-        b->last = error_tail + sizeof(error_tail) - 1;
+
+        if (clcf->server_tokens) {
+            b->pos = error_full_tail;
+            b->last = error_full_tail + sizeof(error_full_tail) - 1;
+        } else {
+            b->pos = error_tail;
+            b->last = error_tail + sizeof(error_tail) - 1;
+        }
 
         cl->next = ngx_alloc_chain_link(r->pool);
         if (cl->next == NULL) {
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -434,7 +434,7 @@ ngx_http_upstream_check_broken_connectio
             ev->error = 1;
         }
 
-        if (!u->cachable && !u->store && u->peer.connection) {
+        if (!u->cacheable && !u->store && u->peer.connection) {
             ngx_log_error(NGX_LOG_INFO, ev->log, ev->kq_errno,
                           "kevent() reported that client closed prematurely "
                           "connection, so upstream connection is closed too");
@@ -500,7 +500,7 @@ ngx_http_upstream_check_broken_connectio
     ev->eof = 1;
     c->error = 1;
 
-    if (!u->cachable && !u->store && u->peer.connection) {
+    if (!u->cacheable && !u->store && u->peer.connection) {
         ngx_log_error(NGX_LOG_INFO, ev->log, err,
                       "client closed prematurely connection, "
                       "so upstream connection is closed too");
@@ -978,8 +978,7 @@ ngx_http_upstream_process_header(ngx_eve
 #endif
     }
 
-    n = u->peer.connection->recv(u->peer.connection, u->buffer.last,
-                                 u->buffer.end - u->buffer.last);
+    n = c->recv(c, u->buffer.last, u->buffer.end - u->buffer.last);
 
     if (n == NGX_AGAIN) {
 #if 0
@@ -1512,7 +1511,7 @@ ngx_http_upstream_send_response(ngx_http
         }
     }
 
-    if (u->cachable) {
+    if (u->cacheable) {
         header = (ngx_http_cache_header_t *) u->buffer->start;
 
         header->expires = u->cache->ctx.expires;
@@ -1540,7 +1539,7 @@ ngx_http_upstream_send_response(ngx_http
     p->pool = r->pool;
     p->log = c->log;
 
-    p->cachable = u->cachable || u->store;
+    p->cacheable = u->cacheable || u->store;
 
     p->temp_file = ngx_pcalloc(r->pool, sizeof(ngx_temp_file_t));
     if (p->temp_file == NULL) {
@@ -1553,7 +1552,7 @@ ngx_http_upstream_send_response(ngx_http
     p->temp_file->path = u->conf->temp_path;
     p->temp_file->pool = r->pool;
 
-    if (u->cachable || u->store) {
+    if (u->cacheable || u->store) {
         p->temp_file->persistent = 1;
 
     } else {
@@ -1577,7 +1576,7 @@ ngx_http_upstream_send_response(ngx_http
 
     p->preread_size = u->buffer.last - u->buffer.pos;
 
-    if (u->cachable) {
+    if (u->cacheable) {
 
         p->buf_to_file = ngx_calloc_buf(r->pool);
         if (p->buf_to_file == NULL) {
@@ -1954,14 +1953,14 @@ ngx_http_upstream_process_body(ngx_event
 
 #if (NGX_HTTP_FILE_CACHE)
 
-        if (p->upstream_done && u->cachable) {
+        if (p->upstream_done && u->cacheable) {
             if (ngx_http_cache_update(r) == NGX_ERROR) {
                 ngx_http_busy_unlock(u->conf->busy_lock, &u->busy_lock);
                 ngx_http_upstream_finalize_request(r, u, 0);
                 return;
             }
 
-        } else if (p->upstream_eof && u->cachable) {
+        } else if (p->upstream_eof && u->cacheable) {
 
             /* TODO: check length & update cache */
 
@@ -1989,7 +1988,7 @@ ngx_http_upstream_process_body(ngx_event
         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0,
                        "http upstream downstream error");
 
-        if (!u->cachable && u->peer.connection) {
+        if (!u->cacheable && u->peer.connection) {
             ngx_http_upstream_finalize_request(r, u, 0);
         }
     }
@@ -2711,7 +2710,7 @@ ngx_http_upstream_addr_variable(ngx_http
     ngx_http_upstream_state_t  *state;
 
     v->valid = 1;
-    v->no_cachable = 0;
+    v->no_cacheable = 0;
     v->not_found = 0;
 
     if (r->upstream_states == NULL || r->upstream_states->nelts == 0) {
@@ -2782,7 +2781,7 @@ ngx_http_upstream_status_variable(ngx_ht
     ngx_http_upstream_state_t  *state;
 
     v->valid = 1;
-    v->no_cachable = 0;
+    v->no_cacheable = 0;
     v->not_found = 0;
 
     if (r->upstream_states == NULL || r->upstream_states->nelts == 0) {
@@ -2848,7 +2847,7 @@ ngx_http_upstream_response_time_variable
     ngx_http_upstream_state_t  *state;
 
     v->valid = 1;
-    v->no_cachable = 0;
+    v->no_cacheable = 0;
     v->not_found = 0;
 
     if (r->upstream_states == NULL || r->upstream_states->nelts == 0) {
@@ -3062,7 +3061,7 @@ ngx_http_upstream_server(ngx_conf_t *cf,
     u.url = value[1];
     u.default_port = 80;
 
-    if (ngx_parse_url(cf, &u) != NGX_OK) {
+    if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
         if (u.err) {
             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                "%s in upstream \"%V\"", u.err, &u.url);
@@ -3166,7 +3165,7 @@ ngx_http_upstream_add(ngx_conf_t *cf, ng
 
     if (!(flags & NGX_HTTP_UPSTREAM_CREATE)) {
 
-        if (ngx_parse_url(cf, u) != NGX_OK) {
+        if (ngx_parse_url(cf->pool, u) != NGX_OK) {
             if (u->err) {
                 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                    "%s in upstream \"%V\"", u->err, &u->url);
--- a/src/http/ngx_http_upstream.h
+++ b/src/http/ngx_http_upstream.h
@@ -243,7 +243,7 @@ struct ngx_http_upstream_s {
     ngx_http_cleanup_pt            *cleanup;
 
     unsigned                        store:1;
-    unsigned                        cachable:1;
+    unsigned                        cacheable:1;
     unsigned                        accel:1;
 
     unsigned                        buffering:1;
--- a/src/http/ngx_http_upstream_round_robin.c
+++ b/src/http/ngx_http_upstream_round_robin.c
@@ -73,7 +73,7 @@ ngx_http_upstream_init_round_robin(ngx_c
     u.host = us->host;
     u.port = (in_port_t) (us->port ? us->port : us->default_port);
 
-    if (ngx_inet_resolve_host(cf, &u) != NGX_OK) {
+    if (ngx_inet_resolve_host(cf->pool, &u) != NGX_OK) {
         if (u.err) {
             ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
                           "%s in upstream \"%V\" in %s:%ui",
@@ -94,17 +94,14 @@ ngx_http_upstream_init_round_robin(ngx_c
     peers->number = n;
     peers->name = &us->host;
 
-    n = 0;
-
     for (i = 0; i < u.naddrs; i++) {
-        peers->peer[n].sockaddr = u.addrs[i].sockaddr;
-        peers->peer[n].socklen = u.addrs[i].socklen;
-        peers->peer[n].name = u.addrs[i].name;
-        peers->peer[n].weight = 1;
-        peers->peer[n].current_weight = 1;
-        peers->peer[n].max_fails = 1;
-        peers->peer[n].fail_timeout = 10;
-        n++;
+        peers->peer[i].sockaddr = u.addrs[i].sockaddr;
+        peers->peer[i].socklen = u.addrs[i].socklen;
+        peers->peer[i].name = u.addrs[i].name;
+        peers->peer[i].weight = 1;
+        peers->peer[i].current_weight = 1;
+        peers->peer[i].max_fails = 1;
+        peers->peer[i].fail_timeout = 10;
     }
 
     us->peer.data = peers;
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -143,34 +143,34 @@ static ngx_http_variable_t  ngx_http_cor
 
     { ngx_string("uri"), NULL, ngx_http_variable_request,
       offsetof(ngx_http_request_t, uri),
-      NGX_HTTP_VAR_NOCACHABLE, 0 },
+      NGX_HTTP_VAR_NOCACHEABLE, 0 },
 
     { ngx_string("document_uri"), NULL, ngx_http_variable_request,
       offsetof(ngx_http_request_t, uri),
-      NGX_HTTP_VAR_NOCACHABLE, 0 },
+      NGX_HTTP_VAR_NOCACHEABLE, 0 },
 
     { ngx_string("request"), NULL, ngx_http_variable_request,
       offsetof(ngx_http_request_t, request_line), 0, 0 },
 
     { ngx_string("document_root"), NULL,
-      ngx_http_variable_document_root, 0, NGX_HTTP_VAR_NOCACHABLE, 0 },
+      ngx_http_variable_document_root, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
 
     { ngx_string("query_string"), NULL, ngx_http_variable_request,
       offsetof(ngx_http_request_t, args),
-      NGX_HTTP_VAR_NOCACHABLE, 0 },
+      NGX_HTTP_VAR_NOCACHEABLE, 0 },
 
     { ngx_string("args"),
       ngx_http_variable_request_set,
       ngx_http_variable_request,
       offsetof(ngx_http_request_t, args),
-      NGX_HTTP_VAR_CHANGABLE|NGX_HTTP_VAR_NOCACHABLE, 0 },
+      NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE, 0 },
 
     { ngx_string("is_args"), NULL, ngx_http_variable_is_args,
-      0, NGX_HTTP_VAR_NOCACHABLE, 0 },
+      0, NGX_HTTP_VAR_NOCACHEABLE, 0 },
 
     { ngx_string("request_filename"), NULL,
       ngx_http_variable_request_filename, 0,
-      NGX_HTTP_VAR_NOCACHABLE, 0 },
+      NGX_HTTP_VAR_NOCACHEABLE, 0 },
 
     { ngx_string("server_name"), NULL, ngx_http_variable_request,
       offsetof(ngx_http_request_t, server_name), 0, 0 },
@@ -215,7 +215,7 @@ static ngx_http_variable_t  ngx_http_cor
     { ngx_string("limit_rate"), ngx_http_variable_request_set_size,
       ngx_http_variable_request,
       offsetof(ngx_http_request_t, limit_rate),
-      NGX_HTTP_VAR_CHANGABLE|NGX_HTTP_VAR_NOCACHABLE, 0 },
+      NGX_HTTP_VAR_CHANGEABLE|NGX_HTTP_VAR_NOCACHEABLE, 0 },
 
     { ngx_string("nginx_version"), NULL, ngx_http_variable_nginx_version,
       0, 0, 0 },
@@ -251,7 +251,7 @@ ngx_http_add_variable(ngx_conf_t *cf, ng
 
         v = key[i].value;
 
-        if (!(v->flags & NGX_HTTP_VAR_CHANGABLE)) {
+        if (!(v->flags & NGX_HTTP_VAR_CHANGEABLE)) {
             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                "the duplicate \"%V\" variable", name);
             return NULL;
@@ -375,8 +375,8 @@ ngx_http_get_indexed_variable(ngx_http_r
     if (v[index].get_handler(r, &r->variables[index], v[index].data)
         == NGX_OK)
     {
-        if (v[index].flags & NGX_HTTP_VAR_NOCACHABLE) {
-            r->variables[index].no_cachable = 1;
+        if (v[index].flags & NGX_HTTP_VAR_NOCACHEABLE) {
+            r->variables[index].no_cacheable = 1;
         }
 
         return &r->variables[index];
@@ -397,7 +397,7 @@ ngx_http_get_flushed_variable(ngx_http_r
     v = &r->variables[index];
 
     if (v->valid) {
-        if (!v->no_cachable) {
+        if (!v->no_cacheable) {
             return v;
         }
 
@@ -497,7 +497,7 @@ ngx_http_variable_request(ngx_http_reque
     if (s->data) {
         v->len = s->len;
         v->valid = 1;
-        v->no_cachable = 0;
+        v->no_cacheable = 0;
         v->not_found = 0;
         v->data = s->data;
 
@@ -559,7 +559,7 @@ ngx_http_variable_header(ngx_http_reques
     if (h) {
         v->len = h->value.len;
         v->valid = 1;
-        v->no_cachable = 0;
+        v->no_cacheable = 0;
         v->not_found = 0;
         v->data = h->value.data;
 
@@ -591,7 +591,7 @@ ngx_http_variable_headers(ngx_http_reque
     }
 
     v->valid = 1;
-    v->no_cachable = 0;
+    v->no_cacheable = 0;
     v->not_found = 0;
 
     h = a->elts;
@@ -691,7 +691,7 @@ ngx_http_variable_unknown_header(ngx_htt
         if (n + prefix == var->len && n == header[i].key.len) {
             v->len = header[i].value.len;
             v->valid = 1;
-            v->no_cachable = 0;
+            v->no_cacheable = 0;
             v->not_found = 0;
             v->data = header[i].value.data;
 
@@ -730,7 +730,7 @@ ngx_http_variable_host(ngx_http_request_
     }
 
     v->valid = 1;
-    v->no_cachable = 0;
+    v->no_cacheable = 0;
     v->not_found = 0;
 
     return NGX_OK;
@@ -749,7 +749,7 @@ ngx_http_variable_binary_remote_addr(ngx
 
     v->len = sizeof(in_addr_t);
     v->valid = 1;
-    v->no_cachable = 0;
+    v->no_cacheable = 0;
     v->not_found = 0;
     v->data = (u_char *) &sin->sin_addr.s_addr;
 
@@ -763,7 +763,7 @@ ngx_http_variable_remote_addr(ngx_http_r
 {
     v->len = r->connection->addr_text.len;
     v->valid = 1;
-    v->no_cachable = 0;
+    v->no_cacheable = 0;
     v->not_found = 0;
     v->data = r->connection->addr_text.data;
 
@@ -780,7 +780,7 @@ ngx_http_variable_remote_port(ngx_http_r
 
     v->len = 0;
     v->valid = 1;
-    v->no_cachable = 0;
+    v->no_cacheable = 0;
     v->not_found = 0;
 
     v->data = ngx_palloc(r->pool, sizeof("65535") - 1);
@@ -832,7 +832,7 @@ ngx_http_variable_server_addr(ngx_http_r
     v->len = ngx_inet_ntop(c->listening->family, &r->in_addr,
                            v->data, INET_ADDRSTRLEN);
     v->valid = 1;
-    v->no_cachable = 0;
+    v->no_cacheable = 0;
     v->not_found = 0;
 
     return NGX_OK;
@@ -845,7 +845,7 @@ ngx_http_variable_server_port(ngx_http_r
 {
     v->len = r->port_text->len - 1;
     v->valid = 1;
-    v->no_cachable = 0;
+    v->no_cacheable = 0;
     v->not_found = 0;
     v->data = r->port_text->data + 1;
 
@@ -862,7 +862,7 @@ ngx_http_variable_scheme(ngx_http_reques
     if (r->connection->ssl) {
         v->len = sizeof("https") - 1;
         v->valid = 1;
-        v->no_cachable = 0;
+        v->no_cacheable = 0;
         v->not_found = 0;
         v->data = (u_char *) "https";
 
@@ -873,7 +873,7 @@ ngx_http_variable_scheme(ngx_http_reques
 
     v->len = sizeof("http") - 1;
     v->valid = 1;
-    v->no_cachable = 0;
+    v->no_cacheable = 0;
     v->not_found = 0;
     v->data = (u_char *) "http";
 
@@ -886,7 +886,7 @@ ngx_http_variable_is_args(ngx_http_reque
     ngx_http_variable_value_t *v, uintptr_t data)
 {
     v->valid = 1;
-    v->no_cachable = 0;
+    v->no_cacheable = 0;
     v->not_found = 0;
 
     if (r->args.len == 0) {
@@ -914,7 +914,7 @@ ngx_http_variable_document_root(ngx_http
     if (clcf->root_lengths == NULL) {
         v->len = clcf->root.len;
         v->valid = 1;
-        v->no_cachable = 0;
+        v->no_cacheable = 0;
         v->not_found = 0;
         v->data = clcf->root.data;
 
@@ -932,7 +932,7 @@ ngx_http_variable_document_root(ngx_http
 
         v->len = path.len;
         v->valid = 1;
-        v->no_cachable = 0;
+        v->no_cacheable = 0;
         v->not_found = 0;
         v->data = path.data;
     }
@@ -956,7 +956,7 @@ ngx_http_variable_request_filename(ngx_h
 
     v->len = path.len - 1;
     v->valid = 1;
-    v->no_cachable = 0;
+    v->no_cacheable = 0;
     v->not_found = 0;
     v->data = path.data;
 
@@ -971,7 +971,7 @@ ngx_http_variable_request_method(ngx_htt
     if (r->main->method_name.data) {
         v->len = r->main->method_name.len;
         v->valid = 1;
-        v->no_cachable = 0;
+        v->no_cacheable = 0;
         v->not_found = 0;
         v->data = r->main->method_name.data;
 
@@ -1002,7 +1002,7 @@ ngx_http_variable_remote_user(ngx_http_r
 
     v->len = r->headers_in.user.len;
     v->valid = 1;
-    v->no_cachable = 0;
+    v->no_cacheable = 0;
     v->not_found = 0;
     v->data = r->headers_in.user.data;
 
@@ -1030,7 +1030,7 @@ ngx_http_variable_body_bytes_sent(ngx_ht
 
     v->len = ngx_sprintf(p, "%O", sent) - p;
     v->valid = 1;
-    v->no_cachable = 0;
+    v->no_cacheable = 0;
     v->not_found = 0;
     v->data = p;
 
@@ -1045,7 +1045,7 @@ ngx_http_variable_sent_content_type(ngx_
     if (r->headers_out.content_type.len) {
         v->len = r->headers_out.content_type.len;
         v->valid = 1;
-        v->no_cachable = 0;
+        v->no_cacheable = 0;
         v->not_found = 0;
         v->data = r->headers_out.content_type.data;
 
@@ -1066,7 +1066,7 @@ ngx_http_variable_sent_content_length(ng
     if (r->headers_out.content_length) {
         v->len = r->headers_out.content_length->value.len;
         v->valid = 1;
-        v->no_cachable = 0;
+        v->no_cacheable = 0;
         v->not_found = 0;
         v->data = r->headers_out.content_length->value.data;
 
@@ -1081,7 +1081,7 @@ ngx_http_variable_sent_content_length(ng
 
         v->len = ngx_sprintf(p, "%O", r->headers_out.content_length_n) - p;
         v->valid = 1;
-        v->no_cachable = 0;
+        v->no_cacheable = 0;
         v->not_found = 0;
         v->data = p;
 
@@ -1103,7 +1103,7 @@ ngx_http_variable_sent_last_modified(ngx
     if (r->headers_out.last_modified) {
         v->len = r->headers_out.last_modified->value.len;
         v->valid = 1;
-        v->no_cachable = 0;
+        v->no_cacheable = 0;
         v->not_found = 0;
         v->data = r->headers_out.last_modified->value.data;
 
@@ -1119,7 +1119,7 @@ ngx_http_variable_sent_last_modified(ngx
 
         v->len = ngx_http_time(p, r->headers_out.last_modified_time) - p;
         v->valid = 1;
-        v->no_cachable = 0;
+        v->no_cacheable = 0;
         v->not_found = 0;
         v->data = p;
 
@@ -1150,7 +1150,7 @@ ngx_http_variable_sent_connection(ngx_ht
 
     v->len = len;
     v->valid = 1;
-    v->no_cachable = 0;
+    v->no_cacheable = 0;
     v->not_found = 0;
     v->data = (u_char *) p;
 
@@ -1177,7 +1177,7 @@ ngx_http_variable_sent_keep_alive(ngx_ht
 
             v->len = ngx_sprintf(p, "timeout=%T", clcf->keepalive_header) - p;
             v->valid = 1;
-            v->no_cachable = 0;
+            v->no_cacheable = 0;
             v->not_found = 0;
             v->data = p;
 
@@ -1198,7 +1198,7 @@ ngx_http_variable_sent_transfer_encoding
     if (r->chunked) {
         v->len = sizeof("chunked") - 1;
         v->valid = 1;
-        v->no_cachable = 0;
+        v->no_cacheable = 0;
         v->not_found = 0;
         v->data = (u_char *) "chunked";
 
@@ -1217,7 +1217,7 @@ ngx_http_variable_request_completion(ngx
     if (r->request_complete) {
         v->len = 2;
         v->valid = 1;
-        v->no_cachable = 0;
+        v->no_cacheable = 0;
         v->not_found = 0;
         v->data = (u_char *) "OK";
 
@@ -1226,7 +1226,7 @@ ngx_http_variable_request_completion(ngx
 
     v->len = 0;
     v->valid = 1;
-    v->no_cachable = 0;
+    v->no_cacheable = 0;
     v->not_found = 0;
     v->data = (u_char *) "";
 
@@ -1246,7 +1246,7 @@ ngx_http_variable_request_body_file(ngx_
 
     v->len = r->request_body->temp_file->file.name.len;
     v->valid = 1;
-    v->no_cachable = 0;
+    v->no_cacheable = 0;
     v->not_found = 0;
     v->data = r->request_body->temp_file->file.name.data;
 
@@ -1260,7 +1260,7 @@ ngx_http_variable_nginx_version(ngx_http
 {
     v->len = sizeof(NGINX_VERSION) - 1;
     v->valid = 1;
-    v->no_cachable = 0;
+    v->no_cacheable = 0;
     v->not_found = 0;
     v->data = (u_char *) NGINX_VERSION;
 
@@ -1368,7 +1368,7 @@ ngx_http_variables_init_vars(ngx_conf_t 
         if (ngx_strncmp(v[i].name.data, "upstream_http_", 14) == 0) {
             v[i].get_handler = ngx_http_upstream_header_variable;
             v[i].data = (uintptr_t) &v[i].name;
-            v[i].flags = NGX_HTTP_VAR_NOCACHABLE;
+            v[i].flags = NGX_HTTP_VAR_NOCACHEABLE;
 
             continue;
         }
--- a/src/http/ngx_http_variables.h
+++ b/src/http/ngx_http_variables.h
@@ -26,10 +26,10 @@ typedef ngx_int_t (*ngx_http_get_variabl
     ngx_http_variable_value_t *v, uintptr_t data);
 
 
-#define NGX_HTTP_VAR_CHANGABLE   1
-#define NGX_HTTP_VAR_NOCACHABLE  2
-#define NGX_HTTP_VAR_INDEXED     4
-#define NGX_HTTP_VAR_NOHASH      8
+#define NGX_HTTP_VAR_CHANGEABLE   1
+#define NGX_HTTP_VAR_NOCACHEABLE  2
+#define NGX_HTTP_VAR_INDEXED      4
+#define NGX_HTTP_VAR_NOHASH       8
 
 
 struct ngx_http_variable_s {
--- a/src/mail/ngx_mail.h
+++ b/src/mail/ngx_mail.h
@@ -102,7 +102,7 @@ typedef enum {
     ngx_pop3_auth_login_password,
     ngx_pop3_auth_plain,
     ngx_pop3_auth_cram_md5
-} ngx_po3_state_e;
+} ngx_pop3_state_e;
 
 
 typedef enum {
--- a/src/mail/ngx_mail_auth_http_module.c
+++ b/src/mail/ngx_mail_auth_http_module.c
@@ -1368,7 +1368,7 @@ ngx_mail_auth_http(ngx_conf_t *cf, ngx_c
         u.url.data += 7;
     }
 
-    if (ngx_parse_url(cf, &u) != NGX_OK) {
+    if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
         if (u.err) {
             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                "%s in auth_http \"%V\"", u.err, &u.url);
--- a/src/mail/ngx_mail_core_module.c
+++ b/src/mail/ngx_mail_core_module.c
@@ -285,7 +285,7 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx
     u.url = value[1];
     u.listen = 1;
 
-    if (ngx_parse_url(cf, &u) != NGX_OK) {
+    if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
         if (u.err) {
             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                                "%s in \"%V\" of the \"listen\" directive",
--- a/src/os/unix/ngx_posix_config.h
+++ b/src/os/unix/ngx_posix_config.h
@@ -19,6 +19,12 @@
 #endif
 
 
+#ifdef __CYGWIN__
+#define timezonevar             /* timezone is variable */
+#define NGX_BROKEN_SCM_RIGHTS   1
+#endif
+
+
 #include <sys/types.h>
 #include <sys/time.h>
 #if (NGX_HAVE_UNISTD_H)
@@ -64,6 +70,15 @@
 #include <limits.h>             /* IOV_MAX */
 #endif
 
+#if (NGX_HAVE_MALLOC_H)
+#include <malloc.h>             /* memalign() */
+#endif
+
+#if (NGX_HAVE_CRYPT_H)
+#include <crypt.h>
+#endif
+
+
 #ifndef IOV_MAX
 #define IOV_MAX   16
 #endif
--- a/src/os/unix/ngx_process_cycle.c
+++ b/src/os/unix/ngx_process_cycle.c
@@ -14,7 +14,7 @@ static void ngx_start_worker_processes(n
     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);
+static ngx_uint_t ngx_reap_children(ngx_cycle_t *cycle);
 static void ngx_master_process_exit(ngx_cycle_t *cycle);
 static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data);
 static void ngx_worker_process_init(ngx_cycle_t *cycle, ngx_uint_t priority);
@@ -157,9 +157,9 @@ ngx_master_process_cycle(ngx_cycle_t *cy
 
         if (ngx_reap) {
             ngx_reap = 0;
-            ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "reap childs");
+            ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "reap children");
 
-            live = ngx_reap_childs(cycle);
+            live = ngx_reap_children(cycle);
         }
 
         if (!live && (ngx_terminate || ngx_quit)) {
@@ -409,6 +409,12 @@ ngx_signal_worker_processes(ngx_cycle_t 
     ngx_err_t      err;
     ngx_channel_t  ch;
 
+#if (NGX_BROKEN_SCM_RIGHTS)
+
+    ch.command = 0;
+
+#else
+
     switch (signo) {
 
     case ngx_signal_value(NGX_SHUTDOWN_SIGNAL):
@@ -427,6 +433,8 @@ ngx_signal_worker_processes(ngx_cycle_t 
         ch.command = 0;
     }
 
+#endif
+
     ch.fd = -1;
 
 
@@ -496,7 +504,7 @@ ngx_signal_worker_processes(ngx_cycle_t 
 
 
 static ngx_uint_t
-ngx_reap_childs(ngx_cycle_t *cycle)
+ngx_reap_children(ngx_cycle_t *cycle)
 {
     ngx_int_t         i, n;
     ngx_uint_t        live;
@@ -1035,7 +1043,6 @@ static void
 ngx_channel_handler(ngx_event_t *ev)
 {
     ngx_int_t          n;
-    ngx_socket_t       fd;
     ngx_channel_t      ch;
     ngx_connection_t  *c;
 
@@ -1053,17 +1060,7 @@ ngx_channel_handler(ngx_event_t *ev)
     ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0, "channel: %i", n);
 
     if (n == NGX_ERROR) {
-
-        ngx_free_connection(c);
-
-        fd = c->fd;
-        c->fd = (ngx_socket_t) -1;
-
-        if (close(fd) == -1) {
-            ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
-                          "close() channel failed");
-        }
-
+        ngx_close_connection(c);
         return;
     }
 
--- a/src/os/unix/ngx_recv.c
+++ b/src/os/unix/ngx_recv.c
@@ -11,7 +11,8 @@
 
 #if (NGX_HAVE_KQUEUE)
 
-ssize_t ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size)
+ssize_t
+ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size)
 {
     ssize_t       n;
     ngx_err_t     err;
@@ -77,12 +78,6 @@ ssize_t ngx_unix_recv(ngx_connection_t *
                      * even if kqueue reported about available data
                      */
 
-#if 0
-                    ngx_log_error(NGX_LOG_ALERT, c->log, 0,
-                                  "recv() returned 0 while kevent() reported "
-                                  "%d available bytes", rev->available);
-#endif
-
                     rev->eof = 1;
                     rev->available = 0;
                 }
@@ -126,7 +121,8 @@ ssize_t ngx_unix_recv(ngx_connection_t *
 
 #else /* ! NGX_HAVE_KQUEUE */
 
-ssize_t ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size)
+ssize_t
+ngx_unix_recv(ngx_connection_t *c, u_char *buf, size_t size)
 {
     ssize_t       n;
     ngx_err_t     err;
--- a/src/os/unix/ngx_send.c
+++ b/src/os/unix/ngx_send.c
@@ -9,7 +9,8 @@
 #include <ngx_event.h>
 
 
-ssize_t ngx_unix_send(ngx_connection_t *c, u_char *buf, size_t size)
+ssize_t
+ngx_unix_send(ngx_connection_t *c, u_char *buf, size_t size)
 {
     ssize_t       n;
     ngx_err_t     err;
--- a/src/os/unix/ngx_solaris_init.c
+++ b/src/os/unix/ngx_solaris_init.c
@@ -57,7 +57,7 @@ ngx_os_specific_init(ngx_log_t *log)
 
     ngx_os_io = ngx_solaris_io;
 
-    return NGX_OK;;
+    return NGX_OK;
 }