]> granicus.if.org Git - apache/commitdiff
Add a filter_init function to the filters so that a filter can execute
authorJustin Erenkrantz <jerenkrantz@apache.org>
Fri, 28 Jun 2002 08:40:25 +0000 (08:40 +0000)
committerJustin Erenkrantz <jerenkrantz@apache.org>
Fri, 28 Jun 2002 08:40:25 +0000 (08:40 +0000)
arbitrary code before the handlers are invoked.

This resolves an issue with incorrect 304s on If-Modified-Since mod_include
requests since ap_meets_conditions() is not aware that this is a dynamic
request and it is not possible to satisfy 304 for these requests (unless
xbithack full is on, of course).  When mod_include runs as a filter, it is
too late to set any flag since the handler is responsible for calling
ap_meets_conditions(), which it should do before generating any data.

If a module doesn't need to run such arbitrary code, it can just pass NULL
as the argument and all is well.

PR: 9673
Reviewed by: Ryan Bloom and others

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@95906 13f79535-47bb-0310-9956-ffa450edef68

18 files changed:
CHANGES
include/ap_mmn.h
include/util_filter.h
modules/experimental/mod_cache.c
modules/experimental/mod_case_filter.c
modules/experimental/mod_case_filter_in.c
modules/experimental/mod_charset_lite.c
modules/experimental/mod_ext_filter.c
modules/filters/mod_deflate.c
modules/filters/mod_include.c
modules/http/http_core.c
modules/metadata/mod_headers.c
modules/proxy/proxy_ftp.c
modules/ssl/ssl_engine_io.c
modules/test/mod_bucketeer.c
server/config.c
server/core.c
server/util_filter.c

diff --git a/CHANGES b/CHANGES
index 25358a51ffa87cb07ae1ed9125105edca0d4b2a9..2975bf94735126bd23c9590964e7c82ca97e931f 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,5 +1,10 @@
 Changes with Apache 2.0.40
 
+  *) Add a filter_init parameter to the filter registration functions
+     so that a filter can execute arbitrary code before the handlers
+     are invoked.  This resolves a problem where mod_include requests
+     would incorrectly return a 304.  [Justin Erenkrantz]
+
   *) Fix a long-standing bug in 2.0, CGI scripts were being called
      with relative paths instead of absolute paths.  Apache 1.3 used
      absolute paths for everything except for SuExec, this brings back
index 58b7a7fc4368450899f7d8d9c2b1d8948aee23b9..35b343894062bab4eb66629022b3e7313b28b2ee 100644 (file)
  * 20020602 (2.0.37-dev) Bucket API change (metadata buckets)
  * 20020612 (2.0.38-dev) Changed server_rec->[keep_alive_]timeout to apr time
  * 20020625 (2.0.40-dev) Changed conn_rec->keepalive to an enumeration
+ * 20020628 (2.0.40-dev) Added filter_init to filter registration functions
  */
 
 #define MODULE_MAGIC_COOKIE 0x41503230UL /* "AP20" */
 
 #ifndef MODULE_MAGIC_NUMBER_MAJOR
-#define MODULE_MAGIC_NUMBER_MAJOR 20020625
+#define MODULE_MAGIC_NUMBER_MAJOR 20020628
 #endif
 #define MODULE_MAGIC_NUMBER_MINOR 0                     /* 0...n */
 
index 88f0587947fc0689ab24947c74eb71fbe0d6b975..0a9954e04ab9a93be787e92ca76552aa2f509f2f 100644 (file)
@@ -153,12 +153,19 @@ typedef struct ap_filter_t ap_filter_t;
  * for setting the association between a name for a filter and its 
  * associated callback (and other information).
  *
+ * If the initialization function argument passed to the registration
+ * functions is non-NULL, it will be called iff the filter is in the input
+ * or output filter chains and before any data is generated to allow the
+ * filter to prepare for processing.
+ *
  * The *bucket structure (and all those referenced by ->next and ->prev)
  * should be considered "const". The filter is allowed to modify the
  * next/prev to insert/remove/replace elements in the bucket list, but
  * the types and values of the individual buckets should not be altered.
  *
- * The return value of a filter should be an APR status value.
+ * For the input and output filters, the return value of a filter should be
+ * an APR status value.  For the init function, the return value should
+ * be an HTTP error code or OK if it was successful.
  * 
  * @ingroup filter
  * @{
@@ -170,6 +177,7 @@ typedef apr_status_t (*ap_in_filter_func)(ap_filter_t *f,
                                           ap_input_mode_t mode,
                                           apr_read_type_e block,
                                           apr_off_t readbytes);
+typedef int (*ap_init_filter_func)(ap_filter_t *f);
 
 typedef union ap_filter_func {
     ap_out_filter_func out_func;
@@ -242,6 +250,8 @@ struct ap_filter_rec_t {
     const char *name;
     /** The function to call when this filter is invoked. */
     ap_filter_func filter_func;
+    /** The function to call before the handlers are invoked. */
+    ap_init_filter_func filter_init_func;
     /** The type of filter, either AP_FTYPE_CONTENT or AP_FTYPE_CONNECTION.  
      * An AP_FTYPE_CONTENT filter modifies the data based on information 
      * found in the content.  An AP_FTYPE_CONNECTION filter modifies the 
@@ -259,8 +269,8 @@ struct ap_filter_rec_t {
  * requests get an exact copy of the main requests filter chain.
  */
 struct ap_filter_t {
-     /** The internal representation of this filter.  This includes
-      *  the filter's name, type, and the actual function pointer.
+    /** The internal representation of this filter.  This includes
+     *  the filter's name, type, and the actual function pointer.
      */
     ap_filter_rec_t *frec;
 
@@ -324,6 +334,7 @@ AP_DECLARE(apr_status_t) ap_pass_brigade(ap_filter_t *filter,
  */
 AP_DECLARE(ap_filter_rec_t *) ap_register_input_filter(const char *name,
                                           ap_in_filter_func filter_func,
+                                          ap_init_filter_func filter_init,
                                           ap_filter_type ftype);
 /**
  * This function is used to register an output filter with the system. 
@@ -339,6 +350,7 @@ AP_DECLARE(ap_filter_rec_t *) ap_register_input_filter(const char *name,
  */
 AP_DECLARE(ap_filter_rec_t *) ap_register_output_filter(const char *name,
                                             ap_out_filter_func filter_func,
+                                            ap_init_filter_func filter_init,
                                             ap_filter_type ftype);
 
 /**
index a11a5a5ca0cca74681b4d38ca0a752021e53f5c8..d55a099752364c7e51512561ce340eed79238422 100644 (file)
@@ -981,6 +981,7 @@ register_hooks(apr_pool_t *p)
      */
     ap_register_output_filter("CACHE_IN", 
                               cache_in_filter, 
+                              NULL,
                               AP_FTYPE_CONTENT_SET);
     /* CACHE_OUT must go into the filter chain before SUBREQ_CORE to
      * handle subrequsts. Decrementing filter type by 1 ensures this 
@@ -988,9 +989,11 @@ register_hooks(apr_pool_t *p)
      */
     ap_register_output_filter("CACHE_OUT", 
                               cache_out_filter, 
+                              NULL,
                               AP_FTYPE_CONTENT_SET-1);
     ap_register_output_filter("CACHE_CONDITIONAL", 
                               cache_conditional_filter, 
+                              NULL,
                               AP_FTYPE_CONTENT_SET);
     ap_hook_post_config(cache_post_config, NULL, NULL, APR_HOOK_REALLY_FIRST);
 }
index 869d7633735707e2d215baa6f655108be12a67b2..5aaab7744ed4d1aa4af7aeb2ca7ce30f2ea396bb 100644 (file)
@@ -98,7 +98,7 @@ static const command_rec CaseFilterCmds[] =
 static void CaseFilterRegisterHooks(apr_pool_t *p)
     {
     ap_hook_insert_filter(CaseFilterInsertFilter,NULL,NULL,APR_HOOK_MIDDLE);
-    ap_register_output_filter(s_szCaseFilterName,CaseFilterOutFilter,
+    ap_register_output_filter(s_szCaseFilterName,CaseFilterOutFilter,NULL,
                              AP_FTYPE_RESOURCE);
     }
 
index 8e25763cff11fc4521605cecdbbab277c97b8eb4..bda8aacf8180d20eda34ca961e4f84c46e353a15 100644 (file)
@@ -182,7 +182,7 @@ static void CaseFilterInRegisterHooks(apr_pool_t *p)
 {
     ap_hook_insert_filter(CaseFilterInInsertFilter, NULL, NULL, 
                           APR_HOOK_MIDDLE);
-    ap_register_input_filter(s_szCaseFilterName, CaseFilterInFilter,
+    ap_register_input_filter(s_szCaseFilterName, CaseFilterInFilter, NULL,
                              AP_FTYPE_RESOURCE);
 }
 
index 2b1fc9ffa85e3cabca0c002ecc3f49bda99522b7..48f13060f84df1307378ef9b8025d5ba40466e2e 100644 (file)
@@ -1105,9 +1105,9 @@ static void charset_register_hooks(apr_pool_t *p)
 {
     ap_hook_fixups(find_code_page, NULL, NULL, APR_HOOK_MIDDLE);
     ap_hook_insert_filter(xlate_insert_filter, NULL, NULL, APR_HOOK_REALLY_LAST);
-    ap_register_output_filter(XLATEOUT_FILTER_NAME, xlate_out_filter, 
+    ap_register_output_filter(XLATEOUT_FILTER_NAME, xlate_out_filter, NULL,
                               AP_FTYPE_RESOURCE);
-    ap_register_input_filter(XLATEIN_FILTER_NAME, xlate_in_filter, 
+    ap_register_input_filter(XLATEIN_FILTER_NAME, xlate_in_filter, NULL,
                              AP_FTYPE_RESOURCE);
 }
 
index ef95399855d9eaf2915604a2541690de545fe44a..b028ab4300d6203d0de86fa3d0644525d49ef9ea 100644 (file)
@@ -312,12 +312,12 @@ static const char *define_filter(cmd_parms *cmd, void *dummy, const char *args)
      */
     if (filter->mode == OUTPUT_FILTER) {
         /* XXX need a way to ensure uniqueness among all filters */
-        ap_register_output_filter(filter->name, ef_output_filter, AP_FTYPE_RESOURCE);
+        ap_register_output_filter(filter->name, ef_output_filter, NULL, AP_FTYPE_RESOURCE);
     }
 #if 0              /* no input filters yet */
     else if (filter->mode == INPUT_FILTER) {
         /* XXX need a way to ensure uniqueness among all filters */
-        ap_register_input_filter(filter->name, ef_input_filter, AP_FTYPE_RESOURCE);
+        ap_register_input_filter(filter->name, ef_input_filter, NULL, AP_FTYPE_RESOURCE);
     }
 #endif
     else {
index 82b2d9ff2310582cfa0e80a564227ea0429fd8da..83e45446dfb730b400cdc60739e4a9f86e8feb0c 100644 (file)
@@ -760,9 +760,9 @@ static apr_status_t deflate_in_filter(ap_filter_t *f,
 
 static void register_hooks(apr_pool_t *p)
 {
-    ap_register_output_filter(deflateFilterName, deflate_out_filter,
+    ap_register_output_filter(deflateFilterName, deflate_out_filter, NULL,
                               AP_FTYPE_CONTENT_SET);
-    ap_register_input_filter(deflateFilterName, deflate_in_filter,
+    ap_register_input_filter(deflateFilterName, deflate_in_filter, NULL,
                               AP_FTYPE_CONTENT_SET);
 }
 
index 4e9669583163290be38d09d5cd2767120662d061..9a52aec9dddf05ed2e35fdd9009baadfef801120 100644 (file)
@@ -3323,6 +3323,26 @@ static const char *set_xbithack(cmd_parms *cmd, void *xbp, const char *arg)
     return NULL;
 }
 
+static int includes_setup(ap_filter_t *f)
+{
+    include_dir_config *conf = 
+               (include_dir_config *)ap_get_module_config(f->r->per_dir_config,
+                                                          &include_module);
+
+    /* When our xbithack value isn't set to full or our platform isn't
+     * providing group-level protection bits or our group-level bits do not
+     * have group-execite on, we will set the no_local_copy value to 1 so
+     * that we will not send 304s.
+     */
+    if ((*conf->xbithack != xbithack_full)
+        || !(f->r->finfo.valid & APR_FINFO_GPROT)
+        || !(f->r->finfo.protection & APR_GEXECUTE)) {
+        f->r->no_local_copy = 1;
+    }
+    
+    return OK;
+}
+
 static apr_status_t includes_filter(ap_filter_t *f, apr_bucket_brigade *b)
 {
     request_rec *r = f->r;
@@ -3556,7 +3576,8 @@ static void register_hooks(apr_pool_t *p)
     APR_REGISTER_OPTIONAL_FN(ap_register_include_handler);
     ap_hook_post_config(include_post_config, NULL, NULL, APR_HOOK_REALLY_FIRST);
     ap_hook_fixups(include_fixup, NULL, NULL, APR_HOOK_LAST);
-    ap_register_output_filter("INCLUDES", includes_filter, AP_FTYPE_RESOURCE);
+    ap_register_output_filter("INCLUDES", includes_filter, includes_setup,
+                              AP_FTYPE_RESOURCE);
 }
 
 module AP_MODULE_DECLARE_DATA include_module =
index 9db75533fcbc2814f6d4d677cb12a480f198037e..8bd0fb7e8d3c28d2133face362feb1fe0a80f5ac 100644 (file)
@@ -330,15 +330,16 @@ static void register_hooks(apr_pool_t *p)
     ap_hook_create_request(http_create_request, NULL, NULL, APR_HOOK_REALLY_LAST);
     ap_http_input_filter_handle =
         ap_register_input_filter("HTTP_IN", ap_http_filter,
-                                 AP_FTYPE_PROTOCOL);
+                                 NULL, AP_FTYPE_PROTOCOL);
     ap_http_header_filter_handle =
         ap_register_output_filter("HTTP_HEADER", ap_http_header_filter, 
-                                  AP_FTYPE_PROTOCOL);
+                                  NULL, AP_FTYPE_PROTOCOL);
     ap_chunk_filter_handle =
-        ap_register_output_filter("CHUNK", chunk_filter, AP_FTYPE_TRANSCODE);
+        ap_register_output_filter("CHUNK", chunk_filter,
+                                  NULL, AP_FTYPE_TRANSCODE);
     ap_byterange_filter_handle =
         ap_register_output_filter("BYTERANGE", ap_byterange_filter,
-                                  AP_FTYPE_PROTOCOL);
+                                  NULL, AP_FTYPE_PROTOCOL);
     ap_method_registry_init(p);
 }
 
index dee922a66e312fb1e812b197c710a01bd7795992..cf42cdfb43494e3dd05438ae6745a76ee3e9b913 100644 (file)
@@ -620,7 +620,8 @@ static void register_hooks(apr_pool_t *p)
     ap_hook_pre_config(header_pre_config,NULL,NULL,APR_HOOK_MIDDLE);
     ap_hook_insert_filter(ap_headers_insert_output_filter, NULL, NULL, APR_HOOK_LAST);
     ap_hook_fixups(ap_headers_fixup, NULL, NULL, APR_HOOK_LAST);
-    ap_register_output_filter("FIXUP_HEADERS_OUT", ap_headers_output_filter, AP_FTYPE_CONTENT_SET);
+    ap_register_output_filter("FIXUP_HEADERS_OUT", ap_headers_output_filter,
+                              NULL, AP_FTYPE_CONTENT_SET);
 }
 
 module AP_MODULE_DECLARE_DATA headers_module =
index a4c77d3a41d1de562743f403f35bd7c5d47a081b..dea106ad96568836b932f37c5b96004b0e9a37fe 100644 (file)
@@ -1926,7 +1926,8 @@ static void ap_proxy_ftp_register_hook(apr_pool_t *p)
     proxy_hook_scheme_handler(ap_proxy_ftp_handler, NULL, NULL, APR_HOOK_MIDDLE);
     proxy_hook_canon_handler(ap_proxy_ftp_canon, NULL, NULL, APR_HOOK_MIDDLE);
     /* filters */
-    ap_register_output_filter("PROXY_SEND_DIR", ap_proxy_send_dir_filter, AP_FTYPE_RESOURCE);
+    ap_register_output_filter("PROXY_SEND_DIR", ap_proxy_send_dir_filter,
+                              NULL, AP_FTYPE_RESOURCE);
 }
 
 module AP_MODULE_DECLARE_DATA proxy_ftp_module = {
index 47e76329c49ee57a9829c53c5f39d09d50bf077e..cdb6c965c6b172bc5f6b00d925bb0509fd3090ea 100644 (file)
@@ -943,8 +943,8 @@ void ssl_io_filter_init(conn_rec *c, SSL *ssl)
 
 void ssl_io_filter_register(apr_pool_t *p)
 {
-    ap_register_input_filter  (ssl_io_filter, ssl_io_filter_Input,  AP_FTYPE_CONNECTION + 5);
-    ap_register_output_filter (ssl_io_filter, ssl_io_filter_Output, AP_FTYPE_CONNECTION + 5);
+    ap_register_input_filter  (ssl_io_filter, ssl_io_filter_Input,  NULL, AP_FTYPE_CONNECTION + 5);
+    ap_register_output_filter (ssl_io_filter, ssl_io_filter_Output, NULL, AP_FTYPE_CONNECTION + 5);
     return;
 }
 
index 6738cd69cc2a90d450fb93d26a729b802abf7266..f8e4130a48b52bba8991158c1694835c0fcfb327 100644 (file)
@@ -201,7 +201,7 @@ static apr_status_t bucketeer_out_filter(ap_filter_t *f,
 static void register_hooks(apr_pool_t * p)
 {
     ap_register_output_filter(bucketeerFilterName, bucketeer_out_filter,
-                              AP_FTYPE_RESOURCE-1);
+                              NULL, AP_FTYPE_RESOURCE-1);
 }
 
 static const command_rec bucketeer_filter_cmds[] = {
index d8932345da8ccbdf2f95a079aaa8825408a98d0a..1de993011919f7e0c8bfedbf2925a8b5a474db32 100644 (file)
@@ -335,6 +335,20 @@ AP_CORE_DECLARE(ap_conf_vector_t *) ap_create_per_dir_config(apr_pool_t *p)
     return create_empty_config(p);
 }
 
+static int ap_invoke_filter_init(ap_filter_t *filters)
+{
+    while (filters) {
+        if (filters->frec->filter_init_func) {
+            int result = filters->frec->filter_init_func(filters);
+            if (result != OK) {
+                return result;
+            }
+        }
+        filters = filters->next;
+    } 
+    return OK;
+}
+
 AP_CORE_DECLARE(int) ap_invoke_handler(request_rec *r)
 {
     const char *handler;
@@ -352,6 +366,19 @@ AP_CORE_DECLARE(int) ap_invoke_handler(request_rec *r)
      */
     ap_run_insert_filter(r);
 
+    /* Before continuing, allow each filter that is in the two chains to
+     * run their init function to let them do any magic before we could
+     * start generating data.
+     */
+    result = ap_invoke_filter_init(r->input_filters);
+    if (result != OK) {
+        return result;
+    }
+    result = ap_invoke_filter_init(r->output_filters);
+    if (result != OK) {
+        return result;
+    }
+
     if (!r->handler) {
         handler = r->content_type ? r->content_type : ap_default_type(r);
         if ((p=ap_strchr_c(handler, ';')) != NULL) {
index 23f7641ab352c29ff9eecfc92a0b0df8f52cd2f3..3a066f5ecf7503c4289946fe005172c080ccd06a 100644 (file)
@@ -4098,21 +4098,22 @@ static void register_hooks(apr_pool_t *p)
 
     ap_core_input_filter_handle =
         ap_register_input_filter("CORE_IN", core_input_filter,
-                                 AP_FTYPE_NETWORK);
+                                 NULL, AP_FTYPE_NETWORK);
     ap_net_time_filter_handle =
         ap_register_input_filter("NET_TIME", net_time_filter,
-                                 AP_FTYPE_PROTOCOL);
+                                 NULL, AP_FTYPE_PROTOCOL);
     ap_content_length_filter_handle =
         ap_register_output_filter("CONTENT_LENGTH", ap_content_length_filter,
-                                  AP_FTYPE_PROTOCOL);
+                                  NULL, AP_FTYPE_PROTOCOL);
     ap_core_output_filter_handle =
         ap_register_output_filter("CORE", core_output_filter,
-                                  AP_FTYPE_NETWORK);
+                                  NULL, AP_FTYPE_NETWORK);
     ap_subreq_core_filter_handle =
         ap_register_output_filter("SUBREQ_CORE", ap_sub_req_output_filter,
-                                  AP_FTYPE_CONTENT_SET);
-    ap_old_write_func = ap_register_output_filter("OLD_WRITE",
-                                   ap_old_write_filter, AP_FTYPE_RESOURCE - 10);
+                                  NULL, AP_FTYPE_CONTENT_SET);
+    ap_old_write_func =
+        ap_register_output_filter("OLD_WRITE", ap_old_write_filter,
+                                  NULL, AP_FTYPE_RESOURCE - 10);
 }
 
 AP_DECLARE_DATA module core_module = {
index 314ff69695f2faeabc82840216379b8d1a2c747e..30cfa090e4a46cd86393cb6598d476383fc53461 100644 (file)
@@ -234,6 +234,7 @@ AP_DECLARE(ap_filter_rec_t *)ap_get_input_filter_handle(const char *name)
 
 static ap_filter_rec_t *register_filter(const char *name,
                             ap_filter_func filter_func,
+                            ap_init_filter_func filter_init,
                             ap_filter_type ftype,
                             filter_trie_node **reg_filter_set)
 {
@@ -266,6 +267,7 @@ static ap_filter_rec_t *register_filter(const char *name,
         frec->name = normalized_name;
     }
     frec->filter_func = filter_func;
+    frec->filter_init_func = filter_init;
     frec->ftype = ftype;
     
     apr_pool_cleanup_register(FILTER_POOL, NULL, filter_cleanup, 
@@ -275,20 +277,24 @@ static ap_filter_rec_t *register_filter(const char *name,
 
 AP_DECLARE(ap_filter_rec_t *) ap_register_input_filter(const char *name,
                                           ap_in_filter_func filter_func,
+                                          ap_init_filter_func filter_init,
                                           ap_filter_type ftype)
 {
     ap_filter_func f;
     f.in_func = filter_func;
-    return register_filter(name, f, ftype, &registered_input_filters);
+    return register_filter(name, f, filter_init, ftype,
+                           &registered_input_filters);
 }                                                                    
 
 AP_DECLARE(ap_filter_rec_t *) ap_register_output_filter(const char *name,
                                            ap_out_filter_func filter_func,
+                                           ap_init_filter_func filter_init,
                                            ap_filter_type ftype)
 {
     ap_filter_func f;
     f.out_func = filter_func;
-    return register_filter(name, f, ftype, &registered_output_filters);
+    return register_filter(name, f, filter_init, ftype,
+                           &registered_output_filters);
 }
 
 static ap_filter_t *add_any_filter_handle(ap_filter_rec_t *frec, void *ctx,