return NULL;
}
-
static const char *filter_chain(cmd_parms *cmd, void *CFG, const char *arg)
{
mod_filter_chain *p;
return NULL;
}
+static const char *filter_bytype(cmd_parms *cmd, void *CFG,
+ const char *pname, const char *type)
+{
+ char *etype;
+ char *p;
+ const char *rv;
+ const char *fname;
+ const char *expr;
+ int seen_name = 0;
+ mod_filter_cfg *cfg = CFG;
+
+ /* construct fname from name */
+ fname = apr_pstrcat(cmd->pool, "BYTYPE:", pname, NULL);
+
+ /* check whether this is already registered, in which case
+ * it's already in the filter chain
+ */
+ if (apr_hash_get(cfg->live_filters, fname, APR_HASH_KEY_STRING)) {
+ seen_name = 1;
+ }
+
+ /* build expression: "$content-type = /^type/"
+ * Need to escape slashes in content-type
+ */
+ p = etype = apr_palloc(cmd->temp_pool, 2*strlen(type)+1);
+ do {
+ if (*type == '/') {
+ *p++ = '\\';
+ }
+ *p++ = *type++;
+ } while (*type);
+ *p = 0;
+ expr = apr_psprintf(cmd->temp_pool, "$content-type = /^%s/", etype);
+
+ rv = filter_provider(cmd, CFG, fname, pname, expr);
+
+ /* If it's the first time through, add to filterchain */
+ if (rv == NULL && !seen_name) {
+ rv = filter_chain(cmd, CFG, fname);
+ }
+ return rv;
+}
static const char *filter_debug(cmd_parms *cmd, void *CFG, const char *fname,
const char *level)
"list of filter names with optional [+-=!@]"),
AP_INIT_TAKE2("FilterTrace", filter_debug, NULL, RSRC_CONF | ACCESS_CONF,
"filter-name debug-level"),
+ AP_INIT_ITERATE2("AddOutputFilterByType", filter_bytype, NULL, OR_FILEINFO,
+ "DEPRECATED: output filter name followed by one or more content-types"),
#ifndef NO_PROTOCOL
AP_INIT_TAKE23("FilterProtocol", filter_protocol, NULL, OR_OPTIONS,
"filter-name [provider-name] protocol-args"),
return (void *)conf;
}
-/*
- * Overlay one hash table of ct_output_filters onto another
- */
-static void *merge_ct_filters(apr_pool_t *p,
- const void *key,
- apr_ssize_t klen,
- const void *overlay_val,
- const void *base_val,
- const void *data)
-{
- ap_filter_rec_t *cur;
- const ap_filter_rec_t *overlay_info = (const ap_filter_rec_t *)overlay_val;
- const ap_filter_rec_t *base_info = (const ap_filter_rec_t *)base_val;
-
- cur = NULL;
-
- while (overlay_info) {
- ap_filter_rec_t *new;
-
- new = apr_pcalloc(p, sizeof(ap_filter_rec_t));
- new->name = apr_pstrdup(p, overlay_info->name);
- new->next = cur;
- cur = new;
- overlay_info = overlay_info->next;
- }
-
- while (base_info) {
- ap_filter_rec_t *f;
- int found = 0;
-
- /* We can't have dups. */
- f = cur;
- while (f) {
- if (!strcasecmp(base_info->name, f->name)) {
- found = 1;
- break;
- }
-
- f = f->next;
- }
-
- if (!found) {
- f = apr_pcalloc(p, sizeof(ap_filter_rec_t));
- f->name = apr_pstrdup(p, base_info->name);
- f->next = cur;
- cur = f;
- }
-
- base_info = base_info->next;
- }
-
- return cur;
-}
-
static void *merge_core_dir_configs(apr_pool_t *a, void *basev, void *newv)
{
core_dir_config *base = (core_dir_config *)basev;
conf->input_filters = new->input_filters;
}
- if (conf->ct_output_filters && new->ct_output_filters) {
- conf->ct_output_filters = apr_hash_merge(a,
- new->ct_output_filters,
- conf->ct_output_filters,
- merge_ct_filters,
- NULL);
- }
- else if (new->ct_output_filters) {
- conf->ct_output_filters = apr_hash_copy(a, new->ct_output_filters);
- }
- else if (conf->ct_output_filters) {
- /* That memcpy above isn't enough. */
- conf->ct_output_filters = apr_hash_copy(a, base->ct_output_filters);
- }
-
/*
* Now merge the setting of the FileETag directive.
*/
return 0;
}
-static const char *add_ct_output_filters(cmd_parms *cmd, void *conf_,
- const char *arg, const char *arg2)
-{
- core_dir_config *conf = conf_;
- ap_filter_rec_t *old, *new = NULL;
- const char *filter_name;
-
- if (!conf->ct_output_filters) {
- conf->ct_output_filters = apr_hash_make(cmd->pool);
- old = NULL;
- }
- else {
- old = (ap_filter_rec_t*) apr_hash_get(conf->ct_output_filters, arg2,
- APR_HASH_KEY_STRING);
- /* find last entry */
- if (old) {
- while (old->next) {
- old = old->next;
- }
- }
- }
-
- while (*arg &&
- (filter_name = ap_getword(cmd->pool, &arg, ';')) &&
- strcmp(filter_name, "")) {
- new = apr_pcalloc(cmd->pool, sizeof(ap_filter_rec_t));
- new->name = filter_name;
-
- /* We found something, so let's append it. */
- if (old) {
- old->next = new;
- }
- else {
- apr_hash_set(conf->ct_output_filters, arg2,
- APR_HASH_KEY_STRING, new);
- }
- old = new;
- }
-
- if (!new) {
- return "invalid filter name";
- }
-
- return NULL;
-}
-/*
- * Insert filters requested by the AddOutputFilterByType
- * configuration directive. We cannot add filters based
- * on content-type until after the handler has started
- * to run. Only then do we reliably know the content-type.
- */
-void ap_add_output_filters_by_type(request_rec *r)
-{
- core_dir_config *conf;
- const char *ctype;
-
- conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
- &core_module);
-
- /* We can't do anything with no content-type or if we don't have a
- * filter configured.
- */
- if (!r->content_type || !conf->ct_output_filters) {
- return;
- }
-
- /* remove c-t decoration */
- ctype = ap_field_noparam(r->pool, r->content_type);
- if (ctype) {
- ap_filter_rec_t *ct_filter;
- ct_filter = apr_hash_get(conf->ct_output_filters, ctype,
- APR_HASH_KEY_STRING);
- while (ct_filter) {
- ap_add_output_filter(ct_filter->name, NULL, r, r->connection);
- ct_filter = ct_filter->next;
- }
- }
-
- return;
-}
-
static const char *set_trace_enable(cmd_parms *cmd, void *dummy,
const char *arg1)
{
AP_INIT_TAKE1("SetInputFilter", ap_set_string_slot,
(void *)APR_OFFSETOF(core_dir_config, input_filters), OR_FILEINFO,
"filter (or ; delimited list of filters) to be run on the request body"),
-AP_INIT_ITERATE2("AddOutputFilterByType", add_ct_output_filters,
- (void *)APR_OFFSETOF(core_dir_config, ct_output_filters), OR_FILEINFO,
- "output filter name followed by one or more content-types"),
AP_INIT_FLAG("AllowEncodedSlashes", set_allow2f, NULL, RSRC_CONF,
"Allow URLs containing '/' encoded as '%2F'"),