nginx-0.3.47-RELEASE import

    *) Feature: the "upstream" directive.

    *) Change: now the "\" escape symbol in the "\"" and "\'" pairs in the
       SSI command is always removed.
diff --git a/src/http/modules/ngx_http_empty_gif_module.c b/src/http/modules/ngx_http_empty_gif_module.c
index 82bf8c5..b97633a 100644
--- a/src/http/modules/ngx_http_empty_gif_module.c
+++ b/src/http/modules/ngx_http_empty_gif_module.c
@@ -135,7 +135,7 @@
         }
     }
 
-    b = ngx_create_temp_buf(r->pool, sizeof(ngx_empty_gif));
+    b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t));
     if (b == NULL) {
         return NGX_HTTP_INTERNAL_SERVER_ERROR;
     }
@@ -145,6 +145,7 @@
 
     b->pos = ngx_empty_gif;
     b->last = ngx_empty_gif + sizeof(ngx_empty_gif);
+    b->memory = 1;
     b->last_buf = 1;
 
     r->headers_out.status = NGX_HTTP_OK;
diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c
index 777a7dd..82388a6 100644
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -11,16 +11,17 @@
 
 
 typedef struct {
-    ngx_http_upstream_conf_t   upstream;
+    ngx_http_upstream_conf_t       upstream;
 
-    ngx_peers_t               *peers;
+    ngx_http_upstream_srv_conf_t  *upstream_peers;
+    ngx_peers_t                   *peers0;
 
-    ngx_str_t                  index;
+    ngx_str_t                      index;
 
-    ngx_array_t               *flushes;
-    ngx_array_t               *params_len;
-    ngx_array_t               *params;
-    ngx_array_t               *params_source;
+    ngx_array_t                   *flushes;
+    ngx_array_t                   *params_len;
+    ngx_array_t                   *params;
+    ngx_array_t                   *params_source;
 } ngx_http_fastcgi_loc_conf_t;
 
 
@@ -39,14 +40,14 @@
 
 
 typedef struct {
-    ngx_http_fastcgi_state_e   state;
-    u_char                    *pos;
-    u_char                    *last;
-    ngx_uint_t                 type;
-    size_t                     length;
-    size_t                     padding;
+    ngx_http_fastcgi_state_e       state;
+    u_char                        *pos;
+    u_char                        *last;
+    ngx_uint_t                     type;
+    size_t                         length;
+    size_t                         padding;
 
-    ngx_uint_t                 fastcgi_stdout;
+    ngx_uint_t                     fastcgi_stdout;
 } ngx_http_fastcgi_ctx_t;
 
 
@@ -391,8 +392,8 @@
 
     u->peer.log = r->connection->log;
     u->peer.log_error = NGX_ERROR_ERR;
-    u->peer.peers = flcf->peers;
-    u->peer.tries = flcf->peers->number;
+    u->peer.peers = flcf->upstream_peers->peers;
+    u->peer.tries = flcf->upstream_peers->peers->number;
 #if (NGX_THREADS)
     u->peer.lock = &r->connection->lock;
 #endif
@@ -1687,11 +1688,13 @@
     ngx_conf_merge_sec_value(conf->upstream.fail_timeout,
                               prev->upstream.fail_timeout, 10);
 
-    if (conf->peers && conf->peers->number > 1) {
-        for (i = 0; i < conf->peers->number; i++) {
-            conf->peers->peer[i].weight = 1;
-            conf->peers->peer[i].max_fails = conf->upstream.max_fails;
-            conf->peers->peer[i].fail_timeout = conf->upstream.fail_timeout;
+    if (conf->upstream_peers && !conf->upstream_peers->balanced) {
+        for (i = 0; i < conf->upstream_peers->peers->number; i++) {
+            conf->upstream_peers->peers->peer[i].weight = 1;
+            conf->upstream_peers->peers->peer[i].max_fails =
+                                                   conf->upstream.max_fails;
+            conf->upstream_peers->peers->peer[i].fail_timeout =
+                                                   conf->upstream.fail_timeout;
         }
     }
 
@@ -1813,8 +1816,8 @@
 
 peers:
 
-    if (conf->peers == NULL) {
-        conf->peers = prev->peers;
+    if (conf->upstream_peers == NULL) {
+        conf->upstream_peers = prev->upstream_peers;
         conf->upstream.schema = prev->upstream.schema;
     }
 
@@ -1989,12 +1992,9 @@
 {
     ngx_http_fastcgi_loc_conf_t *lcf = conf;
 
+    ngx_url_t                    u;
     ngx_str_t                   *value;
-    ngx_inet_upstream_t          inet_upstream;
     ngx_http_core_loc_conf_t    *clcf;
-#if (NGX_HAVE_UNIX_DOMAIN)
-    ngx_unix_domain_upstream_t   unix_upstream;
-#endif
 
     if (lcf->upstream.schema.len) {
         return "is duplicate";
@@ -2002,40 +2002,14 @@
 
     value = cf->args->elts;
 
-    if (ngx_strncasecmp(value[1].data, "unix:", 5) == 0) {
+    ngx_memzero(&u, sizeof(ngx_url_t));
 
-#if (NGX_HAVE_UNIX_DOMAIN)
+    u.url = value[1];
+    u.upstream = 1;
 
-        ngx_memzero(&unix_upstream, sizeof(ngx_unix_domain_upstream_t));
-
-        unix_upstream.name = value[1];
-        unix_upstream.url = value[1];
-
-        lcf->peers = ngx_unix_upstream_parse(cf, &unix_upstream);
-        if (lcf->peers == NULL) {
-            return NGX_CONF_ERROR;
-        }
-
-        lcf->peers->peer[0].uri_separator = "";
-
-#else
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                           "the unix domain sockets are not supported "
-                           "on this platform");
+    lcf->upstream_peers = ngx_http_upstream_add(cf, &u);
+    if (lcf->upstream_peers == NULL) {
         return NGX_CONF_ERROR;
-
-#endif
-
-    } else {
-        ngx_memzero(&inet_upstream, sizeof(ngx_inet_upstream_t));
-
-        inet_upstream.name = value[1];
-        inet_upstream.url = value[1];
-
-        lcf->peers = ngx_inet_upstream_parse(cf, &inet_upstream);
-        if (lcf->peers == NULL) {
-            return NGX_CONF_ERROR;
-        }
     }
 
     lcf->upstream.schema.len = sizeof("fastcgi://") - 1;
diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
index dd66bfa..f5fb918 100644
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -16,56 +16,56 @@
     ngx_table_elt_t *h, size_t prefix, ngx_http_proxy_redirect_t *pr);
 
 struct ngx_http_proxy_redirect_s {
-    ngx_http_proxy_redirect_pt   handler;
-    ngx_str_t                    redirect;
+    ngx_http_proxy_redirect_pt     handler;
+    ngx_str_t                      redirect;
 
     union {
-        ngx_str_t                text;
+        ngx_str_t                  text;
 
         struct {
-            void                *lengths;
-            void                *values;
+            void                  *lengths;
+            void                  *values;
         } vars;
 
-        void                    *regex;
+        void                      *regex;
     } replacement;
 };
 
 
 typedef struct {
-    ngx_http_upstream_conf_t     upstream;
+    ngx_http_upstream_conf_t       upstream;
 
-    ngx_peers_t                 *peers;
+    ngx_http_upstream_srv_conf_t  *upstream_peers;
 
-    ngx_array_t                 *flushes;
-    ngx_array_t                 *body_set_len;
-    ngx_array_t                 *body_set;
-    ngx_array_t                 *headers_set_len;
-    ngx_array_t                 *headers_set;
-    ngx_hash_t                   headers_set_hash;
+    ngx_array_t                   *flushes;
+    ngx_array_t                   *body_set_len;
+    ngx_array_t                   *body_set;
+    ngx_array_t                   *headers_set_len;
+    ngx_array_t                   *headers_set;
+    ngx_hash_t                     headers_set_hash;
 
-    ngx_array_t                 *headers_source;
-    ngx_array_t                 *headers_names;
+    ngx_array_t                   *headers_source;
+    ngx_array_t                   *headers_names;
 
-    ngx_array_t                 *redirects;
+    ngx_array_t                   *redirects;
 
-    ngx_str_t                    body_source;
+    ngx_str_t                      body_source;
 
-    ngx_str_t                    method;
-    ngx_str_t                    host_header;
-    ngx_str_t                    port_text;
+    ngx_str_t                      method;
+    ngx_str_t                      host_header;
+    ngx_str_t                      port_text;
 
-    ngx_flag_t                   redirect;
+    ngx_flag_t                     redirect;
 } ngx_http_proxy_loc_conf_t;
 
 
 typedef struct {
-    ngx_uint_t                   status;
-    ngx_uint_t                   status_count;
-    u_char                      *status_start;
-    u_char                      *status_end;
+    ngx_uint_t                     status;
+    ngx_uint_t                     status_count;
+    u_char                        *status_start;
+    u_char                        *status_end;
 
-    size_t                       internal_body_length;
+    size_t                         internal_body_length;
 } ngx_http_proxy_ctx_t;
 
 
@@ -407,8 +407,8 @@
 
     u->peer.log = r->connection->log;
     u->peer.log_error = NGX_ERROR_ERR;
-    u->peer.peers = plcf->peers;
-    u->peer.tries = plcf->peers->number;
+    u->peer.peers = plcf->upstream_peers->peers;
+    u->peer.tries = plcf->upstream_peers->peers->number;
 #if (NGX_THREADS)
     u->peer.lock = &r->connection->lock;
 #endif
@@ -1640,11 +1640,13 @@
     ngx_conf_merge_sec_value(conf->upstream.fail_timeout,
                               prev->upstream.fail_timeout, 10);
 
-    if (conf->peers && conf->peers->number > 1) {
-        for (i = 0; i < conf->peers->number; i++) {
-            conf->peers->peer[i].weight = 1;
-            conf->peers->peer[i].max_fails = conf->upstream.max_fails;
-            conf->peers->peer[i].fail_timeout = conf->upstream.fail_timeout;
+    if (conf->upstream_peers && !conf->upstream_peers->balanced) {
+        for (i = 0; i < conf->upstream_peers->peers->number; i++) {
+            conf->upstream_peers->peers->peer[i].weight = 1;
+            conf->upstream_peers->peers->peer[i].max_fails =
+                                                   conf->upstream.max_fails;
+            conf->upstream_peers->peers->peer[i].fail_timeout =
+                                                   conf->upstream.fail_timeout;
         }
     }
 
@@ -1797,8 +1799,8 @@
 
 peers:
 
-    if (conf->peers == NULL) {
-        conf->peers = prev->peers;
+    if (conf->upstream_peers == NULL) {
+        conf->upstream_peers = prev->upstream_peers;
 
         conf->host_header = prev->host_header;
         conf->port_text = prev->port_text;
@@ -2106,14 +2108,11 @@
     size_t                       add;
     u_short                      port;
     ngx_str_t                   *value, *url;
-    ngx_inet_upstream_t          inet_upstream;
+    ngx_url_t                    u;
     ngx_http_core_loc_conf_t    *clcf;
 #if (NGX_HTTP_SSL)
     ngx_pool_cleanup_t          *cln;
 #endif
-#if (NGX_HAVE_UNIX_DOMAIN)
-    ngx_unix_domain_upstream_t   unix_upstream;
-#endif
 
     if (plcf->upstream.schema.len) {
         return "is duplicate";
@@ -2167,53 +2166,23 @@
         return NGX_CONF_ERROR;
     }
 
-    if (ngx_strncasecmp(url->data + add, "unix:", 5) == 0) {
+    ngx_memzero(&u, sizeof(ngx_url_t));
 
-#if (NGX_HAVE_UNIX_DOMAIN)
+    u.url.len = url->len - add;
+    u.url.data = url->data + add;
+    u.default_portn = port;
+    u.uri_part = 1;
+    u.upstream = 1;
 
-        ngx_memzero(&unix_upstream, sizeof(ngx_unix_domain_upstream_t));
-
-        unix_upstream.name = *url;
-        unix_upstream.url.len = url->len - add;
-        unix_upstream.url.data = url->data + add;
-        unix_upstream.uri_part = 1;
-
-        plcf->peers = ngx_unix_upstream_parse(cf, &unix_upstream);
-        if (plcf->peers == NULL) {
-            return NGX_CONF_ERROR;
-        }
-
-        plcf->host_header.len = sizeof("localhost") - 1;
-        plcf->host_header.data = (u_char *) "localhost";
-        plcf->upstream.uri = unix_upstream.uri;
-
-#else
-        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
-                           "the unix domain sockets are not supported "
-                           "on this platform");
+    plcf->upstream_peers = ngx_http_upstream_add(cf, &u);
+    if (plcf->upstream_peers == NULL) {
         return NGX_CONF_ERROR;
-
-#endif
-
-    } else {
-        ngx_memzero(&inet_upstream, sizeof(ngx_inet_upstream_t));
-
-        inet_upstream.name = *url;
-        inet_upstream.url.len = url->len - add;
-        inet_upstream.url.data = url->data + add;
-        inet_upstream.default_port_value = port;
-        inet_upstream.uri_part = 1;
-
-        plcf->peers = ngx_inet_upstream_parse(cf, &inet_upstream);
-        if (plcf->peers == NULL) {
-            return NGX_CONF_ERROR;
-        }
-
-        plcf->host_header = inet_upstream.host_header;
-        plcf->port_text = inet_upstream.port_text;
-        plcf->upstream.uri = inet_upstream.uri;
     }
 
+    plcf->host_header = u.host_header;
+    plcf->port_text = u.port;
+    plcf->upstream.uri = u.uri;
+
     plcf->upstream.schema.len = add;
     plcf->upstream.schema.data = url->data;
 
diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c
index 5024d00..817045e 100644
--- a/src/http/modules/ngx_http_ssi_filter_module.c
+++ b/src/http/modules/ngx_http_ssi_filter_module.c
@@ -1224,38 +1224,14 @@
         case ssi_quoted_symbol_state:
             state = ctx->saved_state;
 
-            if (ch == '\\') {
-                break;
-            }
-
-            if (ch == '"' && state == ssi_double_quoted_value_state) {
-                ctx->param->value.data[ctx->param->value.len - 1] = ch;
-                break;
-            }
-
-            if (ch == '\'' && state == ssi_quoted_value_state) {
-                ctx->param->value.data[ctx->param->value.len - 1] = ch;
-                break;
-            }
-
-            if (ctx->param->value.len == ctx->value_len) {
-                ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
-                              "too long \"%V%c...\" value of \"%V\" "
-                              "parameter in \"%V\" SSI command",
-                              &ctx->param->value, ch, &ctx->param->key,
-                              &ctx->command);
-                state = ssi_error_state;
-                break;
-            }
-
             ctx->param->value.data[ctx->param->value.len++] = ch;
 
             break;
 
         case ssi_postparam_state:
 
-            if (ctx->param->value.len < ctx->value_len / 2) {
-                value = ngx_palloc(r->pool, ctx->param->value.len);
+            if (ctx->param->value.len + 1 < ctx->value_len / 2) {
+                value = ngx_palloc(r->pool, ctx->param->value.len + 1);
                 if (value == NULL) {
                     return NGX_ERROR;
                 }
@@ -1433,7 +1409,7 @@
     size_t                     *size, len, prefix, part_len;
     ngx_str_t                   var, *val;
     ngx_int_t                   key;
-    ngx_uint_t                  i, j, n, bracket;
+    ngx_uint_t                  i, j, n, bracket, quoted;
     ngx_array_t                 lengths, values;
     ngx_http_variable_value_t  *vv;
 
@@ -1567,18 +1543,28 @@
 
         } else {
             part_data = &text->data[i];
+            quoted = 0;
 
             for (p = part_data; i < text->len; i++) {
                 ch = text->data[i];
 
-                if (ch == '$') {
-                    if (text->data[i - 1] != '\\') {
+                if (!quoted) {
+
+                    if (ch == '\\') {
+                        quoted = 1;
+                        continue;
+                    }
+
+                    if (ch == '$') {
                         break;
                     }
 
-                    *(p - 1) = ch;
+                } else {
+                    quoted = 0;
 
-                    continue;
+                    if (ch != '\\' && ch != '\'' && ch != '"' && ch != '$') {
+                        *p++ = '\\';
+                    }
                 }
 
                 *p++ = ch;
@@ -2016,7 +2002,7 @@
         flags = 0;
 
         if (p < last - 1 && p[0] == '\\' && p[1] == '/') {
-	    p++;
+            p++;
         }
     }
 
diff --git a/src/http/modules/perl/ngx_http_perl_module.c b/src/http/modules/perl/ngx_http_perl_module.c
index 6b7298c..975c727 100644
--- a/src/http/modules/perl/ngx_http_perl_module.c
+++ b/src/http/modules/perl/ngx_http_perl_module.c
@@ -399,6 +399,24 @@
 
     dTHXa(ctx->perl);
 
+#if 0
+
+    /* the code is disabled to force the precompiled perl code using only */
+
+    ngx_http_perl_eval_anon_sub(aTHX_ handler, &sv);
+
+    if (sv == &PL_sv_undef) {
+        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                      "eval_pv(\"%V\") failed", handler);
+        return NGX_ERROR;
+    }
+
+    if (sv == NULL) {
+        sv = newSVpvn((char *) handler->data, handler->len);
+    }
+
+#endif
+
     sv = newSVpvn((char *) handler->data, handler->len);
 
     rc = ngx_http_perl_call_handler(aTHX_ r, sv, &params[NGX_HTTP_PERL_SSI_ARG],