]> granicus.if.org Git - apache/blob - include/apreq_parser.h
* Do not reset the retry timeout if the worker is in error at this stage even
[apache] / include / apreq_parser.h
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 #ifndef APREQ_PARSERS_H
19 #define APREQ_PARSERS_H
20 /* These structs are defined below */
21
22 #include "apreq_param.h"
23
24 #ifdef __cplusplus
25 extern "C" {
26 #endif /* __cplusplus */
27
28 /**
29  * @file apreq_parser.h
30  * @brief Request body parser API
31  * @ingroup libapreq2
32  */
33
34 /**
35  * A hook is called by the parser whenever data arrives in a file
36  * upload parameter of the request body. You may associate any number
37  * of hooks with a parser instance with apreq_parser_add_hook().
38  */
39 typedef struct apreq_hook_t apreq_hook_t;
40
41 /**
42  * A request body parser instance.
43  */
44 typedef struct apreq_parser_t apreq_parser_t;
45
46 /** Parser arguments. */
47 #define APREQ_PARSER_ARGS  apreq_parser_t *parser,     \
48                            apr_table_t *t,             \
49                            apr_bucket_brigade *bb
50
51 /** Hook arguments */
52 #define APREQ_HOOK_ARGS    apreq_hook_t *hook,         \
53                            apreq_param_t *param,       \
54                            apr_bucket_brigade *bb
55
56 /**
57  * The callback function implementing a request body parser.
58  */
59 typedef apr_status_t (*apreq_parser_function_t)(APREQ_PARSER_ARGS);
60
61 /**
62  * The callback function of a hook. See apreq_hook_t.
63  */
64 typedef apr_status_t (*apreq_hook_function_t)(APREQ_HOOK_ARGS);
65
66 /**
67  * Declares a API parser.
68  */
69 #define APREQ_DECLARE_PARSER(f) APREQ_DECLARE_NONSTD(apr_status_t) \
70                                 f (APREQ_PARSER_ARGS)
71
72 /**
73  * Declares an API hook.
74  */
75 #define APREQ_DECLARE_HOOK(f)   APREQ_DECLARE_NONSTD(apr_status_t) \
76                                 f (APREQ_HOOK_ARGS)
77
78 /**
79  * A hook is called by the parser whenever data arrives in a file
80  * upload parameter of the request body. You may associate any number
81  * of hooks with a parser instance with apreq_parser_add_hook().
82  */
83 struct apreq_hook_t {
84     apreq_hook_function_t hook; /**< the hook function */
85     apreq_hook_t         *next; /**< next item in the linked list */
86     apr_pool_t           *pool; /**< pool which allocated this hook */
87     void *ctx; /**< a user defined pointer passed to the hook function */
88 };
89
90 /**
91  * A request body parser instance.
92  */
93 struct apreq_parser_t {
94     /** the function which parses chunks of body data */
95     apreq_parser_function_t parser;
96     /** the Content-Type request header */
97     const char             *content_type;
98     /** a pool which outlasts the bucket_alloc. */
99     apr_pool_t             *pool;
100     /** bucket allocator used to create bucket brigades */
101     apr_bucket_alloc_t     *bucket_alloc;
102     /** the maximum in-memory bytes a brigade may use */
103     apr_size_t              brigade_limit;
104     /** the directory for generating temporary files */
105     const char             *temp_dir;
106     /** linked list of hooks */
107     apreq_hook_t           *hook;
108     /** internal context pointer used by the parser function */
109     void                   *ctx;
110 };
111
112
113 /**
114  * Parse the incoming brigade into a table.  Parsers normally
115  * consume all the buckets of the brigade during parsing. However
116  * parsers may leave "rejected" data in the brigade, even during a
117  * successful parse, so callers may need to clean up the brigade
118  * themselves (in particular, rejected buckets should not be
119  * passed back to the parser again).
120  * @remark  bb == NULL is valid: the parser should return its
121  * public status: APR_INCOMPLETE, APR_SUCCESS, or an error code.
122  */
123 static APR_INLINE
124 apr_status_t apreq_parser_run(struct apreq_parser_t *psr, apr_table_t *t,
125                               apr_bucket_brigade *bb)
126 {
127     return psr->parser(psr, t, bb);
128 }
129
130 /**
131  * Run the hook with the current parameter and the incoming
132  * bucket brigade.  The hook may modify the brigade if necessary.
133  * Once all hooks have completed, the contents of the brigade will
134  * be added to the parameter's bb attribute.
135  * @return APR_SUCCESS on success. All other values represent errors.
136  */
137 static APR_INLINE
138 apr_status_t apreq_hook_run(struct apreq_hook_t *h, apreq_param_t *param,
139                             apr_bucket_brigade *bb)
140 {
141     return h->hook(h, param, bb);
142 }
143
144
145 /**
146  * RFC 822 Header parser. It will reject all data
147  * after the first CRLF CRLF sequence (an empty line).
148  * See apreq_parser_run() for more info on rejected data.
149  */
150 APREQ_DECLARE_PARSER(apreq_parse_headers);
151
152 /**
153  * RFC 2396 application/x-www-form-urlencoded parser.
154  */
155 APREQ_DECLARE_PARSER(apreq_parse_urlencoded);
156
157 /**
158  * RFC 2388 multipart/form-data (and XForms 1.0 multipart/related)
159  * parser. It will reject any buckets representing preamble and
160  * postamble text (this is normal behavior, not an error condition).
161  * See apreq_parser_run() for more info on rejected data.
162  */
163 APREQ_DECLARE_PARSER(apreq_parse_multipart);
164
165 /**
166  * Generic parser.  No table entries will be added to
167  * the req->body table by this parser.  The parser creates
168  * a dummy apreq_param_t to pass to any configured hooks.  If
169  * no hooks are configured, the dummy param's bb slot will
170  * contain a copy of the request body.  It can be retrieved
171  * by casting the parser's ctx pointer to (apreq_param_t **).
172  */
173 APREQ_DECLARE_PARSER(apreq_parse_generic);
174
175 /**
176  * apr_xml_parser hook. It will parse until EOS appears.
177  * The parsed document isn't available until parsing has
178  * completed successfully.  The hook's ctx pointer may
179  * be cast as (apr_xml_doc **) to retrieve the
180  * parsed document.
181  */
182 APREQ_DECLARE_HOOK(apreq_hook_apr_xml_parser);
183
184 /**
185  * Construct a parser.
186  *
187  * @param pool Pool used to allocate the parser.
188  * @param ba bucket allocator used to create bucket brigades
189  * @param content_type Content-type that this parser can deal with.
190  * @param pfn The parser function.
191  * @param brigade_limit the maximum in-memory bytes a brigade may use
192  * @param temp_dir the directory used by the parser for temporary files
193  * @param hook Hooks to associate this parser with.
194  * @param ctx Parser's internal scratch pad.
195  * @return New parser.
196  */
197 APREQ_DECLARE(apreq_parser_t *) apreq_parser_make(apr_pool_t *pool,
198                                                   apr_bucket_alloc_t *ba,
199                                                   const char *content_type,
200                                                   apreq_parser_function_t pfn,
201                                                   apr_size_t brigade_limit,
202                                                   const char *temp_dir,
203                                                   apreq_hook_t *hook,
204                                                   void *ctx);
205
206 /**
207  * Construct a hook.
208  *
209  * @param pool used to allocate the hook.
210  * @param hook The hook function.
211  * @param next List of other hooks for this hook to call on.
212  * @param ctx Hook's internal scratch pad.
213  * @return New hook.
214  */
215 APREQ_DECLARE(apreq_hook_t *) apreq_hook_make(apr_pool_t *pool,
216                                               apreq_hook_function_t hook,
217                                               apreq_hook_t *next,
218                                               void *ctx);
219
220
221 /**
222  * Add a new hook to the end of the parser's hook list.
223  *
224  * @param p Parser.
225  * @param h Hook to append.
226  */
227 APREQ_DECLARE(apr_status_t) apreq_parser_add_hook(apreq_parser_t *p,
228                                                   apreq_hook_t *h);
229
230
231 /**
232  * Fetch the default parser function associated with the given MIME type.
233  * @param enctype The desired enctype (can also be a full "Content-Type"
234  *        header).
235  * @return The parser function, or NULL if the enctype is unrecognized.
236  */
237 APREQ_DECLARE(apreq_parser_function_t)apreq_parser(const char *enctype);
238
239
240 /**
241  * Register a new parsing function with a MIME enctype.
242  * Registered parsers are added to apreq_parser()'s
243  * internal lookup table.
244  *
245  * @param enctype The MIME type.
246  * @param pfn     The function to use during parsing. Setting
247  *                parser == NULL will remove an existing parser.
248  *
249  * @return APR_SUCCESS or error.
250  */
251
252 APREQ_DECLARE(apr_status_t) apreq_register_parser(const char *enctype,
253                                                   apreq_parser_function_t pfn);
254
255
256 /**
257  * Returns APREQ_ERROR_GENERAL.  Effectively disables mfd parser
258  * if a file-upload field is present.
259  *
260  */
261 APREQ_DECLARE_HOOK(apreq_hook_disable_uploads);
262
263 /**
264  * Calls apr_brigade_cleanup on the incoming brigade
265  * after passing the brigade to any subsequent hooks.
266  */
267 APREQ_DECLARE_HOOK(apreq_hook_discard_brigade);
268
269 /**
270  * Context struct for the apreq_hook_find_param hook.
271  */
272 typedef struct apreq_hook_find_param_ctx_t {
273     const char    *name;
274     apreq_param_t *param;
275     apreq_hook_t  *prev;
276 } apreq_hook_find_param_ctx_t;
277
278
279 /**
280  * Special purpose utility for locating a parameter
281  * during parsing.  The hook's ctx shoud be initialized
282  * to an apreq_hook_find_param_ctx_t *, with the name
283  * attribute set to the sought parameter name, the param
284  * attribute set to NULL, and the prev attribute set to
285  * the address of the previous hook.  The param attribute
286  * will be reassigned to the first param found, and once
287  * that happens this hook is immediately removed from the chain.
288  *
289  * @remarks When used, this should always be the first hook
290  * invoked, so add it manually with ctx->prev = &parser->hook
291  * instead of using apreq_parser_add_hook.
292  */
293 APREQ_DECLARE_HOOK(apreq_hook_find_param);
294
295
296 #ifdef __cplusplus
297 }
298
299 #endif
300 #endif /* APREQ_PARSERS_H */