⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mod_filter.c

📁 Apache官方在今天放出产品系列2.2的最新版本2.2.11的源码包 最流行的HTTP服务器软件之一
💻 C
📖 第 1 页 / 共 2 页
字号:
        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 + -