static const char *compile_command_add_extension(cmd_parms *cmd, void *overrides, const char *value, const char* extension) { if ( ! ap_strstr(value, "%s")) { return (char*) apr_psprintf(cmd->pool, "(mod_compile) 'AddCompileCommand %s' does not contain a '%%s'.", value); } COMPILE_FIND_CONFIG; #ifdef _DEBUG ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, cmd->server, "compile_command_add_extension('%s', '%s')", value, extension); #endif compile_extension_config_t *extension_config; char *value_normalized = apr_pstrdup(cmd->pool, value); char *extension_normalized = apr_pstrdup(cmd->temp_pool, extension); ap_str_tolower(value_normalized); ap_str_tolower(extension_normalized); if (*extension_normalized == '.') { ++ extension_normalized; } if ( ! config->extension_commands) { config->extension_commands = apr_hash_make(cmd->pool); extension_config = NULL; } else { extension_config = (compile_extension_config_t*) apr_hash_get(config->extension_commands, extension_normalized, APR_HASH_KEY_STRING); } if ( ! extension_config) { extension_config = apr_pcalloc(cmd->pool, sizeof (compile_extension_config_t)); extension_normalized = apr_pstrdup(cmd->pool, extension_normalized); apr_hash_set(config->extension_commands, extension_normalized, APR_HASH_KEY_STRING, extension_config); } extension_config->command_line = value_normalized; return NULL; }
static const char *add_icon(cmd_parms *cmd, void *d, char *icon, char *to) { char *iconbak = ap_pstrdup(cmd->pool, icon); if (icon[0] == '(') { char *alt; char *cl = strchr(iconbak, ')'); if (cl == NULL) { return "missing closing paren"; } alt = ap_getword_nc(cmd->pool, &iconbak, ','); *cl = '\0'; /* Lose closing paren */ add_alt(cmd, d, &alt[1], to); } if (cmd->info == BY_PATH) { if (!strcmp(to, "**DIRECTORY**")) { to = "^^DIRECTORY^^"; } } if (cmd->info == BY_ENCODING) { ap_str_tolower(to); } push_item(((autoindex_config_rec *) d)->icon_list, cmd->info, to, cmd->path, iconbak); return NULL; }
static apr_status_t filter_harness(ap_filter_t *f, apr_bucket_brigade *bb) { apr_status_t ret; #ifndef NO_PROTOCOL const char *cachecontrol; char *str; #endif harness_ctx *ctx = f->ctx; ap_filter_rec_t *filter = f->frec; if (f->r->status != 200 && !apr_table_get(f->r->subprocess_env, "filter-errordocs")) { ap_remove_output_filter(f); return ap_pass_brigade(f->next, bb); } filter_trace(f->c, filter->debug, f->frec->name, bb); /* look up a handler function if we haven't already set it */ if (!ctx->func) { #ifndef NO_PROTOCOL if (f->r->proxyreq) { if (filter->proto_flags & AP_FILTER_PROTO_NO_PROXY) { ap_remove_output_filter(f); return ap_pass_brigade(f->next, bb); } if (filter->proto_flags & AP_FILTER_PROTO_TRANSFORM) { cachecontrol = apr_table_get(f->r->headers_out, "Cache-Control"); if (cachecontrol) { str = apr_pstrdup(f->r->pool, cachecontrol); ap_str_tolower(str); if (strstr(str, "no-transform")) { ap_remove_output_filter(f); return ap_pass_brigade(f->next, bb); } } } } #endif if (!filter_lookup(f, filter)) { ap_remove_output_filter(f); return ap_pass_brigade(f->next, bb); } } /* call the content filter with its own context, then restore our * context */ f->ctx = ctx->fctx; ret = ctx->func(f, bb); ctx->fctx = f->ctx; f->ctx = ctx; return ret; }
static const char *compile_command_remove_extension(cmd_parms *cmd, void *overrides, const char *extension) { COMPILE_FIND_CONFIG; compile_attribute_config_t *attribute; if (*extension == '.') { ++ extension; } if ( ! config->removed_commands) { config->removed_commands = apr_array_make(cmd->pool, 4, sizeof (*attribute)); } attribute = (compile_attribute_config_t*) apr_array_push(config->removed_commands); attribute->name = apr_pstrdup(cmd->pool, extension); ap_str_tolower(attribute->name); return NULL; }
static const char *add_alt(cmd_parms *cmd, void *d, char *alt, char *to) { if (cmd->info == BY_PATH) { if (!strcmp(to, "**DIRECTORY**")) { to = "^^DIRECTORY^^"; } } if (cmd->info == BY_ENCODING) { ap_str_tolower(to); } push_item(((autoindex_config_rec *) d)->alt_list, cmd->info, to, cmd->path, alt); return NULL; }
static apr_status_t ap_compile_output_filter(ap_filter_t *filter, apr_bucket_brigade *input_brigade) { request_rec *request = filter->r; if ( ! request->filename) { return ap_pass_brigade(filter->next, input_brigade); } const char *resource_name; compile_config_t *directory_config = (compile_config_t*) ap_get_module_config(request->per_dir_config, &compile_module); compile_config_t *server_config = (compile_config_t*) ap_get_module_config(request->server->module_config, &compile_module); compile_config_t *config = compile_merge_config(request->pool, server_config, directory_config); if (config->use_path_info) { resource_name = apr_pstrcat(request->pool, request->filename, request->path_info, NULL); } else { resource_name = request->filename; } const char *filename; char *extension; filename = ap_strrchr_c(resource_name, '/'); if (filename == NULL) { filename = resource_name; } else { ++ filename; } extension = ap_getword(request->pool, &filename, '.'); while (*filename && (extension = ap_getword(request->pool, &filename, '.'))) { if (*extension == '\0') { continue; } ap_str_tolower(extension); if (config->extension_commands != NULL) { const compile_extension_config_t *extension_config = NULL; extension_config = (compile_extension_config_t*) apr_hash_get(config->extension_commands, extension, APR_HASH_KEY_STRING); if (extension_config != NULL && extension_config->command_line) { #ifdef _DEBUG ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, request->server, "ap_compile_output_filter('%s')", apr_psprintf(request->pool, extension_config->command_line, resource_name)); #endif // TODO: http://svn.apache.org/repos/asf/httpd/httpd/tags/2.2.6/modules/experimental/mod_case_filter.c // Collect buckets, save to disk, run command line and tail-insert result ap_set_content_type(request, "text/html;charset=utf-8"); break; } } } return ap_pass_brigade(filter->next, input_brigade); }
static int geoip_header_parser(request_rec * r) { char *orgorisp; char *ipaddr; short int country_id; GeoIP *gip; const char *continent_code; const char *country_code; const char *country_name; const char *region_name; geoip_server_config_rec *cfg; unsigned char databaseType; GeoIPRecord *gir; GeoIPRegion *giregion; int i; int netspeed; /* For splitting proxy headers */ char *ipaddr_ptr = 0; char *comma_ptr; char *found_ip; apr_sockaddr_t *sa; char *hostname = 0; cfg = ap_get_module_config(r->server->module_config, &geoip_module); if (!cfg) return DECLINED; if (!cfg->scanProxyHeaders) { ipaddr = r->connection->remote_ip; } else { ap_add_common_vars(r); if (apr_table_get(r->subprocess_env, "HTTP_CLIENT_IP")) { ipaddr_ptr = (char *) apr_table_get(r->subprocess_env, "HTTP_CLIENT_IP"); } else if (apr_table_get(r->subprocess_env, "HTTP_X_FORWARDED_FOR")) { ipaddr_ptr = (char *) apr_table_get(r->subprocess_env, "HTTP_X_FORWARDED_FOR"); } else if (apr_table_get(r->headers_in, "X-Forwarded-For")) { ipaddr_ptr = (char *) apr_table_get(r->headers_in, "X-Forwarded-For"); } else if (apr_table_get(r->subprocess_env, "HTTP_REMOTE_ADDR")) { ipaddr_ptr = (char *) apr_table_get(r->subprocess_env, "HTTP_REMOTE_ADDR"); } if (!ipaddr_ptr) { ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server, "[mod_geoip]: Error while getting ipaddr from proxy headers. Using REMOTE_ADDR."); ipaddr = r->connection->remote_ip; } else { ap_log_error(APLOG_MARK, APLOG_DEBUG | APLOG_NOERRNO, 0, r->server, "[mod_geoip]: IPADDR_PTR: %s", ipaddr_ptr); if (cfg->use_left_public_x_forwarded_for_ip) { // find the first public IP address in a potentially comma-separated list, // fall back to remote_ip if we can't find one ipaddr = first_public_ip_in_list(ipaddr_ptr, r->connection->remote_ip); } else { // leaving some of the following inconsistent indenting intact for easier diff to original maxmind src /* * Check to ensure that the HTTP_CLIENT_IP or * X-Forwarded-For header is not a comma separated * list of addresses, which would cause mod_geoip to * return no country code. If the header is a comma * separated list, return the first IP address in the * list, which is (hopefully!) the real client IP. */ ipaddr = (char *) calloc(8*4+7+1, sizeof(char)); if (cfg->use_last_x_forwarded_for_ip ){ comma_ptr = strrchr(ipaddr_ptr, ','); if ( comma_ptr ) { /* skip over whitespace */ ipaddr_ptr = comma_ptr + strspn(comma_ptr, ", \t"); } } strncpy(ipaddr, ipaddr_ptr, 8*4+7); comma_ptr = strchr(ipaddr, ','); if (comma_ptr != 0) *comma_ptr = '\0'; } } } /* this block should be removed! */ #if 1 if (!cfg->gips) { if (cfg->GeoIPFilenames != NULL) { cfg->gips = malloc(sizeof(GeoIP *) * cfg->numGeoIPFiles); for (i = 0; i < cfg->numGeoIPFiles; i++) { cfg->gips[i] = GeoIP_open(cfg->GeoIPFilenames[i], (cfg->GeoIPFlags2[i] == GEOIP_UNKNOWN) ? cfg->GeoIPFlags : cfg->GeoIPFlags2[i]); if (cfg->gips[i]) { if (cfg->GeoIPEnableUTF8) { GeoIP_set_charset(cfg->gips[i], GEOIP_CHARSET_UTF8); } } else { ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "[mod_geoip]: Error while opening data file %s", cfg->GeoIPFilenames[i]); return DECLINED; } } } else { cfg->gips = malloc(sizeof(GeoIP *)); cfg->gips[0] = GeoIP_new(GEOIP_STANDARD); if (!cfg->gips[0]) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "[mod_geoip]: Error while opening data file"); return DECLINED; } cfg->numGeoIPFiles = 1; } } #endif if (cfg->GeoIPEnableHostnameLookups && apr_sockaddr_info_get(&sa, ipaddr, APR_INET, 0, 0, r->pool) == APR_SUCCESS && apr_getnameinfo(&hostname, sa, 0) == APR_SUCCESS) { ap_str_tolower(hostname); } if (!hostname) hostname = ipaddr; if (cfg->GeoIPOutput & GEOIP_NOTES) { apr_table_setn(r->notes, "GEOIP_ADDR", ipaddr); apr_table_setn(r->notes, "GEOIP_HOST", hostname); } if (cfg->GeoIPOutput & GEOIP_ENV) { apr_table_setn(r->subprocess_env, "GEOIP_ADDR", ipaddr); apr_table_setn(r->subprocess_env, "GEOIP_HOST", hostname); } for (i = 0; i < cfg->numGeoIPFiles; i++) { /* * skip database handles that can not be opned for some * reason */ if (cfg->gips[i] == NULL) continue; databaseType = cfg->gips[i] ? GeoIP_database_edition(cfg->gips[i]) : -1; /* -1 is "magic value" * in case file not * found */ switch (databaseType) { case GEOIP_NETSPEED_EDITION_REV1: orgorisp = GeoIP_name_by_addr(cfg->gips[i], ipaddr); if (orgorisp != NULL) { if (cfg->GeoIPOutput & GEOIP_NOTES) { apr_table_setn(r->notes, "GEOIP_NETSPEED", orgorisp); } if (cfg->GeoIPOutput & GEOIP_ENV) { apr_table_setn(r->subprocess_env, "GEOIP_NETSPEED", orgorisp); } } break; case GEOIP_NETSPEED_EDITION: netspeed = GeoIP_id_by_addr(cfg->gips[i], ipaddr); if (netspeed == GEOIP_UNKNOWN_SPEED) { netspeedstring = "unknown"; } else if (netspeed == GEOIP_DIALUP_SPEED) { netspeedstring = "dialup"; } else if (netspeed == GEOIP_CABLEDSL_SPEED) { netspeedstring = "cabledsl"; } else if (netspeed == GEOIP_CORPORATE_SPEED) { netspeedstring = "corporate"; } if (cfg->GeoIPOutput & GEOIP_NOTES) { apr_table_setn(r->notes, "GEOIP_NETSPEED", netspeedstring); } if (cfg->GeoIPOutput & GEOIP_ENV) { apr_table_setn(r->subprocess_env, "GEOIP_NETSPEED", netspeedstring); } break; case GEOIP_COUNTRY_EDITION_V6: /* Get the Country ID */ country_id = GeoIP_country_id_by_addr_v6(cfg->gips[i], ipaddr); if ( country_id > 0 ) { /* Lookup the Code and the Name with the ID */ continent_code = GeoIP_country_continent[country_id]; country_code = GeoIP_country_code[country_id]; country_name = GeoIP_country_name[country_id]; if (cfg->numGeoIPFiles == 0) { cfg->numGeoIPFiles = 0; } if (cfg->GeoIPFilenames == 0) { cfg->GeoIPFilenames = 0; } /* Set it for our user */ if (cfg->GeoIPOutput & GEOIP_NOTES) { apr_table_setn(r->notes, "GEOIP_CONTINENT_CODE_V6", continent_code); apr_table_setn(r->notes, "GEOIP_COUNTRY_CODE_V6", country_code); apr_table_setn(r->notes, "GEOIP_COUNTRY_NAME_V6", country_name); } if (cfg->GeoIPOutput & GEOIP_ENV) { apr_table_setn(r->subprocess_env, "GEOIP_CONTINENT_CODE_V6", continent_code); apr_table_setn(r->subprocess_env, "GEOIP_COUNTRY_CODE_V6", country_code); apr_table_setn(r->subprocess_env, "GEOIP_COUNTRY_NAME_V6", country_name); } } break; case GEOIP_COUNTRY_EDITION: /* Get the Country ID */ country_id = GeoIP_country_id_by_addr(cfg->gips[i], ipaddr); if ( country_id > 0 ) { /* Lookup the Code and the Name with the ID */ continent_code = GeoIP_country_continent[country_id]; country_code = GeoIP_country_code[country_id]; country_name = GeoIP_country_name[country_id]; if (cfg->numGeoIPFiles == 0) { cfg->numGeoIPFiles = 0; } if (cfg->GeoIPFilenames == 0) { cfg->GeoIPFilenames = 0; } /* Set it for our user */ if (cfg->GeoIPOutput & GEOIP_NOTES) { apr_table_setn(r->notes, "GEOIP_CONTINENT_CODE", continent_code); apr_table_setn(r->notes, "GEOIP_COUNTRY_CODE", country_code); apr_table_setn(r->notes, "GEOIP_COUNTRY_NAME", country_name); } if (cfg->GeoIPOutput & GEOIP_ENV) { apr_table_setn(r->subprocess_env, "GEOIP_CONTINENT_CODE", continent_code); apr_table_setn(r->subprocess_env, "GEOIP_COUNTRY_CODE", country_code); apr_table_setn(r->subprocess_env, "GEOIP_COUNTRY_NAME", country_name); } } break; case GEOIP_REGION_EDITION_REV0: case GEOIP_REGION_EDITION_REV1: giregion = GeoIP_region_by_name(cfg->gips[i], ipaddr); if (giregion != NULL) { if ( giregion->country_code[0] ) { region_name = GeoIP_region_name_by_code(giregion->country_code, giregion->region); } if (cfg->GeoIPOutput & GEOIP_NOTES) { if ( giregion->country_code[0] ){ apr_table_set(r->notes, "GEOIP_COUNTRY_CODE", giregion->country_code); } if (giregion->region[0]) { apr_table_set(r->notes, "GEOIP_REGION", giregion->region); } if ( region_name != NULL ){ apr_table_set(r->notes, "GEOIP_REGION_NAME", region_name); } } if (cfg->GeoIPOutput & GEOIP_ENV) { if ( giregion->country_code[0] ){ apr_table_set(r->subprocess_env, "GEOIP_COUNTRY_CODE", giregion->country_code); } if (giregion->region[0]) { apr_table_set(r->subprocess_env, "GEOIP_REGION", giregion->region); } if ( region_name != NULL ){ apr_table_set(r->subprocess_env, "GEOIP_REGION_NAME", region_name); } } GeoIPRegion_delete(giregion); } break; case GEOIP_CITY_EDITION_REV0_V6: case GEOIP_CITY_EDITION_REV1_V6: gir = GeoIP_record_by_addr_v6(cfg->gips[i], ipaddr); if (gir != NULL) { if ( gir->country_code != NULL ) { region_name = GeoIP_region_name_by_code(gir->country_code, gir->region); } sprintf(metrocodestr, "%d", gir->dma_code); sprintf(areacodestr, "%d", gir->area_code); if (cfg->GeoIPOutput & GEOIP_NOTES) { apr_table_setn(r->notes, "GEOIP_CONTINENT_CODE_V6", gir->continent_code); apr_table_setn(r->notes, "GEOIP_COUNTRY_CODE_V6", gir->country_code); apr_table_setn(r->notes, "GEOIP_COUNTRY_NAME_V6", gir->country_name); if (gir->region != NULL) { apr_table_set(r->notes, "GEOIP_REGION_V6", gir->region); if ( region_name != NULL ){ apr_table_set(r->notes, "GEOIP_REGION_NAME_V6", region_name); } } if (gir->city != NULL) { apr_table_set(r->notes, "GEOIP_CITY_V6", gir->city); } apr_table_setn(r->notes, "GEOIP_DMA_CODE_V6", metrocodestr); apr_table_setn(r->notes, "GEOIP_METRO_CODE_V6", metrocodestr); apr_table_setn(r->notes, "GEOIP_AREA_CODE_V6", areacodestr); } if (cfg->GeoIPOutput & GEOIP_ENV) { apr_table_setn(r->subprocess_env, "GEOIP_CONTINENT_CODE_V6", gir->continent_code); apr_table_setn(r->subprocess_env, "GEOIP_COUNTRY_CODE_V6", gir->country_code); apr_table_setn(r->subprocess_env, "GEOIP_COUNTRY_NAME_V6", gir->country_name); if (gir->region != NULL) { apr_table_set(r->subprocess_env, "GEOIP_REGION_V6", gir->region); if ( region_name != NULL ){ apr_table_set(r->subprocess_env, "GEOIP_REGION_NAME_V6", region_name); } } if (gir->city != NULL) { apr_table_set(r->subprocess_env, "GEOIP_CITY_V6", gir->city); } apr_table_setn(r->subprocess_env, "GEOIP_DMA_CODE_V6", metrocodestr); apr_table_setn(r->subprocess_env, "GEOIP_METRO_CODE_V6", metrocodestr); apr_table_setn(r->subprocess_env, "GEOIP_AREA_CODE_V6", areacodestr); } sprintf(latstr, "%f", gir->latitude); sprintf(lonstr, "%f", gir->longitude); if (cfg->GeoIPOutput & GEOIP_NOTES) { apr_table_setn(r->notes, "GEOIP_LATITUDE_V6", latstr); } if (cfg->GeoIPOutput & GEOIP_ENV) { apr_table_setn(r->subprocess_env, "GEOIP_LATITUDE_V6", latstr); } if (cfg->GeoIPOutput & GEOIP_NOTES) { apr_table_setn(r->notes, "GEOIP_LONGITUDE_V6", lonstr); } if (cfg->GeoIPOutput & GEOIP_ENV) { apr_table_setn(r->subprocess_env, "GEOIP_LONGITUDE_V6", lonstr); } if (gir->postal_code != NULL) { if (cfg->GeoIPOutput & GEOIP_NOTES) { apr_table_set(r->notes, "GEOIP_POSTAL_CODE_V6", gir->postal_code); } if (cfg->GeoIPOutput & GEOIP_ENV) { apr_table_set(r->subprocess_env, "GEOIP_POSTAL_CODE_V6", gir->postal_code); } } GeoIPRecord_delete(gir); } break; case GEOIP_CITY_EDITION_REV0: case GEOIP_CITY_EDITION_REV1: gir = GeoIP_record_by_addr(cfg->gips[i], ipaddr); if (gir != NULL) { if ( gir->country_code != NULL ) { region_name = GeoIP_region_name_by_code(gir->country_code, gir->region); } sprintf(metrocodestr, "%d", gir->dma_code); sprintf(areacodestr, "%d", gir->area_code); if (cfg->GeoIPOutput & GEOIP_NOTES) { apr_table_setn(r->notes, "GEOIP_CONTINENT_CODE", gir->continent_code); apr_table_setn(r->notes, "GEOIP_COUNTRY_CODE", gir->country_code); apr_table_setn(r->notes, "GEOIP_COUNTRY_NAME", gir->country_name); if (gir->region != NULL) { apr_table_set(r->notes, "GEOIP_REGION", gir->region); if ( region_name != NULL ){ apr_table_set(r->notes, "GEOIP_REGION_NAME", region_name); } } if (gir->city != NULL) { apr_table_set(r->notes, "GEOIP_CITY", gir->city); } apr_table_setn(r->notes, "GEOIP_DMA_CODE", metrocodestr); apr_table_setn(r->notes, "GEOIP_METRO_CODE", metrocodestr); apr_table_setn(r->notes, "GEOIP_AREA_CODE", areacodestr); } if (cfg->GeoIPOutput & GEOIP_ENV) { apr_table_setn(r->subprocess_env, "GEOIP_CONTINENT_CODE", gir->continent_code); apr_table_setn(r->subprocess_env, "GEOIP_COUNTRY_CODE", gir->country_code); apr_table_setn(r->subprocess_env, "GEOIP_COUNTRY_NAME", gir->country_name); if (gir->region != NULL) { apr_table_set(r->subprocess_env, "GEOIP_REGION", gir->region); if ( region_name != NULL ){ apr_table_set(r->subprocess_env, "GEOIP_REGION_NAME", region_name); } } if (gir->city != NULL) { apr_table_set(r->subprocess_env, "GEOIP_CITY", gir->city); } apr_table_setn(r->subprocess_env, "GEOIP_DMA_CODE", metrocodestr); apr_table_setn(r->subprocess_env, "GEOIP_METRO_CODE", metrocodestr); apr_table_setn(r->subprocess_env, "GEOIP_AREA_CODE", areacodestr); } sprintf(latstr, "%f", gir->latitude); sprintf(lonstr, "%f", gir->longitude); if (cfg->GeoIPOutput & GEOIP_NOTES) { apr_table_setn(r->notes, "GEOIP_LATITUDE", latstr); } if (cfg->GeoIPOutput & GEOIP_ENV) { apr_table_setn(r->subprocess_env, "GEOIP_LATITUDE", latstr); } if (cfg->GeoIPOutput & GEOIP_NOTES) { apr_table_setn(r->notes, "GEOIP_LONGITUDE", lonstr); } if (cfg->GeoIPOutput & GEOIP_ENV) { apr_table_setn(r->subprocess_env, "GEOIP_LONGITUDE", lonstr); } if (gir->postal_code != NULL) { if (cfg->GeoIPOutput & GEOIP_NOTES) { apr_table_set(r->notes, "GEOIP_POSTAL_CODE", gir->postal_code); } if (cfg->GeoIPOutput & GEOIP_ENV) { apr_table_set(r->subprocess_env, "GEOIP_POSTAL_CODE", gir->postal_code); } } GeoIPRecord_delete(gir); } break; case GEOIP_ORG_EDITION: orgorisp = GeoIP_name_by_addr(cfg->gips[i], ipaddr); if (orgorisp != NULL) { if (cfg->GeoIPOutput & GEOIP_NOTES) { apr_table_setn(r->notes, "GEOIP_ORGANIZATION", orgorisp); } if (cfg->GeoIPOutput & GEOIP_ENV) { apr_table_setn(r->subprocess_env, "GEOIP_ORGANIZATION", orgorisp); } } break; case GEOIP_ISP_EDITION: orgorisp = GeoIP_name_by_addr(cfg->gips[i], ipaddr); if (orgorisp != NULL) { if (cfg->GeoIPOutput & GEOIP_NOTES) { apr_table_setn(r->notes, "GEOIP_ISP", orgorisp); } if (cfg->GeoIPOutput & GEOIP_ENV) { apr_table_setn(r->subprocess_env, "GEOIP_ISP", orgorisp); } } break; case GEOIP_DOMAIN_EDITION: orgorisp = GeoIP_name_by_addr(cfg->gips[i], ipaddr); if (orgorisp != NULL) { if (cfg->GeoIPOutput & GEOIP_NOTES) { apr_table_setn(r->notes, "GEOIP_DOMAIN", orgorisp); } if (cfg->GeoIPOutput & GEOIP_ENV) { apr_table_setn(r->subprocess_env, "GEOIP_DOMAIN", orgorisp); } } break; } } return OK; }
static apr_status_t cache_canonicalise_key(request_rec *r, apr_pool_t* p, const char *uri, apr_uri_t *parsed_uri, const char **key) { cache_server_conf *conf; char *port_str, *hn, *lcs; const char *hostname, *scheme; int i; const char *path; char *querystring; if (*key) { /* * We have been here before during the processing of this request. */ return APR_SUCCESS; } /* * Get the module configuration. We need this for the CacheIgnoreQueryString * option below. */ conf = (cache_server_conf *) ap_get_module_config(r->server->module_config, &cache_module); /* * Use the canonical name to improve cache hit rate, but only if this is * not a proxy request or if this is a reverse proxy request. * We need to handle both cases in the same manner as for the reverse proxy * case we have the following situation: * * If a cached entry is looked up by mod_cache's quick handler r->proxyreq * is still unset in the reverse proxy case as it only gets set in the * translate name hook (either by ProxyPass or mod_rewrite) which is run * after the quick handler hook. This is different to the forward proxy * case where it gets set before the quick handler is run (in the * post_read_request hook). * If a cache entry is created by the CACHE_SAVE filter we always have * r->proxyreq set correctly. * So we must ensure that in the reverse proxy case we use the same code * path and using the canonical name seems to be the right thing to do * in the reverse proxy case. */ if (!r->proxyreq || (r->proxyreq == PROXYREQ_REVERSE)) { if (conf->base_uri && conf->base_uri->hostname) { hostname = conf->base_uri->hostname; } else { /* Use _default_ as the hostname if none present, as in mod_vhost */ hostname = ap_get_server_name(r); if (!hostname) { hostname = "_default_"; } } } else if (parsed_uri->hostname) { /* Copy the parsed uri hostname */ hn = apr_pstrdup(p, parsed_uri->hostname); ap_str_tolower(hn); /* const work-around */ hostname = hn; } else { /* We are a proxied request, with no hostname. Unlikely * to get very far - but just in case */ hostname = "_default_"; } /* * Copy the scheme, ensuring that it is lower case. If the parsed uri * contains no string or if this is not a proxy request get the http * scheme for this request. As r->parsed_uri.scheme is not set if this * is a reverse proxy request, it is ensured that the cases * "no proxy request" and "reverse proxy request" are handled in the same * manner (see above why this is needed). */ if (r->proxyreq && parsed_uri->scheme) { /* Copy the scheme and lower-case it */ lcs = apr_pstrdup(p, parsed_uri->scheme); ap_str_tolower(lcs); /* const work-around */ scheme = lcs; } else { if (conf->base_uri && conf->base_uri->scheme) { scheme = conf->base_uri->scheme; } else { scheme = ap_http_scheme(r); } } /* * If this is a proxy request, but not a reverse proxy request (see comment * above why these cases must be handled in the same manner), copy the * URI's port-string (which may be a service name). If the URI contains * no port-string, use apr-util's notion of the default port for that * scheme - if available. Otherwise use the port-number of the current * server. */ if (r->proxyreq && (r->proxyreq != PROXYREQ_REVERSE)) { if (parsed_uri->port_str) { port_str = apr_pcalloc(p, strlen(parsed_uri->port_str) + 2); port_str[0] = ':'; for (i = 0; parsed_uri->port_str[i]; i++) { port_str[i + 1] = apr_tolower(parsed_uri->port_str[i]); } } else if (apr_uri_port_of_scheme(scheme)) { port_str = apr_psprintf(p, ":%u", apr_uri_port_of_scheme(scheme)); } else { /* No port string given in the AbsoluteUri, and we have no * idea what the default port for the scheme is. Leave it * blank and live with the inefficiency of some extra cached * entities. */ port_str = ""; } } else { if (conf->base_uri && conf->base_uri->port_str) { port_str = conf->base_uri->port_str; } else if (conf->base_uri && conf->base_uri->hostname) { port_str = ""; } else { /* Use the server port */ port_str = apr_psprintf(p, ":%u", ap_get_server_port(r)); } } /* * Check if we need to ignore session identifiers in the URL and do so * if needed. */ path = uri; querystring = parsed_uri->query; if (conf->ignore_session_id->nelts) { int i; char **identifier; identifier = (char **) conf->ignore_session_id->elts; for (i = 0; i < conf->ignore_session_id->nelts; i++, identifier++) { int len; const char *param; len = strlen(*identifier); /* * Check that we have a parameter separator in the last segment * of the path and that the parameter matches our identifier */ if ((param = ap_strrchr_c(path, ';')) && !strncmp(param + 1, *identifier, len) && (*(param + len + 1) == '=') && !ap_strchr_c(param + len + 2, '/')) { path = apr_pstrndup(p, path, param - path); continue; } /* * Check if the identifier is in the querystring and cut it out. */ if (querystring) { /* * First check if the identifier is at the beginning of the * querystring and followed by a '=' */ if (!strncmp(querystring, *identifier, len) && (*(querystring + len) == '=')) { param = querystring; } else { char *complete; /* * In order to avoid subkey matching (PR 48401) prepend * identifier with a '&' and append a '=' */ complete = apr_pstrcat(p, "&", *identifier, "=", NULL); param = strstr(querystring, complete); /* If we found something we are sitting on the '&' */ if (param) { param++; } } if (param) { const char *amp; if (querystring != param) { querystring = apr_pstrndup(p, querystring, param - querystring); } else { querystring = ""; } if ((amp = ap_strchr_c(param + len + 1, '&'))) { querystring = apr_pstrcat(p, querystring, amp + 1, NULL); } else { /* * If querystring is not "", then we have the case * that the identifier parameter we removed was the * last one in the original querystring. Hence we have * a trailing '&' which needs to be removed. */ if (*querystring) { querystring[strlen(querystring) - 1] = '\0'; } } } } } } /* Key format is a URI, optionally without the query-string */ if (conf->ignorequerystring) { *key = apr_pstrcat(p, scheme, "://", hostname, port_str, path, "?", NULL); } else { *key = apr_pstrcat(p, scheme, "://", hostname, port_str, path, "?", querystring, NULL); } /* * Store the key in the request_config for the cache as r->parsed_uri * might have changed in the time from our first visit here triggered by the * quick handler and our possible second visit triggered by the CACHE_SAVE * filter (e.g. r->parsed_uri got unescaped). In this case we would save the * resource in the cache under a key where it is never found by the quick * handler during following requests. */ ap_log_rerror( APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, APLOGNO(00698) "cache: Key for entity %s?%s is %s", uri, parsed_uri->query, *key); return APR_SUCCESS; }
static const char *define_filter(cmd_parms *cmd, void *dummy, const char *args) { ef_server_t *conf = ap_get_module_config(cmd->server->module_config, &ext_filter_module); const char *token; const char *name; char *normalized_name; ef_filter_t *filter; name = ap_getword_white(cmd->pool, &args); if (!name) { return "Filter name not found"; } /* During request processing, we find information about the filter * by looking up the filter name provided by core server in our * hash table. But the core server has normalized the filter * name by converting it to lower case. Thus, when adding the * filter to our hash table we have to use lower case as well. */ normalized_name = apr_pstrdup(cmd->pool, name); ap_str_tolower(normalized_name); if (apr_hash_get(conf->h, normalized_name, APR_HASH_KEY_STRING)) { return apr_psprintf(cmd->pool, "ExtFilter %s is already defined", name); } filter = (ef_filter_t *)apr_pcalloc(conf->p, sizeof(ef_filter_t)); filter->name = name; filter->mode = OUTPUT_FILTER; filter->ftype = AP_FTYPE_RESOURCE; apr_hash_set(conf->h, normalized_name, APR_HASH_KEY_STRING, filter); while (*args) { while (apr_isspace(*args)) { ++args; } /* Nasty parsing... I wish I could simply use ap_getword_white() * here and then look at the token, but ap_getword_white() doesn't * do the right thing when we have cmd="word word word" */ if (!strncasecmp(args, "preservescontentlength", 22)) { token = ap_getword_white(cmd->pool, &args); if (!strcasecmp(token, "preservescontentlength")) { filter->preserves_content_length = 1; } else { return apr_psprintf(cmd->pool, "mangled argument `%s'", token); } continue; } if (!strncasecmp(args, "mode=", 5)) { args += 5; token = ap_getword_white(cmd->pool, &args); if (!strcasecmp(token, "output")) { filter->mode = OUTPUT_FILTER; } else if (!strcasecmp(token, "input")) { filter->mode = INPUT_FILTER; } else { return apr_psprintf(cmd->pool, "Invalid mode: `%s'", token); } continue; } if (!strncasecmp(args, "ftype=", 6)) { args += 6; token = ap_getword_white(cmd->pool, &args); filter->ftype = atoi(token); continue; } if (!strncasecmp(args, "enableenv=", 10)) { args += 10; token = ap_getword_white(cmd->pool, &args); filter->enable_env = token; continue; } if (!strncasecmp(args, "disableenv=", 11)) { args += 11; token = ap_getword_white(cmd->pool, &args); filter->disable_env = token; continue; } if (!strncasecmp(args, "intype=", 7)) { args += 7; filter->intype = ap_getword_white(cmd->pool, &args); continue; } if (!strncasecmp(args, "outtype=", 8)) { args += 8; filter->outtype = ap_getword_white(cmd->pool, &args); continue; } if (!strncasecmp(args, "cmd=", 4)) { args += 4; if ((token = parse_cmd(cmd->pool, &args, filter))) { return token; } continue; } return apr_psprintf(cmd->pool, "Unexpected parameter: `%s'", args); } /* parsing is done... register the filter */ if (filter->mode == OUTPUT_FILTER) { /* XXX need a way to ensure uniqueness among all filters */ ap_register_output_filter(filter->name, ef_output_filter, NULL, filter->ftype); } else if (filter->mode == INPUT_FILTER) { /* XXX need a way to ensure uniqueness among all filters */ ap_register_input_filter(filter->name, ef_input_filter, NULL, filter->ftype); } else { ap_assert(1 != 1); /* we set the field wrong somehow */ } return NULL; }
static int filter_lookup(ap_filter_t *f, ap_filter_rec_t *filter) { ap_filter_provider_t *provider; int match = 0; const char *err = NULL; request_rec *r = f->r; harness_ctx *ctx = f->ctx; provider_ctx *pctx; #ifndef NO_PROTOCOL unsigned int proto_flags; mod_filter_ctx *rctx = ap_get_module_config(r->request_config, &filter_module); #endif /* Check registered providers in order */ for (provider = filter->providers; provider; provider = provider->next) { if (provider->expr) { match = ap_expr_exec(r, provider->expr, &err); if (err) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(01379) "Error evaluating filter dispatch condition: %s", err); match = 0; } ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, "Expression condition for '%s' %s", provider->frec->name, match ? "matched" : "did not match"); } else if (r->content_type) { const char **type = provider->types; size_t len = strcspn(r->content_type, "; \t"); AP_DEBUG_ASSERT(type != NULL); ap_log_rerror(APLOG_MARK, APLOG_TRACE4, 0, r, "Content-Type '%s' ...", r->content_type); while (*type) { /* Handle 'content-type;charset=...' correctly */ if (strncmp(*type, r->content_type, len) == 0 && (*type)[len] == '\0') { ap_log_rerror(APLOG_MARK, APLOG_TRACE4, 0, r, "... matched '%s'", *type); match = 1; break; } else { ap_log_rerror(APLOG_MARK, APLOG_TRACE4, 0, r, "... did not match '%s'", *type); } type++; } ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, "Content-Type condition for '%s' %s", provider->frec->name, match ? "matched" : "did not match"); } else { ap_log_rerror(APLOG_MARK, APLOG_TRACE2, 0, r, "Content-Type condition for '%s' did not match: " "no Content-Type", provider->frec->name); } if (match) { /* condition matches this provider */ #ifndef NO_PROTOCOL /* check protocol * * FIXME: * This is a quick hack and almost certainly buggy. * The idea is that by putting this in mod_filter, we relieve * filter implementations of the burden of fixing up HTTP headers * for cases that are routinely affected by filters. * * Default is ALWAYS to do nothing, so as not to tread on the * toes of filters which want to do it themselves. * */ proto_flags = provider->frec->proto_flags; /* some specific things can't happen in a proxy */ if (r->proxyreq) { if (proto_flags & AP_FILTER_PROTO_NO_PROXY) { /* can't use this provider; try next */ continue; } if (proto_flags & AP_FILTER_PROTO_TRANSFORM) { const char *str = apr_table_get(r->headers_out, "Cache-Control"); if (str) { char *str1 = apr_pstrdup(r->pool, str); ap_str_tolower(str1); if (strstr(str1, "no-transform")) { /* can't use this provider; try next */ continue; } } apr_table_addn(r->headers_out, "Warning", apr_psprintf(r->pool, "214 %s Transformation applied", r->hostname)); } } /* things that are invalidated if the filter transforms content */ if (proto_flags & AP_FILTER_PROTO_CHANGE) { apr_table_unset(r->headers_out, "Content-MD5"); apr_table_unset(r->headers_out, "ETag"); if (proto_flags & AP_FILTER_PROTO_CHANGE_LENGTH) { apr_table_unset(r->headers_out, "Content-Length"); } } /* no-cache is for a filter that has different effect per-hit */ if (proto_flags & AP_FILTER_PROTO_NO_CACHE) { apr_table_unset(r->headers_out, "Last-Modified"); apr_table_addn(r->headers_out, "Cache-Control", "no-cache"); } if (proto_flags & AP_FILTER_PROTO_NO_BYTERANGE) { apr_table_setn(r->headers_out, "Accept-Ranges", "none"); } else if (rctx && rctx->range) { /* restore range header we saved earlier */ apr_table_setn(r->headers_in, "Range", rctx->range); rctx->range = NULL; } #endif for (pctx = ctx->init_ctx; pctx; pctx = pctx->next) { if (pctx->provider == provider) { ctx->fctx = pctx->ctx ; } } ctx->func = provider->frec->filter_func.out_func; return 1; } } /* No provider matched */ return 0; }
static const char *filter_provider(cmd_parms *cmd, void *CFG, const char *args) { mod_filter_cfg *cfg = CFG; int flags; ap_filter_provider_t *provider; const char *rxend; const char *c; char *str; const char *eq; ap_filter_rec_t* frec; ap_filter_rec_t* provider_frec; /* insist on exactly four arguments */ const char *fname = ap_getword_conf(cmd->pool, &args) ; const char *pname = ap_getword_conf(cmd->pool, &args) ; const char *condition = ap_getword_conf(cmd->pool, &args) ; const char *match = ap_getword_conf(cmd->pool, &args) ; eq = ap_getword_conf(cmd->pool, &args) ; if ( !*fname || !*pname || !*match || !*condition || *eq ) { return "usage: FilterProvider filter provider condition match" ; } /* fname has been declared with DeclareFilter, so we can look it up */ frec = apr_hash_get(cfg->live_filters, fname, APR_HASH_KEY_STRING); /* or if provider is mod_filter itself, we can also look it up */ if (!frec) { c = filter_declare(cmd, CFG, fname, NULL); if ( c ) { return c; } frec = apr_hash_get(cfg->live_filters, fname, APR_HASH_KEY_STRING); } if (!frec) { return apr_psprintf(cmd->pool, "Undeclared smart filter %s", fname); } /* if provider has been registered, we can look it up */ provider_frec = ap_get_output_filter_handle(pname); if (!provider_frec) { provider_frec = apr_hash_get(cfg->live_filters, pname, APR_HASH_KEY_STRING); } if (!provider_frec) { return apr_psprintf(cmd->pool, "Unknown filter provider %s", pname); } provider = apr_palloc(cmd->pool, sizeof(ap_filter_provider_t)); if (*match == '!') { provider->not = 1; ++match; } else { provider->not = 0; } switch (*match++) { case '<': if (*match == '=') { provider->match_type = INT_LE; ++match; } else { provider->match_type = INT_LT; } provider->match.number = atoi(match); break; case '>': if (*match == '=') { provider->match_type = INT_GE; ++match; } else { provider->match_type = INT_GT; } provider->match.number = atoi(match); break; case '=': provider->match_type = INT_EQ; provider->match.number = atoi(match); break; case '/': provider->match_type = REGEX_MATCH; rxend = ap_strchr_c(match, '/'); if (!rxend) { return "Bad regexp syntax"; } flags = AP_REG_NOSUB; /* we're not mod_rewrite:-) */ for (c = rxend+1; *c; ++c) { switch (*c) { case 'i': flags |= AP_REG_ICASE; break; } } provider->match.regex = ap_pregcomp(cmd->pool, apr_pstrndup(cmd->pool, match, rxend-match), flags); break; case '*': provider->match_type = DEFINED; provider->match.number = -1; break; case '$': provider->match_type = STRING_CONTAINS; str = apr_pstrdup(cmd->pool, match); ap_str_tolower(str); provider->match.string = str; break; default: provider->match_type = STRING_MATCH; provider->match.string = apr_pstrdup(cmd->pool, match-1); break; } provider->frec = provider_frec; provider->next = frec->providers; frec->providers = provider; /* determine what a filter will dispatch this provider on */ eq = ap_strchr_c(condition, '='); if (eq) { str = apr_pstrdup(cmd->pool, eq+1); if (!strncasecmp(condition, "env=", 4)) { provider->dispatch = SUBPROCESS_ENV; } else if (!strncasecmp(condition, "req=", 4)) { provider->dispatch = REQUEST_HEADERS; } else if (!strncasecmp(condition, "resp=", 5)) { provider->dispatch = RESPONSE_HEADERS; } else { return "FilterProvider: unrecognized dispatch table"; } } else { if (!strcasecmp(condition, "handler")) { provider->dispatch = HANDLER; } else { provider->dispatch = RESPONSE_HEADERS; } str = apr_pstrdup(cmd->pool, condition); ap_str_tolower(str); } if ( (provider->dispatch == RESPONSE_HEADERS) && !strcasecmp(str, "content-type")) { provider->dispatch = CONTENT_TYPE; } provider->value = str; return NULL; }
static int filter_lookup(ap_filter_t *f, ap_filter_rec_t *filter) { ap_filter_provider_t *provider; const char *str = NULL; char *str1; int match; unsigned int proto_flags; request_rec *r = f->r; harness_ctx *ctx = f->ctx; provider_ctx *pctx; mod_filter_ctx *rctx = ap_get_module_config(r->request_config, &filter_module); /* Check registered providers in order */ for (provider = filter->providers; provider; provider = provider->next) { match = 1; switch (provider->dispatch) { case REQUEST_HEADERS: str = apr_table_get(r->headers_in, provider->value); break; case RESPONSE_HEADERS: str = apr_table_get(r->headers_out, provider->value); break; case SUBPROCESS_ENV: str = apr_table_get(r->subprocess_env, provider->value); break; case CONTENT_TYPE: str = r->content_type; break; case HANDLER: str = r->handler; break; } /* treat nulls so we don't have to check every strcmp individually * Not sure if there's anything better to do with them */ if (!str) { if (provider->match_type == DEFINED && provider->match.string) { match = 0; } } else if (!provider->match.string) { match = 0; } else { /* Now we have no nulls, so we can do string and regexp matching */ switch (provider->match_type) { case STRING_MATCH: if (strcasecmp(str, provider->match.string)) { match = 0; } break; case STRING_CONTAINS: str1 = apr_pstrdup(r->pool, str); ap_str_tolower(str1); if (!strstr(str1, provider->match.string)) { match = 0; } break; case REGEX_MATCH: if (ap_regexec(provider->match.regex, str, 0, NULL, 0) == AP_REG_NOMATCH) { match = 0; } break; case INT_EQ: if (atoi(str) != provider->match.number) { match = 0; } break; case INT_LT: if (atoi(str) < provider->match.number) { match = 0; } break; case INT_LE: if (atoi(str) <= provider->match.number) { match = 0; } break; case INT_GT: if (atoi(str) > provider->match.number) { match = 0; } break; case INT_GE: if (atoi(str) >= provider->match.number) { match = 0; } break; case DEFINED: /* we already handled this:-) */ break; } } if (match != provider->not) { /* condition matches this provider */ #ifndef NO_PROTOCOL /* check protocol * * FIXME: * This is a quick hack and almost certainly buggy. * The idea is that by putting this in mod_filter, we relieve * filter implementations of the burden of fixing up HTTP headers * for cases that are routinely affected by filters. * * Default is ALWAYS to do nothing, so as not to tread on the * toes of filters which want to do it themselves. * */ proto_flags = provider->frec->proto_flags; /* some specific things can't happen in a proxy */ if (r->proxyreq) { if (proto_flags & AP_FILTER_PROTO_NO_PROXY) { /* can't use this provider; try next */ continue; } if (proto_flags & AP_FILTER_PROTO_TRANSFORM) { str = apr_table_get(r->headers_out, "Cache-Control"); if (str) { str1 = apr_pstrdup(r->pool, str); ap_str_tolower(str1); if (strstr(str1, "no-transform")) { /* can't use this provider; try next */ continue; } } apr_table_addn(r->headers_out, "Warning", apr_psprintf(r->pool, "214 %s Transformation applied", r->hostname)); } } /* things that are invalidated if the filter transforms content */ if (proto_flags & AP_FILTER_PROTO_CHANGE) { apr_table_unset(r->headers_out, "Content-MD5"); apr_table_unset(r->headers_out, "ETag"); if (proto_flags & AP_FILTER_PROTO_CHANGE_LENGTH) { apr_table_unset(r->headers_out, "Content-Length"); } } /* no-cache is for a filter that has different effect per-hit */ if (proto_flags & AP_FILTER_PROTO_NO_CACHE) { apr_table_unset(r->headers_out, "Last-Modified"); apr_table_addn(r->headers_out, "Cache-Control", "no-cache"); } if (proto_flags & AP_FILTER_PROTO_NO_BYTERANGE) { apr_table_unset(r->headers_out, "Accept-Ranges"); } else if (rctx && rctx->range) { /* restore range header we saved earlier */ apr_table_setn(r->headers_in, "Range", rctx->range); rctx->range = NULL; } #endif for (pctx = ctx->init_ctx; pctx; pctx = pctx->next) { if (pctx->provider == provider) { ctx->fctx = pctx->ctx ; } } ctx->func = provider->frec->filter_func.out_func; return 1; } } /* No provider matched */ return 0; }
static int modperl_filter_add_connection(conn_rec *c, int idx, const char *name, modperl_filter_add_t addfunc, const char *type) { modperl_config_dir_t *dcfg = modperl_config_dir_get_defaults(c->base_server); MpAV *av; if ((av = dcfg->handlers_per_dir[idx])) { modperl_handler_t **handlers = (modperl_handler_t **)av->elts; int i; for (i=0; i<av->nelts; i++) { modperl_filter_ctx_t *ctx; ap_filter_t *f; /* process non-mod_perl filter handlers */ if ((handlers[i]->attrs & MP_FILTER_HTTPD_HANDLER)) { /* non-mp2 filters below PROTOCOL level can't be added * at the connection level, so we need to go through * the pain of figuring out the type of the filter */ ap_filter_rec_t *frec; char *normalized_name = apr_pstrdup(c->pool, handlers[i]->name); ap_str_tolower(normalized_name); frec = idx == MP_INPUT_FILTER_HANDLER ? ap_get_input_filter_handle(normalized_name) : ap_get_output_filter_handle(normalized_name); if (frec && frec->ftype < AP_FTYPE_PROTOCOL) { MP_TRACE_f(MP_FUNC, "a non-mod_perl %s handler %s " "skipped (not a connection filter)", type, handlers[i]->name); continue; } addfunc(handlers[i]->name, NULL, NULL, c); MP_TRACE_f(MP_FUNC, "a non-mod_perl %s handler %s configured " "(connection)", type, handlers[i]->name); continue; } /* skip non-connection level filters, e.g. request filters * configured outside the resource container */ if (!(handlers[i]->attrs & MP_FILTER_CONNECTION_HANDLER)) { MP_TRACE_f(MP_FUNC, "%s is not a FilterConnection handler, skipping", handlers[i]->name); continue; } ctx = (modperl_filter_ctx_t *)apr_pcalloc(c->pool, sizeof(*ctx)); ctx->handler = handlers[i]; f = addfunc(name, (void*)ctx, NULL, c); /* ap_filter_t filter cleanup */ apr_pool_cleanup_register(c->pool, (void *)f, modperl_filter_f_cleanup, apr_pool_cleanup_null); if (handlers[i]->attrs & MP_FILTER_HAS_INIT_HANDLER && handlers[i]->next) { int status = modperl_run_filter_init( f, (idx == MP_INPUT_FILTER_HANDLER ? MP_INPUT_FILTER_MODE : MP_OUTPUT_FILTER_MODE), handlers[i]->next); if (status != OK) { return status; } } MP_TRACE_h(MP_FUNC, "%s handler %s configured (connection)", type, handlers[i]->name); } return OK; } MP_TRACE_h(MP_FUNC, "no %s handlers configured (connection)", type); return DECLINED; }