Modified: httpd/apreq/branches/multi-env-unstable/src/apreq_parsers.c URL: http://svn.apache.org/viewcvs/httpd/apreq/branches/multi-env-unstable/src/apreq_parsers.c?view=diff&r1=151385&r2=151386 ============================================================================== --- httpd/apreq/branches/multi-env-unstable/src/apreq_parsers.c (original) +++ httpd/apreq/branches/multi-env-unstable/src/apreq_parsers.c Fri Feb 4 10:27:55 2005 @@ -15,7 +15,7 @@ */ #include "apreq_params.h" -#include "apreq_env.h" +#include "apreq_parsers.h" #include "apr_lib.h" #include "apr_strings.h" #include "apr_strmatch.h" @@ -45,15 +45,22 @@ APREQ_DECLARE(apreq_parser_t *) apreq_make_parser(apr_pool_t *pool, - const char *enctype, + apr_bucket_alloc_t *ba, + const char *content_type, apreq_parser_function_t parser, + apr_size_t brigade_limit, + const char *temp_dir, apreq_hook_t *hook, void *ctx) { apreq_parser_t *p = apr_palloc(pool, sizeof *p); - p->enctype = enctype; + p->content_type = content_type; p->parser = parser; p->hook = hook; + p->pool = pool; + p->bucket_alloc = ba; + p->brigade_limit = brigade_limit; + p->temp_dir = temp_dir; p->ctx = ctx; return p; } @@ -67,13 +74,15 @@ apreq_hook_t *h = apr_palloc(pool, sizeof *h); h->hook = hook; h->next = next; + h->pool = pool; h->ctx = ctx; return h; } -APREQ_DECLARE(void) apreq_add_hook(apreq_parser_t *p, - apreq_hook_t *h) +/*XXX this may need to check the parser's state before modifying the hook list */ +APREQ_DECLARE(apr_status_t) apreq_parser_add_hook(apreq_parser_t *p, + apreq_hook_t *h) { apreq_hook_t *last = h; @@ -82,6 +91,8 @@ last->next = p->hook; p->hook = h; + + return APR_SUCCESS; } static apr_hash_t *default_parsers; @@ -100,11 +111,15 @@ apreq_register_parser("multipart/related", apreq_parse_multipart); } -APREQ_DECLARE(void) apreq_register_parser(const char *enctype, +APREQ_DECLARE(void) apreq_register_parser(const char *enctype, apreq_parser_function_t parser) { apreq_parser_function_t *f = NULL; - apreq_parser_initialize(); + + if (enctype == NULL) { + apreq_parser_initialize(); + return; + } if (parser != NULL) { f = apr_palloc(default_parser_pool, sizeof *f); *f = parser; @@ -113,78 +128,72 @@ APR_HASH_KEY_STRING, f); } - -APREQ_DECLARE(apreq_parser_t *)apreq_parser(apreq_env_handle_t *env, apreq_hook_t *hook) +APREQ_DECLARE(apreq_parser_function_t)apreq_parser(const char *enctype) { apreq_parser_function_t *f; - apr_pool_t *pool = apreq_env_pool(env); - const char *type = apreq_env_content_type(env); - apr_ssize_t tlen; - - apreq_parser_initialize(); + apr_size_t tlen = 0; - if (type == NULL) + if (enctype == NULL || default_parsers == NULL) return NULL; - tlen = 0; - while(type[tlen] && type[tlen] != ';') + while(enctype[tlen] && enctype[tlen] != ';') ++tlen; - f = apr_hash_get(default_parsers, type, tlen); + f = apr_hash_get(default_parsers, enctype, tlen); if (f != NULL) - return apreq_make_parser(pool, type, *f, hook, NULL); + return *f; else return NULL; } - /******************** application/x-www-form-urlencoded ********************/ -static apr_status_t split_urlword(apr_table_t *t, - apr_bucket_brigade *bb, +static apr_status_t split_urlword(apreq_param_t **p, apr_pool_t *pool, + apr_bucket_brigade *bb, const apr_size_t nlen, const apr_size_t vlen) { - apr_pool_t *pool = apr_table_elts(t)->pool; - apreq_param_t *param = apr_palloc(pool, nlen + vlen + 1 + sizeof *param); - apreq_value_t *v = ¶m->v; + apreq_param_t *param; + apreq_value_t *v; apr_bucket *e, *end; apr_status_t s; - struct iovec vec[APREQ_NELTS]; + struct iovec vec[APREQ_DEFAULT_NELTS]; apr_array_header_t arr; - char *writable_name; + + if (nlen == 0) + return APR_EBADARG; + + param = apr_palloc(pool, nlen + vlen + 1 + sizeof *param); + *(const apreq_value_t **)&v = ¶m->v; arr.pool = pool; arr.elt_size = sizeof(struct iovec); arr.nelts = 0; - arr.nalloc = APREQ_NELTS; + arr.nalloc = APREQ_DEFAULT_NELTS; arr.elts = (char *)vec; - param->bb = NULL; + param->upload = NULL; param->info = NULL; - v->name = writable_name = v->data + vlen + 1; + v->name = v->data + vlen + 1; apr_brigade_partition(bb, nlen+1, &end); for (e = APR_BRIGADE_FIRST(bb); e != end; e = APR_BUCKET_NEXT(e)) { - apr_size_t dlen; - const char *data; - struct iovec *iov; - s = apr_bucket_read(e, &data, &dlen, APR_BLOCK_READ); + struct iovec *iov = apr_array_push(&arr); + apr_size_t len; + s = apr_bucket_read(e, (const char **)&iov->iov_base, + &len, APR_BLOCK_READ); if (s != APR_SUCCESS) return s; - - iov = apr_array_push(&arr); - iov->iov_base = apreq_deconst(data); - iov->iov_len = dlen; + iov->iov_len = len; } ((struct iovec *)arr.elts)[arr.nelts - 1].iov_len--; /* drop '=' sign */ - s = apreq_decodev(writable_name, &v->size, + s = apreq_decodev(v->name, &v->size, (struct iovec *)arr.elts, arr.nelts); if (s != APR_SUCCESS) return s; @@ -196,16 +205,13 @@ apr_brigade_partition(bb, vlen + 1, &end); for (e = APR_BRIGADE_FIRST(bb); e != end; e = APR_BUCKET_NEXT(e)) { - apr_size_t dlen; - const char *data; - struct iovec *iov; - s = apr_bucket_read(e, &data, &dlen, APR_BLOCK_READ); + struct iovec *iov = apr_array_push(&arr); + apr_size_t len; + s = apr_bucket_read(e, (const char **)&iov->iov_base, + &len, APR_BLOCK_READ); if (s != APR_SUCCESS) return s; - - iov = apr_array_push(&arr); - iov->iov_base = apreq_deconst(data); - iov->iov_len = dlen; + iov->iov_len = len; } if (end != APR_BRIGADE_SENTINEL(bb)) @@ -213,13 +219,14 @@ s = apreq_decodev(v->data, &v->size, (struct iovec *)arr.elts, arr.nelts); + if (s != APR_SUCCESS) return s; while ((e = APR_BRIGADE_FIRST(bb)) != end) apr_bucket_delete(e); - apr_table_addn(t, v->name, v->data); + *p = param; return APR_SUCCESS; } @@ -235,15 +242,14 @@ APREQ_DECLARE_PARSER(apreq_parse_urlencoded) { - apr_pool_t *pool = apr_table_elts(t)->pool; + apr_pool_t *pool = parser->pool; apr_ssize_t nlen, vlen; apr_bucket *e; struct url_ctx *ctx; if (parser->ctx == NULL) { - apr_bucket_alloc_t *bb_alloc = apreq_env_bucket_alloc(env); ctx = apr_palloc(pool, sizeof *ctx); - ctx->bb = apr_brigade_create(pool, bb_alloc); + ctx->bb = apr_brigade_create(pool, parser->bucket_alloc); parser->ctx = ctx; ctx->status = URL_NAME; } @@ -261,24 +267,39 @@ e != APR_BRIGADE_SENTINEL(ctx->bb); e = APR_BUCKET_NEXT(e)) { + apreq_param_t *param; apr_size_t off = 0, dlen; const char *data; apr_status_t s; if (APR_BUCKET_IS_EOS(e)) { - s = (ctx->status == URL_NAME) ? APR_SUCCESS : - split_urlword(t, ctx->bb, nlen, vlen); + if (ctx->status == URL_NAME) { + s = APR_SUCCESS; + } + else { + s = split_urlword(¶m, pool, ctx->bb, nlen, vlen); + if (parser->hook != NULL && s == APR_SUCCESS) + s = APREQ_RUN_HOOK(parser->hook, param, NULL); + + if (s == APR_SUCCESS) { + apr_table_addn(t, param->v.name, param->v.data); + ctx->status = URL_COMPLETE; + } + else { + ctx->status = URL_ERROR; + } + } + APR_BRIGADE_CONCAT(bb, ctx->bb); - ctx->status = (s == APR_SUCCESS) ? URL_COMPLETE : URL_ERROR; - apreq_log(APREQ_DEBUG s, env, "url parser saw EOS"); return s; } + s = apr_bucket_read(e, &data, &dlen, APR_BLOCK_READ); if ( s != APR_SUCCESS ) { ctx->status = URL_ERROR; - apreq_log(APREQ_ERROR s, env, "apr_bucket_read failed"); return s; } + parse_url_bucket: switch (ctx->status) { @@ -297,16 +318,22 @@ case URL_VALUE: while (off < dlen) { + switch (data[off++]) { case '&': case ';': - s = split_urlword(t, ctx->bb, nlen, vlen); + s = split_urlword(¶m, pool, ctx->bb, nlen, vlen); + if (parser->hook != NULL && s == APR_SUCCESS) + s = APREQ_RUN_HOOK(parser->hook, param, NULL); + if (s != APR_SUCCESS) { ctx->status = URL_ERROR; - apreq_log(APREQ_ERROR s, env, "split_urlword failed"); return s; } + + apr_table_addn(t, param->v.name, param->v.data); goto parse_url_brigade; + default: ++vlen; } @@ -324,18 +351,26 @@ /********************* header parsing utils ********************/ -static apr_status_t split_header(apr_table_t *t, - apr_bucket_brigade *bb, - const apr_size_t nlen, - const apr_size_t glen, - const apr_size_t vlen) +static apr_status_t split_header_line(apreq_param_t **p, + apr_pool_t *pool, + apr_bucket_brigade *bb, + const apr_size_t nlen, + const apr_size_t glen, + const apr_size_t vlen) { - apr_pool_t *pool = apr_table_elts(t)->pool; - apreq_value_t *v = apr_palloc(pool, nlen + vlen + sizeof *v); - char *writable_name; + apreq_param_t *param; + apreq_value_t *v; apr_size_t off; - v->name = writable_name = v->data + vlen; + if (nlen == 0) + return APR_EBADARG; + + param = apr_palloc(pool, nlen + vlen + sizeof *param); + param->upload = NULL; + param->info = NULL; + + *(const apreq_value_t **)&v = ¶m->v; + v->name = v->data + vlen; /* no +1, since vlen includes extra (CR)LF */ /* copy name */ @@ -354,7 +389,7 @@ dlen = nlen - off; } - memcpy(writable_name + off, data, dlen); + memcpy(v->name + off, data, dlen); off += dlen; apr_bucket_delete(f); } @@ -402,7 +437,7 @@ apr_bucket_delete(f); } - writable_name[nlen] = 0; + v->name[nlen] = 0; /* remove trailing (CR)LF from value */ v->size = vlen - 1; @@ -411,7 +446,7 @@ v->data[v->size] = 0; - apr_table_addn(t, v->name, v->data); + *p = param; return APR_SUCCESS; } @@ -431,15 +466,14 @@ APREQ_DECLARE_PARSER(apreq_parse_headers) { - apr_pool_t *pool = apreq_env_pool(env); + apr_pool_t *pool = parser->pool; apr_ssize_t nlen, glen, vlen; apr_bucket *e; struct hdr_ctx *ctx; if (parser->ctx == NULL) { - apr_bucket_alloc_t *bb_alloc = apreq_env_bucket_alloc(env); ctx = apr_pcalloc(pool, sizeof *ctx); - ctx->bb = apr_brigade_create(pool, bb_alloc); + ctx->bb = apr_brigade_create(pool, parser->bucket_alloc); parser->ctx = ctx; } else @@ -462,6 +496,7 @@ apr_size_t off = 0, dlen; const char *data; apr_status_t s; + apreq_param_t *param; if (APR_BUCKET_IS_EOS(e)) { ctx->status = HDR_COMPLETE; APR_BRIGADE_CONCAT(bb, ctx->bb); @@ -571,11 +606,16 @@ /* can parse brigade now */ if (off > 0) apr_bucket_split(e, off); - s = split_header(t, ctx->bb, nlen, glen, vlen); + s = split_header_line(¶m, pool, ctx->bb, nlen, glen, vlen); + if (parser->hook != NULL && s == APR_SUCCESS) + s = APREQ_RUN_HOOK(parser->hook, param, NULL); + if (s != APR_SUCCESS) { ctx->status = HDR_ERROR; return s; } + + apr_table_addn(t, param->v.name, param->v.data); goto parse_hdr_brigade; } @@ -676,7 +716,7 @@ MFD_ERROR } status; apr_bucket *eos; - const char *param_name; + char *param_name; apreq_param_t *upload; }; @@ -773,105 +813,31 @@ return APR_INCOMPLETE; } -#define MAX_FILE_BUCKET_LENGTH ((apr_off_t) 1 << (6 * sizeof(apr_size_t))) - -APREQ_DECLARE(apr_status_t) apreq_brigade_concat(apreq_env_handle_t *env, - apr_bucket_brigade *out, - apr_bucket_brigade *in) -{ - apr_bucket *last = APR_BRIGADE_LAST(out); - apr_status_t s; - apr_bucket_file *f; - apr_bucket *e; - apr_off_t wlen; - - if (APR_BUCKET_IS_EOS(last)) - return APR_EOF; - - if (! APR_BUCKET_IS_FILE(last)) { - apr_file_t *file; - apr_off_t len; - apr_ssize_t max_brigade = apreq_env_max_brigade(env,-1); - s = apr_brigade_length(out, 1, &len); - if (s != APR_SUCCESS) - return s; +static +struct mfd_ctx * create_multipart_context(const char *content_type, + apr_pool_t *pool, + apr_bucket_alloc_t *ba, + apr_size_t brigade_limit, + const char *temp_dir) - if (max_brigade < 0 || len < max_brigade) { - APR_BRIGADE_CONCAT(out, in); - return APR_SUCCESS; - } - - s = apreq_file_mktemp(&file, apreq_env_pool(env), - apreq_env_temp_dir(env,NULL)); - if (s != APR_SUCCESS) - return s; - - s = apreq_brigade_fwrite(file, &wlen, out); - - if (s != APR_SUCCESS) - return s; - - last = apr_bucket_file_create(file, wlen, 0, out->p, out->bucket_alloc); - APR_BRIGADE_INSERT_TAIL(out, last); - } - - f = last->data; - - if (last->length > MAX_FILE_BUCKET_LENGTH) { - apr_bucket_copy(last, &e); - APR_BRIGADE_INSERT_TAIL(out, e); - e->length = 0; - e->start = last->length + 1; - last = e; - } - - e = APR_BRIGADE_LAST(in); - if (APR_BUCKET_IS_EOS(e)) { - APR_BUCKET_REMOVE(e); - APR_BRIGADE_INSERT_TAIL(out, e); - } - - /* Write the remaining buckets to disk, then delete them. */ - s = apreq_brigade_fwrite(f->fd, &wlen, in); - apr_brigade_cleanup(in); - - if (s == APR_SUCCESS) - last->length += wlen; - return s; -} - -static struct mfd_ctx *create_multipart_context(apreq_env_handle_t *env, - char *enctype) { apr_status_t s; - char *ct; apr_size_t blen; - apr_pool_t *pool = apreq_env_pool(env); - apr_bucket_alloc_t *bucket_alloc = apreq_env_bucket_alloc(env); struct mfd_ctx *ctx = apr_palloc(pool, sizeof *ctx); + char *ct = apr_pstrdup(pool, content_type); + + ct = strchr(ct, ';'); + if (ct == NULL) + return NULL; /* missing semicolon */ - ctx->status = MFD_INIT; - - ct = strchr(enctype, ';'); - if (ct == NULL) { - ctx->status = MFD_ERROR; - apreq_log(APREQ_ERROR APR_EGENERAL, env, - "mfd parser cannot find required " - "semicolon in supplied Content-Type header"); - return NULL; - } *ct++ = 0; - s = apreq_header_attribute(ct, "boundary", 8, (const char **)&ctx->bdry, &blen); - if (s != APR_SUCCESS) { - ctx->status = MFD_ERROR; - apreq_log(APREQ_ERROR APR_EGENERAL, env, - "mfd parser cannot find boundary " - "attribute in supplied Content-Type header"); - return NULL; - } + + if (s != APR_SUCCESS) + return NULL; /* missing boundary */ + ctx->bdry[blen] = 0; *--ctx->bdry = '-'; @@ -879,41 +845,45 @@ *--ctx->bdry = '\n'; *--ctx->bdry = '\r'; - ctx->pattern = apr_strmatch_precompile(pool,ctx->bdry,1); - ctx->hdr_parser = apreq_make_parser(pool, "", apreq_parse_headers, - NULL,NULL); + ctx->status = MFD_INIT; + ctx->pattern = apr_strmatch_precompile(pool, ctx->bdry, 1); + ctx->hdr_parser = apreq_make_parser(pool, ba, "", apreq_parse_headers, + brigade_limit, temp_dir, NULL, NULL); ctx->info = NULL; - ctx->bb = apr_brigade_create(pool, bucket_alloc); - ctx->in = apr_brigade_create(pool, bucket_alloc); - ctx->eos = apr_bucket_eos_create(bucket_alloc); + ctx->bb = apr_brigade_create(pool, ba); + ctx->in = apr_brigade_create(pool, ba); + ctx->eos = apr_bucket_eos_create(ba); ctx->mix_parser = NULL; ctx->param_name = NULL; ctx->upload = NULL; + return ctx; } APREQ_DECLARE_PARSER(apreq_parse_multipart) { - apr_pool_t *pool = apreq_env_pool(env); + apr_pool_t *pool = parser->pool; + apr_bucket_alloc_t *ba = parser->bucket_alloc; struct mfd_ctx *ctx = parser->ctx; apr_status_t s; if (ctx == NULL) { - ctx = create_multipart_context(env, apr_pstrdup(pool, - parser->enctype)); + ctx = create_multipart_context(parser->content_type, + pool, ba, + parser->brigade_limit, + parser->temp_dir); if (ctx == NULL) return APR_EGENERAL; - ctx->mix_parser = apreq_make_parser(pool, "", apreq_parse_multipart, - NULL, parser->hook); + + ctx->mix_parser = apreq_make_parser(pool, ba, "", + apreq_parse_multipart, + parser->brigade_limit, + parser->temp_dir, + parser->hook, + NULL); parser->ctx = ctx; } - else if (ctx->status == MFD_COMPLETE) { - apreq_log(APREQ_DEBUG APR_SUCCESS, env, - "mfd parser is already complete- " - "all further input brigades will be ignored."); - return APR_SUCCESS; - } PARSER_STATUS_CHECK(MFD); APR_BRIGADE_CONCAT(ctx->in, bb); @@ -963,11 +933,11 @@ case MFD_HEADER: { if (ctx->info == NULL) { - ctx->info = apr_table_make(pool, APREQ_NELTS); + ctx->info = apr_table_make(pool, APREQ_DEFAULT_NELTS); /* flush out old header parser internal structs for reuse */ ctx->hdr_parser->ctx = NULL; } - s = APREQ_RUN_PARSER(ctx->hdr_parser, env, ctx->info, ctx->in); + s = APREQ_RUN_PARSER(ctx->hdr_parser, ctx->info, ctx->in); switch (s) { case APR_SUCCESS: ctx->status = MFD_POST_HEADER; @@ -1041,8 +1011,9 @@ && strncmp(ct, "multipart/mixed", 15) == 0) { struct mfd_ctx *mix_ctx; - mix_ctx = create_multipart_context(env, - apr_pstrdup(pool, ct)); + mix_ctx = create_multipart_context(ct, pool, ba, + parser->brigade_limit, + parser->temp_dir); if (mix_ctx == NULL) { ctx->status = MFD_ERROR; return APR_EGENERAL; @@ -1059,10 +1030,11 @@ } else { apreq_param_t *param; + param = apreq_make_param(pool, name, nlen, filename, flen); param->info = ctx->info; - param->bb = apr_brigade_create(pool, + param->upload = apr_brigade_create(pool, ctx->bb->bucket_alloc); ctx->upload = param; ctx->status = MFD_UPLOAD; @@ -1084,7 +1056,7 @@ param = apreq_make_param(pool, name, nlen, filename, flen); param->info = ctx->info; - param->bb = apr_brigade_create(pool, + param->upload = apr_brigade_create(pool, ctx->bb->bucket_alloc); ctx->upload = param; ctx->status = MFD_UPLOAD; @@ -1107,7 +1079,7 @@ param = apreq_make_param(pool, name, nlen, filename, flen); param->info = ctx->info; - param->bb = apr_brigade_create(pool, + param->upload = apr_brigade_create(pool, ctx->bb->bucket_alloc); ctx->upload = param; ctx->status = MFD_UPLOAD; @@ -1130,7 +1102,7 @@ case APR_INCOMPLETE: APREQ_BRIGADE_SETASIDE(ctx->in, pool); - APREQ_BRIGADE_SETASIDE(ctx->bb,pool); + APREQ_BRIGADE_SETASIDE(ctx->bb, pool); return s; case APR_SUCCESS: @@ -1141,14 +1113,23 @@ } len = off; param = apr_palloc(pool, len + sizeof *param); - param->bb = NULL; + param->upload = NULL; param->info = ctx->info; - v = ¶m->v; + *(const apreq_value_t **)&v = ¶m->v; v->name = ctx->param_name; apr_brigade_flatten(ctx->bb, v->data, &len); v->size = len; v->data[v->size] = 0; + + if (parser->hook != NULL) { + s = APREQ_RUN_HOOK(parser->hook, param, NULL); + if (s != APR_SUCCESS) { + ctx->status = MFD_ERROR; + return s; + } + } + apr_table_addn(t, v->name, v->data); ctx->status = MFD_NEXTLINE; ctx->param_name = NULL; @@ -1172,8 +1153,8 @@ switch (s) { case APR_INCOMPLETE: - if (parser->hook) { - s = APREQ_RUN_HOOK(parser->hook, env, param, ctx->bb); + if (parser->hook != NULL) { + s = APREQ_RUN_HOOK(parser->hook, param, ctx->bb); if (s != APR_SUCCESS) { ctx->status = MFD_ERROR; return s; @@ -1181,13 +1162,14 @@ } APREQ_BRIGADE_SETASIDE(ctx->bb, pool); APREQ_BRIGADE_SETASIDE(ctx->in, pool); - s = apreq_brigade_concat(env, param->bb, ctx->bb); + s = apreq_brigade_concat(pool, parser->temp_dir, parser->brigade_limit, + param->upload, ctx->bb); return (s == APR_SUCCESS) ? APR_INCOMPLETE : s; case APR_SUCCESS: - if (parser->hook) { + if (parser->hook != NULL) { APR_BRIGADE_INSERT_TAIL(ctx->bb, ctx->eos); - s = APREQ_RUN_HOOK(parser->hook, env, param, ctx->bb); + s = APREQ_RUN_HOOK(parser->hook, param, ctx->bb); APR_BUCKET_REMOVE(ctx->eos); if (s != APR_SUCCESS) { ctx->status = MFD_ERROR; @@ -1196,7 +1178,8 @@ } apr_table_addn(t, param->v.name, param->v.data); APREQ_BRIGADE_SETASIDE(ctx->bb, pool); - s = apreq_brigade_concat(env, param->bb, ctx->bb); + s = apreq_brigade_concat(pool, parser->temp_dir, parser->brigade_limit, + param->upload, ctx->bb); if (s != APR_SUCCESS) return s; @@ -1215,7 +1198,7 @@ case MFD_MIXED: { - s = APREQ_RUN_PARSER(ctx->mix_parser, env, t, ctx->in); + s = APREQ_RUN_PARSER(ctx->mix_parser, t, ctx->in); switch (s) { case APR_SUCCESS: ctx->status = MFD_INIT; @@ -1240,17 +1223,16 @@ APREQ_DECLARE_HOOK(apreq_hook_disable_uploads) { - apreq_log(APREQ_ERROR APR_EGENERAL, env, - "Uploads are disabled for this request."); - return APR_EGENERAL; + return (bb == NULL) ? APR_SUCCESS : APR_EGENERAL; } APREQ_DECLARE_HOOK(apreq_hook_discard_brigade) { apr_status_t s = APR_SUCCESS; if (hook->next) - s = APREQ_RUN_HOOK(hook->next, env, param, bb); - apr_brigade_cleanup(bb); + s = APREQ_RUN_HOOK(hook->next, param, bb); + if (bb != NULL) + apr_brigade_cleanup(bb); return s; } @@ -1266,11 +1248,10 @@ } status; }; - APREQ_DECLARE_PARSER(apreq_parse_generic) { struct gen_ctx *ctx = parser->ctx; - apr_pool_t *pool = apreq_env_pool(env); + apr_pool_t *pool = parser->pool; apr_status_t s = APR_SUCCESS; apr_bucket *e = APR_BRIGADE_LAST(bb); unsigned saw_eos = 0; @@ -1280,8 +1261,8 @@ ctx->status = GEN_INCOMPLETE; ctx->param = apreq_make_param(pool, "_dummy_", strlen("_dummy_"), "", 0); - ctx->param->bb = apr_brigade_create(pool, apreq_env_bucket_alloc(env)); - ctx->param->info = apr_table_make(pool, APREQ_NELTS); + ctx->param->upload = apr_brigade_create(pool, parser->bucket_alloc); + ctx->param->info = apr_table_make(pool, APREQ_DEFAULT_NELTS); } @@ -1295,8 +1276,8 @@ e = APR_BUCKET_PREV(e); } - if (parser->hook) { - s = APREQ_RUN_HOOK(parser->hook, env, ctx->param, bb); + if (parser->hook != NULL) { + s = APREQ_RUN_HOOK(parser->hook, ctx->param, bb); if (s != APR_SUCCESS) { ctx->status = GEN_ERROR; return s; @@ -1304,7 +1285,8 @@ } APREQ_BRIGADE_SETASIDE(bb, pool); - s = apreq_brigade_concat(env, ctx->param->bb, bb); + s = apreq_brigade_concat(pool, parser->temp_dir, parser->brigade_limit, + ctx->param->upload, bb); if (s != APR_SUCCESS) { ctx->status = GEN_ERROR; @@ -1333,7 +1315,7 @@ APREQ_DECLARE_HOOK(apreq_hook_apr_xml_parser) { - apr_pool_t *pool = apreq_env_pool(env); + apr_pool_t *pool = hook->pool; struct xml_ctx *ctx = hook->ctx; apr_status_t s = APR_SUCCESS; apr_bucket *e; @@ -1358,12 +1340,10 @@ if (s == APR_SUCCESS) { ctx->status = XML_COMPLETE; if (hook->next) - s = APREQ_RUN_HOOK(hook->next, env, param, bb); + s = APREQ_RUN_HOOK(hook->next, param, bb); } else { ctx->status = XML_ERROR; - apreq_log(APREQ_ERROR s, env, "apreq_parse_xml: " - "apr_xml_parser_done failed"); } return s; } @@ -1375,8 +1355,6 @@ if (s != APR_SUCCESS) { ctx->status = XML_ERROR; - apreq_log(APREQ_ERROR s, env, "apreq_parse_xml: " - "apr_bucket_read failed"); return s; } @@ -1384,15 +1362,13 @@ if (s != APR_SUCCESS) { ctx->status = XML_ERROR; - apreq_log(APREQ_ERROR s, env, "apreq_parse_xml: " - "apr_xml_parser_feed failed"); return s; } } if (hook->next) - return APREQ_RUN_HOOK(hook->next, env, param, bb); + return APREQ_RUN_HOOK(hook->next, param, bb); return APR_SUCCESS; }
Added: httpd/apreq/branches/multi-env-unstable/src/apreq_parsers.h URL: http://svn.apache.org/viewcvs/httpd/apreq/branches/multi-env-unstable/src/apreq_parsers.h?view=auto&rev=151386 ============================================================================== --- httpd/apreq/branches/multi-env-unstable/src/apreq_parsers.h (added) +++ httpd/apreq/branches/multi-env-unstable/src/apreq_parsers.h Fri Feb 4 10:27:55 2005 @@ -0,0 +1,226 @@ +#ifndef APREQ_PARSERS_H +#define APREQ_PARSERS_H +/* These structs are defined below */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +typedef struct apreq_hook_t apreq_hook_t; +typedef struct apreq_parser_t apreq_parser_t; + +/** Parser arguments. */ +#define APREQ_PARSER_ARGS apreq_parser_t *parser, \ + apr_table_t *t, \ + apr_bucket_brigade *bb + +/** Hook arguments */ +#define APREQ_HOOK_ARGS apreq_hook_t *hook, \ + apreq_param_t *param, \ + apr_bucket_brigade *bb + +typedef apr_status_t (*apreq_parser_function_t)(APREQ_PARSER_ARGS); +typedef apr_status_t (*apreq_hook_function_t)(APREQ_HOOK_ARGS); + +/** + * Declares a API parser. + */ +#define APREQ_DECLARE_PARSER(f) APREQ_DECLARE_NONSTD(apr_status_t) \ + (f) (APREQ_PARSER_ARGS) + +/** + * Declares an API hook. + */ +#define APREQ_DECLARE_HOOK(f) APREQ_DECLARE_NONSTD(apr_status_t) \ + (f) (APREQ_HOOK_ARGS) + +/** + * Singly linked list of hooks. + * + */ +struct apreq_hook_t { + apreq_hook_function_t hook; + apreq_hook_t *next; + apr_pool_t *pool; + void *ctx; +}; + +/** + * Request parser with associated enctype and hooks. + * + */ +struct apreq_parser_t { + apreq_parser_function_t parser; + const char *content_type; + apr_pool_t *pool; + apr_bucket_alloc_t *bucket_alloc; + apr_size_t brigade_limit; + const char *temp_dir; + apreq_hook_t *hook; + void *ctx; +}; + + + + +/** + * Parse the incoming brigade into a table. Parsers normally + * consume all the buckets of the brigade during parsing. However + * parsers may leave "rejected" data in the brigade, even during a + * successful parse, so callers may need to clean up the brigade + * themselves (in particular, rejected buckets should not be + * passed back to the parser again). + * @remark bb == NULL is valid: the parser should return its + * public status: APR_INCOMPLETE, APR_SUCCESS, or an error code. + */ +#define APREQ_RUN_PARSER(psr,t,bb) (psr)->parser(psr,t,bb) + +/** + * Run the hook with the current parameter and the incoming + * bucket brigade. The hook may modify the brigade if necessary. + * Once all hooks have completed, the contents of the brigade will + * be added to the parameter's bb attribute. + * @return APR_SUCCESS on success. All other values represent errors. + */ +#define APREQ_RUN_HOOK(h,param,bb) (h)->hook(h,param,bb) + + +/** + * Rfc822 Header parser. It will reject all data + * after the first CRLF CRLF sequence (an empty line). + * See #APREQ_RUN_PARSER for more info on rejected data. + */ +APREQ_DECLARE_PARSER(apreq_parse_headers); + +/** + * Rfc2396 application/x-www-form-urlencoded parser. + */ +APREQ_DECLARE_PARSER(apreq_parse_urlencoded); + +/** + * Rfc2388 multipart/form-data (and XForms 1.0 multipart/related) + * parser. It will reject any buckets representing preamble and + * postamble text (this is normal behavior, not an error condition). + * See #APREQ_RUN_PARSER for more info on rejected data. + */ +APREQ_DECLARE_PARSER(apreq_parse_multipart); + +/** + * Generic parser. No table entries will be added to + * the req->body table by this parser. The parser creates + * a dummy apreq_param_t to pass to any configured hooks. If + * no hooks are configured, the dummy param's bb slot will + * contain a copy of the request body. It can be retrieved + * by casting the parser's ctx pointer to (apreq_param_t **). + */ +APREQ_DECLARE_PARSER(apreq_parse_generic); + +/** + * apr_xml_parser hook. It will parse until EOS appears. + * The parsed document isn't available until parsing has + * completed successfully. The hook's ctx pointer may + * be cast as (apr_xml_doc **) to retrieve the + * parsed document. + */ +APREQ_DECLARE_HOOK(apreq_hook_apr_xml_parser); + +/** + * Construct a parser. + * + * @param pool Pool used to allocate the parser. + * @param enctype Content-type that this parser can deal with. + * @param parser The parser function. + * @param hook Hooks to asssociate this parser with. + * @param ctx Parser's internal scratch pad. + * @return New parser. + */ +APREQ_DECLARE(apreq_parser_t *) + apreq_make_parser(apr_pool_t *pool, + apr_bucket_alloc_t *bucket_alloc, + const char *content_type, + apreq_parser_function_t parser, + apr_size_t brigade_limit, + const char *temp_dir, + apreq_hook_t *hook, + void *ctx); + +/** + * Construct a hook. + * + * @param pool used to allocate the hook. + * @param hook The hook function. + * @param next List of other hooks for this hook to call on. + * @param ctx Hook's internal scratch pad. + * @return New hook. + */ +APREQ_DECLARE(apreq_hook_t *) + apreq_make_hook(apr_pool_t *pool, + apreq_hook_function_t hook, + apreq_hook_t *next, + void *ctx); + + +/** + * Add a new hook to the end of the parser's hook list. + * + * @param p Parser. + * @param h Hook to append. + */ +APREQ_DECLARE(apr_status_t) apreq_parser_add_hook(apreq_parser_t *p, + apreq_hook_t *h); + + +/** + * Create the default parser associated with the + * current request's Content-Type (if possible). + * @param env The current environment. + * @param hook Hook(s) to add to the parser. + * @return New parser, NULL if the Content-Type is + * unrecognized. + * + * @param env The current environment. + * @param hook Additional hooks to supply the parser with. + * @return The parser; NULL if the environment's + * Content-Type is unrecognized. + */ +APREQ_DECLARE(apreq_parser_function_t)apreq_parser(const char *enctype); + + +/** + * Register a new parsing function with a MIME enctype. + * Registered parsers are added to apreq_parser()'s + * internal lookup table. + * + * @param enctype The MIME type. + * @param parser The function to use during parsing. Setting + * parser == NULL will remove an existing parser. + * @remark This is not a thread-safe operation, so applications + * should only call this during process startup, + * or within a request-thread mutex. + */ + +APREQ_DECLARE(void) apreq_register_parser(const char *enctype, + apreq_parser_function_t parser); + + +/** + * Returns APR_EGENERAL. Effectively disables mfd parser + * if a file-upload field is present. + * + */ +APREQ_DECLARE_HOOK(apreq_hook_disable_uploads); + +/** + * Calls apr_brigade_cleanup on the incoming brigade + * after passing the brigade to any subsequent hooks. + */ +APREQ_DECLARE_HOOK(apreq_hook_discard_brigade); + + +#ifdef __cplusplus +} + +#endif +#endif /* APREQ_PARSERS_H */ + + Modified: httpd/apreq/branches/multi-env-unstable/t/Makefile.am URL: http://svn.apache.org/viewcvs/httpd/apreq/branches/multi-env-unstable/t/Makefile.am?view=diff&r1=151385&r2=151386 ============================================================================== --- httpd/apreq/branches/multi-env-unstable/t/Makefile.am (original) +++ httpd/apreq/branches/multi-env-unstable/t/Makefile.am Fri Feb 4 10:27:55 2005 @@ -3,7 +3,7 @@ LDFLAGS = @APR_LDFLAGS@ @APU_LDFLAGS@ noinst_LIBRARIES = libapreq2_tests.a -libapreq2_tests_a_SOURCES = CuTest.h test_apreq.h CuTest.c version.c cookie.c params.c parsers.c +libapreq2_tests_a_SOURCES = test_apreq.h CuTest.h CuTest.c version.c cookie.c params.c parsers.c check_PROGRAMS = testall testall_LDADD = libapreq2_tests.a Modified: httpd/apreq/branches/multi-env-unstable/t/cookie.c URL: http://svn.apache.org/viewcvs/httpd/apreq/branches/multi-env-unstable/t/cookie.c?view=diff&r1=151385&r2=151386 ============================================================================== --- httpd/apreq/branches/multi-env-unstable/t/cookie.c (original) +++ httpd/apreq/branches/multi-env-unstable/t/cookie.c Fri Feb 4 10:27:55 2005 @@ -15,56 +15,66 @@ */ #include "apreq_env.h" -#include "apreq.h" -#include "apreq_cookie.h" #include "apr_strings.h" #include "test_apreq.h" +#include "apreq_cookie.h" + +static const char nscookies[] = "a=1; foo=bar; fl=left; fr=right;bad; " + "ns=foo=1&bar=2,frl=right-left; " + "flr=left-right; fll=left-left; " + "good_one=1;bad"; -static apreq_jar_t *j = NULL; +static apr_table_t *jar; static void jar_make(CuTest *tc) { - j = apreq_jar(apreq_env_make_custom(p, NULL, NULL, NULL, NULL, NULL), - "a=1; foo=bar; fl=left; fr=right;bad; ns=foo=1&bar=2," - "frl=right-left; flr=left-right; fll=left-left; good_one=1;bad"); - CuAssertPtrNotNull(tc, j); + apr_status_t s; + + jar = apr_table_make(p, APREQ_DEFAULT_NELTS); + CuAssertPtrNotNull(tc, jar); + s = apreq_parse_cookie_header(p, jar, nscookies); + CuAssertIntEquals(tc, APREQ_ERROR_NOTOKEN, s); } -static void jar_table_get(CuTest *tc) + +static void jar_get(CuTest *tc) { const char *val; - val = apr_table_get(j->cookies,"a"); + val = apr_table_get(jar,"a"); CuAssertStrEquals(tc,"1",val); /* ignore wacky cookies that don't have an '=' sign */ - val = apr_table_get(j->cookies,"bad"); + val = apr_table_get(jar,"bad"); CuAssertPtrEquals(tc,NULL,val); /* accept wacky cookies that contain multiple '=' */ - val = apr_table_get(j->cookies,"ns"); + val = apr_table_get(jar,"ns"); CuAssertStrEquals(tc,"foo=1&bar=2",val); - val = apr_table_get(j->cookies,"foo"); + val = apr_table_get(jar,"foo"); CuAssertStrEquals(tc,"bar",val); - val = apr_table_get(j->cookies,"fl"); + val = apr_table_get(jar,"fl"); CuAssertStrEquals(tc,"left",val); - val = apr_table_get(j->cookies,"fr"); + val = apr_table_get(jar,"fr"); CuAssertStrEquals(tc,"right",val); - val = apr_table_get(j->cookies,"frl"); + val = apr_table_get(jar,"frl"); CuAssertStrEquals(tc,"right-left",val); - val = apr_table_get(j->cookies,"flr"); + val = apr_table_get(jar,"flr"); CuAssertStrEquals(tc,"left-right",val); - val = apr_table_get(j->cookies,"fll"); + val = apr_table_get(jar,"fll"); CuAssertStrEquals(tc,"left-left",val); } static void netscape_cookie(CuTest *tc) { + char *val; apreq_cookie_t *c; apreq_cookie_version_t version = APREQ_COOKIE_VERSION_NETSCAPE; - c = apreq_cookie(j,"foo"); + *(const char **)&val = apr_table_get(jar, "foo"); + CuAssertPtrNotNull(tc, val); + c = apreq_value_to_cookie(val); CuAssertStrEquals(tc,"bar",apreq_cookie_value(c)); CuAssertIntEquals(tc, version,c->version); @@ -109,15 +119,14 @@ expires), apreq_cookie_as_string(c,p)); } - static void ua_version(CuTest *tc) { apreq_cookie_version_t v; char version[] = "$Version=\"1\""; - v = apreq_ua_cookie_version(apreq_env_make_custom(p, NULL, NULL, NULL, NULL, NULL)); + v = apreq_ua_cookie_version(apreq_handle_custom(p, NULL, NULL, NULL, NULL, 0, NULL)); CuAssertIntEquals(tc, APREQ_COOKIE_VERSION_NETSCAPE, v); - v = apreq_ua_cookie_version(apreq_env_make_custom(p, NULL, NULL, version, NULL, NULL)); + v = apreq_ua_cookie_version(apreq_handle_custom(p, NULL, NULL, version, NULL, 0, NULL)); CuAssertIntEquals(tc, APREQ_COOKIE_VERSION_RFC, v); } @@ -127,7 +136,7 @@ CuSuite *suite = CuSuiteNew("Cookie"); SUITE_ADD_TEST(suite, jar_make); - SUITE_ADD_TEST(suite, jar_table_get); + SUITE_ADD_TEST(suite, jar_get); SUITE_ADD_TEST(suite, netscape_cookie); SUITE_ADD_TEST(suite, rfc_cookie); SUITE_ADD_TEST(suite, ua_version); Modified: httpd/apreq/branches/multi-env-unstable/t/params.c URL: http://svn.apache.org/viewcvs/httpd/apreq/branches/multi-env-unstable/t/params.c?view=diff&r1=151385&r2=151386 ============================================================================== --- httpd/apreq/branches/multi-env-unstable/t/params.c (original) +++ httpd/apreq/branches/multi-env-unstable/t/params.c Fri Feb 4 10:27:55 2005 @@ -15,40 +15,48 @@ */ #include "apreq_env.h" -#include "apreq.h" -#include "apreq_params.h" #include "apr_strings.h" #include "test_apreq.h" -static apreq_request_t *r = NULL; +static const char query_string[] = "a=1;quux=foo+bar&a=2&plus=%2B;" + "uplus=%U002b;okie=dokie;" + "novalue1;novalue2="; +static apr_table_t *args; + +#define strtoval(s) \ + ((const apreq_value_t *)(s - offsetof(apreq_value_t, data))) static void request_make(CuTest *tc) { - r = apreq_request(apreq_env_make_custom(p, NULL, NULL, NULL, NULL, NULL), "a=1;quux=foo+bar&a=2&plus=%2B;uplus=%U002b;okie=dokie;novalue1;novalue2="); - CuAssertPtrNotNull(tc, r); - CuAssertIntEquals(tc,8, apr_table_elts(r->args)->nelts); + apr_status_t s; + args = apr_table_make(p, APREQ_DEFAULT_NELTS); + CuAssertPtrNotNull(tc, args); + s = apreq_parse_query_string(p, args, query_string); + CuAssertIntEquals(tc, APR_SUCCESS, s); + CuAssertIntEquals(tc,8, apr_table_elts(args)->nelts); } + static void request_args_get(CuTest *tc) { const char *val; - apreq_value_t *v; + const apreq_value_t *v; - val = apr_table_get(r->args,"a"); + val = apr_table_get(args,"a"); CuAssertStrEquals(tc,"1",val); - val = apr_table_get(r->args,"quux"); + val = apr_table_get(args,"quux"); CuAssertStrEquals(tc,"foo bar",val); - v = apreq_strtoval(val); + v = strtoval(val); CuAssertIntEquals(tc, 7, v->size); - val = apr_table_get(r->args,"plus"); + val = apr_table_get(args,"plus"); CuAssertStrEquals(tc,"+",val); - val = apr_table_get(r->args,"uplus"); + val = apr_table_get(args,"uplus"); CuAssertStrEquals(tc,"+",val); - val = apr_table_get(r->args,"okie"); + val = apr_table_get(args,"okie"); CuAssertStrEquals(tc,"dokie",val); - val = apr_table_get(r->args,"novalue1"); + val = apr_table_get(args,"novalue1"); CuAssertStrEquals(tc,"",val); - val = apr_table_get(r->args,"novalue2"); + val = apr_table_get(args,"novalue2"); CuAssertStrEquals(tc,"",val); } @@ -57,12 +65,13 @@ { const char *val; apr_array_header_t *arr; - arr = apreq_params_as_array(p,r,"a"); + arr = apreq_params_as_array(p,args,"a"); CuAssertIntEquals(tc,2,arr->nelts); - val = apreq_params_as_string(p,r,"a",APREQ_JOIN_AS_IS); + val = apreq_params_as_string(p,args,"a",APREQ_JOIN_AS_IS); CuAssertStrEquals(tc,"1, 2", val); } + static void string_decoding_in_place(CuTest *tc) { char *s1 = apr_palloc(p,4096); @@ -120,37 +129,34 @@ CuAssertStrNEquals(tc, "20", val, 2); s = apreq_header_attribute(hdr, "age", 3, &val, &vlen); - CuAssertIntEquals(tc, APR_EGENERAL, s); + CuAssertIntEquals(tc, APREQ_ERROR_BADTOKEN, s); s = apreq_header_attribute(hdr, "no-quote", 8, &val, &vlen); - CuAssertIntEquals(tc, APR_EGENERAL, s); + CuAssertIntEquals(tc, APREQ_ERROR_BADTOKEN, s); } static void make_values(CuTest *tc) { - apreq_value_t *v1, *v2; + apreq_value_t *v; apr_size_t len = 4; char *name = apr_palloc(p,len); char *val = apr_palloc(p,len); strcpy(name, "foo"); strcpy(val, "bar"); - v1 = apreq_make_value(p, name, len, val, len); - CuAssertStrEquals(tc, name, v1->name); - CuAssertIntEquals(tc, len, v1->size); - CuAssertStrEquals(tc, val, v1->data); - - v2 = apreq_copy_value(p, v1); - CuAssertStrEquals(tc, name, v2->name); - CuAssertIntEquals(tc, len, v2->size); - CuAssertStrEquals(tc, val, v2->data); + v = apreq_make_value(p, name, len, val, len); + CuAssertStrEquals(tc, name, v->name); + CuAssertIntEquals(tc, len, v->size); + CuAssertStrEquals(tc, val, v->data); + } static void make_param(CuTest *tc) { apreq_param_t *param, *result; + apr_status_t s; apr_size_t nlen = 3, vlen = 11; char *name = apr_palloc(p,nlen+1); char *val = apr_palloc(p,vlen+1); @@ -166,7 +172,7 @@ encode = apreq_encode_param(p, param); CuAssertStrEquals(tc, "foo=bar+%3e+alpha", encode); - result = apreq_decode_param(p, encode, nlen, vlen+2); + s = apreq_decode_param(&result, p, encode, nlen, vlen+2); CuAssertStrEquals(tc, name, result->v.name); CuAssertIntEquals(tc, vlen, result->v.size); CuAssertStrEquals(tc, val, result->v.data); @@ -223,6 +229,7 @@ CuAssertStrEquals(tc, hay, full); } + CuSuite *testparam(void) { CuSuite *suite = CuSuiteNew("Param"); @@ -236,7 +243,6 @@ SUITE_ADD_TEST(suite, quote_strings); SUITE_ADD_TEST(suite, make_param); SUITE_ADD_TEST(suite, test_memmem); - return suite; } Modified: httpd/apreq/branches/multi-env-unstable/t/parsers.c URL: http://svn.apache.org/viewcvs/httpd/apreq/branches/multi-env-unstable/t/parsers.c?view=diff&r1=151385&r2=151386 ============================================================================== --- httpd/apreq/branches/multi-env-unstable/t/parsers.c (original) +++ httpd/apreq/branches/multi-env-unstable/t/parsers.c Fri Feb 4 10:27:55 2005 @@ -15,8 +15,6 @@ */ #include "apreq_env.h" -#include "apreq.h" -#include "apreq_params.h" #include "apr_strings.h" #include "apr_xml.h" #include "test_apreq.h" @@ -24,6 +22,7 @@ #define CRLF "\015\012" static char url_data[] = "alpha=one&beta=two;omega=last%2"; + static char form_data[] = "--AaB03x" CRLF /* 10 chars 012345678901234567890123456789012345678901234567890123456789 */ @@ -99,64 +98,51 @@ "--AaB03x--" CRLF; -extern apr_table_t *table; +#define URL_ENCTYPE "application/x-www-form-urlencoded" +#define MFD_ENCTYPE "multipart/form-data" +#define MR_ENCTYPE "multipart/related" +#define XML_ENCTYPE "application/xml" static void locate_default_parsers(CuTest *tc) { - apreq_request_t *req; - apreq_parser_t *parser; + apreq_parser_function_t f; - req = apreq_request(apreq_env_make_custom(p, NULL, NULL, NULL, "application/x-www-form-urlencoded", NULL), NULL); - CuAssertPtrNotNull(tc, req); - CuAssertStrEquals(tc, APREQ_URL_ENCTYPE, apreq_enctype(req->env)); - parser = apreq_parser(req->env, NULL); - CuAssertPtrNotNull(tc, parser); - CuAssertStrEquals(tc, APREQ_URL_ENCTYPE, parser->enctype); - - req = apreq_request(apreq_env_make_custom(p, NULL, NULL, NULL, APREQ_MFD_ENCTYPE - "; charset=\"iso-8859-1\"; boundary=\"AaB03x\"", - NULL), NULL); - CuAssertPtrNotNull(tc, req); - parser = apreq_parser(req->env, NULL); - CuAssertPtrNotNull(tc, parser); - CuAssertStrNEquals(tc, APREQ_MFD_ENCTYPE, parser->enctype, - strlen(APREQ_MFD_ENCTYPE)); - - req = apreq_request(apreq_env_make_custom(p, NULL, NULL, NULL, "multipart/related; boundary=f93dcbA3; " - "type=application/xml; start=\"<[EMAIL PROTECTED]>\"", - NULL), NULL); - CuAssertPtrNotNull(tc, req); - parser = apreq_parser(req->env, NULL); - CuAssertPtrNotNull(tc, parser); - CuAssertStrNEquals(tc, "multipart/related", parser->enctype, - strlen("multipart/related")); + /* initialize default-parser hash */ + apreq_register_parser(NULL, NULL); + + f = apreq_parser(URL_ENCTYPE); + CuAssertPtrNotNull(tc, f); + CuAssertPtrEquals(tc, apreq_parse_urlencoded, f); + + f = apreq_parser(MFD_ENCTYPE); + CuAssertPtrNotNull(tc, f); + CuAssertPtrEquals(tc, apreq_parse_multipart, f); + + f = apreq_parser(MR_ENCTYPE); + CuAssertPtrNotNull(tc, f); + CuAssertPtrEquals(tc, apreq_parse_multipart, f); } - static void parse_urlencoded(CuTest *tc) { const char *val; - apreq_env_handle_t *env; - apreq_request_t *req; apr_status_t rv; - const char *enctype; + apr_bucket_alloc_t *ba; apr_bucket_brigade *bb; + apreq_parser_t *parser; + apr_table_t *body; - bb = apr_brigade_create(p, apr_bucket_alloc_create(p)); - - env = apreq_env_make_custom(p, NULL, NULL, NULL, APREQ_URL_ENCTYPE, bb); - req = apreq_request(env, NULL); - - CuAssertPtrNotNull(tc, req); - - enctype = apreq_enctype(req->env); - CuAssertStrEquals(tc, APREQ_URL_ENCTYPE, enctype); + body = apr_table_make(p, APREQ_DEFAULT_NELTS); + ba = apr_bucket_alloc_create(p); + bb = apr_brigade_create(p, ba); + parser = apreq_make_parser(p, ba, URL_ENCTYPE, apreq_parse_urlencoded, + 100, NULL, NULL, NULL); APR_BRIGADE_INSERT_HEAD(bb, apr_bucket_immortal_create(url_data,strlen(url_data), bb->bucket_alloc)); - rv = apreq_env_read(env, APR_BLOCK_READ, 65536); + rv = APREQ_RUN_PARSER(parser, body, bb); CuAssertIntEquals(tc, APR_INCOMPLETE, rv); APR_BRIGADE_INSERT_HEAD(bb, @@ -165,40 +151,44 @@ APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_eos_create(bb->bucket_alloc)); - rv = apreq_env_read(env, APR_BLOCK_READ, 65536); + rv = APREQ_RUN_PARSER(parser, body, bb); CuAssertIntEquals(tc, APR_SUCCESS, rv); - CuAssertPtrNotNull(tc, req->body); - val = apr_table_get(req->body,"alpha"); - + val = apr_table_get(body,"alpha"); CuAssertStrEquals(tc, "one", val); - val = apr_table_get(req->body,"beta"); + val = apr_table_get(body,"beta"); CuAssertStrEquals(tc, "two", val); - val = apr_table_get(req->body,"omega"); + val = apr_table_get(body,"omega"); CuAssertStrEquals(tc, "last+last", val); } static void parse_multipart(CuTest *tc) { - apr_status_t rv; apr_size_t i, j; apr_bucket_alloc_t *ba; + for (j = 0; j <= strlen(form_data); ++j) { - apr_bucket_brigade *bb; ba = apr_bucket_alloc_create(p); - bb = apr_brigade_create(p, ba); for (i = 0; i <= strlen(form_data); ++i) { - apreq_env_handle_t *env; - apreq_request_t *req; - apr_bucket_brigade *vb; const char *val; char *val2; apr_size_t len; - apr_table_t *t; + apr_table_t *t, *body; + apreq_parser_t *parser; + apr_bucket_brigade *bb, *vb; + apr_status_t rv; + + bb = apr_brigade_create(p, ba); + body = apr_table_make(p, APREQ_DEFAULT_NELTS); + parser = apreq_make_parser(p, ba, MFD_ENCTYPE + "; charset=\"iso-8859-1\"" + "; boundary=\"AaB03x\"", + apreq_parse_multipart, + 1000, NULL, NULL, NULL); apr_bucket *e = apr_bucket_immortal_create(form_data, strlen(form_data), @@ -208,13 +198,6 @@ APR_BRIGADE_INSERT_HEAD(bb, e); APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_eos_create(bb->bucket_alloc)); - env = apreq_env_make_custom(p, NULL, NULL, NULL, - APREQ_MFD_ENCTYPE "; charset=\"iso-8859-1\"; boundary=\"AaB03x\"", - bb); - req = apreq_request(env, NULL); - CuAssertPtrNotNull(tc, req); - CuAssertStrEquals(tc, APREQ_MFD_ENCTYPE, apreq_enctype(req->env)); - /* Split e into three buckets */ apr_bucket_split(e, j); f = APR_BUCKET_NEXT(e); @@ -224,28 +207,23 @@ apr_bucket_split(f, i - j); tail = apr_brigade_split(bb, f); - req->body = NULL; - req->parser = NULL; - req->body_status = APR_EINIT; - rv = apreq_env_read(env, APR_BLOCK_READ, 65536); + rv = APREQ_RUN_PARSER(parser, body, bb); CuAssertIntEquals(tc, (j < strlen(form_data)) ? APR_INCOMPLETE : APR_SUCCESS, rv); - APR_BRIGADE_CONCAT(bb, tail); - rv = apreq_env_read(env, APR_BLOCK_READ, 65536); + rv = APREQ_RUN_PARSER(parser, body, tail); CuAssertIntEquals(tc, APR_SUCCESS, rv); - CuAssertPtrNotNull(tc, req->body); - CuAssertIntEquals(tc, 2, apr_table_elts(req->body)->nelts); + CuAssertIntEquals(tc, 2, apr_table_elts(body)->nelts); - val = apr_table_get(req->body,"field1"); + val = apr_table_get(body,"field1"); CuAssertStrEquals(tc, "Joe owes =80100.", val); - t = apreq_value_to_param(apreq_strtoval(val))->info; + t = apreq_value_to_param(val)->info; val = apr_table_get(t, "content-transfer-encoding"); CuAssertStrEquals(tc,"quoted-printable", val); - val = apr_table_get(req->body, "pics"); + val = apr_table_get(body, "pics"); CuAssertStrEquals(tc, "file1.txt", val); - t = apreq_value_to_param(apreq_strtoval(val))->info; - vb = apreq_value_to_param(apreq_strtoval(val))->bb; + t = apreq_value_to_param(val)->info; + vb = apreq_value_to_param(val)->upload; apr_brigade_pflatten(vb, &val2, &len, p); CuAssertIntEquals(tc,strlen("... contents of file1.txt ..." CRLF), len); CuAssertStrNEquals(tc,"... contents of file1.txt ..." CRLF, val2, len); @@ -254,6 +232,7 @@ apr_brigade_cleanup(vb); apr_brigade_cleanup(bb); } + apr_bucket_alloc_destroy(ba); apr_pool_clear(p); } @@ -262,68 +241,73 @@ static void parse_disable_uploads(CuTest *tc) { const char *val; - apr_table_t *t; + apr_table_t *t, *body; apr_status_t rv; - apreq_request_t *req = apreq_request(apreq_env_make_custom(p, NULL, NULL, NULL, APREQ_MFD_ENCTYPE - "; charset=\"iso-8859-1\"; boundary=\"AaB03x\"", - NULL), NULL); - apr_bucket_brigade *bb = apr_brigade_create(p, - apr_bucket_alloc_create(p)); - apr_bucket *e = apr_bucket_immortal_create(form_data, - strlen(form_data), - bb->bucket_alloc); + apr_bucket_alloc_t *ba; + apr_bucket_brigade *bb; + apr_bucket *e; + apreq_parser_t *parser; + apreq_hook_t *hook; - CuAssertPtrNotNull(tc, req); - CuAssertStrEquals(tc, APREQ_MFD_ENCTYPE - "; charset=\"iso-8859-1\"; boundary=\"AaB03x\"", apreq_env_content_type(req->env)); + ba = apr_bucket_alloc_create(p); + bb = apr_brigade_create(p, ba); + e = apr_bucket_immortal_create(form_data, strlen(form_data), ba); APR_BRIGADE_INSERT_HEAD(bb, e); APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_eos_create(bb->bucket_alloc)); - req->body = NULL; - req->parser = apreq_parser(req->env, apreq_make_hook(p, - apreq_hook_disable_uploads, NULL, NULL)); + body = apr_table_make(p, APREQ_DEFAULT_NELTS); + hook = apreq_make_hook(p, apreq_hook_disable_uploads, NULL, NULL); - rv = apreq_parse_request(req,bb); + parser = apreq_make_parser(p, ba, MFD_ENCTYPE + "; charset=\"iso-8859-1\"" + "; boundary=\"AaB03x\"", + apreq_parse_multipart, + 1000, NULL, hook, NULL); + + + rv = APREQ_RUN_PARSER(parser, body, bb); CuAssertIntEquals(tc, APR_EGENERAL, rv); - CuAssertPtrNotNull(tc, req->body); - CuAssertIntEquals(tc, 1, apr_table_elts(req->body)->nelts); + CuAssertIntEquals(tc, 1, apr_table_elts(body)->nelts); - val = apr_table_get(req->body,"field1"); + val = apr_table_get(body,"field1"); CuAssertStrEquals(tc, "Joe owes =80100.", val); - t = apreq_value_to_param(apreq_strtoval(val))->info; + t = apreq_value_to_param(val)->info; val = apr_table_get(t, "content-transfer-encoding"); CuAssertStrEquals(tc,"quoted-printable", val); - val = apr_table_get(req->body, "pics"); + val = apr_table_get(body, "pics"); CuAssertPtrEquals(tc, NULL, val); } + static void parse_generic(CuTest *tc) { char *val; apr_size_t vlen; apr_status_t rv; apreq_param_t *dummy; - apreq_request_t *req = apreq_request(apreq_env_make_custom(p, NULL, NULL, NULL, APREQ_XML_ENCTYPE, NULL), NULL); - apr_bucket_brigade *bb = apr_brigade_create(p, - apr_bucket_alloc_create(p)); + apreq_parser_t *parser; + apr_table_t *body; + apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p); + apr_bucket_brigade *bb = apr_brigade_create(p, ba); apr_bucket *e = apr_bucket_immortal_create(xml_data, - strlen(xml_data), - bb->bucket_alloc); + strlen(xml_data), + ba); - CuAssertPtrNotNull(tc, req); APR_BRIGADE_INSERT_HEAD(bb, e); - APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_eos_create(bb->bucket_alloc)); + APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_eos_create(ba)); + + body = apr_table_make(p, APREQ_DEFAULT_NELTS); + + parser = apreq_make_parser(p, ba, "application/xml", + apreq_parse_generic, 1000, NULL, NULL, NULL); - req->body = NULL; - req->parser = apreq_make_parser(p, APREQ_XML_ENCTYPE, - apreq_parse_generic, NULL, NULL); - rv = apreq_parse_request(req,bb); + rv = APREQ_RUN_PARSER(parser, body, bb); CuAssertIntEquals(tc, APR_SUCCESS, rv); - dummy = *(apreq_param_t **)req->parser->ctx; + dummy = *(apreq_param_t **)parser->ctx; CuAssertPtrNotNull(tc, dummy); - apr_brigade_pflatten(dummy->bb, &val, &vlen, p); + apr_brigade_pflatten(dummy->upload, &val, &vlen, p); CuAssertIntEquals(tc, strlen(xml_data), vlen); CuAssertStrNEquals(tc, xml_data, val, vlen); @@ -333,29 +317,31 @@ { apr_status_t rv; apreq_param_t *dummy; - apreq_request_t *req = apreq_request(apreq_env_make_custom(p, NULL, NULL, NULL, APREQ_XML_ENCTYPE, NULL), NULL); - apr_bucket_brigade *bb = apr_brigade_create(p, - apr_bucket_alloc_create(p)); + apreq_parser_t *parser; + apreq_hook_t *hook; + apr_table_t *body; + apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p); + apr_bucket_brigade *bb = apr_brigade_create(p, ba); apr_bucket *e = apr_bucket_immortal_create(xml_data, - strlen(xml_data), - bb->bucket_alloc); + strlen(xml_data), + ba); - CuAssertPtrNotNull(tc, req); APR_BRIGADE_INSERT_HEAD(bb, e); - APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_eos_create(bb->bucket_alloc)); + APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_eos_create(ba)); - req->body = NULL; - req->parser = apreq_make_parser(p, APREQ_XML_ENCTYPE, - apreq_parse_generic, - apreq_make_hook(p, apreq_hook_discard_brigade, - NULL,NULL), NULL); - rv = apreq_parse_request(req,bb); + body = apr_table_make(p, APREQ_DEFAULT_NELTS); + + hook = apreq_make_hook(p, apreq_hook_discard_brigade, NULL, NULL); + parser = apreq_make_parser(p, ba, "application/xml", + apreq_parse_generic, 1000, NULL, hook, NULL); + + + rv = APREQ_RUN_PARSER(parser, body, bb); CuAssertIntEquals(tc, APR_SUCCESS, rv); - dummy = *(apreq_param_t **)req->parser->ctx; + dummy = *(apreq_param_t **)parser->ctx; CuAssertPtrNotNull(tc, dummy); - CuAssertPtrNotNull(tc, dummy->bb); - CuAssertTrue(tc, APR_BRIGADE_EMPTY(dummy->bb)); - + CuAssertPtrNotNull(tc, dummy->upload); + CuAssertTrue(tc, APR_BRIGADE_EMPTY(dummy->upload)); } @@ -371,34 +357,37 @@ apr_status_t rv; int ns_map = 0; apr_xml_doc *doc; + apr_table_t *body; + apreq_parser_t *parser; apreq_hook_t *xml_hook; apreq_param_t *param; - apreq_request_t *req = apreq_request(apreq_env_make_custom(p, NULL, NULL, NULL, ct, NULL), NULL); - apr_bucket_brigade *bb = apr_brigade_create(p, - apr_bucket_alloc_create(p)); + apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p); + apr_bucket_brigade *bb = apr_brigade_create(p, ba); apr_bucket *e = apr_bucket_immortal_create(rel_data, strlen(rel_data), bb->bucket_alloc); - CuAssertPtrNotNull(tc, req); APR_BRIGADE_INSERT_HEAD(bb, e); APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_eos_create(bb->bucket_alloc)); xml_hook = apreq_make_hook(p, apreq_hook_apr_xml_parser, NULL, NULL); - req->body = NULL; - req->parser = apreq_make_parser(p, ct, - apreq_parse_multipart, xml_hook, NULL); - rv = apreq_parse_request(req,bb); + body = apr_table_make(p, APREQ_DEFAULT_NELTS); + parser = apreq_make_parser(p, ba, ct, apreq_parse_multipart, + 1000, NULL, xml_hook, NULL); + + rv = APREQ_RUN_PARSER(parser, body, bb); CuAssertIntEquals(tc, APR_SUCCESS, rv); - CuAssertPtrNotNull(tc, req->body); - param = apreq_param(req, "<[EMAIL PROTECTED]>"); + val = apr_table_get(body, "<[EMAIL PROTECTED]>"); + CuAssertPtrNotNull(tc, val); + param = apreq_value_to_param(val); + CuAssertPtrNotNull(tc, param); CuAssertPtrNotNull(tc, param->info); val = apr_table_get(param->info, "Content-Length"); CuAssertStrEquals(tc, "400", val); - CuAssertPtrNotNull(tc, param->bb); - apr_brigade_pflatten(param->bb, &val2, &vlen, p); + CuAssertPtrNotNull(tc, param->upload); + apr_brigade_pflatten(param->upload, &val2, &vlen, p); CuAssertIntEquals(tc, 400, vlen); CuAssertStrNEquals(tc,rel_data + 122, val2, 400); @@ -408,17 +397,22 @@ CuAssertIntEquals(tc, 400 - 22, vlen); CuAssertStrNEquals(tc, rel_data + 122 + 23, val, 400 - 23); - param = apreq_param(req, "<[EMAIL PROTECTED]>"); + + val = apr_table_get(body, "<[EMAIL PROTECTED]>"); + CuAssertPtrNotNull(tc, val); + param = apreq_value_to_param(val); CuAssertPtrNotNull(tc, param); - CuAssertPtrNotNull(tc, param->bb); - apr_brigade_pflatten(param->bb, &val2, &vlen, p); + CuAssertPtrNotNull(tc, param->upload); + apr_brigade_pflatten(param->upload, &val2, &vlen, p); CuAssertIntEquals(tc, dlen, vlen); CuAssertStrNEquals(tc, data, val2, vlen); - param = apreq_param(req, "<[EMAIL PROTECTED]>"); + val = apr_table_get(body, "<[EMAIL PROTECTED]>"); + CuAssertPtrNotNull(tc, val); + param = apreq_value_to_param(val); CuAssertPtrNotNull(tc, param); - CuAssertPtrNotNull(tc, param->bb); - apr_brigade_pflatten(param->bb, &val2, &vlen, p); + CuAssertPtrNotNull(tc, param->upload); + apr_brigade_pflatten(param->upload, &val2, &vlen, p); CuAssertIntEquals(tc, dlen, vlen); CuAssertStrNEquals(tc, data, val2, vlen); } @@ -438,54 +432,56 @@ apreq_param_t *param; const apr_array_header_t *arr; array_elt *elt; - apreq_request_t *req = apreq_request(apreq_env_make_custom(p, NULL, NULL, NULL, APREQ_MFD_ENCTYPE - "; charset=\"iso-8859-1\"; boundary=\"AaB03x\"", NULL), - NULL); - apr_bucket_brigade *bb = apr_brigade_create(p, - apr_bucket_alloc_create(p)); + char ct[] = MFD_ENCTYPE "; charset=\"iso-8859-1\"; boundary=\"AaB03x\""; + apreq_parser_t *parser; + apr_table_t *body = apr_table_make(p, APREQ_DEFAULT_NELTS); + apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p); + apr_bucket_brigade *bb = apr_brigade_create(p, ba); apr_bucket *e = apr_bucket_immortal_create(mix_data, strlen(mix_data), bb->bucket_alloc); - CuAssertPtrNotNull(tc, req); APR_BRIGADE_INSERT_HEAD(bb, e); APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_eos_create(bb->bucket_alloc)); - rv = apreq_parse_request(req,bb); + parser = apreq_make_parser(p, ba, ct, apreq_parse_multipart, + 1000, NULL, NULL, NULL); + + rv = APREQ_RUN_PARSER(parser, body, bb); CuAssertIntEquals(tc, APR_SUCCESS, rv); - param = apreq_param(req, "submit-name"); - CuAssertPtrNotNull(tc, param); - CuAssertStrEquals(tc, "Larry", param->v.data); + val = apr_table_get(body, "submit-name"); + CuAssertPtrNotNull(tc, val); + CuAssertStrEquals(tc, "Larry", val); - val = apr_table_get(req->body,"field1"); + val = apr_table_get(body,"field1"); CuAssertStrEquals(tc, "Joe owes =80100.", val); - param = apreq_param(req, "files"); - CuAssertPtrNotNull(tc, param); - CuAssertStrEquals(tc, "file1.txt", param->v.data); + val = apr_table_get(body, "files"); + CuAssertPtrNotNull(tc, val); + CuAssertStrEquals(tc, "file1.txt", val); + param = apreq_value_to_param(val); - CuAssertPtrNotNull(tc, param->bb); - apr_brigade_pflatten(param->bb, &val2, &vlen, p); + CuAssertPtrNotNull(tc, param->upload); + apr_brigade_pflatten(param->upload, &val2, &vlen, p); CuAssertIntEquals(tc, strlen("... contents of file1.txt ..."), vlen); CuAssertStrNEquals(tc, "... contents of file1.txt ...", val2, vlen); - arr = apr_table_elts(req->body); + arr = apr_table_elts(body); CuAssertIntEquals(tc, 4, arr->nelts); elt = (array_elt *)&arr->elts[2 * arr->elt_size]; CuAssertStrEquals(tc, "files", elt->key); CuAssertStrEquals(tc, "file2.gif", elt->val); - param = apreq_value_to_param(apreq_strtoval(elt->val)); - CuAssertPtrNotNull(tc, param->bb); - apr_brigade_pflatten(param->bb, &val2, &vlen, p); + param = apreq_value_to_param(elt->val); + CuAssertPtrNotNull(tc, param->upload); + apr_brigade_pflatten(param->upload, &val2, &vlen, p); CuAssertIntEquals(tc, strlen("...contents of file2.gif..."), vlen); CuAssertStrNEquals(tc, "...contents of file2.gif...", val2, vlen); } - CuSuite *testparser(void) { CuSuite *suite = CuSuiteNew("Parsers"); @@ -494,9 +490,9 @@ SUITE_ADD_TEST(suite, parse_multipart); SUITE_ADD_TEST(suite, parse_disable_uploads); SUITE_ADD_TEST(suite, parse_generic); + SUITE_ADD_TEST(suite, hook_discard); SUITE_ADD_TEST(suite, parse_related); SUITE_ADD_TEST(suite, parse_mixed); - SUITE_ADD_TEST(suite, hook_discard); return suite; } Modified: httpd/apreq/branches/multi-env-unstable/t/test_apreq.h URL: http://svn.apache.org/viewcvs/httpd/apreq/branches/multi-env-unstable/t/test_apreq.h?view=diff&r1=151385&r2=151386 ============================================================================== --- httpd/apreq/branches/multi-env-unstable/t/test_apreq.h (original) +++ httpd/apreq/branches/multi-env-unstable/t/test_apreq.h Fri Feb 4 10:27:55 2005 @@ -14,11 +14,12 @@ ** limitations under the License. */ -#ifndef APREQ_TEST_INCLUDES -#define APREQ_TEST_INCLUDES +#ifndef TEST_APREQ_H +#define TEST_APREQ_H #include "CuTest.h" #include "apr_pools.h" +#include "apreq_env.h" #ifndef apr_table_nelts #define apr_table_nelts(t) apr_table_elts(t)->nelts #endif @@ -27,7 +28,8 @@ * a bit more consistent... */ -extern apr_pool_t *p; + +extern apr_pool_t *p;//*global_test_pool; CuSuite *getsuite(void); CuSuite *testversion(void); @@ -37,9 +39,10 @@ CuSuite *testparam(void); CuSuite *testparser(void); CuSuite *testperformance(void); + /* Assert that RV is an APR_SUCCESS value; else fail giving strerror * for RV and CONTEXT message. */ void apr_assert_success(CuTest* tc, const char *context, apr_status_t rv); -#endif /* APR_TEST_INCLUDES */ +#endif /* TEST_APREQ_H */ Added: httpd/apreq/branches/multi-env-unstable/t/test_module.c URL: http://svn.apache.org/viewcvs/httpd/apreq/branches/multi-env-unstable/t/test_module.c?view=auto&rev=151386 ============================================================================== (empty) Added: httpd/apreq/branches/multi-env-unstable/t/test_module.h URL: http://svn.apache.org/viewcvs/httpd/apreq/branches/multi-env-unstable/t/test_module.h?view=auto&rev=151386 ============================================================================== (empty)
