nginx-0.3.55-RELEASE import

    *) Feature: the "stub" parameter in the "include" SSI command.

    *) Feature: the "block" SSI command.

    *) Feature: the unicode2nginx script was added to contrib.

    *) Bugfix: if a "root" was specified by variable only, then the root
       was relative to a server prefix.

    *) Bugfix: if the request contained "//" or "/./" and escaped symbols
       after them, then the proxied request was sent unescaped.

    *) Bugfix: the $r->headers_in("Cookie") of the ngx_http_perl_module now
       returns all "Cookie" header lines.

    *) Bugfix: a segmentation fault occurred if
       "client_body_in_file_only on" was used and nginx switched to a next
       upstream.

    *) Bugfix: on some condition while reconfiguration character codes
       inside the "charset_map" may be treated invalid; the bug had
       appeared in 0.3.50.
diff --git a/src/http/modules/ngx_http_access_module.c b/src/http/modules/ngx_http_access_module.c
index b8aa3aa..93c8652 100644
--- a/src/http/modules/ngx_http_access_module.c
+++ b/src/http/modules/ngx_http_access_module.c
@@ -55,7 +55,7 @@
 
 
 
-ngx_http_module_t  ngx_http_access_module_ctx = {
+static ngx_http_module_t  ngx_http_access_module_ctx = {
     NULL,                                  /* preconfiguration */
     NULL,                                  /* postconfiguration */
 
diff --git a/src/http/modules/ngx_http_addition_filter_module.c b/src/http/modules/ngx_http_addition_filter_module.c
index 15231ce..31209f9 100644
--- a/src/http/modules/ngx_http_addition_filter_module.c
+++ b/src/http/modules/ngx_http_addition_filter_module.c
@@ -143,7 +143,7 @@
         ctx->before_body_sent = 1;
 
         if (conf->before_body.len) {
-            if (ngx_http_subrequest(r, &conf->before_body, NULL, 0)
+            if (ngx_http_subrequest(r, &conf->before_body, NULL, NULL, 0)
                 == NGX_ERROR)
             {
                 return NGX_ERROR;
@@ -167,7 +167,7 @@
         return rc;
     }
 
-    if (ngx_http_subrequest(r, &conf->after_body, NULL, 0) == NGX_ERROR) {
+    if (ngx_http_subrequest(r, &conf->after_body, NULL, NULL, 0) == NGX_ERROR) {
         return NGX_ERROR;
     }
 
diff --git a/src/http/modules/ngx_http_auth_basic_module.c b/src/http/modules/ngx_http_auth_basic_module.c
index 5dd2876..113527f 100644
--- a/src/http/modules/ngx_http_auth_basic_module.c
+++ b/src/http/modules/ngx_http_auth_basic_module.c
@@ -60,7 +60,7 @@
 };
 
 
-ngx_http_module_t  ngx_http_auth_basic_module_ctx = {
+static ngx_http_module_t  ngx_http_auth_basic_module_ctx = {
     NULL,                                  /* preconfiguration */
     NULL,                                  /* postconfiguration */
 
diff --git a/src/http/modules/ngx_http_autoindex_module.c b/src/http/modules/ngx_http_autoindex_module.c
index 5354568..7064f37 100644
--- a/src/http/modules/ngx_http_autoindex_module.c
+++ b/src/http/modules/ngx_http_autoindex_module.c
@@ -81,7 +81,7 @@
 };
 
 
-ngx_http_module_t  ngx_http_autoindex_module_ctx = {
+static ngx_http_module_t  ngx_http_autoindex_module_ctx = {
     NULL,                                  /* preconfiguration */
     NULL,                                  /* postconfiguration */
 
diff --git a/src/http/modules/ngx_http_charset_filter_module.c b/src/http/modules/ngx_http_charset_filter_module.c
index e3fdb65..ab6f5ce 100644
--- a/src/http/modules/ngx_http_charset_filter_module.c
+++ b/src/http/modules/ngx_http_charset_filter_module.c
@@ -1325,6 +1325,9 @@
 
     if (ngx_strcasecmp(name->data, "utf-8") == 0) {
         c->utf8 = 1;
+
+    } else {
+        c->utf8 = 0;
     }
 
     return i;
diff --git a/src/http/modules/ngx_http_chunked_filter_module.c b/src/http/modules/ngx_http_chunked_filter_module.c
index 6581e59..4e02194 100644
--- a/src/http/modules/ngx_http_chunked_filter_module.c
+++ b/src/http/modules/ngx_http_chunked_filter_module.c
@@ -95,8 +95,11 @@
 
         size += ngx_buf_size(cl->buf);
 
-        if (cl->buf->flush || ngx_buf_in_memory(cl->buf) || cl->buf->in_file) {
-
+        if (cl->buf->flush
+            || cl->buf->sync
+            || ngx_buf_in_memory(cl->buf)
+            || cl->buf->in_file)
+        {
             tl = ngx_alloc_chain_link(r->pool);
             if (tl == NULL) {
                 return NGX_ERROR;
diff --git a/src/http/modules/ngx_http_dav_module.c b/src/http/modules/ngx_http_dav_module.c
index 53ef21c..0ea937f 100644
--- a/src/http/modules/ngx_http_dav_module.c
+++ b/src/http/modules/ngx_http_dav_module.c
@@ -57,7 +57,7 @@
 };
 
 
-ngx_http_module_t  ngx_http_dav_module_ctx = {
+static ngx_http_module_t  ngx_http_dav_module_ctx = {
     NULL,                                  /* preconfiguration */
     NULL,                                  /* postconfiguration */
 
diff --git a/src/http/modules/ngx_http_empty_gif_module.c b/src/http/modules/ngx_http_empty_gif_module.c
index b97633a..69b6c89 100644
--- a/src/http/modules/ngx_http_empty_gif_module.c
+++ b/src/http/modules/ngx_http_empty_gif_module.c
@@ -74,7 +74,7 @@
 };
 
 
-ngx_http_module_t  ngx_http_empty_gif_module_ctx = {
+static ngx_http_module_t  ngx_http_empty_gif_module_ctx = {
     NULL,                          /* preconfiguration */
     NULL,                          /* postconfiguration */
 
diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c
index 28f860e..8d5ef95 100644
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -347,7 +347,7 @@
 };
 
 
-ngx_http_module_t  ngx_http_fastcgi_module_ctx = {
+static ngx_http_module_t  ngx_http_fastcgi_module_ctx = {
     ngx_http_fastcgi_add_variables,        /* preconfiguration */
     NULL,                                  /* postconfiguration */
 
diff --git a/src/http/modules/ngx_http_index_module.c b/src/http/modules/ngx_http_index_module.c
index 4ef2910..b93e6fb 100644
--- a/src/http/modules/ngx_http_index_module.c
+++ b/src/http/modules/ngx_http_index_module.c
@@ -72,7 +72,7 @@
 };
 
 
-ngx_http_module_t  ngx_http_index_module_ctx = {
+static ngx_http_module_t  ngx_http_index_module_ctx = {
     NULL,                                  /* preconfiguration */
     NULL,                                  /* postconfiguration */
 
diff --git a/src/http/modules/ngx_http_log_module.c b/src/http/modules/ngx_http_log_module.c
index f85a6c8..c81ad2e 100644
--- a/src/http/modules/ngx_http_log_module.c
+++ b/src/http/modules/ngx_http_log_module.c
@@ -142,7 +142,7 @@
 };
 
 
-ngx_http_module_t  ngx_http_log_module_ctx = {
+static ngx_http_module_t  ngx_http_log_module_ctx = {
     ngx_http_log_set_formats,              /* preconfiguration */
     ngx_http_log_init,                     /* postconfiguration */
 
diff --git a/src/http/modules/ngx_http_memcached_module.c b/src/http/modules/ngx_http_memcached_module.c
index 4373692..61a9502 100644
--- a/src/http/modules/ngx_http_memcached_module.c
+++ b/src/http/modules/ngx_http_memcached_module.c
@@ -112,7 +112,7 @@
 };
 
 
-ngx_http_module_t  ngx_http_memcached_module_ctx = {
+static ngx_http_module_t  ngx_http_memcached_module_ctx = {
     NULL,                                  /* preconfiguration */
     NULL,                                  /* postconfiguration */
 
diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
index 5999f2e..a6adc3c 100644
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -327,7 +327,7 @@
 };
 
 
-ngx_http_module_t  ngx_http_proxy_module_ctx = {
+static ngx_http_module_t  ngx_http_proxy_module_ctx = {
     ngx_http_proxy_add_variables,          /* preconfiguration */
     NULL,                                  /* postconfiguration */
 
diff --git a/src/http/modules/ngx_http_realip_module.c b/src/http/modules/ngx_http_realip_module.c
index 3940ee4..8f128d2 100644
--- a/src/http/modules/ngx_http_realip_module.c
+++ b/src/http/modules/ngx_http_realip_module.c
@@ -61,7 +61,7 @@
 
 
 
-ngx_http_module_t  ngx_http_realip_module_ctx = {
+static ngx_http_module_t  ngx_http_realip_module_ctx = {
     NULL,                                  /* preconfiguration */
     NULL,                                  /* postconfiguration */
 
diff --git a/src/http/modules/ngx_http_rewrite_module.c b/src/http/modules/ngx_http_rewrite_module.c
index 88988bd..980de19 100644
--- a/src/http/modules/ngx_http_rewrite_module.c
+++ b/src/http/modules/ngx_http_rewrite_module.c
@@ -102,7 +102,7 @@
 };
 
 
-ngx_http_module_t  ngx_http_rewrite_module_ctx = {
+static ngx_http_module_t  ngx_http_rewrite_module_ctx = {
     NULL,                                  /* preconfiguration */
     NULL,                                  /* postconfiguration */
 
diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c
index 5a65a03..ef870be 100644
--- a/src/http/modules/ngx_http_ssi_filter_module.c
+++ b/src/http/modules/ngx_http_ssi_filter_module.c
@@ -36,6 +36,13 @@
 } ngx_http_ssi_var_t;
 
 
+typedef struct {
+    ngx_str_t     name;
+    ngx_chain_t  *bufs;
+    ngx_uint_t    count;
+} ngx_http_ssi_block_t;
+
+
 typedef enum {
     ssi_start_state = 0,
     ssi_tag_state,
@@ -83,6 +90,10 @@
     ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
 static ngx_int_t ngx_http_ssi_endif(ngx_http_request_t *r,
     ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
+static ngx_int_t ngx_http_ssi_block(ngx_http_request_t *r,
+    ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
+static ngx_int_t ngx_http_ssi_endblock(ngx_http_request_t *r,
+    ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
 
 static ngx_int_t ngx_http_ssi_date_gmt_local_variable(ngx_http_request_t *r,
     ngx_http_variable_value_t *v,  uintptr_t gmt);
@@ -189,6 +200,7 @@
 #define  NGX_HTTP_SSI_INCLUDE_VIRTUAL  0
 #define  NGX_HTTP_SSI_INCLUDE_FILE     1
 #define  NGX_HTTP_SSI_INCLUDE_WAIT     2
+#define  NGX_HTTP_SSI_INCLUDE_STUB     3
 
 #define  NGX_HTTP_SSI_ECHO_VAR         0
 #define  NGX_HTTP_SSI_ECHO_DEFAULT     1
@@ -201,11 +213,14 @@
 
 #define  NGX_HTTP_SSI_IF_EXPR          0
 
+#define  NGX_HTTP_SSI_BLOCK_NAME       0
+
 
 static ngx_http_ssi_param_t  ngx_http_ssi_include_params[] = {
     { ngx_string("virtual"), NGX_HTTP_SSI_INCLUDE_VIRTUAL, 0, 0 },
     { ngx_string("file"), NGX_HTTP_SSI_INCLUDE_FILE, 0, 0 },
     { ngx_string("wait"), NGX_HTTP_SSI_INCLUDE_WAIT, 0, 0 },
+    { ngx_string("stub"), NGX_HTTP_SSI_INCLUDE_STUB, 0, 0 },
     { ngx_null_string, 0, 0, 0 }
 };
 
@@ -237,6 +252,12 @@
 };
 
 
+static ngx_http_ssi_param_t  ngx_http_ssi_block_params[] = {
+    { ngx_string("name"), NGX_HTTP_SSI_BLOCK_NAME, 1, 0 },
+    { ngx_null_string, 0, 0, 0 }
+};
+
+
 static ngx_http_ssi_param_t  ngx_http_ssi_no_params[] = {
     { ngx_null_string, 0, 0, 0 }
 };
@@ -244,21 +265,27 @@
 
 static ngx_http_ssi_command_t  ngx_http_ssi_commands[] = {
     { ngx_string("include"), ngx_http_ssi_include,
-                       ngx_http_ssi_include_params, 0, 1 },
-    { ngx_string("echo"), ngx_http_ssi_echo, ngx_http_ssi_echo_params, 0, 0 },
+                       ngx_http_ssi_include_params, 0, 0, 1 },
+    { ngx_string("echo"), ngx_http_ssi_echo,
+                       ngx_http_ssi_echo_params, 0, 0, 0 },
     { ngx_string("config"), ngx_http_ssi_config,
-                       ngx_http_ssi_config_params, 0, 0 },
-    { ngx_string("set"), ngx_http_ssi_set, ngx_http_ssi_set_params, 0, 0 },
+                       ngx_http_ssi_config_params, 0, 0, 0 },
+    { ngx_string("set"), ngx_http_ssi_set, ngx_http_ssi_set_params, 0, 0, 0 },
 
-    { ngx_string("if"), ngx_http_ssi_if, ngx_http_ssi_if_params, 0, 0 },
+    { ngx_string("if"), ngx_http_ssi_if, ngx_http_ssi_if_params, 0, 0, 0 },
     { ngx_string("elif"), ngx_http_ssi_if, ngx_http_ssi_if_params,
-                       NGX_HTTP_SSI_COND_IF, 0 },
+                       NGX_HTTP_SSI_COND_IF, 0, 0 },
     { ngx_string("else"), ngx_http_ssi_else, ngx_http_ssi_no_params,
-                       NGX_HTTP_SSI_COND_IF, 0 },
+                       NGX_HTTP_SSI_COND_IF, 0, 0 },
     { ngx_string("endif"), ngx_http_ssi_endif, ngx_http_ssi_no_params,
-                       NGX_HTTP_SSI_COND_ELSE, 0 },
+                       NGX_HTTP_SSI_COND_ELSE, 0, 0 },
 
-    { ngx_null_string, NULL, NULL, 0, 0 }
+    { ngx_string("block"), ngx_http_ssi_block,
+                       ngx_http_ssi_block_params, 0, 0, 0 },
+    { ngx_string("endblock"), ngx_http_ssi_endblock,
+                       ngx_http_ssi_no_params, 0, 1, 0 },
+
+    { ngx_null_string, NULL, NULL, 0, 0, 0 }
 };
 
 
@@ -348,13 +375,15 @@
 static ngx_int_t
 ngx_http_ssi_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
 {
+    size_t                     len;
     ngx_int_t                  rc;
     ngx_buf_t                 *b;
     ngx_uint_t                 i, index;
-    ngx_chain_t               *cl;
+    ngx_chain_t               *cl, **ll;
     ngx_table_elt_t           *param;
     ngx_connection_t          *c;
-    ngx_http_ssi_ctx_t        *ctx;
+    ngx_http_ssi_ctx_t        *ctx, *mctx;
+    ngx_http_ssi_block_t      *bl;
     ngx_http_ssi_param_t      *prm;
     ngx_http_ssi_command_t    *cmd;
     ngx_http_ssi_loc_conf_t   *slcf;
@@ -510,6 +539,47 @@
                     ctx->last_out = &cl->next;
 
                 } else {
+                    if (ctx->block
+                        && ctx->saved + (ctx->copy_end - ctx->copy_start))
+                    {
+                        b = ngx_create_temp_buf(r->pool,
+                               ctx->saved + (ctx->copy_end - ctx->copy_start));
+
+                        if (b == NULL) {
+                            return NGX_ERROR;
+                        }
+
+                        if (ctx->saved) {
+                            b->last = ngx_cpymem(b->pos, ngx_http_ssi_string,
+                                                 ctx->saved);
+                        }
+
+                        b->last = ngx_cpymem(b->last, ctx->copy_start,
+                                             ctx->copy_end - ctx->copy_start);
+
+                        cl = ngx_alloc_chain_link(r->pool);
+                        if (cl == NULL) {
+                            return NGX_ERROR;
+                        }
+
+                        cl->buf = b;
+                        cl->next = NULL;
+
+                        b = NULL;
+
+                        mctx = ngx_http_get_module_ctx(r->main,
+                                                   ngx_http_ssi_filter_module);
+                        bl = mctx->blocks->elts;
+                        for (ll = &bl[mctx->blocks->nelts - 1].bufs;
+                             *ll;
+                             ll = &(*ll)->next)
+                        {
+                            /* void */
+                        }
+
+                        *ll = cl;
+                    }
+
                     ctx->saved = 0;
                 }
             }
@@ -559,8 +629,79 @@
                     goto ssi_error;
                 }
 
-                if (!ctx->output && cmd->conditional == 0) {
-                    continue;
+                if (!ctx->output && !cmd->block) {
+
+                    if (ctx->block) {
+
+                        /* reconstruct the SSI command text */
+
+                        len = 5 + ctx->command.len + 4;
+
+                        param = ctx->params.elts;
+                        for (i = 0; i < ctx->params.nelts; i++) {
+                            len += 1 + param[i].key.len + 2
+                                + param[i].value.len + 1;
+                        }
+
+                        b = ngx_create_temp_buf(r->pool, len);
+
+                        if (b == NULL) {
+                            return NGX_ERROR;
+                        }
+
+                        cl = ngx_alloc_chain_link(r->pool);
+                        if (cl == NULL) {
+                            return NGX_ERROR;
+                        }
+
+                        cl->buf = b;
+                        cl->next = NULL;
+
+                        *b->last++ = '<';
+                        *b->last++ = '!';
+                        *b->last++ = '-';
+                        *b->last++ = '-';
+                        *b->last++ = '#';
+
+                        b->last = ngx_cpymem(b->last, ctx->command.data,
+                                             ctx->command.len);
+
+                        for (i = 0; i < ctx->params.nelts; i++) {
+                            *b->last++ = ' ';
+                            b->last = ngx_cpymem(b->last, param[i].key.data,
+                                                 param[i].key.len);
+                            *b->last++ = '=';
+                            *b->last++ = '"';
+                            b->last = ngx_cpymem(b->last, param[i].value.data,
+                                                 param[i].value.len);
+                            *b->last++ = '"';
+                        }
+
+                        *b->last++ = ' ';
+                        *b->last++ = '-';
+                        *b->last++ = '-';
+                        *b->last++ = '>';
+
+                        mctx = ngx_http_get_module_ctx(r->main,
+                                                   ngx_http_ssi_filter_module);
+                        bl = mctx->blocks->elts;
+                        for (ll = &bl[mctx->blocks->nelts - 1].bufs;
+                             *ll;
+                             ll = &(*ll)->next)
+                        {
+                            /* void */
+                        }
+
+                        *ll = cl;
+
+                        b = NULL;
+
+                        continue;
+                    }
+
+                    if (cmd->conditional == 0) {
+                        continue;
+                    }
                 }
 
                 if (ctx->params.nelts > NGX_HTTP_SSI_MAX_PARAMS) {
@@ -1382,8 +1523,12 @@
 
     ctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module);
 
-    var = ctx->variables.elts;
-    for (i = 0; i < ctx->variables.nelts; i++) {
+    if (ctx->variables == NULL) {
+        return NULL;
+    }
+
+    var = ctx->variables->elts;
+    for (i = 0; i < ctx->variables->nelts; i++) {
         if (name->len != var[i].name.len) {
             continue;
         }
@@ -1663,13 +1808,18 @@
 ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
     ngx_str_t **params)
 {
-    ngx_int_t    rc;
-    ngx_str_t   *uri, *file, *wait, args;
-    ngx_uint_t   flags;
+    ngx_int_t              rc;
+    ngx_str_t             *uri, *file, *wait, *stub, args;
+    ngx_buf_t             *b;
+    ngx_uint_t             flags, i;
+    ngx_chain_t           *out, *cl, *tl, **ll;
+    ngx_http_ssi_ctx_t    *mctx;
+    ngx_http_ssi_block_t  *bl;
 
     uri = params[NGX_HTTP_SSI_INCLUDE_VIRTUAL];
     file = params[NGX_HTTP_SSI_INCLUDE_FILE];
     wait = params[NGX_HTTP_SSI_INCLUDE_WAIT];
+    stub = params[NGX_HTTP_SSI_INCLUDE_STUB];
 
     if (uri && file) {
         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
@@ -1687,8 +1837,7 @@
     if (wait) {
         if (uri == NULL) {
             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
-                          "\"wait\" may not be used with file=\"%V\"",
-                          uri, file);
+                          "\"wait\" may not be used with file=\"%V\"", file);
             return NGX_HTTP_SSI_ERROR;
         }
 
@@ -1699,7 +1848,7 @@
         {
             ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                           "invalid value \"%V\" in the \"wait\" parameter",
-                          &wait);
+                          wait);
             return NGX_HTTP_SSI_ERROR;
         }
     }
@@ -1725,7 +1874,68 @@
         return NGX_HTTP_SSI_ERROR;
     }
 
-    rc = ngx_http_subrequest(r, uri, &args, flags);
+    out = NULL;
+
+    if (stub) {
+        mctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module);
+
+        if (mctx->blocks) {
+            bl = mctx->blocks->elts;
+            for (i = 0; i < mctx->blocks->nelts; i++) {
+                if (stub->len == bl[i].name.len
+                    && ngx_strncmp(stub->data, bl[i].name.data, stub->len) == 0)
+                {
+                    goto found;
+                }
+            }
+        }
+
+        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                      "\"stub\"=\"%V\" for \"include\" not found", stub);
+        return NGX_HTTP_SSI_ERROR;
+
+    found:
+
+        if (bl[i].count++) {
+
+            ll = &out;
+
+            for (tl = bl[i].bufs; tl; tl = tl->next) {
+
+                if (ctx->free) {
+                    cl = ctx->free;
+                    ctx->free = ctx->free->next;
+                    b = cl->buf;
+
+                } else {
+                    b = ngx_alloc_buf(r->pool);
+                    if (b == NULL) {
+                        return NGX_ERROR;
+                    }
+
+                    cl = ngx_alloc_chain_link(r->pool);
+                    if (cl == NULL) {
+                        return NGX_ERROR;
+                    }
+
+                    cl->buf = b;
+                }
+
+                ngx_memcpy(b, tl->buf, sizeof(ngx_buf_t));
+
+                b->pos = b->start;
+
+                *ll = cl;
+                cl->next = NULL;
+                ll = &cl->next;
+            }
+
+        } else {
+            out = bl[i].bufs;
+        }
+    }
+
+    rc = ngx_http_subrequest(r, uri, &args, out, flags);
 
     if (rc == NGX_ERROR) {
         return NGX_HTTP_SSI_ERROR;
@@ -1861,10 +2071,10 @@
 
     mctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module);
 
-    if (mctx->variables.elts == NULL) {
-        if (ngx_array_init(&mctx->variables, r->pool, 4,
-                           sizeof(ngx_http_ssi_var_t)) != NGX_OK)
-        {
+    if (mctx->variables == NULL) {
+        mctx->variables = ngx_array_create(r->pool, 4,
+                                           sizeof(ngx_http_ssi_var_t));
+        if (mctx->variables == NULL) {
             return NGX_HTTP_SSI_ERROR;
         }
     }
@@ -1893,7 +2103,7 @@
         return NGX_OK;
     }
 
-    var = ngx_array_push(&mctx->variables);
+    var = ngx_array_push(mctx->variables);
     if (var == NULL) {
         return NGX_HTTP_SSI_ERROR;
     }
@@ -2136,6 +2346,56 @@
 
 
 static ngx_int_t
+ngx_http_ssi_block(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
+    ngx_str_t **params)
+{
+    ngx_http_ssi_ctx_t    *mctx;
+    ngx_http_ssi_block_t  *bl;
+
+    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                   "ssi block");
+
+    mctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module);
+
+    if (mctx->blocks == NULL) {
+        mctx->blocks = ngx_array_create(r->pool, 4,
+                                        sizeof(ngx_http_ssi_block_t));
+        if (mctx->blocks == NULL) {
+            return NGX_HTTP_SSI_ERROR;
+        }
+    }
+
+    bl = ngx_array_push(mctx->blocks);
+    if (bl == NULL) {
+        return NGX_HTTP_SSI_ERROR;
+    }
+
+    bl->name = *params[NGX_HTTP_SSI_BLOCK_NAME];
+    bl->bufs = NULL;
+    bl->count = 0;
+
+    ctx->output = 0;
+    ctx->block = 1;
+
+    return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_ssi_endblock(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
+    ngx_str_t **params)
+{
+    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                   "ssi endblock");
+
+    ctx->output = 1;
+    ctx->block = 0;
+
+    return NGX_OK;
+}
+
+
+static ngx_int_t
 ngx_http_ssi_date_gmt_local_variable(ngx_http_request_t *r,
     ngx_http_variable_value_t *v,  uintptr_t gmt)
 {
diff --git a/src/http/modules/ngx_http_ssi_filter_module.h b/src/http/modules/ngx_http_ssi_filter_module.h
index 0d9618b..dc3eff0 100644
--- a/src/http/modules/ngx_http_ssi_filter_module.h
+++ b/src/http/modules/ngx_http_ssi_filter_module.h
@@ -56,9 +56,11 @@
 
     size_t                    value_len;
 
-    ngx_array_t               variables;
+    ngx_array_t              *variables;
+    ngx_array_t              *blocks;
 
     unsigned                  conditional:2;
+    unsigned                  block:1;
     unsigned                  output:1;
     unsigned                  output_chosen:1;
     unsigned                  wait:1;
@@ -88,6 +90,7 @@
     ngx_http_ssi_param_t     *params;
 
     unsigned                  conditional:2;
+    unsigned                  block:1;
     unsigned                  flush:1;
 } ngx_http_ssi_command_t;
 
diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c
index a57fbfb..8c78e0f 100644
--- a/src/http/modules/ngx_http_ssl_module.c
+++ b/src/http/modules/ngx_http_ssl_module.c
@@ -85,7 +85,7 @@
       NULL },
 
     { ngx_string("ssl_verify_client"),
-      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_1MORE,
+      NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG,
       ngx_conf_set_flag_slot,
       NGX_HTTP_SRV_CONF_OFFSET,
       offsetof(ngx_http_ssl_srv_conf_t, verify),
diff --git a/src/http/modules/ngx_http_status_module.c b/src/http/modules/ngx_http_status_module.c
index cf4f33f..a2e2dbc 100644
--- a/src/http/modules/ngx_http_status_module.c
+++ b/src/http/modules/ngx_http_status_module.c
@@ -36,7 +36,7 @@
 
 
 
-ngx_http_module_t  ngx_http_status_module_ctx = {
+static ngx_http_module_t  ngx_http_status_module_ctx = {
     NULL,                                  /* pre conf */
 
     NULL,                                  /* create main configuration */
diff --git a/src/http/modules/ngx_http_stub_status_module.c b/src/http/modules/ngx_http_stub_status_module.c
index 7cdb3c1..4fe9c04 100644
--- a/src/http/modules/ngx_http_stub_status_module.c
+++ b/src/http/modules/ngx_http_stub_status_module.c
@@ -26,7 +26,7 @@
 
 
 
-ngx_http_module_t  ngx_http_stub_status_module_ctx = {
+static ngx_http_module_t  ngx_http_stub_status_module_ctx = {
     NULL,                                  /* preconfiguration */
     NULL,                                  /* postconfiguration */
 
diff --git a/src/http/modules/ngx_http_userid_filter_module.c b/src/http/modules/ngx_http_userid_filter_module.c
index bdad35d..648f1ad 100644
--- a/src/http/modules/ngx_http_userid_filter_module.c
+++ b/src/http/modules/ngx_http_userid_filter_module.c
@@ -160,7 +160,7 @@
 };
 
 
-ngx_http_module_t  ngx_http_userid_filter_module_ctx = {
+static ngx_http_module_t  ngx_http_userid_filter_module_ctx = {
     ngx_http_userid_add_variables,         /* preconfiguration */
     NULL,                                  /* postconfiguration */
 
diff --git a/src/http/modules/perl/nginx.xs b/src/http/modules/perl/nginx.xs
index 735cc37..8e287a6 100644
--- a/src/http/modules/perl/nginx.xs
+++ b/src/http/modules/perl/nginx.xs
@@ -199,13 +199,16 @@
     CODE:
 
     dXSTARG;
-    ngx_http_request_t  *r;
-    SV                  *key;
-    u_char              *p;
-    STRLEN               len;
-    ngx_uint_t           i;
-    ngx_list_part_t     *part;
-    ngx_table_elt_t     *header;
+    ngx_http_request_t         *r;
+    SV                         *key;
+    u_char                     *p, *lowcase_key, *cookie;
+    STRLEN                      len;
+    ssize_t                     size;
+    ngx_uint_t                  i, n, hash;
+    ngx_list_part_t            *part;
+    ngx_table_elt_t            *h, **ph;
+    ngx_http_header_t          *hh;
+    ngx_http_core_main_conf_t  *cmcf;
 
     ngx_http_perl_set_request(r);
 
@@ -217,8 +220,85 @@
 
     p = (u_char *) SvPV(key, len);
 
+    /* look up hashed headers */
+
+    lowcase_key = ngx_palloc(r->pool, len);
+    if (lowcase_key == NULL) {
+        XSRETURN_UNDEF;
+    }
+
+    hash = 0;
+    for (i = 0; i < len; i++) {
+        lowcase_key[i] = ngx_tolower(p[i]);
+        hash = ngx_hash(hash, lowcase_key[i]);
+    }
+
+    cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
+
+    hh = ngx_hash_find(&cmcf->headers_in_hash, hash, lowcase_key, len);
+
+    if (hh) {
+        if (hh->offset) {
+
+            ph = (ngx_table_elt_t **) ((char *) &r->headers_in + hh->offset);
+
+            if (*ph) {
+                ngx_http_perl_set_targ((*ph)->value.data, (*ph)->value.len, 0);
+
+                goto done;
+            }
+
+            XSRETURN_UNDEF;
+        }
+
+        /* Cookie */
+
+        n = r->headers_in.cookies.nelts;
+
+        if (n == 0) {
+            XSRETURN_UNDEF;
+        }
+
+        ph = r->headers_in.cookies.elts;
+
+        if (n == 1) {
+            ngx_http_perl_set_targ((*ph)->value.data, (*ph)->value.len, 0);
+
+            goto done;
+        }
+
+        size = - (ssize_t) (sizeof("; ") - 1);
+
+        for (i = 0; i < n; i++) {
+            size += ph[i]->value.len + sizeof("; ") - 1;
+        }
+
+        cookie = ngx_palloc(r->pool, size);
+        if (cookie == NULL) {
+            XSRETURN_UNDEF;
+        }
+
+        p = cookie;
+
+        for (i = 0; /* void */ ; i++) {
+            p = ngx_copy(p, ph[i]->value.data, ph[i]->value.len);
+
+            if (i == n - 1) {
+                break;
+            }
+
+            *p++ = ';'; *p++ = ' ';
+        }
+
+        ngx_http_perl_set_targ(cookie, size, 0);
+
+        goto done;
+    }
+
+    /* iterate over all headers */
+
     part = &r->headers_in.headers.part;
-    header = part->elts;
+    h = part->elts;
 
     for (i = 0; /* void */ ; i++) {
 
@@ -228,17 +308,17 @@
             }
 
             part = part->next;
-            header = part->elts;
+            h = part->elts;
             i = 0;
         }
 
-        if (len != header[i].key.len
-            || ngx_strcasecmp(p, header[i].key.data) != 0)
+        if (len != h[i].key.len
+            || ngx_strcasecmp(p, h[i].key.data) != 0)
         {
             continue;
         }
 
-        ngx_http_perl_set_targ(header[i].value.data, header[i].value.len, 0);
+        ngx_http_perl_set_targ(h[i].value.data, h[i].value.len, 0);
 
         goto done;
     }
diff --git a/src/http/modules/perl/ngx_http_perl_module.c b/src/http/modules/perl/ngx_http_perl_module.c
index bf976e9..b3e1175 100644
--- a/src/http/modules/perl/ngx_http_perl_module.c
+++ b/src/http/modules/perl/ngx_http_perl_module.c
@@ -170,7 +170,7 @@
 };
 
 static ngx_http_ssi_command_t  ngx_http_perl_ssi_command = {
-    ngx_string("perl"), ngx_http_perl_ssi, ngx_http_perl_ssi_params, 0, 1
+    ngx_string("perl"), ngx_http_perl_ssi, ngx_http_perl_ssi_params, 0, 0, 1
 };
 
 #endif