# HG changeset patch # User Igor Sysoev # Date 1152216000 -14400 # Node ID 56688ed172c8c4de5d81bacaf8b7dd0a90e83005 # Parent f04a548781100998d5e0e15c7ffab7ce4ab0da00 nginx 0.3.53 *) Change: the "add_header" directive adds the string to 204, 301, and 302 responses. *) Feature: the "server" directive in the "upstream" context supports the "weight" parameter. *) Feature: the "server_name" directive supports the "*" wildcard. *) Feature: nginx supports the request body size more than 2G. *) Bugfix: if a client was successfully authorized using "satisfy_any on", then anyway the message "access forbidden by rule" was written in the log. *) Bugfix: the "PUT" method may erroneously not create a file and return the 409 code. *) Bugfix: if the IMAP/POP3 backend returned an error, then nginx continued proxying anyway. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,27 @@ +Changes with nginx 0.3.53 07 Jul 2006 + + *) Change: the "add_header" directive adds the string to 204, 301, and + 302 responses. + + *) Feature: the "server" directive if the "upstream" context supports + the "weight" parameter. + + *) Feature: the "server_name" directive supports the "*" wildcard. + + *) Feature: nginx supports the request body size more than 2G. + + *) Bugfix: if a client was successfully authorized using "satisfy_any + on", then anyway the "access forbidden by rule" message was written + in the log. + + *) Bugfix: the "PUT" method may erroneously not create a file and + return the 409 code. + + *) Bugfix: if the IMAP/POP3 backend returned an error, then nginx + continued proxying anyway. + + Changes with nginx 0.3.52 03 Jul 2006 *) Change: the ngx_http_index_module behavior for the "POST /" requests @@ -1390,8 +1413,8 @@ Changes with nginx 0.1.23 *) Feature: the %request_time log parameter. *) Feature: if the request has no the "Host" header line, then the - proxy_preserve_host directive set this header line to the first - server name of the server_name directive. + "proxy_preserve_host" directive set this header line to the first + server name of the "server_name" directive. *) Bugfix: nginx could not be built on platforms different from i386, amd64, sparc и ppc; bug appeared in 0.1.22. @@ -1587,8 +1610,8 @@ Changes with nginx 0.1.13 *) Feature: the server_names_hash and server_names_hash_threshold directives. - *) Bugfix: the *.domain.tld names in the server_name directive did not - work. + *) Bugfix: the *.domain.tld names in the "server_name" directive did + not work. *) Bugfix: the %request_length log parameter logged the incorrect length. diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,27 @@ +Изменения в nginx 0.3.53 07.07.2006 + + *) Изменение: директива add_header добавляет строки в ответы с кодом + 204, 301 и 302. + + *) Добавление: директива server в блоке upstream поддерживает параметр + weight. + + *) Добавление: директива server_name поддерживает маску "*". + + *) Добавление: nginx поддерживает тело запроса больше 2G. + + *) Исправление: если при использовании "satisfy_any on" клиент успешно + проходил аутентификацию, в лог всё равно записалоcь сообщение + "access forbidden by rule". + + *) Исправление: метод PUT мог ошибочно не создать файл и вернуть код + 409. + + *) Исправление: если во время аутентификации IMAP/POP3 бэкенд возвращал + ошибку, nginx продолжал проксирование. + + Изменения в nginx 0.3.52 03.07.2006 *) Изменение: восстановлено поведение модуля ngx_http_index_module для diff --git a/html/50x.html b/html/50x.html --- a/html/50x.html +++ b/html/50x.html @@ -6,9 +6,13 @@ body { font-family: Tahoma, Verdana, Ari -

+ + + + +
The page you are looking for is temporarily unavailable.
Please try again later. -

+
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_VER "nginx/0.3.52" +#define NGINX_VER "nginx/0.3.53" #define NGINX_VAR "NGINX" #define NGX_OLDPID_EXT ".oldbin" diff --git a/src/core/ngx_conf_file.c b/src/core/ngx_conf_file.c --- a/src/core/ngx_conf_file.c +++ b/src/core/ngx_conf_file.c @@ -1036,6 +1036,37 @@ ngx_conf_set_size_slot(ngx_conf_t *cf, n char * +ngx_conf_set_off_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + char *p = conf; + + off_t *op; + ngx_str_t *value; + ngx_conf_post_t *post; + + + op = (off_t *) (p + cmd->offset); + if (*op != NGX_CONF_UNSET) { + return "is duplicate"; + } + + value = cf->args->elts; + + *op = ngx_parse_offset(&value[1]); + if (*op == (off_t) NGX_ERROR) { + return "invalid value"; + } + + if (cmd->post) { + post = cmd->post; + return post->post_handler(cf, post, op); + } + + return NGX_CONF_OK; +} + + +char * ngx_conf_set_msec_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *p = conf; diff --git a/src/core/ngx_conf_file.h b/src/core/ngx_conf_file.h --- a/src/core/ngx_conf_file.h +++ b/src/core/ngx_conf_file.h @@ -236,8 +236,8 @@ char *ngx_conf_check_num_bounds(ngx_conf conf = default; \ } -#define ngx_conf_init_unsigned_value(conf, default) \ - if (conf == (unsigned) NGX_CONF_UNSET) { \ +#define ngx_conf_init_uint_value(conf, default) \ + if (conf == NGX_CONF_UNSET_UINT) { \ conf = default; \ } @@ -261,7 +261,7 @@ char *ngx_conf_check_num_bounds(ngx_conf conf = (prev == NULL) ? default : prev; \ } -#define ngx_conf_merge_unsigned_value(conf, prev, default) \ +#define ngx_conf_merge_uint_value(conf, prev, default) \ if (conf == NGX_CONF_UNSET_UINT) { \ conf = (prev == NGX_CONF_UNSET_UINT) ? default : prev; \ } @@ -281,6 +281,11 @@ char *ngx_conf_check_num_bounds(ngx_conf conf = (prev == NGX_CONF_UNSET_SIZE) ? default : prev; \ } +#define ngx_conf_merge_off_value(conf, prev, default) \ + if (conf == NGX_CONF_UNSET) { \ + conf = (prev == NGX_CONF_UNSET) ? default : prev; \ + } + #define ngx_conf_merge_str_value(conf, prev, default) \ if (conf.data == NULL) { \ if (prev.data) { \ @@ -328,6 +333,7 @@ char *ngx_conf_set_str_array_slot(ngx_co char *ngx_conf_set_keyval_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); char *ngx_conf_set_num_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); char *ngx_conf_set_size_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +char *ngx_conf_set_off_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); char *ngx_conf_set_msec_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); char *ngx_conf_set_sec_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); char *ngx_conf_set_bufs_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); 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 @@ -479,7 +479,6 @@ ngx_inet_resolve_peer(ngx_conf_t *cf, ng } peers->number = i; - peers->weight = 1; for (i = 0; h->h_addr_list[i] != NULL; i++) { @@ -511,6 +510,10 @@ ngx_inet_resolve_peer(ngx_conf_t *cf, ng - peers->peer[i].name.data; peers->peer[i].uri_separator = ""; + + peers->peer[i].weight = NGX_CONF_UNSET_UINT; + peers->peer[i].max_fails = NGX_CONF_UNSET_UINT; + peers->peer[i].fail_timeout = NGX_CONF_UNSET; } } else { @@ -643,7 +646,6 @@ ngx_inet_upstream_parse(ngx_conf_t *cf, } peers->number = i; - peers->weight = 1; for (i = 0; h->h_addr_list[i] != NULL; i++) { @@ -677,6 +679,10 @@ ngx_inet_upstream_parse(ngx_conf_t *cf, peers->peer[i].name.len = len + u->port_text.len; peers->peer[i].uri_separator = ""; + + peers->peer[i].weight = NGX_CONF_UNSET_UINT; + peers->peer[i].max_fails = NGX_CONF_UNSET_UINT; + peers->peer[i].fail_timeout = NGX_CONF_UNSET; } } else { 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 @@ -29,6 +29,7 @@ typedef struct { ngx_str_t name; char *uri_separator; + ngx_uint_t current_weight; ngx_uint_t weight; ngx_uint_t fails; @@ -45,7 +46,6 @@ typedef struct { struct ngx_peers_s { ngx_uint_t current; - ngx_uint_t weight; ngx_uint_t number; ngx_uint_t last_cached; diff --git a/src/core/ngx_parse.c b/src/core/ngx_parse.c --- a/src/core/ngx_parse.c +++ b/src/core/ngx_parse.c @@ -47,6 +47,51 @@ ngx_parse_size(ngx_str_t *line) } +off_t +ngx_parse_offset(ngx_str_t *line) +{ + u_char last; + off_t offset; + size_t len; + ngx_int_t scale; + + len = line->len; + last = line->data[len - 1]; + + switch (last) { + case 'K': + case 'k': + len--; + scale = 1024; + break; + + case 'M': + case 'm': + len--; + scale = 1024 * 1024; + break; + + case 'G': + case 'g': + len--; + scale = 1024 * 1024 * 1024; + break; + + default: + scale = 1; + } + + offset = ngx_atoof(line->data, len); + if (offset == NGX_ERROR) { + return NGX_ERROR; + } + + offset *= scale; + + return offset; +} + + ngx_int_t ngx_parse_time(ngx_str_t *line, ngx_int_t sec) { diff --git a/src/core/ngx_parse.h b/src/core/ngx_parse.h --- a/src/core/ngx_parse.h +++ b/src/core/ngx_parse.h @@ -16,6 +16,7 @@ ssize_t ngx_parse_size(ngx_str_t *line); +off_t ngx_parse_offset(ngx_str_t *line); ngx_int_t ngx_parse_time(ngx_str_t *line, ngx_int_t sec); diff --git a/src/event/modules/ngx_devpoll_module.c b/src/event/modules/ngx_devpoll_module.c --- a/src/event/modules/ngx_devpoll_module.c +++ b/src/event/modules/ngx_devpoll_module.c @@ -510,8 +510,8 @@ ngx_devpoll_init_conf(ngx_cycle_t *cycle { ngx_devpoll_conf_t *dpcf = conf; - ngx_conf_init_unsigned_value(dpcf->changes, 32); - ngx_conf_init_unsigned_value(dpcf->events, 32); + ngx_conf_init_uint_value(dpcf->changes, 32); + ngx_conf_init_uint_value(dpcf->events, 32); return NGX_CONF_OK; } diff --git a/src/event/modules/ngx_epoll_module.c b/src/event/modules/ngx_epoll_module.c --- a/src/event/modules/ngx_epoll_module.c +++ b/src/event/modules/ngx_epoll_module.c @@ -479,11 +479,13 @@ ngx_epoll_process_events(ngx_cycle_t *cy c->fd, revents); } +#if 0 if (revents & ~(EPOLLIN|EPOLLOUT|EPOLLERR|EPOLLHUP)) { ngx_log_error(NGX_LOG_ALERT, log, 0, "strange epoll_wait() events fd:%d ev:%04XD", c->fd, revents); } +#endif if ((revents & (EPOLLERR|EPOLLHUP)) && (revents & (EPOLLIN|EPOLLOUT)) == 0) @@ -564,7 +566,7 @@ ngx_epoll_init_conf(ngx_cycle_t *cycle, { ngx_epoll_conf_t *epcf = conf; - ngx_conf_init_unsigned_value(epcf->events, 512); + ngx_conf_init_uint_value(epcf->events, 512); return NGX_CONF_OK; } 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 @@ -1205,10 +1205,10 @@ ngx_event_init_conf(ngx_cycle_t *cycle, return NGX_CONF_ERROR; } - ngx_conf_init_unsigned_value(ecf->connections, connections); + ngx_conf_init_uint_value(ecf->connections, connections); cycle->connection_n = ecf->connections; - ngx_conf_init_unsigned_value(ecf->use, module->ctx_index); + ngx_conf_init_uint_value(ecf->use, module->ctx_index); event_module = module->ctx; ngx_conf_init_ptr_value(ecf->name, event_module->name->data); diff --git a/src/event/ngx_event_connect.c b/src/event/ngx_event_connect.c --- a/src/event/ngx_event_connect.c +++ b/src/event/ngx_event_connect.c @@ -81,8 +81,6 @@ ngx_event_connect_peer(ngx_peer_connecti pc->peers->current = 0; } - pc->peers->weight = pc->peers->peer[pc->peers->current].weight; - pc->tries--; if (pc->tries) { @@ -92,16 +90,16 @@ ngx_event_connect_peer(ngx_peer_connecti goto failed; } - pc->peers->weight--; + peer->current_weight--; - if (pc->peers->weight == 0) { + if (peer->current_weight == 0) { + peer->current_weight = peer->weight; + pc->peers->current++; if (pc->peers->current >= pc->peers->number) { pc->peers->current = 0; } - - pc->peers->weight = pc->peers->peer[pc->peers->current].weight; } } else { @@ -131,6 +129,20 @@ ngx_event_connect_peer(ngx_peer_connecti goto failed; } + + peer->current_weight--; + + if (peer->current_weight == 0) { + peer->current_weight = peer->weight; + + if (pc->cur_peer == pc->peers->current) { + pc->peers->current++; + + if (pc->peers->current >= pc->peers->number) { + pc->peers->current = 0; + } + } + } } } @@ -358,15 +370,22 @@ failed: void ngx_event_connect_peer_failed(ngx_peer_connection_t *pc, ngx_uint_t down) { - time_t now; + time_t now; + ngx_peer_t *peer; if (down) { now = ngx_time(); /* ngx_lock_mutex(pc->peers->mutex); */ - pc->peers->peer[pc->cur_peer].fails++; - pc->peers->peer[pc->cur_peer].accessed = now; + peer = &pc->peers->peer[pc->cur_peer]; + + peer->fails++; + peer->accessed = now; + + if (peer->current_weight > 1) { + peer->current_weight /= 2; + } /* ngx_unlock_mutex(pc->peers->mutex); */ } 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 @@ -92,6 +92,7 @@ ngx_http_access_handler(ngx_http_request ngx_uint_t i; struct sockaddr_in *sin; ngx_http_access_rule_t *rule; + ngx_http_core_loc_conf_t *clcf; ngx_http_access_loc_conf_t *alcf; alcf = ngx_http_get_module_loc_conf(r, ngx_http_access_module); @@ -113,8 +114,12 @@ ngx_http_access_handler(ngx_http_request if ((sin->sin_addr.s_addr & rule[i].mask) == rule[i].addr) { if (rule[i].deny) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "access forbidden by rule"); + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + if (!clcf->satisfy_any) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "access forbidden by rule"); + } return NGX_HTTP_FORBIDDEN; } diff --git a/src/http/modules/ngx_http_auth_basic_module.c b/src/http/modules/ngx_http_auth_basic_module.c --- a/src/http/modules/ngx_http_auth_basic_module.c +++ b/src/http/modules/ngx_http_auth_basic_module.c @@ -136,7 +136,7 @@ ngx_http_auth_basic_handler(ngx_http_req fd = ngx_open_file(alcf->user_file.data, NGX_FILE_RDONLY, NGX_FILE_OPEN); if (fd == NGX_INVALID_FILE) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, ngx_errno, + ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, ngx_open_file_n " \"%s\" failed", alcf->user_file.data); return NGX_HTTP_INTERNAL_SERVER_ERROR; } diff --git a/src/http/modules/ngx_http_charset_filter_module.c b/src/http/modules/ngx_http_charset_filter_module.c --- a/src/http/modules/ngx_http_charset_filter_module.c +++ b/src/http/modules/ngx_http_charset_filter_module.c @@ -188,7 +188,7 @@ ngx_http_charset_header_filter(ngx_http_ { u_char *ct; ngx_int_t charset, source_charset; - ngx_str_t *mc; + ngx_str_t *mc, *from, *to; ngx_uint_t n; ngx_http_charset_t *charsets; ngx_http_charset_ctx_t *ctx; @@ -288,13 +288,10 @@ ngx_http_charset_header_filter(ngx_http_ return ngx_http_next_header_filter(r); } - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "no \"charset_map\" between the charsets " - "\"%V\" and \"%V\"", - &charsets[lcf->source_charset].name, - &r->main->headers_out.charset); + from = &charsets[lcf->source_charset].name; + to = &r->main->headers_out.charset; - return ngx_http_next_header_filter(r); + goto no_charset_map; } source_charset = ngx_http_charset_get_charset(charsets, n, @@ -308,11 +305,12 @@ ngx_http_charset_header_filter(ngx_http_ r->headers_out.charset.data) != 0) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "no \"charset_map\" between the charsets " - "\"%V\" and \"%V\"", - &r->headers_out.charset, - &r->main->headers_out.charset); + from = &r->headers_out.charset; + to = (charset == NGX_HTTP_NO_CHARSET) ? + &r->main->headers_out.charset: + &charsets[charset].name; + + goto no_charset_map; } return ngx_http_next_header_filter(r); @@ -322,18 +320,24 @@ ngx_http_charset_header_filter(ngx_http_ && (charsets[source_charset].tables == NULL || charsets[source_charset].tables[charset] == NULL)) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "no \"charset_map\" between the charsets " - "\"%V\" and \"%V\"", - &charsets[source_charset].name, &charsets[charset].name); + from = &charsets[source_charset].name; + to = &charsets[charset].name; - return ngx_http_next_header_filter(r); + goto no_charset_map; } r->headers_out.content_type.len = r->headers_out.content_type_len; return ngx_http_charset_set_charset(r, mcf->charsets.elts, charset, source_charset); + +no_charset_map: + + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "no \"charset_map\" between the charsets " + "\"%V\" and \"%V\"", from, to); + + return ngx_http_next_header_filter(r); } @@ -392,12 +396,15 @@ ngx_http_charset_set_charset(ngx_http_re ctx->from_utf8 = charsets[source_charset].utf8; ctx->to_utf8 = charsets[charset].utf8; + r->filter_need_in_memory = 1; + if ((ctx->to_utf8 || ctx->from_utf8) && r == r->main) { ngx_http_clear_content_length(r); + + } else { + r->filter_need_temporary = 1; } - r->filter_need_in_memory = 1; - return ngx_http_next_header_filter(r); } diff --git a/src/http/modules/ngx_http_dav_module.c b/src/http/modules/ngx_http_dav_module.c --- a/src/http/modules/ngx_http_dav_module.c +++ b/src/http/modules/ngx_http_dav_module.c @@ -251,17 +251,20 @@ ngx_http_dav_put_handler(ngx_http_reques } else { status = NGX_HTTP_NO_CONTENT; - } + + if (ngx_is_dir(&fi)) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, NGX_EISDIR, + "\"%s\" could not be created", path.data); - if (ngx_is_dir(&fi)) { - if (ngx_delete_file(temp->data) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, - ngx_delete_file_n " \"%s\" failed", - temp->data); + if (ngx_delete_file(temp->data) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, + ngx_delete_file_n " \"%s\" failed", + temp->data); + } + + ngx_http_finalize_request(r, NGX_HTTP_CONFLICT); + return; } - - ngx_http_finalize_request(r, NGX_HTTP_CONFLICT); - return; } if (ngx_rename_file(temp->data, path.data) != NGX_FILE_ERROR) { diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -1565,6 +1565,7 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf uintptr_t *code; ngx_str_t *header; ngx_uint_t i, j; + ngx_peer_t *peer; ngx_array_t hide_headers; ngx_keyval_t *src; ngx_hash_key_t *hk; @@ -1693,20 +1694,23 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf |NGX_HTTP_UPSTREAM_FT_ERROR |NGX_HTTP_UPSTREAM_FT_TIMEOUT)); - ngx_conf_merge_unsigned_value(conf->upstream.max_fails, + ngx_conf_merge_uint_value(conf->upstream.max_fails, prev->upstream.max_fails, 1); ngx_conf_merge_sec_value(conf->upstream.fail_timeout, prev->upstream.fail_timeout, 10); - if (conf->upstream_peers && !conf->upstream_peers->balanced) { + if (conf->upstream_peers) { + peer = conf->upstream_peers->peers->peer; for (i = 0; i < conf->upstream_peers->peers->number; i++) { - conf->upstream_peers->peers->peer[i].weight = 1; - conf->upstream_peers->peers->peer[i].max_fails = - conf->upstream.max_fails; - conf->upstream_peers->peers->peer[i].fail_timeout = - conf->upstream.fail_timeout; + ngx_conf_init_uint_value(peer[i].weight, 1); + peer[i].current_weight = peer[i].weight; + ngx_conf_init_uint_value(peer[i].max_fails, + conf->upstream.max_fails); + ngx_conf_init_value(peer[i].fail_timeout, + conf->upstream.fail_timeout); } + } ngx_conf_merge_path_value(conf->upstream.temp_path, diff --git a/src/http/modules/ngx_http_gzip_filter_module.c b/src/http/modules/ngx_http_gzip_filter_module.c --- a/src/http/modules/ngx_http_gzip_filter_module.c +++ b/src/http/modules/ngx_http_gzip_filter_module.c @@ -1087,7 +1087,7 @@ ngx_http_gzip_merge_conf(ngx_conf_t *cf, ngx_conf_merge_bufs_value(conf->bufs, prev->bufs, 4, ngx_pagesize); - ngx_conf_merge_unsigned_value(conf->http_version, prev->http_version, + ngx_conf_merge_uint_value(conf->http_version, prev->http_version, NGX_HTTP_VERSION_11); ngx_conf_merge_bitmask_value(conf->proxied, prev->proxied, (NGX_CONF_BITMASK_SET|NGX_HTTP_GZIP_PROXIED_OFF)); diff --git a/src/http/modules/ngx_http_headers_filter_module.c b/src/http/modules/ngx_http_headers_filter_module.c --- a/src/http/modules/ngx_http_headers_filter_module.c +++ b/src/http/modules/ngx_http_headers_filter_module.c @@ -103,9 +103,12 @@ ngx_http_headers_filter(ngx_http_request ngx_http_header_val_t *h; ngx_http_headers_conf_t *conf; - if ((r->headers_out.status != NGX_HTTP_OK - && r->headers_out.status != NGX_HTTP_NOT_MODIFIED) - || r != r->main) + if (r != r->main + || (r->headers_out.status != NGX_HTTP_OK + && r->headers_out.status != NGX_HTTP_NO_CONTENT + && r->headers_out.status != NGX_HTTP_MOVED_PERMANENTLY + && r->headers_out.status != NGX_HTTP_MOVED_TEMPORARILY + && r->headers_out.status != NGX_HTTP_NOT_MODIFIED)) { return ngx_http_next_header_filter(r); } diff --git a/src/http/modules/ngx_http_log_module.c b/src/http/modules/ngx_http_log_module.c --- a/src/http/modules/ngx_http_log_module.c +++ b/src/http/modules/ngx_http_log_module.c @@ -478,7 +478,7 @@ static u_char * ngx_http_log_request_length(ngx_http_request_t *r, u_char *buf, ngx_http_log_op_t *op) { - return ngx_sprintf(buf, "%z", r->request_length); + return ngx_sprintf(buf, "%O", r->request_length); } diff --git a/src/http/modules/ngx_http_memcached_module.c b/src/http/modules/ngx_http_memcached_module.c --- a/src/http/modules/ngx_http_memcached_module.c +++ b/src/http/modules/ngx_http_memcached_module.c @@ -560,7 +560,7 @@ ngx_http_memcached_merge_loc_conf(ngx_co |NGX_HTTP_UPSTREAM_FT_ERROR |NGX_HTTP_UPSTREAM_FT_TIMEOUT)); - ngx_conf_merge_unsigned_value(conf->upstream.max_fails, + ngx_conf_merge_uint_value(conf->upstream.max_fails, prev->upstream.max_fails, 1); ngx_conf_merge_sec_value(conf->upstream.fail_timeout, 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 @@ -1520,6 +1520,7 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t uintptr_t *code; ngx_str_t *header; ngx_uint_t i, j; + ngx_peer_t *peer; ngx_array_t hide_headers; ngx_keyval_t *src, *s, *h; ngx_hash_key_t *hk; @@ -1647,19 +1648,21 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t |NGX_HTTP_UPSTREAM_FT_ERROR |NGX_HTTP_UPSTREAM_FT_TIMEOUT)); - ngx_conf_merge_unsigned_value(conf->upstream.max_fails, + ngx_conf_merge_uint_value(conf->upstream.max_fails, prev->upstream.max_fails, 1); ngx_conf_merge_sec_value(conf->upstream.fail_timeout, prev->upstream.fail_timeout, 10); - if (conf->upstream_peers && !conf->upstream_peers->balanced) { + if (conf->upstream_peers) { + peer = conf->upstream_peers->peers->peer; for (i = 0; i < conf->upstream_peers->peers->number; i++) { - conf->upstream_peers->peers->peer[i].weight = 1; - conf->upstream_peers->peers->peer[i].max_fails = - conf->upstream.max_fails; - conf->upstream_peers->peers->peer[i].fail_timeout = - conf->upstream.fail_timeout; + ngx_conf_init_uint_value(peer[i].weight, 1); + peer[i].current_weight = peer[i].weight; + ngx_conf_init_uint_value(peer[i].max_fails, + conf->upstream.max_fails); + ngx_conf_init_value(peer[i].fail_timeout, + conf->upstream.fail_timeout); } } 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 @@ -243,7 +243,7 @@ ngx_http_realip_merge_loc_conf(ngx_conf_ conf->from = prev->from; } - ngx_conf_merge_unsigned_value(conf->xfwd, prev->xfwd, 0); + ngx_conf_merge_uint_value(conf->xfwd, prev->xfwd, 0); return NGX_CONF_OK; } diff --git a/src/http/modules/ngx_http_rewrite_module.c b/src/http/modules/ngx_http_rewrite_module.c --- a/src/http/modules/ngx_http_rewrite_module.c +++ b/src/http/modules/ngx_http_rewrite_module.c @@ -245,7 +245,7 @@ ngx_http_rewrite_merge_loc_conf(ngx_conf ngx_conf_merge_value(conf->log, prev->log, 0); ngx_conf_merge_value(conf->uninitialized_variable_warn, prev->uninitialized_variable_warn, 1); - ngx_conf_merge_unsigned_value(conf->stack_size, prev->stack_size, 10); + ngx_conf_merge_uint_value(conf->stack_size, prev->stack_size, 10); if (conf->codes == NULL) { return NGX_CONF_OK; diff --git a/src/http/modules/ngx_http_userid_filter_module.c b/src/http/modules/ngx_http_userid_filter_module.c --- a/src/http/modules/ngx_http_userid_filter_module.c +++ b/src/http/modules/ngx_http_userid_filter_module.c @@ -670,8 +670,8 @@ ngx_http_userid_merge_conf(ngx_conf_t *c ngx_http_userid_conf_t *prev = parent; ngx_http_userid_conf_t *conf = child; - ngx_conf_merge_unsigned_value(conf->enable, prev->enable, - NGX_HTTP_USERID_OFF); + ngx_conf_merge_uint_value(conf->enable, prev->enable, + NGX_HTTP_USERID_OFF); ngx_conf_merge_str_value(conf->name, prev->name, "uid"); ngx_conf_merge_str_value(conf->domain, prev->domain, ""); diff --git a/src/http/modules/perl/ngx_http_perl_module.c b/src/http/modules/perl/ngx_http_perl_module.c --- a/src/http/modules/perl/ngx_http_perl_module.c +++ b/src/http/modules/perl/ngx_http_perl_module.c @@ -833,9 +833,9 @@ ngx_http_perl_init_main_conf(ngx_conf_t ngx_http_perl_main_conf_t *pmcf = conf; #if (NGX_HAVE_PERL_CLONE || NGX_HAVE_PERL_MULTIPLICITY) - ngx_conf_init_unsigned_value(pmcf->interp_max, 10); + ngx_conf_init_uint_value(pmcf->interp_max, 10); #else - ngx_conf_init_unsigned_value(pmcf->interp_max, 1); + ngx_conf_init_uint_value(pmcf->interp_max, 1); #endif pmcf->free_perls = ngx_pcalloc(cf->pool, 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 @@ -242,7 +242,7 @@ static ngx_command_t ngx_http_core_comm { ngx_string("client_max_body_size"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_size_slot, + ngx_conf_set_off_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_core_loc_conf_t, client_max_body_size), NULL }, @@ -634,6 +634,12 @@ ngx_http_core_run_phases(ngx_http_reques } if (r->phase == NGX_HTTP_ACCESS_PHASE && r->access_code) { + + if (r->access_code == NGX_HTTP_FORBIDDEN) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "access forbidden by rule"); + } + ngx_http_finalize_request(r, r->access_code); return; } @@ -690,15 +696,15 @@ ngx_http_find_location_config(ngx_http_r ngx_http_update_location_config(r); ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http cl:%z max:%uz", + "http cl:%O max:%O", r->headers_in.content_length_n, clcf->client_max_body_size); if (r->headers_in.content_length_n != -1 && clcf->client_max_body_size - && clcf->client_max_body_size < (size_t) r->headers_in.content_length_n) + && clcf->client_max_body_size < r->headers_in.content_length_n) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "client intented to send too large body: %z bytes", + "client intented to send too large body: %O bytes", r->headers_in.content_length_n); return NGX_HTTP_REQUEST_ENTITY_TOO_LARGE; @@ -2015,7 +2021,7 @@ ngx_http_core_create_loc_conf(ngx_conf_t * lcf->alias = 0; */ - lcf->client_max_body_size = NGX_CONF_UNSET_SIZE; + lcf->client_max_body_size = NGX_CONF_UNSET; lcf->client_body_buffer_size = NGX_CONF_UNSET_SIZE; lcf->client_body_timeout = NGX_CONF_UNSET_MSEC; lcf->satisfy_any = NGX_CONF_UNSET; @@ -2086,12 +2092,12 @@ ngx_http_core_merge_loc_conf(ngx_conf_t conf->post_action = prev->post_action; } - ngx_conf_merge_unsigned_value(conf->types_hash_max_size, - prev->types_hash_max_size, 1024); - - ngx_conf_merge_unsigned_value(conf->types_hash_bucket_size, - prev->types_hash_bucket_size, - ngx_cacheline_size); + ngx_conf_merge_uint_value(conf->types_hash_max_size, + prev->types_hash_max_size, 1024); + + ngx_conf_merge_uint_value(conf->types_hash_bucket_size, + prev->types_hash_bucket_size, + ngx_cacheline_size); conf->types_hash_bucket_size = ngx_align(conf->types_hash_bucket_size, ngx_cacheline_size); @@ -2175,7 +2181,7 @@ ngx_http_core_merge_loc_conf(ngx_conf_t ngx_conf_merge_str_value(conf->default_type, prev->default_type, "text/plain"); - ngx_conf_merge_size_value(conf->client_max_body_size, + ngx_conf_merge_off_value(conf->client_max_body_size, prev->client_max_body_size, 1 * 1024 * 1024); ngx_conf_merge_size_value(conf->client_body_buffer_size, prev->client_body_buffer_size, @@ -2451,6 +2457,11 @@ ngx_http_core_server_name(ngx_conf_t *cf ch = value[i].data[0]; + if (value[i].len == 1 && ch == '*') { + cscf->wildcard = 1; + continue; + } + if (value[i].len == 0 || (ch == '*' && (value[i].len < 3 || value[i].data[1] != '.')) || (ch == '.' && value[i].len < 2)) 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 @@ -116,6 +116,8 @@ typedef struct { ngx_flag_t optimize_server_names; ngx_flag_t ignore_invalid_headers; + + ngx_uint_t wildcard; /* unsigned wildcard:1 */ } ngx_http_core_srv_conf_t; @@ -213,7 +215,8 @@ struct ngx_http_core_loc_conf_s { ngx_hash_t types_hash; ngx_str_t default_type; - size_t client_max_body_size; /* client_max_body_size */ + off_t client_max_body_size; /* client_max_body_size */ + size_t client_body_buffer_size; /* client_body_buffer_size */ size_t send_lowat; /* send_lowat */ size_t postpone_output; /* postpone_output */ 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 @@ -84,7 +84,7 @@ static ngx_str_t ngx_http_status_lines[] ngx_string("406 Not Acceptable"), ngx_null_string, /* "407 Proxy Authentication Required" */ ngx_string("408 Request Time-out"), - ngx_null_string, /* "409 Conflict" */ + ngx_string("409 Conflict"), ngx_string("410 Gone"), ngx_string("411 Length Required"), ngx_null_string, /* "412 Precondition Failed" */ 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 @@ -1235,7 +1235,7 @@ ngx_http_process_request_header(ngx_http if (r->headers_in.content_length) { r->headers_in.content_length_n = - ngx_atosz(r->headers_in.content_length->value.data, + ngx_atoof(r->headers_in.content_length->value.data, r->headers_in.content_length->value.len); if (r->headers_in.content_length_n == NGX_ERROR) { @@ -1395,6 +1395,13 @@ ngx_http_find_virtual_server(ngx_http_re } } + cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); + + if (cscf->wildcard) { + r->server_name.len = len; + r->server_name.data = host; + } + return; found: 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 @@ -192,7 +192,7 @@ typedef struct { ngx_array_t cookies; size_t host_name_len; - ssize_t content_length_n; + off_t content_length_n; time_t keep_alive_n; unsigned connection_type:2; @@ -250,7 +250,7 @@ typedef struct { ngx_temp_file_t *temp_file; ngx_chain_t *bufs; ngx_buf_t *buf; - size_t rest; + off_t rest; ngx_chain_t *to_write; ngx_http_client_body_handler_pt post_handler; } ngx_http_request_body_t; @@ -366,7 +366,7 @@ struct ngx_http_request_s { /* used to learn the Apache compatible response length without a header */ size_t header_size; - size_t request_length; + off_t request_length; void **err_ctx; ngx_uint_t err_status; diff --git a/src/http/ngx_http_request_body.c b/src/http/ngx_http_request_body.c --- a/src/http/ngx_http_request_body.c +++ b/src/http/ngx_http_request_body.c @@ -30,7 +30,8 @@ ngx_int_t ngx_http_read_client_request_body(ngx_http_request_t *r, ngx_http_client_body_handler_pt post_handler) { - ssize_t size, preread; + size_t preread; + ssize_t size; ngx_buf_t *b; ngx_chain_t *cl, **next; ngx_http_request_body_t *rb; @@ -95,7 +96,7 @@ ngx_http_read_client_request_body(ngx_ht /* the whole request body was pre-read */ - r->header_in->pos += r->headers_in.content_length_n; + r->header_in->pos += (size_t) r->headers_in.content_length_n; r->request_length += r->headers_in.content_length_n; if (r->request_body_in_file_only) { @@ -143,8 +144,8 @@ ngx_http_read_client_request_body(ngx_ht size = clcf->client_body_buffer_size; size += size >> 2; - if (rb->rest < (size_t) size) { - size = rb->rest; + if (rb->rest < size) { + size = (ssize_t) rb->rest; if (r->request_body_in_single_buf) { size += preread; @@ -242,7 +243,7 @@ ngx_http_do_read_client_request_body(ngx size = rb->buf->end - rb->buf->last; if (size > rb->rest) { - size = rb->rest; + size = (size_t) rb->rest; } n = c->recv(c, rb->buf->last, size); @@ -429,7 +430,7 @@ ngx_http_discard_body(ngx_http_request_t r->headers_in.content_length_n -= size; } else { - r->header_in->pos += r->headers_in.content_length_n; + r->header_in->pos += (size_t) r->headers_in.content_length_n; r->headers_in.content_length_n = 0; return NGX_OK; } @@ -468,7 +469,8 @@ ngx_http_read_discarded_body_handler(ngx static ngx_int_t ngx_http_read_discarded_body(ngx_http_request_t *r) { - ssize_t size, n; + size_t size; + ssize_t n; u_char buffer[NGX_HTTP_DISCARD_BUFFER_SIZE]; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, @@ -478,12 +480,9 @@ ngx_http_read_discarded_body(ngx_http_re return NGX_OK; } - - size = r->headers_in.content_length_n; - - if (size > NGX_HTTP_DISCARD_BUFFER_SIZE) { - size = NGX_HTTP_DISCARD_BUFFER_SIZE; - } + size = (r->headers_in.content_length_n > NGX_HTTP_DISCARD_BUFFER_SIZE) ? + NGX_HTTP_DISCARD_BUFFER_SIZE: + (size_t) r->headers_in.content_length_n; n = r->connection->recv(r->connection, buffer, size); diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -226,7 +226,7 @@ static ngx_command_t ngx_http_upstream_ NULL }, { ngx_string("server"), - NGX_HTTP_UPS_CONF|NGX_CONF_TAKE1, + NGX_HTTP_UPS_CONF|NGX_CONF_TAKE12, ngx_http_upstream_server, NGX_HTTP_SRV_CONF_OFFSET, 0, @@ -2729,7 +2729,6 @@ ngx_http_upstream(ngx_conf_t *cf, ngx_co } uscf->peers->number = n; - uscf->peers->weight = 1; n = 0; @@ -2750,6 +2749,8 @@ ngx_http_upstream_server(ngx_conf_t *cf, ngx_str_t *value; ngx_url_t u; + ngx_int_t weight; + ngx_uint_t i; ngx_peers_t **peers; if (uscf->servers == NULL) { @@ -2780,9 +2781,41 @@ ngx_http_upstream_server(ngx_conf_t *cf, return NGX_CONF_ERROR; } + weight = 1; + + if (cf->args->nelts == 3) { + + value = &value[2]; + + if (ngx_strncmp(value->data, "weight=", 7) == 0) { + + weight = ngx_atoi(&value->data[7], value->len - 7); + + if (weight == NGX_ERROR || weight == 0) { + goto invalid; + } + + } else { + goto invalid; + } + } + + for (i = 0; i < u.peers->number; i++) { + u.peers->peer[i].weight = weight; + u.peers->peer[i].current_weight = weight; + u.peers->peer[i].max_fails = NGX_CONF_UNSET_UINT; + u.peers->peer[i].fail_timeout = NGX_CONF_UNSET; + } + *peers = u.peers; return NGX_CONF_OK; + +invalid: + + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid parameter \"%V\"", value); + + return NGX_CONF_ERROR; } @@ -2893,8 +2926,7 @@ ngx_http_upstream_init_main_conf(ngx_con } uscfp[i]->peers = ngx_inet_resolve_peer(cf, &uscfp[i]->host, - uscfp[i]->port); - + uscfp[i]->port); if (uscfp[i]->peers == NULL) { return NGX_CONF_ERROR; } @@ -2908,6 +2940,7 @@ ngx_http_upstream_init_main_conf(ngx_con } } + if (ngx_array_init(&headers_in, cf->temp_pool, 32, sizeof(ngx_hash_key_t)) != NGX_OK) { diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h --- a/src/http/ngx_http_upstream.h +++ b/src/http/ngx_http_upstream.h @@ -56,8 +56,6 @@ typedef struct { ngx_str_t file_name; ngx_uint_t line; in_port_t port; - - ngx_uint_t balanced; /* unsigned balanced:1; */ } ngx_http_upstream_srv_conf_t; diff --git a/src/imap/ngx_imap.h b/src/imap/ngx_imap.h --- a/src/imap/ngx_imap.h +++ b/src/imap/ngx_imap.h @@ -109,7 +109,7 @@ typedef enum { ngx_imap_start = 0, ngx_imap_login, ngx_imap_user, - ngx_imap_passwd, + ngx_imap_passwd } ngx_imap_state_e; diff --git a/src/imap/ngx_imap_core_module.c b/src/imap/ngx_imap_core_module.c --- a/src/imap/ngx_imap_core_module.c +++ b/src/imap/ngx_imap_core_module.c @@ -205,7 +205,7 @@ ngx_imap_core_merge_srv_conf(ngx_conf_t prev->imap_client_buffer_size, (size_t) ngx_pagesize); ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 60000); - ngx_conf_merge_unsigned_value(conf->protocol, prev->protocol, + ngx_conf_merge_uint_value(conf->protocol, prev->protocol, NGX_IMAP_IMAP_PROTOCOL); ngx_conf_merge_value(conf->so_keepalive, prev->so_keepalive, 0); diff --git a/src/imap/ngx_imap_proxy_module.c b/src/imap/ngx_imap_proxy_module.c --- a/src/imap/ngx_imap_proxy_module.c +++ b/src/imap/ngx_imap_proxy_module.c @@ -23,7 +23,7 @@ static void ngx_imap_proxy_imap_handler( static void ngx_imap_proxy_pop3_handler(ngx_event_t *rev); static void ngx_imap_proxy_dummy_handler(ngx_event_t *ev); static ngx_int_t ngx_imap_proxy_read_response(ngx_imap_session_t *s, - ngx_uint_t what); + ngx_uint_t state); static void ngx_imap_proxy_handler(ngx_event_t *ev); static void ngx_imap_proxy_internal_server_error(ngx_imap_session_t *s); static void ngx_imap_proxy_close_session(ngx_imap_session_t *s); @@ -32,10 +32,6 @@ static char *ngx_imap_proxy_merge_conf(n void *child); -#define NGX_IMAP_WAIT_OK 0 -#define NGX_IMAP_WAIT_NEXT 1 - - static ngx_command_t ngx_imap_proxy_commands[] = { { ngx_string("proxy"), @@ -201,8 +197,7 @@ ngx_imap_proxy_imap_handler(ngx_event_t } } - rc = ngx_imap_proxy_read_response(s, s->imap_state == ngx_imap_start ? - NGX_IMAP_WAIT_OK : NGX_IMAP_WAIT_NEXT); + rc = ngx_imap_proxy_read_response(s, s->imap_state); if (rc == NGX_AGAIN) { return; @@ -274,6 +269,23 @@ ngx_imap_proxy_imap_handler(ngx_event_t s->imap_state = ngx_imap_passwd; break; + case ngx_imap_passwd: + s->connection->read->handler = ngx_imap_proxy_handler; + s->connection->write->handler = ngx_imap_proxy_handler; + rev->handler = ngx_imap_proxy_handler; + c->write->handler = ngx_imap_proxy_handler; + + pcf = ngx_imap_get_module_srv_conf(s, ngx_imap_proxy_module); + ngx_add_timer(s->connection->read, pcf->timeout); + ngx_del_timer(c->read); + + c->log->action = NULL; + ngx_log_error(NGX_LOG_INFO, c->log, 0, "client logged in"); + + ngx_imap_proxy_handler(s->connection->write); + + return; + default: #if (NGX_SUPPRESS_WARN) line.len = 0; @@ -293,20 +305,6 @@ ngx_imap_proxy_imap_handler(ngx_event_t s->proxy->buffer->pos = s->proxy->buffer->start; s->proxy->buffer->last = s->proxy->buffer->start; - - if (s->imap_state == ngx_imap_passwd) { - s->connection->read->handler = ngx_imap_proxy_handler; - s->connection->write->handler = ngx_imap_proxy_handler; - rev->handler = ngx_imap_proxy_handler; - c->write->handler = ngx_imap_proxy_handler; - - pcf = ngx_imap_get_module_srv_conf(s, ngx_imap_proxy_module); - ngx_add_timer(s->connection->read, pcf->timeout); - ngx_del_timer(c->read); - - c->log->action = NULL; - ngx_log_error(NGX_LOG_INFO, c->log, 0, "client logged in"); - } } @@ -344,7 +342,7 @@ ngx_imap_proxy_pop3_handler(ngx_event_t } } - rc = ngx_imap_proxy_read_response(s, NGX_IMAP_WAIT_OK); + rc = ngx_imap_proxy_read_response(s, 0); if (rc == NGX_AGAIN) { return; @@ -395,6 +393,23 @@ ngx_imap_proxy_pop3_handler(ngx_event_t s->imap_state = ngx_pop3_passwd; break; + case ngx_pop3_passwd: + s->connection->read->handler = ngx_imap_proxy_handler; + s->connection->write->handler = ngx_imap_proxy_handler; + rev->handler = ngx_imap_proxy_handler; + c->write->handler = ngx_imap_proxy_handler; + + pcf = ngx_imap_get_module_srv_conf(s, ngx_imap_proxy_module); + ngx_add_timer(s->connection->read, pcf->timeout); + ngx_del_timer(c->read); + + c->log->action = NULL; + ngx_log_error(NGX_LOG_INFO, c->log, 0, "client logged in"); + + ngx_imap_proxy_handler(s->connection->write); + + return; + default: #if (NGX_SUPPRESS_WARN) line.len = 0; @@ -414,20 +429,6 @@ ngx_imap_proxy_pop3_handler(ngx_event_t s->proxy->buffer->pos = s->proxy->buffer->start; s->proxy->buffer->last = s->proxy->buffer->start; - - if (s->imap_state == ngx_pop3_passwd) { - s->connection->read->handler = ngx_imap_proxy_handler; - s->connection->write->handler = ngx_imap_proxy_handler; - rev->handler = ngx_imap_proxy_handler; - c->write->handler = ngx_imap_proxy_handler; - - pcf = ngx_imap_get_module_srv_conf(s, ngx_imap_proxy_module); - ngx_add_timer(s->connection->read, pcf->timeout); - ngx_del_timer(c->read); - - c->log->action = NULL; - ngx_log_error(NGX_LOG_INFO, c->log, 0, "client logged in"); - } } @@ -449,7 +450,7 @@ ngx_imap_proxy_dummy_handler(ngx_event_t static ngx_int_t -ngx_imap_proxy_read_response(ngx_imap_session_t *s, ngx_uint_t what) +ngx_imap_proxy_read_response(ngx_imap_session_t *s, ngx_uint_t state) { u_char *p; ssize_t n; @@ -496,15 +497,29 @@ ngx_imap_proxy_read_response(ngx_imap_se } } else { - if (what == NGX_IMAP_WAIT_OK) { + switch (state) { + + case ngx_imap_start: if (p[0] == '*' && p[1] == ' ' && p[2] == 'O' && p[3] == 'K') { return NGX_OK; } + break; - } else { + case ngx_imap_login: + case ngx_imap_user: if (p[0] == '+') { return NGX_OK; } + break; + + case ngx_imap_passwd: + if (ngx_strncmp(p, s->tag.data, s->tag.len) == 0) { + p += s->tag.len; + if (p[0] == 'O' && p[1] == 'K') { + return NGX_OK; + } + } + break; } } diff --git a/src/os/unix/ngx_errno.h b/src/os/unix/ngx_errno.h --- a/src/os/unix/ngx_errno.h +++ b/src/os/unix/ngx_errno.h @@ -24,6 +24,7 @@ typedef int ngx_err_t; #define NGX_EBUSY EBUSY #define NGX_EEXIST EEXIST #define NGX_ENOTDIR ENOTDIR +#define NGX_EISDIR EISDIR #define NGX_EINVAL EINVAL #define NGX_ENOSPC ENOSPC #define NGX_EPIPE EPIPE