842ae4bd224140319ae7feec1872b93dfd491143fielding/* Licensed to the Apache Software Foundation (ASF) under one or more
842ae4bd224140319ae7feec1872b93dfd491143fielding * contributor license agreements. See the NOTICE file distributed with
842ae4bd224140319ae7feec1872b93dfd491143fielding * this work for additional information regarding copyright ownership.
842ae4bd224140319ae7feec1872b93dfd491143fielding * The ASF licenses this file to You under the Apache License, Version 2.0
842ae4bd224140319ae7feec1872b93dfd491143fielding * (the "License"); you may not use this file except in compliance with
842ae4bd224140319ae7feec1872b93dfd491143fielding * the License. You may obtain a copy of the License at
777a2b42697cb8cb94ac4e73774862f879259c45rbb *
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * http://www.apache.org/licenses/LICENSE-2.0
777a2b42697cb8cb94ac4e73774862f879259c45rbb *
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * Unless required by applicable law or agreed to in writing, software
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * distributed under the License is distributed on an "AS IS" BASIS,
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * See the License for the specific language governing permissions and
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * limitations under the License.
777a2b42697cb8cb94ac4e73774862f879259c45rbb */
777a2b42697cb8cb94ac4e73774862f879259c45rbb
024cd9589e52cf11ce765dfddb5b5f0c6e421a48gstein#define APR_WANT_STRFUNC
024cd9589e52cf11ce765dfddb5b5f0c6e421a48gstein#include "apr_want.h"
03dbadb45ac72ccc5b4ea8ba6d6d5ceaed3f8b56jerenkrantz#include "apr_lib.h"
03dbadb45ac72ccc5b4ea8ba6d6d5ceaed3f8b56jerenkrantz#include "apr_hash.h"
03dbadb45ac72ccc5b4ea8ba6d6d5ceaed3f8b56jerenkrantz#include "apr_strings.h"
024cd9589e52cf11ce765dfddb5b5f0c6e421a48gstein
bfb62a96023822c56c9120e4ee627d4091cc59c2rbb#include "httpd.h"
447d8ea77d7e9fcc7aa286122668d8fe0f8cc690fuankg#include "http_config.h"
7184de27ec1d62a83c41cdeac0953ca9fd661e8csf#include "http_core.h"
38fc36de17ee342781e35643c325f22ac9fe6ddagstein#include "http_log.h"
777a2b42697cb8cb94ac4e73774862f879259c45rbb#include "util_filter.h"
777a2b42697cb8cb94ac4e73774862f879259c45rbb
1fd12b55be5aebd93227eb2821285f073e15df2djerenkrantz/* NOTE: Apache's current design doesn't allow a pool to be passed thru,
777a2b42697cb8cb94ac4e73774862f879259c45rbb so we depend on a global to hold the correct pool
777a2b42697cb8cb94ac4e73774862f879259c45rbb*/
24efed0910118b762a4eb84830875d4714b8d315ianh#define FILTER_POOL apr_hook_global_pool
12b170a812f740fafc96da32a188a8b2761a3d5cjim#include "ap_hooks.h" /* for apr_hook_global_pool */
777a2b42697cb8cb94ac4e73774862f879259c45rbb
777a2b42697cb8cb94ac4e73774862f879259c45rbb/*
777a2b42697cb8cb94ac4e73774862f879259c45rbb** This macro returns true/false if a given filter should be inserted BEFORE
777a2b42697cb8cb94ac4e73774862f879259c45rbb** another filter. This will happen when one of: 1) there isn't another
777a2b42697cb8cb94ac4e73774862f879259c45rbb** filter; 2) that filter has a higher filter type (class); 3) that filter
777a2b42697cb8cb94ac4e73774862f879259c45rbb** corresponds to a different request.
777a2b42697cb8cb94ac4e73774862f879259c45rbb*/
777a2b42697cb8cb94ac4e73774862f879259c45rbb#define INSERT_BEFORE(f, before_this) ((before_this) == NULL \
018c3674550f6780e0cebce1f4ffeb9c7674a5c5rbb || (before_this)->frec->ftype > (f)->frec->ftype \
018c3674550f6780e0cebce1f4ffeb9c7674a5c5rbb || (before_this)->r != (f)->r)
777a2b42697cb8cb94ac4e73774862f879259c45rbb
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp/* Trie structure to hold the mapping from registered
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp * filter names to filters
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp */
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp
7184de27ec1d62a83c41cdeac0953ca9fd661e8csf/* we know core's module_index is 0 */
7184de27ec1d62a83c41cdeac0953ca9fd661e8csf#undef APLOG_MODULE_INDEX
7184de27ec1d62a83c41cdeac0953ca9fd661e8csf#define APLOG_MODULE_INDEX AP_CORE_MODULE_INDEX
36ef8f77bffe75d1aa327882be1b5bdbe2ff567asf
5b33c03529e21b31bfd2a23fc30b126cb6370376brianptypedef struct filter_trie_node filter_trie_node;
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp
5b33c03529e21b31bfd2a23fc30b126cb6370376brianptypedef struct {
c190745fde0395805665ac637a4179ddbcaa1cdbwrowe int c;
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp filter_trie_node *child;
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp} filter_trie_child_ptr;
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp/* Each trie node has an array of pointers to its children.
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp * The array is kept in sorted order so that add_any_filter()
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp * can do a binary search
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp */
5b33c03529e21b31bfd2a23fc30b126cb6370376brianpstruct filter_trie_node {
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp ap_filter_rec_t *frec;
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp filter_trie_child_ptr *children;
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp int nchildren;
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp int size;
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp};
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp#define TRIE_INITIAL_SIZE 4
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp/* Link a trie node to its parent
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp */
5b33c03529e21b31bfd2a23fc30b126cb6370376brianpstatic void trie_node_link(apr_pool_t *p, filter_trie_node *parent,
c190745fde0395805665ac637a4179ddbcaa1cdbwrowe filter_trie_node *child, int c)
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp{
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp int i, j;
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp if (parent->nchildren == parent->size) {
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp filter_trie_child_ptr *new;
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp parent->size *= 2;
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp new = (filter_trie_child_ptr *)apr_palloc(p, parent->size *
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp sizeof(filter_trie_child_ptr));
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp memcpy(new, parent->children, parent->nchildren *
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp sizeof(filter_trie_child_ptr));
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp parent->children = new;
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp }
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp for (i = 0; i < parent->nchildren; i++) {
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp if (c == parent->children[i].c) {
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp return;
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp }
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp else if (c < parent->children[i].c) {
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp break;
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp }
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp }
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp for (j = parent->nchildren; j > i; j--) {
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp parent->children[j].c = parent->children[j - 1].c;
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp parent->children[j].child = parent->children[j - 1].child;
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp }
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp parent->children[i].c = c;
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp parent->children[i].child = child;
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp parent->nchildren++;
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp}
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp/* Allocate a new node for a trie.
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp * If parent is non-NULL, link the new node under the parent node with
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp * key 'c' (or, if an existing child node matches, return that one)
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp */
5b33c03529e21b31bfd2a23fc30b126cb6370376brianpstatic filter_trie_node *trie_node_alloc(apr_pool_t *p,
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp filter_trie_node *parent, char c)
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp{
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp filter_trie_node *new_node;
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp if (parent) {
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp int i;
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp for (i = 0; i < parent->nchildren; i++) {
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp if (c == parent->children[i].c) {
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp return parent->children[i].child;
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp }
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp else if (c < parent->children[i].c) {
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp break;
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp }
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp }
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp new_node =
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp (filter_trie_node *)apr_palloc(p, sizeof(filter_trie_node));
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp trie_node_link(p, parent, new_node, c);
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp }
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp else { /* No parent node */
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp new_node = (filter_trie_node *)apr_palloc(p,
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp sizeof(filter_trie_node));
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp }
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp new_node->frec = NULL;
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp new_node->nchildren = 0;
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp new_node->size = TRIE_INITIAL_SIZE;
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp new_node->children = (filter_trie_child_ptr *)apr_palloc(p,
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp new_node->size * sizeof(filter_trie_child_ptr));
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp return new_node;
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp}
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp
5b33c03529e21b31bfd2a23fc30b126cb6370376brianpstatic filter_trie_node *registered_output_filters = NULL;
5b33c03529e21b31bfd2a23fc30b126cb6370376brianpstatic filter_trie_node *registered_input_filters = NULL;
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp
777a2b42697cb8cb94ac4e73774862f879259c45rbb
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmstatic apr_status_t filter_cleanup(void *ctx)
777a2b42697cb8cb94ac4e73774862f879259c45rbb{
1296b2d30150ccb4ae9f6d690846b4e8f8571fd2rbb registered_output_filters = NULL;
1296b2d30150ccb4ae9f6d690846b4e8f8571fd2rbb registered_input_filters = NULL;
777a2b42697cb8cb94ac4e73774862f879259c45rbb return APR_SUCCESS;
777a2b42697cb8cb94ac4e73774862f879259c45rbb}
777a2b42697cb8cb94ac4e73774862f879259c45rbb
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianpstatic ap_filter_rec_t *get_filter_handle(const char *name,
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp const filter_trie_node *filter_set)
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp{
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp if (filter_set) {
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp const char *n;
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp const filter_trie_node *node;
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp node = filter_set;
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp for (n = name; *n; n++) {
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp int start, end;
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp start = 0;
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp end = node->nchildren - 1;
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp while (end >= start) {
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp int middle = (end + start) / 2;
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp char ch = node->children[middle].c;
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp if (*n == ch) {
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp node = node->children[middle].child;
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp break;
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp }
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp else if (*n < ch) {
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp end = middle - 1;
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp }
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp else {
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp start = middle + 1;
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp }
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp }
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp if (end < start) {
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp node = NULL;
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp break;
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp }
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp }
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp if (node && node->frec) {
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp return node->frec;
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp }
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp }
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp return NULL;
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp}
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp
542f434598f16966bede223e4ee4e201240dace4ianhAP_DECLARE(ap_filter_rec_t *)ap_get_output_filter_handle(const char *name)
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp{
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp return get_filter_handle(name, registered_output_filters);
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp}
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp
542f434598f16966bede223e4ee4e201240dace4ianhAP_DECLARE(ap_filter_rec_t *)ap_get_input_filter_handle(const char *name)
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp{
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp return get_filter_handle(name, registered_input_filters);
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp}
7a8a0744e378f2343c3ee6787fac0f8f959d2141brianp
fd492f9543f14fb5bae78e04b135c3448eb9cc56rbbstatic ap_filter_rec_t *register_filter(const char *name,
dddcaef56e65bdada3dde770f59c1838320f362etrawick ap_filter_func filter_func,
0fdf8c342123fde84405b885fb1720ebc652e10djerenkrantz ap_init_filter_func filter_init,
dddcaef56e65bdada3dde770f59c1838320f362etrawick ap_filter_type ftype,
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp filter_trie_node **reg_filter_set)
777a2b42697cb8cb94ac4e73774862f879259c45rbb{
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp ap_filter_rec_t *frec;
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp char *normalized_name;
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp const char *n;
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp filter_trie_node *node;
777a2b42697cb8cb94ac4e73774862f879259c45rbb
03dbadb45ac72ccc5b4ea8ba6d6d5ceaed3f8b56jerenkrantz if (!*reg_filter_set) {
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp *reg_filter_set = trie_node_alloc(FILTER_POOL, NULL, 0);
03dbadb45ac72ccc5b4ea8ba6d6d5ceaed3f8b56jerenkrantz }
03dbadb45ac72ccc5b4ea8ba6d6d5ceaed3f8b56jerenkrantz
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp normalized_name = apr_pstrdup(FILTER_POOL, name);
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp ap_str_tolower(normalized_name);
777a2b42697cb8cb94ac4e73774862f879259c45rbb
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp node = *reg_filter_set;
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp for (n = normalized_name; *n; n++) {
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp filter_trie_node *child = trie_node_alloc(FILTER_POOL, node, *n);
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp if (apr_isalpha(*n)) {
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp trie_node_link(FILTER_POOL, node, child, apr_toupper(*n));
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp }
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp node = child;
5b33c03529e21b31bfd2a23fc30b126cb6370376brianp }
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp if (node->frec) {
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp frec = node->frec;
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp }
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp else {
ae3dea49b7dbd3cdf991225881cf01e62689af2bniq frec = apr_pcalloc(FILTER_POOL, sizeof(*frec));
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp node->frec = frec;
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp frec->name = normalized_name;
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp }
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp frec->filter_func = filter_func;
0fdf8c342123fde84405b885fb1720ebc652e10djerenkrantz frec->filter_init_func = filter_init;
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp frec->ftype = ftype;
e8f95a682820a599fe41b22977010636be5c2717jim
e8f95a682820a599fe41b22977010636be5c2717jim apr_pool_cleanup_register(FILTER_POOL, NULL, filter_cleanup,
1fd12b55be5aebd93227eb2821285f073e15df2djerenkrantz apr_pool_cleanup_null);
fd492f9543f14fb5bae78e04b135c3448eb9cc56rbb return frec;
777a2b42697cb8cb94ac4e73774862f879259c45rbb}
777a2b42697cb8cb94ac4e73774862f879259c45rbb
fd492f9543f14fb5bae78e04b135c3448eb9cc56rbbAP_DECLARE(ap_filter_rec_t *) ap_register_input_filter(const char *name,
3515be87ebb5aa9a49f8a782d0d657d0d064be08rbb ap_in_filter_func filter_func,
0fdf8c342123fde84405b885fb1720ebc652e10djerenkrantz ap_init_filter_func filter_init,
dddcaef56e65bdada3dde770f59c1838320f362etrawick ap_filter_type ftype)
1296b2d30150ccb4ae9f6d690846b4e8f8571fd2rbb{
3515be87ebb5aa9a49f8a782d0d657d0d064be08rbb ap_filter_func f;
3515be87ebb5aa9a49f8a782d0d657d0d064be08rbb f.in_func = filter_func;
0fdf8c342123fde84405b885fb1720ebc652e10djerenkrantz return register_filter(name, f, filter_init, ftype,
0fdf8c342123fde84405b885fb1720ebc652e10djerenkrantz &registered_input_filters);
e8f95a682820a599fe41b22977010636be5c2717jim}
1296b2d30150ccb4ae9f6d690846b4e8f8571fd2rbb
d6f31486d449475eb8656f3f6dc874cac70a12eaniqAP_DECLARE(ap_filter_rec_t *) ap_register_output_filter(const char *name,
d6f31486d449475eb8656f3f6dc874cac70a12eaniq ap_out_filter_func filter_func,
d6f31486d449475eb8656f3f6dc874cac70a12eaniq ap_init_filter_func filter_init,
d6f31486d449475eb8656f3f6dc874cac70a12eaniq ap_filter_type ftype)
d6f31486d449475eb8656f3f6dc874cac70a12eaniq{
d6f31486d449475eb8656f3f6dc874cac70a12eaniq return ap_register_output_filter_protocol(name, filter_func,
d6f31486d449475eb8656f3f6dc874cac70a12eaniq filter_init, ftype, 0);
d6f31486d449475eb8656f3f6dc874cac70a12eaniq}
d6f31486d449475eb8656f3f6dc874cac70a12eaniq
ae3dea49b7dbd3cdf991225881cf01e62689af2bniqAP_DECLARE(ap_filter_rec_t *) ap_register_output_filter_protocol(
ae3dea49b7dbd3cdf991225881cf01e62689af2bniq const char *name,
ae3dea49b7dbd3cdf991225881cf01e62689af2bniq ap_out_filter_func filter_func,
ae3dea49b7dbd3cdf991225881cf01e62689af2bniq ap_init_filter_func filter_init,
ae3dea49b7dbd3cdf991225881cf01e62689af2bniq ap_filter_type ftype,
ae3dea49b7dbd3cdf991225881cf01e62689af2bniq unsigned int proto_flags)
ae3dea49b7dbd3cdf991225881cf01e62689af2bniq{
ae3dea49b7dbd3cdf991225881cf01e62689af2bniq ap_filter_rec_t* ret ;
3515be87ebb5aa9a49f8a782d0d657d0d064be08rbb ap_filter_func f;
3515be87ebb5aa9a49f8a782d0d657d0d064be08rbb f.out_func = filter_func;
ae3dea49b7dbd3cdf991225881cf01e62689af2bniq ret = register_filter(name, f, filter_init, ftype,
ae3dea49b7dbd3cdf991225881cf01e62689af2bniq &registered_output_filters);
ae3dea49b7dbd3cdf991225881cf01e62689af2bniq ret->proto_flags = proto_flags ;
ae3dea49b7dbd3cdf991225881cf01e62689af2bniq return ret ;
1296b2d30150ccb4ae9f6d690846b4e8f8571fd2rbb}
1296b2d30150ccb4ae9f6d690846b4e8f8571fd2rbb
e8f95a682820a599fe41b22977010636be5c2717jimstatic ap_filter_t *add_any_filter_handle(ap_filter_rec_t *frec, void *ctx,
e8f95a682820a599fe41b22977010636be5c2717jim request_rec *r, conn_rec *c,
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp ap_filter_t **r_filters,
e57e920838f31508f1418aa4c25ce55b345b2cebrbb ap_filter_t **p_filters,
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp ap_filter_t **c_filters)
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp{
bc0ebf8a6b6f96df7f05ced975fc5fd4f5846607jorton apr_pool_t *p = frec->ftype < AP_FTYPE_CONNECTION && r ? r->pool : c->pool;
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp ap_filter_t *f = apr_palloc(p, sizeof(*f));
fc0ec1015978e3923ba0473efa14316df82195c3rbb ap_filter_t **outf;
fc0ec1015978e3923ba0473efa14316df82195c3rbb
1f863242c3901a633082bab8a34e8cb7422ab421jerenkrantz if (frec->ftype < AP_FTYPE_PROTOCOL) {
fc0ec1015978e3923ba0473efa14316df82195c3rbb if (r) {
fc0ec1015978e3923ba0473efa14316df82195c3rbb outf = r_filters;
fc0ec1015978e3923ba0473efa14316df82195c3rbb }
fc0ec1015978e3923ba0473efa14316df82195c3rbb else {
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(00080)
237b1c198de800d82b737a77ca5e48fe1ff7bc94trawick "a content filter was added without a request: %s", frec->name);
fc0ec1015978e3923ba0473efa14316df82195c3rbb return NULL;
fc0ec1015978e3923ba0473efa14316df82195c3rbb }
fc0ec1015978e3923ba0473efa14316df82195c3rbb }
fc0ec1015978e3923ba0473efa14316df82195c3rbb else if (frec->ftype < AP_FTYPE_CONNECTION) {
fc0ec1015978e3923ba0473efa14316df82195c3rbb if (r) {
fc0ec1015978e3923ba0473efa14316df82195c3rbb outf = p_filters;
fc0ec1015978e3923ba0473efa14316df82195c3rbb }
fc0ec1015978e3923ba0473efa14316df82195c3rbb else {
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(00081)
237b1c198de800d82b737a77ca5e48fe1ff7bc94trawick "a protocol filter was added without a request: %s", frec->name);
fc0ec1015978e3923ba0473efa14316df82195c3rbb return NULL;
fc0ec1015978e3923ba0473efa14316df82195c3rbb }
fc0ec1015978e3923ba0473efa14316df82195c3rbb }
fc0ec1015978e3923ba0473efa14316df82195c3rbb else {
fc0ec1015978e3923ba0473efa14316df82195c3rbb outf = c_filters;
fc0ec1015978e3923ba0473efa14316df82195c3rbb }
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp f->frec = frec;
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp f->ctx = ctx;
bc0ebf8a6b6f96df7f05ced975fc5fd4f5846607jorton /* f->r must always be NULL for connection filters */
bc0ebf8a6b6f96df7f05ced975fc5fd4f5846607jorton f->r = frec->ftype < AP_FTYPE_CONNECTION ? r : NULL;
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp f->c = c;
b02d7873a18d729ee1bdca1e218ed305fa39447brbb f->next = NULL;
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp if (INSERT_BEFORE(f, *outf)) {
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp f->next = *outf;
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb if (*outf) {
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb ap_filter_t *first = NULL;
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb if (r) {
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb /* If we are adding our first non-connection filter,
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb * Then don't try to find the right location, it is
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb * automatically first.
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb */
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb if (*r_filters != *c_filters) {
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb first = *r_filters;
f2e44cb59ba866e43a710f467c2ea386c5e3b040rbb while (first && (first->next != (*outf))) {
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb first = first->next;
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb }
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb }
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb }
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb if (first && first != (*outf)) {
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb first->next = f;
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb }
fc0ec1015978e3923ba0473efa14316df82195c3rbb }
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp *outf = f;
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp }
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp else {
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp ap_filter_t *fscan = *outf;
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp while (!INSERT_BEFORE(f, fscan->next))
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp fscan = fscan->next;
fc0ec1015978e3923ba0473efa14316df82195c3rbb
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp f->next = fscan->next;
43c3e6a4b559b76b750c245ee95e2782c15b4296jim fscan->next = f;
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp }
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp
b0e8ad4dd64745bef003618fdf500b9025e43e56rbb if (frec->ftype < AP_FTYPE_CONNECTION && (*r_filters == *c_filters)) {
b0e8ad4dd64745bef003618fdf500b9025e43e56rbb *r_filters = *p_filters;
b0e8ad4dd64745bef003618fdf500b9025e43e56rbb }
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp return f;
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp}
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp
e8f95a682820a599fe41b22977010636be5c2717jimstatic ap_filter_t *add_any_filter(const char *name, void *ctx,
e8f95a682820a599fe41b22977010636be5c2717jim request_rec *r, conn_rec *c,
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb const filter_trie_node *reg_filter_set,
e8f95a682820a599fe41b22977010636be5c2717jim ap_filter_t **r_filters,
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb ap_filter_t **p_filters,
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb ap_filter_t **c_filters)
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb{
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb if (reg_filter_set) {
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb const char *n;
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb const filter_trie_node *node;
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb node = reg_filter_set;
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb for (n = name; *n; n++) {
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb int start, end;
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb start = 0;
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb end = node->nchildren - 1;
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb while (end >= start) {
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb int middle = (end + start) / 2;
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb char ch = node->children[middle].c;
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb if (*n == ch) {
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb node = node->children[middle].child;
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb break;
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb }
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb else if (*n < ch) {
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb end = middle - 1;
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb }
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb else {
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb start = middle + 1;
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb }
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb }
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb if (end < start) {
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb node = NULL;
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb break;
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb }
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb }
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb if (node && node->frec) {
e8f95a682820a599fe41b22977010636be5c2717jim return add_any_filter_handle(node->frec, ctx, r, c, r_filters,
2458e3dab5d1694c5e08cac8543ef348f4ea73e4rbb p_filters, c_filters);
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb }
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb }
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, r ? r->connection : c, APLOGNO(00082)
237b1c198de800d82b737a77ca5e48fe1ff7bc94trawick "an unknown filter was not added: %s", name);
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb return NULL;
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb}
ebe7da316894e2b93b4a905fccd2496d0ed1bc78rbb
2a0c3663b66c9af764267ac3c4e140e659598474benAP_DECLARE(ap_filter_t *) ap_add_input_filter(const char *name, void *ctx,
1fd12b55be5aebd93227eb2821285f073e15df2djerenkrantz request_rec *r, conn_rec *c)
f47ab288f31c5af82a434a321919649a5559770crbb{
2a0c3663b66c9af764267ac3c4e140e659598474ben return add_any_filter(name, ctx, r, c, registered_input_filters,
e8f95a682820a599fe41b22977010636be5c2717jim r ? &r->input_filters : NULL,
e57e920838f31508f1418aa4c25ce55b345b2cebrbb r ? &r->proto_input_filters : NULL, &c->input_filters);
f47ab288f31c5af82a434a321919649a5559770crbb}
f47ab288f31c5af82a434a321919649a5559770crbb
435c423bdcfa61ff871a9e289d1140f2bac839b8brianpAP_DECLARE(ap_filter_t *) ap_add_input_filter_handle(ap_filter_rec_t *f,
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp void *ctx,
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp request_rec *r,
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp conn_rec *c)
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp{
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp return add_any_filter_handle(f, ctx, r, c, r ? &r->input_filters : NULL,
e8f95a682820a599fe41b22977010636be5c2717jim r ? &r->proto_input_filters : NULL,
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp &c->input_filters);
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp}
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp
2a0c3663b66c9af764267ac3c4e140e659598474benAP_DECLARE(ap_filter_t *) ap_add_output_filter(const char *name, void *ctx,
1fd12b55be5aebd93227eb2821285f073e15df2djerenkrantz request_rec *r, conn_rec *c)
f47ab288f31c5af82a434a321919649a5559770crbb{
2a0c3663b66c9af764267ac3c4e140e659598474ben return add_any_filter(name, ctx, r, c, registered_output_filters,
e8f95a682820a599fe41b22977010636be5c2717jim r ? &r->output_filters : NULL,
e57e920838f31508f1418aa4c25ce55b345b2cebrbb r ? &r->proto_output_filters : NULL, &c->output_filters);
f47ab288f31c5af82a434a321919649a5559770crbb}
f47ab288f31c5af82a434a321919649a5559770crbb
435c423bdcfa61ff871a9e289d1140f2bac839b8brianpAP_DECLARE(ap_filter_t *) ap_add_output_filter_handle(ap_filter_rec_t *f,
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp void *ctx,
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp request_rec *r,
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp conn_rec *c)
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp{
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp return add_any_filter_handle(f, ctx, r, c, r ? &r->output_filters : NULL,
e57e920838f31508f1418aa4c25ce55b345b2cebrbb r ? &r->proto_output_filters : NULL,
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp &c->output_filters);
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp}
435c423bdcfa61ff871a9e289d1140f2bac839b8brianp
881aedce0b7a1e63932857ad38c3a5edbcb67617akestatic void remove_any_filter(ap_filter_t *f, ap_filter_t **r_filt, ap_filter_t **p_filt,
1fd12b55be5aebd93227eb2821285f073e15df2djerenkrantz ap_filter_t **c_filt)
bffadf7ad3d13f1141c0d681d033d2eaf55562e8rbb{
13bac43a0f21d8c6401debc1baa76be984474074rbb ap_filter_t **curr = r_filt ? r_filt : c_filt;
7a070705443ac7e8df63551c0a1b2544a8ea945bdougm ap_filter_t *fscan = *curr;
bffadf7ad3d13f1141c0d681d033d2eaf55562e8rbb
a9021be6b29f32457c1475cff0df979280710a24jerenkrantz if (p_filt && *p_filt == f)
881aedce0b7a1e63932857ad38c3a5edbcb67617ake *p_filt = (*p_filt)->next;
881aedce0b7a1e63932857ad38c3a5edbcb67617ake
7a070705443ac7e8df63551c0a1b2544a8ea945bdougm if (*curr == f) {
7a070705443ac7e8df63551c0a1b2544a8ea945bdougm *curr = (*curr)->next;
bffadf7ad3d13f1141c0d681d033d2eaf55562e8rbb return;
bffadf7ad3d13f1141c0d681d033d2eaf55562e8rbb }
bffadf7ad3d13f1141c0d681d033d2eaf55562e8rbb
7a070705443ac7e8df63551c0a1b2544a8ea945bdougm while (fscan->next != f) {
7a070705443ac7e8df63551c0a1b2544a8ea945bdougm if (!(fscan = fscan->next)) {
7a070705443ac7e8df63551c0a1b2544a8ea945bdougm return;
7a070705443ac7e8df63551c0a1b2544a8ea945bdougm }
13bac43a0f21d8c6401debc1baa76be984474074rbb }
7a070705443ac7e8df63551c0a1b2544a8ea945bdougm
7a070705443ac7e8df63551c0a1b2544a8ea945bdougm fscan->next = f->next;
13bac43a0f21d8c6401debc1baa76be984474074rbb}
13bac43a0f21d8c6401debc1baa76be984474074rbb
13bac43a0f21d8c6401debc1baa76be984474074rbbAP_DECLARE(void) ap_remove_input_filter(ap_filter_t *f)
13bac43a0f21d8c6401debc1baa76be984474074rbb{
e8f95a682820a599fe41b22977010636be5c2717jim remove_any_filter(f, f->r ? &f->r->input_filters : NULL,
e8f95a682820a599fe41b22977010636be5c2717jim f->r ? &f->r->proto_input_filters : NULL,
1fd12b55be5aebd93227eb2821285f073e15df2djerenkrantz &f->c->input_filters);
13bac43a0f21d8c6401debc1baa76be984474074rbb}
13bac43a0f21d8c6401debc1baa76be984474074rbb
13bac43a0f21d8c6401debc1baa76be984474074rbbAP_DECLARE(void) ap_remove_output_filter(ap_filter_t *f)
13bac43a0f21d8c6401debc1baa76be984474074rbb{
e8f95a682820a599fe41b22977010636be5c2717jim remove_any_filter(f, f->r ? &f->r->output_filters : NULL,
e8f95a682820a599fe41b22977010636be5c2717jim f->r ? &f->r->proto_output_filters : NULL,
1fd12b55be5aebd93227eb2821285f073e15df2djerenkrantz &f->c->output_filters);
bffadf7ad3d13f1141c0d681d033d2eaf55562e8rbb}
bffadf7ad3d13f1141c0d681d033d2eaf55562e8rbb
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejimAP_DECLARE(apr_status_t) ap_remove_input_filter_byhandle(ap_filter_t *next,
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim const char *handle)
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim{
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim ap_filter_t *found = NULL;
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim ap_filter_rec_t *filter;
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim if (!handle) {
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim return APR_EINVAL;
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim }
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim filter = ap_get_input_filter_handle(handle);
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim if (!filter) {
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim return APR_NOTFOUND;
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim }
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim while (next) {
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim if (next->frec == filter) {
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim found = next;
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim break;
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim }
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim next = next->next;
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim }
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim if (found) {
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim ap_remove_input_filter(found);
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim return APR_SUCCESS;
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim }
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim return APR_NOTFOUND;
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim}
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejimAP_DECLARE(apr_status_t) ap_remove_output_filter_byhandle(ap_filter_t *next,
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim const char *handle)
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim{
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim ap_filter_t *found = NULL;
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim ap_filter_rec_t *filter;
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim if (!handle) {
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim return APR_EINVAL;
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim }
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim filter = ap_get_output_filter_handle(handle);
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim if (!filter) {
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim return APR_NOTFOUND;
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim }
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim while (next) {
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim if (next->frec == filter) {
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim found = next;
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim break;
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim }
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim next = next->next;
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim }
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim if (found) {
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim ap_remove_output_filter(found);
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim return APR_SUCCESS;
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim }
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim return APR_NOTFOUND;
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim}
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim
b1de4d11181d00bd6a3bf45b4b5a7a5f30b2714ejim
e8f95a682820a599fe41b22977010636be5c2717jim/*
e8f95a682820a599fe41b22977010636be5c2717jim * Read data from the next filter in the filter stack. Data should be
91f8fecd254fcdfcde4607b28ee192276c29c1a2rbb * modified in the bucket brigade that is passed in. The core allocates the
91f8fecd254fcdfcde4607b28ee192276c29c1a2rbb * bucket brigade, modules that wish to replace large chunks of data or to
91f8fecd254fcdfcde4607b28ee192276c29c1a2rbb * save data off to the side should probably create their own temporary
91f8fecd254fcdfcde4607b28ee192276c29c1a2rbb * brigade especially for that use.
91f8fecd254fcdfcde4607b28ee192276c29c1a2rbb */
b1ed4c9098a3c73d140abd3c1f42312e7be3021fgsteinAP_DECLARE(apr_status_t) ap_get_brigade(ap_filter_t *next,
e8f95a682820a599fe41b22977010636be5c2717jim apr_bucket_brigade *bb,
b1ed4c9098a3c73d140abd3c1f42312e7be3021fgstein ap_input_mode_t mode,
3fde4c273ea649d1320ec9c51e7d096cd9340a94jerenkrantz apr_read_type_e block,
7727f4c9a1ac856edd057f21c4b8dbf63c6c9eefjerenkrantz apr_off_t readbytes)
91f8fecd254fcdfcde4607b28ee192276c29c1a2rbb{
91f8fecd254fcdfcde4607b28ee192276c29c1a2rbb if (next) {
e8f95a682820a599fe41b22977010636be5c2717jim return next->frec->filter_func.in_func(next, bb, mode, block,
3fde4c273ea649d1320ec9c51e7d096cd9340a94jerenkrantz readbytes);
91f8fecd254fcdfcde4607b28ee192276c29c1a2rbb }
91f8fecd254fcdfcde4607b28ee192276c29c1a2rbb return AP_NOBODY_READ;
91f8fecd254fcdfcde4607b28ee192276c29c1a2rbb}
91f8fecd254fcdfcde4607b28ee192276c29c1a2rbb
bfb62a96023822c56c9120e4ee627d4091cc59c2rbb/* Pass the buckets to the next filter in the filter stack. If the
bfb62a96023822c56c9120e4ee627d4091cc59c2rbb * current filter is a handler, we should get NULL passed in instead of
bfb62a96023822c56c9120e4ee627d4091cc59c2rbb * the current filter. At that point, we can just call the first filter in
4b86db47932a21da10cd35317b3da737f2b073c4rbb * the stack, or r->output_filters.
bfb62a96023822c56c9120e4ee627d4091cc59c2rbb */
e8f95a682820a599fe41b22977010636be5c2717jimAP_DECLARE(apr_status_t) ap_pass_brigade(ap_filter_t *next,
1fd12b55be5aebd93227eb2821285f073e15df2djerenkrantz apr_bucket_brigade *bb)
bfb62a96023822c56c9120e4ee627d4091cc59c2rbb{
c286a073ee4a1cd2cb145094520a3a1af6c9c736rbb if (next) {
b980ad7fdc218b4855cde9f75a747527f50c554dwrowe apr_bucket *e;
b980ad7fdc218b4855cde9f75a747527f50c554dwrowe if ((e = APR_BRIGADE_LAST(bb)) && APR_BUCKET_IS_EOS(e) && next->r) {
edcb7bd7ea2d7175a7f5887be3934231ce0d2060rbb /* This is only safe because HTTP_HEADER filter is always in
edcb7bd7ea2d7175a7f5887be3934231ce0d2060rbb * the filter stack. This ensures that there is ALWAYS a
edcb7bd7ea2d7175a7f5887be3934231ce0d2060rbb * request-based filter that we can attach this to. If the
edcb7bd7ea2d7175a7f5887be3934231ce0d2060rbb * HTTP_FILTER is removed, and another filter is not put in its
edcb7bd7ea2d7175a7f5887be3934231ce0d2060rbb * place, then handlers like mod_cgi, which attach their own
edcb7bd7ea2d7175a7f5887be3934231ce0d2060rbb * EOS bucket to the brigade will be broken, because we will
edcb7bd7ea2d7175a7f5887be3934231ce0d2060rbb * get two EOS buckets on the same request.
edcb7bd7ea2d7175a7f5887be3934231ce0d2060rbb */
da76b1004afd7a8785684c84e4d4b5c893c65572rbb next->r->eos_sent = 1;
c4955dc69110568b20f1517b8bf113a791bf6496nd
c4955dc69110568b20f1517b8bf113a791bf6496nd /* remember the eos for internal redirects, too */
c4955dc69110568b20f1517b8bf113a791bf6496nd if (next->r->prev) {
c4955dc69110568b20f1517b8bf113a791bf6496nd request_rec *prev = next->r->prev;
c4955dc69110568b20f1517b8bf113a791bf6496nd
c4955dc69110568b20f1517b8bf113a791bf6496nd while (prev) {
c4955dc69110568b20f1517b8bf113a791bf6496nd prev->eos_sent = 1;
c4955dc69110568b20f1517b8bf113a791bf6496nd prev = prev->prev;
c4955dc69110568b20f1517b8bf113a791bf6496nd }
c4955dc69110568b20f1517b8bf113a791bf6496nd }
da76b1004afd7a8785684c84e4d4b5c893c65572rbb }
3515be87ebb5aa9a49f8a782d0d657d0d064be08rbb return next->frec->filter_func.out_func(next, bb);
c286a073ee4a1cd2cb145094520a3a1af6c9c736rbb }
c286a073ee4a1cd2cb145094520a3a1af6c9c736rbb return AP_NOBODY_WROTE;
bfb62a96023822c56c9120e4ee627d4091cc59c2rbb}
bfb62a96023822c56c9120e4ee627d4091cc59c2rbb
5fcee27172ebd5529ba056deaf01a3755fc4ae05jim/* Pass the buckets to the next filter in the filter stack
5fcee27172ebd5529ba056deaf01a3755fc4ae05jim * checking return status for filter errors.
5fcee27172ebd5529ba056deaf01a3755fc4ae05jim * returns: OK if ap_pass_brigade returns APR_SUCCESS
5fcee27172ebd5529ba056deaf01a3755fc4ae05jim * AP_FILTER_ERROR if filter error exists
5fcee27172ebd5529ba056deaf01a3755fc4ae05jim * HTTP_INTERNAL_SERVER_ERROR for all other cases
5fcee27172ebd5529ba056deaf01a3755fc4ae05jim * logged with optional errmsg
5fcee27172ebd5529ba056deaf01a3755fc4ae05jim */
5fcee27172ebd5529ba056deaf01a3755fc4ae05jimAP_DECLARE(apr_status_t) ap_pass_brigade_fchk(request_rec *r,
5fcee27172ebd5529ba056deaf01a3755fc4ae05jim apr_bucket_brigade *bb,
eed23c0ffbac879e3502737c44070dc1212daeb0jim const char *fmt,
eed23c0ffbac879e3502737c44070dc1212daeb0jim ...)
5fcee27172ebd5529ba056deaf01a3755fc4ae05jim{
5fcee27172ebd5529ba056deaf01a3755fc4ae05jim apr_status_t rv;
5fcee27172ebd5529ba056deaf01a3755fc4ae05jim
5fcee27172ebd5529ba056deaf01a3755fc4ae05jim rv = ap_pass_brigade(r->output_filters, bb);
5fcee27172ebd5529ba056deaf01a3755fc4ae05jim if (rv != APR_SUCCESS) {
5fcee27172ebd5529ba056deaf01a3755fc4ae05jim if (rv != AP_FILTER_ERROR) {
eed23c0ffbac879e3502737c44070dc1212daeb0jim if (!fmt)
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r, APLOGNO(00083)
eed23c0ffbac879e3502737c44070dc1212daeb0jim "ap_pass_brigade returned %d", rv);
eed23c0ffbac879e3502737c44070dc1212daeb0jim else {
eed23c0ffbac879e3502737c44070dc1212daeb0jim va_list ap;
eed23c0ffbac879e3502737c44070dc1212daeb0jim const char *res;
eed23c0ffbac879e3502737c44070dc1212daeb0jim va_start(ap, fmt);
eed23c0ffbac879e3502737c44070dc1212daeb0jim res = apr_pvsprintf(r->pool, fmt, ap);
eed23c0ffbac879e3502737c44070dc1212daeb0jim va_end(ap);
59bdac473e4f8e7b7aa2548947722c278289ed26sf ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r, "%s", res);
eed23c0ffbac879e3502737c44070dc1212daeb0jim }
5fcee27172ebd5529ba056deaf01a3755fc4ae05jim return HTTP_INTERNAL_SERVER_ERROR;
5fcee27172ebd5529ba056deaf01a3755fc4ae05jim }
5fcee27172ebd5529ba056deaf01a3755fc4ae05jim return AP_FILTER_ERROR;
5fcee27172ebd5529ba056deaf01a3755fc4ae05jim }
5fcee27172ebd5529ba056deaf01a3755fc4ae05jim return OK;
5fcee27172ebd5529ba056deaf01a3755fc4ae05jim}
5fcee27172ebd5529ba056deaf01a3755fc4ae05jim
e8f95a682820a599fe41b22977010636be5c2717jimAP_DECLARE(apr_status_t) ap_save_brigade(ap_filter_t *f,
1fd12b55be5aebd93227eb2821285f073e15df2djerenkrantz apr_bucket_brigade **saveto,
9ce0a03f13db4815dd3e554409d672caa1a4671drbb apr_bucket_brigade **b, apr_pool_t *p)
bfb62a96023822c56c9120e4ee627d4091cc59c2rbb{
b980ad7fdc218b4855cde9f75a747527f50c554dwrowe apr_bucket *e;
2bf024084f1b0f2c9617bbd68834f057a3d91686jorton apr_status_t rv, srv = APR_SUCCESS;
bfb62a96023822c56c9120e4ee627d4091cc59c2rbb
bfb62a96023822c56c9120e4ee627d4091cc59c2rbb /* If have never stored any data in the filter, then we had better
bfb62a96023822c56c9120e4ee627d4091cc59c2rbb * create an empty bucket brigade so that we can concat.
bfb62a96023822c56c9120e4ee627d4091cc59c2rbb */
d5c441f3a1b7ba48984481b8e29427f7edefbfb4rbb if (!(*saveto)) {
2fc50921b88defeb7127985dfe4b4130175e069ejwoolley *saveto = apr_brigade_create(p, f->c->bucket_alloc);
bfb62a96023822c56c9120e4ee627d4091cc59c2rbb }
e8f95a682820a599fe41b22977010636be5c2717jim
2e7ef6efb7164346000607d5b5c2d2d392d1a5eajwoolley for (e = APR_BRIGADE_FIRST(*b);
2e7ef6efb7164346000607d5b5c2d2d392d1a5eajwoolley e != APR_BRIGADE_SENTINEL(*b);
2e7ef6efb7164346000607d5b5c2d2d392d1a5eajwoolley e = APR_BUCKET_NEXT(e))
2e7ef6efb7164346000607d5b5c2d2d392d1a5eajwoolley {
5cce835f242c1abff3e9a6c1791806bd588eb908gstein rv = apr_bucket_setaside(e, p);
42d3dd0fe6973dc43e01f19f964c918e57309295jorton
42d3dd0fe6973dc43e01f19f964c918e57309295jorton /* If the bucket type does not implement setaside, then
42d3dd0fe6973dc43e01f19f964c918e57309295jorton * (hopefully) morph it into a bucket type which does, and set
42d3dd0fe6973dc43e01f19f964c918e57309295jorton * *that* aside... */
42d3dd0fe6973dc43e01f19f964c918e57309295jorton if (rv == APR_ENOTIMPL) {
42d3dd0fe6973dc43e01f19f964c918e57309295jorton const char *s;
42d3dd0fe6973dc43e01f19f964c918e57309295jorton apr_size_t n;
42d3dd0fe6973dc43e01f19f964c918e57309295jorton
42d3dd0fe6973dc43e01f19f964c918e57309295jorton rv = apr_bucket_read(e, &s, &n, APR_BLOCK_READ);
42d3dd0fe6973dc43e01f19f964c918e57309295jorton if (rv == APR_SUCCESS) {
42d3dd0fe6973dc43e01f19f964c918e57309295jorton rv = apr_bucket_setaside(e, p);
42d3dd0fe6973dc43e01f19f964c918e57309295jorton }
42d3dd0fe6973dc43e01f19f964c918e57309295jorton }
42d3dd0fe6973dc43e01f19f964c918e57309295jorton
42d3dd0fe6973dc43e01f19f964c918e57309295jorton if (rv != APR_SUCCESS) {
2bf024084f1b0f2c9617bbd68834f057a3d91686jorton srv = rv;
2bf024084f1b0f2c9617bbd68834f057a3d91686jorton /* Return an error but still save the brigade if
2bf024084f1b0f2c9617bbd68834f057a3d91686jorton * ->setaside() is really not implemented. */
2bf024084f1b0f2c9617bbd68834f057a3d91686jorton if (rv != APR_ENOTIMPL) {
2bf024084f1b0f2c9617bbd68834f057a3d91686jorton return rv;
2bf024084f1b0f2c9617bbd68834f057a3d91686jorton }
28a78e701246ca1fd94c22aae3a4a12f22f5b2bbtrawick }
bfb62a96023822c56c9120e4ee627d4091cc59c2rbb }
b980ad7fdc218b4855cde9f75a747527f50c554dwrowe APR_BRIGADE_CONCAT(*saveto, *b);
2bf024084f1b0f2c9617bbd68834f057a3d91686jorton return srv;
bfb62a96023822c56c9120e4ee627d4091cc59c2rbb}
2d87d8f191175a0683f430d790d81a5604b74ec6rbb
e8f95a682820a599fe41b22977010636be5c2717jimAP_DECLARE_NONSTD(apr_status_t) ap_filter_flush(apr_bucket_brigade *bb,
1fd12b55be5aebd93227eb2821285f073e15df2djerenkrantz void *ctx)
2d87d8f191175a0683f430d790d81a5604b74ec6rbb{
2d87d8f191175a0683f430d790d81a5604b74ec6rbb ap_filter_t *f = ctx;
f822171b79ee41e8efdb2aeba38e55436e8a8fb6jorton apr_status_t rv;
2d87d8f191175a0683f430d790d81a5604b74ec6rbb
f822171b79ee41e8efdb2aeba38e55436e8a8fb6jorton rv = ap_pass_brigade(f, bb);
f822171b79ee41e8efdb2aeba38e55436e8a8fb6jorton
1c708e0bf6df4e4796b166776d14c7a32810a301jorton /* Before invocation of the flush callback, apr_brigade_write et
1c708e0bf6df4e4796b166776d14c7a32810a301jorton * al may place transient buckets in the brigade, which will fall
1c708e0bf6df4e4796b166776d14c7a32810a301jorton * out of scope after returning. Empty the brigade here, to avoid
1c708e0bf6df4e4796b166776d14c7a32810a301jorton * issues with leaving such buckets in the brigade if some filter
1c708e0bf6df4e4796b166776d14c7a32810a301jorton * fails and leaves a non-empty brigade. */
f822171b79ee41e8efdb2aeba38e55436e8a8fb6jorton apr_brigade_cleanup(bb);
f822171b79ee41e8efdb2aeba38e55436e8a8fb6jorton
f822171b79ee41e8efdb2aeba38e55436e8a8fb6jorton return rv;
2d87d8f191175a0683f430d790d81a5604b74ec6rbb}
2d87d8f191175a0683f430d790d81a5604b74ec6rbb
39d25d098171c176443e752773a644c429e88394gsteinAP_DECLARE(apr_status_t) ap_fflush(ap_filter_t *f, apr_bucket_brigade *bb)
2d87d8f191175a0683f430d790d81a5604b74ec6rbb{
2d87d8f191175a0683f430d790d81a5604b74ec6rbb apr_bucket *b;
2d87d8f191175a0683f430d790d81a5604b74ec6rbb
2fc50921b88defeb7127985dfe4b4130175e069ejwoolley b = apr_bucket_flush_create(f->c->bucket_alloc);
2d87d8f191175a0683f430d790d81a5604b74ec6rbb APR_BRIGADE_INSERT_TAIL(bb, b);
d353d275978f11f5221110e8f954d09d03ec5e3arbb return ap_pass_brigade(f, bb);
2d87d8f191175a0683f430d790d81a5604b74ec6rbb}
2d87d8f191175a0683f430d790d81a5604b74ec6rbb
7928dad64ccfb725ff5a76c4dfd15ddc5d5d439fgsteinAP_DECLARE_NONSTD(apr_status_t) ap_fputstrs(ap_filter_t *f,
7928dad64ccfb725ff5a76c4dfd15ddc5d5d439fgstein apr_bucket_brigade *bb, ...)
1e778f12c67b18c85678d6f4cf05eaf45c37eebbrbb{
1e778f12c67b18c85678d6f4cf05eaf45c37eebbrbb va_list args;
7928dad64ccfb725ff5a76c4dfd15ddc5d5d439fgstein apr_status_t rv;
1e778f12c67b18c85678d6f4cf05eaf45c37eebbrbb
1e778f12c67b18c85678d6f4cf05eaf45c37eebbrbb va_start(args, bb);
7928dad64ccfb725ff5a76c4dfd15ddc5d5d439fgstein rv = apr_brigade_vputstrs(bb, ap_filter_flush, f, args);
1e778f12c67b18c85678d6f4cf05eaf45c37eebbrbb va_end(args);
7928dad64ccfb725ff5a76c4dfd15ddc5d5d439fgstein return rv;
1e778f12c67b18c85678d6f4cf05eaf45c37eebbrbb}
1e778f12c67b18c85678d6f4cf05eaf45c37eebbrbb
7928dad64ccfb725ff5a76c4dfd15ddc5d5d439fgsteinAP_DECLARE_NONSTD(apr_status_t) ap_fprintf(ap_filter_t *f,
7928dad64ccfb725ff5a76c4dfd15ddc5d5d439fgstein apr_bucket_brigade *bb,
7928dad64ccfb725ff5a76c4dfd15ddc5d5d439fgstein const char *fmt,
7928dad64ccfb725ff5a76c4dfd15ddc5d5d439fgstein ...)
7928dad64ccfb725ff5a76c4dfd15ddc5d5d439fgstein{
1e778f12c67b18c85678d6f4cf05eaf45c37eebbrbb va_list args;
7928dad64ccfb725ff5a76c4dfd15ddc5d5d439fgstein apr_status_t rv;
1e778f12c67b18c85678d6f4cf05eaf45c37eebbrbb
1e778f12c67b18c85678d6f4cf05eaf45c37eebbrbb va_start(args, fmt);
7928dad64ccfb725ff5a76c4dfd15ddc5d5d439fgstein rv = apr_brigade_vprintf(bb, ap_filter_flush, f, fmt, args);
1e778f12c67b18c85678d6f4cf05eaf45c37eebbrbb va_end(args);
7928dad64ccfb725ff5a76c4dfd15ddc5d5d439fgstein return rv;
1e778f12c67b18c85678d6f4cf05eaf45c37eebbrbb}
ae3dea49b7dbd3cdf991225881cf01e62689af2bniqAP_DECLARE(void) ap_filter_protocol(ap_filter_t *f, unsigned int flags)
ae3dea49b7dbd3cdf991225881cf01e62689af2bniq{
ae3dea49b7dbd3cdf991225881cf01e62689af2bniq f->frec->proto_flags = flags ;
ae3dea49b7dbd3cdf991225881cf01e62689af2bniq}