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 "apreq_parser.h"
19 #include "apreq_util.h"
20 #include "apreq_error.h"
23 #define PARSER_STATUS_CHECK(PREFIX) do { \
24 if (ctx->status == PREFIX##_ERROR) \
25 return APREQ_ERROR_GENERAL; \
26 else if (ctx->status == PREFIX##_COMPLETE) \
28 else if (bb == NULL) \
29 return APR_INCOMPLETE; \
35 apr_bucket_brigade *bb;
47 /******************** application/x-www-form-urlencoded ********************/
49 static apr_status_t split_urlword(apreq_param_t **p, apr_pool_t *pool,
50 apr_bucket_brigade *bb,
58 struct iovec vec[APREQ_DEFAULT_NELTS];
59 apr_array_header_t arr;
61 apreq_charset_t charset;
66 param = apreq_param_make(pool, NULL, nlen, NULL, vlen);
67 *(const apreq_value_t **)&v = ¶m->v;
70 arr.elt_size = sizeof(struct iovec);
72 arr.nalloc = APREQ_DEFAULT_NELTS;
73 arr.elts = (char *)vec;
76 e = APR_BRIGADE_FIRST(bb);
78 while (!APR_BUCKET_IS_EOS(e)) {
79 struct iovec *iov = apr_array_push(&arr);
81 s = apr_bucket_read(e, (const char **)&iov->iov_base,
82 &len, APR_BLOCK_READ);
89 e = APR_BUCKET_NEXT(e);
99 while (!APR_BUCKET_IS_EOS(e)) {
100 struct iovec *iov = apr_array_push(&arr);
102 s = apr_bucket_read(e, (const char **)&iov->iov_base,
103 &len, APR_BLOCK_READ);
104 if (s != APR_SUCCESS)
110 e = APR_BUCKET_NEXT(e);
119 s = apreq_decodev(v->data, &vlen,
120 (struct iovec *)arr.elts + mark, arr.nelts - mark);
121 if (s != APR_SUCCESS)
124 charset = apreq_charset_divine(v->data, vlen);
126 v->name = v->data + vlen + 1;
129 s = apreq_decodev(v->name, &nlen, (struct iovec *)arr.elts, mark);
130 if (s != APR_SUCCESS)
133 switch (apreq_charset_divine(v->name, nlen)) {
134 case APREQ_CHARSET_UTF8:
135 if (charset == APREQ_CHARSET_ASCII)
136 charset = APREQ_CHARSET_UTF8;
137 case APREQ_CHARSET_ASCII:
140 case APREQ_CHARSET_LATIN1:
141 if (charset != APREQ_CHARSET_CP1252)
142 charset = APREQ_CHARSET_LATIN1;
144 case APREQ_CHARSET_CP1252:
145 charset = APREQ_CHARSET_CP1252;
150 while ((f = APR_BRIGADE_FIRST(bb)) != e)
151 apr_bucket_delete(f);
153 apreq_param_tainted_on(param);
154 apreq_param_charset_set(param, charset);
159 APREQ_DECLARE_PARSER(apreq_parse_urlencoded)
161 apr_pool_t *pool = parser->pool;
165 if (parser->ctx == NULL) {
166 ctx = apr_pcalloc(pool, sizeof *ctx);
167 ctx->bb = apr_brigade_create(pool, parser->bucket_alloc);
169 ctx->status = URL_NAME;
174 PARSER_STATUS_CHECK(URL);
175 e = APR_BRIGADE_LAST(ctx->bb);
176 APR_BRIGADE_CONCAT(ctx->bb, bb);
180 for (e = APR_BUCKET_NEXT(e);
181 e != APR_BRIGADE_SENTINEL(ctx->bb);
182 e = APR_BUCKET_NEXT(e))
184 apreq_param_t *param;
185 apr_size_t off = 0, dlen;
189 if (APR_BUCKET_IS_EOS(e)) {
190 if (ctx->status == URL_NAME) {
194 s = split_urlword(¶m, pool, ctx->bb, ctx->nlen, ctx->vlen);
195 if (parser->hook != NULL && s == APR_SUCCESS)
196 s = apreq_hook_run(parser->hook, param, NULL);
198 if (s == APR_SUCCESS) {
199 apreq_value_table_add(¶m->v, t);
200 ctx->status = URL_COMPLETE;
203 ctx->status = URL_ERROR;
207 APR_BRIGADE_CONCAT(bb, ctx->bb);
211 s = apr_bucket_read(e, &data, &dlen, APR_BLOCK_READ);
212 if ( s != APR_SUCCESS ) {
213 ctx->status = URL_ERROR;
219 switch (ctx->status) {
223 switch (data[off++]) {
225 apr_bucket_split(e, off);
229 e = APR_BUCKET_NEXT(e);
230 ctx->status = URL_VALUE;
231 goto parse_url_bucket;
241 switch (data[off++]) {
244 apr_bucket_split(e, off);
245 s = split_urlword(¶m, pool, ctx->bb,
246 ctx->nlen, ctx->vlen);
247 if (parser->hook != NULL && s == APR_SUCCESS)
248 s = apreq_hook_run(parser->hook, param, NULL);
250 if (s != APR_SUCCESS) {
251 ctx->status = URL_ERROR;
255 apreq_value_table_add(¶m->v, t);
256 ctx->status = URL_NAME;
259 e = APR_BRIGADE_SENTINEL(ctx->bb);
260 goto parse_url_brigade;
271 apreq_brigade_setaside(ctx->bb, pool);
272 return APR_INCOMPLETE;