diff --git a/include/http_core.h b/include/http_core.h index 73274f4e76..c71748602f 100644 --- a/include/http_core.h +++ b/include/http_core.h @@ -423,6 +423,7 @@ typedef struct { #endif apr_array_header_t *filters; + apr_array_header_t *input_filters; } core_dir_config; /* Per-server core configuration */ diff --git a/include/httpd.h b/include/httpd.h index 4cebd4dc8e..ad5cbe9117 100644 --- a/include/httpd.h +++ b/include/httpd.h @@ -806,8 +806,11 @@ struct request_rec { #endif /*APACHE_XLATE*/ /** A list of output filters to be used for this request - * @defvar ap_filter_t *filters */ + * @defvar ap_filter_t *output_filters */ struct ap_filter_t *output_filters; + /** A list of input filters to be used for this request + * @defvar ap_filter_t *filters */ + struct ap_filter_t *input_filters; /** A flag to determine if the eos bucket has been sent yet * @defvar int eos_sent */ int eos_sent; diff --git a/include/util_filter.h b/include/util_filter.h index ea0e447e33..4deb67cad3 100644 --- a/include/util_filter.h +++ b/include/util_filter.h @@ -320,10 +320,11 @@ API_EXPORT(void) ap_register_output_filter(const char *name, * Add a filter to the current connection. Filters are added in a FIFO manner. * The first filter added will be the first filter called. * @param name The name of the filter to add + * @param r The request to add this filter for (or NULL if it isn't associated with a request) * @param c The connection to add the fillter for - * @deffunc void ap_add_input_filter(const char *name, void *ctx, conn_rec *r) + * @deffunc void ap_add_input_filter(const char *name, void *ctx, request_rec *r, conn_rec *c) */ -API_EXPORT(void) ap_add_input_filter(const char *name, void *ctx, conn_rec *r); +API_EXPORT(void) ap_add_input_filter(const char *name, void *ctx, request_rec *r, conn_rec *c); /** * Add a filter to the current request. Filters are added in a FIFO manner. diff --git a/modules/http/http_core.c b/modules/http/http_core.c index 9fe6a97c68..dc1bf2ddd1 100644 --- a/modules/http/http_core.c +++ b/modules/http/http_core.c @@ -187,6 +187,7 @@ static void *create_core_dir_config(apr_pool_t *a, char *dir) conf->add_default_charset_name = DEFAULT_ADD_DEFAULT_CHARSET_NAME; conf->filters = apr_make_array(a, 2, sizeof(void *)); + conf->input_filters = apr_make_array(a, 2, sizeof(void *)); return (void *)conf; } @@ -327,6 +328,8 @@ static void *merge_core_dir_configs(apr_pool_t *a, void *basev, void *newv) } } conf->filters = apr_append_arrays(a, base->filters, new->filters); + conf->input_filters = apr_append_arrays(a, base->input_filters, + new->input_filters); return (void*)conf; } @@ -1884,6 +1887,16 @@ static const char *add_filter(cmd_parms *cmd, void *dummy, const char *arg) return NULL; } +static const char *add_input_filter(cmd_parms *cmd, void *dummy, const char *arg) +{ + core_dir_config *conf = dummy; + char **newfilter; + + newfilter = (char **)apr_push_array(conf->input_filters); + *newfilter = apr_pstrdup(cmd->pool, arg); + return NULL; +} + static const char *add_module_command(cmd_parms *cmd, void *dummy, const char *arg) { @@ -2765,13 +2778,15 @@ AP_INIT_TAKE12("RLimitNPROC", set_limit_nproc, AP_INIT_TAKE12("RLimitNPROC", no_set_limit, NULL, OR_ALL, "soft/hard limits for max number of processes per uid"), #endif -/* XXX This should be allowable in .htaccess files, but currently it won't +/* XXX These should be allowable in .htaccess files, but currently it won't * play well with the Options stuff. Until that is fixed, I would prefer * to leave it just in the conf file. Other should feel free to disagree * with me. Rbb. */ AP_INIT_ITERATE("AddOutputFilter", add_filter, NULL, ACCESS_CONF, "filters to be run"), +AP_INIT_ITERATE("AddInputFilter", add_input_filter, NULL, ACCESS_CONF, + "filters to be run on the request body"), { NULL } }; @@ -3436,6 +3451,12 @@ static void core_register_filter(request_rec *r) char *foobar = items[i]; ap_add_output_filter(foobar, NULL, r, r->connection); } + + items = (char **)conf->input_filters->elts; + for (i = 0; i < conf->input_filters->nelts; i++) { + char *foobar = items[i]; + ap_add_input_filter(foobar, NULL, r, r->connection); + } } static void register_hooks(void) diff --git a/modules/http/http_protocol.c b/modules/http/http_protocol.c index f80f5f4829..2b39f05613 100644 --- a/modules/http/http_protocol.c +++ b/modules/http/http_protocol.c @@ -1249,6 +1249,7 @@ request_rec *ap_read_request(conn_rec *conn) r->status = HTTP_REQUEST_TIME_OUT; /* Until we get a request */ r->the_request = NULL; r->output_filters = conn->output_filters; + r->input_filters = conn->input_filters; #ifdef APACHE_XLATE r->rrx = apr_pcalloc(p, sizeof(struct ap_rr_xlate)); diff --git a/modules/http/http_request.c b/modules/http/http_request.c index c346fe11e0..7b86159165 100644 --- a/modules/http/http_request.c +++ b/modules/http/http_request.c @@ -780,6 +780,7 @@ API_EXPORT(request_rec *) ap_sub_req_method_uri(const char *method, /* start with the same set of output filters */ rnew->output_filters = r->output_filters; + /* no input filters for a subrequest */ ap_set_sub_req_protocol(rnew, r); @@ -875,6 +876,7 @@ API_EXPORT(request_rec *) ap_sub_req_lookup_file(const char *new_file, /* start with the same set of output filters */ rnew->output_filters = r->output_filters; + /* no input filters for a subrequest */ ap_set_sub_req_protocol(rnew, r); fdir = ap_make_dirstr_parent(rnew->pool, r->filename); @@ -1374,6 +1376,7 @@ static request_rec *internal_internal_redirect(const char *new_uri, new->vlist_validator = r->vlist_validator; new->output_filters = r->connection->output_filters; + new->input_filters = r->connection->input_filters; apr_table_setn(new->subprocess_env, "REDIRECT_STATUS", apr_psprintf(r->pool, "%d", r->status)); diff --git a/server/connection.c b/server/connection.c index e4dd226eba..e1b56fed52 100644 --- a/server/connection.c +++ b/server/connection.c @@ -216,7 +216,7 @@ CORE_EXPORT(void) ap_process_connection(conn_rec *c) int ap_pre_http_connection(conn_rec *c) { - ap_add_input_filter("CORE_IN", NULL, c); + ap_add_input_filter("CORE_IN", NULL, NULL, c); ap_add_output_filter("CORE", NULL, NULL, c); return OK; } diff --git a/server/util_filter.c b/server/util_filter.c index 1d26b8e194..14ef6553d0 100644 --- a/server/util_filter.c +++ b/server/util_filter.c @@ -118,25 +118,28 @@ API_EXPORT(void) ap_register_output_filter(const char *name, ®istered_output_filters); } -API_EXPORT(void) ap_add_input_filter(const char *name, void *ctx, conn_rec *c) +API_EXPORT(void) ap_add_input_filter(const char *name, void *ctx, + request_rec *r, conn_rec *c) { ap_filter_rec_t *frec = registered_input_filters; for (; frec != NULL; frec = frec->next) { if (!strcasecmp(name, frec->name)) { - ap_filter_t *f = apr_pcalloc(c->pool, sizeof(*f)); + apr_pool_t *p = r ? r->pool : c->pool; + ap_filter_t *f = apr_pcalloc(p, sizeof(*f)); + ap_filter_t **outf = r ? &r->input_filters : &c->input_filters; f->frec = frec; f->ctx = ctx; - f->r = NULL; + f->r = r; f->c = c; - if (INSERT_BEFORE(f, c->input_filters)) { - f->next = c->input_filters; - c->input_filters = f; + if (INSERT_BEFORE(f, *outf)) { + f->next = *outf; + *outf = f; } else { - ap_filter_t *fscan = c->input_filters; + ap_filter_t *fscan = *outf; while (!INSERT_BEFORE(f, fscan->next)) fscan = fscan->next; f->next = fscan->next;