1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #define APR_WANT_STRFUNC
21 #include "apr_strings.h"
25 #include "util_filter.h"
27 /* NOTE: Apache's current design doesn't allow a pool to be passed thru,
28 so we depend on a global to hold the correct pool
30 #define FILTER_POOL apr_hook_global_pool
31 #include "apr_hooks.h" /* for apr_hook_global_pool */
34 ** This macro returns true/false if a given filter should be inserted BEFORE
35 ** another filter. This will happen when one of: 1) there isn't another
36 ** filter; 2) that filter has a higher filter type (class); 3) that filter
37 ** corresponds to a different request.
39 #define INSERT_BEFORE(f, before_this) ((before_this) == NULL \
40 || (before_this)->frec->ftype > (f)->frec->ftype \
41 || (before_this)->r != (f)->r)
43 /* Trie structure to hold the mapping from registered
44 * filter names to filters
47 typedef struct filter_trie_node filter_trie_node
;
51 filter_trie_node
*child
;
52 } filter_trie_child_ptr
;
54 /* Each trie node has an array of pointers to its children.
55 * The array is kept in sorted order so that add_any_filter()
56 * can do a binary search
58 struct filter_trie_node
{
59 ap_filter_rec_t
*frec
;
60 filter_trie_child_ptr
*children
;
65 #define TRIE_INITIAL_SIZE 4
67 /* Link a trie node to its parent
69 static void trie_node_link(apr_pool_t
*p
, filter_trie_node
*parent
,
70 filter_trie_node
*child
, int c
)
74 if (parent
->nchildren
== parent
->size
) {
75 filter_trie_child_ptr
*new;
77 new = (filter_trie_child_ptr
*)apr_palloc(p
, parent
->size
*
78 sizeof(filter_trie_child_ptr
));
79 memcpy(new, parent
->children
, parent
->nchildren
*
80 sizeof(filter_trie_child_ptr
));
81 parent
->children
= new;
84 for (i
= 0; i
< parent
->nchildren
; i
++) {
85 if (c
== parent
->children
[i
].c
) {
88 else if (c
< parent
->children
[i
].c
) {
92 for (j
= parent
->nchildren
; j
> i
; j
--) {
93 parent
->children
[j
].c
= parent
->children
[j
- 1].c
;
94 parent
->children
[j
].child
= parent
->children
[j
- 1].child
;
96 parent
->children
[i
].c
= c
;
97 parent
->children
[i
].child
= child
;
102 /* Allocate a new node for a trie.
103 * If parent is non-NULL, link the new node under the parent node with
104 * key 'c' (or, if an existing child node matches, return that one)
106 static filter_trie_node
*trie_node_alloc(apr_pool_t
*p
,
107 filter_trie_node
*parent
, char c
)
109 filter_trie_node
*new_node
;
112 for (i
= 0; i
< parent
->nchildren
; i
++) {
113 if (c
== parent
->children
[i
].c
) {
114 return parent
->children
[i
].child
;
116 else if (c
< parent
->children
[i
].c
) {
121 (filter_trie_node
*)apr_palloc(p
, sizeof(filter_trie_node
));
122 trie_node_link(p
, parent
, new_node
, c
);
124 else { /* No parent node */
125 new_node
= (filter_trie_node
*)apr_palloc(p
,
126 sizeof(filter_trie_node
));
129 new_node
->frec
= NULL
;
130 new_node
->nchildren
= 0;
131 new_node
->size
= TRIE_INITIAL_SIZE
;
132 new_node
->children
= (filter_trie_child_ptr
*)apr_palloc(p
,
133 new_node
->size
* sizeof(filter_trie_child_ptr
));
137 static filter_trie_node
*registered_output_filters
= NULL
;
138 static filter_trie_node
*registered_input_filters
= NULL
;
141 static apr_status_t
filter_cleanup(void *ctx
)
143 registered_output_filters
= NULL
;
144 registered_input_filters
= NULL
;
148 static ap_filter_rec_t
*get_filter_handle(const char *name
,
149 const filter_trie_node
*filter_set
)
153 const filter_trie_node
*node
;
156 for (n
= name
; *n
; n
++) {
159 end
= node
->nchildren
- 1;
160 while (end
>= start
) {
161 int middle
= (end
+ start
) / 2;
162 char ch
= node
->children
[middle
].c
;
164 node
= node
->children
[middle
].child
;
180 if (node
&& node
->frec
) {
187 AP_DECLARE(ap_filter_rec_t
*)ap_get_output_filter_handle(const char *name
)
189 return get_filter_handle(name
, registered_output_filters
);
192 AP_DECLARE(ap_filter_rec_t
*)ap_get_input_filter_handle(const char *name
)
194 return get_filter_handle(name
, registered_input_filters
);
197 static ap_filter_rec_t
*register_filter(const char *name
,
198 ap_filter_func filter_func
,
199 ap_init_filter_func filter_init
,
200 ap_filter_type ftype
,
201 filter_trie_node
**reg_filter_set
)
203 ap_filter_rec_t
*frec
;
204 char *normalized_name
;
206 filter_trie_node
*node
;
208 if (!*reg_filter_set
) {
209 *reg_filter_set
= trie_node_alloc(FILTER_POOL
, NULL
, 0);
212 normalized_name
= apr_pstrdup(FILTER_POOL
, name
);
213 ap_str_tolower(normalized_name
);
215 node
= *reg_filter_set
;
216 for (n
= normalized_name
; *n
; n
++) {
217 filter_trie_node
*child
= trie_node_alloc(FILTER_POOL
, node
, *n
);
218 if (apr_isalpha(*n
)) {
219 trie_node_link(FILTER_POOL
, node
, child
, apr_toupper(*n
));
227 frec
= apr_pcalloc(FILTER_POOL
, sizeof(*frec
));
229 frec
->name
= normalized_name
;
231 frec
->filter_func
= filter_func
;
232 frec
->filter_init_func
= filter_init
;
235 apr_pool_cleanup_register(FILTER_POOL
, NULL
, filter_cleanup
,
236 apr_pool_cleanup_null
);
240 AP_DECLARE(ap_filter_rec_t
*) ap_register_input_filter(const char *name
,
241 ap_in_filter_func filter_func
,
242 ap_init_filter_func filter_init
,
243 ap_filter_type ftype
)
246 f
.in_func
= filter_func
;
247 return register_filter(name
, f
, filter_init
, ftype
,
248 ®istered_input_filters
);
251 AP_DECLARE(ap_filter_rec_t
*) ap_register_output_filter(const char *name
,
252 ap_out_filter_func filter_func
,
253 ap_init_filter_func filter_init
,
254 ap_filter_type ftype
)
256 return ap_register_output_filter_protocol(name
, filter_func
,
257 filter_init
, ftype
, 0);
260 AP_DECLARE(ap_filter_rec_t
*) ap_register_output_filter_protocol(
262 ap_out_filter_func filter_func
,
263 ap_init_filter_func filter_init
,
264 ap_filter_type ftype
,
265 unsigned int proto_flags
)
267 ap_filter_rec_t
* ret
;
269 f
.out_func
= filter_func
;
270 ret
= register_filter(name
, f
, filter_init
, ftype
,
271 ®istered_output_filters
);
272 ret
->proto_flags
= proto_flags
;
276 static ap_filter_t
*add_any_filter_handle(ap_filter_rec_t
*frec
, void *ctx
,
277 request_rec
*r
, conn_rec
*c
,
278 ap_filter_t
**r_filters
,
279 ap_filter_t
**p_filters
,
280 ap_filter_t
**c_filters
)
282 apr_pool_t
*p
= frec
->ftype
< AP_FTYPE_CONNECTION
&& r
? r
->pool
: c
->pool
;
283 ap_filter_t
*f
= apr_palloc(p
, sizeof(*f
));
286 if (frec
->ftype
< AP_FTYPE_PROTOCOL
) {
291 ap_log_error(APLOG_MARK
, APLOG_ERR
, 0, NULL
,
292 "a content filter was added without a request: %s", frec
->name
);
296 else if (frec
->ftype
< AP_FTYPE_CONNECTION
) {
301 ap_log_error(APLOG_MARK
, APLOG_ERR
, 0, NULL
,
302 "a protocol filter was added without a request: %s", frec
->name
);
312 /* f->r must always be NULL for connection filters */
313 f
->r
= frec
->ftype
< AP_FTYPE_CONNECTION
? r
: NULL
;
317 if (INSERT_BEFORE(f
, *outf
)) {
321 ap_filter_t
*first
= NULL
;
324 /* If we are adding our first non-connection filter,
325 * Then don't try to find the right location, it is
326 * automatically first.
328 if (*r_filters
!= *c_filters
) {
330 while (first
&& (first
->next
!= (*outf
))) {
335 if (first
&& first
!= (*outf
)) {
342 ap_filter_t
*fscan
= *outf
;
343 while (!INSERT_BEFORE(f
, fscan
->next
))
346 f
->next
= fscan
->next
;
350 if (frec
->ftype
< AP_FTYPE_CONNECTION
&& (*r_filters
== *c_filters
)) {
351 *r_filters
= *p_filters
;
356 static ap_filter_t
*add_any_filter(const char *name
, void *ctx
,
357 request_rec
*r
, conn_rec
*c
,
358 const filter_trie_node
*reg_filter_set
,
359 ap_filter_t
**r_filters
,
360 ap_filter_t
**p_filters
,
361 ap_filter_t
**c_filters
)
363 if (reg_filter_set
) {
365 const filter_trie_node
*node
;
367 node
= reg_filter_set
;
368 for (n
= name
; *n
; n
++) {
371 end
= node
->nchildren
- 1;
372 while (end
>= start
) {
373 int middle
= (end
+ start
) / 2;
374 char ch
= node
->children
[middle
].c
;
376 node
= node
->children
[middle
].child
;
392 if (node
&& node
->frec
) {
393 return add_any_filter_handle(node
->frec
, ctx
, r
, c
, r_filters
,
394 p_filters
, c_filters
);
398 ap_log_error(APLOG_MARK
, APLOG_ERR
, 0, NULL
,
399 "an unknown filter was not added: %s", name
);
403 AP_DECLARE(ap_filter_t
*) ap_add_input_filter(const char *name
, void *ctx
,
404 request_rec
*r
, conn_rec
*c
)
406 return add_any_filter(name
, ctx
, r
, c
, registered_input_filters
,
407 r
? &r
->input_filters
: NULL
,
408 r
? &r
->proto_input_filters
: NULL
, &c
->input_filters
);
411 AP_DECLARE(ap_filter_t
*) ap_add_input_filter_handle(ap_filter_rec_t
*f
,
416 return add_any_filter_handle(f
, ctx
, r
, c
, r
? &r
->input_filters
: NULL
,
417 r
? &r
->proto_input_filters
: NULL
,
421 AP_DECLARE(ap_filter_t
*) ap_add_output_filter(const char *name
, void *ctx
,
422 request_rec
*r
, conn_rec
*c
)
424 return add_any_filter(name
, ctx
, r
, c
, registered_output_filters
,
425 r
? &r
->output_filters
: NULL
,
426 r
? &r
->proto_output_filters
: NULL
, &c
->output_filters
);
429 AP_DECLARE(ap_filter_t
*) ap_add_output_filter_handle(ap_filter_rec_t
*f
,
434 return add_any_filter_handle(f
, ctx
, r
, c
, r
? &r
->output_filters
: NULL
,
435 r
? &r
->proto_output_filters
: NULL
,
439 static void remove_any_filter(ap_filter_t
*f
, ap_filter_t
**r_filt
, ap_filter_t
**p_filt
,
440 ap_filter_t
**c_filt
)
442 ap_filter_t
**curr
= r_filt
? r_filt
: c_filt
;
443 ap_filter_t
*fscan
= *curr
;
445 if (p_filt
&& *p_filt
== f
)
446 *p_filt
= (*p_filt
)->next
;
449 *curr
= (*curr
)->next
;
453 while (fscan
->next
!= f
) {
454 if (!(fscan
= fscan
->next
)) {
459 fscan
->next
= f
->next
;
462 AP_DECLARE(void) ap_remove_input_filter(ap_filter_t
*f
)
464 remove_any_filter(f
, f
->r
? &f
->r
->input_filters
: NULL
,
465 f
->r
? &f
->r
->proto_input_filters
: NULL
,
466 &f
->c
->input_filters
);
469 AP_DECLARE(void) ap_remove_output_filter(ap_filter_t
*f
)
471 remove_any_filter(f
, f
->r
? &f
->r
->output_filters
: NULL
,
472 f
->r
? &f
->r
->proto_output_filters
: NULL
,
473 &f
->c
->output_filters
);
477 * Read data from the next filter in the filter stack. Data should be
478 * modified in the bucket brigade that is passed in. The core allocates the
479 * bucket brigade, modules that wish to replace large chunks of data or to
480 * save data off to the side should probably create their own temporary
481 * brigade especially for that use.
483 AP_DECLARE(apr_status_t
) ap_get_brigade(ap_filter_t
*next
,
484 apr_bucket_brigade
*bb
,
485 ap_input_mode_t mode
,
486 apr_read_type_e block
,
490 return next
->frec
->filter_func
.in_func(next
, bb
, mode
, block
,
493 return AP_NOBODY_READ
;
496 /* Pass the buckets to the next filter in the filter stack. If the
497 * current filter is a handler, we should get NULL passed in instead of
498 * the current filter. At that point, we can just call the first filter in
499 * the stack, or r->output_filters.
501 AP_DECLARE(apr_status_t
) ap_pass_brigade(ap_filter_t
*next
,
502 apr_bucket_brigade
*bb
)
506 if ((e
= APR_BRIGADE_LAST(bb
)) && APR_BUCKET_IS_EOS(e
) && next
->r
) {
507 /* This is only safe because HTTP_HEADER filter is always in
508 * the filter stack. This ensures that there is ALWAYS a
509 * request-based filter that we can attach this to. If the
510 * HTTP_FILTER is removed, and another filter is not put in its
511 * place, then handlers like mod_cgi, which attach their own
512 * EOS bucket to the brigade will be broken, because we will
513 * get two EOS buckets on the same request.
515 next
->r
->eos_sent
= 1;
517 /* remember the eos for internal redirects, too */
519 request_rec
*prev
= next
->r
->prev
;
527 return next
->frec
->filter_func
.out_func(next
, bb
);
529 return AP_NOBODY_WROTE
;
532 AP_DECLARE(apr_status_t
) ap_save_brigade(ap_filter_t
*f
,
533 apr_bucket_brigade
**saveto
,
534 apr_bucket_brigade
**b
, apr_pool_t
*p
)
537 apr_status_t rv
, srv
= APR_SUCCESS
;
539 /* If have never stored any data in the filter, then we had better
540 * create an empty bucket brigade so that we can concat.
543 *saveto
= apr_brigade_create(p
, f
->c
->bucket_alloc
);
546 for (e
= APR_BRIGADE_FIRST(*b
);
547 e
!= APR_BRIGADE_SENTINEL(*b
);
548 e
= APR_BUCKET_NEXT(e
))
550 rv
= apr_bucket_setaside(e
, p
);
552 /* If the bucket type does not implement setaside, then
553 * (hopefully) morph it into a bucket type which does, and set
555 if (rv
== APR_ENOTIMPL
) {
559 rv
= apr_bucket_read(e
, &s
, &n
, APR_BLOCK_READ
);
560 if (rv
== APR_SUCCESS
) {
561 rv
= apr_bucket_setaside(e
, p
);
565 if (rv
!= APR_SUCCESS
) {
567 /* Return an error but still save the brigade if
568 * ->setaside() is really not implemented. */
569 if (rv
!= APR_ENOTIMPL
) {
574 APR_BRIGADE_CONCAT(*saveto
, *b
);
578 AP_DECLARE_NONSTD(apr_status_t
) ap_filter_flush(apr_bucket_brigade
*bb
,
581 ap_filter_t
*f
= ctx
;
584 rv
= ap_pass_brigade(f
, bb
);
586 /* Before invocation of the flush callback, apr_brigade_write et
587 * al may place transient buckets in the brigade, which will fall
588 * out of scope after returning. Empty the brigade here, to avoid
589 * issues with leaving such buckets in the brigade if some filter
590 * fails and leaves a non-empty brigade. */
591 apr_brigade_cleanup(bb
);
596 AP_DECLARE(apr_status_t
) ap_fflush(ap_filter_t
*f
, apr_bucket_brigade
*bb
)
600 b
= apr_bucket_flush_create(f
->c
->bucket_alloc
);
601 APR_BRIGADE_INSERT_TAIL(bb
, b
);
602 return ap_pass_brigade(f
, bb
);
605 AP_DECLARE_NONSTD(apr_status_t
) ap_fputstrs(ap_filter_t
*f
,
606 apr_bucket_brigade
*bb
, ...)
612 rv
= apr_brigade_vputstrs(bb
, ap_filter_flush
, f
, args
);
617 AP_DECLARE_NONSTD(apr_status_t
) ap_fprintf(ap_filter_t
*f
,
618 apr_bucket_brigade
*bb
,
626 rv
= apr_brigade_vprintf(bb
, ap_filter_flush
, f
, fmt
, args
);
630 AP_DECLARE(void) ap_filter_protocol(ap_filter_t
*f
, unsigned int flags
)
632 f
->frec
->proto_flags
= flags
;