mod_ext_filter.c revision 459eaf0826f995b73a0dc066f59ea10d2824e72d
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/* Licensed to the Apache Software Foundation (ASF) under one or more
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * contributor license agreements. See the NOTICE file distributed with
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * this work for additional information regarding copyright ownership.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * The ASF licenses this file to You under the Apache License, Version 2.0
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * (the "License"); you may not use this file except in compliance with
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * the License. You may obtain a copy of the License at
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * http://www.apache.org/licenses/LICENSE-2.0
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * Unless required by applicable law or agreed to in writing, software
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * distributed under the License is distributed on an "AS IS" BASIS,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * See the License for the specific language governing permissions and
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * limitations under the License.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow/*
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * mod_ext_filter allows Unix-style filters to filter http content.
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include "httpd.h"
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include "http_config.h"
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include "http_log.h"
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include "http_protocol.h"
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include "http_core.h"
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include "apr_buckets.h"
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include "util_filter.h"
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include "util_script.h"
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include "util_time.h"
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include "apr_strings.h"
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include "apr_hash.h"
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include "apr_lib.h"
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#include "apr_poll.h"
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross#define APR_WANT_STRFUNC
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross#include "apr_want.h"
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Rosstypedef struct ef_server_t {
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross apr_pool_t *p;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow apr_hash_t *h;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow} ef_server_t;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowtypedef struct ef_filter_t {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow const char *name;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow enum {INPUT_FILTER=1, OUTPUT_FILTER} mode;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ap_filter_type ftype;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow const char *command;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross const char *enable_env;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow const char *disable_env;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross char **args;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow const char *intype; /* list of IMTs we process (well, just one for now) */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#define INTYPE_ALL (char *)1
4bff34e37def8a90f9194d81bc345c52ba20086athurlow const char *outtype; /* IMT of filtered output */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#define OUTTYPE_UNCHANGED (char *)1
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int preserves_content_length;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow} ef_filter_t;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowtypedef struct ef_dir_t {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int log_stderr;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int onfail;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross} ef_dir_t;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
4bff34e37def8a90f9194d81bc345c52ba20086athurlowtypedef struct ef_ctx_t {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross apr_pool_t *p;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow apr_proc_t *proc;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross apr_procattr_t *procattr;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ef_dir_t *dc;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ef_filter_t *filter;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross int noop;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#if APR_FILES_AS_SOCKETS
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross apr_pollset_t *pollset;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#endif
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross} ef_ctx_t;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossmodule AP_MODULE_DECLARE_DATA ext_filter_module;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossstatic const server_rec *main_server;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossstatic apr_status_t ef_output_filter(ap_filter_t *, apr_bucket_brigade *);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossstatic apr_status_t ef_input_filter(ap_filter_t *, apr_bucket_brigade *,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ap_input_mode_t, apr_read_type_e,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross apr_off_t);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#define ERRFN_USERDATA_KEY "EXTFILTCHILDERRFN"
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic void *create_ef_dir_conf(apr_pool_t *p, char *dummy)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ef_dir_t *dc = (ef_dir_t *)apr_pcalloc(p, sizeof(ef_dir_t));
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross dc->log_stderr = -1;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross dc->onfail = -1;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return dc;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossstatic void *create_ef_server_conf(apr_pool_t *p, server_rec *s)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ef_server_t *conf;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross conf = (ef_server_t *)apr_pcalloc(p, sizeof(ef_server_t));
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross conf->p = p;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross conf->h = apr_hash_make(conf->p);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return conf;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic void *merge_ef_dir_conf(apr_pool_t *p, void *basev, void *overridesv)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross{
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ef_dir_t *a = (ef_dir_t *)apr_pcalloc (p, sizeof(ef_dir_t));
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ef_dir_t *base = (ef_dir_t *)basev, *over = (ef_dir_t *)overridesv;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (over->log_stderr != -1) { /* if admin coded something... */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross a->log_stderr = over->log_stderr;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross else {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross a->log_stderr = base->log_stderr;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (over->onfail != -1) { /* if admin coded something... */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross a->onfail = over->onfail;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross else {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross a->onfail = base->onfail;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return a;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross}
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossstatic const char *add_options(cmd_parms *cmd, void *in_dc,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross const char *arg)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ef_dir_t *dc = in_dc;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (!strcasecmp(arg, "LogStderr")) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross dc->log_stderr = 1;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross else if (!strcasecmp(arg, "NoLogStderr")) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross dc->log_stderr = 0;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross else if (!strcasecmp(arg, "Onfail=remove")) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow dc->onfail = 1;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross else if (!strcasecmp(arg, "Onfail=abort")) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross dc->onfail = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow else {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return apr_pstrcat(cmd->temp_pool,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross "Invalid ExtFilterOptions option: ",
4bff34e37def8a90f9194d81bc345c52ba20086athurlow arg,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross NULL);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return NULL;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross}
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossstatic const char *parse_cmd(apr_pool_t *p, const char **args, ef_filter_t *filter)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (**args == '"') {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross const char *start = *args + 1;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross char *parms;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross int escaping = 0;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow apr_status_t rv;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ++*args; /* move past leading " */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* find true end of args string (accounting for escaped quotes) */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross while (**args && (**args != '"' || (**args == '"' && escaping))) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (escaping) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross escaping = 0;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross else if (**args == '\\') {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross escaping = 1;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ++*args;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (**args != '"') {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return "Expected cmd= delimiter";
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* copy *just* the arg string for parsing, */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross parms = apr_pstrndup(p, start, *args - start);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ++*args; /* move past trailing " */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* parse and tokenize the args. */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross rv = apr_tokenize_to_argv(parms, &(filter->args), p);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (rv != APR_SUCCESS) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return "cmd= parse error";
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross else
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* simple path */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* Allocate space for two argv pointers and parse the args. */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross filter->args = (char **)apr_palloc(p, 2 * sizeof(char *));
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross filter->args[0] = ap_getword_white(p, args);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross filter->args[1] = NULL; /* end of args */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (!filter->args[0]) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return "Invalid cmd= parameter";
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross filter->command = filter->args[0];
02d09e03eb27f3a2dc299de704e45dae5173f43fGordon Ross
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return NULL;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross}
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossstatic const char *define_filter(cmd_parms *cmd, void *dummy, const char *args)
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ef_server_t *conf = ap_get_module_config(cmd->server->module_config,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross &ext_filter_module);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross const char *token;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow const char *name;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow char *normalized_name;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ef_filter_t *filter;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross name = ap_getword_white(cmd->pool, &args);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (!name) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return "Filter name not found";
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* During request processing, we find information about the filter
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * by looking up the filter name provided by core server in our
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * hash table. But the core server has normalized the filter
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * name by converting it to lower case. Thus, when adding the
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * filter to our hash table we have to use lower case as well.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross normalized_name = apr_pstrdup(cmd->pool, name);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ap_str_tolower(normalized_name);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (apr_hash_get(conf->h, normalized_name, APR_HASH_KEY_STRING)) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return apr_psprintf(cmd->pool, "ExtFilter %s is already defined",
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross name);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross filter = (ef_filter_t *)apr_pcalloc(conf->p, sizeof(ef_filter_t));
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross filter->name = name;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow filter->mode = OUTPUT_FILTER;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross filter->ftype = AP_FTYPE_RESOURCE;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross apr_hash_set(conf->h, normalized_name, APR_HASH_KEY_STRING, filter);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross while (*args) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross while (apr_isspace(*args)) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ++args;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* Nasty parsing... I wish I could simply use ap_getword_white()
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross * here and then look at the token, but ap_getword_white() doesn't
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross * do the right thing when we have cmd="word word word"
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross */
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross if (!strncasecmp(args, "preservescontentlength", 22)) {
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross token = ap_getword_white(cmd->pool, &args);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross if (!strcasecmp(token, "preservescontentlength")) {
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross filter->preserves_content_length = 1;
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross }
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross else {
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross return apr_psprintf(cmd->pool,
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross "mangled argument `%s'",
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross token);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross continue;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross if (!strncasecmp(args, "mode=", 5)) {
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross args += 5;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross token = ap_getword_white(cmd->pool, &args);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (!strcasecmp(token, "output")) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross filter->mode = OUTPUT_FILTER;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross else if (!strcasecmp(token, "input")) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross filter->mode = INPUT_FILTER;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross else {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return apr_psprintf(cmd->pool, "Invalid mode: `%s'",
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross token);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross continue;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (!strncasecmp(args, "ftype=", 6)) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross args += 6;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross token = ap_getword_white(cmd->pool, &args);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross filter->ftype = atoi(token);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross continue;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (!strncasecmp(args, "enableenv=", 10)) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross args += 10;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross token = ap_getword_white(cmd->pool, &args);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross filter->enable_env = token;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross continue;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (!strncasecmp(args, "disableenv=", 11)) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross args += 11;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross token = ap_getword_white(cmd->pool, &args);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross filter->disable_env = token;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross continue;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (!strncasecmp(args, "intype=", 7)) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross args += 7;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross filter->intype = ap_getword_white(cmd->pool, &args);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross continue;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (!strncasecmp(args, "outtype=", 8)) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross args += 8;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross filter->outtype = ap_getword_white(cmd->pool, &args);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross continue;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (!strncasecmp(args, "cmd=", 4)) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross args += 4;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if ((token = parse_cmd(cmd->pool, &args, filter))) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return token;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross continue;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return apr_psprintf(cmd->pool, "Unexpected parameter: `%s'",
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross args);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* parsing is done... register the filter
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (filter->mode == OUTPUT_FILTER) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* XXX need a way to ensure uniqueness among all filters */
02d09e03eb27f3a2dc299de704e45dae5173f43fGordon Ross ap_register_output_filter(filter->name, ef_output_filter, NULL, filter->ftype);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross else if (filter->mode == INPUT_FILTER) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* XXX need a way to ensure uniqueness among all filters */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ap_register_input_filter(filter->name, ef_input_filter, NULL, filter->ftype);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross else {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ap_assert(1 != 1); /* we set the field wrong somehow */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return NULL;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross}
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic const command_rec cmds[] =
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross AP_INIT_ITERATE("ExtFilterOptions",
4bff34e37def8a90f9194d81bc345c52ba20086athurlow add_options,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross NULL,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ACCESS_CONF, /* same as SetInputFilter/SetOutputFilter */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross "valid options: LogStderr, NoLogStderr"),
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross AP_INIT_RAW_ARGS("ExtFilterDefine",
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross define_filter,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross NULL,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross RSRC_CONF,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross "Define an external filter"),
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross {NULL}
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross};
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic int ef_init(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *main_s)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross main_server = main_s;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return OK;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross}
1b34bc4aa5ecbd590d45845d21c8478049df6dcfbs
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossstatic void register_hooks(apr_pool_t *p)
1b34bc4aa5ecbd590d45845d21c8478049df6dcfbs{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ap_hook_post_config(ef_init, NULL, NULL, APR_HOOK_MIDDLE);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross}
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossstatic apr_status_t set_resource_limits(request_rec *r,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross apr_procattr_t *procattr)
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#if defined(RLIMIT_CPU) || defined(RLIMIT_NPROC) || \
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined (RLIMIT_AS)
1b34bc4aa5ecbd590d45845d21c8478049df6dcfbs core_dir_config *conf =
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross (core_dir_config *)ap_get_core_module_config(r->per_dir_config);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross apr_status_t rv;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#ifdef RLIMIT_CPU
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross rv = apr_procattr_limit_set(procattr, APR_LIMIT_CPU, conf->limit_cpu);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ap_assert(rv == APR_SUCCESS); /* otherwise, we're out of sync with APR */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#endif
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross rv = apr_procattr_limit_set(procattr, APR_LIMIT_MEM, conf->limit_mem);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ap_assert(rv == APR_SUCCESS); /* otherwise, we're out of sync with APR */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#endif
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#ifdef RLIMIT_NPROC
1b34bc4aa5ecbd590d45845d21c8478049df6dcfbs rv = apr_procattr_limit_set(procattr, APR_LIMIT_NPROC, conf->limit_nproc);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ap_assert(rv == APR_SUCCESS); /* otherwise, we're out of sync with APR */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#endif
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#endif /* if at least one limit defined */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return APR_SUCCESS;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross}
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossstatic apr_status_t ef_close_file(void *vfile)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return apr_file_close(vfile);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross}
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossstatic void child_errfn(apr_pool_t *pool, apr_status_t err, const char *description)
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross{
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross request_rec *r;
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross void *vr;
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross apr_file_t *stderr_log;
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross char errbuf[200];
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross char time_str[APR_CTIME_LEN];
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross apr_pool_userdata_get(&vr, ERRFN_USERDATA_KEY, pool);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross r = vr;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross apr_file_open_stderr(&stderr_log, pool);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ap_recent_ctime(time_str, apr_time_now());
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross apr_file_printf(stderr_log,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross "[%s] [client %s] mod_ext_filter (%d)%s: %s\n",
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross time_str,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross r->useragent_ip,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross err,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross apr_strerror(err, errbuf, sizeof(errbuf)),
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross description);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross}
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross/* init_ext_filter_process: get the external filter process going
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * This is per-filter-instance (i.e., per-request) initialization.
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossstatic apr_status_t init_ext_filter_process(ap_filter_t *f)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ef_ctx_t *ctx = f->ctx;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross apr_status_t rc;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ef_dir_t *dc = ctx->dc;
02d09e03eb27f3a2dc299de704e45dae5173f43fGordon Ross const char * const *env;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
1b34bc4aa5ecbd590d45845d21c8478049df6dcfbs ctx->proc = apr_pcalloc(ctx->p, sizeof(*ctx->proc));
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross rc = apr_procattr_create(&ctx->procattr, ctx->p);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross ap_assert(rc == APR_SUCCESS);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross rc = apr_procattr_io_set(ctx->procattr,
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross APR_CHILD_BLOCK,
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross APR_CHILD_BLOCK,
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross APR_CHILD_BLOCK);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross ap_assert(rc == APR_SUCCESS);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross rc = set_resource_limits(f->r, ctx->procattr);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross ap_assert(rc == APR_SUCCESS);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross if (dc->log_stderr > 0) {
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross rc = apr_procattr_child_err_set(ctx->procattr,
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross f->r->server->error_log, /* stderr in child */
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross NULL);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross ap_assert(rc == APR_SUCCESS);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross }
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross rc = apr_procattr_child_errfn_set(ctx->procattr, child_errfn);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross ap_assert(rc == APR_SUCCESS);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross apr_pool_userdata_set(f->r, ERRFN_USERDATA_KEY, apr_pool_cleanup_null, ctx->p);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross rc = apr_procattr_error_check_set(ctx->procattr, 1);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross if (rc != APR_SUCCESS) {
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross return rc;
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross }
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross /* add standard CGI variables as well as DOCUMENT_URI, DOCUMENT_PATH_INFO,
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross * and QUERY_STRING_UNESCAPED
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross */
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross ap_add_cgi_vars(f->r);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross ap_add_common_vars(f->r);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross apr_table_setn(f->r->subprocess_env, "DOCUMENT_URI", f->r->uri);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross apr_table_setn(f->r->subprocess_env, "DOCUMENT_PATH_INFO", f->r->path_info);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross if (f->r->args) {
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross /* QUERY_STRING is added by ap_add_cgi_vars */
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross char *arg_copy = apr_pstrdup(f->r->pool, f->r->args);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross ap_unescape_url(arg_copy);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross apr_table_setn(f->r->subprocess_env, "QUERY_STRING_UNESCAPED",
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross ap_escape_shell_cmd(f->r->pool, arg_copy));
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross }
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross env = (const char * const *) ap_create_environment(ctx->p,
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross f->r->subprocess_env);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross rc = apr_proc_create(ctx->proc,
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross ctx->filter->command,
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross (const char * const *)ctx->filter->args,
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross env, /* environment */
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross ctx->procattr,
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross ctx->p);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross if (rc != APR_SUCCESS) {
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, f->r, APLOGNO(01458)
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross "couldn't create child process to run `%s'",
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross ctx->filter->command);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross return rc;
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross }
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross apr_pool_note_subprocess(ctx->p, ctx->proc, APR_KILL_AFTER_TIMEOUT);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross /* We don't want the handle to the child's stdin inherited by any
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross * other processes created by httpd. Otherwise, when we close our
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross * handle, the child won't see EOF because another handle will still
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross * be open.
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross */
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross apr_pool_cleanup_register(ctx->p, ctx->proc->in,
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross apr_pool_cleanup_null, /* other mechanism */
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross ef_close_file);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross#if APR_FILES_AS_SOCKETS
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross {
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross apr_pollfd_t pfd = { 0 };
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross rc = apr_pollset_create(&ctx->pollset, 2, ctx->p, 0);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross ap_assert(rc == APR_SUCCESS);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross pfd.p = ctx->p;
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross pfd.desc_type = APR_POLL_FILE;
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross pfd.reqevents = APR_POLLOUT;
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross pfd.desc.f = ctx->proc->in;
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross rc = apr_pollset_add(ctx->pollset, &pfd);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross ap_assert(rc == APR_SUCCESS);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross pfd.reqevents = APR_POLLIN;
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross pfd.desc.f = ctx->proc->out;
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross rc = apr_pollset_add(ctx->pollset, &pfd);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross ap_assert(rc == APR_SUCCESS);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross }
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross#endif
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross return APR_SUCCESS;
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross}
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross
430b4c467020edf2445feb0c21db01c88b86243aGordon Rossstatic const char *get_cfg_string(ef_dir_t *dc, ef_filter_t *filter, apr_pool_t *p)
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross{
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross const char *log_stderr_str = dc->log_stderr < 1 ?
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross "NoLogStderr" : "LogStderr";
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross const char *preserve_content_length_str = filter->preserves_content_length ?
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross "PreservesContentLength" : "!PreserveContentLength";
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross const char *intype_str = !filter->intype ?
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross "*/*" : filter->intype;
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross const char *outtype_str = !filter->outtype ?
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross "(unchanged)" : filter->outtype;
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross return apr_psprintf(p,
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross "ExtFilterOptions %s %s ExtFilterInType %s "
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross "ExtFilterOuttype %s",
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross log_stderr_str, preserve_content_length_str,
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross intype_str, outtype_str);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross}
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross
430b4c467020edf2445feb0c21db01c88b86243aGordon Rossstatic ef_filter_t *find_filter_def(const server_rec *s, const char *fname)
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross{
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross ef_server_t *sc;
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross ef_filter_t *f;
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross sc = ap_get_module_config(s->module_config, &ext_filter_module);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross f = apr_hash_get(sc->h, fname, APR_HASH_KEY_STRING);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross if (!f && s != main_server) {
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross s = main_server;
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross sc = ap_get_module_config(s->module_config, &ext_filter_module);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross f = apr_hash_get(sc->h, fname, APR_HASH_KEY_STRING);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross }
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross return f;
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross}
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross
430b4c467020edf2445feb0c21db01c88b86243aGordon Rossstatic apr_status_t init_filter_instance(ap_filter_t *f)
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross{
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross ef_ctx_t *ctx;
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross ef_dir_t *dc;
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross apr_status_t rv;
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross f->ctx = ctx = apr_pcalloc(f->r->pool, sizeof(ef_ctx_t));
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross dc = ap_get_module_config(f->r->per_dir_config,
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross &ext_filter_module);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross ctx->dc = dc;
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross /* look for the user-defined filter */
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross ctx->filter = find_filter_def(f->r->server, f->frec->name);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross if (!ctx->filter) {
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r, APLOGNO(01459)
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross "couldn't find definition of filter '%s'",
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross f->frec->name);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross return APR_EINVAL;
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross }
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross ctx->p = f->r->pool;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (ctx->filter->intype &&
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ctx->filter->intype != INTYPE_ALL) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross const char *ctypes;
1b34bc4aa5ecbd590d45845d21c8478049df6dcfbs
1b34bc4aa5ecbd590d45845d21c8478049df6dcfbs if (ctx->filter->mode == INPUT_FILTER) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ctypes = apr_table_get(f->r->headers_in, "Content-Type");
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross else {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ctypes = f->r->content_type;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (ctypes) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross const char *ctype = ap_getword(f->r->pool, &ctypes, ';');
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (strcasecmp(ctx->filter->intype, ctype)) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* wrong IMT for us; don't mess with the output */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ctx->noop = 1;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross else {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ctx->noop = 1;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (ctx->filter->enable_env &&
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross !apr_table_get(f->r->subprocess_env, ctx->filter->enable_env)) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* an environment variable that enables the filter isn't set; bail */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ctx->noop = 1;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (ctx->filter->disable_env &&
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross apr_table_get(f->r->subprocess_env, ctx->filter->disable_env)) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* an environment variable that disables the filter is set; bail */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ctx->noop = 1;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (!ctx->noop) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross rv = init_ext_filter_process(f);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (rv != APR_SUCCESS) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return rv;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (ctx->filter->outtype &&
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ctx->filter->outtype != OUTTYPE_UNCHANGED) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ap_set_content_type(f->r, ctx->filter->outtype);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (ctx->filter->preserves_content_length != 1) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* nasty, but needed to avoid confusing the browser
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow apr_table_unset(f->r->headers_out, "Content-Length");
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (APLOGrtrace1(f->r)) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, f->r,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross "%sfiltering `%s' of type `%s' through `%s', cfg %s",
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ctx->noop ? "NOT " : "",
4bff34e37def8a90f9194d81bc345c52ba20086athurlow f->r->uri ? f->r->uri : f->r->filename,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross f->r->content_type ? f->r->content_type : "(unspecified)",
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ctx->filter->command,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross get_cfg_string(dc, ctx->filter, f->r->pool));
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return APR_SUCCESS;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross/* drain_available_output():
4bff34e37def8a90f9194d81bc345c52ba20086athurlow *
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * if any data is available from the filter, read it and append it
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * to the the bucket brigade
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossstatic apr_status_t drain_available_output(ap_filter_t *f,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross apr_bucket_brigade *bb)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross request_rec *r = f->r;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow conn_rec *c = r->connection;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ef_ctx_t *ctx = f->ctx;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross apr_size_t len;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross char buf[4096];
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross apr_status_t rv;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross apr_bucket *b;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross while (1) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross int lvl = APLOG_TRACE5;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross len = sizeof(buf);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross rv = apr_file_read(ctx->proc->out, buf, &len);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (rv && !APR_STATUS_IS_EAGAIN(rv))
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross lvl = APLOG_DEBUG;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ap_log_rerror(APLOG_MARK, lvl, rv, r, APLOGNO(01460)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross "apr_file_read(child output), len %" APR_SIZE_T_FMT,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross !rv ? len : -1);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (rv != APR_SUCCESS) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return rv;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross b = apr_bucket_heap_create(buf, len, NULL, c->bucket_alloc);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross APR_BRIGADE_INSERT_TAIL(bb, b);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return APR_SUCCESS;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* we should never get here; if we do, a bogus error message would be
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * the least of our problems
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return APR_ANONYMOUS;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross}
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlowstatic apr_status_t pass_data_to_filter(ap_filter_t *f, const char *data,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross apr_size_t len, apr_bucket_brigade *bb)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ef_ctx_t *ctx = f->ctx;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross apr_status_t rv;
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross apr_size_t bytes_written = 0;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross apr_size_t tmplen;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
4bff34e37def8a90f9194d81bc345c52ba20086athurlow do {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow tmplen = len - bytes_written;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow rv = apr_file_write_full(ctx->proc->in,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross (const char *)data + bytes_written,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross tmplen, &tmplen);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross bytes_written += tmplen;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (rv != APR_SUCCESS && !APR_STATUS_IS_EAGAIN(rv)) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r, APLOGNO(01461)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross "apr_file_write(child input), len %" APR_SIZE_T_FMT,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow tmplen);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return rv;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (APR_STATUS_IS_EAGAIN(rv)) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* XXX handle blocking conditions here... if we block, we need
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * to read data from the child process and pass it down to the
4bff34e37def8a90f9194d81bc345c52ba20086athurlow * next filter!
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross rv = drain_available_output(f, bb);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (APR_STATUS_IS_EAGAIN(rv)) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross#if APR_FILES_AS_SOCKETS
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross int num_events;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow const apr_pollfd_t *pdesc;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross rv = apr_pollset_poll(ctx->pollset, f->r->server->timeout,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross &num_events, &pdesc);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (rv != APR_SUCCESS && !APR_STATUS_IS_EINTR(rv)) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ap_log_rerror(APLOG_MARK, APLOG_WARNING, rv, f->r, APLOGNO(01462)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross "apr_pollset_poll()");
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* some error such as APR_TIMEUP */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return rv;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ap_log_rerror(APLOG_MARK, APLOG_TRACE6, rv, f->r,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow "apr_pollset_poll()");
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#else /* APR_FILES_AS_SOCKETS */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* Yuck... I'd really like to wait until I can read
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * or write, but instead I have to sleep and try again
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
4bff34e37def8a90f9194d81bc345c52ba20086athurlow apr_sleep(100000); /* 100 milliseconds */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ap_log_rerror(APLOG_MARK, APLOG_TRACE6, 0, f->r, "apr_sleep()");
4bff34e37def8a90f9194d81bc345c52ba20086athurlow#endif /* APR_FILES_AS_SOCKETS */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross else if (rv != APR_SUCCESS) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return rv;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow } while (bytes_written < len);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return rv;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross}
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross/* ef_unified_filter:
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross *
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * runs the bucket brigade bb through the filter and puts the result into
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * bb, dropping the previous content of bb (the input)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossstatic int ef_unified_filter(ap_filter_t *f, apr_bucket_brigade *bb)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross request_rec *r = f->r;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow conn_rec *c = r->connection;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ef_ctx_t *ctx = f->ctx;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross apr_bucket *b;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross apr_size_t len;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross const char *data;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross apr_status_t rv;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross char buf[4096];
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross apr_bucket *eos = NULL;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross apr_bucket_brigade *bb_tmp;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross bb_tmp = apr_brigade_create(r->pool, c->bucket_alloc);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross for (b = APR_BRIGADE_FIRST(bb);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross b != APR_BRIGADE_SENTINEL(bb);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow b = APR_BUCKET_NEXT(b))
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (APR_BUCKET_IS_EOS(b)) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross eos = b;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross break;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross rv = apr_bucket_read(b, &data, &len, APR_BLOCK_READ);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (rv != APR_SUCCESS) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01463) "apr_bucket_read()");
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return rv;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
4bff34e37def8a90f9194d81bc345c52ba20086athurlow /* Good cast, we just tested len isn't negative */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (len > 0 &&
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross (rv = pass_data_to_filter(f, data, (apr_size_t)len, bb_tmp))
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross != APR_SUCCESS) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return rv;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross apr_brigade_cleanup(bb);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross APR_BRIGADE_CONCAT(bb, bb_tmp);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross apr_brigade_destroy(bb_tmp);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (eos) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* close the child's stdin to signal that no more data is coming;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * that will cause the child to finish generating output
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if ((rv = apr_file_close(ctx->proc->in)) != APR_SUCCESS) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01464)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross "apr_file_close(child input)");
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return rv;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* since we've seen eos and closed the child's stdin, set the proper pipe
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross * timeout; we don't care if we don't return from apr_file_read() for a while...
4bff34e37def8a90f9194d81bc345c52ba20086athurlow */
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross rv = apr_file_pipe_timeout_set(ctx->proc->out,
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross r->server->timeout);
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross if (rv) {
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01465)
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross "apr_file_pipe_timeout_set(child output)");
430b4c467020edf2445feb0c21db01c88b86243aGordon Ross return rv;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
4bff34e37def8a90f9194d81bc345c52ba20086athurlow do {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow int lvl = APLOG_TRACE6;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross len = sizeof(buf);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross rv = apr_file_read(ctx->proc->out, buf, &len);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (rv && !APR_STATUS_IS_EOF(rv) && !APR_STATUS_IS_EAGAIN(rv))
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross lvl = APLOG_ERR;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ap_log_rerror(APLOG_MARK, lvl, rv, r, APLOGNO(01466)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross "apr_file_read(child output), len %" APR_SIZE_T_FMT,
4bff34e37def8a90f9194d81bc345c52ba20086athurlow !rv ? len : -1);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (APR_STATUS_IS_EAGAIN(rv)) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (eos) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross /* should not occur, because we have an APR timeout in place */
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross AP_DEBUG_ASSERT(1 != 1);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return APR_SUCCESS;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (rv == APR_SUCCESS) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross b = apr_bucket_heap_create(buf, len, NULL, c->bucket_alloc);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross APR_BRIGADE_INSERT_TAIL(bb, b);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross } while (rv == APR_SUCCESS);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (!APR_STATUS_IS_EOF(rv)) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return rv;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (eos) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross b = apr_bucket_eos_create(c->bucket_alloc);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross APR_BRIGADE_INSERT_TAIL(bb, b);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return APR_SUCCESS;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross}
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossstatic apr_status_t ef_output_filter(ap_filter_t *f, apr_bucket_brigade *bb)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross request_rec *r = f->r;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ef_ctx_t *ctx = f->ctx;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross apr_status_t rv;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (!ctx) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if ((rv = init_filter_instance(f)) != APR_SUCCESS) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ctx = f->ctx;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01467)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross "can't initialise output filter %s: %s",
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross f->frec->name,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross (ctx->dc->onfail == 1) ? "removing" : "aborting");
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ap_remove_output_filter(f);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (ctx->dc->onfail == 1) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return ap_pass_brigade(f->next, bb);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross else {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross apr_bucket *e;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross f->r->status_line = "500 Internal Server Error";
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross apr_brigade_cleanup(bb);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross e = ap_bucket_error_create(HTTP_INTERNAL_SERVER_ERROR,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross NULL, r->pool,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross f->c->bucket_alloc);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross APR_BRIGADE_INSERT_TAIL(bb, e);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross e = apr_bucket_eos_create(f->c->bucket_alloc);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross APR_BRIGADE_INSERT_TAIL(bb, e);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ap_pass_brigade(f->next, bb);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return AP_FILTER_ERROR;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ctx = f->ctx;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (ctx->noop) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ap_remove_output_filter(f);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return ap_pass_brigade(f->next, bb);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross rv = ef_unified_filter(f, bb);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (rv != APR_SUCCESS) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01468)
4bff34e37def8a90f9194d81bc345c52ba20086athurlow "ef_unified_filter() failed");
9c9af2590af49bb395bc8d2eace0f2d4ea16d165Gordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if ((rv = ap_pass_brigade(f->next, bb)) != APR_SUCCESS) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r, APLOGNO(01469)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross "ap_pass_brigade() failed");
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return rv;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross}
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Rossstatic apr_status_t ef_input_filter(ap_filter_t *f, apr_bucket_brigade *bb,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ap_input_mode_t mode, apr_read_type_e block,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross apr_off_t readbytes)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ef_ctx_t *ctx = f->ctx;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross apr_status_t rv;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (!ctx) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if ((rv = init_filter_instance(f)) != APR_SUCCESS) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ctx = f->ctx;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r, APLOGNO(01470)
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross "can't initialise input filter %s: %s",
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross f->frec->name,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross (ctx->dc->onfail == 1) ? "removing" : "aborting");
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ap_remove_input_filter(f);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (ctx->dc->onfail == 1) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return ap_get_brigade(f->next, bb, mode, block, readbytes);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
4bff34e37def8a90f9194d81bc345c52ba20086athurlow else {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow f->r->status = HTTP_INTERNAL_SERVER_ERROR;
4bff34e37def8a90f9194d81bc345c52ba20086athurlow return HTTP_INTERNAL_SERVER_ERROR;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross ctx = f->ctx;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
4bff34e37def8a90f9194d81bc345c52ba20086athurlow if (ctx->noop) {
4bff34e37def8a90f9194d81bc345c52ba20086athurlow ap_remove_input_filter(f);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return ap_get_brigade(f->next, bb, mode, block, readbytes);
4bff34e37def8a90f9194d81bc345c52ba20086athurlow }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross rv = ap_get_brigade(f->next, bb, mode, block, readbytes);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross if (rv != APR_SUCCESS) {
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return rv;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross }
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross rv = ef_unified_filter(f, bb);
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross return rv;
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross}
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon RossAP_DECLARE_MODULE(ext_filter) =
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross{
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross STANDARD20_MODULE_STUFF,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross create_ef_dir_conf,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross merge_ef_dir_conf,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross create_ef_server_conf,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross NULL,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross cmds,
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross register_hooks
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross};
613a2f6ba31e891e3d947a356daf5e563d43c1ceGordon Ross