From 1f14b397102d1ed423465223722726e995858cb5 Mon Sep 17 00:00:00 2001 From: Joe Orton Date: Thu, 23 Apr 2026 15:38:40 +0100 Subject: [PATCH 1/6] Remove apreq from trunk per PMC vote: https://lists.apache.org/thread/hlvtnmg8qq1m10xlmgvyn12wrw4z3gp3 --- include/apreq.h | 263 ------ include/apreq_cookie.h | 237 ----- include/apreq_error.h | 98 -- include/apreq_module.h | 457 --------- include/apreq_param.h | 209 ----- include/apreq_parser.h | 300 ------ include/apreq_util.h | 443 --------- modules/apreq/Makefile.in | 1 - modules/apreq/NWGNUmakefile | 250 ----- modules/apreq/apreq_module_apache2.h | 182 ---- modules/apreq/apreq_private_apache2.h | 56 -- modules/apreq/config.m4 | 9 - modules/apreq/filter.c | 532 ----------- modules/apreq/handle.c | 440 --------- modules/apreq/mod_apreq.dsp | 115 --- server/Makefile.in | 6 +- server/apreq_cookie.c | 537 ----------- server/apreq_error.c | 105 --- server/apreq_module.c | 65 -- server/apreq_module_cgi.c | 1025 --------------------- server/apreq_module_custom.c | 304 ------ server/apreq_param.c | 272 ------ server/apreq_parser.c | 358 ------- server/apreq_parser_header.c | 448 --------- server/apreq_parser_multipart.c | 689 -------------- server/apreq_parser_urlencoded.c | 277 ------ server/apreq_util.c | 1228 ------------------------- 27 files changed, 1 insertion(+), 8905 deletions(-) delete mode 100644 include/apreq.h delete mode 100644 include/apreq_cookie.h delete mode 100644 include/apreq_error.h delete mode 100644 include/apreq_module.h delete mode 100644 include/apreq_param.h delete mode 100644 include/apreq_parser.h delete mode 100644 include/apreq_util.h delete mode 100644 modules/apreq/Makefile.in delete mode 100644 modules/apreq/NWGNUmakefile delete mode 100644 modules/apreq/apreq_module_apache2.h delete mode 100644 modules/apreq/apreq_private_apache2.h delete mode 100644 modules/apreq/config.m4 delete mode 100644 modules/apreq/filter.c delete mode 100644 modules/apreq/handle.c delete mode 100644 modules/apreq/mod_apreq.dsp delete mode 100644 server/apreq_cookie.c delete mode 100644 server/apreq_error.c delete mode 100644 server/apreq_module.c delete mode 100644 server/apreq_module_cgi.c delete mode 100644 server/apreq_module_custom.c delete mode 100644 server/apreq_param.c delete mode 100644 server/apreq_parser.c delete mode 100644 server/apreq_parser_header.c delete mode 100644 server/apreq_parser_multipart.c delete mode 100644 server/apreq_parser_urlencoded.c delete mode 100644 server/apreq_util.c diff --git a/include/apreq.h b/include/apreq.h deleted file mode 100644 index bc3cda84016..00000000000 --- a/include/apreq.h +++ /dev/null @@ -1,263 +0,0 @@ -/* -** Licensed to the Apache Software Foundation (ASF) under one or more -** contributor license agreements. See the NOTICE file distributed with -** this work for additional information regarding copyright ownership. -** The ASF licenses this file to You under the Apache License, Version 2.0 -** (the "License"); you may not use this file except in compliance with -** the License. You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#ifndef APREQ_H -#define APREQ_H - -#ifdef APREQ_DEBUG -#include -#endif - -#include "ap_config.h" -#include "apr_tables.h" -#include - -#ifdef __cplusplus - extern "C" { -#endif - -/** - * @file apreq.h - * @brief Main header file... - * @ingroup libapreq2 - * - * Define the common data structures. - */ - -/** - * Read chucks of data in 64k blocks from the request - */ - -#define APREQ_DEFAULT_READ_BLOCK_SIZE (64 * 1024) - -/** - * Maximum number of bytes mod_apreq2 will send off to libapreq2 for parsing. - * mod_apreq2 will log this event and subsequently remove itself - * from the filter chain. - * @see ap_set_read_limit - */ -#define APREQ_DEFAULT_READ_LIMIT (64 * 1024 * 1024) -/** - * Maximum number of bytes mod_apreq2 will let accumulate within the - * heap-buckets in a brigade. Excess data will be spooled to an - * appended file bucket - * @see ap_set_brigade_read_limit - */ -#define APREQ_DEFAULT_BRIGADE_LIMIT (256 * 1024) - -/** - * Number of elements in the initial apr_table - * @see apr_table_make - */ -#define APREQ_DEFAULT_NELTS 8 - - - -/** - * Check to see if specified bit f is off in bitfield name - */ -#define APREQ_FLAGS_OFF(f, name) ((f) &= ~(name##_MASK << name##_BIT)) -/** - * Check to see if specified bit f is on in bitfield name - */ -#define APREQ_FLAGS_ON(f, name) ((f) |= (name##_MASK << name##_BIT)) -/** - * Get specified bit f in bitfield name - */ -#define APREQ_FLAGS_GET(f, name) (((f) >> name##_BIT) & name##_MASK) -/** - * Set specified bit f in bitfield name to value - * Note the below BIT/Mask defines are used sans the - * _BIT, _MASK because of the this define's \#\#_MASK, \#\#_BIT usage. - * Each come in a pair - */ -#define APREQ_FLAGS_SET(f, name, value) \ - ((f) = (((f) & ~(name##_MASK << name##_BIT)) \ - | ((name##_MASK & (value)) << name##_BIT))) - -/** - * Charset Bit - * @see APREQ_FLAGS_OFF @see APREQ_FLAGS_ON - * @see APREQ_FLAGS_GET @see APREQ_FLAGS_SET - */ -#define APREQ_CHARSET_BIT 0 - -/** - * Charset Mask - * @see APREQ_FLAGS_OFF @see APREQ_FLAGS_ON - * @see APREQ_FLAGS_GET @see APREQ_FLAGS_SET - */ -#define APREQ_CHARSET_MASK 255 - -/** - * Tainted Bit - * @see APREQ_FLAGS_OFF @see APREQ_FLAGS_ON - * @see APREQ_FLAGS_GET @see APREQ_FLAGS_SET - */ -#define APREQ_TAINTED_BIT 8 -/** - * Tainted Mask - * @see APREQ_FLAGS_OFF @see APREQ_FLAGS_ON - * @see APREQ_FLAGS_GET @see APREQ_FLAGS_SET - */ -#define APREQ_TAINTED_MASK 1 - -/** - * Cookier Version Bit - * @see APREQ_FLAGS_OFF @see APREQ_FLAGS_ON - * @see APREQ_FLAGS_GET @see APREQ_FLAGS_SET - */ - -#define APREQ_COOKIE_VERSION_BIT 11 -/** - * Cookie Version Mask - * @see APREQ_FLAGS_OFF @see APREQ_FLAGS_ON - * @see APREQ_FLAGS_GET @see APREQ_FLAGS_SET - */ -#define APREQ_COOKIE_VERSION_MASK 3 - -/** - * Cookie's Secure Bit - * @see APREQ_FLAGS_OFF @see APREQ_FLAGS_ON - * @see APREQ_FLAGS_GET @see APREQ_FLAGS_SET - */ -#define APREQ_COOKIE_SECURE_BIT 13 -/** - * Cookie's Secure Mask - * @see APREQ_FLAGS_OFF @see APREQ_FLAGS_ON - * @see APREQ_FLAGS_GET @see APREQ_FLAGS_SET - */ -#define APREQ_COOKIE_SECURE_MASK 1 - -/** - * Cookie's HttpOnly Bit - * @see APREQ_FLAGS_OFF @see APREQ_FLAGS_ON - * @see APREQ_FLAGS_GET @see APREQ_FLAGS_SET - */ -#define APREQ_COOKIE_HTTPONLY_BIT 14 -/** - * Cookie's HttpOnly Mask - * @see APREQ_FLAGS_OFF @see APREQ_FLAGS_ON - * @see APREQ_FLAGS_GET @see APREQ_FLAGS_SET - */ -#define APREQ_COOKIE_HTTPONLY_MASK 1 - -/** Character encodings. */ -typedef enum { - APREQ_CHARSET_ASCII =0, - APREQ_CHARSET_LATIN1 =1, /* ISO-8859-1 */ - APREQ_CHARSET_CP1252 =2, /* Windows-1252 */ - APREQ_CHARSET_UTF8 =8 -} apreq_charset_t; - - -/** @enum apreq_join_t Join type */ -typedef enum { - APREQ_JOIN_AS_IS, /**< Join the strings without modification */ - APREQ_JOIN_ENCODE, /**< Url-encode the strings before joining them */ - APREQ_JOIN_DECODE, /**< Url-decode the strings before joining them */ - APREQ_JOIN_QUOTE /**< Quote the strings, backslashing existing quote marks. */ -} apreq_join_t; - -/** @enum apreq_match_t Match type */ -typedef enum { - APREQ_MATCH_FULL, /**< Full match only. */ - APREQ_MATCH_PARTIAL /**< Partial matches are ok. */ -} apreq_match_t; - -/** @enum apreq_expires_t Expiration date format */ -typedef enum { - APREQ_EXPIRES_HTTP, /**< Use date formatting consistent with RFC 2616 */ - APREQ_EXPIRES_NSCOOKIE /**< Use format consistent with Netscape's Cookie Spec */ -} apreq_expires_t; - - -/** @brief libapreq's pre-extensible string type */ -typedef struct apreq_value_t { - char *name; /**< value name */ - apr_size_t nlen; /**< length of name */ - apr_size_t dlen; /**< length of data */ - char data[1]; /**< value data */ -} apreq_value_t; - -/** - * Adds the specified apreq_value_t to the apr_table_t. - * - * @param v value to add - * @param t add v to this table - * - * @return void - * - * @ see apr_table_t @see apr_value_t - */ - -static APR_INLINE -void apreq_value_table_add(const apreq_value_t *v, apr_table_t *t) { - apr_table_addn(t, v->name, v->data); -} - -/** - * @param T type - * @param A attribute - * @param P - * - * XXX - */ -#define apreq_attr_to_type(T,A,P) ( (T*) ((char*)(P)-offsetof(T,A)) ) - -/** - * Initialize libapreq2. Applications (except apache modules using - * mod_apreq) should call this exactly once before they use any - * libapreq2 modules. If you want to modify the list of default parsers - * with apreq_register_parser(), please use apreq_pre_initialize() - * and apreq_post_initialize() instead. - * - * @param pool a base pool persisting while libapreq2 is used - * @remarks after you destroy the pool, you have to call this function again - * with a new pool if you still plan to use libapreq2 - */ -APREQ_DECLARE(apr_status_t) apreq_initialize(apr_pool_t *pool); - - -/** - * Pre-initialize libapreq2. Applications (except apache modules using - * mod_apreq2) should call this exactly once before they register custom - * parsers with libapreq2. mod_apreq2 does this automatically during the - * post-config phase, so modules that need call apreq_register_parser should - * create a post-config hook using APR_HOOK_MIDDLE. - * - * @param pool a base pool persisting while libapreq2 is used - * @remarks after you destroyed the pool, you have to call this function again - * with a new pool if you still plan to use libapreq2 - */ -APREQ_DECLARE(apr_status_t) apreq_pre_initialize(apr_pool_t *pool); - -/** - * Post-initialize libapreq2. Applications (except apache modules using - * mod_apreq2) should this exactly once before they use any - * libapreq2 modules for parsing. - * - * @param pool the same pool that was used in apreq_pre_initialize(). - */ -APREQ_DECLARE(apr_status_t) apreq_post_initialize(apr_pool_t *pool); - - -#ifdef __cplusplus - } -#endif - -#endif /* APREQ_H */ diff --git a/include/apreq_cookie.h b/include/apreq_cookie.h deleted file mode 100644 index 282cf86fca7..00000000000 --- a/include/apreq_cookie.h +++ /dev/null @@ -1,237 +0,0 @@ -/* -** Licensed to the Apache Software Foundation (ASF) under one or more -** contributor license agreements. See the NOTICE file distributed with -** this work for additional information regarding copyright ownership. -** The ASF licenses this file to You under the Apache License, Version 2.0 -** (the "License"); you may not use this file except in compliance with -** the License. You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#ifndef APREQ_COOKIE_H -#define APREQ_COOKIE_H - -#include "apreq.h" -#include "apr_time.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @file apreq_cookie.h - * @brief Cookies and Jars. - * @ingroup libapreq2 - * - * apreq_cookie.h describes a common server-side API for request (incoming) - * and response (outgoing) cookies. It aims towards compliance with the - * standard cookie specifications listed below. - * - * @see http://wp.netscape.com/newsref/std/cookie_spec.html - * @see http://www.ietf.org/rfc/rfc2109.txt - * @see http://www.ietf.org/rfc/rfc2964.txt - * @see http://www.ietf.org/rfc/rfc2965.txt - * - */ - -/** This macro is deprecated. - * - * Maximum length of a single Set-Cookie(2) header. - */ -#define APREQ_COOKIE_MAX_LENGTH 4096 - -/** @brief Cookie type, supporting both Netscape and RFC cookie specifications. - */ - -typedef struct apreq_cookie_t { - - char *path; /**< Restricts url path */ - char *domain; /**< Restricts server domain */ - char *port; /**< Restricts server port */ - char *comment; /**< RFC cookies may send a comment */ - char *commentURL; /**< RFC cookies may place an URL here */ - apr_time_t max_age; /**< total duration of cookie: -1 == session */ - unsigned flags; /**< charsets, taint marks, app-specific bits */ - const apreq_value_t v; /**< "raw" cookie value */ - -} apreq_cookie_t; - - -/** Upgrades a jar's table values to apreq_cookie_t structs. */ -static APR_INLINE -apreq_cookie_t *apreq_value_to_cookie(const char *val) -{ - union { const char *in; char *out; } deconst; - - deconst.in = val; - return apreq_attr_to_type(apreq_cookie_t, v, - apreq_attr_to_type(apreq_value_t, data, deconst.out)); -} - -/**@return 1 if this is an RFC cookie, 0 if its a Netscape cookie. */ -static APR_INLINE -unsigned apreq_cookie_version(const apreq_cookie_t *c) { - return APREQ_FLAGS_GET(c->flags, APREQ_COOKIE_VERSION); -} - -/** Sets the cookie's protocol version. */ -static APR_INLINE -void apreq_cookie_version_set(apreq_cookie_t *c, unsigned v) { - APREQ_FLAGS_SET(c->flags, APREQ_COOKIE_VERSION, v); -} - -/** @return 1 if the secure flag is set, 0 otherwise. */ -static APR_INLINE -unsigned apreq_cookie_is_secure(const apreq_cookie_t *c) { - return APREQ_FLAGS_GET(c->flags, APREQ_COOKIE_SECURE); -} - -/** Sets the cookie's secure flag, meaning it only - * comes back over an SSL-encrypted connction. - */ -static APR_INLINE -void apreq_cookie_secure_on(apreq_cookie_t *c) { - APREQ_FLAGS_ON(c->flags, APREQ_COOKIE_SECURE); -} - -/** Turns off the cookie's secure flag. */ -static APR_INLINE -void apreq_cookie_secure_off(apreq_cookie_t *c) { - APREQ_FLAGS_OFF(c->flags, APREQ_COOKIE_SECURE); -} - -/** @return 1 if the HttpOnly flag is set, 0 otherwise. */ -static APR_INLINE -unsigned apreq_cookie_is_httponly(const apreq_cookie_t *c) { - return APREQ_FLAGS_GET(c->flags, APREQ_COOKIE_HTTPONLY); -} - -/** Sets the cookie's HttpOnly flag, meaning it is not - * accessible through client-side script in supported - * browsers. - */ -static APR_INLINE -void apreq_cookie_httponly_on(apreq_cookie_t *c) { - APREQ_FLAGS_ON(c->flags, APREQ_COOKIE_HTTPONLY); -} - -/** Turns off the cookie's HttpOnly flag. */ -static APR_INLINE -void apreq_cookie_httponly_off(apreq_cookie_t *c) { - APREQ_FLAGS_OFF(c->flags, APREQ_COOKIE_HTTPONLY); -} - - -/** @return 1 if the taint flag is set, 0 otherwise. */ -static APR_INLINE -unsigned apreq_cookie_is_tainted(const apreq_cookie_t *c) { - return APREQ_FLAGS_GET(c->flags, APREQ_TAINTED); -} - -/** Sets the cookie's tainted flag. */ -static APR_INLINE -void apreq_cookie_tainted_on(apreq_cookie_t *c) { - APREQ_FLAGS_ON(c->flags, APREQ_TAINTED); -} - -/** Turns off the cookie's tainted flag. */ -static APR_INLINE -void apreq_cookie_tainted_off(apreq_cookie_t *c) { - APREQ_FLAGS_OFF(c->flags, APREQ_TAINTED); -} - -/** - * Parse a cookie header and store the cookies in an apr_table_t. - * - * @param pool pool which allocates the cookies - * @param jar table where parsed cookies are stored - * @param header the header value - * - * @return APR_SUCCESS. - * @return ::APREQ_ERROR_BADSEQ if an unparsable character sequence appears. - * @return ::APREQ_ERROR_MISMATCH if an rfc-cookie attribute appears in a - * netscape cookie header. - * @return ::APR_ENOTIMPL if an unrecognized rfc-cookie attribute appears. - * @return ::APREQ_ERROR_NOTOKEN if a required token was not present. - * @return ::APREQ_ERROR_BADCHAR if an unexpected token was present. - */ -APREQ_DECLARE(apr_status_t) apreq_parse_cookie_header(apr_pool_t *pool, - apr_table_t *jar, - const char *header); - -/** - * Returns a new cookie, made from the argument list. - * - * @param pool Pool which allocates the cookie. - * @param name The cookie's name. - * @param nlen Length of name. - * @param value The cookie's value. - * @param vlen Length of value. - * - * @return the new cookie - */ -APREQ_DECLARE(apreq_cookie_t *) apreq_cookie_make(apr_pool_t *pool, - const char *name, - const apr_size_t nlen, - const char *value, - const apr_size_t vlen); - -/** - * Returns a string that represents the cookie as it would appear - * in a valid "Set-Cookie*" header. - * - * @param c cookie. - * @param p pool which allocates the returned string. - * - * @return header string. - */ -APREQ_DECLARE(char*) apreq_cookie_as_string(const apreq_cookie_t *c, - apr_pool_t *p); - - -/** - * Same functionality as apreq_cookie_as_string. Stores the string - * representation in buf, using up to len bytes in buf as storage. - * The return value has the same semantics as that of apr_snprintf, - * including the special behavior for a "len = 0" argument. - * - * @param c cookie. - * @param buf storage location for the result. - * @param len size of buf's storage area. - * - * @return size of resulting header string. - */ -APREQ_DECLARE(int) apreq_cookie_serialize(const apreq_cookie_t *c, - char *buf, apr_size_t len); - -/** - * Set the Cookie's expiration date. - * - * @param c The cookie. - * @param time_str If NULL, the Cookie's expiration date is unset, - * making it a session cookie. This means no "expires" or "max-age" - * attribute will appear in the cookie's serialized form. If time_str - * is not NULL, the expiration date will be reset to the offset (from now) - * represented by time_str. The time_str should be in a format that - * apreq_atoi64t() can understand, namely /[+-]?\\d+\\s*[YMDhms]/. - * - * @remarks Now time_str may also be a fixed date; see apr_date_parse_rfc() - * for admissible formats. - */ -APREQ_DECLARE(void) apreq_cookie_expires(apreq_cookie_t *c, - const char *time_str); - -#ifdef __cplusplus - } -#endif - -#endif /*APREQ_COOKIE_H*/ - - diff --git a/include/apreq_error.h b/include/apreq_error.h deleted file mode 100644 index d669b89cdfd..00000000000 --- a/include/apreq_error.h +++ /dev/null @@ -1,98 +0,0 @@ -/* -** Licensed to the Apache Software Foundation (ASF) under one or more -** contributor license agreements. See the NOTICE file distributed with -** this work for additional information regarding copyright ownership. -** The ASF licenses this file to You under the Apache License, Version 2.0 -** (the "License"); you may not use this file except in compliance with -** the License. You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#ifndef APREQ_ERROR_H -#define APREQ_ERROR_H - -#include "apr_errno.h" -#include "apreq.h" - -#ifdef __cplusplus - extern "C" { -#endif - -/** - * apreq's wrapper around apr_strerror(); - * recognizes APREQ_ERROR_* status codes. - */ -APREQ_DECLARE(char *) apreq_strerror(apr_status_t s, - char *buf, - apr_size_t bufsize); - -/** - * @file apreq_error.h - * @brief Error status codes. - * @ingroup libapreq2 - * - * Define the APREQ_ error codes. - */ - -#ifndef APR_EBADARG -/** - * Bad Arguments return value - * @see APR_BADARG - */ -#define APR_EBADARG APR_BADARG /* XXX: don't use APR_BADARG */ -#endif - -/** Internal apreq error. */ -#define APREQ_ERROR_GENERAL APR_OS_START_USERERR -/** Attempted to perform unsafe action with tainted data. */ -#define APREQ_ERROR_TAINTED (APREQ_ERROR_GENERAL + 1) -/** Parsing interrupted. */ -#define APREQ_ERROR_INTERRUPT (APREQ_ERROR_GENERAL + 2) - -/** Invalid input data. */ -#define APREQ_ERROR_BADDATA (APREQ_ERROR_GENERAL + 10) -/** Invalid character. */ -#define APREQ_ERROR_BADCHAR (APREQ_ERROR_BADDATA + 1) -/** Invalid byte sequence. */ -#define APREQ_ERROR_BADSEQ (APREQ_ERROR_BADDATA + 2) -/** Invalid attribute. */ -#define APREQ_ERROR_BADATTR (APREQ_ERROR_BADDATA + 3) -/** Invalid header. */ -#define APREQ_ERROR_BADHEADER (APREQ_ERROR_BADDATA + 4) -/** Invalid utf8 encoding. */ -#define APREQ_ERROR_BADUTF8 (APREQ_ERROR_BADDATA + 5) - -/** Missing input data. */ -#define APREQ_ERROR_NODATA (APREQ_ERROR_GENERAL + 20) -/** Missing required token. */ -#define APREQ_ERROR_NOTOKEN (APREQ_ERROR_NODATA + 1) -/** Missing attribute. */ -#define APREQ_ERROR_NOATTR (APREQ_ERROR_NODATA + 2) -/** Missing header. */ -#define APREQ_ERROR_NOHEADER (APREQ_ERROR_NODATA + 3) -/** Missing parser. */ -#define APREQ_ERROR_NOPARSER (APREQ_ERROR_NODATA + 4) - - -/** Conflicting information. */ -#define APREQ_ERROR_MISMATCH (APREQ_ERROR_GENERAL + 30) -/** Exceeds configured maximum limit. */ -#define APREQ_ERROR_OVERLIMIT (APREQ_ERROR_MISMATCH + 1) -/** Below configured minimum limit. */ -#define APREQ_ERROR_UNDERLIMIT (APREQ_ERROR_MISMATCH + 2) -/** Setting already configured. */ -#define APREQ_ERROR_NOTEMPTY (APREQ_ERROR_MISMATCH + 3) - - -#ifdef __cplusplus - } -#endif - -#endif /* APREQ_ERROR_H */ diff --git a/include/apreq_module.h b/include/apreq_module.h deleted file mode 100644 index 5f964348fa7..00000000000 --- a/include/apreq_module.h +++ /dev/null @@ -1,457 +0,0 @@ -/* -** Licensed to the Apache Software Foundation (ASF) under one or more -** contributor license agreements. See the NOTICE file distributed with -** this work for additional information regarding copyright ownership. -** The ASF licenses this file to You under the Apache License, Version 2.0 -** (the "License"); you may not use this file except in compliance with -** the License. You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#ifndef APREQ_MODULE_H -#define APREQ_MODULE_H - -#include "apreq_cookie.h" -#include "apreq_parser.h" -#include "apreq_error.h" - -#ifdef __cplusplus - extern "C" { -#endif - -/** - * @file apreq_module.h - * @brief Module API - * @ingroup libapreq2 - */ - - -/** - * An apreq handle associated with a module. The structure - * may have variable size, because the module may append its own data - * structures after it. - */ -typedef struct apreq_handle_t { - /** the apreq module which implements this handle */ - const struct apreq_module_t *module; - /** the pool which defines the lifetime of the parsed data */ - apr_pool_t *pool; - /** the allocator, which persists at least as long as the pool */ - apr_bucket_alloc_t *bucket_alloc; - -} apreq_handle_t; - -/** - * @brief Vtable describing the necessary module functions. - */ - - -typedef struct apreq_module_t { - /** name of this apreq module */ - const char *name; - /** magic number identifying the module and version */ - apr_uint32_t magic_number; - - /** get a table with all cookies */ - apr_status_t (*jar)(apreq_handle_t *, const apr_table_t **); - /** get a table with all query string parameters */ - apr_status_t (*args)(apreq_handle_t *, const apr_table_t **); - /** get a table with all body parameters */ - apr_status_t (*body)(apreq_handle_t *, const apr_table_t **); - - /** get a cookie by its name */ - apreq_cookie_t *(*jar_get)(apreq_handle_t *, const char *); - /** get a query string parameter by its name */ - apreq_param_t *(*args_get)(apreq_handle_t *, const char *); - /** get a body parameter by its name */ - apreq_param_t *(*body_get)(apreq_handle_t *, const char *); - - /** gets the parser associated with the request body */ - apr_status_t (*parser_get)(apreq_handle_t *, const apreq_parser_t **); - /** manually set a parser for the request body */ - apr_status_t (*parser_set)(apreq_handle_t *, apreq_parser_t *); - /** add a hook function */ - apr_status_t (*hook_add)(apreq_handle_t *, apreq_hook_t *); - - /** determine the maximum in-memory bytes a brigade may use */ - apr_status_t (*brigade_limit_get)(apreq_handle_t *, apr_size_t *); - /** set the maximum in-memory bytes a brigade may use */ - apr_status_t (*brigade_limit_set)(apreq_handle_t *, apr_size_t); - - /** determine the maximum amount of data that will be fed into a parser */ - apr_status_t (*read_limit_get)(apreq_handle_t *, apr_uint64_t *); - /** set the maximum amount of data that will be fed into a parser */ - apr_status_t (*read_limit_set)(apreq_handle_t *, apr_uint64_t); - - /** determine the directory used by the parser for temporary files */ - apr_status_t (*temp_dir_get)(apreq_handle_t *, const char **); - /** set the directory used by the parser for temporary files */ - apr_status_t (*temp_dir_set)(apreq_handle_t *, const char *); - -} apreq_module_t; - - -/** - * Defines the module-specific status codes which - * are commonly considered to be non-fatal. - * - * @param s status code returned by an apreq_module_t method. - * - * @return 1 if s is fatal, 0 otherwise. - */ -static APR_INLINE -unsigned apreq_module_status_is_error(apr_status_t s) { - switch (s) { - case APR_SUCCESS: - case APR_INCOMPLETE: - case APR_EINIT: - case APREQ_ERROR_NODATA: - case APREQ_ERROR_NOPARSER: - case APREQ_ERROR_NOHEADER: - return 0; - default: - return 1; - } -} - - -/** - * Expose the parsed "cookie" header associated to this handle. - * - * @param req The request handle - * @param t The resulting table, which will either be NULL or a - * valid table object on return. - * - * @return APR_SUCCESS or a module-specific error status code. - */ -static APR_INLINE -apr_status_t apreq_jar(apreq_handle_t *req, const apr_table_t **t) -{ - return req->module->jar(req,t); -} - -/** - * Expose the parsed "query string" associated to this handle. - * - * @param req The request handle - * @param t The resulting table, which will either be NULL or a - * valid table object on return. - * - * @return APR_SUCCESS or a module-specific error status code. - */ -static APR_INLINE -apr_status_t apreq_args(apreq_handle_t *req, const apr_table_t **t) -{ - return req->module->args(req,t); -} - -/** - * Expose the parsed "request body" associated to this handle. - * - * @param req The request handle - * @param t The resulting table, which will either be NULL or a - * valid table object on return. - * - * @return APR_SUCCESS or a module-specific error status code. - */ -static APR_INLINE -apr_status_t apreq_body(apreq_handle_t *req, const apr_table_t **t) -{ - return req->module->body(req, t); -} - - -/** - * Fetch the first cookie with the given name. - * - * @param req The request handle - * @param name Case-insensitive cookie name. - * - * @return First matching cookie, or NULL if none match. - */ -static APR_INLINE -apreq_cookie_t *apreq_jar_get(apreq_handle_t *req, const char *name) -{ - return req->module->jar_get(req, name); -} - -/** - * Fetch the first query string param with the given name. - * - * @param req The request handle - * @param name Case-insensitive param name. - * - * @return First matching param, or NULL if none match. - */ -static APR_INLINE -apreq_param_t *apreq_args_get(apreq_handle_t *req, const char *name) -{ - return req->module->args_get(req, name); -} - -/** - * Fetch the first body param with the given name. - * - * @param req The request handle - * @param name Case-insensitive cookie name. - * - * @return First matching param, or NULL if none match. - */ -static APR_INLINE -apreq_param_t *apreq_body_get(apreq_handle_t *req, const char *name) -{ - return req->module->body_get(req, name); -} - -/** - * Fetch the active body parser. - * - * @param req The request handle - * @param parser Points to the active parser on return. - * - * @return APR_SUCCESS or module-specific error. - * - */ -static APR_INLINE -apr_status_t apreq_parser_get(apreq_handle_t *req, - const apreq_parser_t **parser) -{ - return req->module->parser_get(req, parser); -} - - -/** - * Set the body parser for this request. - * - * @param req The request handle - * @param parser New parser to use. - * - * @return APR_SUCCESS or module-specific error. - */ -static APR_INLINE -apr_status_t apreq_parser_set(apreq_handle_t *req, - apreq_parser_t *parser) -{ - return req->module->parser_set(req, parser); -} - -/** - * Add a parser hook for this request. - * - * @param req The request handle - * @param hook Hook to add. - * - * @return APR_SUCCESS or module-specific error. - */ -static APR_INLINE -apr_status_t apreq_hook_add(apreq_handle_t *req, apreq_hook_t *hook) -{ - return req->module->hook_add(req, hook); -} - - -/** - * Set the active brigade limit. - * - * @param req The handle. - * @param bytes New limit to use. - * - * @return APR_SUCCESS or module-specific error. - * - */ -static APR_INLINE -apr_status_t apreq_brigade_limit_set(apreq_handle_t *req, - apr_size_t bytes) -{ - return req->module->brigade_limit_set(req, bytes); -} - -/** - * Get the active brigade limit. - * - * @param req The handle. - * @param bytes Pointer to resulting (current) limit. - * - * @return APR_SUCCESS or a module-specific error, - * which may leave bytes undefined. - */ -static APR_INLINE -apr_status_t apreq_brigade_limit_get(apreq_handle_t *req, - apr_size_t *bytes) -{ - return req->module->brigade_limit_get(req, bytes); -} - -/** - * Set the active read limit. - * - * @param req The handle. - * @param bytes New limit to use. - * - * @return APR_SUCCESS or a module-specific error. - * - */ -static APR_INLINE -apr_status_t apreq_read_limit_set(apreq_handle_t *req, - apr_uint64_t bytes) -{ - return req->module->read_limit_set(req, bytes); -} - -/** - * Get the active read limit. - * - * @param req The request handle. - * @param bytes Pointer to resulting (current) limit. - * - * @return APR_SUCCESS or a module-specific error, - * which may leave bytes undefined. - */ -static APR_INLINE -apr_status_t apreq_read_limit_get(apreq_handle_t *req, - apr_uint64_t *bytes) -{ - return req->module->read_limit_get(req, bytes); -} - -/** - * Set the active temp directory. - * - * @param req The handle. - * @param path New path to use; may be NULL. - * - * @return APR_SUCCESS or a module-specific error . - */ -static APR_INLINE -apr_status_t apreq_temp_dir_set(apreq_handle_t *req, const char *path) -{ - return req->module->temp_dir_set(req, path); -} - -/** - * Get the active temp directory. - * - * @param req The handle. - * @param path Resulting path to temp dir. - * - * @return APR_SUCCESS implies path is valid, but may also be NULL. - * Any other return value is module-specific, and may leave - * path undefined. - */ -static APR_INLINE -apr_status_t apreq_temp_dir_get(apreq_handle_t *req, const char **path) -{ - return req->module->temp_dir_get(req, path); -} - - - -/** - * Convenience macro for defining a module by mapping - * a function prefix to an associated apreq_module_t structure. - * - * @param pre Prefix to define new module. All attributes of - * the apreq_module_t struct are defined with this as their - * prefix. The generated struct is named by appending "_module" to - * the prefix. - * @param mmn Magic number (i.e. version number) of this module. - */ -#define APREQ_MODULE(pre, mmn) const apreq_module_t \ - pre##_module = { #pre, mmn, \ - pre##_jar, pre##_args, pre##_body, \ - pre##_jar_get, pre##_args_get, pre##_body_get, \ - pre##_parser_get, pre##_parser_set, pre##_hook_add, \ - pre##_brigade_limit_get, pre##_brigade_limit_set, \ - pre##_read_limit_get, pre##_read_limit_set, \ - pre##_temp_dir_get, pre##_temp_dir_set, \ - } - - -/** - * Create an apreq handle which is suitable for a CGI program. It - * reads input from stdin and writes output to stdout. - * - * @param pool Pool associated to this handle. - * - * @return New handle; can only be NULL if the pool allocation failed. - * - * @remarks The handle gets cached in the pool's userdata, so subsequent - * calls will retrieve the original cached handle. - */ -APREQ_DECLARE(apreq_handle_t*) apreq_handle_cgi(apr_pool_t *pool); - -/** - * Create a custom apreq handle which knows only some static - * values. Useful if you want to test the parser code or if you have - * got data from a custom source (neither Apache 2 nor CGI). - * - * @param pool allocates the parse data, - * @param query_string parsed into args table - * @param cookie value of the request "Cookie" header - * @param parser parses the request body - * @param read_limit maximum bytes to read from the body - * @param in brigade containing the request body - * - * @return new handle; can only be NULL if the pool allocation failed. - */ -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); - -/** - * Find the first query string parameter or body parameter with the - * specified name. The match is case-insensitive. - * - * @param req request handle. - * @param key desired parameter name - * - * @return The first matching parameter (with args searched first) or NULL. - */ -APREQ_DECLARE(apreq_param_t *)apreq_param(apreq_handle_t *req, const char *key); - -/** - * Find the first cookie with the specified name. - * The match is case-insensitive. - * - * @param req request handle. - * @param name desired cookie name - * - * @return The first matching cookie or NULL. - */ -#define apreq_cookie(req, name) apreq_jar_get(req, name) - -/** - * Returns a table containing key-value pairs for the full request - * (args + body). - * - * @param req request handle - * @param p allocates the returned table. - * - * @return table representing all available params; is never NULL. - */ -APREQ_DECLARE(apr_table_t *) apreq_params(apreq_handle_t *req, apr_pool_t *p); - - -/** - * Returns a table containing all request cookies. - * - * @param req the apreq request handle - * @param p Allocates the returned table. - */ -APREQ_DECLARE(apr_table_t *)apreq_cookies(apreq_handle_t *req, apr_pool_t *p); - -#ifdef __cplusplus - } -#endif - -#endif /* APREQ_MODULE_H */ diff --git a/include/apreq_param.h b/include/apreq_param.h deleted file mode 100644 index 832cfc2f387..00000000000 --- a/include/apreq_param.h +++ /dev/null @@ -1,209 +0,0 @@ -/* -** Licensed to the Apache Software Foundation (ASF) under one or more -** contributor license agreements. See the NOTICE file distributed with -** this work for additional information regarding copyright ownership. -** The ASF licenses this file to You under the Apache License, Version 2.0 -** (the "License"); you may not use this file except in compliance with -** the License. You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#ifndef APREQ_PARAM_H -#define APREQ_PARAM_H - -#include "apreq.h" -#include "apr_buckets.h" - -#ifdef __cplusplus -extern "C" { -#endif - - -/** - * @file apreq_param.h - * @brief Request parsing and parameter API - * @ingroup libapreq2 - */ - - -/** Common data structure for params and file uploads */ -typedef struct apreq_param_t { - apr_table_t *info; /**< header table associated with the param */ - apr_bucket_brigade *upload; /**< brigade used to spool upload files */ - unsigned flags; /**< charsets, taint marks, app-specific bits */ - const apreq_value_t v; /**< underlying name/value info */ -} apreq_param_t; - - -/** @return 1 if the taint flag is set, 0 otherwise. */ -static APR_INLINE -unsigned apreq_param_is_tainted(const apreq_param_t *p) { - return APREQ_FLAGS_GET(p->flags, APREQ_TAINTED); -} - -/** Sets the tainted flag. */ -static APR_INLINE -void apreq_param_tainted_on(apreq_param_t *p) { - APREQ_FLAGS_ON(p->flags, APREQ_TAINTED); -} - -/** Turns off the taint flag. */ -static APR_INLINE -void apreq_param_tainted_off(apreq_param_t *p) { - APREQ_FLAGS_OFF(p->flags, APREQ_TAINTED); -} - -/** Sets the character encoding for this parameter. */ -static APR_INLINE -apreq_charset_t apreq_param_charset_set(apreq_param_t *p, apreq_charset_t c) { - apreq_charset_t old = (apreq_charset_t) - APREQ_FLAGS_GET(p->flags, APREQ_CHARSET); - APREQ_FLAGS_SET(p->flags, APREQ_CHARSET, c); - return old; -} - -/** Gets the character encoding for this parameter. */ -static APR_INLINE -apreq_charset_t apreq_param_charset_get(apreq_param_t *p) { - return (apreq_charset_t)APREQ_FLAGS_GET(p->flags, APREQ_CHARSET); -} - - -/** Upgrades args and body table values to apreq_param_t structs. */ -static APR_INLINE -apreq_param_t *apreq_value_to_param(const char *val) -{ - union { const char *in; char *out; } deconst; - - deconst.in = val; - return apreq_attr_to_type(apreq_param_t, v, - apreq_attr_to_type(apreq_value_t, data, deconst.out)); -} - - - -/** creates a param from name/value information */ -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); - -/** - * Url-decodes a name=value pair into a param. - * - * @param param points to the decoded parameter on success - * @param pool Pool from which the param is allocated. - * @param word Start of the name=value pair. - * @param nlen Length of urlencoded name. - * @param vlen Length of urlencoded value. - * - * @return APR_SUCCESS on success. - * @return ::APREQ_ERROR_BADSEQ or ::APREQ_ERROR_BADCHAR on malformed input. - * - * @remarks Unless vlen == 0, this function assumes there is - * exactly one character ('=') which separates the pair. - * - */ -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); - -/** - * 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_param_encode(apr_pool_t *pool, - const apreq_param_t *param); - -/** - * Parse a url-encoded string into a param table. - * @param pool pool used to allocate the param data. - * @param t 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. - * - */ -APREQ_DECLARE(apr_status_t) apreq_parse_query_string(apr_pool_t *pool, - apr_table_t *t, - const char *qs); - - -/** - * Returns an array of parameters (apreq_param_t *) matching the given key. - * The key is case-insensitive. - * @param p Allocates the returned array. - * @param t the parameter table returned by apreq_args(), apreq_body() - * or apreq_params() - * @param key Null-terminated search key, case insensitive. - * key==NULL fetches all parameters. - * @return an array of apreq_param_t* (pointers) - * @remark Also parses the request if necessary. - */ -APREQ_DECLARE(apr_array_header_t *) apreq_params_as_array(apr_pool_t *p, - const apr_table_t *t, - const char *key); - -/** - * Returns a ", " -joined string containing all parameters - * for the requested key, an empty string if none are found. - * The key is case-insensitive. - * - * @param p Allocates the return string. - * @param t the parameter table returned by apreq_args(), apreq_body() - * or apreq_params() - * @param key Null-terminated parameter name, case insensitive. - * key==NULL fetches all values. - * @param mode Join type- see apreq_join(). - * @return the joined string or NULL on error - * @remark Also parses the request if necessary. - */ -APREQ_DECLARE(const char *) apreq_params_as_string(apr_pool_t *p, - const apr_table_t *t, - const char *key, - apreq_join_t mode); - -/** - * Returns a table of all params in req->body with non-NULL upload brigades. - * @param body parameter table returned by apreq_body() or apreq_params() - * @param pool Pool which allocates the table struct. - * @return Upload table. - * @remark Will parse the request if necessary. - */ -APREQ_DECLARE(const apr_table_t *) apreq_uploads(const apr_table_t *body, - apr_pool_t *pool); - -/** - * Returns the first param in req->body which has both param->v.name - * matching key (case insensitive) and param->upload != NULL. - * @param body parameter table returned by apreq_body() or apreq_params() - * @param name Parameter name. key == NULL returns first upload. - * @return Corresponding upload, NULL if none found. - * @remark Will parse the request as necessary. - */ -APREQ_DECLARE(const apreq_param_t *) apreq_upload(const apr_table_t *body, - const char *name); - - -#ifdef __cplusplus -} -#endif - -#endif /* APREQ_PARAM_H */ - - - diff --git a/include/apreq_parser.h b/include/apreq_parser.h deleted file mode 100644 index 11465d0eaa5..00000000000 --- a/include/apreq_parser.h +++ /dev/null @@ -1,300 +0,0 @@ -/* -** Licensed to the Apache Software Foundation (ASF) under one or more -** contributor license agreements. See the NOTICE file distributed with -** this work for additional information regarding copyright ownership. -** The ASF licenses this file to You under the Apache License, Version 2.0 -** (the "License"); you may not use this file except in compliance with -** the License. You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#ifndef APREQ_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); - -/** - * Context struct for the apreq_hook_find_param hook. - */ -typedef struct apreq_hook_find_param_ctx_t { - const char *name; - apreq_param_t *param; - apreq_hook_t *prev; -} apreq_hook_find_param_ctx_t; - - -/** - * Special purpose utility for locating a parameter - * during parsing. The hook's ctx should be initialized - * to an apreq_hook_find_param_ctx_t *, with the name - * attribute set to the sought parameter name, the param - * attribute set to NULL, and the prev attribute set to - * the address of the previous hook. The param attribute - * will be reassigned to the first param found, and once - * that happens this hook is immediately removed from the chain. - * - * @remarks When used, this should always be the first hook - * invoked, so add it manually with ctx->prev = &parser->hook - * instead of using apreq_parser_add_hook. - */ -APREQ_DECLARE_HOOK(apreq_hook_find_param); - - -#ifdef __cplusplus -} - -#endif -#endif /* APREQ_PARSERS_H */ diff --git a/include/apreq_util.h b/include/apreq_util.h deleted file mode 100644 index 58d57a16c8d..00000000000 --- a/include/apreq_util.h +++ /dev/null @@ -1,443 +0,0 @@ -/* -** Licensed to the Apache Software Foundation (ASF) under one or more -** contributor license agreements. See the NOTICE file distributed with -** this work for additional information regarding copyright ownership. -** The ASF licenses this file to You under the Apache License, Version 2.0 -** (the "License"); you may not use this file except in compliance with -** the License. You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#ifndef APREQ_UTIL_H -#define APREQ_UTIL_H - -#include "apr_file_io.h" -#include "apr_buckets.h" -#include "apreq.h" - -#ifdef __cplusplus - extern "C" { -#endif - -/** - * This header contains useful functions for creating new - * parsers, hooks or modules. It includes - * - * - string <-> array converters - * - substring search functions - * - simple encoders & decoders for urlencoded strings - * - simple time, date, & file-size converters - * @file apreq_util.h - * @brief Utility functions for apreq. - * @ingroup libapreq2 - */ - -/** - * Join an array of values. The result is an empty string if there are - * no values. - * - * @param p Pool to allocate return value. - * @param sep String that is inserted between the joined values. - * @param arr Array of apreq_value_t entries. - * @param mode Join type- see apreq_join_t. - * - * @return Joined string, or NULL on error - */ -APREQ_DECLARE(char *) apreq_join(apr_pool_t *p, - const char *sep, - const apr_array_header_t *arr, - apreq_join_t mode); - -/** - * Returns offset of match string's location, or -1 if no match is found. - * - * @param hay Location of bytes to scan. - * @param hlen Number of bytes available for scanning. - * @param ndl Search string - * @param nlen Length of search string. - * @param type Match type. - * - * @return Offset of match string, or -1 if no match is found. - * - */ -APREQ_DECLARE(apr_ssize_t) apreq_index(const char* hay, apr_size_t hlen, - const char* ndl, apr_size_t nlen, - const apreq_match_t type); - -/** - * Places a quoted copy of src into dest. Embedded quotes are escaped with a - * backslash ('\'). - * - * @param dest Location of quoted copy. Must be large enough to hold the copy - * and trailing null byte. - * @param src Original string. - * @param slen Length of original string. - * @param dest Destination string. - * - * @return length of quoted copy in dest. - */ -APREQ_DECLARE(apr_size_t) apreq_quote(char *dest, const char *src, - const apr_size_t slen); - -/** - * - * Same as apreq_quote() except when src begins and ends in quote marks. In - * that case it assumes src is quoted correctly, and just copies src to dest. - * - * @param dest Location of quoted copy. Must be large enough to hold the copy - * and trailing null byte. - * @param src Original string. - * @param slen Length of original string. - * @param dest Destination string. - * - * @return length of quoted copy in dest. - */ -APREQ_DECLARE(apr_size_t) apreq_quote_once(char *dest, const char *src, - const apr_size_t slen); - -/** - * Url-encodes a string. - * - * @param dest Location of url-encoded result string. Caller must ensure it - * is large enough to hold the encoded string and trailing '\\0'. - * @param src Original string. - * @param slen Length of original string. - * - * @return length of url-encoded string in dest; does not exceed 3 * slen. - */ -APREQ_DECLARE(apr_size_t) apreq_encode(char *dest, const char *src, - const apr_size_t slen); - -/** - * Convert a string from cp1252 to utf8. Caller must ensure it is large enough - * to hold the encoded string and trailing '\\0'. - * - * @param dest Location of utf8-encoded result string. Caller must ensure it - * is large enough to hold the encoded string and trailing '\\0'. - * @param src Original string. - * @param slen Length of original string. - * - * @return length of utf8-encoded string in dest; does not exceed 3 * slen. - */ -APREQ_DECLARE(apr_size_t) apreq_cp1252_to_utf8(char *dest, - const char *src, apr_size_t slen); - -/** - * Heuristically determine the charset of a string. - * - * @param src String to scan. - * @param slen Length of string. - * - * @return APREQ_CHARSET_ASCII if the string contains only 7-bit chars; - * @return APREQ_CHARSET_UTF8 if the string is a valid utf8 byte sequence; - * @return APREQ_CHARSET_LATIN1 if the string has no control chars; - * @return APREQ_CHARSET_CP1252 if the string has control chars. - */ -APREQ_DECLARE(apreq_charset_t) apreq_charset_divine(const char *src, - apr_size_t slen); - -/** - * Url-decodes a string. - * - * @param dest Location of url-encoded result string. Caller must ensure dest is - * large enough to hold the encoded string and trailing null character. - * @param dlen points to resultant length of url-decoded string in dest - * @param src Original string. - * @param slen Length of original string. - * - * @return APR_SUCCESS. - * @return APR_INCOMPLETE if the string - * ends in the middle of an escape sequence. - * @return ::APREQ_ERROR_BADSEQ or ::APREQ_ERROR_BADCHAR on malformed input. - * - * @remarks In the non-success case, dlen will be set to include - * the last successfully 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 successfully decoded value. This function decodes - * \%uXXXX into a utf8 (wide) character, following ECMA-262 - * (the Javascript spec) Section B.2.1. - */ - -APREQ_DECLARE(apr_status_t) apreq_decodev(char *dest, apr_size_t *dlen, - struct iovec *v, int nelts); - -/** - * Returns an url-encoded copy of a string. - * - * @param p Pool used to allocate the return value. - * @param src Original string. - * @param slen Length of original string. - * - * @return The url-encoded string. - * - * @remarks Use this function insead of apreq_encode if its - * caller might otherwise overflow dest. - */ -static APR_INLINE -char *apreq_escape(apr_pool_t *p, const char *src, const apr_size_t slen) -{ - char *rv; - - if (src == NULL) - return NULL; - - rv = (char *)apr_palloc(p, 3 * slen + 1); - apreq_encode(rv, src, slen); - return rv; -} - -/** - * An \e in-situ url-decoder. - * - * @param str The string to decode - * - * @return Length of decoded string, or < 0 on error. - */ -static APR_INLINE apr_ssize_t apreq_unescape(char *str) -{ - apr_size_t len; - apr_status_t rv = apreq_decode(str, &len, str, strlen(str)); - if (rv == APR_SUCCESS) - return (apr_ssize_t)len; - else - return -1; -} - -/** - * Converts file sizes (KMG) to bytes - * - * @param s file size matching m/^\\d+[KMG]b?$/i - * - * @return 64-bit integer representation of s. - * - * @todo What happens when s is malformed? Should this return - * an unsigned value instead? - */ - -APREQ_DECLARE(apr_int64_t) apreq_atoi64f(const char *s); - -/** - * Converts time strings (YMDhms) to seconds - * - * @param s time string matching m/^\\+?\\d+[YMDhms]$/ - * - * @return 64-bit integer representation of s as seconds. - * - * @todo What happens when s is malformed? Should this return - * an unsigned value instead? - */ - -APREQ_DECLARE(apr_int64_t) apreq_atoi64t(const char *s); - -/** - * Writes brigade to a file. - * - * @param f File that gets the brigade. - * @param wlen On a successful return, wlen holds the length of - * the brigade, which is the amount of data written to - * the file. - * @param bb Bucket brigade. - * - * @return APR_SUCCESS. - * @return Error status code from either an unsuccessful apr_bucket_read(), - * or a failed apr_file_writev(). - * - * @remarks This function leaks a bucket brigade into bb->p whenever - * the final bucket in bb is a spool bucket. - */ - -APREQ_DECLARE(apr_status_t) apreq_brigade_fwrite(apr_file_t *f, - apr_off_t *wlen, - apr_bucket_brigade *bb); -/** - * Makes a temporary file. - * - * @param fp Points to the temporary apr_file_t on success. - * @param pool Pool to associate with the temp file. When the - * pool is destroyed, the temp file will be closed - * and deleted. - * @param path The base directory which will contain the temp file. - * If param == NULL, the directory will be selected via - * tempnam(). See the tempnam manpage for details. - * - * @return APR_SUCCESS. - * @return Error status code from unsuccessful apr_filepath_merge(), - * or a failed apr_file_mktemp(). - */ - -APREQ_DECLARE(apr_status_t) apreq_file_mktemp(apr_file_t **fp, - apr_pool_t *pool, - const char *path); - -/** - * Set aside all buckets in the brigade. - * - * @param bb Brigade. - * @param p Setaside buckets into this pool. - * @return APR_SUCCESS. - * @return Error status code from an unsuccessful apr_bucket_setaside(). - */ - -static APR_INLINE -apr_status_t apreq_brigade_setaside(apr_bucket_brigade *bb, apr_pool_t *p) -{ - apr_bucket *e; - for (e = APR_BRIGADE_FIRST(bb); e != APR_BRIGADE_SENTINEL(bb); - e = APR_BUCKET_NEXT(e)) - { - apr_status_t rv = apr_bucket_setaside(e, p); - if (rv != APR_SUCCESS) - return rv; - } - return APR_SUCCESS; -} - - -/** - * Copy a brigade. - * - * @param d (destination) Copied buckets are appended to this brigade. - * @param s (source) Brigade to copy from. - * - * @return APR_SUCCESS. - * @return Error status code from an unsuccessful apr_bucket_copy(). - * - * @remarks s == d produces Undefined Behavior. - */ - -static APR_INLINE -apr_status_t apreq_brigade_copy(apr_bucket_brigade *d, apr_bucket_brigade *s) { - apr_bucket *e; - for (e = APR_BRIGADE_FIRST(s); e != APR_BRIGADE_SENTINEL(s); - e = APR_BUCKET_NEXT(e)) - { - apr_bucket *c; - apr_status_t rv = apr_bucket_copy(e, &c); - if (rv != APR_SUCCESS) - return rv; - - APR_BRIGADE_INSERT_TAIL(d, c); - } - return APR_SUCCESS; -} - -/** - * Move the front of a brigade. - * - * @param d (destination) Append buckets to this brigade. - * @param s (source) Brigade to take buckets from. - * @param e First bucket of s after the move. All buckets - * before e are appended to d. - * - * @remarks This moves all buckets when e == APR_BRIGADE_SENTINEL(s). - */ - -static APR_INLINE -void apreq_brigade_move(apr_bucket_brigade *d, apr_bucket_brigade *s, - apr_bucket *e) -{ - apr_bucket *f; - - if (e != APR_BRIGADE_SENTINEL(s)) { - f = APR_RING_FIRST(&s->list); - if (f == e) /* zero buckets to be moved */ - return; - - /* obtain the last bucket to be moved */ - e = APR_RING_PREV(e, link); - - APR_RING_UNSPLICE(f, e, link); - APR_RING_SPLICE_HEAD(&d->list, f, e, apr_bucket, link); - } - else { - APR_BRIGADE_CONCAT(d, s); - } -} - - -/** - * Search a header string for the value of a particular named attribute. - * - * @param hdr Header string to scan. - * @param name Name of attribute to search for. - * @param nlen Length of name. - * @param val Location of (first) matching value. - * @param vlen Length of matching value. - * - * @return APR_SUCCESS. - * @return ::APREQ_ERROR_NOATTR if the attribute is not found. - * @return ::APREQ_ERROR_BADSEQ if an unpaired quote mark was detected. - */ -APREQ_DECLARE(apr_status_t) apreq_header_attribute(const char *hdr, - const char *name, - const apr_size_t nlen, - const char **val, - apr_size_t *vlen); - - -/** - * Concatenates the brigades, spooling large brigades into - * a tempfile (APREQ_SPOOL) bucket. - * - * @param pool Pool for creating a tempfile bucket. - * @param temp_dir Directory for tempfile creation. - * @param brigade_limit If out's length would exceed this value, - * the appended buckets get written to a tempfile. - * @param out Resulting brigade. - * @param in Brigade to append. - * - * @return APR_SUCCESS. - * @return Error status code resulting from either apr_brigade_length(), - * apreq_file_mktemp(), apreq_brigade_fwrite(), or apr_file_seek(). - * - * @todo Flesh out these error codes, making them as explicit as possible. - */ -APREQ_DECLARE(apr_status_t) apreq_brigade_concat(apr_pool_t *pool, - const char *temp_dir, - apr_size_t brigade_limit, - apr_bucket_brigade *out, - apr_bucket_brigade *in); - -/** - * Determines the spool file used by the brigade. Returns NULL if the - * brigade is not spooled in a file (does not use an APREQ_SPOOL - * bucket). - * - * @param bb the bucket brigade - * @return the spool file, or NULL. - */ -APREQ_DECLARE(apr_file_t *) apreq_brigade_spoolfile(apr_bucket_brigade *bb); - -#ifdef __cplusplus - } -#endif - -#endif /* APREQ_UTIL_H */ diff --git a/modules/apreq/Makefile.in b/modules/apreq/Makefile.in deleted file mode 100644 index f34af9cbd66..00000000000 --- a/modules/apreq/Makefile.in +++ /dev/null @@ -1 +0,0 @@ -include $(top_srcdir)/build/special.mk diff --git a/modules/apreq/NWGNUmakefile b/modules/apreq/NWGNUmakefile deleted file mode 100644 index 40a716e9d2f..00000000000 --- a/modules/apreq/NWGNUmakefile +++ /dev/null @@ -1,250 +0,0 @@ -# -# Make sure all needed macro's are defined -# - -# -# Get the 'head' of the build environment if necessary. This includes default -# targets and paths to tools -# - -ifndef EnvironmentDefined -include $(AP_WORK)/build/NWGNUhead.inc -endif - -# -# These directories will be at the beginning of the include list, followed by -# INCDIRS -# -XINCDIRS += \ - $(APR)/include \ - $(APRUTIL)/include \ - $(SRC)/include \ - $(NWOS) \ - $(EOLIST) - -# -# These flags will come after CFLAGS -# -XCFLAGS += \ - $(EOLIST) - -# -# These defines will come after DEFINES -# -XDEFINES += \ - $(EOLIST) - -# -# These flags will be added to the link.opt file -# -XLFLAGS += \ - $(EOLIST) - -# -# These values will be appended to the correct variables based on the value of -# RELEASE -# -ifeq "$(RELEASE)" "debug" -XINCDIRS += \ - $(EOLIST) - -XCFLAGS += \ - $(EOLIST) - -XDEFINES += \ - $(EOLIST) - -XLFLAGS += \ - $(EOLIST) -endif - -ifeq "$(RELEASE)" "noopt" -XINCDIRS += \ - $(EOLIST) - -XCFLAGS += \ - $(EOLIST) - -XDEFINES += \ - $(EOLIST) - -XLFLAGS += \ - $(EOLIST) -endif - -ifeq "$(RELEASE)" "release" -XINCDIRS += \ - $(EOLIST) - -XCFLAGS += \ - $(EOLIST) - -XDEFINES += \ - $(EOLIST) - -XLFLAGS += \ - $(EOLIST) -endif - -# -# These are used by the link target if an NLM is being generated -# This is used by the link 'name' directive to name the nlm. If left blank -# TARGET_nlm (see below) will be used. -# -NLM_NAME = mod_apreq - -# -# This is used by the link '-desc ' directive. -# If left blank, NLM_NAME will be used. -# -NLM_DESCRIPTION = Apache $(VERSION_STR) Request Filter Module - -# -# This is used by the '-threadname' directive. If left blank, -# NLM_NAME Thread will be used. -# -NLM_THREAD_NAME = apreq Module - -# -# If this is specified, it will override VERSION value in -# $(AP_WORK)/build/NWGNUenvironment.inc -# -NLM_VERSION = - -# -# If this is specified, it will override the default of 64K -# -NLM_STACK_SIZE = 8192 - - -# -# If this is specified it will be used by the link '-entry' directive -# -NLM_ENTRY_SYM = - -# -# If this is specified it will be used by the link '-exit' directive -# -NLM_EXIT_SYM = - -# -# If this is specified it will be used by the link '-check' directive -# -NLM_CHECK_SYM = - -# -# If these are specified it will be used by the link '-flags' directive -# -NLM_FLAGS = - -# -# If this is specified it will be linked in with the XDCData option in the def -# file instead of the default of $(NWOS)/apache.xdc. XDCData can be disabled -# by setting APACHE_UNIPROC in the environment -# -XDCDATA = - -# -# If there is an NLM target, put it here -# -TARGET_nlm = \ - $(OBJDIR)/$(NLM_NAME).nlm \ - $(EOLIST) - -# -# If there is an LIB target, put it here -# -TARGET_lib = \ - $(EOLIST) - -# -# These are the OBJ files needed to create the NLM target above. -# Paths must all use the '/' character -# -FILES_nlm_objs = \ - $(OBJDIR)/filter.o \ - $(OBJDIR)/handle.o \ - $(EOLIST) - -# -# These are the LIB files needed to create the NLM target above. -# These will be added as a library command in the link.opt file. -# -FILES_nlm_libs = \ - $(PRELUDE) \ - $(EOLIST) - -# -# These are the modules that the above NLM target depends on to load. -# These will be added as a module command in the link.opt file. -# -FILES_nlm_modules = \ - aprlib \ - libc \ - $(EOLIST) - -# -# If the nlm has a msg file, put it's path here -# -FILE_nlm_msg = - -# -# If the nlm has a hlp file put it's path here -# -FILE_nlm_hlp = - -# -# If this is specified, it will override $(NWOS)\copyright.txt. -# -FILE_nlm_copyright = - -# -# Any additional imports go here -# -FILES_nlm_Ximports = \ - @aprlib.imp \ - @httpd.imp \ - @libc.imp \ - $(EOLIST) - -# -# Any symbols exported to here -# -FILES_nlm_exports = \ - apreq_module \ - $(EOLIST) - -# -# These are the OBJ files needed to create the LIB target above. -# Paths must all use the '/' character -# -FILES_lib_objs = \ - $(EOLIST) - -# -# implement targets and dependencies (leave this section alone) -# - -libs :: $(OBJDIR) $(TARGET_lib) - -nlms :: libs $(TARGET_nlm) - -# -# Updated this target to create necessary directories and copy files to the -# correct place. (See $(AP_WORK)/build/NWGNUhead.inc for examples) -# -install :: nlms FORCE - $(call COPY,$(OBJDIR)/*.nlm, $(INSTALLBASE)/modules/) - -# -# Any specialized rules here -# - -# -# Include the 'tail' makefile that has targets that depend on variables defined -# in this makefile -# - -include $(APBUILD)/NWGNUtail.inc - - diff --git a/modules/apreq/apreq_module_apache2.h b/modules/apreq/apreq_module_apache2.h deleted file mode 100644 index a0c0b909b68..00000000000 --- a/modules/apreq/apreq_module_apache2.h +++ /dev/null @@ -1,182 +0,0 @@ -/* -** Licensed to the Apache Software Foundation (ASF) under one or more -** contributor license agreements. See the NOTICE file distributed with -** this work for additional information regarding copyright ownership. -** The ASF licenses this file to You under the Apache License, Version 2.0 -** (the "License"); you may not use this file except in compliance with -** the License. You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#ifndef APREQ_APACHE2_H -#define APREQ_APACHE2_H - -#include "apreq_module.h" -#include "apr_optional.h" -#include - -#ifdef __cplusplus - extern "C" { -#endif - - -/** - * @defgroup mod_apreq2 Apache 2.X Filter Module - * @ingroup APACHE_MODS - * @brief mod_apreq2 - DSO that ties libapreq2 to Apache HTTPD 2.X. - * - * mod_apreq2 provides the "APREQ2" input filter for using libapreq2 - * (and allow its parsed data structures to be shared) within - * the Apache 2.X webserver. Using it, libapreq2 works properly - * in every phase of the HTTP request, from translation handlers - * to output filters, and even for subrequests / internal redirects. - * - *
- * - *

Activating mod_apreq2 in Apache 2.X

- * - * The installation process triggered by - * % make install - * will not modify your webserver's config file. Hence, - * be sure you activate it on startup by adding a LoadModule directive - * to your webserver config; e.g. - * - * @code - * - * LoadModule apreq_module modules/mod_apreq2.so - * - * @endcode - * - * The mod_apreq2 filter is named "apreq2", and may be used in Apache's - * input filter directives, e.g. - * @code - * - * AddInputFilter apreq2 # or - * SetInputFilter apreq2 - * - * @endcode - * - * However, this is not required because libapreq2 will add the filter (only) - * if it's necessary. You just need to ensure that your module invokes - * apreq_handle_apache2() before the content handler ultimately reads - * from the input filter chain. It is important to realize that no - * matter how the input filters are initially arranged, the APREQ2 filter - * will attempt to reposition itself to be the last input filter to read the - * data. - * - * If you want to use other input filters to transform the incoming HTTP - * request data, is important to register those filters with Apache - * as having type AP_FTYPE_CONTENT_SET or AP_FTYPE_RESOURCE. Due to the - * limitations of Apache's current input filter design, types higher than - * AP_FTYPE_CONTENT_SET may not work properly whenever the apreq filter is - * active. - * - * This is especially true when a content handler uses libapreq2 to parse - * some of the post data before doing an internal redirect. Any input - * filter subsequently added to the redirected request will bypass the - * original apreq filter (and therefore lose access to some of the original - * post data), unless its type is less than the type of the apreq filter - * (currently AP_FTYPE_PROTOCOL-1). - * - * - *

Server Configuration Directives

- * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
Per-directory commands for mod_apreq2
DirectiveContextDefaultDescription
APREQ2_ReadLimitdirectory #APREQ_DEFAULT_READ_LIMIT Maximum number of bytes mod_apreq2 will send off to libapreq2 - * for parsing. mod_apreq2 will log this event and subsequently - * remove itself from the filter chain. - *
APREQ2_BrigadeLimitdirectory#APREQ_DEFAULT_BRIGADE_LIMIT Maximum number of bytes mod_apreq2 will let accumulate - * within the heap-buckets in a brigade. Excess data will be - * spooled to an appended file bucket. - *
APREQ2_TempDirdirectoryNULL Sets the location of the temporary directory apreq will use to spool - * overflow brigade data (based on the APREQ2_BrigadeLimit setting). - * If left unset, libapreq2 will select a platform-specific location - * via apr_temp_dir_get(). - *
- * - *

Implementation Details

- *
- *   XXX apreq as a normal input filter
- *   XXX apreq as a "virtual" content handler.
- *   XXX apreq as a transparent "tee".
- *   XXX apreq parser registration in post_config
- * 
- * - * @{ - */ -/** - * Create an apreq handle which communicates with an Apache 2.X - * request_rec. - */ -APREQ_DECLARE(apreq_handle_t *) apreq_handle_apache2(request_rec *r); - -/** - * - * - */ -#ifdef WIN32 -typedef __declspec(dllexport) apreq_handle_t * -(__stdcall apr_OFN_apreq_handle_apache2_t) (request_rec *r); -#else -APR_DECLARE_OPTIONAL_FN(APREQ_DECLARE(apreq_handle_t *), - apreq_handle_apache2, (request_rec *r)); -#endif - -/** - * The mod_apreq2 filter is named "apreq2", and may be used in Apache's - * input filter directives, e.g. - * @code - * - * AddInputFilter apreq2 # or - * SetInputFilter apreq2 - * @endcode - * See above - */ -#define APREQ_FILTER_NAME "apreq2" - -/** - * The Apache2 Module Magic Number for use in the Apache 2.x module structures - * This gets bumped if changes in th4e API will break third party applications - * using this apache2 module - * @see APREQ_MODULE - */ -#define APREQ_APACHE2_MMN 20101207 - -/** @} */ - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/modules/apreq/apreq_private_apache2.h b/modules/apreq/apreq_private_apache2.h deleted file mode 100644 index 173060dc48c..00000000000 --- a/modules/apreq/apreq_private_apache2.h +++ /dev/null @@ -1,56 +0,0 @@ -extern module AP_MODULE_DECLARE_DATA apreq_module; - -struct dir_config { - const char *temp_dir; - apr_uint64_t read_limit; - apr_size_t brigade_limit; -}; - -/* The "warehouse", stored in r->request_config */ -struct apache2_handle { - apreq_handle_t handle; - request_rec *r; - apr_table_t *jar, *args; - apr_status_t jar_status, args_status; - ap_filter_t *f; -}; - -/* Tracks the apreq filter state */ -struct filter_ctx { - apr_bucket_brigade *bb; /* input brigade that's passed to the parser */ - apr_bucket_brigade *bbtmp; /* temporary copy of bb, destined for the spool */ - apr_bucket_brigade *spool; /* copied prefetch data for downstream filters */ - apreq_parser_t *parser; - apreq_hook_t *hook_queue; - apreq_hook_t *find_param; - apr_table_t *body; - apr_status_t body_status; - apr_status_t filter_error; - apr_uint64_t bytes_read; /* Total bytes read into this filter. */ - apr_uint64_t read_limit; /* Max bytes the filter may show to parser */ - apr_size_t brigade_limit; - const char *temp_dir; -}; - -apr_status_t apreq_filter_prefetch(ap_filter_t *f, apr_off_t readbytes); -apr_status_t apreq_filter(ap_filter_t *f, - apr_bucket_brigade *bb, - ap_input_mode_t mode, - apr_read_type_e block, - apr_off_t readbytes); - -void apreq_filter_make_context(ap_filter_t *f); -void apreq_filter_init_context(ap_filter_t *f); - -APR_INLINE -static void apreq_filter_relocate(ap_filter_t *f) -{ - request_rec *r = f->r; - - if (f != r->input_filters) { - ap_filter_t *top = r->input_filters; - ap_remove_input_filter(f); - r->input_filters = f; - f->next = top; - } -} diff --git a/modules/apreq/config.m4 b/modules/apreq/config.m4 deleted file mode 100644 index a61c4231b09..00000000000 --- a/modules/apreq/config.m4 +++ /dev/null @@ -1,9 +0,0 @@ -dnl modules enabled in this directory by default - -dnl APACHE_MODULE(name, helptext[, objects[, structname[, default[, config]]]]) - -APACHE_MODPATH_INIT(apreq) - -APACHE_MODULE(apreq, Apache Request Filter, filter.lo handle.lo, , most) - -APACHE_MODPATH_FINISH diff --git a/modules/apreq/filter.c b/modules/apreq/filter.c deleted file mode 100644 index b4a1a4ebac7..00000000000 --- a/modules/apreq/filter.c +++ /dev/null @@ -1,532 +0,0 @@ -/* -** Licensed to the Apache Software Foundation (ASF) under one or more -** contributor license agreements. See the NOTICE file distributed with -** this work for additional information regarding copyright ownership. -** The ASF licenses this file to You under the Apache License, Version 2.0 -** (the "License"); you may not use this file except in compliance with -** the License. You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#include "httpd.h" -#include "http_config.h" -#include "http_log.h" -#include "util_filter.h" -#include "apr_tables.h" -#include "apr_buckets.h" -#include "http_request.h" -#include "apr_strings.h" - -#include "apreq_module_apache2.h" -#include "apreq_private_apache2.h" -#include "apreq_error.h" -#include "apreq_util.h" - -static void *apreq_create_dir_config(apr_pool_t *p, char *d) -{ - /* d == OR_ALL */ - struct dir_config *dc = apr_palloc(p, sizeof *dc); - dc->temp_dir = NULL; - dc->read_limit = -1; - dc->brigade_limit = -1; - return dc; -} - -static void *apreq_merge_dir_config(apr_pool_t *p, void *a_, void *b_) -{ - struct dir_config *a = a_, *b = b_, *c = apr_palloc(p, sizeof *c); - - c->temp_dir = (b->temp_dir != NULL) /* overrides ok */ - ? b->temp_dir : a->temp_dir; - - c->brigade_limit = (b->brigade_limit == (apr_size_t)-1) /* overrides ok */ - ? a->brigade_limit : b->brigade_limit; - - c->read_limit = (b->read_limit < a->read_limit) /* yes, min */ - ? b->read_limit : a->read_limit; - - return c; -} - -static const char *apreq_set_temp_dir(cmd_parms *cmd, void *data, - const char *arg) -{ - struct dir_config *conf = data; - const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT); - - if (err != NULL) - return err; - - conf->temp_dir = arg; - return NULL; -} - -static const char *apreq_set_read_limit(cmd_parms *cmd, void *data, - const char *arg) -{ - struct dir_config *conf = data; - const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT); - - if (err != NULL) - return err; - - conf->read_limit = apreq_atoi64f(arg); - return NULL; -} - -static const char *apreq_set_brigade_limit(cmd_parms *cmd, void *data, - const char *arg) -{ - struct dir_config *conf = data; - const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT); - - if (err != NULL) - return err; - - conf->brigade_limit = apreq_atoi64f(arg); - return NULL; -} - - -static const command_rec apreq_cmds[] = -{ - AP_INIT_TAKE1("APREQ2_TempDir", apreq_set_temp_dir, NULL, OR_ALL, - "Default location of temporary directory"), - AP_INIT_TAKE1("APREQ2_ReadLimit", apreq_set_read_limit, NULL, OR_ALL, - "Maximum amount of data that will be fed into a parser."), - AP_INIT_TAKE1("APREQ2_BrigadeLimit", apreq_set_brigade_limit, NULL, OR_ALL, - "Maximum in-memory bytes a brigade may use."), - { NULL } -}; - - -void apreq_filter_init_context(ap_filter_t *f) -{ - request_rec *r = f->r; - struct filter_ctx *ctx = f->ctx; - apr_bucket_alloc_t *ba = r->connection->bucket_alloc; - const char *cl_header; - - if (r->method_number == M_GET) { - /* Don't parse GET (this protects against subrequest body parsing). */ - ctx->body_status = APREQ_ERROR_NODATA; - return; - } - - cl_header = apr_table_get(r->headers_in, "Content-Length"); - if (cl_header != NULL) { - apr_off_t cl; - - if (!ap_parse_strict_length(&cl, cl_header)) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, r, APLOGNO(02045) - "Invalid Content-Length header (%s)", cl_header); - ctx->body_status = APREQ_ERROR_BADHEADER; - return; - } - if ((apr_uint64_t)cl > ctx->read_limit) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_EGENERAL, r, APLOGNO(02046) - "Content-Length header (%s) exceeds configured " - "max_body limit (%" APR_UINT64_T_FMT ")", - cl_header, ctx->read_limit); - ctx->body_status = APREQ_ERROR_OVERLIMIT; - return; - } - } - - if (ctx->parser == NULL) { - const char *ct_header = apr_table_get(r->headers_in, "Content-Type"); - - if (ct_header != NULL) { - apreq_parser_function_t pf = apreq_parser(ct_header); - - if (pf != NULL) { - ctx->parser = apreq_parser_make(r->pool, ba, ct_header, pf, - ctx->brigade_limit, - ctx->temp_dir, - ctx->hook_queue, - NULL); - } - else { - ctx->body_status = APREQ_ERROR_NOPARSER; - return; - } - } - else { - ctx->body_status = APREQ_ERROR_NOHEADER; - return; - } - } - else { - if (ctx->parser->brigade_limit > ctx->brigade_limit) - ctx->parser->brigade_limit = ctx->brigade_limit; - if (ctx->temp_dir != NULL) - ctx->parser->temp_dir = ctx->temp_dir; - if (ctx->hook_queue != NULL) - apreq_parser_add_hook(ctx->parser, ctx->hook_queue); - } - - ctx->hook_queue = NULL; - ctx->bb = apr_brigade_create(r->pool, ba); - ctx->bbtmp = apr_brigade_create(r->pool, ba); - ctx->spool = apr_brigade_create(r->pool, ba); - ctx->body = apr_table_make(r->pool, APREQ_DEFAULT_NELTS); - ctx->body_status = APR_INCOMPLETE; -} - - -/* - * Situations to contend with: - * - * 1) Often the filter will be added by the content handler itself, - * so the apreq_filter_init hook will not be run. - * 2) If an auth handler uses apreq, the apreq_filter will ensure - * it's part of the protocol filters. apreq_filter_init does NOT need - * to notify the protocol filter that it must not continue parsing, - * the apreq filter can perform this check itself. apreq_filter_init - * just needs to ensure cfg->f does not point at it. - * 3) If req->proto_input_filters and req->input_filters are apreq - * filters, and req->input_filters->next == req->proto_input_filters, - * it is safe for apreq_filter to "steal" the proto filter's context - * and subsequently drop it from the chain. - */ - - -/* Examines the input_filter chain and moves the apreq filter(s) around - * before the filter chain is stacked by ap_get_brigade. - */ - - -static apr_status_t apreq_filter_init(ap_filter_t *f) -{ - request_rec *r = f->r; - struct filter_ctx *ctx = f->ctx; - struct apache2_handle *handle = - (struct apache2_handle *)apreq_handle_apache2(r); - - /* Don't parse GET (this protects against subrequest body parsing). */ - if (f->r->method_number == M_GET) - return APR_SUCCESS; - - if (ctx == NULL || ctx->body_status == APR_EINIT) { - if (f == r->input_filters) { - handle->f = f; - } - else if (r->input_filters->frec->filter_func.in_func == apreq_filter) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, APLOGNO(02047) - "removing intermediate apreq filter"); - if (handle->f == f) - handle->f = r->input_filters; - ap_remove_input_filter(f); - } - else { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, APLOGNO(02048) - "relocating intermediate apreq filter"); - apreq_filter_relocate(f); - handle->f = f; - } - return APR_SUCCESS; - } - - /* else this is a protocol filter which may still be active. - * if it is, we must deregister it now. - */ - if (handle->f == f) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, APLOGNO(02049) - "disabling stale protocol filter"); - if (ctx->body_status == APR_INCOMPLETE) - ctx->body_status = APREQ_ERROR_INTERRUPT; - handle->f = NULL; - } - return APR_SUCCESS; -} - - - -apr_status_t apreq_filter_prefetch(ap_filter_t *f, apr_off_t readbytes) -{ - struct filter_ctx *ctx = f->ctx; - request_rec *r = f->r; - apr_status_t rv; - apr_off_t len; - - if (ctx->body_status == APR_EINIT) - apreq_filter_init_context(f); - - if (ctx->body_status != APR_INCOMPLETE || readbytes == 0) - return ctx->body_status; - - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, APLOGNO(02050) - "prefetching %" APR_OFF_T_FMT " bytes", readbytes); - - rv = ap_get_brigade(f->next, ctx->bb, AP_MODE_READBYTES, - APR_BLOCK_READ, readbytes); - - if (rv != APR_SUCCESS) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(02051) - "ap_get_brigade failed during prefetch"); - ctx->filter_error = rv; - return ctx->body_status = APREQ_ERROR_GENERAL; - } - - apreq_brigade_setaside(ctx->bb, r->pool); - apreq_brigade_copy(ctx->bbtmp, ctx->bb); - - rv = apreq_brigade_concat(r->pool, ctx->temp_dir, ctx->brigade_limit, - ctx->spool, ctx->bbtmp); - if (rv != APR_SUCCESS && rv != APR_EOF) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, APLOGNO(02052) - "apreq_brigade_concat failed; TempDir problem?"); - ctx->filter_error = APR_EGENERAL; - return ctx->body_status = rv; - } - - /* Adding "f" to the protocol filter chain ensures the - * spooled data is preserved across internal redirects. - */ - - if (f != r->proto_input_filters) { - ap_filter_t *in; - for (in = r->input_filters; in != r->proto_input_filters; - in = in->next) - { - if (f == in) { - r->proto_input_filters = f; - break; - } - } - } - - apr_brigade_length(ctx->bb, 1, &len); - ctx->bytes_read += len; - - if (ctx->bytes_read > ctx->read_limit) { - ctx->body_status = APREQ_ERROR_OVERLIMIT; - ap_log_rerror(APLOG_MARK, APLOG_ERR, ctx->body_status, r, APLOGNO(02053) - "Bytes read (%" APR_UINT64_T_FMT - ") exceeds configured read limit (%" APR_UINT64_T_FMT ")", - ctx->bytes_read, ctx->read_limit); - return ctx->body_status; - } - - ctx->body_status = apreq_parser_run(ctx->parser, ctx->body, ctx->bb); - apr_brigade_cleanup(ctx->bb); - - return ctx->body_status; -} - - - -apr_status_t apreq_filter(ap_filter_t *f, - apr_bucket_brigade *bb, - ap_input_mode_t mode, - apr_read_type_e block, - apr_off_t readbytes) -{ - request_rec *r = f->r; - struct filter_ctx *ctx; - apr_status_t rv; - apr_off_t len; - - switch (mode) { - case AP_MODE_READBYTES: - /* only the modes above are supported */ - break; - - case AP_MODE_EXHAUSTIVE: /* not worth supporting at this level */ - case AP_MODE_GETLINE: /* chunked trailers are b0rked in ap_http_filter */ - return ap_get_brigade(f->next, bb, mode, block, readbytes); - - default: - return APR_ENOTIMPL; - } - - if (f->ctx == NULL) - apreq_filter_make_context(f); - - ctx = f->ctx; - - if (ctx->body_status == APR_EINIT) - apreq_filter_init_context(f); - - if (ctx->spool && !APR_BRIGADE_EMPTY(ctx->spool)) { - apr_bucket *e; - rv = apr_brigade_partition(ctx->spool, readbytes, &e); - if (rv != APR_SUCCESS && rv != APR_INCOMPLETE) - return rv; - - if (APR_BUCKET_IS_EOS(e)) - e = APR_BUCKET_NEXT(e); - - apreq_brigade_move(bb, ctx->spool, e); - return APR_SUCCESS; - } - else if (ctx->body_status != APR_INCOMPLETE) { - if (ctx->filter_error) - return ctx->filter_error; - - rv = ap_get_brigade(f->next, bb, mode, block, readbytes); - ap_remove_input_filter(f); - return rv; - } - - - rv = ap_get_brigade(f->next, bb, mode, block, readbytes); - if (rv != APR_SUCCESS) - return rv; - - apreq_brigade_copy(ctx->bb, bb); - apr_brigade_length(bb, 1, &len); - ctx->bytes_read += len; - - if (ctx->bytes_read > ctx->read_limit) { - ctx->body_status = APREQ_ERROR_OVERLIMIT; - ap_log_rerror(APLOG_MARK, APLOG_ERR, ctx->body_status, r, APLOGNO(02054) - "Bytes read (%" APR_UINT64_T_FMT - ") exceeds configured max_body limit (%" - APR_UINT64_T_FMT ")", - ctx->bytes_read, ctx->read_limit); - } - else { - ctx->body_status = apreq_parser_run(ctx->parser, ctx->body, ctx->bb); - apr_brigade_cleanup(ctx->bb); - } - return APR_SUCCESS; -} - - -static int apreq_pre_init(apr_pool_t *p, apr_pool_t *plog, - apr_pool_t *ptemp, server_rec *base_server) -{ - apr_status_t status; - - status = apreq_pre_initialize(p); - if (status != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_STARTUP|APLOG_ERR, status, base_server, APLOGNO(02055) - "Failed to pre-initialize libapreq2"); - return HTTP_INTERNAL_SERVER_ERROR; - } - APR_REGISTER_OPTIONAL_FN(apreq_handle_apache2); - return OK; -} - -static int apreq_post_init(apr_pool_t *p, apr_pool_t *plog, - apr_pool_t *ptemp, server_rec *base_server) -{ - apr_status_t status; - - status = apreq_post_initialize(p); - if (status != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_STARTUP|APLOG_ERR, status, base_server, APLOGNO(02056) - "Failed to post-initialize libapreq2"); - return HTTP_INTERNAL_SERVER_ERROR; - } - return OK; -} - -static void register_hooks (apr_pool_t *p) -{ - /* APR_HOOK_FIRST because we want other modules to be able to - * register parsers in their post_config hook via APR_HOOK_MIDDLE. - */ - ap_hook_post_config(apreq_pre_init, NULL, NULL, APR_HOOK_FIRST); - - /* APR_HOOK_LAST because we need to lock the default_parsers hash - * (to prevent further modifications) before the server forks. - */ - ap_hook_post_config(apreq_post_init, NULL, NULL, APR_HOOK_LAST); - - ap_register_input_filter(APREQ_FILTER_NAME, apreq_filter, apreq_filter_init, - AP_FTYPE_PROTOCOL-1); -} - - - -/** @} */ - - -module AP_MODULE_DECLARE_DATA apreq_module = { -#line __LINE__ "mod_apreq2.c" - STANDARD20_MODULE_STUFF, - apreq_create_dir_config, - apreq_merge_dir_config, - NULL, - NULL, - apreq_cmds, - register_hooks, -}; - - -void apreq_filter_make_context(ap_filter_t *f) -{ - request_rec *r; - struct filter_ctx *ctx; - struct dir_config *d; - - r = f->r; - d = ap_get_module_config(r->per_dir_config, &apreq_module); - - if (f == r->input_filters - && r->proto_input_filters == f->next - && f->next->frec->filter_func.in_func == apreq_filter - && f->r->method_number != M_GET) - { - - ctx = f->next->ctx; - - switch (ctx->body_status) { - - case APREQ_ERROR_INTERRUPT: - ctx->body_status = APR_INCOMPLETE; - /* fall thru */ - - case APR_SUCCESS: - - if (d != NULL) { - ctx->temp_dir = d->temp_dir; - ctx->read_limit = d->read_limit; - ctx->brigade_limit = d->brigade_limit; - - if (ctx->parser != NULL) { - ctx->parser->temp_dir = d->temp_dir; - ctx->parser->brigade_limit = d->brigade_limit; - } - - } - - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, APLOGNO(02057) - "stealing filter context"); - f->ctx = ctx; - r->proto_input_filters = f; - ap_remove_input_filter(f->next); - - return; - - default: - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, ctx->body_status, r, APLOGNO(02058) - "cannot steal context: bad filter status"); - } - } - - ctx = apr_pcalloc(r->pool, sizeof *ctx); - ctx->body_status = APR_EINIT; - - if (d == NULL) { - ctx->read_limit = (apr_uint64_t)-1; - ctx->brigade_limit = APREQ_DEFAULT_BRIGADE_LIMIT; - } else { - ctx->temp_dir = d->temp_dir; - ctx->read_limit = (d->read_limit == (apr_uint64_t)-1) - ? APREQ_DEFAULT_READ_LIMIT : d->read_limit; - ctx->brigade_limit = (d->brigade_limit == (apr_size_t)-1) - ? APREQ_DEFAULT_BRIGADE_LIMIT : d->brigade_limit; - } - - f->ctx = ctx; -} diff --git a/modules/apreq/handle.c b/modules/apreq/handle.c deleted file mode 100644 index d6c73bf5232..00000000000 --- a/modules/apreq/handle.c +++ /dev/null @@ -1,440 +0,0 @@ -/* -** Licensed to the Apache Software Foundation (ASF) under one or more -** contributor license agreements. See the NOTICE file distributed with -** this work for additional information regarding copyright ownership. -** The ASF licenses this file to You under the Apache License, Version 2.0 -** (the "License"); you may not use this file except in compliance with -** the License. You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#include "httpd.h" -#include "http_config.h" -#include "http_log.h" -#include "util_filter.h" -#include "apr_tables.h" -#include "apr_buckets.h" -#include "http_request.h" -#include "apr_strings.h" - -#include "apreq_module_apache2.h" -#include "apreq_private_apache2.h" -#include "apreq_error.h" - - -APR_INLINE -static ap_filter_t *get_apreq_filter(apreq_handle_t *handle) -{ - struct apache2_handle *req = (struct apache2_handle *)handle; - - if (req->f == NULL) { - req->f = ap_add_input_filter(APREQ_FILTER_NAME, NULL, - req->r, - req->r->connection); - /* ap_add_input_filter does not guarantee cfg->f == r->input_filters, - * so we reposition the new filter there as necessary. - */ - apreq_filter_relocate(req->f); - } - - return req->f; -} - - -static apr_status_t apache2_jar(apreq_handle_t *handle, const apr_table_t **t) -{ - struct apache2_handle *req = (struct apache2_handle*)handle; - request_rec *r = req->r; - - if (req->jar_status == APR_EINIT) { - const char *cookies = apr_table_get(r->headers_in, "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 apache2_args(apreq_handle_t *handle, const apr_table_t **t) -{ - struct apache2_handle *req = (struct apache2_handle*)handle; - request_rec *r = req->r; - - if (req->args_status == APR_EINIT) { - if (r->args != NULL) { - req->args = apr_table_make(handle->pool, APREQ_DEFAULT_NELTS); - req->args_status = - apreq_parse_query_string(handle->pool, req->args, r->args); - } - else - req->args_status = APREQ_ERROR_NODATA; - } - - *t = req->args; - return req->args_status; -} - - - - -static apreq_cookie_t *apache2_jar_get(apreq_handle_t *handle, const char *name) -{ - struct apache2_handle *req = (struct apache2_handle *)handle; - const apr_table_t *t; - const char *val; - - if (req->jar_status == APR_EINIT) - apache2_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 *apache2_args_get(apreq_handle_t *handle, const char *name) -{ - struct apache2_handle *req = (struct apache2_handle *)handle; - const apr_table_t *t; - const char *val; - - if (req->args_status == APR_EINIT) - apache2_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 apache2_body(apreq_handle_t *handle, const apr_table_t **t) -{ - ap_filter_t *f = get_apreq_filter(handle); - struct filter_ctx *ctx; - - if (f->ctx == NULL) - apreq_filter_make_context(f); - - ctx = f->ctx; - - switch (ctx->body_status) { - - case APR_EINIT: - apreq_filter_init_context(f); - if (ctx->body_status != APR_INCOMPLETE) - break; - - case APR_INCOMPLETE: - while (apreq_filter_prefetch(f, APREQ_DEFAULT_READ_BLOCK_SIZE) == APR_INCOMPLETE) - ; /*loop*/ - } - - *t = ctx->body; - return ctx->body_status; -} - -static apreq_param_t *apache2_body_get(apreq_handle_t *handle, const char *name) -{ - ap_filter_t *f = get_apreq_filter(handle); - struct filter_ctx *ctx; - const char *val; - apreq_hook_t *h; - apreq_hook_find_param_ctx_t *hook_ctx; - - if (f->ctx == NULL) - apreq_filter_make_context(f); - - ctx = f->ctx; - - switch (ctx->body_status) { - - case APR_SUCCESS: - - val = apr_table_get(ctx->body, name); - if (val != NULL) - return apreq_value_to_param(val); - return NULL; - - - case APR_EINIT: - - apreq_filter_init_context(f); - if (ctx->body_status != APR_INCOMPLETE) - return NULL; - apreq_filter_prefetch(f, APREQ_DEFAULT_READ_BLOCK_SIZE); - - - case APR_INCOMPLETE: - - val = apr_table_get(ctx->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 */ - hook_ctx = apr_palloc(handle->pool, sizeof *hook_ctx); - - if (ctx->find_param == NULL) - ctx->find_param = apreq_hook_make(handle->pool, - apreq_hook_find_param, - NULL, NULL); - h = ctx->find_param; - h->next = ctx->parser->hook; - h->ctx = hook_ctx; - ctx->parser->hook = h; - hook_ctx->name = name; - hook_ctx->param = NULL; - hook_ctx->prev = ctx->parser->hook; - - do { - apreq_filter_prefetch(f, APREQ_DEFAULT_READ_BLOCK_SIZE); - if (hook_ctx->param != NULL) - return hook_ctx->param; - } while (ctx->body_status == APR_INCOMPLETE); - - ctx->parser->hook = h->next; - return NULL; - - - default: - - if (ctx->body == NULL) - return NULL; - - val = apr_table_get(ctx->body, name); - if (val != NULL) - return apreq_value_to_param(val); - return NULL; - - } - - /* not reached */ - return NULL; -} - -static -apr_status_t apache2_parser_get(apreq_handle_t *handle, - const apreq_parser_t **parser) -{ - ap_filter_t *f = get_apreq_filter(handle); - struct filter_ctx *ctx = f->ctx; - - if (ctx == NULL) { - *parser = NULL; - return APR_EINIT; - } - *parser = ctx->parser; - return APR_SUCCESS; -} - -static -apr_status_t apache2_parser_set(apreq_handle_t *handle, - apreq_parser_t *parser) -{ - ap_filter_t *f = get_apreq_filter(handle); - struct filter_ctx *ctx; - - if (f->ctx == NULL) - apreq_filter_make_context(f); - - ctx = f->ctx; - - if (ctx->parser == NULL) { - ctx->parser = parser; - return APR_SUCCESS; - } - else - return APREQ_ERROR_NOTEMPTY; -} - - - -static -apr_status_t apache2_hook_add(apreq_handle_t *handle, - apreq_hook_t *hook) -{ - ap_filter_t *f = get_apreq_filter(handle); - struct filter_ctx *ctx; - - if (f->ctx == NULL) - apreq_filter_make_context(f); - - ctx = f->ctx; - - if (ctx->parser != NULL) { - return apreq_parser_add_hook(ctx->parser, hook); - } - else if (ctx->hook_queue != NULL) { - apreq_hook_t *h = ctx->hook_queue; - while (h->next != NULL) - h = h->next; - h->next = hook; - } - else { - ctx->hook_queue = hook; - } - return APR_SUCCESS; - -} - -static -apr_status_t apache2_brigade_limit_set(apreq_handle_t *handle, - apr_size_t bytes) -{ - ap_filter_t *f = get_apreq_filter(handle); - struct filter_ctx *ctx; - - if (f->ctx == NULL) - apreq_filter_make_context(f); - - ctx = f->ctx; - - if (ctx->body_status == APR_EINIT || ctx->brigade_limit > bytes) { - ctx->brigade_limit = bytes; - return APR_SUCCESS; - } - - return APREQ_ERROR_MISMATCH; -} - -static -apr_status_t apache2_brigade_limit_get(apreq_handle_t *handle, - apr_size_t *bytes) -{ - ap_filter_t *f = get_apreq_filter(handle); - struct filter_ctx *ctx; - - if (f->ctx == NULL) - apreq_filter_make_context(f); - - ctx = f->ctx; - *bytes = ctx->brigade_limit; - return APR_SUCCESS; -} - -static -apr_status_t apache2_read_limit_set(apreq_handle_t *handle, - apr_uint64_t bytes) -{ - ap_filter_t *f = get_apreq_filter(handle); - struct filter_ctx *ctx; - - if (f->ctx == NULL) - apreq_filter_make_context(f); - - ctx = f->ctx; - - if (ctx->read_limit > bytes && ctx->bytes_read < bytes) { - ctx->read_limit = bytes; - return APR_SUCCESS; - } - - return APREQ_ERROR_MISMATCH; -} - -static -apr_status_t apache2_read_limit_get(apreq_handle_t *handle, - apr_uint64_t *bytes) -{ - ap_filter_t *f = get_apreq_filter(handle); - struct filter_ctx *ctx; - - if (f->ctx == NULL) - apreq_filter_make_context(f); - - ctx = f->ctx; - *bytes = ctx->read_limit; - return APR_SUCCESS; -} - -static -apr_status_t apache2_temp_dir_set(apreq_handle_t *handle, - const char *path) -{ - ap_filter_t *f = get_apreq_filter(handle); - struct filter_ctx *ctx; - - if (f->ctx == NULL) - apreq_filter_make_context(f); - - ctx = f->ctx; - /* init vs incomplete state? */ - if (ctx->temp_dir == NULL && ctx->bytes_read == 0) { - if (path != NULL) - ctx->temp_dir = apr_pstrdup(handle->pool, path); - return APR_SUCCESS; - } - - return APREQ_ERROR_NOTEMPTY; -} - -static -apr_status_t apache2_temp_dir_get(apreq_handle_t *handle, - const char **path) -{ - ap_filter_t *f = get_apreq_filter(handle); - struct filter_ctx *ctx; - - if (f->ctx == NULL) - apreq_filter_make_context(f); - - ctx = f->ctx; - *path = ctx->parser ? ctx->parser->temp_dir : ctx->temp_dir; - return APR_SUCCESS; -} - -static APREQ_MODULE(apache2, APREQ_APACHE2_MMN); - -APREQ_DECLARE(apreq_handle_t *) apreq_handle_apache2(request_rec *r) -{ - struct apache2_handle *req = - ap_get_module_config(r->request_config, &apreq_module); - - if (req != NULL) { - get_apreq_filter(&req->handle); - return &req->handle; - } - - req = apr_palloc(r->pool, sizeof *req); - ap_set_module_config(r->request_config, &apreq_module, req); - - req->handle.module = &apache2_module; - req->handle.pool = r->pool; - req->handle.bucket_alloc = r->connection->bucket_alloc; - req->r = r; - - req->args_status = req->jar_status = APR_EINIT; - req->args = req->jar = NULL; - - req->f = NULL; - - get_apreq_filter(&req->handle); - return &req->handle; - -} diff --git a/modules/apreq/mod_apreq.dsp b/modules/apreq/mod_apreq.dsp deleted file mode 100644 index d6fffa24696..00000000000 --- a/modules/apreq/mod_apreq.dsp +++ /dev/null @@ -1,115 +0,0 @@ -# Microsoft Developer Studio Project File - Name="mod_apreq" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 - -CFG=mod_apreq - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "mod_apreq.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "mod_apreq.mak" CFG="mod_apreq - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "mod_apreq - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE "mod_apreq - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -MTL=midl.exe -RSC=rc.exe - -!IF "$(CFG)" == "mod_apreq - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "APREQ_DECLARE_EXPORT" /FD /c -# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "APREQ_DECLARE_EXPORT" /Fd"Release\mod_apreq_src" /FD /c -# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" -# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /fo"Release/mod_apreq.res" /i "../../include" /i "../../srclib/apr/include" /d "NDEBUG" /d BIN_NAME="mod_apreq.so" /d LONG_NAME="apreq_module for Apache" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /out:".\Release\mod_apreq.so" /base:@..\..\os\win32\BaseAddr.ref,mod_apreq.so -# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Release\mod_apreq.so" /base:@..\..\os\win32\BaseAddr.ref,mod_apreq.so /opt:ref -# Begin Special Build Tool -TargetPath=.\Release\mod_apreq.so -SOURCE="$(InputPath)" -PostBuild_Desc=Embed .manifest -PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 -# End Special Build Tool - -!ELSEIF "$(CFG)" == "mod_apreq - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MDd /W3 /EHsc /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "APREQ_DECLARE_EXPORT" /FD /c -# ADD CPP /nologo /MDd /W3 /EHsc /Zi /Od /I "../../include" /I "../../srclib/apr/include" /I "../../srclib/apr-util/include" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "APREQ_DECLARE_EXPORT" /Fd"Debug\mod_apreq_src" /FD /c -# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" -# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /fo"Debug/mod_apreq.res" /i "../../include" /i "../../srclib/apr/include" /d "_DEBUG" /d BIN_NAME="mod_apreq.so" /d LONG_NAME="apreq_module for Apache" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_apreq.so" /base:@..\..\os\win32\BaseAddr.ref,mod_apreq.so -# ADD LINK32 kernel32.lib /nologo /subsystem:windows /dll /incremental:no /debug /out:".\Debug\mod_apreq.so" /base:@..\..\os\win32\BaseAddr.ref,mod_apreq.so -# Begin Special Build Tool -TargetPath=.\Debug\mod_apreq.so -SOURCE="$(InputPath)" -PostBuild_Desc=Embed .manifest -PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 -# End Special Build Tool - -!ENDIF - -# Begin Target - -# Name "mod_apreq - Win32 Release" -# Name "mod_apreq - Win32 Debug" -# Begin Source File - -SOURCE=.\filter.c -# End Source File -# Begin Source File - -SOURCE=.\handle.c -# End Source File -# Begin Source File - -SOURCE=..\..\build\win32\httpd.rc -# End Source File -# End Target -# End Project diff --git a/server/Makefile.in b/server/Makefile.in index 3b25ebcafda..fba9f47c170 100644 --- a/server/Makefile.in +++ b/server/Makefile.in @@ -15,11 +15,7 @@ LTLIBRARY_SOURCES = \ util_filter.c util_pcre.c util_regex.c $(EXPORTS_DOT_C) \ scoreboard.c error_bucket.c protocol.c core.c request.c ssl.c provider.c \ eoc_bucket.c eor_bucket.c headers_bucket.c core_filters.c \ - util_expr_parse.c util_expr_scan.c util_expr_eval.c \ - apreq_cookie.c apreq_error.c apreq_module.c \ - apreq_module_cgi.c apreq_module_custom.c apreq_param.c \ - apreq_parser.c apreq_parser_header.c apreq_parser_multipart.c \ - apreq_parser_urlencoded.c apreq_util.c + util_expr_parse.c util_expr_scan.c util_expr_eval.c LTLIBRARY_DEPENDENCIES = test_char.h diff --git a/server/apreq_cookie.c b/server/apreq_cookie.c deleted file mode 100644 index 53ae16f64d6..00000000000 --- a/server/apreq_cookie.c +++ /dev/null @@ -1,537 +0,0 @@ -/* -** Licensed to the Apache Software Foundation (ASF) under one or more -** contributor license agreements. See the NOTICE file distributed with -** this work for additional information regarding copyright ownership. -** The ASF licenses this file to You under the Apache License, Version 2.0 -** (the "License"); you may not use this file except in compliance with -** the License. You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#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; - - case 'h': /* httponly */ - if (vlen > 0 && *val != '0' && strncasecmp("off",val,vlen)) - apreq_cookie_httponly_on(c); - else - apreq_cookie_httponly_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; - int nlen_set = 0; - hdr = *data; - - while (apr_isspace(*hdr) || *hdr == '=') - ++hdr; - - key = hdr; - *n = hdr; - - scan_name: - - switch (*hdr) { - - case 0: - case ';': - case ',': - if (!nlen_set) - *nlen = hdr - key; - *v = hdr; - *vlen = 0; - *data = hdr; - return *nlen ? APREQ_ERROR_NOTOKEN : APREQ_ERROR_BADCHAR; - - case '=': - if (!nlen_set) { - *nlen = hdr - key; - nlen_set = 1; - } - break; - - case ' ': - case '\t': - case '\r': - case '\n': - if (!nlen_set) { - *nlen = hdr - key; - nlen_set = 1; - } - /* fall thru */ - - default: - ++hdr; - goto scan_name; - } - - val = hdr + 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 */ - *data = val; - 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; - apr_status_t rv = APR_SUCCESS; - - parse_cookie_header: - - c = NULL; - version = NETSCAPE; - - while (apr_isspace(*hdr)) - ++hdr; - - - if (*hdr == '$' && strncasecmp(hdr, "$Version", 8) == 0) { - /* XXX cheat: assume "$Version" => RFC Cookie header */ - version = RFC; - skip_version_string: - switch (*hdr++) { - case 0: - return rv; - 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 = 0, 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 rv; - - case ',': - ++hdr; - if (c != NULL) { - ADD_COOKIE(j, c); - } - goto parse_cookie_header; - - case '$': - ++hdr; - if (c == NULL) { - rv = APREQ_ERROR_BADCHAR; - goto parse_cookie_error; - } - else if (version == NETSCAPE) { - rv = APREQ_ERROR_MISMATCH; - } - - status = get_pair(p, &hdr, &name, &nlen, &value, &vlen, 1); - if (status != APR_SUCCESS) { - rv = status; - goto parse_cookie_error; - } - - status = apreq_cookie_attr(p, c, name, nlen, value, vlen); - - switch (status) { - - case APR_ENOTIMPL: - rv = APREQ_ERROR_BADATTR; - /* fall thru */ - - case APR_SUCCESS: - break; - - default: - rv = status; - goto parse_cookie_error; - } - - break; - - default: - if (c != NULL) { - ADD_COOKIE(j, c); - } - - status = get_pair(p, &hdr, &name, &nlen, &value, &vlen, 0); - - if (status != APR_SUCCESS) { - c = NULL; - rv = status; - goto parse_cookie_error; - } - - c = apreq_cookie_make(p, name, nlen, value, vlen); - apreq_cookie_tainted_on(c); - if (version != NETSCAPE) - apreq_cookie_version_set(c, version); - } - } - - parse_cookie_error: - - switch (*hdr) { - - case 0: - return rv; - - case ',': - case ';': - if (c != NULL) - ADD_COOKIE(j, c); - ++hdr; - goto parse_cookie_header; - - default: - ++hdr; - goto parse_cookie_error; - } - - /* not reached */ - return rv; -} - - -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 accommodate 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"); - - f += strlen(f); - - if (apreq_cookie_is_httponly(c)) - strcpy(f, "; HttpOnly"); - - 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"); - - f += strlen(f); - - if (apreq_cookie_is_httponly(c)) - strcpy(f, "; HttpOnly"); - - 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; -} - diff --git a/server/apreq_error.c b/server/apreq_error.c deleted file mode 100644 index 92a270bbe92..00000000000 --- a/server/apreq_error.c +++ /dev/null @@ -1,105 +0,0 @@ -/* Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#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)); -} - diff --git a/server/apreq_module.c b/server/apreq_module.c deleted file mode 100644 index 9ba5a765ed3..00000000000 --- a/server/apreq_module.c +++ /dev/null @@ -1,65 +0,0 @@ -/* -** Licensed to the Apache Software Foundation (ASF) under one or more -** contributor license agreements. See the NOTICE file distributed with -** this work for additional information regarding copyright ownership. -** The ASF licenses this file to You under the Apache License, Version 2.0 -** (the "License"); you may not use this file except in compliance with -** the License. You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#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; - -} - -APREQ_DECLARE(apr_table_t *)apreq_cookies(apreq_handle_t *req, apr_pool_t *p) -{ - const apr_table_t *jar; - apreq_jar(req, &jar); - - if (jar != NULL) - return apr_table_copy(p, jar); - else - return NULL; - -} - - -/** @} */ diff --git a/server/apreq_module_cgi.c b/server/apreq_module_cgi.c deleted file mode 100644 index d67371b4dfb..00000000000 --- a/server/apreq_module_cgi.c +++ /dev/null @@ -1,1025 +0,0 @@ -/* -** Licensed to the Apache Software Foundation (ASF) under one or more -** contributor license agreements. See the NOTICE file distributed with -** this work for additional information regarding copyright ownership. -** The ASF licenses this file to You under the Apache License, Version 2.0 -** (the "License"); you may not use this file except in compliance with -** the License. You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#define APR_WANT_STRFUNC -#include "apr_want.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" - -#include "httpd.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__ - -/** Interactive patch: - * TODO Don't use 65K buffer - * TODO Handle empty/non-existent parameters - * TODO Allow body elements to be files - * TODO When running body/get/cookies all at once, include previous cached - * values (and don't start at 0 in count) - * TODO What happens if user does apreq_param, but needs POST value - we'll - * never catch it now, as args param will match... - */ - -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; - - int interactive_mode; - const char *promptstr; - apr_file_t *sout, *sin; -}; - -#define CRLF "\015\012" -static const char *nullstr = 0; -#define DEFAULT_PROMPT "([$t] )$n(\\($l\\))([$d]): " -#define MAX_PROMPT_NESTING_LEVELS 8 -#define MAX_BUFFER_SIZE 65536 - -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 char* chomp(char* str) -{ - long p = (long)strlen(str); - while (--p >= 0) { - switch ((char)(str[p])) { - case '\015': - case '\012':str[p]='\000'; - break; - default:return str; - } - } - return str; -} - -/** TODO: Support wide-characters */ -/* prompt takes a apreq_handle and 2 strings - name and type - and prompts a - user for input via stdin/stdout. used in interactive mode. - - name must be defined. type can be null. - - we take the promptstring defined in the handle and interpolate variables as - follows: - - $n - name of the variable we're asking for (param 2 to prompt()) - $t - type of the variable we're asking for - like cookie, get, post, etc - (param 3 to prompt()) - parentheses - if a variable is surrounded by parentheses, and interpolates - as null, then nothing else in the parentheses will be displayed - Useful if you want a string to only show up if a given variable - is available - - These are planned for forward-compatibility, but the underlying features - need some love... I left these in here just as feature reminders, rather - than completely removing them from the code - at least they provide sanity - testing of the default prompt & parentheses - issac - - $l - label for the param - the end-user-developer can provide a textual - description of the param (name) being requested (currently unused in - lib) - $d - default value for the param (currently unused in lib) - -*/ -static char *prompt(apreq_handle_t *handle, const char *name, - const char *type) { - struct cgi_handle *req = (struct cgi_handle *)handle; - const char *defval = nullstr; - const char *label = NULL; - const char *cprompt; - char buf[MAX_PROMPT_NESTING_LEVELS][MAX_BUFFER_SIZE]; - /* Array of current arg for given p-level */ - char *start, curarg[MAX_PROMPT_NESTING_LEVELS] = ""; - /* Parenthesis level (for argument/text grouping) */ - int plevel; - - cprompt = req->promptstr - 1; - *buf[0] = plevel = 0; - start = buf[0]; - - while (*(++cprompt) != 0) { - switch (*cprompt) { - case '$': /* interpolate argument; curarg[plevel] => 1 */ - cprompt++; - switch (*cprompt) { - case 't': - if (type != NULL) { - strcpy(start, type); - start += strlen(type); - curarg[plevel] = 1; - } else { - curarg[plevel] = curarg[plevel] | 0; - } - break; - case 'n': - /* Name can't be null :-) [If it can, we should - * immediately return NULL] */ - strcpy(start, name); - start += strlen(name); - curarg[plevel] = 1; - break; - case 'l': - if (label != NULL) { - strcpy(start, label); - start += strlen(label); - curarg[plevel] = 1; - } else { - curarg[plevel] = curarg[plevel] | 0; - } - break; - case 'd': - /* TODO: Once null defaults are available, - * remove if and use nullstr if defval == NULL */ - if (defval != NULL) { - strcpy(start, defval); - start += strlen(defval); - curarg[plevel] = 1; - } else { - curarg[plevel] = curarg[plevel] | 0; - } - break; - default: - /* Handle this? */ - break; - } - break; - - case '(': - if (plevel <= MAX_PROMPT_NESTING_LEVELS) { - plevel++; - curarg[plevel] = *buf[plevel] = 0; - start = buf[plevel]; - } - /* else? */ - break; - - case ')': - if (plevel > 0) { - *start = 0; /* Null terminate current string */ - - /* Move pointer to end of string */ - plevel--; - start = buf[plevel] + strlen(buf[plevel]); - - /* If old curarg was set, concat buffer with level down */ - if (curarg[plevel + 1]) { - strcpy(start, buf[plevel + 1]); - start += strlen(buf[plevel + 1]); - } - - break; - } - case '\\': /* Check next character for escape sequence - * (just ignore it for now) */ - (void)*cprompt++; - /* Fallthrough */ - - default: - *start++ = *cprompt; - } - } - - *start = 0; /* Null terminate the string */ - - apr_file_printf(req->sout, "%s", buf[0]); - apr_file_gets(buf[0], MAX_BUFFER_SIZE, req->sin); - chomp(buf[0]); - if (strcmp(buf[0], "")) { -/* if (strcmp(buf[0], nullstr)) */ - return apr_pstrdup(handle->pool, buf[0]); -/* return NULL; */ - } - - if (defval != nullstr) - return apr_pstrdup(handle->pool, defval); - - return NULL; -} - -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+5; *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; - - if (cl_header != NULL) { - apr_off_t content_length; - - if (!ap_parse_strict_length(&content_length, cl_header)) { - 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; - } - 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->interactive_mode && req->jar_status != APR_SUCCESS) { - char buf[65536]; - const char *name, *val; - apreq_cookie_t *p; - int i = 1; - apr_file_printf(req->sout, "[CGI] Requested all cookies\n"); - while (1) { - apr_file_printf(req->sout, "[CGI] Please enter a name for cookie %d (or just hit ENTER to end): ", - i++); - apr_file_gets(buf, 65536, req->sin); - chomp(buf); - if (!strcmp(buf, "")) { - break; - } - name = apr_pstrdup(handle->pool, buf); - val = prompt(handle, name, "cookie"); - if (val == NULL) - val = ""; - p = apreq_cookie_make(handle->pool, name, strlen(name), val, strlen(val)); - if (p == NULL) - return APR_ENOMEM; - apreq_cookie_tainted_on(p); - apreq_value_table_add(&p->v, req->jar); - } - req->jar_status = APR_SUCCESS; - } /** Fallthrough */ - - if (req->jar_status == APR_EINIT) { - const char *cookies = cgi_header_in(handle, "Cookie"); - if (cookies != NULL) { - 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->interactive_mode && req->args_status != APR_SUCCESS) { - char buf[65536]; - const char *name, *val; - apreq_param_t *p; - int i = 1; - apr_file_printf(req->sout, "[CGI] Requested all argument parameters\n"); - while (1) { - apr_file_printf(req->sout, "[CGI] Please enter a name for parameter %d (or just hit ENTER to end): ", - i++); - apr_file_gets(buf, 65536, req->sin); - chomp(buf); - if (!strcmp(buf, "")) { - break; - } - name = apr_pstrdup(handle->pool, buf); - val = prompt(handle, name, "parameter"); - if (val == NULL) - val = ""; - p = apreq_param_make(handle->pool, name, strlen(name), val, strlen(val)); - if (p == NULL) - return APR_ENOMEM; - apreq_param_tainted_on(p); - apreq_value_table_add(&p->v, req->args); - val = p->v.data; - } - req->args_status = APR_SUCCESS; - } /** Fallthrough */ - - if (req->args_status == APR_EINIT) { - const char *qs = cgi_query_string(handle); - if (qs != NULL) { - 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 = NULL; - - if (req->jar_status == APR_EINIT && !req->interactive_mode) - cgi_jar(handle, &t); - else - t = req->jar; - - val = apr_table_get(t, name); - if (val == NULL) { - if (!req->interactive_mode) { - return NULL; - } else { - apreq_cookie_t *p; - val = prompt(handle, name, "cookie"); - if (val == NULL) - return NULL; - p = apreq_cookie_make(handle->pool, name, strlen(name), val, strlen(val)); - if (p == NULL) - return NULL; - apreq_cookie_tainted_on(p); - apreq_value_table_add(&p->v, req->jar); - val = p->v.data; - } - } - - - 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 = NULL; - - if (req->args_status == APR_EINIT && !req->interactive_mode) - cgi_args(handle, &t); - else - t = req->args; - - val = apr_table_get(t, name); - if (val == NULL) { - if (!req->interactive_mode) { - return NULL; - } else { - apreq_param_t *p; - val = prompt(handle, name, "parameter"); - if (val == NULL) - return NULL; - p = apreq_param_make(handle->pool, name, strlen(name), val, strlen(val)); - if (p == NULL) - return NULL; - apreq_param_tainted_on(p); - apreq_value_table_add(&p->v, req->args); - val = p->v.data; - } - } - - - 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; - - if (req->interactive_mode && req->body_status != APR_SUCCESS) { - const char *name, *val; - apreq_param_t *p; - int i = 1; - apr_file_printf(req->sout, "[CGI] Requested all body parameters\n"); - while (1) { - char buf[65536]; - apr_file_printf(req->sout, "[CGI] Please enter a name for parameter %d (or just hit ENTER to end): ", - i++); - apr_file_gets(buf, 65536, req->sin); - chomp(buf); - if (!strcmp(buf, "")) { - break; - } - name = apr_pstrdup(handle->pool, buf); - val = prompt(handle, name, "parameter"); - if (val == NULL) - val = ""; - p = apreq_param_make(handle->pool, name, strlen(name), val, strlen(val)); - if (p == NULL) - return APR_ENOMEM; - apreq_param_tainted_on(p); - apreq_value_table_add(&p->v, req->body); - val = p->v.data; - } - req->body_status = APR_SUCCESS; - } /** Fallthrough */ - - 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 = NULL; - apreq_hook_t *h; - apreq_hook_find_param_ctx_t *hook_ctx; - - if (req->interactive_mode) { - val = apr_table_get(req->body, name); - if (val == NULL) { - return NULL; - } else { - apreq_param_t *p; - val = prompt(handle, name, "parameter"); - if (val == NULL) - return NULL; - p = apreq_param_make(handle->pool, name, strlen(name), val, strlen(val)); - if (p == NULL) - return NULL; - apreq_param_tainted_on(p); - apreq_value_table_add(&p->v, req->body); - val = p->v.data; - return apreq_value_to_param(val); - } - } - - - 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 */ - - hook_ctx = apr_palloc(handle->pool, sizeof *hook_ctx); - - 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; - h->ctx = hook_ctx; - hook_ctx->name = name; - hook_ctx->param = NULL; - hook_ctx->prev = req->parser->hook; - - do { - cgi_read(handle, APREQ_DEFAULT_READ_BLOCK_SIZE); - if (hook_ctx->param != NULL) - return hook_ctx->param; - } 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 - -/** Determine if we're interactive mode or not. Order is - QUERY_STRING ? NO : Interactive - - I think we should just rely on GATEWAY_INTERFACE to set - non-interactive mode, and be interactive if it's not there - - Behaviour change should really be: - Always check query_string before prompting user, - but rewrite body/cookies to get if interactive - - Definitely more work needed here... -*/ -static int is_interactive_mode(apr_pool_t *pool) -{ - char *value = NULL, qs[] = "GATEWAY_INTERFACE"; - apr_status_t rv; - - rv = apr_env_get(&value, qs, pool); - if (rv != APR_SUCCESS) - if (rv == APR_ENOENT) - return 1; - - /** handle else? (!SUCCESS && !ENOENT) */ - return 0; -} - -static APREQ_MODULE(cgi, 20090110); - -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 = apr_table_make(pool, APREQ_DEFAULT_NELTS); - req->body = apr_table_make(pool, APREQ_DEFAULT_NELTS); - req->jar = apr_table_make(pool, APREQ_DEFAULT_NELTS); - - req->args_status = - req->jar_status = - req->body_status = APR_EINIT; - - if (is_interactive_mode(pool)) { - req->interactive_mode = 1; - apr_file_open_stdout(&(req->sout), pool); - apr_file_open_stdin(&(req->sin), pool); - req->promptstr=apr_pstrdup(pool, DEFAULT_PROMPT); - } - - 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; -} diff --git a/server/apreq_module_custom.c b/server/apreq_module_custom.c deleted file mode 100644 index e1e6f58bfe5..00000000000 --- a/server/apreq_module_custom.c +++ /dev/null @@ -1,304 +0,0 @@ -/* -** Licensed to the Apache Software Foundation (ASF) under one or more -** contributor license agreements. See the NOTICE file distributed with -** this work for additional information regarding copyright ownership. -** The ASF licenses this file to You under the Apache License, Version 2.0 -** (the "License"); you may not use this file except in compliance with -** the License. You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#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, 20070428); - -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->bytes_read = 0; - 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; -} - diff --git a/server/apreq_param.c b/server/apreq_param.c deleted file mode 100644 index 83e185b595a..00000000000 --- a/server/apreq_param.c +++ /dev/null @@ -1,272 +0,0 @@ -/* -** Licensed to the Apache Software Foundation (ASF) under one or more -** contributor license agreements. See the NOTICE file distributed with -** this work for additional information regarding copyright ownership. -** The ASF licenses this file to You under the Apache License, Version 2.0 -** (the "License"); you may not use this file except in compliance with -** the License. You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#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 = ¶m->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(¶m, pool, start, nlen, vlen); - if (s != APR_SUCCESS) - return s; - - apreq_param_tainted_on(param); - apreq_value_table_add(¶m->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, ¶m, body, name, NULL); - return param; -} diff --git a/server/apreq_parser.c b/server/apreq_parser.c deleted file mode 100644 index f4188873037..00000000000 --- a/server/apreq_parser.c +++ /dev/null @@ -1,358 +0,0 @@ -/* -** Licensed to the Apache Software Foundation (ASF) under one or more -** contributor license agreements. See the NOTICE file distributed with -** this work for additional information regarding copyright ownership. -** The ASF licenses this file to You under the Apache License, Version 2.0 -** (the "License"); you may not use this file except in compliance with -** the License. You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#include "apreq_error.h" -#include "apreq_parser.h" -#include "apreq_util.h" -#include "apr_strings.h" -#include "apr_xml.h" -#include "apr_hash.h" - -#define PARSER_STATUS_CHECK(PREFIX) do { \ - if (ctx->status == PREFIX##_ERROR) \ - return APREQ_ERROR_GENERAL; \ - else if (ctx->status == PREFIX##_COMPLETE) \ - return APR_SUCCESS; \ - else if (bb == NULL) \ - return APR_INCOMPLETE; \ -} while (0); - -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) -{ - apreq_parser_t *p = apr_palloc(pool, sizeof *p); - p->content_type = content_type; - p->parser = pfn; - p->hook = hook; - p->pool = pool; - p->bucket_alloc = ba; - p->brigade_limit = brigade_limit; - p->temp_dir = temp_dir; - p->ctx = ctx; - return p; -} - -APREQ_DECLARE(apreq_hook_t *) apreq_hook_make(apr_pool_t *pool, - apreq_hook_function_t hook, - apreq_hook_t *next, - void *ctx) -{ - apreq_hook_t *h = apr_palloc(pool, sizeof *h); - h->hook = hook; - h->next = next; - h->pool = pool; - h->ctx = ctx; - return h; -} - - -/*XXX this may need to check the parser's state before modifying the hook list */ -APREQ_DECLARE(apr_status_t) apreq_parser_add_hook(apreq_parser_t *p, - apreq_hook_t *h) -{ - apreq_hook_t *last = h; - - while (last->next) - last = last->next; - - last->next = p->hook; - p->hook = h; - - return APR_SUCCESS; -} - -static int default_parsers_lock = 0; -static apr_hash_t *default_parsers = NULL; -static apr_pool_t *default_parser_pool = NULL; - -static apr_status_t apreq_parsers_cleanup(void *data) -{ - default_parsers_lock = 0; - default_parsers = NULL; - default_parser_pool = NULL; - - return APR_SUCCESS; -} - -APREQ_DECLARE(apr_status_t) apreq_pre_initialize(apr_pool_t *pool) -{ - apr_status_t status; - - if (default_parser_pool != NULL) - return APR_SUCCESS; - - if (default_parsers_lock) - return APREQ_ERROR_GENERAL; - - status = apr_pool_create(&default_parser_pool, pool); - if (status != APR_SUCCESS) - return status; - apr_pool_tag(default_parser_pool, "apreq_default_parser"); - - apr_pool_cleanup_register(default_parser_pool, NULL, - apreq_parsers_cleanup, - apr_pool_cleanup_null); - - default_parsers = apr_hash_make(default_parser_pool); - - apreq_register_parser("application/x-www-form-urlencoded", - apreq_parse_urlencoded); - apreq_register_parser("multipart/form-data", apreq_parse_multipart); - apreq_register_parser("multipart/related", apreq_parse_multipart); - - return APR_SUCCESS; -} - -APREQ_DECLARE(apr_status_t) apreq_post_initialize(apr_pool_t *pool) -{ - (void)pool; - - if (default_parser_pool == NULL) - return APREQ_ERROR_GENERAL; - - default_parsers_lock = 1; - return APR_SUCCESS; -} - -APREQ_DECLARE(apr_status_t) apreq_initialize(apr_pool_t *pool) -{ - apr_status_t s = apreq_pre_initialize(pool); - - if (s != APR_SUCCESS) - return s; - - return apreq_post_initialize(pool); -} - - -APREQ_DECLARE(apr_status_t) apreq_register_parser(const char *enctype, - apreq_parser_function_t pfn) -{ - apreq_parser_function_t *f = NULL; - - if (default_parsers == NULL) - return APR_EINIT; - - if (enctype == NULL) - return APR_EINVAL; - - if (default_parsers_lock) - return APREQ_ERROR_GENERAL; - - if (pfn != NULL) { - f = apr_palloc(default_parser_pool, sizeof *f); - *f = pfn; - } - apr_hash_set(default_parsers, apr_pstrdup(default_parser_pool, enctype), - APR_HASH_KEY_STRING, f); - - return APR_SUCCESS; -} - -APREQ_DECLARE(apreq_parser_function_t)apreq_parser(const char *enctype) -{ - apreq_parser_function_t *f; - apr_size_t tlen = 0; - - if (enctype == NULL || default_parsers_lock == 0) - return NULL; - - while (enctype[tlen] && enctype[tlen] != ';') - ++tlen; - - f = apr_hash_get(default_parsers, enctype, tlen); - - if (f != NULL) - return *f; - else - return NULL; -} - -APREQ_DECLARE_HOOK(apreq_hook_disable_uploads) -{ - return (bb == NULL) ? APR_SUCCESS : APREQ_ERROR_GENERAL; -} - -APREQ_DECLARE_HOOK(apreq_hook_discard_brigade) -{ - apr_status_t s = APR_SUCCESS; - if (hook->next) - s = apreq_hook_run(hook->next, param, bb); - if (bb != NULL) - apr_brigade_cleanup(bb); - return s; -} - - -/* generic parser */ - -struct gen_ctx { - apreq_param_t *param; - enum { - GEN_INCOMPLETE, - GEN_COMPLETE, - GEN_ERROR - } status; -}; - -APREQ_DECLARE_PARSER(apreq_parse_generic) -{ - struct gen_ctx *ctx = parser->ctx; - apr_pool_t *pool = parser->pool; - apr_status_t s = APR_SUCCESS; - apr_bucket *e = APR_BRIGADE_LAST(bb); - unsigned saw_eos = 0; - - if (ctx == NULL) { - parser->ctx = ctx = apr_palloc(pool, sizeof *ctx); - ctx->status = GEN_INCOMPLETE; - ctx->param = apreq_param_make(pool, - "_dummy_", strlen("_dummy_"), "", 0); - if (ctx->param == NULL) - return APR_ENOMEM; - ctx->param->upload = apr_brigade_create(pool, parser->bucket_alloc); - ctx->param->info = apr_table_make(pool, APREQ_DEFAULT_NELTS); - } - - - PARSER_STATUS_CHECK(GEN); - - while (e != APR_BRIGADE_SENTINEL(bb)) { - if (APR_BUCKET_IS_EOS(e)) { - saw_eos = 1; - break; - } - e = APR_BUCKET_PREV(e); - } - - if (parser->hook != NULL) { - s = apreq_hook_run(parser->hook, ctx->param, bb); - if (s != APR_SUCCESS) { - ctx->status = GEN_ERROR; - return s; - } - } - - apreq_brigade_setaside(bb, pool); - s = apreq_brigade_concat(pool, parser->temp_dir, parser->brigade_limit, - ctx->param->upload, bb); - - if (s != APR_SUCCESS) { - ctx->status = GEN_ERROR; - return s; - } - - if (saw_eos) { - ctx->status = GEN_COMPLETE; - return APR_SUCCESS; - } - else - return APR_INCOMPLETE; -} - - -struct xml_ctx { - apr_xml_doc *doc; - apr_xml_parser *xml_parser; - enum { - XML_INCOMPLETE, - XML_COMPLETE, - XML_ERROR - } status; -}; - - -APREQ_DECLARE_HOOK(apreq_hook_apr_xml_parser) -{ - apr_pool_t *pool = hook->pool; - struct xml_ctx *ctx = hook->ctx; - apr_status_t s = APR_SUCCESS; - apr_bucket *e; - - if (ctx == NULL) { - hook->ctx = ctx = apr_palloc(pool, sizeof *ctx); - ctx->doc = NULL; - ctx->xml_parser = apr_xml_parser_create(pool); - ctx->status = XML_INCOMPLETE; - } - - PARSER_STATUS_CHECK(XML); - - for (e = APR_BRIGADE_FIRST(bb); e != APR_BRIGADE_SENTINEL(bb); - e = APR_BUCKET_NEXT(e)) - { - const char *data; - apr_size_t dlen; - - if (APR_BUCKET_IS_EOS(e)) { - s = apr_xml_parser_done(ctx->xml_parser, &ctx->doc); - if (s == APR_SUCCESS) { - ctx->status = XML_COMPLETE; - if (hook->next) - s = apreq_hook_run(hook->next, param, bb); - } - else { - ctx->status = XML_ERROR; - } - return s; - } - else if (APR_BUCKET_IS_METADATA(e)) { - continue; - } - - s = apr_bucket_read(e, &data, &dlen, APR_BLOCK_READ); - - if (s != APR_SUCCESS) { - ctx->status = XML_ERROR; - return s; - } - - s = apr_xml_parser_feed(ctx->xml_parser, data, dlen); - - if (s != APR_SUCCESS) { - ctx->status = XML_ERROR; - return s; - } - } - - if (hook->next) - return apreq_hook_run(hook->next, param, bb); - - return APR_SUCCESS; -} - - -APREQ_DECLARE_HOOK(apreq_hook_find_param) -{ - apreq_hook_find_param_ctx_t *ctx = hook->ctx; - int is_final = (bb == NULL) || APR_BUCKET_IS_EOS(APR_BRIGADE_LAST(bb)); - apr_status_t s = (hook->next == NULL) - ? APR_SUCCESS : apreq_hook_run(hook->next, param, bb); - - if (is_final && s == APR_SUCCESS && ctx->param == NULL - && strcasecmp(ctx->name, param->v.name) == 0) { - ctx->param = param; - ctx->prev->next = hook->next; - } - return s; -} diff --git a/server/apreq_parser_header.c b/server/apreq_parser_header.c deleted file mode 100644 index e3c789eb129..00000000000 --- a/server/apreq_parser_header.c +++ /dev/null @@ -1,448 +0,0 @@ -/* -** Licensed to the Apache Software Foundation (ASF) under one or more -** contributor license agreements. See the NOTICE file distributed with -** this work for additional information regarding copyright ownership. -** The ASF licenses this file to You under the Apache License, Version 2.0 -** (the "License"); you may not use this file except in compliance with -** the License. You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ -#include -#include "apreq_parser.h" -#include "apreq_error.h" -#include "apreq_util.h" - -#include "apr_lib.h" /* for apr_iscntrl() & co */ - -#define PARSER_STATUS_CHECK(PREFIX) do { \ - if (ctx->status == PREFIX##_ERROR) \ - return APREQ_ERROR_GENERAL; \ - else if (ctx->status == PREFIX##_COMPLETE) \ - return APR_SUCCESS; \ - else if (bb == NULL) \ - return APR_INCOMPLETE; \ -} while (0); - - -struct hdr_ctx { - apr_bucket_brigade *bb; - apr_size_t nlen; - apr_size_t glen; - apr_size_t vlen; - enum { - HDR_NAME, - HDR_GAP, - HDR_VALUE, - HDR_NEWLINE, - HDR_ENDLINE, - HDR_FOLDLINE, - HDR_LASTLINE, - HDR_COMPLETE, - HDR_ERROR - } status; -}; - -/********************* header parsing utils ********************/ - - -static apr_bucket *split_header_line(apr_bucket *e, apr_size_t *off, - const char **data, apr_size_t *dlen) -{ - if (*off > 1) { - apr_bucket_split(e, *off - 1); - e = APR_BUCKET_NEXT(e); - *dlen -= *off - 1; - *data += *off - 1; - *off = 1; - } - return e; -} - -static apr_status_t consume_header_line(apreq_param_t **p, - apr_pool_t *pool, - apr_bucket_brigade *bb, - apr_size_t nlen, - apr_size_t glen, - apr_size_t vlen) -{ - apreq_param_t *param; - apreq_value_t *v; - apr_bucket *e, *f; - apr_status_t s; - struct iovec vec[APREQ_DEFAULT_NELTS], *iov; - apr_array_header_t arr; - char *dest; - const char *data; - apr_size_t dlen; - int i, eol = 0; - - param = apreq_param_make(pool, NULL, nlen, NULL, vlen); - if (param == NULL) - return APR_ENOMEM; - *(const apreq_value_t **)&v = ¶m->v; - - arr.pool = pool; - arr.elt_size = sizeof(struct iovec); - arr.nelts = 0; - arr.nalloc = APREQ_DEFAULT_NELTS; - arr.elts = (char *)vec; - - e = APR_BRIGADE_FIRST(bb); - - /* store name in a temporary iovec array */ - do { - apr_size_t len; - - assert(e != APR_BRIGADE_SENTINEL(bb)); - iov = (struct iovec *)apr_array_push(&arr); - s = apr_bucket_read(e, (const char **)&iov->iov_base, - &len, APR_BLOCK_READ); - if (s != APR_SUCCESS) - return s; - iov->iov_len = len; - - assert(nlen >= len); - nlen -= len; - - e = APR_BUCKET_NEXT(e); - } while (nlen > 0); - - /* skip gap */ - do { - assert(e != APR_BRIGADE_SENTINEL(bb)); - s = apr_bucket_read(e, &data, &dlen, APR_BLOCK_READ); - if (s != APR_SUCCESS) - return s; - - assert(glen >= dlen); - glen -= dlen; - - e = APR_BUCKET_NEXT(e); - } while (glen > 0); - - /* copy value */ - dest = v->data; - do { - apr_size_t off; - - assert(e != APR_BRIGADE_SENTINEL(bb)); - s = apr_bucket_read(e, &data, &dlen, APR_BLOCK_READ); - if (s != APR_SUCCESS) - return s; - - for (off = 0; off < dlen; ++off) { - const char ch = data[off]; - if (ch == '\r' || ch == '\n') { - /* Eat [CR]LF of continuation or end of line */ - if (!vlen && ch == '\n') - eol = 1; /* done */ - continue; - } - assert(vlen > 0); - *dest = ch; - ++dest; - --vlen; - } - - e = APR_BUCKET_NEXT(e); - } while (!eol); - v->dlen = dest - v->data; - *dest++ = 0; - - /* write name */ - v->name = dest; - for (i = 0; i < arr.nelts; ++i) { - iov = &((struct iovec *)arr.elts)[i]; - memcpy(dest, iov->iov_base, iov->iov_len); - dest += iov->iov_len; - ++iov; - } - v->nlen = dest - v->name; - *dest = 0; - - while ((f = APR_BRIGADE_FIRST(bb)) != e) - apr_bucket_delete(f); - - apreq_param_tainted_on(param); - *p = param; - return APR_SUCCESS; - -} - -#define IS_TOKEN_CHAR(c) (apr_isalnum(c) \ - || ((c) && strchr("!#$%&'*+-.^_`|~", (c)))) - -APREQ_DECLARE_PARSER(apreq_parse_headers) -{ - apr_pool_t *pool = parser->pool; - apr_bucket *e; - struct hdr_ctx *ctx; - char ch; - - if (parser->ctx == NULL) { - ctx = apr_pcalloc(pool, sizeof *ctx); - ctx->bb = apr_brigade_create(pool, parser->bucket_alloc); - parser->ctx = ctx; - ctx->status = HDR_NAME; - } - else - ctx = parser->ctx; - - PARSER_STATUS_CHECK(HDR); - e = APR_BRIGADE_LAST(ctx->bb); - APR_BRIGADE_CONCAT(ctx->bb, bb); - - /* parse the brigade for CRLF_CRLF-terminated header block, - * each time starting from the front of the brigade. - */ - - for (e = APR_BUCKET_NEXT(e); - e != APR_BRIGADE_SENTINEL(ctx->bb); - e = APR_BUCKET_NEXT(e)) - { - apr_size_t off = 0, dlen; - const char *data; - apr_status_t s; - apreq_param_t *param = NULL; /* silences gcc-4.0 warning */ - - if (APR_BUCKET_IS_EOS(e)) { - ctx->status = HDR_COMPLETE; - APR_BRIGADE_CONCAT(bb, ctx->bb); - return APR_SUCCESS; - } - - s = apr_bucket_read(e, &data, &dlen, APR_BLOCK_READ); - if ( s != APR_SUCCESS ) { - ctx->status = HDR_ERROR; - return s; - } - if (dlen == 0) - continue; - - parse_hdr_bucket: - - /* gap nlen = 13 - * vvv glen = 3 - * Sample-Header: grape vlen = 5 - * ^^^^^^^^^^^^^ ^^^^^ - * name value - */ - - switch (ctx->status) { - - case HDR_NAME: - - while (off < dlen) { - ch = data[off++]; - switch (ch) { - case ':': - if (!ctx->nlen) { - ctx->status = HDR_ERROR; - return APREQ_ERROR_BADHEADER; - } - e = split_header_line(e, &off, &data, &dlen); - ++ctx->glen; - ctx->status = HDR_GAP; - goto parse_hdr_bucket; - - default: - if (!IS_TOKEN_CHAR(ch)) { - ctx->status = HDR_ERROR; - return APREQ_ERROR_BADCHAR; - } - ++ctx->nlen; - } - } - break; - - - case HDR_GAP: - - while (off < dlen) { - ch = data[off++]; - switch (ch) { - case ' ': - case '\t': - ++ctx->glen; - break; - - case '\n': - e = split_header_line(e, &off, &data, &dlen); - ctx->status = HDR_NEWLINE; - goto parse_hdr_bucket; - - case '\r': - e = split_header_line(e, &off, &data, &dlen); - ctx->status = HDR_ENDLINE; - goto parse_hdr_bucket; - - default: - if (apr_iscntrl(ch)) { - ctx->status = HDR_ERROR; - return APREQ_ERROR_BADCHAR; - } - e = split_header_line(e, &off, &data, &dlen); - ++ctx->vlen; - ctx->status = HDR_VALUE; - goto parse_hdr_bucket; - } - } - break; - - - case HDR_VALUE: - - while (off < dlen) { - ch = data[off++]; - switch (ch) { - case '\n': - ctx->status = HDR_NEWLINE; - goto parse_hdr_bucket; - - case '\r': - ctx->status = HDR_ENDLINE; - goto parse_hdr_bucket; - - default: - if (apr_iscntrl(ch)) { - ctx->status = HDR_ERROR; - return APREQ_ERROR_BADCHAR; - } - ++ctx->vlen; - } - } - break; - - - case HDR_ENDLINE: - case HDR_LASTLINE: - - if (off == dlen) - break; - - if (data[off++] != '\n') { - ctx->status = HDR_ERROR; - return APREQ_ERROR_BADHEADER; - } - - if (ctx->status == HDR_LASTLINE) { - ctx->status = HDR_COMPLETE; - goto parse_hdr_bucket; - } - - /* fall thru */ - ctx->status = HDR_NEWLINE; - - case HDR_NEWLINE: - - if (off == dlen) - break; - - ch = data[off++]; - switch (ch) { - case ' ': - case '\t': - ++ctx->vlen; - break; - - default: - e = split_header_line(e, &off, &data, &dlen); - - /* consume from splitted brigade now */ - s = consume_header_line(¶m, pool, ctx->bb, - ctx->nlen, ctx->glen, ctx->vlen); - if (parser->hook != NULL && s == APR_SUCCESS) - s = apreq_hook_run(parser->hook, param, NULL); - if (s != APR_SUCCESS) { - ctx->status = HDR_ERROR; - return s; - } - apreq_value_table_add(¶m->v, t); - ctx->nlen = 0; - ctx->vlen = 0; - ctx->glen = 0; - - switch (ch) { - case '\n': - ctx->status = HDR_COMPLETE; - break; - - case '\r': - ctx->status = HDR_LASTLINE; - break; - - default: - if (!IS_TOKEN_CHAR(ch)) { - ctx->status = HDR_ERROR; - return APREQ_ERROR_BADCHAR; - } - ++ctx->nlen; - ctx->status = HDR_NAME; - break; - } - goto parse_hdr_bucket; - } - - /* fall thru */ - ctx->status = HDR_FOLDLINE; - - case HDR_FOLDLINE: - - while (off < dlen) { - ch = data[off++]; - switch (ch) { - case ' ': - case '\t': - ++ctx->vlen; - break; - - case '\n': - ctx->status = HDR_NEWLINE; - goto parse_hdr_bucket; - - case '\r': - ctx->status = HDR_ENDLINE; - goto parse_hdr_bucket; - - default: - if (apr_iscntrl(ch)) { - ctx->status = HDR_ERROR; - return APREQ_ERROR_BADCHAR; - } - ctx->status = HDR_VALUE; - ++ctx->vlen; - goto parse_hdr_bucket; - } - } - break; - - - case HDR_COMPLETE: - - if (off < dlen) - apr_bucket_split(e, off); - - e = APR_BUCKET_NEXT(e); - do { - apr_bucket *f = APR_BRIGADE_FIRST(ctx->bb); - apr_bucket_delete(f); - } while (e != APR_BRIGADE_FIRST(ctx->bb)); - - APR_BRIGADE_CONCAT(bb, ctx->bb); - return APR_SUCCESS; - - - default: - assert(0); /* not reached */ - } - } - apreq_brigade_setaside(ctx->bb,pool); - return APR_INCOMPLETE; -} diff --git a/server/apreq_parser_multipart.c b/server/apreq_parser_multipart.c deleted file mode 100644 index 2bea98efbd6..00000000000 --- a/server/apreq_parser_multipart.c +++ /dev/null @@ -1,689 +0,0 @@ -/* -** Licensed to the Apache Software Foundation (ASF) under one or more -** contributor license agreements. See the NOTICE file distributed with -** this work for additional information regarding copyright ownership. -** The ASF licenses this file to You under the Apache License, Version 2.0 -** (the "License"); you may not use this file except in compliance with -** the License. You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#include "apreq_parser.h" -#include "apreq_error.h" -#include "apreq_util.h" -#include "apr_strings.h" -#include "apr_strmatch.h" - -#ifndef CRLF -#define CRLF "\015\012" -#endif - -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) - -#define PARSER_STATUS_CHECK(PREFIX) do { \ - if (ctx->status == PREFIX##_ERROR) \ - return APREQ_ERROR_GENERAL; \ - else if (ctx->status == PREFIX##_COMPLETE) \ - return APR_SUCCESS; \ - else if (bb == NULL) \ - return APR_INCOMPLETE; \ -} while (0); - -/* maximum recursion level in the mfd parser */ -#define MAX_LEVEL 8 - -struct mfd_ctx { - apr_table_t *info; - apr_bucket_brigade *in; - apr_bucket_brigade *bb; - apreq_parser_t *hdr_parser; - apreq_parser_t *next_parser; - const apr_strmatch_pattern *pattern; - char *bdry; - enum { - MFD_INIT, - MFD_NEXTLINE, - MFD_HEADER, - MFD_POST_HEADER, - MFD_PARAM, - MFD_UPLOAD, - MFD_MIXED, - MFD_COMPLETE, - MFD_ERROR - } status; - apr_bucket *eos; - const char *param_name; - apreq_param_t *upload; - unsigned level; -}; - - -/********************* multipart/form-data *********************/ - -APR_INLINE -static apr_status_t brigade_start_string(apr_bucket_brigade *bb, - const char *start_string) -{ - apr_bucket *e; - apr_size_t slen = strlen(start_string); - - for (e = APR_BRIGADE_FIRST(bb); e != APR_BRIGADE_SENTINEL(bb); - e = APR_BUCKET_NEXT(e)) - { - const char *buf; - apr_status_t s, bytes_to_check; - apr_size_t blen; - - if (slen == 0) - return APR_SUCCESS; - - if (APR_BUCKET_IS_EOS(e)) - return APR_EOF; - - s = apr_bucket_read(e, &buf, &blen, APR_BLOCK_READ); - - if (s != APR_SUCCESS) - return s; - - if (blen == 0) - continue; - - bytes_to_check = MIN(slen,blen); - - if (strncmp(buf,start_string,bytes_to_check) != 0) - return APREQ_ERROR_GENERAL; - - slen -= bytes_to_check; - start_string += bytes_to_check; - } - - /* slen > 0, so brigade isn't large enough yet */ - return APR_INCOMPLETE; -} - - -static apr_status_t split_on_bdry(apr_bucket_brigade *out, - apr_bucket_brigade *in, - const apr_strmatch_pattern *pattern, - const char *bdry) -{ - apr_bucket *e = APR_BRIGADE_FIRST(in); - apr_size_t blen = strlen(bdry), off = 0; - - while ( e != APR_BRIGADE_SENTINEL(in) ) { - apr_ssize_t idx; - apr_size_t len; - const char *buf; - apr_status_t s; - - if (APR_BUCKET_IS_EOS(e)) - return APR_EOF; - - s = apr_bucket_read(e, &buf, &len, APR_BLOCK_READ); - if (s != APR_SUCCESS) - return s; - - if (len == 0) { - apr_bucket *f = e; - e = APR_BUCKET_NEXT(e); - apr_bucket_delete(f); - continue; - } - - look_for_boundary_up_front: - if (strncmp(bdry + off, buf, MIN(len, blen - off)) == 0) { - if ( len >= blen - off ) { - /* complete match */ - if (len > blen - off) - apr_bucket_split(e, blen - off); - e = APR_BUCKET_NEXT(e); - - do { - apr_bucket *f = APR_BRIGADE_FIRST(in); - apr_bucket_delete(f); - } while (APR_BRIGADE_FIRST(in) != e); - - return APR_SUCCESS; - } - /* partial match */ - off += len; - e = APR_BUCKET_NEXT(e); - continue; - } - else if (off > 0) { - /* prior (partial) strncmp failed, - * so we can move previous buckets across - * and retest buf against the full bdry. - */ - - /* give hints to GCC by making the brigade volatile, otherwise the - * loop below will end up being endless. See: - * https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=193740 - */ - apr_bucket_brigade * volatile in_v = in; - - do { - apr_bucket *f = APR_BRIGADE_FIRST(in_v); - APR_BUCKET_REMOVE(f); - APR_BRIGADE_INSERT_TAIL(out, f); - } while (e != APR_BRIGADE_FIRST(in_v)); - off = 0; - goto look_for_boundary_up_front; - } - - if (pattern != NULL && len >= blen) { - const char *match = apr_strmatch(pattern, buf, len); - if (match != NULL) - idx = match - buf; - else { - idx = apreq_index(buf + len-blen, blen, bdry, blen, - APREQ_MATCH_PARTIAL); - if (idx >= 0) - idx += len-blen; - } - } - else - idx = apreq_index(buf, len, bdry, blen, APREQ_MATCH_PARTIAL); - - /* Theoretically idx should never be 0 here, because we - * already tested the front of the brigade for a potential match. - * However, it doesn't hurt to allow for the possibility, - * since this will just start the whole loop over again. - */ - if (idx >= 0) - apr_bucket_split(e, idx); - - APR_BUCKET_REMOVE(e); - APR_BRIGADE_INSERT_TAIL(out, e); - e = APR_BRIGADE_FIRST(in); - } - - return APR_INCOMPLETE; -} - - -static -struct mfd_ctx * create_multipart_context(const char *content_type, - apr_pool_t *pool, - apr_bucket_alloc_t *ba, - apr_size_t brigade_limit, - const char *temp_dir, - unsigned level) - -{ - apr_status_t s; - apr_size_t blen; - struct mfd_ctx *ctx; - const char *attr; - char *buf; - - attr = (content_type) ? strchr(content_type, ';') : NULL; - if (!attr) - return NULL; /* missing semicolon */ - - ctx = apr_palloc(pool, sizeof *ctx); - - attr++; - blen = strlen(attr) + 1; - buf = apr_palloc(pool, 4 + blen); - buf += 4; - memcpy(buf, attr, blen); - - s = apreq_header_attribute(buf, "boundary", 8, - (const char **)&ctx->bdry, &blen); - if (s != APR_SUCCESS || !blen) - return NULL; /* missing or empty boundary */ - - ctx->bdry[blen] = 0; - - *--ctx->bdry = '-'; - *--ctx->bdry = '-'; - *--ctx->bdry = '\n'; - *--ctx->bdry = '\r'; - - ctx->status = MFD_INIT; - ctx->pattern = apr_strmatch_precompile(pool, ctx->bdry, 1); - ctx->hdr_parser = apreq_parser_make(pool, ba, "", - apreq_parse_headers, - brigade_limit, - temp_dir, NULL, NULL); - ctx->info = NULL; - ctx->bb = apr_brigade_create(pool, ba); - ctx->in = apr_brigade_create(pool, ba); - ctx->eos = apr_bucket_eos_create(ba); - ctx->next_parser = NULL; - ctx->param_name = NULL; - ctx->upload = NULL; - ctx->level = level; - - return ctx; -} - -APREQ_DECLARE_PARSER(apreq_parse_multipart) -{ - apr_pool_t *pool = parser->pool; - apr_bucket_alloc_t *ba = parser->bucket_alloc; - struct mfd_ctx *ctx = parser->ctx; - apr_status_t s; - - if (ctx == NULL) { - ctx = create_multipart_context(parser->content_type, - pool, ba, - parser->brigade_limit, - parser->temp_dir, 1); - if (ctx == NULL) - return APREQ_ERROR_GENERAL; - - - parser->ctx = ctx; - } - - PARSER_STATUS_CHECK(MFD); - APR_BRIGADE_CONCAT(ctx->in, bb); - - mfd_parse_brigade: - - switch (ctx->status) { - - case MFD_INIT: - { - s = split_on_bdry(ctx->bb, ctx->in, NULL, ctx->bdry + 2); - if (s != APR_SUCCESS) { - apreq_brigade_setaside(ctx->in, pool); - apreq_brigade_setaside(ctx->bb, pool); - return s; - } - ctx->status = MFD_NEXTLINE; - /* Be polite and return any preamble text to the caller. */ - APR_BRIGADE_CONCAT(bb, ctx->bb); - } - - /* fall through */ - - case MFD_NEXTLINE: - { - s = split_on_bdry(ctx->bb, ctx->in, NULL, CRLF); - if (s == APR_EOF) { - ctx->status = MFD_COMPLETE; - return APR_SUCCESS; - } - if (s != APR_SUCCESS) { - apreq_brigade_setaside(ctx->in, pool); - apreq_brigade_setaside(ctx->bb, pool); - return s; - } - if (!APR_BRIGADE_EMPTY(ctx->bb)) { - char *line; - apr_size_t len; - apr_brigade_pflatten(ctx->bb, &line, &len, pool); - - if (len >= 2 && strncmp(line, "--", 2) == 0) { - APR_BRIGADE_CONCAT(bb, ctx->in); - ctx->status = MFD_COMPLETE; - return APR_SUCCESS; - } - apr_brigade_cleanup(ctx->bb); - } - - ctx->status = MFD_HEADER; - ctx->info = NULL; - } - /* fall through */ - - case MFD_HEADER: - { - if (ctx->info == NULL) { - ctx->info = apr_table_make(pool, APREQ_DEFAULT_NELTS); - /* flush out header parser internal structs for reuse */ - ctx->hdr_parser->ctx = NULL; - } - s = apreq_parser_run(ctx->hdr_parser, ctx->info, ctx->in); - switch (s) { - case APR_SUCCESS: - ctx->status = MFD_POST_HEADER; - break; - case APR_INCOMPLETE: - apreq_brigade_setaside(ctx->in, pool); - return APR_INCOMPLETE; - default: - ctx->status = MFD_ERROR; - return s; - } - } - /* fall through */ - - case MFD_POST_HEADER: - { - /* Must handle special case of missing CRLF (mainly - * coming from empty file uploads). See RFC2065 S5.1.1: - * - * body-part = MIME-part-header [CRLF *OCTET] - * - * So the CRLF we already matched in MFD_HEADER may have been - * part of the boundary string! Both Konqueror (v??) and - * Mozilla-0.97 are known to emit such blocks. - * - * Here we first check for this condition with - * brigade_start_string, and prefix the brigade with - * an additional CRLF bucket if necessary. - */ - - const char *cd, *ct, *name, *filename; - apr_size_t nlen, flen; - apr_bucket *e; - - switch (brigade_start_string(ctx->in, ctx->bdry + 2)) { - - case APR_INCOMPLETE: - apreq_brigade_setaside(ctx->in, pool); - return APR_INCOMPLETE; - - case APR_SUCCESS: - /* part has no body- return CRLF to front */ - e = apr_bucket_immortal_create(CRLF, 2, - ctx->bb->bucket_alloc); - APR_BRIGADE_INSERT_HEAD(ctx->in, e); - break; - - default: - ; /* has body, ok */ - } - - cd = apr_table_get(ctx->info, "Content-Disposition"); - - /* First check to see if must descend into a new multipart - * block. If we do, create a new parser and pass control - * to it. - */ - - ct = apr_table_get(ctx->info, "Content-Type"); - - if (ct != NULL && strncmp(ct, "multipart/", 10) == 0) { - struct mfd_ctx *next_ctx; - - if (ctx->level >= MAX_LEVEL) { - ctx->status = MFD_ERROR; - goto mfd_parse_brigade; - } - - next_ctx = create_multipart_context(ct, pool, ba, - parser->brigade_limit, - parser->temp_dir, - ctx->level + 1); - if (next_ctx == NULL) { - ctx->status = MFD_ERROR; - goto mfd_parse_brigade; - } - - if (cd != NULL) { - s = apreq_header_attribute(cd, "name", 4, - &name, &nlen); - if (s == APR_SUCCESS && nlen) { - next_ctx->param_name = apr_pstrmemdup(pool, name, - nlen); - } - else if (s != APREQ_ERROR_NOATTR) { - ctx->status = MFD_ERROR; - goto mfd_parse_brigade; - } - } - if (!next_ctx->param_name) { - const char *cid = apr_table_get(ctx->info, - "Content-ID"); - if (cid) { - next_ctx->param_name = apr_pstrdup(pool, cid); - } - else { - next_ctx->param_name = ""; - } - } - - ctx->next_parser = apreq_parser_make(pool, ba, ct, - apreq_parse_multipart, - parser->brigade_limit, - parser->temp_dir, - parser->hook, - next_ctx); - ctx->status = MFD_MIXED; - goto mfd_parse_brigade; - - } - - /* Look for a normal form-data part. */ - - if (cd != NULL && strncmp(cd, "form-data", 9) == 0) { - s = apreq_header_attribute(cd, "name", 4, &name, &nlen); - if (s != APR_SUCCESS || !nlen) { - ctx->status = MFD_ERROR; - goto mfd_parse_brigade; - } - - s = apreq_header_attribute(cd, "filename", - 8, &filename, &flen); - if (s == APR_SUCCESS && flen) { - apreq_param_t *param; - - param = apreq_param_make(pool, name, nlen, - filename, flen); - if (param == NULL) - return APR_ENOMEM; - apreq_param_tainted_on(param); - param->info = ctx->info; - param->upload - = apr_brigade_create(pool, ctx->bb->bucket_alloc); - ctx->upload = param; - ctx->status = MFD_UPLOAD; - goto mfd_parse_brigade; - } - else if (s != APREQ_ERROR_NOATTR) { - ctx->status = MFD_ERROR; - goto mfd_parse_brigade; - } - else { - ctx->param_name = apr_pstrmemdup(pool, name, nlen); - ctx->status = MFD_PARAM; - /* fall thru */ - } - } - - /* else check for a file part in a multipart section */ - else if (cd != NULL && strncmp(cd, "file", 4) == 0) { - apreq_param_t *param; - - s = apreq_header_attribute(cd, "filename", - 8, &filename, &flen); - if (s != APR_SUCCESS || !flen || !ctx->param_name) { - ctx->status = MFD_ERROR; - goto mfd_parse_brigade; - } - name = ctx->param_name; - nlen = strlen(name); - param = apreq_param_make(pool, name, nlen, - filename, flen); - if (param == NULL) - return APR_ENOMEM; - apreq_param_tainted_on(param); - param->info = ctx->info; - param->upload = apr_brigade_create(pool, - ctx->bb->bucket_alloc); - ctx->upload = param; - ctx->status = MFD_UPLOAD; - goto mfd_parse_brigade; - } - - /* otherwise look for Content-ID in multipart/mixed case */ - else { - const char *cid = apr_table_get(ctx->info, "Content-ID"); - apreq_param_t *param; - - if (cid != NULL) { - name = cid; - nlen = strlen(name); - } - else { - name = ""; - nlen = 0; - } - - filename = ""; - flen = 0; - param = apreq_param_make(pool, name, nlen, - filename, flen); - if (param == NULL) - return APR_ENOMEM; - apreq_param_tainted_on(param); - param->info = ctx->info; - param->upload = apr_brigade_create(pool, - ctx->bb->bucket_alloc); - ctx->upload = param; - ctx->status = MFD_UPLOAD; - goto mfd_parse_brigade; - } - } - /* fall through */ - - case MFD_PARAM: - { - apreq_param_t *param; - apreq_value_t *v; - apr_size_t len; - apr_off_t off; - - s = split_on_bdry(ctx->bb, ctx->in, ctx->pattern, ctx->bdry); - - switch (s) { - - case APR_INCOMPLETE: - apreq_brigade_setaside(ctx->in, pool); - apreq_brigade_setaside(ctx->bb, pool); - return s; - - case APR_SUCCESS: - s = apr_brigade_length(ctx->bb, 1, &off); - if (s != APR_SUCCESS) { - ctx->status = MFD_ERROR; - return s; - } - len = off; - param = apreq_param_make(pool, ctx->param_name, - strlen(ctx->param_name), - NULL, len); - if (param == NULL) - return APR_ENOMEM; - apreq_param_tainted_on(param); - param->info = ctx->info; - - *(const apreq_value_t **)&v = ¶m->v; - apr_brigade_flatten(ctx->bb, v->data, &len); - v->data[len] = 0; - - if (parser->hook != NULL) { - s = apreq_hook_run(parser->hook, param, NULL); - if (s != APR_SUCCESS) { - ctx->status = MFD_ERROR; - return s; - } - } - - apreq_param_charset_set(param, - apreq_charset_divine(v->data, len)); - apreq_value_table_add(v, t); - ctx->status = MFD_NEXTLINE; - ctx->param_name = NULL; - apr_brigade_cleanup(ctx->bb); - goto mfd_parse_brigade; - - default: - ctx->status = MFD_ERROR; - return s; - } - - - } - break; /* not reached */ - - case MFD_UPLOAD: - { - apreq_param_t *param = ctx->upload; - - s = split_on_bdry(ctx->bb, ctx->in, ctx->pattern, ctx->bdry); - switch (s) { - - case APR_INCOMPLETE: - if (parser->hook != NULL) { - s = apreq_hook_run(parser->hook, param, ctx->bb); - if (s != APR_SUCCESS) { - ctx->status = MFD_ERROR; - return s; - } - } - apreq_brigade_setaside(ctx->bb, pool); - apreq_brigade_setaside(ctx->in, pool); - s = apreq_brigade_concat(pool, parser->temp_dir, - parser->brigade_limit, - param->upload, ctx->bb); - return (s == APR_SUCCESS) ? APR_INCOMPLETE : s; - - case APR_SUCCESS: - if (parser->hook != NULL) { - APR_BRIGADE_INSERT_TAIL(ctx->bb, ctx->eos); - s = apreq_hook_run(parser->hook, param, ctx->bb); - APR_BUCKET_REMOVE(ctx->eos); - if (s != APR_SUCCESS) { - ctx->status = MFD_ERROR; - return s; - } - } - apreq_value_table_add(¶m->v, t); - apreq_brigade_setaside(ctx->bb, pool); - s = apreq_brigade_concat(pool, parser->temp_dir, - parser->brigade_limit, - param->upload, ctx->bb); - - if (s != APR_SUCCESS) - return s; - - ctx->status = MFD_NEXTLINE; - goto mfd_parse_brigade; - - default: - ctx->status = MFD_ERROR; - return s; - } - - } - break; /* not reached */ - - - case MFD_MIXED: - { - s = apreq_parser_run(ctx->next_parser, t, ctx->in); - switch (s) { - case APR_SUCCESS: - ctx->status = MFD_INIT; - ctx->param_name = NULL; - goto mfd_parse_brigade; - case APR_INCOMPLETE: - APR_BRIGADE_CONCAT(bb, ctx->in); - return APR_INCOMPLETE; - default: - ctx->status = MFD_ERROR; - return s; - } - - } - break; /* not reached */ - - default: - return APREQ_ERROR_GENERAL; - } - - return APR_INCOMPLETE; -} diff --git a/server/apreq_parser_urlencoded.c b/server/apreq_parser_urlencoded.c deleted file mode 100644 index fd8945596c8..00000000000 --- a/server/apreq_parser_urlencoded.c +++ /dev/null @@ -1,277 +0,0 @@ -/* -** Licensed to the Apache Software Foundation (ASF) under one or more -** contributor license agreements. See the NOTICE file distributed with -** this work for additional information regarding copyright ownership. -** The ASF licenses this file to You under the Apache License, Version 2.0 -** (the "License"); you may not use this file except in compliance with -** the License. You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#include "apreq_parser.h" -#include "apreq_util.h" -#include "apreq_error.h" - - -#define PARSER_STATUS_CHECK(PREFIX) do { \ - if (ctx->status == PREFIX##_ERROR) \ - return APREQ_ERROR_GENERAL; \ - else if (ctx->status == PREFIX##_COMPLETE) \ - return APR_SUCCESS; \ - else if (bb == NULL) \ - return APR_INCOMPLETE; \ -} while (0); - - - -struct url_ctx { - apr_bucket_brigade *bb; - apr_size_t nlen; - apr_size_t vlen; - enum { - URL_NAME, - URL_VALUE, - URL_COMPLETE, - URL_ERROR - } status; -}; - - -/******************** application/x-www-form-urlencoded ********************/ - -static apr_status_t split_urlword(apreq_param_t **p, apr_pool_t *pool, - apr_bucket_brigade *bb, - apr_size_t nlen, - apr_size_t vlen) -{ - apreq_param_t *param; - apreq_value_t *v; - apr_bucket *e, *f; - apr_status_t s; - struct iovec vec[APREQ_DEFAULT_NELTS]; - apr_array_header_t arr; - apr_size_t mark; - apreq_charset_t charset; - - if (nlen == 0) - return APR_EBADARG; - - param = apreq_param_make(pool, NULL, nlen, NULL, vlen); - if (param == NULL) - return APR_ENOMEM; - *(const apreq_value_t **)&v = ¶m->v; - - arr.pool = pool; - arr.elt_size = sizeof(struct iovec); - arr.nelts = 0; - arr.nalloc = APREQ_DEFAULT_NELTS; - arr.elts = (char *)vec; - - ++nlen, ++vlen; - e = APR_BRIGADE_FIRST(bb); - - while (!APR_BUCKET_IS_EOS(e)) { - struct iovec *iov = apr_array_push(&arr); - apr_size_t len; - s = apr_bucket_read(e, (const char **)&iov->iov_base, - &len, APR_BLOCK_READ); - if (s != APR_SUCCESS) - return s; - - iov->iov_len = len; - nlen -= len; - - e = APR_BUCKET_NEXT(e); - - if (nlen == 0) { - iov->iov_len--; - break; - } - } - - mark = arr.nelts; - - while (!APR_BUCKET_IS_EOS(e)) { - struct iovec *iov = apr_array_push(&arr); - apr_size_t len; - s = apr_bucket_read(e, (const char **)&iov->iov_base, - &len, APR_BLOCK_READ); - if (s != APR_SUCCESS) - return s; - - iov->iov_len = len; - vlen -= len; - - e = APR_BUCKET_NEXT(e); - - if (vlen == 0) { - iov->iov_len--; - break; - } - - } - - s = apreq_decodev(v->data, &vlen, - (struct iovec *)arr.elts + mark, arr.nelts - mark); - if (s != APR_SUCCESS) - return s; - - charset = apreq_charset_divine(v->data, vlen); - - v->name = v->data + vlen + 1; - v->dlen = vlen; - - s = apreq_decodev(v->name, &nlen, (struct iovec *)arr.elts, mark); - if (s != APR_SUCCESS) - return s; - - switch (apreq_charset_divine(v->name, 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; - } - - v->nlen = nlen; - - while ((f = APR_BRIGADE_FIRST(bb)) != e) - apr_bucket_delete(f); - - apreq_param_tainted_on(param); - apreq_param_charset_set(param, charset); - *p = param; - return APR_SUCCESS; -} - -APREQ_DECLARE_PARSER(apreq_parse_urlencoded) -{ - apr_pool_t *pool = parser->pool; - apr_bucket *e; - struct url_ctx *ctx; - - if (parser->ctx == NULL) { - ctx = apr_pcalloc(pool, sizeof *ctx); - ctx->bb = apr_brigade_create(pool, parser->bucket_alloc); - parser->ctx = ctx; - ctx->status = URL_NAME; - } - else - ctx = parser->ctx; - - PARSER_STATUS_CHECK(URL); - e = APR_BRIGADE_LAST(ctx->bb); - APR_BRIGADE_CONCAT(ctx->bb, bb); - - parse_url_brigade: - - for (e = APR_BUCKET_NEXT(e); - e != APR_BRIGADE_SENTINEL(ctx->bb); - e = APR_BUCKET_NEXT(e)) - { - apreq_param_t *param; - apr_size_t off = 0, dlen; - const char *data; - apr_status_t s; - - if (APR_BUCKET_IS_EOS(e)) { - if (ctx->status == URL_NAME) { - s = APR_SUCCESS; - } - else { - s = split_urlword(¶m, pool, ctx->bb, ctx->nlen, ctx->vlen); - if (parser->hook != NULL && s == APR_SUCCESS) - s = apreq_hook_run(parser->hook, param, NULL); - - if (s == APR_SUCCESS) { - apreq_value_table_add(¶m->v, t); - ctx->status = URL_COMPLETE; - } - else { - ctx->status = URL_ERROR; - } - } - - APR_BRIGADE_CONCAT(bb, ctx->bb); - return s; - } - - s = apr_bucket_read(e, &data, &dlen, APR_BLOCK_READ); - if ( s != APR_SUCCESS ) { - ctx->status = URL_ERROR; - return s; - } - - parse_url_bucket: - - switch (ctx->status) { - - case URL_NAME: - while (off < dlen) { - switch (data[off++]) { - case '=': - apr_bucket_split(e, off); - dlen -= off; - data += off; - off = 0; - e = APR_BUCKET_NEXT(e); - ctx->status = URL_VALUE; - goto parse_url_bucket; - default: - ++ctx->nlen; - } - } - break; - - case URL_VALUE: - while (off < dlen) { - - switch (data[off++]) { - case '&': - case ';': - apr_bucket_split(e, off); - s = split_urlword(¶m, pool, ctx->bb, - ctx->nlen, ctx->vlen); - if (parser->hook != NULL && s == APR_SUCCESS) - s = apreq_hook_run(parser->hook, param, NULL); - - if (s != APR_SUCCESS) { - ctx->status = URL_ERROR; - return s; - } - - apreq_value_table_add(¶m->v, t); - ctx->status = URL_NAME; - ctx->nlen = 0; - ctx->vlen = 0; - e = APR_BRIGADE_SENTINEL(ctx->bb); - goto parse_url_brigade; - - default: - ++ctx->vlen; - } - } - break; - default: - ; /* not reached */ - } - } - apreq_brigade_setaside(ctx->bb, pool); - return APR_INCOMPLETE; -} - - diff --git a/server/apreq_util.c b/server/apreq_util.c deleted file mode 100644 index 11b66f9a147..00000000000 --- a/server/apreq_util.c +++ /dev/null @@ -1,1228 +0,0 @@ -/* -** Licensed to the Apache Software Foundation (ASF) under one or more -** contributor license agreements. See the NOTICE file distributed with -** this work for additional information regarding copyright ownership. -** The ASF licenses this file to You under the Apache License, Version 2.0 -** (the "License"); you may not use this file except in compliance with -** the License. You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -#include "apreq_util.h" -#include "apreq_error.h" -#include "apr_time.h" -#include "apr_strings.h" -#include "apr_lib.h" -#include - -#undef MAX -#undef MIN -#define MIN(a,b) ( (a) < (b) ? (a) : (b) ) -#define MAX(a,b) ( (a) > (b) ? (a) : (b) ) - -/* used for specifying file sizes */ - -APREQ_DECLARE(apr_int64_t) apreq_atoi64f(const char *s) -{ - apr_int64_t n = 0; - char *p; - if (s == NULL) - return 0; - - n = apr_strtoi64(s, &p, 0); - - if (p == NULL) - return n; - while (apr_isspace(*p)) - ++p; - - switch (*p) { - case 'G': /* fall thru */ - case 'g': return n * 1024*1024*1024; - case 'M': /* fall thru */ - case 'm': return n * 1024*1024; - case 'K': /* fall thru */ - case 'k': return n * 1024; - } - - return n; -} - - -/* converts date offsets (e.g. "+3M") to seconds */ - -APREQ_DECLARE(apr_int64_t) apreq_atoi64t(const char *s) -{ - apr_int64_t n = 0; - char *p; - if (s == NULL) - return 0; - n = apr_strtoi64(s, &p, 0); /* XXX: what about overflow? */ - - if (p == NULL) - return n; - while (apr_isspace(*p)) - ++p; - - switch (*p) { - case 'Y': /* fall thru */ - case 'y': return n * 60*60*24*365; - case 'M': return n * 60*60*24*30; - case 'D': /* fall thru */ - case 'd': return n * 60*60*24; - case 'H': /* fall thru */ - case 'h': return n * 60*60; - case 'm': return n * 60; - case 's': /* fall thru */ - default: - return n; - } - /* should never get here */ - return -1; -} - - -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) -{ - apr_size_t len = hlen; - const char *end = hay + hlen; - const char *begin = hay; - - while ( (hay = memchr(hay, ndl[0], len)) ) { - len = end - hay; - - /* done if matches up to capacity of buffer */ - if ( memcmp(hay, ndl, MIN(nlen, len)) == 0 ) { - if (type == APREQ_MATCH_FULL && len < nlen) - hay = NULL; /* insufficient room for match */ - break; - } - --len; - ++hay; - } - - return hay ? hay - begin : -1; -} - - -static const char c2x_table[] = "0123456789ABCDEF"; -static APR_INLINE unsigned char hex2_to_char(const char *what) -{ - register unsigned char digit; - -#if !APR_CHARSET_EBCDIC - digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A') + 10 : (what[0] - '0')); - digit *= 16; - digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A') + 10 : (what[1] - '0')); -#else /*APR_CHARSET_EBCDIC*/ - char xstr[5]; - xstr[0]='0'; - xstr[1]='x'; - xstr[2]=what[0]; - xstr[3]=what[1]; - xstr[4]='\0'; - digit = apr_xlate_conv_byte(ap_hdrs_from_ascii, 0xFF & strtol(xstr, NULL, 16)); -#endif /*APR_CHARSET_EBCDIC*/ - return (digit); -} - - -/* Unicode notes: "bmp" refers to the 16-bit - * Unicode Basic Multilingual Plane. Here we're - * restricting our unicode internals to 16-bit - * codepoints, to keep the code as simple as possible. - * This should be sufficient for apreq itself, since - * we really only need to validate RFC3986-encoded utf8. - */ - -/* Converts Windows cp1252 to Unicode. */ - -static APR_INLINE -apr_uint16_t cp1252_to_bmp(unsigned char c) -{ - /* We only need to deal with iso-8859-1 control chars - * in the 0x80 - 0x9F range. - */ - if ((c & 0xE0) != 0x80) - return c; - - switch (c) { - case 0x80: return 0x20AC; - case 0x82: return 0x201A; - case 0x83: return 0x192; - case 0x84: return 0x201E; - case 0x85: return 0x2026; - case 0x86: return 0x2020; - case 0x87: return 0x2021; - case 0x88: return 0x2C6; - case 0x89: return 0x2030; - case 0x8A: return 0x160; - case 0x8B: return 0x2039; - case 0x8C: return 0x152; - case 0x8E: return 0x17D; - case 0x91: return 0x2018; - case 0x92: return 0x2019; - case 0x93: return 0x201C; - case 0x94: return 0x201D; - case 0x95: return 0x2022; - case 0x96: return 0x2013; - case 0x97: return 0x2014; - case 0x98: return 0x2DC; - case 0x99: return 0x2122; - case 0x9A: return 0x161; - case 0x9B: return 0x203A; - case 0x9C: return 0x153; - case 0x9E: return 0x17E; - case 0x9F: return 0x178; - } - return c; -} - -/* converts cp1252 to utf8 */ -APREQ_DECLARE(apr_size_t) apreq_cp1252_to_utf8(char *dest, - const char *src, apr_size_t slen) -{ - const unsigned char *s = (unsigned const char *)src; - const unsigned char *end = s + slen; - unsigned char *d = (unsigned char *)dest; - apr_uint16_t c; - - while (s < end) { - c = cp1252_to_bmp(*s++); - - if (c < 0x80) { - *d++ = c; - } - else if (c < 0x800) { - *d++ = 0xC0 | (c >> 6); - *d++ = 0x80 | (c & 0x3F); - } - else { - *d++ = 0xE0 | (c >> 12); - *d++ = 0x80 | ((c >> 6) & 0x3F); - *d++ = 0x80 | (c & 0x3F); - } - } - *d = 0; - return d - (unsigned char *)dest; -} - - -/** - * Valid utf8 bit patterns: (true utf8 must satisfy a minimality condition) - * - * 0aaaaaaa - * 110bbbba 10aaaaaa minimality mask: 0x1E - * 1110cccc 10cbbbba 10aaaaaa 0x0F || 0x20 - * 11110ddd 10ddcccc 10cbbbba 10aaaaaa 0x07 || 0x30 - * 111110ee 10eeeddd 10ddcccc 10cbbbba 10aaaaaa 0x03 || 0x38 - * 1111110f 10ffffee 10eeeddd 10ddcccc 10cbbbba 10aaaaaa 0x01 || 0x3C - * - * Charset divination heuristics: - * 1) presume ascii; if not, then - * 2) presume utf8; if not, then - * 3) presume latin1; unless there are control chars, in which case - * 4) punt to cp1252. - * - * Note: in downgrading from 2 to 3, we need to be careful - * about earlier control characters presumed to be valid utf8. - */ - -APREQ_DECLARE(apreq_charset_t) apreq_charset_divine(const char *src, - apr_size_t slen) - -{ - apreq_charset_t rv = APREQ_CHARSET_ASCII; - register unsigned char trail = 0, saw_cntrl = 0, mask = 0; - register const unsigned char *s = (const unsigned char *)src; - const unsigned char *end = s + slen; - - for (; s < end; ++s) { - if (trail) { - if ((*s & 0xC0) == 0x80 && (mask == 0 || (mask & *s))) { - mask = 0; - --trail; - - if ((*s & 0xE0) == 0x80) { - saw_cntrl = 1; - } - } - else { - trail = 0; - if (saw_cntrl) - return APREQ_CHARSET_CP1252; - rv = APREQ_CHARSET_LATIN1; - } - } - else if (*s < 0x80) { - /* do nothing */ - } - else if (*s < 0xA0) { - return APREQ_CHARSET_CP1252; - } - else if (*s < 0xC0) { - if (saw_cntrl) - return APREQ_CHARSET_CP1252; - rv = APREQ_CHARSET_LATIN1; - } - else if (rv == APREQ_CHARSET_LATIN1) { - /* do nothing */ - } - - /* utf8 cases */ - - else if (*s < 0xE0) { - if (*s & 0x1E) { - rv = APREQ_CHARSET_UTF8; - trail = 1; - mask = 0; - } - else if (saw_cntrl) - return APREQ_CHARSET_CP1252; - else - rv = APREQ_CHARSET_LATIN1; - } - else if (*s < 0xF0) { - mask = (*s & 0x0F) ? 0 : 0x20; - rv = APREQ_CHARSET_UTF8; - trail = 2; - } - else if (*s < 0xF8) { - mask = (*s & 0x07) ? 0 : 0x30; - rv = APREQ_CHARSET_UTF8; - trail = 3; - } - else if (*s < 0xFC) { - mask = (*s & 0x03) ? 0 : 0x38; - rv = APREQ_CHARSET_UTF8; - trail = 4; - } - else if (*s < 0xFE) { - mask = (*s & 0x01) ? 0 : 0x3C; - rv = APREQ_CHARSET_UTF8; - trail = 5; - } - else { - rv = APREQ_CHARSET_UTF8; - } - } - - return trail ? saw_cntrl ? - APREQ_CHARSET_CP1252 : APREQ_CHARSET_LATIN1 : rv; -} - - -static APR_INLINE apr_uint16_t hex4_to_bmp(const char *what) -{ - register apr_uint16_t digit = 0; - -#if !APR_CHARSET_EBCDIC - digit = (what[0] >= 'A' ? ((what[0] & 0xDF)-'A') + 10 : (what[0]-'0')); - digit *= 16; - digit += (what[1] >= 'A' ? ((what[1] & 0xDF)-'A') + 10 : (what[1]-'0')); - digit *= 16; - digit += (what[2] >= 'A' ? ((what[2] & 0xDF)-'A') + 10 : (what[2]-'0')); - digit *= 16; - digit += (what[3] >= 'A' ? ((what[3] & 0xDF)-'A') + 10 : (what[3]-'0')); - -#else /*APR_CHARSET_EBCDIC*/ - char xstr[7]; - xstr[0]='0'; - xstr[1]='x'; - xstr[2]=what[0]; - xstr[3]=what[1]; - xstr[4]=what[2]; - xstr[5]=what[3]; - xstr[6]='\0'; - digit = apr_xlate_conv_byte(ap_hdrs_from_ascii, 0xFFFF & strtol(xstr, NULL, 16)); -#endif /*APR_CHARSET_EBCDIC*/ - return (digit); -} - - -static apr_status_t url_decode(char *dest, apr_size_t *dlen, - const char *src, apr_size_t *slen) -{ - register const char *s = src; - unsigned char *start = (unsigned char *)dest; - register unsigned char *d = (unsigned char *)dest; - const char *end = src + *slen; - - for (; s < end; ++d, ++s) { - switch (*s) { - - case '+': - *d = ' '; - break; - - case '%': - if (s + 2 < end && apr_isxdigit(s[1]) && apr_isxdigit(s[2])) { - *d = hex2_to_char(s + 1); - s += 2; - } - else if (s + 5 < end && (s[1] == 'u' || s[1] == 'U') && - apr_isxdigit(s[2]) && apr_isxdigit(s[3]) && - apr_isxdigit(s[4]) && apr_isxdigit(s[5])) - { - apr_uint16_t c = hex4_to_bmp(s+2); - - if (c < 0x80) { - *d = c; - } - else if (c < 0x800) { - *d++ = 0xC0 | (c >> 6); - *d = 0x80 | (c & 0x3F); - } - else { - *d++ = 0xE0 | (c >> 12); - *d++ = 0x80 | ((c >> 6) & 0x3F); - *d = 0x80 | (c & 0x3F); - } - s += 5; - } - else { - *dlen = d - start; - *slen = s - src; - if (s + 5 < end - || (s + 2 < end && !apr_isxdigit(s[2])) - || (s + 1 < end && !apr_isxdigit(s[1]) - && s[1] != 'u' && s[1] != 'U')) - { - *d = 0; - return APREQ_ERROR_BADSEQ; - } - - memmove(d, s, end - s); - d[end - s] = 0; - return APR_INCOMPLETE; - } - break; - - default: - if (*s > 0) { - *d = *s; - } - else { - *d = 0; - *dlen = d - start; - *slen = s - src; - return APREQ_ERROR_BADCHAR; - } - } - } - - *d = 0; - *dlen = d - start; - *slen = s - src; - return APR_SUCCESS; -} - - -APREQ_DECLARE(apr_status_t) apreq_decode(char *d, apr_size_t *dlen, - const char *s, apr_size_t slen) -{ - apr_size_t len = 0; - const char *end = s + slen; - - if (s == (const char *)d) { /* optimize for src = dest case */ - for ( ; d < end; ++d) { - if (*d == '%' || *d == '+') - break; - else if (*d == 0) { - *dlen = (const char *)d - s; - return APREQ_ERROR_BADCHAR; - } - } - len = (const char *)d - s; - s = (const char *)d; - slen -= len; - } - - return url_decode(d, dlen, s, &slen); -} - -APREQ_DECLARE(apr_status_t) apreq_decodev(char *d, apr_size_t *dlen, - struct iovec *v, int nelts) -{ - apr_status_t status = APR_SUCCESS; - int n = 0; - - *dlen = 0; - - while (n < nelts) { - apr_size_t slen, len; - - slen = v[n].iov_len; - switch (status = url_decode(d, &len, v[n].iov_base, &slen)) { - - case APR_SUCCESS: - d += len; - *dlen += len; - ++n; - continue; - - case APR_INCOMPLETE: - d += len; - *dlen += len; - slen = v[n].iov_len - slen; - - if (++n == nelts) { - return status; - } - memcpy(d + slen, v[n].iov_base, v[n].iov_len); - v[n].iov_len += slen; - v[n].iov_base = d; - continue; - - default: - *dlen += len; - return status; - } - } - - return status; -} - - -APREQ_DECLARE(apr_size_t) apreq_encode(char *dest, const char *src, - const apr_size_t slen) -{ - char *d = dest; - const unsigned char *s = (const unsigned char *)src; - unsigned char c; - - for ( ; s < (const unsigned char *)src + slen; ++s) { - c = *s; - if ( c < 0x80 && (apr_isalnum(c) - || c == '-' || c == '.' - || c == '_' || c == '~') ) - *d++ = c; - - else if ( c == ' ' ) - *d++ = '+'; - - else { -#if APR_CHARSET_EBCDIC - c = apr_xlate_conv_byte(ap_hdrs_to_ascii, (unsigned char)c); -#endif - *d++ = '%'; - *d++ = c2x_table[c >> 4]; - *d++ = c2x_table[c & 0xf]; - } - } - *d = 0; - - return d - dest; -} - -static int is_quoted(const char *p, const apr_size_t len) -{ - if (len > 1 && p[0] == '"' && p[len-1] == '"') { - apr_size_t i; - int backslash = 0; - - for (i = 1; i < len - 1; i++) { - if (p[i] == '\\') - backslash = !backslash; - else if (p[i] == 0 || (p[i] == '"' && !backslash)) - return 0; - else - backslash = 0; - } - - return !backslash; - } - - return 0; -} - -APREQ_DECLARE(apr_size_t) apreq_quote_once(char *dest, const char *src, - const apr_size_t slen) -{ - if (is_quoted(src, slen)) { - /* looks like src is already quoted */ - memcpy(dest, src, slen); - dest[slen] = 0; - 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; - } - - *d++ = '"'; - - while (s <= last) { - switch (*s) { - case 0: - *d++ = '\\'; - *d++ = '0'; - s++; - break; - - case '\\': - case '"': - *d++ = '\\'; - - default: - *d++ = *s++; - } - } - - *d++ = '"'; - *d = 0; - - return d - dest; -} - -APREQ_DECLARE(char *) apreq_join(apr_pool_t *p, - const char *sep, - const apr_array_header_t *arr, - apreq_join_t mode) -{ - apr_size_t len, slen; - char *rv; - const apreq_value_t **a = (const apreq_value_t **)arr->elts; - char *d; - const int n = arr->nelts; - int j; - - slen = sep ? strlen(sep) : 0; - - if (n == 0) - return apr_pstrdup(p, ""); - - for (j=0, len=0; j < n; ++j) - len += a[j]->dlen + slen + 1; - - /* Allocated the required space */ - - switch (mode) { - case APREQ_JOIN_ENCODE: - len += 2 * len; - break; - case APREQ_JOIN_QUOTE: - len = 2 * (len + n); - break; - case APREQ_JOIN_AS_IS: - case APREQ_JOIN_DECODE: - /* nothing special required, just here to keep noisy compilers happy */ - break; - } - - rv = apr_palloc(p, len); - - /* Pass two --- copy the argument strings into the result space */ - - d = rv; - - switch (mode) { - - case APREQ_JOIN_ENCODE: - d += apreq_encode(d, a[0]->data, a[0]->dlen); - - for (j = 1; j < n; ++j) { - memcpy(d, sep, slen); - d += slen; - d += apreq_encode(d, a[j]->data, a[j]->dlen); - } - break; - - case APREQ_JOIN_DECODE: - if (apreq_decode(d, &len, a[0]->data, a[0]->dlen)) - return NULL; - else - d += len; - - for (j = 1; j < n; ++j) { - memcpy(d, sep, slen); - d += slen; - - if (apreq_decode(d, &len, a[j]->data, a[j]->dlen)) - return NULL; - else - d += len; - } - break; - - - case APREQ_JOIN_QUOTE: - d += apreq_quote_once(d, a[0]->data, a[0]->dlen); - - for (j = 1; j < n; ++j) { - memcpy(d, sep, slen); - d += slen; - d += apreq_quote_once(d, a[j]->data, a[j]->dlen); - } - break; - - - case APREQ_JOIN_AS_IS: - memcpy(d,a[0]->data, a[0]->dlen); - d += a[0]->dlen; - - for (j = 1; j < n ; ++j) { - memcpy(d, sep, slen); - d += slen; - memcpy(d, a[j]->data, a[j]->dlen); - d += a[j]->dlen; - } - break; - } - - *d = 0; - return rv; -} - -/* - * This is intentionally not apr_file_writev() - * note, this is iterative and not recursive - */ -APR_INLINE -static apr_status_t apreq_fwritev(apr_file_t *f, struct iovec *v, - int *nelts, apr_size_t *bytes_written) -{ - apr_size_t len; - int n; - apr_status_t s; - - *bytes_written = 0; - - while (1) { - /* try to write */ - s = apr_file_writev(f, v, *nelts, &len); - - *bytes_written += len; - - if (s != APR_SUCCESS) - return s; - - /* see how far we've come */ - n = 0; - -#ifdef SOLARIS2 -# ifdef __GNUC__ - /* - * iovec.iov_len is a long here - * which causes a comparison between - * signed(long) and unsigned(apr_size_t) - * - */ - while (n < *nelts && len >= (apr_size_t)v[n].iov_len) -# else - /* - * Sun C however defines this as size_t which is unsigned - * - */ - while (n < *nelts && len >= v[n].iov_len) -# endif /* !__GNUC__ */ -#else - /* - * Hopefully everything else does this - * (this was the default for years) - */ - while (n < *nelts && len >= v[n].iov_len) -#endif - len -= v[n++].iov_len; - - if (n == *nelts) { - /* nothing left to write, report success */ - *nelts = 0; - return APR_SUCCESS; - } - - /* incomplete write: must shift v */ - v[n].iov_len -= len; - v[n].iov_base = (char *)(v[n].iov_base) + len; - - if (n > 0) { - /* we're satisfied for now if we can remove one iovec from - the "v" array */ - (*nelts) -= n; - memmove(v, v + n, sizeof(*v) * *nelts); - - return APR_SUCCESS; - } - - /* we're still in the first iovec - check for endless loop, - and then try again */ - if (len == 0) - return APREQ_ERROR_GENERAL; - } -} - - - - -struct cleanup_data { - const char *fname; - apr_pool_t *pool; -}; - -static apr_status_t apreq_file_cleanup(void *d) -{ - struct cleanup_data *data = d; - return apr_file_remove(data->fname, data->pool); -} - -/* - * The reason we need the above cleanup is because on Windows, APR_DELONCLOSE - * forces applications to open the file with FILE_SHARED_DELETE - * set, which is, unfortunately, a property that is preserved - * across NTFS "hard" links. This breaks apps that link() the temp - * file to a permanent location, and subsequently expect to open it - * before the original tempfile is closed+deleted. In fact, even - * Apache::Upload does this, so it is a common enough event that the - * apreq_file_cleanup workaround is necessary. - */ - -APREQ_DECLARE(apr_status_t) apreq_file_mktemp(apr_file_t **fp, - apr_pool_t *pool, - const char *path) -{ - apr_status_t rc; - char *tmpl; - struct cleanup_data *data; - apr_int32_t flag; - - if (path == NULL) { - rc = apr_temp_dir_get(&path, pool); - if (rc != APR_SUCCESS) - return rc; - } - rc = apr_filepath_merge(&tmpl, path, "apreqXXXXXX", - APR_FILEPATH_NOTRELATIVE, pool); - - if (rc != APR_SUCCESS) - return rc; - - data = apr_palloc(pool, sizeof *data); - /* cleanups are LIFO, so this one will run just after - the cleanup set by mktemp */ - apr_pool_cleanup_register(pool, data, - apreq_file_cleanup, apreq_file_cleanup); - - /* NO APR_DELONCLOSE! see comment above */ - flag = APR_CREATE | APR_READ | APR_WRITE | APR_EXCL | APR_BINARY; - - rc = apr_file_mktemp(fp, tmpl, flag, pool); - - if (rc == APR_SUCCESS) { - apr_file_name_get(&data->fname, *fp); - data->pool = pool; - } - else { - apr_pool_cleanup_kill(pool, data, apreq_file_cleanup); - } - - return rc; -} - - -#define IS_SPACE_CHAR(c) ((c) == '\t' || (c) == ' ') -#define IS_TOKEN_CHAR(c) (apr_isalnum(c) \ - || ((c) && strchr("!#$%&'*+-.^_`|~", (c)))) - -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) -{ - int done = 0; - - if (!nlen) - return APREQ_ERROR_NOATTR; - - do { - const char *hde, *v; - apr_size_t tail = 0; - - /* Parse the name => [hdr:hde[ */ - hde = hdr; - look_for_end_name: - switch (*hde) { - case 0: - case '\r': - case '\n': - done = 1; - case '=': - case ';': - case ',': - v = hde; - hde -= tail; - break; - case ' ': - case '\t': - if (hde == hdr) - ++hdr; - else - ++tail; - ++hde; - goto look_for_end_name; - default: - /* The name is a token */ - if (!IS_TOKEN_CHAR(*hde)) - return APREQ_ERROR_BADCHAR; - /* Nothing after the tail */ - if (tail) - return APREQ_ERROR_BADATTR; - ++hde; - goto look_for_end_name; - } - - /* Parse the value => (*val, *vlen) */ - if (*v == '=') { - if (hde == hdr) { - /* The name can't be empty */ - return APREQ_ERROR_BADATTR; - } - - ++v; - while (IS_SPACE_CHAR(*v)) - ++v; - - /* Quoted string ? */ - if (*v == '"') { - *val = ++v; - - /* XXX: the interface does not permit unescaping, - * it should have pool to allocate from. - * The caller can't know whether a returned '\\' is - * a quoted-char or not.. - */ - look_for_end_quote: - switch (*v) { - case 0: - case '\r': - case '\n': - return APREQ_ERROR_BADSEQ; - case '"': - *vlen = v - *val; - break; - case '\\': - if (v[1] != 0) - ++v; - ++v; - goto look_for_end_quote; - default: - if (apr_iscntrl(*v)) - return APREQ_ERROR_BADCHAR; - ++v; - goto look_for_end_quote; - } - - look_for_after_quote: - switch (*v) { - case 0: - case '\r': - case '\n': - done = 1; - case ';': - case ',': - break; - case ' ': - case '\t': - goto look_for_after_quote; - default: - if (apr_iscntrl(*v)) - return APREQ_ERROR_BADCHAR; - return APREQ_ERROR_BADSEQ; - } - } - else { - *val = v; - tail = 0; - - look_for_end_value: - switch (*v) { - case 0: - case '\r': - case '\n': - done = 1; - case ';': - case ',': - *vlen = v - *val - tail; - break; - case ' ': - case '\t': - if (*val == v) - ++*val; - else - ++tail; - ++v; - goto look_for_end_value; - default: - if (apr_iscntrl(*v)) - return APREQ_ERROR_BADCHAR; - ++v; - tail = 0; - goto look_for_end_value; - } - } - } - else { - *val = NULL; - *vlen = 0; - } - - if (hdr + nlen == hde && strncasecmp(hdr, name, nlen) == 0) { - return APR_SUCCESS; - } - - hdr = v + 1; - } while (!done); - - return APREQ_ERROR_NOATTR; -} - - - -#define BUCKET_IS_SPOOL(e) ((e)->type == &spool_bucket_type) -#define FILE_BUCKET_LIMIT ((apr_size_t)-1 - 1) - -static -void spool_bucket_destroy(void *data) -{ - apr_bucket_type_file.destroy(data); -} - -static -apr_status_t spool_bucket_read(apr_bucket *e, const char **str, - apr_size_t *len, apr_read_type_e block) -{ - return apr_bucket_type_file.read(e, str, len, block); -} - -static -apr_status_t spool_bucket_setaside(apr_bucket *data, apr_pool_t *reqpool) -{ - return apr_bucket_type_file.setaside(data, reqpool); -} - -static -apr_status_t spool_bucket_split(apr_bucket *a, apr_size_t point) -{ - apr_status_t rv = apr_bucket_shared_split(a, point); - a->type = &apr_bucket_type_file; - return rv; -} - -static -apr_status_t spool_bucket_copy(apr_bucket *e, apr_bucket **c) -{ - apr_status_t rv = apr_bucket_shared_copy(e, c); - (*c)->type = &apr_bucket_type_file; - return rv; -} - -static const apr_bucket_type_t spool_bucket_type = { - "APREQ_SPOOL", 5, APR_BUCKET_DATA, - spool_bucket_destroy, - spool_bucket_read, - spool_bucket_setaside, - spool_bucket_split, - spool_bucket_copy, -}; - -APREQ_DECLARE(apr_file_t *)apreq_brigade_spoolfile(apr_bucket_brigade *bb) -{ - apr_bucket *last; - - last = APR_BRIGADE_LAST(bb); - if (BUCKET_IS_SPOOL(last)) - return ((apr_bucket_file *)last->data)->fd; - - return NULL; -} - -APREQ_DECLARE(apr_status_t) apreq_brigade_concat(apr_pool_t *pool, - const char *temp_dir, - apr_size_t heap_limit, - apr_bucket_brigade *out, - apr_bucket_brigade *in) -{ - apr_status_t s; - apr_bucket_file *f; - apr_off_t wlen; - apr_file_t *file; - apr_off_t in_len, out_len; - apr_bucket *last_in, *last_out; - - last_out = APR_BRIGADE_LAST(out); - - if (APR_BUCKET_IS_EOS(last_out)) - return APR_EOF; - - s = apr_brigade_length(out, 0, &out_len); - if (s != APR_SUCCESS) - return s; - - /* This cast, when out_len = -1, is intentional */ - if ((apr_uint64_t)out_len < heap_limit) { - - s = apr_brigade_length(in, 0, &in_len); - if (s != APR_SUCCESS) - return s; - - /* This cast, when in_len = -1, is intentional */ - if ((apr_uint64_t)in_len < heap_limit - (apr_uint64_t)out_len) { - APR_BRIGADE_CONCAT(out, in); - return APR_SUCCESS; - } - } - - if (!BUCKET_IS_SPOOL(last_out)) { - - s = apreq_file_mktemp(&file, pool, temp_dir); - if (s != APR_SUCCESS) - return s; - - s = apreq_brigade_fwrite(file, &wlen, out); - - if (s != APR_SUCCESS) - return s; - - apr_brigade_cleanup(out); - last_out = apr_bucket_file_create(file, 0, wlen, - out->p, out->bucket_alloc); - last_out->type = &spool_bucket_type; - APR_BRIGADE_INSERT_TAIL(out, last_out); - f = last_out->data; - } - else { - f = last_out->data; - /* Need to seek here, just in case our spool bucket - * was read from between apreq_brigade_concat calls. - */ - wlen = last_out->start + last_out->length; - s = apr_file_seek(f->fd, APR_SET, &wlen); - if (s != APR_SUCCESS) - return s; - } - - if (in == out) - return APR_SUCCESS; - - last_in = APR_BRIGADE_LAST(in); - - if (APR_BUCKET_IS_EOS(last_in)) - APR_BUCKET_REMOVE(last_in); - - s = apreq_brigade_fwrite(f->fd, &wlen, in); - - if (s == APR_SUCCESS) { - - /* We have to deal with the possibility that the new - * data may be too large to be represented by a single - * temp_file bucket. - */ - - while ((apr_uint64_t)wlen > FILE_BUCKET_LIMIT - last_out->length) { - apr_bucket *e; - - apr_bucket_copy(last_out, &e); - e->length = 0; - e->start = last_out->start + FILE_BUCKET_LIMIT; - wlen -= FILE_BUCKET_LIMIT - last_out->length; - last_out->length = FILE_BUCKET_LIMIT; - - /* Copying makes the bucket types exactly the - * opposite of what we need here. - */ - last_out->type = &apr_bucket_type_file; - e->type = &spool_bucket_type; - - APR_BRIGADE_INSERT_TAIL(out, e); - last_out = e; - } - - last_out->length += wlen; - - if (APR_BUCKET_IS_EOS(last_in)) - APR_BRIGADE_INSERT_TAIL(out, last_in); - - } - else if (APR_BUCKET_IS_EOS(last_in)) - APR_BRIGADE_INSERT_TAIL(in, last_in); - - apr_brigade_cleanup(in); - return s; -} - -APREQ_DECLARE(apr_status_t) apreq_brigade_fwrite(apr_file_t *f, - apr_off_t *wlen, - apr_bucket_brigade *bb) -{ - struct iovec v[APREQ_DEFAULT_NELTS]; - apr_status_t s; - apr_bucket *e, *first; - int n = 0; - apr_bucket_brigade *tmp = bb; - *wlen = 0; - - if (BUCKET_IS_SPOOL(APR_BRIGADE_LAST(bb))) { - tmp = apr_brigade_create(bb->p, bb->bucket_alloc); - - s = apreq_brigade_copy(tmp, bb); - if (s != APR_SUCCESS) - return s; - } - - for (e = APR_BRIGADE_FIRST(tmp); e != APR_BRIGADE_SENTINEL(tmp); - e = APR_BUCKET_NEXT(e)) - { - apr_size_t len; - if (n == APREQ_DEFAULT_NELTS) { - s = apreq_fwritev(f, v, &n, &len); - if (s != APR_SUCCESS) - return s; - - if (tmp != bb) { - while ((first = APR_BRIGADE_FIRST(tmp)) != e) - apr_bucket_delete(first); - } - - *wlen += len; - } - s = apr_bucket_read(e, (const char **)&(v[n].iov_base), - &len, APR_BLOCK_READ); - if (s != APR_SUCCESS) - return s; - - v[n++].iov_len = len; - } - - while (n > 0) { - apr_size_t len; - s = apreq_fwritev(f, v, &n, &len); - if (s != APR_SUCCESS) - return s; - *wlen += len; - - if (tmp != bb) { - while ((first = APR_BRIGADE_FIRST(tmp)) != e) - apr_bucket_delete(first); - } - } - return APR_SUCCESS; -} From c9da8bc592eae6eb40bf2f9512d48540651e6b13 Mon Sep 17 00:00:00 2001 From: Joe Orton Date: Thu, 23 Apr 2026 15:41:12 +0100 Subject: [PATCH 2/6] Revert "Added apreq to NetWare build." r1201918 This reverts commit 69218cb9126e098cae7e2a7095dd38f66363603f. --- NWGNUmakefile | 11 ----------- build/make_nw_export.awk | 4 ++-- build/nw_export.inc | 12 ------------ modules/NWGNUmakefile | 1 - 4 files changed, 2 insertions(+), 26 deletions(-) diff --git a/NWGNUmakefile b/NWGNUmakefile index 5efac172575..b4621ec8ca3 100644 --- a/NWGNUmakefile +++ b/NWGNUmakefile @@ -218,17 +218,6 @@ TARGET_lib = \ # Paths must all use the '/' character # FILES_nlm_objs = \ - $(OBJDIR)/apreq_cookie.o \ - $(OBJDIR)/apreq_error.o \ - $(OBJDIR)/apreq_module.o \ - $(OBJDIR)/apreq_module_cgi.o \ - $(OBJDIR)/apreq_module_custom.o \ - $(OBJDIR)/apreq_param.o \ - $(OBJDIR)/apreq_parser.o \ - $(OBJDIR)/apreq_parser_header.o \ - $(OBJDIR)/apreq_parser_multipart.o \ - $(OBJDIR)/apreq_parser_urlencoded.o \ - $(OBJDIR)/apreq_util.o \ $(OBJDIR)/buildmark.o \ $(OBJDIR)/config.o \ $(OBJDIR)/connection.o \ diff --git a/build/make_nw_export.awk b/build/make_nw_export.awk index c89d2de25ca..af22eec3da9 100644 --- a/build/make_nw_export.awk +++ b/build/make_nw_export.awk @@ -28,8 +28,8 @@ function add_symbol(sym_name) { # List of functions that we don't support, yet?? #/ap_some_name/{next} -/^[ \t]*(AP|DAV|CACHE|PROXY)([RU]|REQ|_CORE)?_DECLARE[^(]*[(][^)]*[)]([^ ]* )*[^(]+[(]/ { - sub("[ \t]*(AP|DAV|CACHE|PROXY)([RU]|REQ|_CORE)?_DECLARE[^(]*[(][^)]*[)][ \t]*", "") +/^[ \t]*(AP|DAV|CACHE|PROXY)([RU]|_CORE)?_DECLARE[^(]*[(][^)]*[)]([^ ]* )*[^(]+[(]/ { + sub("[ \t]*(AP|DAV|CACHE|PROXY)([RU]|_CORE)?_DECLARE[^(]*[(][^)]*[)][ \t]*", "") sub("[(].*", "") sub("([^ ]* (^([ \t]*[(])))+", "") add_symbol($0) diff --git a/build/nw_export.inc b/build/nw_export.inc index af8d8fe80a2..f0a26f567e5 100644 --- a/build/nw_export.inc +++ b/build/nw_export.inc @@ -23,12 +23,6 @@ #define APR_DECLARE_OPTIONAL_FN APR_DECLARE_OPTIONAL_FN #undef APR_DECLARE_EXTERNAL_HOOK #define APR_DECLARE_EXTERNAL_HOOK APR_DECLARE_EXTERNAL_HOOK -#undef APREQ_DECLARE -#define APREQ_DECLARE APREQ_DECLARE -#undef APREQ_DECLARE_NONSTD -#define APREQ_DECLARE_NONSTD APREQ_DECLARE_NONSTD -#undef APREQ_DECLARE_DATA -#define APREQ_DECLARE_DATA APREQ_DECLARE_DATA #undef APACHE_OS_H #include "httpd.h" @@ -41,12 +35,6 @@ #include "ap_provider.h" #include "ap_release.h" #include "ap_expr.h" -#include "apreq_cookie.h" -#include "apreq_error.h" -#include "apreq_module.h" -#include "apreq_param.h" -#include "apreq_parser.h" -#include "apreq_util.h" #include "http_config.h" #include "http_connection.h" #include "http_core.h" diff --git a/modules/NWGNUmakefile b/modules/NWGNUmakefile index 8535a5862ea..ac8ee3e0351 100644 --- a/modules/NWGNUmakefile +++ b/modules/NWGNUmakefile @@ -33,7 +33,6 @@ endif SUBDIRS = \ aaa \ - apreq \ cache \ cluster \ core \ From fbc88b4583a294ab3a1498ecb8b8f600a93a7c47 Mon Sep 17 00:00:00 2001 From: Joe Orton Date: Thu, 23 Apr 2026 15:43:14 +0100 Subject: [PATCH 3/6] Revert "add apreq in Win32" r1825396 This reverts commit 2d80cdeb7b319cc6ed4772617addc273c1c8913a. --- Apache-apr2.dsw | 24 ----- Apache.dsw | 52 +--------- build/installwinconf.awk | 1 - libapreq.dsp | 200 --------------------------------------- os/win32/BaseAddr.ref | 2 - 5 files changed, 1 insertion(+), 278 deletions(-) delete mode 100644 libapreq.dsp diff --git a/Apache-apr2.dsw b/Apache-apr2.dsw index 95381bec6a7..9a5419c3210 100644 --- a/Apache-apr2.dsw +++ b/Apache-apr2.dsw @@ -87,9 +87,6 @@ Package=<4> Project_Dep_Name httpd End Project Dependency Begin Project Dependency - Project_Dep_Name mod_apreq - End Project Dependency - Begin Project Dependency Project_Dep_Name ApacheMonitor End Project Dependency Begin Project Dependency @@ -744,27 +741,6 @@ Package=<4> ############################################################################### -Project: "libapreq"=.\libapreq.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name libapr - End Project Dependency - Begin Project Dependency - Project_Dep_Name libapriconv - End Project Dependency - Begin Project Dependency - Project_Dep_Name libhttpd - End Project Dependency -}}} - -############################################################################### - Project: "libhttpd"=.\libhttpd.dsp - Package Owner=<4> Package=<5> diff --git a/Apache.dsw b/Apache.dsw index 8124df949c2..f49ff5ef602 100644 --- a/Apache.dsw +++ b/Apache.dsw @@ -90,9 +90,6 @@ Package=<4> Project_Dep_Name httpd End Project Dependency Begin Project Dependency - Project_Dep_Name mod_apreq - End Project Dependency - Begin Project Dependency Project_Dep_Name ApacheMonitor End Project Dependency Begin Project Dependency @@ -906,30 +903,6 @@ Package=<4> ############################################################################### -Project: "libapreq"=.\libapreq.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name libapr - End Project Dependency - Begin Project Dependency - Project_Dep_Name libapriconv - End Project Dependency - Begin Project Dependency - Project_Dep_Name libaprutil - End Project Dependency - Begin Project Dependency - Project_Dep_Name libhttpd - End Project Dependency -}}} - -############################################################################### - Project: "libhttpd"=.\libhttpd.dsp - Package Owner=<4> Package=<5> @@ -1056,30 +1029,6 @@ Package=<4> ############################################################################### -Project: "mod_apreq"=.\modules\apreq\mod_apreq.dsp - Package Owner=<4> - -Package=<5> -{{{ -}}} - -Package=<4> -{{{ - Begin Project Dependency - Project_Dep_Name libapr - End Project Dependency - Begin Project Dependency - Project_Dep_Name libaprutil - End Project Dependency - Begin Project Dependency - Project_Dep_Name libhttpd - End Project Dependency - Begin Project Dependency - Project_Dep_Name libapreq - End Project Dependency -}}} - -############################################################################### - Project: "mod_asis"=.\modules\generators\mod_asis.dsp - Package Owner=<4> Package=<5> @@ -1099,6 +1048,7 @@ Package=<4> End Project Dependency }}} + ############################################################################### Project: "mod_access_compat"=.\modules\aaa\mod_access_compat.dsp - Package Owner=<4> diff --git a/build/installwinconf.awk b/build/installwinconf.awk index a5811a8a7af..5339b8aef9c 100644 --- a/build/installwinconf.awk +++ b/build/installwinconf.awk @@ -99,7 +99,6 @@ BEGIN { print "LoadModule alias_module modules/mod_alias.so" > dstfl; print "#LoadModule allowhandlers_module modules/mod_allowhandlers.so" > dstfl; print "#LoadModule allowmethods_module modules/mod_allowmethods.so" > dstfl; - print "#LoadModule apreq_module modules/mod_apreq.so" > dstfl; print "LoadModule asis_module modules/mod_asis.so" > dstfl; print "LoadModule auth_basic_module modules/mod_auth_basic.so" > dstfl; print "#LoadModule auth_digest_module modules/mod_auth_digest.so" > dstfl; diff --git a/libapreq.dsp b/libapreq.dsp deleted file mode 100644 index a4fb37f4627..00000000000 --- a/libapreq.dsp +++ /dev/null @@ -1,200 +0,0 @@ -# Microsoft Developer Studio Project File - Name="libapreq" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 - -CFG=libapreq - Win32 Release -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "libapreq.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "libapreq.mak" CFG="libapreq - Win32 Release" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "libapreq - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE "libapreq - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" -CPP=cl.exe -MTL=midl.exe -RSC=rc.exe - -!IF "$(CFG)" == "libapreq - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MD /W3 /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "AP_DECLARE_EXPORT" /D "APREQ_DECLARE_EXPORT" /FD /c -# ADD CPP /nologo /MD /W3 /Zi /O2 /Oy- /I "./include" /I "./srclib/apr/include" /I "./srclib/apr-util/include" /I "./srclib/pcre" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "AP_DECLARE_EXPORT" /D "APREQ_DECLARE_EXPORT" /Fd"Release\libapreq_cl" /FD /c -# ADD BASE MTL /nologo /D "NDEBUG" /win32 -# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x409 /d "NDEBUG" -# ADD RSC /l 0x409 /fo"Release/libapreq.res" /i "./include" /i "./srclib/apr/include" /d "NDEBUG" /d BIN_NAME="libapreq.dll" /d LONG_NAME="libapreq" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /machine:IX86 -# ADD LINK32 pcre.lib kernel32.lib user32.lib advapi32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /debug /machine:IX86 /libpath:"./srclib/pcre" /base:@"os\win32\BaseAddr.ref",libapreq.dll /opt:ref -# Begin Special Build Tool -TargetPath=.\Release\libapreq.dll -SOURCE="$(InputPath)" -PostBuild_Desc=Embed .manifest -PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 -# End Special Build Tool - -!ELSEIF "$(CFG)" == "libapreq - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Ignore_Export_Lib 0 -# PROP Target_Dir "" -# ADD BASE CPP /nologo /MDd /W3 /Zi /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS"/D "AP_DECLARE_EXPORT" /D "APREQ_DECLARE_EXPORT" /FD /EHsc /c -# ADD CPP /nologo /MDd /W3 /Zi /Od /I "./include" /I "./srclib/apr/include" /I "./srclib/apr-util/include" /I "./srclib/pcre" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "AP_DECLARE_EXPORT" /D "APREQ_DECLARE_EXPORT" /Fd"Debug\libapreq_cl" /FD /EHsc /c -# ADD BASE MTL /nologo /D "_DEBUG" /win32 -# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 -# ADD BASE RSC /l 0x409 /d "_DEBUG" -# ADD RSC /l 0x409 /fo"Debug/libapreq.res" /i "./include" /i "./srclib/apr/include" /d "_DEBUG" /d BIN_NAME="libapreq.dll" /d LONG_NAME="libapreq" -BSC32=bscmake.exe -# ADD BASE BSC32 /nologo -# ADD BSC32 /nologo -LINK32=link.exe -# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:IX86 -# ADD LINK32 pcred.lib kernel32.lib user32.lib advapi32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:IX86 /libpath:"./srclib/pcre" /base:@"os\win32\BaseAddr.ref",libapreq.dll -# Begin Special Build Tool -TargetPath=.\Debug\libapreq.dll -SOURCE="$(InputPath)" -PostBuild_Desc=Embed .manifest -PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2 -# End Special Build Tool - -!ENDIF - -# Begin Target - -# Name "libapreq - Win32 Release" -# Name "libapreq - Win32 Debug" -# Begin Group "headers" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90" -# Begin Source File - -SOURCE=.\include\ap_config.h -# End Source File -# Begin Source File - -SOURCE=.\include\ap_release.h -# End Source File -# Begin Source File - -SOURCE=.\include\apreq.h -# End Source File -# Begin Source File - -SOURCE=.\include\apreq_cookie.h -# End Source File -# Begin Source File - -SOURCE=.\include\apreq_error.h -# End Source File -# Begin Source File - -SOURCE=.\include\apreq_module.h -# End Source File -# Begin Source File - -SOURCE=.\include\apreq_param.h -# End Source File -# Begin Source File - -SOURCE=.\include\apreq_parser.h -# End Source File -# Begin Source File - -SOURCE=.\include\apreq_util.h -# End Source File -# End Group -# Begin Group "libapreq" - -# PROP Default_Filter "" -# Begin Source File - -SOURCE=.\server\apreq_cookie.c -# End Source File -# Begin Source File - -SOURCE=.\server\apreq_error.c -# End Source File -# Begin Source File - -SOURCE=.\server\apreq_module.c -# End Source File -# Begin Source File - -SOURCE=.\server\apreq_module_cgi.c -# End Source File -# Begin Source File - -SOURCE=.\server\apreq_module_custom.c -# End Source File -# Begin Source File - -SOURCE=.\server\apreq_param.c -# End Source File -# Begin Source File - -SOURCE=.\server\apreq_parser.c -# End Source File -# Begin Source File - -SOURCE=.\server\apreq_parser_header.c -# End Source File -# Begin Source File - -SOURCE=.\server\apreq_parser_multipart.c -# End Source File -# Begin Source File - -SOURCE=.\server\apreq_parser_urlencoded.c -# End Source File -# Begin Source File - -SOURCE=.\server\apreq_util.c -# End Source File -# Begin Source File - -SOURCE=.\server\buildmark.c -# PROP Exclude_From_Build 1 -# End Source File -# End Group -# Begin Source File - -SOURCE=.\build\win32\httpd.rc -# End Source File -# End Target -# End Project diff --git a/os/win32/BaseAddr.ref b/os/win32/BaseAddr.ref index 4c6291ddcf3..eac33f733a9 100644 --- a/os/win32/BaseAddr.ref +++ b/os/win32/BaseAddr.ref @@ -123,7 +123,6 @@ mod_cache_socache.so 0x70B60000 0x00020000 mod_allowhandlers.so 0x70B80000 0x00010000 mod_macro.so 0x70B90000 0x00020000 mod_proxy_wstunnel.so 0x70BB0000 0x00020000 -mod_apreq.so 0x70BD0000 0x00020000 mod_authnz_fcgi.so 0x70BF0000 0x00020000 mod_dialup.so 0x70C10000 0x00010000 mod_optional_fn_export.so 0x70C20000 0x00010000 @@ -139,5 +138,4 @@ mod_proxy_hcheck.so 0x70E00000 0x00020000 mod_socache_redis.so 0x70E20000 0x00020000 mod_md.so 0x70E40000 0x00030000 mod_proxy_uwsgi.so 0x70E70000 0x00020000 -libapreq.dll 0x70E90000 0x00020000 mod_log_json.so 0x70EB0000 0x00020000 From fc9292145fc0ce9994d3f220ad658cb40dbe55dd Mon Sep 17 00:00:00 2001 From: Joe Orton Date: Thu, 23 Apr 2026 15:44:49 +0100 Subject: [PATCH 4/6] Remove references to apreq from CHANGES, httpd.spec.in. --- CHANGES | 6 ------ build/rpm/httpd.spec.in | 1 - 2 files changed, 7 deletions(-) diff --git a/CHANGES b/CHANGES index 50274805404..0139c07e8f9 100644 --- a/CHANGES +++ b/CHANGES @@ -2005,10 +2005,6 @@ Changes with Apache 2.5.0-alpha *) mod_authnz_ldap: Resolve crashes with LDAP authz and non-LDAP authn since r1608202. [Eric Covener] - *) apreq: Content-Length header should be always interpreted as a decimal. - Leading 0 could be erroneously considered as an octal value. PR 56598. - [Chris Card ] - *) mod_proxy: Now allow for 191 character worker names, with non-fatal errors if name is truncated. PR53218. [Jim Jagielski] @@ -2229,8 +2225,6 @@ Changes with Apache 2.5.0-alpha *) mod_noloris - *) APREQ - *) Simple MPM *) mod_serf diff --git a/build/rpm/httpd.spec.in b/build/rpm/httpd.spec.in index a8fabb06e0c..7527036d88e 100644 --- a/build/rpm/httpd.spec.in +++ b/build/rpm/httpd.spec.in @@ -306,7 +306,6 @@ rm -rf $RPM_BUILD_ROOT %{_libdir}/httpd/modules/mod_alias.so %{_libdir}/httpd/modules/mod_allowhandlers.so %{_libdir}/httpd/modules/mod_allowmethods.so -%{_libdir}/httpd/modules/mod_apreq.so %{_libdir}/httpd/modules/mod_asis.so %{_libdir}/httpd/modules/mod_auth_basic.so %{_libdir}/httpd/modules/mod_auth_digest.so From d9d330d4abab4adf07d97a9e48950206f0f9771d Mon Sep 17 00:00:00 2001 From: Joe Orton Date: Thu, 23 Apr 2026 15:48:09 +0100 Subject: [PATCH 5/6] Partial revert of r1825400. --- Makefile.win | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Makefile.win b/Makefile.win index 2caa7b39331..2368c7d19b4 100644 --- a/Makefile.win +++ b/Makefile.win @@ -508,7 +508,6 @@ _build: $(MAKE) $(MAKEOPT) -f gen_test_char.mak CFG="gen_test_char - Win32 $(LONG)" RECURSE=0 $(CTARGET) cd .. $(MAKE) $(MAKEOPT) -f libhttpd.mak CFG="libhttpd - Win32 $(LONG)" RECURSE=0 $(CTARGET) - $(MAKE) $(MAKEOPT) -f libapreq.mak CFG="libapreq - Win32 $(LONG)" RECURSE=0 $(CTARGET) $(MAKE) $(MAKEOPT) -f httpd.mak CFG="httpd - Win32 $(LONG)" RECURSE=0 $(CTARGET) # build ldap prior to authnz_ldap cd modules\ldap @@ -540,9 +539,6 @@ _build: $(MAKE) $(MAKEOPT) -f mod_authz_owner.mak CFG="mod_authz_owner - Win32 $(LONG)" RECURSE=0 $(CTARGET) $(MAKE) $(MAKEOPT) -f mod_authz_user.mak CFG="mod_authz_user - Win32 $(LONG)" RECURSE=0 $(CTARGET) cd ..\.. - cd modules\apreq - $(MAKE) $(MAKEOPT) -f mod_apreq.mak CFG="mod_apreq - Win32 $(LONG)" RECURSE=0 $(CTARGET) - cd ..\.. cd modules\arch\win32 $(MAKE) $(MAKEOPT) -f mod_isapi.mak CFG="mod_isapi - Win32 $(LONG)" RECURSE=0 $(CTARGET) cd ..\..\.. @@ -828,7 +824,6 @@ _build: _copybin: copy $(LONG)\httpd.$(src_exe) "$(inst_exe)" <.y - copy $(LONG)\libapreq.$(src_dll) "$(inst_dll)" <.y copy $(LONG)\libhttpd.$(src_dll) "$(inst_dll)" <.y copy srclib\apr\$(LONG)\libapr-1.$(src_dll) "$(inst_dll)" <.y !IF EXIST("srclib\apr-util") @@ -872,7 +867,6 @@ _copybin: copy modules\aaa\$(LONG)\mod_authz_host.$(src_so) "$(inst_so)" <.y copy modules\aaa\$(LONG)\mod_authz_owner.$(src_so) "$(inst_so)" <.y copy modules\aaa\$(LONG)\mod_authz_user.$(src_so) "$(inst_so)" <.y - copy modules\apreq\$(LONG)\mod_apreq.$(src_so) "$(inst_so)" <.y copy modules\arch\win32\$(LONG)\mod_isapi.$(src_so) "$(inst_so)" <.y copy modules\cache\$(LONG)\mod_cache.$(src_so) "$(inst_so)" <.y copy modules\cache\$(LONG)\mod_cache_disk.$(src_so) "$(inst_so)" <.y From ad5c5c4ef018178b233c3b1d300e67b5dd9bd0ad Mon Sep 17 00:00:00 2001 From: Joe Orton Date: Thu, 23 Apr 2026 15:49:22 +0100 Subject: [PATCH 6/6] Revert apreq support from cmake. --- CMakeLists.txt | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d6606a2731e..e9b39bdd13e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -321,7 +321,6 @@ SET(MODULE_LIST "modules/aaa/mod_authz_host+A+host-based authorization control" "modules/aaa/mod_authz_owner+I+'require file-owner' authorization control" "modules/aaa/mod_authz_user+A+'require user' authorization control" - "modules/apreq/mod_apreq+i+Apache Request Filter" "modules/arch/win32/mod_isapi+I+isapi extension support" "modules/cache/mod_cache+I+dynamic file caching. At least one storage management module (e.g. mod_cache_disk) is also necessary." "modules/cache/mod_cache_disk+I+disk caching module" @@ -437,9 +436,6 @@ SET(installed_mod_libs_exps) # Define extra definitions, sources, headers, etc. required by some modules. # This could be included in the master list of modules above, though it # certainly would get a lot more unreadable. -SET(mod_apreq_extra_defines APREQ_DECLARE_EXPORT) -SET(mod_apreq_extra_sources modules/apreq/handle.c) -SET(mod_apreq_main_source modules/apreq/filter.c) SET(mod_authz_dbd_extra_defines AUTHZ_DBD_DECLARE_EXPORT) SET(mod_authnz_ldap_requires APR_HAS_LDAP) SET(mod_authnz_ldap_extra_libs mod_ldap) @@ -684,17 +680,6 @@ SET(HTTPD_MAIN_SOURCES SET(LIBHTTPD_SOURCES ${extra_builtin_modules} ${PROJECT_BINARY_DIR}/modules.c - server/apreq_cookie.c - server/apreq_error.c - server/apreq_module.c - server/apreq_module_cgi.c - server/apreq_module_custom.c - server/apreq_param.c - server/apreq_parser.c - server/apreq_parser_header.c - server/apreq_parser_multipart.c - server/apreq_parser_urlencoded.c - server/apreq_util.c modules/arch/win32/mod_win32.c modules/core/mod_so.c modules/http/byterange_filter.c @@ -921,7 +906,6 @@ TARGET_COMPILE_DEFINITIONS(libhttpd PRIVATE "LONG_NAME=Apache HTTP Server Core" "BIN_NAME=libhttpd.dll" "AP_DECLARE_EXPORT" - "APREQ_DECLARE_EXPORT" ) TARGET_COMPILE_OPTIONS(libhttpd PRIVATE ${PCRE_CFLAGS} ${EXTRA_COMPILE_FLAGS}) ADD_DEPENDENCIES(libhttpd test_char_header)