changeset 346:05693816539c NGINX_0_6_17

nginx 0.6.17 *) Feature: the "If-Range" request header line support. Thanks to Alexander V. Inyukhin. *) Bugfix: URL double escaping in a redirect of the "msie_refresh" directive; bug appeared in 0.6.4. *) Bugfix: the "autoindex" directive did not work with the "alias /" directive. *) Bugfix: a segmentation fault might occur in worker process if subrequests were used. *) Bugfix: the big responses may be transferred truncated if SSL and gzip were used. *) Bugfix: the $status variable was equal to 0 if a proxied server returned response in HTTP/0.9 version.
author Igor Sysoev <http://sysoev.ru>
date Thu, 15 Nov 2007 00:00:00 +0300
parents 4279bc4cdec6
children d53199b68e17
files CHANGES CHANGES.ru auto/cc/msvc auto/cc/name src/core/nginx.h src/core/ngx_string.c src/core/ngx_times.c src/event/ngx_event_pipe.c src/http/modules/ngx_http_autoindex_module.c src/http/modules/ngx_http_fastcgi_module.c src/http/modules/ngx_http_gzip_filter_module.c src/http/modules/ngx_http_index_module.c src/http/modules/ngx_http_log_module.c src/http/modules/ngx_http_not_modified_filter_module.c src/http/modules/ngx_http_proxy_module.c src/http/modules/ngx_http_range_filter_module.c src/http/modules/ngx_http_userid_filter_module.c src/http/modules/perl/nginx.pm src/http/ngx_http_parse_time.c src/http/ngx_http_request.c src/http/ngx_http_request.h src/http/ngx_http_request_body.c src/http/ngx_http_upstream.c src/mail/ngx_mail_auth_http_module.c
diffstat 24 files changed, 151 insertions(+), 53 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,25 @@
 
+Changes with nginx 0.6.17                                        15 Nov 2007
+
+    *) Feature: the "If-Range" request header line support.
+       Thanks to Alexander V. Inyukhin.
+
+    *) Bugfix: URL double escaping in a redirect of the "msie_refresh" 
+       directive; bug appeared in 0.6.4.
+
+    *) Bugfix: the "autoindex" directive did not work with the "alias /" 
+       directive.
+
+    *) Bugfix: a segmentation fault might occur in worker process if 
+       subrequests were used.
+
+    *) Bugfix: the big responses may be transferred truncated if SSL and 
+       gzip were used.
+
+    *) Bugfix: the $status variable was equal to 0 if a proxied server 
+       returned response in HTTP/0.9 version.
+
+
 Changes with nginx 0.6.16                                        29 Oct 2007
 
     *) Change: now the uname(2) is used on Linux instead of procfs.
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,25 @@
 
+Изменения в nginx 0.6.17                                          15.11.2007
+
+    *) Добавление: поддержка строки "If-Range" в заголовке запроса.
+       Спасибо Александру Инюхину.
+
+    *) Исправление: при использовании директивы msie_refresh повторно 
+       экранировались уже экранированные символы; ошибка появилась в 0.6.4.
+
+    *) Исправление: директива autoindex не работала при использовании 
+       "alias /".
+
+    *) Исправление: при использовании подзапросов в рабочем процессе мог 
+       произойти segmentation fault.
+
+    *) Исправление: при использовании SSL и gzip большие ответы могли 
+       передаваться не полностью.
+
+    *) Исправление: если ответ проксированного сервера был версии HTTP/0.9, 
+       то переменная $status была равна 0.
+
+
 Изменения в nginx 0.6.16                                          29.10.2007
 
     *) Изменение: теперь на Linux используется uname(2) вместо procfs.
@@ -74,7 +95,7 @@
        строке "Connection" в заголовке запроса только, если они были в 
        нижнем регистре; ошибка появилась в 0.6.11.
 
-    *) Исправление: sub_filter не работал с пустую строку замены.
+    *) Исправление: sub_filter не работал с пустой строкой замены.
 
     *) Исправление: в парсинге sub_filter.
 
--- a/auto/cc/msvc
+++ b/auto/cc/msvc
@@ -2,7 +2,7 @@
 # Copyright (C) Igor Sysoev
 
 
-# MSVC 6.0 SP2, MSVC Toolkit 2003 (7.1)
+# MSVC 6.0 SP2, MSVC Toolkit 2003 (7.1), MSVC 2005 Express Edition SP1 (8.0)
 
 # optimizations
 
@@ -91,17 +91,17 @@ CORE_LIBS="$CORE_LIBS kernel32.lib user3
 CORE_LINK="$CORE_LINK -subsystem:windows -entry:mainCRTStartup"
 
 # debug
-CFLAGS="$CFLAGS -Yd"
-CORE_LINK="$CORE_LINK -debug -debugtype:coff"
+if [ $NGX_CC_NAME != msvc8 ]; then
+   CFLAGS="$CFLAGS -Zi"
+   CORE_LINK="$CORE_LINK -debug"
+fi
 
 
 # precompiled headers
-if [ $NGX_CC_NAME != msvc7 ]; then
-    CORE_DEPS="$CORE_DEPS $NGX_OBJS/ngx_config.pch"
-    NGX_PCH="$NGX_OBJS/ngx_config.pch"
-    NGX_BUILD_PCH="-Ycngx_config.h -Fp$NGX_OBJS/ngx_config.pch"
-    NGX_USE_PCH="-Yungx_config.h -Fp$NGX_OBJS/ngx_config.pch"
-fi
+CORE_DEPS="$CORE_DEPS $NGX_OBJS/ngx_config.pch"
+NGX_PCH="$NGX_OBJS/ngx_config.pch"
+NGX_BUILD_PCH="-Ycngx_config.h -Fp$NGX_OBJS/ngx_config.pch"
+NGX_USE_PCH="-Yungx_config.h -Fp$NGX_OBJS/ngx_config.pch"
 
 
 # the resource file
--- a/auto/cc/name
+++ b/auto/cc/name
@@ -25,6 +25,13 @@ fi
 
 if [ "$CC" = cl ]; then
     if `$NGX_WINE $CC -v 2>&1 \
+        | grep '^Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14' \
+        >/dev/null 2>&1`; then
+
+        NGX_CC_NAME=msvc8
+        echo " + using Microsoft Visual C++ 8 compiler"
+
+    else if `$NGX_WINE $CC -v 2>&1 \
         | grep '^Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13' \
         >/dev/null 2>&1`; then
 
@@ -35,6 +42,7 @@ if [ "$CC" = cl ]; then
         NGX_CC_NAME=msvc
         echo " + using Microsoft Visual C++ compiler"
     fi
+    fi
 
 else
 if [ "$CC" = wcl386 ]; then
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define NGINX_VERSION      "0.6.16"
+#define NGINX_VERSION      "0.6.17"
 #define NGINX_VER          "nginx/" NGINX_VERSION
 
 #define NGINX_VAR          "NGINX"
--- a/src/core/ngx_string.c
+++ b/src/core/ngx_string.c
@@ -1147,7 +1147,7 @@ ngx_escape_uri(u_char *dst, u_char *src,
         0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
 
                     /* ?>=< ;:98 7654 3210  /.-, +*)( '&%$ #"!  */
-        0x000000a5, /* 0000 0000 0000 0000  0000 0000 1010 0101 */
+        0x00000085, /* 0000 0000 0000 0000  0000 0000 1000 0101 */
 
                     /* _^]\ [ZYX WVUT SRQP  ONML KJIH GFED CBA@ */
         0x00000000, /* 0000 0000 0000 0000  0000 0000 0000 0000 */
--- a/src/core/ngx_times.c
+++ b/src/core/ngx_times.c
@@ -205,16 +205,16 @@ ngx_gmtime(time_t t, ngx_tm_t *tp)
 {
     ngx_int_t  sec, min, hour, mday, mon, year, wday, yday, days;
 
-    days = t / 86400;
+    days = (ngx_int_t) (t / 86400);
 
     /* Jaunary 1, 1970 was Thursday */
     wday = (4 + days) % 7;
 
     t %= 86400;
-    hour = t / 3600;
+    hour = (ngx_int_t) (t / 3600);
     t %= 3600;
-    min = t / 60;
-    sec = t % 60;
+    min = (ngx_int_t) (t / 60);
+    sec = (ngx_int_t) (t % 60);
 
     /* the algorithm based on Gauss's formula */
 
--- a/src/event/ngx_event_pipe.c
+++ b/src/event/ngx_event_pipe.c
@@ -421,6 +421,7 @@ ngx_event_pipe_write_to_downstream(ngx_e
 {
     u_char            *prev;
     size_t             bsize;
+    ngx_int_t          rc;
     ngx_uint_t         flush, prev_last_shadow;
     ngx_chain_t       *out, **ll, *cl;
     ngx_connection_t  *downstream;
@@ -451,7 +452,13 @@ ngx_event_pipe_write_to_downstream(ngx_e
                     cl->buf->recycled = 0;
                 }
 
-                if (p->output_filter(p->output_ctx, p->out) == NGX_ERROR) {
+                rc = p->output_filter(p->output_ctx, p->out);
+
+                if (downstream->destroyed) {
+                    return NGX_ABORT;
+                }
+
+                if (rc == NGX_ERROR) {
                     p->downstream_error = 1;
                     return ngx_event_pipe_drain_chains(p);
                 }
@@ -467,12 +474,13 @@ ngx_event_pipe_write_to_downstream(ngx_e
                     cl->buf->recycled = 0;
                 }
 
-                if (p->output_filter(p->output_ctx, p->in) == NGX_ERROR) {
+                rc = p->output_filter(p->output_ctx, p->in);
 
-                    if (downstream->destroyed) {
-                        return NGX_ABORT;
-                    }
+                if (downstream->destroyed) {
+                    return NGX_ABORT;
+                }
 
+                if (rc == NGX_ERROR) {
                     p->downstream_error = 1;
                     return ngx_event_pipe_drain_chains(p);
                 }
@@ -602,7 +610,13 @@ ngx_event_pipe_write_to_downstream(ngx_e
             break;
         }
 
-        if (p->output_filter(p->output_ctx, out) == NGX_ERROR) {
+        rc = p->output_filter(p->output_ctx, out);
+
+        if (downstream->destroyed) {
+            return NGX_ABORT;
+        }
+
+        if (rc == NGX_ERROR) {
             p->downstream_error = 1;
             return ngx_event_pipe_drain_chains(p);
         }
--- a/src/http/modules/ngx_http_autoindex_module.c
+++ b/src/http/modules/ngx_http_autoindex_module.c
@@ -181,7 +181,10 @@ ngx_http_autoindex_handler(ngx_http_requ
     }
 
     allocated = path.len;
-    path.len = last - path.data - 1;
+    path.len = last - path.data;
+    if (path.len > 1) {
+        path.len--;
+    }
     path.data[path.len] = '\0';
 
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -432,7 +432,7 @@ ngx_http_fastcgi_handler(ngx_http_reques
     if (r->subrequest_in_memory) {
         ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
                       "ngx_http_fastcgi_module does not support "
-                      "subrequest in memeory");
+                      "subrequest in memory");
         return NGX_HTTP_INTERNAL_SERVER_ERROR;
     }
 
--- a/src/http/modules/ngx_http_gzip_filter_module.c
+++ b/src/http/modules/ngx_http_gzip_filter_module.c
@@ -837,12 +837,15 @@ ngx_http_gzip_body_filter(ngx_http_reque
             }
         }
 
-        if (last == NGX_AGAIN && !ctx->done) {
-            return NGX_AGAIN;
-        }
+        if (ctx->out == NULL) {
 
-        if (ctx->out == NULL && ctx->busy == NULL) {
-            return NGX_OK;
+            if (last == NGX_AGAIN) {
+                return NGX_AGAIN;
+            }
+
+            if (ctx->busy == NULL) {
+                return NGX_OK;
+            }
         }
 
         last = ngx_http_next_body_filter(r, ctx->out);
--- a/src/http/modules/ngx_http_index_module.c
+++ b/src/http/modules/ngx_http_index_module.c
@@ -279,7 +279,7 @@ ngx_http_index_test_dir(ngx_http_request
     ngx_open_file_info_t  of;
 
     c = *last;
-    if (c != '/') {
+    if (c != '/' || path == last) {
         /* "alias" without trailing slash */
         c = *(++last);
     }
--- a/src/http/modules/ngx_http_log_module.c
+++ b/src/http/modules/ngx_http_log_module.c
@@ -400,7 +400,8 @@ ngx_http_log_request_time(ngx_http_reque
 
     tp = ngx_timeofday();
 
-    ms = (tp->sec - r->start_sec) * 1000 + (tp->msec - r->start_msec);
+    ms = (ngx_msec_int_t)
+             ((tp->sec - r->start_sec) * 1000 + (tp->msec - r->start_msec));
     ms = (ms >= 0) ? ms : 0;
 
     return ngx_sprintf(buf, "%T.%03M", ms / 1000, ms % 1000);
--- a/src/http/modules/ngx_http_not_modified_filter_module.c
+++ b/src/http/modules/ngx_http_not_modified_filter_module.c
@@ -70,7 +70,7 @@ ngx_int_t ngx_http_not_modified_header_f
      * I think that the equality of the dates is correcter
      */
 
-    if (ims != NGX_ERROR && ims == r->headers_out.last_modified_time) {
+    if (ims == r->headers_out.last_modified_time) {
         r->headers_out.status = NGX_HTTP_NOT_MODIFIED;
         r->headers_out.content_type.len = 0;
         ngx_http_clear_content_length(r);
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -860,7 +860,8 @@ ngx_http_proxy_process_status_line(ngx_h
 #endif
 
         r->http_version = NGX_HTTP_VERSION_9;
-        p->status = NGX_HTTP_OK;
+        u->headers_in.status_n = NGX_HTTP_OK;
+        u->state->status = NGX_HTTP_OK;
 
         return NGX_OK;
     }
--- a/src/http/modules/ngx_http_range_filter_module.c
+++ b/src/http/modules/ngx_http_range_filter_module.c
@@ -134,6 +134,7 @@ ngx_http_range_header_filter(ngx_http_re
     u_char                       *p;
     size_t                        len;
     off_t                         start, end;
+    time_t                        if_range;
     ngx_int_t                     rc;
     ngx_uint_t                    suffix, i;
     ngx_atomic_uint_t             boundary;
@@ -156,18 +157,21 @@ ngx_http_range_header_filter(ngx_http_re
                            (u_char *) "bytes=", 6)
            != 0)
     {
-        r->headers_out.accept_ranges = ngx_list_push(&r->headers_out.headers);
-        if (r->headers_out.accept_ranges == NULL) {
-            return NGX_ERROR;
-        }
+        goto next_filter;
+    }
+
+    if (r->headers_in.if_range && r->headers_out.last_modified_time != -1) {
+
+        if_range = ngx_http_parse_time(r->headers_in.if_range->value.data,
+                                       r->headers_in.if_range->value.len);
 
-        r->headers_out.accept_ranges->hash = 1;
-        r->headers_out.accept_ranges->key.len = sizeof("Accept-Ranges") - 1;
-        r->headers_out.accept_ranges->key.data = (u_char *) "Accept-Ranges";
-        r->headers_out.accept_ranges->value.len = sizeof("bytes") - 1;
-        r->headers_out.accept_ranges->value.data = (u_char *) "bytes";
+        ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+                       "http ir:%d lm:%d",
+                       if_range, r->headers_out.last_modified_time);
 
-        return ngx_http_next_header_filter(r);
+        if (if_range != r->headers_out.last_modified_time) {
+            goto next_filter;
+        }
     }
 
     ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_range_filter_ctx_t));
@@ -461,6 +465,21 @@ ngx_http_range_header_filter(ngx_http_re
     }
 
     return ngx_http_next_header_filter(r);
+
+next_filter:
+
+    r->headers_out.accept_ranges = ngx_list_push(&r->headers_out.headers);
+    if (r->headers_out.accept_ranges == NULL) {
+        return NGX_ERROR;
+    }
+
+    r->headers_out.accept_ranges->hash = 1;
+    r->headers_out.accept_ranges->key.len = sizeof("Accept-Ranges") - 1;
+    r->headers_out.accept_ranges->key.data = (u_char *) "Accept-Ranges";
+    r->headers_out.accept_ranges->value.len = sizeof("bytes") - 1;
+    r->headers_out.accept_ranges->value.data = (u_char *) "bytes";
+
+    return ngx_http_next_header_filter(r);
 }
 
 
--- a/src/http/modules/ngx_http_userid_filter_module.c
+++ b/src/http/modules/ngx_http_userid_filter_module.c
@@ -318,7 +318,7 @@ ngx_http_userid_set_uid(ngx_http_request
             } else {
                 ctx->uid_set[0] = conf->service;
             }
-            ctx->uid_set[1] = ngx_time();
+            ctx->uid_set[1] = (uint32_t) ngx_time();
             ctx->uid_set[2] = ngx_pid;
             ctx->uid_set[3] = sequencer_v1;
             sequencer_v1 += 0x100;
@@ -345,7 +345,7 @@ ngx_http_userid_set_uid(ngx_http_request
                 ctx->uid_set[0] = htonl(conf->service);
             }
 
-            ctx->uid_set[1] = htonl(ngx_time());
+            ctx->uid_set[1] = htonl((uint32_t) ngx_time());
             ctx->uid_set[2] = htonl(ngx_pid);
             ctx->uid_set[3] = htonl(sequencer_v2);
             sequencer_v2 += 0x100;
--- 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.16';
+our $VERSION = '0.6.17';
 
 require XSLoader;
 XSLoader::load('nginx', $VERSION);
--- a/src/http/ngx_http_parse_time.c
+++ b/src/http/ngx_http_parse_time.c
@@ -11,7 +11,8 @@
 
 static int mday[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
 
-time_t ngx_http_parse_time(u_char *value, size_t len)
+time_t
+ngx_http_parse_time(u_char *value, size_t len)
 {
     u_char  *p, *end;
     int      day, month, year, hour, min, sec;
@@ -247,7 +248,7 @@ time_t ngx_http_parse_time(u_char *value
         year -= 1;
     }
 
-    /* Gauss's formula for Grigorian days from 1 March 1 BC */
+    /* Gauss's formula for Grigorian days from March 1, 1 BC */
 
     return (365 * year + year / 4 - year / 100 + year / 400
             + 367 * month / 12 - 31
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -96,6 +96,10 @@ ngx_http_header_t  ngx_http_headers_in[]
     { ngx_string("Range"), offsetof(ngx_http_headers_in_t, range),
                  ngx_http_process_header_line },
 
+    { ngx_string("If-Range"),
+                 offsetof(ngx_http_headers_in_t, if_range),
+                 ngx_http_process_unique_header_line },
+
     { ngx_string("Transfer-Encoding"),
                  offsetof(ngx_http_headers_in_t, transfer_encoding),
                  ngx_http_process_header_line },
@@ -2337,7 +2341,7 @@ ngx_http_lingering_close_handler(ngx_eve
         return;
     }
 
-    timer = r->lingering_time - ngx_time();
+    timer = (ngx_msec_t) (r->lingering_time - ngx_time());
     if (timer <= 0) {
         ngx_http_close_request(r, 0);
         return;
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -168,6 +168,7 @@ typedef struct {
     ngx_table_elt_t                  *content_type;
 
     ngx_table_elt_t                  *range;
+    ngx_table_elt_t                  *if_range;
 
     ngx_table_elt_t                  *transfer_encoding;
 
--- a/src/http/ngx_http_request_body.c
+++ b/src/http/ngx_http_request_body.c
@@ -493,7 +493,7 @@ ngx_http_read_discarded_request_body_han
     }
 
     if (r->lingering_time) {
-        timer = r->lingering_time - ngx_time();
+        timer = (ngx_msec_t) (r->lingering_time - ngx_time());
 
         if (timer <= 0) {
             r->discard_body = 0;
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -2873,7 +2873,8 @@ ngx_http_upstream_response_time_variable
 
     for ( ;; ) {
         if (state[i].status) {
-            ms = state[i].response_sec * 1000 + state[i].response_msec;
+            ms = (ngx_msec_int_t)
+                     (state[i].response_sec * 1000 + state[i].response_msec);
             ms = (ms >= 0) ? ms : 0;
             p = ngx_sprintf(p, "%d.%03d", ms / 1000, ms % 1000);
 
--- a/src/mail/ngx_mail_auth_http_module.c
+++ b/src/mail/ngx_mail_auth_http_module.c
@@ -718,7 +718,7 @@ ngx_mail_auth_http_process_headers(ngx_m
                     return;
                 }
 
-                ngx_add_timer(s->connection->read, timer * 1000);
+                ngx_add_timer(s->connection->read, (ngx_msec_t) (timer * 1000));
 
                 s->connection->read->handler = ngx_mail_auth_sleep_handler;
 
@@ -735,7 +735,7 @@ ngx_mail_auth_http_process_headers(ngx_m
                     return;
                 }
 
-                ngx_add_timer(s->connection->read, timer * 1000);
+                ngx_add_timer(s->connection->read, (ngx_msec_t) (timer * 1000));
 
                 s->connection->read->handler = ngx_mail_auth_sleep_handler;