removed some of the debug logging and added author details
[httpd-crcsyncproxy.git] / server / util_filter.c
blobf2e5b5d29990b56b1df0c9e629b8b0f9cee95e71
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
18 #include "apr_want.h"
19 #include "apr_lib.h"
20 #include "apr_hash.h"
21 #include "apr_strings.h"
23 #include "httpd.h"
24 #include "http_log.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;
49 typedef struct {
50 int c;
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;
61 int nchildren;
62 int size;
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)
72 int i, j;
74 if (parent->nchildren == parent->size) {
75 filter_trie_child_ptr *new;
76 parent->size *= 2;
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) {
86 return;
88 else if (c < parent->children[i].c) {
89 break;
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;
99 parent->nchildren++;
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;
110 if (parent) {
111 int i;
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) {
117 break;
120 new_node =
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));
134 return new_node;
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;
145 return APR_SUCCESS;
148 static ap_filter_rec_t *get_filter_handle(const char *name,
149 const filter_trie_node *filter_set)
151 if (filter_set) {
152 const char *n;
153 const filter_trie_node *node;
155 node = filter_set;
156 for (n = name; *n; n++) {
157 int start, end;
158 start = 0;
159 end = node->nchildren - 1;
160 while (end >= start) {
161 int middle = (end + start) / 2;
162 char ch = node->children[middle].c;
163 if (*n == ch) {
164 node = node->children[middle].child;
165 break;
167 else if (*n < ch) {
168 end = middle - 1;
170 else {
171 start = middle + 1;
174 if (end < start) {
175 node = NULL;
176 break;
180 if (node && node->frec) {
181 return node->frec;
184 return NULL;
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;
205 const char *n;
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));
221 node = child;
223 if (node->frec) {
224 frec = node->frec;
226 else {
227 frec = apr_pcalloc(FILTER_POOL, sizeof(*frec));
228 node->frec = frec;
229 frec->name = normalized_name;
231 frec->filter_func = filter_func;
232 frec->filter_init_func = filter_init;
233 frec->ftype = ftype;
235 apr_pool_cleanup_register(FILTER_POOL, NULL, filter_cleanup,
236 apr_pool_cleanup_null);
237 return frec;
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)
245 ap_filter_func f;
246 f.in_func = filter_func;
247 return register_filter(name, f, filter_init, ftype,
248 &registered_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(
261 const char *name,
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 ;
268 ap_filter_func f;
269 f.out_func = filter_func;
270 ret = register_filter(name, f, filter_init, ftype,
271 &registered_output_filters);
272 ret->proto_flags = proto_flags ;
273 return ret ;
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));
284 ap_filter_t **outf;
286 if (frec->ftype < AP_FTYPE_PROTOCOL) {
287 if (r) {
288 outf = r_filters;
290 else {
291 ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
292 "a content filter was added without a request: %s", frec->name);
293 return NULL;
296 else if (frec->ftype < AP_FTYPE_CONNECTION) {
297 if (r) {
298 outf = p_filters;
300 else {
301 ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
302 "a protocol filter was added without a request: %s", frec->name);
303 return NULL;
306 else {
307 outf = c_filters;
310 f->frec = frec;
311 f->ctx = ctx;
312 /* f->r must always be NULL for connection filters */
313 f->r = frec->ftype < AP_FTYPE_CONNECTION ? r : NULL;
314 f->c = c;
315 f->next = NULL;
317 if (INSERT_BEFORE(f, *outf)) {
318 f->next = *outf;
320 if (*outf) {
321 ap_filter_t *first = NULL;
323 if (r) {
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) {
329 first = *r_filters;
330 while (first && (first->next != (*outf))) {
331 first = first->next;
335 if (first && first != (*outf)) {
336 first->next = f;
339 *outf = f;
341 else {
342 ap_filter_t *fscan = *outf;
343 while (!INSERT_BEFORE(f, fscan->next))
344 fscan = fscan->next;
346 f->next = fscan->next;
347 fscan->next = f;
350 if (frec->ftype < AP_FTYPE_CONNECTION && (*r_filters == *c_filters)) {
351 *r_filters = *p_filters;
353 return f;
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) {
364 const char *n;
365 const filter_trie_node *node;
367 node = reg_filter_set;
368 for (n = name; *n; n++) {
369 int start, end;
370 start = 0;
371 end = node->nchildren - 1;
372 while (end >= start) {
373 int middle = (end + start) / 2;
374 char ch = node->children[middle].c;
375 if (*n == ch) {
376 node = node->children[middle].child;
377 break;
379 else if (*n < ch) {
380 end = middle - 1;
382 else {
383 start = middle + 1;
386 if (end < start) {
387 node = NULL;
388 break;
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);
400 return NULL;
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,
412 void *ctx,
413 request_rec *r,
414 conn_rec *c)
416 return add_any_filter_handle(f, ctx, r, c, r ? &r->input_filters : NULL,
417 r ? &r->proto_input_filters : NULL,
418 &c->input_filters);
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,
430 void *ctx,
431 request_rec *r,
432 conn_rec *c)
434 return add_any_filter_handle(f, ctx, r, c, r ? &r->output_filters : NULL,
435 r ? &r->proto_output_filters : NULL,
436 &c->output_filters);
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;
448 if (*curr == f) {
449 *curr = (*curr)->next;
450 return;
453 while (fscan->next != f) {
454 if (!(fscan = fscan->next)) {
455 return;
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,
487 apr_off_t readbytes)
489 if (next) {
490 return next->frec->filter_func.in_func(next, bb, mode, block,
491 readbytes);
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)
504 if (next) {
505 apr_bucket *e;
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 */
518 if (next->r->prev) {
519 request_rec *prev = next->r->prev;
521 while (prev) {
522 prev->eos_sent = 1;
523 prev = prev->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)
536 apr_bucket *e;
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.
542 if (!(*saveto)) {
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
554 * *that* aside... */
555 if (rv == APR_ENOTIMPL) {
556 const char *s;
557 apr_size_t n;
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) {
566 srv = rv;
567 /* Return an error but still save the brigade if
568 * ->setaside() is really not implemented. */
569 if (rv != APR_ENOTIMPL) {
570 return rv;
574 APR_BRIGADE_CONCAT(*saveto, *b);
575 return srv;
578 AP_DECLARE_NONSTD(apr_status_t) ap_filter_flush(apr_bucket_brigade *bb,
579 void *ctx)
581 ap_filter_t *f = ctx;
582 apr_status_t rv;
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);
593 return rv;
596 AP_DECLARE(apr_status_t) ap_fflush(ap_filter_t *f, apr_bucket_brigade *bb)
598 apr_bucket *b;
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, ...)
608 va_list args;
609 apr_status_t rv;
611 va_start(args, bb);
612 rv = apr_brigade_vputstrs(bb, ap_filter_flush, f, args);
613 va_end(args);
614 return rv;
617 AP_DECLARE_NONSTD(apr_status_t) ap_fprintf(ap_filter_t *f,
618 apr_bucket_brigade *bb,
619 const char *fmt,
620 ...)
622 va_list args;
623 apr_status_t rv;
625 va_start(args, fmt);
626 rv = apr_brigade_vprintf(bb, ap_filter_flush, f, fmt, args);
627 va_end(args);
628 return rv;
630 AP_DECLARE(void) ap_filter_protocol(ap_filter_t *f, unsigned int flags)
632 f->frec->proto_flags = flags ;