# HG changeset patch # User Igor Sysoev # Date 1211140800 -14400 # Node ID edf1cb6c328eb13c27880d1f4cb5ea068f7aec37 # Parent 52f3c9c7eff03fee0a2ede166976441aa22a3651 nginx 0.7.0 *) Change: now the 0x00-0x1F, '"' and '\' characters are escaped as \xXX in an access_log. Thanks to Maxim Dounin. *) Change: now nginx allows several "Host" request header line. *) Feature: the "modified" flag in the "expires" directive. *) Feature: the $uid_got and $uid_set variables may be used at any request processing stage. *) Feature: the $hostname variable. Thanks to Andrei Nigmatulin. *) Feature: DESTDIR support. Thanks to Todd A. Fisher and Andras Voroskoi. *) Bugfix: a segmentation fault might occur in worker process on Linux, if keepalive was enabled. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,27 @@ +Changes with nginx 0.7.0 19 May 2008 + + *) Change: now the 0x00-0x1F, '"' and '\' characters are escaped as + \xXX in an access_log. + Thanks to Maxim Dounin. + + *) Change: now nginx allows several "Host" request header line. + + *) Feature: the "modified" flag in the "expires" directive. + + *) Feature: the $uid_got and $uid_set variables may be used at any + request processing stage. + + *) Feature: the $hostname variable. + Thanks to Andrei Nigmatulin. + + *) Feature: DESTDIR support. + Thanks to Todd A. Fisher and Andras Voroskoi. + + *) Bugfix: a segmentation fault might occur in worker process on Linux, + if keepalive was enabled. + + Changes with nginx 0.6.31 12 May 2008 *) Bugfix: nginx did not process FastCGI response if header was at the diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,28 @@ +Изменения в nginx 0.7.0 19.05.2008 + + *) Изменение: теперь символы 0x00-0x1F, '"' и '\' в access_log + записываются в виде \xXX. + Спасибо Максиму Дунину. + + *) Изменение: теперь nginx разрешает несколько строк "Host" в заголовке + запроса. + + *) Добавление: директива expires поддерживает флаг modified. + + *) Добавление: переменные $uid_got и $uid_set можно использовать на + любой стадии обработки запроса. + + *) Добавление: переменная $hostname. + Спасибо Андрею Нигматулину. + + *) Добавление: поддержка DESTDIR. + Спасибо Todd A. Fisher и Andras Voroskoi. + + *) Исправление: при использовании keepalive на Linux в рабочем процессе + мог произойти segmentation fault. + + Изменения в nginx 0.6.31 12.05.2008 *) Исправление: nginx не обрабатывал ответ FastCGI-сервера, если строка diff --git a/auto/install b/auto/install --- a/auto/install +++ b/auto/install @@ -17,47 +17,53 @@ fi cat << END >> $NGX_MAKEFILE -install: $NGX_OBJS${ngx_dirsep}nginx${ngx_binext} \ +install: $NGX_OBJS${ngx_dirsep}nginx${ngx_binext} \ $NGX_INSTALL_PERL_MODULES - test -d '$NGX_PREFIX' || mkdir -p '$NGX_PREFIX' + test -d '\$(DESTDIR)$NGX_PREFIX' || mkdir -p '\$(DESTDIR)$NGX_PREFIX' - test -d '`dirname "$NGX_SBIN_PATH"`' \ - || mkdir -p '`dirname "$NGX_SBIN_PATH"`' - test ! -f '$NGX_SBIN_PATH' || mv '$NGX_SBIN_PATH' '$NGX_SBIN_PATH.old' - cp $NGX_OBJS/nginx '$NGX_SBIN_PATH' + test -d '\$(DESTDIR)`dirname "$NGX_SBIN_PATH"`' \ + || mkdir -p '\$(DESTDIR)`dirname "$NGX_SBIN_PATH"`' + test ! -f '\$(DESTDIR)$NGX_SBIN_PATH' \ + || mv '\$(DESTDIR)$NGX_SBIN_PATH' \ + '\$(DESTDIR)$NGX_SBIN_PATH.old' + cp $NGX_OBJS/nginx '\$(DESTDIR)$NGX_SBIN_PATH' - test -d '$NGX_CONF_PREFIX' || mkdir -p '$NGX_CONF_PREFIX' + test -d '\$(DESTDIR)$NGX_CONF_PREFIX' \ + || mkdir -p '\$(DESTDIR)$NGX_CONF_PREFIX' - cp conf/koi-win '$NGX_CONF_PREFIX' - cp conf/koi-utf '$NGX_CONF_PREFIX' - cp conf/win-utf '$NGX_CONF_PREFIX' + cp conf/koi-win '\$(DESTDIR)$NGX_CONF_PREFIX' + cp conf/koi-utf '\$(DESTDIR)$NGX_CONF_PREFIX' + cp conf/win-utf '\$(DESTDIR)$NGX_CONF_PREFIX' - test -f '$NGX_CONF_PREFIX/mime.types' \ - || cp conf/mime.types '$NGX_CONF_PREFIX' - cp conf/mime.types '$NGX_CONF_PREFIX/mime.types.default' + test -f '\$(DESTDIR)$NGX_CONF_PREFIX/mime.types' \ + || cp conf/mime.types '\$(DESTDIR)$NGX_CONF_PREFIX' + cp conf/mime.types '\$(DESTDIR)$NGX_CONF_PREFIX/mime.types.default' - test -f '$NGX_CONF_PREFIX/fastcgi_params' \ - || cp conf/fastcgi_params '$NGX_CONF_PREFIX' - cp conf/fastcgi_params '$NGX_CONF_PREFIX/fastcgi_params.default' + test -f '\$(DESTDIR)$NGX_CONF_PREFIX/fastcgi_params' \ + || cp conf/fastcgi_params '\$(DESTDIR)$NGX_CONF_PREFIX' + cp conf/fastcgi_params \ + '\$(DESTDIR)$NGX_CONF_PREFIX/fastcgi_params.default' - test -f '$NGX_CONF_PATH' || cp conf/nginx.conf '$NGX_CONF_PREFIX' - cp conf/nginx.conf '$NGX_CONF_PREFIX/nginx.conf.default' + test -f '\$(DESTDIR)$NGX_CONF_PATH' \ + || cp conf/nginx.conf '\$(DESTDIR)$NGX_CONF_PREFIX' + cp conf/nginx.conf '\$(DESTDIR)$NGX_CONF_PREFIX/nginx.conf.default' - test -d '`dirname "$NGX_PID_PATH"`' \ - || mkdir -p '`dirname "$NGX_PID_PATH"`' + test -d '\$(DESTDIR)`dirname "$NGX_PID_PATH"`' \ + || mkdir -p '\$(DESTDIR)`dirname "$NGX_PID_PATH"`' - test -d '`dirname "$NGX_HTTP_LOG_PATH"`' || \ - mkdir -p '`dirname "$NGX_HTTP_LOG_PATH"`' + test -d '\$(DESTDIR)`dirname "$NGX_HTTP_LOG_PATH"`' || \ + mkdir -p '\$(DESTDIR)`dirname "$NGX_HTTP_LOG_PATH"`' - test -d '$NGX_PREFIX/html' || cp -r html '$NGX_PREFIX' + test -d '\$(DESTDIR)$NGX_PREFIX/html' \ + || cp -r html '\$(DESTDIR)$NGX_PREFIX' END -if test -n "$NGX_ERROR_LOG_PATH"; then +if test -n "\$(DESTDIR)$NGX_ERROR_LOG_PATH"; then cat << END >> $NGX_MAKEFILE - test -d '`dirname "$NGX_ERROR_LOG_PATH"`' || \ - mkdir -p '`dirname "$NGX_ERROR_LOG_PATH"`' + test -d '\$(DESTDIR)`dirname "$NGX_ERROR_LOG_PATH"`' || \ + mkdir -p '\$(DESTDIR)`dirname "$NGX_ERROR_LOG_PATH"`' END fi diff --git a/auto/lib/conf b/auto/lib/conf --- a/auto/lib/conf +++ b/auto/lib/conf @@ -16,6 +16,7 @@ if [ $USE_MD5 = YES ]; then have=NGX_HAVE_OPENSSL_MD5_H . auto/have have=NGX_OPENSSL_MD5 . auto/have MD5=YES + MD5_LIB=OpenSSL else . auto/lib/md5/conf @@ -28,6 +29,7 @@ if [ $USE_SHA1 = YES ]; then if [ $OPENSSL != NONE -a $OPENSSL != NO ]; then have=NGX_HAVE_OPENSSL_SHA1_H . auto/have SHA1=YES + SHA1_LIB=OpenSSL else . auto/lib/sha1/conf diff --git a/auto/lib/md5/conf b/auto/lib/md5/conf --- a/auto/lib/md5/conf +++ b/auto/lib/md5/conf @@ -45,6 +45,7 @@ if [ $MD5 != NONE ]; then else if [ "$NGX_PLATFORM" != win32 ]; then + MD5=NO # Solaris 8/9 @@ -58,55 +59,43 @@ else ngx_feature_test="MD5_CTX md5; MD5Init(&md5)" . auto/feature - if [ $ngx_found = yes ]; then - CORE_LIBS="$CORE_LIBS $ngx_feature_libs" - MD5=YES - MD5_LIB=md5 - ngx_found=no + ngx_md5_lib="system md5" - else + if [ $ngx_found = no ]; then + # FreeBSD ngx_feature="rsaref md library" - ngx_feature_name= - ngx_feature_run=no - ngx_feature_incs="#include " - ngx_feature_path= ngx_feature_libs="-lmd" - ngx_feature_test="MD5_CTX md5; MD5Init(&md5)" . auto/feature + + ngx_md5_lib="system md" fi + if [ $ngx_found = no ]; then + + # OpenSSL crypto library + + ngx_feature="OpenSSL md5 crypto library" + ngx_feature_name="NGX_OPENSSL_MD5" + ngx_feature_incs="#include " + ngx_feature_libs="-lcrypto" + ngx_feature_test="MD5_CTX md5; MD5_Init(&md5)" + . auto/feature + + ngx_md5_lib="system crypto" + + if [ $ngx_found = yes ]; then + have=NGX_HAVE_OPENSSL_MD5_H . auto/have + fi + fi if [ $ngx_found = yes ]; then CORE_LIBS="$CORE_LIBS $ngx_feature_libs" MD5=YES - MD5_LIB=md - ngx_found=no - - else - if [ $MD5 = NO ]; then - - # OpenSSL crypto library - - ngx_feature="OpenSSL md5 crypto library" - ngx_feature_name="NGX_OPENSSL_MD5" - ngx_feature_run=no - ngx_feature_incs="#include " - ngx_feature_path= - ngx_feature_libs="-lcrypto" - ngx_feature_test="MD5_CTX md5; MD5_Init(&md5)" - . auto/feature - fi + MD5_LIB=$ngx_md5_lib fi - - if [ $ngx_found = yes ]; then - have=NGX_HAVE_OPENSSL_MD5_H . auto/have - CORE_LIBS="$CORE_LIBS $ngx_feature_libs" - MD5=YES - MD5_LIB=crypto - fi fi fi diff --git a/auto/lib/pcre/conf b/auto/lib/pcre/conf --- a/auto/lib/pcre/conf +++ b/auto/lib/pcre/conf @@ -84,6 +84,7 @@ if [ $PCRE != NONE ]; then else if [ "$NGX_PLATFORM" != win32 ]; then + PCRE=NO ngx_feature="PCRE library" @@ -95,20 +96,11 @@ else ngx_feature_test="pcre *re; re = pcre_compile(NULL, 0, NULL, 0, NULL)" . auto/feature - if [ $ngx_found = yes ]; then - CORE_DEPS="$CORE_DEPS $REGEX_DEPS" - CORE_SRCS="$CORE_SRCS $REGEX_SRCS" - CORE_LIBS="$CORE_LIBS $ngx_feature_libs" - PCRE=YES - ngx_found=no + if [ $ngx_found = no ]; then - else # FreeBSD port ngx_feature="PCRE library in /usr/local/" - ngx_feature_name="NGX_PCRE" - ngx_feature_run=no - ngx_feature_incs="#include " ngx_feature_path="/usr/local/include" if [ $NGX_RPATH = YES ]; then @@ -117,8 +109,49 @@ else ngx_feature_libs="-L/usr/local/lib -lpcre" fi - ngx_feature_test="pcre *re; - re = pcre_compile(NULL, 0, NULL, 0, NULL)" + . auto/feature + fi + + if [ $ngx_found = no ]; then + + # Linux package + + ngx_feature="PCRE library in /usr/include/pcre/" + ngx_feature_path="/usr/include/pcre" + ngx_feature_libs="-lpcre" + + . auto/feature + fi + + if [ $ngx_found = no ]; then + + # NetBSD port + + ngx_feature="PCRE library in /usr/pkg/" + ngx_feature_path="/usr/pkg/include" + + if [ $NGX_RPATH = YES ]; then + ngx_feature_libs="-R/usr/pkg/lib -L/usr/pkg/lib -lpcre" + else + ngx_feature_libs="-L/usr/pkg/lib -lpcre" + fi + + . auto/feature + fi + + if [ $ngx_found = no ]; then + + # MacPorts + + ngx_feature="PCRE library in /opt/local/" + ngx_feature_path="/opt/local/include" + + if [ $NGX_RPATH = YES ]; then + ngx_feature_libs="-R/opt/local/lib -L/opt/local/lib -lpcre" + else + ngx_feature_libs="-L/opt/local/lib -lpcre" + fi + . auto/feature fi @@ -128,94 +161,6 @@ else CORE_INCS="$CORE_INCS $ngx_feature_path" CORE_LIBS="$CORE_LIBS $ngx_feature_libs" PCRE=YES - ngx_found=no - - else - # Linux package - - if [ $PCRE = NO ]; then - - ngx_feature="PCRE library in /usr/include/pcre/" - ngx_feature_name="NGX_PCRE" - ngx_feature_run=no - ngx_feature_incs="#include " - ngx_feature_path="/usr/include/pcre" - ngx_feature_libs="-lpcre" - ngx_feature_test="pcre *re; - re = pcre_compile(NULL, 0, NULL, 0, NULL)" - . auto/feature - fi - fi - - if [ $ngx_found = yes ]; then - CORE_DEPS="$CORE_DEPS $REGEX_DEPS" - CORE_SRCS="$CORE_SRCS $REGEX_SRCS" - CORE_INCS="$CORE_INCS $ngx_feature_path" - CORE_LIBS="$CORE_LIBS $ngx_feature_libs" - PCRE=YES - ngx_found=no - - else - # NetBSD port - - if [ $PCRE = NO ]; then - - ngx_feature="PCRE library in /usr/pkg/" - ngx_feature_name="NGX_PCRE" - ngx_feature_run=no - ngx_feature_incs="#include " - ngx_feature_path="/usr/pkg/include" - - if [ $NGX_RPATH = YES ]; then - ngx_feature_libs="-R/usr/pkg/lib -L/usr/pkg/lib -lpcre" - else - ngx_feature_libs="-L/usr/pkg/lib -lpcre" - fi - - ngx_feature_test="pcre *re; - re = pcre_compile(NULL, 0, NULL, 0, NULL)" - . auto/feature - fi - fi - - if [ $ngx_found = yes ]; then - CORE_DEPS="$CORE_DEPS $REGEX_DEPS" - CORE_SRCS="$CORE_SRCS $REGEX_SRCS" - CORE_INCS="$CORE_INCS $ngx_feature_path" - CORE_LIBS="$CORE_LIBS $ngx_feature_libs" - PCRE=YES - ngx_found=no - - else - # MacPorts - - if [ $PCRE = NO ]; then - - ngx_feature="PCRE library in /opt/local/" - ngx_feature_name="NGX_PCRE" - ngx_feature_run=no - ngx_feature_incs="#include " - ngx_feature_path="/opt/local/include" - - if [ $NGX_RPATH = YES ]; then - ngx_feature_libs="-R/opt/local/lib -L/opt/local/lib -lpcre" - else - ngx_feature_libs="-L/opt/local/lib -lpcre" - fi - - ngx_feature_test="pcre *re; - re = pcre_compile(NULL, 0, NULL, 0, NULL)" - . auto/feature - fi - fi - - if [ $ngx_found = yes ]; then - CORE_DEPS="$CORE_DEPS $REGEX_DEPS" - CORE_SRCS="$CORE_SRCS $REGEX_SRCS" - CORE_INCS="$CORE_INCS $ngx_feature_path" - CORE_LIBS="$CORE_LIBS $ngx_feature_libs" - PCRE=YES - ngx_found=no fi fi diff --git a/auto/lib/sha1/conf b/auto/lib/sha1/conf --- a/auto/lib/sha1/conf +++ b/auto/lib/sha1/conf @@ -35,6 +35,7 @@ if [ $SHA1 != NONE ]; then else if [ "$NGX_PLATFORM" != win32 ]; then + SHA1=NO # FreeBSD @@ -48,35 +49,28 @@ else ngx_feature_test="SHA_CTX sha1; SHA1_Init(&sha1)" . auto/feature + ngx_sha1_lib="system md" + + if [ $ngx_found = no ]; then + + # OpenSSL crypto library + + ngx_feature="OpenSSL sha1 crypto library" + ngx_feature_incs="#include " + ngx_feature_libs="-lcrypto" + . auto/feature + + ngx_sha1_lib="system crypto" + + if [ $ngx_found = yes ]; then + have=NGX_HAVE_OPENSSL_SHA1_H . auto/have + fi + fi if [ $ngx_found = yes ]; then CORE_LIBS="$CORE_LIBS $ngx_feature_libs" SHA1=YES - SHA1_LIB=md - ngx_found=no - - else - if [ $SHA1 = NO ]; then - - # OpenSSL crypto library - - ngx_feature="OpenSSL sha1 crypto library" - ngx_feature_name= - ngx_feature_run=no - ngx_feature_incs="#include " - ngx_feature_path= - ngx_feature_libs="-lcrypto" - ngx_feature_test="SHA_CTX sha1; SHA1_Init(&sha1)" - . auto/feature - fi - fi - - - if [ $ngx_found = yes ]; then - have=NGX_HAVE_OPENSSL_SHA1_H . auto/have - CORE_LIBS="$CORE_LIBS $ngx_feature_libs" - SHA1=YES - SHA1_LIB=crypto + SHA1_LIB=$ngx_sha1_lib fi fi diff --git a/auto/summary b/auto/summary --- a/auto/summary +++ b/auto/summary @@ -51,26 +51,14 @@ case $OPENSSL in esac case $MD5 in - YES) - case $OPENSSL in - NONE|NO) echo " + md5: using system $MD5_LIB library" ;; - *) echo " + md5: using OpenSSL library" ;; - esac - ;; - + YES) echo " + md5: using $MD5_LIB library" ;; NONE) echo " + md5 library is not used" ;; NO) echo " + md5 library is not found" ;; *) echo " + using md5 library: $MD5" ;; esac case $SHA1 in - YES) - case $OPENSSL in - NONE|NO) echo " + sha1: using system $SHA1_LIB library" ;; - *) echo " + sha1: using OpenSSL library" ;; - esac - ;; - + YES) echo " + sha1: using $SHA1_LIB library" ;; NONE) echo " + sha1 library is not used" ;; NO) echo " + sha1 library is not found" ;; *) echo " + using sha1 library: $SHA1" ;; diff --git a/src/core/nginx.h b/src/core/nginx.h --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -8,7 +8,7 @@ #define _NGINX_H_INCLUDED_ -#define NGINX_VERSION "0.6.31" +#define NGINX_VERSION "0.7.0" #define NGINX_VER "nginx/" NGINX_VERSION #define NGINX_VAR "NGINX" diff --git a/src/core/ngx_config.h b/src/core/ngx_config.h --- a/src/core/ngx_config.h +++ b/src/core/ngx_config.h @@ -116,10 +116,11 @@ typedef intptr_t ngx_flag_t; #define INET_ADDRSTRLEN 16 #endif -#define NGX_MAXHOSTNAMELEN 64 -/* -#define NGX_MAXHOSTNAMELEN MAXHOSTNAMELEN -*/ +#ifdef MAXHOSTNAMELEN +#define NGX_MAXHOSTNAMELEN MAXHOSTNAMELEN +#else +#define NGX_MAXHOSTNAMELEN 256 +#endif #if ((__GNU__ == 2) && (__GNUC_MINOR__ < 8)) diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c --- a/src/core/ngx_cycle.c +++ b/src/core/ngx_cycle.c @@ -57,6 +57,7 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) ngx_listening_t *ls, *nls; ngx_core_conf_t *ccf, *old_ccf; ngx_core_module_t *module; + char hostname[NGX_MAXHOSTNAMELEN]; log = old_cycle->log; @@ -170,6 +171,26 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) } + if (gethostname(hostname, NGX_MAXHOSTNAMELEN) == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "gethostname() failed"); + ngx_destroy_pool(pool); + return NULL; + } + + /* on Linux gethostname() silently truncates name that does not fit */ + + hostname[NGX_MAXHOSTNAMELEN - 1] = '\0'; + cycle->hostname.len = ngx_strlen(hostname); + + cycle->hostname.data = ngx_palloc(pool, cycle->hostname.len); + if (cycle->hostname.data == NULL) { + ngx_destroy_pool(pool); + return NULL; + } + + ngx_memcpy(cycle->hostname.data, hostname, cycle->hostname.len); + + for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_CORE_MODULE) { continue; diff --git a/src/core/ngx_cycle.h b/src/core/ngx_cycle.h --- a/src/core/ngx_cycle.h +++ b/src/core/ngx_cycle.h @@ -62,6 +62,7 @@ struct ngx_cycle_s { ngx_str_t conf_file; ngx_str_t root; ngx_str_t lock_file; + ngx_str_t hostname; }; diff --git a/src/core/ngx_open_file_cache.c b/src/core/ngx_open_file_cache.c --- a/src/core/ngx_open_file_cache.c +++ b/src/core/ngx_open_file_cache.c @@ -413,13 +413,13 @@ failed: if (file->count == 0) { - if (file->fd != NGX_INVALID_FILE) { - 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", + if (file->fd != NGX_INVALID_FILE) { + 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", file->name); - } - } + } + } ngx_free(file->name); ngx_free(file); diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c --- a/src/core/ngx_resolver.c +++ b/src/core/ngx_resolver.c @@ -202,7 +202,7 @@ ngx_resolver_cleanup_tree(ngx_resolver_t ngx_queue_remove(&rn->queue); for (ctx = rn->waiting; ctx; ctx = next) { - next = ctx->next; + next = ctx->next; if (ctx->event) { ngx_resolver_free(r, ctx->event); diff --git a/src/core/ngx_string.h b/src/core/ngx_string.h --- a/src/core/ngx_string.h +++ b/src/core/ngx_string.h @@ -25,11 +25,12 @@ typedef struct { typedef struct { - unsigned len:29; + unsigned len:28; unsigned valid:1; unsigned no_cacheable:1; unsigned not_found:1; + unsigned escape:1; u_char *data; } ngx_variable_value_t; diff --git a/src/http/modules/ngx_http_dav_module.c b/src/http/modules/ngx_http_dav_module.c --- a/src/http/modules/ngx_http_dav_module.c +++ b/src/http/modules/ngx_http_dav_module.c @@ -512,7 +512,7 @@ ngx_http_dav_mkcol_handler(ngx_http_requ static ngx_int_t ngx_http_dav_copy_move_handler(ngx_http_request_t *r) { - u_char *p, *desthost, *last, ch; + u_char *p, *host, *last, ch; size_t len, root; ngx_err_t err; ngx_int_t rc, depth; @@ -520,7 +520,7 @@ ngx_http_dav_copy_move_handler(ngx_http_ ngx_str_t path, uri; ngx_tree_ctx_t tree; ngx_file_info_t fi; - ngx_table_elt_t *host, *dest, *over; + ngx_table_elt_t *dest, *over; ngx_http_dav_copy_ctx_t copy; ngx_http_dav_loc_conf_t *dlcf; @@ -536,9 +536,9 @@ ngx_http_dav_copy_move_handler(ngx_http_ return NGX_HTTP_BAD_REQUEST; } - host = r->headers_in.host; + len = r->headers_in.server.len; - if (host == NULL) { + if (len == 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "client sent no \"Host\" header"); return NGX_HTTP_BAD_REQUEST; @@ -553,7 +553,7 @@ ngx_http_dav_copy_move_handler(ngx_http_ goto invalid_destination; } - desthost = dest->value.data + sizeof("https://") - 1; + host = dest->value.data + sizeof("https://") - 1; } else #endif @@ -564,12 +564,10 @@ ngx_http_dav_copy_move_handler(ngx_http_ goto invalid_destination; } - desthost = dest->value.data + sizeof("http://") - 1; + host = dest->value.data + sizeof("http://") - 1; } - len = r->headers_in.host_name_len; - - if (ngx_strncmp(desthost, host->value.data, len) != 0) { + if (ngx_strncmp(host, r->headers_in.server.data, len) != 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "\"Destination\" URI \"%V\" is handled by " "different repository than the source URI", @@ -579,7 +577,7 @@ ngx_http_dav_copy_move_handler(ngx_http_ last = dest->value.data + dest->value.len; - for (p = desthost + len; p < last; p++) { + for (p = host + len; p < last; p++) { if (*p == '/') { goto destination_done; } diff --git a/src/http/modules/ngx_http_headers_filter_module.c b/src/http/modules/ngx_http_headers_filter_module.c --- a/src/http/modules/ngx_http_headers_filter_module.c +++ b/src/http/modules/ngx_http_headers_filter_module.c @@ -31,18 +31,20 @@ struct ngx_http_header_val_s { }; +#define NGX_HTTP_EXPIRES_OFF 0 +#define NGX_HTTP_EXPIRES_EPOCH 1 +#define NGX_HTTP_EXPIRES_MAX 2 +#define NGX_HTTP_EXPIRES_ACCESS 3 +#define NGX_HTTP_EXPIRES_MODIFIED 4 + + typedef struct { - time_t expires; + ngx_uint_t expires; + time_t expires_time; ngx_array_t *headers; } ngx_http_headers_conf_t; -#define NGX_HTTP_EXPIRES_UNSET -2147483647 -#define NGX_HTTP_EXPIRES_OFF -2147483646 -#define NGX_HTTP_EXPIRES_EPOCH -2147483645 -#define NGX_HTTP_EXPIRES_MAX -2147483644 - - static ngx_int_t ngx_http_set_expires(ngx_http_request_t *r, ngx_http_headers_conf_t *conf); static ngx_int_t ngx_http_add_cache_control(ngx_http_request_t *r, @@ -76,7 +78,7 @@ static ngx_command_t ngx_http_headers_f { ngx_string("expires"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF - |NGX_CONF_TAKE1, + |NGX_CONF_TAKE12, ngx_http_headers_expires, NGX_HTTP_LOC_CONF_OFFSET, 0, @@ -185,6 +187,7 @@ static ngx_int_t ngx_http_set_expires(ngx_http_request_t *r, ngx_http_headers_conf_t *conf) { size_t len; + time_t since; ngx_uint_t i; ngx_table_elt_t *expires, *cc, **ccp; @@ -266,7 +269,7 @@ ngx_http_set_expires(ngx_http_request_t return NGX_ERROR; } - if (conf->expires == 0) { + if (conf->expires_time == 0) { ngx_memcpy(expires->value.data, ngx_cached_http_time.data, ngx_cached_http_time.len + 1); @@ -276,9 +279,18 @@ ngx_http_set_expires(ngx_http_request_t return NGX_OK; } - ngx_http_time(expires->value.data, ngx_time() + conf->expires); + if (conf->expires == NGX_HTTP_EXPIRES_ACCESS + || r->headers_out.last_modified_time == -1) + { + since = ngx_time(); - if (conf->expires < 0) { + } else { + since = r->headers_out.last_modified_time; + } + + ngx_http_time(expires->value.data, since + conf->expires_time); + + if (conf->expires_time < 0) { cc->value.len = sizeof("no-cache") - 1; cc->value.data = (u_char *) "no-cache"; @@ -291,7 +303,8 @@ ngx_http_set_expires(ngx_http_request_t return NGX_ERROR; } - cc->value.len = ngx_sprintf(cc->value.data, "max-age=%T", conf->expires) + cc->value.len = ngx_sprintf(cc->value.data, "max-age=%T", + since + conf->expires_time - ngx_time()) - cc->value.data; return NGX_OK; @@ -413,9 +426,10 @@ ngx_http_headers_create_conf(ngx_conf_t * set by ngx_pcalloc(): * * conf->headers = NULL; + * conf->expires_time = 0; */ - conf->expires = NGX_HTTP_EXPIRES_UNSET; + conf->expires = NGX_CONF_UNSET_UINT; return conf; } @@ -427,9 +441,13 @@ ngx_http_headers_merge_conf(ngx_conf_t * ngx_http_headers_conf_t *prev = parent; ngx_http_headers_conf_t *conf = child; - if (conf->expires == NGX_HTTP_EXPIRES_UNSET) { - conf->expires = (prev->expires == NGX_HTTP_EXPIRES_UNSET) ? - NGX_HTTP_EXPIRES_OFF : prev->expires; + if (conf->expires == NGX_CONF_UNSET_UINT) { + conf->expires = prev->expires; + conf->expires_time = prev->expires_time; + + if (conf->expires == NGX_CONF_UNSET_UINT) { + conf->expires = NGX_HTTP_EXPIRES_OFF; + } } if (conf->headers == NULL) { @@ -455,56 +473,73 @@ ngx_http_headers_expires(ngx_conf_t *cf, { ngx_http_headers_conf_t *hcf = conf; - ngx_uint_t minus; + ngx_uint_t minus, n; ngx_str_t *value; - if (hcf->expires != NGX_HTTP_EXPIRES_UNSET) { + if (hcf->expires != NGX_CONF_UNSET_UINT) { return "is duplicate"; } value = cf->args->elts; - if (ngx_strcmp(value[1].data, "epoch") == 0) { - hcf->expires = NGX_HTTP_EXPIRES_EPOCH; - return NGX_CONF_OK; - } + if (cf->args->nelts == 2) { + + if (ngx_strcmp(value[1].data, "epoch") == 0) { + hcf->expires = NGX_HTTP_EXPIRES_EPOCH; + return NGX_CONF_OK; + } + + if (ngx_strcmp(value[1].data, "max") == 0) { + hcf->expires = NGX_HTTP_EXPIRES_MAX; + return NGX_CONF_OK; + } - if (ngx_strcmp(value[1].data, "max") == 0) { - hcf->expires = NGX_HTTP_EXPIRES_MAX; - return NGX_CONF_OK; + if (ngx_strcmp(value[1].data, "off") == 0) { + hcf->expires = NGX_HTTP_EXPIRES_OFF; + return NGX_CONF_OK; + } + + hcf->expires = NGX_HTTP_EXPIRES_ACCESS; + + n = 1; + + } else { /* cf->args->nelts == 3 */ + + if (ngx_strcmp(value[1].data, "modified") != 0) { + return "invalid value"; + } + + hcf->expires = NGX_HTTP_EXPIRES_MODIFIED; + + n = 2; } - if (ngx_strcmp(value[1].data, "off") == 0) { - hcf->expires = NGX_HTTP_EXPIRES_OFF; - return NGX_CONF_OK; - } - - if (value[1].data[0] == '+') { - value[1].data++; - value[1].len--; + if (value[n].data[0] == '+') { + value[n].data++; + value[n].len--; minus = 0; - } else if (value[1].data[0] == '-') { - value[1].data++; - value[1].len--; + } else if (value[n].data[0] == '-') { + value[n].data++; + value[n].len--; minus = 1; } else { minus = 0; } - hcf->expires = ngx_parse_time(&value[1], 1); + hcf->expires_time = ngx_parse_time(&value[n], 1); - if (hcf->expires == NGX_ERROR) { + if (hcf->expires_time == NGX_ERROR) { return "invalid value"; } - if (hcf->expires == NGX_PARSE_LARGE_TIME) { + if (hcf->expires_time == NGX_PARSE_LARGE_TIME) { return "value must be less than 68 years"; } if (minus) { - hcf->expires = - hcf->expires; + hcf->expires_time = - hcf->expires_time; } return NGX_CONF_OK; diff --git a/src/http/modules/ngx_http_log_module.c b/src/http/modules/ngx_http_log_module.c --- a/src/http/modules/ngx_http_log_module.c +++ b/src/http/modules/ngx_http_log_module.c @@ -88,6 +88,7 @@ static size_t ngx_http_log_variable_getl uintptr_t data); static u_char *ngx_http_log_variable(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op); +static uintptr_t ngx_http_log_escape(u_char *dst, u_char *src, size_t size); static void *ngx_http_log_create_main_conf(ngx_conf_t *cf); @@ -478,6 +479,7 @@ ngx_http_log_variable_compile(ngx_conf_t static size_t ngx_http_log_variable_getlen(ngx_http_request_t *r, uintptr_t data) { + uintptr_t len; ngx_http_variable_value_t *value; value = ngx_http_get_indexed_variable(r, data); @@ -486,7 +488,11 @@ ngx_http_log_variable_getlen(ngx_http_re return 1; } - return value->len; + len = ngx_http_log_escape(NULL, value->data, value->len); + + value->escape = len ? 1 : 0; + + return value->len + len * 3; } @@ -502,7 +508,70 @@ ngx_http_log_variable(ngx_http_request_t return buf + 1; } - return ngx_cpymem(buf, value->data, value->len); + if (value->escape == 0) { + return ngx_cpymem(buf, value->data, value->len); + + } else { + return (u_char *) ngx_http_log_escape(buf, value->data, value->len); + } +} + + +static uintptr_t +ngx_http_log_escape(u_char *dst, u_char *src, size_t size) +{ + ngx_uint_t i, n; + static u_char hex[] = "0123456789ABCDEF"; + + static uint32_t escape[] = { + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + + /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ + 0x00000004, /* 0000 0000 0000 0000 0000 0000 0000 0100 */ + + /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */ + 0x10000000, /* 0001 0000 0000 0000 0000 0000 0000 0000 */ + + /* ~}| {zyx wvut srqp onml kjih gfed cba` */ + 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ + + 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ + 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ + 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ + 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ + }; + + + if (dst == NULL) { + + /* find the number of the characters to be escaped */ + + n = 0; + + for (i = 0; i < size; i++) { + if (escape[*src >> 5] & (1 << (*src & 0x1f))) { + n++; + } + src++; + } + + return (uintptr_t) n; + } + + for (i = 0; i < size; i++) { + if (escape[*src >> 5] & (1 << (*src & 0x1f))) { + *dst++ = '\\'; + *dst++ = 'x'; + *dst++ = hex[*src >> 4]; + *dst++ = hex[*src & 0xf]; + src++; + + } else { + *dst++ = *src++; + } + } + + return (uintptr_t) dst; } diff --git a/src/http/modules/ngx_http_userid_filter_module.c b/src/http/modules/ngx_http_userid_filter_module.c --- a/src/http/modules/ngx_http_userid_filter_module.c +++ b/src/http/modules/ngx_http_userid_filter_module.c @@ -41,15 +41,14 @@ typedef struct { } ngx_http_userid_ctx_t; -static void ngx_http_userid_get_uid(ngx_http_request_t *r, - ngx_http_userid_ctx_t *ctx, ngx_http_userid_conf_t *conf); +static ngx_http_userid_ctx_t *ngx_http_userid_get_uid(ngx_http_request_t *r, + ngx_http_userid_conf_t *conf); +static ngx_int_t ngx_http_userid_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, ngx_str_t *name, uint32_t *uid); static ngx_int_t ngx_http_userid_set_uid(ngx_http_request_t *r, ngx_http_userid_ctx_t *ctx, ngx_http_userid_conf_t *conf); static ngx_int_t ngx_http_userid_add_variables(ngx_conf_t *cf); -static ngx_int_t ngx_http_userid_variable(ngx_http_request_t *r, - ngx_http_variable_value_t *v, uintptr_t data); - static ngx_int_t ngx_http_userid_init(ngx_conf_t *cf); static void *ngx_http_userid_create_conf(ngx_conf_t *cf); static char *ngx_http_userid_merge_conf(ngx_conf_t *cf, void *parent, @@ -191,7 +190,6 @@ static ngx_str_t ngx_http_userid_set = static ngx_int_t ngx_http_userid_filter(ngx_http_request_t *r) { - ngx_int_t rc; ngx_http_userid_ctx_t *ctx; ngx_http_userid_conf_t *conf; @@ -201,25 +199,18 @@ ngx_http_userid_filter(ngx_http_request_ conf = ngx_http_get_module_loc_conf(r, ngx_http_userid_filter_module); - if (conf->enable == NGX_HTTP_USERID_OFF) { + if (conf->enable <= NGX_HTTP_USERID_LOG) { return ngx_http_next_header_filter(r); } + ctx = ngx_http_userid_get_uid(r, conf); - ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_userid_ctx_t)); if (ctx == NULL) { return NGX_ERROR; } - ngx_http_set_ctx(r, ctx, ngx_http_userid_filter_module); - - ngx_http_userid_get_uid(r, ctx, conf); + if (ctx->uid_got[3] != 0) { - if (conf->enable == NGX_HTTP_USERID_LOG) { - return ngx_http_next_header_filter(r); - } - - if (ctx->uid_got[3] != 0) { if (conf->mark == '\0') { return ngx_http_next_header_filter(r); @@ -233,28 +224,95 @@ ngx_http_userid_filter(ngx_http_request_ } } - rc = ngx_http_userid_set_uid(r, ctx, conf); + /* ctx->status == NGX_DECLINED */ - if (rc != NGX_OK) { - return rc; + if (ngx_http_userid_set_uid(r, ctx, conf) == NGX_OK) { + return ngx_http_next_header_filter(r); } - return ngx_http_next_header_filter(r); + return NGX_ERROR; +} + + +static ngx_int_t +ngx_http_userid_got_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_http_userid_ctx_t *ctx; + ngx_http_userid_conf_t *conf; + + conf = ngx_http_get_module_loc_conf(r->main, ngx_http_userid_filter_module); + + if (conf->enable == NGX_HTTP_USERID_OFF) { + v->not_found = 1; + return NGX_OK; + } + + ctx = ngx_http_userid_get_uid(r, conf); + + if (ctx == NULL) { + return NGX_ERROR; + } + + if (ctx->uid_got[3] != 0) { + return ngx_http_userid_variable(r, v, &conf->name, ctx->uid_got); + } + + /* ctx->status == NGX_DECLINED */ + + v->not_found = 1; + + return NGX_OK; } -static void -ngx_http_userid_get_uid(ngx_http_request_t *r, ngx_http_userid_ctx_t *ctx, - ngx_http_userid_conf_t *conf) +static ngx_int_t +ngx_http_userid_set_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) { - ngx_int_t n; - ngx_str_t src, dst; - ngx_table_elt_t **cookies; + ngx_http_userid_ctx_t *ctx; + ngx_http_userid_conf_t *conf; + + ctx = ngx_http_get_module_ctx(r, ngx_http_userid_filter_module); + + if (ctx == NULL || ctx->uid_set[3] == 0) { + v->not_found = 1; + return NGX_OK; + } + + conf = ngx_http_get_module_loc_conf(r, ngx_http_userid_filter_module); + + return ngx_http_userid_variable(r, v, &conf->name, ctx->uid_set); +} + + +static ngx_http_userid_ctx_t * +ngx_http_userid_get_uid(ngx_http_request_t *r, ngx_http_userid_conf_t *conf) +{ + ngx_int_t n; + ngx_str_t src, dst; + ngx_table_elt_t **cookies; + ngx_http_userid_ctx_t *ctx; + + ctx = ngx_http_get_module_ctx(r, ngx_http_userid_filter_module); + + if (ctx) { + return ctx; + } + + if (ctx == NULL) { + ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_userid_ctx_t)); + if (ctx == NULL) { + return NULL; + } + + ngx_http_set_ctx(r, ctx, ngx_http_userid_filter_module); + } n = ngx_http_parse_multi_header_lines(&r->headers_in.cookies, &conf->name, &ctx->cookie); if (n == NGX_DECLINED) { - return; + return ctx; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, @@ -265,7 +323,7 @@ ngx_http_userid_get_uid(ngx_http_request ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "client sent too short userid cookie \"%V\"", &cookies[n]->value); - return; + return ctx; } src = ctx->cookie; @@ -286,13 +344,15 @@ ngx_http_userid_get_uid(ngx_http_request ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "client sent invalid userid cookie \"%V\"", &cookies[n]->value); - return; + return ctx; } ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "uid: %08XD%08XD%08XD%08XD", ctx->uid_got[0], ctx->uid_got[1], ctx->uid_got[2], ctx->uid_got[3]); + + return ctx; } @@ -304,7 +364,6 @@ ngx_http_userid_set_uid(ngx_http_request size_t len; ngx_str_t src, dst; ngx_table_elt_t *set_cookie, *p3p; - /* * TODO: in the threaded mode the sequencers should be in TLS and their * ranges should be divided between threads @@ -433,50 +492,10 @@ ngx_http_userid_set_uid(ngx_http_request static ngx_int_t -ngx_http_userid_add_variables(ngx_conf_t *cf) +ngx_http_userid_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, + ngx_str_t *name, uint32_t *uid) { - ngx_http_variable_t *var; - - var = ngx_http_add_variable(cf, &ngx_http_userid_got, NGX_HTTP_VAR_NOHASH); - if (var == NULL) { - return NGX_ERROR; - } - - var->get_handler = ngx_http_userid_variable; - var->data = offsetof(ngx_http_userid_ctx_t, uid_got); - - var = ngx_http_add_variable(cf, &ngx_http_userid_set, NGX_HTTP_VAR_NOHASH); - if (var == NULL) { - return NGX_ERROR; - } - - var->get_handler = ngx_http_userid_variable; - var->data = offsetof(ngx_http_userid_ctx_t, uid_set); - - return NGX_OK; -} - - -static ngx_int_t -ngx_http_userid_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, - uintptr_t data) -{ - uint32_t *uid; - ngx_http_userid_ctx_t *ctx; - ngx_http_userid_conf_t *conf; - - ctx = ngx_http_get_module_ctx(r, ngx_http_userid_filter_module); - - uid = (uint32_t *) ((char *) ctx + data); - - if (ctx == NULL || uid[3] == 0) { - v->not_found = 1; - return NGX_OK; - } - - conf = ngx_http_get_module_loc_conf(r, ngx_http_userid_filter_module); - - v->len = conf->name.len + sizeof("=00001111222233334444555566667777") - 1; + v->len = name->len + sizeof("=00001111222233334444555566667777") - 1; v->data = ngx_palloc(r->pool, v->len); if (v->data == NULL) { return NGX_ERROR; @@ -487,7 +506,30 @@ ngx_http_userid_variable(ngx_http_reques v->not_found = 0; ngx_sprintf(v->data, "%V=%08XD%08XD%08XD%08XD", - &conf->name, uid[0], uid[1], uid[2], uid[3]); + name, uid[0], uid[1], uid[2], uid[3]); + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_userid_add_variables(ngx_conf_t *cf) +{ + ngx_http_variable_t *var; + + var = ngx_http_add_variable(cf, &ngx_http_userid_got, NGX_HTTP_VAR_NOHASH); + if (var == NULL) { + return NGX_ERROR; + } + + var->get_handler = ngx_http_userid_got_variable; + + var = ngx_http_add_variable(cf, &ngx_http_userid_set, NGX_HTTP_VAR_NOHASH); + if (var == NULL) { + return NGX_ERROR; + } + + var->get_handler = ngx_http_userid_set_variable; return NGX_OK; } diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm --- a/src/http/modules/perl/nginx.pm +++ b/src/http/modules/perl/nginx.pm @@ -47,7 +47,7 @@ our @EXPORT = qw( HTTP_INSUFFICIENT_STORAGE ); -our $VERSION = '0.6.31'; +our $VERSION = '0.7.0'; require XSLoader; XSLoader::load('nginx', $VERSION); diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -2606,20 +2606,7 @@ ngx_http_core_merge_srv_conf(ngx_conf_t } if (conf->server_name.data == NULL) { - conf->server_name.data = ngx_palloc(cf->pool, NGX_MAXHOSTNAMELEN); - if (conf->server_name.data == NULL) { - return NGX_CONF_ERROR; - } - - if (gethostname((char *) conf->server_name.data, NGX_MAXHOSTNAMELEN) - == -1) - { - ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno, - "gethostname() failed"); - return NGX_CONF_ERROR; - } - - conf->server_name.len = ngx_strlen(conf->server_name.data); + conf->server_name = cf->cycle->hostname; sn = ngx_array_push(&conf->server_names); if (sn == NULL) { @@ -2922,7 +2909,7 @@ ngx_http_core_merge_loc_conf(ngx_conf_t return NGX_CONF_ERROR; } } - + conf->resolver = prev->resolver; } @@ -3216,8 +3203,7 @@ ngx_http_core_server_name(ngx_conf_t *cf value[i].len--; value[i].data++; - sn->regex = ngx_regex_compile(&value[i], NGX_REGEX_CASELESS, cf->pool, - &err); + sn->regex = ngx_regex_compile(&value[i], 0, cf->pool, &err); if (sn->regex == NULL) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data); diff --git a/src/http/ngx_http_header_filter_module.c b/src/http/ngx_http_header_filter_module.c --- a/src/http/ngx_http_header_filter_module.c +++ b/src/http/ngx_http_header_filter_module.c @@ -286,9 +286,8 @@ ngx_http_header_filter(ngx_http_request_ cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); host = cscf->server_name; - } else if (r->headers_in.host) { - host.len = r->headers_in.host_name_len; - host.data = r->headers_in.host->value.data; + } else if (r->headers_in.server.len) { + host = r->headers_in.server; } else { host.data = addr; diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -21,15 +21,20 @@ static ngx_int_t ngx_http_process_header ngx_table_elt_t *h, ngx_uint_t offset); static ngx_int_t ngx_http_process_unique_header_line(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset); +static ngx_int_t ngx_http_process_host(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset); static ngx_int_t ngx_http_process_connection(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset); +static ngx_int_t ngx_http_process_user_agent(ngx_http_request_t *r, + ngx_table_elt_t *h, ngx_uint_t offset); static ngx_int_t ngx_http_process_cookie(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset); static ngx_int_t ngx_http_process_request_header(ngx_http_request_t *r); static void ngx_http_process_request(ngx_http_request_t *r); -static void ngx_http_find_virtual_server(ngx_http_request_t *r, u_char *host, - size_t len, ngx_uint_t hash); +static ssize_t ngx_http_validate_host(u_char *host, size_t len); +static ngx_int_t ngx_http_find_virtual_server(ngx_http_request_t *r, + u_char *host, size_t len); static void ngx_http_request_handler(ngx_event_t *ev); static ngx_int_t ngx_http_set_write_handler(ngx_http_request_t *r); @@ -69,18 +74,15 @@ static char *ngx_http_client_errors[] = ngx_http_header_t ngx_http_headers_in[] = { - { ngx_string("Host"), offsetof(ngx_http_headers_in_t, host), - ngx_http_process_unique_header_line }, - - { ngx_string("Connection"), offsetof(ngx_http_headers_in_t, connection), - ngx_http_process_connection }, + { ngx_string("Host"), 0, ngx_http_process_host }, + + { ngx_string("Connection"), 0, ngx_http_process_connection }, { ngx_string("If-Modified-Since"), offsetof(ngx_http_headers_in_t, if_modified_since), ngx_http_process_unique_header_line }, - { ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent), - ngx_http_process_header_line }, + { ngx_string("User-Agent"), 0, ngx_http_process_user_agent }, { ngx_string("Referer"), offsetof(ngx_http_headers_in_t, referer), ngx_http_process_header_line }, @@ -562,8 +564,6 @@ ngx_http_ssl_handshake_handler(ngx_conne int ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg) { - u_char *p; - ngx_uint_t hash; const char *servername; ngx_connection_t *c; ngx_http_request_t *r; @@ -582,21 +582,13 @@ ngx_http_ssl_servername(ngx_ssl_conn_t * r = c->data; - if (r->virtual_names == NULL) { + if (ngx_http_find_virtual_server(r, (u_char *) servername, + ngx_strlen(servername)) + != NGX_OK) + { return SSL_TLSEXT_ERR_NOACK; } - /* it seems browsers send low case server name */ - - hash = 0; - - for (p = (u_char *) servername; *p; p++) { - hash = ngx_hash(hash, *p); - } - - ngx_http_find_virtual_server(r, (u_char *) servername, - p - (u_char *) servername, hash); - sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module); SSL_set_SSL_CTX(ssl_conn, sscf->ssl.ctx); @@ -726,7 +718,31 @@ ngx_http_process_request_line(ngx_event_ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http exten: \"%V\"", &r->exten); + if (r->host_start && r->host_end) { + n = ngx_http_validate_host(r->host_start, + r->host_end - r->host_start); + + if (n <= 0) { + ngx_log_error(NGX_LOG_INFO, c->log, 0, + "client sent invalid host in request line"); + ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); + return; + } + + r->headers_in.server.len = n; + r->headers_in.server.data = r->host_start; + } + if (r->http_version < NGX_HTTP_VERSION_10) { + + if (ngx_http_find_virtual_server(r, r->headers_in.server.data, + r->headers_in.server.len) + == NGX_ERROR) + { + ngx_http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + ngx_http_process_request(r); return; } @@ -1217,6 +1233,36 @@ ngx_http_process_unique_header_line(ngx_ static ngx_int_t +ngx_http_process_host(ngx_http_request_t *r, ngx_table_elt_t *h, + ngx_uint_t offset) +{ + ssize_t len; + + if (r->headers_in.host == NULL) { + r->headers_in.host = h; + } + + len = ngx_http_validate_host(h->value.data, h->value.len); + + if (len <= 0) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent invalid host header"); + ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); + return NGX_ERROR; + } + + if (r->headers_in.server.len) { + return NGX_OK; + } + + r->headers_in.server.len = len; + r->headers_in.server.data = h->value.data; + + return NGX_OK; +} + + +static ngx_int_t ngx_http_process_connection(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset) { @@ -1232,6 +1278,60 @@ ngx_http_process_connection(ngx_http_req static ngx_int_t +ngx_http_process_user_agent(ngx_http_request_t *r, ngx_table_elt_t *h, + ngx_uint_t offset) +{ + u_char *ua, *user_agent; + + if (r->headers_in.user_agent) { + return NGX_OK; + } + + r->headers_in.user_agent = h; + + /* check some widespread browsers while the header is in CPU cache */ + + user_agent = h->value.data; + + ua = ngx_strstrn(user_agent, "MSIE", 4 - 1); + + if (ua && ua + 8 < user_agent + h->value.len) { + + r->headers_in.msie = 1; + + if (ua[4] == ' ' && ua[5] == '4' && ua[6] == '.') { + r->headers_in.msie4 = 1; + } + +#if 0 + /* MSIE ignores the SSL "close notify" alert */ + if (c->ssl) { + c->ssl->no_send_shutdown = 1; + } +#endif + } + + if (ngx_strstrn(user_agent, "Opera", 5 - 1)) { + r->headers_in.opera = 1; + r->headers_in.msie = 0; + r->headers_in.msie4 = 0; + } + + if (!r->headers_in.msie && !r->headers_in.opera) { + + if (ngx_strstrn(user_agent, "Gecko/", 6 - 1)) { + r->headers_in.gecko = 1; + + } else if (ngx_strstrn(user_agent, "Konqueror", 9 - 1)) { + r->headers_in.konqueror = 1; + } + } + + return NGX_OK; +} + + +static ngx_int_t ngx_http_process_cookie(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset) { @@ -1252,57 +1352,19 @@ ngx_http_process_cookie(ngx_http_request static ngx_int_t ngx_http_process_request_header(ngx_http_request_t *r) { - size_t len; - u_char *host, *ua, *user_agent, ch; - ngx_uint_t hash; - - if (r->headers_in.host) { - - hash = 0; - - for (len = 0; len < r->headers_in.host->value.len; len++) { - ch = r->headers_in.host->value.data[len]; - - if (ch == ':') { - break; - } - - ch = ngx_tolower(ch); - r->headers_in.host->value.data[len] = ch; - hash = ngx_hash(hash, ch); - } - - if (len && r->headers_in.host->value.data[len - 1] == '.') { - len--; - hash = ngx_hash_key(r->headers_in.host->value.data, len); - } - - r->headers_in.host_name_len = len; - - if (r->virtual_names) { - - host = r->host_start; - - if (host == NULL) { - host = r->headers_in.host->value.data; - len = r->headers_in.host_name_len; - - } else { - len = r->host_end - host; - } - - ngx_http_find_virtual_server(r, host, len, hash); - } - - } else { - if (r->http_version > NGX_HTTP_VERSION_10) { - ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, - "client sent HTTP/1.1 request without \"Host\" header"); - ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); - return NGX_ERROR; - } - - r->headers_in.host_name_len = 0; + if (ngx_http_find_virtual_server(r, r->headers_in.server.data, + r->headers_in.server.len) + == NGX_ERROR) + { + ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return NGX_ERROR; + } + + if (r->headers_in.host == NULL && r->http_version > NGX_HTTP_VERSION_10) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "client sent HTTP/1.1 request without \"Host\" header"); + ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); + return NGX_ERROR; } if (r->headers_in.content_length) { @@ -1353,50 +1415,6 @@ ngx_http_process_request_header(ngx_http } } - if (r->headers_in.user_agent) { - - /* - * check some widespread browsers while the headers are still - * in CPU cache - */ - - user_agent = r->headers_in.user_agent->value.data; - - ua = ngx_strstrn(user_agent, "MSIE", 4 - 1); - - if (ua && ua + 8 < user_agent + r->headers_in.user_agent->value.len) { - - r->headers_in.msie = 1; - - if (ua[4] == ' ' && ua[5] == '4' && ua[6] == '.') { - r->headers_in.msie4 = 1; - } - -#if 0 - /* MSIE ignores the SSL "close notify" alert */ - if (c->ssl) { - c->ssl->no_send_shutdown = 1; - } -#endif - } - - if (ngx_strstrn(user_agent, "Opera", 5 - 1)) { - r->headers_in.opera = 1; - r->headers_in.msie = 0; - r->headers_in.msie4 = 0; - } - - if (!r->headers_in.msie && !r->headers_in.opera) { - - if (ngx_strstrn(user_agent, "Gecko/", 6 - 1)) { - r->headers_in.gecko = 1; - - } else if (ngx_strstrn(user_agent, "Konqueror", 9 - 1)) { - r->headers_in.konqueror = 1; - } - } - } - return NGX_OK; } @@ -1479,14 +1497,89 @@ ngx_http_process_request(ngx_http_reques } -static void -ngx_http_find_virtual_server(ngx_http_request_t *r, u_char *host, size_t len, - ngx_uint_t hash) +static ssize_t +ngx_http_validate_host(u_char *host, size_t len) { + u_char ch; + size_t i, last; + ngx_uint_t dot; + + last = len; + dot = 0; + + for (i = 0; i < len; i++) { + ch = host[i]; + + if (ch == '.') { + if (dot) { + return -1; + } + + dot = 1; + continue; + } + + dot = 0; + + if (ch == ':') { + last = i; + continue; + } + + if (ch == '/' || ch == '\0') { + return -1; + } + +#if (NGX_WIN32) + if (ch == '\\') { + return -1; + } +#endif + } + + if (dot) { + last--; + } + + return last; +} + + +static ngx_int_t +ngx_http_find_virtual_server(ngx_http_request_t *r, u_char *host, size_t len) +{ + u_char *server, ch; + ngx_uint_t i, hash; ngx_http_core_loc_conf_t *clcf; ngx_http_core_srv_conf_t *cscf; - - cscf = ngx_hash_find_combined(&r->virtual_names->names, hash, host, len); + u_char buf[32]; + + if (len == 0 || r->virtual_names == NULL) { + return NGX_DECLINED; + } + + if (len <= 32) { + server = buf; + + } else { + server = ngx_palloc(r->pool, len); + if (server == NULL) { + return NGX_ERROR; + } + } + + hash = 0; + + for (i = 0; i < len; i++) { + ch = host[i]; + + ch = ngx_tolower(ch); + server[i] = ch; + + hash = ngx_hash(hash, ch); + } + + cscf = ngx_hash_find_combined(&r->virtual_names->names, hash, server, len); if (cscf) { goto found; @@ -1501,7 +1594,7 @@ ngx_http_find_virtual_server(ngx_http_re ngx_http_server_name_t *sn; name.len = len; - name.data = host; + name.data = server; sn = r->virtual_names->regex; @@ -1518,7 +1611,7 @@ ngx_http_find_virtual_server(ngx_http_re ngx_regex_exec_n " failed: %d on \"%V\" using \"%V\"", n, &name, &sn[i].name); - return; + return NGX_ERROR; } /* match */ @@ -1531,7 +1624,7 @@ ngx_http_find_virtual_server(ngx_http_re #endif - return; + return NGX_OK; found: @@ -1545,7 +1638,7 @@ found: r->connection->log->log_level = clcf->err_log->log_level; } - return; + return NGX_OK; } @@ -2064,7 +2157,8 @@ ngx_http_set_keepalive(ngx_http_request_ hc->pipeline = 1; c->log->action = "reading client pipelined request line"; - ngx_http_init_request(rev); + rev->handler = ngx_http_init_request; + ngx_post_event(rev, &ngx_posted_events); return; } @@ -2180,7 +2274,7 @@ ngx_http_set_keepalive(ngx_http_request_ c->idle = 1; if (rev->ready) { - ngx_http_keepalive_handler(rev); + ngx_post_event(rev, &ngx_posted_events); } } diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -206,7 +206,7 @@ typedef struct { ngx_array_t cookies; - size_t host_name_len; + ngx_str_t server; off_t content_length_n; time_t keep_alive_n; diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c --- a/src/http/ngx_http_variables.c +++ b/src/http/ngx_http_variables.c @@ -75,6 +75,8 @@ static ngx_int_t ngx_http_variable_sent_ static ngx_int_t ngx_http_variable_nginx_version(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_hostname(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); /* * TODO: @@ -221,6 +223,9 @@ static ngx_http_variable_t ngx_http_cor { ngx_string("nginx_version"), NULL, ngx_http_variable_nginx_version, 0, 0, 0 }, + { ngx_string("hostname"), NULL, ngx_http_variable_hostname, + 0, 0, 0 }, + { ngx_null_string, NULL, NULL, 0, 0, 0 } }; @@ -712,26 +717,15 @@ ngx_http_variable_host(ngx_http_request_ { ngx_http_core_srv_conf_t *cscf; - if (r->host_start == NULL) { - - if (r->headers_in.host) { - v->len = r->headers_in.host_name_len; - v->data = r->headers_in.host->value.data; - - } else { - cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); - - v->len = cscf->server_name.len; - v->data = cscf->server_name.data; - } - - } else if (r->host_end) { - v->len = r->host_end - r->host_start; - v->data = r->host_start; + if (r->headers_in.server.len) { + v->len = r->headers_in.server.len; + v->data = r->headers_in.server.data; } else { - v->not_found = 1; - return NGX_OK; + cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); + + v->len = cscf->server_name.len; + v->data = cscf->server_name.data; } v->valid = 1; @@ -1283,6 +1277,20 @@ ngx_http_variable_nginx_version(ngx_http } +static ngx_int_t +ngx_http_variable_hostname(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + v->len = ngx_cycle->hostname.len; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->data = ngx_cycle->hostname.data; + + return NGX_OK; +} + + ngx_int_t ngx_http_variables_add_core_vars(ngx_conf_t *cf) { diff --git a/src/http/ngx_http_variables.h b/src/http/ngx_http_variables.h --- a/src/http/ngx_http_variables.h +++ b/src/http/ngx_http_variables.h @@ -16,7 +16,7 @@ typedef ngx_variable_value_t ngx_http_variable_value_t; -#define ngx_http_variable(v) { sizeof(v) - 1, 1, 0, 0, (u_char *) v } +#define ngx_http_variable(v) { sizeof(v) - 1, 1, 0, 0, 0, (u_char *) v } typedef struct ngx_http_variable_s ngx_http_variable_t; diff --git a/src/mail/ngx_mail_core_module.c b/src/mail/ngx_mail_core_module.c --- a/src/mail/ngx_mail_core_module.c +++ b/src/mail/ngx_mail_core_module.c @@ -185,20 +185,7 @@ ngx_mail_core_merge_srv_conf(ngx_conf_t ngx_conf_merge_str_value(conf->server_name, prev->server_name, ""); if (conf->server_name.len == 0) { - conf->server_name.data = ngx_palloc(cf->pool, NGX_MAXHOSTNAMELEN); - if (conf->server_name.data == NULL) { - return NGX_CONF_ERROR; - } - - if (gethostname((char *) conf->server_name.data, NGX_MAXHOSTNAMELEN) - == -1) - { - ngx_log_error(NGX_LOG_EMERG, cf->log, ngx_errno, - "gethostname() failed"); - return NGX_CONF_ERROR; - } - - conf->server_name.len = ngx_strlen(conf->server_name.data); + conf->server_name = cf->cycle->hostname; } if (conf->protocol == NULL) { diff --git a/src/os/unix/ngx_posix_config.h b/src/os/unix/ngx_posix_config.h --- a/src/os/unix/ngx_posix_config.h +++ b/src/os/unix/ngx_posix_config.h @@ -110,7 +110,7 @@ #include /* ALIGN() */ -/* +/* * FreeBSD 3.x has no CMSG_SPACE() and CMSG_LEN() and has the broken CMSG_DATA() */