Coverage Report

Created: 2023-03-26 06:28

/src/httpd/server/apreq_param.c
Line
Count
Source (jump to first uncovered line)
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 "apreq_param.h"
19
#include "apreq_error.h"
20
#include "apreq_util.h"
21
#include "apr_strings.h"
22
#include "apr_lib.h"
23
24
#define MAX_LEN         (1024 * 1024)
25
#define MAX_BRIGADE_LEN (1024 * 256)
26
#define MAX_READ_AHEAD  (1024 * 64)
27
28
29
APREQ_DECLARE(apreq_param_t *) apreq_param_make(apr_pool_t *p,
30
                                                const char *name,
31
                                                const apr_size_t nlen,
32
                                                const char *val,
33
                                                const apr_size_t vlen)
34
2.56k
{
35
2.56k
    apreq_param_t *param;
36
2.56k
    apreq_value_t *v;
37
38
2.56k
    param = apr_palloc(p, nlen + vlen + 1 + sizeof *param);
39
40
2.56k
    if (param == NULL)
41
0
        return NULL;
42
43
2.56k
    param->info = NULL;
44
2.56k
    param->upload = NULL;
45
2.56k
    param->flags = 0;
46
47
2.56k
    *(const apreq_value_t **)&v = &param->v;
48
49
2.56k
    if (vlen && val != NULL)
50
4
        memcpy(v->data, val, vlen);
51
2.56k
    v->data[vlen] = 0;
52
2.56k
    v->dlen = vlen;
53
54
2.56k
    v->name = v->data + vlen + 1;
55
2.56k
    if (nlen && name != NULL)
56
65
        memcpy(v->name, name, nlen);
57
2.56k
    v->name[nlen] = 0;
58
2.56k
    v->nlen = nlen;
59
60
2.56k
    return param;
61
2.56k
}
62
63
APREQ_DECLARE(apr_status_t) apreq_param_decode(apreq_param_t **param,
64
                                               apr_pool_t *pool,
65
                                               const char *word,
66
                                               apr_size_t nlen,
67
                                               apr_size_t vlen)
68
0
{
69
0
    apr_status_t status;
70
0
    apreq_value_t *v;
71
0
    apreq_param_t *p;
72
0
    apreq_charset_t charset;
73
74
0
    if (nlen == 0) {
75
0
        *param = NULL;
76
0
        return APR_EBADARG;
77
0
    }
78
79
0
    p = apr_palloc(pool, nlen + vlen + 1 + sizeof *p);
80
0
    p->info = NULL;
81
0
    p->upload = NULL;
82
0
    p->flags = 0;
83
0
    *(const apreq_value_t **)&v = &p->v;
84
85
0
    if (vlen > 0) {
86
0
        status = apreq_decode(v->data, &v->dlen, word + nlen + 1, vlen);
87
0
        if (status != APR_SUCCESS) {
88
0
            *param = NULL;
89
0
            return status;
90
0
        }
91
0
        charset = apreq_charset_divine(v->data, v->dlen);
92
0
    }
93
0
    else {
94
0
        v->data[0] = 0;
95
0
        v->dlen = 0;
96
0
        charset = APREQ_CHARSET_ASCII;
97
0
    }
98
0
    v->name = v->data + vlen + 1;
99
100
0
    status = apreq_decode(v->name, &v->nlen, word, nlen);
101
0
    if (status != APR_SUCCESS) {
102
0
        *param = NULL;
103
0
        return status;
104
0
    }
105
106
0
    switch (apreq_charset_divine(v->name, v->nlen)) {
107
0
    case APREQ_CHARSET_UTF8:
108
0
        if (charset == APREQ_CHARSET_ASCII)
109
0
            charset = APREQ_CHARSET_UTF8;
110
0
    case APREQ_CHARSET_ASCII:
111
0
        break;
112
113
0
    case APREQ_CHARSET_LATIN1:
114
0
        if (charset != APREQ_CHARSET_CP1252)
115
0
            charset = APREQ_CHARSET_LATIN1;
116
0
        break;
117
0
    case APREQ_CHARSET_CP1252:
118
0
        charset = APREQ_CHARSET_CP1252;
119
0
    }
120
121
0
    apreq_param_charset_set(p, charset);
122
0
    *param = p;
123
124
0
    return APR_SUCCESS;
125
0
}
126
127
128
APREQ_DECLARE(char *) apreq_param_encode(apr_pool_t *pool,
129
                                         const apreq_param_t *param)
130
0
{
131
0
    apr_size_t dlen;
132
0
    char *data;
133
0
    data = apr_palloc(pool, 3 * (param->v.nlen + param->v.dlen) + 2);
134
0
    dlen = apreq_encode(data, param->v.name, param->v.nlen);
135
0
    data[dlen++] = '=';
136
0
    dlen += apreq_encode(data + dlen, param->v.data, param->v.dlen);
137
138
0
    return data;
139
0
}
140
141
APREQ_DECLARE(apr_status_t) apreq_parse_query_string(apr_pool_t *pool,
142
                                                     apr_table_t *t,
143
                                                     const char *qs)
144
0
{
145
0
    const char *start = qs;
146
0
    apr_size_t nlen = 0;
147
148
0
    for (;;++qs) {
149
0
        switch (*qs) {
150
151
0
        case '=':
152
0
            if (nlen == 0) {
153
0
                nlen = qs - start;
154
0
            }
155
0
            break;
156
157
0
        case '&':
158
0
        case ';':
159
0
        case 0:
160
0
            if (qs > start) {
161
0
                apr_size_t vlen = 0;
162
0
                apreq_param_t *param;
163
0
                apr_status_t s;
164
0
                if (nlen == 0)
165
0
                    nlen = qs - start;
166
0
                else
167
0
                    vlen = qs - start - nlen - 1;
168
169
0
                s = apreq_param_decode(&param, pool, start, nlen, vlen);
170
0
                if (s != APR_SUCCESS)
171
0
                    return s;
172
173
0
                apreq_param_tainted_on(param);
174
0
                apreq_value_table_add(&param->v, t);
175
0
            }
176
177
0
            if (*qs == 0)
178
0
                return APR_SUCCESS;
179
180
0
            nlen = 0;
181
0
            start = qs + 1;
182
0
        }
183
0
    }
184
    /* not reached */
185
0
    return APR_INCOMPLETE;
186
0
}
187
188
189
190
191
static int param_push(void *data, const char *key, const char *val)
192
0
{
193
0
    apr_array_header_t *arr = data;
194
0
    *(apreq_param_t **)apr_array_push(arr) =
195
0
        apreq_value_to_param(val);
196
0
    return 1;   /* keep going */
197
0
}
198
199
200
APREQ_DECLARE(apr_array_header_t *) apreq_params_as_array(apr_pool_t *p,
201
                                                          const apr_table_t *t,
202
                                                          const char *key)
203
0
{
204
0
    apr_array_header_t *arr;
205
206
0
    arr = apr_array_make(p, apr_table_elts(t)->nelts,
207
0
                         sizeof(apreq_param_t *));
208
209
0
    apr_table_do(param_push, arr, t, key, NULL);
210
0
    return arr;
211
0
}
212
213
APREQ_DECLARE(const char *) apreq_params_as_string(apr_pool_t *p,
214
                                                   const apr_table_t *t,
215
                                                   const char *key,
216
                                                   apreq_join_t mode)
217
0
{
218
0
    apr_array_header_t *arr = apreq_params_as_array(p, t, key);
219
0
    apreq_param_t **elt = (apreq_param_t **)arr->elts;
220
0
    apreq_param_t **const end = elt + arr->nelts;
221
0
    if (arr->nelts == 0)
222
0
        return apr_pstrdup(p, "");
223
224
0
    while (elt < end) {
225
0
        *(const apreq_value_t **)elt = &(**elt).v;
226
0
        ++elt;
227
0
    }
228
0
    return apreq_join(p, ", ", arr, mode);
229
0
}
230
231
232
233
static int upload_push(void *data, const char *key, const char *val)
234
0
{
235
0
    apr_table_t *t = data;
236
0
    apreq_param_t *p = apreq_value_to_param(val);
237
238
0
    if (p->upload != NULL)
239
0
        apreq_value_table_add(&p->v, t);
240
0
    return 1;   /* keep going */
241
0
}
242
243
244
APREQ_DECLARE(const apr_table_t *) apreq_uploads(const apr_table_t *body,
245
                                                 apr_pool_t *pool)
246
0
{
247
0
    apr_table_t *t = apr_table_make(pool, APREQ_DEFAULT_NELTS);
248
0
    apr_table_do(upload_push, t, body, NULL);
249
0
    return t;
250
0
}
251
252
static int upload_set(void *data, const char *key, const char *val)
253
0
{
254
0
    const apreq_param_t **q = data;
255
0
    apreq_param_t *p = apreq_value_to_param(val);
256
257
0
    if (p->upload != NULL) {
258
0
        *q = p;
259
0
        return 0; /* upload found, stop */
260
0
    }
261
0
    else
262
0
        return 1; /* keep searching */
263
0
}
264
265
266
APREQ_DECLARE(const apreq_param_t *) apreq_upload(const apr_table_t *body,
267
                                                  const char *name)
268
0
{
269
0
    apreq_param_t *param = NULL;
270
0
    apr_table_do(upload_set, &param, body, name, NULL);
271
0
    return param;
272
0
}