📄 mod_filter.c
字号:
else if (!strcasecmp(arg, "change=1:1")) { flags |= AP_FILTER_PROTO_CHANGE; } else if (!strcasecmp(arg, "byteranges=no")) { flags |= AP_FILTER_PROTO_NO_BYTERANGE; } else if (!strcasecmp(arg, "proxy=no")) { flags |= AP_FILTER_PROTO_NO_PROXY; } else if (!strcasecmp(arg, "proxy=transform")) { flags |= AP_FILTER_PROTO_TRANSFORM; } else if (!strcasecmp(arg, "cache=no")) { flags |= AP_FILTER_PROTO_NO_CACHE; } } if (pname) { provider->frec->proto_flags = flags; } else { filter->proto_flags = flags; } return NULL;}#endifstatic const char *filter_declare(cmd_parms *cmd, void *CFG, const char *fname, const char *place){ mod_filter_cfg *cfg = (mod_filter_cfg *)CFG; ap_filter_rec_t *filter; filter = apr_pcalloc(cmd->pool, sizeof(ap_filter_rec_t)); apr_hash_set(cfg->live_filters, fname, APR_HASH_KEY_STRING, filter); filter->name = fname; filter->filter_init_func = filter_init; filter->filter_func.out_func = filter_harness; filter->ftype = AP_FTYPE_RESOURCE; filter->next = NULL; if (place) { if (!strcasecmp(place, "CONTENT_SET")) { filter->ftype = AP_FTYPE_CONTENT_SET; } else if (!strcasecmp(place, "PROTOCOL")) { filter->ftype = AP_FTYPE_PROTOCOL; } else if (!strcasecmp(place, "CONNECTION")) { filter->ftype = AP_FTYPE_CONNECTION; } else if (!strcasecmp(place, "NETWORK")) { filter->ftype = AP_FTYPE_NETWORK; } } return NULL;}static const char *filter_provider(cmd_parms *cmd, void *CFG, const char *args){ mod_filter_cfg *cfg = CFG; int flags; ap_filter_provider_t *provider; const char *rxend; const char *c; char *str; const char *eq; ap_filter_rec_t* frec; ap_filter_rec_t* provider_frec; /* insist on exactly four arguments */ const char *fname = ap_getword_conf(cmd->pool, &args) ; const char *pname = ap_getword_conf(cmd->pool, &args) ; const char *condition = ap_getword_conf(cmd->pool, &args) ; const char *match = ap_getword_conf(cmd->pool, &args) ; eq = ap_getword_conf(cmd->pool, &args) ; if ( !*fname || !*pname || !*match || !*condition || *eq ) { return "usage: FilterProvider filter provider condition match" ; } /* fname has been declared with DeclareFilter, so we can look it up */ frec = apr_hash_get(cfg->live_filters, fname, APR_HASH_KEY_STRING); /* or if provider is mod_filter itself, we can also look it up */ if (!frec) { c = filter_declare(cmd, CFG, fname, NULL); if ( c ) { return c; } frec = apr_hash_get(cfg->live_filters, fname, APR_HASH_KEY_STRING); } if (!frec) { return apr_psprintf(cmd->pool, "Undeclared smart filter %s", fname); } /* if provider has been registered, we can look it up */ provider_frec = ap_get_output_filter_handle(pname); if (!provider_frec) { return apr_psprintf(cmd->pool, "Unknown filter provider %s", pname); } provider = apr_palloc(cmd->pool, sizeof(ap_filter_provider_t)); if (*match == '!') { provider->not = 1; ++match; } else { provider->not = 0; } switch (*match++) { case '<': if (*match == '=') { provider->match_type = INT_LE; ++match; } else { provider->match_type = INT_LT; } provider->match.number = atoi(match); break; case '>': if (*match == '=') { provider->match_type = INT_GE; ++match; } else { provider->match_type = INT_GT; } provider->match.number = atoi(match); break; case '=': provider->match_type = INT_EQ; provider->match.number = atoi(match); break; case '/': provider->match_type = REGEX_MATCH; rxend = ap_strchr_c(match, '/'); if (!rxend) { return "Bad regexp syntax"; } flags = AP_REG_NOSUB; /* we're not mod_rewrite:-) */ for (c = rxend+1; *c; ++c) { switch (*c) { case 'i': flags |= AP_REG_ICASE; break; } } provider->match.regex = ap_pregcomp(cmd->pool, apr_pstrndup(cmd->pool, match, rxend-match), flags); if (provider->match.regex == NULL) { return "Bad regexp"; } break; case '*': provider->match_type = DEFINED; provider->match.number = -1; break; case '$': provider->match_type = STRING_CONTAINS; str = apr_pstrdup(cmd->pool, match); ap_str_tolower(str); provider->match.string = str; break; default: provider->match_type = STRING_MATCH; provider->match.string = apr_pstrdup(cmd->pool, match-1); break; } provider->frec = provider_frec; provider->next = frec->providers; frec->providers = provider; /* determine what a filter will dispatch this provider on */ eq = ap_strchr_c(condition, '='); if (eq) { str = apr_pstrdup(cmd->pool, eq+1); if (!strncasecmp(condition, "env=", 4)) { provider->dispatch = SUBPROCESS_ENV; } else if (!strncasecmp(condition, "req=", 4)) { provider->dispatch = REQUEST_HEADERS; } else if (!strncasecmp(condition, "resp=", 5)) { provider->dispatch = RESPONSE_HEADERS; } else { return "FilterProvider: unrecognized dispatch table"; } } else { if (!strcasecmp(condition, "handler")) { provider->dispatch = HANDLER; } else { provider->dispatch = RESPONSE_HEADERS; } str = apr_pstrdup(cmd->pool, condition); ap_str_tolower(str); } if ( (provider->dispatch == RESPONSE_HEADERS) && !strcasecmp(str, "content-type")) { provider->dispatch = CONTENT_TYPE; } provider->value = str; return NULL;}static const char *filter_chain(cmd_parms *cmd, void *CFG, const char *arg){ mod_filter_chain *p; mod_filter_chain *q; mod_filter_cfg *cfg = CFG; switch (arg[0]) { case '+': /* add to end of chain */ p = apr_pcalloc(cmd->pool, sizeof(mod_filter_chain)); p->fname = arg+1; if (cfg->chain) { for (q = cfg->chain; q->next; q = q->next); q->next = p; } else { cfg->chain = p; } break; case '@': /* add to start of chain */ p = apr_palloc(cmd->pool, sizeof(mod_filter_chain)); p->fname = arg+1; p->next = cfg->chain; cfg->chain = p; break; case '-': /* remove from chain */ if (cfg->chain) { if (strcasecmp(cfg->chain->fname, arg+1)) { for (p = cfg->chain; p->next; p = p->next) { if (!strcasecmp(p->next->fname, arg+1)) { p->next = p->next->next; } } } else { cfg->chain = cfg->chain->next; } } break; case '!': /* Empty the chain */ /** IG: Add a NULL provider to the beginning so that * we can ensure that we'll empty everything before * this when doing config merges later */ p = apr_pcalloc(cmd->pool, sizeof(mod_filter_chain)); p->fname = NULL; cfg->chain = p; break; case '=': /* initialise chain with this arg */ /** IG: Prepend a NULL provider to the beginning as above */ p = apr_pcalloc(cmd->pool, sizeof(mod_filter_chain)); p->fname = NULL; p->next = apr_pcalloc(cmd->pool, sizeof(mod_filter_chain)); p->next->fname = arg+1; cfg->chain = p; break; default: /* add to end */ p = apr_pcalloc(cmd->pool, sizeof(mod_filter_chain)); p->fname = arg; if (cfg->chain) { for (q = cfg->chain; q->next; q = q->next); q->next = p; } else { cfg->chain = p; } break; } return NULL;}static const char *filter_debug(cmd_parms *cmd, void *CFG, const char *fname, const char *level){ mod_filter_cfg *cfg = CFG; ap_filter_rec_t *frec = apr_hash_get(cfg->live_filters, fname, APR_HASH_KEY_STRING); if (!frec) { return apr_psprintf(cmd->pool, "Undeclared smart filter %s", fname); } frec->debug = atoi(level); return NULL;}static void filter_insert(request_rec *r){ mod_filter_chain *p; ap_filter_rec_t *filter; mod_filter_cfg *cfg = ap_get_module_config(r->per_dir_config, &filter_module);#ifndef NO_PROTOCOL int ranges = 1; mod_filter_ctx *ctx = apr_pcalloc(r->pool, sizeof(mod_filter_ctx)); ap_set_module_config(r->request_config, &filter_module, ctx);#endif /** IG: Now that we've merged to the final config, go one last time * through the chain, and prune out the NULL filters */ for (p = cfg->chain; p; p = p->next) { if (p->fname == NULL) cfg->chain = p->next; } for (p = cfg->chain; p; p = p->next) { filter = apr_hash_get(cfg->live_filters, p->fname, APR_HASH_KEY_STRING); if (filter == NULL) { ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, "Unknown filter %s not added", p->fname); continue; } ap_add_output_filter_handle(filter, NULL, r, r->connection);#ifndef NO_PROTOCOL if (ranges && (filter->proto_flags & (AP_FILTER_PROTO_NO_BYTERANGE | AP_FILTER_PROTO_CHANGE_LENGTH))) { ctx->range = apr_table_get(r->headers_in, "Range"); apr_table_unset(r->headers_in, "Range"); ranges = 0; }#endif } return;}static void filter_hooks(apr_pool_t *pool){ ap_hook_insert_filter(filter_insert, NULL, NULL, APR_HOOK_MIDDLE);}static void *filter_config(apr_pool_t *pool, char *x){ mod_filter_cfg *cfg = apr_palloc(pool, sizeof(mod_filter_cfg)); cfg->live_filters = apr_hash_make(pool); cfg->chain = NULL; return cfg;}static void *filter_merge(apr_pool_t *pool, void *BASE, void *ADD){ mod_filter_cfg *base = BASE; mod_filter_cfg *add = ADD; mod_filter_chain *savelink = 0; mod_filter_chain *newlink; mod_filter_chain *p; mod_filter_cfg *conf = apr_palloc(pool, sizeof(mod_filter_cfg)); conf->live_filters = apr_hash_overlay(pool, add->live_filters, base->live_filters); if (base->chain && add->chain) { for (p = base->chain; p; p = p->next) { newlink = apr_pmemdup(pool, p, sizeof(mod_filter_chain)); if (newlink->fname == NULL) { conf->chain = savelink = newlink; } else if (savelink) { savelink->next = newlink; savelink = newlink; } else { conf->chain = savelink = newlink; } } for (p = add->chain; p; p = p->next) { newlink = apr_pmemdup(pool, p, sizeof(mod_filter_chain)); /** Filter out merged chain resets */ if (newlink->fname == NULL) { conf->chain = savelink = newlink; } else if (savelink) { savelink->next = newlink; savelink = newlink; } else { conf->chain = savelink = newlink; } } } else if (add->chain) { conf->chain = add->chain; } else { conf->chain = base->chain; } return conf;}static const command_rec filter_cmds[] = { AP_INIT_TAKE12("FilterDeclare", filter_declare, NULL, OR_OPTIONS, "filter-name [, filter-type]"), /** we don't have a TAKE4, so we have to use RAW_ARGS */ AP_INIT_RAW_ARGS("FilterProvider", filter_provider, NULL, OR_OPTIONS, "filter-name, provider-name, dispatch--criterion, dispatch-match"), AP_INIT_ITERATE("FilterChain", filter_chain, NULL, OR_OPTIONS, "list of filter names with optional [+-=!@]"), AP_INIT_TAKE2("FilterTrace", filter_debug, NULL, RSRC_CONF | ACCESS_CONF, "Debug level"),#ifndef NO_PROTOCOL AP_INIT_TAKE23("FilterProtocol", filter_protocol, NULL, OR_OPTIONS, "filter-name [provider-name] protocol-args"),#endif { NULL }};module AP_MODULE_DECLARE_DATA filter_module = { STANDARD20_MODULE_STUFF, filter_config, filter_merge, NULL, NULL, filter_cmds, filter_hooks};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -