diff options
Diffstat (limited to 'app/nginx/src/http/modules/ngx_http_sub_filter_module.c')
-rw-r--r-- | app/nginx/src/http/modules/ngx_http_sub_filter_module.c | 1018 |
1 files changed, 0 insertions, 1018 deletions
diff --git a/app/nginx/src/http/modules/ngx_http_sub_filter_module.c b/app/nginx/src/http/modules/ngx_http_sub_filter_module.c deleted file mode 100644 index de58c6f..0000000 --- a/app/nginx/src/http/modules/ngx_http_sub_filter_module.c +++ /dev/null @@ -1,1018 +0,0 @@ - -/* - * Copyright (C) Igor Sysoev - * Copyright (C) Nginx, Inc. - */ - - -#include <ngx_config.h> -#include <ngx_core.h> -#include <ngx_http.h> - - -typedef struct { - ngx_http_complex_value_t match; - ngx_http_complex_value_t value; -} ngx_http_sub_pair_t; - - -typedef struct { - ngx_str_t match; - ngx_http_complex_value_t *value; -} ngx_http_sub_match_t; - - -typedef struct { - ngx_uint_t min_match_len; - ngx_uint_t max_match_len; - - u_char index[257]; - u_char shift[256]; -} ngx_http_sub_tables_t; - - -typedef struct { - ngx_uint_t dynamic; /* unsigned dynamic:1; */ - - ngx_array_t *pairs; - - ngx_http_sub_tables_t *tables; - - ngx_hash_t types; - - ngx_flag_t once; - ngx_flag_t last_modified; - - ngx_array_t *types_keys; - ngx_array_t *matches; -} ngx_http_sub_loc_conf_t; - - -typedef struct { - ngx_str_t saved; - ngx_str_t looked; - - 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 applied; - - ngx_int_t offset; - ngx_uint_t index; - - ngx_http_sub_tables_t *tables; - ngx_array_t *matches; -} ngx_http_sub_ctx_t; - - -static ngx_uint_t ngx_http_sub_cmp_index; - - -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, ngx_uint_t flush); -static ngx_int_t ngx_http_sub_match(ngx_http_sub_ctx_t *ctx, ngx_int_t start, - ngx_str_t *m); - -static char * ngx_http_sub_filter(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 void ngx_http_sub_init_tables(ngx_http_sub_tables_t *tables, - ngx_http_sub_match_t *match, ngx_uint_t n); -static ngx_int_t ngx_http_sub_cmp_matches(const void *one, const void *two); -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_types_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_sub_loc_conf_t, types_keys), - &ngx_http_html_default_types[0] }, - - { 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_string("sub_filter_last_modified"), - 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, last_modified), - 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 *m; - ngx_uint_t i, j, n; - ngx_http_sub_ctx_t *ctx; - ngx_http_sub_pair_t *pairs; - ngx_http_sub_match_t *matches; - ngx_http_sub_loc_conf_t *slcf; - - slcf = ngx_http_get_module_loc_conf(r, ngx_http_sub_filter_module); - - if (slcf->pairs == NULL - || r->headers_out.content_length_n == 0 - || ngx_http_test_content_type(r, &slcf->types) == NULL) - { - return ngx_http_next_header_filter(r); - } - - ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_sub_ctx_t)); - if (ctx == NULL) { - return NGX_ERROR; - } - - if (slcf->dynamic == 0) { - ctx->tables = slcf->tables; - ctx->matches = slcf->matches; - - } else { - pairs = slcf->pairs->elts; - n = slcf->pairs->nelts; - - matches = ngx_pcalloc(r->pool, sizeof(ngx_http_sub_match_t) * n); - if (matches == NULL) { - return NGX_ERROR; - } - - j = 0; - for (i = 0; i < n; i++) { - matches[j].value = &pairs[i].value; - - if (pairs[i].match.lengths == NULL) { - matches[j].match = pairs[i].match.value; - j++; - continue; - } - - m = &matches[j].match; - if (ngx_http_complex_value(r, &pairs[i].match, m) != NGX_OK) { - return NGX_ERROR; - } - - if (m->len == 0) { - continue; - } - - ngx_strlow(m->data, m->data, m->len); - j++; - } - - if (j == 0) { - return ngx_http_next_header_filter(r); - } - - ctx->matches = ngx_palloc(r->pool, sizeof(ngx_array_t)); - if (ctx->matches == NULL) { - return NGX_ERROR; - } - - ctx->matches->elts = matches; - ctx->matches->nelts = j; - - ctx->tables = ngx_palloc(r->pool, sizeof(ngx_http_sub_tables_t)); - if (ctx->tables == NULL) { - return NGX_ERROR; - } - - ngx_http_sub_init_tables(ctx->tables, ctx->matches->elts, - ctx->matches->nelts); - } - - ngx_http_set_ctx(r, ctx, ngx_http_sub_filter_module); - - ctx->saved.data = ngx_pnalloc(r->pool, ctx->tables->max_match_len - 1); - if (ctx->saved.data == NULL) { - return NGX_ERROR; - } - - ctx->looked.data = ngx_pnalloc(r->pool, ctx->tables->max_match_len - 1); - if (ctx->looked.data == NULL) { - return NGX_ERROR; - } - - ctx->offset = ctx->tables->min_match_len - 1; - ctx->last_out = &ctx->out; - - r->filter_need_in_memory = 1; - - if (r == r->main) { - ngx_http_clear_content_length(r); - - if (!slcf->last_modified) { - ngx_http_clear_last_modified(r); - ngx_http_clear_etag(r); - - } else { - ngx_http_weak_etag(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_str_t *sub; - ngx_uint_t flush, last; - ngx_chain_t *cl; - ngx_http_sub_ctx_t *ctx; - ngx_http_sub_match_t *match; - 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_OK) { - return NGX_ERROR; - } - } - - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http sub filter \"%V\"", &r->uri); - - flush = 0; - last = 0; - - 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->buf->flush || ctx->buf->recycled) { - flush = 1; - } - - if (ctx->in == NULL) { - last = flush; - } - - b = NULL; - - while (ctx->pos < ctx->buf->last) { - - rc = ngx_http_sub_parse(r, ctx, last); - - ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "parse: %i, looked: \"%V\" %p-%p", - rc, &ctx->looked, ctx->copy_start, ctx->copy_end); - - if (rc == NGX_ERROR) { - return rc; - } - - if (ctx->saved.len) { - - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "saved: \"%V\"", &ctx->saved); - - cl = ngx_chain_get_free_buf(r->pool, &ctx->free); - if (cl == NULL) { - return NGX_ERROR; - } - - b = cl->buf; - - ngx_memzero(b, sizeof(ngx_buf_t)); - - b->pos = ngx_pnalloc(r->pool, ctx->saved.len); - if (b->pos == NULL) { - return NGX_ERROR; - } - - ngx_memcpy(b->pos, ctx->saved.data, ctx->saved.len); - b->last = b->pos + ctx->saved.len; - b->memory = 1; - - *ctx->last_out = cl; - ctx->last_out = &cl->next; - - ctx->saved.len = 0; - } - - if (ctx->copy_start != ctx->copy_end) { - - cl = ngx_chain_get_free_buf(r->pool, &ctx->free); - if (cl == NULL) { - return NGX_ERROR; - } - - b = cl->buf; - - 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->last_in_chain = 0; - b->recycled = 0; - - if (b->in_file) { - b->file_last = b->file_pos + (b->last - ctx->buf->pos); - b->file_pos += b->pos - ctx->buf->pos; - } - - *ctx->last_out = cl; - ctx->last_out = &cl->next; - } - - if (rc == NGX_AGAIN) { - continue; - } - - - /* rc == NGX_OK */ - - cl = ngx_chain_get_free_buf(r->pool, &ctx->free); - if (cl == NULL) { - return NGX_ERROR; - } - - b = cl->buf; - - ngx_memzero(b, sizeof(ngx_buf_t)); - - slcf = ngx_http_get_module_loc_conf(r, ngx_http_sub_filter_module); - - if (ctx->sub == NULL) { - ctx->sub = ngx_pcalloc(r->pool, sizeof(ngx_str_t) - * ctx->matches->nelts); - if (ctx->sub == NULL) { - return NGX_ERROR; - } - } - - sub = &ctx->sub[ctx->index]; - - if (sub->data == NULL) { - match = ctx->matches->elts; - - if (ngx_http_complex_value(r, match[ctx->index].value, sub) - != NGX_OK) - { - return NGX_ERROR; - } - } - - if (sub->len) { - b->memory = 1; - b->pos = sub->data; - b->last = sub->data + sub->len; - - } else { - b->sync = 1; - } - - *ctx->last_out = cl; - ctx->last_out = &cl->next; - - ctx->index = 0; - ctx->once = slcf->once && (++ctx->applied == ctx->matches->nelts); - - continue; - } - - if (ctx->looked.len - && (ctx->buf->last_buf || ctx->buf->last_in_chain)) - { - cl = ngx_chain_get_free_buf(r->pool, &ctx->free); - if (cl == NULL) { - return NGX_ERROR; - } - - b = cl->buf; - - ngx_memzero(b, sizeof(ngx_buf_t)); - - b->pos = ctx->looked.data; - b->last = b->pos + ctx->looked.len; - b->memory = 1; - - *ctx->last_out = cl; - ctx->last_out = &cl->next; - - ctx->looked.len = 0; - } - - if (ctx->buf->last_buf || ctx->buf->flush || ctx->buf->sync - || ngx_buf_in_memory(ctx->buf)) - { - if (b == NULL) { - cl = ngx_chain_get_free_buf(r->pool, &ctx->free); - if (cl == NULL) { - return NGX_ERROR; - } - - b = cl->buf; - - ngx_memzero(b, sizeof(ngx_buf_t)); - - b->sync = 1; - - *ctx->last_out = cl; - ctx->last_out = &cl->next; - } - - b->last_buf = ctx->buf->last_buf; - b->last_in_chain = ctx->buf->last_in_chain; - b->flush = ctx->buf->flush; - b->shadow = ctx->buf; - - b->recycled = ctx->buf->recycled; - } - - ctx->buf = NULL; - } - - 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 (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, - ngx_uint_t flush) -{ - u_char *p, c; - ngx_str_t *m; - ngx_int_t offset, start, next, end, len, rc; - ngx_uint_t shift, i, j; - ngx_http_sub_match_t *match; - ngx_http_sub_tables_t *tables; - ngx_http_sub_loc_conf_t *slcf; - - slcf = ngx_http_get_module_loc_conf(r, ngx_http_sub_filter_module); - tables = ctx->tables; - match = ctx->matches->elts; - - offset = ctx->offset; - end = ctx->buf->last - ctx->pos; - - if (ctx->once) { - /* sets start and next to end */ - offset = end + (ngx_int_t) tables->min_match_len - 1; - goto again; - } - - while (offset < end) { - - c = offset < 0 ? ctx->looked.data[ctx->looked.len + offset] - : ctx->pos[offset]; - - c = ngx_tolower(c); - - shift = tables->shift[c]; - if (shift > 0) { - offset += shift; - continue; - } - - /* a potential match */ - - start = offset - (ngx_int_t) tables->min_match_len + 1; - - i = ngx_max((ngx_uint_t) tables->index[c], ctx->index); - j = tables->index[c + 1]; - - while (i != j) { - - if (slcf->once && ctx->sub && ctx->sub[i].data) { - goto next; - } - - m = &match[i].match; - - rc = ngx_http_sub_match(ctx, start, m); - - if (rc == NGX_DECLINED) { - goto next; - } - - ctx->index = i; - - if (rc == NGX_AGAIN) { - goto again; - } - - ctx->offset = offset + (ngx_int_t) m->len; - next = start + (ngx_int_t) m->len; - end = ngx_max(next, 0); - rc = NGX_OK; - - goto done; - - next: - - i++; - } - - offset++; - ctx->index = 0; - } - - if (flush) { - for ( ;; ) { - start = offset - (ngx_int_t) tables->min_match_len + 1; - - if (start >= end) { - break; - } - - for (i = 0; i < ctx->matches->nelts; i++) { - m = &match[i].match; - - if (ngx_http_sub_match(ctx, start, m) == NGX_AGAIN) { - goto again; - } - } - - offset++; - } - } - -again: - - ctx->offset = offset; - start = offset - (ngx_int_t) tables->min_match_len + 1; - next = start; - rc = NGX_AGAIN; - -done: - - /* send [ - looked.len, start ] to client */ - - ctx->saved.len = ctx->looked.len + ngx_min(start, 0); - ngx_memcpy(ctx->saved.data, ctx->looked.data, ctx->saved.len); - - ctx->copy_start = ctx->pos; - ctx->copy_end = ctx->pos + ngx_max(start, 0); - - /* save [ next, end ] in looked */ - - len = ngx_min(next, 0); - p = ctx->looked.data; - p = ngx_movemem(p, p + ctx->looked.len + len, - len); - - len = ngx_max(next, 0); - p = ngx_cpymem(p, ctx->pos + len, end - len); - ctx->looked.len = p - ctx->looked.data; - - /* update position */ - - ctx->pos += end; - ctx->offset -= end; - - return rc; -} - - -static ngx_int_t -ngx_http_sub_match(ngx_http_sub_ctx_t *ctx, ngx_int_t start, ngx_str_t *m) -{ - u_char *p, *last, *pat, *pat_end; - - pat = m->data; - pat_end = m->data + m->len; - - if (start >= 0) { - p = ctx->pos + start; - - } else { - last = ctx->looked.data + ctx->looked.len; - p = last + start; - - while (p < last && pat < pat_end) { - if (ngx_tolower(*p) != *pat) { - return NGX_DECLINED; - } - - p++; - pat++; - } - - p = ctx->pos; - } - - while (p < ctx->buf->last && pat < pat_end) { - if (ngx_tolower(*p) != *pat) { - return NGX_DECLINED; - } - - p++; - pat++; - } - - if (pat != pat_end) { - /* partial match */ - return NGX_AGAIN; - } - - return NGX_OK; -} - - -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_http_sub_pair_t *pair; - ngx_http_compile_complex_value_t ccv; - - value = cf->args->elts; - - if (value[1].len == 0) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "empty search pattern"); - return NGX_CONF_ERROR; - } - - if (slcf->pairs == NULL) { - slcf->pairs = ngx_array_create(cf->pool, 1, - sizeof(ngx_http_sub_pair_t)); - if (slcf->pairs == NULL) { - return NGX_CONF_ERROR; - } - } - - if (slcf->pairs->nelts == 255) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "number of search patterns exceeds 255"); - return NGX_CONF_ERROR; - } - - ngx_strlow(value[1].data, value[1].data, value[1].len); - - pair = ngx_array_push(slcf->pairs); - if (pair == NULL) { - return NGX_CONF_ERROR; - } - - ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); - - ccv.cf = cf; - ccv.value = &value[1]; - ccv.complex_value = &pair->match; - - if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { - return NGX_CONF_ERROR; - } - - if (ccv.complex_value->lengths != NULL) { - slcf->dynamic = 1; - - } else { - ngx_strlow(pair->match.value.data, pair->match.value.data, - pair->match.value.len); - } - - ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); - - ccv.cf = cf; - ccv.value = &value[2]; - ccv.complex_value = &pair->value; - - if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { - return NGX_CONF_ERROR; - } - - 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 NULL; - } - - /* - * set by ngx_pcalloc(): - * - * conf->dynamic = 0; - * conf->pairs = NULL; - * conf->tables = NULL; - * conf->types = { NULL }; - * conf->types_keys = NULL; - * conf->matches = NULL; - */ - - slcf->once = NGX_CONF_UNSET; - slcf->last_modified = NGX_CONF_UNSET; - - return slcf; -} - - -static char * -ngx_http_sub_merge_conf(ngx_conf_t *cf, void *parent, void *child) -{ - ngx_uint_t i, n; - ngx_http_sub_pair_t *pairs; - ngx_http_sub_match_t *matches; - ngx_http_sub_loc_conf_t *prev = parent; - ngx_http_sub_loc_conf_t *conf = child; - - ngx_conf_merge_value(conf->once, prev->once, 1); - ngx_conf_merge_value(conf->last_modified, prev->last_modified, 0); - - if (ngx_http_merge_types(cf, &conf->types_keys, &conf->types, - &prev->types_keys, &prev->types, - ngx_http_html_default_types) - != NGX_OK) - { - return NGX_CONF_ERROR; - } - - if (conf->pairs == NULL) { - conf->dynamic = prev->dynamic; - conf->pairs = prev->pairs; - conf->matches = prev->matches; - conf->tables = prev->tables; - } - - if (conf->pairs && conf->dynamic == 0 && conf->tables == NULL) { - pairs = conf->pairs->elts; - n = conf->pairs->nelts; - - matches = ngx_palloc(cf->pool, sizeof(ngx_http_sub_match_t) * n); - if (matches == NULL) { - return NGX_CONF_ERROR; - } - - for (i = 0; i < n; i++) { - matches[i].match = pairs[i].match.value; - matches[i].value = &pairs[i].value; - } - - conf->matches = ngx_palloc(cf->pool, sizeof(ngx_array_t)); - if (conf->matches == NULL) { - return NGX_CONF_ERROR; - } - - conf->matches->elts = matches; - conf->matches->nelts = n; - - conf->tables = ngx_palloc(cf->pool, sizeof(ngx_http_sub_tables_t)); - if (conf->tables == NULL) { - return NGX_CONF_ERROR; - } - - ngx_http_sub_init_tables(conf->tables, conf->matches->elts, - conf->matches->nelts); - } - - return NGX_CONF_OK; -} - - -static void -ngx_http_sub_init_tables(ngx_http_sub_tables_t *tables, - ngx_http_sub_match_t *match, ngx_uint_t n) -{ - u_char c; - ngx_uint_t i, j, min, max, ch; - - min = match[0].match.len; - max = match[0].match.len; - - for (i = 1; i < n; i++) { - min = ngx_min(min, match[i].match.len); - max = ngx_max(max, match[i].match.len); - } - - tables->min_match_len = min; - tables->max_match_len = max; - - ngx_http_sub_cmp_index = tables->min_match_len - 1; - ngx_sort(match, n, sizeof(ngx_http_sub_match_t), ngx_http_sub_cmp_matches); - - min = ngx_min(min, 255); - ngx_memset(tables->shift, min, 256); - - ch = 0; - - for (i = 0; i < n; i++) { - - for (j = 0; j < min; j++) { - c = match[i].match.data[tables->min_match_len - 1 - j]; - tables->shift[c] = ngx_min(tables->shift[c], (u_char) j); - } - - c = match[i].match.data[tables->min_match_len - 1]; - while (ch <= (ngx_uint_t) c) { - tables->index[ch++] = (u_char) i; - } - } - - while (ch < 257) { - tables->index[ch++] = (u_char) n; - } -} - - -static ngx_int_t -ngx_http_sub_cmp_matches(const void *one, const void *two) -{ - ngx_int_t c1, c2; - ngx_http_sub_match_t *first, *second; - - first = (ngx_http_sub_match_t *) one; - second = (ngx_http_sub_match_t *) two; - - c1 = first->match.data[ngx_http_sub_cmp_index]; - c2 = second->match.data[ngx_http_sub_cmp_index]; - - return c1 - c2; -} - - -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; -} |