static const char *add_filter(cmd_parms *cmd, void *CFG,
                              const char *fname, const char *pname,
                              const char *expr, const char **types)
{
    mod_filter_cfg *cfg = CFG;
    ap_filter_provider_t *provider;
    const char *c;
    ap_filter_rec_t* frec;
    ap_filter_rec_t* provider_frec;
    ap_expr_info_t *node;
    const char *err = NULL;

    /* 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 (expr) {
        node = ap_expr_parse_cmd(cmd, expr, 0, &err, NULL);
        if (err) {
            return apr_pstrcat(cmd->pool,
                               "Error parsing FilterProvider expression:", err,
                               NULL);
        }
        provider->expr = node;
        provider->types = NULL;
    }
    else {
        provider->types = types;
        provider->expr = NULL;
    }
    provider->frec = provider_frec;
    provider->next = frec->providers;
    frec->providers = provider;
    return NULL;
}
Exemple #2
0
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) {
        provider_frec = apr_hash_get(cfg->live_filters, pname,
                                     APR_HASH_KEY_STRING);
    }
    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);
        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;
}