1 /* ====================================================================
2 * The Apache Software License, Version 1.1
4 * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
19 * 3. The end-user documentation included with the redistribution,
20 * if any, must include the following acknowledgment:
21 * "This product includes software developed by the
22 * Apache Software Foundation (http://www.apache.org/)."
23 * Alternately, this acknowledgment may appear in the software itself,
24 * if and wherever such third-party acknowledgments normally appear.
26 * 4. The names "Apache" and "Apache Software Foundation" must
27 * not be used to endorse or promote products derived from this
28 * software without prior written permission. For written
29 * permission, please contact apache@apache.org.
31 * 5. Products derived from this software may not be called "Apache",
32 * nor may "Apache" appear in their name, without prior written
33 * permission of the Apache Software Foundation.
35 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47 * ====================================================================
49 * This software consists of voluntary contributions made by many
50 * individuals on behalf of the Apache Software Foundation. For more
51 * information on the Apache Software Foundation, please see
52 * <http://www.apache.org/>.
55 #define APR_WANT_STRFUNC
59 #include "apr_strings.h"
63 #include "util_filter.h"
65 /* NOTE: Apache's current design doesn't allow a pool to be passed thru,
66 so we depend on a global to hold the correct pool
68 #define FILTER_POOL apr_global_hook_pool
69 #include "apr_hooks.h" /* for apr_global_hook_pool */
72 ** This macro returns true/false if a given filter should be inserted BEFORE
73 ** another filter. This will happen when one of: 1) there isn't another
74 ** filter; 2) that filter has a higher filter type (class); 3) that filter
75 ** corresponds to a different request.
77 #define INSERT_BEFORE(f, before_this) ((before_this) == NULL \
78 || (before_this)->frec->ftype > (f)->frec->ftype \
79 || (before_this)->r != (f)->r)
81 /* Trie structure to hold the mapping from registered
82 * filter names to filters
85 typedef struct filter_trie_node filter_trie_node;
89 filter_trie_node *child;
90 } filter_trie_child_ptr;
92 /* Each trie node has an array of pointers to its children.
93 * The array is kept in sorted order so that add_any_filter()
94 * can do a binary search
96 struct filter_trie_node {
97 ap_filter_rec_t *frec;
98 filter_trie_child_ptr *children;
103 #define TRIE_INITIAL_SIZE 4
105 /* Link a trie node to its parent
107 static void trie_node_link(apr_pool_t *p, filter_trie_node *parent,
108 filter_trie_node *child, int c)
112 if (parent->nchildren == parent->size) {
113 filter_trie_child_ptr *new;
115 new = (filter_trie_child_ptr *)apr_palloc(p, parent->size *
116 sizeof(filter_trie_child_ptr));
117 memcpy(new, parent->children, parent->nchildren *
118 sizeof(filter_trie_child_ptr));
119 parent->children = new;
122 for (i = 0; i < parent->nchildren; i++) {
123 if (c == parent->children[i].c) {
126 else if (c < parent->children[i].c) {
130 for (j = parent->nchildren; j > i; j--) {
131 parent->children[j].c = parent->children[j - 1].c;
132 parent->children[j].child = parent->children[j - 1].child;
134 parent->children[i].c = c;
135 parent->children[i].child = child;
140 /* Allocate a new node for a trie.
141 * If parent is non-NULL, link the new node under the parent node with
142 * key 'c' (or, if an existing child node matches, return that one)
144 static filter_trie_node *trie_node_alloc(apr_pool_t *p,
145 filter_trie_node *parent, char c)
147 filter_trie_node *new_node;
150 for (i = 0; i < parent->nchildren; i++) {
151 if (c == parent->children[i].c) {
152 return parent->children[i].child;
154 else if (c < parent->children[i].c) {
159 (filter_trie_node *)apr_palloc(p, sizeof(filter_trie_node));
160 trie_node_link(p, parent, new_node, c);
162 else { /* No parent node */
163 new_node = (filter_trie_node *)apr_palloc(p,
164 sizeof(filter_trie_node));
167 new_node->frec = NULL;
168 new_node->nchildren = 0;
169 new_node->size = TRIE_INITIAL_SIZE;
170 new_node->children = (filter_trie_child_ptr *)apr_palloc(p,
171 new_node->size * sizeof(filter_trie_child_ptr));
175 static filter_trie_node *registered_output_filters = NULL;
176 static filter_trie_node *registered_input_filters = NULL;
179 static apr_status_t filter_cleanup(void *ctx)
181 registered_output_filters = NULL;
182 registered_input_filters = NULL;
186 static ap_filter_rec_t *register_filter(const char *name,
187 ap_filter_func filter_func,
188 ap_filter_type ftype,
189 filter_trie_node **reg_filter_set)
191 ap_filter_rec_t *frec = apr_palloc(FILTER_POOL, sizeof(*frec));
193 filter_trie_node *node;
195 if (!*reg_filter_set) {
196 *reg_filter_set = trie_node_alloc(FILTER_POOL, NULL, 0);
199 frec->name = apr_pstrdup(FILTER_POOL, name);
200 ap_str_tolower((char *)frec->name);
201 frec->filter_func = filter_func;
204 node = *reg_filter_set;
205 for (n = frec->name; *n; n++) {
206 filter_trie_node *child = trie_node_alloc(FILTER_POOL, node, *n);
207 if (apr_isalpha(*n)) {
208 trie_node_link(FILTER_POOL, node, child, apr_toupper(*n));
214 apr_pool_cleanup_register(FILTER_POOL, NULL, filter_cleanup,
215 apr_pool_cleanup_null);
219 AP_DECLARE(ap_filter_rec_t *) ap_register_input_filter(const char *name,
220 ap_in_filter_func filter_func,
221 ap_filter_type ftype)
224 f.in_func = filter_func;
225 return register_filter(name, f, ftype, ®istered_input_filters);
228 AP_DECLARE(ap_filter_rec_t *) ap_register_output_filter(const char *name,
229 ap_out_filter_func filter_func,
230 ap_filter_type ftype)
233 f.out_func = filter_func;
234 return register_filter(name, f, ftype, ®istered_output_filters);
237 static ap_filter_t *add_any_filter(const char *name, void *ctx,
238 request_rec *r, conn_rec *c,
239 const filter_trie_node *reg_filter_set,
240 ap_filter_t **r_filters,
241 ap_filter_t **c_filters)
243 if (reg_filter_set) {
245 const filter_trie_node *node;
247 node = reg_filter_set;
248 for (n = name; *n; n++) {
251 end = node->nchildren - 1;
252 while (end >= start) {
253 int middle = (end + start) / 2;
254 char ch = node->children[middle].c;
256 node = node->children[middle].child;
272 if (node && node->frec) {
273 apr_pool_t* p = r ? r->pool : c->pool;
274 ap_filter_t *f = apr_palloc(p, sizeof(*f));
275 ap_filter_t **outf = r ? r_filters : c_filters;
277 f->frec = node->frec;
282 if (INSERT_BEFORE(f, *outf)) {
287 ap_filter_t *fscan = *outf;
288 while (!INSERT_BEFORE(f, fscan->next))
290 f->next = fscan->next;
298 ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, NULL,
299 "an unknown filter was not added: %s", name);
303 AP_DECLARE(ap_filter_t *) ap_add_input_filter(const char *name, void *ctx,
304 request_rec *r, conn_rec *c)
306 return add_any_filter(name, ctx, r, c, registered_input_filters,
307 r ? &r->input_filters : NULL, &c->input_filters);
310 AP_DECLARE(ap_filter_t *) ap_add_output_filter(const char *name, void *ctx,
311 request_rec *r, conn_rec *c)
313 return add_any_filter(name, ctx, r, c, registered_output_filters,
314 r ? &r->output_filters : NULL, &c->output_filters);
317 static void remove_any_filter(ap_filter_t *f, ap_filter_t **r_filt,
318 ap_filter_t **c_filt)
320 ap_filter_t **curr = r_filt ? r_filt : c_filt;
321 ap_filter_t *fscan = *curr;
324 *curr = (*curr)->next;
328 while (fscan->next != f) {
329 if (!(fscan = fscan->next)) {
334 fscan->next = f->next;
337 AP_DECLARE(void) ap_remove_input_filter(ap_filter_t *f)
339 remove_any_filter(f, f->r ? &f->r->input_filters : NULL,
340 &f->c->input_filters);
343 AP_DECLARE(void) ap_remove_output_filter(ap_filter_t *f)
345 remove_any_filter(f, f->r ? &f->r->output_filters : NULL,
346 &f->c->output_filters);
350 * Read data from the next filter in the filter stack. Data should be
351 * modified in the bucket brigade that is passed in. The core allocates the
352 * bucket brigade, modules that wish to replace large chunks of data or to
353 * save data off to the side should probably create their own temporary
354 * brigade especially for that use.
356 AP_DECLARE(apr_status_t) ap_get_brigade(ap_filter_t *next,
357 apr_bucket_brigade *bb,
358 ap_input_mode_t mode,
359 apr_off_t *readbytes)
362 return next->frec->filter_func.in_func(next, bb, mode, readbytes);
364 return AP_NOBODY_READ;
367 /* Pass the buckets to the next filter in the filter stack. If the
368 * current filter is a handler, we should get NULL passed in instead of
369 * the current filter. At that point, we can just call the first filter in
370 * the stack, or r->output_filters.
372 AP_DECLARE(apr_status_t) ap_pass_brigade(ap_filter_t *next,
373 apr_bucket_brigade *bb)
377 if ((e = APR_BRIGADE_LAST(bb)) && APR_BUCKET_IS_EOS(e) && next->r) {
378 /* This is only safe because HTTP_HEADER filter is always in
379 * the filter stack. This ensures that there is ALWAYS a
380 * request-based filter that we can attach this to. If the
381 * HTTP_FILTER is removed, and another filter is not put in its
382 * place, then handlers like mod_cgi, which attach their own
383 * EOS bucket to the brigade will be broken, because we will
384 * get two EOS buckets on the same request.
386 next->r->eos_sent = 1;
388 return next->frec->filter_func.out_func(next, bb);
390 return AP_NOBODY_WROTE;
393 AP_DECLARE(apr_status_t) ap_save_brigade(ap_filter_t *f,
394 apr_bucket_brigade **saveto,
395 apr_bucket_brigade **b, apr_pool_t *p)
400 /* If have never stored any data in the filter, then we had better
401 * create an empty bucket brigade so that we can concat.
404 *saveto = apr_brigade_create(p);
407 APR_RING_FOREACH(e, &(*b)->list, apr_bucket, link) {
408 rv = apr_bucket_setaside(e, p);
409 if (rv != APR_SUCCESS
410 /* ### this ENOTIMPL will go away once we implement setaside
411 ### for all bucket types. */
412 && rv != APR_ENOTIMPL) {
416 APR_BRIGADE_CONCAT(*saveto, *b);
420 AP_DECLARE_NONSTD(apr_status_t) ap_filter_flush(apr_bucket_brigade *bb,
423 ap_filter_t *f = ctx;
425 return ap_pass_brigade(f, bb);
428 AP_DECLARE(apr_status_t) ap_fflush(ap_filter_t *f, apr_bucket_brigade *bb)
432 b = apr_bucket_flush_create();
433 APR_BRIGADE_INSERT_TAIL(bb, b);
434 return ap_pass_brigade(f, bb);
437 AP_DECLARE_NONSTD(apr_status_t) ap_fputstrs(ap_filter_t *f,
438 apr_bucket_brigade *bb, ...)
444 rv = apr_brigade_vputstrs(bb, ap_filter_flush, f, args);
449 AP_DECLARE_NONSTD(apr_status_t) ap_fprintf(ap_filter_t *f,
450 apr_bucket_brigade *bb,
458 rv = apr_brigade_vprintf(bb, ap_filter_flush, f, fmt, args);