httpd-apreq-cvs mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From j...@apache.org
Subject svn commit: r380784 [2/4] - in /httpd/apreq/branches/apr-build-system: ./ build/ include/ library/ module/ module/apache2/
Date Fri, 24 Feb 2006 18:56:38 GMT
Added: httpd/apreq/branches/apr-build-system/include/apreq_parser.h
URL: http://svn.apache.org/viewcvs/httpd/apreq/branches/apr-build-system/include/apreq_parser.h?rev=380784&view=auto
==============================================================================
--- httpd/apreq/branches/apr-build-system/include/apreq_parser.h (added)
+++ httpd/apreq/branches/apr-build-system/include/apreq_parser.h Fri Feb 24 10:56:34 2006
@@ -0,0 +1,286 @@
+/*
+**  Copyright 2003-2006  The Apache Software Foundation
+**
+**  Licensed 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);
+
+/**
+ * Special purpose utility for locating a parameter
+ * during parsing.  The hook's ctx shoud be initialized
+ * to a const char *, which is a pointer to the desired
+ * param name.  The hook's ctx will be reassigned to the
+ * first param found.
+ *
+ * @remarks When used, this should always be the first hook
+ * invoked, so add it manually as parser->hook instead of
+ * using apreq_parser_add_hook.
+ */
+APREQ_DECLARE_HOOK(apreq_hook_find_param);
+
+
+#ifdef __cplusplus
+}
+
+#endif
+#endif /* APREQ_PARSERS_H */

Propchange: httpd/apreq/branches/apr-build-system/include/apreq_parser.h
------------------------------------------------------------------------------
    svn:eol-style = native

Added: httpd/apreq/branches/apr-build-system/include/apreq_util.h
URL: http://svn.apache.org/viewcvs/httpd/apreq/branches/apr-build-system/include/apreq_util.h?rev=380784&view=auto
==============================================================================
--- httpd/apreq/branches/apr-build-system/include/apreq_util.h (added)
+++ httpd/apreq/branches/apr-build-system/include/apreq_util.h Fri Feb 24 10:56:34 2006
@@ -0,0 +1,442 @@
+/*
+**  Copyright 2003-2006  The Apache Software Foundation
+**
+**  Licensed 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       In the future, this function may do something
+ *                intelligent with file buckets.
+ */
+
+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 */

Propchange: httpd/apreq/branches/apr-build-system/include/apreq_util.h
------------------------------------------------------------------------------
    svn:eol-style = native

Added: httpd/apreq/branches/apr-build-system/include/apreq_version.h
URL: http://svn.apache.org/viewcvs/httpd/apreq/branches/apr-build-system/include/apreq_version.h?rev=380784&view=auto
==============================================================================
--- httpd/apreq/branches/apr-build-system/include/apreq_version.h (added)
+++ httpd/apreq/branches/apr-build-system/include/apreq_version.h Fri Feb 24 10:56:34 2006
@@ -0,0 +1,104 @@
+/*
+**  Copyright 2003-2006  The Apache Software Foundation
+**
+**  Licensed 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_VERSION_H
+#define APREQ_VERSION_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "apr_version.h"
+#include "apreq.h"
+
+/**
+ * @file apreq_version.h
+ * @brief Versioning API for libapreq
+ * @ingroup libapreq2
+ *
+ * There are several different mechanisms for accessing the version. There
+ * is a string form, and a set of numbers; in addition, there are constants
+ * which can be compiled into your application, and you can query the library
+ * being used for its actual version.
+ *
+ * Note that it is possible for an application to detect that it has been
+ * compiled against a different version of libapreq by use of the compile-time
+ * constants and the use of the run-time query function.
+ *
+ * libapreq version numbering follows the guidelines specified in:
+ *
+ *     http://apr.apache.org/versioning.html
+ */
+
+/* The numeric compile-time version constants. These constants are the
+ * authoritative version numbers for libapreq.
+ */
+
+/** major version
+ * Major API changes that could cause compatibility problems for older
+ * programs such as structure size changes.  No binary compatibility is
+ * possible across a change in the major version.
+ */
+#define APREQ_MAJOR_VERSION       2
+
+/**
+ * Minor API changes that do not cause binary compatibility problems.
+ * Should be reset to 0 when upgrading APREQ_MAJOR_VERSION
+ */
+#define APREQ_MINOR_VERSION       5
+
+/** patch level */
+#define APREQ_PATCH_VERSION       8
+
+/**
+ *  This symbol is defined for internal, "development" copies of libapreq.
+ *  This symbol will be \#undef'd for releases.
+ */
+#define APREQ_IS_DEV_VERSION
+
+
+/** The formatted string of libapreq's version */
+#define APREQ_VERSION_STRING \
+     APR_STRINGIFY(APREQ_MAJOR_VERSION) "." \
+     APR_STRINGIFY(APREQ_MINOR_VERSION) "." \
+     APR_STRINGIFY(APREQ_PATCH_VERSION) \
+     APREQ_IS_DEV_STRING
+
+/**
+ * Return libapreq's version information information in a numeric form.
+ *
+ *  @param pvsn Pointer to a version structure for returning the version
+ *              information.
+ */
+APREQ_DECLARE(void) apreq_version(apr_version_t *pvsn);
+
+/** Return libapreq's version information as a string. */
+APREQ_DECLARE(const char *) apreq_version_string(void);
+
+
+/** Internal: string form of the "is dev" flag */
+#ifdef APREQ_IS_DEV_VERSION
+#define APREQ_IS_DEV_STRING "-dev"
+#else
+#define APREQ_IS_DEV_STRING ""
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* APREQ_VERSION_H */

Propchange: httpd/apreq/branches/apr-build-system/include/apreq_version.h
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: httpd/apreq/branches/apr-build-system/library/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Fri Feb 24 10:56:34 2006
@@ -0,0 +1 @@
+.libs

Added: httpd/apreq/branches/apr-build-system/library/cookie.c
URL: http://svn.apache.org/viewcvs/httpd/apreq/branches/apr-build-system/library/cookie.c?rev=380784&view=auto
==============================================================================
--- httpd/apreq/branches/apr-build-system/library/cookie.c (added)
+++ httpd/apreq/branches/apr-build-system/library/cookie.c Fri Feb 24 10:56:34 2006
@@ -0,0 +1,466 @@
+/*
+**  Copyright 2003-2006  The Apache Software Foundation
+**
+**  Licensed 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.
+*/
+
+#include "apreq_cookie.h"
+#include "apreq_error.h"
+#include "apreq_util.h"
+#include "apr_strings.h"
+#include "apr_lib.h"
+#include "apr_date.h"
+
+
+#define RFC      1
+#define NETSCAPE 0
+
+#define ADD_COOKIE(j,c) apreq_value_table_add(&c->v, j)
+
+APREQ_DECLARE(void) apreq_cookie_expires(apreq_cookie_t *c,
+                                         const char *time_str)
+{
+    if (time_str == NULL) {
+        c->max_age = -1;
+        return;
+    }
+
+    if (!strcasecmp(time_str, "now"))
+        c->max_age = 0;
+    else {
+        c->max_age = apr_date_parse_rfc(time_str);
+        if (c->max_age == APR_DATE_BAD)
+            c->max_age = apr_time_from_sec(apreq_atoi64t(time_str));
+        else
+            c->max_age -= apr_time_now();
+    }
+}
+
+static apr_status_t apreq_cookie_attr(apr_pool_t *p,
+                                      apreq_cookie_t *c,
+                                      const char *attr,
+                                      apr_size_t alen,
+                                      const char *val,
+                                      apr_size_t vlen)
+{
+    if (alen < 2)
+        return APR_EBADARG;
+
+    if ( attr[0] ==  '-' || attr[0] == '$' ) {
+        ++attr;
+        --alen;
+    }
+
+    switch (apr_tolower(*attr)) {
+
+    case 'n': /* name is not an attr */
+        return APR_ENOTIMPL;
+
+    case 'v': /* version; value is not an attr */
+        if (alen == 5 && strncasecmp(attr,"value", 5) == 0)
+            return APR_ENOTIMPL;
+
+        while (!apr_isdigit(*val)) {
+            if (vlen == 0)
+                return APREQ_ERROR_BADSEQ;
+            ++val;
+            --vlen;
+        }
+        apreq_cookie_version_set(c, *val - '0');
+        return APR_SUCCESS;
+
+    case 'e': case 'm': /* expires, max-age */
+        apreq_cookie_expires(c, val);
+        return APR_SUCCESS;
+
+    case 'd':
+        c->domain = apr_pstrmemdup(p,val,vlen);
+        return APR_SUCCESS;
+
+    case 'p':
+        if (alen != 4)
+            break;
+        if (!strncasecmp("port", attr, 4)) {
+            c->port = apr_pstrmemdup(p,val,vlen);
+            return APR_SUCCESS;
+        }
+        else if (!strncasecmp("path", attr, 4)) {
+            c->path = apr_pstrmemdup(p,val,vlen);
+            return APR_SUCCESS;
+        }
+        break;
+
+    case 'c':
+        if (!strncasecmp("commentURL", attr, 10)) {
+            c->commentURL = apr_pstrmemdup(p,val,vlen);
+            return APR_SUCCESS;
+        }
+        else if (!strncasecmp("comment", attr, 7)) {
+            c->comment = apr_pstrmemdup(p,val,vlen);
+            return APR_SUCCESS;
+        }
+        break;
+
+    case 's':
+        if (vlen > 0 && *val != '0' && strncasecmp("off",val,vlen))
+            apreq_cookie_secure_on(c);
+        else
+            apreq_cookie_secure_off(c);
+        return APR_SUCCESS;
+
+    };
+
+    return APR_ENOTIMPL;
+}
+
+APREQ_DECLARE(apreq_cookie_t *) apreq_cookie_make(apr_pool_t *p,
+                                                  const char *name,
+                                                  const apr_size_t nlen,
+                                                  const char *value,
+                                                  const apr_size_t vlen)
+{
+    apreq_cookie_t *c;
+    apreq_value_t *v;
+
+    c = apr_palloc(p, nlen + vlen + 1 + sizeof *c);
+
+    if (c == NULL)
+        return NULL;
+
+    *(const apreq_value_t **)&v = &c->v;
+
+    if (vlen > 0 && value != NULL)
+        memcpy(v->data, value, vlen);
+    v->data[vlen] = 0;
+    v->dlen = vlen;
+    v->name = v->data + vlen + 1;
+    if (nlen && name != NULL)
+        memcpy(v->name, name, nlen);
+    v->name[nlen] = 0;
+    v->nlen = nlen;
+
+    c->path = NULL;
+    c->domain = NULL;
+    c->port = NULL;
+    c->comment = NULL;
+    c->commentURL = NULL;
+    c->max_age = -1;    /* session cookie is the default */
+    c->flags = 0;
+
+
+    return c;
+}
+
+static APR_INLINE
+apr_status_t get_pair(apr_pool_t *p, const char **data,
+                      const char **n, apr_size_t *nlen,
+                      const char **v, apr_size_t *vlen, unsigned unquote)
+{
+    const char *hdr, *key, *val;
+
+    hdr = *data;
+
+    while (apr_isspace(*hdr) || *hdr == '=')
+        ++hdr;
+
+    key = strchr(hdr, '=');
+
+    if (key == NULL)
+        return APREQ_ERROR_NOTOKEN;
+
+    val = key + 1;
+
+    do --key;
+    while (key > hdr && apr_isspace(*key));
+
+    *n = key;
+
+    while (key >= hdr && !apr_isspace(*key))
+        --key;
+
+    *nlen = *n - key;
+    *n = key + 1;
+
+    while (apr_isspace(*val))
+        ++val;
+
+    if (*val == '"') {
+        unsigned saw_backslash = 0;
+        for (*v = (unquote) ? ++val : val++; *val; ++val) {
+            switch (*val) {
+            case '"':
+                *data = val + 1;
+
+                if (!unquote) {
+                    *vlen = (val - *v) + 1;
+                }
+                else if (!saw_backslash) {
+                    *vlen = val - *v;
+                }
+                else {
+                    char *dest = apr_palloc(p, val - *v), *d = dest;
+                    const char *s = *v;
+                    while (s < val) {
+                        if (*s == '\\')
+                            ++s;
+                        *d++ = *s++;
+                    }
+
+                    *vlen = d - dest;
+                    *v = dest;
+                }
+
+                return APR_SUCCESS;
+            case '\\':
+                saw_backslash = 1;
+                if (val[1] != 0)
+                    ++val;
+            default:
+                break;
+            }
+        }
+        /* bad sequence: no terminating quote found */
+        return APREQ_ERROR_BADSEQ;
+    }
+    else {
+        /* value is not wrapped in quotes */
+        for (*v = val; *val; ++val) {
+            switch (*val) {
+            case ';':
+            case ',':
+            case ' ':
+            case '\t':
+            case '\r':
+            case '\n':
+                *data = val;
+                *vlen = val - *v;
+                return APR_SUCCESS;
+            default:
+                break;
+            }
+        }
+    }
+
+    *data = val;
+    *vlen = val - *v;
+
+    return APR_SUCCESS;
+}
+
+
+
+APREQ_DECLARE(apr_status_t)apreq_parse_cookie_header(apr_pool_t *p,
+                                                     apr_table_t *j,
+                                                     const char *hdr)
+{
+    apreq_cookie_t *c;
+    unsigned version;
+
+ parse_cookie_header:
+
+    c = NULL;
+    version = NETSCAPE;
+
+    while (apr_isspace(*hdr))
+        ++hdr;
+
+
+    if (*hdr == '$') {
+        /* XXX cheat: assume "$..." => "$Version" => RFC Cookie header */
+        version = RFC;
+    skip_version_string:
+        switch (*hdr++) {
+        case 0:
+            return APR_SUCCESS;
+        case ',':
+            goto parse_cookie_header;
+        case ';':
+            break;
+        default:
+            goto skip_version_string;
+        }
+    }
+
+    for (;;) {
+        apr_status_t status;
+        const char *name, *value;
+        apr_size_t nlen, vlen;
+
+        while (*hdr == ';' || apr_isspace(*hdr))
+            ++hdr;
+
+        switch (*hdr) {
+
+        case 0:
+            /* this is the normal exit point */
+            if (c != NULL) {
+                ADD_COOKIE(j, c);
+            }
+            return APR_SUCCESS;
+
+        case ',':
+            ++hdr;
+            if (c != NULL) {
+                ADD_COOKIE(j, c);
+            }
+            goto parse_cookie_header;
+
+        case '$':
+            if (c == NULL) {
+                return APREQ_ERROR_BADCHAR;
+            }
+            else if (version == NETSCAPE) {
+                return APREQ_ERROR_MISMATCH;
+            }
+
+            ++hdr;
+            status = get_pair(p, &hdr, &name, &nlen, &value, &vlen, 1);
+            if (status != APR_SUCCESS)
+                return status;
+
+            status = apreq_cookie_attr(p, c, name, nlen, value, vlen);
+
+            switch (status) {
+            case APR_ENOTIMPL:
+                /* XXX: skip unrecognized attr?  Not really correct,
+                   but for now, just fall through */
+
+            case APR_SUCCESS:
+                break;
+            default:
+                return status;
+            }
+
+            break;
+
+        default:
+            if (c != NULL) {
+                ADD_COOKIE(j, c);
+            }
+
+            status = get_pair(p, &hdr, &name, &nlen, &value, &vlen, 0);
+
+            if (status != APR_SUCCESS)
+                return status;
+
+            c = apreq_cookie_make(p, name, nlen, value, vlen);
+            apreq_cookie_tainted_on(c);
+            if (version != NETSCAPE)
+                apreq_cookie_version_set(c, version);
+        }
+    }
+
+    /* NOT REACHED */
+    return APREQ_ERROR_GENERAL;
+}
+
+
+APREQ_DECLARE(int) apreq_cookie_serialize(const apreq_cookie_t *c,
+                                          char *buf, apr_size_t len)
+{
+    /*  The format string must be large enough to accomodate all
+     *  of the cookie attributes.  The current attributes sum to
+     *  ~90 characters (w/ 6-8 padding chars per attr), so anything
+     *  over 100 should be fine.
+     */
+
+    unsigned version = apreq_cookie_version(c);
+    char format[128] = "%s=%s";
+    char *f = format + strlen(format);
+
+    /* XXX protocol enforcement (for debugging, anyway) ??? */
+
+    if (c->v.name == NULL)
+        return -1;
+
+#define NULL2EMPTY(attr) (attr ? attr : "")
+
+
+    if (version == NETSCAPE) {
+        char expires[APR_RFC822_DATE_LEN] = {0};
+
+#define ADD_NS_ATTR(name) do {                  \
+    if (c->name != NULL)                        \
+        strcpy(f, "; " #name "=%s");            \
+    else                                        \
+        strcpy(f, "%0.s");                      \
+    f += strlen(f);                             \
+} while (0)
+
+        ADD_NS_ATTR(path);
+        ADD_NS_ATTR(domain);
+
+        if (c->max_age != -1) {
+            strcpy(f, "; expires=%s");
+            apr_rfc822_date(expires, c->max_age + apr_time_now());
+            expires[7] = '-';
+            expires[11] = '-';
+        }
+        else
+            strcpy(f, "");
+
+        f += strlen(f);
+
+        if (apreq_cookie_is_secure(c))
+            strcpy(f, "; secure");
+
+        return apr_snprintf(buf, len, format, c->v.name, c->v.data,
+           NULL2EMPTY(c->path), NULL2EMPTY(c->domain), expires);
+    }
+
+    /* c->version == RFC */
+
+    strcpy(f,"; Version=%u");
+    f += strlen(f);
+
+/* ensure RFC attributes are always quoted */
+#define ADD_RFC_ATTR(name) do {                 \
+    if (c->name != NULL)                        \
+        if (*c->name == '"')                    \
+            strcpy(f, "; " #name "=%s");        \
+        else                                    \
+            strcpy(f, "; " #name "=\"%s\"");    \
+    else                                        \
+        strcpy(f, "%0.s");                      \
+    f += strlen (f);                            \
+} while (0)
+
+    ADD_RFC_ATTR(path);
+    ADD_RFC_ATTR(domain);
+    ADD_RFC_ATTR(port);
+    ADD_RFC_ATTR(comment);
+    ADD_RFC_ATTR(commentURL);
+
+    strcpy(f, c->max_age != -1 ? "; max-age=%" APR_TIME_T_FMT : "");
+
+    f += strlen(f);
+
+    if (apreq_cookie_is_secure(c))
+        strcpy(f, "; secure");
+
+    return apr_snprintf(buf, len, format, c->v.name, c->v.data, version,
+                        NULL2EMPTY(c->path), NULL2EMPTY(c->domain),
+                        NULL2EMPTY(c->port), NULL2EMPTY(c->comment),
+                        NULL2EMPTY(c->commentURL), apr_time_sec(c->max_age));
+}
+
+
+APREQ_DECLARE(char*) apreq_cookie_as_string(const apreq_cookie_t *c,
+                                            apr_pool_t *p)
+{
+    int n = apreq_cookie_serialize(c, NULL, 0);
+    char *s = apr_palloc(p, n + 1);
+    apreq_cookie_serialize(c, s, n + 1);
+    return s;
+}
+

Propchange: httpd/apreq/branches/apr-build-system/library/cookie.c
------------------------------------------------------------------------------
    svn:eol-style = native

Added: httpd/apreq/branches/apr-build-system/library/error.c
URL: http://svn.apache.org/viewcvs/httpd/apreq/branches/apr-build-system/library/error.c?rev=380784&view=auto
==============================================================================
--- httpd/apreq/branches/apr-build-system/library/error.c (added)
+++ httpd/apreq/branches/apr-build-system/library/error.c Fri Feb 24 10:56:34 2006
@@ -0,0 +1,104 @@
+/* Copyright 2000-2006 The Apache Software Foundation
+ *
+ * Licensed 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.
+ */
+
+#include "apreq_error.h"
+#include "apr_strings.h"
+
+/*
+ * stuffbuffer - like apr_cpystrn() but returns the address of the
+ * dest buffer instead of the address of the terminating '\0'
+ */
+static char *stuffbuffer(char *buf, apr_size_t bufsize, const char *s)
+{
+    apr_cpystrn(buf,s,bufsize);
+    return buf;
+}
+
+static const char *apreq_error_string(apr_status_t statcode)
+{
+    switch (statcode) {
+
+
+/* 0's: generic error status codes */
+
+    case APREQ_ERROR_GENERAL:
+        return "Internal apreq error";
+
+    case APREQ_ERROR_TAINTED:
+        return "Attempt to perform unsafe action with tainted data";
+
+
+/* 10's: malformed input */
+
+    case APREQ_ERROR_BADDATA:
+        return "Malformed input data";
+
+    case APREQ_ERROR_BADCHAR:
+        return "Invalid character";
+
+    case APREQ_ERROR_BADSEQ:
+        return "Invalid byte sequence";
+
+    case APREQ_ERROR_BADATTR:
+        return "Unrecognized attribute";
+
+    case APREQ_ERROR_BADHEADER:
+        return "Malformed header string";
+
+
+/* 20's: missing input */
+
+    case APREQ_ERROR_NODATA:
+        return "Missing input data";
+
+    case APREQ_ERROR_NOTOKEN:
+        return "Expected token not present";
+
+    case APREQ_ERROR_NOATTR:
+        return "Missing attribute";
+
+    case APREQ_ERROR_NOHEADER:
+        return "Missing header";
+
+    case APREQ_ERROR_NOPARSER:
+        return "Missing parser";
+
+
+/* 30's: configuration conflicts */
+
+    case APREQ_ERROR_MISMATCH:
+        return "Conflicting information";
+
+    case APREQ_ERROR_OVERLIMIT:
+        return "Exceeds configured maximum limit";
+
+    case APREQ_ERROR_NOTEMPTY:
+        return "Setting already configured";
+
+
+    default:
+        return "Error string not yet specified by apreq";
+    }
+}
+
+
+APREQ_DECLARE(char *) apreq_strerror(apr_status_t statcode, char *buf,
+                                 apr_size_t bufsize)
+{
+    if (statcode < APR_OS_START_USERERR || statcode >= APR_OS_START_EAIERR)
+        return apr_strerror(statcode, buf, bufsize);
+    return stuffbuffer(buf, bufsize, apreq_error_string(statcode));
+}
+

Propchange: httpd/apreq/branches/apr-build-system/library/error.c
------------------------------------------------------------------------------
    svn:eol-style = native

Added: httpd/apreq/branches/apr-build-system/library/module.c
URL: http://svn.apache.org/viewcvs/httpd/apreq/branches/apr-build-system/library/module.c?rev=380784&view=auto
==============================================================================
--- httpd/apreq/branches/apr-build-system/library/module.c (added)
+++ httpd/apreq/branches/apr-build-system/library/module.c Fri Feb 24 10:56:34 2006
@@ -0,0 +1,52 @@
+/*
+**  Copyright 2003-2006  The Apache Software Foundation
+**
+**  Licensed 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.
+*/
+
+#include "apreq_module.h"
+#include "apreq_error.h"
+#include "apr_strings.h"
+#include "apr_lib.h"
+#include "apr_file_io.h"
+
+APREQ_DECLARE(apreq_param_t *)apreq_param(apreq_handle_t *req, const char *key)
+{
+    apreq_param_t *param = apreq_args_get(req, key);
+    if (param == NULL)
+        return apreq_body_get(req, key);
+    else
+        return param;
+}
+
+APREQ_DECLARE(apr_table_t *)apreq_params(apreq_handle_t *req, apr_pool_t *p)
+{
+    const apr_table_t *args, *body;
+    apreq_args(req, &args);
+    apreq_body(req, &body);
+
+    if (args != NULL)
+        if (body != NULL)
+            return apr_table_overlay(p, args, body);
+        else
+            return apr_table_copy(p, args);
+    else
+        if (body != NULL)
+            return apr_table_copy(p, body);
+        else
+            return NULL;
+
+}
+
+
+/** @} */

Propchange: httpd/apreq/branches/apr-build-system/library/module.c
------------------------------------------------------------------------------
    svn:eol-style = native

Added: httpd/apreq/branches/apr-build-system/library/module_cgi.c
URL: http://svn.apache.org/viewcvs/httpd/apreq/branches/apr-build-system/library/module_cgi.c?rev=380784&view=auto
==============================================================================
--- httpd/apreq/branches/apr-build-system/library/module_cgi.c (added)
+++ httpd/apreq/branches/apr-build-system/library/module_cgi.c Fri Feb 24 10:56:34 2006
@@ -0,0 +1,688 @@
+/*
+**  Copyright 2003-2006  The Apache Software Foundation
+**
+**  Licensed 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.
+*/
+#include <assert.h>
+
+#include "apreq_module.h"
+#include "apreq_error.h"
+#include "apr_strings.h"
+#include "apr_lib.h"
+#include "apr_env.h"
+#include "apreq_util.h"
+
+#define USER_DATA_KEY "apreq"
+
+/* Parroting APLOG_* ... */
+
+#define	CGILOG_EMERG	0	/* system is unusable */
+#define	CGILOG_ALERT	1	/* action must be taken immediately */
+#define	CGILOG_CRIT	2	/* critical conditions */
+#define	CGILOG_ERR	3	/* error conditions */
+#define	CGILOG_WARNING	4	/* warning conditions */
+#define	CGILOG_NOTICE	5	/* normal but significant condition */
+#define	CGILOG_INFO	6	/* informational */
+#define	CGILOG_DEBUG	7	/* debug-level messages */
+
+#define CGILOG_LEVELMASK 7
+#define CGILOG_MARK     __FILE__, __LINE__
+
+
+
+
+struct cgi_handle {
+    struct apreq_handle_t       handle;
+
+    apr_table_t                 *jar, *args, *body;
+    apr_status_t                 jar_status,
+                                 args_status,
+                                 body_status;
+
+    apreq_parser_t              *parser;
+    apreq_hook_t                *hook_queue;
+    apreq_hook_t                *find_param;
+
+    const char                  *temp_dir;
+    apr_size_t                   brigade_limit;
+    apr_uint64_t                 read_limit;
+    apr_uint64_t                 bytes_read;
+
+    apr_bucket_brigade          *in;
+    apr_bucket_brigade          *tmpbb;
+
+};
+
+#define CRLF "\015\012"
+
+typedef struct {
+    const char *t_name;
+    int      t_val;
+} TRANS;
+
+static const TRANS priorities[] = {
+    {"emerg",   CGILOG_EMERG},
+    {"alert",   CGILOG_ALERT},
+    {"crit",    CGILOG_CRIT},
+    {"error",   CGILOG_ERR},
+    {"warn",    CGILOG_WARNING},
+    {"notice",  CGILOG_NOTICE},
+    {"info",    CGILOG_INFO},
+    {"debug",   CGILOG_DEBUG},
+    {NULL,      -1},
+};
+
+static const char *cgi_header_in(apreq_handle_t *handle,
+                                 const char *name)
+{
+    apr_pool_t *p = handle->pool;
+    char *key = apr_pstrcat(p, "HTTP_", name, NULL);
+    char *k, *value = NULL;
+    for (k = key; *k; ++k) {
+        if (*k == '-')
+            *k = '_';
+        else
+            *k = apr_toupper(*k);
+    }
+
+    if (!strcmp(key, "HTTP_CONTENT_TYPE")
+        || !strcmp(key, "HTTP_CONTENT_LENGTH"))
+        {
+            key += 5; /* strlen("HTTP_") */
+        }
+
+    apr_env_get(&value, key, p);
+
+    return value;
+}
+
+
+
+
+static void cgi_log_error(const char *file, int line, int level,
+                          apr_status_t status, apreq_handle_t *handle,
+                          const char *fmt, ...)
+{
+    apr_pool_t *p = handle->pool;
+    char buf[256];
+    char *log_level_string, *ra;
+    const char *remote_addr;
+    unsigned log_level = CGILOG_WARNING;
+    char date[APR_CTIME_LEN];
+    va_list vp;
+#ifndef WIN32
+    apr_file_t *err;
+#endif
+
+    va_start(vp, fmt);
+
+    if (apr_env_get(&log_level_string, "LOG_LEVEL", p) == APR_SUCCESS)
+        log_level = (log_level_string[0] - '0');
+
+    level &= CGILOG_LEVELMASK;
+
+    if (level < (int)log_level) {
+
+        if (apr_env_get(&ra, "REMOTE_ADDR", p) == APR_SUCCESS)
+            remote_addr = ra;
+        else
+            remote_addr = "address unavailable";
+
+        apr_ctime(date, apr_time_now());
+
+#ifndef WIN32
+
+        apr_file_open_stderr(&err, p);
+        apr_file_printf(err, "[%s] [%s] [%s] %s(%d): %s: %s\n",
+                        date, priorities[level].t_name, remote_addr, file, line,
+                        apr_strerror(status,buf,255),apr_pvsprintf(p,fmt,vp));
+        apr_file_flush(err);
+
+#else
+        fprintf(stderr, "[%s] [%s] [%s] %s(%d): %s: %s\n",
+                date, priorities[level].t_name, remote_addr, file, line,
+                apr_strerror(status,buf,255),apr_pvsprintf(p,fmt,vp));
+#endif
+    }
+
+    va_end(vp);
+
+}
+
+
+APR_INLINE
+static const char *cgi_query_string(apreq_handle_t *handle)
+{
+    char *value = NULL, qs[] = "QUERY_STRING";
+    apr_env_get(&value, qs, handle->pool);
+    return value;
+}
+
+
+static void init_body(apreq_handle_t *handle)
+{
+    struct cgi_handle *req = (struct cgi_handle *)handle;
+    const char *cl_header = cgi_header_in(handle, "Content-Length");
+    apr_bucket_alloc_t *ba = handle->bucket_alloc;
+    apr_pool_t *pool = handle->pool;
+    apr_file_t *file;
+    apr_bucket *eos, *pipe;
+
+    req->body  = apr_table_make(pool, APREQ_DEFAULT_NELTS);
+
+    if (cl_header != NULL) {
+        char *dummy;
+        apr_int64_t content_length = apr_strtoi64(cl_header, &dummy, 0);
+
+        if (dummy == NULL || *dummy != 0) {
+            req->body_status = APREQ_ERROR_BADHEADER;
+            cgi_log_error(CGILOG_MARK, CGILOG_ERR, req->body_status, handle,
+                          "Invalid Content-Length header (%s)", cl_header);
+            return;
+        }
+        else if ((apr_uint64_t)content_length > req->read_limit) {
+            req->body_status = APREQ_ERROR_OVERLIMIT;
+            cgi_log_error(CGILOG_MARK, CGILOG_ERR, req->body_status, handle,
+                          "Content-Length header (%s) exceeds configured "
+                          "max_body limit (%" APR_UINT64_T_FMT ")",
+                          cl_header, req->read_limit);
+            return;
+        }
+    }
+
+    if (req->parser == NULL) {
+        const char *ct_header = cgi_header_in(handle, "Content-Type");
+
+        if (ct_header != NULL) {
+            apreq_parser_function_t pf = apreq_parser(ct_header);
+
+            if (pf != NULL) {
+                req->parser = apreq_parser_make(pool,
+                                                ba,
+                                                ct_header,
+                                                pf,
+                                                req->brigade_limit,
+                                                req->temp_dir,
+                                                req->hook_queue,
+                                                NULL);
+            }
+            else {
+                req->body_status = APREQ_ERROR_NOPARSER;
+                return;
+            }
+        }
+        else {
+            req->body_status = APREQ_ERROR_NOHEADER;
+            return;
+        }
+    }
+    else {
+        if (req->parser->brigade_limit > req->brigade_limit)
+            req->parser->brigade_limit = req->brigade_limit;
+        if (req->temp_dir != NULL)
+            req->parser->temp_dir = req->temp_dir;
+        if (req->hook_queue != NULL)
+            apreq_parser_add_hook(req->parser, req->hook_queue);
+    }
+
+    req->hook_queue = NULL;
+    req->in         = apr_brigade_create(pool, ba);
+    req->tmpbb      = apr_brigade_create(pool, ba);
+
+    apr_file_open_stdin(&file, pool); // error status?
+    pipe = apr_bucket_pipe_create(file, ba);
+    eos = apr_bucket_eos_create(ba);
+    APR_BRIGADE_INSERT_HEAD(req->in, pipe);
+    APR_BRIGADE_INSERT_TAIL(req->in, eos);
+
+    req->body_status = APR_INCOMPLETE;
+
+}
+
+static apr_status_t cgi_read(apreq_handle_t *handle,
+                             apr_off_t bytes)
+{
+    struct cgi_handle *req = (struct cgi_handle *)handle;
+    apr_bucket *e;
+    apr_status_t s;
+
+    if (req->body_status == APR_EINIT)
+        init_body(handle);
+
+    if (req->body_status != APR_INCOMPLETE)
+        return req->body_status;
+
+
+    switch (s = apr_brigade_partition(req->in, bytes, &e)) {
+        apr_off_t len;
+
+    case APR_SUCCESS:
+
+        apreq_brigade_move(req->tmpbb, req->in, e);
+        req->bytes_read += bytes;
+
+        if (req->bytes_read > req->read_limit) {
+            req->body_status = APREQ_ERROR_OVERLIMIT;
+            cgi_log_error(CGILOG_MARK, CGILOG_ERR, req->body_status,
+                          handle, "Bytes read (%" APR_UINT64_T_FMT
+                          ") exceeds configured limit (%" APR_UINT64_T_FMT ")",
+                          req->bytes_read, req->read_limit);
+            break;
+        }
+
+        req->body_status =
+            apreq_parser_run(req->parser, req->body, req->tmpbb);
+        apr_brigade_cleanup(req->tmpbb);
+        break;
+
+
+    case APR_INCOMPLETE:
+
+        apreq_brigade_move(req->tmpbb, req->in, e);
+        s = apr_brigade_length(req->tmpbb, 1, &len);
+
+        if (s != APR_SUCCESS) {
+            req->body_status = s;
+            break;
+        }
+        req->bytes_read += len;
+
+        if (req->bytes_read > req->read_limit) {
+            req->body_status = APREQ_ERROR_OVERLIMIT;
+            cgi_log_error(CGILOG_MARK, CGILOG_ERR, req->body_status, handle,
+                          "Bytes read (%" APR_UINT64_T_FMT
+                          ") exceeds configured limit (%" APR_UINT64_T_FMT ")",
+                          req->bytes_read, req->read_limit);
+
+            break;
+        }
+
+        req->body_status =
+            apreq_parser_run(req->parser, req->body, req->tmpbb);
+        apr_brigade_cleanup(req->tmpbb);
+        break;
+
+    default:
+        req->body_status = s;
+    }
+
+    return req->body_status;
+}
+
+
+
+static apr_status_t cgi_jar(apreq_handle_t *handle,
+                            const apr_table_t **t)
+{
+    struct cgi_handle *req = (struct cgi_handle *)handle;
+
+    if (req->jar_status == APR_EINIT) {
+        const char *cookies = cgi_header_in(handle, "Cookie");
+        if (cookies != NULL) {
+            req->jar = apr_table_make(handle->pool, APREQ_DEFAULT_NELTS);
+            req->jar_status =
+                apreq_parse_cookie_header(handle->pool, req->jar, cookies);
+        }
+        else
+            req->jar_status = APREQ_ERROR_NODATA;
+    }
+
+    *t = req->jar;
+    return req->jar_status;
+}
+
+static apr_status_t cgi_args(apreq_handle_t *handle,
+                             const apr_table_t **t)
+{
+    struct cgi_handle *req = (struct cgi_handle *)handle;
+
+    if (req->args_status == APR_EINIT) {
+        const char *qs = cgi_query_string(handle);
+        if (qs != NULL) {
+            req->args = apr_table_make(handle->pool, APREQ_DEFAULT_NELTS);
+            req->args_status =
+                apreq_parse_query_string(handle->pool, req->args, qs);
+        }
+        else
+            req->args_status = APREQ_ERROR_NODATA;
+    }
+
+    *t = req->args;
+    return req->args_status;
+}
+
+
+
+
+static apreq_cookie_t *cgi_jar_get(apreq_handle_t *handle,
+                                   const char *name)
+{
+    struct cgi_handle *req = (struct cgi_handle *)handle;
+    const apr_table_t *t;
+    const char *val;
+
+    if (req->jar_status == APR_EINIT)
+        cgi_jar(handle, &t);
+    else
+        t = req->jar;
+
+    if (t == NULL)
+        return NULL;
+
+    val = apr_table_get(t, name);
+    if (val == NULL)
+        return NULL;
+
+    return apreq_value_to_cookie(val);
+}
+
+static apreq_param_t *cgi_args_get(apreq_handle_t *handle,
+                                   const char *name)
+{
+    struct cgi_handle *req = (struct cgi_handle *)handle;
+    const apr_table_t *t;
+    const char *val;
+
+    if (req->args_status == APR_EINIT)
+        cgi_args(handle, &t);
+    else
+        t = req->args;
+
+    if (t == NULL)
+        return NULL;
+
+    val = apr_table_get(t, name);
+    if (val == NULL)
+        return NULL;
+
+    return apreq_value_to_param(val);
+}
+
+
+
+static apr_status_t cgi_body(apreq_handle_t *handle,
+                             const apr_table_t **t)
+{
+    struct cgi_handle *req = (struct cgi_handle *)handle;
+
+    switch (req->body_status) {
+
+    case APR_EINIT:
+        init_body(handle);
+        if (req->body_status != APR_INCOMPLETE)
+            break;
+
+    case APR_INCOMPLETE:
+        while (cgi_read(handle, APREQ_DEFAULT_READ_BLOCK_SIZE)
+               == APR_INCOMPLETE)
+            ;   /*loop*/
+    }
+
+    *t = req->body;
+    return req->body_status;
+}
+
+static apreq_param_t *cgi_body_get(apreq_handle_t *handle,
+                                   const char *name)
+{
+    struct cgi_handle *req = (struct cgi_handle *)handle;
+    const char *val;
+    apreq_hook_t *h;
+
+    switch (req->body_status) {
+
+    case APR_SUCCESS:
+
+        val = apr_table_get(req->body, name);
+        if (val != NULL)
+            return apreq_value_to_param(val);
+        return NULL;
+
+
+    case APR_EINIT:
+
+        init_body(handle);
+        if (req->body_status != APR_INCOMPLETE)
+            return NULL;
+        cgi_read(handle, APREQ_DEFAULT_READ_BLOCK_SIZE);
+
+
+    case APR_INCOMPLETE:
+
+        val = apr_table_get(req->body, name);
+        if (val != NULL)
+            return apreq_value_to_param(val);
+
+        /* Not seen yet, so we need to scan for
+           param while prefetching the body */
+
+        if (req->find_param == NULL)
+            req->find_param = apreq_hook_make(handle->pool,
+                                              apreq_hook_find_param,
+                                              NULL, NULL);
+        h = req->find_param;
+        h->next = req->parser->hook;
+        req->parser->hook = h;
+        *(const char **)&h->ctx = name;
+
+        do {
+            cgi_read(handle, APREQ_DEFAULT_READ_BLOCK_SIZE);
+            if (h->ctx != name) {
+                req->parser->hook = h->next;
+                return h->ctx;
+            }
+        } while (req->body_status == APR_INCOMPLETE);
+
+        req->parser->hook = h->next;
+        return NULL;
+
+
+    default:
+
+        if (req->body == NULL)
+            return NULL;
+
+        val = apr_table_get(req->body, name);
+        if (val != NULL)
+            return apreq_value_to_param(val);
+        return NULL;
+    }
+
+    /* not reached */
+    return NULL;
+}
+
+static apr_status_t cgi_parser_get(apreq_handle_t *handle,
+                                   const apreq_parser_t **parser)
+{
+    struct cgi_handle *req = (struct cgi_handle *)handle;
+
+    *parser = req->parser;
+    return APR_SUCCESS;
+}
+
+static apr_status_t cgi_parser_set(apreq_handle_t *handle,
+                                   apreq_parser_t *parser)
+{
+    struct cgi_handle *req = (struct cgi_handle *)handle;
+
+    if (req->parser == NULL) {
+
+        if (req->hook_queue != NULL) {
+            apr_status_t s = apreq_parser_add_hook(parser, req->hook_queue);
+            if (s != APR_SUCCESS)
+                return s;
+        }
+        if (req->temp_dir != NULL) {
+            parser->temp_dir = req->temp_dir;
+        }
+        if (req->brigade_limit < parser->brigade_limit) {
+            parser->brigade_limit = req->brigade_limit;
+        }
+
+        req->hook_queue = NULL;
+        req->parser = parser;
+        return APR_SUCCESS;
+    }
+    else
+        return APREQ_ERROR_MISMATCH;
+}
+
+
+static apr_status_t cgi_hook_add(apreq_handle_t *handle,
+                                     apreq_hook_t *hook)
+{
+    struct cgi_handle *req = (struct cgi_handle *)handle;
+
+    if (req->parser != NULL) {
+        return apreq_parser_add_hook(req->parser, hook);
+    }
+    else if (req->hook_queue != NULL) {
+        apreq_hook_t *h = req->hook_queue;
+        while (h->next != NULL)
+            h = h->next;
+        h->next = hook;
+    }
+    else {
+        req->hook_queue = hook;
+    }
+    return APR_SUCCESS;
+
+}
+
+static apr_status_t cgi_brigade_limit_set(apreq_handle_t *handle,
+                                          apr_size_t bytes)
+{
+    struct cgi_handle *req = (struct cgi_handle *)handle;
+    apr_size_t *limit = (req->parser == NULL)
+                      ? &req->brigade_limit
+                      : &req->parser->brigade_limit;
+
+    if (*limit > bytes) {
+        *limit = bytes;
+        return APR_SUCCESS;
+    }
+
+    return APREQ_ERROR_MISMATCH;
+}
+
+static apr_status_t cgi_brigade_limit_get(apreq_handle_t *handle,
+                                          apr_size_t *bytes)
+{
+    struct cgi_handle *req = (struct cgi_handle *)handle;
+    *bytes = (req->parser == NULL)
+           ?  req->brigade_limit
+           :  req->parser->brigade_limit;
+
+    return APR_SUCCESS;
+}
+
+static apr_status_t cgi_read_limit_set(apreq_handle_t *handle,
+                                       apr_uint64_t bytes)
+{
+    struct cgi_handle *req = (struct cgi_handle *)handle;
+
+    if (req->read_limit > bytes && req->bytes_read < bytes) {
+        req->read_limit = bytes;
+        return APR_SUCCESS;
+    }
+
+    return APREQ_ERROR_MISMATCH;
+}
+
+
+static apr_status_t cgi_read_limit_get(apreq_handle_t *handle,
+                                       apr_uint64_t *bytes)
+{
+    struct cgi_handle *req = (struct cgi_handle *)handle;
+    *bytes = req->read_limit;
+    return APR_SUCCESS;
+}
+
+
+static apr_status_t cgi_temp_dir_set(apreq_handle_t *handle,
+                                     const char *path)
+{
+    struct cgi_handle *req = (struct cgi_handle *)handle;
+    const char **temp_dir = (req->parser == NULL)
+                          ? &req->temp_dir
+                          : &req->parser->temp_dir;
+
+
+    if (*temp_dir == NULL && req->bytes_read == 0) {
+        if (path != NULL)
+            *temp_dir = apr_pstrdup(handle->pool, path);
+        return APR_SUCCESS;
+    }
+
+    return APREQ_ERROR_MISMATCH;
+}
+
+
+static apr_status_t cgi_temp_dir_get(apreq_handle_t *handle,
+                                     const char **path)
+{
+    struct cgi_handle *req = (struct cgi_handle *)handle;
+    *path = (req->parser == NULL)
+           ? req->temp_dir
+           : req->parser->temp_dir;
+    return APR_SUCCESS;
+}
+
+
+
+#ifdef APR_POOL_DEBUG
+static apr_status_t ba_cleanup(void *data)
+{
+    apr_bucket_alloc_t *ba = data;
+    apr_bucket_alloc_destroy(ba);
+    return APR_SUCCESS;
+}
+#endif
+
+static APREQ_MODULE(cgi, 20050425);
+
+APREQ_DECLARE(apreq_handle_t *)apreq_handle_cgi(apr_pool_t *pool)
+{
+    apr_bucket_alloc_t *ba;
+    struct cgi_handle *req;
+    void *data;
+
+    apr_pool_userdata_get(&data, USER_DATA_KEY, pool);
+
+    if (data != NULL)
+        return data;
+
+    req = apr_pcalloc(pool, sizeof *req);
+    ba = apr_bucket_alloc_create(pool);
+
+    /* check pool's userdata first. */
+
+    req->handle.module        = &cgi_module;
+    req->handle.pool          = pool;
+    req->handle.bucket_alloc  = ba;
+    req->read_limit           = (apr_uint64_t) -1;
+    req->brigade_limit        = APREQ_DEFAULT_BRIGADE_LIMIT;
+
+    req->args_status =
+        req->jar_status =
+            req->body_status = APR_EINIT;
+
+    apr_pool_userdata_setn(&req->handle, USER_DATA_KEY, NULL, pool);
+
+#ifdef APR_POOL_DEBUG
+    apr_pool_cleanup_register(pool, ba, ba_cleanup, ba_cleanup);
+#endif
+
+    return &req->handle;
+}

Propchange: httpd/apreq/branches/apr-build-system/library/module_cgi.c
------------------------------------------------------------------------------
    svn:eol-style = native

Added: httpd/apreq/branches/apr-build-system/library/module_custom.c
URL: http://svn.apache.org/viewcvs/httpd/apreq/branches/apr-build-system/library/module_custom.c?rev=380784&view=auto
==============================================================================
--- httpd/apreq/branches/apr-build-system/library/module_custom.c (added)
+++ httpd/apreq/branches/apr-build-system/library/module_custom.c Fri Feb 24 10:56:34 2006
@@ -0,0 +1,302 @@
+/*
+**  Copyright 2003-2006  The Apache Software Foundation
+**
+**  Licensed 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.
+*/
+
+#include "apr_strings.h"
+#include "apreq_module.h"
+#include "apreq_error.h"
+#include "apreq_util.h"
+
+#define READ_BYTES (64 * 1024)
+
+struct custom_handle {
+    struct apreq_handle_t        handle;
+
+    apr_table_t                 *jar, *args, *body;
+    apr_status_t                 jar_status,
+                                 args_status,
+                                 body_status;
+
+    apreq_parser_t              *parser;
+
+    apr_uint64_t                 read_limit;
+    apr_uint64_t                 bytes_read;
+    apr_bucket_brigade          *in;
+    apr_bucket_brigade          *tmpbb;
+};
+
+
+static apr_status_t custom_parse_brigade(apreq_handle_t *handle, apr_uint64_t bytes)
+{
+    struct custom_handle *req = (struct custom_handle *)handle;
+    apr_status_t s;
+    apr_bucket *e;
+
+    if (req->body_status != APR_INCOMPLETE)
+        return req->body_status;
+
+    switch (s = apr_brigade_partition(req->in, bytes, &e)) {
+        apr_off_t len;
+
+    case APR_SUCCESS:
+        apreq_brigade_move(req->tmpbb, req->in, e);
+        req->bytes_read += bytes;
+
+        if (req->bytes_read > req->read_limit) {
+            req->body_status = APREQ_ERROR_OVERLIMIT;
+            break;
+        }
+
+        req->body_status =
+            apreq_parser_run(req->parser, req->body, req->tmpbb);
+
+        apr_brigade_cleanup(req->tmpbb);
+        break;
+
+    case APR_INCOMPLETE:
+        apreq_brigade_move(req->tmpbb, req->in, e);
+        s = apr_brigade_length(req->tmpbb, 1, &len);
+        if (s != APR_SUCCESS) {
+            req->body_status = s;
+            break;
+        }
+        req->bytes_read += len;
+
+        if (req->bytes_read > req->read_limit) {
+            req->body_status = APREQ_ERROR_OVERLIMIT;
+            break;
+        }
+        req->body_status =
+            apreq_parser_run(req->parser, req->body, req->tmpbb);
+
+        apr_brigade_cleanup(req->tmpbb);
+        break;
+
+    default:
+        req->body_status = s;
+    }
+
+    return req->body_status;
+}
+
+
+
+static apr_status_t custom_jar(apreq_handle_t *handle, const apr_table_t **t)
+{
+    struct custom_handle *req = (struct custom_handle *)handle;
+    *t = req->jar;
+    return req->jar_status;
+}
+
+static apr_status_t custom_args(apreq_handle_t *handle, const apr_table_t **t)
+{
+    struct custom_handle *req = (struct custom_handle*)handle;
+    *t = req->args;
+    return req->args_status;
+}
+
+static apr_status_t custom_body(apreq_handle_t *handle, const apr_table_t **t)
+{
+    struct custom_handle *req = (struct custom_handle*)handle;
+    while (req->body_status == APR_INCOMPLETE)
+        custom_parse_brigade(handle, READ_BYTES);
+    *t = req->body;
+    return req->body_status;
+}
+
+
+
+static apreq_cookie_t *custom_jar_get(apreq_handle_t *handle, const char *name)
+{
+    struct custom_handle *req = (struct custom_handle*)handle;
+    const char *val;
+
+    if (req->jar == NULL || name == NULL)
+        return NULL;
+
+    val = apr_table_get(req->jar, name);
+
+    if (val == NULL)
+        return NULL;
+
+    return apreq_value_to_cookie(val);
+}
+
+static apreq_param_t *custom_args_get(apreq_handle_t *handle, const char *name)
+{
+    struct custom_handle *req = (struct custom_handle*)handle;
+    const char *val;
+
+    if (req->args == NULL || name == NULL)
+        return NULL;
+
+    val = apr_table_get(req->args, name);
+
+    if (val == NULL)
+        return NULL;
+
+    return apreq_value_to_param(val);
+}
+
+static apreq_param_t *custom_body_get(apreq_handle_t *handle, const char *name)
+{
+    struct custom_handle *req = (struct custom_handle*)handle;
+    const char *val;
+
+    if (req->body == NULL || name == NULL)
+        return NULL;
+
+    while (1) {
+        *(const char **)&val = apr_table_get(req->body, name);
+        if (val != NULL)
+            break;
+
+        if (req->body_status == APR_INCOMPLETE)
+            custom_parse_brigade(handle, READ_BYTES);
+        else
+            return NULL;
+    }
+
+    return apreq_value_to_param(val);
+}
+
+
+
+static apr_status_t custom_parser_get(apreq_handle_t *handle,
+                                      const apreq_parser_t **parser)
+{
+    struct custom_handle *req = (struct custom_handle*)handle;
+    *parser = req->parser;
+
+    return APR_SUCCESS;
+}
+
+static apr_status_t custom_parser_set(apreq_handle_t *handle,
+                                      apreq_parser_t *parser)
+{
+    (void)handle;
+    (void)parser;
+    return APR_ENOTIMPL;
+}
+
+static apr_status_t custom_hook_add(apreq_handle_t *handle,
+                                    apreq_hook_t *hook)
+{
+    struct custom_handle *req = (struct custom_handle*)handle;
+    apreq_parser_add_hook(req->parser, hook);
+    return APR_SUCCESS;
+}
+
+static apr_status_t custom_brigade_limit_get(apreq_handle_t *handle,
+                                             apr_size_t *bytes)
+{
+    struct custom_handle *req = (struct custom_handle*)handle;
+    *bytes = req->parser->brigade_limit;
+    return APR_SUCCESS;
+}
+
+static apr_status_t custom_brigade_limit_set(apreq_handle_t *handle,
+                                             apr_size_t bytes)
+{
+    (void)handle;
+    (void)bytes;
+    return APR_ENOTIMPL;
+}
+
+static apr_status_t custom_read_limit_get(apreq_handle_t *handle,
+                                          apr_uint64_t *bytes)
+{
+    struct custom_handle *req = (struct custom_handle*)handle;
+    *bytes = req->read_limit;
+    return APR_SUCCESS;
+}
+
+static apr_status_t custom_read_limit_set(apreq_handle_t *handle,
+                                          apr_uint64_t bytes)
+{
+    (void)handle;
+    (void)bytes;
+    return APR_ENOTIMPL;
+}
+
+static apr_status_t custom_temp_dir_get(apreq_handle_t *handle,
+                                        const char **path)
+{
+    struct custom_handle *req = (struct custom_handle*)handle;
+
+    *path = req->parser->temp_dir;
+    return APR_SUCCESS;
+}
+
+static apr_status_t custom_temp_dir_set(apreq_handle_t *handle,
+                                        const char *path)
+{
+    (void)handle;
+    (void)path;
+    return APR_ENOTIMPL;
+}
+
+
+static APREQ_MODULE(custom, 20050516);
+
+APREQ_DECLARE(apreq_handle_t *)apreq_handle_custom(apr_pool_t *pool,
+                                                   const char *query_string,
+                                                   const char *cookie,
+                                                   apreq_parser_t *parser,
+                                                   apr_uint64_t read_limit,
+                                                   apr_bucket_brigade *in)
+{
+    struct custom_handle *req;
+    req = apr_palloc(pool, sizeof(*req));
+    req->handle.module = &custom_module;
+    req->handle.pool = pool;
+    req->handle.bucket_alloc = in->bucket_alloc;
+    req->read_limit = read_limit;
+    req->parser = parser;
+    req->in = apr_brigade_create(pool, in->bucket_alloc);
+    req->tmpbb = apr_brigade_create(pool, in->bucket_alloc);
+    req->body = apr_table_make(pool, APREQ_DEFAULT_NELTS);
+    req->body_status = APR_INCOMPLETE;
+    APR_BRIGADE_CONCAT(req->in, in);
+
+    if (cookie != NULL) {
+        req->jar = apr_table_make(pool, APREQ_DEFAULT_NELTS);
+        req->jar_status =
+            apreq_parse_cookie_header(pool, req->jar, cookie);
+    }
+    else {
+        req->jar = NULL;
+        req->jar_status = APREQ_ERROR_NODATA;
+    }
+
+
+    if (query_string != NULL) {
+        req->args = apr_table_make(pool, APREQ_DEFAULT_NELTS);
+        req->args_status =
+            apreq_parse_query_string(pool, req->args, query_string);
+    }
+    else {
+        req->args = NULL;
+        req->args_status = APREQ_ERROR_NODATA;
+    }
+
+    if (!APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(req->in))) {
+        apr_bucket *eos = apr_bucket_eos_create(in->bucket_alloc);
+        APR_BRIGADE_INSERT_TAIL(req->in, eos);
+    }
+
+    return &req->handle;
+}
+

Propchange: httpd/apreq/branches/apr-build-system/library/module_custom.c
------------------------------------------------------------------------------
    svn:eol-style = native

Added: httpd/apreq/branches/apr-build-system/library/param.c
URL: http://svn.apache.org/viewcvs/httpd/apreq/branches/apr-build-system/library/param.c?rev=380784&view=auto
==============================================================================
--- httpd/apreq/branches/apr-build-system/library/param.c (added)
+++ httpd/apreq/branches/apr-build-system/library/param.c Fri Feb 24 10:56:34 2006
@@ -0,0 +1,271 @@
+/*
+**  Copyright 2003-2006  The Apache Software Foundation
+**
+**  Licensed 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.
+*/
+
+#include "apreq_param.h"
+#include "apreq_error.h"
+#include "apreq_util.h"
+#include "apr_strings.h"
+#include "apr_lib.h"
+
+#define MAX_LEN         (1024 * 1024)
+#define MAX_BRIGADE_LEN (1024 * 256)
+#define MAX_READ_AHEAD  (1024 * 64)
+
+
+APREQ_DECLARE(apreq_param_t *) apreq_param_make(apr_pool_t *p,
+                                                const char *name,
+                                                const apr_size_t nlen,
+                                                const char *val,
+                                                const apr_size_t vlen)
+{
+    apreq_param_t *param;
+    apreq_value_t *v;
+
+    param = apr_palloc(p, nlen + vlen + 1 + sizeof *param);
+
+    if (param == NULL)
+        return NULL;
+
+    param->info = NULL;
+    param->upload = NULL;
+    param->flags = 0;
+
+    *(const apreq_value_t **)&v = &param->v;
+
+    if (vlen && val != NULL)
+        memcpy(v->data, val, vlen);
+    v->data[vlen] = 0;
+    v->dlen = vlen;
+
+    v->name = v->data + vlen + 1;
+    if (nlen && name != NULL)
+        memcpy(v->name, name, nlen);
+    v->name[nlen] = 0;
+    v->nlen = nlen;
+
+    return param;
+}
+
+APREQ_DECLARE(apr_status_t) apreq_param_decode(apreq_param_t **param,
+                                               apr_pool_t *pool,
+                                               const char *word,
+                                               apr_size_t nlen,
+                                               apr_size_t vlen)
+{
+    apr_status_t status;
+    apreq_value_t *v;
+    apreq_param_t *p;
+    apreq_charset_t charset;
+
+    if (nlen == 0) {
+        *param = NULL;
+        return APR_EBADARG;
+    }
+
+    p = apr_palloc(pool, nlen + vlen + 1 + sizeof *p);
+    p->info = NULL;
+    p->upload = NULL;
+    p->flags = 0;
+    *(const apreq_value_t **)&v = &p->v;
+
+    if (vlen > 0) {
+        status = apreq_decode(v->data, &v->dlen, word + nlen + 1, vlen);
+        if (status != APR_SUCCESS) {
+            *param = NULL;
+            return status;
+        }
+        charset = apreq_charset_divine(v->data, v->dlen);
+    }
+    else {
+        v->data[0] = 0;
+        v->dlen = 0;
+        charset = APREQ_CHARSET_ASCII;
+    }
+    v->name = v->data + vlen + 1;
+
+    status = apreq_decode(v->name, &v->nlen, word, nlen);
+    if (status != APR_SUCCESS) {
+        *param = NULL;
+        return status;
+    }
+
+    switch (apreq_charset_divine(v->name, v->nlen)) {
+    case APREQ_CHARSET_UTF8:
+        if (charset == APREQ_CHARSET_ASCII)
+            charset = APREQ_CHARSET_UTF8;
+    case APREQ_CHARSET_ASCII:
+        break;
+
+    case APREQ_CHARSET_LATIN1:
+        if (charset != APREQ_CHARSET_CP1252)
+            charset = APREQ_CHARSET_LATIN1;
+        break;
+    case APREQ_CHARSET_CP1252:
+        charset = APREQ_CHARSET_CP1252;
+    }
+
+    apreq_param_charset_set(p, charset);
+    *param = p;
+
+    return APR_SUCCESS;
+}
+
+
+APREQ_DECLARE(char *) apreq_param_encode(apr_pool_t *pool,
+                                         const apreq_param_t *param)
+{
+    apr_size_t dlen;
+    char *data;
+    data = apr_palloc(pool, 3 * (param->v.nlen + param->v.dlen) + 2);
+    dlen = apreq_encode(data, param->v.name, param->v.nlen);
+    data[dlen++] = '=';
+    dlen += apreq_encode(data + dlen, param->v.data, param->v.dlen);
+
+    return data;
+}
+
+APREQ_DECLARE(apr_status_t) apreq_parse_query_string(apr_pool_t *pool,
+                                                     apr_table_t *t,
+                                                     const char *qs)
+{
+    const char *start = qs;
+    apr_size_t nlen = 0;
+
+    for (;;++qs) {
+        switch (*qs) {
+
+        case '=':
+            if (nlen == 0) {
+                nlen = qs - start;
+            }
+            break;
+
+        case '&':
+        case ';':
+        case 0:
+            if (qs > start) {
+                apr_size_t vlen = 0;
+                apreq_param_t *param;
+                apr_status_t s;
+                if (nlen == 0)
+                    nlen = qs - start;
+                else
+                    vlen = qs - start - nlen - 1;
+
+                s = apreq_param_decode(&param, pool, start, nlen, vlen);
+                if (s != APR_SUCCESS)
+                    return s;
+
+                apreq_param_tainted_on(param);
+                apreq_value_table_add(&param->v, t);
+            }
+
+            if (*qs == 0)
+                return APR_SUCCESS;
+
+            nlen = 0;
+            start = qs + 1;
+        }
+    }
+    /* not reached */
+    return APR_INCOMPLETE;
+}
+
+
+
+
+static int param_push(void *data, const char *key, const char *val)
+{
+    apr_array_header_t *arr = data;
+    *(apreq_param_t **)apr_array_push(arr) =
+        apreq_value_to_param(val);
+    return 1;   /* keep going */
+}
+
+
+APREQ_DECLARE(apr_array_header_t *) apreq_params_as_array(apr_pool_t *p,
+                                                          const apr_table_t *t,
+                                                          const char *key)
+{
+    apr_array_header_t *arr;
+
+    arr = apr_array_make(p, apr_table_elts(t)->nelts,
+                         sizeof(apreq_param_t *));
+
+    apr_table_do(param_push, arr, t, key, NULL);
+    return arr;
+}
+
+APREQ_DECLARE(const char *) apreq_params_as_string(apr_pool_t *p,
+                                                   const apr_table_t *t,
+                                                   const char *key,
+                                                   apreq_join_t mode)
+{
+    apr_array_header_t *arr = apreq_params_as_array(p, t, key);
+    apreq_param_t **elt = (apreq_param_t **)arr->elts;
+    apreq_param_t **const end = elt + arr->nelts;
+    if (arr->nelts == 0)
+        return apr_pstrdup(p, "");
+
+    while (elt < end) {
+        *(const apreq_value_t **)elt = &(**elt).v;
+        ++elt;
+    }
+    return apreq_join(p, ", ", arr, mode);
+}
+
+
+
+static int upload_push(void *data, const char *key, const char *val)
+{
+    apr_table_t *t = data;
+    apreq_param_t *p = apreq_value_to_param(val);
+
+    if (p->upload != NULL)
+        apreq_value_table_add(&p->v, t);
+    return 1;   /* keep going */
+}
+
+
+APREQ_DECLARE(const apr_table_t *) apreq_uploads(const apr_table_t *body,
+                                                 apr_pool_t *pool)
+{
+    apr_table_t *t = apr_table_make(pool, APREQ_DEFAULT_NELTS);
+    apr_table_do(upload_push, t, body, NULL);
+    return t;
+}
+
+static int upload_set(void *data, const char *key, const char *val)
+{
+    const apreq_param_t **q = data;
+    apreq_param_t *p = apreq_value_to_param(val);
+
+    if (p->upload != NULL) {
+        *q = p;
+        return 0; /* upload found, stop */
+    }
+    else
+        return 1; /* keep searching */
+}
+
+
+APREQ_DECLARE(const apreq_param_t *) apreq_upload(const apr_table_t *body,
+                                                  const char *name)
+{
+    apreq_param_t *param = NULL;
+    apr_table_do(upload_set, &param, body, name, NULL);
+    return param;
+}

Propchange: httpd/apreq/branches/apr-build-system/library/param.c
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message