summaryrefslogtreecommitdiff
path: root/server/apreq_module_custom.c
diff options
context:
space:
mode:
Diffstat (limited to 'server/apreq_module_custom.c')
-rw-r--r--server/apreq_module_custom.c304
1 files changed, 304 insertions, 0 deletions
diff --git a/server/apreq_module_custom.c b/server/apreq_module_custom.c
new file mode 100644
index 0000000000..e1e6f58bfe
--- /dev/null
+++ b/server/apreq_module_custom.c
@@ -0,0 +1,304 @@
+/*
+** 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
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** 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 "apr_strings.h"
+#include "apreq_module.h"
+#include "apreq_error.h"
+#include "apreq_util.h"
+
+#define READ_BYTES (64 * 1024)
+
+struct custom_handle {
+ struct apreq_handle_t handle;
+
+ apr_table_t *jar, *args, *body;
+ apr_status_t jar_status,
+ args_status,
+ body_status;
+
+ apreq_parser_t *parser;
+
+ apr_uint64_t read_limit;
+ apr_uint64_t bytes_read;
+ apr_bucket_brigade *in;
+ apr_bucket_brigade *tmpbb;
+};
+
+
+static apr_status_t custom_parse_brigade(apreq_handle_t *handle, apr_uint64_t bytes)
+{
+ struct custom_handle *req = (struct custom_handle *)handle;
+ apr_status_t s;
+ apr_bucket *e;
+
+ if (req->body_status != APR_INCOMPLETE)
+ return req->body_status;
+
+ switch (s = apr_brigade_partition(req->in, bytes, &e)) {
+ apr_off_t len;
+
+ case APR_SUCCESS:
+ apreq_brigade_move(req->tmpbb, req->in, e);
+ req->bytes_read += bytes;
+
+ if (req->bytes_read > req->read_limit) {
+ req->body_status = APREQ_ERROR_OVERLIMIT;
+ break;
+ }
+
+ req->body_status =
+ apreq_parser_run(req->parser, req->body, req->tmpbb);
+
+ apr_brigade_cleanup(req->tmpbb);
+ break;
+
+ case APR_INCOMPLETE:
+ apreq_brigade_move(req->tmpbb, req->in, e);
+ s = apr_brigade_length(req->tmpbb, 1, &len);
+ if (s != APR_SUCCESS) {
+ req->body_status = s;
+ break;
+ }
+ req->bytes_read += len;
+
+ if (req->bytes_read > req->read_limit) {
+ req->body_status = APREQ_ERROR_OVERLIMIT;
+ break;
+ }
+ req->body_status =
+ apreq_parser_run(req->parser, req->body, req->tmpbb);
+
+ apr_brigade_cleanup(req->tmpbb);
+ break;
+
+ default:
+ req->body_status = s;
+ }
+
+ return req->body_status;
+}
+
+
+
+static apr_status_t custom_jar(apreq_handle_t *handle, const apr_table_t **t)
+{
+ struct custom_handle *req = (struct custom_handle *)handle;
+ *t = req->jar;
+ return req->jar_status;
+}
+
+static apr_status_t custom_args(apreq_handle_t *handle, const apr_table_t **t)
+{
+ struct custom_handle *req = (struct custom_handle*)handle;
+ *t = req->args;
+ return req->args_status;
+}
+
+static apr_status_t custom_body(apreq_handle_t *handle, const apr_table_t **t)
+{
+ struct custom_handle *req = (struct custom_handle*)handle;
+ while (req->body_status == APR_INCOMPLETE)
+ custom_parse_brigade(handle, READ_BYTES);
+ *t = req->body;
+ return req->body_status;
+}
+
+
+
+static apreq_cookie_t *custom_jar_get(apreq_handle_t *handle, const char *name)
+{
+ struct custom_handle *req = (struct custom_handle*)handle;
+ const char *val;
+
+ if (req->jar == NULL || name == NULL)
+ return NULL;
+
+ val = apr_table_get(req->jar, name);
+
+ if (val == NULL)
+ return NULL;
+
+ return apreq_value_to_cookie(val);
+}
+
+static apreq_param_t *custom_args_get(apreq_handle_t *handle, const char *name)
+{
+ struct custom_handle *req = (struct custom_handle*)handle;
+ const char *val;
+
+ if (req->args == NULL || name == NULL)
+ return NULL;
+
+ val = apr_table_get(req->args, name);
+
+ if (val == NULL)
+ return NULL;
+
+ return apreq_value_to_param(val);
+}
+
+static apreq_param_t *custom_body_get(apreq_handle_t *handle, const char *name)
+{
+ struct custom_handle *req = (struct custom_handle*)handle;
+ const char *val;
+
+ if (req->body == NULL || name == NULL)
+ return NULL;
+
+ while (1) {
+ *(const char **)&val = apr_table_get(req->body, name);
+ if (val != NULL)
+ break;
+
+ if (req->body_status == APR_INCOMPLETE)
+ custom_parse_brigade(handle, READ_BYTES);
+ else
+ return NULL;
+ }
+
+ return apreq_value_to_param(val);
+}
+
+
+
+static apr_status_t custom_parser_get(apreq_handle_t *handle,
+ const apreq_parser_t **parser)
+{
+ struct custom_handle *req = (struct custom_handle*)handle;
+ *parser = req->parser;
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t custom_parser_set(apreq_handle_t *handle,
+ apreq_parser_t *parser)
+{
+ (void)handle;
+ (void)parser;
+ return APR_ENOTIMPL;
+}
+
+static apr_status_t custom_hook_add(apreq_handle_t *handle,
+ apreq_hook_t *hook)
+{
+ struct custom_handle *req = (struct custom_handle*)handle;
+ apreq_parser_add_hook(req->parser, hook);
+ return APR_SUCCESS;
+}
+
+static apr_status_t custom_brigade_limit_get(apreq_handle_t *handle,
+ apr_size_t *bytes)
+{
+ struct custom_handle *req = (struct custom_handle*)handle;
+ *bytes = req->parser->brigade_limit;
+ return APR_SUCCESS;
+}
+
+static apr_status_t custom_brigade_limit_set(apreq_handle_t *handle,
+ apr_size_t bytes)
+{
+ (void)handle;
+ (void)bytes;
+ return APR_ENOTIMPL;
+}
+
+static apr_status_t custom_read_limit_get(apreq_handle_t *handle,
+ apr_uint64_t *bytes)
+{
+ struct custom_handle *req = (struct custom_handle*)handle;
+ *bytes = req->read_limit;
+ return APR_SUCCESS;
+}
+
+static apr_status_t custom_read_limit_set(apreq_handle_t *handle,
+ apr_uint64_t bytes)
+{
+ (void)handle;
+ (void)bytes;
+ return APR_ENOTIMPL;
+}
+
+static apr_status_t custom_temp_dir_get(apreq_handle_t *handle,
+ const char **path)
+{
+ struct custom_handle *req = (struct custom_handle*)handle;
+
+ *path = req->parser->temp_dir;
+ return APR_SUCCESS;
+}
+
+static apr_status_t custom_temp_dir_set(apreq_handle_t *handle,
+ const char *path)
+{
+ (void)handle;
+ (void)path;
+ return APR_ENOTIMPL;
+}
+
+
+static APREQ_MODULE(custom, 20070428);
+
+APREQ_DECLARE(apreq_handle_t *)apreq_handle_custom(apr_pool_t *pool,
+ const char *query_string,
+ const char *cookie,
+ apreq_parser_t *parser,
+ apr_uint64_t read_limit,
+ apr_bucket_brigade *in)
+{
+ struct custom_handle *req;
+ req = apr_palloc(pool, sizeof(*req));
+ req->handle.module = &custom_module;
+ req->handle.pool = pool;
+ req->handle.bucket_alloc = in->bucket_alloc;
+ req->read_limit = read_limit;
+ req->bytes_read = 0;
+ req->parser = parser;
+ req->in = apr_brigade_create(pool, in->bucket_alloc);
+ req->tmpbb = apr_brigade_create(pool, in->bucket_alloc);
+ req->body = apr_table_make(pool, APREQ_DEFAULT_NELTS);
+ req->body_status = APR_INCOMPLETE;
+ APR_BRIGADE_CONCAT(req->in, in);
+
+ if (cookie != NULL) {
+ req->jar = apr_table_make(pool, APREQ_DEFAULT_NELTS);
+ req->jar_status =
+ apreq_parse_cookie_header(pool, req->jar, cookie);
+ }
+ else {
+ req->jar = NULL;
+ req->jar_status = APREQ_ERROR_NODATA;
+ }
+
+
+ if (query_string != NULL) {
+ req->args = apr_table_make(pool, APREQ_DEFAULT_NELTS);
+ req->args_status =
+ apreq_parse_query_string(pool, req->args, query_string);
+ }
+ else {
+ req->args = NULL;
+ req->args_status = APREQ_ERROR_NODATA;
+ }
+
+ if (!APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(req->in))) {
+ apr_bucket *eos = apr_bucket_eos_create(in->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(req->in, eos);
+ }
+
+ return &req->handle;
+}
+