joes 2004/06/04 15:02:11
Modified: . CHANGES STATUS
src README apreq.c apreq.h apreq_cookie.h apreq_env.h
apreq_params.c apreq_params.h apreq_parsers.c
apreq_version.h
Log:
apreq_run_(hook|parser) are macros, so they are capitalized now.
Fixed apreq_params_as_string() and added apreq_params_as_array().
Reworked definitions of APREQ_DECLARE_HOOK, APREQ_DECLARE_PARSER
and apreq_(parser|hook)_t, hopefully to be more Win32 friendly.
Also updated the documentation.
Revision Changes Path
1.32 +7 -0 httpd-apreq-2/CHANGES
Index: CHANGES
===================================================================
RCS file: /home/cvs/httpd-apreq-2/CHANGES,v
retrieving revision 1.31
retrieving revision 1.32
diff -u -r1.31 -r1.32
--- CHANGES 18 Apr 2004 01:40:47 -0000 1.31
+++ CHANGES 4 Jun 2004 22:02:11 -0000 1.32
@@ -4,6 +4,13 @@
@section v2_03_dev Changes with libapreq2-2.03-dev
- C API [joes]
+ apreq_run_(hook|parser) are macros, so they are capitalized now.
+ Fixed apreq_params_as_string() and added apreq_params_as_array().
+ Reworked definitions of APREQ_DECLARE_HOOK, APREQ_DECLARE_PARSER
+ and apreq_(parser|hook)_t, hopefully to be more Win32 friendly.
+ Also updated the documentation.
+
+- C API [joes]
Compensate for a missing CRLF in empty file upload block, which
actually complies with RFC 2046 Section 5.1.1. Konqueror (version unknown)
and Mozilla 0.9.7 are known to emit such blocks.
1.46 +4 -1 httpd-apreq-2/STATUS
Index: STATUS
===================================================================
RCS file: /home/cvs/httpd-apreq-2/STATUS,v
retrieving revision 1.45
retrieving revision 1.46
diff -u -r1.45 -r1.46
--- STATUS 22 May 2004 15:25:43 -0000 1.45
+++ STATUS 4 Jun 2004 22:02:11 -0000 1.46
@@ -92,6 +92,9 @@
but there are too many problems with the current (May 2004)
ports of the auto* tools for us to accomodate FreeBSD (yet).
+ - The current API does not handle failed query_string parsing
+ adequately (apreq_request does log an error message, but
+ there's no status code in the struct for users to interrogate).
WISH LIST:
1.5 +7 -15 httpd-apreq-2/src/README
Index: README
===================================================================
RCS file: /home/cvs/httpd-apreq-2/src/README,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- README 17 Jul 2003 21:56:38 -0000 1.4
+++ README 4 Jun 2004 22:02:11 -0000 1.5
@@ -3,20 +3,13 @@
Data structures and relations:
- BASE:
+ BASIC VALUE TYPE:
apreq_value_t: basic type for handling opaque data. The type
is meant to be extended by placing all "metadata"
in front (within a larger structure).
- apreq_table_t : apreq_value_t container. treats value_t as
- "key -> data" pair and provides lookup api.
- Custom copy/merge functions can be added to
- internally handle additional metadata attached
- to the contained apreq_value_t's.
-
-
- COOKIE EXTENSIONS:
+ COOKIES:
apreq_cookie_t: extends apreq_value_t to represent server-side
cookie data.
@@ -24,11 +17,11 @@
apreq_jar_t: A pool and a table with cookie-based copy/merge functions.
This struct is analogous to apreq_request_t for params.
-
- PARAM EXTENSIONS:
+ PARAMS:
apreq_param_t: extends apreq_value_t to represent POST param data.
+
apreq_request_t: maintains arg/body tables which represent parsed data.
REQUEST STATES:
@@ -46,9 +39,8 @@
PARSER EXTENSIONS:
- apreq_parser_t: extends apreq_value_t to represent a parser callback,
- with its associated configuration data.
+ apreq_parser_t: parser callback, with its associated configuration data.
- apreq_hook_t: extends multipart/form-data by transforming the input
- brigade and pushing buckets onto the current param->bb.
+ apreq_hook_t: extends multipart/form-data parser by transforming incoming
+ brigades which represent the contents of a file upload.
1.33 +22 -9 httpd-apreq-2/src/apreq.c
Index: apreq.c
===================================================================
RCS file: /home/cvs/httpd-apreq-2/src/apreq.c,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -r1.32 -r1.33
--- apreq.c 24 Mar 2004 08:22:48 -0000 1.32
+++ apreq.c 4 Jun 2004 22:02:11 -0000 1.33
@@ -404,30 +404,38 @@
return d - dest;
}
+APREQ_DECLARE(apr_size_t) apreq_quote_once(char *dest, const char *src,
+ const apr_size_t slen)
+{
+ if (slen > 1 && src[0] == '"' && src[slen-1] == '"') {
+ /* looks like src is already quoted */
+ memcpy(dest, src, slen);
+ return slen;
+ }
+ else
+ return apreq_quote(dest, src, slen);
+}
+
APREQ_DECLARE(apr_size_t) apreq_quote(char *dest, const char *src,
const apr_size_t slen)
{
char *d = dest;
const char *s = src;
+ const char *const last = src + slen - 1;
if (slen == 0) {
*d = 0;
return 0;
}
- if (src[0] == '"' && src[slen-1] == '"') { /* src is already quoted */
- memcpy(dest, src, slen);
- return slen;
- }
-
*d++ = '"';
- while (s < src + slen) {
+ while (s <= last) {
switch (*s) {
case '\\':
- if (s < src + slen - 1) {
+ if (s < last) {
*d++ = *s++;
break;
}
@@ -533,12 +541,13 @@
case QUOTE:
- d += apreq_quote(d, a[0]->data, a[0]->size);
+
+ d += apreq_quote_once(d, a[0]->data, a[0]->size);
for (j = 1; j < n; ++j) {
memcpy(d, sep, slen);
d += slen;
- d += apreq_quote(d, a[j]->data, a[j]->size);
+ d += apreq_quote_once(d, a[j]->data, a[j]->size);
}
break;
@@ -578,6 +587,10 @@
return rv->data;
}
+APREQ_DECLARE(apr_ssize_t) apreq_unescape(char *str)
+{
+ return apreq_decode(str,str,strlen(str));
+}
APR_INLINE
static apr_status_t apreq_fwritev(apr_file_t *f, struct iovec *v,
1.39 +63 -14 httpd-apreq-2/src/apreq.h
Index: apreq.h
===================================================================
RCS file: /home/cvs/httpd-apreq-2/src/apreq.h,v
retrieving revision 1.38
retrieving revision 1.39
diff -u -r1.38 -r1.39
--- apreq.h 24 Mar 2004 08:22:48 -0000 1.38
+++ apreq.h 4 Jun 2004 22:02:11 -0000 1.39
@@ -114,7 +114,7 @@
*/
typedef struct apreq_value_t {
const char *name; /**< value's name */
- apr_status_t status; /**< APR status, usually SUCCESS or INCOMPLETE*/
+ apr_status_t status; /**< APR status, usually APR_SUCCESS or
APR_INCOMPLETE*/
apr_size_t size; /**< Size of data.*/
char data[1]; /**< Actual data bytes.*/
} apreq_value_t;
@@ -126,9 +126,25 @@
#define apreq_attr_to_type(T,A,P) ( (T*) ((char*)(P)-offsetof(T,A)) )
-#define apreq_char_to_value(ptr) apreq_attr_to_type(apreq_value_t, data,
ptr)
+/**
+ * Converts (char *) to (apreq_value_t *). The char * is assumed
+ * to point at the data attribute of an apreq_value_t struct.
+ *
+ * @param ptr points at the data field of an apreq_value_t struct.
+ */
+
+#define apreq_char_to_value(ptr) apreq_attr_to_type(apreq_value_t, data,
ptr)
#define apreq_strtoval(ptr) apreq_char_to_value(ptr)
+
+/**
+ * Computes the length of the string, but unlike strlen(),
+ * it permits embedded null characters.
+ *
+ * @param ptr points at the data field of an apreq_value_t struct.
+ *
+ */
+
#define apreq_strlen(ptr) (apreq_strtoval(ptr)->size)
/**
@@ -220,40 +236,56 @@
* @param ndl Search string
* @param nlen Length of search string.
* @param type Match type.
+ * @return Offset of match string, or -1 if mo 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.
- * @param dest Location of quoted copy. Must be large enough to hold the
copy.
+ * 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);
-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
dest is
- * large enough.
+ * @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.
*/
-
-APREQ_DECLARE(apr_size_t) apreq_encode(char *dest, const char *src, const
apr_size_t slen);
+APREQ_DECLARE(apr_size_t) apreq_encode(char *dest, const char *src,
+ const apr_size_t slen);
/**
* Url-decodes a string.
- * @param dest Location of url-decoded result string. Caller must ensure
dest is
- * large enough.
+ * @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 src Original string.
* @param slen Length of original string.
- * @return Length of url-decoded string in dest, or < 0 on
- * decoding (bad data) error.
+ * @return Length of url-decoded string in dest, or < 0 on decoding (bad
data) error.
*/
APREQ_DECLARE(apr_ssize_t) apreq_decode(char *dest, const char *src, const
apr_size_t slen);
@@ -274,10 +306,11 @@
* An \e in-situ url-decoder.
* @param str The string to decode
* @return Length of decoded string, or < 0 on error.
+ * @remark Equivalent to apreq_decode(str,str,strlen(str)).
*/
APREQ_DECLARE(apr_ssize_t) apreq_unescape(char *str);
-#define apreq_unescape(str) apreq_decode(str,str,strlen(str))
+
/** @enum apreq_expires_t Expiration date format */
typedef enum {
@@ -340,6 +373,7 @@
* @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 on success; error code otherwise.
*/
APREQ_DECLARE(apr_status_t) apreq_file_mktemp(apr_file_t **fp,
@@ -356,9 +390,24 @@
APREQ_DECLARE(apr_file_t *) apreq_brigade_spoolfile(apr_bucket_brigade *bb);
+/**
+ * Duplicate a brigade.
+ * @param bb Original brigade.
+ * @return New brigade containing a bucket-by-bucket copy of the original.
+ */
+
APREQ_DECLARE(apr_bucket_brigade *)
apreq_brigade_copy(const apr_bucket_brigade *bb);
+/**
+ * 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 if found, otherwise APR_NOTFOUND.
+ */
APREQ_DECLARE(apr_status_t)
apreq_header_attribute(const char *hdr,
const char *name, const apr_size_t nlen,
1.21 +4 -0 httpd-apreq-2/src/apreq_cookie.h
Index: apreq_cookie.h
===================================================================
RCS file: /home/cvs/httpd-apreq-2/src/apreq_cookie.h,v
retrieving revision 1.20
retrieving revision 1.21
diff -u -r1.20 -r1.21
--- apreq_cookie.h 28 Feb 2004 07:48:14 -0000 1.20
+++ apreq_cookie.h 4 Jun 2004 22:02:11 -0000 1.21
@@ -197,6 +197,10 @@
APREQ_DECLARE(apr_status_t) apreq_cookie_bake2(const apreq_cookie_t *c,
void *env);
+/**
+ *
+ *
+ */
APREQ_DECLARE(apreq_cookie_version_t) apreq_ua_cookie_version(void *env);
/** @} */
1.23 +152 -0 httpd-apreq-2/src/apreq_env.h
Index: apreq_env.h
===================================================================
RCS file: /home/cvs/httpd-apreq-2/src/apreq_env.h,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -r1.22 -r1.23
--- apreq_env.h 24 Mar 2004 08:22:48 -0000 1.22
+++ apreq_env.h 4 Jun 2004 22:02:11 -0000 1.23
@@ -74,37 +74,166 @@
* @{
*/
+/**
+ * Analog of Apache's ap_log_rerror().
+ * @param file Filename to list in the log message.
+ * @param line Line number from the file.
+ * @param level Log level.
+ * @param status Status code.
+ * @param env Current environment.
+ * @param fmt Format string for the log message.
+ */
+
APREQ_DECLARE_NONSTD(void) apreq_log(const char *file, int line,
int level, apr_status_t status,
void *env, const char *fmt, ...);
+/**
+ * Pool associated with the environment.
+ * @param env The current environment
+ * @return The associated pool.
+ */
APREQ_DECLARE(apr_pool_t *) apreq_env_pool(void *env);
+
+/**
+ * Get/set the jar currently associated to the environment.
+ * @param env The current environment.
+ * @param jar New Jar to associate.
+ * @return The previous jar associated to the environment.
+ * jar == NULL gets the current jar, which will remain associated
+ * after the call.
+ */
APREQ_DECLARE(apreq_jar_t *) apreq_env_jar(void *env, apreq_jar_t *jar);
+
+/**
+ * Get/set the request currently associated to the environment.
+ * @param env The current environment.
+ * @param req New request to associate.
+ * @return The previous request associated to the environment.
+ * req == NULL gets the current request, which will remain associated
+ * after the call.
+ */
APREQ_DECLARE(apreq_request_t *) apreq_env_request(void *env,
apreq_request_t *req);
+/**
+ * Fetch the query string.
+ * @param env The current environment.
+ * @return The query string.
+ */
APREQ_DECLARE(const char *) apreq_env_query_string(void *env);
+
+/**
+ * Fetch the header value (joined by ", " if there are multiple headers)
+ * for a given header name.
+ * @param env The current environment.
+ * @param name The header name.
+ * @return The value of the header, NULL if not found.
+ */
APREQ_DECLARE(const char *) apreq_env_header_in(void *env, const char *name);
+
+/**
+ * Fetch the environment's "Content-Type" header.
+ * @param env The current environment.
+ * @return The value of the Content-Type header, NULL if not found.
+ */
#define apreq_env_content_type(env) apreq_env_header_in(env, "Content-Type")
+
+
+/**
+ * Fetch the environment's "Cookie" header.
+ * @param env The current environment.
+ * @return The value of the "Cookie" header, NULL if not found.
+ */
#define apreq_env_cookie(env) apreq_env_header_in(env, "Cookie")
+
+/**
+ * Fetch the environment's "Cookie2" header.
+ * @param env The current environment.
+ * @return The value of the "Cookie2" header, NULL if not found.
+ */
#define apreq_env_cookie2(env) apreq_env_header_in(env, "Cookie2")
+/**
+ * Add a header field to the environment's outgoing response headers
+ * @param env The current environment.
+ * @param name The name of the outgoing header.
+ * @param val Value of the outgoing header.
+ * @return APR_SUCCESS on success, error code otherwise.
+ */
APREQ_DECLARE(apr_status_t)apreq_env_header_out(void *env,
const char *name,
char *val);
+/**
+ * Add a "Set-Cookie" header to the outgoing response headers.
+ * @param e The current environment.
+ * @param s The cookie string.
+ * @return APR_SUCCESS on success, error code otherwise.
+ */
#define apreq_env_set_cookie(e,s) apreq_env_header_out(e,"Set-Cookie",s)
+
+/**
+ * Add a "Set-Cookie2" header to the outgoing response headers.
+ * @param e The current environment.
+ * @param s The cookie string.
+ * @return APR_SUCCESS on success, error code otherwise.
+ */
#define apreq_env_set_cookie2(e,s) apreq_env_header_out(e,"Set-Cookie2",s)
+/**
+ * Read data from the environment and into the current active parser.
+ * @param env The current environment.
+ * @param block Read type (APR_READ_BLOCK or APR_READ_NONBLOCK).
+ * @param bytes Maximum number of bytes to read.
+ * @return APR_INCOMPLETE if there's more data to read,
+ * APR_SUCCESS if everything was read & parsed successfully,
+ * error code otherwise.
+ */
APREQ_DECLARE(apr_status_t) apreq_env_read(void *env,
apr_read_type_e block,
apr_off_t bytes);
+/**
+ * Get/set the current temporary directory.
+ * @param env The current environment.
+ * @param path The full pathname of the new directory.
+ * @return The path of the previous temporary directory. Note: a call using
+ * path==NULL fetches the current directory without resetting it to NULL.
+ */
+
APREQ_DECLARE(const char *) apreq_env_temp_dir(void *env, const char *path);
+
+/**
+ * Get/set the current max_body setting. This is the maximum
+ * amount of bytes that will be read into the environment's parser.
+ * @param env The current environment.
+ * @param bytes The new max_body setting.
+ * @return The previous max_body setting. Note: a call using
+ * bytes == -1 fetches the current max_body setting without modifying it.
+ *
+ */
+
APREQ_DECLARE(apr_off_t) apreq_env_max_body(void *env, apr_off_t bytes);
+
+/**
+ * Get/set the current max_brigade setting. This is the maximum
+ * amount of heap-allocated buckets libapreq2 will use for its brigades.
+ * If additional buckets are necessary, they will be created from a
temporary file.
+ * @param env The current environment.
+ * @param bytes The new max_brigade setting.
+ * @return The previous max_brigade setting. Note: a call using
+ * bytes == -1 fetches the current max_brigade setting without modifying it.
+ *
+ */
APREQ_DECLARE(apr_ssize_t) apreq_env_max_brigade(void *env, apr_ssize_t
bytes);
+/**
+ * The environment structure, which must be fully defined
+ * for libapreq2 to operate properly in a given environment.
+ */
+
typedef struct apreq_env_t {
const char *name;
apr_uint32_t magic_number;
@@ -121,15 +250,38 @@
apr_ssize_t (*max_brigade)(void *, apr_ssize_t);
} apreq_env_t;
+/**
+ * Convenience macro for defining an environment module by mapping
+ * a function prefix to an associated environment structure.
+ * @param pre Prefix to define new environment. All attributes of
+ * the apreq_env_t struct are defined with this as their prefix. The
+ * generated struct is named by appending "_module" to the prefix.
+ * @param name Name of this environment.
+ * @param mmn Magic number (i.e. version number) of this environment.
+ */
#define APREQ_ENV_MODULE(pre, name, mmn) const apreq_env_t pre##_module = { \
name, mmn, pre##_log, pre##_pool, pre##_jar, pre##_request, \
pre##_query_string, pre##_header_in, pre##_header_out, pre##_read, \
pre##_temp_dir, pre##_max_body, pre##_max_brigade }
+/**
+ * Get/set function for the active environment stucture. Usually this
+ * is called only once per process, to define the correct environment.
+ * @param mod The new active environment.
+ * @return The previous active environment. Note: a call using
+ * mod == NULL fetches the current environment module without modifying it.
+ */
APREQ_DECLARE(const apreq_env_t *) apreq_env_module(const apreq_env_t *mod);
+/**
+ * The current environment's name.
+ */
#define apreq_env_name (apreq_env_module(NULL)->name)
+
+/**
+ * The current environment's magic (ie. version) number.
+ */
#define apreq_env_magic_number (apreq_env_module(NULL)->magic_number)
/** @} */
1.40 +52 -1 httpd-apreq-2/src/apreq_params.c
Index: apreq_params.c
===================================================================
RCS file: /home/cvs/httpd-apreq-2/src/apreq_params.c,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -r1.39 -r1.40
--- apreq_params.c 13 Apr 2004 21:46:38 -0000 1.39
+++ apreq_params.c 4 Jun 2004 22:02:11 -0000 1.40
@@ -129,6 +129,57 @@
}
+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(apreq_strtoval(val));
+ return 0;
+}
+
+
+APREQ_DECLARE(apr_array_header_t *) apreq_params_as_array(apr_pool_t *p,
+ apreq_request_t
*req,
+ const char *key)
+{
+ apr_status_t s;
+ apr_array_header_t *arr = apr_array_make(p,
apr_table_elts(req->args)->nelts,
+ sizeof(apreq_param_t *));
+
+ apr_table_do(param_push, arr, req->args, key);
+
+ do s = apreq_env_read(req->env, APR_BLOCK_READ, APREQ_READ_AHEAD);
+ while (s == APR_INCOMPLETE);
+
+ if (req->body)
+ apr_table_do(param_push, arr, req->body, key);
+
+ return arr;
+}
+
+APREQ_DECLARE(const char *) apreq_params_as_string(apr_pool_t *p,
+ apreq_request_t *req,
+ const char *key,
+ apreq_join_t mode)
+{
+ /* Must adjust apreq_param_t pointers to apreq_value_t. */
+#ifdef DEBUG
+ assert(sizeof(apreq_param_t **) == sizeof(apreq_value_t **));
+#endif
+ apr_array_header_t *arr = apreq_params_as_array(p, req, key);
+ apreq_param_t **elt = (apreq_param_t **)arr->elts;
+ apreq_param_t **const end = elt + arr->nelts;
+ if (arr->nelts == 0)
+ return NULL;
+
+ while (elt < end) {
+ *(apreq_value_t **)elt = &(**elt).v;
+ ++elt;
+ }
+ return apreq_join(p, ", ", arr, mode);
+}
+
+
APREQ_DECLARE(apreq_param_t *) apreq_decode_param(apr_pool_t *pool,
const char *word,
const apr_size_t nlen,
@@ -242,7 +293,7 @@
if (req->body == NULL)
req->body = apr_table_make(apreq_env_pool(req->env),APREQ_NELTS);
- return apreq_run_parser(req->parser, req->env, req->body, bb);
+ return APREQ_RUN_PARSER(req->parser, req->env, req->body, bb);
}
1.28 +164 -50 httpd-apreq-2/src/apreq_params.h
Index: apreq_params.h
===================================================================
RCS file: /home/cvs/httpd-apreq-2/src/apreq_params.h,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -r1.27 -r1.28
--- apreq_params.h 24 Mar 2004 08:22:48 -0000 1.27
+++ apreq_params.h 4 Jun 2004 22:02:11 -0000 1.28
@@ -42,6 +42,7 @@
apreq_value_t v; /**< underlying name/value/status info */
} apreq_param_t;
+/* These structs are defined below */
typedef struct apreq_hook_t apreq_hook_t;
typedef struct apreq_parser_t apreq_parser_t;
@@ -96,33 +97,49 @@
* if NULL.
* @remark Also parses the request as necessary.
*/
-
APREQ_DECLARE(apreq_param_t *) apreq_param(const apreq_request_t *req,
const char *name);
+
/**
- * Returns all parameters for the requested key,
- * NULL if none found. The key is case-insensitive.
+ * Returns a table containing key-value pairs for the full request
+ * (args + body).
+ * @param p Allocates the returned table.
* @param req The current apreq_request_t object.
- * @param key Nul-terminated search key. Returns the first table value
- * if NULL.
- * @remark Also parses the request as necessary.
+ * @remark Also parses the request if necessary.
*/
-
APREQ_DECLARE(apr_table_t *) apreq_params(apr_pool_t *p,
const apreq_request_t *req);
+
+/**
+ * Returns an array of parameters (apreq_param_t *) matching the given key.
+ * The key is case-insensitive.
+ * @param p Allocates the returned array.
+ * @param req The current apreq_request_t object.
+ * @param key Null-terminated search key. key==NULL fetches all parameters.
+ * @remark Also parses the request if necessary.
+ */
+APREQ_DECLARE(apr_array_header_t *) apreq_params_as_array(apr_pool_t *p,
+ apreq_request_t
*req,
+ const char *key);
+
/**
* Returns a ", " -separated string containing all parameters
- * for the requested key, NULL if none found. The key is case-insensitive.
+ * for the requested key, NULL if none are found. The key is
case-insensitive.
+ * @param p Allocates the return string.
* @param req The current apreq_request_t object.
- * @param key Nul-terminated search key. Returns the first table value
- * if NULL.
- * @remark Also parses the request as necessary.
+ * @param key Null-terminated parameter name. key==NULL fetches all values.
+ * @param mode Join type- see apreq_join().
+ * @return Returned string is the data attribute of an apreq_value_t,
+ * so it is safe to use in apreq_strlen() and apreq_strtoval().
+ * @remark Also parses the request if necessary.
*/
-#define apreq_params_as_string(req,key,pool, mode) \
- apreq_join(pool, ", ", apreq_params(req,pool,key), mode)
+APREQ_DECLARE(const char *) apreq_params_as_string(apr_pool_t *p,
+ apreq_request_t *req,
+ const char *key,
+ apreq_join_t mode);
/**
@@ -142,6 +159,9 @@
const apr_size_t vlen);
/**
* Url-encodes the param into a name-value pair.
+ * @param pool Pool which allocates the returned string.
+ * @param param Param to encode.
+ * @return name-value pair representing the param.
*/
APREQ_DECLARE(char *) apreq_encode_param(apr_pool_t *pool,
@@ -152,6 +172,7 @@
* @param pool pool used to allocate the param data.
* @param table table to which the params are added.
* @param qs Query string to url-decode.
+ * @return APR_SUCCESS if successful, error otherwise.
* @remark This function uses [&;] as the set of tokens
* to delineate words, and will treat a word w/o '='
* as a name-value pair with value-length = 0.
@@ -169,12 +190,6 @@
* @return APR_INCOMPLETE if the parse is incomplete,
* APR_SUCCESS if the parser is finished (saw eos),
* unrecoverable error value otherwise.
- *
- * @remark Polymorphic buckets (file, pipe, socket, etc.)
- * will generate new buckets during parsing, which
- * may cause problems with the configuration checks.
- * To be on the safe side, the caller should avoid
- * placing such buckets in the passed brigade.
*/
APREQ_DECLARE(apr_status_t)apreq_parse_request(apreq_request_t *req,
@@ -183,6 +198,8 @@
* Returns a table of all params in req->body with non-NULL bucket brigades.
* @param pool Pool which allocates the table struct.
* @param req Current request.
+ * @return Upload table.
+ * @remark Will parse the request if necessary.
*/
APREQ_DECLARE(apr_table_t *) apreq_uploads(apr_pool_t *pool,
@@ -191,63 +208,160 @@
/**
* Returns the first param in req->body which has both param->v.name
* matching key and param->bb != NULL.
+ * @param req The current request.
+ * @param key Parameter name. key == NULL returns first upload.
+ * @return Corresponding upload, NULL if none found.
+ * @remark Will parse the request as necessary.
*/
APREQ_DECLARE(apreq_param_t *) apreq_upload(const apreq_request_t *req,
const char *key);
+/** Parser arguments. */
+#define APREQ_PARSER_ARGS (apreq_parser_t *parser, \
+ void *env, \
+ apr_table_t *t, \
+ apr_bucket_brigade *bb)
+
+/** Hook arguments */
+#define APREQ_HOOK_ARGS (apreq_hook_t *hook, \
+ void *env, \
+ const apreq_param_t *param, \
+ apr_bucket_brigade *bb)
-#define APREQ_DECLARE_PARSER(f) apr_status_t (f)(apreq_parser_t *parser, \
- void *env, \
- apr_table_t *t, \
- apr_bucket_brigade *bb)
-
-#define APREQ_DECLARE_HOOK(f) apr_status_t (f)(apreq_hook_t *hook, \
- void *env, \
- const apreq_param_t *param, \
- apr_bucket_brigade *bb)
+/**
+ * Declares a API parser.
+ */
+#define APREQ_DECLARE_PARSER(f) APREQ_DECLARE(apr_status_t) \
+ (f) APREQ_PARSER_ARGS
+
+/**
+ * Declares an API hook.
+ */
+#define APREQ_DECLARE_HOOK(f) APREQ_DECLARE(apr_status_t) \
+ (f) APREQ_HOOK_ARGS
+/**
+ * Singly linked list of hooks.
+ *
+ */
struct apreq_hook_t {
- APREQ_DECLARE_HOOK (*hook);
- apreq_hook_t *next;
- void *ctx;
+ apr_status_t (*hook) APREQ_HOOK_ARGS;
+ apreq_hook_t *next;
+ void *ctx;
};
+/**
+ * Request parser with associated enctype and hooks.
+ *
+ */
struct apreq_parser_t {
- APREQ_DECLARE_PARSER (*parser);
- const char *enctype;
- apreq_hook_t *hook;
- void *ctx;
+ apr_status_t (*parser) APREQ_PARSER_ARGS;
+ const char *enctype;
+ apreq_hook_t *hook;
+ void *ctx;
};
-#define apreq_run_parser(psr,env,t,bb) (psr)->parser(psr,env,t,bb)
-#define apreq_run_hook(h,env,param,bb) (h)->hook(h,env,param,bb)
+/**
+ * Parse the incoming brigade into a table.
+ */
+#define APREQ_RUN_PARSER(psr,env,t,bb) (psr)->parser(psr,env,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.
+ */
+#define APREQ_RUN_HOOK(h,env,param,bb) (h)->hook(h,env,param,bb)
+/**
+ * Concatenates the brigades, spooling large brigades into
+ * a tempfile bucket according to the environment's max_brigade
+ * setting- see apreq_env_max_brigade().
+ * @param env Environment.
+ * @param out Resulting brigade.
+ * @param in Brigade to append.
+ * @return APR_SUCCESS on success, error code otherwise.
+ */
APREQ_DECLARE(apr_status_t) apreq_brigade_concat(void *env,
apr_bucket_brigade *out,
apr_bucket_brigade *in);
+/**
+ * Rfc822 Header parser.
+ */
APREQ_DECLARE_PARSER(apreq_parse_headers);
+
+/**
+ * Rfc2396 application/x-www-form-urlencoded parser.
+ */
APREQ_DECLARE_PARSER(apreq_parse_urlencoded);
+
+/**
+ * Rfc2388 multipart/form-data parser.
+ */
APREQ_DECLARE_PARSER(apreq_parse_multipart);
-APREQ_DECLARE(apreq_parser_t *) apreq_make_parser(apr_pool_t *pool,
- const char *enctype,
-
APREQ_DECLARE_PARSER(*parser),
- apreq_hook_t *hook,
- void *ctx);
-
-APREQ_DECLARE(apreq_hook_t *) apreq_make_hook(apr_pool_t *pool,
- APREQ_DECLARE_HOOK(*hook),
- apreq_hook_t *next,
- void *ctx);
+/**
+ * Construct a parser.
+ *
+ * @param pool Pool used to allocate the parser.
+ * @param enctype Content-type that this parser can deal with.
+ * @param parser The parser function.
+ * @param hook Hooks to asssociate this parser with.
+ * @param ctx Parser's internal scratch pad.
+ * @return New parser.
+ */
+APREQ_DECLARE(apreq_parser_t *)
+ apreq_make_parser(apr_pool_t *pool,
+ const char *enctype,
+ apr_status_t (*parser) APREQ_PARSER_ARGS,
+ apreq_hook_t *hook,
+ void *ctx);
-APREQ_DECLARE(apr_status_t)apreq_add_hook(apreq_parser_t *p,
- apreq_hook_t *h);
+/**
+ * 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_make_hook(apr_pool_t *pool,
+ apr_status_t (*hook) APREQ_HOOK_ARGS,
+ apreq_hook_t *next,
+ void *ctx);
-APREQ_DECLARE(apreq_parser_t *)apreq_parser(void *env, apreq_hook_t *hook);
+/**
+ * Add a new hook to the end of the parser's hook list.
+ *
+ * @param p Parser.
+ * @param h Hook to append.
+ */
+APREQ_DECLARE(void) apreq_add_hook(apreq_parser_t *p,
+ apreq_hook_t *h);
+
+/**
+ * Create the default parser associated with the
+ * current request's Content-Type (if possible).
+ * @param env The current environment.
+ * @param hook Hook(s) to add to the parser.
+ * @return New parser, NULL if the Content-Type is
+ * unrecognized. apreq_parser() currently recognizes
+ * APREQ_URL_ENCTYPE and APREQ_MFD_ENCTYPE.
+ *
+ * @param env The current environment.
+ * @param hook Additional hooks to supply the parser with.
+ * @return The built-in parser; NULL if the environment's
+ * Content-Type is unrecognized.
+ */
+APREQ_DECLARE(apreq_parser_t *)apreq_parser(void *env,
+ apreq_hook_t *hook);
/** @} */
#ifdef __cplusplus
1.45 +16 -18 httpd-apreq-2/src/apreq_parsers.c
Index: apreq_parsers.c
===================================================================
RCS file: /home/cvs/httpd-apreq-2/src/apreq_parsers.c,v
retrieving revision 1.44
retrieving revision 1.45
diff -u -r1.44 -r1.45
--- apreq_parsers.c 30 Apr 2004 05:08:35 -0000 1.44
+++ apreq_parsers.c 4 Jun 2004 22:02:11 -0000 1.45
@@ -31,11 +31,12 @@
#define CRLF "\015\012"
#endif
-APREQ_DECLARE(apreq_parser_t *) apreq_make_parser(apr_pool_t *pool,
- const char *enctype,
-
APREQ_DECLARE_PARSER(*parser),
- apreq_hook_t *hook,
- void *ctx)
+APREQ_DECLARE(apreq_parser_t *)
+ apreq_make_parser(apr_pool_t *pool,
+ const char *enctype,
+ apr_status_t (*parser) APREQ_PARSER_ARGS,
+ apreq_hook_t *hook,
+ void *ctx)
{
apreq_parser_t *p = apr_palloc(pool, sizeof *p);
p->enctype = apr_pstrdup(pool,enctype);
@@ -45,10 +46,11 @@
return p;
}
-APREQ_DECLARE(apreq_hook_t *) apreq_make_hook(apr_pool_t *pool,
- APREQ_DECLARE_HOOK(*hook),
- apreq_hook_t *next,
- void *ctx)
+APREQ_DECLARE(apreq_hook_t *)
+ apreq_make_hook(apr_pool_t *pool,
+ apr_status_t (*hook) APREQ_HOOK_ARGS,
+ apreq_hook_t *next,
+ void *ctx)
{
apreq_hook_t *h = apr_palloc(pool, sizeof *h);
h->hook = hook;
@@ -58,20 +60,16 @@
}
-APREQ_DECLARE(apr_status_t)apreq_add_hook(apreq_parser_t *p,
- apreq_hook_t *h)
+APREQ_DECLARE(void) apreq_add_hook(apreq_parser_t *p,
+ apreq_hook_t *h)
{
apreq_hook_t *last = h;
- if (p == NULL || h == NULL)
- return APR_EINIT;
-
while (last->next)
last = last->next;
last->next = p->hook;
p->hook = h;
- return APR_SUCCESS;
}
APREQ_DECLARE(apreq_parser_t *)apreq_parser(void *env, apreq_hook_t *hook)
@@ -839,7 +837,7 @@
if (ctx->info == NULL)
ctx->info = apr_table_make(pool, APREQ_NELTS);
- s = apreq_run_parser(ctx->hdr_parser, env, ctx->info, bb);
+ s = APREQ_RUN_PARSER(ctx->hdr_parser, env, ctx->info, bb);
if (s != APR_SUCCESS)
return (s == APR_EOF) ? APR_SUCCESS : s;
@@ -984,7 +982,7 @@
case APR_INCOMPLETE:
if (parser->hook) {
- s = apreq_run_hook(parser->hook, env, param, ctx->bb);
+ s = APREQ_RUN_HOOK(parser->hook, env, param, ctx->bb);
if (s != APR_INCOMPLETE && s != APR_SUCCESS)
return s;
}
@@ -996,7 +994,7 @@
apr_bucket *eos =
apr_bucket_eos_create(ctx->bb->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(ctx->bb, eos);
- s = apreq_run_hook(parser->hook, env, param, ctx->bb);
+ s = APREQ_RUN_HOOK(parser->hook, env, param, ctx->bb);
apr_bucket_delete(eos);
if (s != APR_SUCCESS)
return s;
1.9 +1 -1 httpd-apreq-2/src/apreq_version.h
Index: apreq_version.h
===================================================================
RCS file: /home/cvs/httpd-apreq-2/src/apreq_version.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -r1.8 -r1.9
--- apreq_version.h 24 Mar 2004 08:22:48 -0000 1.8
+++ apreq_version.h 4 Jun 2004 22:02:11 -0000 1.9
@@ -60,7 +60,7 @@
#define APREQ_MINOR_VERSION 0
/** patch level */
-#define APREQ_PATCH_VERSION 5
+#define APREQ_PATCH_VERSION 6
/**
* This symbol is defined for internal, "development" copies of libapreq.