On Mon, Feb 18, 2002 at 09:49:27AM -0600, William A. Rowe, Jr. wrote:
> -1.  It requires the user to install mod_mime.  mod_mime handles mime types
> for files, if the server is filesystem-less (a distinct possibility in 2.1 and
> beyond, even in 2.0 for that matter, but not trivial) then they lose this legit
> directive.
> 
> Please make this a core directive, as I've already moved SetHandler and the
> Set{Input|Output}Filter directives.  No sense in populating more cruft in the
> wrong module.

Well, it wasn't like I didn't see this veto coming a mile away.
This patch is much more complicated since it has to essentially
duplicate logic that mod_mime already has.

I'll commit this soon-ish unless you scream.  -- justin

Index: include/ap_mmn.h
===================================================================
RCS file: /home/cvs/httpd-2.0/include/ap_mmn.h,v
retrieving revision 1.32
diff -u -r1.32 ap_mmn.h
--- include/ap_mmn.h    29 Jan 2002 00:00:39 -0000      1.32
+++ include/ap_mmn.h    19 Feb 2002 00:17:04 -0000
@@ -95,12 +95,13 @@
  * 20020118 (2.0.31-dev) Input filtering split of blocking and mode
  * 20020127 (2.0.31-dev) bump for pre_mpm hook change
  * 20020128 (2.0.31-dev) bump for pre_config hook change
+ * 20020218 (2.0.33-dev) bump for AddOutputFilterByType directive
  */
 
 #define MODULE_MAGIC_COOKIE 0x41503230UL /* "AP20" */
 
 #ifndef MODULE_MAGIC_NUMBER_MAJOR
-#define MODULE_MAGIC_NUMBER_MAJOR 20020128
+#define MODULE_MAGIC_NUMBER_MAJOR 20020218
 #endif
 #define MODULE_MAGIC_NUMBER_MINOR 0                     /* 0...n */
 #define MODULE_MAGIC_NUMBER MODULE_MAGIC_NUMBER_MAJOR  /* backward compat */
Index: include/http_core.h
===================================================================
RCS file: /home/cvs/httpd-2.0/include/http_core.h,v
retrieving revision 1.61
diff -u -r1.61 http_core.h
--- include/http_core.h 27 Jan 2002 19:12:56 -0000      1.61
+++ include/http_core.h 19 Feb 2002 00:17:04 -0000
@@ -507,6 +507,8 @@
     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: server/core.c
===================================================================
RCS file: /home/cvs/httpd-2.0/server/core.c,v
retrieving revision 1.148
diff -u -r1.148 core.c
--- server/core.c       17 Feb 2002 19:21:31 -0000      1.148
+++ server/core.c       19 Feb 2002 00:17:13 -0000
@@ -183,6 +183,56 @@
     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;
+            }
+            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;
@@ -344,6 +394,21 @@
         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.
      */
@@ -2359,6 +2424,34 @@
 }
 #endif
 
+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;
+
+    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);
+    }
+
+    new = apr_pcalloc(cmd->pool, sizeof(ap_filter_rec_t));
+    new->name = apr_pstrdup(cmd->pool, arg);
+
+    /* We found something, so let's append it.  */ 
+    if (old) {
+        new->next = old;
+    }
+
+    apr_hash_set(conf->ct_output_filters, arg2, APR_HASH_KEY_STRING, new);
+    
+    return NULL; 
+}
+
 static apr_status_t writev_it_all(apr_socket_t *s,
                                   struct iovec *vec, int nvec,
                                   apr_size_t len, apr_size_t *nbytes)
@@ -2737,6 +2830,9 @@
 AP_INIT_TAKE1("SetInputFilter", ap_set_string_slot, 
        (void *)APR_XtOffsetOf(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_XtOffsetOf(core_dir_config, ct_output_filters), OR_FILEINFO,
+     "output filter name (or ; delimited names) followed by one or more 
+content-types"),
 
 /*
  * These are default configuration directives that mpms can/should
@@ -2879,6 +2975,35 @@
     return OK;
 }
 
+static int core_filters_type(request_rec *r)
+{
+    core_dir_config *conf;
+    const char *ctype, *ctypes;
+
+    conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
+                                                   &core_module);
+
+    /* We can't do anything with proxy requests or if we don't have a filter
+     * configured. */ 
+    if (r->proxyreq != PROXYREQ_NONE || !conf->ct_output_filters) {
+        return OK;
+    }
+
+    ctypes = r->content_type;
+  
+    /* We must be able to handle decorated content-types.  */
+    while (*ctypes && (ctype = ap_getword(r->pool, &ctypes, ';'))) {
+        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 OK;
+}
 
 static int default_handler(request_rec *r)
 {
@@ -3738,6 +3863,7 @@
     /* FIXME: I suspect we can eliminate the need for these do_nothings - Ben */
     ap_hook_type_checker(do_nothing,NULL,NULL,APR_HOOK_REALLY_LAST);
     ap_hook_fixups(core_override_type,NULL,NULL,APR_HOOK_REALLY_FIRST);
+    ap_hook_fixups(core_filters_type,NULL,NULL,APR_HOOK_MIDDLE);
     ap_hook_access_checker(do_nothing,NULL,NULL,APR_HOOK_REALLY_LAST);
     ap_hook_create_request(core_create_req, NULL, NULL, APR_HOOK_MIDDLE);
     APR_OPTIONAL_HOOK(proxy, create_req, core_create_proxy_req, NULL, NULL, 

Reply via email to