📄 util_filter.c
字号:
/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as * applicable. * * Licensed 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. */#define APR_WANT_STRFUNC#include "apr_want.h"#include "apr_lib.h"#include "apr_hash.h"#include "apr_strings.h"#include "httpd.h"#include "http_log.h"#include "util_filter.h"/* NOTE: Apache's current design doesn't allow a pool to be passed thru, so we depend on a global to hold the correct pool*/#define FILTER_POOL apr_hook_global_pool#include "apr_hooks.h" /* for apr_hook_global_pool *//*** This macro returns true/false if a given filter should be inserted BEFORE** another filter. This will happen when one of: 1) there isn't another** filter; 2) that filter has a higher filter type (class); 3) that filter** corresponds to a different request.*/#define INSERT_BEFORE(f, before_this) ((before_this) == NULL \ || (before_this)->frec->ftype > (f)->frec->ftype \ || (before_this)->r != (f)->r)/* Trie structure to hold the mapping from registered * filter names to filters */typedef struct filter_trie_node filter_trie_node;typedef struct { int c; filter_trie_node *child;} filter_trie_child_ptr;/* Each trie node has an array of pointers to its children. * The array is kept in sorted order so that add_any_filter() * can do a binary search */struct filter_trie_node { ap_filter_rec_t *frec; filter_trie_child_ptr *children; int nchildren; int size;};#define TRIE_INITIAL_SIZE 4/* Link a trie node to its parent */static void trie_node_link(apr_pool_t *p, filter_trie_node *parent, filter_trie_node *child, int c){ int i, j; if (parent->nchildren == parent->size) { filter_trie_child_ptr *new; parent->size *= 2; new = (filter_trie_child_ptr *)apr_palloc(p, parent->size * sizeof(filter_trie_child_ptr)); memcpy(new, parent->children, parent->nchildren * sizeof(filter_trie_child_ptr)); parent->children = new; } for (i = 0; i < parent->nchildren; i++) { if (c == parent->children[i].c) { return; } else if (c < parent->children[i].c) { break; } } for (j = parent->nchildren; j > i; j--) { parent->children[j].c = parent->children[j - 1].c; parent->children[j].child = parent->children[j - 1].child; } parent->children[i].c = c; parent->children[i].child = child; parent->nchildren++;}/* Allocate a new node for a trie. * If parent is non-NULL, link the new node under the parent node with * key 'c' (or, if an existing child node matches, return that one) */static filter_trie_node *trie_node_alloc(apr_pool_t *p, filter_trie_node *parent, char c){ filter_trie_node *new_node; if (parent) { int i; for (i = 0; i < parent->nchildren; i++) { if (c == parent->children[i].c) { return parent->children[i].child; } else if (c < parent->children[i].c) { break; } } new_node = (filter_trie_node *)apr_palloc(p, sizeof(filter_trie_node)); trie_node_link(p, parent, new_node, c); } else { /* No parent node */ new_node = (filter_trie_node *)apr_palloc(p, sizeof(filter_trie_node)); } new_node->frec = NULL; new_node->nchildren = 0; new_node->size = TRIE_INITIAL_SIZE; new_node->children = (filter_trie_child_ptr *)apr_palloc(p, new_node->size * sizeof(filter_trie_child_ptr)); return new_node;}static filter_trie_node *registered_output_filters = NULL;static filter_trie_node *registered_input_filters = NULL;static apr_status_t filter_cleanup(void *ctx){ registered_output_filters = NULL; registered_input_filters = NULL; return APR_SUCCESS;}static ap_filter_rec_t *get_filter_handle(const char *name, const filter_trie_node *filter_set){ if (filter_set) { const char *n; const filter_trie_node *node; node = filter_set; for (n = name; *n; n++) { int start, end; start = 0; end = node->nchildren - 1; while (end >= start) { int middle = (end + start) / 2; char ch = node->children[middle].c; if (*n == ch) { node = node->children[middle].child; break; } else if (*n < ch) { end = middle - 1; } else { start = middle + 1; } } if (end < start) { node = NULL; break; } } if (node && node->frec) { return node->frec; } } return NULL;}AP_DECLARE(ap_filter_rec_t *)ap_get_output_filter_handle(const char *name){ return get_filter_handle(name, registered_output_filters);}AP_DECLARE(ap_filter_rec_t *)ap_get_input_filter_handle(const char *name){ return get_filter_handle(name, registered_input_filters);}static ap_filter_rec_t *register_filter(const char *name, ap_filter_func filter_func, ap_init_filter_func filter_init, ap_filter_type ftype, filter_trie_node **reg_filter_set){ ap_filter_rec_t *frec; char *normalized_name; const char *n; filter_trie_node *node; if (!*reg_filter_set) { *reg_filter_set = trie_node_alloc(FILTER_POOL, NULL, 0); } normalized_name = apr_pstrdup(FILTER_POOL, name); ap_str_tolower(normalized_name); node = *reg_filter_set; for (n = normalized_name; *n; n++) { filter_trie_node *child = trie_node_alloc(FILTER_POOL, node, *n); if (apr_isalpha(*n)) { trie_node_link(FILTER_POOL, node, child, apr_toupper(*n)); } node = child; } if (node->frec) { frec = node->frec; } else { frec = apr_palloc(FILTER_POOL, sizeof(*frec)); node->frec = frec; frec->name = normalized_name; } frec->filter_func = filter_func; frec->filter_init_func = filter_init; frec->ftype = ftype; apr_pool_cleanup_register(FILTER_POOL, NULL, filter_cleanup, apr_pool_cleanup_null); return frec;}AP_DECLARE(ap_filter_rec_t *) ap_register_input_filter(const char *name, ap_in_filter_func filter_func, ap_init_filter_func filter_init, ap_filter_type ftype){ ap_filter_func f; f.in_func = filter_func; return register_filter(name, f, filter_init, ftype, ®istered_input_filters);} AP_DECLARE(ap_filter_rec_t *) ap_register_output_filter(const char *name, ap_out_filter_func filter_func, ap_init_filter_func filter_init, ap_filter_type ftype){ ap_filter_func f; f.out_func = filter_func; return register_filter(name, f, filter_init, ftype, ®istered_output_filters);}static ap_filter_t *add_any_filter_handle(ap_filter_rec_t *frec, void *ctx, request_rec *r, conn_rec *c, ap_filter_t **r_filters, ap_filter_t **p_filters, ap_filter_t **c_filters){ apr_pool_t* p = r ? r->pool : c->pool; ap_filter_t *f = apr_palloc(p, sizeof(*f)); ap_filter_t **outf; if (frec->ftype < AP_FTYPE_PROTOCOL) { if (r) { outf = r_filters; } else { ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "a content filter was added without a request: %s", frec->name); return NULL; } } else if (frec->ftype < AP_FTYPE_CONNECTION) { if (r) { outf = p_filters; } else { ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, "a protocol filter was added without a request: %s", frec->name); return NULL; } } else { outf = c_filters; } f->frec = frec; f->ctx = ctx; f->r = r; f->c = c; f->next = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -