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/* 18 * An example input filter - this converts input to upper case. Note that 19 * because of the moment it gets inserted it does NOT convert request headers. 20 */ 21 22#include "httpd.h" 23#include "http_config.h" 24#include "apr_buckets.h" 25#include "apr_general.h" 26#include "apr_lib.h" 27#include "util_filter.h" 28#include "http_request.h" 29 30#include <ctype.h> 31 32static const char s_szCaseFilterName[] = "CaseFilterIn"; 33module AP_MODULE_DECLARE_DATA case_filter_in_module; 34 35typedef struct 36{ 37 int bEnabled; 38} CaseFilterInConfig; 39 40typedef struct 41{ 42 apr_bucket_brigade *pbbTmp; 43} CaseFilterInContext; 44 45static void *CaseFilterInCreateServerConfig(apr_pool_t *p, server_rec *s) 46{ 47 CaseFilterInConfig *pConfig = apr_pcalloc(p, sizeof *pConfig); 48 49 pConfig->bEnabled = 0; 50 51 return pConfig; 52} 53 54static void CaseFilterInInsertFilter(request_rec *r) 55{ 56 CaseFilterInConfig *pConfig=ap_get_module_config(r->server->module_config, 57 &case_filter_in_module); 58 if(!pConfig->bEnabled) 59 return; 60 61 ap_add_input_filter(s_szCaseFilterName,NULL,r,r->connection); 62} 63 64static apr_status_t CaseFilterInFilter(ap_filter_t *f, 65 apr_bucket_brigade *pbbOut, 66 ap_input_mode_t eMode, 67 apr_read_type_e eBlock, 68 apr_off_t nBytes) 69{ 70 request_rec *r = f->r; 71 conn_rec *c = r->connection; 72 CaseFilterInContext *pCtx; 73 apr_status_t ret; 74 75 if (!(pCtx = f->ctx)) { 76 f->ctx = pCtx = apr_palloc(r->pool, sizeof *pCtx); 77 pCtx->pbbTmp = apr_brigade_create(r->pool, c->bucket_alloc); 78 } 79 80 if (APR_BRIGADE_EMPTY(pCtx->pbbTmp)) { 81 ret = ap_get_brigade(f->next, pCtx->pbbTmp, eMode, eBlock, nBytes); 82 83 if (eMode == AP_MODE_EATCRLF || ret != APR_SUCCESS) 84 return ret; 85 } 86 87 while(!APR_BRIGADE_EMPTY(pCtx->pbbTmp)) { 88 apr_bucket *pbktIn = APR_BRIGADE_FIRST(pCtx->pbbTmp); 89 apr_bucket *pbktOut; 90 const char *data; 91 apr_size_t len; 92 char *buf; 93 apr_size_t n; 94 95 /* It is tempting to do this... 96 * APR_BUCKET_REMOVE(pB); 97 * APR_BRIGADE_INSERT_TAIL(pbbOut,pB); 98 * and change the case of the bucket data, but that would be wrong 99 * for a file or socket buffer, for example... 100 */ 101 102 if(APR_BUCKET_IS_EOS(pbktIn)) { 103 APR_BUCKET_REMOVE(pbktIn); 104 APR_BRIGADE_INSERT_TAIL(pbbOut, pbktIn); 105 break; 106 } 107 108 ret=apr_bucket_read(pbktIn, &data, &len, eBlock); 109 if(ret != APR_SUCCESS) 110 return ret; 111 112 buf = ap_malloc(len); 113 for(n=0 ; n < len ; ++n) 114 buf[n] = apr_toupper(data[n]); 115 116 pbktOut = apr_bucket_heap_create(buf, len, 0, c->bucket_alloc); 117 APR_BRIGADE_INSERT_TAIL(pbbOut, pbktOut); 118 apr_bucket_delete(pbktIn); 119 } 120 121 return APR_SUCCESS; 122} 123 124 125static const char *CaseFilterInEnable(cmd_parms *cmd, void *dummy, int arg) 126{ 127 CaseFilterInConfig *pConfig 128 = ap_get_module_config(cmd->server->module_config, 129 &case_filter_in_module); 130 pConfig->bEnabled=arg; 131 132 return NULL; 133} 134 135static const command_rec CaseFilterInCmds[] = 136{ 137 AP_INIT_FLAG("CaseFilterIn", CaseFilterInEnable, NULL, RSRC_CONF, 138 "Run an input case filter on this host"), 139 { NULL } 140}; 141 142 143static void CaseFilterInRegisterHooks(apr_pool_t *p) 144{ 145 ap_hook_insert_filter(CaseFilterInInsertFilter, NULL, NULL, 146 APR_HOOK_MIDDLE); 147 ap_register_input_filter(s_szCaseFilterName, CaseFilterInFilter, NULL, 148 AP_FTYPE_RESOURCE); 149} 150 151AP_DECLARE_MODULE(case_filter_in) = 152{ 153 STANDARD20_MODULE_STUFF, 154 NULL, 155 NULL, 156 CaseFilterInCreateServerConfig, 157 NULL, 158 CaseFilterInCmds, 159 CaseFilterInRegisterHooks 160}; 161