-/* ====================================================================
- * The Apache Software License, Version 1.1
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
*
- * Copyright (c) 2000-2003 The Apache Software Foundation. All rights
- * reserved.
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Apache" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- *
- * Portions of this software are based upon public domain software
- * originally written at the National Center for Supercomputing Applications,
- * University of Illinois, Urbana-Champaign.
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
*/
/*
#include "http_config.h"
#include "http_log.h"
#include "http_protocol.h"
-#define CORE_PRIVATE
+
#include "http_core.h"
#include "apr_buckets.h"
#include "util_filter.h"
} ef_filter_t;
typedef struct ef_dir_t {
- int debug;
int log_stderr;
+ int onfail;
} ef_dir_t;
typedef struct ef_ctx_t {
ef_filter_t *filter;
int noop;
#if APR_FILES_AS_SOCKETS
- apr_pollfd_t *pollset;
+ apr_pollset_t *pollset;
#endif
} ef_ctx_t;
static const server_rec *main_server;
static apr_status_t ef_output_filter(ap_filter_t *, apr_bucket_brigade *);
-static apr_status_t ef_input_filter(ap_filter_t *, apr_bucket_brigade *,
- ap_input_mode_t, apr_read_type_e,
+static apr_status_t ef_input_filter(ap_filter_t *, apr_bucket_brigade *,
+ ap_input_mode_t, apr_read_type_e,
apr_off_t);
-#define DBGLVL_SHOWOPTIONS 1
-#define DBGLVL_ERRORCHECK 2
-#define DBGLVL_GORY 9
-
#define ERRFN_USERDATA_KEY "EXTFILTCHILDERRFN"
static void *create_ef_dir_conf(apr_pool_t *p, char *dummy)
{
ef_dir_t *dc = (ef_dir_t *)apr_pcalloc(p, sizeof(ef_dir_t));
- dc->debug = -1;
dc->log_stderr = -1;
+ dc->onfail = -1;
return dc;
}
ef_dir_t *a = (ef_dir_t *)apr_pcalloc (p, sizeof(ef_dir_t));
ef_dir_t *base = (ef_dir_t *)basev, *over = (ef_dir_t *)overridesv;
- if (over->debug != -1) { /* if admin coded something... */
- a->debug = over->debug;
+ if (over->log_stderr != -1) { /* if admin coded something... */
+ a->log_stderr = over->log_stderr;
}
else {
- a->debug = base->debug;
+ a->log_stderr = base->log_stderr;
}
- if (over->log_stderr != -1) { /* if admin coded something... */
- a->log_stderr = over->log_stderr;
+ if (over->onfail != -1) { /* if admin coded something... */
+ a->onfail = over->onfail;
}
else {
- a->log_stderr = base->log_stderr;
+ a->onfail = base->onfail;
}
return a;
{
ef_dir_t *dc = in_dc;
- if (!strncasecmp(arg, "DebugLevel=", 11)) {
- dc->debug = atoi(arg + 11);
- }
- else if (!strcasecmp(arg, "LogStderr")) {
+ if (!strcasecmp(arg, "LogStderr")) {
dc->log_stderr = 1;
}
else if (!strcasecmp(arg, "NoLogStderr")) {
dc->log_stderr = 0;
}
+ else if (!strcasecmp(arg, "Onfail=remove")) {
+ dc->onfail = 1;
+ }
+ else if (!strcasecmp(arg, "Onfail=abort")) {
+ dc->onfail = 0;
+ }
else {
- return apr_pstrcat(cmd->temp_pool,
+ return apr_pstrcat(cmd->temp_pool,
"Invalid ExtFilterOptions option: ",
arg,
NULL);
return "Invalid cmd= parameter";
}
filter->command = filter->args[0];
-
+
return NULL;
}
&ext_filter_module);
const char *token;
const char *name;
+ char *normalized_name;
ef_filter_t *filter;
name = ap_getword_white(cmd->pool, &args);
return "Filter name not found";
}
- if (apr_hash_get(conf->h, name, APR_HASH_KEY_STRING)) {
+ /* During request processing, we find information about the filter
+ * by looking up the filter name provided by core server in our
+ * hash table. But the core server has normalized the filter
+ * name by converting it to lower case. Thus, when adding the
+ * filter to our hash table we have to use lower case as well.
+ */
+ normalized_name = apr_pstrdup(cmd->pool, name);
+ ap_str_tolower(normalized_name);
+
+ if (apr_hash_get(conf->h, normalized_name, APR_HASH_KEY_STRING)) {
return apr_psprintf(cmd->pool, "ExtFilter %s is already defined",
name);
}
filter->name = name;
filter->mode = OUTPUT_FILTER;
filter->ftype = AP_FTYPE_RESOURCE;
- apr_hash_set(conf->h, name, APR_HASH_KEY_STRING, filter);
+ apr_hash_set(conf->h, normalized_name, APR_HASH_KEY_STRING, filter);
while (*args) {
while (apr_isspace(*args)) {
filter->preserves_content_length = 1;
}
else {
- return apr_psprintf(cmd->pool,
+ return apr_psprintf(cmd->pool,
"mangled argument `%s'",
token);
}
filter->enable_env = token;
continue;
}
-
+
if (!strncasecmp(args, "disableenv=", 11)) {
args += 11;
token = ap_getword_white(cmd->pool, &args);
filter->disable_env = token;
continue;
}
-
+
if (!strncasecmp(args, "intype=", 7)) {
args += 7;
filter->intype = ap_getword_white(cmd->pool, &args);
args);
}
- /* parsing is done... register the filter
+ /* parsing is done... register the filter
*/
if (filter->mode == OUTPUT_FILTER) {
/* XXX need a way to ensure uniqueness among all filters */
add_options,
NULL,
ACCESS_CONF, /* same as SetInputFilter/SetOutputFilter */
- "valid options: DebugLevel=n, LogStderr, NoLogStderr"),
+ "valid options: LogStderr, NoLogStderr"),
AP_INIT_RAW_ARGS("ExtFilterDefine",
define_filter,
NULL,
ap_hook_post_config(ef_init, NULL, NULL, APR_HOOK_MIDDLE);
}
-static apr_status_t set_resource_limits(request_rec *r,
+static apr_status_t set_resource_limits(request_rec *r,
apr_procattr_t *procattr)
{
#if defined(RLIMIT_CPU) || defined(RLIMIT_NPROC) || \
defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined (RLIMIT_AS)
- core_dir_config *conf =
- (core_dir_config *)ap_get_module_config(r->per_dir_config,
- &core_module);
+ core_dir_config *conf =
+ (core_dir_config *)ap_get_core_module_config(r->per_dir_config);
apr_status_t rv;
#ifdef RLIMIT_CPU
apr_file_printf(stderr_log,
"[%s] [client %s] mod_ext_filter (%d)%s: %s\n",
time_str,
- r->connection->remote_ip,
+ r->useragent_ip,
err,
apr_strerror(err, errbuf, sizeof(errbuf)),
description);
rc = apr_procattr_child_errfn_set(ctx->procattr, child_errfn);
ap_assert(rc == APR_SUCCESS);
apr_pool_userdata_set(f->r, ERRFN_USERDATA_KEY, apr_pool_cleanup_null, ctx->p);
-
- if (dc->debug >= DBGLVL_ERRORCHECK) {
- rc = apr_procattr_error_check_set(ctx->procattr, 1);
- ap_assert(rc == APR_SUCCESS);
+
+ rc = apr_procattr_error_check_set(ctx->procattr, 1);
+ if (rc != APR_SUCCESS) {
+ return rc;
}
-
+
/* add standard CGI variables as well as DOCUMENT_URI, DOCUMENT_PATH_INFO,
* and QUERY_STRING_UNESCAPED
*/
env = (const char * const *) ap_create_environment(ctx->p,
f->r->subprocess_env);
- rc = apr_proc_create(ctx->proc,
- ctx->filter->command,
- (const char * const *)ctx->filter->args,
+ rc = apr_proc_create(ctx->proc,
+ ctx->filter->command,
+ (const char * const *)ctx->filter->args,
env, /* environment */
- ctx->procattr,
+ ctx->procattr,
ctx->p);
if (rc != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, f->r,
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, f->r, APLOGNO(01458)
"couldn't create child process to run `%s'",
ctx->filter->command);
return rc;
* be open.
*/
- apr_pool_cleanup_register(ctx->p, ctx->proc->in,
+ apr_pool_cleanup_register(ctx->p, ctx->proc->in,
apr_pool_cleanup_null, /* other mechanism */
ef_close_file);
#if APR_FILES_AS_SOCKETS
{
- apr_socket_t *newsock;
+ apr_pollfd_t pfd = { 0 };
- rc = apr_poll_setup(&ctx->pollset, 2, ctx->p);
- ap_assert(rc == APR_SUCCESS);
- rc = apr_socket_from_file(&newsock, ctx->proc->in);
+ rc = apr_pollset_create(&ctx->pollset, 2, ctx->p, 0);
ap_assert(rc == APR_SUCCESS);
- rc = apr_poll_socket_add(ctx->pollset, newsock, APR_POLLOUT);
- ap_assert(rc == APR_SUCCESS);
- rc = apr_socket_from_file(&newsock, ctx->proc->out);
+
+ pfd.p = ctx->p;
+ pfd.desc_type = APR_POLL_FILE;
+ pfd.reqevents = APR_POLLOUT;
+ pfd.desc.f = ctx->proc->in;
+ rc = apr_pollset_add(ctx->pollset, &pfd);
ap_assert(rc == APR_SUCCESS);
- rc = apr_poll_socket_add(ctx->pollset, newsock, APR_POLLIN);
+
+ pfd.reqevents = APR_POLLIN;
+ pfd.desc.f = ctx->proc->out;
+ rc = apr_pollset_add(ctx->pollset, &pfd);
ap_assert(rc == APR_SUCCESS);
}
#endif
static const char *get_cfg_string(ef_dir_t *dc, ef_filter_t *filter, apr_pool_t *p)
{
- const char *debug_str = dc->debug == -1 ?
- "DebugLevel=0" : apr_psprintf(p, "DebugLevel=%d", dc->debug);
const char *log_stderr_str = dc->log_stderr < 1 ?
"NoLogStderr" : "LogStderr";
const char *preserve_content_length_str = filter->preserves_content_length ?
"*/*" : filter->intype;
const char *outtype_str = !filter->outtype ?
"(unchanged)" : filter->outtype;
-
+
return apr_psprintf(p,
- "ExtFilterOptions %s %s %s ExtFilterInType %s "
+ "ExtFilterOptions %s %s ExtFilterInType %s "
"ExtFilterOuttype %s",
- debug_str, log_stderr_str, preserve_content_length_str,
+ log_stderr_str, preserve_content_length_str,
intype_str, outtype_str);
}
/* look for the user-defined filter */
ctx->filter = find_filter_def(f->r->server, f->frec->name);
if (!ctx->filter) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r,
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, f->r, APLOGNO(01459)
"couldn't find definition of filter '%s'",
f->frec->name);
return APR_EINVAL;
/* wrong IMT for us; don't mess with the output */
ctx->noop = 1;
}
- }
+ }
else {
ctx->noop = 1;
}
ap_set_content_type(f->r, ctx->filter->outtype);
}
if (ctx->filter->preserves_content_length != 1) {
- /* nasty, but needed to avoid confusing the browser
+ /* nasty, but needed to avoid confusing the browser
*/
apr_table_unset(f->r->headers_out, "Content-Length");
}
}
- if (dc->debug >= DBGLVL_SHOWOPTIONS) {
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, f->r,
+ if (APLOGrtrace1(f->r)) {
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE1, 0, f->r,
"%sfiltering `%s' of type `%s' through `%s', cfg %s",
ctx->noop ? "NOT " : "",
f->r->uri ? f->r->uri : f->r->filename,
return APR_SUCCESS;
}
-/* drain_available_output():
+/* drain_available_output():
*
* if any data is available from the filter, read it and append it
* to the the bucket brigade
request_rec *r = f->r;
conn_rec *c = r->connection;
ef_ctx_t *ctx = f->ctx;
- ef_dir_t *dc = ctx->dc;
apr_size_t len;
char buf[4096];
apr_status_t rv;
apr_bucket *b;
while (1) {
+ int lvl = APLOG_TRACE5;
len = sizeof(buf);
- rv = apr_file_read(ctx->proc->out,
- buf,
- &len);
- if ((rv && !APR_STATUS_IS_EAGAIN(rv)) ||
- dc->debug >= DBGLVL_GORY) {
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r,
- "apr_file_read(child output), len %" APR_SIZE_T_FMT,
- !rv ? len : -1);
- }
+ rv = apr_file_read(ctx->proc->out, buf, &len);
+ if (rv && !APR_STATUS_IS_EAGAIN(rv))
+ lvl = APLOG_DEBUG;
+ ap_log_rerror(APLOG_MARK, lvl, rv, r, APLOGNO(01460)
+ "apr_file_read(child output), len %" APR_SIZE_T_FMT,
+ !rv ? len : -1);
if (rv != APR_SUCCESS) {
return rv;
}
return APR_SUCCESS;
}
/* we should never get here; if we do, a bogus error message would be
- * the least of our problems
+ * the least of our problems
*/
return APR_ANONYMOUS;
}
-static apr_status_t pass_data_to_filter(ap_filter_t *f, const char *data,
+static apr_status_t pass_data_to_filter(ap_filter_t *f, const char *data,
apr_size_t len, apr_bucket_brigade *bb)
{
ef_ctx_t *ctx = f->ctx;
- ef_dir_t *dc = ctx->dc;
apr_status_t rv;
apr_size_t bytes_written = 0;
apr_size_t tmplen;
-
+
do {
tmplen = len - bytes_written;
rv = apr_file_write(ctx->proc->in,
&tmplen);
bytes_written += tmplen;
if (rv != APR_SUCCESS && !APR_STATUS_IS_EAGAIN(rv)) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r,
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r, APLOGNO(01461)
"apr_file_write(child input), len %" APR_SIZE_T_FMT,
tmplen);
return rv;
}
if (APR_STATUS_IS_EAGAIN(rv)) {
- /* XXX handle blocking conditions here... if we block, we need
+ /* XXX handle blocking conditions here... if we block, we need
* to read data from the child process and pass it down to the
* next filter!
*/
if (APR_STATUS_IS_EAGAIN(rv)) {
#if APR_FILES_AS_SOCKETS
int num_events;
-
- rv = apr_poll(ctx->pollset, 2,
- &num_events, f->r->server->timeout);
- if (rv || dc->debug >= DBGLVL_GORY) {
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG,
- rv, f->r, "apr_poll()");
- }
- if (rv != APR_SUCCESS && !APR_STATUS_IS_EINTR(rv)) {
+ const apr_pollfd_t *pdesc;
+
+ rv = apr_pollset_poll(ctx->pollset, f->r->server->timeout,
+ &num_events, &pdesc);
+ if (rv != APR_SUCCESS && !APR_STATUS_IS_EINTR(rv)) {
+ ap_log_rerror(APLOG_MARK, APLOG_WARNING, rv, f->r, APLOGNO(01462)
+ "apr_pollset_poll()");
/* some error such as APR_TIMEUP */
return rv;
}
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE6, rv, f->r,
+ "apr_pollset_poll()");
#else /* APR_FILES_AS_SOCKETS */
/* Yuck... I'd really like to wait until I can read
- * or write, but instead I have to sleep and try again
+ * or write, but instead I have to sleep and try again
*/
apr_sleep(100000); /* 100 milliseconds */
- if (dc->debug >= DBGLVL_GORY) {
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG,
- 0, f->r, "apr_sleep()");
- }
+ ap_log_rerror(APLOG_MARK, APLOG_TRACE6, 0, f->r, "apr_sleep()");
#endif /* APR_FILES_AS_SOCKETS */
}
else if (rv != APR_SUCCESS) {
return rv;
}
-/* ef_unified_filter:
+/* ef_unified_filter:
*
- * runs the bucket brigade bb through the filter and puts the result into
+ * runs the bucket brigade bb through the filter and puts the result into
* bb, dropping the previous content of bb (the input)
*/
conn_rec *c = r->connection;
ef_ctx_t *ctx = f->ctx;
apr_bucket *b;
- ef_dir_t *dc;
apr_size_t len;
const char *data;
apr_status_t rv;
apr_bucket *eos = NULL;
apr_bucket_brigade *bb_tmp;
- dc = ctx->dc;
bb_tmp = apr_brigade_create(r->pool, c->bucket_alloc);
for (b = APR_BRIGADE_FIRST(bb);
rv = apr_bucket_read(b, &data, &len, APR_BLOCK_READ);
if (rv != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, "apr_bucket_read()");
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01463) "apr_bucket_read()");
return rv;
}
apr_brigade_cleanup(bb);
APR_BRIGADE_CONCAT(bb, bb_tmp);
apr_brigade_destroy(bb_tmp);
-
+
if (eos) {
/* close the child's stdin to signal that no more data is coming;
* that will cause the child to finish generating output
*/
if ((rv = apr_file_close(ctx->proc->in)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01464)
"apr_file_close(child input)");
return rv;
}
- /* since we've seen eos and closed the child's stdin, set the proper pipe
- * timeout; we don't care if we don't return from apr_file_read() for a while...
+ /* since we've seen eos and closed the child's stdin, set the proper pipe
+ * timeout; we don't care if we don't return from apr_file_read() for a while...
*/
- rv = apr_file_pipe_timeout_set(ctx->proc->out,
+ rv = apr_file_pipe_timeout_set(ctx->proc->out,
r->server->timeout);
if (rv) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01465)
"apr_file_pipe_timeout_set(child output)");
return rv;
}
}
do {
+ int lvl = APLOG_TRACE6;
len = sizeof(buf);
- rv = apr_file_read(ctx->proc->out,
- buf,
- &len);
- if ((rv && !APR_STATUS_IS_EOF(rv) && !APR_STATUS_IS_EAGAIN(rv)) ||
- dc->debug >= DBGLVL_GORY) {
- ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r,
- "apr_file_read(child output), len %" APR_SIZE_T_FMT,
- !rv ? len : -1);
- }
+ rv = apr_file_read(ctx->proc->out, buf, &len);
+ if (rv && !APR_STATUS_IS_EOF(rv) && !APR_STATUS_IS_EAGAIN(rv))
+ lvl = APLOG_ERR;
+ ap_log_rerror(APLOG_MARK, lvl, rv, r, APLOGNO(01466)
+ "apr_file_read(child output), len %" APR_SIZE_T_FMT,
+ !rv ? len : -1);
if (APR_STATUS_IS_EAGAIN(rv)) {
if (eos) {
/* should not occur, because we have an APR timeout in place */
}
return APR_SUCCESS;
}
-
+
if (rv == APR_SUCCESS) {
b = apr_bucket_heap_create(buf, len, NULL, c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, b);
if (!ctx) {
if ((rv = init_filter_instance(f)) != APR_SUCCESS) {
- return rv;
+ ctx = f->ctx;
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01467)
+ "can't initialise output filter %s: %s",
+ f->frec->name,
+ (ctx->dc->onfail == 1) ? "removing" : "aborting");
+ ap_remove_output_filter(f);
+ if (ctx->dc->onfail == 1) {
+ return ap_pass_brigade(f->next, bb);
+ }
+ else {
+ apr_bucket *e;
+ f->r->status_line = "500 Internal Server Error";
+
+ apr_brigade_cleanup(bb);
+ e = ap_bucket_error_create(HTTP_INTERNAL_SERVER_ERROR,
+ NULL, r->pool,
+ f->c->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(bb, e);
+ e = apr_bucket_eos_create(f->c->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(bb, e);
+ ap_pass_brigade(f->next, bb);
+ return AP_FILTER_ERROR;
+ }
}
ctx = f->ctx;
}
}
rv = ef_unified_filter(f, bb);
- if (rv != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+ if (rv != APR_SUCCESS) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(01468)
"ef_unified_filter() failed");
}
if ((rv = ap_pass_brigade(f->next, bb)) != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r, APLOGNO(01469)
"ap_pass_brigade() failed");
}
return rv;
}
-static int ef_input_filter(ap_filter_t *f, apr_bucket_brigade *bb,
+static int ef_input_filter(ap_filter_t *f, apr_bucket_brigade *bb,
ap_input_mode_t mode, apr_read_type_e block,
apr_off_t readbytes)
{
if (!ctx) {
if ((rv = init_filter_instance(f)) != APR_SUCCESS) {
- return rv;
+ ctx = f->ctx;
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, f->r, APLOGNO(01470)
+ "can't initialise input filter %s: %s",
+ f->frec->name,
+ (ctx->dc->onfail == 1) ? "removing" : "aborting");
+ ap_remove_input_filter(f);
+ if (ctx->dc->onfail == 1) {
+ return ap_get_brigade(f->next, bb, mode, block, readbytes);
+ }
+ else {
+ f->r->status = HTTP_INTERNAL_SERVER_ERROR;
+ return HTTP_INTERNAL_SERVER_ERROR;
+ }
}
ctx = f->ctx;
}
return rv;
}
-module AP_MODULE_DECLARE_DATA ext_filter_module =
+AP_DECLARE_MODULE(ext_filter) =
{
STANDARD20_MODULE_STUFF,
create_ef_dir_conf,