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 27static const char s_szCaseFilterName[]="CaseFilter"; 28module AP_MODULE_DECLARE_DATA case_filter_module; 29 30typedef struct 31 { 32 int bEnabled; 33 } CaseFilterConfig; 34 35static 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 44static 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 55static 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 for (pbktIn = APR_BRIGADE_FIRST(pbbIn); 65 pbktIn != APR_BRIGADE_SENTINEL(pbbIn); 66 pbktIn = APR_BUCKET_NEXT(pbktIn)) 67 { 68 const char *data; 69 apr_size_t len; 70 char *buf; 71 apr_size_t n; 72 apr_bucket *pbktOut; 73 74 if(APR_BUCKET_IS_EOS(pbktIn)) 75 { 76 apr_bucket *pbktEOS=apr_bucket_eos_create(c->bucket_alloc); 77 APR_BRIGADE_INSERT_TAIL(pbbOut,pbktEOS); 78 continue; 79 } 80 81 /* read */ 82 apr_bucket_read(pbktIn,&data,&len,APR_BLOCK_READ); 83 84 /* write */ 85 buf = apr_bucket_alloc(len, c->bucket_alloc); 86 for(n=0 ; n < len ; ++n) 87 buf[n] = apr_toupper(data[n]); 88 89 pbktOut = apr_bucket_heap_create(buf, len, apr_bucket_free, 90 c->bucket_alloc); 91 APR_BRIGADE_INSERT_TAIL(pbbOut,pbktOut); 92 } 93 94 /* Q: is there any advantage to passing a brigade for each bucket? 95 * A: obviously, it can cut down server resource consumption, if this 96 * experimental module was fed a file of 4MB, it would be using 8MB for 97 * the 'read' buckets and the 'write' buckets. 98 * 99 * Note it is more efficient to consume (destroy) each bucket as it's 100 * processed above than to do a single cleanup down here. In any case, 101 * don't let our caller pass the same buckets to us, twice; 102 */ 103 apr_brigade_cleanup(pbbIn); 104 return ap_pass_brigade(f->next,pbbOut); 105 } 106 107static const char *CaseFilterEnable(cmd_parms *cmd, void *dummy, int arg) 108 { 109 CaseFilterConfig *pConfig=ap_get_module_config(cmd->server->module_config, 110 &case_filter_module); 111 pConfig->bEnabled=arg; 112 113 return NULL; 114 } 115 116static const command_rec CaseFilterCmds[] = 117 { 118 AP_INIT_FLAG("CaseFilter", CaseFilterEnable, NULL, RSRC_CONF, 119 "Run a case filter on this host"), 120 { NULL } 121 }; 122 123static void CaseFilterRegisterHooks(apr_pool_t *p) 124 { 125 ap_hook_insert_filter(CaseFilterInsertFilter,NULL,NULL,APR_HOOK_MIDDLE); 126 ap_register_output_filter(s_szCaseFilterName,CaseFilterOutFilter,NULL, 127 AP_FTYPE_RESOURCE); 128 } 129 130AP_DECLARE_MODULE(case_filter) = 131{ 132 STANDARD20_MODULE_STUFF, 133 NULL, 134 NULL, 135 CaseFilterCreateServerConfig, 136 NULL, 137 CaseFilterCmds, 138 CaseFilterRegisterHooks 139}; 140