summaryrefslogtreecommitdiff
path: root/src/http
diff options
context:
space:
mode:
authorNGINX team <nginx@nginx.org>2012-02-15 14:39:49 +0000
committerJon Kolb <jon@b0g.us>2012-02-15 14:39:49 +0000
commit616d163c4ad4900518e06187809dab9d0dd6e2c9 (patch)
tree6fa8ead9a35711578f7ce2b1bd88c4641189b880 /src/http
parent01f0bd5ae6dffe914b2909caf428f565a1c60351 (diff)
downloadnginx-616d163c4ad4900518e06187809dab9d0dd6e2c9.tar.gz
Changes with nginx 1.1.15 15 Feb 2012v1.1.15
*) Feature: the "disable_symlinks" directive. *) Feature: the "proxy_cookie_domain" and "proxy_cookie_path" directives. *) Bugfix: nginx might log incorrect error "upstream prematurely closed connection" instead of correct "upstream sent too big header" one. Thanks to Feibo Li. *) Bugfix: nginx could not be built with the ngx_http_perl_module if the --with-openssl option was used. *) Bugfix: internal redirects to named locations were not limited. *) Bugfix: calling $r->flush() multiple times might cause errors in the ngx_http_gzip_filter_module. *) Bugfix: temporary files might be not removed if the "proxy_store" directive were used with SSI includes. *) Bugfix: in some cases non-cacheable variables (such as the $args variable) returned old empty cached value. *) Bugfix: a segmentation fault might occur in a worker process if too many SSI subrequests were issued simultaneously; the bug had appeared in 0.7.25.
Diffstat (limited to 'src/http')
-rw-r--r--src/http/modules/ngx_http_flv_module.c7
-rw-r--r--src/http/modules/ngx_http_gzip_filter_module.c22
-rw-r--r--src/http/modules/ngx_http_gzip_static_module.c7
-rw-r--r--src/http/modules/ngx_http_headers_filter_module.c6
-rw-r--r--src/http/modules/ngx_http_index_module.c22
-rw-r--r--src/http/modules/ngx_http_limit_conn_module.c4
-rw-r--r--src/http/modules/ngx_http_log_module.c14
-rw-r--r--src/http/modules/ngx_http_mp4_module.c7
-rw-r--r--src/http/modules/ngx_http_proxy_module.c533
-rw-r--r--src/http/modules/ngx_http_range_filter_module.c26
-rw-r--r--src/http/modules/ngx_http_static_module.c7
-rw-r--r--src/http/modules/ngx_http_userid_filter_module.c6
-rw-r--r--src/http/modules/perl/Makefile.PL6
-rw-r--r--src/http/modules/perl/nginx.pm2
-rw-r--r--src/http/modules/perl/nginx.xs3
-rw-r--r--src/http/ngx_http_busy_lock.c2
-rw-r--r--src/http/ngx_http_core_module.c62
-rw-r--r--src/http/ngx_http_core_module.h4
-rw-r--r--src/http/ngx_http_file_cache.c15
-rw-r--r--src/http/ngx_http_request.c5
-rw-r--r--src/http/ngx_http_request.h2
-rw-r--r--src/http/ngx_http_script.c3
-rw-r--r--src/http/ngx_http_upstream.c62
-rw-r--r--src/http/ngx_http_upstream.h2
-rw-r--r--src/http/ngx_http_variables.c2
25 files changed, 657 insertions, 174 deletions
diff --git a/src/http/modules/ngx_http_flv_module.c b/src/http/modules/ngx_http_flv_module.c
index f6870235b..292e37013 100644
--- a/src/http/modules/ngx_http_flv_module.c
+++ b/src/http/modules/ngx_http_flv_module.c
@@ -109,6 +109,9 @@ ngx_http_flv_handler(ngx_http_request_t *r)
of.min_uses = clcf->open_file_cache_min_uses;
of.errors = clcf->open_file_cache_errors;
of.events = clcf->open_file_cache_events;
+#if (NGX_HAVE_OPENAT)
+ of.disable_symlinks = clcf->disable_symlinks;
+#endif
if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
!= NGX_OK)
@@ -127,6 +130,10 @@ ngx_http_flv_handler(ngx_http_request_t *r)
break;
case NGX_EACCES:
+#if (NGX_HAVE_OPENAT)
+ case NGX_EMLINK:
+ case NGX_ELOOP:
+#endif
level = NGX_LOG_ERR;
rc = NGX_HTTP_FORBIDDEN;
diff --git a/src/http/modules/ngx_http_gzip_filter_module.c b/src/http/modules/ngx_http_gzip_filter_module.c
index 4429e01ba..128d3d9c8 100644
--- a/src/http/modules/ngx_http_gzip_filter_module.c
+++ b/src/http/modules/ngx_http_gzip_filter_module.c
@@ -759,6 +759,7 @@ static ngx_int_t
ngx_http_gzip_filter_deflate(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx)
{
int rc;
+ ngx_buf_t *b;
ngx_chain_t *cl;
ngx_http_gzip_conf_t *conf;
@@ -770,7 +771,7 @@ ngx_http_gzip_filter_deflate(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx)
rc = deflate(&ctx->zstream, ctx->flush);
- if (rc != Z_OK && rc != Z_STREAM_END) {
+ if (rc != Z_OK && rc != Z_STREAM_END && rc != Z_BUF_ERROR) {
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
"deflate() failed: %d, %d", ctx->flush, rc);
return NGX_ERROR;
@@ -819,8 +820,6 @@ ngx_http_gzip_filter_deflate(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx)
if (ctx->flush == Z_SYNC_FLUSH) {
- ctx->zstream.avail_out = 0;
- ctx->out_buf->flush = 1;
ctx->flush = Z_NO_FLUSH;
cl = ngx_alloc_chain_link(r->pool);
@@ -828,7 +827,22 @@ ngx_http_gzip_filter_deflate(ngx_http_request_t *r, ngx_http_gzip_ctx_t *ctx)
return NGX_ERROR;
}
- cl->buf = ctx->out_buf;
+ b = ctx->out_buf;
+
+ if (ngx_buf_size(b) == 0) {
+
+ b = ngx_calloc_buf(ctx->request->pool);
+ if (b == NULL) {
+ return NGX_ERROR;
+ }
+
+ } else {
+ ctx->zstream.avail_out = 0;
+ }
+
+ b->flush = 1;
+
+ cl->buf = b;
cl->next = NULL;
*ctx->last_out = cl;
ctx->last_out = &cl->next;
diff --git a/src/http/modules/ngx_http_gzip_static_module.c b/src/http/modules/ngx_http_gzip_static_module.c
index 18c28d8f5..2fad280e9 100644
--- a/src/http/modules/ngx_http_gzip_static_module.c
+++ b/src/http/modules/ngx_http_gzip_static_module.c
@@ -129,6 +129,9 @@ ngx_http_gzip_static_handler(ngx_http_request_t *r)
of.min_uses = clcf->open_file_cache_min_uses;
of.errors = clcf->open_file_cache_errors;
of.events = clcf->open_file_cache_events;
+#if (NGX_HAVE_OPENAT)
+ of.disable_symlinks = clcf->disable_symlinks;
+#endif
if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
!= NGX_OK)
@@ -145,6 +148,10 @@ ngx_http_gzip_static_handler(ngx_http_request_t *r)
return NGX_DECLINED;
case NGX_EACCES:
+#if (NGX_HAVE_OPENAT)
+ case NGX_EMLINK:
+ case NGX_ELOOP:
+#endif
level = NGX_LOG_ERR;
break;
diff --git a/src/http/modules/ngx_http_headers_filter_module.c b/src/http/modules/ngx_http_headers_filter_module.c
index daa17623c..ff33f1f78 100644
--- a/src/http/modules/ngx_http_headers_filter_module.c
+++ b/src/http/modules/ngx_http_headers_filter_module.c
@@ -530,7 +530,7 @@ ngx_http_headers_expires(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
hcf->expires_time = ngx_parse_time(&value[n], 1);
- if (hcf->expires_time == NGX_ERROR) {
+ if (hcf->expires_time == (time_t) NGX_ERROR) {
return "invalid value";
}
@@ -540,10 +540,6 @@ ngx_http_headers_expires(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return "daily time value must be less than 24 hours";
}
- if (hcf->expires_time == NGX_PARSE_LARGE_TIME) {
- return "value must be less than 68 years";
- }
-
if (minus) {
hcf->expires_time = - hcf->expires_time;
}
diff --git a/src/http/modules/ngx_http_index_module.c b/src/http/modules/ngx_http_index_module.c
index 0835a7cf8..7d99c18e5 100644
--- a/src/http/modules/ngx_http_index_module.c
+++ b/src/http/modules/ngx_http_index_module.c
@@ -209,6 +209,9 @@ ngx_http_index_handler(ngx_http_request_t *r)
of.test_only = 1;
of.errors = clcf->open_file_cache_errors;
of.events = clcf->open_file_cache_events;
+#if (NGX_HAVE_OPENAT)
+ of.disable_symlinks = clcf->disable_symlinks;
+#endif
if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
!= NGX_OK)
@@ -220,6 +223,14 @@ ngx_http_index_handler(ngx_http_request_t *r)
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
+#if (NGX_HAVE_OPENAT)
+ if (of.err == NGX_EMLINK
+ || of.err == NGX_ELOOP)
+ {
+ return NGX_HTTP_FORBIDDEN;
+ }
+#endif
+
if (of.err == NGX_ENOTDIR
|| of.err == NGX_ENAMETOOLONG
|| of.err == NGX_EACCES)
@@ -296,12 +307,23 @@ ngx_http_index_test_dir(ngx_http_request_t *r, ngx_http_core_loc_conf_t *clcf,
of.test_only = 1;
of.valid = clcf->open_file_cache_valid;
of.errors = clcf->open_file_cache_errors;
+#if (NGX_HAVE_OPENAT)
+ of.disable_symlinks = clcf->disable_symlinks;
+#endif
if (ngx_open_cached_file(clcf->open_file_cache, &dir, &of, r->pool)
!= NGX_OK)
{
if (of.err) {
+#if (NGX_HAVE_OPENAT)
+ if (of.err == NGX_EMLINK
+ || of.err == NGX_ELOOP)
+ {
+ return NGX_HTTP_FORBIDDEN;
+ }
+#endif
+
if (of.err == NGX_ENOENT) {
*last = c;
return ngx_http_index_error(r, clcf, dir.data, NGX_ENOENT);
diff --git a/src/http/modules/ngx_http_limit_conn_module.c b/src/http/modules/ngx_http_limit_conn_module.c
index f98e7bc51..6322fd682 100644
--- a/src/http/modules/ngx_http_limit_conn_module.c
+++ b/src/http/modules/ngx_http_limit_conn_module.c
@@ -159,8 +159,6 @@ ngx_http_limit_conn_handler(ngx_http_request_t *r)
return NGX_DECLINED;
}
- r->main->limit_conn_set = 1;
-
lccf = ngx_http_get_module_loc_conf(r, ngx_http_limit_conn_module);
limits = lccf->limits.elts;
@@ -187,6 +185,8 @@ ngx_http_limit_conn_handler(ngx_http_request_t *r)
continue;
}
+ r->main->limit_conn_set = 1;
+
hash = ngx_crc32_short(vv->data, len);
shpool = (ngx_slab_pool_t *) limits[i].shm_zone->shm.addr;
diff --git a/src/http/modules/ngx_http_log_module.c b/src/http/modules/ngx_http_log_module.c
index c55131772..da3b33c96 100644
--- a/src/http/modules/ngx_http_log_module.c
+++ b/src/http/modules/ngx_http_log_module.c
@@ -373,6 +373,8 @@ ngx_http_log_script_write(ngx_http_request_t *r, ngx_http_log_script_t *script,
ngx_http_log_loc_conf_t *llcf;
ngx_http_core_loc_conf_t *clcf;
+ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
if (!r->root_tested) {
/* test root directory existance */
@@ -384,8 +386,6 @@ ngx_http_log_script_write(ngx_http_request_t *r, ngx_http_log_script_t *script,
path.data[root] = '\0';
- clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-
ngx_memzero(&of, sizeof(ngx_open_file_info_t));
of.valid = clcf->open_file_cache_valid;
@@ -394,6 +394,9 @@ ngx_http_log_script_write(ngx_http_request_t *r, ngx_http_log_script_t *script,
of.test_only = 1;
of.errors = clcf->open_file_cache_errors;
of.events = clcf->open_file_cache_events;
+#if (NGX_HAVE_OPENAT)
+ of.disable_symlinks = clcf->disable_symlinks;
+#endif
if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
!= NGX_OK)
@@ -441,6 +444,9 @@ ngx_http_log_script_write(ngx_http_request_t *r, ngx_http_log_script_t *script,
of.valid = llcf->open_file_cache_valid;
of.min_uses = llcf->open_file_cache_min_uses;
of.directio = NGX_OPEN_FILE_DIRECTIO_OFF;
+#if (NGX_HAVE_OPENAT)
+ of.disable_symlinks = clcf->disable_symlinks;
+#endif
if (ngx_open_cached_file(llcf->open_file_cache, &log, &of, r->pool)
!= NGX_OK)
@@ -1249,7 +1255,7 @@ ngx_http_log_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
s.data = value[i].data + 9;
inactive = ngx_parse_time(&s, 1);
- if (inactive < 0) {
+ if (inactive == (time_t) NGX_ERROR) {
goto failed;
}
@@ -1272,7 +1278,7 @@ ngx_http_log_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
s.data = value[i].data + 6;
valid = ngx_parse_time(&s, 1);
- if (valid < 0) {
+ if (valid == (time_t) NGX_ERROR) {
goto failed;
}
diff --git a/src/http/modules/ngx_http_mp4_module.c b/src/http/modules/ngx_http_mp4_module.c
index 816cc4c83..f63b2bc56 100644
--- a/src/http/modules/ngx_http_mp4_module.c
+++ b/src/http/modules/ngx_http_mp4_module.c
@@ -440,6 +440,9 @@ ngx_http_mp4_handler(ngx_http_request_t *r)
of.min_uses = clcf->open_file_cache_min_uses;
of.errors = clcf->open_file_cache_errors;
of.events = clcf->open_file_cache_events;
+#if (NGX_HAVE_OPENAT)
+ of.disable_symlinks = clcf->disable_symlinks;
+#endif
if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
!= NGX_OK)
@@ -458,6 +461,10 @@ ngx_http_mp4_handler(ngx_http_request_t *r)
break;
case NGX_EACCES:
+#if (NGX_HAVE_OPENAT)
+ case NGX_EMLINK:
+ case NGX_ELOOP:
+#endif
level = NGX_LOG_ERR;
rc = NGX_HTTP_FORBIDDEN;
diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
index fb86f0106..f2bff3d3d 100644
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -10,20 +10,21 @@
#include <ngx_http.h>
-typedef struct ngx_http_proxy_redirect_s ngx_http_proxy_redirect_t;
+typedef struct ngx_http_proxy_rewrite_s ngx_http_proxy_rewrite_t;
-typedef ngx_int_t (*ngx_http_proxy_redirect_pt)(ngx_http_request_t *r,
- ngx_table_elt_t *h, size_t prefix, ngx_http_proxy_redirect_t *pr);
+typedef ngx_int_t (*ngx_http_proxy_rewrite_pt)(ngx_http_request_t *r,
+ ngx_table_elt_t *h, size_t prefix, size_t len,
+ ngx_http_proxy_rewrite_t *pr);
-struct ngx_http_proxy_redirect_s {
- ngx_http_proxy_redirect_pt handler;
+struct ngx_http_proxy_rewrite_s {
+ ngx_http_proxy_rewrite_pt handler;
union {
ngx_http_complex_value_t complex;
#if (NGX_PCRE)
ngx_http_regex_t *regex;
#endif
- } redirect;
+ } pattern;
ngx_http_complex_value_t replacement;
};
@@ -54,6 +55,8 @@ typedef struct {
ngx_array_t *proxy_values;
ngx_array_t *redirects;
+ ngx_array_t *cookie_domains;
+ ngx_array_t *cookie_paths;
ngx_str_t body_source;
@@ -123,6 +126,12 @@ static ngx_int_t
ngx_http_variable_value_t *v, uintptr_t data);
static ngx_int_t ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r,
ngx_table_elt_t *h, size_t prefix);
+static ngx_int_t ngx_http_proxy_rewrite_cookie(ngx_http_request_t *r,
+ ngx_table_elt_t *h);
+static ngx_int_t ngx_http_proxy_rewrite_cookie_value(ngx_http_request_t *r,
+ ngx_table_elt_t *h, u_char *value, ngx_array_t *rewrites);
+static ngx_int_t ngx_http_proxy_rewrite(ngx_http_request_t *r,
+ ngx_table_elt_t *h, size_t prefix, size_t len, ngx_str_t *replacement);
static ngx_int_t ngx_http_proxy_add_variables(ngx_conf_t *cf);
static void *ngx_http_proxy_create_loc_conf(ngx_conf_t *cf);
@@ -135,6 +144,10 @@ static char *ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
+static char *ngx_http_proxy_cookie_domain(ngx_conf_t *cf, ngx_command_t *cmd,
+ void *conf);
+static char *ngx_http_proxy_cookie_path(ngx_conf_t *cf, ngx_command_t *cmd,
+ void *conf);
static char *ngx_http_proxy_store(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
#if (NGX_HTTP_CACHE)
@@ -146,6 +159,9 @@ static char *ngx_http_proxy_cache_key(ngx_conf_t *cf, ngx_command_t *cmd,
static char *ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data);
+static ngx_int_t ngx_http_proxy_rewrite_regex(ngx_conf_t *cf,
+ ngx_http_proxy_rewrite_t *pr, ngx_str_t *regex, ngx_uint_t caseless);
+
#if (NGX_HTTP_SSL)
static ngx_int_t ngx_http_proxy_set_ssl(ngx_conf_t *cf,
ngx_http_proxy_loc_conf_t *plcf);
@@ -198,6 +214,20 @@ static ngx_command_t ngx_http_proxy_commands[] = {
0,
NULL },
+ { ngx_string("proxy_cookie_domain"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
+ ngx_http_proxy_cookie_domain,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ 0,
+ NULL },
+
+ { ngx_string("proxy_cookie_path"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE12,
+ ngx_http_proxy_cookie_path,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ 0,
+ NULL },
+
{ ngx_string("proxy_store"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_http_proxy_store,
@@ -649,6 +679,10 @@ ngx_http_proxy_handler(ngx_http_request_t *r)
u->rewrite_redirect = ngx_http_proxy_rewrite_redirect;
}
+ if (plcf->cookie_domains || plcf->cookie_paths) {
+ u->rewrite_cookie = ngx_http_proxy_rewrite_cookie;
+ }
+
u->buffering = plcf->upstream.buffering;
u->pipe = ngx_pcalloc(r->pool, sizeof(ngx_event_pipe_t));
@@ -2272,10 +2306,11 @@ static ngx_int_t
ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r, ngx_table_elt_t *h,
size_t prefix)
{
+ size_t len;
ngx_int_t rc;
ngx_uint_t i;
+ ngx_http_proxy_rewrite_t *pr;
ngx_http_proxy_loc_conf_t *plcf;
- ngx_http_proxy_redirect_t *pr;
plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
@@ -2285,8 +2320,10 @@ ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r, ngx_table_elt_t *h,
return NGX_DECLINED;
}
+ len = h->value.len - prefix;
+
for (i = 0; i < plcf->redirects->nelts; i++) {
- rc = pr[i].handler(r, h, prefix, &pr[i]);
+ rc = pr[i].handler(r, h, prefix, len, &pr[i]);
if (rc != NGX_DECLINED) {
return rc;
@@ -2298,65 +2335,127 @@ ngx_http_proxy_rewrite_redirect(ngx_http_request_t *r, ngx_table_elt_t *h,
static ngx_int_t
-ngx_http_proxy_rewrite_redirect_complex(ngx_http_request_t *r,
- ngx_table_elt_t *h, size_t prefix, ngx_http_proxy_redirect_t *pr)
+ngx_http_proxy_rewrite_cookie(ngx_http_request_t *r, ngx_table_elt_t *h)
{
- size_t len;
- u_char *data, *p;
- ngx_str_t redirect, replacement;
+ size_t prefix;
+ u_char *p;
+ ngx_int_t rc, rv;
+ ngx_http_proxy_loc_conf_t *plcf;
- if (ngx_http_complex_value(r, &pr->redirect.complex, &redirect) != NGX_OK) {
- return NGX_ERROR;
+ p = (u_char *) ngx_strchr(h->value.data, ';');
+ if (p == NULL) {
+ return NGX_DECLINED;
}
- if (redirect.len > h->value.len - prefix
- || ngx_rstrncmp(h->value.data + prefix, redirect.data,
- redirect.len) != 0)
- {
- return NGX_DECLINED;
+ prefix = p + 1 - h->value.data;
+
+ rv = NGX_DECLINED;
+
+ plcf = ngx_http_get_module_loc_conf(r, ngx_http_proxy_module);
+
+ if (plcf->cookie_domains) {
+ p = ngx_strcasestrn(h->value.data + prefix, "domain=", 7 - 1);
+
+ if (p) {
+ rc = ngx_http_proxy_rewrite_cookie_value(r, h, p + 7,
+ plcf->cookie_domains);
+ if (rc == NGX_ERROR) {
+ return NGX_ERROR;
+ }
+
+ if (rc != NGX_DECLINED) {
+ rv = rc;
+ }
+ }
}
- if (ngx_http_complex_value(r, &pr->replacement, &replacement) != NGX_OK) {
- return NGX_ERROR;
+ if (plcf->cookie_paths) {
+ p = ngx_strcasestrn(h->value.data + prefix, "path=", 5 - 1);
+
+ if (p) {
+ rc = ngx_http_proxy_rewrite_cookie_value(r, h, p + 5,
+ plcf->cookie_paths);
+ if (rc == NGX_ERROR) {
+ return NGX_ERROR;
+ }
+
+ if (rc != NGX_DECLINED) {
+ rv = rc;
+ }
+ }
}
- len = replacement.len + h->value.len - redirect.len;
+ return rv;
+}
+
- data = ngx_pnalloc(r->pool, len);
- if (data == NULL) {
- return NGX_ERROR;
+static ngx_int_t
+ngx_http_proxy_rewrite_cookie_value(ngx_http_request_t *r, ngx_table_elt_t *h,
+ u_char *value, ngx_array_t *rewrites)
+{
+ size_t len, prefix;
+ u_char *p;
+ ngx_int_t rc;
+ ngx_uint_t i;
+ ngx_http_proxy_rewrite_t *pr;
+
+ prefix = value - h->value.data;
+
+ p = (u_char *) ngx_strchr(value, ';');
+
+ len = p ? (size_t) (p - value) : (h->value.len - prefix);
+
+ pr = rewrites->elts;
+
+ for (i = 0; i < rewrites->nelts; i++) {
+ rc = pr[i].handler(r, h, prefix, len, &pr[i]);
+
+ if (rc != NGX_DECLINED) {
+ return rc;
+ }
}
- p = ngx_copy(data, h->value.data, prefix);
+ return NGX_DECLINED;
+}
+
- if (replacement.len) {
- p = ngx_copy(p, replacement.data, replacement.len);
+static ngx_int_t
+ngx_http_proxy_rewrite_complex_handler(ngx_http_request_t *r,
+ ngx_table_elt_t *h, size_t prefix, size_t len, ngx_http_proxy_rewrite_t *pr)
+{
+ ngx_str_t pattern, replacement;
+
+ if (ngx_http_complex_value(r, &pr->pattern.complex, &pattern) != NGX_OK) {
+ return NGX_ERROR;
}
- ngx_memcpy(p, h->value.data + prefix + redirect.len,
- h->value.len - redirect.len - prefix);
+ if (pattern.len > len
+ || ngx_rstrncmp(h->value.data + prefix, pattern.data,
+ pattern.len) != 0)
+ {
+ return NGX_DECLINED;
+ }
- h->value.len = len;
- h->value.data = data;
+ if (ngx_http_complex_value(r, &pr->replacement, &replacement) != NGX_OK) {
+ return NGX_ERROR;
+ }
- return NGX_OK;
+ return ngx_http_proxy_rewrite(r, h, prefix, pattern.len, &replacement);
}
#if (NGX_PCRE)
static ngx_int_t
-ngx_http_proxy_rewrite_redirect_regex(ngx_http_request_t *r, ngx_table_elt_t *h,
- size_t prefix, ngx_http_proxy_redirect_t *pr)
+ngx_http_proxy_rewrite_regex_handler(ngx_http_request_t *r, ngx_table_elt_t *h,
+ size_t prefix, size_t len, ngx_http_proxy_rewrite_t *pr)
{
- size_t len;
- u_char *data;
- ngx_str_t redirect, replacement;
+ ngx_str_t pattern, replacement;
- redirect.len = h->value.len - prefix;
- redirect.data = h->value.data + prefix;
+ pattern.len = len;
+ pattern.data = h->value.data + prefix;
- if (ngx_http_regex_exec(r, pr->redirect.regex, &redirect) != NGX_OK) {
+ if (ngx_http_regex_exec(r, pr->pattern.regex, &pattern) != NGX_OK) {
return NGX_DECLINED;
}
@@ -2364,28 +2463,84 @@ ngx_http_proxy_rewrite_redirect_regex(ngx_http_request_t *r, ngx_table_elt_t *h,
return NGX_ERROR;
}
- if (!prefix) {
+ if (prefix == 0 && h->value.len == len) {
h->value = replacement;
return NGX_OK;
}
- len = prefix + replacement.len;
+ return ngx_http_proxy_rewrite(r, h, prefix, len, &replacement);
+}
- data = ngx_pnalloc(r->pool, len);
- if (data == NULL) {
+#endif
+
+
+static ngx_int_t
+ngx_http_proxy_rewrite_domain_handler(ngx_http_request_t *r,
+ ngx_table_elt_t *h, size_t prefix, size_t len, ngx_http_proxy_rewrite_t *pr)
+{
+ u_char *p;
+ ngx_str_t pattern, replacement;
+
+ if (ngx_http_complex_value(r, &pr->pattern.complex, &pattern) != NGX_OK) {
return NGX_ERROR;
}
- ngx_memcpy(data, h->value.data, prefix);
- ngx_memcpy(data + prefix, replacement.data, replacement.len);
+ p = h->value.data + prefix;
- h->value.len = len;
- h->value.data = data;
+ if (p[0] == '.') {
+ p++;
+ prefix++;
+ len--;
+ }
- return NGX_OK;
+ if (pattern.len != len || ngx_rstrncasecmp(pattern.data, p, len) != 0) {
+ return NGX_DECLINED;
+ }
+
+ if (ngx_http_complex_value(r, &pr->replacement, &replacement) != NGX_OK) {
+ return NGX_ERROR;
+ }
+
+ return ngx_http_proxy_rewrite(r, h, prefix, len, &replacement);
}
-#endif
+
+static ngx_int_t
+ngx_http_proxy_rewrite(ngx_http_request_t *r, ngx_table_elt_t *h, size_t prefix,
+ size_t len, ngx_str_t *replacement)
+{
+ u_char *p, *data;
+ size_t new_len;
+
+ new_len = replacement->len + h->value.len - len;
+
+ if (replacement->len > len) {
+
+ data = ngx_pnalloc(r->pool, new_len);
+ if (data == NULL) {
+ return NGX_ERROR;
+ }
+
+ p = ngx_copy(data, h->value.data, prefix);
+ p = ngx_copy(p, replacement->data, replacement->len);
+
+ ngx_memcpy(p, h->value.data + prefix + len,
+ h->value.len - len - prefix);
+
+ h->value.data = data;
+
+ } else {
+ p = ngx_copy(h->value.data + prefix, replacement->data,
+ replacement->len);
+
+ ngx_memmove(p, h->value.data + prefix + len,
+ h->value.len - len - prefix);
+ }
+
+ h->value.len = new_len;
+
+ return NGX_OK;
+}
static ngx_int_t
@@ -2486,6 +2641,9 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
conf->redirect = NGX_CONF_UNSET;
conf->upstream.change_buffering = 1;
+ conf->cookie_domains = NGX_CONF_UNSET_PTR;
+ conf->cookie_paths = NGX_CONF_UNSET_PTR;
+
conf->http_version = NGX_CONF_UNSET_UINT;
conf->headers_hash_max_size = NGX_CONF_UNSET_UINT;
@@ -2507,7 +2665,7 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
size_t size;
ngx_hash_init_t hash;
ngx_http_core_loc_conf_t *clcf;
- ngx_http_proxy_redirect_t *pr;
+ ngx_http_proxy_rewrite_t *pr;
ngx_http_script_compile_t sc;
if (conf->upstream.store != 0) {
@@ -2760,7 +2918,7 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
if (conf->redirects == NULL && conf->url.data) {
conf->redirects = ngx_array_create(cf->pool, 1,
- sizeof(ngx_http_proxy_redirect_t));
+ sizeof(ngx_http_proxy_rewrite_t));
if (conf->redirects == NULL) {
return NGX_CONF_ERROR;
}
@@ -2770,27 +2928,27 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
return NGX_CONF_ERROR;
}
- ngx_memzero(&pr->redirect.complex,
+ ngx_memzero(&pr->pattern.complex,
sizeof(ngx_http_complex_value_t));
ngx_memzero(&pr->replacement, sizeof(ngx_http_complex_value_t));
- pr->handler = ngx_http_proxy_rewrite_redirect_complex;
+ pr->handler = ngx_http_proxy_rewrite_complex_handler;
if (conf->vars.uri.len) {
- pr->redirect.complex.value = conf->url;
+ pr->pattern.complex.value = conf->url;
pr->replacement.value = conf->location;
} else {
- pr->redirect.complex.value.len = conf->url.len
- + sizeof("/") - 1;
+ pr->pattern.complex.value.len = conf->url.len
+ + sizeof("/") - 1;
- p = ngx_pnalloc(cf->pool, pr->redirect.complex.value.len);
+ p = ngx_pnalloc(cf->pool, pr->pattern.complex.value.len);
if (p == NULL) {
return NGX_CONF_ERROR;
}
- pr->redirect.complex.value.data = p;
+ pr->pattern.complex.value.data = p;
p = ngx_cpymem(p, conf->url.data, conf->url.len);
*p = '/';
@@ -2800,6 +2958,10 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
}
}
+ ngx_conf_merge_ptr_value(conf->cookie_domains, prev->cookie_domains, NULL);
+
+ ngx_conf_merge_ptr_value(conf->cookie_paths, prev->cookie_paths, NULL);
+
#if (NGX_HTTP_SSL)
if (conf->upstream.ssl == NULL) {
conf->upstream.ssl = prev->upstream.ssl;
@@ -3285,7 +3447,7 @@ ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
u_char *p;
ngx_str_t *value;
- ngx_http_proxy_redirect_t *pr;
+ ngx_http_proxy_rewrite_t *pr;
ngx_http_compile_complex_value_t ccv;
if (plcf->redirect == 0) {
@@ -3320,7 +3482,7 @@ ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
if (plcf->redirects == NULL) {
plcf->redirects = ngx_array_create(cf->pool, 1,
- sizeof(ngx_http_proxy_redirect_t));
+ sizeof(ngx_http_proxy_rewrite_t));
if (plcf->redirects == NULL) {
return NGX_CONF_ERROR;
}
@@ -3346,25 +3508,25 @@ ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return NGX_CONF_ERROR;
}
- pr->handler = ngx_http_proxy_rewrite_redirect_complex;
+ pr->handler = ngx_http_proxy_rewrite_complex_handler;
- ngx_memzero(&pr->redirect.complex, sizeof(ngx_http_complex_value_t));
+ ngx_memzero(&pr->pattern.complex, sizeof(ngx_http_complex_value_t));
ngx_memzero(&pr->replacement, sizeof(ngx_http_complex_value_t));
if (plcf->vars.uri.len) {
- pr->redirect.complex.value = plcf->url;
+ pr->pattern.complex.value = plcf->url;
pr->replacement.value = plcf->location;
} else {
- pr->redirect.complex.value.len = plcf->url.len + sizeof("/") - 1;
+ pr->pattern.complex.value.len = plcf->url.len + sizeof("/") - 1;
- p = ngx_pnalloc(cf->pool, pr->redirect.complex.value.len);
+ p = ngx_pnalloc(cf->pool, pr->pattern.complex.value.len);
if (p == NULL) {
return NGX_CONF_ERROR;
}
- pr->redirect.complex.value.data = p;
+ pr->pattern.complex.value.data = p;
p = ngx_cpymem(p, plcf->url.data, plcf->url.len);
*p = '/';
@@ -3377,54 +3539,212 @@ ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
if (value[1].data[0] == '~') {
-#if (NGX_PCRE)
- u_char errstr[NGX_MAX_CONF_ERRSTR];
- ngx_regex_compile_t rc;
-
value[1].len--;
value[1].data++;
- ngx_memzero(&rc, sizeof(ngx_regex_compile_t));
-
if (value[1].data[0] == '*') {
value[1].len--;
value[1].data++;
- rc.options = NGX_REGEX_CASELESS;
+
+ if (ngx_http_proxy_rewrite_regex(cf, pr, &value[1], 1) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+
+ } else {
+ if (ngx_http_proxy_rewrite_regex(cf, pr, &value[1], 0) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
}
- rc.pattern = value[1];
- rc.err.len = NGX_MAX_CONF_ERRSTR;
- rc.err.data = errstr;
+ } else {
+
+ ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
+
+ ccv.cf = cf;
+ ccv.value = &value[1];
+ ccv.complex_value = &pr->pattern.complex;
- pr->redirect.regex = ngx_http_regex_compile(cf, &rc);
- if (pr->redirect.regex == NULL) {
+ if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
return NGX_CONF_ERROR;
}
- pr->handler = ngx_http_proxy_rewrite_redirect_regex;
+ pr->handler = ngx_http_proxy_rewrite_complex_handler;
+ }
+
+
+ ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
+
+ ccv.cf = cf;
+ ccv.value = &value[2];
+ ccv.complex_value = &pr->replacement;
+
+ if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+
+ return NGX_CONF_OK;
+}
+
+
+static char *
+ngx_http_proxy_cookie_domain(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+ ngx_http_proxy_loc_conf_t *plcf = conf;
+
+ ngx_str_t *value;
+ ngx_http_proxy_rewrite_t *pr;
+ ngx_http_compile_complex_value_t ccv;
+
+ if (plcf->cookie_domains == NULL) {
+ return NGX_CONF_OK;
+ }
+
+ value = cf->args->elts;
+
+ if (cf->args->nelts == 2) {
+
+ if (ngx_strcmp(value[1].data, "off") == 0) {
+ plcf->cookie_domains = NULL;
+ return NGX_CONF_OK;
+ }
-#else
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "using regex \"%V\" requires PCRE library",
- &value[1]);
+ "invalid parameter \"%V\"", &value[1]);
+ return NGX_CONF_ERROR;
+ }
+
+ if (plcf->cookie_domains == NGX_CONF_UNSET_PTR) {
+ plcf->cookie_domains = ngx_array_create(cf->pool, 1,
+ sizeof(ngx_http_proxy_rewrite_t));
+ if (plcf->cookie_domains == NULL) {
+ return NGX_CONF_ERROR;
+ }
+ }
+ pr = ngx_array_push(plcf->cookie_domains);
+ if (pr == NULL) {
return NGX_CONF_ERROR;
-#endif
+ }
+
+ if (value[1].data[0] == '~') {
+ value[1].len--;
+ value[1].data++;
+
+ if (ngx_http_proxy_rewrite_regex(cf, pr, &value[1], 1) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+
} else {
+ if (value[1].data[0] == '.') {
+ value[1].len--;
+ value[1].data++;
+ }
+
ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
ccv.cf = cf;
ccv.value = &value[1];
- ccv.complex_value = &pr->redirect.complex;
+ ccv.complex_value = &pr->pattern.complex;
if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
return NGX_CONF_ERROR;
}
- pr->handler = ngx_http_proxy_rewrite_redirect_complex;
+ pr->handler = ngx_http_proxy_rewrite_domain_handler;
+
+ if (value[2].data[0] == '.') {
+ value[2].len--;
+ value[2].data++;
+ }
+ }
+
+ ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
+
+ ccv.cf = cf;
+ ccv.value = &value[2];
+ ccv.complex_value = &pr->replacement;
+
+ if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+
+ return NGX_CONF_OK;
+}
+
+
+static char *
+ngx_http_proxy_cookie_path(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+ ngx_http_proxy_loc_conf_t *plcf = conf;
+
+ ngx_str_t *value;
+ ngx_http_proxy_rewrite_t *pr;
+ ngx_http_compile_complex_value_t ccv;
+
+ if (plcf->cookie_paths == NULL) {
+ return NGX_CONF_OK;
+ }
+
+ value = cf->args->elts;
+
+ if (cf->args->nelts == 2) {
+
+ if (ngx_strcmp(value[1].data, "off") == 0) {
+ plcf->cookie_paths = NULL;
+ return NGX_CONF_OK;
+ }
+
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid parameter \"%V\"", &value[1]);
+ return NGX_CONF_ERROR;
+ }
+
+ if (plcf->cookie_paths == NGX_CONF_UNSET_PTR) {
+ plcf->cookie_paths = ngx_array_create(cf->pool, 1,
+ sizeof(ngx_http_proxy_rewrite_t));
+ if (plcf->cookie_paths == NULL) {
+ return NGX_CONF_ERROR;
+ }
+ }
+
+ pr = ngx_array_push(plcf->cookie_paths);
+ if (pr == NULL) {
+ return NGX_CONF_ERROR;
}
+ if (value[1].data[0] == '~') {
+ value[1].len--;
+ value[1].data++;
+
+ if (value[1].data[0] == '*') {
+ value[1].len--;
+ value[1].data++;
+
+ if (ngx_http_proxy_rewrite_regex(cf, pr, &value[1], 1) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+
+ } else {
+ if (ngx_http_proxy_rewrite_regex(cf, pr, &value[1], 0) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+ }
+
+ } else {
+
+ ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
+
+ ccv.cf = cf;
+ ccv.value = &value[1];
+ ccv.complex_value = &pr->pattern.complex;
+
+ if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
+ return NGX_CONF_ERROR;
+ }
+
+ pr->handler = ngx_http_proxy_rewrite_complex_handler;
+ }
ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
@@ -3440,6 +3760,43 @@ ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
+static ngx_int_t
+ngx_http_proxy_rewrite_regex(ngx_conf_t *cf, ngx_http_proxy_rewrite_t *pr,
+ ngx_str_t *regex, ngx_uint_t caseless)
+{
+#if (NGX_PCRE)
+ u_char errstr[NGX_MAX_CONF_ERRSTR];
+ ngx_regex_compile_t rc;
+
+ ngx_memzero(&rc, sizeof(ngx_regex_compile_t));
+
+ rc.pattern = *regex;
+ rc.err.len = NGX_MAX_CONF_ERRSTR;
+ rc.err.data = errstr;
+
+ if (caseless) {
+ rc.options = NGX_REGEX_CASELESS;
+ }
+
+ pr->pattern.regex = ngx_http_regex_compile(cf, &rc);
+ if (pr->pattern.regex == NULL) {
+ return NGX_ERROR;
+ }
+
+ pr->handler = ngx_http_proxy_rewrite_regex_handler;
+
+ return NGX_OK;
+
+#else
+
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "using regex \"%V\" requires PCRE library", regex);
+ return NGX_ERROR;
+
+#endif
+}
+
+
static char *
ngx_http_proxy_store(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
diff --git a/src/http/modules/ngx_http_range_filter_module.c b/src/http/modules/ngx_http_range_filter_module.c
index 3380e5e0e..0eaeff915 100644
--- a/src/http/modules/ngx_http_range_filter_module.c
+++ b/src/http/modules/ngx_http_range_filter_module.c
@@ -595,15 +595,8 @@ ngx_http_range_test_overlapped(ngx_http_request_t *r,
buf = in->buf;
if (!buf->last_buf) {
-
- if (buf->in_file) {
- start = buf->file_pos + ctx->offset;
- last = buf->file_last + ctx->offset;
-
- } else {
- start = buf->pos - buf->start + ctx->offset;
- last = buf->last - buf->start + ctx->offset;
- }
+ start = ctx->offset;
+ last = ctx->offset + ngx_buf_size(buf);
range = ctx->ranges.elts;
for (i = 0; i < ctx->ranges.nelts; i++) {
@@ -716,7 +709,6 @@ static ngx_int_t
ngx_http_range_multipart_body(ngx_http_request_t *r,
ngx_http_range_filter_ctx_t *ctx, ngx_chain_t *in)
{
- off_t body_start;
ngx_buf_t *b, *buf;
ngx_uint_t i;
ngx_chain_t *out, *hcl, *rcl, *dcl, **ll;
@@ -726,12 +718,6 @@ ngx_http_range_multipart_body(ngx_http_request_t *r,
buf = in->buf;
range = ctx->ranges.elts;
-#if (NGX_HTTP_CACHE)
- body_start = r->cached ? r->cache->body_start : 0;
-#else
- body_start = 0;
-#endif
-
for (i = 0; i < ctx->ranges.nelts; i++) {
/*
@@ -792,13 +778,13 @@ ngx_http_range_multipart_body(ngx_http_request_t *r,
b->file = buf->file;
if (buf->in_file) {
- b->file_pos = body_start + range[i].start;
- b->file_last = body_start + range[i].end;
+ b->file_pos = buf->file_pos + range[i].start;
+ b->file_last = buf->file_pos + range[i].end;
}
if (ngx_buf_in_memory(buf)) {
- b->pos = buf->start + (size_t) range[i].start;
- b->last = buf->start + (size_t) range[i].end;
+ b->pos = buf->pos + (size_t) range[i].start;
+ b->last = buf->pos + (size_t) range[i].end;
}
dcl = ngx_alloc_chain_link(r->pool);
diff --git a/src/http/modules/ngx_http_static_module.c b/src/http/modules/ngx_http_static_module.c
index a0e302ad1..f4904fc00 100644
--- a/src/http/modules/ngx_http_static_module.c
+++ b/src/http/modules/ngx_http_static_module.c
@@ -94,6 +94,9 @@ ngx_http_static_handler(ngx_http_request_t *r)
of.min_uses = clcf->open_file_cache_min_uses;
of.errors = clcf->open_file_cache_errors;
of.events = clcf->open_file_cache_events;
+#if (NGX_HAVE_OPENAT)
+ of.disable_symlinks = clcf->disable_symlinks;
+#endif
if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
!= NGX_OK)
@@ -112,6 +115,10 @@ ngx_http_static_handler(ngx_http_request_t *r)
break;
case NGX_EACCES:
+#if (NGX_HAVE_OPENAT)
+ case NGX_EMLINK:
+ case NGX_ELOOP:
+#endif
level = NGX_LOG_ERR;
rc = NGX_HTTP_FORBIDDEN;
diff --git a/src/http/modules/ngx_http_userid_filter_module.c b/src/http/modules/ngx_http_userid_filter_module.c
index 894e2c14e..8713dd629 100644
--- a/src/http/modules/ngx_http_userid_filter_module.c
+++ b/src/http/modules/ngx_http_userid_filter_module.c
@@ -774,14 +774,10 @@ ngx_http_userid_expires(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
ucf->expires = ngx_parse_time(&value[1], 1);
- if (ucf->expires == NGX_ERROR) {
+ if (ucf->expires == (time_t) NGX_ERROR) {
return "invalid value";
}
- if (ucf->expires == NGX_PARSE_LARGE_TIME) {
- return "value must be less than 68 years";
- }
-
return NGX_CONF_OK;
}
diff --git a/src/http/modules/perl/Makefile.PL b/src/http/modules/perl/Makefile.PL
index 6575f284c..cfb38c190 100644
--- a/src/http/modules/perl/Makefile.PL
+++ b/src/http/modules/perl/Makefile.PL
@@ -25,7 +25,11 @@ WriteMakefile(
"-I ../../../../../$ENV{NGX_OBJS} " .
($ENV{NGX_PCRE} =~ /^(YES|NO)/ ? "" :
($ENV{NGX_PCRE} =~ m#^/# ? "-I $ENV{NGX_PCRE} " :
- "-I ../../../../../$ENV{NGX_PCRE} ")),
+ "-I ../../../../../$ENV{NGX_PCRE} ")) .
+ ($ENV{NGX_OPENSSL} =~ /^(YES|NO)/ ? "" :
+ ($ENV{NGX_OPENSSL} =~ m#^/# ?
+ "-I $ENV{NGX_OPENSSL}/.openssl/include " :
+ "-I ../../../../../$ENV{NGX_OPENSSL}/.openssl/include ")),
depend => {
'nginx.c' =>
diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm
index 7f060d745..b671c2dd0 100644
--- a/src/http/modules/perl/nginx.pm
+++ b/src/http/modules/perl/nginx.pm
@@ -48,7 +48,7 @@ our @EXPORT = qw(
HTTP_INSUFFICIENT_STORAGE
);
-our $VERSION = '1.1.14';
+our $VERSION = '1.1.15';
require XSLoader;
XSLoader::load('nginx', $VERSION);
diff --git a/src/http/modules/perl/nginx.xs b/src/http/modules/perl/nginx.xs
index dc69d509a..8def03eb1 100644
--- a/src/http/modules/perl/nginx.xs
+++ b/src/http/modules/perl/nginx.xs
@@ -662,6 +662,9 @@ sendfile(r, filename, offset = -1, bytes = 0)
of.min_uses = clcf->open_file_cache_min_uses;
of.errors = clcf->open_file_cache_errors;
of.events = clcf->open_file_cache_events;
+#if (NGX_HAVE_OPENAT)
+ of.disable_symlinks = clcf->disable_symlinks;
+#endif
if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
!= NGX_OK)
diff --git a/src/http/ngx_http_busy_lock.c b/src/http/ngx_http_busy_lock.c
index 35a03acaa..cd8e07cd6 100644
--- a/src/http/ngx_http_busy_lock.c
+++ b/src/http/ngx_http_busy_lock.c
@@ -274,7 +274,7 @@ char *ngx_http_set_busy_lock_slot(ngx_conf_t *cf, ngx_command_t *cmd,
line.data = value[i].data + 2;
bl->timeout = ngx_parse_time(&line, 1);
- if (bl->timeout == NGX_ERROR) {
+ if (bl->timeout == (time_t) NGX_ERROR) {
invalid = 1;
break;
}
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index 251f932fd..35b538b6e 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -187,6 +187,18 @@ static ngx_str_t ngx_http_gzip_private = ngx_string("private");
#endif
+#if (NGX_HAVE_OPENAT)
+
+static ngx_conf_enum_t ngx_http_core_disable_symlinks[] = {
+ { ngx_string("off"), NGX_DISABLE_SYMLINKS_OFF },
+ { ngx_string("if_not_owner"), NGX_DISABLE_SYMLINKS_NOTOWNER },
+ { ngx_string("on"), NGX_DISABLE_SYMLINKS_ON },
+ { ngx_null_string, 0 }
+};
+
+#endif
+
+
static ngx_command_t ngx_http_core_commands[] = {
{ ngx_string("variables_hash_max_size"),
@@ -764,6 +776,17 @@ static ngx_command_t ngx_http_core_commands[] = {
#endif
+#if (NGX_HAVE_OPENAT)
+
+ { ngx_string("disable_symlinks"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_enum_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_core_loc_conf_t, disable_symlinks),
+ &ngx_http_core_disable_symlinks },
+
+#endif
+
ngx_null_command
};
@@ -1297,6 +1320,9 @@ ngx_http_core_try_files_phase(ngx_http_request_t *r,
of.test_only = 1;
of.errors = clcf->open_file_cache_errors;
of.events = clcf->open_file_cache_events;
+#if (NGX_HAVE_OPENAT)
+ of.disable_symlinks = clcf->disable_symlinks;
+#endif
if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
!= NGX_OK)
@@ -2453,7 +2479,6 @@ ngx_http_subrequest(ngx_http_request_t *r,
sr->start_sec = tp->sec;
sr->start_msec = tp->msec;
- r->main->subrequests++;
r->main->count++;
*psr = sr;
@@ -2525,6 +2550,16 @@ ngx_http_named_location(ngx_http_request_t *r, ngx_str_t *name)
ngx_http_core_main_conf_t *cmcf;
r->main->count++;
+ r->uri_changes--;
+
+ if (r->uri_changes == 0) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "rewrite or internal redirection cycle "
+ "while redirect to named location \"%V\"", name);
+
+ ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+ return NGX_DONE;
+ }
cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module);
@@ -3335,6 +3370,10 @@ ngx_http_core_create_loc_conf(ngx_conf_t *cf)
#endif
#endif
+#if (NGX_HAVE_OPENAT)
+ clcf->disable_symlinks = NGX_CONF_UNSET_UINT;
+#endif
+
return clcf;
}
@@ -3614,6 +3653,11 @@ ngx_http_core_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
#endif
#endif
+#if (NGX_HAVE_OPENAT)
+ ngx_conf_merge_uint_value(conf->disable_symlinks, prev->disable_symlinks,
+ NGX_DISABLE_SYMLINKS_OFF);
+#endif
+
return NGX_CONF_OK;
}
@@ -3844,7 +3888,7 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
s.len = p - s.data;
lsopt.tcp_keepidle = ngx_parse_time(&s, 1);
- if (lsopt.tcp_keepidle == NGX_ERROR) {
+ if (lsopt.tcp_keepidle == (time_t) NGX_ERROR) {
goto invalid_so_keepalive;
}
}
@@ -3860,7 +3904,7 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
s.len = p - s.data;
lsopt.tcp_keepintvl = ngx_parse_time(&s, 1);
- if (lsopt.tcp_keepintvl == NGX_ERROR) {
+ if (lsopt.tcp_keepintvl == (time_t) NGX_ERROR) {
goto invalid_so_keepalive;
}
}
@@ -4507,7 +4551,7 @@ ngx_http_core_open_file_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
s.data = value[i].data + 9;
inactive = ngx_parse_time(&s, 1);
- if (inactive < 0) {
+ if (inactive == (time_t) NGX_ERROR) {
goto failed;
}
@@ -4594,24 +4638,16 @@ ngx_http_core_keepalive(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return "invalid value";
}
- if (clcf->keepalive_timeout == (ngx_msec_t) NGX_PARSE_LARGE_TIME) {
- return "value must be less than 597 hours";
- }
-
if (cf->args->nelts == 2) {
return NGX_CONF_OK;
}
clcf->keepalive_header = ngx_parse_time(&value[2], 1);
- if (clcf->keepalive_header == NGX_ERROR) {
+ if (clcf->keepalive_header == (time_t) NGX_ERROR) {
return "invalid value";
}
- if (clcf->keepalive_header == NGX_PARSE_LARGE_TIME) {
- return "value must be less than 68 years";
- }
-
return NGX_CONF_OK;
}
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
index 38f58dfcb..3d6408a1e 100644
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -404,6 +404,10 @@ struct ngx_http_core_loc_conf_s {
#endif
#endif
+#if (NGX_HAVE_OPENAT)
+ ngx_uint_t disable_symlinks; /* disable_symlinks */
+#endif
+
ngx_array_t *error_pages; /* error_page */
ngx_http_try_file_t *try_files; /* try_files */
diff --git a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c
index 4840233ed..eb1e99015 100644
--- a/src/http/ngx_http_file_cache.c
+++ b/src/http/ngx_http_file_cache.c
@@ -1597,7 +1597,8 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
time_t inactive;
ssize_t size;
ngx_str_t s, name, *value;
- ngx_int_t loader_files, loader_sleep, loader_threshold;
+ ngx_int_t loader_files;
+ ngx_msec_t loader_sleep, loader_threshold;
ngx_uint_t i, n;
ngx_http_file_cache_t *cache;
@@ -1704,7 +1705,7 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
s.data = value[i].data + 9;
inactive = ngx_parse_time(&s, 1);
- if (inactive < 0) {
+ if (inactive == (time_t) NGX_ERROR) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid inactive value \"%V\"", &value[i]);
return NGX_CONF_ERROR;
@@ -1746,7 +1747,7 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
s.data = value[i].data + 13;
loader_sleep = ngx_parse_time(&s, 0);
- if (loader_sleep < 0) {
+ if (loader_sleep == (ngx_msec_t) NGX_ERROR) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid loader_sleep value \"%V\"", &value[i]);
return NGX_CONF_ERROR;
@@ -1761,7 +1762,7 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
s.data = value[i].data + 17;
loader_threshold = ngx_parse_time(&s, 0);
- if (loader_threshold < 0) {
+ if (loader_threshold == (ngx_msec_t) NGX_ERROR) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid loader_threshold value \"%V\"", &value[i]);
return NGX_CONF_ERROR;
@@ -1788,8 +1789,8 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
cache->path->conf_file = cf->conf_file->file.name.data;
cache->path->line = cf->conf_file->line;
cache->loader_files = loader_files;
- cache->loader_sleep = (ngx_msec_t) loader_sleep;
- cache->loader_threshold = (ngx_msec_t) loader_threshold;
+ cache->loader_sleep = loader_sleep;
+ cache->loader_threshold = loader_threshold;
if (ngx_add_path(cf, &cache->path) != NGX_OK) {
return NGX_CONF_ERROR;
@@ -1843,7 +1844,7 @@ ngx_http_file_cache_valid_set_slot(ngx_conf_t *cf, ngx_command_t *cmd,
n = cf->args->nelts - 1;
valid = ngx_parse_time(&value[n], 1);
- if (valid < 0) {
+ if (valid == (time_t) NGX_ERROR) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid time value \"%V\"", &value[n]);
return NGX_CONF_ERROR;
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 2b3f0065b..a8515f376 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -2010,6 +2010,7 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
if (r == c->data) {
r->main->count--;
+ r->main->subrequests++;
if (!r->logged) {
@@ -2927,6 +2928,10 @@ ngx_http_post_action(ngx_http_request_t *r)
return NGX_DECLINED;
}
+ if (r->post_action && r->uri_changes == 0) {
+ return NGX_DECLINED;
+ }
+
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"post action: \"%V\"", &clcf->post_action);
diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
index 220aa139b..108dba92d 100644
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -478,7 +478,7 @@ struct ngx_http_request_s {
/*
* instead of using the request context data in
- * ngx_http_limit_zone_module and ngx_http_limit_req_module
+ * ngx_http_limit_conn_module and ngx_http_limit_req_module
* we use the single bits in the request structure
*/
unsigned limit_conn_set:1;
diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c
index 77ac9a629..a8f193a32 100644
--- a/src/http/ngx_http_script.c
+++ b/src/http/ngx_http_script.c
@@ -1505,6 +1505,9 @@ ngx_http_script_file_code(ngx_http_script_engine_t *e)
of.test_only = 1;
of.errors = clcf->open_file_cache_errors;
of.events = clcf->open_file_cache_events;
+#if (NGX_HAVE_OPENAT)
+ of.disable_symlinks = clcf->disable_symlinks;
+#endif
if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool)
!= NGX_OK)
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index ba21c0135..4504d9823 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -110,6 +110,8 @@ static ngx_int_t ngx_http_upstream_rewrite_location(ngx_http_request_t *r,
ngx_table_elt_t *h, ngx_uint_t offset);
static ngx_int_t ngx_http_upstream_rewrite_refresh(ngx_http_request_t *r,
ngx_table_elt_t *h, ngx_uint_t offset);
+static ngx_int_t ngx_http_upstream_rewrite_set_cookie(ngx_http_request_t *r,
+ ngx_table_elt_t *h, ngx_uint_t offset);
static ngx_int_t ngx_http_upstream_copy_allow_ranges(ngx_http_request_t *r,
ngx_table_elt_t *h, ngx_uint_t offset);
@@ -198,7 +200,7 @@ ngx_http_upstream_header_t ngx_http_upstream_headers_in[] = {
{ ngx_string("Set-Cookie"),
ngx_http_upstream_process_set_cookie, 0,
- ngx_http_upstream_copy_header_line, 0, 1 },
+ ngx_http_upstream_rewrite_set_cookie, 0, 1 },
{ ngx_string("Content-Disposition"),
ngx_http_upstream_ignore_header_line, 0,
@@ -1591,7 +1593,7 @@ ngx_http_upstream_process_header(ngx_http_request_t *r, ngx_http_upstream_t *u)
if (rc == NGX_AGAIN) {
- if (u->buffer.pos == u->buffer.end) {
+ if (u->buffer.last == u->buffer.end) {
ngx_log_error(NGX_LOG_ERR, c->log, 0,
"upstream sent too big header");
@@ -2649,7 +2651,6 @@ ngx_http_upstream_process_upstream(ngx_http_request_t *r,
static void
ngx_http_upstream_process_request(ngx_http_request_t *r)
{
- ngx_uint_t del;
ngx_temp_file_t *tf;
ngx_event_pipe_t *p;
ngx_http_upstream_t *u;
@@ -2661,30 +2662,16 @@ ngx_http_upstream_process_request(ngx_http_request_t *r)
if (u->store) {
- del = p->upstream_error;
-
- tf = u->pipe->temp_file;
-
if (p->upstream_eof || p->upstream_done) {
+ tf = u->pipe->temp_file;
+
if (u->headers_in.status_n == NGX_HTTP_OK
&& (u->headers_in.content_length_n == -1
|| (u->headers_in.content_length_n == tf->offset)))
{
ngx_http_upstream_store(r, u);
-
- } else {
- del = 1;
- }
- }
-
- if (del && tf->file.fd != NGX_INVALID_FILE) {
-
- if (ngx_delete_file(tf->file.name.data) == NGX_FILE_ERROR) {
-
- ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
- ngx_delete_file_n " \"%s\" failed",
- u->pipe->temp_file->file.name.data);
+ u->store = 0;
}
}
}
@@ -3047,6 +3034,18 @@ ngx_http_upstream_finalize_request(ngx_http_request_t *r,
u->pipe->temp_file->file.fd);
}
+ if (u->store && u->pipe && u->pipe->temp_file
+ && u->pipe->temp_file->file.fd != NGX_INVALID_FILE)
+ {
+ if (ngx_delete_file(u->pipe->temp_file->file.name.data)
+ == NGX_FILE_ERROR)
+ {
+ ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno,
+ ngx_delete_file_n " \"%s\" failed",
+ u->pipe->temp_file->file.name.data);
+ }
+ }
+
#if (NGX_HTTP_CACHE)
if (r->cache) {
@@ -3673,6 +3672,27 @@ ngx_http_upstream_rewrite_refresh(ngx_http_request_t *r, ngx_table_elt_t *h,
static ngx_int_t
+ngx_http_upstream_rewrite_set_cookie(ngx_http_request_t *r, ngx_table_elt_t *h,
+ ngx_uint_t offset)
+{
+ ngx_table_elt_t *ho;
+
+ ho = ngx_list_push(&r->headers_out.headers);
+ if (ho == NULL) {
+ return NGX_ERROR;
+ }
+
+ *ho = *h;
+
+ if (r->upstream->rewrite_cookie) {
+ return r->upstream->rewrite_cookie(r, ho);
+ }
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
ngx_http_upstream_copy_allow_ranges(ngx_http_request_t *r,
ngx_table_elt_t *h, ngx_uint_t offset)
{
@@ -4248,7 +4268,7 @@ ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
fail_timeout = ngx_parse_time(&s, 1);
- if (fail_timeout == NGX_ERROR) {
+ if (fail_timeout == (time_t) NGX_ERROR) {
goto invalid;
}
diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h
index d99b904fb..f32c98522 100644
--- a/src/http/ngx_http_upstream.h
+++ b/src/http/ngx_http_upstream.h
@@ -299,6 +299,8 @@ struct ngx_http_upstream_s {
ngx_int_t rc);
ngx_int_t (*rewrite_redirect)(ngx_http_request_t *r,
ngx_table_elt_t *h, size_t prefix);
+ ngx_int_t (*rewrite_cookie)(ngx_http_request_t *r,
+ ngx_table_elt_t *h);
ngx_msec_t timeout;
diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c
index d6bb92c98..78cfa234a 100644
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -432,7 +432,7 @@ ngx_http_get_flushed_variable(ngx_http_request_t *r, ngx_uint_t index)
v = &r->variables[index];
- if (v->valid) {
+ if (v->valid || v->not_found) {
if (!v->no_cacheable) {
return v;
}