diff options
Diffstat (limited to 'srclib/libapreq/library/param.c')
-rw-r--r-- | srclib/libapreq/library/param.c | 272 |
1 files changed, 272 insertions, 0 deletions
diff --git a/srclib/libapreq/library/param.c b/srclib/libapreq/library/param.c new file mode 100644 index 0000000000..83e185b595 --- /dev/null +++ b/srclib/libapreq/library/param.c @@ -0,0 +1,272 @@ +/* +** 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 "apreq_param.h" +#include "apreq_error.h" +#include "apreq_util.h" +#include "apr_strings.h" +#include "apr_lib.h" + +#define MAX_LEN (1024 * 1024) +#define MAX_BRIGADE_LEN (1024 * 256) +#define MAX_READ_AHEAD (1024 * 64) + + +APREQ_DECLARE(apreq_param_t *) apreq_param_make(apr_pool_t *p, + const char *name, + const apr_size_t nlen, + const char *val, + const apr_size_t vlen) +{ + apreq_param_t *param; + apreq_value_t *v; + + param = apr_palloc(p, nlen + vlen + 1 + sizeof *param); + + if (param == NULL) + return NULL; + + param->info = NULL; + param->upload = NULL; + param->flags = 0; + + *(const apreq_value_t **)&v = ¶m->v; + + if (vlen && val != NULL) + memcpy(v->data, val, vlen); + v->data[vlen] = 0; + v->dlen = vlen; + + v->name = v->data + vlen + 1; + if (nlen && name != NULL) + memcpy(v->name, name, nlen); + v->name[nlen] = 0; + v->nlen = nlen; + + return param; +} + +APREQ_DECLARE(apr_status_t) apreq_param_decode(apreq_param_t **param, + apr_pool_t *pool, + const char *word, + apr_size_t nlen, + apr_size_t vlen) +{ + apr_status_t status; + apreq_value_t *v; + apreq_param_t *p; + apreq_charset_t charset; + + if (nlen == 0) { + *param = NULL; + return APR_EBADARG; + } + + p = apr_palloc(pool, nlen + vlen + 1 + sizeof *p); + p->info = NULL; + p->upload = NULL; + p->flags = 0; + *(const apreq_value_t **)&v = &p->v; + + if (vlen > 0) { + status = apreq_decode(v->data, &v->dlen, word + nlen + 1, vlen); + if (status != APR_SUCCESS) { + *param = NULL; + return status; + } + charset = apreq_charset_divine(v->data, v->dlen); + } + else { + v->data[0] = 0; + v->dlen = 0; + charset = APREQ_CHARSET_ASCII; + } + v->name = v->data + vlen + 1; + + status = apreq_decode(v->name, &v->nlen, word, nlen); + if (status != APR_SUCCESS) { + *param = NULL; + return status; + } + + switch (apreq_charset_divine(v->name, v->nlen)) { + case APREQ_CHARSET_UTF8: + if (charset == APREQ_CHARSET_ASCII) + charset = APREQ_CHARSET_UTF8; + case APREQ_CHARSET_ASCII: + break; + + case APREQ_CHARSET_LATIN1: + if (charset != APREQ_CHARSET_CP1252) + charset = APREQ_CHARSET_LATIN1; + break; + case APREQ_CHARSET_CP1252: + charset = APREQ_CHARSET_CP1252; + } + + apreq_param_charset_set(p, charset); + *param = p; + + return APR_SUCCESS; +} + + +APREQ_DECLARE(char *) apreq_param_encode(apr_pool_t *pool, + const apreq_param_t *param) +{ + apr_size_t dlen; + char *data; + data = apr_palloc(pool, 3 * (param->v.nlen + param->v.dlen) + 2); + dlen = apreq_encode(data, param->v.name, param->v.nlen); + data[dlen++] = '='; + dlen += apreq_encode(data + dlen, param->v.data, param->v.dlen); + + return data; +} + +APREQ_DECLARE(apr_status_t) apreq_parse_query_string(apr_pool_t *pool, + apr_table_t *t, + const char *qs) +{ + const char *start = qs; + apr_size_t nlen = 0; + + for (;;++qs) { + switch (*qs) { + + case '=': + if (nlen == 0) { + nlen = qs - start; + } + break; + + case '&': + case ';': + case 0: + if (qs > start) { + apr_size_t vlen = 0; + apreq_param_t *param; + apr_status_t s; + if (nlen == 0) + nlen = qs - start; + else + vlen = qs - start - nlen - 1; + + s = apreq_param_decode(¶m, pool, start, nlen, vlen); + if (s != APR_SUCCESS) + return s; + + apreq_param_tainted_on(param); + apreq_value_table_add(¶m->v, t); + } + + if (*qs == 0) + return APR_SUCCESS; + + nlen = 0; + start = qs + 1; + } + } + /* not reached */ + return APR_INCOMPLETE; +} + + + + +static int param_push(void *data, const char *key, const char *val) +{ + apr_array_header_t *arr = data; + *(apreq_param_t **)apr_array_push(arr) = + apreq_value_to_param(val); + return 1; /* keep going */ +} + + +APREQ_DECLARE(apr_array_header_t *) apreq_params_as_array(apr_pool_t *p, + const apr_table_t *t, + const char *key) +{ + apr_array_header_t *arr; + + arr = apr_array_make(p, apr_table_elts(t)->nelts, + sizeof(apreq_param_t *)); + + apr_table_do(param_push, arr, t, key, NULL); + return arr; +} + +APREQ_DECLARE(const char *) apreq_params_as_string(apr_pool_t *p, + const apr_table_t *t, + const char *key, + apreq_join_t mode) +{ + apr_array_header_t *arr = apreq_params_as_array(p, t, key); + apreq_param_t **elt = (apreq_param_t **)arr->elts; + apreq_param_t **const end = elt + arr->nelts; + if (arr->nelts == 0) + return apr_pstrdup(p, ""); + + while (elt < end) { + *(const apreq_value_t **)elt = &(**elt).v; + ++elt; + } + return apreq_join(p, ", ", arr, mode); +} + + + +static int upload_push(void *data, const char *key, const char *val) +{ + apr_table_t *t = data; + apreq_param_t *p = apreq_value_to_param(val); + + if (p->upload != NULL) + apreq_value_table_add(&p->v, t); + return 1; /* keep going */ +} + + +APREQ_DECLARE(const apr_table_t *) apreq_uploads(const apr_table_t *body, + apr_pool_t *pool) +{ + apr_table_t *t = apr_table_make(pool, APREQ_DEFAULT_NELTS); + apr_table_do(upload_push, t, body, NULL); + return t; +} + +static int upload_set(void *data, const char *key, const char *val) +{ + const apreq_param_t **q = data; + apreq_param_t *p = apreq_value_to_param(val); + + if (p->upload != NULL) { + *q = p; + return 0; /* upload found, stop */ + } + else + return 1; /* keep searching */ +} + + +APREQ_DECLARE(const apreq_param_t *) apreq_upload(const apr_table_t *body, + const char *name) +{ + apreq_param_t *param = NULL; + apr_table_do(upload_set, ¶m, body, name, NULL); + return param; +} |