summaryrefslogtreecommitdiff
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
parent01f0bd5ae6dffe914b2909caf428f565a1c60351 (diff)
downloadnginx-1.1.15.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.
-rw-r--r--CHANGES30
-rw-r--r--CHANGES.ru30
-rw-r--r--auto/lib/perl/make1
-rwxr-xr-xauto/unix24
-rw-r--r--src/core/nginx.h4
-rw-r--r--src/core/ngx_conf_file.c10
-rw-r--r--src/core/ngx_core.h5
-rw-r--r--src/core/ngx_open_file_cache.c370
-rw-r--r--src/core/ngx_open_file_cache.h8
-rw-r--r--src/core/ngx_parse.h3
-rw-r--r--src/core/ngx_resolver.c2
-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
-rw-r--r--src/mail/ngx_mail_core_module.c4
-rw-r--r--src/os/unix/ngx_errno.h5
-rw-r--r--src/os/unix/ngx_files.h19
-rw-r--r--src/os/unix/ngx_posix_init.c6
40 files changed, 1123 insertions, 229 deletions
diff --git a/CHANGES b/CHANGES
index 8655769d9..e460866ec 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,34 @@
+Changes with nginx 1.1.15 15 Feb 2012
+
+ *) 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.
+
+
Changes with nginx 1.1.14 30 Jan 2012
*) Feature: multiple "limit_req" limits may be used simultaneously.
diff --git a/CHANGES.ru b/CHANGES.ru
index 8811c92f2..9f71304c1 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,34 @@
+Изменения в nginx 1.1.15 15.02.2012
+
+ *) Добавление: директива disable_symlinks.
+
+ *) Добавление: директивы proxy_cookie_domain и proxy_cookie_path.
+
+ *) Исправление: nginx мог некорректно сообщать об ошибке "upstream
+ prematurely closed connection" вместо "upstream sent too big header".
+ Спасибо Feibo Li.
+
+ *) Исправление: nginx не собирался с модулем ngx_http_perl_module, если
+ использовался параметр --with-openssl.
+
+ *) Исправление: количество внутренних перенаправлений в именованные
+ location'ы не ограничивалось.
+
+ *) Исправление: вызов $r->flush() несколько раз подряд мог приводить к
+ ошибкам в модуле ngx_http_gzip_filter_module.
+
+ *) Исправление: при использовании директивы proxy_store с
+ SSI-подзапросами временные файлы могли не удаляться.
+
+ *) Исправление: в некоторых случаях некэшируемые переменные (такие, как
+ $args) возвращали старое пустое закэшированное значение.
+
+ *) Исправление: в рабочем процессе мог произойти segmentation fault,
+ если одновременно создавалось слишком много SSI-подзапросов; ошибка
+ появилась в 0.7.25.
+
+
Изменения в nginx 1.1.14 30.01.2012
*) Добавление: теперь можно указать несколько ограничений limit_req
diff --git a/auto/lib/perl/make b/auto/lib/perl/make
index f5d9ab501..b4df01dd9 100644
--- a/auto/lib/perl/make
+++ b/auto/lib/perl/make
@@ -28,6 +28,7 @@ $NGX_OBJS/src/http/modules/perl/Makefile: \
&& NGX_PM_CFLAGS="\$(NGX_PM_CFLAGS) -g $NGX_CC_OPT" \
NGX_PCRE=$PCRE \
NGX_OBJS=$NGX_OBJS \
+ NGX_OPENSSL=$OPENSSL \
$NGX_PERL Makefile.PL \
LIB=$NGX_PERL_MODULES \
INSTALLSITEMAN3DIR=$NGX_PERL_MODULES_MAN
diff --git a/auto/unix b/auto/unix
index 398b9bec4..d786bb433 100755
--- a/auto/unix
+++ b/auto/unix
@@ -721,3 +721,27 @@ ngx_feature_path=
ngx_feature_libs=
ngx_feature_test="struct dirent dir; dir.d_type = DT_REG"
. auto/feature
+
+
+ngx_feature="sysconf(_SC_NPROCESSORS_ONLN)"
+ngx_feature_name="NGX_HAVE_SC_NPROCESSORS_ONLN"
+ngx_feature_run=no
+ngx_feature_incs=
+ngx_feature_path=
+ngx_feature_libs=
+ngx_feature_test="sysconf(_SC_NPROCESSORS_ONLN)"
+. auto/feature
+
+
+ngx_feature="openat(), fstatat()"
+ngx_feature_name="NGX_HAVE_OPENAT"
+ngx_feature_run=no
+ngx_feature_incs="#include <sys/types.h>
+ #include <sys/stat.h>
+ #include <fcntl.h>"
+ngx_feature_path=
+ngx_feature_libs=
+ngx_feature_test="struct stat sb;
+ openat(AT_FDCWD, \".\", O_RDONLY|O_NOFOLLOW);
+ fstatat(AT_FDCWD, \".\", &sb, AT_SYMLINK_NOFOLLOW);"
+. auto/feature
diff --git a/src/core/nginx.h b/src/core/nginx.h
index 3105fa349..a22b37732 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -9,8 +9,8 @@
#define _NGINX_H_INCLUDED_
-#define nginx_version 1001014
-#define NGINX_VERSION "1.1.14"
+#define nginx_version 1001015
+#define NGINX_VERSION "1.1.15"
#define NGINX_VER "nginx/" NGINX_VERSION
#define NGINX_VAR "NGINX"
diff --git a/src/core/ngx_conf_file.c b/src/core/ngx_conf_file.c
index 832650141..6d998a5f0 100644
--- a/src/core/ngx_conf_file.c
+++ b/src/core/ngx_conf_file.c
@@ -1295,10 +1295,6 @@ ngx_conf_set_msec_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
return "invalid value";
}
- if (*msp == (ngx_msec_t) NGX_PARSE_LARGE_TIME) {
- return "value must be less than 597 hours";
- }
-
if (cmd->post) {
post = cmd->post;
return post->post_handler(cf, post, msp);
@@ -1326,14 +1322,10 @@ ngx_conf_set_sec_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
value = cf->args->elts;
*sp = ngx_parse_time(&value[1], 1);
- if (*sp == NGX_ERROR) {
+ if (*sp == (time_t) NGX_ERROR) {
return "invalid value";
}
- if (*sp == NGX_PARSE_LARGE_TIME) {
- return "value must be less than 68 years";
- }
-
if (cmd->post) {
post = cmd->post;
return post->post_handler(cf, post, sp);
diff --git a/src/core/ngx_core.h b/src/core/ngx_core.h
index 1ae55163d..435ce64e7 100644
--- a/src/core/ngx_core.h
+++ b/src/core/ngx_core.h
@@ -91,5 +91,10 @@ typedef void (*ngx_connection_handler_pt)(ngx_connection_t *c);
void ngx_cpuinfo(void);
+#if (NGX_HAVE_OPENAT)
+#define NGX_DISABLE_SYMLINKS_OFF 0
+#define NGX_DISABLE_SYMLINKS_ON 1
+#define NGX_DISABLE_SYMLINKS_NOTOWNER 2
+#endif
#endif /* _NGX_CORE_H_INCLUDED_ */
diff --git a/src/core/ngx_open_file_cache.c b/src/core/ngx_open_file_cache.c
index 9ac552111..c871f74b1 100644
--- a/src/core/ngx_open_file_cache.c
+++ b/src/core/ngx_open_file_cache.c
@@ -22,8 +22,17 @@
static void ngx_open_file_cache_cleanup(void *data);
-static ngx_int_t ngx_open_and_stat_file(u_char *name, ngx_open_file_info_t *of,
- ngx_log_t *log);
+#if (NGX_HAVE_OPENAT)
+static ngx_fd_t ngx_openat_file_owner(ngx_fd_t at_fd, const u_char *name,
+ ngx_int_t mode, ngx_int_t create, ngx_int_t access, ngx_log_t *log);
+#endif
+static ngx_fd_t ngx_open_file_wrapper(ngx_str_t *name,
+ ngx_open_file_info_t *of, ngx_int_t mode, ngx_int_t create,
+ ngx_int_t access, ngx_log_t *log);
+static ngx_int_t ngx_file_info_wrapper(ngx_str_t *name,
+ ngx_open_file_info_t *of, ngx_file_info_t *fi, ngx_log_t *log);
+static ngx_int_t ngx_open_and_stat_file(ngx_str_t *name,
+ ngx_open_file_info_t *of, ngx_log_t *log);
static void ngx_open_file_add_event(ngx_open_file_cache_t *cache,
ngx_cached_open_file_t *file, ngx_open_file_info_t *of, ngx_log_t *log);
static void ngx_open_file_cleanup(void *data);
@@ -147,9 +156,9 @@ ngx_open_cached_file(ngx_open_file_cache_t *cache, ngx_str_t *name,
if (of->test_only) {
- if (ngx_file_info(name->data, &fi) == NGX_FILE_ERROR) {
- of->err = ngx_errno;
- of->failed = ngx_file_info_n;
+ if (ngx_file_info_wrapper(name, of, &fi, pool->log)
+ == NGX_FILE_ERROR)
+ {
return NGX_ERROR;
}
@@ -170,7 +179,7 @@ ngx_open_cached_file(ngx_open_file_cache_t *cache, ngx_str_t *name,
return NGX_ERROR;
}
- rc = ngx_open_and_stat_file(name->data, of, pool->log);
+ rc = ngx_open_and_stat_file(name, of, pool->log);
if (rc == NGX_OK && !of->is_dir) {
cln->handler = ngx_pool_cleanup_file;
@@ -205,7 +214,7 @@ ngx_open_cached_file(ngx_open_file_cache_t *cache, ngx_str_t *name,
/* file was not used often enough to keep open */
- rc = ngx_open_and_stat_file(name->data, of, pool->log);
+ rc = ngx_open_and_stat_file(name, of, pool->log);
if (rc != NGX_OK && (of->err == 0 || !of->errors)) {
goto failed;
@@ -217,7 +226,11 @@ ngx_open_cached_file(ngx_open_file_cache_t *cache, ngx_str_t *name,
if (file->use_event
|| (file->event == NULL
&& (of->uniq == 0 || of->uniq == file->uniq)
- && now - file->created < of->valid))
+ && now - file->created < of->valid
+#if (NGX_HAVE_OPENAT)
+ && of->disable_symlinks == file->disable_symlinks
+#endif
+ ))
{
if (file->err == 0) {
@@ -239,7 +252,12 @@ ngx_open_cached_file(ngx_open_file_cache_t *cache, ngx_str_t *name,
} else {
of->err = file->err;
+#if (NGX_HAVE_OPENAT)
+ of->failed = file->disable_symlinks ? ngx_openat_file_n
+ : ngx_open_file_n;
+#else
of->failed = ngx_open_file_n;
+#endif
}
goto found;
@@ -263,7 +281,7 @@ ngx_open_cached_file(ngx_open_file_cache_t *cache, ngx_str_t *name,
of->fd = file->fd;
of->uniq = file->uniq;
- rc = ngx_open_and_stat_file(name->data, of, pool->log);
+ rc = ngx_open_and_stat_file(name, of, pool->log);
if (rc != NGX_OK && (of->err == 0 || !of->errors)) {
goto failed;
@@ -311,8 +329,7 @@ ngx_open_cached_file(ngx_open_file_cache_t *cache, ngx_str_t *name,
if (ngx_close_file(file->fd) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_ALERT, pool->log, ngx_errno,
- ngx_close_file_n " \"%s\" failed",
- name->data);
+ ngx_close_file_n " \"%V\" failed", name);
}
goto add_event;
@@ -329,7 +346,7 @@ ngx_open_cached_file(ngx_open_file_cache_t *cache, ngx_str_t *name,
/* not found */
- rc = ngx_open_and_stat_file(name->data, of, pool->log);
+ rc = ngx_open_and_stat_file(name, of, pool->log);
if (rc != NGX_OK && (of->err == 0 || !of->errors)) {
goto failed;
@@ -376,6 +393,9 @@ update:
file->fd = of->fd;
file->err = of->err;
+#if (NGX_HAVE_OPENAT)
+ file->disable_symlinks = of->disable_symlinks;
+#endif
if (of->err == 0) {
file->uniq = of->uniq;
@@ -452,7 +472,7 @@ failed:
if (of->fd != NGX_INVALID_FILE) {
if (ngx_close_file(of->fd) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_ALERT, pool->log, ngx_errno,
- ngx_close_file_n " \"%s\" failed", name->data);
+ ngx_close_file_n " \"%V\" failed", name);
}
}
@@ -460,17 +480,297 @@ failed:
}
+#if (NGX_HAVE_OPENAT)
+
+static ngx_fd_t
+ngx_openat_file_owner(ngx_fd_t at_fd, const u_char *name,
+ ngx_int_t mode, ngx_int_t create, ngx_int_t access, ngx_log_t *log)
+{
+ ngx_fd_t fd;
+ ngx_err_t err;
+ ngx_file_info_t fi, atfi;
+
+ /*
+ * To allow symlinks with the same owner, use openat() (followed
+ * by fstat()) and fstatat(AT_SYMLINK_NOFOLLOW), and then compare
+ * uids between fstat() and fstatat().
+ *
+ * As there is a race between openat() and fstatat() we don't
+ * know if openat() in fact opened symlink or not. Therefore,
+ * we have to compare uids even if fstatat() reports the opened
+ * component isn't a symlink (as we don't know whether it was
+ * symlink during openat() or not).
+ */
+
+ fd = ngx_openat_file(at_fd, name, mode, create, access);
+
+ if (fd == NGX_FILE_ERROR) {
+ return NGX_FILE_ERROR;
+ }
+
+ if (ngx_file_at_info(at_fd, name, &atfi, AT_SYMLINK_NOFOLLOW)
+ == NGX_FILE_ERROR)
+ {
+ err = ngx_errno;
+ goto failed;
+ }
+
+ if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) {
+ err = ngx_errno;
+ goto failed;
+ }
+
+ if (fi.st_uid != atfi.st_uid) {
+ err = NGX_ELOOP;
+ goto failed;
+ }
+
+ return fd;
+
+failed:
+
+ if (ngx_close_file(fd) == NGX_FILE_ERROR) {
+ ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+ ngx_close_file_n " \"%V\" failed", name);
+ }
+
+ ngx_set_errno(err);
+
+ return NGX_INVALID_FILE;
+}
+
+#endif
+
+
+static ngx_fd_t
+ngx_open_file_wrapper(ngx_str_t *name, ngx_open_file_info_t *of,
+ ngx_int_t mode, ngx_int_t create, ngx_int_t access, ngx_log_t *log)
+{
+ ngx_fd_t fd;
+
+#if !(NGX_HAVE_OPENAT)
+
+ fd = ngx_open_file(name->data, mode, create, access);
+
+ if (fd == NGX_INVALID_FILE) {
+ of->err = ngx_errno;
+ of->failed = ngx_open_file_n;
+ return NGX_INVALID_FILE;
+ }
+
+ return fd;
+
+#else
+
+ u_char *p, *cp, *end;
+ ngx_fd_t at_fd;
+ ngx_str_t at_name;
+ ngx_file_info_t fi;
+
+ if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_OFF) {
+ fd = ngx_open_file(name->data, mode, create, access);
+
+ if (fd == NGX_INVALID_FILE) {
+ of->err = ngx_errno;
+ of->failed = ngx_open_file_n;
+ return NGX_INVALID_FILE;
+ }
+
+ return fd;
+ }
+
+ p = name->data;
+ end = p + name->len;
+
+ at_fd = AT_FDCWD;
+ at_name = *name;
+
+ if (p[0] == '/') {
+ at_fd = ngx_openat_file(at_fd, "/",
+ NGX_FILE_RDONLY|NGX_FILE_NONBLOCK,
+ NGX_FILE_OPEN, 0);
+
+ if (at_fd == NGX_FILE_ERROR) {
+ of->err = ngx_errno;
+ of->failed = ngx_openat_file_n;
+ return NGX_FILE_ERROR;
+ }
+
+ at_name.len = 1;
+ p++;
+ }
+
+ for ( ;; ) {
+ cp = ngx_strlchr(p, end, '/');
+ if (cp == NULL) {
+ break;
+ }
+
+ if (cp == p) {
+ p++;
+ continue;
+ }
+
+ *cp = '\0';
+
+ if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_NOTOWNER) {
+ fd = ngx_openat_file_owner(at_fd, p,
+ NGX_FILE_RDONLY|NGX_FILE_NONBLOCK,
+ NGX_FILE_OPEN, 0, log);
+
+ } else {
+ fd = ngx_openat_file(at_fd, p,
+ NGX_FILE_RDONLY|NGX_FILE_NONBLOCK|NGX_FILE_NOFOLLOW,
+ NGX_FILE_OPEN, 0);
+ }
+
+ *cp = '/';
+
+ if (fd == NGX_INVALID_FILE) {
+ of->err = ngx_errno;
+ of->failed = ngx_openat_file_n;
+ goto failed;
+ }
+
+ if (at_fd != AT_FDCWD && ngx_close_file(at_fd) == NGX_FILE_ERROR) {
+ ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+ ngx_close_file_n " \"%V\" failed", at_name);
+ }
+
+ p = cp + 1;
+ at_fd = fd;
+ at_name.len = cp - at_name.data;
+ }
+
+ if (p == end && at_fd != AT_FDCWD) {
+
+ /*
+ * If pathname ends with a trailing slash, check if last path
+ * component is a directory; if not, fail with ENOTDIR as per
+ * POSIX.
+ *
+ * We use separate check instead of O_DIRECTORY in the loop above,
+ * as O_DIRECTORY doesn't work on FreeBSD 8.
+ *
+ * Note this returns already opened file descriptor, with different
+ * mode/create/access. This is believed to be safe as we don't
+ * use this codepath to create directories.
+ */
+
+ if (ngx_fd_info(at_fd, &fi) == NGX_FILE_ERROR) {
+ of->err = ngx_errno;
+ of->failed = ngx_fd_info_n;
+ fd = NGX_INVALID_FILE;
+
+ goto failed;
+ }
+
+ if (ngx_is_dir(&fi)) {
+ return at_fd;
+ }
+
+ of->err = ENOTDIR;
+ of->failed = ngx_openat_file_n;
+ fd = NGX_INVALID_FILE;
+
+ goto failed;
+ }
+
+ if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_NOTOWNER) {
+ fd = ngx_openat_file_owner(at_fd, p, mode, create, access, log);
+
+ } else {
+ fd = ngx_openat_file(at_fd, p, mode|NGX_FILE_NOFOLLOW, create, access);
+ }
+
+ if (fd == NGX_INVALID_FILE) {
+ of->err = ngx_errno;
+ of->failed = ngx_openat_file_n;
+ }
+
+failed:
+
+ if (at_fd != AT_FDCWD && ngx_close_file(at_fd) == NGX_FILE_ERROR) {
+ ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+ ngx_close_file_n " \"%V\" failed", at_name);
+ }
+
+ return fd;
+#endif
+}
+
+
+static ngx_int_t
+ngx_file_info_wrapper(ngx_str_t *name, ngx_open_file_info_t *of,
+ ngx_file_info_t *fi, ngx_log_t *log)
+{
+ ngx_int_t rc;
+
+#if !(NGX_HAVE_OPENAT)
+
+ rc = ngx_file_info(name->data, fi);
+
+ if (rc == NGX_FILE_ERROR) {
+ of->err = ngx_errno;
+ of->failed = ngx_file_info_n;
+ return NGX_FILE_ERROR;
+ }
+
+ return rc;
+
+#else
+
+ ngx_fd_t fd;
+
+ if (of->disable_symlinks == NGX_DISABLE_SYMLINKS_OFF) {
+
+ rc = ngx_file_info(name->data, fi);
+
+ if (rc == NGX_FILE_ERROR) {
+ of->err = ngx_errno;
+ of->failed = ngx_file_info_n;
+ return NGX_FILE_ERROR;
+ }
+
+ return rc;
+ }
+
+ fd = ngx_open_file_wrapper(name, of, NGX_FILE_RDONLY|NGX_FILE_NONBLOCK,
+ NGX_FILE_OPEN, 0, log);
+
+ if (fd == NGX_INVALID_FILE) {
+ return NGX_FILE_ERROR;
+ }
+
+ rc = ngx_fd_info(fd, fi);
+
+ if (rc == NGX_FILE_ERROR) {
+ of->err = ngx_errno;
+ of->failed = ngx_fd_info_n;
+ }
+
+ if (ngx_close_file(fd) == NGX_FILE_ERROR) {
+ ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+ ngx_close_file_n " \"%V\" failed", name);
+ }
+
+ return rc;
+#endif
+}
+
+
static ngx_int_t
-ngx_open_and_stat_file(u_char *name, ngx_open_file_info_t *of, ngx_log_t *log)
+ngx_open_and_stat_file(ngx_str_t *name, ngx_open_file_info_t *of,
+ ngx_log_t *log)
{
ngx_fd_t fd;
ngx_file_info_t fi;
if (of->fd != NGX_INVALID_FILE) {
- if (ngx_file_info(name, &fi) == NGX_FILE_ERROR) {
- of->failed = ngx_file_info_n;
- goto failed;
+ if (ngx_file_info_wrapper(name, of, &fi, log) == NGX_FILE_ERROR) {
+ of->fd = NGX_INVALID_FILE;
+ return NGX_ERROR;
}
if (of->uniq == ngx_file_uniq(&fi)) {
@@ -479,9 +779,9 @@ ngx_open_and_stat_file(u_char *name, ngx_open_file_info_t *of, ngx_log_t *log)
} else if (of->test_dir) {
- if (ngx_file_info(name, &fi) == NGX_FILE_ERROR) {
- of->failed = ngx_file_info_n;
- goto failed;
+ if (ngx_file_info_wrapper(name, of, &fi, log) == NGX_FILE_ERROR) {
+ of->fd = NGX_INVALID_FILE;
+ return NGX_ERROR;
}
if (ngx_is_dir(&fi)) {
@@ -496,26 +796,27 @@ ngx_open_and_stat_file(u_char *name, ngx_open_file_info_t *of, ngx_log_t *log)
* This flag has no effect on a regular files.
*/
- fd = ngx_open_file(name, NGX_FILE_RDONLY|NGX_FILE_NONBLOCK,
- NGX_FILE_OPEN, 0);
+ fd = ngx_open_file_wrapper(name, of, NGX_FILE_RDONLY|NGX_FILE_NONBLOCK,
+ NGX_FILE_OPEN, 0, log);
} else {
- fd = ngx_open_file(name, NGX_FILE_APPEND, NGX_FILE_CREATE_OR_OPEN,
- NGX_FILE_DEFAULT_ACCESS);
+ fd = ngx_open_file_wrapper(name, of, NGX_FILE_APPEND,
+ NGX_FILE_CREATE_OR_OPEN,
+ NGX_FILE_DEFAULT_ACCESS, log);
}
if (fd == NGX_INVALID_FILE) {
- of->failed = ngx_open_file_n;
- goto failed;
+ of->fd = NGX_INVALID_FILE;
+ return NGX_ERROR;
}
if (ngx_fd_info(fd, &fi) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_CRIT, log, ngx_errno,
- ngx_fd_info_n " \"%s\" failed", name);
+ ngx_fd_info_n " \"%V\" failed", name);
if (ngx_close_file(fd) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
- ngx_close_file_n " \"%s\" failed", name);
+ ngx_close_file_n " \"%V\" failed", name);
}
of->fd = NGX_INVALID_FILE;
@@ -526,7 +827,7 @@ ngx_open_and_stat_file(u_char *name, ngx_open_file_info_t *of, ngx_log_t *log)
if (ngx_is_dir(&fi)) {
if (ngx_close_file(fd) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
- ngx_close_file_n " \"%s\" failed", name);
+ ngx_close_file_n " \"%V\" failed", name);
}
of->fd = NGX_INVALID_FILE;
@@ -537,14 +838,14 @@ ngx_open_and_stat_file(u_char *name, ngx_open_file_info_t *of, ngx_log_t *log)
if (of->read_ahead && ngx_file_size(&fi) > NGX_MIN_READ_AHEAD) {
if (ngx_read_ahead(fd, of->read_ahead) == NGX_ERROR) {
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
- ngx_read_ahead_n " \"%s\" failed", name);
+ ngx_read_ahead_n " \"%V\" failed", name);
}
}
if (of->directio <= ngx_file_size(&fi)) {
if (ngx_directio_on(fd) == NGX_FILE_ERROR) {
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
- ngx_directio_on_n " \"%s\" failed", name);
+ ngx_directio_on_n " \"%V\" failed", name);
} else {
of->is_directio = 1;
@@ -564,13 +865,6 @@ done:
of->is_exec = ngx_is_exec(&fi);
return NGX_OK;
-
-failed:
-
- of->fd = NGX_INVALID_FILE;
- of->err = ngx_errno;
-
- return NGX_ERROR;
}
diff --git a/src/core/ngx_open_file_cache.h b/src/core/ngx_open_file_cache.h
index 436de3060..0ff345318 100644
--- a/src/core/ngx_open_file_cache.h
+++ b/src/core/ngx_open_file_cache.h
@@ -32,6 +32,10 @@ typedef struct {
ngx_uint_t min_uses;
+#if (NGX_HAVE_OPENAT)
+ unsigned disable_symlinks:2;
+#endif
+
unsigned test_dir:1;
unsigned test_only:1;
unsigned log:1;
@@ -64,6 +68,10 @@ struct ngx_cached_open_file_s {
uint32_t uses;
+#if (NGX_HAVE_OPENAT)
+ unsigned disable_symlinks:2;
+#endif
+
unsigned count:24;
unsigned close:1;
unsigned use_event:1;
diff --git a/src/core/ngx_parse.h b/src/core/ngx_parse.h
index 0c8114fb6..ec093b5a2 100644
--- a/src/core/ngx_parse.h
+++ b/src/core/ngx_parse.h
@@ -13,9 +13,6 @@
#include <ngx_core.h>
-#define NGX_PARSE_LARGE_TIME -2
-
-
ssize_t ngx_parse_size(ngx_str_t *line);
off_t ngx_parse_offset(ngx_str_t *line);
ngx_int_t ngx_parse_time(ngx_str_t *line, ngx_uint_t is_sec);
diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c
index 6ab0ddb51..5a0ade729 100644
--- a/src/core/ngx_resolver.c
+++ b/src/core/ngx_resolver.c
@@ -160,7 +160,7 @@ ngx_resolver_create(ngx_conf_t *cf, ngx_str_t *names, ngx_uint_t n)
r->valid = ngx_parse_time(&s, 1);
- if (r->valid == NGX_ERROR) {
+ if (r->valid == (time_t) NGX_ERROR) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"invalid parameter: %V", &names[i]);
return NULL;
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;
}
diff --git a/src/mail/ngx_mail_core_module.c b/src/mail/ngx_mail_core_module.c
index 2fb537a25..52a536936 100644
--- a/src/mail/ngx_mail_core_module.c
+++ b/src/mail/ngx_mail_core_module.c
@@ -479,7 +479,7 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
s.len = p - s.data;
ls->tcp_keepidle = ngx_parse_time(&s, 1);
- if (ls->tcp_keepidle == NGX_ERROR) {
+ if (ls->tcp_keepidle == (time_t) NGX_ERROR) {
goto invalid_so_keepalive;
}
}
@@ -495,7 +495,7 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
s.len = p - s.data;
ls->tcp_keepintvl = ngx_parse_time(&s, 1);
- if (ls->tcp_keepintvl == NGX_ERROR) {
+ if (ls->tcp_keepintvl == (time_t) NGX_ERROR) {
goto invalid_so_keepalive;
}
}
diff --git a/src/os/unix/ngx_errno.h b/src/os/unix/ngx_errno.h
index 092d05a0b..78af40bfe 100644
--- a/src/os/unix/ngx_errno.h
+++ b/src/os/unix/ngx_errno.h
@@ -48,6 +48,11 @@ typedef int ngx_err_t;
#define NGX_EILSEQ EILSEQ
#define NGX_ENOMOREFILES 0
+#if (NGX_HAVE_OPENAT)
+#define NGX_EMLINK EMLINK
+#define NGX_ELOOP ELOOP
+#endif
+
#if (__hpux__)
#define NGX_EAGAIN EWOULDBLOCK
#else
diff --git a/src/os/unix/ngx_files.h b/src/os/unix/ngx_files.h
index abeb1570b..1526f9b77 100644
--- a/src/os/unix/ngx_files.h
+++ b/src/os/unix/ngx_files.h
@@ -76,6 +76,10 @@ typedef struct {
#define NGX_FILE_APPEND O_WRONLY|O_APPEND
#define NGX_FILE_NONBLOCK O_NONBLOCK
+#if (NGX_HAVE_OPENAT)
+#define NGX_FILE_NOFOLLOW O_NOFOLLOW
+#endif
+
#define NGX_FILE_DEFAULT_ACCESS 0644
#define NGX_FILE_OWNER_ACCESS 0600
@@ -324,6 +328,21 @@ ngx_int_t ngx_directio_off(ngx_fd_t fd);
size_t ngx_fs_bsize(u_char *name);
+#if (NGX_HAVE_OPENAT)
+
+#define ngx_openat_file(fd, name, mode, create, access) \
+ openat(fd, (const char *) name, mode|create, access)
+
+#define ngx_openat_file_n "openat()"
+
+#define ngx_file_at_info(fd, name, sb, flag) \
+ fstatat(fd, (const char *) name, sb, flag)
+
+#define ngx_file_at_info_n "fstatat()"
+
+#endif
+
+
#define ngx_stderr STDERR_FILENO
#define ngx_set_stderr(fd) dup2(fd, STDERR_FILENO)
#define ngx_set_stderr_n "dup2(STDERR_FILENO)"
diff --git a/src/os/unix/ngx_posix_init.c b/src/os/unix/ngx_posix_init.c
index 02642bd7c..eea65a903 100644
--- a/src/os/unix/ngx_posix_init.c
+++ b/src/os/unix/ngx_posix_init.c
@@ -47,7 +47,13 @@ ngx_os_init(ngx_log_t *log)
for (n = ngx_pagesize; n >>= 1; ngx_pagesize_shift++) { /* void */ }
+#if (NGX_HAVE_SC_NPROCESSORS_ONLN)
if (ngx_ncpu == 0) {
+ ngx_ncpu = sysconf(_SC_NPROCESSORS_ONLN);
+ }
+#endif
+
+ if (ngx_ncpu < 1) {
ngx_ncpu = 1;
}