in mod_perl 2.0 we register only four filter names (in:out:req:conn) and then we install the actuall perl callbacks using one of these four filter names and storing the actual filter's callback information in f->ctx. If later on we want to do something with an inserted filter we have no API to find it, since it's not identified by name, but the data inside f->ctx. Therefore we need a new API to traverse the filter chain and find what we want using a custom callback.

Here is the API and implementation that I came up with (it needs the docco and the standard DECLARE stuff, which I ask to disregard for now and concentrate on the API/implementation itself; once it's polished I'll post a complete patch).

The function that I'm requesting to add is somewhat similar to apr_table_do.

typedef int (ap_filter_chain_traverse_fh_t)(void *data, ap_filter_t *f);
int ap_filter_chain_traverse(ap_filter_chain_traverse_fh_t *traverse,
                             void *data, ap_filter_t **chain);

int ap_filter_chain_traverse(ap_filter_chain_traverse_fh_t *traverse,
                                    void *data, ap_filter_t **chain)
{
    int rv = 0;
    ap_filter_t *curr = *chain;

    while (curr) {
        if ((rv = (*traverse)(data, curr)) != 0) {
            return rv;
        }
        curr = curr->next;
    }
    return rv;
}

I'm not sure regarding the chain argument. Looking at the util_filter.c, it looks in proto_ and normal chain. Could there be a problem on the caller side?
Won't it be enough to use one of r->output_filters, c->output_filters, r->input_filters, c->input_filters if all I care is the custom filters?


Here is an example of usage by mod_perl 2.0. This is an implementation of a function that will remove a filter by its perl handler name, e.g.:

$r->remove_output_filter("TestHandler::out_filter");

there is a wrapper that translates this perl-side call to C's modperl_filter_remove_by_handler_name().

typedef struct {
    char* filter_name;
    char* handler_name;
    ap_filter_t* f;
} filter_chain_traverse_t;

static int find_filter_by_handler_name(void *data, ap_filter_t *f)
{
    apr_pool_t* p = f->r ? f->r->pool : f->c->pool;
    filter_chain_traverse_t* traverse = (filter_chain_traverse_t*)data;
    char *normalized_name;

    /* 'name' in frec is always lowercased */
    normalized_name = apr_pstrdup(p, traverse->filter_name);
    ap_str_tolower(normalized_name);

    /* skip non-mod_perl filters */
    if (strNE(f->frec->name, normalized_name)) {
        return 0;
    } else {
        modperl_filter_ctx_t *ctx = f->ctx;
        if (strEQ(ctx->handler->name, traverse->handler_name)) {
            traverse->f = f;
            return 1; /* found what we wanted */
        }
    }

    return 0;
}

/*  modperl_filter_remove_by_handler_name(aTHX_ r, c,
 *                                        MP_OUTPUT_FILTER_MODE,
 *                                        "MyFilter::output_lc")
 */
void modperl_filter_remove_by_handler_name(pTHX_ request_rec *r,
                                           conn_rec *c,
                                           modperl_filter_mode_e mode,
                                           char* handler_name)
{
    int rv = 0;
    apr_pool_t *pool = r ? r->pool : c->pool;
    ap_filter_t *f;
    filter_chain_traverse_t *traverse =
        apr_pcalloc(pool, sizeof(filter_chain_traverse_t*));

    /* XXX: generalize for conn/req in/out */
    traverse->filter_name = MP_FILTER_REQUEST_OUTPUT_NAME;
    traverse->handler_name = handler_name;

    rv = ap_filter_chain_traverse(find_filter_by_handler_name, traverse,
                                  &r->output_filters); /* XXX: generalize */
    if (rv) {
        f = traverse->f; /* XXX: validate */
        MP_TRACE_f(MP_FUNC, "found filter handler %s\n", handler_name);
    }
    else {
        Perl_croak(aTHX_ "unable to find filter handler '%s'\n", handler_name);
    }

    MP_TRACE_f(MP_FUNC, "removing filter %s\n", handler_name);
    if (mode == MP_INPUT_FILTER_MODE) {
        ap_remove_input_filter(f);
    }
    else {
        ap_remove_output_filter(f);
    }
}


__________________________________________________________________ Stas Bekman JAm_pH ------> Just Another mod_perl Hacker http://stason.org/ mod_perl Guide ---> http://perl.apache.org mailto:[EMAIL PROTECTED] http://use.perl.org http://apacheweek.com http://modperlbook.org http://apache.org http://ticketmaster.com



Reply via email to