# HG changeset patch # User Igor Sysoev # Date 1176926400 -14400 # Node ID 2ceaee987f3725ee05ff7bbcf8f70e84b74beb9f # Parent 65b7ac8795e387bafd6a21d08e68d313d985fc58 nginx 0.5.18 *) Feature: the ngx_http_sub_filter_module. *) Feature: the "$upstream_http_..." variables. *) Feature: now the $upstream_status and $upstream_response_time variables keep data about all upstreams before X-Accel-Redirect. *) Bugfix: a segmentation fault occurred in master process after first reconfiguration and receiving any signal if nginx was built with ngx_http_perl_module and perl did not support multiplicity; bug appeared in 0.5.9. *) Bugfix: if perl did not support multiplicity, then after reconfiguration perl code did not work; bug appeared in 0.3.38. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,22 @@ +Changes with nginx 0.5.18 19 Apr 2007 + + *) Feature: the ngx_http_sub_filter_module. + + *) Feature: the "$upstream_http_..." variables. + + *) Feature: now the $upstream_status and $upstream_response_time + variables keep data about all upstreams before X-Accel-Redirect. + + *) Bugfix: a segmentation fault occurred in master process after first + reconfiguration and receiving any signal if nginx was built with + ngx_http_perl_module and perl did not support multiplicity; bug + appeared in 0.5.9. + + *) Bugfix: if perl did not support multiplicity, then after + reconfiguration perl code did not work; bug appeared in 0.3.38. + + Changes with nginx 0.5.17 02 Apr 2007 *) Change: now nginx always returns the 405 status for the TRACE method. diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,23 @@ +Изменения в nginx 0.5.18 19.04.2007 + + *) Добавление: модуль ngx_http_sub_filter_module. + + *) Добавление: переменные "$upstream_http_...". + + *) Добавление: теперь переменные $upstream_status и + $upstream_response_time содержат данные о всех обращениях к + апстримам, сделанным до X-Accel-Redirect. + + *) Исправление: если nginx был собран с модулем ngx_http_perl_module и + perl не поддерживал multiplicity, то после первой переконфигурации и + после получения любого сигнала в основном процессе происходил + segmentation fault; ошибка появилась в 0.5.9. + + *) Исправление: если perl не поддерживал multiplicity, то после + переконфигурации перловый код не работал; ошибка появилась в 0.3.38. + + Изменения в nginx 0.5.17 02.04.2007 *) Изменение: теперь nginx для метода TRACE всегда возвращает код 405. diff --git a/auto/cc/icc b/auto/cc/icc --- a/auto/cc/icc +++ b/auto/cc/icc @@ -5,7 +5,7 @@ # Intel C++ compiler 7.1, 8.0, 8.1, 9.0 NGX_ICC_VER=`$CC -V 2>&1 | grep 'Version' 2>&1 \ - | sed -e 's/^.* Version \(.*\) Build.*$/\1/'` + | sed -e 's/^.* Version \([^ ]*\) *Build.*$/\1/'` echo " + icc version: $NGX_ICC_VER" @@ -26,6 +26,11 @@ case "$NGX_ICC_VER" in IPO="-ipo" ;; + # 8.1.38 under FreeBSD can not link -ipo + 8.1) + IPO="-ip" + ;; + *) IPO="-ipo -ipo_obj" ;; diff --git a/auto/lib/pcre/make b/auto/lib/pcre/make --- a/auto/lib/pcre/make +++ b/auto/lib/pcre/make @@ -53,14 +53,16 @@ END *) cat << END >> $NGX_MAKEFILE -$PCRE/pcre.h: $NGX_MAKEFILE +$PCRE/pcre.h: $PCRE/Makefile + +$PCRE/Makefile: $NGX_MAKEFILE cd $PCRE \\ && if [ -f Makefile ]; then \$(MAKE) distclean; fi \\ && CC="\$(CC)" CFLAGS="$PCRE_OPT" \\ ./configure --disable-shared -$PCRE/.libs/libpcre.a: $PCRE/pcre.h +$PCRE/.libs/libpcre.a: $PCRE/Makefile cd $PCRE \\ && \$(MAKE) libpcre.la diff --git a/auto/modules b/auto/modules --- a/auto/modules +++ b/auto/modules @@ -129,6 +129,11 @@ if [ $HTTP_SSI = YES ]; then HTTP_SRCS="$HTTP_SRCS $HTTP_SSI_SRCS" fi +if [ $HTTP_SUB = YES ]; then + HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_SUB_FILTER_MODULE" + HTTP_SRCS="$HTTP_SRCS $HTTP_SUB_SRCS" +fi + if [ $HTTP_ADDITION = YES ]; then HTTP_FILTER_MODULES="$HTTP_FILTER_MODULES $HTTP_ADDITION_FILTER_MODULE" HTTP_SRCS="$HTTP_SRCS $HTTP_ADDITION_SRCS" diff --git a/auto/options b/auto/options --- a/auto/options +++ b/auto/options @@ -53,6 +53,7 @@ HTTP_SSL=NO HTTP_SSI=YES HTTP_POSTPONE=NO HTTP_REALIP=NO +HTTP_SUB=NO HTTP_ADDITION=NO HTTP_DAV=NO HTTP_ACCESS=YES @@ -152,6 +153,7 @@ do --with-http_ssl_module) HTTP_SSL=YES ;; --with-http_realip_module) HTTP_REALIP=YES ;; --with-http_addition_module) HTTP_ADDITION=YES ;; + --with-http_sub_module) HTTP_SUB=YES ;; --with-http_dav_module) HTTP_DAV=YES ;; --with-http_flv_module) HTTP_FLV=YES ;; @@ -259,6 +261,7 @@ cat << END --with-http_ssl_module enable ngx_http_ssl_module --with-http_realip_module enable ngx_http_realip_module --with-http_addition_module enable ngx_http_addition_module + --with-http_sub_module enable ngx_http_sub_module --with-http_dav_module enable ngx_http_dav_module --with-http_flv_module enable ngx_http_flv_module diff --git a/auto/sources b/auto/sources --- a/auto/sources +++ b/auto/sources @@ -317,6 +317,10 @@ HTTP_SSI_DEPS=src/http/modules/ngx_http_ HTTP_SSI_SRCS=src/http/modules/ngx_http_ssi_filter_module.c +HTTP_SUB_FILTER_MODULE=ngx_http_sub_filter_module +HTTP_SUB_SRCS=src/http/modules/ngx_http_sub_filter_module.c + + HTTP_USERID_FILTER_MODULE=ngx_http_userid_filter_module HTTP_USERID_SRCS=src/http/modules/ngx_http_userid_filter_module.c 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.5.17" +#define NGINX_VERSION "0.5.18" #define NGINX_VER "nginx/" NGINX_VERSION #define NGINX_VAR "NGINX" diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c --- a/src/core/ngx_cycle.c +++ b/src/core/ngx_cycle.c @@ -54,11 +54,8 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) ngx_list_part_t *part, *opart; ngx_open_file_t *file; ngx_listening_t *ls, *nls; - ngx_core_conf_t *ccf; + ngx_core_conf_t *ccf, *old_ccf; ngx_core_module_t *module; -#if !(WIN32) - ngx_core_conf_t *old_ccf; -#endif log = old_cycle->log; @@ -747,6 +744,14 @@ old_shm_zone_done: failed: + if (!ngx_is_init_cycle(old_cycle)) { + old_ccf = (ngx_core_conf_t *) ngx_get_conf(old_cycle->conf_ctx, + ngx_core_module); + if (old_ccf->environment) { + environ = old_ccf->environment; + } + } + /* rollback the new cycle configuration */ part = &cycle->open_files.part; diff --git a/src/core/ngx_regex.h b/src/core/ngx_regex.h --- a/src/core/ngx_regex.h +++ b/src/core/ngx_regex.h @@ -22,10 +22,10 @@ typedef pcre ngx_regex_t; void ngx_regex_init(void); ngx_regex_t *ngx_regex_compile(ngx_str_t *pattern, ngx_int_t options, - ngx_pool_t *pool, ngx_str_t *err); + ngx_pool_t *pool, ngx_str_t *err); ngx_int_t ngx_regex_capture_count(ngx_regex_t *re); -ngx_int_t ngx_regex_exec(ngx_regex_t *re, ngx_str_t *s, - int *captures, ngx_int_t size); +ngx_int_t ngx_regex_exec(ngx_regex_t *re, ngx_str_t *s, int *captures, + ngx_int_t size); #define ngx_regex_exec_n "pcre_exec()" #define ngx_regex_capture_count_n "pcre_fullinfo()" 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 @@ -585,7 +585,7 @@ destination_done: if (depth != 0 && depth != NGX_HTTP_DAV_INFINITY_DEPTH) { return NGX_HTTP_BAD_REQUEST; } - + over = r->headers_in.overwrite; if (over) { @@ -1003,7 +1003,7 @@ static ngx_int_t ngx_http_dav_depth(ngx_http_request_t *r, ngx_int_t dflt) { ngx_table_elt_t *depth; - + depth = r->headers_in.depth; if (depth == NULL) { 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 @@ -302,7 +302,7 @@ ngx_http_log_write(ngx_http_request_t *r log->disk_full_time = now; } - if (now - log->error_log_time > 60) { + if (now - log->error_log_time > 59) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, err, ngx_write_fd_n " to \"%V\" failed", &log->file->name); @@ -313,7 +313,7 @@ ngx_http_log_write(ngx_http_request_t *r return; } - if (now - log->error_log_time > 60) { + if (now - log->error_log_time > 59) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, ngx_write_fd_n " to \"%V\" was incomplete: %z of %uz", &log->file->name, n, len); diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c --- a/src/http/modules/ngx_http_ssi_filter_module.c +++ b/src/http/modules/ngx_http_ssi_filter_module.c @@ -107,8 +107,8 @@ static char *ngx_http_ssi_types(ngx_conf static ngx_int_t ngx_http_ssi_preconfiguration(ngx_conf_t *cf); static void *ngx_http_ssi_create_main_conf(ngx_conf_t *cf); static char *ngx_http_ssi_init_main_conf(ngx_conf_t *cf, void *conf); -static void *ngx_http_ssi_create_conf(ngx_conf_t *cf); -static char *ngx_http_ssi_merge_conf(ngx_conf_t *cf, +static void *ngx_http_ssi_create_loc_conf(ngx_conf_t *cf); +static char *ngx_http_ssi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child); static ngx_int_t ngx_http_ssi_filter_init(ngx_conf_t *cf); @@ -173,8 +173,8 @@ static ngx_http_module_t ngx_http_ssi_f NULL, /* create server configuration */ NULL, /* merge server configuration */ - ngx_http_ssi_create_conf, /* create location configuration */ - ngx_http_ssi_merge_conf /* merge location configuration */ + ngx_http_ssi_create_loc_conf, /* create location configuration */ + ngx_http_ssi_merge_loc_conf /* merge location configuration */ }; @@ -2746,7 +2746,7 @@ ngx_http_ssi_init_main_conf(ngx_conf_t * static void * -ngx_http_ssi_create_conf(ngx_conf_t *cf) +ngx_http_ssi_create_loc_conf(ngx_conf_t *cf) { ngx_http_ssi_loc_conf_t *slcf; @@ -2773,7 +2773,7 @@ ngx_http_ssi_create_conf(ngx_conf_t *cf) static char * -ngx_http_ssi_merge_conf(ngx_conf_t *cf, void *parent, void *child) +ngx_http_ssi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) { ngx_http_ssi_loc_conf_t *prev = parent; ngx_http_ssi_loc_conf_t *conf = child; diff --git a/src/http/modules/ngx_http_sub_filter_module.c b/src/http/modules/ngx_http_sub_filter_module.c new file mode 100644 --- /dev/null +++ b/src/http/modules/ngx_http_sub_filter_module.c @@ -0,0 +1,794 @@ + +/* + * Copyright (C) Igor Sysoev + */ + + +#include +#include +#include + + +typedef struct { + ngx_str_t match; + ngx_str_t sub; + + ngx_array_t *types; /* array of ngx_str_t */ + + ngx_array_t *sub_lengths; + ngx_array_t *sub_values; + + ngx_flag_t once; +} ngx_http_sub_loc_conf_t; + + +typedef enum { + sub_start_state = 0, + sub_match_state, +} ngx_http_sub_state_e; + + +typedef struct { + ngx_str_t match; + + ngx_uint_t once; /* unsigned once:1 */ + + ngx_buf_t *buf; + + u_char *pos; + u_char *copy_start; + u_char *copy_end; + + ngx_chain_t *in; + ngx_chain_t *out; + ngx_chain_t **last_out; + ngx_chain_t *busy; + ngx_chain_t *free; + + ngx_str_t sub; + + ngx_uint_t state; + size_t saved; + size_t looked; +} ngx_http_sub_ctx_t; + + +static ngx_int_t ngx_http_sub_output(ngx_http_request_t *r, + ngx_http_sub_ctx_t *ctx); +static ngx_int_t ngx_http_sub_parse(ngx_http_request_t *r, + ngx_http_sub_ctx_t *ctx); + +static char * ngx_http_sub_filter(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); +static char *ngx_http_sub_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +static void *ngx_http_sub_create_conf(ngx_conf_t *cf); +static char *ngx_http_sub_merge_conf(ngx_conf_t *cf, + void *parent, void *child); +static ngx_int_t ngx_http_sub_filter_init(ngx_conf_t *cf); + + +static ngx_command_t ngx_http_sub_filter_commands[] = { + + { ngx_string("sub_filter"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE2, + ngx_http_sub_filter, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("sub_filter_types"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_1MORE, + ngx_http_sub_types, + NGX_HTTP_LOC_CONF_OFFSET, + 0, + NULL }, + + { ngx_string("sub_filter_once"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_sub_loc_conf_t, once), + NULL }, + + ngx_null_command +}; + + +static ngx_http_module_t ngx_http_sub_filter_module_ctx = { + NULL, /* preconfiguration */ + ngx_http_sub_filter_init, /* postconfiguration */ + + NULL, /* create main configuration */ + NULL, /* init main configuration */ + + NULL, /* create server configuration */ + NULL, /* merge server configuration */ + + ngx_http_sub_create_conf, /* create location configuration */ + ngx_http_sub_merge_conf /* merge location configuration */ +}; + + +ngx_module_t ngx_http_sub_filter_module = { + NGX_MODULE_V1, + &ngx_http_sub_filter_module_ctx, /* module context */ + ngx_http_sub_filter_commands, /* module directives */ + NGX_HTTP_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + + +static ngx_http_output_header_filter_pt ngx_http_next_header_filter; +static ngx_http_output_body_filter_pt ngx_http_next_body_filter; + + +static ngx_int_t +ngx_http_sub_header_filter(ngx_http_request_t *r) +{ + ngx_str_t *type; + ngx_uint_t i; + ngx_http_sub_ctx_t *ctx; + ngx_http_sub_loc_conf_t *slcf; + + slcf = ngx_http_get_module_loc_conf(r, ngx_http_sub_filter_module); + + if (slcf->match.len == 0 + || r->headers_out.content_type.len == 0 + || r->headers_out.content_length_n == 0) + { + return ngx_http_next_header_filter(r); + } + + type = slcf->types->elts; + for (i = 0; i < slcf->types->nelts; i++) { + if (r->headers_out.content_type.len >= type[i].len + && ngx_strncasecmp(r->headers_out.content_type.data, + type[i].data, type[i].len) == 0) + { + goto found; + } + } + + return ngx_http_next_header_filter(r); + +found: + + ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_sub_ctx_t)); + if (ctx == NULL) { + return NGX_ERROR; + } + + ngx_http_set_ctx(r, ctx, ngx_http_sub_filter_module); + + ctx->match = slcf->match; + ctx->last_out = &ctx->out; + ctx->sub = slcf->sub; + + r->filter_need_in_memory = 1; + + if (r == r->main) { + ngx_http_clear_content_length(r); + ngx_http_clear_last_modified(r); + } + + return ngx_http_next_header_filter(r); +} + + +static ngx_int_t +ngx_http_sub_body_filter(ngx_http_request_t *r, ngx_chain_t *in) +{ + ngx_int_t rc; + ngx_buf_t *b; + ngx_chain_t *cl; + ngx_http_sub_ctx_t *ctx; + ngx_http_sub_loc_conf_t *slcf; + + ctx = ngx_http_get_module_ctx(r, ngx_http_sub_filter_module); + + if (ctx == NULL) { + return ngx_http_next_body_filter(r, in); + } + + if ((in == NULL + && ctx->buf == NULL + && ctx->in == NULL + && ctx->busy == NULL)) + { + return ngx_http_next_body_filter(r, in); + } + + if (ctx->once && (ctx->buf == NULL || ctx->in == NULL)) { + + if (ctx->busy) { + if (ngx_http_sub_output(r, ctx) == NGX_ERROR) { + return NGX_ERROR; + } + } + + return ngx_http_next_body_filter(r, in); + } + + /* add the incoming chain to the chain ctx->in */ + + if (in) { + if (ngx_chain_add_copy(r->pool, &ctx->in, in) == NGX_ERROR) { + return NGX_ERROR; + } + } + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http sub filter \"%V\"", &r->uri); + + while (ctx->in || ctx->buf) { + + if (ctx->buf == NULL ){ + ctx->buf = ctx->in->buf; + ctx->in = ctx->in->next; + ctx->pos = ctx->buf->pos; + } + + if (ctx->state == sub_start_state) { + ctx->copy_start = ctx->pos; + ctx->copy_end = ctx->pos; + } + + b = NULL; + + while (ctx->pos < ctx->buf->last) { + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "saved: %d state: %d", ctx->saved, ctx->state); + + rc = ngx_http_sub_parse(r, ctx); + + ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "parse: %d, looked: %d %p-%p", + rc, ctx->looked, ctx->copy_start, ctx->copy_end); + + if (rc == NGX_ERROR) { + return rc; + } + + if (ctx->copy_start != ctx->copy_end) { + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "saved: %d", ctx->saved); + + if (ctx->saved) { + + if (ctx->free) { + cl = ctx->free; + ctx->free = ctx->free->next; + b = cl->buf; + ngx_memzero(b, sizeof(ngx_buf_t)); + + } else { + b = ngx_calloc_buf(r->pool); + if (b == NULL) { + return NGX_ERROR; + } + + cl = ngx_alloc_chain_link(r->pool); + if (cl == NULL) { + return NGX_ERROR; + } + + cl->buf = b; + } + + b->memory = 1; + b->pos = ctx->match.data; + b->last = ctx->match.data + ctx->saved; + + *ctx->last_out = cl; + ctx->last_out = &cl->next; + + ctx->saved = 0; + } + + if (ctx->free) { + cl = ctx->free; + ctx->free = ctx->free->next; + b = cl->buf; + + } else { + b = ngx_alloc_buf(r->pool); + if (b == NULL) { + return NGX_ERROR; + } + + cl = ngx_alloc_chain_link(r->pool); + if (cl == NULL) { + return NGX_ERROR; + } + + cl->buf = b; + } + + ngx_memcpy(b, ctx->buf, sizeof(ngx_buf_t)); + + b->pos = ctx->copy_start; + b->last = ctx->copy_end; + b->shadow = NULL; + b->last_buf = 0; + b->recycled = 0; + + if (b->in_file) { + b->file_last = b->file_pos + (b->last - b->start); + b->file_pos += b->pos - b->start; + } + + cl->next = NULL; + *ctx->last_out = cl; + ctx->last_out = &cl->next; + } + + if (ctx->state == sub_start_state) { + ctx->copy_start = ctx->pos; + ctx->copy_end = ctx->pos; + + } else { + ctx->copy_start = NULL; + ctx->copy_end = NULL; + } + + if (rc == NGX_AGAIN) { + continue; + } + + + /* rc == NGX_OK */ + + b = ngx_calloc_buf(r->pool); + if (b == NULL) { + return NGX_ERROR; + } + + cl = ngx_alloc_chain_link(r->pool); + if (cl == NULL) { + return NGX_ERROR; + } + + slcf = ngx_http_get_module_loc_conf(r, ngx_http_sub_filter_module); + + if (ctx->sub.data == NULL) { + + if (ngx_http_script_run(r, &ctx->sub, slcf->sub_lengths->elts, + 0, slcf->sub_values->elts) + == NULL) + { + return NGX_ERROR; + } + } + + b->memory = 1; + b->pos = ctx->sub.data; + b->last = ctx->sub.data + ctx->sub.len; + + cl->buf = b; + cl->next = NULL; + *ctx->last_out = cl; + ctx->last_out = &cl->next; + + ctx->once = slcf->once; + + continue; + } + + if (ctx->buf->last_buf || ngx_buf_in_memory(ctx->buf)) { + if (b == NULL) { + if (ctx->free) { + cl = ctx->free; + ctx->free = ctx->free->next; + b = cl->buf; + ngx_memzero(b, sizeof(ngx_buf_t)); + + } else { + b = ngx_calloc_buf(r->pool); + if (b == NULL) { + return NGX_ERROR; + } + + cl = ngx_alloc_chain_link(r->pool); + if (cl == NULL) { + return NGX_ERROR; + } + + cl->buf = b; + } + + b->sync = 1; + + cl->next = NULL; + *ctx->last_out = cl; + ctx->last_out = &cl->next; + } + + b->last_buf = ctx->buf->last_buf; + b->shadow = ctx->buf; + + b->recycled = ctx->buf->recycled; + } + + ctx->buf = NULL; + + ctx->saved = ctx->looked; + } + + if (ctx->out == NULL && ctx->busy == NULL) { + return NGX_OK; + } + + return ngx_http_sub_output(r, ctx); +} + + +static ngx_int_t +ngx_http_sub_output(ngx_http_request_t *r, ngx_http_sub_ctx_t *ctx) +{ + ngx_int_t rc; + ngx_buf_t *b; + ngx_chain_t *cl; + +#if 1 + b = NULL; + for (cl = ctx->out; cl; cl = cl->next) { + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "sub out: %p %p", cl->buf, cl->buf->pos); + if (cl->buf == b) { + ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, + "the same buf was used in sub"); + ngx_debug_point(); + return NGX_ERROR; + } + b = cl->buf; + } +#endif + + rc = ngx_http_next_body_filter(r, ctx->out); + + if (ctx->busy == NULL) { + ctx->busy = ctx->out; + + } else { + for (cl = ctx->busy; cl->next; cl = cl->next) { /* void */ } + cl->next = ctx->out; + } + + ctx->out = NULL; + ctx->last_out = &ctx->out; + + while (ctx->busy) { + + cl = ctx->busy; + b = cl->buf; + + if (ngx_buf_size(b) != 0) { + break; + } + +#if (NGX_HAVE_WRITE_ZEROCOPY) + if (b->zerocopy_busy) { + break; + } +#endif + + if (b->shadow) { + b->shadow->pos = b->shadow->last; + } + + ctx->busy = cl->next; + + if (ngx_buf_in_memory(b) || b->in_file) { + /* add data bufs only to the free buf chain */ + + cl->next = ctx->free; + ctx->free = cl; + } + } + + if (ctx->in || ctx->buf) { + r->buffered |= NGX_HTTP_SUB_BUFFERED; + + } else { + r->buffered &= ~NGX_HTTP_SUB_BUFFERED; + } + + return rc; +} + + +static ngx_int_t +ngx_http_sub_parse(ngx_http_request_t *r, ngx_http_sub_ctx_t *ctx) +{ + u_char *p, *last, *copy_end, ch, match; + size_t looked; + ngx_http_sub_state_e state; + + if (ctx->once) { + ctx->copy_start = ctx->pos; + ctx->copy_end = ctx->buf->last; + ctx->pos = ctx->buf->last; + ctx->looked = 0; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "once"); + + return NGX_AGAIN; + } + + state = ctx->state; + looked = ctx->looked; + last = ctx->buf->last; + copy_end = ctx->copy_end; + + for (p = ctx->pos; p < last; p++) { + + ch = *p; + ch = ngx_tolower(ch); + + if (state == sub_start_state) { + + /* the tight loop */ + + match = ctx->match.data[0]; + + for ( ;; ) { + if (ch == match) { + copy_end = p; + looked = 1; + state = sub_match_state; + + goto match_started; + } + + if (++p == last) { + break; + } + + ch = *p; + ch = ngx_tolower(ch); + } + + ctx->pos = p; + ctx->looked = looked; + ctx->copy_end = p; + + if (ctx->copy_start == NULL) { + ctx->copy_start = ctx->buf->pos; + } + + return NGX_AGAIN; + + match_started: + + continue; + } + + /* state == sub_match_state */ + + if (ch == ctx->match.data[looked]) { + looked++; + + if (looked == ctx->match.len) { + ctx->state = sub_start_state; + ctx->pos = p + 1; + ctx->looked = looked; + ctx->copy_end = copy_end; + + if (ctx->copy_start == NULL && copy_end) { + ctx->copy_start = ctx->buf->pos; + } + + return NGX_OK; + } + + } else if (ch == ctx->match.data[0]) { + copy_end = p; + looked = 1; + + } else { + copy_end = p; + looked = 0; + state = sub_start_state; + } + } + + ctx->state = state; + ctx->pos = p; + ctx->looked = looked; + + ctx->copy_end = (state == sub_start_state) ? p : copy_end; + + if (ctx->copy_start == NULL && ctx->copy_end) { + ctx->copy_start = ctx->buf->pos; + } + + return NGX_AGAIN; +} + + +static char * +ngx_http_sub_filter(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_http_sub_loc_conf_t *slcf = conf; + + ngx_str_t *value; + ngx_int_t n; + ngx_uint_t i; + ngx_http_script_compile_t sc; + + if (slcf->match.len) { + return "is duplicate"; + } + + value = cf->args->elts; + + slcf->match = value[1]; + + for (i = 0; i < value[1].len; i++) { + value[1].data[i] = ngx_tolower(value[1].data[i]); + } + + n = ngx_http_script_variables_count(&value[2]); + + if (n == 0) { + slcf->sub = value[2]; + return NGX_CONF_OK; + } + + ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); + + sc.cf = cf; + sc.source = &value[2]; + sc.lengths = &slcf->sub_lengths; + sc.values = &slcf->sub_values; + sc.variables = n; + sc.complete_lengths = 1; + sc.complete_values = 1; + + if (ngx_http_script_compile(&sc) != NGX_OK) { + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; +} + + +static char * +ngx_http_sub_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_http_sub_loc_conf_t *slcf = conf; + + ngx_str_t *value, *type; + ngx_uint_t i; + + if (slcf->types == NULL) { + slcf->types = ngx_array_create(cf->pool, 4, sizeof(ngx_str_t)); + if (slcf->types == NULL) { + return NGX_CONF_ERROR; + } + + type = ngx_array_push(slcf->types); + if (type == NULL) { + return NGX_CONF_ERROR; + } + + type->len = sizeof("text/html") - 1; + type->data = (u_char *) "text/html"; + } + + value = cf->args->elts; + + for (i = 1; i < cf->args->nelts; i++) { + + if (ngx_strcmp(value[i].data, "text/html") == 0) { + continue; + } + + type = ngx_array_push(slcf->types); + if (type == NULL) { + return NGX_CONF_ERROR; + } + + type->len = value[i].len; + + type->data = ngx_palloc(cf->pool, type->len + 1); + if (type->data == NULL) { + return NGX_CONF_ERROR; + } + + ngx_cpystrn(type->data, value[i].data, type->len + 1); + } + + return NGX_CONF_OK; +} + + +static void * +ngx_http_sub_create_conf(ngx_conf_t *cf) +{ + ngx_http_sub_loc_conf_t *slcf; + + slcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_sub_loc_conf_t)); + if (slcf == NULL) { + return NGX_CONF_ERROR; + } + + /* + * set by ngx_pcalloc(): + * + * conf->match.len = 0; + * conf->match.data = NULL; + * conf->sub.len = 0; + * conf->sub.data = NULL; + * conf->sub_lengths = NULL; + * conf->sub_values = NULL; + * conf->types = NULL; + */ + + slcf->once = NGX_CONF_UNSET; + + return slcf; +} + + +static char * +ngx_http_sub_merge_conf(ngx_conf_t *cf, void *parent, void *child) +{ + ngx_http_sub_loc_conf_t *prev = parent; + ngx_http_sub_loc_conf_t *conf = child; + + ngx_str_t *type; + + ngx_conf_merge_value(conf->once, prev->once, 1); + ngx_conf_merge_str_value(conf->match, prev->match, ""); + + if (conf->sub.data == NULL && conf->sub_lengths == NULL) { + conf->sub = prev->sub; + conf->sub_lengths = prev->sub_lengths; + conf->sub_values = prev->sub_values; + } + + if (conf->types == NULL) { + if (prev->types == NULL) { + conf->types = ngx_array_create(cf->pool, 1, sizeof(ngx_str_t)); + if (conf->types == NULL) { + return NGX_CONF_ERROR; + } + + type = ngx_array_push(conf->types); + if (type == NULL) { + return NGX_CONF_ERROR; + } + + type->len = sizeof("text/html") - 1; + type->data = (u_char *) "text/html"; + + } else { + conf->types = prev->types; + } + } + + return NGX_CONF_OK; +} + + +static ngx_int_t +ngx_http_sub_filter_init(ngx_conf_t *cf) +{ + ngx_http_next_header_filter = ngx_http_top_header_filter; + ngx_http_top_header_filter = ngx_http_sub_header_filter; + + ngx_http_next_body_filter = ngx_http_top_body_filter; + ngx_http_top_body_filter = ngx_http_sub_body_filter; + + 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.5.17'; +our $VERSION = '0.5.18'; require XSLoader; XSLoader::load('nginx', $VERSION); 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 @@ -459,6 +459,11 @@ ngx_http_perl_init_interpreter(ngx_conf_ #if !(NGX_HAVE_PERL_MULTIPLICITY) if (perl) { + + if (ngx_set_environment(cf->cycle, NULL) == NULL) { + return NGX_CONF_ERROR; + } + if (ngx_http_perl_run_requires(aTHX_ &pmcf->requires, cf->log) != NGX_OK) { @@ -466,6 +471,7 @@ ngx_http_perl_init_interpreter(ngx_conf_ } pmcf->perl = perl; + pmcf->nginx = nginx_stash; return NGX_CONF_OK; } 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 @@ -124,7 +124,8 @@ #define NGX_HTTP_WRITE_BUFFERED 0x10 #define NGX_HTTP_GZIP_BUFFERED 0x20 #define NGX_HTTP_SSI_BUFFERED 0x01 -#define NGX_HTTP_COPY_BUFFERED 0x02 +#define NGX_HTTP_SUB_BUFFERED 0x02 +#define NGX_HTTP_COPY_BUFFERED 0x04 typedef enum { @@ -329,6 +330,8 @@ struct ngx_http_request_s { ngx_http_cache_t *cache; ngx_http_upstream_t *upstream; + ngx_array_t *upstream_states; + /* of ngx_http_upstream_state_t */ ngx_pool_t *pool; ngx_buf_t *header_in; 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 @@ -328,12 +328,25 @@ ngx_http_upstream_init(ngx_http_request_ u->writer.pool = r->pool; - if (ngx_array_init(&u->states, r->pool, 1, - sizeof(ngx_http_upstream_state_t)) - != NGX_OK) - { - ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); - return; + if (r->upstream_states == NULL) { + + r->upstream_states = ngx_array_create(r->pool, 1, + sizeof(ngx_http_upstream_state_t)); + if (r->upstream_states == NULL) { + ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + + } else { + + u->state = ngx_array_push(r->upstream_states); + if (u->state == NULL) { + ngx_http_upstream_finalize_request(r, u, + NGX_HTTP_INTERNAL_SERVER_ERROR); + return; + } + + ngx_memzero(u->state, sizeof(ngx_http_upstream_state_t)); } cln = ngx_http_cleanup_add(r, 0); @@ -509,7 +522,7 @@ ngx_http_upstream_connect(ngx_http_reque u->state->response_msec = tp->msec - u->state->response_msec; } - u->state = ngx_array_push(&u->states); + u->state = ngx_array_push(r->upstream_states); if (u->state == NULL) { ngx_http_upstream_finalize_request(r, u, NGX_HTTP_INTERNAL_SERVER_ERROR); @@ -767,7 +780,7 @@ ngx_http_upstream_send_request(ngx_http_ "http upstream send request"); if (!u->request_sent && ngx_http_upstream_test_connect(c) != NGX_OK) { - ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR); + ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR); return; } @@ -914,7 +927,7 @@ ngx_http_upstream_process_header(ngx_eve } if (!u->request_sent && ngx_http_upstream_test_connect(c) != NGX_OK) { - ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR); + ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_ERROR); return; } @@ -1259,33 +1272,33 @@ ngx_http_upstream_test_connect(ngx_conne #if (NGX_HAVE_KQUEUE) if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { - if (c->write->pending_eof) { - (void) ngx_connection_error(c, c->write->kq_errno, - "kevent() reported that connect() failed"); - return NGX_ERROR; - } + if (c->write->pending_eof) { + (void) ngx_connection_error(c, c->write->kq_errno, + "kevent() reported that connect() failed"); + return NGX_ERROR; + } } else #endif { - err = 0; - len = sizeof(int); - - /* - * BSDs and Linux return 0 and set a pending error in err - * Solaris returns -1 and sets errno - */ - - if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len) - == -1) - { - err = ngx_errno; - } - - if (err) { - (void) ngx_connection_error(c, err, "connect() failed"); - return NGX_ERROR; - } + err = 0; + len = sizeof(int); + + /* + * BSDs and Linux return 0 and set a pending error in err + * Solaris returns -1 and sets errno + */ + + if (getsockopt(c->fd, SOL_SOCKET, SO_ERROR, (void *) &err, &len) + == -1) + { + err = ngx_errno; + } + + if (err) { + (void) ngx_connection_error(c, err, "connect() failed"); + return NGX_ERROR; + } } return NGX_OK; @@ -2502,21 +2515,18 @@ ngx_http_upstream_status_variable(ngx_ht u_char *p; size_t len; ngx_uint_t i; - ngx_http_upstream_t *u; ngx_http_upstream_state_t *state; v->valid = 1; v->no_cachable = 0; v->not_found = 0; - u = r->upstream; - - if (u == NULL || u->states.nelts == 0) { + if (r->upstream_states == NULL || r->upstream_states->nelts == 0) { v->not_found = 1; return NGX_OK; } - len = u->states.nelts * (3 + 2); + len = r->upstream_states->nelts * (3 + 2); p = ngx_palloc(r->pool, len); if (p == NULL) { @@ -2526,22 +2536,35 @@ ngx_http_upstream_status_variable(ngx_ht v->data = p; i = 0; - state = u->states.elts; + state = r->upstream_states->elts; for ( ;; ) { - if (state[i].status == 0) { - *p++ = '-'; + if (state[i].status) { + p = ngx_sprintf(p, "%ui", state[i].status); } else { - p = ngx_sprintf(p, "%ui", state[i].status); + *p++ = '-'; } - if (++i == u->states.nelts) { + if (++i == r->upstream_states->nelts) { break; } - *p++ = ','; - *p++ = ' '; + if (state[i].peer) { + *p++ = ','; + *p++ = ' '; + + } else { + *p++ = ' '; + *p++ = ':'; + *p++ = ' '; + + if (++i == r->upstream_states->nelts) { + break; + } + + continue; + } } v->len = p - v->data; @@ -2558,21 +2581,18 @@ ngx_http_upstream_response_time_variable size_t len; ngx_uint_t i; ngx_msec_int_t ms; - ngx_http_upstream_t *u; ngx_http_upstream_state_t *state; v->valid = 1; v->no_cachable = 0; v->not_found = 0; - u = r->upstream; - - if (u == NULL || u->states.nelts == 0) { + if (r->upstream_states == NULL || r->upstream_states->nelts == 0) { v->not_found = 1; return NGX_OK; } - len = u->states.nelts * (NGX_TIME_T_LEN + 4 + 2); + len = r->upstream_states->nelts * (NGX_TIME_T_LEN + 4 + 2); p = ngx_palloc(r->pool, len); if (p == NULL) { @@ -2582,24 +2602,37 @@ ngx_http_upstream_response_time_variable v->data = p; i = 0; - state = u->states.elts; + state = r->upstream_states->elts; for ( ;; ) { - if (state[i].status == 0) { - *p++ = '-'; - - } else { + if (state[i].status) { ms = state[i].response_sec * 1000 + state[i].response_msec; ms = (ms >= 0) ? ms : 0; p = ngx_sprintf(p, "%d.%03d", ms / 1000, ms % 1000); + + } else { + *p++ = '-'; } - if (++i == u->states.nelts) { + if (++i == r->upstream_states->nelts) { break; } - *p++ = ','; - *p++ = ' '; + if (state[i].peer) { + *p++ = ','; + *p++ = ' '; + + } else { + *p++ = ' '; + *p++ = ':'; + *p++ = ' '; + + if (++i == r->upstream_states->nelts) { + break; + } + + continue; + } } v->len = p - v->data; @@ -2608,6 +2641,21 @@ ngx_http_upstream_response_time_variable } +ngx_int_t +ngx_http_upstream_header_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + if (r->upstream == NULL) { + v->not_found = 1; + return NGX_OK; + } + + return ngx_http_variable_unknown_header(v, (ngx_str_t *) data, + &r->upstream->headers_in.headers.part, + sizeof("upstream_http_") - 1); +} + + static char * ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) { 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 @@ -232,7 +232,6 @@ struct ngx_http_upstream_s { ngx_str_t method; ngx_http_upstream_state_t *state; - ngx_array_t states; /* of ngx_http_upstream_state_t */ ngx_str_t uri; @@ -248,6 +247,9 @@ struct ngx_http_upstream_s { }; +ngx_int_t ngx_http_upstream_header_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); + void ngx_http_upstream_init(ngx_http_request_t *r); ngx_http_upstream_srv_conf_t *ngx_http_upstream_add(ngx_conf_t *cf, ngx_url_t *u, ngx_uint_t flags); 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 @@ -23,8 +23,6 @@ static ngx_int_t ngx_http_variable_unkno ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_unknown_header_out(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); -static ngx_int_t ngx_http_variable_unknown_header(ngx_http_variable_value_t *v, - ngx_str_t *var, ngx_list_part_t *part, size_t prefix); static ngx_int_t ngx_http_variable_host(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); @@ -451,6 +449,17 @@ ngx_http_get_variable(ngx_http_request_t return NULL; } + if (ngx_strncmp(name->data, "upstream_http_", 10) == 0) { + + if (ngx_http_upstream_header_variable(r, vv, (uintptr_t) name) + == NGX_OK) + { + return vv; + } + + return NULL; + } + vv->not_found = 1; if (nowarn == 0) { @@ -614,7 +623,7 @@ ngx_http_variable_unknown_header_out(ngx } -static ngx_int_t +ngx_int_t ngx_http_variable_unknown_header(ngx_http_variable_value_t *v, ngx_str_t *var, ngx_list_part_t *part, size_t prefix) { @@ -1292,6 +1301,14 @@ ngx_http_variables_init_vars(ngx_conf_t continue; } + if (ngx_strncmp(v[i].name.data, "upstream_http_", 14) == 0) { + v[i].get_handler = ngx_http_upstream_header_variable; + v[i].data = (uintptr_t) &v[i].name; + v[i].flags = NGX_HTTP_VAR_NOCACHABLE; + + continue; + } + ngx_log_error(NGX_LOG_EMERG, cf->log, 0, "unknown \"%V\" variable", &v[i].name); diff --git a/src/http/ngx_http_variables.h b/src/http/ngx_http_variables.h --- a/src/http/ngx_http_variables.h +++ b/src/http/ngx_http_variables.h @@ -61,6 +61,10 @@ ngx_http_variable_value_t *ngx_http_get_ ngx_http_variable_value_t *ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key, ngx_uint_t nowarn); +ngx_int_t ngx_http_variable_unknown_header(ngx_http_variable_value_t *v, + ngx_str_t *var, ngx_list_part_t *part, size_t prefix); + + #define ngx_http_clear_variable(r, index) r->variables0[index].text.data = NULL; 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 @@ -686,19 +686,19 @@ ngx_mail_auth_http_process_headers(ngx_m ctx->err.len = ctx->errcode.len + ctx->errmsg.len + sizeof(" " CRLF) - 1; - p = ngx_palloc(s->connection->pool, ctx->err.len); - if (p == NULL) { - ngx_close_connection(ctx->peer.connection); - ngx_destroy_pool(ctx->pool); - ngx_mail_session_internal_server_error(s); - return; - } + p = ngx_palloc(s->connection->pool, ctx->err.len); + if (p == NULL) { + ngx_close_connection(ctx->peer.connection); + ngx_destroy_pool(ctx->pool); + ngx_mail_session_internal_server_error(s); + return; + } - ctx->err.data = p; + ctx->err.data = p; - p = ngx_cpymem(p, ctx->errcode.data, ctx->errcode.len); + p = ngx_cpymem(p, ctx->errcode.data, ctx->errcode.len); *p++ = ' '; - p = ngx_cpymem(p, ctx->errmsg.data, ctx->errmsg.len); + p = ngx_cpymem(p, ctx->errmsg.data, ctx->errmsg.len); *p++ = CR; *p = LF; } 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 @@ -63,7 +63,7 @@ static ngx_conf_bitmask_t ngx_smtp_auth static ngx_str_t ngx_smtp_auth_methods_names[] = { - ngx_string("PLAIN"), + ngx_string("PLAIN"), ngx_string("LOGIN"), ngx_null_string, /* APOP */ ngx_string("CRAM-MD5") diff --git a/src/mail/ngx_mail_handler.c b/src/mail/ngx_mail_handler.c --- a/src/mail/ngx_mail_handler.c +++ b/src/mail/ngx_mail_handler.c @@ -297,19 +297,19 @@ ngx_mail_init_session(ngx_connection_t * - s->salt.data; if (s->protocol == NGX_MAIL_POP3_PROTOCOL) { - s->out.data = ngx_palloc(c->pool, + s->out.data = ngx_palloc(c->pool, greetings[0].len + 1 + s->salt.len); - if (s->out.data == NULL) { - ngx_mail_session_internal_server_error(s); - return; - } + if (s->out.data == NULL) { + ngx_mail_session_internal_server_error(s); + return; + } - p = ngx_cpymem(s->out.data, + p = ngx_cpymem(s->out.data, greetings[0].data, greetings[0].len - 2); - *p++ = ' '; - p = ngx_cpymem(p, s->salt.data, s->salt.len); + *p++ = ' '; + p = ngx_cpymem(p, s->salt.data, s->salt.len); - s->out.len = p - s->out.data; + s->out.len = p - s->out.data; } } @@ -1408,31 +1408,31 @@ ngx_smtp_auth_state(ngx_event_t *rev) case NGX_SMTP_MAIL: if (s->connection->log->log_level >= NGX_LOG_INFO) { - l.len = s->buffer->last - s->buffer->start; - l.data = s->buffer->start; + l.len = s->buffer->last - s->buffer->start; + l.data = s->buffer->start; - for (i = 0; i < l.len; i++) { - ch = l.data[i]; + for (i = 0; i < l.len; i++) { + ch = l.data[i]; - if (ch != CR && ch != LF) { - continue; - } + if (ch != CR && ch != LF) { + continue; + } - l.data[i] = ' '; - } + l.data[i] = ' '; + } - while (i) { - if (l.data[i - 1] != ' ') { - break; - } + while (i) { + if (l.data[i - 1] != ' ') { + break; + } - i--; - } + i--; + } - l.len = i; + l.len = i; - ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, - "client was rejected: \"%V\"", &l); + ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, + "client was rejected: \"%V\"", &l); } text = smtp_auth_required; diff --git a/src/mail/ngx_mail_proxy_module.c b/src/mail/ngx_mail_proxy_module.c --- a/src/mail/ngx_mail_proxy_module.c +++ b/src/mail/ngx_mail_proxy_module.c @@ -702,20 +702,20 @@ ngx_mail_proxy_read_response(ngx_mail_se case ngx_smtp_helo: case ngx_smtp_noxclient: - if (p[0] == '2' && p[1] == '5' && p[2] == '0') { - return NGX_OK; - } - break; + if (p[0] == '2' && p[1] == '5' && p[2] == '0') { + return NGX_OK; + } + break; case ngx_smtp_start: case ngx_smtp_xclient: - if (p[0] == '2' && p[1] == '2' && p[2] == '0') { - return NGX_OK; - } - break; + if (p[0] == '2' && p[1] == '2' && p[2] == '0') { + return NGX_OK; + } + break; } - break; + break; } pcf = ngx_mail_get_module_srv_conf(s, ngx_mail_proxy_module);