# HG changeset patch # User Igor Sysoev # Date 1192996800 -14400 # Node ID 4276c2f1f434d6e7e350d9675b2fcc6efb99f79c # Parent 183b4761fe5b9bfcc0690957bfff099f61c81541 nginx 0.6.15 *) Feature: cygwin compatibility. Thanks to Vladimir Kutakov. *) Feature: the "merge_slashes" directive. *) Feature: the "gzip_vary" directive. *) Feature: the "server_tokens" directive. *) Bugfix: nginx did not unescape URI in the "include" SSI command. *) Bugfix: the segmentation fault was occurred on start or while reconfiguration if variable was used in the "charset" or "source_charset" directives. *) Bugfix: nginx returned the 400 response on requests like "GET http://www.domain.com HTTP/1.0". Thanks to James Oakley. *) Bugfix: if request with request body was redirected using the "error_page" directive, then nginx tried to read the request body again; bug appeared in 0.6.7. *) Bugfix: a segmentation fault occurred in worker process if no server_name was explicitly defined for server processing request; bug appeared in 0.6.7. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,34 @@ +Changes with nginx 0.6.15 22 Oct 2007 + + *) Feature: cygwin compatibility. + Thanks to Vladimir Kutakov. + + *) Feature: the "merge_slashes" directive. + + *) Feature: the "gzip_vary" directive. + + *) Feature: the "server_tokens" directive. + + *) Bugfix: nginx did not unescape URI in the "include" SSI command. + + *) Bugfix: the segmentation fault was occurred on start or while + reconfiguration if variable was used in the "charset" or + "source_charset" directives. + + *) Bugfix: nginx returned the 400 response on requests like + "GET http://www.domain.com HTTP/1.0". + Thanks to James Oakley. + + *) Bugfix: if request with request body was redirected using the + "error_page" directive, then nginx tried to read the request body + again; bug appeared in 0.6.7. + + *) Bugfix: a segmentation fault occurred in worker process if no + server_name was explicitly defined for server processing request; + bug appeared in 0.6.7. + + Changes with nginx 0.6.14 15 Oct 2007 *) Change: now by default the "echo" SSI command uses entity encoding. diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,34 @@ +Изменения в nginx 0.6.15 22.10.2007 + + *) Добавление: совместимость с cygwin. + Спасибо Владимиру Кутакову. + + *) Добавление: директива merge_slashes. + + *) Добавление: директива gzip_vary. + + *) Добавление: директива server_tokens. + + *) Исправление: nginx не раскодировал URI в команде SSI include. + + *) Исправление: при использовании переменной в директивах charset или + source_charset на старте или во время переконфигурации происходил + segmentation fault, + + *) Исправление: nginx возвращал ошибку 400 на запросы вида + "GET http://www.domain.com HTTP/1.0". + Спасибо James Oakley. + + *) Исправление: после перенаправления запроса с телом запроса с помощью + директивы error_page nginx пытался снова прочитать тело запроса; + ошибка появилась в 0.6.7. + + *) Исправление: в рабочем процессе происходил segmentation fault, если + у сервера, обрабатывающему запрос, не был явно определён + server_name; ошибка появилась в 0.6.7. + + Изменения в nginx 0.6.14 15.10.2007 *) Изменение: теперь по умолчанию команда SSI echo использует diff --git a/auto/headers b/auto/headers --- a/auto/headers +++ b/auto/headers @@ -6,3 +6,5 @@ ngx_include="unistd.h"; . auto/includ ngx_include="inttypes.h"; . auto/include ngx_include="limits.h"; . auto/include ngx_include="sys/filio.h"; . auto/include +ngx_include="crypt.h"; . auto/include +ngx_include="malloc.h"; . auto/include diff --git a/auto/sources b/auto/sources --- a/auto/sources +++ b/auto/sources @@ -21,6 +21,8 @@ CORE_DEPS="src/core/nginx.h \ src/core/ngx_file.h \ src/core/ngx_crc.h \ src/core/ngx_crc32.h \ + src/core/ngx_md5.h \ + src/core/ngx_sha1.h \ src/core/ngx_rbtree.h \ src/core/ngx_radix_tree.h \ src/core/ngx_slab.h \ 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.14" +#define NGINX_VERSION "0.6.15" #define NGINX_VER "nginx/" NGINX_VERSION #define NGINX_VAR "NGINX" diff --git a/src/core/ngx_md5.h b/src/core/ngx_md5.h new file mode 100644 --- /dev/null +++ b/src/core/ngx_md5.h @@ -0,0 +1,40 @@ + +/* + * Copyright (C) Igor Sysoev + */ + + +#ifndef _NGX_MD5_H_INCLUDED_ +#define _NGX_MD5_H_INCLUDED_ + + +#include +#include + + +#if (NGX_HAVE_OPENSSL_MD5_H) +#include +#else +#include +#endif + + +typedef MD5_CTX ngx_md5_t; + + +#if (NGX_OPENSSL_MD5) + +#define ngx_md5_init MD5_Init +#define ngx_md5_update MD5_Update +#define ngx_md5_final MD5_Final + +#else + +#define ngx_md5_init MD5Init +#define ngx_md5_update MD5Update +#define ngx_md5_final MD5Final + +#endif + + +#endif /* _NGX_MD5_H_INCLUDED_ */ diff --git a/src/core/ngx_sha1.h b/src/core/ngx_sha1.h new file mode 100644 --- /dev/null +++ b/src/core/ngx_sha1.h @@ -0,0 +1,30 @@ + +/* + * Copyright (C) Igor Sysoev + */ + + +#ifndef _NGX_SHA1_H_INCLUDED_ +#define _NGX_SHA1_H_INCLUDED_ + + +#include +#include + + +#if (NGX_HAVE_OPENSSL_SHA1_H) +#include +#else +#include +#endif + + +typedef SHA_CTX ngx_sha1_t; + + +#define ngx_sha1_init SHA1_Init +#define ngx_sha1_update SHA1_Update +#define ngx_sha1_final SHA1_Final + + +#endif /* _NGX_SHA1_H_INCLUDED_ */ diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c --- a/src/core/ngx_string.c +++ b/src/core/ngx_string.c @@ -1243,7 +1243,9 @@ ngx_unescape_uri(u_char **dst, u_char ** switch (state) { case sw_usual: - if (ch == '?' && type == NGX_UNESCAPE_URI) { + if (ch == '?' + && (type & (NGX_UNESCAPE_URI|NGX_UNESCAPE_REDIRECT))) + { *d++ = ch; goto done; } @@ -1286,7 +1288,7 @@ ngx_unescape_uri(u_char **dst, u_char ** if (ch >= '0' && ch <= '9') { ch = (u_char) ((decoded << 4) + ch - '0'); - if (type == NGX_UNESCAPE_URI) { + if (type & NGX_UNESCAPE_REDIRECT) { if (ch > '%' && ch < 0x7f) { *d++ = ch; break; @@ -1306,7 +1308,17 @@ ngx_unescape_uri(u_char **dst, u_char ** if (c >= 'a' && c <= 'f') { ch = (u_char) ((decoded << 4) + c - 'a' + 10); - if (type == NGX_UNESCAPE_URI) { + if (type & NGX_UNESCAPE_URI) { + if (ch == '?') { + *d++ = ch; + goto done; + } + + *d++ = ch; + break; + } + + if (type & NGX_UNESCAPE_REDIRECT) { if (ch == '?') { *d++ = ch; goto done; 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 @@ -155,14 +155,15 @@ size_t ngx_utf_length(u_char *p, size_t u_char *ngx_utf_cpystrn(u_char *dst, u_char *src, size_t n); -#define NGX_ESCAPE_URI 0 -#define NGX_ESCAPE_ARGS 1 -#define NGX_ESCAPE_HTML 2 -#define NGX_ESCAPE_REFRESH 3 -#define NGX_ESCAPE_MEMCACHED 4 -#define NGX_ESCAPE_MAIL_AUTH 5 +#define NGX_ESCAPE_URI 0 +#define NGX_ESCAPE_ARGS 1 +#define NGX_ESCAPE_HTML 2 +#define NGX_ESCAPE_REFRESH 3 +#define NGX_ESCAPE_MEMCACHED 4 +#define NGX_ESCAPE_MAIL_AUTH 5 -#define NGX_UNESCAPE_URI 1 +#define NGX_UNESCAPE_URI 1 +#define NGX_UNESCAPE_REDIRECT 2 uintptr_t ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type); diff --git a/src/http/modules/ngx_http_charset_filter_module.c b/src/http/modules/ngx_http_charset_filter_module.c --- a/src/http/modules/ngx_http_charset_filter_module.c +++ b/src/http/modules/ngx_http_charset_filter_module.c @@ -366,8 +366,8 @@ ngx_http_charset_header_filter(ngx_http_ no_charset_map: ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "no \"charset_map\" between the charsets " - "\"%V\" and \"%V\"", from, to); + "no \"charset_map\" between the charsets \"%V\" and \"%V\"", + from, to); return ngx_http_next_header_filter(r); } @@ -1462,6 +1462,12 @@ ngx_http_charset_merge_loc_conf(ngx_conf return NGX_CONF_OK; } + if (conf->source_charset >= NGX_HTTP_CHARSET_VAR + || conf->charset >= NGX_HTTP_CHARSET_VAR) + { + return NGX_CONF_OK; + } + mcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_charset_filter_module); recode = mcf->recodes.elts; @@ -1519,9 +1525,8 @@ ngx_http_charset_postconfiguration(ngx_c } ngx_log_error(NGX_LOG_EMERG, cf->log, 0, - " no \"charset_map\" between the charsets " - "\"%V\" and \"%V\"", - &charset[c].name, &charset[recode[i].dst].name); + "no \"charset_map\" between the charsets \"%V\" and \"%V\"", + &charset[c].name, &charset[recode[i].dst].name); return NGX_ERROR; next: diff --git a/src/http/modules/ngx_http_gzip_filter_module.c b/src/http/modules/ngx_http_gzip_filter_module.c --- a/src/http/modules/ngx_http_gzip_filter_module.c +++ b/src/http/modules/ngx_http_gzip_filter_module.c @@ -14,6 +14,7 @@ typedef struct { ngx_flag_t enable; ngx_flag_t no_buffer; + ngx_flag_t vary; ngx_array_t *types; /* array of ngx_str_t */ @@ -192,6 +193,13 @@ static ngx_command_t ngx_http_gzip_filt offsetof(ngx_http_gzip_conf_t, min_length), NULL }, + { ngx_string("gzip_vary"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_gzip_conf_t, vary), + NULL }, + ngx_null_command }; @@ -261,6 +269,7 @@ ngx_http_gzip_header_filter(ngx_http_req { ngx_str_t *type; ngx_uint_t i; + ngx_table_elt_t *header; ngx_http_gzip_ctx_t *ctx; ngx_http_gzip_conf_t *conf; @@ -336,16 +345,31 @@ found: ctx->request = r; - r->headers_out.content_encoding = ngx_list_push(&r->headers_out.headers); - if (r->headers_out.content_encoding == NULL) { + header = ngx_list_push(&r->headers_out.headers); + if (header == NULL) { return NGX_ERROR; } - r->headers_out.content_encoding->hash = 1; - r->headers_out.content_encoding->key.len = sizeof("Content-Encoding") - 1; - r->headers_out.content_encoding->key.data = (u_char *) "Content-Encoding"; - r->headers_out.content_encoding->value.len = sizeof("gzip") - 1; - r->headers_out.content_encoding->value.data = (u_char *) "gzip"; + header->hash = 1; + header->key.len = sizeof("Content-Encoding") - 1; + header->key.data = (u_char *) "Content-Encoding"; + header->value.len = sizeof("gzip") - 1; + header->value.data = (u_char *) "gzip"; + + r->headers_out.content_encoding = header; + + if (conf->vary) { + header = ngx_list_push(&r->headers_out.headers); + if (header == NULL) { + return NGX_ERROR; + } + + header->hash = 1; + header->key.len = sizeof("Vary") - 1; + header->key.data = (u_char *) "Vary"; + header->value.len = sizeof("Accept-Encoding") - 1; + header->value.data = (u_char *) "Accept-Encoding"; + } ctx->length = r->headers_out.content_length_n; @@ -996,6 +1020,7 @@ ngx_http_gzip_create_conf(ngx_conf_t *cf conf->enable = NGX_CONF_UNSET; conf->no_buffer = NGX_CONF_UNSET; + conf->vary = NGX_CONF_UNSET; conf->http_version = NGX_CONF_UNSET_UINT; @@ -1031,6 +1056,7 @@ ngx_http_gzip_merge_conf(ngx_conf_t *cf, MAX_MEM_LEVEL - 1); ngx_conf_merge_value(conf->min_length, prev->min_length, 20); ngx_conf_merge_value(conf->no_buffer, prev->no_buffer, 0); + ngx_conf_merge_value(conf->vary, prev->vary, 0); if (conf->types == NULL) { if (prev->types == NULL) { diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c --- a/src/http/modules/ngx_http_ssi_filter_module.c +++ b/src/http/modules/ngx_http_ssi_filter_module.c @@ -1858,6 +1858,8 @@ static ngx_int_t ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, ngx_str_t **params) { + u_char *dst, *src; + size_t len; ngx_int_t rc, key; ngx_str_t *uri, *file, *wait, *set, *stub, args; ngx_buf_t *b; @@ -1927,13 +1929,25 @@ ngx_http_ssi_include(ngx_http_request_t return rc; } + dst = uri->data; + src = uri->data; + + ngx_unescape_uri(&dst, &src, uri->len, NGX_UNESCAPE_URI); + + len = (uri->data + uri->len) - src; + if (len) { + dst = ngx_copy(dst, src, len); + } + + uri->len = dst - uri->data; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "ssi include: \"%V\"", uri); + args.len = 0; args.data = NULL; flags = 0; - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "ssi include: \"%V\"", uri); - if (ngx_http_parse_unsafe_uri(r, uri, &args, &flags) != NGX_OK) { return NGX_HTTP_SSI_ERROR; } 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.14'; +our $VERSION = '0.6.15'; require XSLoader; XSLoader::load('nginx', $VERSION); diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h --- a/src/http/ngx_http.h +++ b/src/http/ngx_http.h @@ -64,7 +64,8 @@ int ngx_http_ssl_servername(ngx_ssl_conn #endif ngx_int_t ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b); -ngx_int_t ngx_http_parse_complex_uri(ngx_http_request_t *r); +ngx_int_t ngx_http_parse_complex_uri(ngx_http_request_t *r, + ngx_uint_t merge_slashes); ngx_int_t ngx_http_parse_unsafe_uri(ngx_http_request_t *r, ngx_str_t *uri, ngx_str_t *args, ngx_uint_t *flags); ngx_int_t ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b); 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 @@ -185,6 +185,13 @@ static ngx_command_t ngx_http_core_comm offsetof(ngx_http_core_srv_conf_t, ignore_invalid_headers), NULL }, + { ngx_string("merge_slashes"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_SRV_CONF_OFFSET, + offsetof(ngx_http_core_srv_conf_t, merge_slashes), + NULL }, + { ngx_string("location"), NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_BLOCK|NGX_CONF_TAKE12, ngx_http_core_location, @@ -427,6 +434,13 @@ static ngx_command_t ngx_http_core_comm offsetof(ngx_http_core_loc_conf_t, recursive_error_pages), NULL }, + { ngx_string("server_tokens"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_core_loc_conf_t, server_tokens), + NULL }, + { ngx_string("error_page"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF |NGX_CONF_2MORE, @@ -681,7 +695,7 @@ ngx_http_core_find_config_phase(ngx_http && clcf->client_max_body_size < r->headers_in.content_length_n) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "client intented to send too large body: %O bytes", + "client intended to send too large body: %O bytes", r->headers_in.content_length_n); ngx_http_finalize_request(r, NGX_HTTP_REQUEST_ENTITY_TOO_LARGE); @@ -1598,7 +1612,7 @@ ngx_http_named_location(ngx_http_request } ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "could not find name location \"%V\"", name); + "could not find named location \"%V\"", name); ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NGX_DONE; @@ -2233,6 +2247,7 @@ ngx_http_core_create_srv_conf(ngx_conf_t cscf->client_header_buffer_size = NGX_CONF_UNSET_SIZE; cscf->optimize_server_names = NGX_CONF_UNSET; cscf->ignore_invalid_headers = NGX_CONF_UNSET; + cscf->merge_slashes = NGX_CONF_UNSET; return cscf; } @@ -2292,9 +2307,12 @@ ngx_http_core_merge_srv_conf(ngx_conf_t return NGX_CONF_ERROR; } +#if (NGX_PCRE) + sn->regex = NULL; +#endif + sn->core_srv_conf = conf; sn->name.len = conf->server_name.len; sn->name.data = conf->server_name.data; - sn->core_srv_conf = conf; } ngx_conf_merge_size_value(conf->connection_pool_size, @@ -2322,6 +2340,8 @@ ngx_http_core_merge_srv_conf(ngx_conf_t ngx_conf_merge_value(conf->ignore_invalid_headers, prev->ignore_invalid_headers, 1); + ngx_conf_merge_value(conf->merge_slashes, prev->merge_slashes, 1); + return NGX_CONF_OK; } @@ -2377,6 +2397,7 @@ ngx_http_core_create_loc_conf(ngx_conf_t lcf->msie_refresh = NGX_CONF_UNSET; lcf->log_not_found = NGX_CONF_UNSET; lcf->recursive_error_pages = NGX_CONF_UNSET; + lcf->server_tokens = NGX_CONF_UNSET; lcf->types_hash_max_size = NGX_CONF_UNSET_UINT; lcf->types_hash_bucket_size = NGX_CONF_UNSET_UINT; lcf->open_file_cache = NGX_CONF_UNSET_PTR; @@ -2565,6 +2586,7 @@ ngx_http_core_merge_loc_conf(ngx_conf_t ngx_conf_merge_value(conf->log_not_found, prev->log_not_found, 1); ngx_conf_merge_value(conf->recursive_error_pages, prev->recursive_error_pages, 0); + ngx_conf_merge_value(conf->server_tokens, prev->server_tokens, 1); ngx_conf_merge_ptr_value(conf->open_file_cache, prev->open_file_cache, NULL); diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -143,6 +143,7 @@ typedef struct { ngx_flag_t optimize_server_names; ngx_flag_t ignore_invalid_headers; + ngx_flag_t merge_slashes; } ngx_http_core_srv_conf_t; @@ -185,7 +186,6 @@ typedef struct { #if (NGX_PCRE) ngx_uint_t nregex; ngx_http_server_name_t *regex; - #endif /* the default server configuration for this address:port */ @@ -285,6 +285,7 @@ struct ngx_http_core_loc_conf_s { ngx_flag_t msie_refresh; /* msie_refresh */ ngx_flag_t log_not_found; /* log_not_found */ ngx_flag_t recursive_error_pages; /* recursive_error_pages */ + ngx_flag_t server_tokens; /* server_tokens */ ngx_array_t *error_pages; /* error_page */ 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 @@ -45,7 +45,8 @@ ngx_module_t ngx_http_header_filter_mod }; -static char ngx_http_server_string[] = "Server: " NGINX_VER CRLF; +static char ngx_http_server_string[] = "Server: nginx" CRLF; +static char ngx_http_server_full_string[] = "Server: " NGINX_VER CRLF; static ngx_str_t ngx_http_status_lines[] = { @@ -237,8 +238,11 @@ ngx_http_header_filter(ngx_http_request_ len += ngx_http_status_lines[status].len; } + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + if (r->headers_out.server == NULL) { - len += sizeof(ngx_http_server_string) - 1; + len += clcf->server_tokens ? sizeof(ngx_http_server_full_string) - 1: + sizeof(ngx_http_server_string) - 1; } if (r->headers_out.date == NULL) { @@ -268,8 +272,6 @@ ngx_http_header_filter(ngx_http_request_ len += sizeof("Last-Modified: Mon, 28 Sep 1970 06:00:00 GMT" CRLF) - 1; } - clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); - if (r->headers_out.location && r->headers_out.location->value.len && r->headers_out.location->value.data[0] == '/') @@ -365,8 +367,16 @@ ngx_http_header_filter(ngx_http_request_ *b->last++ = CR; *b->last++ = LF; if (r->headers_out.server == NULL) { - b->last = ngx_cpymem(b->last, ngx_http_server_string, - sizeof(ngx_http_server_string) - 1); + if (clcf->server_tokens) { + p = (u_char *) ngx_http_server_full_string; + len = sizeof(ngx_http_server_full_string) - 1; + + } else { + p = (u_char *) ngx_http_server_string; + len = sizeof(ngx_http_server_string) - 1; + } + + b->last = ngx_cpymem(b->last, p, len); } if (r->headers_out.date == NULL) { diff --git a/src/http/ngx_http_parse.c b/src/http/ngx_http_parse.c --- a/src/http/ngx_http_parse.c +++ b/src/http/ngx_http_parse.c @@ -335,18 +335,26 @@ ngx_http_parse_request_line(ngx_http_req break; } + r->host_end = p; + switch (ch) { case ':': - r->host_end = p; state = sw_port; break; case '/': - r->host_end = p; r->uri_start = p; state = sw_after_slash_in_uri; break; + case ' ': + /* + * use single "/" from request line to preserve pointers, + * if request line will be copied to large client buffer + */ + r->uri_start = r->schema_end + 1; + r->uri_end = r->schema_end + 2; + state = sw_http_09; + break; default: - r->host_end = p; return NGX_HTTP_PARSE_INVALID_REQUEST; } break; @@ -362,6 +370,16 @@ ngx_http_parse_request_line(ngx_http_req r->uri_start = p; state = sw_after_slash_in_uri; break; + case ' ': + r->port_end = p; + /* + * use single "/" from request line to preserve pointers, + * if request line will be copied to large client buffer + */ + r->uri_start = r->schema_end + 1; + r->uri_end = r->schema_end + 2; + state = sw_http_09; + break; default: return NGX_HTTP_PARSE_INVALID_REQUEST; } @@ -890,7 +908,7 @@ header_done: ngx_int_t -ngx_http_parse_complex_uri(ngx_http_request_t *r) +ngx_http_parse_complex_uri(ngx_http_request_t *r, ngx_uint_t merge_slashes) { u_char c, ch, decoded, *p, *u; enum { @@ -998,8 +1016,12 @@ ngx_http_parse_complex_uri(ngx_http_requ switch(ch) { #if (NGX_WIN32) case '\\': + break; #endif case '/': + if (merge_slashes) { + *u++ = ch; + } break; case '.': state = sw_dot; 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 @@ -602,10 +602,11 @@ ngx_http_ssl_servername(ngx_ssl_conn_t * static void ngx_http_process_request_line(ngx_event_t *rev) { - ssize_t n; - ngx_int_t rc, rv; - ngx_connection_t *c; - ngx_http_request_t *r; + ssize_t n; + ngx_int_t rc, rv; + ngx_connection_t *c; + ngx_http_request_t *r; + ngx_http_core_srv_conf_t *cscf; c = rev->data; r = c->data; @@ -657,7 +658,9 @@ ngx_http_process_request_line(ngx_event_ return; } - rc = ngx_http_parse_complex_uri(r); + cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); + + rc = ngx_http_parse_complex_uri(r, cscf->merge_slashes); if (rc == NGX_HTTP_PARSE_INVALID_REQUEST) { ngx_log_error(NGX_LOG_INFO, c->log, 0, diff --git a/src/http/ngx_http_request_body.c b/src/http/ngx_http_request_body.c --- a/src/http/ngx_http_request_body.c +++ b/src/http/ngx_http_request_body.c @@ -442,7 +442,7 @@ ngx_http_discard_request_body(ngx_http_r ngx_del_timer(rev); } - if (r->headers_in.content_length_n <= 0) { + if (r->headers_in.content_length_n <= 0 || r->request_body) { return NGX_OK; } diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c --- a/src/http/ngx_http_script.c +++ b/src/http/ngx_http_script.c @@ -750,7 +750,8 @@ ngx_http_script_regex_end_code(ngx_http_ dst = e->buf.data; src = e->buf.data; - ngx_unescape_uri(&dst, &src, e->pos - e->buf.data, NGX_UNESCAPE_URI); + ngx_unescape_uri(&dst, &src, e->pos - e->buf.data, + NGX_UNESCAPE_REDIRECT); if (src < e->pos) { dst = ngx_copy(dst, src, e->pos - src); diff --git a/src/http/ngx_http_special_response.c b/src/http/ngx_http_special_response.c --- a/src/http/ngx_http_special_response.c +++ b/src/http/ngx_http_special_response.c @@ -10,8 +10,15 @@ #include +static u_char error_full_tail[] = +"
" NGINX_VER "
" CRLF +"" CRLF +"" CRLF +; + + static u_char error_tail[] = -"
" NGINX_VER "
" CRLF +"
nginx
" CRLF "" CRLF "" CRLF ; @@ -471,7 +478,8 @@ ngx_http_special_response_handler(ngx_ht if (!r->zero_body) { if (error_pages[err].len) { r->headers_out.content_length_n = error_pages[err].len - + sizeof(error_tail) - 1; + + (clcf->server_tokens ? sizeof(error_full_tail) - 1: + sizeof(error_tail) - 1); if (clcf->msie_padding && r->headers_in.msie @@ -568,8 +576,14 @@ ngx_http_special_response_handler(ngx_ht } b->memory = 1; - b->pos = error_tail; - b->last = error_tail + sizeof(error_tail) - 1; + + if (clcf->server_tokens) { + b->pos = error_full_tail; + b->last = error_full_tail + sizeof(error_full_tail) - 1; + } else { + b->pos = error_tail; + b->last = error_tail + sizeof(error_tail) - 1; + } cl->next = ngx_alloc_chain_link(r->pool); if (cl->next == 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 @@ -19,6 +19,12 @@ #endif +#ifdef __CYGWIN__ +#define timezonevar /* timezone is variable */ +#define NGX_BROKEN_SCM_RIGHTS 1 +#endif + + #include #include #if (NGX_HAVE_UNISTD_H) @@ -64,6 +70,15 @@ #include /* IOV_MAX */ #endif +#if (NGX_HAVE_MALLOC_H) +#include /* memalign() */ +#endif + +#if (NGX_HAVE_CRYPT_H) +#include +#endif + + #ifndef IOV_MAX #define IOV_MAX 16 #endif diff --git a/src/os/unix/ngx_process_cycle.c b/src/os/unix/ngx_process_cycle.c --- a/src/os/unix/ngx_process_cycle.c +++ b/src/os/unix/ngx_process_cycle.c @@ -409,6 +409,12 @@ ngx_signal_worker_processes(ngx_cycle_t ngx_err_t err; ngx_channel_t ch; +#if (NGX_BROKEN_SCM_RIGHTS) + + ch.command = 0; + +#else + switch (signo) { case ngx_signal_value(NGX_SHUTDOWN_SIGNAL): @@ -427,6 +433,8 @@ ngx_signal_worker_processes(ngx_cycle_t ch.command = 0; } +#endif + ch.fd = -1; @@ -1035,7 +1043,6 @@ static void ngx_channel_handler(ngx_event_t *ev) { ngx_int_t n; - ngx_socket_t fd; ngx_channel_t ch; ngx_connection_t *c; @@ -1053,17 +1060,7 @@ ngx_channel_handler(ngx_event_t *ev) ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0, "channel: %i", n); if (n == NGX_ERROR) { - - ngx_free_connection(c); - - fd = c->fd; - c->fd = (ngx_socket_t) -1; - - if (close(fd) == -1) { - ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, - "close() channel failed"); - } - + ngx_close_connection(c); return; }