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
/* Prepare to make this a #define in 2.2 */
252
AP_DECLARE(ap_filter_rec_t *) ap_register_output_filter(const char *name,
253
ap_out_filter_func filter_func,
254
ap_init_filter_func filter_init,
255
ap_filter_type ftype)
257
return ap_register_output_filter_protocol(name, filter_func,
258
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 = 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);
316
if (INSERT_BEFORE(f, *outf)) {
320
ap_filter_t *first = NULL;
323
/* If we are adding our first non-connection filter,
324
* Then don't try to find the right location, it is
325
* automatically first.
327
if (*r_filters != *c_filters) {
329
while (first && (first->next != (*outf))) {
334
if (first && first != (*outf)) {
341
ap_filter_t *fscan = *outf;
342
while (!INSERT_BEFORE(f, fscan->next))
345
f->next = fscan->next;
349
if (frec->ftype < AP_FTYPE_CONNECTION && (*r_filters == *c_filters)) {
350
*r_filters = *p_filters;
355
static ap_filter_t *add_any_filter(const char *name, void *ctx,
356
request_rec *r, conn_rec *c,
357
const filter_trie_node *reg_filter_set,
358
ap_filter_t **r_filters,
359
ap_filter_t **p_filters,
360
ap_filter_t **c_filters)
362
if (reg_filter_set) {
364
const filter_trie_node *node;
366
node = reg_filter_set;
367
for (n = name; *n; n++) {
370
end = node->nchildren - 1;
371
while (end >= start) {
372
int middle = (end + start) / 2;
373
char ch = node->children[middle].c;
375
node = node->children[middle].child;
391
if (node && node->frec) {
392
return add_any_filter_handle(node->frec, ctx, r, c, r_filters,
393
p_filters, c_filters);
397
ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
398
"an unknown filter was not added: %s", name);
402
AP_DECLARE(ap_filter_t *) ap_add_input_filter(const char *name, void *ctx,
403
request_rec *r, conn_rec *c)
405
return add_any_filter(name, ctx, r, c, registered_input_filters,
406
r ? &r->input_filters : NULL,
407
r ? &r->proto_input_filters : NULL, &c->input_filters);
410
AP_DECLARE(ap_filter_t *) ap_add_input_filter_handle(ap_filter_rec_t *f,
415
return add_any_filter_handle(f, ctx, r, c, r ? &r->input_filters : NULL,
416
r ? &r->proto_input_filters : NULL,
420
AP_DECLARE(ap_filter_t *) ap_add_output_filter(const char *name, void *ctx,
421
request_rec *r, conn_rec *c)
423
return add_any_filter(name, ctx, r, c, registered_output_filters,
424
r ? &r->output_filters : NULL,
425
r ? &r->proto_output_filters : NULL, &c->output_filters);
428
AP_DECLARE(ap_filter_t *) ap_add_output_filter_handle(ap_filter_rec_t *f,
433
return add_any_filter_handle(f, ctx, r, c, r ? &r->output_filters : NULL,
434
r ? &r->proto_output_filters : NULL,
438
static void remove_any_filter(ap_filter_t *f, ap_filter_t **r_filt, ap_filter_t **p_filt,
439
ap_filter_t **c_filt)
441
ap_filter_t **curr = r_filt ? r_filt : c_filt;
442
ap_filter_t *fscan = *curr;
444
if (p_filt && *p_filt == f)
445
*p_filt = (*p_filt)->next;
448
*curr = (*curr)->next;
452
while (fscan->next != f) {
453
if (!(fscan = fscan->next)) {
458
fscan->next = f->next;
461
AP_DECLARE(void) ap_remove_input_filter(ap_filter_t *f)
463
remove_any_filter(f, f->r ? &f->r->input_filters : NULL,
464
f->r ? &f->r->proto_input_filters : NULL,
465
&f->c->input_filters);
468
AP_DECLARE(void) ap_remove_output_filter(ap_filter_t *f)
470
remove_any_filter(f, f->r ? &f->r->output_filters : NULL,
471
f->r ? &f->r->proto_output_filters : NULL,
472
&f->c->output_filters);
476
* Read data from the next filter in the filter stack. Data should be
477
* modified in the bucket brigade that is passed in. The core allocates the
478
* bucket brigade, modules that wish to replace large chunks of data or to
479
* save data off to the side should probably create their own temporary
480
* brigade especially for that use.
482
AP_DECLARE(apr_status_t) ap_get_brigade(ap_filter_t *next,
483
apr_bucket_brigade *bb,
484
ap_input_mode_t mode,
485
apr_read_type_e block,
489
return next->frec->filter_func.in_func(next, bb, mode, block,
492
return AP_NOBODY_READ;
495
/* Pass the buckets to the next filter in the filter stack. If the
496
* current filter is a handler, we should get NULL passed in instead of
497
* the current filter. At that point, we can just call the first filter in
498
* the stack, or r->output_filters.
500
AP_DECLARE(apr_status_t) ap_pass_brigade(ap_filter_t *next,
501
apr_bucket_brigade *bb)
505
if ((e = APR_BRIGADE_LAST(bb)) && APR_BUCKET_IS_EOS(e) && next->r) {
506
/* This is only safe because HTTP_HEADER filter is always in
507
* the filter stack. This ensures that there is ALWAYS a
508
* request-based filter that we can attach this to. If the
509
* HTTP_FILTER is removed, and another filter is not put in its
510
* place, then handlers like mod_cgi, which attach their own
511
* EOS bucket to the brigade will be broken, because we will
512
* get two EOS buckets on the same request.
514
next->r->eos_sent = 1;
516
/* remember the eos for internal redirects, too */
518
request_rec *prev = next->r->prev;
526
return next->frec->filter_func.out_func(next, bb);
528
return AP_NOBODY_WROTE;
531
AP_DECLARE(apr_status_t) ap_save_brigade(ap_filter_t *f,
532
apr_bucket_brigade **saveto,
533
apr_bucket_brigade **b, apr_pool_t *p)
536
apr_status_t rv, srv = APR_SUCCESS;
538
/* If have never stored any data in the filter, then we had better
539
* create an empty bucket brigade so that we can concat.
542
*saveto = apr_brigade_create(p, f->c->bucket_alloc);
545
for (e = APR_BRIGADE_FIRST(*b);
546
e != APR_BRIGADE_SENTINEL(*b);
547
e = APR_BUCKET_NEXT(e))
549
rv = apr_bucket_setaside(e, p);
551
/* If the bucket type does not implement setaside, then
552
* (hopefully) morph it into a bucket type which does, and set
554
if (rv == APR_ENOTIMPL) {
558
rv = apr_bucket_read(e, &s, &n, APR_BLOCK_READ);
559
if (rv == APR_SUCCESS) {
560
rv = apr_bucket_setaside(e, p);
564
if (rv != APR_SUCCESS) {
566
/* Return an error but still save the brigade if
567
* ->setaside() is really not implemented. */
568
if (rv != APR_ENOTIMPL) {
573
APR_BRIGADE_CONCAT(*saveto, *b);
577
AP_DECLARE_NONSTD(apr_status_t) ap_filter_flush(apr_bucket_brigade *bb,
580
ap_filter_t *f = ctx;
582
return ap_pass_brigade(f, bb);
585
AP_DECLARE(apr_status_t) ap_fflush(ap_filter_t *f, apr_bucket_brigade *bb)
589
b = apr_bucket_flush_create(f->c->bucket_alloc);
590
APR_BRIGADE_INSERT_TAIL(bb, b);
591
return ap_pass_brigade(f, bb);
594
AP_DECLARE_NONSTD(apr_status_t) ap_fputstrs(ap_filter_t *f,
595
apr_bucket_brigade *bb, ...)
601
rv = apr_brigade_vputstrs(bb, ap_filter_flush, f, args);
606
AP_DECLARE_NONSTD(apr_status_t) ap_fprintf(ap_filter_t *f,
607
apr_bucket_brigade *bb,
615
rv = apr_brigade_vprintf(bb, ap_filter_flush, f, fmt, args);
619
AP_DECLARE(void) ap_filter_protocol(ap_filter_t *f, unsigned int flags)
621
f->frec->proto_flags = flags ;