2 ** Licensed to the Apache Software Foundation (ASF) under one or more
3 ** contributor license agreements. See the NOTICE file distributed with
4 ** this work for additional information regarding copyright ownership.
5 ** The ASF licenses this file to You under the Apache License, Version 2.0
6 ** (the "License"); you may not use this file except in compliance with
7 ** the License. You may obtain a copy of the License at
9 ** http://www.apache.org/licenses/LICENSE-2.0
11 ** Unless required by applicable law or agreed to in writing, software
12 ** distributed under the License is distributed on an "AS IS" BASIS,
13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 ** See the License for the specific language governing permissions and
15 ** limitations under the License.
19 #include "http_config.h"
21 #include "util_filter.h"
22 #include "apr_tables.h"
23 #include "apr_buckets.h"
24 #include "http_request.h"
25 #include "apr_strings.h"
27 #include "apreq_module_apache2.h"
28 #include "apreq_private_apache2.h"
29 #include "apreq_error.h"
33 static ap_filter_t *get_apreq_filter(apreq_handle_t *handle)
35 struct apache2_handle *req = (struct apache2_handle *)handle;
38 req->f = ap_add_input_filter(APREQ_FILTER_NAME, NULL,
41 /* ap_add_input_filter does not guarantee cfg->f == r->input_filters,
42 * so we reposition the new filter there as necessary.
44 apreq_filter_relocate(req->f);
51 static apr_status_t apache2_jar(apreq_handle_t *handle, const apr_table_t **t)
53 struct apache2_handle *req = (struct apache2_handle*)handle;
54 request_rec *r = req->r;
56 if (req->jar_status == APR_EINIT) {
57 const char *cookies = apr_table_get(r->headers_in, "Cookie");
58 if (cookies != NULL) {
59 req->jar = apr_table_make(handle->pool, APREQ_DEFAULT_NELTS);
61 apreq_parse_cookie_header(handle->pool, req->jar, cookies);
64 req->jar_status = APREQ_ERROR_NODATA;
68 return req->jar_status;
71 static apr_status_t apache2_args(apreq_handle_t *handle, const apr_table_t **t)
73 struct apache2_handle *req = (struct apache2_handle*)handle;
74 request_rec *r = req->r;
76 if (req->args_status == APR_EINIT) {
77 if (r->args != NULL) {
78 req->args = apr_table_make(handle->pool, APREQ_DEFAULT_NELTS);
80 apreq_parse_query_string(handle->pool, req->args, r->args);
83 req->args_status = APREQ_ERROR_NODATA;
87 return req->args_status;
93 static apreq_cookie_t *apache2_jar_get(apreq_handle_t *handle, const char *name)
95 struct apache2_handle *req = (struct apache2_handle *)handle;
99 if (req->jar_status == APR_EINIT)
100 apache2_jar(handle, &t);
107 val = apr_table_get(t, name);
111 return apreq_value_to_cookie(val);
114 static apreq_param_t *apache2_args_get(apreq_handle_t *handle, const char *name)
116 struct apache2_handle *req = (struct apache2_handle *)handle;
117 const apr_table_t *t;
120 if (req->args_status == APR_EINIT)
121 apache2_args(handle, &t);
128 val = apr_table_get(t, name);
132 return apreq_value_to_param(val);
136 static apr_status_t apache2_body(apreq_handle_t *handle, const apr_table_t **t)
138 ap_filter_t *f = get_apreq_filter(handle);
139 struct filter_ctx *ctx;
142 apreq_filter_make_context(f);
146 switch (ctx->body_status) {
149 apreq_filter_init_context(f);
150 if (ctx->body_status != APR_INCOMPLETE)
154 while (apreq_filter_prefetch(f, APREQ_DEFAULT_READ_BLOCK_SIZE) == APR_INCOMPLETE)
159 return ctx->body_status;
162 static apreq_param_t *apache2_body_get(apreq_handle_t *handle, const char *name)
164 ap_filter_t *f = get_apreq_filter(handle);
165 struct filter_ctx *ctx;
168 apreq_hook_find_param_ctx_t *hook_ctx;
171 apreq_filter_make_context(f);
175 switch (ctx->body_status) {
179 val = apr_table_get(ctx->body, name);
181 return apreq_value_to_param(val);
187 apreq_filter_init_context(f);
188 if (ctx->body_status != APR_INCOMPLETE)
190 apreq_filter_prefetch(f, APREQ_DEFAULT_READ_BLOCK_SIZE);
195 val = apr_table_get(ctx->body, name);
197 return apreq_value_to_param(val);
199 /* Not seen yet, so we need to scan for
200 param while prefetching the body */
201 hook_ctx = apr_palloc(handle->pool, sizeof *hook_ctx);
203 if (ctx->find_param == NULL)
204 ctx->find_param = apreq_hook_make(handle->pool,
205 apreq_hook_find_param,
208 h->next = ctx->parser->hook;
210 ctx->parser->hook = h;
212 hook_ctx->name = name;
213 hook_ctx->param = NULL;
214 hook_ctx->prev = ctx->parser->hook;
217 apreq_filter_prefetch(f, APREQ_DEFAULT_READ_BLOCK_SIZE);
218 if (hook_ctx->param != NULL)
219 return hook_ctx->param;
220 } while (ctx->body_status == APR_INCOMPLETE);
222 ctx->parser->hook = h->next;
228 if (ctx->body == NULL)
231 val = apr_table_get(ctx->body, name);
233 return apreq_value_to_param(val);
243 apr_status_t apache2_parser_get(apreq_handle_t *handle,
244 const apreq_parser_t **parser)
246 ap_filter_t *f = get_apreq_filter(handle);
247 struct filter_ctx *ctx = f->ctx;
253 *parser = ctx->parser;
258 apr_status_t apache2_parser_set(apreq_handle_t *handle,
259 apreq_parser_t *parser)
261 ap_filter_t *f = get_apreq_filter(handle);
262 struct filter_ctx *ctx;
265 apreq_filter_make_context(f);
269 if (ctx->parser == NULL) {
270 ctx->parser = parser;
274 return APREQ_ERROR_NOTEMPTY;
280 apr_status_t apache2_hook_add(apreq_handle_t *handle,
283 ap_filter_t *f = get_apreq_filter(handle);
284 struct filter_ctx *ctx;
287 apreq_filter_make_context(f);
291 if (ctx->parser != NULL) {
292 return apreq_parser_add_hook(ctx->parser, hook);
294 else if (ctx->hook_queue != NULL) {
295 apreq_hook_t *h = ctx->hook_queue;
296 while (h->next != NULL)
301 ctx->hook_queue = hook;
308 apr_status_t apache2_brigade_limit_set(apreq_handle_t *handle,
311 ap_filter_t *f = get_apreq_filter(handle);
312 struct filter_ctx *ctx;
315 apreq_filter_make_context(f);
319 if (ctx->body_status == APR_EINIT || ctx->brigade_limit > bytes) {
320 ctx->brigade_limit = bytes;
324 return APREQ_ERROR_MISMATCH;
328 apr_status_t apache2_brigade_limit_get(apreq_handle_t *handle,
331 ap_filter_t *f = get_apreq_filter(handle);
332 struct filter_ctx *ctx;
335 apreq_filter_make_context(f);
338 *bytes = ctx->brigade_limit;
343 apr_status_t apache2_read_limit_set(apreq_handle_t *handle,
346 ap_filter_t *f = get_apreq_filter(handle);
347 struct filter_ctx *ctx;
350 apreq_filter_make_context(f);
354 if (ctx->read_limit > bytes && ctx->bytes_read < bytes) {
355 ctx->read_limit = bytes;
359 return APREQ_ERROR_MISMATCH;
363 apr_status_t apache2_read_limit_get(apreq_handle_t *handle,
366 ap_filter_t *f = get_apreq_filter(handle);
367 struct filter_ctx *ctx;
370 apreq_filter_make_context(f);
373 *bytes = ctx->read_limit;
378 apr_status_t apache2_temp_dir_set(apreq_handle_t *handle,
381 ap_filter_t *f = get_apreq_filter(handle);
382 struct filter_ctx *ctx;
385 apreq_filter_make_context(f);
388 /* init vs incomplete state? */
389 if (ctx->temp_dir == NULL && ctx->bytes_read == 0) {
391 ctx->temp_dir = apr_pstrdup(handle->pool, path);
395 return APREQ_ERROR_NOTEMPTY;
399 apr_status_t apache2_temp_dir_get(apreq_handle_t *handle,
402 ap_filter_t *f = get_apreq_filter(handle);
403 struct filter_ctx *ctx;
406 apreq_filter_make_context(f);
409 *path = ctx->parser ? ctx->parser->temp_dir : ctx->temp_dir;
413 static APREQ_MODULE(apache2, APREQ_APACHE2_MMN);
415 APREQ_DECLARE(apreq_handle_t *) apreq_handle_apache2(request_rec *r)
417 struct apache2_handle *req =
418 ap_get_module_config(r->request_config, &apreq_module);
421 get_apreq_filter(&req->handle);
425 req = apr_palloc(r->pool, sizeof *req);
426 ap_set_module_config(r->request_config, &apreq_module, req);
428 req->handle.module = &apache2_module;
429 req->handle.pool = r->pool;
430 req->handle.bucket_alloc = r->connection->bucket_alloc;
433 req->args_status = req->jar_status = APR_EINIT;
434 req->args = req->jar = NULL;
438 get_apreq_filter(&req->handle);