]> granicus.if.org Git - apache/commitdiff
Move AddOutputFilterByType implementation from core to mod_filter.
authorNick Kew <niq@apache.org>
Thu, 22 Jul 2010 21:54:39 +0000 (21:54 +0000)
committerNick Kew <niq@apache.org>
Thu, 22 Jul 2010 21:54:39 +0000 (21:54 +0000)
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@966869 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
include/http_core.h
modules/filters/mod_filter.c
modules/http/http_protocol.c
server/core.c

diff --git a/CHANGES b/CHANGES
index 96d99b42d544ee887b9249166a361f83ac76edfd..66a3d15b2ffd317c6a737b4761148b18358dcf1e 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -46,6 +46,11 @@ Changes with Apache 2.3.7
   *) Update SSL cipher suite and add example for SSLHonorCipherOrder.
      [Lars Eilebrecht, Rainer Jung]
 
+  *) move AddOutputFilterByType from core to mod_filter.  This should
+     fix nasty side-effects that happen when content_type is set
+     more than once in processing a request, and make it fully
+     compatible with dynamic and proxied contents. [Nick Kew]
+
 Changes with Apache 2.3.6
 
   *) SECURITY: CVE-2009-3555 (cve.mitre.org)
index ed334ba50332f88ba4fe9917f9f7767423ec4ce3..82a0a4687c11fafc4f1e68fcb6b984dd2a195dd7 100644 (file)
@@ -507,8 +507,6 @@ typedef struct {
     const char *input_filters;   /* forced with SetInputFilters */
     int accept_path_info;        /* forced with AcceptPathInfo */
 
-    apr_hash_t *ct_output_filters; /* added with AddOutputFilterByType */
-
     /*
      * What attributes/data should be included in ETag generation?
      */
index dd2c9795160e574e7757d725e01b77e1df4450b0..dc48a80b5f37b85be58be55537af80e3c71d5126 100644 (file)
@@ -436,7 +436,6 @@ static const char *filter_provider(cmd_parms *cmd, void *CFG,
 
     return NULL;
 }
-
 static const char *filter_chain(cmd_parms *cmd, void *CFG, const char *arg)
 {
     mod_filter_chain *p;
@@ -511,6 +510,48 @@ static const char *filter_chain(cmd_parms *cmd, void *CFG, const char *arg)
 
     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)
@@ -642,6 +683,8 @@ static const command_rec filter_cmds[] = {
         "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"),
index 54814a92d921bb81add6bc3cccfde823ac519775..f8010b294fa6bbdf526d564597751eff894fc479 100644 (file)
@@ -846,13 +846,6 @@ AP_DECLARE(void) ap_set_content_type(request_rec *r, const char *ct)
     }
     else if (!r->content_type || strcmp(r->content_type, ct)) {
         r->content_type = ct;
-
-        /* Insert filters requested by the AddOutputFiltersByType
-         * configuration directive. Content-type filters must be
-         * inserted after the content handlers have run because
-         * only then, do we reliably know the content-type.
-         */
-        ap_add_output_filters_by_type(r);
     }
 }
 
index ce8e4cd4c9f4a8f7e6a850cd0d16bbcd6958091a..98a183bf2fd45eab2836655b3fd11e56d459dd5b 100644 (file)
@@ -161,60 +161,6 @@ static void *create_core_dir_config(apr_pool_t *a, char *dir)
     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;
@@ -373,21 +319,6 @@ static void *merge_core_dir_configs(apr_pool_t *a, void *basev, void *newv)
         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.
      */
@@ -3154,87 +3085,6 @@ AP_DECLARE(int) ap_is_recursion_limit_exceeded(const request_rec *r)
     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)
 {
@@ -3445,9 +3295,6 @@ AP_INIT_TAKE1("SetOutputFilter", ap_set_string_slot,
 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'"),