upload http
[bottlenecks.git] / rubbos / app / httpd-2.0.64 / modules / experimental / mod_case_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 #include "httpd.h"
18 #include "http_config.h"
19 #include "apr_buckets.h"
20 #include "apr_general.h"
21 #include "apr_lib.h"
22 #include "util_filter.h"
23 #include "http_request.h"
24
25 #include <ctype.h>
26
27 static const char s_szCaseFilterName[]="CaseFilter";
28 module AP_MODULE_DECLARE_DATA case_filter_module;
29
30 typedef struct
31     {
32     int bEnabled;
33     } CaseFilterConfig;
34
35 static void *CaseFilterCreateServerConfig(apr_pool_t *p,server_rec *s)
36     {
37     CaseFilterConfig *pConfig=apr_pcalloc(p,sizeof *pConfig);
38
39     pConfig->bEnabled=0;
40
41     return pConfig;
42     }
43
44 static void CaseFilterInsertFilter(request_rec *r)
45     {
46     CaseFilterConfig *pConfig=ap_get_module_config(r->server->module_config,
47                                                    &case_filter_module);
48
49     if(!pConfig->bEnabled)
50         return;
51
52     ap_add_output_filter(s_szCaseFilterName,NULL,r,r->connection);
53     }
54
55 static apr_status_t CaseFilterOutFilter(ap_filter_t *f,
56                                         apr_bucket_brigade *pbbIn)
57     {
58     request_rec *r = f->r;
59     conn_rec *c = r->connection;
60     apr_bucket *pbktIn;
61     apr_bucket_brigade *pbbOut;
62
63     pbbOut=apr_brigade_create(r->pool, c->bucket_alloc);
64     APR_BRIGADE_FOREACH(pbktIn,pbbIn)
65         {
66         const char *data;
67         apr_size_t len;
68         char *buf;
69         apr_size_t n;
70         apr_bucket *pbktOut;
71
72         if(APR_BUCKET_IS_EOS(pbktIn))
73             {
74             apr_bucket *pbktEOS=apr_bucket_eos_create(c->bucket_alloc);
75             APR_BRIGADE_INSERT_TAIL(pbbOut,pbktEOS);
76             continue;
77             }
78
79         /* read */
80         apr_bucket_read(pbktIn,&data,&len,APR_BLOCK_READ);
81
82         /* write */
83         buf = apr_bucket_alloc(len, c->bucket_alloc);
84         for(n=0 ; n < len ; ++n)
85             buf[n] = apr_toupper(data[n]);
86
87         pbktOut = apr_bucket_heap_create(buf, len, apr_bucket_free,
88                                          c->bucket_alloc);
89         APR_BRIGADE_INSERT_TAIL(pbbOut,pbktOut);
90         }
91
92     /* Q: is there any advantage to passing a brigade for each bucket? 
93      * A: obviously, it can cut down server resource consumption, if this
94      * experimental module was fed a file of 4MB, it would be using 8MB for
95      * the 'read' buckets and the 'write' buckets.
96      *
97      * Note it is more efficient to consume (destroy) each bucket as it's
98      * processed above than to do a single cleanup down here.  In any case,
99      * don't let our caller pass the same buckets to us, twice;
100      */
101     apr_brigade_cleanup(pbbIn);
102     return ap_pass_brigade(f->next,pbbOut);
103     }
104
105 static const char *CaseFilterEnable(cmd_parms *cmd, void *dummy, int arg)
106     {
107     CaseFilterConfig *pConfig=ap_get_module_config(cmd->server->module_config,
108                                                    &case_filter_module);
109     pConfig->bEnabled=arg;
110
111     return NULL;
112     }
113
114 static const command_rec CaseFilterCmds[] = 
115     {
116     AP_INIT_FLAG("CaseFilter", CaseFilterEnable, NULL, RSRC_CONF,
117                  "Run a case filter on this host"),
118     { NULL }
119     };
120
121 static void CaseFilterRegisterHooks(apr_pool_t *p)
122     {
123     ap_hook_insert_filter(CaseFilterInsertFilter,NULL,NULL,APR_HOOK_MIDDLE);
124     ap_register_output_filter(s_szCaseFilterName,CaseFilterOutFilter,NULL,
125                               AP_FTYPE_RESOURCE);
126     }
127
128 module AP_MODULE_DECLARE_DATA case_filter_module =
129 {
130     STANDARD20_MODULE_STUFF,
131     NULL,
132     NULL,
133     CaseFilterCreateServerConfig,
134     NULL,
135     CaseFilterCmds,
136     CaseFilterRegisterHooks
137 };