Blame server/util_filter.c

Packit 90a5c9
/* Licensed to the Apache Software Foundation (ASF) under one or more
Packit 90a5c9
 * contributor license agreements.  See the NOTICE file distributed with
Packit 90a5c9
 * this work for additional information regarding copyright ownership.
Packit 90a5c9
 * The ASF licenses this file to You under the Apache License, Version 2.0
Packit 90a5c9
 * (the "License"); you may not use this file except in compliance with
Packit 90a5c9
 * the License.  You may obtain a copy of the License at
Packit 90a5c9
 *
Packit 90a5c9
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit 90a5c9
 *
Packit 90a5c9
 * Unless required by applicable law or agreed to in writing, software
Packit 90a5c9
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit 90a5c9
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit 90a5c9
 * See the License for the specific language governing permissions and
Packit 90a5c9
 * limitations under the License.
Packit 90a5c9
 */
Packit 90a5c9
Packit 90a5c9
#define APR_WANT_STRFUNC
Packit 90a5c9
#include "apr_want.h"
Packit 90a5c9
#include "apr_lib.h"
Packit 90a5c9
#include "apr_hash.h"
Packit 90a5c9
#include "apr_strings.h"
Packit 90a5c9
Packit 90a5c9
#include "httpd.h"
Packit 90a5c9
#include "http_config.h"
Packit 90a5c9
#include "http_core.h"
Packit 90a5c9
#include "http_log.h"
Packit 90a5c9
#include "util_filter.h"
Packit 90a5c9
Packit 90a5c9
/* NOTE: Apache's current design doesn't allow a pool to be passed thru,
Packit 90a5c9
   so we depend on a global to hold the correct pool
Packit 90a5c9
*/
Packit 90a5c9
#define FILTER_POOL     apr_hook_global_pool
Packit 90a5c9
#include "ap_hooks.h"   /* for apr_hook_global_pool */
Packit 90a5c9
Packit 90a5c9
/*
Packit 90a5c9
** This macro returns true/false if a given filter should be inserted BEFORE
Packit 90a5c9
** another filter. This will happen when one of: 1) there isn't another
Packit 90a5c9
** filter; 2) that filter has a higher filter type (class); 3) that filter
Packit 90a5c9
** corresponds to a different request.
Packit 90a5c9
*/
Packit 90a5c9
#define INSERT_BEFORE(f, before_this) ((before_this) == NULL \
Packit 90a5c9
                           || (before_this)->frec->ftype > (f)->frec->ftype \
Packit 90a5c9
                           || (before_this)->r != (f)->r)
Packit 90a5c9
Packit 90a5c9
/* Trie structure to hold the mapping from registered
Packit 90a5c9
 * filter names to filters
Packit 90a5c9
 */
Packit 90a5c9
Packit 90a5c9
/* we know core's module_index is 0 */
Packit 90a5c9
#undef APLOG_MODULE_INDEX
Packit 90a5c9
#define APLOG_MODULE_INDEX AP_CORE_MODULE_INDEX
Packit 90a5c9
Packit 90a5c9
typedef struct filter_trie_node filter_trie_node;
Packit 90a5c9
Packit 90a5c9
typedef struct {
Packit 90a5c9
    int c;
Packit 90a5c9
    filter_trie_node *child;
Packit 90a5c9
} filter_trie_child_ptr;
Packit 90a5c9
Packit 90a5c9
/* Each trie node has an array of pointers to its children.
Packit 90a5c9
 * The array is kept in sorted order so that add_any_filter()
Packit 90a5c9
 * can do a binary search
Packit 90a5c9
 */
Packit 90a5c9
struct filter_trie_node {
Packit 90a5c9
    ap_filter_rec_t *frec;
Packit 90a5c9
    filter_trie_child_ptr *children;
Packit 90a5c9
    int nchildren;
Packit 90a5c9
    int size;
Packit 90a5c9
};
Packit 90a5c9
Packit 90a5c9
#define TRIE_INITIAL_SIZE 4
Packit 90a5c9
Packit 90a5c9
/* Link a trie node to its parent
Packit 90a5c9
 */
Packit 90a5c9
static void trie_node_link(apr_pool_t *p, filter_trie_node *parent,
Packit 90a5c9
                           filter_trie_node *child, int c)
Packit 90a5c9
{
Packit 90a5c9
    int i, j;
Packit 90a5c9
Packit 90a5c9
    if (parent->nchildren == parent->size) {
Packit 90a5c9
        filter_trie_child_ptr *new;
Packit 90a5c9
        parent->size *= 2;
Packit 90a5c9
        new = (filter_trie_child_ptr *)apr_palloc(p, parent->size *
Packit 90a5c9
                                             sizeof(filter_trie_child_ptr));
Packit 90a5c9
        memcpy(new, parent->children, parent->nchildren *
Packit 90a5c9
               sizeof(filter_trie_child_ptr));
Packit 90a5c9
        parent->children = new;
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    for (i = 0; i < parent->nchildren; i++) {
Packit 90a5c9
        if (c == parent->children[i].c) {
Packit 90a5c9
            return;
Packit 90a5c9
        }
Packit 90a5c9
        else if (c < parent->children[i].c) {
Packit 90a5c9
            break;
Packit 90a5c9
        }
Packit 90a5c9
    }
Packit 90a5c9
    for (j = parent->nchildren; j > i; j--) {
Packit 90a5c9
        parent->children[j].c = parent->children[j - 1].c;
Packit 90a5c9
        parent->children[j].child = parent->children[j - 1].child;
Packit 90a5c9
    }
Packit 90a5c9
    parent->children[i].c = c;
Packit 90a5c9
    parent->children[i].child = child;
Packit 90a5c9
Packit 90a5c9
    parent->nchildren++;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
/* Allocate a new node for a trie.
Packit 90a5c9
 * If parent is non-NULL, link the new node under the parent node with
Packit 90a5c9
 * key 'c' (or, if an existing child node matches, return that one)
Packit 90a5c9
 */
Packit 90a5c9
static filter_trie_node *trie_node_alloc(apr_pool_t *p,
Packit 90a5c9
                                         filter_trie_node *parent, char c)
Packit 90a5c9
{
Packit 90a5c9
    filter_trie_node *new_node;
Packit 90a5c9
    if (parent) {
Packit 90a5c9
        int i;
Packit 90a5c9
        for (i = 0; i < parent->nchildren; i++) {
Packit 90a5c9
            if (c == parent->children[i].c) {
Packit 90a5c9
                return parent->children[i].child;
Packit 90a5c9
            }
Packit 90a5c9
            else if (c < parent->children[i].c) {
Packit 90a5c9
                break;
Packit 90a5c9
            }
Packit 90a5c9
        }
Packit 90a5c9
        new_node =
Packit 90a5c9
            (filter_trie_node *)apr_palloc(p, sizeof(filter_trie_node));
Packit 90a5c9
        trie_node_link(p, parent, new_node, c);
Packit 90a5c9
    }
Packit 90a5c9
    else { /* No parent node */
Packit 90a5c9
        new_node = (filter_trie_node *)apr_palloc(p,
Packit 90a5c9
                                                  sizeof(filter_trie_node));
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    new_node->frec = NULL;
Packit 90a5c9
    new_node->nchildren = 0;
Packit 90a5c9
    new_node->size = TRIE_INITIAL_SIZE;
Packit 90a5c9
    new_node->children = (filter_trie_child_ptr *)apr_palloc(p,
Packit 90a5c9
                             new_node->size * sizeof(filter_trie_child_ptr));
Packit 90a5c9
    return new_node;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
static filter_trie_node *registered_output_filters = NULL;
Packit 90a5c9
static filter_trie_node *registered_input_filters = NULL;
Packit 90a5c9
Packit 90a5c9
Packit 90a5c9
static apr_status_t filter_cleanup(void *ctx)
Packit 90a5c9
{
Packit 90a5c9
    registered_output_filters = NULL;
Packit 90a5c9
    registered_input_filters = NULL;
Packit 90a5c9
    return APR_SUCCESS;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
static ap_filter_rec_t *get_filter_handle(const char *name,
Packit 90a5c9
                                          const filter_trie_node *filter_set)
Packit 90a5c9
{
Packit 90a5c9
    if (filter_set) {
Packit 90a5c9
        const char *n;
Packit 90a5c9
        const filter_trie_node *node;
Packit 90a5c9
Packit 90a5c9
        node = filter_set;
Packit 90a5c9
        for (n = name; *n; n++) {
Packit 90a5c9
            int start, end;
Packit 90a5c9
            start = 0;
Packit 90a5c9
            end = node->nchildren - 1;
Packit 90a5c9
            while (end >= start) {
Packit 90a5c9
                int middle = (end + start) / 2;
Packit 90a5c9
                char ch = node->children[middle].c;
Packit 90a5c9
                if (*n == ch) {
Packit 90a5c9
                    node = node->children[middle].child;
Packit 90a5c9
                    break;
Packit 90a5c9
                }
Packit 90a5c9
                else if (*n < ch) {
Packit 90a5c9
                    end = middle - 1;
Packit 90a5c9
                }
Packit 90a5c9
                else {
Packit 90a5c9
                    start = middle + 1;
Packit 90a5c9
                }
Packit 90a5c9
            }
Packit 90a5c9
            if (end < start) {
Packit 90a5c9
                node = NULL;
Packit 90a5c9
                break;
Packit 90a5c9
            }
Packit 90a5c9
        }
Packit 90a5c9
Packit 90a5c9
        if (node && node->frec) {
Packit 90a5c9
            return node->frec;
Packit 90a5c9
        }
Packit 90a5c9
    }
Packit 90a5c9
    return NULL;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
AP_DECLARE(ap_filter_rec_t *)ap_get_output_filter_handle(const char *name)
Packit 90a5c9
{
Packit 90a5c9
    return get_filter_handle(name, registered_output_filters);
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
AP_DECLARE(ap_filter_rec_t *)ap_get_input_filter_handle(const char *name)
Packit 90a5c9
{
Packit 90a5c9
    return get_filter_handle(name, registered_input_filters);
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
static ap_filter_rec_t *register_filter(const char *name,
Packit 90a5c9
                            ap_filter_func filter_func,
Packit 90a5c9
                            ap_init_filter_func filter_init,
Packit 90a5c9
                            ap_filter_type ftype,
Packit 90a5c9
                            filter_trie_node **reg_filter_set)
Packit 90a5c9
{
Packit 90a5c9
    ap_filter_rec_t *frec;
Packit 90a5c9
    char *normalized_name;
Packit 90a5c9
    const char *n;
Packit 90a5c9
    filter_trie_node *node;
Packit 90a5c9
Packit 90a5c9
    if (!*reg_filter_set) {
Packit 90a5c9
        *reg_filter_set = trie_node_alloc(FILTER_POOL, NULL, 0);
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    normalized_name = apr_pstrdup(FILTER_POOL, name);
Packit 90a5c9
    ap_str_tolower(normalized_name);
Packit 90a5c9
Packit 90a5c9
    node = *reg_filter_set;
Packit 90a5c9
    for (n = normalized_name; *n; n++) {
Packit 90a5c9
        filter_trie_node *child = trie_node_alloc(FILTER_POOL, node, *n);
Packit 90a5c9
        if (apr_isalpha(*n)) {
Packit 90a5c9
            trie_node_link(FILTER_POOL, node, child, apr_toupper(*n));
Packit 90a5c9
        }
Packit 90a5c9
        node = child;
Packit 90a5c9
    }
Packit 90a5c9
    if (node->frec) {
Packit 90a5c9
        frec = node->frec;
Packit 90a5c9
    }
Packit 90a5c9
    else {
Packit 90a5c9
        frec = apr_pcalloc(FILTER_POOL, sizeof(*frec));
Packit 90a5c9
        node->frec = frec;
Packit 90a5c9
        frec->name = normalized_name;
Packit 90a5c9
    }
Packit 90a5c9
    frec->filter_func = filter_func;
Packit 90a5c9
    frec->filter_init_func = filter_init;
Packit 90a5c9
    frec->ftype = ftype;
Packit 90a5c9
Packit 90a5c9
    apr_pool_cleanup_register(FILTER_POOL, NULL, filter_cleanup,
Packit 90a5c9
                              apr_pool_cleanup_null);
Packit 90a5c9
    return frec;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
AP_DECLARE(ap_filter_rec_t *) ap_register_input_filter(const char *name,
Packit 90a5c9
                                          ap_in_filter_func filter_func,
Packit 90a5c9
                                          ap_init_filter_func filter_init,
Packit 90a5c9
                                          ap_filter_type ftype)
Packit 90a5c9
{
Packit 90a5c9
    ap_filter_func f;
Packit 90a5c9
    f.in_func = filter_func;
Packit 90a5c9
    return register_filter(name, f, filter_init, ftype,
Packit 90a5c9
                           &registered_input_filters);
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
AP_DECLARE(ap_filter_rec_t *) ap_register_output_filter(const char *name,
Packit 90a5c9
                                           ap_out_filter_func filter_func,
Packit 90a5c9
                                           ap_init_filter_func filter_init,
Packit 90a5c9
                                           ap_filter_type ftype)
Packit 90a5c9
{
Packit 90a5c9
    return ap_register_output_filter_protocol(name, filter_func,
Packit 90a5c9
                                              filter_init, ftype, 0);
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
AP_DECLARE(ap_filter_rec_t *) ap_register_output_filter_protocol(
Packit 90a5c9
                                           const char *name,
Packit 90a5c9
                                           ap_out_filter_func filter_func,
Packit 90a5c9
                                           ap_init_filter_func filter_init,
Packit 90a5c9
                                           ap_filter_type ftype,
Packit 90a5c9
                                           unsigned int proto_flags)
Packit 90a5c9
{
Packit 90a5c9
    ap_filter_rec_t* ret ;
Packit 90a5c9
    ap_filter_func f;
Packit 90a5c9
    f.out_func = filter_func;
Packit 90a5c9
    ret = register_filter(name, f, filter_init, ftype,
Packit 90a5c9
                          &registered_output_filters);
Packit 90a5c9
    ret->proto_flags = proto_flags ;
Packit 90a5c9
    return ret ;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
static ap_filter_t *add_any_filter_handle(ap_filter_rec_t *frec, void *ctx,
Packit 90a5c9
                                          request_rec *r, conn_rec *c,
Packit 90a5c9
                                          ap_filter_t **r_filters,
Packit 90a5c9
                                          ap_filter_t **p_filters,
Packit 90a5c9
                                          ap_filter_t **c_filters)
Packit 90a5c9
{
Packit 90a5c9
    apr_pool_t *p = frec->ftype < AP_FTYPE_CONNECTION && r ? r->pool : c->pool;
Packit 90a5c9
    ap_filter_t *f = apr_palloc(p, sizeof(*f));
Packit 90a5c9
    ap_filter_t **outf;
Packit 90a5c9
Packit 90a5c9
    if (frec->ftype < AP_FTYPE_PROTOCOL) {
Packit 90a5c9
        if (r) {
Packit 90a5c9
            outf = r_filters;
Packit 90a5c9
        }
Packit 90a5c9
        else {
Packit 90a5c9
            ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(00080)
Packit 90a5c9
                          "a content filter was added without a request: %s", frec->name);
Packit 90a5c9
            return NULL;
Packit 90a5c9
        }
Packit 90a5c9
    }
Packit 90a5c9
    else if (frec->ftype < AP_FTYPE_CONNECTION) {
Packit 90a5c9
        if (r) {
Packit 90a5c9
            outf = p_filters;
Packit 90a5c9
        }
Packit 90a5c9
        else {
Packit 90a5c9
            ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c, APLOGNO(00081)
Packit 90a5c9
                          "a protocol filter was added without a request: %s", frec->name);
Packit 90a5c9
            return NULL;
Packit 90a5c9
        }
Packit 90a5c9
    }
Packit 90a5c9
    else {
Packit 90a5c9
        outf = c_filters;
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    f->frec = frec;
Packit 90a5c9
    f->ctx = ctx;
Packit 90a5c9
    /* f->r must always be NULL for connection filters */
Packit 90a5c9
    f->r = frec->ftype < AP_FTYPE_CONNECTION ? r : NULL;
Packit 90a5c9
    f->c = c;
Packit 90a5c9
    f->next = NULL;
Packit 90a5c9
Packit 90a5c9
    if (INSERT_BEFORE(f, *outf)) {
Packit 90a5c9
        f->next = *outf;
Packit 90a5c9
Packit 90a5c9
        if (*outf) {
Packit 90a5c9
            ap_filter_t *first = NULL;
Packit 90a5c9
Packit 90a5c9
            if (r) {
Packit 90a5c9
                /* If we are adding our first non-connection filter,
Packit 90a5c9
                 * Then don't try to find the right location, it is
Packit 90a5c9
                 * automatically first.
Packit 90a5c9
                 */
Packit 90a5c9
                if (*r_filters != *c_filters) {
Packit 90a5c9
                    first = *r_filters;
Packit 90a5c9
                    while (first && (first->next != (*outf))) {
Packit 90a5c9
                        first = first->next;
Packit 90a5c9
                    }
Packit 90a5c9
                }
Packit 90a5c9
            }
Packit 90a5c9
            if (first && first != (*outf)) {
Packit 90a5c9
                first->next = f;
Packit 90a5c9
            }
Packit 90a5c9
        }
Packit 90a5c9
        *outf = f;
Packit 90a5c9
    }
Packit 90a5c9
    else {
Packit 90a5c9
        ap_filter_t *fscan = *outf;
Packit 90a5c9
        while (!INSERT_BEFORE(f, fscan->next))
Packit 90a5c9
            fscan = fscan->next;
Packit 90a5c9
Packit 90a5c9
        f->next = fscan->next;
Packit 90a5c9
        fscan->next = f;
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    if (frec->ftype < AP_FTYPE_CONNECTION && (*r_filters == *c_filters)) {
Packit 90a5c9
        *r_filters = *p_filters;
Packit 90a5c9
    }
Packit 90a5c9
    return f;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
static ap_filter_t *add_any_filter(const char *name, void *ctx,
Packit 90a5c9
                                   request_rec *r, conn_rec *c,
Packit 90a5c9
                                   const filter_trie_node *reg_filter_set,
Packit 90a5c9
                                   ap_filter_t **r_filters,
Packit 90a5c9
                                   ap_filter_t **p_filters,
Packit 90a5c9
                                   ap_filter_t **c_filters)
Packit 90a5c9
{
Packit 90a5c9
    if (reg_filter_set) {
Packit 90a5c9
        const char *n;
Packit 90a5c9
        const filter_trie_node *node;
Packit 90a5c9
Packit 90a5c9
        node = reg_filter_set;
Packit 90a5c9
        for (n = name; *n; n++) {
Packit 90a5c9
            int start, end;
Packit 90a5c9
            start = 0;
Packit 90a5c9
            end = node->nchildren - 1;
Packit 90a5c9
            while (end >= start) {
Packit 90a5c9
                int middle = (end + start) / 2;
Packit 90a5c9
                char ch = node->children[middle].c;
Packit 90a5c9
                if (*n == ch) {
Packit 90a5c9
                    node = node->children[middle].child;
Packit 90a5c9
                    break;
Packit 90a5c9
                }
Packit 90a5c9
                else if (*n < ch) {
Packit 90a5c9
                    end = middle - 1;
Packit 90a5c9
                }
Packit 90a5c9
                else {
Packit 90a5c9
                    start = middle + 1;
Packit 90a5c9
                }
Packit 90a5c9
            }
Packit 90a5c9
            if (end < start) {
Packit 90a5c9
                node = NULL;
Packit 90a5c9
                break;
Packit 90a5c9
            }
Packit 90a5c9
        }
Packit 90a5c9
Packit 90a5c9
        if (node && node->frec) {
Packit 90a5c9
            return add_any_filter_handle(node->frec, ctx, r, c, r_filters,
Packit 90a5c9
                                         p_filters, c_filters);
Packit 90a5c9
        }
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, r ? r->connection : c, APLOGNO(00082)
Packit 90a5c9
                  "an unknown filter was not added: %s", name);
Packit 90a5c9
    return NULL;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
AP_DECLARE(ap_filter_t *) ap_add_input_filter(const char *name, void *ctx,
Packit 90a5c9
                                              request_rec *r, conn_rec *c)
Packit 90a5c9
{
Packit 90a5c9
    return add_any_filter(name, ctx, r, c, registered_input_filters,
Packit 90a5c9
                          r ? &r->input_filters : NULL,
Packit 90a5c9
                          r ? &r->proto_input_filters : NULL, &c->input_filters);
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
AP_DECLARE(ap_filter_t *) ap_add_input_filter_handle(ap_filter_rec_t *f,
Packit 90a5c9
                                                     void *ctx,
Packit 90a5c9
                                                     request_rec *r,
Packit 90a5c9
                                                     conn_rec *c)
Packit 90a5c9
{
Packit 90a5c9
    return add_any_filter_handle(f, ctx, r, c, r ? &r->input_filters : NULL,
Packit 90a5c9
                                 r ? &r->proto_input_filters : NULL,
Packit 90a5c9
                                 &c->input_filters);
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
AP_DECLARE(ap_filter_t *) ap_add_output_filter(const char *name, void *ctx,
Packit 90a5c9
                                               request_rec *r, conn_rec *c)
Packit 90a5c9
{
Packit 90a5c9
    return add_any_filter(name, ctx, r, c, registered_output_filters,
Packit 90a5c9
                          r ? &r->output_filters : NULL,
Packit 90a5c9
                          r ? &r->proto_output_filters : NULL, &c->output_filters);
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
AP_DECLARE(ap_filter_t *) ap_add_output_filter_handle(ap_filter_rec_t *f,
Packit 90a5c9
                                                      void *ctx,
Packit 90a5c9
                                                      request_rec *r,
Packit 90a5c9
                                                      conn_rec *c)
Packit 90a5c9
{
Packit 90a5c9
    return add_any_filter_handle(f, ctx, r, c, r ? &r->output_filters : NULL,
Packit 90a5c9
                                 r ? &r->proto_output_filters : NULL,
Packit 90a5c9
                                 &c->output_filters);
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
static void remove_any_filter(ap_filter_t *f, ap_filter_t **r_filt, ap_filter_t **p_filt,
Packit 90a5c9
                              ap_filter_t **c_filt)
Packit 90a5c9
{
Packit 90a5c9
    ap_filter_t **curr = r_filt ? r_filt : c_filt;
Packit 90a5c9
    ap_filter_t *fscan = *curr;
Packit 90a5c9
Packit 90a5c9
    if (p_filt && *p_filt == f)
Packit 90a5c9
        *p_filt = (*p_filt)->next;
Packit 90a5c9
Packit 90a5c9
    if (*curr == f) {
Packit 90a5c9
        *curr = (*curr)->next;
Packit 90a5c9
        return;
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    while (fscan->next != f) {
Packit 90a5c9
        if (!(fscan = fscan->next)) {
Packit 90a5c9
            return;
Packit 90a5c9
        }
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    fscan->next = f->next;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
AP_DECLARE(void) ap_remove_input_filter(ap_filter_t *f)
Packit 90a5c9
{
Packit 90a5c9
    remove_any_filter(f, f->r ? &f->r->input_filters : NULL,
Packit 90a5c9
                      f->r ? &f->r->proto_input_filters : NULL,
Packit 90a5c9
                      &f->c->input_filters);
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
AP_DECLARE(void) ap_remove_output_filter(ap_filter_t *f)
Packit 90a5c9
{
Packit 90a5c9
    remove_any_filter(f, f->r ? &f->r->output_filters : NULL,
Packit 90a5c9
                      f->r ? &f->r->proto_output_filters : NULL,
Packit 90a5c9
                      &f->c->output_filters);
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
AP_DECLARE(apr_status_t) ap_remove_input_filter_byhandle(ap_filter_t *next,
Packit 90a5c9
                                                         const char *handle)
Packit 90a5c9
{
Packit 90a5c9
    ap_filter_t *found = NULL;
Packit 90a5c9
    ap_filter_rec_t *filter;
Packit 90a5c9
Packit 90a5c9
    if (!handle) {
Packit 90a5c9
        return APR_EINVAL;
Packit 90a5c9
    }
Packit 90a5c9
    filter = ap_get_input_filter_handle(handle);
Packit 90a5c9
    if (!filter) {
Packit 90a5c9
        return APR_NOTFOUND;
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    while (next) {
Packit 90a5c9
        if (next->frec == filter) {
Packit 90a5c9
            found = next;
Packit 90a5c9
            break;
Packit 90a5c9
        }
Packit 90a5c9
        next = next->next;
Packit 90a5c9
    }
Packit 90a5c9
    if (found) {
Packit 90a5c9
        ap_remove_input_filter(found);
Packit 90a5c9
        return APR_SUCCESS;
Packit 90a5c9
    }
Packit 90a5c9
    return APR_NOTFOUND;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
AP_DECLARE(apr_status_t) ap_remove_output_filter_byhandle(ap_filter_t *next,
Packit 90a5c9
                                                          const char *handle)
Packit 90a5c9
{
Packit 90a5c9
    ap_filter_t *found = NULL;
Packit 90a5c9
    ap_filter_rec_t *filter;
Packit 90a5c9
Packit 90a5c9
    if (!handle) {
Packit 90a5c9
        return APR_EINVAL;
Packit 90a5c9
    }
Packit 90a5c9
    filter = ap_get_output_filter_handle(handle);
Packit 90a5c9
    if (!filter) {
Packit 90a5c9
        return APR_NOTFOUND;
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    while (next) {
Packit 90a5c9
        if (next->frec == filter) {
Packit 90a5c9
            found = next;
Packit 90a5c9
            break;
Packit 90a5c9
        }
Packit 90a5c9
        next = next->next;
Packit 90a5c9
    }
Packit 90a5c9
    if (found) {
Packit 90a5c9
        ap_remove_output_filter(found);
Packit 90a5c9
        return APR_SUCCESS;
Packit 90a5c9
    }
Packit 90a5c9
    return APR_NOTFOUND;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
Packit 90a5c9
/*
Packit 90a5c9
 * Read data from the next filter in the filter stack.  Data should be
Packit 90a5c9
 * modified in the bucket brigade that is passed in.  The core allocates the
Packit 90a5c9
 * bucket brigade, modules that wish to replace large chunks of data or to
Packit 90a5c9
 * save data off to the side should probably create their own temporary
Packit 90a5c9
 * brigade especially for that use.
Packit 90a5c9
 */
Packit 90a5c9
AP_DECLARE(apr_status_t) ap_get_brigade(ap_filter_t *next,
Packit 90a5c9
                                        apr_bucket_brigade *bb,
Packit 90a5c9
                                        ap_input_mode_t mode,
Packit 90a5c9
                                        apr_read_type_e block,
Packit 90a5c9
                                        apr_off_t readbytes)
Packit 90a5c9
{
Packit 90a5c9
    if (next) {
Packit 90a5c9
        return next->frec->filter_func.in_func(next, bb, mode, block,
Packit 90a5c9
                                               readbytes);
Packit 90a5c9
    }
Packit 90a5c9
    return AP_NOBODY_READ;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
/* Pass the buckets to the next filter in the filter stack.  If the
Packit 90a5c9
 * current filter is a handler, we should get NULL passed in instead of
Packit 90a5c9
 * the current filter.  At that point, we can just call the first filter in
Packit 90a5c9
 * the stack, or r->output_filters.
Packit 90a5c9
 */
Packit 90a5c9
AP_DECLARE(apr_status_t) ap_pass_brigade(ap_filter_t *next,
Packit 90a5c9
                                         apr_bucket_brigade *bb)
Packit 90a5c9
{
Packit 90a5c9
    if (next) {
Packit 90a5c9
        apr_bucket *e;
Packit 90a5c9
        if ((e = APR_BRIGADE_LAST(bb)) && APR_BUCKET_IS_EOS(e) && next->r) {
Packit 90a5c9
            /* This is only safe because HTTP_HEADER filter is always in
Packit 90a5c9
             * the filter stack.   This ensures that there is ALWAYS a
Packit 90a5c9
             * request-based filter that we can attach this to.  If the
Packit 90a5c9
             * HTTP_FILTER is removed, and another filter is not put in its
Packit 90a5c9
             * place, then handlers like mod_cgi, which attach their own
Packit 90a5c9
             * EOS bucket to the brigade will be broken, because we will
Packit 90a5c9
             * get two EOS buckets on the same request.
Packit 90a5c9
             */
Packit 90a5c9
            next->r->eos_sent = 1;
Packit 90a5c9
Packit 90a5c9
            /* remember the eos for internal redirects, too */
Packit 90a5c9
            if (next->r->prev) {
Packit 90a5c9
                request_rec *prev = next->r->prev;
Packit 90a5c9
Packit 90a5c9
                while (prev) {
Packit 90a5c9
                    prev->eos_sent = 1;
Packit 90a5c9
                    prev = prev->prev;
Packit 90a5c9
                }
Packit 90a5c9
            }
Packit 90a5c9
        }
Packit 90a5c9
        return next->frec->filter_func.out_func(next, bb);
Packit 90a5c9
    }
Packit 90a5c9
    return AP_NOBODY_WROTE;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
/* Pass the buckets to the next filter in the filter stack
Packit 90a5c9
 * checking return status for filter errors.
Packit 90a5c9
 * returns: OK if ap_pass_brigade returns APR_SUCCESS
Packit 90a5c9
 *          AP_FILTER_ERROR if filter error exists
Packit 90a5c9
 *          HTTP_INTERNAL_SERVER_ERROR for all other cases
Packit 90a5c9
 *          logged with optional errmsg
Packit 90a5c9
 */
Packit 90a5c9
AP_DECLARE(apr_status_t) ap_pass_brigade_fchk(request_rec *r,
Packit 90a5c9
                                              apr_bucket_brigade *bb,
Packit 90a5c9
                                              const char *fmt,
Packit 90a5c9
                                              ...)
Packit 90a5c9
{
Packit 90a5c9
    apr_status_t rv;
Packit 90a5c9
Packit 90a5c9
    rv = ap_pass_brigade(r->output_filters, bb);
Packit 90a5c9
    if (rv != APR_SUCCESS) {
Packit 90a5c9
        if (rv != AP_FILTER_ERROR) {
Packit 90a5c9
            if (!fmt)
Packit 90a5c9
                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r, APLOGNO(00083)
Packit 90a5c9
                              "ap_pass_brigade returned %d", rv);
Packit 90a5c9
            else {
Packit 90a5c9
                va_list ap;
Packit 90a5c9
                const char *res;
Packit 90a5c9
                va_start(ap, fmt);
Packit 90a5c9
                res = apr_pvsprintf(r->pool, fmt, ap);
Packit 90a5c9
                va_end(ap);
Packit 90a5c9
                ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r, APLOGNO(03158)
Packit 90a5c9
                              "%s", res);
Packit 90a5c9
            }
Packit 90a5c9
            return HTTP_INTERNAL_SERVER_ERROR;
Packit 90a5c9
        }
Packit 90a5c9
        return AP_FILTER_ERROR;
Packit 90a5c9
    }
Packit 90a5c9
    return OK;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
AP_DECLARE(apr_status_t) ap_save_brigade(ap_filter_t *f,
Packit 90a5c9
                                         apr_bucket_brigade **saveto,
Packit 90a5c9
                                         apr_bucket_brigade **b, apr_pool_t *p)
Packit 90a5c9
{
Packit 90a5c9
    apr_bucket *e;
Packit 90a5c9
    apr_status_t rv, srv = APR_SUCCESS;
Packit 90a5c9
Packit 90a5c9
    /* If have never stored any data in the filter, then we had better
Packit 90a5c9
     * create an empty bucket brigade so that we can concat.
Packit 90a5c9
     */
Packit 90a5c9
    if (!(*saveto)) {
Packit 90a5c9
        *saveto = apr_brigade_create(p, f->c->bucket_alloc);
Packit 90a5c9
    }
Packit 90a5c9
Packit 90a5c9
    for (e = APR_BRIGADE_FIRST(*b);
Packit 90a5c9
         e != APR_BRIGADE_SENTINEL(*b);
Packit 90a5c9
         e = APR_BUCKET_NEXT(e))
Packit 90a5c9
    {
Packit 90a5c9
        rv = apr_bucket_setaside(e, p);
Packit 90a5c9
Packit 90a5c9
        /* If the bucket type does not implement setaside, then
Packit 90a5c9
         * (hopefully) morph it into a bucket type which does, and set
Packit 90a5c9
         * *that* aside... */
Packit 90a5c9
        if (rv == APR_ENOTIMPL) {
Packit 90a5c9
            const char *s;
Packit 90a5c9
            apr_size_t n;
Packit 90a5c9
Packit 90a5c9
            rv = apr_bucket_read(e, &s, &n, APR_BLOCK_READ);
Packit 90a5c9
            if (rv == APR_SUCCESS) {
Packit 90a5c9
                rv = apr_bucket_setaside(e, p);
Packit 90a5c9
            }
Packit 90a5c9
        }
Packit 90a5c9
Packit 90a5c9
        if (rv != APR_SUCCESS) {
Packit 90a5c9
            srv = rv;
Packit 90a5c9
            /* Return an error but still save the brigade if
Packit 90a5c9
             * ->setaside() is really not implemented. */
Packit 90a5c9
            if (rv != APR_ENOTIMPL) {
Packit 90a5c9
                return rv;
Packit 90a5c9
            }
Packit 90a5c9
        }
Packit 90a5c9
    }
Packit 90a5c9
    APR_BRIGADE_CONCAT(*saveto, *b);
Packit 90a5c9
    return srv;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
AP_DECLARE_NONSTD(apr_status_t) ap_filter_flush(apr_bucket_brigade *bb,
Packit 90a5c9
                                                void *ctx)
Packit 90a5c9
{
Packit 90a5c9
    ap_filter_t *f = ctx;
Packit 90a5c9
    apr_status_t rv;
Packit 90a5c9
Packit 90a5c9
    rv = ap_pass_brigade(f, bb);
Packit 90a5c9
Packit 90a5c9
    /* Before invocation of the flush callback, apr_brigade_write et
Packit 90a5c9
     * al may place transient buckets in the brigade, which will fall
Packit 90a5c9
     * out of scope after returning.  Empty the brigade here, to avoid
Packit 90a5c9
     * issues with leaving such buckets in the brigade if some filter
Packit 90a5c9
     * fails and leaves a non-empty brigade. */
Packit 90a5c9
    apr_brigade_cleanup(bb);
Packit 90a5c9
Packit 90a5c9
    return rv;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
AP_DECLARE(apr_status_t) ap_fflush(ap_filter_t *f, apr_bucket_brigade *bb)
Packit 90a5c9
{
Packit 90a5c9
    apr_bucket *b;
Packit 90a5c9
Packit 90a5c9
    b = apr_bucket_flush_create(f->c->bucket_alloc);
Packit 90a5c9
    APR_BRIGADE_INSERT_TAIL(bb, b);
Packit 90a5c9
    return ap_pass_brigade(f, bb);
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
AP_DECLARE_NONSTD(apr_status_t) ap_fputstrs(ap_filter_t *f,
Packit 90a5c9
                                            apr_bucket_brigade *bb, ...)
Packit 90a5c9
{
Packit 90a5c9
    va_list args;
Packit 90a5c9
    apr_status_t rv;
Packit 90a5c9
Packit 90a5c9
    va_start(args, bb);
Packit 90a5c9
    rv = apr_brigade_vputstrs(bb, ap_filter_flush, f, args);
Packit 90a5c9
    va_end(args);
Packit 90a5c9
    return rv;
Packit 90a5c9
}
Packit 90a5c9
Packit 90a5c9
AP_DECLARE_NONSTD(apr_status_t) ap_fprintf(ap_filter_t *f,
Packit 90a5c9
                                           apr_bucket_brigade *bb,
Packit 90a5c9
                                           const char *fmt,
Packit 90a5c9
                                           ...)
Packit 90a5c9
{
Packit 90a5c9
    va_list args;
Packit 90a5c9
    apr_status_t rv;
Packit 90a5c9
Packit 90a5c9
    va_start(args, fmt);
Packit 90a5c9
    rv = apr_brigade_vprintf(bb, ap_filter_flush, f, fmt, args);
Packit 90a5c9
    va_end(args);
Packit 90a5c9
    return rv;
Packit 90a5c9
}
Packit 90a5c9
AP_DECLARE(void) ap_filter_protocol(ap_filter_t *f, unsigned int flags)
Packit 90a5c9
{
Packit 90a5c9
    f->frec->proto_flags = flags ;
Packit 90a5c9
}