summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CHANGES5
-rw-r--r--include/ap_mmn.h3
-rw-r--r--include/util_filter.h18
-rw-r--r--modules/experimental/mod_cache.c3
-rw-r--r--modules/experimental/mod_case_filter.c2
-rw-r--r--modules/experimental/mod_case_filter_in.c2
-rw-r--r--modules/experimental/mod_charset_lite.c4
-rw-r--r--modules/experimental/mod_ext_filter.c4
-rw-r--r--modules/filters/mod_deflate.c4
-rw-r--r--modules/filters/mod_include.c23
-rw-r--r--modules/http/http_core.c9
-rw-r--r--modules/metadata/mod_headers.c3
-rw-r--r--modules/proxy/proxy_ftp.c3
-rw-r--r--modules/ssl/ssl_engine_io.c4
-rw-r--r--modules/test/mod_bucketeer.c2
-rw-r--r--server/config.c27
-rw-r--r--server/core.c15
-rw-r--r--server/util_filter.c10
18 files changed, 110 insertions, 31 deletions
diff --git a/CHANGES b/CHANGES
index 25358a51ff..2975bf9473 100644
--- 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
diff --git a/include/ap_mmn.h b/include/ap_mmn.h
index 58b7a7fc43..35b3438940 100644
--- a/include/ap_mmn.h
+++ b/include/ap_mmn.h
@@ -109,12 +109,13 @@
* 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 */
diff --git a/include/util_filter.h b/include/util_filter.h
index 88f0587947..0a9954e04a 100644
--- a/include/util_filter.h
+++ b/include/util_filter.h
@@ -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);
/**
diff --git a/modules/experimental/mod_cache.c b/modules/experimental/mod_cache.c
index a11a5a5ca0..d55a099752 100644
--- a/modules/experimental/mod_cache.c
+++ b/modules/experimental/mod_cache.c
@@ -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);
}
diff --git a/modules/experimental/mod_case_filter.c b/modules/experimental/mod_case_filter.c
index 869d763373..5aaab7744e 100644
--- a/modules/experimental/mod_case_filter.c
+++ b/modules/experimental/mod_case_filter.c
@@ -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);
}
diff --git a/modules/experimental/mod_case_filter_in.c b/modules/experimental/mod_case_filter_in.c
index 8e25763cff..bda8aacf81 100644
--- a/modules/experimental/mod_case_filter_in.c
+++ b/modules/experimental/mod_case_filter_in.c
@@ -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);
}
diff --git a/modules/experimental/mod_charset_lite.c b/modules/experimental/mod_charset_lite.c
index 2b1fc9ffa8..48f13060f8 100644
--- a/modules/experimental/mod_charset_lite.c
+++ b/modules/experimental/mod_charset_lite.c
@@ -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);
}
diff --git a/modules/experimental/mod_ext_filter.c b/modules/experimental/mod_ext_filter.c
index ef95399855..b028ab4300 100644
--- a/modules/experimental/mod_ext_filter.c
+++ b/modules/experimental/mod_ext_filter.c
@@ -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 {
diff --git a/modules/filters/mod_deflate.c b/modules/filters/mod_deflate.c
index 82b2d9ff23..83e45446df 100644
--- a/modules/filters/mod_deflate.c
+++ b/modules/filters/mod_deflate.c
@@ -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);
}
diff --git a/modules/filters/mod_include.c b/modules/filters/mod_include.c
index 4e96695831..9a52aec9dd 100644
--- a/modules/filters/mod_include.c
+++ b/modules/filters/mod_include.c
@@ -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 =
diff --git a/modules/http/http_core.c b/modules/http/http_core.c
index 9db75533fc..8bd0fb7e8d 100644
--- a/modules/http/http_core.c
+++ b/modules/http/http_core.c
@@ -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);
}
diff --git a/modules/metadata/mod_headers.c b/modules/metadata/mod_headers.c
index dee922a66e..cf42cdfb43 100644
--- a/modules/metadata/mod_headers.c
+++ b/modules/metadata/mod_headers.c
@@ -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 =
diff --git a/modules/proxy/proxy_ftp.c b/modules/proxy/proxy_ftp.c
index a4c77d3a41..dea106ad96 100644
--- a/modules/proxy/proxy_ftp.c
+++ b/modules/proxy/proxy_ftp.c
@@ -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 = {
diff --git a/modules/ssl/ssl_engine_io.c b/modules/ssl/ssl_engine_io.c
index 47e76329c4..cdb6c965c6 100644
--- a/modules/ssl/ssl_engine_io.c
+++ b/modules/ssl/ssl_engine_io.c
@@ -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;
}
diff --git a/modules/test/mod_bucketeer.c b/modules/test/mod_bucketeer.c
index 6738cd69cc..f8e4130a48 100644
--- a/modules/test/mod_bucketeer.c
+++ b/modules/test/mod_bucketeer.c
@@ -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[] = {
diff --git a/server/config.c b/server/config.c
index d8932345da..1de9930119 100644
--- a/server/config.c
+++ b/server/config.c
@@ -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) {
diff --git a/server/core.c b/server/core.c
index 23f7641ab3..3a066f5ecf 100644
--- a/server/core.c
+++ b/server/core.c
@@ -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 = {
diff --git a/server/util_filter.c b/server/util_filter.c
index 314ff69695..30cfa090e4 100644
--- a/server/util_filter.c
+++ b/server/util_filter.c
@@ -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,