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.
18 #include "apr_strings.h"
19 #include "apreq_module.h"
20 #include "apreq_error.h"
21 #include "apreq_util.h"
23 #define READ_BYTES (64 * 1024)
25 struct custom_handle {
26 struct apreq_handle_t handle;
28 apr_table_t *jar, *args, *body;
29 apr_status_t jar_status,
33 apreq_parser_t *parser;
35 apr_uint64_t read_limit;
36 apr_uint64_t bytes_read;
37 apr_bucket_brigade *in;
38 apr_bucket_brigade *tmpbb;
42 static apr_status_t custom_parse_brigade(apreq_handle_t *handle, apr_uint64_t bytes)
44 struct custom_handle *req = (struct custom_handle *)handle;
48 if (req->body_status != APR_INCOMPLETE)
49 return req->body_status;
51 switch (s = apr_brigade_partition(req->in, bytes, &e)) {
55 apreq_brigade_move(req->tmpbb, req->in, e);
56 req->bytes_read += bytes;
58 if (req->bytes_read > req->read_limit) {
59 req->body_status = APREQ_ERROR_OVERLIMIT;
64 apreq_parser_run(req->parser, req->body, req->tmpbb);
66 apr_brigade_cleanup(req->tmpbb);
70 apreq_brigade_move(req->tmpbb, req->in, e);
71 s = apr_brigade_length(req->tmpbb, 1, &len);
72 if (s != APR_SUCCESS) {
76 req->bytes_read += len;
78 if (req->bytes_read > req->read_limit) {
79 req->body_status = APREQ_ERROR_OVERLIMIT;
83 apreq_parser_run(req->parser, req->body, req->tmpbb);
85 apr_brigade_cleanup(req->tmpbb);
92 return req->body_status;
97 static apr_status_t custom_jar(apreq_handle_t *handle, const apr_table_t **t)
99 struct custom_handle *req = (struct custom_handle *)handle;
101 return req->jar_status;
104 static apr_status_t custom_args(apreq_handle_t *handle, const apr_table_t **t)
106 struct custom_handle *req = (struct custom_handle*)handle;
108 return req->args_status;
111 static apr_status_t custom_body(apreq_handle_t *handle, const apr_table_t **t)
113 struct custom_handle *req = (struct custom_handle*)handle;
114 while (req->body_status == APR_INCOMPLETE)
115 custom_parse_brigade(handle, READ_BYTES);
117 return req->body_status;
122 static apreq_cookie_t *custom_jar_get(apreq_handle_t *handle, const char *name)
124 struct custom_handle *req = (struct custom_handle*)handle;
127 if (req->jar == NULL || name == NULL)
130 val = apr_table_get(req->jar, name);
135 return apreq_value_to_cookie(val);
138 static apreq_param_t *custom_args_get(apreq_handle_t *handle, const char *name)
140 struct custom_handle *req = (struct custom_handle*)handle;
143 if (req->args == NULL || name == NULL)
146 val = apr_table_get(req->args, name);
151 return apreq_value_to_param(val);
154 static apreq_param_t *custom_body_get(apreq_handle_t *handle, const char *name)
156 struct custom_handle *req = (struct custom_handle*)handle;
159 if (req->body == NULL || name == NULL)
163 *(const char **)&val = apr_table_get(req->body, name);
167 if (req->body_status == APR_INCOMPLETE)
168 custom_parse_brigade(handle, READ_BYTES);
173 return apreq_value_to_param(val);
178 static apr_status_t custom_parser_get(apreq_handle_t *handle,
179 const apreq_parser_t **parser)
181 struct custom_handle *req = (struct custom_handle*)handle;
182 *parser = req->parser;
187 static apr_status_t custom_parser_set(apreq_handle_t *handle,
188 apreq_parser_t *parser)
195 static apr_status_t custom_hook_add(apreq_handle_t *handle,
198 struct custom_handle *req = (struct custom_handle*)handle;
199 apreq_parser_add_hook(req->parser, hook);
203 static apr_status_t custom_brigade_limit_get(apreq_handle_t *handle,
206 struct custom_handle *req = (struct custom_handle*)handle;
207 *bytes = req->parser->brigade_limit;
211 static apr_status_t custom_brigade_limit_set(apreq_handle_t *handle,
219 static apr_status_t custom_read_limit_get(apreq_handle_t *handle,
222 struct custom_handle *req = (struct custom_handle*)handle;
223 *bytes = req->read_limit;
227 static apr_status_t custom_read_limit_set(apreq_handle_t *handle,
235 static apr_status_t custom_temp_dir_get(apreq_handle_t *handle,
238 struct custom_handle *req = (struct custom_handle*)handle;
240 *path = req->parser->temp_dir;
244 static apr_status_t custom_temp_dir_set(apreq_handle_t *handle,
253 static APREQ_MODULE(custom, 20070428);
255 APREQ_DECLARE(apreq_handle_t *)apreq_handle_custom(apr_pool_t *pool,
256 const char *query_string,
258 apreq_parser_t *parser,
259 apr_uint64_t read_limit,
260 apr_bucket_brigade *in)
262 struct custom_handle *req;
263 req = apr_palloc(pool, sizeof(*req));
264 req->handle.module = &custom_module;
265 req->handle.pool = pool;
266 req->handle.bucket_alloc = in->bucket_alloc;
267 req->read_limit = read_limit;
269 req->parser = parser;
270 req->in = apr_brigade_create(pool, in->bucket_alloc);
271 req->tmpbb = apr_brigade_create(pool, in->bucket_alloc);
272 req->body = apr_table_make(pool, APREQ_DEFAULT_NELTS);
273 req->body_status = APR_INCOMPLETE;
274 APR_BRIGADE_CONCAT(req->in, in);
276 if (cookie != NULL) {
277 req->jar = apr_table_make(pool, APREQ_DEFAULT_NELTS);
279 apreq_parse_cookie_header(pool, req->jar, cookie);
283 req->jar_status = APREQ_ERROR_NODATA;
287 if (query_string != NULL) {
288 req->args = apr_table_make(pool, APREQ_DEFAULT_NELTS);
290 apreq_parse_query_string(pool, req->args, query_string);
294 req->args_status = APREQ_ERROR_NODATA;
297 if (!APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(req->in))) {
298 apr_bucket *eos = apr_bucket_eos_create(in->bucket_alloc);
299 APR_BRIGADE_INSERT_TAIL(req->in, eos);