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
