]> granicus.if.org Git - apache/blob - server/util_filter.c
non-static directive parsers should be AP_DECLARE_NONSTD()
[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_log.h"
25 #include "util_filter.h"
26
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
29 */
30 #define FILTER_POOL     apr_hook_global_pool
31 #include "apr_hooks.h"   /* for apr_hook_global_pool */
32
33 /*
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.
38 */
39 #define INSERT_BEFORE(f, before_this) ((before_this) == NULL \
40                            || (before_this)->frec->ftype > (f)->frec->ftype \
41                            || (before_this)->r != (f)->r)
42
43 /* Trie structure to hold the mapping from registered
44  * filter names to filters
45  */
46
47 typedef struct filter_trie_node filter_trie_node;
48
49 typedef struct {
50     int c;
51     filter_trie_node *child;
52 } filter_trie_child_ptr;
53
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
57  */
58 struct filter_trie_node {
59     ap_filter_rec_t *frec;
60     filter_trie_child_ptr *children;
61     int nchildren;
62     int size;
63 };
64
65 #define TRIE_INITIAL_SIZE 4
66
67 /* Link a trie node to its parent
68  */
69 static void trie_node_link(apr_pool_t *p, filter_trie_node *parent,
70                            filter_trie_node *child, int c)
71 {
72     int i, j;
73
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;
82     }
83
84     for (i = 0; i < parent->nchildren; i++) {
85         if (c == parent->children[i].c) {
86             return;
87         }
88         else if (c < parent->children[i].c) {
89             break;
90         }
91     }
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;
95     }
96     parent->children[i].c = c;
97     parent->children[i].child = child;
98
99     parent->nchildren++;
100 }
101
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)
105  */
106 static filter_trie_node *trie_node_alloc(apr_pool_t *p,
107                                          filter_trie_node *parent, char c)
108 {
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;
115             }
116             else if (c < parent->children[i].c) {
117                 break;
118             }
119         }
120         new_node =
121             (filter_trie_node *)apr_palloc(p, sizeof(filter_trie_node));
122         trie_node_link(p, parent, new_node, c);
123     }
124     else { /* No parent node */
125         new_node = (filter_trie_node *)apr_palloc(p,
126                                                   sizeof(filter_trie_node));
127     }
128
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;
135 }
136
137 static filter_trie_node *registered_output_filters = NULL;
138 static filter_trie_node *registered_input_filters = NULL;
139
140
141 static apr_status_t filter_cleanup(void *ctx)
142 {
143     registered_output_filters = NULL;
144     registered_input_filters = NULL;
145     return APR_SUCCESS;
146 }
147
148 static ap_filter_rec_t *get_filter_handle(const char *name,
149                                           const filter_trie_node *filter_set)
150 {
151     if (filter_set) {
152         const char *n;
153         const filter_trie_node *node;
154
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;
166                 }
167                 else if (*n < ch) {
168                     end = middle - 1;
169                 }
170                 else {
171                     start = middle + 1;
172                 }
173             }
174             if (end < start) {
175                 node = NULL;
176                 break;
177             }
178         }
179
180         if (node && node->frec) {
181             return node->frec;
182         }
183     }
184     return NULL;
185 }
186
187 AP_DECLARE(ap_filter_rec_t *)ap_get_output_filter_handle(const char *name)
188 {
189     return get_filter_handle(name, registered_output_filters);
190 }
191
192 AP_DECLARE(ap_filter_rec_t *)ap_get_input_filter_handle(const char *name)
193 {
194     return get_filter_handle(name, registered_input_filters);
195 }
196
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)
202 {
203     ap_filter_rec_t *frec;
204     char *normalized_name;
205     const char *n;
206     filter_trie_node *node;
207
208     if (!*reg_filter_set) {
209         *reg_filter_set = trie_node_alloc(FILTER_POOL, NULL, 0);
210     }
211
212     normalized_name = apr_pstrdup(FILTER_POOL, name);
213     ap_str_tolower(normalized_name);
214
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));
220         }
221         node = child;
222     }
223     if (node->frec) {
224         frec = node->frec;
225     }
226     else {
227         frec = apr_pcalloc(FILTER_POOL, sizeof(*frec));
228         node->frec = frec;
229         frec->name = normalized_name;
230     }
231     frec->filter_func = filter_func;
232     frec->filter_init_func = filter_init;
233     frec->ftype = ftype;
234
235     apr_pool_cleanup_register(FILTER_POOL, NULL, filter_cleanup,
236                               apr_pool_cleanup_null);
237     return frec;
238 }
239
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)
244 {
245     ap_filter_func f;
246     f.in_func = filter_func;
247     return register_filter(name, f, filter_init, ftype,
248                            &registered_input_filters);
249 }
250
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)
255 {
256     return ap_register_output_filter_protocol(name, filter_func,
257                                               filter_init, ftype, 0);
258 }
259
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)
266 {
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 ;
274 }
275
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)
281 {
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;
285
286     if (frec->ftype < AP_FTYPE_PROTOCOL) {
287         if (r) {
288             outf = r_filters;
289         }
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;
294         }
295     }
296     else if (frec->ftype < AP_FTYPE_CONNECTION) {
297         if (r) {
298             outf = p_filters;
299         }
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;
304         }
305     }
306     else {
307         outf = c_filters;
308     }
309
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;
316
317     if (INSERT_BEFORE(f, *outf)) {
318         f->next = *outf;
319
320         if (*outf) {
321             ap_filter_t *first = NULL;
322
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.
327                  */
328                 if (*r_filters != *c_filters) {
329                     first = *r_filters;
330                     while (first && (first->next != (*outf))) {
331                         first = first->next;
332                     }
333                 }
334             }
335             if (first && first != (*outf)) {
336                 first->next = f;
337             }
338         }
339         *outf = f;
340     }
341     else {
342         ap_filter_t *fscan = *outf;
343         while (!INSERT_BEFORE(f, fscan->next))
344             fscan = fscan->next;
345
346         f->next = fscan->next;
347         fscan->next = f;
348     }
349
350     if (frec->ftype < AP_FTYPE_CONNECTION && (*r_filters == *c_filters)) {
351         *r_filters = *p_filters;
352     }
353     return f;
354 }
355
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)
362 {
363     if (reg_filter_set) {
364         const char *n;
365         const filter_trie_node *node;
366
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;
378                 }
379                 else if (*n < ch) {
380                     end = middle - 1;
381                 }
382                 else {
383                     start = middle + 1;
384                 }
385             }
386             if (end < start) {
387                 node = NULL;
388                 break;
389             }
390         }
391
392         if (node && node->frec) {
393             return add_any_filter_handle(node->frec, ctx, r, c, r_filters,
394                                          p_filters, c_filters);
395         }
396     }
397
398     ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL,
399                  "an unknown filter was not added: %s", name);
400     return NULL;
401 }
402
403 AP_DECLARE(ap_filter_t *) ap_add_input_filter(const char *name, void *ctx,
404                                               request_rec *r, conn_rec *c)
405 {
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);
409 }
410
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)
415 {
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);
419 }
420
421 AP_DECLARE(ap_filter_t *) ap_add_output_filter(const char *name, void *ctx,
422                                                request_rec *r, conn_rec *c)
423 {
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);
427 }
428
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)
433 {
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);
437 }
438
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)
441 {
442     ap_filter_t **curr = r_filt ? r_filt : c_filt;
443     ap_filter_t *fscan = *curr;
444
445     if (p_filt && *p_filt == f)
446         *p_filt = (*p_filt)->next;
447
448     if (*curr == f) {
449         *curr = (*curr)->next;
450         return;
451     }
452
453     while (fscan->next != f) {
454         if (!(fscan = fscan->next)) {
455             return;
456         }
457     }
458
459     fscan->next = f->next;
460 }
461
462 AP_DECLARE(void) ap_remove_input_filter(ap_filter_t *f)
463 {
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);
467 }
468
469 AP_DECLARE(void) ap_remove_output_filter(ap_filter_t *f)
470 {
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);
474 }
475
476 /*
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.
482  */
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)
488 {
489     if (next) {
490         return next->frec->filter_func.in_func(next, bb, mode, block,
491                                                readbytes);
492     }
493     return AP_NOBODY_READ;
494 }
495
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.
500  */
501 AP_DECLARE(apr_status_t) ap_pass_brigade(ap_filter_t *next,
502                                          apr_bucket_brigade *bb)
503 {
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.
514              */
515             next->r->eos_sent = 1;
516
517             /* remember the eos for internal redirects, too */
518             if (next->r->prev) {
519                 request_rec *prev = next->r->prev;
520
521                 while (prev) {
522                     prev->eos_sent = 1;
523                     prev = prev->prev;
524                 }
525             }
526         }
527         return next->frec->filter_func.out_func(next, bb);
528     }
529     return AP_NOBODY_WROTE;
530 }
531
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)
535 {
536     apr_bucket *e;
537     apr_status_t rv, srv = APR_SUCCESS;
538
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.
541      */
542     if (!(*saveto)) {
543         *saveto = apr_brigade_create(p, f->c->bucket_alloc);
544     }
545
546     for (e = APR_BRIGADE_FIRST(*b);
547          e != APR_BRIGADE_SENTINEL(*b);
548          e = APR_BUCKET_NEXT(e))
549     {
550         rv = apr_bucket_setaside(e, p);
551
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;
558
559             rv = apr_bucket_read(e, &s, &n, APR_BLOCK_READ);
560             if (rv == APR_SUCCESS) {
561                 rv = apr_bucket_setaside(e, p);
562             }
563         }
564
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;
571             }
572         }
573     }
574     APR_BRIGADE_CONCAT(*saveto, *b);
575     return srv;
576 }
577
578 AP_DECLARE_NONSTD(apr_status_t) ap_filter_flush(apr_bucket_brigade *bb,
579                                                 void *ctx)
580 {
581     ap_filter_t *f = ctx;
582     apr_status_t rv;
583
584     rv = ap_pass_brigade(f, bb);
585
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);
592
593     return rv;
594 }
595
596 AP_DECLARE(apr_status_t) ap_fflush(ap_filter_t *f, apr_bucket_brigade *bb)
597 {
598     apr_bucket *b;
599
600     b = apr_bucket_flush_create(f->c->bucket_alloc);
601     APR_BRIGADE_INSERT_TAIL(bb, b);
602     return ap_pass_brigade(f, bb);
603 }
604
605 AP_DECLARE_NONSTD(apr_status_t) ap_fputstrs(ap_filter_t *f,
606                                             apr_bucket_brigade *bb, ...)
607 {
608     va_list args;
609     apr_status_t rv;
610
611     va_start(args, bb);
612     rv = apr_brigade_vputstrs(bb, ap_filter_flush, f, args);
613     va_end(args);
614     return rv;
615 }
616
617 AP_DECLARE_NONSTD(apr_status_t) ap_fprintf(ap_filter_t *f,
618                                            apr_bucket_brigade *bb,
619                                            const char *fmt,
620                                            ...)
621 {
622     va_list args;
623     apr_status_t rv;
624
625     va_start(args, fmt);
626     rv = apr_brigade_vprintf(bb, ap_filter_flush, f, fmt, args);
627     va_end(args);
628     return rv;
629 }
630 AP_DECLARE(void) ap_filter_protocol(ap_filter_t *f, unsigned int flags)
631 {
632     f->frec->proto_flags = flags ;
633 }