]> granicus.if.org Git - apache/blob - include/apreq_util.h
mod_authn_socache.c: fix creation of default socache_instance.
[apache] / include / apreq_util.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_UTIL_H
19 #define APREQ_UTIL_H
20
21 #include "apr_file_io.h"
22 #include "apr_buckets.h"
23 #include "apreq.h"
24
25 #ifdef  __cplusplus
26  extern "C" {
27 #endif
28
29 /**
30  * This header contains useful functions for creating new
31  * parsers, hooks or modules.  It includes
32  *
33  *    - string <-> array converters
34  *    - substring search functions
35  *    - simple encoders & decoders for urlencoded strings
36  *    - simple time, date, & file-size converters
37  * @file apreq_util.h
38  * @brief Utility functions for apreq.
39  * @ingroup libapreq2
40  */
41
42 /**
43  * Join an array of values. The result is an empty string if there are
44  * no values.
45  *
46  * @param p    Pool to allocate return value.
47  * @param sep  String that is inserted between the joined values.
48  * @param arr  Array of apreq_value_t entries.
49  * @param mode Join type- see apreq_join_t.
50  *
51  * @return Joined string, or NULL on error
52  */
53 APREQ_DECLARE(char *) apreq_join(apr_pool_t *p,
54                                  const char *sep,
55                                  const apr_array_header_t *arr,
56                                  apreq_join_t mode);
57
58 /**
59  * Returns offset of match string's location, or -1 if no match is found.
60  *
61  * @param hay  Location of bytes to scan.
62  * @param hlen Number of bytes available for scanning.
63  * @param ndl  Search string
64  * @param nlen Length of search string.
65  * @param type Match type.
66  *
67  * @return Offset of match string, or -1 if no match is found.
68  *
69  */
70 APREQ_DECLARE(apr_ssize_t) apreq_index(const char* hay, apr_size_t hlen,
71                                        const char* ndl, apr_size_t nlen,
72                                        const apreq_match_t type);
73
74 /**
75  * Places a quoted copy of src into dest.  Embedded quotes are escaped with a
76  * backslash ('\').
77  *
78  * @param dest Location of quoted copy.  Must be large enough to hold the copy
79  *             and trailing null byte.
80  * @param src  Original string.
81  * @param slen Length of original string.
82  * @param dest Destination string.
83  *
84  * @return length of quoted copy in dest.
85  */
86 APREQ_DECLARE(apr_size_t) apreq_quote(char *dest, const char *src,
87                                       const apr_size_t slen);
88
89 /**
90  *
91  * Same as apreq_quote() except when src begins and ends in quote marks. In
92  * that case it assumes src is quoted correctly, and just copies src to dest.
93  *
94  * @param dest Location of quoted copy.  Must be large enough to hold the copy
95  *             and trailing null byte.
96  * @param src  Original string.
97  * @param slen Length of original string.
98  * @param dest Destination string.
99  *
100  * @return length of quoted copy in dest.
101  */
102 APREQ_DECLARE(apr_size_t) apreq_quote_once(char *dest, const char *src,
103                                            const apr_size_t slen);
104
105 /**
106  * Url-encodes a string.
107  *
108  * @param dest Location of url-encoded result string. Caller must ensure it
109  *             is large enough to hold the encoded string and trailing '\\0'.
110  * @param src  Original string.
111  * @param slen Length of original string.
112  *
113  * @return length of url-encoded string in dest; does not exceed 3 * slen.
114  */
115 APREQ_DECLARE(apr_size_t) apreq_encode(char *dest, const char *src,
116                                        const apr_size_t slen);
117
118 /**
119  * Convert a string from cp1252 to utf8.  Caller must ensure it is large enough
120  * to hold the encoded string and trailing '\\0'.
121  *
122  * @param dest Location of utf8-encoded result string. Caller must ensure it
123  *             is large enough to hold the encoded string and trailing '\\0'.
124  * @param src  Original string.
125  * @param slen Length of original string.
126  *
127  * @return length of utf8-encoded string in dest; does not exceed 3 * slen.
128  */
129 APREQ_DECLARE(apr_size_t) apreq_cp1252_to_utf8(char *dest,
130                                                const char *src, apr_size_t slen);
131
132 /**
133  * Heuristically determine the charset of a string.
134  *
135  * @param src  String to scan.
136  * @param slen Length of string.
137  *
138  * @return APREQ_CHARSET_ASCII  if the string contains only 7-bit chars;
139  * @return APREQ_CHARSET_UTF8   if the string is a valid utf8 byte sequence;
140  * @return APREQ_CHARSET_LATIN1 if the string has no control chars;
141  * @return APREQ_CHARSET_CP1252 if the string has control chars.
142  */
143 APREQ_DECLARE(apreq_charset_t) apreq_charset_divine(const char *src,
144                                                     apr_size_t slen);
145
146 /**
147  * Url-decodes a string.
148  *
149  * @param dest Location of url-encoded result string. Caller must ensure dest is
150  *             large enough to hold the encoded string and trailing null character.
151  * @param dlen points to resultant length of url-decoded string in dest
152  * @param src  Original string.
153  * @param slen Length of original string.
154  *
155  * @return APR_SUCCESS.
156  * @return APR_INCOMPLETE if the string
157  *                        ends in the middle of an escape sequence.
158  * @return ::APREQ_ERROR_BADSEQ or ::APREQ_ERROR_BADCHAR on malformed input.
159  *
160  * @remarks In the non-success case, dlen will be set to include
161  *          the last succesfully decoded value.  This function decodes
162  *          \%uXXXX into a utf8 (wide) character, following ECMA-262
163  *          (the Javascript spec) Section B.2.1.
164  */
165
166 APREQ_DECLARE(apr_status_t) apreq_decode(char *dest, apr_size_t *dlen,
167                                          const char *src, apr_size_t slen);
168
169 /**
170  * Url-decodes an iovec array.
171  *
172  * @param dest  Location of url-encoded result string. Caller must ensure dest is
173  *              large enough to hold the encoded string and trailing null character.
174  * @param dlen  Resultant length of dest.
175  * @param v     Array of iovecs that represent the source string
176  * @param nelts Number of iovecs in the array.
177  *
178  * @return APR_SUCCESS.
179  * @return APR_INCOMPLETE if the iovec
180  *                        ends in the middle of an escape sequence.
181  * @return ::APREQ_ERROR_BADSEQ or ::APREQ_ERROR_BADCHAR on malformed input.
182  *
183  * @remarks In the non-APR_SUCCESS case, dlen will be set to include
184  *          the last succesfully decoded value.  This function decodes
185  *          \%uXXXX into a utf8 (wide) character, following ECMA-262
186  *          (the Javascript spec) Section B.2.1.
187  */
188
189 APREQ_DECLARE(apr_status_t) apreq_decodev(char *dest, apr_size_t *dlen,
190                                           struct iovec *v, int nelts);
191
192 /**
193  * Returns an url-encoded copy of a string.
194  *
195  * @param p    Pool used to allocate the return value.
196  * @param src  Original string.
197  * @param slen Length of original string.
198  *
199  * @return The url-encoded string.
200  *
201  * @remarks Use this function insead of apreq_encode if its
202  *          caller might otherwise overflow dest.
203  */
204 static APR_INLINE
205 char *apreq_escape(apr_pool_t *p, const char *src, const apr_size_t slen)
206 {
207     char *rv;
208
209     if (src == NULL)
210         return NULL;
211
212     rv = (char *)apr_palloc(p, 3 * slen + 1);
213     apreq_encode(rv, src, slen);
214     return rv;
215 }
216
217 /**
218  * An \e in-situ url-decoder.
219  *
220  * @param str  The string to decode
221  *
222  * @return  Length of decoded string, or < 0 on error.
223  */
224 static APR_INLINE apr_ssize_t apreq_unescape(char *str)
225 {
226     apr_size_t len;
227     apr_status_t rv = apreq_decode(str, &len, str, strlen(str));
228     if (rv == APR_SUCCESS)
229         return (apr_ssize_t)len;
230     else
231         return -1;
232 }
233
234 /**
235  * Converts file sizes (KMG) to bytes
236  *
237  * @param s  file size matching m/^\\d+[KMG]b?$/i
238  *
239  * @return 64-bit integer representation of s.
240  *
241  * @todo What happens when s is malformed?  Should this return
242  *       an unsigned value instead?
243  */
244
245 APREQ_DECLARE(apr_int64_t) apreq_atoi64f(const char *s);
246
247 /**
248  * Converts time strings (YMDhms) to seconds
249  *
250  * @param s time string matching m/^\\+?\\d+[YMDhms]$/
251  *
252  * @return 64-bit integer representation of s as seconds.
253  *
254  * @todo What happens when s is malformed?  Should this return
255  *       an unsigned value instead?
256  */
257
258 APREQ_DECLARE(apr_int64_t) apreq_atoi64t(const char *s);
259
260 /**
261  * Writes brigade to a file.
262  *
263  * @param f       File that gets the brigade.
264  * @param wlen    On a successful return, wlen holds the length of
265  *                the brigade, which is the amount of data written to
266  *                the file.
267  * @param bb      Bucket brigade.
268  *
269  * @return APR_SUCCESS.
270  * @return Error status code from either an unsuccessful apr_bucket_read(),
271  *         or a failed apr_file_writev().
272  *
273  * @remarks       This function leaks a bucket brigade into bb->p whenever
274  *                the final bucket in bb is a spool bucket.
275  */
276
277 APREQ_DECLARE(apr_status_t) apreq_brigade_fwrite(apr_file_t *f,
278                                                  apr_off_t *wlen,
279                                                  apr_bucket_brigade *bb);
280 /**
281  * Makes a temporary file.
282  *
283  * @param fp    Points to the temporary apr_file_t on success.
284  * @param pool  Pool to associate with the temp file.  When the
285  *              pool is destroyed, the temp file will be closed
286  *              and deleted.
287  * @param path  The base directory which will contain the temp file.
288  *              If param == NULL, the directory will be selected via
289  *              tempnam().  See the tempnam manpage for details.
290  *
291  * @return APR_SUCCESS.
292  * @return Error status code from unsuccessful apr_filepath_merge(),
293  *         or a failed apr_file_mktemp().
294  */
295
296 APREQ_DECLARE(apr_status_t) apreq_file_mktemp(apr_file_t **fp,
297                                               apr_pool_t *pool,
298                                               const char *path);
299
300 /**
301  * Set aside all buckets in the brigade.
302  *
303  * @param bb Brigade.
304  * @param p  Setaside buckets into this pool.
305  * @return APR_SUCCESS.
306  * @return Error status code from an unsuccessful apr_bucket_setaside().
307  */
308
309 static APR_INLINE
310 apr_status_t apreq_brigade_setaside(apr_bucket_brigade *bb, apr_pool_t *p)
311 {
312     apr_bucket *e;
313     for (e = APR_BRIGADE_FIRST(bb); e != APR_BRIGADE_SENTINEL(bb);
314          e = APR_BUCKET_NEXT(e))
315     {
316         apr_status_t rv = apr_bucket_setaside(e, p);
317         if (rv != APR_SUCCESS)
318             return rv;
319     }
320     return APR_SUCCESS;
321 }
322
323
324 /**
325  * Copy a brigade.
326  *
327  * @param d (destination) Copied buckets are appended to this brigade.
328  * @param s (source) Brigade to copy from.
329  *
330  * @return APR_SUCCESS.
331  * @return Error status code from an unsuccessful apr_bucket_copy().
332  *
333  * @remarks s == d produces Undefined Behavior.
334  */
335
336 static APR_INLINE
337 apr_status_t apreq_brigade_copy(apr_bucket_brigade *d, apr_bucket_brigade *s) {
338     apr_bucket *e;
339     for (e = APR_BRIGADE_FIRST(s); e != APR_BRIGADE_SENTINEL(s);
340          e = APR_BUCKET_NEXT(e))
341     {
342         apr_bucket *c;
343         apr_status_t rv = apr_bucket_copy(e, &c);
344         if (rv != APR_SUCCESS)
345             return rv;
346
347         APR_BRIGADE_INSERT_TAIL(d, c);
348     }
349     return APR_SUCCESS;
350 }
351
352 /**
353  * Move the front of a brigade.
354  *
355  * @param d (destination) Append buckets to this brigade.
356  * @param s (source) Brigade to take buckets from.
357  * @param e First bucket of s after the move.  All buckets
358  *          before e are appended to d.
359  *
360  * @remarks This moves all buckets when e == APR_BRIGADE_SENTINEL(s).
361  */
362
363 static APR_INLINE
364 void apreq_brigade_move(apr_bucket_brigade *d, apr_bucket_brigade *s,
365                         apr_bucket *e)
366 {
367     apr_bucket *f;
368
369     if (e != APR_BRIGADE_SENTINEL(s)) {
370         f = APR_RING_FIRST(&s->list);
371         if (f == e) /* zero buckets to be moved */
372             return;
373
374         /* obtain the last bucket to be moved */
375         e = APR_RING_PREV(e, link);
376
377         APR_RING_UNSPLICE(f, e, link);
378         APR_RING_SPLICE_HEAD(&d->list, f, e, apr_bucket, link);
379     }
380     else {
381         APR_BRIGADE_CONCAT(d, s);
382     }
383 }
384
385
386 /**
387  * Search a header string for the value of a particular named attribute.
388  *
389  * @param hdr Header string to scan.
390  * @param name Name of attribute to search for.
391  * @param nlen Length of name.
392  * @param val Location of (first) matching value.
393  * @param vlen Length of matching value.
394  *
395  * @return APR_SUCCESS.
396  * @return ::APREQ_ERROR_NOATTR if the attribute is not found.
397  * @return ::APREQ_ERROR_BADSEQ if an unpaired quote mark was detected.
398  */
399 APREQ_DECLARE(apr_status_t) apreq_header_attribute(const char *hdr,
400                                                    const char *name,
401                                                    const apr_size_t nlen,
402                                                    const char **val,
403                                                    apr_size_t *vlen);
404
405
406 /**
407  * Concatenates the brigades, spooling large brigades into
408  * a tempfile (APREQ_SPOOL) bucket.
409  *
410  * @param pool           Pool for creating a tempfile bucket.
411  * @param temp_dir       Directory for tempfile creation.
412  * @param brigade_limit  If out's length would exceed this value,
413  *                       the appended buckets get written to a tempfile.
414  * @param out            Resulting brigade.
415  * @param in             Brigade to append.
416  *
417  * @return APR_SUCCESS.
418  * @return Error status code resulting from either apr_brigade_length(),
419  *         apreq_file_mktemp(), apreq_brigade_fwrite(), or apr_file_seek().
420  *
421  * @todo Flesh out these error codes, making them as explicit as possible.
422  */
423 APREQ_DECLARE(apr_status_t) apreq_brigade_concat(apr_pool_t *pool,
424                                                  const char *temp_dir,
425                                                  apr_size_t brigade_limit,
426                                                  apr_bucket_brigade *out,
427                                                  apr_bucket_brigade *in);
428
429 /**
430  * Determines the spool file used by the brigade. Returns NULL if the
431  * brigade is not spooled in a file (does not use an APREQ_SPOOL
432  * bucket).
433  *
434  * @param bb the bucket brigade
435  * @return the spool file, or NULL.
436  */
437 APREQ_DECLARE(apr_file_t *) apreq_brigade_spoolfile(apr_bucket_brigade *bb);
438
439 #ifdef __cplusplus
440  }
441 #endif
442
443 #endif /* APREQ_UTIL_H */