summaryrefslogtreecommitdiff
path: root/srclib/libapreq/include/apreq_util.h
diff options
context:
space:
mode:
Diffstat (limited to 'srclib/libapreq/include/apreq_util.h')
-rw-r--r--srclib/libapreq/include/apreq_util.h443
1 files changed, 443 insertions, 0 deletions
diff --git a/srclib/libapreq/include/apreq_util.h b/srclib/libapreq/include/apreq_util.h
new file mode 100644
index 0000000000..feb2d396ce
--- /dev/null
+++ b/srclib/libapreq/include/apreq_util.h
@@ -0,0 +1,443 @@
+/*
+** 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_UTIL_H
+#define APREQ_UTIL_H
+
+#include "apr_file_io.h"
+#include "apr_buckets.h"
+#include "apreq.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/**
+ * This header contains useful functions for creating new
+ * parsers, hooks or modules. It includes
+ *
+ * - string <-> array converters
+ * - substring search functions
+ * - simple encoders & decoders for urlencoded strings
+ * - simple time, date, & file-size converters
+ * @file apreq_util.h
+ * @brief Utility functions for apreq.
+ * @ingroup libapreq2
+ */
+
+/**
+ * Join an array of values. The result is an empty string if there are
+ * no values.
+ *
+ * @param p Pool to allocate return value.
+ * @param sep String that is inserted between the joined values.
+ * @param arr Array of apreq_value_t entries.
+ * @param mode Join type- see apreq_join_t.
+ *
+ * @return Joined string, or NULL on error
+ */
+APREQ_DECLARE(char *) apreq_join(apr_pool_t *p,
+ const char *sep,
+ const apr_array_header_t *arr,
+ apreq_join_t mode);
+
+/**
+ * Returns offset of match string's location, or -1 if no match is found.
+ *
+ * @param hay Location of bytes to scan.
+ * @param hlen Number of bytes available for scanning.
+ * @param ndl Search string
+ * @param nlen Length of search string.
+ * @param type Match type.
+ *
+ * @return Offset of match string, or -1 if no match is found.
+ *
+ */
+APREQ_DECLARE(apr_ssize_t) apreq_index(const char* hay, apr_size_t hlen,
+ const char* ndl, apr_size_t nlen,
+ const apreq_match_t type);
+
+/**
+ * Places a quoted copy of src into dest. Embedded quotes are escaped with a
+ * backslash ('\').
+ *
+ * @param dest Location of quoted copy. Must be large enough to hold the copy
+ * and trailing null byte.
+ * @param src Original string.
+ * @param slen Length of original string.
+ * @param dest Destination string.
+ *
+ * @return length of quoted copy in dest.
+ */
+APREQ_DECLARE(apr_size_t) apreq_quote(char *dest, const char *src,
+ const apr_size_t slen);
+
+/**
+ *
+ * Same as apreq_quote() except when src begins and ends in quote marks. In
+ * that case it assumes src is quoted correctly, and just copies src to dest.
+ *
+ * @param dest Location of quoted copy. Must be large enough to hold the copy
+ * and trailing null byte.
+ * @param src Original string.
+ * @param slen Length of original string.
+ * @param dest Destination string.
+ *
+ * @return length of quoted copy in dest.
+ */
+APREQ_DECLARE(apr_size_t) apreq_quote_once(char *dest, const char *src,
+ const apr_size_t slen);
+
+/**
+ * Url-encodes a string.
+ *
+ * @param dest Location of url-encoded result string. Caller must ensure it
+ * is large enough to hold the encoded string and trailing '\\0'.
+ * @param src Original string.
+ * @param slen Length of original string.
+ *
+ * @return length of url-encoded string in dest; does not exceed 3 * slen.
+ */
+APREQ_DECLARE(apr_size_t) apreq_encode(char *dest, const char *src,
+ const apr_size_t slen);
+
+/**
+ * Convert a string from cp1252 to utf8. Caller must ensure it is large enough
+ * to hold the encoded string and trailing '\\0'.
+ *
+ * @param dest Location of utf8-encoded result string. Caller must ensure it
+ * is large enough to hold the encoded string and trailing '\\0'.
+ * @param src Original string.
+ * @param slen Length of original string.
+ *
+ * @return length of utf8-encoded string in dest; does not exceed 3 * slen.
+ */
+APREQ_DECLARE(apr_size_t) apreq_cp1252_to_utf8(char *dest,
+ const char *src, apr_size_t slen);
+
+/**
+ * Heuristically determine the charset of a string.
+ *
+ * @param src String to scan.
+ * @param slen Length of string.
+ *
+ * @return APREQ_CHARSET_ASCII if the string contains only 7-bit chars;
+ * @return APREQ_CHARSET_UTF8 if the string is a valid utf8 byte sequence;
+ * @return APREQ_CHARSET_LATIN1 if the string has no control chars;
+ * @return APREQ_CHARSET_CP1252 if the string has control chars.
+ */
+APREQ_DECLARE(apreq_charset_t) apreq_charset_divine(const char *src,
+ apr_size_t slen);
+
+/**
+ * Url-decodes a string.
+ *
+ * @param dest Location of url-encoded result string. Caller must ensure dest is
+ * large enough to hold the encoded string and trailing null character.
+ * @param dlen points to resultant length of url-decoded string in dest
+ * @param src Original string.
+ * @param slen Length of original string.
+ *
+ * @return APR_SUCCESS.
+ * @return APR_INCOMPLETE if the string
+ * ends in the middle of an escape sequence.
+ * @return ::APREQ_ERROR_BADSEQ or ::APREQ_ERROR_BADCHAR on malformed input.
+ *
+ * @remarks In the non-success case, dlen will be set to include
+ * the last succesfully decoded value. This function decodes
+ * \%uXXXX into a utf8 (wide) character, following ECMA-262
+ * (the Javascript spec) Section B.2.1.
+ */
+
+APREQ_DECLARE(apr_status_t) apreq_decode(char *dest, apr_size_t *dlen,
+ const char *src, apr_size_t slen);
+
+/**
+ * Url-decodes an iovec array.
+ *
+ * @param dest Location of url-encoded result string. Caller must ensure dest is
+ * large enough to hold the encoded string and trailing null character.
+ * @param dlen Resultant length of dest.
+ * @param v Array of iovecs that represent the source string
+ * @param nelts Number of iovecs in the array.
+ *
+ * @return APR_SUCCESS.
+ * @return APR_INCOMPLETE if the iovec
+ * ends in the middle of an escape sequence.
+ * @return ::APREQ_ERROR_BADSEQ or ::APREQ_ERROR_BADCHAR on malformed input.
+ *
+ * @remarks In the non-APR_SUCCESS case, dlen will be set to include
+ * the last succesfully decoded value. This function decodes
+ * \%uXXXX into a utf8 (wide) character, following ECMA-262
+ * (the Javascript spec) Section B.2.1.
+ */
+
+APREQ_DECLARE(apr_status_t) apreq_decodev(char *dest, apr_size_t *dlen,
+ struct iovec *v, int nelts);
+
+/**
+ * Returns an url-encoded copy of a string.
+ *
+ * @param p Pool used to allocate the return value.
+ * @param src Original string.
+ * @param slen Length of original string.
+ *
+ * @return The url-encoded string.
+ *
+ * @remarks Use this function insead of apreq_encode if its
+ * caller might otherwise overflow dest.
+ */
+static APR_INLINE
+char *apreq_escape(apr_pool_t *p, const char *src, const apr_size_t slen)
+{
+ char *rv;
+
+ if (src == NULL)
+ return NULL;
+
+ rv = (char *)apr_palloc(p, 3 * slen + 1);
+ apreq_encode(rv, src, slen);
+ return rv;
+}
+
+/**
+ * An \e in-situ url-decoder.
+ *
+ * @param str The string to decode
+ *
+ * @return Length of decoded string, or < 0 on error.
+ */
+static APR_INLINE apr_ssize_t apreq_unescape(char *str)
+{
+ apr_size_t len;
+ apr_status_t rv = apreq_decode(str, &len, str, strlen(str));
+ if (rv == APR_SUCCESS)
+ return (apr_ssize_t)len;
+ else
+ return -1;
+}
+
+/**
+ * Converts file sizes (KMG) to bytes
+ *
+ * @param s file size matching m/^\\d+[KMG]b?$/i
+ *
+ * @return 64-bit integer representation of s.
+ *
+ * @todo What happens when s is malformed? Should this return
+ * an unsigned value instead?
+ */
+
+APREQ_DECLARE(apr_int64_t) apreq_atoi64f(const char *s);
+
+/**
+ * Converts time strings (YMDhms) to seconds
+ *
+ * @param s time string matching m/^\\+?\\d+[YMDhms]$/
+ *
+ * @return 64-bit integer representation of s as seconds.
+ *
+ * @todo What happens when s is malformed? Should this return
+ * an unsigned value instead?
+ */
+
+APREQ_DECLARE(apr_int64_t) apreq_atoi64t(const char *s);
+
+/**
+ * Writes brigade to a file.
+ *
+ * @param f File that gets the brigade.
+ * @param wlen On a successful return, wlen holds the length of
+ * the brigade, which is the amount of data written to
+ * the file.
+ * @param bb Bucket brigade.
+ *
+ * @return APR_SUCCESS.
+ * @return Error status code from either an unsuccessful apr_bucket_read(),
+ * or a failed apr_file_writev().
+ *
+ * @remarks This function leaks a bucket brigade into bb->p whenever
+ * the final bucket in bb is a spool bucket.
+ */
+
+APREQ_DECLARE(apr_status_t) apreq_brigade_fwrite(apr_file_t *f,
+ apr_off_t *wlen,
+ apr_bucket_brigade *bb);
+/**
+ * Makes a temporary file.
+ *
+ * @param fp Points to the temporary apr_file_t on success.
+ * @param pool Pool to associate with the temp file. When the
+ * pool is destroyed, the temp file will be closed
+ * and deleted.
+ * @param path The base directory which will contain the temp file.
+ * If param == NULL, the directory will be selected via
+ * tempnam(). See the tempnam manpage for details.
+ *
+ * @return APR_SUCCESS.
+ * @return Error status code from unsuccessful apr_filepath_merge(),
+ * or a failed apr_file_mktemp().
+ */
+
+APREQ_DECLARE(apr_status_t) apreq_file_mktemp(apr_file_t **fp,
+ apr_pool_t *pool,
+ const char *path);
+
+/**
+ * Set aside all buckets in the brigade.
+ *
+ * @param bb Brigade.
+ * @param p Setaside buckets into this pool.
+ * @return APR_SUCCESS.
+ * @return Error status code from an unsuccessful apr_bucket_setaside().
+ */
+
+static APR_INLINE
+apr_status_t apreq_brigade_setaside(apr_bucket_brigade *bb, apr_pool_t *p)
+{
+ apr_bucket *e;
+ for (e = APR_BRIGADE_FIRST(bb); e != APR_BRIGADE_SENTINEL(bb);
+ e = APR_BUCKET_NEXT(e))
+ {
+ apr_status_t rv = apr_bucket_setaside(e, p);
+ if (rv != APR_SUCCESS)
+ return rv;
+ }
+ return APR_SUCCESS;
+}
+
+
+/**
+ * Copy a brigade.
+ *
+ * @param d (destination) Copied buckets are appended to this brigade.
+ * @param s (source) Brigade to copy from.
+ *
+ * @return APR_SUCCESS.
+ * @return Error status code from an unsuccessful apr_bucket_copy().
+ *
+ * @remarks s == d produces Undefined Behavior.
+ */
+
+static APR_INLINE
+apr_status_t apreq_brigade_copy(apr_bucket_brigade *d, apr_bucket_brigade *s) {
+ apr_bucket *e;
+ for (e = APR_BRIGADE_FIRST(s); e != APR_BRIGADE_SENTINEL(s);
+ e = APR_BUCKET_NEXT(e))
+ {
+ apr_bucket *c;
+ apr_status_t rv = apr_bucket_copy(e, &c);
+ if (rv != APR_SUCCESS)
+ return rv;
+
+ APR_BRIGADE_INSERT_TAIL(d, c);
+ }
+ return APR_SUCCESS;
+}
+
+/**
+ * Move the front of a brigade.
+ *
+ * @param d (destination) Append buckets to this brigade.
+ * @param s (source) Brigade to take buckets from.
+ * @param e First bucket of s after the move. All buckets
+ * before e are appended to d.
+ *
+ * @remarks This moves all buckets when e == APR_BRIGADE_SENTINEL(s).
+ */
+
+static APR_INLINE
+void apreq_brigade_move(apr_bucket_brigade *d, apr_bucket_brigade *s,
+ apr_bucket *e)
+{
+ apr_bucket *f;
+
+ if (e != APR_BRIGADE_SENTINEL(s)) {
+ f = APR_RING_FIRST(&s->list);
+ if (f == e) /* zero buckets to be moved */
+ return;
+
+ /* obtain the last bucket to be moved */
+ e = APR_RING_PREV(e, link);
+
+ APR_RING_UNSPLICE(f, e, link);
+ APR_RING_SPLICE_HEAD(&d->list, f, e, apr_bucket, link);
+ }
+ else {
+ APR_BRIGADE_CONCAT(d, s);
+ }
+}
+
+
+/**
+ * Search a header string for the value of a particular named attribute.
+ *
+ * @param hdr Header string to scan.
+ * @param name Name of attribute to search for.
+ * @param nlen Length of name.
+ * @param val Location of (first) matching value.
+ * @param vlen Length of matching value.
+ *
+ * @return APR_SUCCESS.
+ * @return ::APREQ_ERROR_NOATTR if the attribute is not found.
+ * @return ::APREQ_ERROR_BADSEQ if an unpaired quote mark was detected.
+ */
+APREQ_DECLARE(apr_status_t) apreq_header_attribute(const char *hdr,
+ const char *name,
+ const apr_size_t nlen,
+ const char **val,
+ apr_size_t *vlen);
+
+
+/**
+ * Concatenates the brigades, spooling large brigades into
+ * a tempfile (APREQ_SPOOL) bucket.
+ *
+ * @param pool Pool for creating a tempfile bucket.
+ * @param temp_dir Directory for tempfile creation.
+ * @param brigade_limit If out's length would exceed this value,
+ * the appended buckets get written to a tempfile.
+ * @param out Resulting brigade.
+ * @param in Brigade to append.
+ *
+ * @return APR_SUCCESS.
+ * @return Error status code resulting from either apr_brigade_length(),
+ * apreq_file_mktemp(), apreq_brigade_fwrite(), or apr_file_seek().
+ *
+ * @todo Flesh out these error codes, making them as explicit as possible.
+ */
+APREQ_DECLARE(apr_status_t) apreq_brigade_concat(apr_pool_t *pool,
+ const char *temp_dir,
+ apr_size_t brigade_limit,
+ apr_bucket_brigade *out,
+ apr_bucket_brigade *in);
+
+/**
+ * Determines the spool file used by the brigade. Returns NULL if the
+ * brigade is not spooled in a file (does not use an APREQ_SPOOL
+ * bucket).
+ *
+ * @param bb the bucket brigade
+ * @return the spool file, or NULL.
+ */
+APREQ_DECLARE(apr_file_t *)apreq_brigade_spoolfile(apr_bucket_brigade *bb);
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* APREQ_UTIL_H */