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
###############################################################################
-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>
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
###############################################################################
-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>
###############################################################################
-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>
End Project Dependency
}}}
+
###############################################################################
Project: "mod_access_compat"=.\modules\aaa\mod_access_compat.dsp - Package Owner=<4>
*) 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 <ctcard hotmail com>]
-
*) mod_proxy: Now allow for 191 character worker names, with non-fatal
errors if name is truncated. PR53218. [Jim Jagielski]
*) mod_noloris
- *) APREQ
-
*) Simple MPM
*) mod_serf
"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"
# 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)
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
"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)
$(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
$(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 ..\..\..
_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")
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
# 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 \
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;
# 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)
#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"
#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"
%{_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
+++ /dev/null
-/*
-** 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 <assert.h>
-#endif
-
-#include "ap_config.h"
-#include "apr_tables.h"
-#include <stddef.h>
-
-#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 */
+++ /dev/null
-/*
-** 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*/
-
-
+++ /dev/null
-/*
-** 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 */
+++ /dev/null
-/*
-** 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 */
+++ /dev/null
-/*
-** 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 */
-
-
-
+++ /dev/null
-/*
-** 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 */
+++ /dev/null
-/*
-** 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 */
+++ /dev/null
-# Microsoft Developer Studio Project File - Name="libapreq" - Package Owner=<4>\r
-# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
-# ** DO NOT EDIT **\r
-\r
-# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102\r
-\r
-CFG=libapreq - Win32 Release\r
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
-!MESSAGE use the Export Makefile command and run\r
-!MESSAGE \r
-!MESSAGE NMAKE /f "libapreq.mak".\r
-!MESSAGE \r
-!MESSAGE You can specify a configuration when running NMAKE\r
-!MESSAGE by defining the macro CFG on the command line. For example:\r
-!MESSAGE \r
-!MESSAGE NMAKE /f "libapreq.mak" CFG="libapreq - Win32 Release"\r
-!MESSAGE \r
-!MESSAGE Possible choices for configuration are:\r
-!MESSAGE \r
-!MESSAGE "libapreq - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")\r
-!MESSAGE "libapreq - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")\r
-!MESSAGE \r
-\r
-# Begin Project\r
-# PROP AllowPerConfigDependencies 0\r
-# PROP Scc_ProjName ""\r
-# PROP Scc_LocalPath ""\r
-CPP=cl.exe\r
-MTL=midl.exe\r
-RSC=rc.exe\r
-\r
-!IF "$(CFG)" == "libapreq - Win32 Release"\r
-\r
-# PROP BASE Use_MFC 0\r
-# PROP BASE Use_Debug_Libraries 0\r
-# PROP BASE Output_Dir "Release"\r
-# PROP BASE Intermediate_Dir "Release"\r
-# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 0\r
-# PROP Use_Debug_Libraries 0\r
-# PROP Output_Dir "Release"\r
-# PROP Intermediate_Dir "Release"\r
-# PROP Ignore_Export_Lib 0\r
-# PROP Target_Dir ""\r
-# ADD BASE CPP /nologo /MD /W3 /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "AP_DECLARE_EXPORT" /D "APREQ_DECLARE_EXPORT" /FD /c\r
-# 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\r
-# ADD BASE MTL /nologo /D "NDEBUG" /win32\r
-# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32\r
-# ADD BASE RSC /l 0x409 /d "NDEBUG"\r
-# 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"\r
-BSC32=bscmake.exe\r
-# ADD BASE BSC32 /nologo\r
-# ADD BSC32 /nologo\r
-LINK32=link.exe\r
-# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /machine:IX86\r
-# 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\r
-# Begin Special Build Tool\r
-TargetPath=.\Release\libapreq.dll\r
-SOURCE="$(InputPath)"\r
-PostBuild_Desc=Embed .manifest\r
-PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2\r
-# End Special Build Tool\r
-\r
-!ELSEIF "$(CFG)" == "libapreq - Win32 Debug"\r
-\r
-# PROP BASE Use_MFC 0\r
-# PROP BASE Use_Debug_Libraries 1\r
-# PROP BASE Output_Dir "Debug"\r
-# PROP BASE Intermediate_Dir "Debug"\r
-# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 0\r
-# PROP Use_Debug_Libraries 1\r
-# PROP Output_Dir "Debug"\r
-# PROP Intermediate_Dir "Debug"\r
-# PROP Ignore_Export_Lib 0\r
-# PROP Target_Dir ""\r
-# 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\r
-# 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\r
-# ADD BASE MTL /nologo /D "_DEBUG" /win32\r
-# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32\r
-# ADD BASE RSC /l 0x409 /d "_DEBUG"\r
-# 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"\r
-BSC32=bscmake.exe\r
-# ADD BASE BSC32 /nologo\r
-# ADD BSC32 /nologo\r
-LINK32=link.exe\r
-# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib ws2_32.lib mswsock.lib /nologo /subsystem:windows /dll /incremental:no /debug /machine:IX86\r
-# 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\r
-# Begin Special Build Tool\r
-TargetPath=.\Debug\libapreq.dll\r
-SOURCE="$(InputPath)"\r
-PostBuild_Desc=Embed .manifest\r
-PostBuild_Cmds=if exist $(TargetPath).manifest mt.exe -manifest $(TargetPath).manifest -outputresource:$(TargetPath);2\r
-# End Special Build Tool\r
-\r
-!ENDIF \r
-\r
-# Begin Target\r
-\r
-# Name "libapreq - Win32 Release"\r
-# Name "libapreq - Win32 Debug"\r
-# Begin Group "headers"\r
-\r
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;hpj;bat;for;f90"\r
-# Begin Source File\r
-\r
-SOURCE=.\include\ap_config.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\include\ap_release.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\include\apreq.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\include\apreq_cookie.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\include\apreq_error.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\include\apreq_module.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\include\apreq_param.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\include\apreq_parser.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\include\apreq_util.h\r
-# End Source File\r
-# End Group\r
-# Begin Group "libapreq"\r
-\r
-# PROP Default_Filter ""\r
-# Begin Source File\r
-\r
-SOURCE=.\server\apreq_cookie.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\server\apreq_error.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\server\apreq_module.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\server\apreq_module_cgi.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\server\apreq_module_custom.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\server\apreq_param.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\server\apreq_parser.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\server\apreq_parser_header.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\server\apreq_parser_multipart.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\server\apreq_parser_urlencoded.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\server\apreq_util.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\server\buildmark.c\r
-# PROP Exclude_From_Build 1\r
-# End Source File\r
-# End Group\r
-# Begin Source File\r
-\r
-SOURCE=.\build\win32\httpd.rc\r
-# End Source File\r
-# End Target\r
-# End Project\r
SUBDIRS = \
aaa \
- apreq \
cache \
cluster \
core \
+++ /dev/null
-include $(top_srcdir)/build/special.mk
+++ /dev/null
-#
-# 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
-
-
+++ /dev/null
-/*
-** 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 <httpd.h>
-
-#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.
- *
- * <hr>
- *
- * <h2>Activating mod_apreq2 in Apache 2.X</h2>
- *
- * The installation process triggered by
- * <code>% make install</code>
- * <em>will not modify your webserver's config file</em>. 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() <em>before the content handler ultimately reads
- * from the input filter chain</em>. 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).
- *
- *
- * <H2>Server Configuration Directives</H2>
- *
- * <TABLE class="qref">
- * <CAPTION>Per-directory commands for mod_apreq2</CAPTION>
- * <TR>
- * <TH>Directive</TH>
- * <TH>Context</TH>
- * <TH>Default</TH><TH>Description</TH>
- * </TR>
- * <TR class="odd">
- * <TD>APREQ2_ReadLimit</TD>
- * <TD>directory</TD>
- * <TD> #APREQ_DEFAULT_READ_LIMIT </TD>
- * <TD> 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.
- * </TD>
- * </TR>
- * <TR>
- * <TD>APREQ2_BrigadeLimit</TD>
- * <TD>directory</TD>
- * <TD>#APREQ_DEFAULT_BRIGADE_LIMIT</TD>
- * <TD> 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.
- * </TD>
- * </TR>
- * <TR class="odd">
- * <TD>APREQ2_TempDir</TD>
- * <TD>directory</TD>
- * <TD>NULL</TD>
- * <TD> 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().
- * </TD>
- * </TR>
- * </TABLE>
- *
- * <H2>Implementation Details</H2>
- * <PRE>
- * 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
- * </PRE>
- *
- * @{
- */
-/**
- * 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
+++ /dev/null
-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;
- }
-}
+++ /dev/null
-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
+++ /dev/null
-/*
-** 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;
-}
+++ /dev/null
-/*
-** 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;
-
-}
+++ /dev/null
-# 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
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
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
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
+++ /dev/null
-/*
-** 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;
-}
-
+++ /dev/null
-/* 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));
-}
-
+++ /dev/null
-/*
-** 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;
-
-}
-
-
-/** @} */
+++ /dev/null
-/*
-** 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;
-}
+++ /dev/null
-/*
-** 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;
-}
-
+++ /dev/null
-/*
-** 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;
-}
+++ /dev/null
-/*
-** 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;
-}
+++ /dev/null
-/*
-** 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 <assert.h>
-#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;
-}
+++ /dev/null
-/*
-** 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;
-}
+++ /dev/null
-/*
-** 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;
-}
-
-
+++ /dev/null
-/*
-** 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 <assert.h>
-
-#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;
-}