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