static void ngx_http_replace_cleanup_pool(void *data) { sre_pool_t *pool = data; if (pool) { dd("destroy sre pool %p", pool); sre_destroy_pool(pool); } }
static char * ngx_http_replace_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) { u_char **value; sre_int_t err_offset, err_regex_id; ngx_str_t prefix, suffix; sre_pool_t *ppool; /* parser pool */ sre_regex_t *re; sre_program_t *prog; ngx_http_replace_main_conf_t *rmcf; ngx_http_replace_loc_conf_t *prev = parent; ngx_http_replace_loc_conf_t *conf = child; ngx_conf_merge_size_value(conf->max_buffered_size, prev->max_buffered_size, 8192); ngx_conf_merge_uint_value(conf->last_modified, prev->last_modified, NGX_HTTP_REPLACE_CLEAR_LAST_MODIFIED); 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->skip == NULL) { conf->skip = prev->skip; } if (conf->regexes.nelts > 0 && conf->program == NULL) { dd("parsing and compiling %d regexes", (int) conf->regexes.nelts); ppool = sre_create_pool(1024); if (ppool == NULL) { return NGX_CONF_ERROR; } value = conf->regexes.elts; re = sre_regex_parse_multi(ppool, value, conf->regexes.nelts, &conf->ncaps, conf->multi_flags.elts, &err_offset, &err_regex_id); if (re == NULL) { if (err_offset >= 0) { prefix.data = value[err_regex_id]; prefix.len = err_offset; suffix.data = value[err_regex_id] + err_offset; suffix.len = ngx_strlen(value[err_regex_id]) - err_offset; ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "failed to parse regex at offset %i: " "syntax error; marked by <-- HERE in " "\"%V <-- HERE %V\"", (ngx_int_t) err_offset, &prefix, &suffix); } else { if (err_regex_id >= 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "failed to parse regex \"%s\"", value[err_regex_id]); } else { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "failed to parse regex \"%s\" " "and its siblings", value[0]); } } sre_destroy_pool(ppool); return NGX_CONF_ERROR; } rmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_replace_filter_module); prog = sre_regex_compile(rmcf->compiler_pool, re); sre_destroy_pool(ppool); if (prog == NULL) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "failed to compile regex \"%s\" and its " "siblings", value[0]); return NGX_CONF_ERROR; } conf->program = prog; conf->ovecsize = 2 * (conf->ncaps + 1) * sizeof(sre_int_t); } else { conf->regexes = prev->regexes; conf->multi_once = prev->multi_once; conf->multi_flags = prev->multi_flags; conf->multi_replace = prev->multi_replace; conf->parse_buf = prev->parse_buf; conf->verbatim = prev->verbatim; conf->program = prev->program; conf->ncaps = prev->ncaps; conf->ovecsize = prev->ovecsize; conf->seen_once = prev->seen_once; conf->seen_global = prev->seen_global; } return NGX_CONF_OK; }
static char * ngx_http_replace_filter(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_http_replace_loc_conf_t *rlcf = conf; ngx_http_replace_main_conf_t *rmcf; int *flags; u_char *p, **re; ngx_str_t *value; ngx_uint_t i; uint8_t *once; ngx_pool_cleanup_t *cln; ngx_http_replace_complex_value_t *cv; ngx_http_replace_compile_complex_value_t ccv; value = cf->args->elts; re = ngx_array_push(&rlcf->regexes); if (re == NULL) { return NGX_CONF_ERROR; } *re = value[1].data; cv = ngx_array_push(&rlcf->multi_replace); if (cv == NULL) { return NGX_CONF_ERROR; } ngx_memzero(cv, sizeof(ngx_http_replace_complex_value_t)); ngx_memzero(&ccv, sizeof(ngx_http_replace_compile_complex_value_t)); ccv.cf = cf; ccv.value = &value[2]; ccv.complex_value = cv; if (ngx_http_replace_compile_complex_value(&ccv) != NGX_OK) { return NGX_CONF_ERROR; } /* check variable usage in the "replace" argument */ if (cv->capture_variables) { rlcf->parse_buf = ngx_http_replace_capturing_parse; } else if (rlcf->parse_buf == NULL) { rlcf->parse_buf = ngx_http_replace_non_capturing_parse; } #if 0 rlcf->parse_buf = ngx_http_replace_capturing_parse; #endif flags = ngx_array_push(&rlcf->multi_flags); if (flags == NULL) { return NGX_CONF_ERROR; } *flags = 0; once = ngx_array_push(&rlcf->multi_once); if (once == NULL) { return NGX_CONF_ERROR; } *once = 1; /* default to once */ if (cf->args->nelts == 4) { /* 3 user args */ p = value[3].data; for (i = 0; i < value[3].len; i++) { switch (p[i]) { case 'i': *flags |= SRE_REGEX_CASELESS; break; case 'g': *once = 0; break; default: return "specifies an unrecognized regex flag"; } } } if (*once) { rlcf->seen_once = 1; } else { rlcf->seen_global = 1; } if (rlcf->seen_once && rlcf->regexes.nelts > 1) { rlcf->parse_buf = ngx_http_replace_capturing_parse; if (rlcf->verbatim.value.data == NULL) { ngx_str_t v = ngx_string("$&"); ngx_memzero(&ccv, sizeof(ngx_http_replace_compile_complex_value_t)); ccv.cf = cf; ccv.value = &v; ccv.complex_value = &rlcf->verbatim; if (ngx_http_replace_compile_complex_value(&ccv) != NGX_OK) { return NGX_CONF_ERROR; } } } rmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_replace_filter_module); if (rmcf->compiler_pool == NULL) { rmcf->compiler_pool = sre_create_pool(SREGEX_COMPILER_POOL_SIZE); if (rmcf->compiler_pool == NULL) { return NGX_CONF_ERROR; } cln = ngx_pool_cleanup_add(cf->pool, 0); if (cln == NULL) { sre_destroy_pool(rmcf->compiler_pool); rmcf->compiler_pool = NULL; return NGX_CONF_ERROR; } cln->data = rmcf->compiler_pool; cln->handler = ngx_http_replace_cleanup_pool; } return NGX_CONF_OK; }
static ngx_int_t ngx_http_replace_header_filter(ngx_http_request_t *r) { size_t size; ngx_str_t skip; ngx_pool_cleanup_t *cln; ngx_http_replace_ctx_t *ctx; ngx_http_replace_loc_conf_t *rlcf; rlcf = ngx_http_get_module_loc_conf(r, ngx_http_replace_filter_module); dd("replace header filter"); if (rlcf->regexes.nelts == 0 || r->headers_out.content_length_n == 0 || (r->headers_out.content_encoding && r->headers_out.content_encoding->value.len) || ngx_http_test_content_type(r, &rlcf->types) == NULL) { return ngx_http_next_header_filter(r); } dd("skip: %p", rlcf->skip); if (rlcf->skip != NULL) { if (ngx_http_complex_value(r, rlcf->skip, &skip) != NGX_OK) { return NGX_ERROR; } if (skip.len && (skip.len != 1 || skip.data[0] != '0')) { return ngx_http_next_header_filter(r); } } ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_replace_ctx_t)); if (ctx == NULL) { return NGX_ERROR; } ctx->last_special = &ctx->special; ctx->last_pending = &ctx->pending; ctx->last_pending2 = &ctx->pending2; ctx->last_captured = &ctx->captured; ctx->sub = ngx_pcalloc(r->pool, rlcf->multi_replace.nelts * sizeof(ngx_str_t)); if (ctx->sub == NULL) { return NGX_ERROR; } ctx->ovector = ngx_palloc(r->pool, rlcf->ovecsize); if (ctx->ovector == NULL) { return NGX_ERROR; } size = ngx_align(rlcf->regexes.nelts, 8) / 8; ctx->disabled = ngx_pcalloc(r->pool, size); if (ctx->disabled == NULL) { return NGX_ERROR; } ctx->vm_pool = sre_create_pool(1024); if (ctx->vm_pool == NULL) { return NGX_ERROR; } dd("created vm pool %p", ctx->vm_pool); cln = ngx_pool_cleanup_add(r->pool, 0); if (cln == NULL) { sre_destroy_pool(ctx->vm_pool); return NGX_ERROR; } cln->data = ctx->vm_pool; cln->handler = ngx_http_replace_cleanup_pool; ctx->vm_ctx = sre_vm_pike_create_ctx(ctx->vm_pool, rlcf->program, ctx->ovector, rlcf->ovecsize); if (ctx->vm_ctx == NULL) { return NGX_ERROR; } ngx_http_set_ctx(r, ctx, ngx_http_replace_filter_module); ctx->last_out = &ctx->out; r->filter_need_in_memory = 1; if (r == r->main) { ngx_http_clear_content_length(r); if (rlcf->last_modified == NGX_HTTP_REPLACE_CLEAR_LAST_MODIFIED) { ngx_http_clear_last_modified(r); } } return ngx_http_next_header_filter(r); }
RegexSearch::~RegexSearch() { sre_destroy_pool(sre_pool_); }