Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 301 lines (259 sloc) 10.113 kb
2e7d4eb @pgollucci import apreq include files
pgollucci authored
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) \
a57712f Added apreq to NetWare build.
Guenter Knauf authored
70 f (APREQ_PARSER_ARGS)
2e7d4eb @pgollucci import apreq include files
pgollucci authored
71
72 /**
73 * Declares an API hook.
74 */
75 #define APREQ_DECLARE_HOOK(f) APREQ_DECLARE_NONSTD(apr_status_t) \
a57712f Added apreq to NetWare build.
Guenter Knauf authored
76 f (APREQ_HOOK_ARGS)
2e7d4eb @pgollucci import apreq include files
pgollucci authored
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 */
Something went wrong with that request. Please try again.