]> granicus.if.org Git - apache/blob - modules/apreq/handle.c
Add lots of unique tags to error log messages
[apache] / modules / apreq / handle.c
1 /*
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
8 **
9 **      http://www.apache.org/licenses/LICENSE-2.0
10 **
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.
16 */
17
18 #include "httpd.h"
19 #include "http_config.h"
20 #include "http_log.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"
26
27 #include "apreq_module_apache2.h"
28 #include "apreq_private_apache2.h"
29 #include "apreq_error.h"
30
31
32 APR_INLINE
33 static ap_filter_t *get_apreq_filter(apreq_handle_t *handle)
34 {
35     struct apache2_handle *req = (struct apache2_handle *)handle;
36
37     if (req->f == NULL) {
38         req->f = ap_add_input_filter(APREQ_FILTER_NAME, NULL,
39                                      req->r,
40                                      req->r->connection);
41         /* ap_add_input_filter does not guarantee cfg->f == r->input_filters,
42          * so we reposition the new filter there as necessary.
43          */
44         apreq_filter_relocate(req->f);
45     }
46
47     return req->f;
48 }
49
50
51 static apr_status_t apache2_jar(apreq_handle_t *handle, const apr_table_t **t)
52 {
53     struct apache2_handle *req = (struct apache2_handle*)handle;
54     request_rec *r = req->r;
55
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);
60             req->jar_status =
61                 apreq_parse_cookie_header(handle->pool, req->jar, cookies);
62         }
63         else
64             req->jar_status = APREQ_ERROR_NODATA;
65     }
66
67     *t = req->jar;
68     return req->jar_status;
69 }
70
71 static apr_status_t apache2_args(apreq_handle_t *handle, const apr_table_t **t)
72 {
73     struct apache2_handle *req = (struct apache2_handle*)handle;
74     request_rec *r = req->r;
75
76     if (req->args_status == APR_EINIT) {
77         if (r->args != NULL) {
78             req->args = apr_table_make(handle->pool, APREQ_DEFAULT_NELTS);
79             req->args_status =
80                 apreq_parse_query_string(handle->pool, req->args, r->args);
81         }
82         else
83             req->args_status = APREQ_ERROR_NODATA;
84     }
85
86     *t = req->args;
87     return req->args_status;
88 }
89
90
91
92
93 static apreq_cookie_t *apache2_jar_get(apreq_handle_t *handle, const char *name)
94 {
95     struct apache2_handle *req = (struct apache2_handle *)handle;
96     const apr_table_t *t;
97     const char *val;
98
99     if (req->jar_status == APR_EINIT)
100         apache2_jar(handle, &t);
101     else
102         t = req->jar;
103
104     if (t == NULL)
105         return NULL;
106
107     val = apr_table_get(t, name);
108     if (val == NULL)
109         return NULL;
110
111     return apreq_value_to_cookie(val);
112 }
113
114 static apreq_param_t *apache2_args_get(apreq_handle_t *handle, const char *name)
115 {
116     struct apache2_handle *req = (struct apache2_handle *)handle;
117     const apr_table_t *t;
118     const char *val;
119
120     if (req->args_status == APR_EINIT)
121         apache2_args(handle, &t);
122     else
123         t = req->args;
124
125     if (t == NULL)
126         return NULL;
127
128     val = apr_table_get(t, name);
129     if (val == NULL)
130         return NULL;
131
132     return apreq_value_to_param(val);
133 }
134
135
136 static apr_status_t apache2_body(apreq_handle_t *handle, const apr_table_t **t)
137 {
138     ap_filter_t *f = get_apreq_filter(handle);
139     struct filter_ctx *ctx;
140
141     if (f->ctx == NULL)
142         apreq_filter_make_context(f);
143
144     ctx = f->ctx;
145
146     switch (ctx->body_status) {
147
148     case APR_EINIT:
149         apreq_filter_init_context(f);
150         if (ctx->body_status != APR_INCOMPLETE)
151             break;
152
153     case APR_INCOMPLETE:
154         while (apreq_filter_prefetch(f, APREQ_DEFAULT_READ_BLOCK_SIZE) == APR_INCOMPLETE)
155             ;   /*loop*/
156     }
157
158     *t = ctx->body;
159     return ctx->body_status;
160 }
161
162 static apreq_param_t *apache2_body_get(apreq_handle_t *handle, const char *name)
163 {
164     ap_filter_t *f = get_apreq_filter(handle);
165     struct filter_ctx *ctx;
166     const char *val;
167     apreq_hook_t *h;
168     apreq_hook_find_param_ctx_t *hook_ctx;
169
170     if (f->ctx == NULL)
171         apreq_filter_make_context(f);
172
173     ctx = f->ctx;
174
175     switch (ctx->body_status) {
176
177     case APR_SUCCESS:
178
179         val = apr_table_get(ctx->body, name);
180         if (val != NULL)
181             return apreq_value_to_param(val);
182         return NULL;
183
184
185     case APR_EINIT:
186
187         apreq_filter_init_context(f);
188         if (ctx->body_status != APR_INCOMPLETE)
189             return NULL;
190         apreq_filter_prefetch(f, APREQ_DEFAULT_READ_BLOCK_SIZE);
191
192
193     case APR_INCOMPLETE:
194
195         val = apr_table_get(ctx->body, name);
196         if (val != NULL)
197             return apreq_value_to_param(val);
198
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);
202
203         if (ctx->find_param == NULL)
204             ctx->find_param = apreq_hook_make(handle->pool,
205                                               apreq_hook_find_param,
206                                               NULL, NULL);
207         h = ctx->find_param;
208         h->next = ctx->parser->hook;
209         h->ctx = hook_ctx;
210         ctx->parser->hook = h;
211         h->ctx = hook_ctx;
212         hook_ctx->name = name;
213         hook_ctx->param = NULL;
214         hook_ctx->prev = ctx->parser->hook;
215
216         do {
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);
221
222         ctx->parser->hook = h->next;
223         return NULL;
224
225
226     default:
227
228         if (ctx->body == NULL)
229             return NULL;
230
231         val = apr_table_get(ctx->body, name);
232         if (val != NULL)
233             return apreq_value_to_param(val);
234         return NULL;
235
236     }
237
238     /* not reached */
239     return NULL;
240 }
241
242 static
243 apr_status_t apache2_parser_get(apreq_handle_t *handle,
244                                   const apreq_parser_t **parser)
245 {
246     ap_filter_t *f = get_apreq_filter(handle);
247     struct filter_ctx *ctx = f->ctx;
248
249     if (ctx == NULL) {
250         *parser = NULL;
251         return APR_EINIT;
252     }
253     *parser = ctx->parser;
254     return APR_SUCCESS;
255 }
256
257 static
258 apr_status_t apache2_parser_set(apreq_handle_t *handle,
259                                 apreq_parser_t *parser)
260 {
261     ap_filter_t *f = get_apreq_filter(handle);
262     struct filter_ctx *ctx;
263
264     if (f->ctx == NULL)
265         apreq_filter_make_context(f);
266
267     ctx = f->ctx;
268
269     if (ctx->parser == NULL) {
270         ctx->parser = parser;
271         return APR_SUCCESS;
272     }
273     else
274         return APREQ_ERROR_NOTEMPTY;
275 }
276
277
278
279 static
280 apr_status_t apache2_hook_add(apreq_handle_t *handle,
281                               apreq_hook_t *hook)
282 {
283     ap_filter_t *f = get_apreq_filter(handle);
284     struct filter_ctx *ctx;
285
286     if (f->ctx == NULL)
287         apreq_filter_make_context(f);
288
289     ctx = f->ctx;
290
291     if (ctx->parser != NULL) {
292         return apreq_parser_add_hook(ctx->parser, hook);
293     }
294     else if (ctx->hook_queue != NULL) {
295         apreq_hook_t *h = ctx->hook_queue;
296         while (h->next != NULL)
297             h = h->next;
298         h->next = hook;
299     }
300     else {
301         ctx->hook_queue = hook;
302     }
303     return APR_SUCCESS;
304
305 }
306
307 static
308 apr_status_t apache2_brigade_limit_set(apreq_handle_t *handle,
309                                        apr_size_t bytes)
310 {
311     ap_filter_t *f = get_apreq_filter(handle);
312     struct filter_ctx *ctx;
313
314     if (f->ctx == NULL)
315         apreq_filter_make_context(f);
316
317     ctx = f->ctx;
318
319     if (ctx->body_status == APR_EINIT || ctx->brigade_limit > bytes) {
320         ctx->brigade_limit = bytes;
321         return APR_SUCCESS;
322     }
323
324     return APREQ_ERROR_MISMATCH;
325 }
326
327 static
328 apr_status_t apache2_brigade_limit_get(apreq_handle_t *handle,
329                                        apr_size_t *bytes)
330 {
331     ap_filter_t *f = get_apreq_filter(handle);
332     struct filter_ctx *ctx;
333
334     if (f->ctx == NULL)
335         apreq_filter_make_context(f);
336
337     ctx = f->ctx;
338     *bytes = ctx->brigade_limit;
339     return APR_SUCCESS;
340 }
341
342 static
343 apr_status_t apache2_read_limit_set(apreq_handle_t *handle,
344                                     apr_uint64_t bytes)
345 {
346     ap_filter_t *f = get_apreq_filter(handle);
347     struct filter_ctx *ctx;
348
349     if (f->ctx == NULL)
350         apreq_filter_make_context(f);
351
352     ctx = f->ctx;
353
354     if (ctx->read_limit > bytes && ctx->bytes_read < bytes) {
355         ctx->read_limit = bytes;
356         return APR_SUCCESS;
357     }
358
359     return APREQ_ERROR_MISMATCH;
360 }
361
362 static
363 apr_status_t apache2_read_limit_get(apreq_handle_t *handle,
364                                     apr_uint64_t *bytes)
365 {
366     ap_filter_t *f = get_apreq_filter(handle);
367     struct filter_ctx *ctx;
368
369     if (f->ctx == NULL)
370         apreq_filter_make_context(f);
371
372     ctx = f->ctx;
373     *bytes = ctx->read_limit;
374     return APR_SUCCESS;
375 }
376
377 static
378 apr_status_t apache2_temp_dir_set(apreq_handle_t *handle,
379                                   const char *path)
380 {
381     ap_filter_t *f = get_apreq_filter(handle);
382     struct filter_ctx *ctx;
383
384     if (f->ctx == NULL)
385         apreq_filter_make_context(f);
386
387     ctx = f->ctx;
388     /* init vs incomplete state? */
389     if (ctx->temp_dir == NULL && ctx->bytes_read == 0) {
390         if (path != NULL)
391             ctx->temp_dir = apr_pstrdup(handle->pool, path);
392         return APR_SUCCESS;
393     }
394
395     return APREQ_ERROR_NOTEMPTY;
396 }
397
398 static
399 apr_status_t apache2_temp_dir_get(apreq_handle_t *handle,
400                                   const char **path)
401 {
402     ap_filter_t *f = get_apreq_filter(handle);
403     struct filter_ctx *ctx;
404
405     if (f->ctx == NULL)
406         apreq_filter_make_context(f);
407
408     ctx = f->ctx;
409     *path = ctx->parser ? ctx->parser->temp_dir : ctx->temp_dir;
410     return APR_SUCCESS;
411 }
412
413 static APREQ_MODULE(apache2, APREQ_APACHE2_MMN);
414
415 APREQ_DECLARE(apreq_handle_t *) apreq_handle_apache2(request_rec *r)
416 {
417     struct apache2_handle *req =
418         ap_get_module_config(r->request_config, &apreq_module);
419
420     if (req != NULL) {
421         get_apreq_filter(&req->handle);
422         return &req->handle;
423     }
424
425     req = apr_palloc(r->pool, sizeof *req);
426     ap_set_module_config(r->request_config, &apreq_module, req);
427
428     req->handle.module = &apache2_module;
429     req->handle.pool = r->pool;
430     req->handle.bucket_alloc = r->connection->bucket_alloc;
431     req->r = r;
432
433     req->args_status = req->jar_status = APR_EINIT;
434     req->args = req->jar = NULL;
435
436     req->f = NULL;
437
438     get_apreq_filter(&req->handle);
439     return &req->handle;
440
441 }