# HG changeset patch # User Igor Sysoev # Date 1219694400 -14400 # Node ID 6ebbca3d5ed73b82e1e0aa14adff133b50bbb4ea # Parent 59e324e4d6d3a87accb4231b6c003e927a32db90 nginx 0.7.12 *) Feature: the "server_name" directive supports empty name "". *) Feature: the "gzip_disable" directive supports special "msie6" mask. *) Bugfix: if the "max_fails=0" parameter was used in upstream with several servers, then a worker process exited on a SIGFPE signal. Thanks to Maxim Dounin. *) Bugfix: a request body was dropped while redirection via an "error_page" directive. *) Bugfix: a full response was returned for request method HEAD while redirection via an "error_page" directive. *) Bugfix: the $r->header_in() method did not return value of the "Host", "User-Agent", and "Connection" request header lines; the bug had appeared in 0.7.0. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,25 @@ +Changes with nginx 0.7.12 26 Aug 2008 + + *) Feature: the "server_name" directive supports empty name "". + + *) Feature: the "gzip_disable" directive supports special "msie6" mask. + + *) Bugfix: if the "max_fails=0" parameter was used in upstream with + several servers, then a worker process exited on a SIGFPE signal. + Thanks to Maxim Dounin. + + *) Bugfix: a request body was dropped while redirection via an + "error_page" directive. + + *) Bugfix: a full response was returned for request method HEAD while + redirection via an "error_page" directive. + + *) Bugfix: the $r->header_in() method did not return value of the + "Host", "User-Agent", and "Connection" request header lines; the bug + had appeared in 0.7.0. + + Changes with nginx 0.7.11 18 Aug 2008 *) Change: now ngx_http_charset_module does not work by default with diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,26 @@ +Изменения в nginx 0.7.12 26.08.2008 + + *) Добавление: директива server_name поддерживает пустое имя "". + + *) Добавление: директива gzip_disable поддерживает специальную маску + msie6. + + *) Исправление: при использовании параметра max_fails=0 в upstream'е с + несколькими серверами рабочий процесс выходил по сигналу SIGFPE. + Спасибо Максиму Дунину. + + *) Исправление: при перенаправлении запроса с помощью директивы + error_page терялось тело запроса. + + *) Исправление: при перенаправлении запроса с методом HEAD с помощью + директивы error_page возвращался полный ответ. + + *) Исправление: метод $r->header_in() не возвращал значения строк + "Host", "User-Agent", и "Connection" из заголовка запроса; ошибка + появилась в 0.7.0. + + Изменения в nginx 0.7.11 18.08.2008 *) Изменение: теперь ngx_http_charset_module по умолчанию не работает diff --git a/conf/mime.types b/conf/mime.types --- a/conf/mime.types +++ b/conf/mime.types @@ -33,6 +33,8 @@ types { application/vnd.ms-powerpoint ppt; application/vnd.wap.wmlc wmlc; application/vnd.wap.xhtml+xml xhtml; + application/vnd.google-earth.kml+xml kml; + application/vnd.google-earth.kmz kmz; application/x-cocoa cco; application/x-java-archive-diff jardiff; application/x-java-jnlp-file jnlp; 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.7.11" +#define NGINX_VERSION "0.7.12" #define NGINX_VER "nginx/" NGINX_VERSION #define NGINX_VAR "NGINX" diff --git a/src/core/ngx_config.h b/src/core/ngx_config.h --- a/src/core/ngx_config.h +++ b/src/core/ngx_config.h @@ -116,10 +116,6 @@ typedef intptr_t ngx_flag_t; #define INADDR_NONE ((unsigned int) -1) #endif -#ifndef INET_ADDRSTRLEN /* Win32 */ -#define INET_ADDRSTRLEN 16 -#endif - #ifdef MAXHOSTNAMELEN #define NGX_MAXHOSTNAMELEN MAXHOSTNAMELEN #else diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c --- a/src/core/ngx_connection.c +++ b/src/core/ngx_connection.c @@ -37,23 +37,23 @@ ngx_listening_inet_stream_socket(ngx_con ls->addr_text.data = ngx_pnalloc(cf->pool, - INET_ADDRSTRLEN - 1 + sizeof(":65535") - 1); + NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1); if (ls->addr_text.data == NULL) { return NULL; } - len = ngx_inet_ntop(AF_INET, &addr, ls->addr_text.data, INET_ADDRSTRLEN); + len = ngx_inet_ntop(AF_INET, &addr, ls->addr_text.data, + NGX_INET_ADDRSTRLEN); ls->addr_text.len = ngx_sprintf(ls->addr_text.data + len, ":%d", port) - ls->addr_text.data; ls->fd = (ngx_socket_t) -1; - ls->family = AF_INET; ls->type = SOCK_STREAM; ls->sockaddr = (struct sockaddr *) sin; ls->socklen = sizeof(struct sockaddr_in); ls->addr = offsetof(struct sockaddr_in, sin_addr); - ls->addr_text_max_len = INET_ADDRSTRLEN; + ls->addr_text_max_len = NGX_INET_ADDRSTRLEN; return ls; } @@ -104,17 +104,16 @@ ngx_set_inherited_sockets(ngx_cycle_t *c continue; } - ls[i].addr_text_max_len = INET_ADDRSTRLEN; + ls[i].addr_text_max_len = NGX_INET_ADDRSTRLEN; ls[i].addr_text.data = ngx_pnalloc(cycle->pool, - INET_ADDRSTRLEN - 1 + sizeof(":65535") - 1); + NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1); if (ls[i].addr_text.data == NULL) { return NGX_ERROR; } - ls[i].family = sin->sin_family; - len = ngx_sock_ntop(ls[i].family, ls[i].sockaddr, - ls[i].addr_text.data, INET_ADDRSTRLEN); + len = ngx_sock_ntop(ls[i].sockaddr, ls[i].addr_text.data, + NGX_INET_ADDRSTRLEN); if (len == 0) { return NGX_ERROR; } @@ -254,7 +253,7 @@ ngx_open_listening_sockets(ngx_cycle_t * continue; } - s = ngx_socket(ls[i].family, ls[i].type, 0); + s = ngx_socket(ls[i].sockaddr->sa_family, ls[i].type, 0); if (s == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, 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 @@ -23,7 +23,6 @@ struct ngx_listening_s { size_t addr_text_max_len; ngx_str_t addr_text; - int family; int type; int backlog; diff --git a/src/core/ngx_hash.c b/src/core/ngx_hash.c --- a/src/core/ngx_hash.c +++ b/src/core/ngx_hash.c @@ -220,6 +220,10 @@ ngx_hash_find_combined(ngx_hash_combined } } + if (len == 0) { + return NULL; + } + if (hash->wc_head && hash->wc_head->hash.buckets) { value = ngx_hash_find_wc_head(hash->wc_head, name, len); diff --git a/src/core/ngx_inet.c b/src/core/ngx_inet.c --- a/src/core/ngx_inet.c +++ b/src/core/ngx_inet.c @@ -8,7 +8,8 @@ #include -static size_t ngx_sprint_uchar(u_char *text, u_char c, size_t len); +static ngx_int_t ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u); +static ngx_int_t ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u); /* AF_INET only */ @@ -56,166 +57,43 @@ ngx_inet_addr(u_char *text, size_t len) } -/* - * ngx_sock_ntop() and ngx_inet_ntop() may be implemented as - * "ngx_sprintf(text, "%ud.%ud.%ud.%ud", p[0], p[1], p[2], p[3])", however, - * they had been implemented long before the ngx_sprintf() had appeared - * and they are faster by 1.5-2.5 times, so it is worth to keep them. - * - * By the way, the implementation using ngx_sprintf() is faster by 2.5-3 times - * than using FreeBSD libc's snprintf(). - */ - /* AF_INET only */ size_t -ngx_sock_ntop(int family, struct sockaddr *sa, u_char *text, size_t len) +ngx_sock_ntop(struct sockaddr *sa, u_char *text, size_t len) { u_char *p; - size_t n; - ngx_uint_t i; struct sockaddr_in *sin; - if (len == 0) { - return 0; - } + if (sa->sa_family == AF_INET) { - if (family != AF_INET) { - return 0; - } + sin = (struct sockaddr_in *) sa; + p = (u_char *) &sin->sin_addr; - sin = (struct sockaddr_in *) sa; - p = (u_char *) &sin->sin_addr; - - if (len > INET_ADDRSTRLEN) { - len = INET_ADDRSTRLEN; + return ngx_snprintf(text, len, "%ud.%ud.%ud.%ud", + p[0], p[1], p[2], p[3]) + - text; } - n = ngx_sprint_uchar(text, p[0], len); - - i = 1; - - do { - if (len == n) { - text[n - 1] = '\0'; - return n; - } - - text[n++] = '.'; - - if (len == n) { - text[n - 1] = '\0'; - return n; - } - - n += ngx_sprint_uchar(&text[n], p[i++], len - n); - - } while (i < 4); - - if (len == n) { - text[n] = '\0'; - return n; - } - - text[n] = '\0'; - - return n; + return 0; } size_t ngx_inet_ntop(int family, void *addr, u_char *text, size_t len) { - u_char *p; - size_t n; - ngx_uint_t i; - - if (len == 0) { - return 0; - } + u_char *p; - if (family != AF_INET) { - return 0; - } - - p = (u_char *) addr; - - if (len > INET_ADDRSTRLEN) { - len = INET_ADDRSTRLEN; - } - - n = ngx_sprint_uchar(text, p[0], len); + if (family == AF_INET) { - i = 1; - - do { - if (len == n) { - text[n - 1] = '\0'; - return n; - } - - text[n++] = '.'; + p = (u_char *) addr; - if (len == n) { - text[n - 1] = '\0'; - return n; - } - - n += ngx_sprint_uchar(&text[n], p[i++], len - n); - - } while (i < 4); - - if (len == n) { - text[n] = '\0'; - return n; + return ngx_snprintf(text, len, "%ud.%ud.%ud.%ud", + p[0], p[1], p[2], p[3]) + - text; } - text[n] = '\0'; - - return n; -} - - -static size_t -ngx_sprint_uchar(u_char *text, u_char c, size_t len) -{ - size_t n; - ngx_uint_t c1, c2; - - n = 0; - - if (len == n) { - return n; - } - - c1 = c / 100; - - if (c1) { - *text++ = (u_char) (c1 + '0'); - n++; - - if (len == n) { - return n; - } - } - - c2 = (c % 100) / 10; - - if (c1 || c2) { - *text++ = (u_char) (c2 + '0'); - n++; - - if (len == n) { - return n; - } - } - - c2 = c % 10; - - *text = (u_char) (c2 + '0'); - n++; - - return n; + return 0; } @@ -224,43 +102,48 @@ ngx_sprint_uchar(u_char *text, u_char c, ngx_int_t ngx_ptocidr(ngx_str_t *text, void *cidr) { - ngx_int_t m; - ngx_uint_t i; + u_char *addr, *mask, *last; + ngx_int_t shift; ngx_inet_cidr_t *in_cidr; in_cidr = cidr; - - for (i = 0; i < text->len; i++) { - if (text->data[i] == '/') { - break; - } - } + addr = text->data; + last = addr + text->len; - if (i == text->len) { - return NGX_ERROR; - } + mask = ngx_strlchr(addr, last, '/'); - text->data[i] = '\0'; - in_cidr->addr = inet_addr((char *) text->data); - text->data[i] = '/'; + in_cidr->addr = ngx_inet_addr(addr, (mask ? mask : last) - addr); + if (in_cidr->addr == INADDR_NONE) { return NGX_ERROR; } - m = ngx_atoi(&text->data[i + 1], text->len - (i + 1)); - if (m == NGX_ERROR) { + if (mask == NULL) { + in_cidr->mask = 0xffffffff; + return NGX_OK; + } + + mask++; + + shift = ngx_atoi(mask, last - mask); + if (shift == NGX_ERROR) { return NGX_ERROR; } - if (m == 0) { + if (shift == 0) { /* the x86 compilers use the shl instruction that shifts by modulo 32 */ in_cidr->mask = 0; - return NGX_OK; + + if (in_cidr->addr == 0) { + return NGX_OK; + } + + return NGX_DONE; } - in_cidr->mask = htonl((ngx_uint_t) (0 - (1 << (32 - m)))); + in_cidr->mask = htonl((ngx_uint_t) (0 - (1 << (32 - shift)))); if (in_cidr->addr == (in_cidr->addr & in_cidr->mask)) { return NGX_OK; @@ -275,85 +158,12 @@ ngx_ptocidr(ngx_str_t *text, void *cidr) ngx_int_t ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u) { - u_char *p, *host, *port_start; - size_t len, port_len; - ngx_int_t port; - ngx_uint_t i; - struct hostent *h; -#if (NGX_HAVE_UNIX_DOMAIN) - struct sockaddr_un *saun; -#endif + u_char *p; - len = u->url.len; p = u->url.data; if (ngx_strncasecmp(p, (u_char *) "unix:", 5) == 0) { - -#if (NGX_HAVE_UNIX_DOMAIN) - - p += 5; - len -= 5; - - u->uri.len = len; - u->uri.data = p; - - if (u->uri_part) { - for (i = 0; i < len; i++) { - - if (p[i] == ':') { - len = i; - - u->uri.len -= len + 1; - u->uri.data += len + 1; - - break; - } - } - } - - if (len == 0) { - u->err = "no path in the unix domain socket"; - return NGX_ERROR; - } - - if (len + 1 > sizeof(saun->sun_path)) { - u->err = "too long path in the unix domain socket"; - return NGX_ERROR; - } - - u->addrs = ngx_pcalloc(pool, sizeof(ngx_peer_addr_t)); - if (u->addrs == NULL) { - return NGX_ERROR; - } - - saun = ngx_pcalloc(pool, sizeof(struct sockaddr_un)); - if (saun == NULL) { - return NGX_ERROR; - } - - u->naddrs = 1; - - saun->sun_family = AF_UNIX; - (void) ngx_cpystrn((u_char *) saun->sun_path, p, len + 1); - - u->addrs[0].sockaddr = (struct sockaddr *) saun; - u->addrs[0].socklen = sizeof(struct sockaddr_un); - u->addrs[0].name.len = len + 5; - u->addrs[0].name.data = u->url.data; - - u->host.len = len; - u->host.data = p; - - u->unix_socket = 1; - - return NGX_OK; - -#else - u->err = "the unix domain sockets are not supported on this platform"; - - return NGX_ERROR; - -#endif + return ngx_parse_unix_domain_url(pool, u); } if ((p[0] == ':' || p[0] == '/') && !u->listen) { @@ -361,150 +171,219 @@ ngx_parse_url(ngx_pool_t *pool, ngx_url_ return NGX_ERROR; } - u->host.data = p; + return ngx_parse_inet_url(pool, u); +} - port_start = NULL; - port_len = 0; - - for (i = 0; i < len; i++) { - if (p[i] == ':') { - port_start = &p[i + 1]; - u->host.len = i; - - if (!u->uri_part) { - port_len = len - (i + 1); - break; - } - } +static ngx_int_t +ngx_parse_unix_domain_url(ngx_pool_t *pool, ngx_url_t *u) +{ +#if (NGX_HAVE_UNIX_DOMAIN) + u_char *path, *uri, *last; + size_t len; + struct sockaddr_un *saun; - if (p[i] == '/') { - u->uri.len = len - i; - u->uri.data = &p[i]; + len = u->url.len; + path = u->url.data; - if (u->host.len == 0) { - u->host.len = i; - } + path += 5; + len -= 5; + + if (u->uri_part) { - if (port_start == NULL) { - u->no_port = 1; - goto no_port; - } - - port_len = &p[i] - port_start; + last = path + len; + uri = ngx_strlchr(path, last, ':'); - if (port_len == 0) { - u->err = "invalid port"; - return NGX_ERROR; - } - - break; + if (uri) { + len = uri - path; + uri++; + u->uri.len = last - uri; + u->uri.data = uri; } } - if (port_start) { + if (len == 0) { + u->err = "no path in the unix domain socket"; + return NGX_ERROR; + } + + u->host.len = len++; + u->host.data = path; + u->family = AF_UNIX; + + if (len > sizeof(saun->sun_path)) { + u->err = "too long path in the unix domain socket"; + return NGX_ERROR; + } - if (port_len == 0) { - port_len = &p[i] - port_start; + u->addrs = ngx_pcalloc(pool, sizeof(ngx_peer_addr_t)); + if (u->addrs == NULL) { + return NGX_ERROR; + } + + saun = ngx_pcalloc(pool, sizeof(struct sockaddr_un)); + if (saun == NULL) { + return NGX_ERROR; + } + + u->naddrs = 1; + + saun->sun_family = AF_UNIX; + (void) ngx_cpystrn((u_char *) saun->sun_path, path, len); + + u->addrs[0].sockaddr = (struct sockaddr *) saun; + u->addrs[0].socklen = sizeof(struct sockaddr_un); + u->addrs[0].name.len = len + 4; + u->addrs[0].name.data = u->url.data; - if (port_len == 0) { - u->err = "invalid port"; - return NGX_ERROR; - } + return NGX_OK; + +#else + + u->err = "the unix domain sockets are not supported on this platform"; + + return NGX_ERROR; + +#endif +} + + +static ngx_int_t +ngx_parse_inet_url(ngx_pool_t *pool, ngx_url_t *u) +{ + u_char *p, *host, *port, *last, *uri; + size_t len; + ngx_int_t n; + struct hostent *h; + + u->family = AF_INET; + + host = u->url.data; + + last = host + u->url.len; + + port = ngx_strlchr(host, last, ':'); + + uri = ngx_strlchr(port ? port : host, last, '/'); + + if (uri) { + if (u->listen || !u->uri_part) { + u->err = "invalid host"; + return NGX_ERROR; } - port = ngx_atoi(port_start, port_len); + u->uri.len = last - uri; + u->uri.data = uri; + + last = uri; + } - if (port == NGX_ERROR || port < 1 || port > 65536) { + if (port) { + port++; + + len = last - port; + + if (len == 0) { u->err = "invalid port"; return NGX_ERROR; } - u->port_text.len = port_len; - u->port_text.data = port_start; - - } else { - port = ngx_atoi(p, len); - - if (port == NGX_ERROR) { - u->host.len = len; - u->no_port = 1; - - goto no_port; - } - - u->wildcard = 1; - } + n = ngx_atoi(port, len); - u->port = (in_port_t) port; - -no_port: - - if (u->listen) { - - if (u->port == 0) { - if (u->default_port == 0) { - u->err = "no port"; - return NGX_ERROR; - } - - u->port = u->default_port; - } - - if (u->host.len == 1 && u->host.data[0] == '*') { - u->host.len = 0; + if (n < 1 || n > 65536) { + u->err = "invalid port"; + return NGX_ERROR; } - /* AF_INET only */ + u->port = (in_port_t) n; - if (u->host.len) { + u->port_text.len = len; + u->port_text.data = port; + + last = port - 1; - host = ngx_alloc(u->host.len + 1, pool->log); - if (host == NULL) { - return NGX_ERROR; - } + } else { + if (uri == NULL) { - (void) ngx_cpystrn(host, u->host.data, u->host.len + 1); + if (u->listen) { - u->addr.in_addr = inet_addr((const char *) host); + /* test value as port only */ + + n = ngx_atoi(host, last - host); - if (u->addr.in_addr == INADDR_NONE) { - h = gethostbyname((const char *) host); + if (n != NGX_ERROR) { + + if (n < 1 || n > 65536) { + u->err = "invalid port"; + return NGX_ERROR; + } - if (h == NULL || h->h_addr_list[0] == NULL) { - ngx_free(host); - u->err = "host not found"; - return NGX_ERROR; + u->port = (in_port_t) n; + + u->port_text.len = last - host; + u->port_text.data = host; + + return NGX_OK; } - - u->addr.in_addr = *(in_addr_t *) (h->h_addr_list[0]); } - - ngx_free(host); - - } else { - u->addr.in_addr = INADDR_ANY; } - return NGX_OK; + u->no_port = 1; } - if (u->host.len == 0) { + len = last - host; + + if (len == 0) { u->err = "no host"; return NGX_ERROR; } + if (len == 1 && *host == '*') { + len = 0; + } + + u->host.len = len; + u->host.data = host; + if (u->no_resolve) { return NGX_OK; } + if (len++) { + + p = ngx_alloc(len, pool->log); + if (p == NULL) { + return NGX_ERROR; + } + + (void) ngx_cpystrn(p, host, len); + + u->addr.in_addr = inet_addr((const char *) p); + + if (u->addr.in_addr == INADDR_NONE) { + h = gethostbyname((const char *) p); + + if (h == NULL || h->h_addr_list[0] == NULL) { + ngx_free(p); + u->err = "host not found"; + return NGX_ERROR; + } + + u->addr.in_addr = *(in_addr_t *) (h->h_addr_list[0]); + } + + ngx_free(p); + + } else { + u->addr.in_addr = INADDR_ANY; + } + if (u->no_port) { u->port = u->default_port; } - if (u->port == 0) { - u->err = "no port"; - return NGX_ERROR; + if (u->listen) { + return NGX_OK; } if (ngx_inet_resolve_host(pool, u) != NGX_OK) { @@ -576,14 +455,14 @@ ngx_inet_resolve_host(ngx_pool_t *pool, u->addrs[i].sockaddr = (struct sockaddr *) sin; u->addrs[i].socklen = sizeof(struct sockaddr_in); - len = INET_ADDRSTRLEN - 1 + 1 + sizeof(":65536") - 1; + len = NGX_INET_ADDRSTRLEN + sizeof(":65536") - 1; p = ngx_pnalloc(pool, len); if (p == NULL) { return NGX_ERROR; } - len = ngx_sock_ntop(AF_INET, (struct sockaddr *) sin, p, len); + len = ngx_sock_ntop((struct sockaddr *) sin, p, len); u->addrs[i].name.len = ngx_sprintf(&p[len], ":%d", u->port) - p; u->addrs[i].name.data = p; diff --git a/src/core/ngx_inet.h b/src/core/ngx_inet.h --- a/src/core/ngx_inet.h +++ b/src/core/ngx_inet.h @@ -12,6 +12,9 @@ #include +#define NGX_INET_ADDRSTRLEN (sizeof("255.255.255.255") - 1) + + typedef struct { in_addr_t addr; in_addr_t mask; @@ -31,8 +34,6 @@ typedef struct { typedef struct { - ngx_int_t type; - ngx_str_t url; ngx_str_t host; ngx_str_t port_text; @@ -40,15 +41,14 @@ typedef struct { in_port_t port; in_port_t default_port; + int family; unsigned listen:1; unsigned uri_part:1; unsigned no_resolve:1; unsigned one_addr:1; - unsigned wildcard:1; unsigned no_port:1; - unsigned unix_socket:1; ngx_url_addr_t addr; @@ -60,7 +60,7 @@ typedef struct { in_addr_t ngx_inet_addr(u_char *text, size_t len); -size_t ngx_sock_ntop(int family, struct sockaddr *sa, u_char *text, size_t len); +size_t ngx_sock_ntop(struct sockaddr *sa, u_char *text, size_t len); size_t ngx_inet_ntop(int family, void *addr, u_char *text, size_t len); ngx_int_t ngx_ptocidr(ngx_str_t *text, void *cidr); ngx_int_t ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u); 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 @@ -54,8 +54,24 @@ void ngx_strlow(u_char *dst, u_char *src #define ngx_strstr(s1, s2) strstr((const char *) s1, (const char *) s2) +#define ngx_strlen(s) strlen((const char *) s) + #define ngx_strchr(s1, c) strchr((const char *) s1, (int) c) -#define ngx_strlen(s) strlen((const char *) s) + +static ngx_inline u_char * +ngx_strlchr(u_char *p, u_char *last, u_char c) +{ + while (p < last) { + + if (*p == c) { + return p; + } + + p++; + } + + return NULL; +} /* diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c --- a/src/event/ngx_event.c +++ b/src/event/ngx_event.c @@ -1051,13 +1051,6 @@ ngx_event_debug_connection(ngx_conf_t *c return NGX_CONF_ERROR; } - dc->addr = inet_addr((char *) value[1].data); - - if (dc->addr != INADDR_NONE) { - dc->mask = 0xffffffff; - return NGX_CONF_OK; - } - rc = ngx_ptocidr(&value[1], &in_cidr); if (rc == NGX_DONE) { diff --git a/src/event/ngx_event_accept.c b/src/event/ngx_event_accept.c --- a/src/event/ngx_event_accept.c +++ b/src/event/ngx_event_accept.c @@ -207,8 +207,7 @@ ngx_event_accept(ngx_event_t *ev) return; } - c->addr_text.len = ngx_sock_ntop(ls->family, c->sockaddr, - c->addr_text.data, + c->addr_text.len = ngx_sock_ntop(c->sockaddr, c->addr_text.data, ls->addr_text_max_len); if (c->addr_text.len == 0) { ngx_close_accepted_connection(c); diff --git a/src/http/modules/ngx_http_access_module.c b/src/http/modules/ngx_http_access_module.c --- a/src/http/modules/ngx_http_access_module.c +++ b/src/http/modules/ngx_http_access_module.c @@ -166,14 +166,6 @@ ngx_http_access_rule(ngx_conf_t *cf, ngx return NGX_CONF_OK; } - rule->addr = inet_addr((char *) value[1].data); - - if (rule->addr != INADDR_NONE) { - rule->mask = 0xffffffff; - - return NGX_CONF_OK; - } - rc = ngx_ptocidr(&value[1], &in_cidr); if (rc == NGX_ERROR) { diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -2546,7 +2546,7 @@ static ngx_int_t ngx_http_proxy_set_vars(ngx_pool_t *pool, ngx_url_t *u, ngx_http_proxy_vars_t *v) { - if (!u->unix_socket) { + if (u->family != AF_UNIX) { if (u->no_port || u->port == u->default_port) { v->host_header = u->host; diff --git a/src/http/modules/ngx_http_realip_module.c b/src/http/modules/ngx_http_realip_module.c --- a/src/http/modules/ngx_http_realip_module.c +++ b/src/http/modules/ngx_http_realip_module.c @@ -251,14 +251,6 @@ ngx_http_realip_from(ngx_conf_t *cf, ngx value = cf->args->elts; - from->addr = inet_addr((char *) value[1].data); - - if (from->addr != INADDR_NONE) { - from->mask = 0xffffffff; - - return NGX_CONF_OK; - } - rc = ngx_ptocidr(&value[1], &in_cidr); if (rc == NGX_ERROR) { diff --git a/src/http/modules/ngx_http_xslt_filter_module.c b/src/http/modules/ngx_http_xslt_filter_module.c --- a/src/http/modules/ngx_http_xslt_filter_module.c +++ b/src/http/modules/ngx_http_xslt_filter_module.c @@ -136,6 +136,7 @@ static void *ngx_http_xslt_filter_create static char *ngx_http_xslt_filter_merge_conf(ngx_conf_t *cf, void *parent, void *child); static ngx_int_t ngx_http_xslt_filter_init(ngx_conf_t *cf); +static void ngx_http_xslt_filter_exit(ngx_cycle_t *cycle); ngx_str_t ngx_http_xslt_default_types[] = { @@ -196,8 +197,8 @@ ngx_module_t ngx_http_xslt_filter_modul NULL, /* init process */ NULL, /* init thread */ NULL, /* exit thread */ - NULL, /* exit process */ - NULL, /* exit master */ + ngx_http_xslt_filter_exit, /* exit process */ + ngx_http_xslt_filter_exit, /* exit master */ NGX_MODULE_V1_PADDING }; 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.7.11'; +our $VERSION = '0.7.12'; 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 @@ -1625,8 +1625,8 @@ ngx_http_server_addr(ngx_http_request_t return NGX_OK; } - s->len = ngx_inet_ntop(c->listening->family, &r->in_addr, - s->data, INET_ADDRSTRLEN); + s->len = ngx_sock_ntop((struct sockaddr *) &sin, s->data, + NGX_INET_ADDRSTRLEN); return NGX_OK; } @@ -1672,6 +1672,10 @@ ngx_http_gzip_ok(ngx_http_request_t *r) clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + if (r->headers_in.msie6 && clcf->gzip_disable_msie6) { + return NGX_DECLINED; + } + if (r->http_version < clcf->gzip_http_version) { return NGX_DECLINED; } @@ -2677,6 +2681,7 @@ ngx_http_core_create_loc_conf(ngx_conf_t lcf->gzip_http_version = NGX_CONF_UNSET_UINT; #if (NGX_PCRE) lcf->gzip_disable = NGX_CONF_UNSET_PTR; + lcf->gzip_disable_msie6 = 3; #endif #endif @@ -2914,6 +2919,11 @@ ngx_http_core_merge_loc_conf(ngx_conf_t ngx_conf_merge_ptr_value(conf->gzip_disable, prev->gzip_disable, NULL); #endif + if (conf->gzip_disable_msie6 == 3) { + conf->gzip_disable_msie6 = + (prev->gzip_disable_msie6 == 3) ? 0 : prev->gzip_disable_msie6; + } + #endif return NGX_CONF_OK; @@ -2962,7 +2972,7 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx ngx_memzero(ls, sizeof(ngx_http_listen_t)); - ls->family = AF_INET; + ls->family = u.family; ls->addr = u.addr.in_addr; ls->port = u.port; ls->file_name = cf->conf_file->file.name.data; @@ -2971,7 +2981,7 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx ls->conf.rcvbuf = -1; ls->conf.sndbuf = -1; - n = ngx_inet_ntop(AF_INET, &ls->addr, ls->conf.addr, INET_ADDRSTRLEN + 6); + n = ngx_inet_ntop(AF_INET, &ls->addr, ls->conf.addr, NGX_INET_ADDRSTRLEN); ngx_sprintf(&ls->conf.addr[n], ":%ui", ls->port); if (cf->args->nelts == 2) { @@ -3094,17 +3104,24 @@ ngx_http_core_server_name(ngx_conf_t *cf ch = value[1].data[0]; - if (cscf->server_name.data == NULL && value[1].len) { - name = value[1]; - - if (ch == '.') { - name.len--; - name.data++; - } - - cscf->server_name.len = name.len; - cscf->server_name.data = ngx_pstrdup(cf->pool, &name); - if (cscf->server_name.data == NULL) { + if (cscf->server_name.data == NULL) { + if (value[1].len) { + name = value[1]; + + if (ch == '.') { + name.len--; + name.data++; + } + + cscf->server_name.len = name.len; + cscf->server_name.data = ngx_pstrdup(cf->pool, &name); + if (cscf->server_name.data == NULL) { + return NGX_CONF_ERROR; + } + + } else { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "the first server name must not be empty"); return NGX_CONF_ERROR; } } @@ -3113,8 +3130,7 @@ ngx_http_core_server_name(ngx_conf_t *cf ch = value[i].data[0]; - if (value[i].len == 0 - || (ch == '*' && (value[i].len < 3 || value[i].data[1] != '.')) + if ((ch == '*' && (value[i].len < 3 || value[i].data[1] != '.')) || (ch == '.' && value[i].len < 2)) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, @@ -3747,8 +3763,9 @@ ngx_http_core_resolver(ngx_conf_t *cf, n static char * ngx_http_gzip_disable(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { + ngx_http_core_loc_conf_t *clcf = conf; + #if (NGX_PCRE) - ngx_http_core_loc_conf_t *clcf = conf; ngx_str_t err, *value; ngx_uint_t i; @@ -3770,6 +3787,11 @@ ngx_http_gzip_disable(ngx_conf_t *cf, ng for (i = 1; i < cf->args->nelts; i++) { + if (ngx_strcmp(value[1].data, "msie6") == 0) { + clcf->gzip_disable_msie6 = 1; + continue; + } + re = ngx_array_push(clcf->gzip_disable); if (re == NULL) { return NGX_CONF_ERROR; @@ -3789,8 +3811,18 @@ ngx_http_gzip_disable(ngx_conf_t *cf, ng return NGX_CONF_OK; #else + ngx_str_t *value; + + value = cf->args->elts; + + if (cf->args->nelts == 2 && ngx_strcmp(value[1].data, "msie6") == 0) { + clcf->gzip_disable_msie6 = 1; + return NGX_CONF_OK; + } + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "\"gzip_disable\" requires PCRE library"); + "without PCRE library \"gzip_disable\" supports " + "builtin \"msie6\" mask only"); return NGX_CONF_ERROR; #endif 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 @@ -47,7 +47,7 @@ typedef struct { ngx_uint_t deferred_accept; #endif - u_char addr[INET_ADDRSTRLEN + 6]; + u_char addr[NGX_INET_ADDRSTRLEN + sizeof(":65535")]; } ngx_http_listen_conf_t; @@ -242,6 +242,9 @@ struct ngx_http_core_loc_conf_s { unsigned auto_redirect:1; unsigned alias:1; +#if (NGX_HTTP_GZIP) + unsigned gzip_disable_msie6:2; +#endif ngx_http_location_tree_node_t *static_locations; ngx_http_core_loc_conf_t **regex_locations; 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 @@ -162,7 +162,7 @@ ngx_http_header_filter(ngx_http_request_ ngx_http_core_loc_conf_t *clcf; ngx_http_core_srv_conf_t *cscf; /* AF_INET only */ - u_char addr[INET_ADDRSTRLEN]; + u_char addr[NGX_INET_ADDRSTRLEN]; r->header_sent = 1; 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 @@ -74,15 +74,18 @@ static char *ngx_http_client_errors[] = ngx_http_header_t ngx_http_headers_in[] = { - { ngx_string("Host"), 0, ngx_http_process_host }, - - { ngx_string("Connection"), 0, ngx_http_process_connection }, + { ngx_string("Host"), offsetof(ngx_http_headers_in_t, host), + ngx_http_process_host }, + + { ngx_string("Connection"), offsetof(ngx_http_headers_in_t, connection), + ngx_http_process_connection }, { ngx_string("If-Modified-Since"), offsetof(ngx_http_headers_in_t, if_modified_since), ngx_http_process_unique_header_line }, - { ngx_string("User-Agent"), 0, ngx_http_process_user_agent }, + { ngx_string("User-Agent"), offsetof(ngx_http_headers_in_t, user_agent), + ngx_http_process_user_agent }, { ngx_string("Referer"), offsetof(ngx_http_headers_in_t, referer), ngx_http_process_header_line }, @@ -568,6 +571,7 @@ ngx_http_ssl_handshake_handler(ngx_conne int ngx_http_ssl_servername(ngx_ssl_conn_t *ssl_conn, int *ad, void *arg) { + size_t len; const char *servername; ngx_connection_t *c; ngx_http_request_t *r; @@ -584,12 +588,15 @@ ngx_http_ssl_servername(ngx_ssl_conn_t * ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "SSL server name: \"%s\"", servername); + len = ngx_strlen(servername); + + if (len == 0) { + return SSL_TLSEXT_ERR_NOACK; + } + r = c->data; - if (ngx_http_find_virtual_server(r, (u_char *) servername, - ngx_strlen(servername)) - != NGX_OK) - { + if (ngx_http_find_virtual_server(r, (u_char *) servername, len) != NGX_OK) { return SSL_TLSEXT_ERR_NOACK; } @@ -1283,7 +1290,7 @@ static ngx_int_t ngx_http_process_user_agent(ngx_http_request_t *r, ngx_table_elt_t *h, ngx_uint_t offset) { - u_char *ua, *user_agent; + u_char *user_agent, *msie; if (r->headers_in.user_agent) { return NGX_OK; @@ -1295,14 +1302,22 @@ ngx_http_process_user_agent(ngx_http_req user_agent = h->value.data; - ua = ngx_strstrn(user_agent, "MSIE", 4 - 1); - - if (ua && ua + 8 < user_agent + h->value.len) { + msie = ngx_strstrn(user_agent, "MSIE ", 5 - 1); + + if (msie && msie + 7 < user_agent + h->value.len) { r->headers_in.msie = 1; - if (ua[4] == ' ' && ua[5] == '4' && ua[6] == '.') { - r->headers_in.msie4 = 1; + if (msie[6] == '.') { + + switch (msie[5]) { + case '4': + r->headers_in.msie4 = 1; + /* fall through */ + case '5': + case '6': + r->headers_in.msie6 = 1; + } } #if 0 @@ -1317,6 +1332,7 @@ ngx_http_process_user_agent(ngx_http_req r->headers_in.opera = 1; r->headers_in.msie = 0; r->headers_in.msie4 = 0; + r->headers_in.msie6 = 0; } if (!r->headers_in.msie && !r->headers_in.opera) { @@ -1556,7 +1572,7 @@ ngx_http_find_virtual_server(ngx_http_re ngx_http_core_srv_conf_t *cscf; u_char buf[32]; - if (len == 0 || r->virtual_names == NULL) { + if (r->virtual_names == NULL) { return NGX_DECLINED; } 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 @@ -214,6 +214,7 @@ typedef struct { unsigned connection_type:2; unsigned msie:1; unsigned msie4:1; + unsigned msie6:1; unsigned opera:1; unsigned gecko:1; unsigned konqueror:1; 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 @@ -327,7 +327,6 @@ static ngx_str_t ngx_http_get_name = { ngx_int_t ngx_http_special_response_handler(ngx_http_request_t *r, ngx_int_t error) { - ngx_int_t rc; ngx_uint_t i, err; ngx_http_err_page_t *err_page; ngx_http_core_loc_conf_t *clcf; @@ -336,12 +335,6 @@ ngx_http_special_response_handler(ngx_ht "http special response: %d, \"%V?%V\"", error, &r->uri, &r->args); - rc = ngx_http_discard_request_body(r); - - if (rc == NGX_HTTP_INTERNAL_SERVER_ERROR) { - error = NGX_HTTP_INTERNAL_SERVER_ERROR; - } - r->err_status = error; if (r->keepalive) { @@ -386,6 +379,10 @@ ngx_http_special_response_handler(ngx_ht } } + if (ngx_http_discard_request_body(r) != NGX_OK) { + error = NGX_HTTP_INTERNAL_SERVER_ERROR; + } + if (clcf->msie_refresh && r->headers_in.msie && (error == NGX_HTTP_MOVED_PERMANENTLY @@ -493,8 +490,10 @@ ngx_http_send_error_page(ngx_http_reques if (uri->data[0] == '/') { - r->method = NGX_HTTP_GET; - r->method_name = ngx_http_get_name; + if (r->method != NGX_HTTP_HEAD) { + r->method = NGX_HTTP_GET; + r->method_name = ngx_http_get_name; + } return ngx_http_internal_redirect(r, uri, args); } diff --git a/src/http/ngx_http_upstream_round_robin.c b/src/http/ngx_http_upstream_round_robin.c --- a/src/http/ngx_http_upstream_round_robin.c +++ b/src/http/ngx_http_upstream_round_robin.c @@ -281,14 +281,14 @@ ngx_http_upstream_create_round_robin_pee for (i = 0; i < ur->naddrs; i++) { - len = INET_ADDRSTRLEN - 1 + 1 + sizeof(":65536") - 1; + len = NGX_INET_ADDRSTRLEN + sizeof(":65536") - 1; p = ngx_pnalloc(r->pool, len); if (p == NULL) { return NGX_ERROR; } - len = ngx_inet_ntop(AF_INET, &ur->addrs[i], p, INET_ADDRSTRLEN); + len = ngx_inet_ntop(AF_INET, &ur->addrs[i], p, NGX_INET_ADDRSTRLEN); len = ngx_sprintf(&p[len], ":%d", ur->port) - p; sin = ngx_pcalloc(r->pool, sizeof(struct sockaddr_in)); @@ -645,7 +645,9 @@ ngx_http_upstream_free_round_robin_peer( peer->fails++; peer->accessed = now; - peer->current_weight -= peer->weight / peer->max_fails; + if (peer->max_fails) { + peer->current_weight -= peer->weight / peer->max_fails; + } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0, "free rr peer failed: %ui %i", diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c --- a/src/http/ngx_http_variables.c +++ b/src/http/ngx_http_variables.c @@ -872,7 +872,7 @@ ngx_http_variable_server_addr(ngx_http_r { ngx_str_t s; - s.data = ngx_pnalloc(r->pool, INET_ADDRSTRLEN); + s.data = ngx_pnalloc(r->pool, NGX_INET_ADDRSTRLEN); if (s.data == NULL) { return NGX_ERROR; } diff --git a/src/mail/ngx_mail.c b/src/mail/ngx_mail.c --- a/src/mail/ngx_mail.c +++ b/src/mail/ngx_mail.c @@ -358,13 +358,13 @@ ngx_mail_block(ngx_conf_t *cf, ngx_comma imip->addrs[i].ctx = in_addr[i].ctx; text = ngx_pnalloc(cf->pool, - INET_ADDRSTRLEN - 1 + sizeof(":65535") - 1); + NGX_INET_ADDRSTRLEN + sizeof(":65535") - 1); if (text == NULL) { return NGX_CONF_ERROR; } len = ngx_inet_ntop(AF_INET, &in_addr[i].addr, text, - INET_ADDRSTRLEN); + NGX_INET_ADDRSTRLEN); len = ngx_sprintf(text + len, ":%d", in_port[p].port) - text; diff --git a/src/mail/ngx_mail_core_module.c b/src/mail/ngx_mail_core_module.c --- a/src/mail/ngx_mail_core_module.c +++ b/src/mail/ngx_mail_core_module.c @@ -329,7 +329,7 @@ ngx_mail_core_listen(ngx_conf_t *cf, ngx imls->addr = u.addr.in_addr; imls->port = u.port; - imls->family = AF_INET; + imls->family = u.family; imls->ctx = cf->ctx; for (m = 0; ngx_modules[m]; m++) { diff --git a/src/os/unix/ngx_files.c b/src/os/unix/ngx_files.c --- a/src/os/unix/ngx_files.c +++ b/src/os/unix/ngx_files.c @@ -265,10 +265,14 @@ ngx_open_glob(ngx_glob_t *gl) return NGX_OK; } +#ifdef GLOB_NOMATCH + if (n == GLOB_NOMATCH && gl->test) { return NGX_OK; } +#endif + return NGX_ERROR; } @@ -276,7 +280,7 @@ ngx_open_glob(ngx_glob_t *gl) ngx_int_t ngx_read_glob(ngx_glob_t *gl, ngx_str_t *name) { - if (gl->n < (size_t) gl->pglob.gl_pathc) { + if (gl->n < (size_t) gl->pglob.gl_matchc) { name->len = (size_t) ngx_strlen(gl->pglob.gl_pathv[gl->n]); name->data = (u_char *) gl->pglob.gl_pathv[gl->n];