| /* |
| ** 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. |
| */ |
| |
| #ifndef APREQ_PARSERS_H |
| #define APREQ_PARSERS_H |
| /* These structs are defined below */ |
| |
| #include "apreq_param.h" |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif /* __cplusplus */ |
| |
| /** |
| * @file apreq_parser.h |
| * @brief Request body parser API |
| * @ingroup libapreq2 |
| */ |
| |
| /** |
| * A hook is called by the parser whenever data arrives in a file |
| * upload parameter of the request body. You may associate any number |
| * of hooks with a parser instance with apreq_parser_add_hook(). |
| */ |
| typedef struct apreq_hook_t apreq_hook_t; |
| |
| /** |
| * A request body parser instance. |
| */ |
| 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 |
| |
| /** |
| * The callback function implementing a request body parser. |
| */ |
| typedef apr_status_t (*apreq_parser_function_t)(APREQ_PARSER_ARGS); |
| |
| /** |
| * The callback function of a hook. See apreq_hook_t. |
| */ |
| 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) |
| |
| /** |
| * A hook is called by the parser whenever data arrives in a file |
| * upload parameter of the request body. You may associate any number |
| * of hooks with a parser instance with apreq_parser_add_hook(). |
| */ |
| struct apreq_hook_t { |
| apreq_hook_function_t hook; /**< the hook function */ |
| apreq_hook_t *next; /**< next item in the linked list */ |
| apr_pool_t *pool; /**< pool which allocated this hook */ |
| void *ctx; /**< a user defined pointer passed to the hook function */ |
| }; |
| |
| /** |
| * A request body parser instance. |
| */ |
| struct apreq_parser_t { |
| /** the function which parses chunks of body data */ |
| apreq_parser_function_t parser; |
| /** the Content-Type request header */ |
| const char *content_type; |
| /** a pool which outlasts the bucket_alloc. */ |
| apr_pool_t *pool; |
| /** bucket allocator used to create bucket brigades */ |
| apr_bucket_alloc_t *bucket_alloc; |
| /** the maximum in-memory bytes a brigade may use */ |
| apr_size_t brigade_limit; |
| /** the directory for generating temporary files */ |
| const char *temp_dir; |
| /** linked list of hooks */ |
| apreq_hook_t *hook; |
| /** internal context pointer used by the parser function */ |
| 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. |
| */ |
| static APR_INLINE |
| apr_status_t apreq_parser_run(struct apreq_parser_t *psr, apr_table_t *t, |
| apr_bucket_brigade *bb) |
| { |
| return 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. |
| */ |
| static APR_INLINE |
| apr_status_t apreq_hook_run(struct apreq_hook_t *h, apreq_param_t *param, |
| apr_bucket_brigade *bb) |
| { |
| return h->hook(h, param, bb); |
| } |
| |
| |
| /** |
| * RFC 822 Header parser. It will reject all data |
| * after the first CRLF CRLF sequence (an empty line). |
| * See apreq_parser_run() for more info on rejected data. |
| */ |
| APREQ_DECLARE_PARSER(apreq_parse_headers); |
| |
| /** |
| * RFC 2396 application/x-www-form-urlencoded parser. |
| */ |
| APREQ_DECLARE_PARSER(apreq_parse_urlencoded); |
| |
| /** |
| * RFC 2388 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_parser_run() 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 ba bucket allocator used to create bucket brigades |
| * @param content_type Content-type that this parser can deal with. |
| * @param pfn The parser function. |
| * @param brigade_limit the maximum in-memory bytes a brigade may use |
| * @param temp_dir the directory used by the parser for temporary files |
| * @param hook Hooks to associate this parser with. |
| * @param ctx Parser's internal scratch pad. |
| * @return New parser. |
| */ |
| APREQ_DECLARE(apreq_parser_t *) apreq_parser_make(apr_pool_t *pool, |
| apr_bucket_alloc_t *ba, |
| const char *content_type, |
| apreq_parser_function_t pfn, |
| 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_hook_make(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); |
| |
| |
| /** |
| * Fetch the default parser function associated with the given MIME type. |
| * @param enctype The desired enctype (can also be a full "Content-Type" |
| * header). |
| * @return The parser function, or NULL if the enctype 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 pfn The function to use during parsing. Setting |
| * parser == NULL will remove an existing parser. |
| * |
| * @return APR_SUCCESS or error. |
| */ |
| |
| APREQ_DECLARE(apr_status_t) apreq_register_parser(const char *enctype, |
| apreq_parser_function_t pfn); |
| |
| |
| /** |
| * Returns APREQ_ERROR_GENERAL. 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); |
| |
| /** |
| * Context struct for the apreq_hook_find_param hook. |
| */ |
| typedef struct apreq_hook_find_param_ctx_t { |
| const char *name; |
| apreq_param_t *param; |
| apreq_hook_t *prev; |
| } apreq_hook_find_param_ctx_t; |
| |
| |
| /** |
| * Special purpose utility for locating a parameter |
| * during parsing. The hook's ctx should be initialized |
| * to an apreq_hook_find_param_ctx_t *, with the name |
| * attribute set to the sought parameter name, the param |
| * attribute set to NULL, and the prev attribute set to |
| * the address of the previous hook. The param attribute |
| * will be reassigned to the first param found, and once |
| * that happens this hook is immediately removed from the chain. |
| * |
| * @remarks When used, this should always be the first hook |
| * invoked, so add it manually with ctx->prev = &parser->hook |
| * instead of using apreq_parser_add_hook. |
| */ |
| APREQ_DECLARE_HOOK(apreq_hook_find_param); |
| |
| |
| #ifdef __cplusplus |
| } |
| |
| #endif |
| #endif /* APREQ_PARSERS_H */ |