# HG changeset patch # User Igor Sysoev # Date 1162242000 -10800 # Node ID f3ec44f4a53b6fe499321d118e778d645e49df88 # Parent b75231e1a3530b7a1dcb5deaddfc3f25b9cafe29 nginx 0.4.12 *) Feature: the ngx_http_perl_module supports the $r->variable method. *) Bugfix: if a big static file was included using SSI in a response, then the response may be transferred incomplete. *) Bugfix: nginx did not omit the "#fragment" part in URI. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,14 @@ +Changes with nginx 0.4.12 31 Oct 2006 + + *) Feature: the ngx_http_perl_module supports the $r->variable method. + + *) Bugfix: if a big static file was included using SSI in a response, + then the response may be transferred incomplete. + + *) Bugfix: nginx did not omit the "#fragment" part in URI. + + Changes with nginx 0.4.11 25 Oct 2006 *) Feature: the POP3 proxy supports the AUTH LOGIN PLAIN and CRAM-MD5. diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,15 @@ +Изменения в nginx 0.4.12 31.10.2006 + + *) Добавление: модуль ngx_http_perl_module поддерживает метод + $r->variable. + + *) Исправление: при включении в ответ большого статического файла с + помощью SSI ответ мог передаваться не полностью. + + *) Исправление: nginx не убирал "#fragment" в URI. + + Изменения в nginx 0.4.11 25.10.2006 *) Добавление: POP3 прокси поддерживает AUTH LOIGN PLAIN и CRAM-MD5. 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.4.11" +#define NGINX_VERSION "0.4.12" #define NGINX_VER "nginx/" NGINX_VERSION #define NGINX_VAR "NGINX" diff --git a/src/core/ngx_connection.h b/src/core/ngx_connection.h --- a/src/core/ngx_connection.h +++ b/src/core/ngx_connection.h @@ -92,8 +92,8 @@ typedef enum { } ngx_connection_tcp_nopush_e; -#define NGX_LOWLEVEL_BUFFERED 0x0000000f -#define NGX_SSL_BUFFERED 0x00000001 +#define NGX_LOWLEVEL_BUFFERED 0x0f +#define NGX_SSL_BUFFERED 0x01 struct ngx_connection_s { @@ -133,7 +133,7 @@ struct ngx_connection_s { ngx_atomic_uint_t number; - ngx_uint_t buffered; + unsigned buffered:8; unsigned log_error:2; /* ngx_connection_log_error_e */ diff --git a/src/core/ngx_output_chain.c b/src/core/ngx_output_chain.c --- a/src/core/ngx_output_chain.c +++ b/src/core/ngx_output_chain.c @@ -445,7 +445,7 @@ ngx_chain_writer(void *data, ngx_chain_t size += ngx_buf_size(in->buf); ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->connection->log, 0, - "chain writer buf size: %uz", ngx_buf_size(in->buf)); + "chain writer buf size: %uO", ngx_buf_size(in->buf)); cl = ngx_alloc_chain_link(ctx->pool); if (cl == NULL) { 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 @@ -688,24 +688,25 @@ ngx_decode_base64(ngx_str_t *dst, ngx_st { size_t len; u_char *d, *s; - static u_char basis64[] = - { 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 62, 77, 77, 77, 63, - 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 77, 77, 77, 77, 77, 77, - 77, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 77, 77, 77, 77, 77, - 77, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 77, 77, 77, 77, 77, + static u_char basis64[] = { + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 62, 77, 77, 77, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 77, 77, 77, 77, 77, 77, + 77, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 77, 77, 77, 77, 77, + 77, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, - 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77 }; + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, + 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77, 77 + }; for (len = 0; len < src->len; len++) { if (src->data[len] == '=') { @@ -887,66 +888,69 @@ ngx_utf_cpystrn(u_char *dst, u_char *src uintptr_t ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type) { - ngx_uint_t i, n; - uint32_t *escape; - static u_char hex[] = "0123456789abcdef"; + ngx_uint_t i, n; + uint32_t *escape; + static u_char hex[] = "0123456789abcdef"; - /* " ", "#", "%", "?", %00-%1F, %7F-%FF */ + /* " ", "#", "%", "?", %00-%1F, %7F-%FF */ - static uint32_t uri[] = - { 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + static uint32_t uri[] = { + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ - /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ - 0x80000029, /* 1000 0000 0000 0000 0000 0000 0010 1001 */ + /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ + 0x80000029, /* 1000 0000 0000 0000 0000 0000 0010 1001 */ + + /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */ + 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ - /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */ - 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ - - /* ~}| {zyx wvut srqp onml kjih gfed cba` */ - 0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */ + /* ~}| {zyx wvut srqp onml kjih gfed cba` */ + 0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */ - 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ - 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ - 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ - 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */ }; + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + }; - /* " ", "#", "%", "+", "?", %00-%1F, %7F-%FF */ + /* " ", "#", "%", "+", "?", %00-%1F, %7F-%FF */ - static uint32_t args[] = - { 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + static uint32_t args[] = { + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + + /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ + 0x80000829, /* 1000 0000 0000 0000 0000 1000 0010 1001 */ - /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ - 0x80000829, /* 1000 0000 0000 0000 0000 1000 0010 1001 */ + /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */ + 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ - /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */ - 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ + /* ~}| {zyx wvut srqp onml kjih gfed cba` */ + 0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */ - /* ~}| {zyx wvut srqp onml kjih gfed cba` */ - 0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + }; - 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ - 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ - 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ - 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */ }; - - /* " ", """, "%", "'", %00-%1F, %7F-%FF */ + /* " ", """, "%", "'", %00-%1F, %7F-%FF */ - static uint32_t html[] = - { 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + static uint32_t html[] = { + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ - /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ - 0x800000ad, /* 0000 0000 0000 0000 0000 0000 1010 1101 */ + /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ + 0x800000ad, /* 0000 0000 0000 0000 0000 0000 1010 1101 */ + + /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */ + 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ - /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */ - 0x00000000, /* 0000 0000 0000 0000 0000 0000 0000 0000 */ + /* ~}| {zyx wvut srqp onml kjih gfed cba` */ + 0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */ - /* ~}| {zyx wvut srqp onml kjih gfed cba` */ - 0x80000000, /* 1000 0000 0000 0000 0000 0000 0000 0000 */ - - 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ - 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ - 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ - 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */ }; + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + }; switch (type) { 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 @@ -973,6 +973,13 @@ ngx_http_ssi_output(ngx_http_request_t * } } + if (ctx->in || ctx->buf) { + r->buffered |= NGX_HTTP_SSI_BUFFERED; + + } else { + r->buffered &= ~NGX_HTTP_SSI_BUFFERED; + } + return rc; } 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 @@ -17,7 +17,7 @@ our @EXPORT = qw( HTTP_SERVER_ERROR ); -our $VERSION = '0.4.11'; +our $VERSION = '0.4.12'; require XSLoader; XSLoader::load('nginx', $VERSION); diff --git a/src/http/modules/perl/nginx.xs b/src/http/modules/perl/nginx.xs --- a/src/http/modules/perl/nginx.xs +++ b/src/http/modules/perl/nginx.xs @@ -763,3 +763,86 @@ unescape(r, text, type = 0) ngx_http_perl_set_targ(p, dst - p, 1); ST(0) = TARG; + + +void +variable(r, name, value = NULL) + CODE: + + dXSTARG; + ngx_http_request_t *r; + SV *name, *value; + u_char *p, *lowcase; + STRLEN len; + ngx_str_t var, val; + ngx_uint_t i, hash; + ngx_http_variable_value_t *vv; + + ngx_http_perl_set_request(r); + + name = ST(1); + + if (SvROK(name) && SvTYPE(SvRV(name)) == SVt_PV) { + name = SvRV(name); + } + + if (items == 2) { + value = NULL; + + } else { + value = ST(2); + + if (SvROK(value) && SvTYPE(SvRV(value)) == SVt_PV) { + value = SvRV(value); + } + + if (ngx_http_perl_sv2str(aTHX_ r, &val, value) != NGX_OK) { + XSRETURN_UNDEF; + } + } + + p = (u_char *) SvPV(name, len); + + lowcase = ngx_palloc(r->pool, len); + if (lowcase == NULL) { + XSRETURN_UNDEF; + } + + hash = 0; + for (i = 0; i < len; i++) { + lowcase[i] = ngx_tolower(p[i]); + hash = ngx_hash(hash, lowcase[i]); + } + + var.len = len; + var.data = lowcase; + + vv = ngx_http_get_variable(r, &var, hash, 1); + if (vv == NULL) { + XSRETURN_UNDEF; + } + + if (vv->not_found) { + if (value == NULL) { + XSRETURN_UNDEF; + } + + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "variable \"%V\" not found", &var); + + XSRETURN_UNDEF; + } + + if (value) { + vv->len = val.len; + vv->valid = 1; + vv->no_cachable = 0; + vv->not_found = 0; + vv->data = val.data; + + XSRETURN_UNDEF; + } + + ngx_http_perl_set_targ(vv->data, vv->len, 0); + + ST(0) = TARG; diff --git a/src/http/ngx_http_copy_filter_module.c b/src/http/ngx_http_copy_filter_module.c --- a/src/http/ngx_http_copy_filter_module.c +++ b/src/http/ngx_http_copy_filter_module.c @@ -109,12 +109,20 @@ ngx_http_copy_filter(ngx_http_request_t rc = ngx_output_chain(ctx, in); + if (!c->destroyed) { + + if (ctx->in == NULL) { + r->buffered &= ~NGX_HTTP_COPY_BUFFERED; + } else { + r->buffered |= NGX_HTTP_COPY_BUFFERED; + } + #if (NGX_DEBUG) - if (!c->destroyed) { ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "copy filter: %i \"%V?%V\"", rc, &r->uri, &r->args); +#endif + } -#endif return rc; } 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 @@ -9,6 +9,29 @@ #include +static uint32_t usual[] = { + 0xffffdbfe, /* 1111 1111 1111 1111 1101 1011 1111 1110 */ + + /* ?>=< ;:98 7654 3210 /.-, +*)( '&%$ #"! */ + 0x7fff37d6, /* 0111 1111 1111 1111 0011 0111 1101 0110 */ + + /* _^]\ [ZYX WVUT SRQP ONML KJIH GFED CBA@ */ +#if (NGX_WIN32) + 0xefffffff, /* 1110 1111 1111 1111 1111 1111 1111 1111 */ +#else + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ +#endif + + /* ~}| {zyx wvut srqp onml kjih gfed cba` */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff, /* 1111 1111 1111 1111 1111 1111 1111 1111 */ + 0xffffffff /* 1111 1111 1111 1111 1111 1111 1111 1111 */ +}; + + /* gcc, icc, msvc and others compile these switches as an jump table */ ngx_int_t @@ -18,7 +41,6 @@ ngx_http_parse_request_line(ngx_http_req enum { sw_start = 0, sw_method, - sw_space_after_method, sw_spaces_before_uri, sw_schema, sw_schema_slash, @@ -118,20 +140,15 @@ ngx_http_parse_request_line(ngx_http_req break; - /* single space after method */ - case sw_space_after_method: - switch (ch) { - case ' ': - state = sw_spaces_before_uri; - break; - default: - return NGX_HTTP_PARSE_INVALID_METHOD; - } - break; - /* space* before URI */ case sw_spaces_before_uri: + if (ch == '/' ){ + r->uri_start = p; + state = sw_after_slash_in_uri; + break; + } + c = (u_char) (ch | 0x20); if (c >= 'a' && c <= 'z') { r->schema_start = p; @@ -140,10 +157,6 @@ ngx_http_parse_request_line(ngx_http_req } switch (ch) { - case '/': - r->uri_start = p; - state = sw_after_slash_in_uri; - break; case ' ': break; default: @@ -196,8 +209,7 @@ ngx_http_parse_request_line(ngx_http_req break; } - if ((ch >= '0' && ch <= '9') || ch == '.' || ch == '-') - { + if ((ch >= '0' && ch <= '9') || ch == '.' || ch == '-') { break; } @@ -235,13 +247,7 @@ ngx_http_parse_request_line(ngx_http_req /* check "/.", "//", "%", and "\" (Win32) in URI */ case sw_after_slash_in_uri: - c = (u_char) (ch | 0x20); - if (c >= 'a' && c <= 'z') { - state = sw_check_uri; - break; - } - - if (ch >= '0' && ch <= '9') { + if (usual[ch >> 5] & (1 << (ch & 0x1f))) { state = sw_check_uri; break; } @@ -282,6 +288,10 @@ ngx_http_parse_request_line(ngx_http_req r->args_start = p + 1; state = sw_uri; break; + case '#': + r->complex_uri = 1; + state = sw_uri; + break; case '+': r->plus_in_uri = 1; break; @@ -297,12 +307,7 @@ ngx_http_parse_request_line(ngx_http_req /* check "/", "%" and "\" (Win32) in URI */ case sw_check_uri: - c = (u_char) (ch | 0x20); - if (c >= 'a' && c <= 'z') { - break; - } - - if (ch >= '0' && ch <= '9') { + if (usual[ch >> 5] & (1 << (ch & 0x1f))) { break; } @@ -341,6 +346,10 @@ ngx_http_parse_request_line(ngx_http_req r->args_start = p + 1; state = sw_uri; break; + case '#': + r->complex_uri = 1; + state = sw_uri; + break; case '+': r->plus_in_uri = 1; break; @@ -352,6 +361,11 @@ ngx_http_parse_request_line(ngx_http_req /* URI */ case sw_uri: + + if (usual[ch >> 5] & (1 << (ch & 0x1f))) { + break; + } + switch (ch) { case ' ': r->uri_end = p; @@ -366,6 +380,9 @@ ngx_http_parse_request_line(ngx_http_req r->uri_end = p; r->http_minor = 9; goto done; + case '#': + r->complex_uri = 1; + break; case '\0': r->zero_in_uri = 1; break; @@ -792,6 +809,13 @@ ngx_http_parse_complex_uri(ngx_http_requ switch (state) { case sw_usual: + + if (usual[ch >> 5] & (1 << (ch & 0x1f))) { + *u++ = ch; + ch = *p++; + break; + } + switch(ch) { #if (NGX_WIN32) case '\\': @@ -822,6 +846,8 @@ ngx_http_parse_complex_uri(ngx_http_requ break; case '?': r->args_start = p; + goto args; + case '#': goto done; case '.': r->uri_ext = u + 1; @@ -833,10 +859,19 @@ ngx_http_parse_complex_uri(ngx_http_requ *u++ = ch; break; } + ch = *p++; break; case sw_slash: + + if (usual[ch >> 5] & (1 << (ch & 0x1f))) { + state = sw_usual; + *u++ = ch; + ch = *p++; + break; + } + switch(ch) { #if (NGX_WIN32) case '\\': @@ -853,6 +888,8 @@ ngx_http_parse_complex_uri(ngx_http_requ break; case '?': r->args_start = p; + goto args; + case '#': goto done; case '+': r->plus_in_uri = 1; @@ -861,10 +898,19 @@ ngx_http_parse_complex_uri(ngx_http_requ *u++ = ch; break; } + ch = *p++; break; case sw_dot: + + if (usual[ch >> 5] & (1 << (ch & 0x1f))) { + state = sw_usual; + *u++ = ch; + ch = *p++; + break; + } + switch(ch) { #if (NGX_WIN32) case '\\': @@ -883,6 +929,8 @@ ngx_http_parse_complex_uri(ngx_http_requ break; case '?': r->args_start = p; + goto args; + case '#': goto done; case '+': r->plus_in_uri = 1; @@ -891,10 +939,19 @@ ngx_http_parse_complex_uri(ngx_http_requ *u++ = ch; break; } + ch = *p++; break; case sw_dot_dot: + + if (usual[ch >> 5] & (1 << (ch & 0x1f))) { + state = sw_usual; + *u++ = ch; + ch = *p++; + break; + } + switch(ch) { #if (NGX_WIN32) case '\\': @@ -915,6 +972,8 @@ ngx_http_parse_complex_uri(ngx_http_requ break; case '?': r->args_start = p; + goto args; + case '#': goto done; #if (NGX_WIN32) case '.': @@ -929,11 +988,20 @@ ngx_http_parse_complex_uri(ngx_http_requ *u++ = ch; break; } + ch = *p++; break; #if (NGX_WIN32) case sw_dot_dot_dot: + + if (usual[ch >> 5] & (1 << (ch & 0x1f))) { + state = sw_usual; + *u++ = ch; + ch = *p++; + break; + } + switch(ch) { case '\\': case '/': @@ -958,6 +1026,8 @@ ngx_http_parse_complex_uri(ngx_http_requ break; case '?': r->args_start = p; + goto args; + case '#': goto done; case '+': r->plus_in_uri = 1; @@ -966,6 +1036,7 @@ ngx_http_parse_complex_uri(ngx_http_requ *u++ = ch; break; } + ch = *p++; break; #endif @@ -1001,7 +1072,11 @@ ngx_http_parse_complex_uri(ngx_http_requ break; } - if (ch == '\0') { + if (ch == '#') { + *u++ = ch; + ch = *p++; + + } else if (ch == '\0') { r->zero_in_uri = 1; } @@ -1032,7 +1107,31 @@ ngx_http_parse_complex_uri(ngx_http_requ done: r->uri.len = u - r->uri.data; - r->uri.data[r->uri.len] = '\0'; + + if (r->uri_ext) { + r->exten.len = u - r->uri_ext; + r->exten.data = r->uri_ext; + } + + r->uri_ext = NULL; + + return NGX_OK; + +args: + + while (p < r->uri_end) { + if (*p++ != '#') { + continue; + } + + r->args.len = p - 1 - r->args_start; + r->args.data = r->args_start; + r->args_start = NULL; + + break; + } + + r->uri.len = u - r->uri.data; if (r->uri_ext) { r->exten.len = u - r->uri_ext; @@ -1072,6 +1171,10 @@ ngx_http_parse_unsafe_uri(ngx_http_reque ch = *p++; + if (usual[ch >> 5] & (1 << (ch & 0x1f))) { + continue; + } + if (ch == '?') { args->len = len - 1; args->data = p; @@ -1085,17 +1188,12 @@ ngx_http_parse_unsafe_uri(ngx_http_reque continue; } - if (ch != '/' + if ((ch == '/' #if (NGX_WIN32) - && ch != '\\' + || ch == '\\' #endif - ) + ) && len > 2) { - continue; - } - - if (len > 2) { - /* detect "/../" */ if (p[0] == '.' && p[1] == '.' && p[2] == '/') { 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 @@ -1736,7 +1736,7 @@ ngx_http_writer(ngx_http_request_t *r) ngx_http_close_request(r, 0); } - if (r == r->main) { + if (r == r->main || r->buffered) { return; } 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 @@ -111,11 +111,11 @@ #define NGX_HTTP_INSUFFICIENT_STORAGE 507 -#define NGX_HTTP_LOWLEVEL_BUFFERED 0x000000f0 -#define NGX_HTTP_WRITE_BUFFERED 0x00000010 -#define NGX_HTTP_GZIP_BUFFERED 0x00000020 -#define NGX_HTTP_SSI_BUFFERED 0x00000100 -#define NGX_HTTP_COPY_BUFFERED 0x00000200 +#define NGX_HTTP_LOWLEVEL_BUFFERED 0xf0 +#define NGX_HTTP_WRITE_BUFFERED 0x10 +#define NGX_HTTP_GZIP_BUFFERED 0x20 +#define NGX_HTTP_SSI_BUFFERED 0x01 +#define NGX_HTTP_COPY_BUFFERED 0x02 typedef enum { @@ -452,6 +452,8 @@ struct ngx_http_request_s { unsigned done:1; unsigned utf8:1; + unsigned buffered:4; + unsigned main_filter_need_in_memory:1; unsigned filter_need_in_memory:1; unsigned filter_need_temporary:1;