blob: 5cd6359a2409aa3975cc45489d05f3597ddfa130 [file] [log] [blame]
/*
** Copyright 2003-2005 The Apache Software Foundation
**
** Licensed 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 env;
const char *cookie_header, *cookie2_header;
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 *env, apr_uint64_t bytes)
{
struct custom_handle *handle = (struct custom_handle*)env;
apr_status_t s;
apr_bucket *e;
if (handle->body_status != APR_INCOMPLETE)
return handle->body_status;
switch (s = apr_brigade_partition(handle->in, bytes, &e)) {
apr_uint64_t len;
case APR_SUCCESS:
apreq_brigade_move(handle->tmpbb, handle->in, e);
handle->bytes_read += bytes;
if (handle->bytes_read > handle->read_limit) {
handle->body_status = APREQ_ERROR_OVERLIMIT;
break;
}
handle->body_status =
apreq_parser_run(handle->parser, handle->body, handle->tmpbb);
apr_brigade_cleanup(handle->tmpbb);
break;
case APR_INCOMPLETE:
apreq_brigade_move(handle->tmpbb, handle->in, e);
s = apr_brigade_length(handle->tmpbb, 1, &len);
if (s != APR_SUCCESS) {
handle->body_status = s;
break;
}
handle->bytes_read += len;
if (handle->bytes_read > handle->read_limit) {
handle->body_status = APREQ_ERROR_OVERLIMIT;
break;
}
handle->body_status =
apreq_parser_run(handle->parser, handle->body, handle->tmpbb);
apr_brigade_cleanup(handle->tmpbb);
break;
default:
handle->body_status = s;
}
return handle->body_status;
}
static apr_status_t custom_jar(apreq_handle_t *env, const apr_table_t **t)
{
struct custom_handle *handle = (struct custom_handle*)env;
*t = handle->jar;
return handle->jar_status;
}
static apr_status_t custom_args(apreq_handle_t *env, const apr_table_t **t)
{
struct custom_handle *handle = (struct custom_handle*)env;
*t = handle->args;
return handle->args_status;
}
static apr_status_t custom_body(apreq_handle_t *env, const apr_table_t **t)
{
struct custom_handle *handle = (struct custom_handle*)env;
while (handle->body_status == APR_INCOMPLETE)
custom_parse_brigade(env, READ_BYTES);
*t = handle->body;
return handle->body_status;
}
static apreq_cookie_t *custom_jar_get(apreq_handle_t *env, const char *name)
{
struct custom_handle *handle = (struct custom_handle*)env;
const char *val;
if (handle->jar == NULL || name == NULL)
return NULL;
val = apr_table_get(handle->jar, name);
if (val == NULL)
return NULL;
return apreq_value_to_cookie(val);
}
static apreq_param_t *custom_args_get(apreq_handle_t *env, const char *name)
{
struct custom_handle *handle = (struct custom_handle*)env;
const char *val;
if (handle->args == NULL || name == NULL)
return NULL;
val = apr_table_get(handle->args, name);
if (val == NULL)
return NULL;
return apreq_value_to_param(val);
}
static apreq_param_t *custom_body_get(apreq_handle_t *env, const char *name)
{
struct custom_handle *handle = (struct custom_handle*)env;
const char *val;
if (handle->body == NULL || name == NULL)
return NULL;
while (1) {
*(const char **)&val = apr_table_get(handle->body, name);
if (val != NULL)
break;
if (handle->body_status == APR_INCOMPLETE)
custom_parse_brigade(env, READ_BYTES);
else
return NULL;
}
return apreq_value_to_param(val);
}
static apr_status_t custom_parser_get(apreq_handle_t *env,
const apreq_parser_t **parser)
{
struct custom_handle *handle = (struct custom_handle*)env;
*parser = handle->parser;
return APR_SUCCESS;
}
static apr_status_t custom_parser_set(apreq_handle_t *env,
apreq_parser_t *parser)
{
(void)env;
(void)parser;
return APR_ENOTIMPL;
}
static apr_status_t custom_hook_add(apreq_handle_t *env,
apreq_hook_t *hook)
{
struct custom_handle *handle = (struct custom_handle*)env;
apreq_parser_add_hook(handle->parser, hook);
return APR_SUCCESS;
}
static apr_status_t custom_brigade_limit_get(apreq_handle_t *env,
apr_size_t *bytes)
{
struct custom_handle *handle = (struct custom_handle*)env;
*bytes = handle->parser->brigade_limit;
return APR_SUCCESS;
}
static apr_status_t custom_brigade_limit_set(apreq_handle_t *env,
apr_size_t bytes)
{
(void)env;
(void)bytes;
return APR_ENOTIMPL;
}
static apr_status_t custom_read_limit_get(apreq_handle_t *env,
apr_uint64_t *bytes)
{
struct custom_handle *handle = (struct custom_handle*)env;
*bytes = handle->read_limit;
return APR_SUCCESS;
}
static apr_status_t custom_read_limit_set(apreq_handle_t *env,
apr_uint64_t bytes)
{
(void)env;
(void)bytes;
return APR_ENOTIMPL;
}
static apr_status_t custom_temp_dir_get(apreq_handle_t *env,
const char **path)
{
struct custom_handle *handle = (struct custom_handle*)env;
*path = handle->parser->temp_dir;
return APR_SUCCESS;
}
static apr_status_t custom_temp_dir_set(apreq_handle_t *env,
const char *path)
{
(void)env;
(void)path;
return APR_ENOTIMPL;
}
static const char *custom_header_in(apreq_handle_t *env,
const char *name)
{
struct custom_handle *handle = (struct custom_handle*)env;
if (strcasecmp(name, "Content-Type") == 0)
return handle->parser->content_type;
else if (strcasecmp(name, "Cookie") == 0)
return handle->cookie_header;
else if (strcasecmp(name, "Cookie2") == 0)
return handle->cookie2_header;
else
return NULL;
}
static apr_status_t custom_header_out(apreq_handle_t *env, const char *name,
char *value)
{
(void)env;
(void)name;
(void)value;
return APR_ENOTIMPL;
}
static APREQ_MODULE(custom, 20050130);
APREQ_DECLARE(apreq_handle_t*) apreq_handle_custom(apr_pool_t *pool,
const char *query_string,
const char *cookie,
const char *cookie2,
apreq_parser_t *parser,
apr_uint64_t read_limit,
apr_bucket_brigade *in)
{
struct custom_handle *handle;
handle = apr_palloc(pool, sizeof(*handle));
handle->env.module = &custom_module;
handle->cookie_header = cookie;
handle->cookie2_header = cookie2;
handle->read_limit = read_limit;
handle->parser = parser;
handle->in = in;
if (cookie != NULL) {
handle->jar = apr_table_make(pool, APREQ_DEFAULT_NELTS);
handle->jar_status =
apreq_parse_cookie_header(pool, handle->args, query_string);
}
else {
handle->jar = NULL;
handle->jar_status = APREQ_ERROR_NODATA;
}
if (query_string != NULL) {
handle->args = apr_table_make(pool, APREQ_DEFAULT_NELTS);
handle->args_status =
apreq_parse_query_string(pool, handle->args, query_string);
}
else {
handle->args = NULL;
handle->args_status = APREQ_ERROR_NODATA;
}
if (in != NULL) {
handle->tmpbb = apr_brigade_create(in->p, in->bucket_alloc);
handle->body = apr_table_make(pool, APREQ_DEFAULT_NELTS);
handle->body_status = APR_INCOMPLETE;
}
else {
handle->body = NULL;
handle->body_status = APREQ_ERROR_NODATA;
}
return &handle->env;
}