-/* ====================================================================
- * The Apache Software License, Version 1.1
- *
- * Copyright (c) 2000 The Apache Software Foundation. All rights
- * reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file util_filter.h
+ * @brief Apache filter library
*/
#ifndef AP_FILTER_H
#define AP_FILTER_H
-#ifdef __cplusplus
-extern "C" {
-#endif
+#include "apr.h"
+#include "apr_buckets.h"
+
+#include "httpd.h"
-#ifdef APR_HAVE_STDARG_H
+#if APR_HAVE_STDARG_H
#include <stdarg.h>
#endif
-#include "httpd.h"
-#include "apr.h"
-#include "ap_buckets.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
/**
- * @package Apache filter library
- */
-
-#define AP_NOBODY_WROTE -1
-#define AP_NOBODY_READ -2
-
-/* ap_input_mode_t - input filtering modes
- *
- * AP_MODE_BLOCKING
- *
- * The filter shouldn't return until data is received or EOF is hit or an error
- * occurs.
- *
- * AP_MODE_NONBLOCKING
- *
- * The filter should process any available data/status as normal, but will not
- * wait for additional data.
- *
- * AP_MODE_PEEK
- *
- * The filter should return APR_SUCCESS if data is available or APR_EOF
- * otherwise. The filter must not return any buckets of data. Data returned
- * on a subsequent call, when mode is AP_MODE_BLOCKING or AP_MODE_NONBLOCKING.
+ * @brief input filtering modes
*/
typedef enum {
- AP_MODE_BLOCKING,
- AP_MODE_NONBLOCKING,
- AP_MODE_PEEK
+ /** The filter should return at most readbytes data. */
+ AP_MODE_READBYTES,
+ /** The filter should return at most one line of CRLF data.
+ * (If a potential line is too long or no CRLF is found, the
+ * filter may return partial data).
+ */
+ AP_MODE_GETLINE,
+ /** The filter should implicitly eat any CRLF pairs that it sees. */
+ AP_MODE_EATCRLF,
+ /** The filter read should be treated as speculative and any returned
+ * data should be stored for later retrieval in another mode. */
+ AP_MODE_SPECULATIVE,
+ /** The filter read should be exhaustive and read until it can not
+ * read any more.
+ * Use this mode with extreme caution.
+ */
+ AP_MODE_EXHAUSTIVE,
+ /** The filter should initialize the connection if needed,
+ * NNTP or FTP over SSL for example.
+ */
+ AP_MODE_INIT
} ap_input_mode_t;
-/*
- * FILTER CHAIN
+/**
+ * @defgroup APACHE_CORE_FILTER Filter Chain
+ * @ingroup APACHE_CORE
*
* Filters operate using a "chaining" mechanism. The filters are chained
* together into a sequence. When output is generated, it is passed through
* stream" marker into the filter chain. The filters will use this to flush
* out any internal state and to detect incomplete syntax (for example, an
* unterminated SSI directive).
+ *
+ * @{
*/
/* forward declare the filter type */
typedef struct ap_filter_t ap_filter_t;
-/*
- * ap_filter_func:
+/**
+ * @name Filter callbacks
*
* This function type is used for filter callbacks. It will be passed a
- * pointer to "this" filter, and a "bucket" containing the content to be
- * filtered.
+ * pointer to "this" filter, and a "bucket brigade" containing the content
+ * to be filtered.
*
* In filter->ctx, the callback will find its context. This context is
* provided here, so that a filter may be installed multiple times, each
*
* Callbacks are associated with a filter definition, which is specified
* by name. See ap_register_input_filter() and ap_register_output_filter()
- * for setting the association between a name for a filter and its
+ * for setting the association between a name for a filter and its
* associated callback (and other information).
*
- * 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.
+ * 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 brigade always belongs to the caller, but the filter
+ * is free to use the buckets within it as it sees fit. Normally,
+ * the brigade will be returned empty. Buckets *may not* be retained
+ * between successive calls to the filter unless they have been
+ * "set aside" with a call apr_bucket_setaside. Typically this will
+ * be done with ap_save_brigade(). Buckets removed from the brigade
+ * become the responsibility of the filter, which must arrange for
+ * them to be deleted, either by doing so directly or by inserting
+ * them in a brigade which will subsequently be destroyed.
+ *
+ * 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
+ * @{
*/
-typedef apr_status_t (*ap_out_filter_func)(ap_filter_t *f, ap_bucket_brigade *b);
-typedef apr_status_t (*ap_in_filter_func)(ap_filter_t *f, ap_bucket_brigade *b,
- ap_input_mode_t mode);
+typedef apr_status_t (*ap_out_filter_func)(ap_filter_t *f,
+ apr_bucket_brigade *b);
+typedef apr_status_t (*ap_in_filter_func)(ap_filter_t *f,
+ apr_bucket_brigade *b,
+ 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;
ap_in_filter_func in_func;
} ap_filter_func;
-/*
- * ap_filter_type:
- *
+/** @} */
+
+/**
* Filters have different types/classifications. These are used to group
* and sort the filters to properly sequence their operation.
*
- * AP_FTYPE_CONTENT:
- * These filters are used to alter the content that is passed through
- * them. Examples are SSI or PHP.
- *
- * AP_FTYPE_HTTP_HEADER: (XXX somebody rename me or get rid of me please)
- * This special type ensures that the HTTP header filter ends up in
- * the proper location in the filter chain.
- *
- * AP_FTYPE_TRANSCODE:
- * These filters implement transport encodings (e.g., chunking).
- *
- * AP_FTYPE_CONNECTION:
- * These filters will alter the content, but in ways that are more
- * strongly associated with the connection. Examples are splitting
- * an HTTP connection into multiple requests and buffering HTTP
- * responses across multiple requests.
- *
- * It is important to note that these types of filters are not allowed
- * in a sub-request. A sub-request's output can certainly be filtered
- * by AP_FTYPE_CONTENT filters, but all of the "final processing" is
- * determined by the main request.
- *
- * AP_FTYPE_NETWORK:
- * These filters don't alter the content. They are responsible for
- * sending/receiving data to/from the client.
- *
* The types have a particular sort order, which allows us to insert them
* into the filter chain in a determistic order. Within a particular grouping,
* the ordering is equivalent to the order of calls to ap_add_*_filter().
*/
typedef enum {
- AP_FTYPE_CONTENT = 10,
- AP_FTYPE_HTTP_HEADER = 20,
- AP_FTYPE_TRANSCODE = 30,
- AP_FTYPE_CONNECTION = 40,
- AP_FTYPE_NETWORK = 50
+ /** These filters are used to alter the content that is passed through
+ * them. Examples are SSI or PHP. */
+ AP_FTYPE_RESOURCE = 10,
+ /** These filters are used to alter the content as a whole, but after all
+ * AP_FTYPE_RESOURCE filters are executed. These filters should not
+ * change the content-type. An example is deflate. */
+ AP_FTYPE_CONTENT_SET = 20,
+ /** These filters are used to handle the protocol between server and
+ * client. Examples are HTTP and POP. */
+ AP_FTYPE_PROTOCOL = 30,
+ /** These filters implement transport encodings (e.g., chunking). */
+ AP_FTYPE_TRANSCODE = 40,
+ /** These filters will alter the content, but in ways that are
+ * more strongly associated with the connection. Examples are
+ * splitting an HTTP connection into multiple requests and
+ * buffering HTTP responses across multiple requests.
+ *
+ * It is important to note that these types of filters are not
+ * allowed in a sub-request. A sub-request's output can certainly
+ * be filtered by ::AP_FTYPE_RESOURCE filters, but all of the "final
+ * processing" is determined by the main request. */
+ AP_FTYPE_CONNECTION = 50,
+ /** These filters don't alter the content. They are responsible for
+ * sending/receiving data to/from the client. */
+ AP_FTYPE_NETWORK = 60
} ap_filter_type;
-/*
- * ap_filter_t:
- *
+/**
* This is the request-time context structure for an installed filter (in
* the output filter chain). It provides the callback to use for filtering,
* the request this filter is associated with (which is important when
*/
typedef struct ap_filter_rec_t ap_filter_rec_t;
+typedef struct ap_filter_provider_t ap_filter_provider_t;
/**
- * This structure is used for recording information about the
+ * @brief This structure is used for recording information about the
* registered filters. It associates a name with the filter's callback
* and filter type.
*
* At the moment, these are simply linked in a chain, so a ->next pointer
* is available.
+ *
+ * It is used for any filter that can be inserted in the filter chain.
+ * This may be either a httpd-2.0 filter or a mod_filter harness.
+ * In the latter case it contains dispatch, provider and protocol information.
+ * In the former case, the new fields (from dispatch) are ignored.
*/
struct ap_filter_rec_t {
/** The registered name for this filter */
const char *name;
+
/** The function to call when this filter is invoked. */
ap_filter_func filter_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
- * data based on the type of connection.
+
+ /** The function to call directly before the handlers are invoked
+ * for a request. The init function is called once directly
+ * before running the handlers for a request or subrequest. The
+ * init function is never called for a connection filter (with
+ * ftype >= AP_FTYPE_CONNECTION). Any use of this function for
+ * filters for protocols other than HTTP is specified by the
+ * module supported that protocol.
*/
- ap_filter_type ftype;
+ ap_init_filter_func filter_init_func;
/** The next filter_rec in the list */
struct ap_filter_rec_t *next;
+
+ /** Providers for this filter */
+ ap_filter_provider_t *providers;
+
+ /** 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
+ * data based on the type of connection.
+ */
+ ap_filter_type ftype;
+
+ /** Trace level for this filter */
+ int debug;
+
+ /** Protocol flags for this filter */
+ unsigned int proto_flags;
};
/**
- * The representation of a filter chain. Each request has a list
+ * @brief The representation of a filter chain.
+ *
+ * Each request has a list
* of these structures which are called in turn to filter the data. Sub
* 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;
request_rec *r;
/** The conn_rec associated with the current filter. This is analogous
- * to the request_rec, except that it is used for input filtering.
+ * to the request_rec, except that it is used for connection filters.
*/
conn_rec *c;
};
/**
* Get the current bucket brigade from the next filter on the filter
- * stack. The filter should return an apr_status_t value. If the bottom-most
- * filter doesn't write to the network, then AP_NOBODY_READ is returned.
+ * stack. The filter returns an apr_status_t value. If the bottom-most
+ * filter doesn't read from the network, then ::AP_NOBODY_READ is returned.
+ * The bucket brigade will be empty when there is nothing left to get.
* @param filter The next filter in the chain
- * @param bucket The current bucket brigade
- * @param mode AP_MODE_BLOCKING, AP_MODE_NONBLOCKING, or AP_MODE_PEEK
- * @return apr_status_t value
- * @deffunc apr_status_t ap_get_brigade(ap_filter_t *filter, ap_bucket_brigade *bucket, ap_input_mode_t mode)
+ * @param bucket The current bucket brigade. The original brigade passed
+ * to ap_get_brigade() must be empty.
+ * @param mode The way in which the data should be read
+ * @param block How the operations should be performed
+ * ::APR_BLOCK_READ, ::APR_NONBLOCK_READ
+ * @param readbytes How many bytes to read from the next filter.
*/
-AP_DECLARE(apr_status_t) ap_get_brigade(ap_filter_t *filter, ap_bucket_brigade *bucket,
- ap_input_mode_t mode);
+AP_DECLARE(apr_status_t) ap_get_brigade(ap_filter_t *filter,
+ apr_bucket_brigade *bucket,
+ ap_input_mode_t mode,
+ apr_read_type_e block,
+ apr_off_t readbytes);
/**
* Pass the current bucket brigade down to the next filter on the filter
- * stack. The filter should return an apr_status_t value. If the bottom-most
- * filter doesn't write to the network, then AP_NOBODY_WROTE is returned.
+ * stack. The filter returns an apr_status_t value. If the bottom-most
+ * filter doesn't write to the network, then ::AP_NOBODY_WROTE is returned.
* @param filter The next filter in the chain
* @param bucket The current bucket brigade
- * @return apr_status_t value
- * @deffunc apr_status_t ap_pass_brigade(ap_filter_t *filter, ap_bucket_brigade *bucket)
+ *
+ * @remark Ownership of the brigade is retained by the caller. On return,
+ * the contents of the brigade are UNDEFINED, and the caller must
+ * either call apr_brigade_cleanup or apr_brigade_destroy on
+ * the brigade.
*/
-AP_DECLARE(apr_status_t) ap_pass_brigade(ap_filter_t *filter, ap_bucket_brigade *bucket);
+AP_DECLARE(apr_status_t) ap_pass_brigade(ap_filter_t *filter,
+ apr_bucket_brigade *bucket);
-/*
- * ap_register_input_filter():
- *
- * This function is used to register an input filter with the system.
- * After this registration is performed, then a filter may be added
- * into the filter chain by using ap_add_input_filter() and simply
- * specifying the name.
- *
- * The filter's callback and type should be passed.
+/**
+ * Pass the current bucket brigade down to the next filter on the filter
+ * stack checking for filter errors. The filter returns an apr_status_t value.
+ * Returns ::OK if the brigade is successfully passed
+ * ::AP_FILTER_ERROR on a filter error
+ * ::HTTP_INTERNAL_SERVER_ERROR on all other errors
+ * @param r The request rec
+ * @param bucket The current bucket brigade
+ * @param fmt The format string. If NULL defaults to "ap_pass_brigade returned"
+ * @param ... The arguments to use to fill out the format string
+ * @remark Ownership of the brigade is retained by the caller. On return,
+ * the contents of the brigade are UNDEFINED, and the caller must
+ * either call apr_brigade_cleanup or apr_brigade_destroy on
+ * the brigade.
*/
+AP_DECLARE(apr_status_t) ap_pass_brigade_fchk(request_rec *r,
+ apr_bucket_brigade *bucket,
+ const char *fmt,
+ ...)
+ __attribute__((format(printf,3,4)));
+
/**
- * Register an input filter for later use. This allows modules to name their
- * filter functions for later addition to a specific request
+ * This function is used to register an input filter with the system.
+ * After this registration is performed, then a filter may be added
+ * into the filter chain by using ap_add_input_filter() and simply
+ * specifying the name.
+ *
* @param name The name to attach to the filter function
* @param filter_func The filter function to name
- * @param The type of filter function, either AP_FTYPE_CONTENT or AP_FTYPE_CONNECTION
- * @deffunc void ap_register_input_filter(const char *name, ap_in_filter_func filter_func, ap_filter_type ftype)
+ * @param filter_init The function to call before the filter handlers
+ are invoked
+ * @param ftype The type of filter function, either ::AP_FTYPE_CONTENT_SET or
+ * ::AP_FTYPE_CONNECTION
+ * @see add_input_filter()
*/
-AP_DECLARE(void) ap_register_input_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_register_output_filter():
- *
- * This function is used to register an output filter with the system.
- * After this registration is performed, then a filter may be added
- * into the filter chain by using ap_add_output_filter() and simply
- * specifying the name.
- *
- * The filter's callback and type should be passed.
- */
+
+/** @deprecated @see ap_register_output_filter_protocol */
+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);
+
+/* For httpd-?.? I suggest replacing the above with
+#define ap_register_output_filter(name,ffunc,init,ftype) \
+ ap_register_output_filter_protocol(name,ffunc,init,ftype,0)
+*/
+
/**
- * Register an output filter for later use. This allows modules to name their
- * filter functions for later addition to a specific request
+ * This function is used to register an output filter with the system.
+ * After this registration is performed, then a filter may be added
+ * directly to the filter chain by using ap_add_output_filter() and
+ * simply specifying the name, or as a provider under mod_filter.
+ *
* @param name The name to attach to the filter function
* @param filter_func The filter function to name
- * @param The type of filter function, either AP_FTYPE_CONTENT or AP_FTYPE_CONNECTION
- * @deffunc void ap_register_output_filter(const char *name, ap_out_filter_func filter_func, ap_filter_type ftype)
+ * @param filter_init The function to call before the filter handlers
+ * are invoked
+ * @param ftype The type of filter function, either ::AP_FTYPE_CONTENT_SET or
+ * ::AP_FTYPE_CONNECTION
+ * @param proto_flags Protocol flags: logical OR of AP_FILTER_PROTO_* bits
+ * @return the filter rec
+ * @see ap_add_output_filter()
*/
-AP_DECLARE(void) ap_register_output_filter(const char *name,
- ap_out_filter_func filter_func,
- ap_filter_type ftype);
+AP_DECLARE(ap_filter_rec_t *) ap_register_output_filter_protocol(
+ const char *name,
+ ap_out_filter_func filter_func,
+ ap_init_filter_func filter_init,
+ ap_filter_type ftype,
+ unsigned int proto_flags);
-/*
- * ap_add_filter():
- *
+/**
* Adds a named filter into the filter chain on the specified request record.
* The filter will be installed with the specified context pointer.
*
* calls to ap_add_filter). If the current filter chain contains filters
* from another request, then this filter will be added before those other
* filters.
- *
+ *
* To re-iterate that last comment. This function is building a FIFO
* list of filters. Take note of that when adding your filter to the chain.
+ *
+ * @param name The name of the filter to add
+ * @param ctx Context data to provide to the filter
+ * @param r The request to add this filter for (or NULL if it isn't associated with a request)
+ * @param c The connection to add the fillter for
*/
+AP_DECLARE(ap_filter_t *) ap_add_input_filter(const char *name, void *ctx,
+ request_rec *r, conn_rec *c);
+
/**
- * Add a filter to the current connection. Filters are added in a FIFO manner.
- * The first filter added will be the first filter called.
- * @param name The name of the filter to add
+ * Variant of ap_add_input_filter() that accepts a registered filter handle
+ * (as returned by ap_register_input_filter()) rather than a filter name
+ *
+ * @param f The filter handle to add
+ * @param ctx Context data to provide to the filter
* @param r The request to add this filter for (or NULL if it isn't associated with a request)
* @param c The connection to add the fillter for
- * @deffunc void ap_add_input_filter(const char *name, void *ctx, request_rec *r, conn_rec *c)
*/
-AP_DECLARE(void) ap_add_input_filter(const char *name, void *ctx, request_rec *r, conn_rec *c);
+AP_DECLARE(ap_filter_t *) ap_add_input_filter_handle(ap_filter_rec_t *f,
+ void *ctx,
+ request_rec *r,
+ conn_rec *c);
+
+/**
+ * Returns the filter handle for use with ap_add_input_filter_handle.
+ *
+ * @param name The filter name to look up
+ */
+AP_DECLARE(ap_filter_rec_t *) ap_get_input_filter_handle(const char *name);
/**
* Add a filter to the current request. Filters are added in a FIFO manner.
* @param ctx Context data to set in the filter
* @param r The request to add this filter for (or NULL if it isn't associated with a request)
* @param c The connection to add this filter for
- * @deffunc void ap_add_output_filter(const char *name, void *ctx, request_rec *r, conn_rec *c)
+ * @note If adding a connection-level output filter (i.e. where the type
+ * is >= AP_FTYPE_CONNECTION) during processing of a request, the request
+ * object r must be passed in to ensure the filter chains are modified
+ * correctly. f->r will still be initialized as NULL in the new filter.
+ */
+AP_DECLARE(ap_filter_t *) ap_add_output_filter(const char *name, void *ctx,
+ request_rec *r, conn_rec *c);
+
+/**
+ * Variant of ap_add_output_filter() that accepts a registered filter handle
+ * (as returned by ap_register_output_filter()) rather than a filter name
+ *
+ * @param f The filter handle to add
+ * @param ctx Context data to set in the filter
+ * @param r The request to add this filter for (or NULL if it isn't associated with a request)
+ * @param c The connection to add the filter for
+ * @note If adding a connection-level output filter (i.e. where the type
+ * is >= AP_FTYPE_CONNECTION) during processing of a request, the request
+ * object r must be passed in to ensure the filter chains are modified
+ * correctly. f->r will still be initialized as NULL in the new filter.
+ */
+AP_DECLARE(ap_filter_t *) ap_add_output_filter_handle(ap_filter_rec_t *f,
+ void *ctx,
+ request_rec *r,
+ conn_rec *c);
+
+/**
+ * Returns the filter handle for use with ap_add_output_filter_handle.
+ *
+ * @param name The filter name to look up
+ */
+AP_DECLARE(ap_filter_rec_t *) ap_get_output_filter_handle(const char *name);
+
+/**
+ * Remove an input filter from either the request or connection stack
+ * it is associated with.
+ * @param f The filter to remove
+ */
+
+AP_DECLARE(void) ap_remove_input_filter(ap_filter_t *f);
+
+/**
+ * Remove an output filter from either the request or connection stack
+ * it is associated with.
+ * @param f The filter to remove
*/
-AP_DECLARE(void) ap_add_output_filter(const char *name, void *ctx,
- request_rec *r, conn_rec *c);
AP_DECLARE(void) ap_remove_output_filter(ap_filter_t *f);
+/**
+ * Remove an input filter from either the request or connection stack
+ * it is associated with.
+ * @param next The filter stack to search
+ * @param handle The filter handle (name) to remove
+ * @return APR_SUCCESS on removal or error
+ */
+AP_DECLARE(apr_status_t) ap_remove_input_filter_byhandle(ap_filter_t *next,
+ const char *handle);
+/**
+ * Remove an output filter from either the request or connection stack
+ * it is associated with.
+ * @param next The filter stack to search
+ * @param handle The filter handle (name) to remove
+ * @return APR_SUCCESS on removal or error
+ */
+AP_DECLARE(apr_status_t) ap_remove_output_filter_byhandle(ap_filter_t *next,
+ const char *handle);
+
/* The next two filters are for abstraction purposes only. They could be
* done away with, but that would require that we break modules if we ever
* want to change our filter registration method. The basic idea, is that
*/
/**
- * prepare a bucket brigade to be setaside. If a different brigade was
+ * prepare a bucket brigade to be setaside. If a different brigade was
* set-aside earlier, then the two brigades are concatenated together.
* @param f The current filter
* @param save_to The brigade that was previously set-aside. Regardless, the
* new bucket brigade is returned in this location.
* @param b The bucket brigade to save aside. This brigade is always empty
* on return
- * @deffunc void ap_save_brigade(ap_filter_t *f, ap_bucket_brigade **save_to, ap_bucket_brigade **b)
+ * @param p Ensure that all data in the brigade lives as long as this pool
+ */
+AP_DECLARE(apr_status_t) ap_save_brigade(ap_filter_t *f,
+ apr_bucket_brigade **save_to,
+ apr_bucket_brigade **b, apr_pool_t *p);
+
+/**
+ * Flush function for apr_brigade_* calls. This calls ap_pass_brigade
+ * to flush the brigade if the brigade buffer overflows.
+ * @param bb The brigade to flush
+ * @param ctx The filter to pass the brigade to
+ * @note this function has nothing to do with FLUSH buckets. It is simply
+ * a way to flush content out of a brigade and down a filter stack.
+ */
+AP_DECLARE_NONSTD(apr_status_t) ap_filter_flush(apr_bucket_brigade *bb,
+ void *ctx);
+
+/**
+ * Flush the current brigade down the filter stack.
+ * @param f The filter we are passing to
+ * @param bb The brigade to flush
+ */
+AP_DECLARE(apr_status_t) ap_fflush(ap_filter_t *f, apr_bucket_brigade *bb);
+
+/**
+ * Write a buffer for the current filter, buffering if possible.
+ * @param f the filter we are writing to
+ * @param bb The brigade to buffer into
+ * @param data The data to write
+ * @param nbyte The number of bytes in the data
+ */
+#define ap_fwrite(f, bb, data, nbyte) \
+ apr_brigade_write(bb, ap_filter_flush, f, data, nbyte)
+
+/**
+ * Write a buffer for the current filter, buffering if possible.
+ * @param f the filter we are writing to
+ * @param bb The brigade to buffer into
+ * @param str The string to write
+ */
+#define ap_fputs(f, bb, str) \
+ apr_brigade_write(bb, ap_filter_flush, f, str, strlen(str))
+
+/**
+ * Write a character for the current filter, buffering if possible.
+ * @param f the filter we are writing to
+ * @param bb The brigade to buffer into
+ * @param c The character to write
+ */
+#define ap_fputc(f, bb, c) \
+ apr_brigade_putc(bb, ap_filter_flush, f, c)
+
+/**
+ * Write an unspecified number of strings to the current filter
+ * @param f the filter we are writing to
+ * @param bb The brigade to buffer into
+ * @param ... The strings to write
+ */
+AP_DECLARE_NONSTD(apr_status_t) ap_fputstrs(ap_filter_t *f,
+ apr_bucket_brigade *bb,
+ ...)
+ AP_FN_ATTR_SENTINEL;
+
+/**
+ * Output data to the filter in printf format
+ * @param f the filter we are writing to
+ * @param bb The brigade to buffer into
+ * @param fmt The format string
+ * @param ... The arguments to use to fill out the format string
+ */
+AP_DECLARE_NONSTD(apr_status_t) ap_fprintf(ap_filter_t *f,
+ apr_bucket_brigade *bb,
+ const char *fmt,
+ ...)
+ __attribute__((format(printf,3,4)));
+
+/**
+ * set protocol requirements for an output content filter
+ * (only works with AP_FTYPE_RESOURCE and AP_FTYPE_CONTENT_SET)
+ * @param f the filter in question
+ * @param proto_flags Logical OR of AP_FILTER_PROTO_* bits
+ */
+AP_DECLARE(void) ap_filter_protocol(ap_filter_t* f, unsigned int proto_flags);
+
+/** Filter changes contents (so invalidating checksums/etc) */
+#define AP_FILTER_PROTO_CHANGE 0x1
+
+/** Filter changes length of contents (so invalidating content-length/etc) */
+#define AP_FILTER_PROTO_CHANGE_LENGTH 0x2
+
+/** Filter requires complete input and can't work on byteranges */
+#define AP_FILTER_PROTO_NO_BYTERANGE 0x4
+
+/** Filter should not run in a proxy */
+#define AP_FILTER_PROTO_NO_PROXY 0x8
+
+/** Filter makes output non-cacheable */
+#define AP_FILTER_PROTO_NO_CACHE 0x10
+
+/** Filter is incompatible with "Cache-Control: no-transform" */
+#define AP_FILTER_PROTO_TRANSFORM 0x20
+
+/**
+ * @}
*/
-AP_DECLARE(void) ap_save_brigade(ap_filter_t *f, ap_bucket_brigade **save_to,
- ap_bucket_brigade **b);
#ifdef __cplusplus
}
#endif
-#endif /* !AP_FILTER_H */
+#endif /* !AP_FILTER_H */