changeset 328:390b8f8309d6 NGINX_0_6_8

nginx 0.6.8 *) Change: now nginx tries to set the "worker_priority", "worker_rlimit_nofile", "worker_rlimit_core", and "worker_rlimit_sigpending" without super-user privileges. *) Change: now nginx escapes space and "%" in request to a mail proxy authentication server. *) Change: now nginx escapes "%" in $memcached_key variable. *) Bugfix: nginx used path relative to configuration prefix for non-absolute configuration file path specified in the "-c" key; bug appeared in 0.6.6. *) Bugfix: nginx did not work on FreeBSD/sparc64.
author Igor Sysoev <http://sysoev.ru>
date Mon, 20 Aug 2007 00:00:00 +0400
parents be18d26e067c
children f2f8dc3e7933
files CHANGES CHANGES.ru src/core/nginx.c src/core/nginx.h src/core/ngx_string.c src/core/ngx_string.h src/http/modules/ngx_http_geo_module.c src/http/modules/ngx_http_limit_zone_module.c src/http/modules/ngx_http_map_module.c src/http/modules/perl/nginx.pm src/http/ngx_http_core_module.c src/http/ngx_http_script.c src/http/ngx_http_write_filter_module.c src/mail/ngx_mail_auth_http_module.c src/mail/ngx_mail_parse.c src/os/unix/ngx_process_cycle.c
diffstat 16 files changed, 142 insertions(+), 92 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES
+++ b/CHANGES
@@ -1,11 +1,29 @@
 
+Changes with nginx 0.6.8                                         20 Aug 2007
+
+    *) Change: now nginx tries to set the "worker_priority", 
+       "worker_rlimit_nofile", "worker_rlimit_core", and 
+       "worker_rlimit_sigpending" without super-user privileges.
+
+    *) Change: now nginx escapes space and "%" in request to a mail proxy 
+       authentication server.
+
+    *) Change: now nginx escapes "%" in $memcached_key variable.
+
+    *) Bugfix: nginx used path relative to configuration prefix for 
+       non-absolute configuration file path specified in the "-c" key; bug 
+       appeared in 0.6.6.
+
+    *) Bugfix: nginx did not work on FreeBSD/sparc64.
+
+
 Changes with nginx 0.6.7                                         15 Aug 2007
 
     *) Change: now the paths specified in the "include", 
        "auth_basic_user_file", "perl_modules", "ssl_certificate", 
        "ssl_certificate_key", and "ssl_client_certificate" directives are 
-       relative to directory of nginx configuration file nginx.conf, but no 
-       to nginx prefix directory.
+       relative to directory of nginx configuration file nginx.conf, but 
+       not to nginx prefix directory.
 
     *) Change: the --sysconfdir=PATH option in configure was canceled.
 
@@ -150,7 +168,7 @@ Changes with nginx 0.6.1                
 Changes with nginx 0.6.0                                         14 Jun 2007
 
     *) Feature: the "server_name", "map", and "valid_referers" directives 
-       supports the "www.example.*" wildcards.
+       support the "www.example.*" wildcards.
 
 
 Changes with nginx 0.5.25                                        11 Jun 2007
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,11 +1,30 @@
 
+Изменения в nginx 0.6.8                                           20.08.2007
+
+    *) Изменение: теперь nginx пытается установить директивы 
+       worker_priority, worker_rlimit_nofile, worker_rlimit_core, 
+       worker_rlimit_sigpending без привилегий root'а.
+
+    *) Изменение: теперь nginx экранирует символы пробела и "%" при 
+       передаче запроса серверу аутентификации почтового прокси-сервера.
+
+    *) Изменение: теперь nginx экранирует символ "%" в переменной 
+       $memcached_key.
+
+    *) Исправление: при указании относительного пути к конфигурационному 
+       файлу в качестве параметра ключа -c nginx определял путь 
+       относительно конфигурационного префикса; ошибка появилась в 0.6.6.
+
+    *) Исправление: nginx не работал на FreeBSD/sparc64.
+
+
 Изменения в nginx 0.6.7                                           15.08.2007
 
     *) Изменение: теперь пути, указанные в директивах include, 
        auth_basic_user_file, perl_modules, ssl_certificate, 
        ssl_certificate_key и ssl_client_certificate, определяются 
-       относительно каталогу конфигурационного файла nginx.conf, а не 
-       относительно префиксу.
+       относительно каталога конфигурационного файла nginx.conf, а не 
+       относительно префикса.
 
     *) Изменение: параметр --sysconfdir=PATH в configure упразднён.
 
--- a/src/core/nginx.c
+++ b/src/core/nginx.c
@@ -656,10 +656,6 @@ ngx_getopt(ngx_cycle_t *cycle, int argc,
         cycle->conf_file.data = (u_char *) NGX_CONF_PATH;
     }
 
-    if (ngx_conf_full_name(cycle, &cycle->conf_file, 1) == NGX_ERROR) {
-        return NGX_ERROR;
-    }
-
     return NGX_OK;
 }
 
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
 #define _NGINX_H_INCLUDED_
 
 
-#define NGINX_VERSION      "0.6.7"
+#define NGINX_VERSION      "0.6.8"
 #define NGINX_VER          "nginx/" NGINX_VERSION
 
 #define NGINX_VAR          "NGINX"
--- a/src/core/ngx_string.c
+++ b/src/core/ngx_string.c
@@ -59,8 +59,9 @@ ngx_pstrdup(ngx_pool_t *pool, ngx_str_t 
  *    %P                        ngx_pid_t
  *    %M                        ngx_msec_t
  *    %r                        rlim_t
- *    %p                        pointer
- *    %V                        pointer to ngx_str_t
+ *    %p                        void *
+ *    %V                        ngx_str_t *
+ *    %v                        ngx_variable_value_t *
  *    %s                        null-terminated string
  *    %Z                        '\0'
  *    %N                        '\n'
@@ -117,7 +118,8 @@ ngx_vsnprintf(u_char *buf, size_t max, c
     uint64_t               ui64;
     ngx_msec_t             ms;
     ngx_uint_t             width, sign, hexadecimal, max_width;
-    ngx_variable_value_t  *v;
+    ngx_str_t             *v;
+    ngx_variable_value_t  *vv;
     static u_char          hex[] = "0123456789abcdef";
     static u_char          HEX[] = "0123456789ABCDEF";
 
@@ -188,7 +190,7 @@ ngx_vsnprintf(u_char *buf, size_t max, c
             switch (*fmt) {
 
             case 'V':
-                v = va_arg(args, ngx_variable_value_t *);
+                v = va_arg(args, ngx_str_t *);
 
                 len = v->len;
                 len = (buf + len < last) ? len : (size_t) (last - buf);
@@ -198,6 +200,17 @@ ngx_vsnprintf(u_char *buf, size_t max, c
 
                 continue;
 
+            case 'v':
+                vv = va_arg(args, ngx_variable_value_t *);
+
+                len = vv->len;
+                len = (buf + len < last) ? len : (size_t) (last - buf);
+
+                buf = ngx_cpymem(buf, vv->data, len);
+                fmt++;
+
+                continue;
+
             case 's':
                 p = va_arg(args, u_char *);
 
@@ -1019,7 +1032,7 @@ ngx_escape_uri(u_char *dst, u_char *src,
         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 */
@@ -1039,13 +1052,13 @@ ngx_escape_uri(u_char *dst, u_char *src,
         0xffffffff  /* 1111 1111 1111 1111  1111 1111 1111 1111 */
     };
 
-                    /* " ", """, "'", %00-%1F, %7F-%FF */
+                    /* " ", """, "%", "'", %00-%1F, %7F-%FF */
 
     static uint32_t   refresh[] = {
         0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
 
                     /* ?>=< ;:98 7654 3210  /.-, +*)( '&%$ #"!  */
-        0x00000085, /* 0000 0000 0000 0000  0000 0000 1000 0101 */
+        0x000000a5, /* 0000 0000 0000 0000  0000 0000 1010 0101 */
 
                     /* _^]\ [ZYX WVUT SRQP  ONML KJIH GFED CBA@ */
         0x00000000, /* 0000 0000 0000 0000  0000 0000 0000 0000 */
@@ -1059,13 +1072,13 @@ ngx_escape_uri(u_char *dst, u_char *src,
         0xffffffff  /* 1111 1111 1111 1111  1111 1111 1111 1111 */
     };
 
-                    /* " ", %00-%1F */
+                    /* " ", "%", %00-%1F */
 
     static uint32_t   memcached[] = {
         0xffffffff, /* 1111 1111 1111 1111  1111 1111 1111 1111 */
 
                     /* ?>=< ;:98 7654 3210  /.-, +*)( '&%$ #"!  */
-        0x00000001, /* 0000 0000 0000 0000  0000 0000 0000 0001 */
+        0x00000021, /* 0000 0000 0000 0000  0000 0000 0010 0001 */
 
                     /* _^]\ [ZYX WVUT SRQP  ONML KJIH GFED CBA@ */
         0x00000000, /* 0000 0000 0000 0000  0000 0000 0000 0000 */
@@ -1079,7 +1092,10 @@ ngx_escape_uri(u_char *dst, u_char *src,
         0x00000000, /* 0000 0000 0000 0000  0000 0000 0000 0000 */
     };
 
-    static uint32_t  *map[] = { uri, args, html, refresh, memcached };
+                    /* mail_auth is the same as memcached */
+
+    static uint32_t  *map[] =
+        { uri, args, html, refresh, memcached, memcached };
 
 
     escape = map[type];
--- a/src/core/ngx_string.h
+++ b/src/core/ngx_string.h
@@ -155,6 +155,7 @@ u_char *ngx_utf_cpystrn(u_char *dst, u_c
 #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
 
--- a/src/http/modules/ngx_http_geo_module.c
+++ b/src/http/modules/ngx_http_geo_module.c
@@ -86,7 +86,7 @@ ngx_http_geo_variable(ngx_http_request_t
     *v = *vv;
 
     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                   "http geo: %V %V", &r->connection->addr_text, v);
+                   "http geo: %V %v", &r->connection->addr_text, v);
 
     return NGX_OK;
 }
@@ -100,8 +100,8 @@ ngx_http_geo_block(ngx_conf_t *cf, ngx_c
     ngx_conf_t                save;
     ngx_pool_t               *pool;
     ngx_radix_tree_t         *tree;
+    ngx_http_variable_t      *var;
     ngx_http_geo_conf_ctx_t   ctx;
-    ngx_http_variable_t  *var;
 
     value = cf->args->elts;
 
@@ -285,9 +285,8 @@ ngx_http_geo(ngx_conf_t *cf, ngx_command
                     ngx_radix32tree_find(ctx->tree, cidrin.addr & cidrin.mask);
 
         ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
-                           "duplicate parameter \"%V\", value: \"%V\", "
-                           "old value: \"%V\"",
-                           &value[0], var, old);
+                "duplicate parameter \"%V\", value: \"%v\", old value: \"%v\"",
+                &value[0], var, old);
 
         rc = ngx_radix32tree_delete(ctx->tree, cidrin.addr, cidrin.mask);
 
--- a/src/http/modules/ngx_http_limit_zone_module.c
+++ b/src/http/modules/ngx_http_limit_zone_module.c
@@ -141,7 +141,7 @@ ngx_http_limit_zone_handler(ngx_http_req
     if (len > 255) {
         ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                       "the value of the \"%V\" variable "
-                      "is more than 255 bytes: \"%V\"",
+                      "is more than 255 bytes: \"%v\"",
                       &ctx->var, vv);
         return NGX_DECLINED;
     }
--- a/src/http/modules/ngx_http_map_module.c
+++ b/src/http/modules/ngx_http_map_module.c
@@ -151,7 +151,7 @@ ngx_http_map_variable(ngx_http_request_t
     }
 
     ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
-                   "http map: \"%V\" \"%V\"", vv, v);
+                   "http map: \"%v\" \"%v\"", vv, v);
 
     return NGX_OK;
 }
--- 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.7';
+our $VERSION = '0.6.8';
 
 require XSLoader;
 XSLoader::load('nginx', $VERSION);
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -620,6 +620,8 @@ ngx_int_t
 ngx_http_core_find_config_phase(ngx_http_request_t *r,
     ngx_http_phase_handler_t *ph)
 {
+    u_char                    *p;
+    size_t                     len;
     ngx_int_t                  rc;
     ngx_http_core_loc_conf_t  *clcf;
     ngx_http_core_srv_conf_t  *cscf;
@@ -680,7 +682,25 @@ ngx_http_core_find_config_phase(ngx_http
          * r->headers_out.location->key fields
          */
 
-        r->headers_out.location->value = clcf->name;
+        if (r->args.len == 0) {
+            r->headers_out.location->value = clcf->name;
+
+        } else {
+            len = clcf->name.len + 1 + r->args.len;
+            p = ngx_palloc(r->pool, len);
+
+            if (p == NULL) {
+                ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR);
+                return NGX_OK;
+            }
+
+            r->headers_out.location->value.len = len;
+            r->headers_out.location->value.data = p;
+
+            p = ngx_cpymem(p, clcf->name.data, clcf->name.len);
+            *p++ = '?';
+            ngx_memcpy(p, r->args.data, r->args.len);
+        }
 
         ngx_http_finalize_request(r, NGX_HTTP_MOVED_PERMANENTLY);
         return NGX_OK;
--- a/src/http/ngx_http_script.c
+++ b/src/http/ngx_http_script.c
@@ -1191,7 +1191,7 @@ ngx_http_script_var_code(ngx_http_script
 
     if (value && !value->not_found) {
         ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
-                       "http script var: \"%V\"", value);
+                       "http script var: \"%v\"", value);
 
         *e->sp = *value;
         e->sp++;
--- a/src/http/ngx_http_write_filter_module.c
+++ b/src/http/ngx_http_write_filter_module.c
@@ -249,7 +249,10 @@ ngx_http_write_filter(ngx_http_request_t
         c->write->delayed = 1;
         ngx_add_timer(c->write, (ngx_msec_t) (sent * 1000 / r->limit_rate + 1));
 
-    } else if (c->write->ready && clcf->sendfile_max_chunk) {
+    } else if (c->write->ready
+               && clcf->sendfile_max_chunk
+               && c->sent - sent >= clcf->sendfile_max_chunk - 2 * ngx_pagesize)
+    {
         c->write->delayed = 1;
         ngx_add_timer(c->write, 1);
     }
--- a/src/mail/ngx_mail_auth_http_module.c
+++ b/src/mail/ngx_mail_auth_http_module.c
@@ -1251,18 +1251,10 @@ ngx_mail_auth_http_create_request(ngx_ma
 static ngx_int_t
 ngx_mail_auth_http_escape(ngx_pool_t *pool, ngx_str_t *text, ngx_str_t *escaped)
 {
-    u_char      ch, *p;
-    ngx_uint_t  i, n;
-
-    n = 0;
+    u_char     *p;
+    uintptr_t   n;
 
-    for (i = 0; i < text->len; i++) {
-        ch = text->data[i];
-
-        if (ch == CR || ch == LF) {
-            n++;
-        }
-    }
+    n = ngx_escape_uri(NULL, text->data, text->len, NGX_ESCAPE_MAIL_AUTH);
 
     if (n == 0) {
         *escaped = *text;
@@ -1276,27 +1268,9 @@ ngx_mail_auth_http_escape(ngx_pool_t *po
         return NGX_ERROR;
     }
 
-    escaped->data = p;
-
-    for (i = 0; i < text->len; i++) {
-        ch = text->data[i];
+    (void) ngx_escape_uri(p, text->data, text->len, NGX_ESCAPE_MAIL_AUTH);
 
-        if (ch == CR) {
-            *p++ = '%';
-            *p++ = '0';
-            *p++ = 'D';
-            continue;
-        }
-
-        if (ch == LF) {
-            *p++ = '%';
-            *p++ = '0';
-            *p++ = 'A';
-            continue;
-        }
-
-        *p++ = ch;
-    }
+    escaped->data = p;
 
     return NGX_OK;
 }
--- a/src/mail/ngx_mail_parse.c
+++ b/src/mail/ngx_mail_parse.c
@@ -434,6 +434,10 @@ ngx_int_t ngx_imap_parse_command(ngx_mai
             break;
 
         case sw_argument:
+            if (ch == ' ' && s->quoted) {
+                break;
+            }
+
             switch (ch) {
             case '"':
                 if (!s->quoted) {
--- a/src/os/unix/ngx_process_cycle.c
+++ b/src/os/unix/ngx_process_cycle.c
@@ -792,49 +792,49 @@ ngx_worker_process_init(ngx_cycle_t *cyc
 
     ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
 
-    if (geteuid() == 0) {
-        if (priority && ccf->priority != 0) {
-            if (setpriority(PRIO_PROCESS, 0, ccf->priority) == -1) {
-                ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
-                              "setpriority(%d) failed", ccf->priority);
-            }
+    if (priority && ccf->priority != 0) {
+        if (setpriority(PRIO_PROCESS, 0, ccf->priority) == -1) {
+            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+                          "setpriority(%d) failed", ccf->priority);
         }
+    }
 
-        if (ccf->rlimit_nofile != NGX_CONF_UNSET) {
-            rlmt.rlim_cur = (rlim_t) ccf->rlimit_nofile;
-            rlmt.rlim_max = (rlim_t) ccf->rlimit_nofile;
+    if (ccf->rlimit_nofile != NGX_CONF_UNSET) {
+        rlmt.rlim_cur = (rlim_t) ccf->rlimit_nofile;
+        rlmt.rlim_max = (rlim_t) ccf->rlimit_nofile;
 
-            if (setrlimit(RLIMIT_NOFILE, &rlmt) == -1) {
-                ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
-                              "setrlimit(RLIMIT_NOFILE, %i) failed",
-                              ccf->rlimit_nofile);
-            }
+        if (setrlimit(RLIMIT_NOFILE, &rlmt) == -1) {
+            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+                          "setrlimit(RLIMIT_NOFILE, %i) failed",
+                          ccf->rlimit_nofile);
         }
+    }
 
-        if (ccf->rlimit_core != NGX_CONF_UNSET_SIZE) {
-            rlmt.rlim_cur = (rlim_t) ccf->rlimit_core;
-            rlmt.rlim_max = (rlim_t) ccf->rlimit_core;
+    if (ccf->rlimit_core != NGX_CONF_UNSET_SIZE) {
+        rlmt.rlim_cur = (rlim_t) ccf->rlimit_core;
+        rlmt.rlim_max = (rlim_t) ccf->rlimit_core;
 
-            if (setrlimit(RLIMIT_CORE, &rlmt) == -1) {
-                ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
-                              "setrlimit(RLIMIT_CORE, %i) failed",
-                              ccf->rlimit_core);
-            }
+        if (setrlimit(RLIMIT_CORE, &rlmt) == -1) {
+            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+                          "setrlimit(RLIMIT_CORE, %i) failed",
+                          ccf->rlimit_core);
         }
+    }
 
 #ifdef RLIMIT_SIGPENDING
-        if (ccf->rlimit_sigpending != NGX_CONF_UNSET) {
-            rlmt.rlim_cur = (rlim_t) ccf->rlimit_sigpending;
-            rlmt.rlim_max = (rlim_t) ccf->rlimit_sigpending;
+    if (ccf->rlimit_sigpending != NGX_CONF_UNSET) {
+        rlmt.rlim_cur = (rlim_t) ccf->rlimit_sigpending;
+        rlmt.rlim_max = (rlim_t) ccf->rlimit_sigpending;
 
-            if (setrlimit(RLIMIT_SIGPENDING, &rlmt) == -1) {
-                ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
-                              "setrlimit(RLIMIT_SIGPENDING, %i) failed",
-                              ccf->rlimit_sigpending);
-            }
+        if (setrlimit(RLIMIT_SIGPENDING, &rlmt) == -1) {
+            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+                          "setrlimit(RLIMIT_SIGPENDING, %i) failed",
+                          ccf->rlimit_sigpending);
         }
+    }
 #endif
 
+    if (geteuid() == 0) {
         if (setgid(ccf->group) == -1) {
             ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                           "setgid(%d) failed", ccf->group);