]> granicus.if.org Git - apache/blob - server/util_filter.c
74dfefba1035dfc45b622d7b32938d2f11a0eceb
[apache] / server / util_filter.c
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
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
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"
22
23 #include "httpd.h"
24 #include "http_config.h"
25 #include "http_core.h"
26 #include "http_log.h"
27 #include "util_filter.h"
28
29 /* NOTE: Apache's current design doesn't allow a pool to be passed thru,
30    so we depend on a global to hold the correct pool
31 */
32 #define FILTER_POOL     apr_hook_global_pool
33 #include "ap_hooks.h"   /* for apr_hook_global_pool */
34
35 /*
36 ** This macro returns true/false if a given filter should be inserted BEFORE
37 ** another filter. This will happen when one of: 1) there isn't another
38 ** filter; 2) that filter has a higher filter type (class); 3) that filter
39 ** corresponds to a different request.
40 */
41 #define INSERT_BEFORE(f, before_this) ((before_this) == NULL \
42                            || (before_this)->frec->ftype > (f)->frec->ftype \
43                            || (before_this)->r != (f)->r)
44
45 /* Trie structure to hold the mapping from registered
46  * filter names to filters
47  */
48
49 /* we know core's module_index is 0 */
50 #undef APLOG_MODULE_INDEX
51 #define APLOG_MODULE_INDEX AP_CORE_MODULE_INDEX
52
53 typedef struct filter_trie_node filter_trie_node;
54
55 typedef struct {
56     int c;
57     filter_trie_node *child;
58 } filter_trie_child_ptr;
59
60 /* Each trie node has an array of pointers to its children.
61  * The array is kept in sorted order so that add_any_filter()
62  * can do a binary search
63  */
64 struct filter_trie_node {
65     ap_filter_rec_t *frec;
66     filter_trie_child_ptr *children;
67     int nchildren;
68     int size;
69 };
70
71 #define TRIE_INITIAL_SIZE 4
72
73 /* Link a trie node to its parent
74  */
75 static void trie_node_link(apr_pool_t *p, filter_trie_node *parent,
76                            filter_trie_node *child, int c)
77 {
78     int i, j;
79
80     if (parent->nchildren == parent->size) {
81         filter_trie_child_ptr *new;
82         parent->size *= 2;
83         new = (filter_trie_child_ptr *)apr_palloc(p, parent->size *
84                                              sizeof(filter_trie_child_ptr));
85         memcpy(new, parent->children, parent->nchildren *
86                sizeof(filter_trie_child_ptr));
87         parent->children = new;
88     }
89
90     for (i = 0; i < parent->nchildren; i++) {
91         if (c == parent->children[i].c) {
92             return;
93         }
94         else if (c < parent->children[i].c) {
95             break;
96         }
97     }
98     for (j = parent->nchildren; j > i; j--) {
99         parent->children[j].c = parent->children[j - 1].c;
100         parent->children[j].child = parent->children[j - 1].child;
101     }
102     parent->children[i].c = c;
103     parent->children[i].child = child;
104
105     parent->nchildren++;
106 }
107
108 /* Allocate a new node for a trie.
109  * If parent is non-NULL, link the new node under the parent node with
110  * key 'c' (or, if an existing child node matches, return that one)
111  */
112 static filter_trie_node *trie_node_alloc(apr_pool_t *p,
113                                          filter_trie_node *parent, char c)
114 {
115     filter_trie_node *new_node;
116     if (parent) {
117         int i;
118         for (i = 0; i < parent->nchildren; i++) {
119             if (c == parent->children[i].c) {
120                 return parent->children[i].child;
121             }
122             else if (c < parent->children[i].c) {
123                 break;
124             }
125         }
126         new_node =
127             (filter_trie_node *)apr_palloc(p, sizeof(filter_trie_node));
128         trie_node_link(p, parent, new_node, c);
129     }
130     else { /* No parent node */
131         new_node = (filter_trie_node *)apr_palloc(p,
132                                                   sizeof(filter_trie_node));
133     }
134
135     new_node->frec = NULL;
136     new_node->nchildren = 0;
137     new_node->size = TRIE_INITIAL_SIZE;
138     new_node->children = (filter_trie_child_ptr *)apr_palloc(p,
139                              new_node->size * sizeof(filter_trie_child_ptr));
140     return new_node;
141 }
142
143 static filter_trie_node *registered_output_filters = NULL;
144 static filter_trie_node *registered_input_filters = NULL;
145
146
147 static apr_status_t filter_cleanup(void *ctx)
148 {
149     registered_output_filters = NULL;
150     registered_input_filters = NULL;
151     return APR_SUCCESS;
152 }
153
154 static ap_filter_rec_t *get_filter_handle(const char *name,
155                                           const filter_trie_node *filter_set)
156 {
157     if (filter_set) {
158         const char *n;
159         const filter_trie_node *node;
160
161         node = filter_set;
162         for (n = name; *n; n++) {
163             int start, end;
164             start = 0;
165             end = node->nchildren - 1;
166             while (end >= start) {
167                 int middle = (end + start) / 2;
168                 char ch = node->children[middle].c;
169                 if (*n == ch) {
170                     node = node->children[middle].child;
171                     break;
172                 }
173                 else if (*n < ch) {
174                     end = middle - 1;
175                 }
176                 else {
177                     start = middle + 1;
178                 }
179             }
180             if (end < start) {
181                 node = NULL;
182                 break;
183             }
184         }
185
186         if (node && node->frec) {
187             return node->frec;
188         }
189     }
190     return NULL;
191 }
192
193 AP_DECLARE(ap_filter_rec_t *)ap_get_output_filter_handle(const char *name)
194 {
195     return get_filter_handle(name, registered_output_filters);
196 }
197
198 AP_DECLARE(ap_filter_rec_t *)ap_get_input_filter_handle(const char *name)
199 {
200     return get_filter_handle(name, registered_input_filters);
201 }
202
203 static ap_filter_rec_t *register_filter(const char *name,
204                             ap_filter_func filter_func,
205                             ap_init_filter_func filter_init,
206                             ap_filter_type ftype,
207                             filter_trie_node **reg_filter_set)
208 {
209     ap_filter_rec_t *frec;
210     char *normalized_name;
211     const char *n;
212     filter_trie_node *node;
213
214     if (!*reg_filter_set) {
215         *reg_filter_set = trie_node_alloc(FILTER_POOL, NULL, 0);
216     }
217
218     normalized_name = apr_pstrdup(FILTER_POOL, name);
219     ap_str_tolower(normalized_name);
220
221     node = *reg_filter_set;
222     for (n = normalized_name; *n; n++) {
223         filter_trie_node *child = trie_node_alloc(FILTER_POOL, node, *n);
224         if (apr_isalpha(*n)) {
225             trie_node_link(FILTER_POOL, node, child, apr_toupper(*n));
226         }
227         node = child;
228     }
229     if (node->frec) {
230         frec = node->frec;
231     }
232     else {
233         frec = apr_pcalloc(FILTER_POOL, sizeof(*frec));
234         node->frec = frec;
235         frec->name = normalized_name;
236     }
237     frec->filter_func = filter_func;
238     frec->filter_init_func = filter_init;
239     frec->ftype = ftype;
240
241     apr_pool_cleanup_register(FILTER_POOL, NULL, filter_cleanup,
242                               apr_pool_cleanup_null);
243     return frec;
244 }
245
246 AP_DECLARE(ap_filter_rec_t *) ap_register_input_filter(const char *name,
247                                           ap_in_filter_func filter_func,
248                                           ap_init_filter_func filter_init,
249                                           ap_filter_type ftype)
250 {
251     ap_filter_func f;
252     f.in_func = filter_func;
253     return register_filter(name, f, filter_init, ftype,
254                            &registered_input_filters);
255 }
256
257 AP_DECLARE(ap_filter_rec_t *) ap_register_output_filter(const char *name,
258                                            ap_out_filter_func filter_func,
259                                            ap_init_filter_func filter_init,
260                                            ap_filter_type ftype)
261 {
262     return ap_register_output_filter_protocol(name, filter_func,
263                                               filter_init, ftype, 0);
264 }
265
266 AP_DECLARE(ap_filter_rec_t *) ap_register_output_filter_protocol(
267                                            const char *name,
268                                            ap_out_filter_func filter_func,
269                                            ap_init_filter_func filter_init,
270                                            ap_filter_type ftype,
271                                            unsigned int proto_flags)
272 {
273     ap_filter_rec_t* ret ;
274     ap_filter_func f;
275     f.out_func = filter_func;
276     ret = register_filter(name, f, filter_init, ftype,
277                           &registered_output_filters);
278     ret->proto_flags = proto_flags ;
279     return ret ;
280 }
281
282 static ap_filter_t *add_any_filter_handle(ap_filter_rec_t *frec, void *ctx,
283                                           request_rec *r, conn_rec *c,
284                                           ap_filter_t **r_filters,
285                                           ap_filter_t **p_filters,
286                                           ap_filter_t **c_filters)
287 {
288     apr_pool_t *p = frec->ftype < AP_FTYPE_CONNECTION && r ? r->pool : c->pool;
289     ap_filter_t *f = apr_palloc(p, sizeof(*f));
290     ap_filter_t **outf;
291
292     if (frec->ftype < AP_FTYPE_PROTOCOL) {
293         if (r) {
294             outf = r_filters;
295         }
296         else {
297             ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c,
298                           "a content filter was added without a request: %s", frec->name);
299             return NULL;
300         }
301     }
302     else if (frec->ftype < AP_FTYPE_CONNECTION) {
303         if (r) {
304             outf = p_filters;
305         }
306         else {
307             ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, c,
308                           "a protocol filter was added without a request: %s", frec->name);
309             return NULL;
310         }
311     }
312     else {
313         outf = c_filters;
314     }
315
316     f->frec = frec;
317     f->ctx = ctx;
318     /* f->r must always be NULL for connection filters */
319     f->r = frec->ftype < AP_FTYPE_CONNECTION ? r : NULL;
320     f->c = c;
321     f->next = NULL;
322
323     if (INSERT_BEFORE(f, *outf)) {
324         f->next = *outf;
325
326         if (*outf) {
327             ap_filter_t *first = NULL;
328
329             if (r) {
330                 /* If we are adding our first non-connection filter,
331                  * Then don't try to find the right location, it is
332                  * automatically first.
333                  */
334                 if (*r_filters != *c_filters) {
335                     first = *r_filters;
336                     while (first && (first->next != (*outf))) {
337                         first = first->next;
338                     }
339                 }
340             }
341             if (first && first != (*outf)) {
342                 first->next = f;
343             }
344         }
345         *outf = f;
346     }
347     else {
348         ap_filter_t *fscan = *outf;
349         while (!INSERT_BEFORE(f, fscan->next))
350             fscan = fscan->next;
351
352         f->next = fscan->next;
353         fscan->next = f;
354     }
355
356     if (frec->ftype < AP_FTYPE_CONNECTION && (*r_filters == *c_filters)) {
357         *r_filters = *p_filters;
358     }
359     return f;
360 }
361
362 static ap_filter_t *add_any_filter(const char *name, void *ctx,
363                                    request_rec *r, conn_rec *c,
364                                    const filter_trie_node *reg_filter_set,
365                                    ap_filter_t **r_filters,
366                                    ap_filter_t **p_filters,
367                                    ap_filter_t **c_filters)
368 {
369     if (reg_filter_set) {
370         const char *n;
371         const filter_trie_node *node;
372
373         node = reg_filter_set;
374         for (n = name; *n; n++) {
375             int start, end;
376             start = 0;
377             end = node->nchildren - 1;
378             while (end >= start) {
379                 int middle = (end + start) / 2;
380                 char ch = node->children[middle].c;
381                 if (*n == ch) {
382                     node = node->children[middle].child;
383                     break;
384                 }
385                 else if (*n < ch) {
386                     end = middle - 1;
387                 }
388                 else {
389                     start = middle + 1;
390                 }
391             }
392             if (end < start) {
393                 node = NULL;
394                 break;
395             }
396         }
397
398         if (node && node->frec) {
399             return add_any_filter_handle(node->frec, ctx, r, c, r_filters,
400                                          p_filters, c_filters);
401         }
402     }
403
404     ap_log_cerror(APLOG_MARK, APLOG_ERR, 0, r ? r->connection : c,
405                   "an unknown filter was not added: %s", name);
406     return NULL;
407 }
408
409 AP_DECLARE(ap_filter_t *) ap_add_input_filter(const char *name, void *ctx,
410                                               request_rec *r, conn_rec *c)
411 {
412     return add_any_filter(name, ctx, r, c, registered_input_filters,
413                           r ? &r->input_filters : NULL,
414                           r ? &r->proto_input_filters : NULL, &c->input_filters);
415 }
416
417 AP_DECLARE(ap_filter_t *) ap_add_input_filter_handle(ap_filter_rec_t *f,
418                                                      void *ctx,
419                                                      request_rec *r,
420                                                      conn_rec *c)
421 {
422     return add_any_filter_handle(f, ctx, r, c, r ? &r->input_filters : NULL,
423                                  r ? &r->proto_input_filters : NULL,
424                                  &c->input_filters);
425 }
426
427 AP_DECLARE(ap_filter_t *) ap_add_output_filter(const char *name, void *ctx,
428                                                request_rec *r, conn_rec *c)
429 {
430     return add_any_filter(name, ctx, r, c, registered_output_filters,
431                           r ? &r->output_filters : NULL,
432                           r ? &r->proto_output_filters : NULL, &c->output_filters);
433 }
434
435 AP_DECLARE(ap_filter_t *) ap_add_output_filter_handle(ap_filter_rec_t *f,
436                                                       void *ctx,
437                                                       request_rec *r,
438                                                       conn_rec *c)
439 {
440     return add_any_filter_handle(f, ctx, r, c, r ? &r->output_filters : NULL,
441                                  r ? &r->proto_output_filters : NULL,
442                                  &c->output_filters);
443 }
444
445 static void remove_any_filter(ap_filter_t *f, ap_filter_t **r_filt, ap_filter_t **p_filt,
446                               ap_filter_t **c_filt)
447 {
448     ap_filter_t **curr = r_filt ? r_filt : c_filt;
449     ap_filter_t *fscan = *curr;
450
451     if (p_filt && *p_filt == f)
452         *p_filt = (*p_filt)->next;
453
454     if (*curr == f) {
455         *curr = (*curr)->next;
456         return;
457     }
458
459     while (fscan->next != f) {
460         if (!(fscan = fscan->next)) {
461             return;
462         }
463     }
464
465     fscan->next = f->next;
466 }
467
468 AP_DECLARE(void) ap_remove_input_filter(ap_filter_t *f)
469 {
470     remove_any_filter(f, f->r ? &f->r->input_filters : NULL,
471                       f->r ? &f->r->proto_input_filters : NULL,
472                       &f->c->input_filters);
473 }
474
475 AP_DECLARE(void) ap_remove_output_filter(ap_filter_t *f)
476 {
477     remove_any_filter(f, f->r ? &f->r->output_filters : NULL,
478                       f->r ? &f->r->proto_output_filters : NULL,
479                       &f->c->output_filters);
480 }
481
482 /*
483  * Read data from the next filter in the filter stack.  Data should be
484  * modified in the bucket brigade that is passed in.  The core allocates the
485  * bucket brigade, modules that wish to replace large chunks of data or to
486  * save data off to the side should probably create their own temporary
487  * brigade especially for that use.
488  */
489 AP_DECLARE(apr_status_t) ap_get_brigade(ap_filter_t *next,
490                                         apr_bucket_brigade *bb,
491                                         ap_input_mode_t mode,
492                                         apr_read_type_e block,
493                                         apr_off_t readbytes)
494 {
495     if (next) {
496         return next->frec->filter_func.in_func(next, bb, mode, block,
497                                                readbytes);
498     }
499     return AP_NOBODY_READ;
500 }
501
502 /* Pass the buckets to the next filter in the filter stack.  If the
503  * current filter is a handler, we should get NULL passed in instead of
504  * the current filter.  At that point, we can just call the first filter in
505  * the stack, or r->output_filters.
506  */
507 AP_DECLARE(apr_status_t) ap_pass_brigade(ap_filter_t *next,
508                                          apr_bucket_brigade *bb)
509 {
510     if (next) {
511         apr_bucket *e;
512         if ((e = APR_BRIGADE_LAST(bb)) && APR_BUCKET_IS_EOS(e) && next->r) {
513             /* This is only safe because HTTP_HEADER filter is always in
514              * the filter stack.   This ensures that there is ALWAYS a
515              * request-based filter that we can attach this to.  If the
516              * HTTP_FILTER is removed, and another filter is not put in its
517              * place, then handlers like mod_cgi, which attach their own
518              * EOS bucket to the brigade will be broken, because we will
519              * get two EOS buckets on the same request.
520              */
521             next->r->eos_sent = 1;
522
523             /* remember the eos for internal redirects, too */
524             if (next->r->prev) {
525                 request_rec *prev = next->r->prev;
526
527                 while (prev) {
528                     prev->eos_sent = 1;
529                     prev = prev->prev;
530                 }
531             }
532         }
533         return next->frec->filter_func.out_func(next, bb);
534     }
535     return AP_NOBODY_WROTE;
536 }
537
538 /* Pass the buckets to the next filter in the filter stack
539  * checking return status for filter errors.
540  * returns: OK if ap_pass_brigade returns APR_SUCCESS
541  *          AP_FILTER_ERROR if filter error exists
542  *          HTTP_INTERNAL_SERVER_ERROR for all other cases
543  *          logged with optional errmsg
544  */
545 AP_DECLARE(apr_status_t) ap_pass_brigade_fchk(request_rec *r,
546                                               apr_bucket_brigade *bb,
547                                               const char *fmt,
548                                               ...)
549 {
550     apr_status_t rv;
551
552     rv = ap_pass_brigade(r->output_filters, bb);
553     if (rv != APR_SUCCESS) {
554         if (rv != AP_FILTER_ERROR) {
555             if (!fmt)
556                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r,
557                               "ap_pass_brigade returned %d", rv);
558             else {
559                 va_list ap;
560                 const char *res;
561                 va_start(ap, fmt);
562                 res = apr_pvsprintf(r->pool, fmt, ap);
563                 va_end(ap);
564                 ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r, res, NULL);
565             }
566             return HTTP_INTERNAL_SERVER_ERROR;
567         }
568         return AP_FILTER_ERROR;
569     }
570     return OK;
571 }
572
573 AP_DECLARE(apr_status_t) ap_save_brigade(ap_filter_t *f,
574                                          apr_bucket_brigade **saveto,
575                                          apr_bucket_brigade **b, apr_pool_t *p)
576 {
577     apr_bucket *e;
578     apr_status_t rv, srv = APR_SUCCESS;
579
580     /* If have never stored any data in the filter, then we had better
581      * create an empty bucket brigade so that we can concat.
582      */
583     if (!(*saveto)) {
584         *saveto = apr_brigade_create(p, f->c->bucket_alloc);
585     }
586
587     for (e = APR_BRIGADE_FIRST(*b);
588          e != APR_BRIGADE_SENTINEL(*b);
589          e = APR_BUCKET_NEXT(e))
590     {
591         rv = apr_bucket_setaside(e, p);
592
593         /* If the bucket type does not implement setaside, then
594          * (hopefully) morph it into a bucket type which does, and set
595          * *that* aside... */
596         if (rv == APR_ENOTIMPL) {
597             const char *s;
598             apr_size_t n;
599
600             rv = apr_bucket_read(e, &s, &n, APR_BLOCK_READ);
601             if (rv == APR_SUCCESS) {
602                 rv = apr_bucket_setaside(e, p);
603             }
604         }
605
606         if (rv != APR_SUCCESS) {
607             srv = rv;
608             /* Return an error but still save the brigade if
609              * ->setaside() is really not implemented. */
610             if (rv != APR_ENOTIMPL) {
611                 return rv;
612             }
613         }
614     }
615     APR_BRIGADE_CONCAT(*saveto, *b);
616     return srv;
617 }
618
619 AP_DECLARE_NONSTD(apr_status_t) ap_filter_flush(apr_bucket_brigade *bb,
620                                                 void *ctx)
621 {
622     ap_filter_t *f = ctx;
623     apr_status_t rv;
624
625     rv = ap_pass_brigade(f, bb);
626
627     /* Before invocation of the flush callback, apr_brigade_write et
628      * al may place transient buckets in the brigade, which will fall
629      * out of scope after returning.  Empty the brigade here, to avoid
630      * issues with leaving such buckets in the brigade if some filter
631      * fails and leaves a non-empty brigade. */
632     apr_brigade_cleanup(bb);
633
634     return rv;
635 }
636
637 AP_DECLARE(apr_status_t) ap_fflush(ap_filter_t *f, apr_bucket_brigade *bb)
638 {
639     apr_bucket *b;
640
641     b = apr_bucket_flush_create(f->c->bucket_alloc);
642     APR_BRIGADE_INSERT_TAIL(bb, b);
643     return ap_pass_brigade(f, bb);
644 }
645
646 AP_DECLARE_NONSTD(apr_status_t) ap_fputstrs(ap_filter_t *f,
647                                             apr_bucket_brigade *bb, ...)
648 {
649     va_list args;
650     apr_status_t rv;
651
652     va_start(args, bb);
653     rv = apr_brigade_vputstrs(bb, ap_filter_flush, f, args);
654     va_end(args);
655     return rv;
656 }
657
658 AP_DECLARE_NONSTD(apr_status_t) ap_fprintf(ap_filter_t *f,
659                                            apr_bucket_brigade *bb,
660                                            const char *fmt,
661                                            ...)
662 {
663     va_list args;
664     apr_status_t rv;
665
666     va_start(args, fmt);
667     rv = apr_brigade_vprintf(bb, ap_filter_flush, f, fmt, args);
668     va_end(args);
669     return rv;
670 }
671 AP_DECLARE(void) ap_filter_protocol(ap_filter_t *f, unsigned int flags)
672 {
673     f->frec->proto_flags = flags ;
674 }