# HG changeset patch # User Igor Sysoev # Date 1187553600 -14400 # Node ID 390b8f8309d6eb6771fec2467145bb42b6b71868 # Parent be18d26e067c6ec74957a61f15c918bba279c080 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. diff --git a/CHANGES b/CHANGES --- 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 diff --git a/CHANGES.ru b/CHANGES.ru --- 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 упразднён. diff --git a/src/core/nginx.c b/src/core/nginx.c --- 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; } 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.7" +#define NGINX_VERSION "0.6.8" #define NGINX_VER "nginx/" NGINX_VERSION #define NGINX_VAR "NGINX" 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 @@ -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]; 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,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 diff --git a/src/http/modules/ngx_http_geo_module.c b/src/http/modules/ngx_http_geo_module.c --- 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); diff --git a/src/http/modules/ngx_http_limit_zone_module.c b/src/http/modules/ngx_http_limit_zone_module.c --- 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; } diff --git a/src/http/modules/ngx_http_map_module.c b/src/http/modules/ngx_http_map_module.c --- 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; } 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.7'; +our $VERSION = '0.6.8'; 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 @@ -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; 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 @@ -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++; diff --git a/src/http/ngx_http_write_filter_module.c b/src/http/ngx_http_write_filter_module.c --- 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); } diff --git a/src/mail/ngx_mail_auth_http_module.c b/src/mail/ngx_mail_auth_http_module.c --- 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; } diff --git a/src/mail/ngx_mail_parse.c b/src/mail/ngx_mail_parse.c --- 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) { 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 @@ -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);