--- /dev/null
+Changes with APR-util 1.2.0
+
+ *) Add sqlite3 support to APR DBD. [Rick Keiner <rick_keiner yahoo.com>]
+
+ *) Fix build failure with non-threaded APR on AIX. PR 34655.
+ [Ryan Murray <rmurray+apache cyberhqz.com>]
+
+ *) Add sqlite2 support to APR DBD. [Ryan Phillips <ryan trolocsis.com>]
+
+ *) Introduction of APR DBD layer. [Nick Kew]
+
+Changes with APR-util 1.1.2
+
+ *) Fix libaprutil.rc for Win32 builds [William Rowe, Justin Erenkrantz]
+
+Changes with APR-util 1.1.1
+
+ *) Fix memory leak in buckets when using APR_POOL_DEBUG mode. [Joe Schaefer]
+
+ *) find_apu.m4: Try installed APR-util before bundled copy if --with-apr-util
+ not passed to configure. [Justin Erenkrantz]
+
+Changes with APR-util 1.1.0
+
+ *) LDAP: Move all certificate initialisation, and the creation of SSL
+ and TLS connections into the apr_ldap_set_option() API. Add support
+ for client certificates. [Graham Leggett]
+
+ *) Emit the run-time link path option in apu-config after installation
+ if the user is linking with libtool. [Justin Erenkrantz]
+
+ *) Port testmd4 and testmd5 to the new test suite. [Thom May]
+
+ *) Allow passing NULL inbuf/inbytes_left parameters to
+ apr_xlate_conv_buffer(), required to correctly terminate the
+ output buffer for some stateful character set encodings.
+ [Joe Orton]
+
+ *) Link libaprutil against the libraries on which it depends.
+ PR 11122. [Joe Orton]
+
+ *) Add apr_brigade_insert_file() function, to safely insert a file
+ into a brigade, regardless of size. [Joe Orton]
+
+Changes with APR-util 1.0.2
+
+ *) Teach apr_ldap_init() how to handle STARTTLS in addition to the existing
+ SSL support. Add apr_ldap_option API. [Graham Leggett]
+
+ *) Rework the LDAP toolkit detection to be more accurate than "OpenLDAP
+ detected regardless", while remaining backwards compatible with v1.0.
+ [Graham Leggett]
+
+ *) Added the apr_ldap_ssl_add_cert() API to allow multiple certificates
+ to be stored and used when establishing an SSL connection to different
+ LDAP servers. [Brad Nicholes]
+
+ *) Fix the detection of ldap.h on Solaris - it needs lber.h to be
+ defined first. [Graham Leggett]
+
+ *) Add a build script to create a solaris package. [Graham Leggett]
+
+Changes with APR-util 1.0.1
+
+ *) Add support for Berkeley DB 4.3. [Jani Averbach <jaa jaa.iki.fi>]
+
+ *) SECURITY: CAN-2004-0786 (cve.mitre.org)
+ Fix input validation in apr_uri_parse() to avoid passing negative
+ length to memcpy for malformed IPv6 literal addresses.
+ [Joe Orton]
+
+Changes with APR-util 1.0
+
+ *) Only install apu-$MAJOR-config and add appropriate detection code to
+ find_apu.m4 (APU_FIND_APU). [Max Bowsher <maxb ukf.net>]
+
+ *) Overhaul support for LDAP URL parsing. Instead of using incompatible
+ URL parsers and memory that needs freeing, apr-util provides a parser
+ which parses the URL and allocates memory from a pool. [Graham Leggett]
+
+ *) Remove support for LDAP v2.0 SDK toolkits. This will be added
+ back properly later assuming there is demand for it. In the mean
+ time, please use an LDAP v3.0 SDK toolkit. [Graham Leggett]
+
+ *) Add an apr_ldap_err_t structure to handle the return of LDAP
+ specific error codes. [Graham Leggett, Brad Nicholes]
+
+ *) Add APR functions to do the job of ldap_init(), hiding toolkit
+ specific SSL/TLS handling. Code derived from httpd util_ldap.
+ [Graham Leggett]
+
+ *) Add an RPM spec file derived from Fedora Core.
+ [Graham Leggett, Joe Orton]
+
+ *) The whole codebase was relicensed and is now available under
+ the Apache License, Version 2.0 (http://www.apache.org/licenses).
+ [Apache Software Foundation]
+
+ *) A new function, apr_reslist_invalidate, was added so that invalid
+ resources can be removed from a reslist instead of being returned
+ to the reslist in a broken state. [Nick Kew <nick webthing.com>]
+
+ *) Switch to a single, top-level make. [Greg Stein]
+
+ *) Add timeout feature to apr_reslist_acquire().
+ [Mladen Turk <mturk apache.org>]
+
+ *) Pass error codes returned from constructors all the way back to
+ the reslist consumer. Also fix a minor reslist memory leak that could
+ happen when a constructor returns an error code. PR 23492.
+ [Snke Tesch <st@kino-fahrplan.de>, Aaron Bannert]
+
+ *) The following header files have been removed:
+
+ apu_compat.h
+
+Changes with APR-util 0.9.5
+
+ *) Fix corrupt output from the apr_xlate_* interfaces on AIX 4.x.
+ [Joe Orton]
+
+ *) Change the order in which ldap.h and lber.h are defined, to fix
+ a compile bug in Solaris v2.8 which requires lber.h then ldap.h.
+ PR 27379. [Andrew Connors <andy.connors idea.com>]
+
+ *) Restore support for SHA1 passwords in apr_validate_password.
+ PR 17343. [Paul Querna <chip force-elite.com>]
+
+ *) Fix DESTDIR install for bundled expat library. PR 14076
+ [David S. Madole <david madole.net>]
+
+ *) Fix occasional crash in apr_rmm_realloc(). PR 22915.
+ [Jay Shrauner <shrauner inktomi.com>]
+
+ *) Fix apr_dbm_exists() for sdbm when sizeof(int) != sizeof(size_t).
+ [Joe Orton]
+
+ *) The whole codebase was relicensed and is now available under
+ the Apache License, Version 2.0 (http://www.apache.org/licenses).
+ [Apache Software Foundation]
+
+ *) Fix xlate.c compile failure on AIX 5.2. PR 25701. [Jeff Trawick]
+
+ *) Fixed a bug in apr_rmm that would cause it to mishandle blocks of
+ a size close to the one requested from the allocator.
+ [Kevin Wang <xwang_tech yahoo.com>]
+
+Changes with APR-util 0.9.4
+
+ *) Changed apr_bucket_alloc_create() so that it uses the allocator
+ from the pool that was passed in rather than creating its own.
+ Also, the bucket_allocator is now allocated from the apr_allocator_t
+ rather than using apr_palloc(). Added apr_bucket_alloc_create_ex()
+ which takes an apr_allocator_t* directly rather than an apr_pool_t*.
+ [Cliff Woolley, Jean-Jacques Clar]
+
+ *) Added debugging consistency checks to the buckets code. Add
+ -DAPR_BUCKET_DEBUG to the build flags to enable.
+ [Cliff Woolley]
+
+ *) Make the version of the db library APU built against visible.
+ [Thom May]
+
+ *) Fix a problem with VPATH builds copying the APR rules.mk into the
+ source directory rather than the build directory. [Justin Erenkrantz]
+
+ *) SECURITY [httpd incident CAN-2003-0189] Address a thread safety
+ issue with apr_password_validate() on AIX, Linux, Mac OS X, and
+ possibly other platforms. [Jeff Trawick, Justin Erenkrantz]
+
+ *) Fix a problem with LDAP configuration which caused subsequent
+ configure tests to fail since LIBS contained LDAP libraries for
+ subsequent tests but LDFLAGS no longer included the path to such
+ LDAP libraries. [Jeff Trawick]
+
+ *) Fix a problem preventing the use of the bundled Expat when APR-util
+ is built stand-alone. [Jeff Trawick]
+
+ *) Use the same compiler and preprocessor for the APR-util config tests
+ which were used by APR. The user can override this via CC and CPP.
+ This was done all along for the actual build, but not necessarily
+ for the config tests. [Jeff Trawick]
+
+ *) Fix apr_uuid_parse() on EBCDIC machines. [Jeff Trawick]
+
+ *) Fix alignment problem when allocating memory using apr_rmm. The problem
+ showed up while trying to write a double in the memory allocated.
+ [Madhusudan Mathihalli]
+
+Changes with APR-util 0.9.3
+
+ *) Allow apr_date_parse_rfc to parse 'Sun, 06-Nov-1994 08:49:37 GMT' as a
+ valid date. [Dmitri Tikhonov <dmitri@netilla.com>]
+
+ *) Fix error in apu-config when symlinks are involved.
+ [Garrett Rooney <rooneg@electricjellyfish.net>]
+
+Changes with APR-util 0.9.2
+
+ *) Fix the APR_BUCKET_IS_foo() macros so they parenthesize their parameter.
+ This fixes compile problems with some types of parameters.
+ [Jim Carlson <jcarlson@jnous.com>]
+
+ *) Queue overwrite, we now return the item pushed, not a reference to it.
+ [Paul Marquis <PMarquis@pobox.com, Jacob Lewallen <jlwalle@cs.ucr.edu>]
+
+ *) Remove include/apr_ldap.h on distclean. PR 15592. [Justin Erenkrantz]
+
+ *) Fix race conditions in apr_queue.
+ [Jacob Lewallen <jlwalle@cs.ucr.edu>]
+
+ *) Stop buildconf copying rules.mk, copy it at configure time.
+ [Thom May]
+
+ *) Make buildconf copy rules.mk as well.
+ [Garrett Rooney <rooneg@electricjellyfish.net>]
+
+ *) Add --includedir flag to apu-config. [Justin Erenkrantz]
+
+ *) Fix brokenness in sdbm when sizeof(int) != sizeof(size_t)
+ (e.g., 64-bit AIX, 64-bit Solaris). PR 14861. [Jeff Trawick]
+
+ *) Have buildconf copy required files from apr so that apr-util can build
+ on its own. [Craig Rodrigues <rodrigc@attbi.com>]
+
+ *) Detect OpenLDAP when used with Solaris 9. PR 13427.
+ [Gary Algier <gaa@ulticom.com>]
+
+ *) Detect Berkeley DB 4.1 when compiled with --with-uniquenames
+ [Thom May]
+
+ *) Allow apu-config to work in symlinked install directories when
+ 'realpath' is available. [Justin Erenkrantz]
+
+ *) Fix bug in apr_strmatch when used with case-insensitive patterns.
+ [Justin Erenkrantz]
+
+ *) Allow apr_queue to have greater than int number of elements.
+ [Justin Erenkrantz]
+
+ *) Detect Berkeley DB 4.0 compiled with --with-uniquenames.
+ [Philip Martin <philip@codematters.co.uk>]
+
+ *) Allocate brigades from a bucket allocator rather than a pool. [Brian Pane]
+
+ *) Update with the latest APR renames [Thom May]
+
+ *) Update doxygen tags. [Justin Erenkrantz]
+
+ *) Add apr_ldap.hw for Windows build.
+ [Andre Schild <A.Schild@aarboard.ch>]
+
+ *) Add IPv6 literal address support to apr_uri_parse(), apr_uri_unparse(),
+ and apr_uri_parse_hostinfo(). PR 11887 [Jeff Trawick]
+
+ *) Add apr_brigade_writev() [Brian Pane]
+
+ *) Add support for Berkeley DB 4.1. [Justin Erenkrantz]
+
+ *) Add --bindir option to apu-config. [Justin Erenkrantz]
+
+Changes with APR-util 0.9.1
+
+ *) Add versioning infrastructure.
+ [Justin Erenkrantz]
+
+ *) Running "make check" in the toplevel directory or the test/ directory
+ will build and run all test programs. [Aaron Bannert]
+
+ *) Bug #9789 : NDBM support
+ [Toomas Soome <tsoome@muhv.pri.ee>, Ian Holsman]
+
+ *) Added a Thread safe FIFO bounded buffer (apr_queue) [Ian Holsman]
+
+ *) Changed file_bucket_setaside() to use apr_file_setaside() instead
+ of turning the file bucket into an mmap bucket. [Brian Pane]
+
+ *) Install libaprutil support libraries before installing libaprutil
+ itself, since on some platforms libaprutil is relinked during
+ make install and the support libraries need to exist already.
+ [Jeff Trawick]
+
+ *) Added a Resource List API for threadsafe access to persistent
+ and dynamically created user-defined resources. [Aaron Bannert]
+
+ *) Adopted apr-util/xlate from apr/i18n for inclusion of apr-iconv
+ as required by missing libiconv. [William Rowe]
+
+ *) Adopted apr-util/crypto/ uuid and md5 from apr. [William Rowe]
+
+ *) Look for expat in lib64 directories. [Peter Poeml <poeml@suse.de>]
+
+ *) Faster implementation of apr_brigade_puts() [Brian Pane]
+
+ *) Fixed a segfault in apr_date_parse_rfc() for some date formats
+ where it was trying to overlay a potentially static input
+ string even though it didn't really need to.
+ [Cliff Woolley, Doug MacEachern]
+
+ *) Ensure that apu-config does not print libtool libraries when
+ using --libs. [Justin Erenkrantz]
+
+ *) Added apr_bucket_file_enable_mmap() function to the bucket
+ API to let an application control whether a file bucket may
+ be turned into an mmap bucket upon read. (The default remains
+ to do the mmap, but this function lets the app prevent the
+ mmap in contexts where mmap would be a bad idea. Examples
+ include multiprocessors where mmap doesn't scale well and
+ NFS-mounted filesystems where a bus error can result if
+ a memory-mapped file is removed or truncated.) [Brian Pane]
+
+ *) Added string-matching API (apr_strmatch.h) [Brian Pane]
+
+ *) Rearrange INCLUDES so that APRUTIL_PRIV_INCLUDES is always
+ first. [Garrett Rooney <rooneg@electricjellyfish.net>]
+
+ *) Add --old-expat option to apu-config to allow users of apr-util to
+ determine what expat it should expect to be installed. If the
+ flag is set to yes, it should include xmlparse.h. If it is set to
+ no, it should include expat.h. [Justin Erenkrantz]
+
+ *) Fix exporting of includes in apu-config. [Justin Erenkrantz]
+
+ *) Change bucket brigades API to allow a "bucket allocator" to be
+ passed in at certain points. This allows us to implement freelists
+ so that we can stop using malloc/free so frequently.
+ [Cliff Woolley, Brian Pane]
+
+ *) add apr_rmm_realloc() function
+ [Madhusudan Mathihalli <madhusudan_mathihalli@hp.com>]
+
+ *) renames: apr_ansi_time_to_apr_time becomes apr_time_ansi_put
+ ap_exploded_time_t becomes apr_time_exp_t
+ [Thom May <thom@planetarytramp.net>]
+
+ *) Add detection support for FreeBSD's expat and expat2 ports.
+ [Justin Erenkrantz]
+
+ *) Deprecate check_brigade_flush(), which had several nasty bugs, and
+ which was causing apr_brigade_write()'s logic to be less than obvious.
+ Everything is now done in a slightly rearranged apr_brigade_write().
+ [Cliff Woolley]
+
+ *) Don't add /usr/include to the INCLUDES variable on expat's account.
+ [Joe Orton <joe@manyfish.co.uk>]
+
+ *) Remove the autoconf 2.5x cache directory in buildconf.
+ [Joe Orton <joe@manyfish.co.uk>]
+
+ *) BerkleyDB should NULL out the key if it is @EOF in vt_db_nextkey
+ [Ian Holsman]
+
+ *) Add ability to natively fetch and split brigades based on LF lines.
+ [Justin Erenkrantz]
+
+ *) add --with-berkeley-db=DIR & --with-gdbm configure flags
+ [Ian Holsman/Justin Erenkrantz]
+
+ *) Fix expat detection to recognize installed versions.
+ [Eric Gillespie, Jr. <epg@pretzelnet.org>]
+
+ *) Add find_apu.m4 to allow third-party programs that use APR-util
+ to have a standard m4 macro for detection. [Justin Erenkrantz]
+
+ *) Add apu-config - a shell script to allow third-party programs
+ easy access to APR configuration parameters. [Justin Erenkrantz]
+
+ *) Add GMT offset calculation to apr_date_parse_rfc().
+ [Justin Erenkrantz]
+
+ *) Introduce the apr_rmm api, to allow relocatable memory management
+ of address-independent data stores, such as shared memory.
+ [William Rowe]
+
+ *) Rework and fix VPATH-build support. [Justin Erenkrantz]
+
+ *) Add support for Berkeley DB4. [Justin Erenkrantz]
+
+ *) Improve testdbm help. [Justin Erenkrantz]
+
+ *) Improve autoconf detection of DBMs. [Justin Erenkrantz]
+
+ *) BerkeleyDBM v2 now checks minor level for cursor ops [Ian Holsman]
+
+ *) Reading a file bucket bigger than APR_MMAP_LIMIT (4MB) now yields
+ a string of 4MB mmap buckets, rather than a string of 8KB heap buckets
+ plus a 4MB mmap bucket. To accomodate this, the mmap bucket destroy
+ function explicitly deletes the apr_mmap_t after last reference
+ to avoid having too much of a large file mapped at once if possible.
+ [Cliff Woolley]
+
+ *) Multi-DBM support (via apr_dbm_open_ex). [Ian Holsman]
+
+ *) Use apr_mmap_dup in mmap_setaside(). [Brian Pane <bpane@pacbell.net>]
+
+ *) Dropped the "w" parameter from apr_bucket_heap_create() and
+ apr_bucket_heap_make(). That parameter was originally intended
+ to return the amount of data copied into the bucket, but it
+ ended up being unnecessary because that amount is invariant from
+ the size of the data and is available as b->length in the
+ resulting bucket anyway. [Cliff Woolley]
+
+ *) Fix Makefile conversion for BSD/OS. [Cliff Woolley]
+
+ *) Use APR_XtOffsetOf instead of offsetof() in the ring macros for
+ portability. [Cliff Woolley]
+
+ *) We now create exports.c and export_vars.h, which in turn create
+ exports.c. From this we generate two more files with different
+ purposes: aprutil.exp - list of exported symbols; and exports.lo
+ (exports.o) - an object file that can be linked with an executable
+ to force resolution of all apr-util symbols. [Aaron Bannert]
+
+ *) Fix Berkley DBM support [Ian Holsman <ianh@apache.org>]
+
+ *) Fix apr_brigade_vprintf so that it can handle more than
+ 4k of data at one time. [Cody Sherr <csherr@covalent.net>]
+
+ *) prefix UNP_* flags with APR_URI_
+
+ rename:
+ apr_uri_components -> apr_uri_t
+ apr_uri_unparse_components -> apr_uri_unparse
+ apr_uri_parse_components -> apr_uri_parse
+ apr_uri_parse_hostinfo_components -> apr_uri_parse_hostinfo
+
+ s/APU_URI_/APR_URI_/g
+ [Perl]
+
+ *) Landed the link-to-LDAP to the build process, and the LDAP v2/v3
+ compatibility functions.
+ [Dave Carrigan <dave@rudedog.org>, Graham Leggett]
+
+ *) Fix URI unparse function to handle the case where it would place a @
+ when both the username and password were present but omitted.
+ [Jon Travis <jtravis@covalent.net]
+
+ *) Added apr_xml_parse_file() routine and a testxml program.
+ [Ian Holsman <ianh@cnet.com>]
+
+ *) Extend apr_bucket struct to add a pointer to a function used
+ to free the bucket. This change enables custom buckets to
+ completely specify how they are to be allocated and freed.
+ Before this change, custom buckets were required to use the
+ same memory allocation scheme as the standard APR buckets.
+ [Saeid Sakhitab, Bill Stoddard, Cliff Woolley, Roy Fielding]
+
+ *) Install Expat when installing APR-util. [Justin Erenkrantz]
+
+ *) Make APR-util configure script rely on APR. This removes the locally
+ generated copy of libtool and uses the one in APR. Fix up how we
+ call the expat configure script. Generate config.nice file.
+ [Justin Erenkrantz]
+
+ *) The apr_bucket lengths are now consistently apr_size_t, while any
+ apr_brigade lengths (short of a read) are consistently apr_off_t.
+ This is required for APR_HAS_LARGE_FILES handling. [William Rowe]
+
+ *) apr_bucket_file_create() and apr_bucket_file_make() now take a pool
+ parameter which is the pool into which any needed data structures
+ should be created during file_read(). This is used for MMAPing the
+ file and reopening the file if the original apr_file_t is in XTHREAD
+ mode. [Cliff Woolley]
+
+ *) apr_brigade_partition() now returns an apr_status_t. [Cliff Woolley]
+
+ *) Add MD4 implementation in crypto. [Sander Striker, Justin Erenkrantz]
+
+ *) Moved httpd 2.0.18's util_date to apr_date and enhanced its parsing
+ capabilities. [Justin Erenkrantz]
+
+ *) Moved httpd 2.0.18's util_uri to apr_uri and name-protected its
+ symbols and functions. [Justin Erenkrantz, Roy Fielding]
+
+ *) Rename field "private" in struct apr_xml_elem to "priv" for C++
+ compatibility. PR #7727 [Joshua MacDonald <jmacd@cs.berkeley.edu>]
+
+ *) Make APR_IMPLEMENT_EXTERNAL_HOOK_BASE generate a
+ ${namespace}_hook_get_${hookname} function to fetch the
+ list of registered hooks [Doug MacEachern]
+
+ *) Allow LTFLAGS to be overridden by the configure command-line
+ (default="--silent") and introduce LT_LDFLAGS. [Roy Fielding]
+
+ *) Add APR_SHARELOCK support to apr_sdbm_open(), locking read operations
+ with a shared lock and all write ops with an excl lock. [Will Rowe]
+
+ *) Namespace protect apr_sdbm, and normalize the return values (including
+ the apr_sdbm_fetch, apr_sdbm_firstkey and apr_sdbm_nextkey functions).
+ Normalized the get/clear error function names, and stores the actual
+ apr error for apr_sdbm_error_get. [Will Rowe]
+
+ *) Introduce an apr_fileperms_t argument to apr_dbm_open(). [Will Rowe]
+
+ *) Removed apr_bucket_do_create() macro, which was causing warnings
+ about unreachable code in some compilers (notably MSVC). What
+ used to be done by this macro is now done inline in the various
+ apr_bucket_foo_create() functions. [Cliff Woolley]
+
+ *) Make clean, distclean, and extraclean consistently according to the
+ Gnu makefile guidelines. [Justin Erenkrantz <jerenkrantz@ebuilt.com>]
+
+ *) Migrate the --disable-libtool changes from APR to APR-util.
+ This cleans things up, and allows more flexibility when building
+ programs. [Ryan Bloom]
+
+ *) Allow APR-util to be compiled without libtool. The default is
+ to use libtool, but it can turned off with --disable-libtool
+ on the configure command. [Ryan Bloom]
+
+ *) Repair calling convention for apr_register_optional_fn to
+ eliminate GP fault on Win32. [William Rowe]
+
+ *) Substantial changes to correct linkage and declarations for
+ generic hooks on dso architectures. [Ben Laurie, Will Rowe]
+
+ *) apr_bucket_shared_destroy() now returns a boolean value.
+ [Cliff Woolley]
+
+ *) We have to initialize the heap buckets to the correct length.
+ we were seeing heap buckets with 17 chars in them reporting
+ a length of 9017, because they were initialized to the amount
+ of memory allocated, instead of the amount of memory used.
+ This was only an issue for heap buckets created by the
+ apr_brigade_* functions. [Ryan Bloom]
+
+ *) apr_bucket_init_types() and apr_bucket_insert_type() have been
+ removed... they're not needed anymore. [Cliff Woolley]
+
+ *) The apr_bucket_shared and apr_bucket_simple structures have been
+ removed as an API simplification/optimization. This should be
+ transparent outside APR-util except to callers who attempt to
+ directly manipulate the buckets' internal structure (which is
+ not recommended anyway) and to callers who create their own
+ bucket types. [Cliff Woolley]
+
+ *) apr_bucket_simple_split() and apr_bucket_simple_copy() are now
+ exported functions, which could be helpful in implementing
+ external bucket types. [Cliff Woolley]
+
+ *) The third parameter to apr_bucket_shared_make() is now
+ 'apr_off_t length' rather than 'apr_off_t end', since the
+ end usually had to be computed by the caller and all we
+ really want is the length anyway. [Cliff Woolley]
+
--- /dev/null
+The MySQL driver is not distributed from apache.org due to licensing issues.
+
+If you wish to build the driver, download apr_dbd_mysql.c from
+http://apache.webthing.com/database/
+and copy it into the dbd directory before running configure.
+
+It is distributed under the GPL to conform with MySQL License terms
+This means it cannot be distributed from apache.org, as that would
+violate ASF policy.
+
+Using the driver with APR and Apache is of course allowed,
+and there is no problem with a third party bundling the driver,
+provided you respect both the ASF and GPL licenses.
--- /dev/null
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+
+
+APACHE PORTABLE RUNTIME SUBCOMPONENTS:
+
+The Apache Portable Runtime includes a number of subcomponents with
+separate copyright notices and license terms. Your use of the source
+code for the these subcomponents is subject to the terms and
+conditions of the following licenses.
+
+For the include\apr_md5.h component:
+/*
+ * This is work is derived from material Copyright RSA Data Security, Inc.
+ *
+ * The RSA copyright statement and Licence for that original material is
+ * included below. This is followed by the Apache copyright statement and
+ * licence for the modifications made to that material.
+ */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+ rights reserved.
+
+ License to copy and use this software is granted provided that it
+ is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+ Algorithm" in all material mentioning or referencing this software
+ or this function.
+
+ License is also granted to make and use derivative works provided
+ that such works are identified as "derived from the RSA Data
+ Security, Inc. MD5 Message-Digest Algorithm" in all material
+ mentioning or referencing the derived work.
+
+ RSA Data Security, Inc. makes no representations concerning either
+ the merchantability of this software or the suitability of this
+ software for any particular purpose. It is provided "as is"
+ without express or implied warranty of any kind.
+
+ These notices must be retained in any copies of any part of this
+ documentation and/or software.
+ */
+
+For the passwd\apr_md5.c component:
+
+/*
+ * This is work is derived from material Copyright RSA Data Security, Inc.
+ *
+ * The RSA copyright statement and Licence for that original material is
+ * included below. This is followed by the Apache copyright statement and
+ * licence for the modifications made to that material.
+ */
+
+/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
+ */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+ rights reserved.
+
+ License to copy and use this software is granted provided that it
+ is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+ Algorithm" in all material mentioning or referencing this software
+ or this function.
+
+ License is also granted to make and use derivative works provided
+ that such works are identified as "derived from the RSA Data
+ Security, Inc. MD5 Message-Digest Algorithm" in all material
+ mentioning or referencing the derived work.
+
+ RSA Data Security, Inc. makes no representations concerning either
+ the merchantability of this software or the suitability of this
+ software for any particular purpose. It is provided "as is"
+ without express or implied warranty of any kind.
+
+ These notices must be retained in any copies of any part of this
+ documentation and/or software.
+ */
+/*
+ * The apr_md5_encode() routine uses much code obtained from the FreeBSD 3.0
+ * MD5 crypt() function, which is licenced as follows:
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
+ * ----------------------------------------------------------------------------
+ */
+
+For the crypto\apr_md4.c component:
+
+ * This is derived from material copyright RSA Data Security, Inc.
+ * Their notice is reproduced below in its entirety.
+ *
+ * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+ * rights reserved.
+ *
+ * License to copy and use this software is granted provided that it
+ * is identified as the "RSA Data Security, Inc. MD4 Message-Digest
+ * Algorithm" in all material mentioning or referencing this software
+ * or this function.
+ *
+ * License is also granted to make and use derivative works provided
+ * that such works are identified as "derived from the RSA Data
+ * Security, Inc. MD4 Message-Digest Algorithm" in all material
+ * mentioning or referencing the derived work.
+ *
+ * RSA Data Security, Inc. makes no representations concerning either
+ * the merchantability of this software or the suitability of this
+ * software for any particular purpose. It is provided "as is"
+ * without express or implied warranty of any kind.
+ *
+ * These notices must be retained in any copies of any part of this
+ * documentation and/or software.
+ */
+
+For the include\apr_md4.h component:
+
+ *
+ * This is derived from material copyright RSA Data Security, Inc.
+ * Their notice is reproduced below in its entirety.
+ *
+ * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+ * rights reserved.
+ *
+ * License to copy and use this software is granted provided that it
+ * is identified as the "RSA Data Security, Inc. MD4 Message-Digest
+ * Algorithm" in all material mentioning or referencing this software
+ * or this function.
+ *
+ * License is also granted to make and use derivative works provided
+ * that such works are identified as "derived from the RSA Data
+ * Security, Inc. MD4 Message-Digest Algorithm" in all material
+ * mentioning or referencing the derived work.
+ *
+ * RSA Data Security, Inc. makes no representations concerning either
+ * the merchantability of this software or the suitability of this
+ * software for any particular purpose. It is provided "as is"
+ * without express or implied warranty of any kind.
+ *
+ * These notices must be retained in any copies of any part of this
+ * documentation and/or software.
+ */
+
+For the test\testmd4.c component:
+
+ *
+ * This is derived from material copyright RSA Data Security, Inc.
+ * Their notice is reproduced below in its entirety.
+ *
+ * Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All
+ * rights reserved.
+ *
+ * RSA Data Security, Inc. makes no representations concerning either
+ * the merchantability of this software or the suitability of this
+ * software for any particular purpose. It is provided "as is"
+ * without express or implied warranty of any kind.
+ *
+ * These notices must be retained in any copies of any part of this
+ * documentation and/or software.
+ */
+
+For the xml\expat\conftools\install-sh component:
+
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission. M.I.T. makes no representations about the
+# suitability of this software for any purpose. It is provided "as is"
+# without express or implied warranty.
+#
+
+For the expat xml parser component:
+
+Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+ and Clark Cooper
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+====================================================================
--- /dev/null
+#
+# Top-level Makefile for APRUTIL
+#
+CPP = @CPP@
+
+# gets substituted into some targets
+APRUTIL_MAJOR_VERSION=@APRUTIL_MAJOR_VERSION@
+APRUTIL_DOTTED_VERSION=@APRUTIL_DOTTED_VERSION@
+
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+INCLUDES = @APRUTIL_PRIV_INCLUDES@ @APR_INCLUDES@ @APRUTIL_INCLUDES@
+APRUTIL_LDFLAGS = @APRUTIL_LDFLAGS@
+APRUTIL_LIBS = @APRUTIL_LIBS@
+
+TARGET_LIB = lib@APRUTIL_LIBNAME@.la
+INSTALL_SUBDIRS = @APR_ICONV_DIR@ @APR_XML_DIR@
+EXTRA_SOURCE_DIRS = @APR_ICONV_DIR@ @APR_XML_DIR@
+APRUTIL_PCFILE = apr-util-$(APRUTIL_MAJOR_VERSION).pc
+APU_CONFIG = apu-$(APRUTIL_MAJOR_VERSION)-config
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+
+TARGETS = $(TARGET_LIB) aprutil.exp
+
+# bring in rules.mk for standard functionality
+@INCLUDE_RULES@
+@INCLUDE_OUTPUTS@
+
+CLEAN_SUBDIRS = test @APR_ICONV_DIR@
+
+CLEAN_TARGETS = exports.c export_vars.c aprutil.exp .make.dirs apu-config.out
+DISTCLEAN_TARGETS = config.cache config.log config.status libtool \
+ include/private/apu_config.h include/private/apu_private.h \
+ include/private/apu_select_dbm.h include/apr_ldap.h include/apu.h \
+ export_vars.sh $(APU_CONFIG) build/rules.mk include/apu_want.h \
+ apr-util.pc build/pkg/pkginfo
+EXTRACLEAN_TARGETS = configure aclocal.m4 include/private/apu_config.h.in \
+ exports.c build-outputs.mk \
+ build/apr_common.m4 build/find_apr.m4 build/install.sh \
+ build/config.guess build/config.sub
+
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+bindir=@bindir@
+libdir=@libdir@
+includedir=@includedir@
+top_srcdir=@abs_srcdir@
+top_blddir=@abs_builddir@
+
+# Create apu-config script suitable for the install tree
+apu-config.out: $(APU_CONFIG)
+ sed 's,^\(location=\).*$$,\1installed,' < $(APU_CONFIG) > $@
+
+install: $(TARGET_LIB) apu-config.out
+ $(APR_MKDIR) $(DESTDIR)$(includedir) $(DESTDIR)$(libdir)/pkgconfig \
+ $(DESTDIR)$(libdir) $(DESTDIR)$(bindir)
+ for f in $(top_srcdir)/include/*.h $(top_blddir)/include/*.h; do \
+ $(INSTALL_DATA) $${f} $(DESTDIR)$(includedir); \
+ done
+ $(INSTALL_DATA) apr-util.pc $(DESTDIR)$(libdir)/pkgconfig/$(APRUTIL_PCFILE)
+ list='$(INSTALL_SUBDIRS)'; for i in $$list; do \
+ ( cd $$i ; $(MAKE) DESTDIR=$(DESTDIR) install ); \
+ done
+ $(LIBTOOL) --mode=install $(INSTALL) -m 755 $(TARGET_LIB) $(DESTDIR)$(libdir)
+ $(INSTALL_DATA) aprutil.exp $(DESTDIR)$(libdir)
+ $(INSTALL) -m 755 apu-config.out $(DESTDIR)$(bindir)/$(APU_CONFIG)
+
+$(TARGET_LIB): $(OBJECTS)
+ $(LINK) @lib_target@ $(ALL_LIBS) $(APRUTIL_LDFLAGS) $(APRUTIL_LIBS)
+
+exports.c: $(HEADERS)
+ $(APR_MKEXPORT) $(HEADERS) > $@
+
+export_vars.c: $(HEADERS)
+ $(APR_MKVAREXPORT) $(HEADERS) > $@
+
+aprutil.exp: exports.c export_vars.c
+ @echo "#! lib@APRUTIL_LIBNAME@.so" > $@
+ @echo "* This file was AUTOGENERATED at build time." >> $@
+ @echo "* Please do not edit by hand." >> $@
+ $(CPP) $(ALL_CPPFLAGS) $(ALL_INCLUDES) exports.c | grep "ap_hack_" | sed -e 's/^.*[)]\(.*\);$$/\1/' >> $@
+ $(CPP) $(ALL_CPPFLAGS) $(ALL_INCLUDES) export_vars.c | sed -e 's/^\#[^!]*//' | sed -e '/^$$/d' >> $@
+
+dox:
+ doxygen $(top_srcdir)/docs/doxygen.conf
+
+test: check
+check: $(TARGET_LIB)
+ cd test && $(MAKE) check
--- /dev/null
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
+Portions of this software were developed at the National Center
+for Supercomputing Applications (NCSA) at the University of
+Illinois at Urbana-Champaign.
+
+This software contains code derived from the RSA Data Security
+Inc. MD5 Message-Digest Algorithm, including various
+modifications by Spyglass Inc., Carnegie Mellon University, and
+Bell Communications Research, Inc (Bellcore).
--- /dev/null
+#
+# Declare the sub-directories to be built here
+#
+
+SUBDIRS = \
+ ldap \
+ xml \
+ $(EOLIST)
+
+#
+# Get the 'head' of the build environment. This includes default targets and
+# paths to tools
+#
+
+include $(APR_WORK)\build\NWGNUhead.inc
+
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(APR)/include \
+ $(APR)/include/arch/NetWare \
+ $(APRUTIL)/include \
+ $(APRUTIL)/uri \
+ $(APRUTIL)/dbm/sdbm \
+ $(APRUTIL)/include/private \
+ $(APRUTIL)/xml/expat/lib \
+ $(LDAPSDK)/inc \
+ $(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 =
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION =
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME =
+#
+# If this is specified, it will override VERSION value in
+# $(APR_WORK)\build\NWGNUenvironment.inc
+#
+NLM_VERSION =
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE =
+
+#
+# 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 this is 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 $(APR)/misc/netware/apache.xdc. XDCData can
+# be disabled by setting APACHE_UNIPROC in the environment
+#
+XDCDATA =
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+ $(OBJDIR)/aprutil.lib \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+ $(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 = \
+ $(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 = \
+ $(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 = \
+ $(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+ $(OBJDIR)/apr_base64.o \
+ $(OBJDIR)/apr_brigade.o \
+ $(OBJDIR)/apr_buckets.o \
+ $(OBJDIR)/apr_buckets_alloc.o \
+ $(OBJDIR)/apr_buckets_eos.o \
+ $(OBJDIR)/apr_buckets_file.o \
+ $(OBJDIR)/apr_buckets_flush.o \
+ $(OBJDIR)/apr_buckets_heap.o \
+ $(OBJDIR)/apr_buckets_mmap.o \
+ $(OBJDIR)/apr_buckets_pipe.o \
+ $(OBJDIR)/apr_buckets_pool.o \
+ $(OBJDIR)/apr_buckets_refcount.o \
+ $(OBJDIR)/apr_buckets_simple.o \
+ $(OBJDIR)/apr_buckets_socket.o \
+ $(OBJDIR)/apr_date.o \
+ $(OBJDIR)/apr_dbm.o \
+ $(OBJDIR)/apr_dbd.o \
+ $(OBJDIR)/apr_dbd_pgsql.o \
+ $(OBJDIR)/apr_dbm_berkeleydb.o \
+ $(OBJDIR)/apr_dbm_sdbm.o \
+ $(OBJDIR)/apr_hooks.o \
+ $(OBJDIR)/apr_md4.o \
+ $(OBJDIR)/apr_md5.o \
+ $(OBJDIR)/apr_queue.o \
+ $(OBJDIR)/apr_reslist.o \
+ $(OBJDIR)/apr_rmm.o \
+ $(OBJDIR)/apr_sha1.o \
+ $(OBJDIR)/apu_version.o \
+ $(OBJDIR)/getuuid.o \
+ $(OBJDIR)/uuid.o \
+ $(OBJDIR)/apr_strmatch.o \
+ $(OBJDIR)/apr_uri.o \
+ $(OBJDIR)/sdbm.o \
+ $(OBJDIR)/sdbm_hash.o \
+ $(OBJDIR)/sdbm_lock.o \
+ $(OBJDIR)/sdbm_pair.o \
+ $(OBJDIR)/xlate.o \
+ $(EOLIST)
+
+#
+# implement targets and dependancies (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 $(APR_WORK)\build\NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+vpath %.c buckets:crypto:dbd:dbm:dbm/sdbm:encoding:hooks:ldap:misc:strmatch:uri:xlate:xml
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(APR_WORK)\build\NWGNUtail.inc
+
+
--- /dev/null
+APRUTIL LIBRARY STATUS: -*-text-*-
+Last modified at [$Date$]
+
+Release:
+ 1.1.2 : released March 17, 2005
+ 1.1.1 : not released
+ 1.1.0 : released January 25, 2005
+ 1.0.1 : released November 18, 2004
+ 1.0.0 : released September 1, 2004
+ 0.9.5 : released November 19, 2004
+ 0.9.4 : released September 25, 2003
+ 0.9.3 : tagged March 30, 2002
+ 0.9.2 : released March 22, 2002 (alpha)
+ 0.9.1 : released September 11, 2002 (alpha)
+ 0.9.0 : not released
+
+ 2.0a9 : released December 12, 2000
+
+
+RELEASE SHOWSTOPPERS:
+
+RELEASE NON-SHOWSTOPPERS BUT WOULD BE REAL NICE TO WRAP THESE UP:
+
+ * Solaris's Sun Freeware (sfw) package has a busted gcc/ld setup.
+ This gcc passes -L/opt/sfw/lib to /usr/ccs/bin/ld, but does not
+ pass -R. Therefore, when trying to run the code using a
+ library from /opt/sfw/lib (say, libdb), the run-time linker
+ will not look in /opt/sfw/lib and the program will die.
+ Status: Workaround is to add "-R/opt/sfw/lib" to LDFLAGS.
+ Should check latest sfw package set and see if Sun
+ may have fixed this.
+
+ * GDBM usage of errno is not-thread-safe. Fix.
+
+Other bugs that need fixing:
+
+
+
+Other features that need writing:
+
+ * possibly move test/testdbm* to util/dbu
+ Justin says: Do we still want to do this? testdate is now in test.
+ Status: Greg +1 (volunteers)
+
+Documentation that needs writing:
+
+ * API documentation
+ Status:
+
+ * doc the lifetimes of apr_dbm return values
+
+
+Available Patches:
+
+
+Open Issues:
+
--- /dev/null
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+APRUTIL_MAJOR_VERSION=@APRUTIL_MAJOR_VERSION@
+includedir=@includedir@
+
+Name: APR Utils
+Description: Companion library for APR
+Version: @APRUTIL_DOTTED_VERSION@
+# assume that apr-util requires libapr of same major version
+Requires: apr-@APRUTIL_MAJOR_VERSION@
+Libs: -L${libdir} -l@APRUTIL_LIBNAME@ @APRUTIL_EXPORT_LIBS@
+Cflags: -I${includedir}
--- /dev/null
+# Microsoft Developer Studio Project File - Name="aprutil" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=aprutil - 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 "aprutil.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 "aprutil.mak" CFG="aprutil - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "aprutil - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "aprutil - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "aprutil - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "LibR"
+# PROP BASE Intermediate_Dir "LibR"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "LibR"
+# PROP Intermediate_Dir "LibR"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "./include" /I "../apr/include" /I "./include/private" /I "../apr-iconv/include" /I "./dbm/sdbm" /I "./xml/expat/lib" /D "NDEBUG" /D "APR_DECLARE_STATIC" /D "APU_DECLARE_STATIC" /D "API_DECLARE_STATIC" /D "APU_USE_SDBM" /D "WIN32" /D "_WINDOWS" /Fd"LibR\aprutil_src" /FD /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"LibR\aprutil-1.lib"
+
+!ELSEIF "$(CFG)" == "aprutil - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "LibD"
+# PROP BASE Intermediate_Dir "LibD"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "LibD"
+# PROP Intermediate_Dir "LibD"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "./include" /I "../apr/include" /I "./include/private" /I "../apr-iconv/include" /I "./dbm/sdbm" /I "./xml/expat/lib" /D "_DEBUG" /D "APR_DECLARE_STATIC" /D "APU_DECLARE_STATIC" /D "API_DECLARE_STATIC" /D "APU_USE_SDBM" /D "WIN32" /D "_WINDOWS" /Fd"LibD\aprutil_src" /FD /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"LibD\aprutil-1.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "aprutil - Win32 Release"
+# Name "aprutil - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter ""
+# Begin Group "buckets"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\buckets\apr_brigade.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_alloc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_eos.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_file.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_flush.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_heap.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_mmap.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_pipe.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_pool.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_refcount.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_simple.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_socket.c
+# End Source File
+# End Group
+# Begin Group "crypto"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\crypto\apr_md4.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\crypto\apr_md5.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\crypto\apr_sha1.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\crypto\getuuid.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\crypto\uuid.c
+# End Source File
+# End Group
+# Begin Group "dbm"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\dbm\apr_dbm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbm\apr_dbm_berkeleydb.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbm\apr_dbm_gdbm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbm\apr_dbm_sdbm.c
+# End Source File
+# End Group
+# Begin Group "encoding"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\encoding\apr_base64.c
+# End Source File
+# End Group
+# Begin Group "hooks"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\hooks\apr_hooks.c
+# End Source File
+# End Group
+# Begin Group "ldap"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\ldap\apr_ldap_init.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ldap\apr_ldap_url.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ldap\apr_ldap_option.c
+# End Source File
+# End Group
+# Begin Group "misc"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\misc\apr_date.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\misc\apr_queue.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\misc\apr_reslist.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\misc\apr_rmm.c
+# End Source File
+# End Group
+# Begin Group "sdbm"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\dbm\sdbm\sdbm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbm\sdbm\sdbm_hash.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbm\sdbm\sdbm_lock.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbm\sdbm\sdbm_pair.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbm\sdbm\sdbm_pair.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbm\sdbm\sdbm_private.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbm\sdbm\sdbm_tune.h
+# End Source File
+# End Group
+# Begin Group "strmatch"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\strmatch\apr_strmatch.c
+# End Source File
+# End Group
+# Begin Group "uri"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\uri\apr_uri.c
+# End Source File
+# End Group
+# Begin Group "xlate"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\xlate\xlate.c
+# End Source File
+# End Group
+# Begin Group "xml"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\xml\apr_xml.c
+# End Source File
+# End Group
+# End Group
+# Begin Group "Generated Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\include\apr_ldap.h.in
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_ldap.hnw
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_ldap.hw
+
+!IF "$(CFG)" == "aprutil - Win32 Release"
+
+# Begin Custom Build - Creating apr_ldap.h from apr_ldap.hw
+InputPath=.\include\apr_ldap.hw
+
+".\include\apr_ldap.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ type .\include\apr_ldap.hw > .\include\apr_ldap.h
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "aprutil - Win32 Debug"
+
+# Begin Custom Build - Creating apr_ldap.h from apr_ldap.hw
+InputPath=.\include\apr_ldap.hw
+
+".\include\apr_ldap.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ type .\include\apr_ldap.hw > .\include\apr_ldap.h
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apu.h.in
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apu.hnw
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apu.hw
+
+!IF "$(CFG)" == "aprutil - Win32 Release"
+
+# Begin Custom Build - Creating apu.h from apu.hw
+InputPath=.\include\apu.hw
+
+".\include\apu.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ type .\include\apu.hw > .\include\apu.h
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "aprutil - Win32 Debug"
+
+# Begin Custom Build - Creating apu.h from apu.hw
+InputPath=.\include\apu.hw
+
+".\include\apu.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ type .\include\apu.hw > .\include\apu.h
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\private\apu_config.h.in
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\private\apu_config.hw
+
+!IF "$(CFG)" == "aprutil - Win32 Release"
+
+# Begin Custom Build - Creating apu_config.h from apu_config.hw
+InputPath=.\include\private\apu_config.hw
+
+".\include\private\apu_config.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ type .\include\private\apu_config.hw > .\include\private\apu_config.h
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "aprutil - Win32 Debug"
+
+# Begin Custom Build - Creating apu_config.h from apu_config.hw
+InputPath=.\include\private\apu_config.hw
+
+".\include\private\apu_config.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ type .\include\private\apu_config.hw > .\include\private\apu_config.h
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\private\apu_select_dbm.h.in
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\private\apu_select_dbm.hw
+
+!IF "$(CFG)" == "aprutil - Win32 Release"
+
+# Begin Custom Build - Creating apu_select_dbm.h from apu_select_dbm.hw
+InputPath=.\include\private\apu_select_dbm.hw
+
+".\include\private\apu_select_dbm.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ type .\include\private\apu_select_dbm.hw > .\include\private\apu_select_dbm.h
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "aprutil - Win32 Debug"
+
+# Begin Custom Build - Creating apu_select_dbm.h from apu_select_dbm.hw
+InputPath=.\include\private\apu_select_dbm.hw
+
+".\include\private\apu_select_dbm.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ type .\include\private\apu_select_dbm.hw > .\include\private\apu_select_dbm.h
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apu_want.h.in
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apu_want.hnw
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apu_want.hw
+
+!IF "$(CFG)" == "aprutil - Win32 Release"
+
+# Begin Custom Build - Creating apu_want.h from apu_want.hw
+InputPath=.\include\apu_want.hw
+
+".\include\apu_want.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ type .\include\apu_want.hw > .\include\apu_want.h
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "aprutil - Win32 Debug"
+
+# Begin Custom Build - Creating apu_want.h from apu_want.hw
+InputPath=.\include\apu_want.hw
+
+".\include\apu_want.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ type .\include\apu_want.hw > .\include\apu_want.h
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\uri\gen_uri_delims.exe
+
+!IF "$(CFG)" == "aprutil - Win32 Release"
+
+# Begin Custom Build - Generating uri_delims.h
+InputPath=.\uri\gen_uri_delims.exe
+
+".\uri\uri_delims.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ .\uri\gen_uri_delims.exe >.\uri\uri_delims.h
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "aprutil - Win32 Debug"
+
+# Begin Custom Build - Generating uri_delims.h
+InputPath=.\uri\gen_uri_delims.exe
+
+".\uri\uri_delims.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ .\uri\gen_uri_delims.exe >.\uri\uri_delims.h
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# End Group
+# Begin Group "Public Header Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\include\apr_anylock.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_base64.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_buckets.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_date.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_dbm.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_hooks.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_ldap_url.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_md4.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_md5.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_optional.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_optional_hooks.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_queue.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_reslist.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_rmm.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_sdbm.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_sha1.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_strmatch.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_uri.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_uuid.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_xlate.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_xml.h
+# End Source File
+# End Group
+# End Target
+# End Project
--- /dev/null
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "apr"="..\apr\apr.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "apriconv"="..\apr-iconv\apriconv.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name apr
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "aprutil"=".\aprutil.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name apr
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name gen_uri_delims
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name xml
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name apriconv
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "libapr"="..\apr\libapr.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "libapriconv"="..\apr-iconv\libapriconv.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name libapr
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "libapriconv_ccs_modules"="..\apr-iconv\ccs\libapriconv_ccs_modules.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
+}}}
+
+###############################################################################
+
+Project: "libapriconv_ces_modules"="..\apr-iconv\ces\libapriconv_ces_modules.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
+}}}
+
+###############################################################################
+
+Project: "libaprutil"=".\libaprutil.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name libapr
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name gen_uri_delims
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name xml
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name libapriconv
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "gen_uri_delims"=".\uri\gen_uri_delims.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "xml"=".\xml\expat\lib\xml.dsp" - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
--- /dev/null
+#!/bin/sh
+# Copyright 2001-2005 The Apache Software Foundation or its licensors, as
+# applicable.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# APR-util script designed to allow easy command line access to APR-util
+# configuration parameters.
+
+APRUTIL_MAJOR_VERSION="@APRUTIL_MAJOR_VERSION@"
+APRUTIL_DOTTED_VERSION="@APRUTIL_DOTTED_VERSION@"
+
+prefix="@prefix@"
+exec_prefix="@exec_prefix@"
+bindir="@bindir@"
+libdir="@libdir@"
+includedir="@includedir@"
+
+LIBS="@APRUTIL_EXPORT_LIBS@"
+INCLUDES="@APRUTIL_INCLUDES@"
+LDFLAGS="@APRUTIL_LDFLAGS@"
+
+APRUTIL_LIBNAME="@APRUTIL_LIBNAME@"
+
+APU_SOURCE_DIR="@abs_srcdir@"
+APU_BUILD_DIR="@abs_builddir@"
+APR_XML_EXPAT_OLD="@APR_XML_EXPAT_OLD@"
+APU_DB_VERSION="@apu_db_version@"
+
+# NOTE: the following line is modified during 'make install': alter with care!
+location=@APU_CONFIG_LOCATION@
+
+show_usage()
+{
+ cat << EOF
+Usage: apu-$APRUTIL_MAJOR_VERSION-config [OPTION]
+
+Known values for OPTION are:
+ --prefix[=DIR] change prefix to DIR
+ --bindir print location where binaries are installed
+ --includes print include information
+ --includedir print location where headers are installed
+ --ldflags print linker flags
+ --libs print library information
+ --srcdir print APR-util source directory
+ --link-ld print link switch(es) for linking to APR-util
+ --link-libtool print the libtool inputs for linking to APR-util
+ --apu-la-file print the path to the .la file, if available
+ --old-expat indicate if APR-util was built against an old expat
+ --db-version print the DB version
+ --version print APR-util's version as a dotted triple
+ --help print this help
+
+When linking with libtool, an application should do something like:
+ APU_LIBS="\`apu-$APRUTIL_MAJOR_VERSION-config --link-libtool --libs\`"
+or when linking directly:
+ APU_LIBS="\`apu-$APRUTIL_MAJOR_VERSION-config --link-ld --libs\`"
+
+An application should use the results of --includes, and --ldflags in
+their build process.
+EOF
+}
+
+if test $# -eq 0; then
+ show_usage
+ exit 1
+fi
+
+if test "$location" = "installed"; then
+ LA_FILE="$libdir/lib${APRUTIL_LIBNAME}.la"
+
+ LIBS=`echo "$LIBS" | sed -e "s $APU_BUILD_DIR/xml/expat $prefix g" -e "s $prefix/lib/libexpat.la -lexpat g"`
+ LDFLAGS=`echo "$LDFLAGS" | sed -e "s $APU_BUILD_DIR/xml/expat $prefix g"`
+ INCLUDES=`echo "$INCLUDES" | sed -e "s $APU_BUILD_DIR/xml/expat $prefix g" -e "s -I$prefix/lib g"`
+else
+ LA_FILE="$APU_BUILD_DIR/lib${APRUTIL_LIBNAME}.la"
+fi
+
+flags=""
+
+while test $# -gt 0; do
+ # Normalize the prefix.
+ case "$1" in
+ -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) optarg= ;;
+ esac
+
+ case "$1" in
+ # It is possible for the user to override our prefix.
+ --prefix=*)
+ prefix=$optarg
+ ;;
+ --prefix)
+ echo $prefix
+ exit 0
+ ;;
+ --bindir)
+ echo $bindir
+ exit 0
+ ;;
+ --libs)
+ flags="$flags $LIBS"
+ ;;
+ --includedir)
+ if test "$location" = "installed"; then
+ flags="$includedir"
+ elif test "$location" = "source"; then
+ flags="$APU_SOURCE_DIR/include"
+ else
+ # this is for VPATH builds
+ flags="$APU_BUILD_DIR/include $APU_SOURCE_DIR/include"
+ fi
+ echo $flags
+ exit 0
+ ;;
+ --includes)
+ if test "$location" = "installed"; then
+ flags="$flags -I$includedir $INCLUDES"
+ elif test "$location" = "source"; then
+ flags="$flags -I$APU_SOURCE_DIR/include $INCLUDES"
+ else
+ # this is for VPATH builds
+ flags="$flags -I$APU_BUILD_DIR/include -I$APU_SOURCE_DIR/include $INCLUDES"
+ fi
+ ;;
+ --ldflags)
+ flags="$flags $LDFLAGS"
+ ;;
+ --srcdir)
+ echo $APU_SOURCE_DIR
+ exit 0
+ ;;
+ --version)
+ echo $APRUTIL_DOTTED_VERSION
+ exit 0
+ ;;
+ --link-ld)
+ if test "$location" = "installed"; then
+ ### avoid using -L if libdir is a "standard" location like /usr/lib
+ flags="$flags -L$libdir -l$APRUTIL_LIBNAME"
+ else
+ flags="$flags -L$APU_BUILD_DIR -l$APRUTIL_LIBNAME"
+ fi
+ ;;
+ --link-libtool)
+ # If the LA_FILE exists where we think it should be, use it. If we're
+ # installed and the LA_FILE does not exist, assume to use -L/-l
+ # (the LA_FILE may not have been installed). If we're building ourselves,
+ # we'll assume that at some point the .la file be created.
+ if test -f "$LA_FILE"; then
+ flags="$flags $LA_FILE"
+ elif test "$location" = "installed"; then
+ ### avoid using -L if libdir is a "standard" location like /usr/lib
+ # Since the user is specifying they are linking with libtool, we
+ # *know* that -R will be recognized by libtool.
+ flags="$flags -L$libdir -R$libdir -l$APRUTIL_LIBNAME"
+ else
+ flags="$flags $LA_FILE"
+ fi
+ ;;
+ --apu-la-file)
+ if test -f "$LA_FILE"; then
+ flags="$flags $LA_FILE"
+ fi
+ ;;
+ --old-expat)
+ if test ! -n "$APR_XML_EXPAT_OLD"; then
+ echo "no"
+ else
+ echo "$APR_XML_EXPAT_OLD"
+ fi
+ exit 0
+ ;;
+ --db-version)
+ echo $APU_DB_VERSION
+ exit 0
+ ;;
+ --help)
+ show_usage
+ exit 0
+ ;;
+ *)
+ show_usage
+ exit 1
+ ;;
+ esac
+
+ # Next please.
+ shift
+done
+
+if test -n "$flags"; then
+ echo "$flags"
+fi
+
+exit 0
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_lib.h"
+#include "apr_strings.h"
+#include "apr_pools.h"
+#include "apr_tables.h"
+#include "apr_buckets.h"
+#include "apr_errno.h"
+#define APR_WANT_MEMFUNC
+#define APR_WANT_STRFUNC
+#include "apr_want.h"
+
+#if APR_HAVE_SYS_UIO_H
+#include <sys/uio.h>
+#endif
+
+static apr_status_t brigade_cleanup(void *data)
+{
+ return apr_brigade_cleanup(data);
+}
+
+APU_DECLARE(apr_status_t) apr_brigade_cleanup(void *data)
+{
+ apr_bucket_brigade *b = data;
+ apr_bucket *e;
+
+ while (!APR_BRIGADE_EMPTY(b)) {
+ e = APR_BRIGADE_FIRST(b);
+ apr_bucket_delete(e);
+ }
+ /* We don't need to free(bb) because it's allocated from a pool. */
+ return APR_SUCCESS;
+}
+
+APU_DECLARE(apr_status_t) apr_brigade_destroy(apr_bucket_brigade *b)
+{
+ apr_pool_cleanup_kill(b->p, b, brigade_cleanup);
+ return apr_brigade_cleanup(b);
+}
+
+APU_DECLARE(apr_bucket_brigade *) apr_brigade_create(apr_pool_t *p,
+ apr_bucket_alloc_t *list)
+{
+ apr_bucket_brigade *b;
+
+ b = apr_palloc(p, sizeof(*b));
+ b->p = p;
+ b->bucket_alloc = list;
+
+ APR_RING_INIT(&b->list, apr_bucket, link);
+
+ apr_pool_cleanup_register(b->p, b, brigade_cleanup, apr_pool_cleanup_null);
+ return b;
+}
+
+APU_DECLARE(apr_bucket_brigade *) apr_brigade_split(apr_bucket_brigade *b,
+ apr_bucket *e)
+{
+ apr_bucket_brigade *a;
+ apr_bucket *f;
+
+ a = apr_brigade_create(b->p, b->bucket_alloc);
+ /* Return an empty brigade if there is nothing left in
+ * the first brigade to split off
+ */
+ if (e != APR_BRIGADE_SENTINEL(b)) {
+ f = APR_RING_LAST(&b->list);
+ APR_RING_UNSPLICE(e, f, link);
+ APR_RING_SPLICE_HEAD(&a->list, e, f, apr_bucket, link);
+ }
+
+ APR_BRIGADE_CHECK_CONSISTENCY(a);
+ APR_BRIGADE_CHECK_CONSISTENCY(b);
+
+ return a;
+}
+
+APU_DECLARE(apr_status_t) apr_brigade_partition(apr_bucket_brigade *b,
+ apr_off_t point,
+ apr_bucket **after_point)
+{
+ apr_bucket *e;
+ const char *s;
+ apr_size_t len;
+ apr_status_t rv;
+
+ if (point < 0) {
+ /* this could cause weird (not necessarily SEGV) things to happen */
+ return APR_EINVAL;
+ }
+ if (point == 0) {
+ *after_point = APR_BRIGADE_FIRST(b);
+ return APR_SUCCESS;
+ }
+
+ APR_BRIGADE_CHECK_CONSISTENCY(b);
+
+ for (e = APR_BRIGADE_FIRST(b);
+ e != APR_BRIGADE_SENTINEL(b);
+ e = APR_BUCKET_NEXT(e))
+ {
+ if ((e->length == (apr_size_t)(-1)) && (point > (apr_size_t)(-1))) {
+ /* point is too far out to simply split this bucket,
+ * we must fix this bucket's size and keep going... */
+ rv = apr_bucket_read(e, &s, &len, APR_BLOCK_READ);
+ if (rv != APR_SUCCESS) {
+ *after_point = e;
+ return rv;
+ }
+ }
+ if ((point < e->length) || (e->length == (apr_size_t)(-1))) {
+ /* We already checked e->length -1 above, so we now
+ * trust e->length < MAX_APR_SIZE_T.
+ * First try to split the bucket natively... */
+ if ((rv = apr_bucket_split(e, (apr_size_t)point))
+ != APR_ENOTIMPL) {
+ *after_point = APR_BUCKET_NEXT(e);
+ return rv;
+ }
+
+ /* if the bucket cannot be split, we must read from it,
+ * changing its type to one that can be split */
+ rv = apr_bucket_read(e, &s, &len, APR_BLOCK_READ);
+ if (rv != APR_SUCCESS) {
+ *after_point = e;
+ return rv;
+ }
+
+ /* this assumes that len == e->length, which is okay because e
+ * might have been morphed by the apr_bucket_read() above, but
+ * if it was, the length would have been adjusted appropriately */
+ if (point < e->length) {
+ rv = apr_bucket_split(e, (apr_size_t)point);
+ *after_point = APR_BUCKET_NEXT(e);
+ return rv;
+ }
+ }
+ if (point == e->length) {
+ *after_point = APR_BUCKET_NEXT(e);
+ return APR_SUCCESS;
+ }
+ point -= e->length;
+ }
+ *after_point = APR_BRIGADE_SENTINEL(b);
+ return APR_INCOMPLETE;
+}
+
+APU_DECLARE(apr_status_t) apr_brigade_length(apr_bucket_brigade *bb,
+ int read_all, apr_off_t *length)
+{
+ apr_off_t total = 0;
+ apr_bucket *bkt;
+
+ for (bkt = APR_BRIGADE_FIRST(bb);
+ bkt != APR_BRIGADE_SENTINEL(bb);
+ bkt = APR_BUCKET_NEXT(bkt))
+ {
+ if (bkt->length == (apr_size_t)(-1)) {
+ const char *ignore;
+ apr_size_t len;
+ apr_status_t status;
+
+ if (!read_all) {
+ *length = -1;
+ return APR_SUCCESS;
+ }
+
+ if ((status = apr_bucket_read(bkt, &ignore, &len,
+ APR_BLOCK_READ)) != APR_SUCCESS) {
+ return status;
+ }
+ }
+
+ total += bkt->length;
+ }
+
+ *length = total;
+ return APR_SUCCESS;
+}
+
+APU_DECLARE(apr_status_t) apr_brigade_flatten(apr_bucket_brigade *bb,
+ char *c, apr_size_t *len)
+{
+ apr_size_t actual = 0;
+ apr_bucket *b;
+
+ for (b = APR_BRIGADE_FIRST(bb);
+ b != APR_BRIGADE_SENTINEL(bb);
+ b = APR_BUCKET_NEXT(b))
+ {
+ const char *str;
+ apr_size_t str_len;
+ apr_status_t status;
+
+ status = apr_bucket_read(b, &str, &str_len, APR_BLOCK_READ);
+ if (status != APR_SUCCESS) {
+ return status;
+ }
+
+ /* If we would overflow. */
+ if (str_len + actual > *len) {
+ str_len = *len - actual;
+ }
+
+ /* XXX: It appears that overflow of the final bucket
+ * is DISCARDED without any warning to the caller.
+ *
+ * No, we only copy the data up to their requested size. -- jre
+ */
+ memcpy(c, str, str_len);
+
+ c += str_len;
+ actual += str_len;
+
+ /* This could probably be actual == *len, but be safe from stray
+ * photons. */
+ if (actual >= *len) {
+ break;
+ }
+ }
+
+ *len = actual;
+ return APR_SUCCESS;
+}
+
+APU_DECLARE(apr_status_t) apr_brigade_pflatten(apr_bucket_brigade *bb,
+ char **c,
+ apr_size_t *len,
+ apr_pool_t *pool)
+{
+ apr_off_t actual;
+ apr_size_t total;
+ apr_status_t rv;
+
+ apr_brigade_length(bb, 1, &actual);
+
+ /* XXX: This is dangerous beyond belief. At least in the
+ * apr_brigade_flatten case, the user explicitly stated their
+ * buffer length - so we don't up and palloc 4GB for a single
+ * file bucket. This API must grow a useful max boundry,
+ * either compiled-in or preset via the *len value.
+ *
+ * Shouldn't both fn's grow an additional return value for
+ * the case that the brigade couldn't be flattened into the
+ * provided or allocated buffer (such as APR_EMOREDATA?)
+ * Not a failure, simply an advisory result.
+ */
+ total = (apr_size_t)actual;
+
+ *c = apr_palloc(pool, total);
+
+ rv = apr_brigade_flatten(bb, *c, &total);
+
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ *len = total;
+ return APR_SUCCESS;
+}
+
+APU_DECLARE(apr_status_t) apr_brigade_split_line(apr_bucket_brigade *bbOut,
+ apr_bucket_brigade *bbIn,
+ apr_read_type_e block,
+ apr_off_t maxbytes)
+{
+ apr_off_t readbytes = 0;
+
+ while (!APR_BRIGADE_EMPTY(bbIn)) {
+ const char *pos;
+ const char *str;
+ apr_size_t len;
+ apr_status_t rv;
+ apr_bucket *e;
+
+ e = APR_BRIGADE_FIRST(bbIn);
+ rv = apr_bucket_read(e, &str, &len, block);
+
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ pos = memchr(str, APR_ASCII_LF, len);
+ /* We found a match. */
+ if (pos != NULL) {
+ apr_bucket_split(e, pos - str + 1);
+ APR_BUCKET_REMOVE(e);
+ APR_BRIGADE_INSERT_TAIL(bbOut, e);
+ return APR_SUCCESS;
+ }
+ APR_BUCKET_REMOVE(e);
+ APR_BRIGADE_INSERT_TAIL(bbOut, e);
+ readbytes += len;
+ /* We didn't find an APR_ASCII_LF within the maximum line length. */
+ if (readbytes >= maxbytes) {
+ break;
+ }
+ }
+
+ return APR_SUCCESS;
+}
+
+
+APU_DECLARE(apr_status_t) apr_brigade_to_iovec(apr_bucket_brigade *b,
+ struct iovec *vec, int *nvec)
+{
+ int left = *nvec;
+ apr_bucket *e;
+ struct iovec *orig;
+ apr_size_t iov_len;
+ apr_status_t rv;
+
+ orig = vec;
+
+ for (e = APR_BRIGADE_FIRST(b);
+ e != APR_BRIGADE_SENTINEL(b);
+ e = APR_BUCKET_NEXT(e))
+ {
+ if (left-- == 0)
+ break;
+
+ rv = apr_bucket_read(e, (const char **)&vec->iov_base, &iov_len,
+ APR_NONBLOCK_READ);
+ if (rv != APR_SUCCESS)
+ return rv;
+ vec->iov_len = iov_len; /* set indirectly in case size differs */
+ ++vec;
+ }
+
+ *nvec = vec - orig;
+ return APR_SUCCESS;
+}
+
+APU_DECLARE(apr_status_t) apr_brigade_vputstrs(apr_bucket_brigade *b,
+ apr_brigade_flush flush,
+ void *ctx,
+ va_list va)
+{
+ for (;;) {
+ const char *str = va_arg(va, const char *);
+ apr_status_t rv;
+
+ if (str == NULL)
+ break;
+
+ rv = apr_brigade_write(b, flush, ctx, str, strlen(str));
+ if (rv != APR_SUCCESS)
+ return rv;
+ }
+
+ return APR_SUCCESS;
+}
+
+APU_DECLARE(apr_status_t) apr_brigade_putc(apr_bucket_brigade *b,
+ apr_brigade_flush flush, void *ctx,
+ const char c)
+{
+ return apr_brigade_write(b, flush, ctx, &c, 1);
+}
+
+APU_DECLARE(apr_status_t) apr_brigade_write(apr_bucket_brigade *b,
+ apr_brigade_flush flush,
+ void *ctx,
+ const char *str, apr_size_t nbyte)
+{
+ apr_bucket *e = APR_BRIGADE_LAST(b);
+ apr_size_t remaining = APR_BUCKET_BUFF_SIZE;
+ char *buf = NULL;
+
+ if (!APR_BRIGADE_EMPTY(b) && APR_BUCKET_IS_HEAP(e)) {
+ apr_bucket_heap *h = e->data;
+
+ /* HEAP bucket start offsets are always in-memory, safe to cast */
+ remaining = h->alloc_len - (e->length + (apr_size_t)e->start);
+ buf = h->base + e->start + e->length;
+ }
+
+ if (nbyte > remaining) {
+ /* either a buffer bucket exists but is full,
+ * or no buffer bucket exists and the data is too big
+ * to buffer. In either case, we should flush. */
+ if (flush) {
+ e = apr_bucket_transient_create(str, nbyte, b->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(b, e);
+ return flush(b, ctx);
+ }
+ else {
+ e = apr_bucket_heap_create(str, nbyte, NULL, b->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(b, e);
+ return APR_SUCCESS;
+ }
+ }
+ else if (!buf) {
+ /* we don't have a buffer, but the data is small enough
+ * that we don't mind making a new buffer */
+ buf = apr_bucket_alloc(APR_BUCKET_BUFF_SIZE, b->bucket_alloc);
+ e = apr_bucket_heap_create(buf, APR_BUCKET_BUFF_SIZE,
+ apr_bucket_free, b->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(b, e);
+ e->length = 0; /* We are writing into the brigade, and
+ * allocating more memory than we need. This
+ * ensures that the bucket thinks it is empty just
+ * after we create it. We'll fix the length
+ * once we put data in it below.
+ */
+ }
+
+ /* there is a sufficiently big buffer bucket available now */
+ memcpy(buf, str, nbyte);
+ e->length += nbyte;
+
+ return APR_SUCCESS;
+}
+
+APU_DECLARE(apr_status_t) apr_brigade_writev(apr_bucket_brigade *b,
+ apr_brigade_flush flush,
+ void *ctx,
+ const struct iovec *vec,
+ apr_size_t nvec)
+{
+ apr_bucket *e;
+ apr_size_t total_len;
+ apr_size_t i;
+ char *buf;
+
+ /* Compute the total length of the data to be written.
+ */
+ total_len = 0;
+ for (i = 0; i < nvec; i++) {
+ total_len += vec[i].iov_len;
+ }
+
+ /* If the data to be written is very large, try to convert
+ * the iovec to transient buckets rather than copying.
+ */
+ if (total_len > APR_BUCKET_BUFF_SIZE) {
+ if (flush) {
+ for (i = 0; i < nvec; i++) {
+ e = apr_bucket_transient_create(vec[i].iov_base,
+ vec[i].iov_len,
+ b->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(b, e);
+ }
+ return flush(b, ctx);
+ }
+ else {
+ for (i = 0; i < nvec; i++) {
+ e = apr_bucket_heap_create((const char *) vec[i].iov_base,
+ vec[i].iov_len, NULL,
+ b->bucket_alloc);
+ APR_BRIGADE_INSERT_TAIL(b, e);
+ }
+ return APR_SUCCESS;
+ }
+ }
+
+ i = 0;
+
+ /* If there is a heap bucket at the end of the brigade
+ * already, copy into the existing bucket.
+ */
+ e = APR_BRIGADE_LAST(b);
+ if (!APR_BRIGADE_EMPTY(b) && APR_BUCKET_IS_HEAP(e)) {
+ apr_bucket_heap *h = e->data;
+ apr_size_t remaining = h->alloc_len -
+ (e->length + (apr_size_t)e->start);
+ buf = h->base + e->start + e->length;
+
+ if (remaining >= total_len) {
+ /* Simple case: all the data will fit in the
+ * existing heap bucket
+ */
+ for (; i < nvec; i++) {
+ apr_size_t len = vec[i].iov_len;
+ memcpy(buf, (const void *) vec[i].iov_base, len);
+ buf += len;
+ }
+ e->length += total_len;
+ return APR_SUCCESS;
+ }
+ else {
+ /* More complicated case: not all of the data
+ * will fit in the existing heap bucket. The
+ * total data size is <= APR_BUCKET_BUFF_SIZE,
+ * so we'll need only one additional bucket.
+ */
+ const char *start_buf = buf;
+ for (; i < nvec; i++) {
+ apr_size_t len = vec[i].iov_len;
+ if (len > remaining) {
+ break;
+ }
+ memcpy(buf, (const void *) vec[i].iov_base, len);
+ buf += len;
+ remaining -= len;
+ }
+ e->length += (buf - start_buf);
+ total_len -= (buf - start_buf);
+
+ if (flush) {
+ apr_status_t rv = flush(b, ctx);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+ }
+
+ /* Now fall through into the case below to
+ * allocate another heap bucket and copy the
+ * rest of the array. (Note that i is not
+ * reset to zero here; it holds the index
+ * of the first vector element to be
+ * written to the new bucket.)
+ */
+ }
+ }
+
+ /* Allocate a new heap bucket, and copy the data into it.
+ * The checks above ensure that the amount of data to be
+ * written here is no larger than APR_BUCKET_BUFF_SIZE.
+ */
+ buf = apr_bucket_alloc(APR_BUCKET_BUFF_SIZE, b->bucket_alloc);
+ e = apr_bucket_heap_create(buf, APR_BUCKET_BUFF_SIZE,
+ apr_bucket_free, b->bucket_alloc);
+ for (; i < nvec; i++) {
+ apr_size_t len = vec[i].iov_len;
+ memcpy(buf, (const void *) vec[i].iov_base, len);
+ buf += len;
+ }
+ e->length = total_len;
+ APR_BRIGADE_INSERT_TAIL(b, e);
+
+ return APR_SUCCESS;
+}
+
+APU_DECLARE(apr_status_t) apr_brigade_puts(apr_bucket_brigade *bb,
+ apr_brigade_flush flush, void *ctx,
+ const char *str)
+{
+ apr_size_t len = strlen(str);
+ apr_bucket *bkt = APR_BRIGADE_LAST(bb);
+ if (!APR_BRIGADE_EMPTY(bb) && APR_BUCKET_IS_HEAP(bkt)) {
+ /* If there is enough space available in a heap bucket
+ * at the end of the brigade, copy the string directly
+ * into the heap bucket
+ */
+ apr_bucket_heap *h = bkt->data;
+ apr_size_t bytes_avail = h->alloc_len - bkt->length;
+
+ if (bytes_avail >= len) {
+ char *buf = h->base + bkt->start + bkt->length;
+ memcpy(buf, str, len);
+ bkt->length += len;
+ return APR_SUCCESS;
+ }
+ }
+
+ /* If the string could not be copied into an existing heap
+ * bucket, delegate the work to apr_brigade_write(), which
+ * knows how to grow the brigade
+ */
+ return apr_brigade_write(bb, flush, ctx, str, len);
+}
+
+APU_DECLARE_NONSTD(apr_status_t) apr_brigade_putstrs(apr_bucket_brigade *b,
+ apr_brigade_flush flush,
+ void *ctx, ...)
+{
+ va_list va;
+ apr_status_t rv;
+
+ va_start(va, ctx);
+ rv = apr_brigade_vputstrs(b, flush, ctx, va);
+ va_end(va);
+ return rv;
+}
+
+APU_DECLARE_NONSTD(apr_status_t) apr_brigade_printf(apr_bucket_brigade *b,
+ apr_brigade_flush flush,
+ void *ctx,
+ const char *fmt, ...)
+{
+ va_list ap;
+ apr_status_t rv;
+
+ va_start(ap, fmt);
+ rv = apr_brigade_vprintf(b, flush, ctx, fmt, ap);
+ va_end(ap);
+ return rv;
+}
+
+struct brigade_vprintf_data_t {
+ apr_vformatter_buff_t vbuff;
+
+ apr_bucket_brigade *b; /* associated brigade */
+ apr_brigade_flush *flusher; /* flushing function */
+ void *ctx;
+
+ char *cbuff; /* buffer to flush from */
+};
+
+static apr_status_t brigade_flush(apr_vformatter_buff_t *buff)
+{
+ /* callback function passed to ap_vformatter to be
+ * called when vformatter needs to buff and
+ * buff.curpos > buff.endpos
+ */
+
+ /* "downcast," have really passed a brigade_vprintf_data_t* */
+ struct brigade_vprintf_data_t *vd = (struct brigade_vprintf_data_t*)buff;
+ apr_status_t res = APR_SUCCESS;
+
+ res = apr_brigade_write(vd->b, *vd->flusher, vd->ctx, vd->cbuff,
+ APR_BUCKET_BUFF_SIZE);
+
+ if(res != APR_SUCCESS) {
+ return -1;
+ }
+
+ vd->vbuff.curpos = vd->cbuff;
+ vd->vbuff.endpos = vd->cbuff + APR_BUCKET_BUFF_SIZE;
+
+ return res;
+}
+
+APU_DECLARE(apr_status_t) apr_brigade_vprintf(apr_bucket_brigade *b,
+ apr_brigade_flush flush,
+ void *ctx,
+ const char *fmt, va_list va)
+{
+ /* the cast, in order of appearance */
+ struct brigade_vprintf_data_t vd;
+ char buf[APR_BUCKET_BUFF_SIZE];
+ apr_size_t written;
+
+ vd.vbuff.curpos = buf;
+ vd.vbuff.endpos = buf + APR_BUCKET_BUFF_SIZE;
+ vd.b = b;
+ vd.flusher = &flush;
+ vd.ctx = ctx;
+ vd.cbuff = buf;
+
+ written = apr_vformatter(brigade_flush, &vd.vbuff, fmt, va);
+
+ if (written == -1) {
+ return -1;
+ }
+
+ /* tack on null terminator to remaining string */
+ *(vd.vbuff.curpos) = '\0';
+
+ /* write out what remains in the buffer */
+ return apr_brigade_write(b, flush, ctx, buf, vd.vbuff.curpos - buf);
+}
+
+/* A "safe" maximum bucket size, 1Gb */
+#define MAX_BUCKET_SIZE (0x40000000)
+
+APU_DECLARE(apr_bucket *) apr_brigade_insert_file(apr_bucket_brigade *bb,
+ apr_file_t *f,
+ apr_off_t start,
+ apr_off_t length,
+ apr_pool_t *p)
+{
+ apr_bucket *e;
+
+ if (sizeof(apr_off_t) == sizeof(apr_size_t) || length < MAX_BUCKET_SIZE) {
+ e = apr_bucket_file_create(f, start, (apr_size_t)length, p,
+ bb->bucket_alloc);
+ }
+ else {
+ /* Several buckets are needed. */
+ e = apr_bucket_file_create(f, start, MAX_BUCKET_SIZE, p,
+ bb->bucket_alloc);
+
+ while (length > MAX_BUCKET_SIZE) {
+ apr_bucket *ce;
+ apr_bucket_copy(e, &ce);
+ APR_BRIGADE_INSERT_TAIL(bb, ce);
+ e->start += MAX_BUCKET_SIZE;
+ length -= MAX_BUCKET_SIZE;
+ }
+ e->length = (apr_size_t)length; /* Resize just the last bucket */
+ }
+
+ APR_BRIGADE_INSERT_TAIL(bb, e);
+ return e;
+}
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_buckets.h"
+
+APU_DECLARE_NONSTD(apr_status_t) apr_bucket_setaside_noop(apr_bucket *data,
+ apr_pool_t *pool)
+{
+ return APR_SUCCESS;
+}
+
+APU_DECLARE_NONSTD(apr_status_t) apr_bucket_setaside_notimpl(apr_bucket *data,
+ apr_pool_t *pool)
+{
+ return APR_ENOTIMPL;
+}
+
+APU_DECLARE_NONSTD(apr_status_t) apr_bucket_split_notimpl(apr_bucket *data,
+ apr_size_t point)
+{
+ return APR_ENOTIMPL;
+}
+
+APU_DECLARE_NONSTD(apr_status_t) apr_bucket_copy_notimpl(apr_bucket *e,
+ apr_bucket **c)
+{
+ return APR_ENOTIMPL;
+}
+
+APU_DECLARE_NONSTD(void) apr_bucket_destroy_noop(void *data)
+{
+ return;
+}
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdlib.h>
+
+#include "apr_buckets.h"
+#include "apr_allocator.h"
+
+#define ALLOC_AMT (8192 - APR_MEMNODE_T_SIZE)
+
+typedef struct node_header_t {
+ apr_size_t size;
+ apr_bucket_alloc_t *alloc;
+ apr_memnode_t *memnode;
+ struct node_header_t *next;
+} node_header_t;
+
+#define SIZEOF_NODE_HEADER_T APR_ALIGN_DEFAULT(sizeof(node_header_t))
+#define SMALL_NODE_SIZE (APR_BUCKET_ALLOC_SIZE + SIZEOF_NODE_HEADER_T)
+
+/** A list of free memory from which new buckets or private bucket
+ * structures can be allocated.
+ */
+struct apr_bucket_alloc_t {
+ apr_pool_t *pool;
+ apr_allocator_t *allocator;
+ node_header_t *freelist;
+ apr_memnode_t *blocks;
+};
+
+static apr_status_t alloc_cleanup(void *data)
+{
+ apr_bucket_alloc_t *list = data;
+
+ apr_allocator_free(list->allocator, list->blocks);
+
+#if APR_POOL_DEBUG
+ if (list->pool && list->allocator != apr_pool_allocator_get(list->pool)) {
+ apr_allocator_destroy(list->allocator);
+ }
+#endif
+
+ return APR_SUCCESS;
+}
+
+APU_DECLARE_NONSTD(apr_bucket_alloc_t *) apr_bucket_alloc_create(apr_pool_t *p)
+{
+ apr_allocator_t *allocator = apr_pool_allocator_get(p);
+ apr_bucket_alloc_t *list;
+
+#if APR_POOL_DEBUG
+ /* may be NULL for debug mode. */
+ if (allocator == NULL) {
+ if (apr_allocator_create(&allocator) != APR_SUCCESS) {
+ abort();
+ }
+ }
+#endif
+
+ list = apr_bucket_alloc_create_ex(allocator);
+ list->pool = p;
+ apr_pool_cleanup_register(list->pool, list, alloc_cleanup,
+ apr_pool_cleanup_null);
+
+ return list;
+}
+
+APU_DECLARE_NONSTD(apr_bucket_alloc_t *) apr_bucket_alloc_create_ex(
+ apr_allocator_t *allocator)
+{
+ apr_bucket_alloc_t *list;
+ apr_memnode_t *block;
+
+ block = apr_allocator_alloc(allocator, ALLOC_AMT);
+ list = (apr_bucket_alloc_t *)block->first_avail;
+ list->pool = NULL;
+ list->allocator = allocator;
+ list->freelist = NULL;
+ list->blocks = block;
+ block->first_avail += APR_ALIGN_DEFAULT(sizeof(*list));
+
+ return list;
+}
+
+APU_DECLARE_NONSTD(void) apr_bucket_alloc_destroy(apr_bucket_alloc_t *list)
+{
+ if (list->pool) {
+ apr_pool_cleanup_kill(list->pool, list, alloc_cleanup);
+ }
+
+ apr_allocator_free(list->allocator, list->blocks);
+
+#if APR_POOL_DEBUG
+ if (list->pool && list->allocator != apr_pool_allocator_get(list->pool)) {
+ apr_allocator_destroy(list->allocator);
+ }
+#endif
+}
+
+APU_DECLARE_NONSTD(void *) apr_bucket_alloc(apr_size_t size,
+ apr_bucket_alloc_t *list)
+{
+ node_header_t *node;
+ apr_memnode_t *active = list->blocks;
+ char *endp;
+
+ size += SIZEOF_NODE_HEADER_T;
+ if (size <= SMALL_NODE_SIZE) {
+ if (list->freelist) {
+ node = list->freelist;
+ list->freelist = node->next;
+ }
+ else {
+ endp = active->first_avail + SMALL_NODE_SIZE;
+ if (endp >= active->endp) {
+ list->blocks = apr_allocator_alloc(list->allocator, ALLOC_AMT);
+ list->blocks->next = active;
+ active = list->blocks;
+ endp = active->first_avail + SMALL_NODE_SIZE;
+ }
+ node = (node_header_t *)active->first_avail;
+ node->alloc = list;
+ node->memnode = active;
+ node->size = SMALL_NODE_SIZE;
+ active->first_avail = endp;
+ }
+ }
+ else {
+ apr_memnode_t *memnode = apr_allocator_alloc(list->allocator, size);
+ node = (node_header_t *)memnode->first_avail;
+ node->alloc = list;
+ node->memnode = memnode;
+ node->size = size;
+ }
+ return ((char *)node) + SIZEOF_NODE_HEADER_T;
+}
+
+#ifdef APR_BUCKET_DEBUG
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+static void check_not_already_free(node_header_t *node)
+{
+ apr_bucket_alloc_t *list = node->alloc;
+ node_header_t *curr = list->freelist;
+
+ while (curr) {
+ if (node == curr) {
+ abort();
+ }
+ curr = curr->next;
+ }
+}
+#else
+#define check_not_already_free(node)
+#endif
+
+APU_DECLARE_NONSTD(void) apr_bucket_free(void *mem)
+{
+ node_header_t *node = (node_header_t *)((char *)mem - SIZEOF_NODE_HEADER_T);
+ apr_bucket_alloc_t *list = node->alloc;
+
+ if (node->size == SMALL_NODE_SIZE) {
+ check_not_already_free(node);
+ node->next = list->freelist;
+ list->freelist = node;
+ }
+ else {
+ apr_allocator_free(list->allocator, node->memnode);
+ }
+}
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_buckets.h"
+
+static apr_status_t eos_bucket_read(apr_bucket *b, const char **str,
+ apr_size_t *len, apr_read_type_e block)
+{
+ *str = NULL;
+ *len = 0;
+ return APR_SUCCESS;
+}
+
+APU_DECLARE(apr_bucket *) apr_bucket_eos_make(apr_bucket *b)
+{
+ b->length = 0;
+ b->start = 0;
+ b->data = NULL;
+ b->type = &apr_bucket_type_eos;
+
+ return b;
+}
+
+APU_DECLARE(apr_bucket *) apr_bucket_eos_create(apr_bucket_alloc_t *list)
+{
+ apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
+
+ APR_BUCKET_INIT(b);
+ b->free = apr_bucket_free;
+ b->list = list;
+ return apr_bucket_eos_make(b);
+}
+
+APU_DECLARE_DATA const apr_bucket_type_t apr_bucket_type_eos = {
+ "EOS", 5, APR_BUCKET_METADATA,
+ apr_bucket_destroy_noop,
+ eos_bucket_read,
+ apr_bucket_setaside_noop,
+ apr_bucket_split_notimpl,
+ apr_bucket_simple_copy
+};
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_general.h"
+#include "apr_file_io.h"
+#include "apr_buckets.h"
+
+#if APR_HAS_MMAP
+#include "apr_mmap.h"
+
+/* mmap support for static files based on ideas from John Heidemann's
+ * patch against 1.0.5. See
+ * <http://www.isi.edu/~johnh/SOFTWARE/APACHE/index.html>.
+ */
+
+#endif /* APR_HAS_MMAP */
+
+static void file_bucket_destroy(void *data)
+{
+ apr_bucket_file *f = data;
+
+ if (apr_bucket_shared_destroy(f)) {
+ /* no need to close the file here; it will get
+ * done automatically when the pool gets cleaned up */
+ apr_bucket_free(f);
+ }
+}
+
+#if APR_HAS_MMAP
+static int file_make_mmap(apr_bucket *e, apr_size_t filelength,
+ apr_off_t fileoffset, apr_pool_t *p)
+{
+ apr_bucket_file *a = e->data;
+ apr_mmap_t *mm;
+
+ if (!a->can_mmap) {
+ return 0;
+ }
+
+ if (filelength > APR_MMAP_LIMIT) {
+ if (apr_mmap_create(&mm, a->fd, fileoffset, APR_MMAP_LIMIT,
+ APR_MMAP_READ, p) != APR_SUCCESS)
+ {
+ return 0;
+ }
+ apr_bucket_split(e, APR_MMAP_LIMIT);
+ filelength = APR_MMAP_LIMIT;
+ }
+ else if ((filelength < APR_MMAP_THRESHOLD) ||
+ (apr_mmap_create(&mm, a->fd, fileoffset, filelength,
+ APR_MMAP_READ, p) != APR_SUCCESS))
+ {
+ return 0;
+ }
+ apr_bucket_mmap_make(e, mm, 0, filelength);
+ file_bucket_destroy(a);
+ return 1;
+}
+#endif
+
+static apr_status_t file_bucket_read(apr_bucket *e, const char **str,
+ apr_size_t *len, apr_read_type_e block)
+{
+ apr_bucket_file *a = e->data;
+ apr_file_t *f = a->fd;
+ apr_bucket *b = NULL;
+ char *buf;
+ apr_status_t rv;
+ apr_size_t filelength = e->length; /* bytes remaining in file past offset */
+ apr_off_t fileoffset = e->start;
+#if APR_HAS_THREADS && !APR_HAS_XTHREAD_FILES
+ apr_int32_t flags;
+#endif
+
+#if APR_HAS_MMAP
+ if (file_make_mmap(e, filelength, fileoffset, a->readpool)) {
+ return apr_bucket_read(e, str, len, block);
+ }
+#endif
+
+#if APR_HAS_THREADS && !APR_HAS_XTHREAD_FILES
+ if ((flags = apr_file_flags_get(f)) & APR_XTHREAD) {
+ /* this file descriptor is shared across multiple threads and
+ * this OS doesn't support that natively, so as a workaround
+ * we must reopen the file into a->readpool */
+ const char *fname;
+ apr_file_name_get(&fname, f);
+
+ rv = apr_file_open(&f, fname, (flags & ~APR_XTHREAD), 0, a->readpool);
+ if (rv != APR_SUCCESS)
+ return rv;
+
+ a->fd = f;
+ }
+#endif
+
+ *len = (filelength > APR_BUCKET_BUFF_SIZE)
+ ? APR_BUCKET_BUFF_SIZE
+ : filelength;
+ *str = NULL; /* in case we die prematurely */
+ buf = apr_bucket_alloc(*len, e->list);
+
+ /* Handle offset ... */
+ rv = apr_file_seek(f, APR_SET, &fileoffset);
+ if (rv != APR_SUCCESS) {
+ apr_bucket_free(buf);
+ return rv;
+ }
+ rv = apr_file_read(f, buf, len);
+ if (rv != APR_SUCCESS && rv != APR_EOF) {
+ apr_bucket_free(buf);
+ return rv;
+ }
+ filelength -= *len;
+ /*
+ * Change the current bucket to refer to what we read,
+ * even if we read nothing because we hit EOF.
+ */
+ apr_bucket_heap_make(e, buf, *len, apr_bucket_free);
+
+ /* If we have more to read from the file, then create another bucket */
+ if (filelength > 0 && rv != APR_EOF) {
+ /* for efficiency, we can just build a new apr_bucket struct
+ * to wrap around the existing file bucket */
+ b = apr_bucket_alloc(sizeof(*b), e->list);
+ b->start = fileoffset + (*len);
+ b->length = filelength;
+ b->data = a;
+ b->type = &apr_bucket_type_file;
+ b->free = apr_bucket_free;
+ b->list = e->list;
+ APR_BUCKET_INSERT_AFTER(e, b);
+ }
+ else {
+ file_bucket_destroy(a);
+ }
+
+ *str = buf;
+ return rv;
+}
+
+APU_DECLARE(apr_bucket *) apr_bucket_file_make(apr_bucket *b, apr_file_t *fd,
+ apr_off_t offset,
+ apr_size_t len, apr_pool_t *p)
+{
+ apr_bucket_file *f;
+
+ f = apr_bucket_alloc(sizeof(*f), b->list);
+ f->fd = fd;
+ f->readpool = p;
+#if APR_HAS_MMAP
+ f->can_mmap = 1;
+#endif
+
+ b = apr_bucket_shared_make(b, f, offset, len);
+ b->type = &apr_bucket_type_file;
+
+ return b;
+}
+
+APU_DECLARE(apr_bucket *) apr_bucket_file_create(apr_file_t *fd,
+ apr_off_t offset,
+ apr_size_t len, apr_pool_t *p,
+ apr_bucket_alloc_t *list)
+{
+ apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
+
+ APR_BUCKET_INIT(b);
+ b->free = apr_bucket_free;
+ b->list = list;
+ return apr_bucket_file_make(b, fd, offset, len, p);
+}
+
+APU_DECLARE(apr_status_t) apr_bucket_file_enable_mmap(apr_bucket *e,
+ int enabled)
+{
+#if APR_HAS_MMAP
+ apr_bucket_file *a = e->data;
+ a->can_mmap = enabled;
+ return APR_SUCCESS;
+#else
+ return APR_ENOTIMPL;
+#endif /* APR_HAS_MMAP */
+}
+
+
+static apr_status_t file_bucket_setaside(apr_bucket *data, apr_pool_t *reqpool)
+{
+ apr_bucket_file *a = data->data;
+ apr_file_t *fd = NULL;
+ apr_file_t *f = a->fd;
+ apr_pool_t *curpool = apr_file_pool_get(f);
+
+ if (apr_pool_is_ancestor(curpool, reqpool)) {
+ return APR_SUCCESS;
+ }
+
+ if (!apr_pool_is_ancestor(a->readpool, reqpool)) {
+ a->readpool = reqpool;
+ }
+
+ apr_file_setaside(&fd, f, reqpool);
+ a->fd = fd;
+ return APR_SUCCESS;
+}
+
+APU_DECLARE_DATA const apr_bucket_type_t apr_bucket_type_file = {
+ "FILE", 5, APR_BUCKET_DATA,
+ file_bucket_destroy,
+ file_bucket_read,
+ file_bucket_setaside,
+ apr_bucket_shared_split,
+ apr_bucket_shared_copy
+};
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_buckets.h"
+
+static apr_status_t flush_bucket_read(apr_bucket *b, const char **str,
+ apr_size_t *len, apr_read_type_e block)
+{
+ *str = NULL;
+ *len = 0;
+ return APR_SUCCESS;
+}
+
+APU_DECLARE(apr_bucket *) apr_bucket_flush_make(apr_bucket *b)
+{
+ b->length = 0;
+ b->start = 0;
+ b->data = NULL;
+ b->type = &apr_bucket_type_flush;
+
+ return b;
+}
+
+APU_DECLARE(apr_bucket *) apr_bucket_flush_create(apr_bucket_alloc_t *list)
+{
+ apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
+
+ APR_BUCKET_INIT(b);
+ b->free = apr_bucket_free;
+ b->list = list;
+ return apr_bucket_flush_make(b);
+}
+
+APU_DECLARE_DATA const apr_bucket_type_t apr_bucket_type_flush = {
+ "FLUSH", 5, APR_BUCKET_METADATA,
+ apr_bucket_destroy_noop,
+ flush_bucket_read,
+ apr_bucket_setaside_noop,
+ apr_bucket_split_notimpl,
+ apr_bucket_simple_copy
+};
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_buckets.h"
+#define APR_WANT_MEMFUNC
+#include "apr_want.h"
+
+static apr_status_t heap_bucket_read(apr_bucket *b, const char **str,
+ apr_size_t *len, apr_read_type_e block)
+{
+ apr_bucket_heap *h = b->data;
+
+ *str = h->base + b->start;
+ *len = b->length;
+ return APR_SUCCESS;
+}
+
+static void heap_bucket_destroy(void *data)
+{
+ apr_bucket_heap *h = data;
+
+ if (apr_bucket_shared_destroy(h)) {
+ (*h->free_func)(h->base);
+ apr_bucket_free(h);
+ }
+}
+
+/* Warning: if you change this function, be sure to
+ * change apr_bucket_pool_make() too! */
+APU_DECLARE(apr_bucket *) apr_bucket_heap_make(apr_bucket *b, const char *buf,
+ apr_size_t length,
+ void (*free_func)(void *data))
+{
+ apr_bucket_heap *h;
+
+ h = apr_bucket_alloc(sizeof(*h), b->list);
+
+ if (!free_func) {
+ h->alloc_len = length;
+ h->base = apr_bucket_alloc(h->alloc_len, b->list);
+ if (h->base == NULL) {
+ apr_bucket_free(h);
+ return NULL;
+ }
+ h->free_func = apr_bucket_free;
+ memcpy(h->base, buf, length);
+ }
+ else {
+ /* XXX: we lose the const qualifier here which indicates
+ * there's something screwy with the API...
+ */
+ h->base = (char *) buf;
+ h->alloc_len = length;
+ h->free_func = free_func;
+ }
+
+ b = apr_bucket_shared_make(b, h, 0, length);
+ b->type = &apr_bucket_type_heap;
+
+ return b;
+}
+
+APU_DECLARE(apr_bucket *) apr_bucket_heap_create(const char *buf,
+ apr_size_t length,
+ void (*free_func)(void *data),
+ apr_bucket_alloc_t *list)
+{
+ apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
+
+ APR_BUCKET_INIT(b);
+ b->free = apr_bucket_free;
+ b->list = list;
+ return apr_bucket_heap_make(b, buf, length, free_func);
+}
+
+APU_DECLARE_DATA const apr_bucket_type_t apr_bucket_type_heap = {
+ "HEAP", 5, APR_BUCKET_DATA,
+ heap_bucket_destroy,
+ heap_bucket_read,
+ apr_bucket_setaside_noop,
+ apr_bucket_shared_split,
+ apr_bucket_shared_copy
+};
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_buckets.h"
+
+#if APR_HAS_MMAP
+
+static apr_status_t mmap_bucket_read(apr_bucket *b, const char **str,
+ apr_size_t *length, apr_read_type_e block)
+{
+ apr_bucket_mmap *m = b->data;
+ apr_status_t ok;
+ void *addr;
+
+ if (!m->mmap) {
+ /* the apr_mmap_t was already cleaned up out from under us */
+ return APR_EINVAL;
+ }
+
+ ok = apr_mmap_offset(&addr, m->mmap, b->start);
+ if (ok != APR_SUCCESS) {
+ return ok;
+ }
+ *str = addr;
+ *length = b->length;
+ return APR_SUCCESS;
+}
+
+static apr_status_t mmap_bucket_cleanup(void *data)
+{
+ /* the apr_mmap_t is about to disappear out from under us, so we
+ * have no choice but to pretend it doesn't exist anymore. the
+ * refcount is now useless because there's nothing to refer to
+ * anymore. so the only valid action on any remaining referrer
+ * is to delete it. no more reads, no more anything. */
+ apr_bucket_mmap *m = data;
+
+ m->mmap = NULL;
+ return APR_SUCCESS;
+}
+
+static void mmap_bucket_destroy(void *data)
+{
+ apr_bucket_mmap *m = data;
+
+ if (apr_bucket_shared_destroy(m)) {
+ if (m->mmap) {
+ apr_pool_cleanup_kill(m->mmap->cntxt, m, mmap_bucket_cleanup);
+ apr_mmap_delete(m->mmap);
+ }
+ apr_bucket_free(m);
+ }
+}
+
+/*
+ * XXX: are the start and length arguments useful?
+ */
+APU_DECLARE(apr_bucket *) apr_bucket_mmap_make(apr_bucket *b, apr_mmap_t *mm,
+ apr_off_t start,
+ apr_size_t length)
+{
+ apr_bucket_mmap *m;
+
+ m = apr_bucket_alloc(sizeof(*m), b->list);
+ m->mmap = mm;
+
+ apr_pool_cleanup_register(mm->cntxt, m, mmap_bucket_cleanup,
+ apr_pool_cleanup_null);
+
+ b = apr_bucket_shared_make(b, m, start, length);
+ b->type = &apr_bucket_type_mmap;
+
+ return b;
+}
+
+
+APU_DECLARE(apr_bucket *) apr_bucket_mmap_create(apr_mmap_t *mm,
+ apr_off_t start,
+ apr_size_t length,
+ apr_bucket_alloc_t *list)
+{
+ apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
+
+ APR_BUCKET_INIT(b);
+ b->free = apr_bucket_free;
+ b->list = list;
+ return apr_bucket_mmap_make(b, mm, start, length);
+}
+
+static apr_status_t mmap_bucket_setaside(apr_bucket *b, apr_pool_t *p)
+{
+ apr_bucket_mmap *m = b->data;
+ apr_mmap_t *mm = m->mmap;
+ apr_mmap_t *new_mm;
+ apr_status_t ok;
+
+ if (!mm) {
+ /* the apr_mmap_t was already cleaned up out from under us */
+ return APR_EINVAL;
+ }
+
+ /* shortcut if possible */
+ if (apr_pool_is_ancestor(mm->cntxt, p)) {
+ return APR_SUCCESS;
+ }
+
+ /* duplicate apr_mmap_t into new pool */
+ ok = apr_mmap_dup(&new_mm, mm, p);
+ if (ok != APR_SUCCESS) {
+ return ok;
+ }
+
+ /* decrement refcount on old apr_bucket_mmap */
+ mmap_bucket_destroy(m);
+
+ /* create new apr_bucket_mmap pointing to new apr_mmap_t */
+ apr_bucket_mmap_make(b, new_mm, b->start, b->length);
+
+ return APR_SUCCESS;
+}
+
+APU_DECLARE_DATA const apr_bucket_type_t apr_bucket_type_mmap = {
+ "MMAP", 5, APR_BUCKET_DATA,
+ mmap_bucket_destroy,
+ mmap_bucket_read,
+ mmap_bucket_setaside,
+ apr_bucket_shared_split,
+ apr_bucket_shared_copy
+};
+
+#endif
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_buckets.h"
+
+static apr_status_t pipe_bucket_read(apr_bucket *a, const char **str,
+ apr_size_t *len, apr_read_type_e block)
+{
+ apr_file_t *p = a->data;
+ char *buf;
+ apr_status_t rv;
+ apr_interval_time_t timeout;
+
+ if (block == APR_NONBLOCK_READ) {
+ apr_file_pipe_timeout_get(p, &timeout);
+ apr_file_pipe_timeout_set(p, 0);
+ }
+
+ *str = NULL;
+ *len = APR_BUCKET_BUFF_SIZE;
+ buf = apr_bucket_alloc(*len, a->list); /* XXX: check for failure? */
+
+ rv = apr_file_read(p, buf, len);
+
+ if (block == APR_NONBLOCK_READ) {
+ apr_file_pipe_timeout_set(p, timeout);
+ }
+
+ if (rv != APR_SUCCESS && rv != APR_EOF) {
+ apr_bucket_free(buf);
+ return rv;
+ }
+ /*
+ * If there's more to read we have to keep the rest of the pipe
+ * for later. Otherwise, we'll close the pipe.
+ * XXX: Note that more complicated bucket types that
+ * refer to data not in memory and must therefore have a read()
+ * function similar to this one should be wary of copying this
+ * code because if they have a destroy function they probably
+ * want to migrate the bucket's subordinate structure from the
+ * old bucket to a raw new one and adjust it as appropriate,
+ * rather than destroying the old one and creating a completely
+ * new bucket.
+ */
+ if (*len > 0) {
+ apr_bucket_heap *h;
+ /* Change the current bucket to refer to what we read */
+ a = apr_bucket_heap_make(a, buf, *len, apr_bucket_free);
+ h = a->data;
+ h->alloc_len = APR_BUCKET_BUFF_SIZE; /* note the real buffer size */
+ *str = buf;
+ APR_BUCKET_INSERT_AFTER(a, apr_bucket_pipe_create(p, a->list));
+ }
+ else {
+ apr_bucket_free(buf);
+ a = apr_bucket_immortal_make(a, "", 0);
+ *str = a->data;
+ if (rv == APR_EOF) {
+ apr_file_close(p);
+ }
+ }
+ return APR_SUCCESS;
+}
+
+APU_DECLARE(apr_bucket *) apr_bucket_pipe_make(apr_bucket *b, apr_file_t *p)
+{
+ /*
+ * A pipe is closed when the end is reached in pipe_bucket_read(). If
+ * the pipe isn't read to the end (e.g., error path), the pipe will be
+ * closed when its pool goes away.
+ *
+ * Note that typically the pipe is allocated from the request pool
+ * so it will disappear when the request is finished. However the
+ * core filter may decide to set aside the tail end of a CGI
+ * response if the connection is pipelined. This turns out not to
+ * be a problem because the core will have read to the end of the
+ * stream so the bucket(s) that it sets aside will be the heap
+ * buckets created by pipe_bucket_read() above.
+ */
+ b->type = &apr_bucket_type_pipe;
+ b->length = (apr_size_t)(-1);
+ b->start = -1;
+ b->data = p;
+
+ return b;
+}
+
+APU_DECLARE(apr_bucket *) apr_bucket_pipe_create(apr_file_t *p,
+ apr_bucket_alloc_t *list)
+{
+ apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
+
+ APR_BUCKET_INIT(b);
+ b->free = apr_bucket_free;
+ b->list = list;
+ return apr_bucket_pipe_make(b, p);
+}
+
+APU_DECLARE_DATA const apr_bucket_type_t apr_bucket_type_pipe = {
+ "PIPE", 5, APR_BUCKET_DATA,
+ apr_bucket_destroy_noop,
+ pipe_bucket_read,
+ apr_bucket_setaside_notimpl,
+ apr_bucket_split_notimpl,
+ apr_bucket_copy_notimpl
+};
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_buckets.h"
+#define APR_WANT_MEMFUNC
+#include "apr_want.h"
+
+static apr_status_t pool_bucket_cleanup(void *data)
+{
+ apr_bucket_pool *p = data;
+
+ /*
+ * If the pool gets cleaned up, we have to copy the data out
+ * of the pool and onto the heap. But the apr_buckets out there
+ * that point to this pool bucket need to be notified such that
+ * they can morph themselves into a regular heap bucket the next
+ * time they try to read. To avoid having to manipulate
+ * reference counts and b->data pointers, the apr_bucket_pool
+ * actually _contains_ an apr_bucket_heap as its first element,
+ * so the two share their apr_bucket_refcount member, and you
+ * can typecast a pool bucket struct to make it look like a
+ * regular old heap bucket struct.
+ */
+ p->heap.base = apr_bucket_alloc(p->heap.alloc_len, p->list);
+ memcpy(p->heap.base, p->base, p->heap.alloc_len);
+ p->base = NULL;
+ p->pool = NULL;
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t pool_bucket_read(apr_bucket *b, const char **str,
+ apr_size_t *len, apr_read_type_e block)
+{
+ apr_bucket_pool *p = b->data;
+ const char *base = p->base;
+
+ if (p->pool == NULL) {
+ /*
+ * pool has been cleaned up... masquerade as a heap bucket from now
+ * on. subsequent bucket operations will use the heap bucket code.
+ */
+ b->type = &apr_bucket_type_heap;
+ base = p->heap.base;
+ }
+ *str = base + b->start;
+ *len = b->length;
+ return APR_SUCCESS;
+}
+
+static void pool_bucket_destroy(void *data)
+{
+ apr_bucket_pool *p = data;
+
+ /* If the pool is cleaned up before the last reference goes
+ * away, the data is really now on the heap; heap_destroy() takes
+ * over. free() in heap_destroy() thinks it's freeing
+ * an apr_bucket_heap, when in reality it's freeing the whole
+ * apr_bucket_pool for us.
+ */
+ if (p->pool) {
+ /* the shared resource is still in the pool
+ * because the pool has not been cleaned up yet
+ */
+ if (apr_bucket_shared_destroy(p)) {
+ apr_pool_cleanup_kill(p->pool, p, pool_bucket_cleanup);
+ apr_bucket_free(p);
+ }
+ }
+ else {
+ /* the shared resource is no longer in the pool, it's
+ * on the heap, but this reference still thinks it's a pool
+ * bucket. we should just go ahead and pass control to
+ * heap_destroy() for it since it doesn't know any better.
+ */
+ apr_bucket_type_heap.destroy(p);
+ }
+}
+
+APU_DECLARE(apr_bucket *) apr_bucket_pool_make(apr_bucket *b,
+ const char *buf, apr_size_t length, apr_pool_t *pool)
+{
+ apr_bucket_pool *p;
+
+ p = apr_bucket_alloc(sizeof(*p), b->list);
+
+ /* XXX: we lose the const qualifier here which indicates
+ * there's something screwy with the API...
+ */
+ /* XXX: why is this? buf is const, p->base is const... what's
+ * the problem? --jcw */
+ p->base = (char *) buf;
+ p->pool = pool;
+ p->list = b->list;
+
+ b = apr_bucket_shared_make(b, p, 0, length);
+ b->type = &apr_bucket_type_pool;
+
+ /* pre-initialize heap bucket member */
+ p->heap.alloc_len = length;
+ p->heap.base = NULL;
+ p->heap.free_func = apr_bucket_free;
+
+ apr_pool_cleanup_register(p->pool, p, pool_bucket_cleanup,
+ apr_pool_cleanup_null);
+ return b;
+}
+
+APU_DECLARE(apr_bucket *) apr_bucket_pool_create(const char *buf,
+ apr_size_t length,
+ apr_pool_t *pool,
+ apr_bucket_alloc_t *list)
+{
+ apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
+
+ APR_BUCKET_INIT(b);
+ b->free = apr_bucket_free;
+ b->list = list;
+ return apr_bucket_pool_make(b, buf, length, pool);
+}
+
+APU_DECLARE_DATA const apr_bucket_type_t apr_bucket_type_pool = {
+ "POOL", 5, APR_BUCKET_DATA,
+ pool_bucket_destroy,
+ pool_bucket_read,
+ apr_bucket_setaside_noop, /* don't need to setaside thanks to the cleanup*/
+ apr_bucket_shared_split,
+ apr_bucket_shared_copy
+};
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_buckets.h"
+
+APU_DECLARE_NONSTD(apr_status_t) apr_bucket_shared_split(apr_bucket *a,
+ apr_size_t point)
+{
+ apr_bucket_refcount *r = a->data;
+ apr_status_t rv;
+
+ if ((rv = apr_bucket_simple_split(a, point)) != APR_SUCCESS) {
+ return rv;
+ }
+ r->refcount++;
+
+ return APR_SUCCESS;
+}
+
+APU_DECLARE_NONSTD(apr_status_t) apr_bucket_shared_copy(apr_bucket *a,
+ apr_bucket **b)
+{
+ apr_bucket_refcount *r = a->data;
+
+ apr_bucket_simple_copy(a, b);
+ r->refcount++;
+
+ return APR_SUCCESS;
+}
+
+APU_DECLARE(int) apr_bucket_shared_destroy(void *data)
+{
+ apr_bucket_refcount *r = data;
+ r->refcount--;
+ return (r->refcount == 0);
+}
+
+APU_DECLARE(apr_bucket *) apr_bucket_shared_make(apr_bucket *b, void *data,
+ apr_off_t start,
+ apr_size_t length)
+{
+ apr_bucket_refcount *r = data;
+
+ b->data = r;
+ b->start = start;
+ b->length = length;
+ /* caller initializes the type field */
+ r->refcount = 1;
+
+ return b;
+}
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_buckets.h"
+
+APU_DECLARE_NONSTD(apr_status_t) apr_bucket_simple_copy(apr_bucket *a,
+ apr_bucket **b)
+{
+ *b = apr_bucket_alloc(sizeof(**b), a->list); /* XXX: check for failure? */
+ **b = *a;
+
+ return APR_SUCCESS;
+}
+
+APU_DECLARE_NONSTD(apr_status_t) apr_bucket_simple_split(apr_bucket *a,
+ apr_size_t point)
+{
+ apr_bucket *b;
+
+ if (point > a->length) {
+ return APR_EINVAL;
+ }
+
+ apr_bucket_simple_copy(a, &b);
+
+ a->length = point;
+ b->length -= point;
+ b->start += point;
+
+ APR_BUCKET_INSERT_AFTER(a, b);
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t simple_bucket_read(apr_bucket *b, const char **str,
+ apr_size_t *len, apr_read_type_e block)
+{
+ *str = (char *)b->data + b->start;
+ *len = b->length;
+ return APR_SUCCESS;
+}
+
+APU_DECLARE(apr_bucket *) apr_bucket_immortal_make(apr_bucket *b,
+ const char *buf,
+ apr_size_t length)
+{
+ b->data = (char *)buf;
+ b->length = length;
+ b->start = 0;
+ b->type = &apr_bucket_type_immortal;
+
+ return b;
+}
+
+APU_DECLARE(apr_bucket *) apr_bucket_immortal_create(const char *buf,
+ apr_size_t length,
+ apr_bucket_alloc_t *list)
+{
+ apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
+
+ APR_BUCKET_INIT(b);
+ b->free = apr_bucket_free;
+ b->list = list;
+ return apr_bucket_immortal_make(b, buf, length);
+}
+
+/*
+ * XXX: This function could do with some tweaking to reduce memory
+ * usage in various cases, e.g. share buffers in the heap between all
+ * the buckets that are set aside, or even spool set-aside data to
+ * disk if it gets too voluminous (but if it does then that's probably
+ * a bug elsewhere). There should probably be a apr_brigade_setaside()
+ * function that co-ordinates the action of all the bucket setaside
+ * functions to improve memory efficiency.
+ */
+static apr_status_t transient_bucket_setaside(apr_bucket *b, apr_pool_t *pool)
+{
+ b = apr_bucket_heap_make(b, (char *)b->data + b->start, b->length, NULL);
+ if (b == NULL) {
+ return APR_ENOMEM;
+ }
+ return APR_SUCCESS;
+}
+
+APU_DECLARE(apr_bucket *) apr_bucket_transient_make(apr_bucket *b,
+ const char *buf,
+ apr_size_t length)
+{
+ b->data = (char *)buf;
+ b->length = length;
+ b->start = 0;
+ b->type = &apr_bucket_type_transient;
+ return b;
+}
+
+APU_DECLARE(apr_bucket *) apr_bucket_transient_create(const char *buf,
+ apr_size_t length,
+ apr_bucket_alloc_t *list)
+{
+ apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
+
+ APR_BUCKET_INIT(b);
+ b->free = apr_bucket_free;
+ b->list = list;
+ return apr_bucket_transient_make(b, buf, length);
+}
+
+const apr_bucket_type_t apr_bucket_type_immortal = {
+ "IMMORTAL", 5, APR_BUCKET_DATA,
+ apr_bucket_destroy_noop,
+ simple_bucket_read,
+ apr_bucket_setaside_noop,
+ apr_bucket_simple_split,
+ apr_bucket_simple_copy
+};
+
+APU_DECLARE_DATA const apr_bucket_type_t apr_bucket_type_transient = {
+ "TRANSIENT", 5, APR_BUCKET_DATA,
+ apr_bucket_destroy_noop,
+ simple_bucket_read,
+ transient_bucket_setaside,
+ apr_bucket_simple_split,
+ apr_bucket_simple_copy
+};
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_buckets.h"
+
+static apr_status_t socket_bucket_read(apr_bucket *a, const char **str,
+ apr_size_t *len, apr_read_type_e block)
+{
+ apr_socket_t *p = a->data;
+ char *buf;
+ apr_status_t rv;
+ apr_interval_time_t timeout;
+
+ if (block == APR_NONBLOCK_READ) {
+ apr_socket_timeout_get(p, &timeout);
+ apr_socket_timeout_set(p, 0);
+ }
+
+ *str = NULL;
+ *len = APR_BUCKET_BUFF_SIZE;
+ buf = apr_bucket_alloc(*len, a->list); /* XXX: check for failure? */
+
+ rv = apr_socket_recv(p, buf, len);
+
+ if (block == APR_NONBLOCK_READ) {
+ apr_socket_timeout_set(p, timeout);
+ }
+
+ if (rv != APR_SUCCESS && rv != APR_EOF) {
+ apr_bucket_free(buf);
+ return rv;
+ }
+ /*
+ * If there's more to read we have to keep the rest of the socket
+ * for later. XXX: Note that more complicated bucket types that
+ * refer to data not in memory and must therefore have a read()
+ * function similar to this one should be wary of copying this
+ * code because if they have a destroy function they probably
+ * want to migrate the bucket's subordinate structure from the
+ * old bucket to a raw new one and adjust it as appropriate,
+ * rather than destroying the old one and creating a completely
+ * new bucket.
+ *
+ * Even if there is nothing more to read, don't close the socket here
+ * as we have to use it to send any response :) We could shut it
+ * down for reading, but there is no benefit to doing so.
+ */
+ if (*len > 0) {
+ apr_bucket_heap *h;
+ /* Change the current bucket to refer to what we read */
+ a = apr_bucket_heap_make(a, buf, *len, apr_bucket_free);
+ h = a->data;
+ h->alloc_len = APR_BUCKET_BUFF_SIZE; /* note the real buffer size */
+ *str = buf;
+ APR_BUCKET_INSERT_AFTER(a, apr_bucket_socket_create(p, a->list));
+ }
+ else {
+ apr_bucket_free(buf);
+ a = apr_bucket_immortal_make(a, "", 0);
+ *str = a->data;
+ }
+ return APR_SUCCESS;
+}
+
+APU_DECLARE(apr_bucket *) apr_bucket_socket_make(apr_bucket *b, apr_socket_t *p)
+{
+ /*
+ * XXX: We rely on a cleanup on some pool or other to actually
+ * destroy the socket. We should probably explicitly call apr to
+ * destroy it instead.
+ *
+ * Note that typically the socket is allocated from the connection pool
+ * so it will disappear when the connection is finished.
+ */
+ b->type = &apr_bucket_type_socket;
+ b->length = (apr_size_t)(-1);
+ b->start = -1;
+ b->data = p;
+
+ return b;
+}
+
+APU_DECLARE(apr_bucket *) apr_bucket_socket_create(apr_socket_t *p,
+ apr_bucket_alloc_t *list)
+{
+ apr_bucket *b = apr_bucket_alloc(sizeof(*b), list);
+
+ APR_BUCKET_INIT(b);
+ b->free = apr_bucket_free;
+ b->list = list;
+ return apr_bucket_socket_make(b, p);
+}
+
+APU_DECLARE_DATA const apr_bucket_type_t apr_bucket_type_socket = {
+ "SOCKET", 5, APR_BUCKET_DATA,
+ apr_bucket_destroy_noop,
+ socket_bucket_read,
+ apr_bucket_setaside_notimpl,
+ apr_bucket_split_notimpl,
+ apr_bucket_copy_notimpl
+};
--- /dev/null
+#
+# Configuration file for APRUTIL. Used by APR/build/gen-build.py
+#
+
+[options]
+
+# the platform-independent .c files
+paths =
+ buckets/*.c
+ crypto/*.c
+ dbm/*.c
+ dbm/sdbm/*.c
+ encoding/*.c
+ hooks/*.c
+ ldap/*.c
+ misc/*.c
+ uri/apr_uri.c
+ xml/*.c
+ strmatch/*.c
+ xlate/*.c
+ dbd/*.c
+
+# we have no platform-specific subdirs
+platform_dirs =
+
+# the public headers
+headers = include/*.h
+
+# gen_uri_delim.c
+
+# we have a recursive makefile for the test files (for now)
+# test/*.c
--- /dev/null
+dnl -------------------------------------------------------- -*- autoconf -*-
+dnl Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+dnl applicable.
+dnl
+dnl Licensed under the Apache License, Version 2.0 (the "License");
+dnl you may not use this file except in compliance with the License.
+dnl You may obtain a copy of the License at
+dnl
+dnl http://www.apache.org/licenses/LICENSE-2.0
+dnl
+dnl Unless required by applicable law or agreed to in writing, software
+dnl distributed under the License is distributed on an "AS IS" BASIS,
+dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+dnl See the License for the specific language governing permissions and
+dnl limitations under the License.
+
+
+dnl
+dnl custom autoconf rules for APRUTIL
+dnl
+
+dnl
+dnl APU_FIND_APR: figure out where APR is located
+dnl
+AC_DEFUN([APU_FIND_APR], [
+
+ dnl use the find_apr.m4 script to locate APR. sets apr_found and apr_config
+ APR_FIND_APR(,,,[1])
+ if test "$apr_found" = "no"; then
+ AC_MSG_ERROR(APR could not be located. Please use the --with-apr option.)
+ fi
+
+ APR_BUILD_DIR="`$apr_config --installbuilddir`"
+
+ dnl make APR_BUILD_DIR an absolute directory (we'll need it in the
+ dnl sub-projects in some cases)
+ APR_BUILD_DIR="`cd $APR_BUILD_DIR && pwd`"
+
+ APR_INCLUDES="`$apr_config --includes`"
+ APR_LIBS="`$apr_config --link-libtool --libs`"
+ APR_SO_EXT="`$apr_config --apr-so-ext`"
+ APR_LIB_TARGET="`$apr_config --apr-lib-target`"
+
+ AC_SUBST(APR_INCLUDES)
+ AC_SUBST(APR_LIBS)
+ AC_SUBST(APR_BUILD_DIR)
+])
+
+
+dnl
+dnl APU_TEST_EXPAT(directory): test if Expat is located in the specified dir
+dnl
+dnl if present: sets expat_include_dir, expat_libs, possibly expat_old
+dnl
+AC_DEFUN([APU_TEST_EXPAT], [
+ AC_MSG_CHECKING(for Expat in ifelse($2,,$1,$2))
+
+ expat_libtool=""
+
+ if test -r "$1/lib/expat.h.in"; then
+ dnl Expat 1.95.* distribution
+ expat_include_dir="$1/lib"
+ expat_ldflags="-L$1/lib"
+ expat_libs="-lexpat"
+ expat_libtool="$1/lib/libexpat.la"
+ elif test -r "$1/include/expat.h" -a \
+ -r "$1/lib/libexpat.la"; then
+ dnl Expat 1.95.* installation (with libtool)
+ expat_include_dir="$1/include"
+ expat_ldflags="-L$1/lib"
+ expat_libs="-lexpat"
+ expat_libtool="$1/lib/libexpat.la"
+ elif test -r "$1/include/expat.h" -a \
+ -r "$1/lib64/libexpat.la"; then
+ dnl Expat 1.95.* installation on certain 64-bit platforms (with libtool)
+ expat_include_dir="$1/include"
+ expat_ldflags="-L$1/lib64"
+ expat_libs="-lexpat"
+ expat_libtool="$1/lib64/libexpat.la"
+ elif test -r "$1/include/expat.h" -a \
+ -r "$1/lib/libexpat.a"; then
+ dnl Expat 1.95.* installation (without libtool)
+ dnl FreeBSD textproc/expat2
+ expat_include_dir="$1/include"
+ expat_ldflags="-L$1/lib"
+ expat_libs="-lexpat"
+ elif test -r "$1/xmlparse.h"; then
+ dnl maybe an expat-lite. use this dir for both includes and libs
+ expat_include_dir="$1"
+ expat_ldflags="-L$1"
+ expat_libs="-lexpat"
+ expat_libtool="$1/libexpat.la"
+ expat_old=yes
+ elif test -r "$1/include/xmlparse.h" -a \
+ -r "$1/lib/libexpat.a"; then
+ dnl previously installed expat
+ expat_include_dir="$1/include"
+ expat_ldflags="-L$1/lib"
+ expat_libs="-lexpat"
+ expat_old=yes
+ elif test -r "$1/include/xml/xmlparse.h" -a \
+ -r "$1/lib/xml/libexpat.a"; then
+ dnl previously installed expat
+ expat_include_dir="$1/include/xml"
+ expat_ldflags="-L$1/lib"
+ expat_libs="-lexpat"
+ expat_old=yes
+ elif test -r "$1/include/xmltok/xmlparse.h"; then
+ dnl Debian distribution
+ expat_include_dir="$1/include/xmltok"
+ expat_ldflags="-L$1/lib"
+ expat_libs="-lxmlparse -lxmltok"
+ expat_old=yes
+ elif test -r "$1/include/xml/xmlparse.h" -a \
+ -r "$1/lib/libexpat.a"; then
+ dnl FreeBSD textproc/expat package
+ expat_include_dir="$1/include/xml"
+ expat_ldflags="-L$1/lib"
+ expat_libs="-lexpat"
+ expat_old=yes
+ elif test -r "$1/xmlparse/xmlparse.h"; then
+ dnl Expat 1.0 or 1.1 source directory
+ expat_include_dir="$1/xmlparse"
+ expat_ldflags="-L$1"
+ expat_libs="-lexpat"
+ expat_old=yes
+ fi
+ dnl ### test for installed Expat 1.95.* distros
+
+ if test -n "$expat_include_dir"; then
+ dnl ### more info about what we found there? version? using .la?
+ AC_MSG_RESULT(yes)
+ else
+ AC_MSG_RESULT(no)
+ fi
+])
+
+
+dnl
+dnl APU_FIND_EXPAT: figure out where EXPAT is located (or use bundled)
+dnl
+AC_DEFUN([APU_FIND_EXPAT], [
+
+AC_ARG_WITH([expat],
+[ --with-expat=DIR specify Expat location], [
+ if test "$withval" = "yes"; then
+ AC_MSG_ERROR([a directory must be specified for --with-expat])
+ elif test "$withval" = "no"; then
+ AC_MSG_ERROR([Expat cannot be disabled (at this time)])
+ else
+ abs_expatdir="`cd $withval && pwd`"
+ APU_TEST_EXPAT($abs_expatdir, $withval)
+ if test -z "$expat_include_dir"; then
+ AC_MSG_ERROR([Expat was not found (or recognized) in \"$withval\"])
+ fi
+ fi
+])
+
+if test -z "$expat_include_dir"; then
+ for d in /usr /usr/local xml/expat-cvs xml/expat $srcdir/xml/expat ; do
+ APU_TEST_EXPAT($d)
+ if test -n "$expat_include_dir"; then
+ dnl For /usr installs of expat, we can't specify -L/usr/lib
+ if test "$d" = "/usr"; then
+ expat_ldflags=""
+ fi
+ break
+ fi
+ done
+fi
+if test -z "$expat_include_dir"; then
+ AC_MSG_ERROR([could not locate Expat. use --with-expat])
+fi
+
+dnl If this expat doesn't use libtool natively, we'll mimic it for our
+dnl dependency library generation.
+if test -z "$expat_libtool"; then
+ expat_libtool="$expat_ldflags $expat_libs"
+fi
+
+if test -n "$expat_old"; then
+ AC_DEFINE(APR_HAVE_OLD_EXPAT, 1, [define if Expat 1.0 or 1.1 was found])
+fi
+
+dnl special-case the bundled distribution (use absolute dirs)
+if test "$expat_include_dir" = "xml/expat/lib" -o "$expat_include_dir" = "xml/expat-cvs/lib"; then
+ bundled_subdir="`echo $expat_include_dir | sed -e 's%/lib%%'`"
+ APR_SUBDIR_CONFIG($bundled_subdir, [--prefix=$prefix --exec-prefix=$exec_prefix --libdir=$libdir --includedir=$includedir --bindir=$bindir])
+ expat_include_dir=$top_builddir/$bundled_subdir/lib
+ expat_ldflags="-L$top_builddir/$bundled_subdir/lib"
+ expat_libs="-lexpat"
+ expat_libtool=$top_builddir/$bundled_subdir/lib/libexpat.la
+ APR_XML_SUBDIRS="`echo $bundled_subdir | sed -e 's%xml/%%'`"
+ APR_ADDTO(APRUTIL_EXPORT_LIBS, [$expat_libtool])
+else
+if test "$expat_include_dir" = "$abs_srcdir/xml/expat/include" -o "$expat_include_dir" = "$abs_srcdir/xml/expat/lib"; then
+ dnl This is a bit of a hack. This only works because we know that
+ dnl we are working with the bundled version of the software.
+ bundled_subdir="xml/expat"
+ APR_SUBDIR_CONFIG($bundled_subdir, [--prefix=$prefix --exec-prefix=$exec_prefix --libdir=$libdir --includedir=$includedir --bindir=$bindir])
+ expat_include_dir=$top_builddir/$bundled_subdir/lib
+ expat_ldflags="-L$top_builddir/$bundled_subdir/lib"
+ expat_libs="-lexpat"
+ expat_libtool=$top_builddir/$bundled_subdir/lib/libexpat.la
+ APR_XML_SUBDIRS="`echo $bundled_subdir | sed -e 's%xml/%%'`"
+ APR_ADDTO(APRUTIL_EXPORT_LIBS, [$expat_libtool])
+else
+ APR_ADDTO(APRUTIL_EXPORT_LIBS, [$expat_libs])
+fi
+fi
+APR_XML_DIR=$bundled_subdir
+APR_XML_EXPAT_OLD=$expat_old
+AC_SUBST(APR_XML_SUBDIRS)
+AC_SUBST(APR_XML_DIR)
+AC_SUBST(APR_XML_EXPAT_OLD)
+
+if test "$expat_include_dir" != "/usr/include"; then
+ APR_ADDTO(APRUTIL_INCLUDES, [-I$expat_include_dir])
+fi
+APR_ADDTO(APRUTIL_LDFLAGS, [$expat_ldflags])
+APR_ADDTO(APRUTIL_LIBS, [$expat_libtool])
+])
+
+
+dnl
+dnl Find a particular LDAP library
+dnl
+AC_DEFUN([APU_FIND_LDAPLIB], [
+ if test ${apu_has_ldap} != "1"; then
+ ldaplib=$1
+ extralib=$2
+ unset ac_cv_lib_${ldaplib}_ldap_init
+ unset ac_cv_lib_${ldaplib}___ldap_init
+ AC_CHECK_LIB(${ldaplib}, ldap_init,
+ [
+ APR_ADDTO(APRUTIL_EXPORT_LIBS,[-l${ldaplib} ${extralib}])
+ APR_ADDTO(APRUTIL_LIBS,[-l${ldaplib} ${extralib}])
+ AC_CHECK_LIB(${ldaplib}, ldapssl_client_init, apu_has_ldapssl_client_init="1", , ${extralib})
+ AC_CHECK_LIB(${ldaplib}, ldapssl_client_deinit, apu_has_ldapssl_client_deinit="1", , ${extralib})
+ AC_CHECK_LIB(${ldaplib}, ldapssl_add_trusted_cert, apu_has_ldapssl_add_trusted_cert="1", , ${extralib})
+ AC_CHECK_LIB(${ldaplib}, ldap_start_tls_s, apu_has_ldap_start_tls_s="1", , ${extralib})
+ AC_CHECK_LIB(${ldaplib}, ldap_sslinit, apu_has_ldap_sslinit="1", , ${extralib})
+ AC_CHECK_LIB(${ldaplib}, ldapssl_init, apu_has_ldapssl_init="1", , ${extralib})
+ AC_CHECK_LIB(${ldaplib}, ldapssl_install_routines, apu_has_ldapssl_install_routines="1", , ${extralib})
+ apu_has_ldap="1";
+ ], , ${extralib})
+ fi
+])
+
+
+dnl
+dnl APU_FIND_LDAP: figure out where LDAP is located
+dnl
+AC_DEFUN([APU_FIND_LDAP], [
+
+echo $ac_n "${nl}checking for ldap support..."
+
+apu_has_ldap="0";
+apu_has_ldapssl_client_init="0"
+apu_has_ldapssl_client_deinit="0"
+apu_has_ldapssl_add_trusted_cert="0"
+apu_has_ldap_start_tls_s="0"
+apu_has_ldapssl_init="0"
+apu_has_ldap_sslinit="0"
+apu_has_ldapssl_install_routines="0"
+apu_has_ldap_openldap="0"
+apu_has_ldap_solaris="0"
+apu_has_ldap_novell="0"
+apu_has_ldap_microsoft="0"
+apu_has_ldap_netscape="0"
+apu_has_ldap_mozilla="0"
+apu_has_ldap_other="0"
+
+AC_ARG_WITH(ldap-include,[ --with-ldap-include=path path to ldap include files with trailing slash])
+AC_ARG_WITH(ldap-lib,[ --with-ldap-lib=path path to ldap lib file])
+AC_ARG_WITH(ldap,[ --with-ldap=library ldap library to use],
+ [
+ save_cppflags="$CPPFLAGS"
+ save_ldflags="$LDFLAGS"
+ save_libs="$LIBS"
+ if test -n "$with_ldap_include"; then
+ CPPFLAGS="$CPPFLAGS -I$with_ldap_include"
+ APR_ADDTO(APRUTIL_INCLUDES, [-I$with_ldap_include])
+ fi
+ if test -n "$with_ldap_lib"; then
+ LDFLAGS="$LDFLAGS -L$with_ldap_lib"
+ APR_ADDTO(APRUTIL_LDFLAGS, [-L$with_ldap_lib])
+ fi
+
+ LIBLDAP="$withval"
+ if test "$LIBLDAP" = "yes"; then
+dnl The iPlanet C SDK 5.0 is as yet untested...
+ APU_FIND_LDAPLIB("ldap50", "-lnspr4 -lplc4 -lplds4 -liutil50 -llber50 -lldif50 -lnss3 -lprldap50 -lssl3 -lssldap50")
+ APU_FIND_LDAPLIB("ldapssl41", "-lnspr3 -lplc3 -lplds3")
+ APU_FIND_LDAPLIB("ldapssl40")
+ APU_FIND_LDAPLIB("ldapssl30")
+ APU_FIND_LDAPLIB("ldapssl20")
+ APU_FIND_LDAPLIB("ldap", "-llber")
+ APU_FIND_LDAPLIB("ldap", "-llber -lresolv")
+ APU_FIND_LDAPLIB("ldap", "-llber -lresolv -lsocket -lnsl")
+ APU_FIND_LDAPLIB("ldap", "-ldl -lpthread")
+ else
+ APU_FIND_LDAPLIB($LIBLDAP)
+ APU_FIND_LDAPLIB($LIBLDAP, "-lresolv")
+ APU_FIND_LDAPLIB($LIBLDAP, "-lresolv -lsocket -lnsl")
+ APU_FIND_LDAPLIB($LIBLDAP, "-ldl -lpthread")
+ fi
+
+ test ${apu_has_ldap} != "1" && AC_MSG_ERROR(could not find an LDAP library)
+ AC_CHECK_LIB(lber, ber_init)
+
+ AC_CHECK_HEADERS(lber.h, lber_h=["#include <lber.h>"])
+
+ # Solaris has a problem in <ldap.h> which prevents it from
+ # being included by itself. Check for <ldap.h> manually,
+ # including lber.h first.
+ AC_CACHE_CHECK([for ldap.h], [apr_cv_hdr_ldap_h],
+ [AC_TRY_CPP(
+ [#ifdef HAVE_LBER_H
+ #include <lber.h>
+ #endif
+ #include <ldap.h>
+ ], [apr_cv_hdr_ldap_h=yes], [apr_cv_hdr_ldap_h=no])])
+ if test "$apr_cv_hdr_ldap_h" = "yes"; then
+ ldap_h=["#include <ldap.h>"]
+ AC_DEFINE([HAVE_LDAP_H], 1, [Defined if ldap.h is present])
+ fi
+
+ AC_CHECK_HEADERS(ldap_ssl.h, ldap_ssl_h=["#include <ldap_ssl.h>"])
+
+ if test "$apr_cv_hdr_ldap_h" = "yes"; then
+ AC_CACHE_CHECK([for LDAP toolkit],
+ [apr_cv_ldap_toolkit], [
+ if test "x$apr_cv_ldap_toolkit" = "x"; then
+ AC_EGREP_CPP([OpenLDAP], [$lber_h
+ $ldap_h
+ LDAP_VENDOR_NAME], [apu_has_ldap_openldap="1"
+ apr_cv_ldap_toolkit="OpenLDAP"])
+ fi
+ if test "x$apr_cv_ldap_toolkit" = "x"; then
+ AC_EGREP_CPP([Sun Microsystems Inc.], [$lber_h
+ $ldap_h
+ LDAP_VENDOR_NAME], [apu_has_ldap_solaris="1"
+ apr_cv_ldap_toolkit="Solaris"])
+ fi
+ if test "x$apr_cv_ldap_toolkit" = "x"; then
+ AC_EGREP_CPP([Novell], [$lber_h
+ $ldap_h
+ LDAP_VENDOR_NAME], [apu_has_ldap_novell="1"
+ apr_cv_ldap_toolkit="Novell"])
+ fi
+ if test "x$apr_cv_ldap_toolkit" = "x"; then
+ AC_EGREP_CPP([Microsoft Corporation.], [$lber_h
+ $ldap_h
+ LDAP_VENDOR_NAME], [apu_has_ldap_microsoft="1"
+ apr_cv_ldap_toolkit="Microsoft"])
+ fi
+ if test "x$apr_cv_ldap_toolkit" = "x"; then
+ AC_EGREP_CPP([Netscape Communications Corp.], [$lber_h
+ $ldap_h
+ LDAP_VENDOR_NAME], [apu_has_ldap_netscape="1"
+ apr_cv_ldap_toolkit="Netscape"])
+ fi
+ if test "x$apr_cv_ldap_toolkit" = "x"; then
+ AC_EGREP_CPP([mozilla.org], [$lber_h
+ $ldap_h
+ LDAP_VENDOR_NAME], [apu_has_ldap_mozilla="1"
+ apr_cv_ldap_toolkit="Mozilla"])
+ fi
+ if test "x$apr_cv_ldap_toolkit" = "x"; then
+ apu_has_ldap_other="1"
+ apr_cv_ldap_toolkit="unknown"
+ fi
+ ])
+ fi
+
+ CPPFLAGS=$save_cppflags
+ LDFLAGS=$save_ldflags
+ LIBS=$save_libs
+ ])
+
+AC_SUBST(ldap_h)
+AC_SUBST(lber_h)
+AC_SUBST(ldap_ssl_h)
+AC_SUBST(apu_has_ldapssl_client_init)
+AC_SUBST(apu_has_ldapssl_client_deinit)
+AC_SUBST(apu_has_ldapssl_add_trusted_cert)
+AC_SUBST(apu_has_ldap_start_tls_s)
+AC_SUBST(apu_has_ldapssl_init)
+AC_SUBST(apu_has_ldap_sslinit)
+AC_SUBST(apu_has_ldapssl_install_routines)
+AC_SUBST(apu_has_ldap)
+AC_SUBST(apu_has_ldap_openldap)
+AC_SUBST(apu_has_ldap_solaris)
+AC_SUBST(apu_has_ldap_novell)
+AC_SUBST(apu_has_ldap_microsoft)
+AC_SUBST(apu_has_ldap_netscape)
+AC_SUBST(apu_has_ldap_mozilla)
+AC_SUBST(apu_has_ldap_other)
+
+])
+
+dnl
+dnl APU_CHECK_CRYPT_R_STYLE
+dnl
+dnl Decide which of a couple of flavors of crypt_r() is necessary for
+dnl this platform.
+dnl
+AC_DEFUN([APU_CHECK_CRYPT_R_STYLE], [
+
+AC_CACHE_CHECK([style of crypt_r], apr_cv_crypt_r_style,
+[AC_TRY_COMPILE([#include <crypt.h>],
+ [CRYPTD buffer;
+ crypt_r("passwd", "hash", &buffer);],
+ [apr_cv_crypt_r_style=cryptd],
+ [AC_TRY_COMPILE([#include <crypt.h>],
+ [struct crypt_data buffer;
+ crypt_r("passwd", "hash", &buffer);],
+ [apr_cv_crypt_r_style=struct_crypt_data],
+ [apr_cv_crypt_r_style=none])])])
+
+if test "$apr_cv_crypt_r_style" = "cryptd"; then
+ AC_DEFINE(CRYPT_R_CRYPTD, 1, [Define if crypt_r has uses CRYPTD])
+elif test "$apr_cv_crypt_r_style" = "struct_crypt_data"; then
+ AC_DEFINE(CRYPT_R_STRUCT_CRYPT_DATA, 1, [Define if crypt_r uses struct crypt_data])
+fi
+])
--- /dev/null
+dnl -------------------------------------------------------- -*- autoconf -*-
+dnl Copyright 2003-2005 The Apache Software Foundation or its licensors, as
+dnl applicable.
+dnl
+dnl Licensed under the Apache License, Version 2.0 (the "License");
+dnl you may not use this file except in compliance with the License.
+dnl You may obtain a copy of the License at
+dnl
+dnl http://www.apache.org/licenses/LICENSE-2.0
+dnl
+dnl Unless required by applicable law or agreed to in writing, software
+dnl distributed under the License is distributed on an "AS IS" BASIS,
+dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+dnl See the License for the specific language governing permissions and
+dnl limitations under the License.
+
+dnl -----------------------------------------------------------------
+dnl apu-hints.m4: apr-util's autoconf macros for platform-specific hints
+dnl
+dnl We preload various configure settings depending
+dnl on previously obtained platform knowledge.
+dnl We allow all settings to be overridden from
+dnl the command-line.
+
+dnl
+dnl APU_PRELOAD
+dnl
+dnl Preload various build parameters based on outside knowledge.
+dnl
+AC_DEFUN([APU_PRELOAD], [
+if test "x$apu_preload_done" != "xyes" ; then
+ apu_preload_done="yes"
+
+ echo "Applying apr-util hints file rules for $host"
+
+ case "$host" in
+ *-dec-osf*)
+ APR_SETIFNULL(apu_crypt_threadsafe, [1])
+ ;;
+ *-hp-hpux11.*)
+ APR_SETIFNULL(apu_crypt_threadsafe, [1])
+ ;;
+ *-ibm-aix4*|*-ibm-aix5.1*)
+ APR_SETIFNULL(apu_iconv_inbuf_const, [1])
+ ;;
+ *-ibm-os390)
+ APR_SETIFNULL(apu_crypt_threadsafe, [1])
+ ;;
+ *-solaris2*)
+ APR_SETIFNULL(apu_iconv_inbuf_const, [1])
+ APR_SETIFNULL(apu_crypt_threadsafe, [1])
+ ;;
+ *-sco3.2v5*)
+ APR_SETIFNULL(apu_db_xtra_libs, [-lsocket])
+ ;;
+ esac
+
+fi
+])
+
+
--- /dev/null
+dnl -------------------------------------------------------- -*- autoconf -*-
+dnl Copyright 2002-2005 The Apache Software Foundation, or its licensors, as
+dnl applicable.
+dnl
+dnl Licensed under the Apache License, Version 2.0 (the "License");
+dnl you may not use this file except in compliance with the License.
+dnl You may obtain a copy of the License at
+dnl
+dnl http://www.apache.org/licenses/LICENSE-2.0
+dnl
+dnl Unless required by applicable law or agreed to in writing, software
+dnl distributed under the License is distributed on an "AS IS" BASIS,
+dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+dnl See the License for the specific language governing permissions and
+dnl limitations under the License.
+
+dnl
+dnl APU_TRY_ICONV[ IF-SUCCESS, IF-FAILURE ]: try to compile for iconv.
+dnl
+AC_DEFUN([APU_TRY_ICONV], [
+ AC_TRY_LINK([
+#include <stdlib.h>
+#include <iconv.h>
+],
+[
+ iconv_t cd = iconv_open("", "");
+ iconv(cd, NULL, NULL, NULL, NULL);
+], [$1], [$2])
+])
+
+dnl
+dnl APU_FIND_ICONV: find an iconv library
+dnl
+AC_DEFUN([APU_FIND_ICONV], [
+
+apu_iconv_dir="unknown"
+have_apr_iconv="0"
+AC_ARG_WITH(iconv,[ --with-iconv[=DIR] path to iconv installation],
+ [ apu_iconv_dir="$withval"
+ if test "$apu_iconv_dir" != "yes"; then
+ APR_ADDTO(CPPFLAGS,[-I$apu_iconv_dir/include])
+ APR_ADDTO(LDFLAGS,[-L$apu_iconv_dir/lib])
+ fi
+ if test -f "$apu_iconv_dir/include/api_version.h"; then
+ have_apr_iconv="1"
+ have_iconv="0"
+ APR_REMOVEFROM(LIBS,[-lapriconv])
+ AC_MSG_RESULT("Using apr-iconv")
+ fi
+ ])
+
+if test "$have_apr_iconv" != "1"; then
+ AC_CHECK_HEADER(iconv.h, [
+ APU_TRY_ICONV([ have_iconv="1" ], [
+
+ APR_ADDTO(LIBS,[-liconv])
+
+ APU_TRY_ICONV([
+ APR_ADDTO(APRUTIL_LIBS,[-liconv])
+ APR_ADDTO(APRUTIL_EXPORT_LIBS,[-liconv])
+ have_iconv="1" ],
+ [ have_iconv="0" ])
+
+ APR_REMOVEFROM(LIBS,[-liconv])
+
+ ])
+ ], [ have_iconv="0" ])
+fi
+
+if test "$apu_iconv_dir" != "unknown"; then
+ if test "$have_iconv" != "1"; then
+ if test "$have_apr_iconv" != "1"; then
+ AC_MSG_ERROR([iconv support requested, but not found])
+ fi
+ fi
+ APR_REMOVEFROM(CPPFLAGS,[-I$apu_iconv_dir/include])
+ APR_REMOVEFROM(LDFLAGS,[-L$apu_iconv_dir/lib])
+ APR_ADDTO(APRUTIL_INCLUDES,[-I$apu_iconv_dir/include])
+ APR_ADDTO(APRUTIL_LDFLAGS,[-L$apu_iconv_dir/lib])
+fi
+
+if test "$have_iconv" = "1"; then
+ APU_CHECK_ICONV_INBUF
+fi
+
+APR_FLAG_HEADERS(iconv.h langinfo.h)
+APR_FLAG_FUNCS(nl_langinfo)
+APR_CHECK_DEFINE(CODESET, langinfo.h, [CODESET defined in langinfo.h])
+
+AC_SUBST(have_iconv)
+AC_SUBST(have_apr_iconv)
+])dnl
+
+dnl
+dnl APU_CHECK_ICONV_INBUF
+dnl
+dnl Decide whether or not the inbuf parameter to iconv() is const.
+dnl
+dnl We try to compile something without const. If it fails to
+dnl compile, we assume that the system's iconv() has const.
+dnl Unfortunately, we won't realize when there was a compile
+dnl warning, so we allow a variable -- apu_iconv_inbuf_const -- to
+dnl be set in hints.m4 to specify whether or not iconv() has const
+dnl on this parameter.
+dnl
+AC_DEFUN([APU_CHECK_ICONV_INBUF], [
+AC_MSG_CHECKING(for type of inbuf parameter to iconv)
+if test "x$apu_iconv_inbuf_const" = "x"; then
+ APR_TRY_COMPILE_NO_WARNING([
+ #include <stddef.h>
+ #include <iconv.h>
+ ],[
+ iconv(0,(char **)0,(size_t *)0,(char **)0,(size_t *)0);
+ ], apu_iconv_inbuf_const="0", apu_iconv_inbuf_const="1")
+fi
+if test "$apu_iconv_inbuf_const" = "1"; then
+ AC_DEFINE(APU_ICONV_INBUF_CONST, 1, [Define if the inbuf parm to iconv() is const char **])
+ msg="const char **"
+else
+ msg="char **"
+fi
+AC_MSG_RESULT([$msg])
+])dnl
--- /dev/null
+dnl -------------------------------------------------------- -*- autoconf -*-
+dnl Copyright 2005 The Apache Software Foundation or its licensors, as
+dnl applicable.
+dnl
+dnl Licensed under the Apache License, Version 2.0 (the "License");
+dnl you may not use this file except in compliance with the License.
+dnl You may obtain a copy of the License at
+dnl
+dnl http://www.apache.org/licenses/LICENSE-2.0
+dnl
+dnl Unless required by applicable law or agreed to in writing, software
+dnl distributed under the License is distributed on an "AS IS" BASIS,
+dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+dnl See the License for the specific language governing permissions and
+dnl limitations under the License.
+
+dnl
+dnl DBD module
+dnl
+
+dnl
+dnl APU_CHECK_DBD: compile backends for apr_dbd.
+dnl
+AC_DEFUN([APU_CHECK_DBD], [
+ apu_have_pgsql=0
+
+ AC_ARG_WITH([pgsql], [
+ --with-pgsql=DIR specify PostgreSQL location
+ ], [
+ apu_have_pgsql=0
+ if test "$withval" = "yes"; then
+ AC_CHECK_HEADER(libpq-fe.h, AC_CHECK_LIB(pq, PQsendQueryPrepared, [apu_have_pgsql=1]))
+ if test "$apu_have_pgsql" == "0"; then
+ AC_CHECK_HEADER(postgresql/libpq-fe.h, AC_CHECK_LIB(pq, PQsendQueryPrepared, [apu_have_pgsql=1]))
+ if test "$apu_have_pgsql" != "0"; then
+ APR_ADDTO(APRUTIL_INCLUDES, [-I$withval/include/postgresql])
+ fi
+ fi
+ elif test "$withval" = "no"; then
+ apu_have_pgsql=0
+ else
+ CPPFLAGS="-I$withval/include"
+ LIBS="-L$withval/lib "
+
+ AC_MSG_NOTICE(checking for pgsql in $withval)
+ AC_CHECK_HEADER(libpq-fe.h, AC_CHECK_LIB(pq, PQsendQueryPrepared, [apu_have_pgsql=1]))
+ if test "$apu_have_pgsql" != "0"; then
+ APR_ADDTO(APRUTIL_LDFLAGS, [-L$withval/lib])
+ APR_ADDTO(APRUTIL_INCLUDES, [-I$withval/include])
+ fi
+ if test "$apu_have_pgsql" != "1"; then
+ AC_CHECK_HEADER(postgresql/libpq-fe.h, AC_CHECK_LIB(pq, PQsendQueryPrepared, [apu_have_pgsql=1]))
+ if test "$apu_have_pgsql" != "0"; then
+ APR_ADDTO(APRUTIL_INCLUDES, [-I$withval/include/postgresql])
+ APR_ADDTO(APRUTIL_LDFLAGS, [-L$withval/lib])
+ fi
+ fi
+ fi
+ ], [
+ apu_have_pgsql=0
+ AC_CHECK_HEADER(libpq-fe.h, AC_CHECK_LIB(pq, PQsendQueryPrepared, [apu_have_pgsql=1]))
+ ])
+ AC_SUBST(apu_have_pgsql)
+ dnl Since we have already done the AC_CHECK_LIB tests, if we have it,
+ dnl we know the library is there.
+ if test "$apu_have_pgsql" = "1"; then
+ APR_ADDTO(APRUTIL_EXPORT_LIBS,[-lpq])
+ APR_ADDTO(APRUTIL_LIBS,[-lpq])
+ fi
+])
+dnl
+AC_DEFUN([APU_CHECK_DBD_MYSQL], [
+ apu_have_mysql=0
+
+ AC_ARG_WITH([mysql], [
+ --with-mysql=DIR **** SEE INSTALL.MySQL ****
+ ], [
+ apu_have_mysql=0
+ if test "$withval" = "yes"; then
+ AC_CHECK_HEADER(mysql.h, AC_CHECK_LIB(mysqlclient_r, mysql_init, [apu_have_mysql=1]))
+ if test "$apu_have_mysql" == "0"; then
+ AC_CHECK_HEADER(mysql/mysql.h, AC_CHECK_LIB(mysqlclient_r, mysql_init, [apu_have_mysql=1]))
+ if test "$apu_have_mysql" != "0"; then
+ APR_ADDTO(APRUTIL_INCLUDES, [-I$withval/include/myql])
+ fi
+ fi
+ elif test "$withval" = "no"; then
+ apu_have_mysql=0
+ else
+ CPPFLAGS="-I$withval/include"
+ LIBS="-L$withval/lib "
+
+ AC_MSG_NOTICE(checking for mysql in $withval)
+ AC_CHECK_HEADER(mysql.h, AC_CHECK_LIB(mysqlclient_r, mysql_init, [apu_have_mysql=1]))
+ if test "$apu_have_mysql" != "0"; then
+ APR_ADDTO(APRUTIL_LDFLAGS, [-L$withval/lib])
+ APR_ADDTO(APRUTIL_INCLUDES, [-I$withval/include])
+ fi
+
+ if test "$apu_have_mysql" != "1"; then
+ AC_CHECK_HEADER(mysql/mysql.h, AC_CHECK_LIB(mysqlclient_r, mysql_init, [apu_have_mysql=1]))
+ if test "$apu_have_mysql" != "0"; then
+ APR_ADDTO(APRUTIL_INCLUDES, [-I$withval/include/mysql])
+ APR_ADDTO(APRUTIL_LDFLAGS, [-L$withval/lib])
+ fi
+ fi
+ fi
+ ], [
+ apu_have_mysql=0
+ AC_CHECK_HEADER(mysql.h, AC_CHECK_LIB(mysqlclient_r, mysql_init, [apu_have_mysql=1]))
+ ])
+
+ AC_SUBST(apu_have_mysql)
+
+ dnl Since we have already done the AC_CHECK_LIB tests, if we have it,
+ dnl we know the library is there.
+ if test "$apu_have_mysql" = "1"; then
+ APR_ADDTO(APRUTIL_EXPORT_LIBS,[-lmysqlclient_r])
+ APR_ADDTO(APRUTIL_LIBS,[-lmysqlclient_r])
+ fi
+])
+dnl
+AC_DEFUN([APU_CHECK_DBD_SQLITE3], [
+ apu_have_sqlite3=0
+
+ AC_ARG_WITH([sqlite3], [
+ --with-sqlite3=DIR
+ ], [
+ apu_have_sqlite3=0
+ if test "$withval" = "yes"; then
+ AC_CHECK_HEADER(sqlite3.h, AC_CHECK_LIB(sqlite3, sqlite3_open, [apu_have_sqlite3=1]))
+ elif test "$withval" = "no"; then
+ apu_have_sqlite3=0
+ else
+ CPPFLAGS="-I$withval/include"
+ LIBS="-L$withval/lib "
+
+ AC_MSG_NOTICE(checking for sqlite3 in $withval)
+ AC_CHECK_HEADER(sqlite3.h, AC_CHECK_LIB(sqlite3, sqlite3_open, [apu_have_sqlite3=1]))
+ if test "$apu_have_sqlite3" != "0"; then
+ APR_ADDTO(APRUTIL_LDFLAGS, [-L$withval/lib])
+ APR_ADDTO(APRUTIL_INCLUDES, [-I$withval/include])
+ fi
+ fi
+ ], [
+ apu_have_sqlite3=0
+ AC_CHECK_HEADER(sqlite3.h, AC_CHECK_LIB(sqlite3, sqlite3_open, [apu_have_sqlite3=1]))
+ ])
+
+ AC_SUBST(apu_have_sqlite3)
+
+ dnl Since we have already done the AC_CHECK_LIB tests, if we have it,
+ dnl we know the library is there.
+ if test "$apu_have_sqlite3" = "1"; then
+ APR_ADDTO(APRUTIL_EXPORT_LIBS,[-lsqlite3])
+ APR_ADDTO(APRUTIL_LIBS,[-lsqlite3])
+ fi
+])
+dnl
+AC_DEFUN([APU_CHECK_DBD_SQLITE2], [
+ apu_have_sqlite2=0
+
+ AC_ARG_WITH([sqlite2], [
+ --with-sqlite2=DIR
+ ], [
+ apu_have_sqlite2=0
+ if test "$withval" = "yes"; then
+ AC_CHECK_HEADER(sqlite.h, AC_CHECK_LIB(sqlite, sqlite_open, [apu_have_sqlite2=1]))
+ elif test "$withval" = "no"; then
+ apu_have_sqlite2=0
+ else
+ CPPFLAGS="-I$withval/include"
+ LIBS="-L$withval/lib "
+
+ AC_MSG_NOTICE(checking for sqlite2 in $withval)
+ AC_CHECK_HEADER(sqlite.h, AC_CHECK_LIB(sqlite, sqlite_open, [apu_have_sqlite2=1]))
+ if test "$apu_have_sqlite2" != "0"; then
+ APR_ADDTO(APRUTIL_LDFLAGS, [-L$withval/lib])
+ APR_ADDTO(APRUTIL_INCLUDES, [-I$withval/include])
+ fi
+ fi
+ ], [
+ apu_have_sqlite2=0
+ AC_CHECK_HEADER(sqlite.h, AC_CHECK_LIB(sqlite, sqlite_open, [apu_have_sqlite2=1]))
+ ])
+
+ AC_SUBST(apu_have_sqlite2)
+
+ dnl Since we have already done the AC_CHECK_LIB tests, if we have it,
+ dnl we know the library is there.
+ if test "$apu_have_sqlite2" = "1"; then
+ APR_ADDTO(APRUTIL_EXPORT_LIBS,[-lsqlite])
+ APR_ADDTO(APRUTIL_LIBS,[-lsqlite])
+ fi
+])
+dnl
+
--- /dev/null
+dnl -------------------------------------------------------- -*- autoconf -*-
+dnl Copyright 2002-2005 The Apache Software Foundation or its licensors, as
+dnl applicable.
+dnl
+dnl Licensed under the Apache License, Version 2.0 (the "License");
+dnl you may not use this file except in compliance with the License.
+dnl You may obtain a copy of the License at
+dnl
+dnl http://www.apache.org/licenses/LICENSE-2.0
+dnl
+dnl Unless required by applicable law or agreed to in writing, software
+dnl distributed under the License is distributed on an "AS IS" BASIS,
+dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+dnl See the License for the specific language governing permissions and
+dnl limitations under the License.
+
+
+dnl
+dnl DBM module
+dnl
+
+dnl APU_LIB_BERKELEY_DB(major, minor, patch, places, headers, libnames)
+dnl
+dnl Search for a useable version of Berkeley DB in a number of
+dnl common places. The installed DB must be no older than the
+dnl version given by MAJOR, MINOR, and PATCH. All of these
+dnl arguments are allowed to be '-1', indicating we don't care.
+dnl PLACES is a list of places to search for a Berkeley DB
+dnl installation. HEADERS is a list of headers to try. LIBNAMES
+dnl is a list of names of the library to attempt to link against,
+dnl typically 'db' and 'db4'.
+dnl
+dnl If we find a useable version, set CPPFLAGS and LIBS as
+dnl appropriate, and set the shell variable `apu_have_db' to
+dnl `1', and apu_db_lib to the matching lib name, and apu_db_header
+dnl to the header to use. Otherwise, set `apu_have_db' to `0'.
+dnl
+dnl This macro also checks for the `--with-berkeley-db=PATH' flag;
+dnl if given, the macro will use the PATH specified, and the
+dnl configuration script will die if it can't find the library. If
+dnl the user gives the `--without-berkeley-db' flag, the entire
+dnl search is skipped.
+dnl
+dnl We cache the results of individual searches under particular
+dnl prefixes, not the overall result of whether we found Berkeley
+dnl DB. That way, the user can re-run the configure script with
+dnl different --with-berkeley-db switch values, without interference
+dnl from the cache.
+
+
+AC_DEFUN([APU_CHECK_BERKELEY_DB], [
+ bdb_version=$1
+ if test "$2" != "-1"; then
+ bdb_version="$bdb_version.$2"
+ if test "$3" != "-1"; then
+ bdb_version="$bdb_version.$3"
+ fi
+ fi
+ bdb_places=$4
+ bdb_default_search_headers=$5
+ bdb_default_search_lib_names=$6
+
+ apu_have_db=0
+
+ # Save the original values of the flags we tweak.
+ apu_check_lib_save_libs="$LIBS"
+ apu_check_lib_save_ldflags="$LDFLAGS"
+ apu_check_lib_save_cppflags="$CPPFLAGS"
+
+ # The variable `found' is the prefix under which we've found
+ # Berkeley DB, or `not' if we haven't found it anywhere yet.
+ found=not
+ for bdb_place in $bdb_places; do
+
+ LDFLAGS="$apu_check_lib_save_ldflags"
+ CPPFLAGS="$apu_check_lib_save_cppflags"
+ case "$bdb_place" in
+ "std" )
+ description="the standard places"
+ ;;
+ *":"* )
+ header="`echo $bdb_place | sed -e 's/:.*$//'`"
+ lib="`echo $bdb_place | sed -e 's/^.*://'`"
+ CPPFLAGS="$CPPFLAGS -I$header"
+ LDFLAGS="$LDFLAGS -L$lib"
+ description="$header and $lib"
+ ;;
+ * )
+ if test -d $bdb_place; then
+ LDFLAGS="$LDFLAGS -L$bdb_place/lib"
+ CPPFLAGS="$CPPFLAGS -I$bdb_place/include"
+ else
+ AC_MSG_CHECKING([for Berkeley DB $bdb_version in $bdb_place])
+ AC_MSG_RESULT([directory not found])
+ continue
+ fi
+ description="$bdb_place"
+ ;;
+ esac
+
+ # Since there is no AC_MSG_NOTICE in autoconf 2.13, we use this
+ # trick to display a message instead.
+ AC_MSG_CHECKING([for Berkeley DB $bdb_version in $description])
+ AC_MSG_RESULT()
+
+ for bdb_libname in $bdb_default_search_lib_names; do
+ for bdb_header in $bdb_default_search_headers; do
+ # Clear the header cache variable for each location
+ changequote(,)
+ cache_id="`echo ac_cv_header_${bdb_header} \
+ | sed -e 's/[^a-zA-Z0-9_]/_/g'`"
+ changequote([,])
+ unset $cache_id
+ AC_CHECK_HEADER([$bdb_header], [
+ if test "$1" = "3" -o "$1" = "4"; then
+ # We generate a separate cache variable for each prefix and libname
+ # we search under. That way, we avoid caching information that
+ # changes if the user runs `configure' with a different set of
+ # switches.
+ changequote(,)
+ cache_id="`echo apu_cv_check_berkeley_db_$1_$2_$3_${bdb_header}_${bdb_libname}_in_${bdb_place} \
+ | sed -e 's/[^a-zA-Z0-9_]/_/g'`"
+ changequote([,])
+
+ AC_MSG_CHECKING([for -l$bdb_libname])
+ dnl We can't use AC_CACHE_CHECK here, because that won't print out
+ dnl the value of the computed cache variable properly.
+ AC_CACHE_VAL($cache_id,
+ [
+ APU_TRY_BERKELEY_DB($1, $2, $3, $bdb_header, $bdb_libname)
+ eval "$cache_id=$apu_try_berkeley_db"
+ ])
+ result="`eval echo '$'$cache_id`"
+ AC_MSG_RESULT($result)
+ elif test "$1" = "1"; then
+ AC_CHECK_LIB($bdb_libname,
+ dbopen,
+ [result=yes],
+ [result=no]
+ )
+ elif test "$1" = "2"; then
+ AC_CHECK_LIB($bdb_libname,
+ db_open,
+ [result=yes],
+ [result=no]
+ )
+ fi
+ ], [result="no"])
+
+ # If we found it, no need to search any more.
+ if test "$result" = "yes"; then
+ found="$bdb_place"
+ break
+ fi
+ done
+ test "$found" != "not" && break
+ done
+ test "$found" != "not" && break
+ done
+
+ # Restore the original values of the flags we tweak.
+ LDFLAGS="$apu_check_lib_save_ldflags"
+ CPPFLAGS="$apu_check_lib_save_cppflags"
+
+ case "$found" in
+ "not")
+ apu_have_db=0
+ ;;
+ "std")
+ apu_db_header=$bdb_header
+ apu_db_lib=$bdb_libname
+ apu_have_db=1
+ ;;
+ *":"*)
+ header="`echo $found | sed -e 's/:.*$//'`"
+ lib="`echo $found | sed -e 's/^.*://'`"
+
+ APR_ADDTO(APRUTIL_INCLUDES, [-I$header])
+ APR_ADDTO(APRUTIL_LDFLAGS, [-L$lib])
+ apu_db_header=$bdb_header
+ apu_db_lib=$bdb_libname
+ apu_have_db=1
+ ;;
+ *)
+ APR_ADDTO(APRUTIL_INCLUDES, [-I$found/include])
+ APR_ADDTO(APRUTIL_LDFLAGS, [-L$found/lib])
+ apu_db_header=$bdb_header
+ apu_db_lib=$bdb_libname
+ apu_have_db=1
+ ;;
+ esac
+])
+
+
+dnl APU_TRY_BERKELEY_DB(major, minor, patch, header, libname)
+dnl
+dnl A subroutine of APU_CHECK_BERKELEY_DB.
+dnl
+dnl Check that a new-enough version of Berkeley DB is installed.
+dnl "New enough" means no older than the version given by MAJOR,
+dnl MINOR, and PATCH. The result of the test is not cached; no
+dnl messages are printed. Use HEADER as the header file to include.
+dnl Use LIBNAME as the library to link against.
+dnl (e.g. LIBNAME should usually be "db" or "db4".)
+dnl
+dnl Set the shell variable `apu_try_berkeley_db' to `yes' if we found
+dnl an appropriate version installed, or `no' otherwise.
+dnl
+dnl This macro uses the Berkeley DB library function `db_version' to
+dnl find the version. If the library installed doesn't have this
+dnl function, then this macro assumes it is too old.
+
+dnl NOTE: This is pretty messed up. It seems that the FreeBSD port of
+dnl Berkeley DB 4 puts the header file in /usr/local/include/db4, but the
+dnl database library in /usr/local/lib, as libdb4.[a|so]. There is no
+dnl /usr/local/include/db.h. So if you check for /usr/local first, you'll
+dnl get the old header file from /usr/include, and the new library from
+dnl /usr/local/lib. Disaster. Thus this test compares the version constants
+dnl in the db.h header with the ones returned by db_version().
+
+
+AC_DEFUN([APU_TRY_BERKELEY_DB],
+ [
+ apu_try_berkeley_db_save_libs="$LIBS"
+
+ apu_check_berkeley_db_major=$1
+ apu_check_berkeley_db_minor=$2
+ apu_check_berkeley_db_patch=$3
+ apu_try_berkeley_db_header=$4
+ apu_try_berkeley_db_libname=$5
+
+ LIBS="$LIBS -l$apu_try_berkeley_db_libname"
+ AC_TRY_RUN(
+ [
+#include <stdio.h>
+#include <$apu_try_berkeley_db_header>
+main ()
+{
+ int major, minor, patch;
+
+ db_version(&major, &minor, &patch);
+
+ /* Sanity check: ensure that db.h constants actually match the db library */
+ if (major != DB_VERSION_MAJOR
+ || minor != DB_VERSION_MINOR
+ || patch != DB_VERSION_PATCH)
+ exit (1);
+
+ /* Run-time check: ensure the library claims to be the correct version. */
+
+ if ($apu_check_berkeley_db_major != -1) {
+ if (major < $apu_check_berkeley_db_major)
+ exit (1);
+ if (major > $apu_check_berkeley_db_major)
+ exit (0);
+ }
+
+ if ($apu_check_berkeley_db_minor != -1) {
+ if (minor < $apu_check_berkeley_db_minor)
+ exit (1);
+ if (minor > $apu_check_berkeley_db_minor)
+ exit (0);
+ }
+
+ if ($apu_check_berkeley_db_patch == -1
+ || patch >= $apu_check_berkeley_db_patch)
+ exit (0);
+ else
+ exit (1);
+}
+ ],
+ [apu_try_berkeley_db=yes],
+ [apu_try_berkeley_db=no],
+ [apu_try_berkeley_db=yes]
+ )
+
+ LIBS="$apu_try_berkeley_db_save_libs"
+ ]
+)
+
+
+dnl
+dnl APU_CHECK_DB1: is DB1 present?
+dnl
+dnl if present: sets apu_db_header, apu_db_lib, and apu_db_version
+dnl
+AC_DEFUN([APU_CHECK_DB1], [
+ places=$1
+ if test -z "$places"; then
+ places="std"
+ fi
+ APU_CHECK_BERKELEY_DB(1, 0, 0,
+ "$places",
+ "db1/db.h db.h",
+ "db1"
+ )
+ if test "$apu_have_db" = "1"; then
+ apu_db_version=1
+ fi
+])
+
+
+dnl
+dnl APU_CHECK_DB185: is DB1.85 present?
+dnl
+dnl if present: sets apu_db_header, apu_db_lib, and apu_db_version
+dnl
+dnl NB: BerkelyDB v2 and above can be compiled in 1.85 mode
+dnl which has a libdb not libdb1 or libdb185
+AC_DEFUN([APU_CHECK_DB185], [
+ places=$1
+ if test -z "$places"; then
+ places="std"
+ fi
+ APU_CHECK_BERKELEY_DB(1, -1, -1,
+ "$places",
+ "db_185.h",
+ "db"
+ )
+ if test "$apu_have_db" = "1"; then
+ apu_db_version=185
+ fi
+])
+
+
+dnl
+dnl APU_CHECK_DB2: is DB2 present?
+dnl
+dnl if present: sets apu_db_header, apu_db_lib, and apu_db_version
+dnl
+AC_DEFUN([APU_CHECK_DB2], [
+ places=$1
+ if test -z "$places"; then
+ places="std"
+ fi
+ APU_CHECK_BERKELEY_DB(2, -1, -1,
+ "$places",
+ "db2/db.h db.h",
+ "db2 db"
+ )
+ if test "$apu_have_db" = "1"; then
+ apu_db_version=2
+ fi
+])
+
+
+dnl
+dnl APU_CHECK_DB3: is DB3 present?
+dnl
+dnl if present: sets apu_db_header, apu_db_lib, and apu_db_version
+dnl
+AC_DEFUN([APU_CHECK_DB3], [
+ places=$1
+ if test -z "$places"; then
+ places="std"
+ fi
+ APU_CHECK_BERKELEY_DB(3, -1, -1,
+ "$places",
+ "db3/db.h db.h",
+ "db3 db"
+ )
+ if test "$apu_have_db" = "1"; then
+ apu_db_version=3
+ fi
+])
+
+
+dnl
+dnl APU_CHECK_DB4: is DB4 present?
+dnl
+dnl if present: sets apu_db_header, apu_db_lib, and apu_db_version
+dnl
+AC_DEFUN([APU_CHECK_DB4], [
+ places=$1
+ if test -z "$places"; then
+ places="std /usr/local /usr/local/BerkeleyDB.4.0 /boot/home/config"
+ fi
+ APU_CHECK_BERKELEY_DB("4", "0", "-1",
+ "$places",
+ "db4/db.h db.h",
+ "db-4.0 db4 db"
+ )
+ if test "$apu_have_db" = "1"; then
+ apu_db_version=4
+ fi
+])
+
+
+dnl
+dnl APU_CHECK_DB41: is DB4.1 present?
+dnl
+dnl if present: sets apu_db_header, apu_db_lib, and apu_db_version
+dnl
+AC_DEFUN([APU_CHECK_DB41], [
+ places=$1
+ if test -z "$places"; then
+ places="std /usr/local /usr/local/BerkeleyDB.4.1 /boot/home/config"
+ fi
+ APU_CHECK_BERKELEY_DB("4", "1", "-1",
+ "$places",
+ "db41/db.h db4/db.h db.h",
+ "db-4.1 db41 db4 db"
+ )
+ if test "$apu_have_db" = "1"; then
+ apu_db_version=4
+ fi
+])
+
+
+dnl
+dnl APU_CHECK_DB42: is DB4.2 present?
+dnl
+dnl if present: sets apu_db_header, apu_db_lib, and apu_db_version
+dnl
+AC_DEFUN([APU_CHECK_DB42], [
+ places=$1
+ if test -z "$places"; then
+ places="std /usr/local /usr/local/BerkeleyDB.4.2 /boot/home/config"
+ fi
+ APU_CHECK_BERKELEY_DB("4", "2", "-1",
+ "$places",
+ "db42/db.h db4/db.h db.h",
+ "db-4.2 db42 db4 db"
+ )
+ if test "$apu_have_db" = "1"; then
+ apu_db_version=4
+ fi
+])
+dnl
+dnl APU_CHECK_DB43: is DB4.3 present?
+dnl
+dnl if present: sets apu_db_header, apu_db_lib, and apu_db_version
+dnl
+AC_DEFUN([APU_CHECK_DB43], [
+ places=$1
+ if test -z "$places"; then
+ places="std /usr/local/BerkeleyDB.4.3 /boot/home/config"
+ fi
+ APU_CHECK_BERKELEY_DB("4", "3", "-1",
+ "$places",
+ "db43/db.h db4/db.h db.h",
+ "db-4.3 db4-4.3 db43 db4 db"
+ )
+ if test "$apu_have_db" = "1"; then
+ apu_db_version=4
+ fi
+])
+
+
+AC_DEFUN([APU_CHECK_DB], [
+ requested=$1
+ check_places=$2
+
+ case "$requested" in
+ db)
+ APU_CHECK_DB_ALL("$check_places")
+ if test "$apu_have_db" = "0"; then
+ AC_MSG_ERROR(Berkeley db requested, but not found)
+ fi
+ ;;
+ db1)
+ APU_CHECK_DB1("$check_places")
+ if test "$apu_db_version" != "1"; then
+ AC_MSG_ERROR(Berkeley db1 not found)
+ fi
+ ;;
+ db185)
+ APU_CHECK_DB185("$check_places")
+ if test "$apu_db_version" != "185"; then
+ AC_MSG_ERROR(Berkeley db185 not found)
+ fi
+ ;;
+ db2)
+ APU_CHECK_DB2("$check_places")
+ if test "$apu_db_version" != "2"; then
+ AC_MSG_ERROR(Berkeley db2 not found)
+ fi
+ ;;
+ db3)
+ APU_CHECK_DB3("$check_places")
+ if test "$apu_db_version" != "3"; then
+ AC_MSG_ERROR(Berkeley db3 not found)
+ fi
+ ;;
+ db4)
+ APU_CHECK_DB4("$check_places")
+ if test "$apu_db_version" != "4"; then
+ AC_MSG_ERROR(Berkeley db4 not found)
+ fi
+ ;;
+ db41)
+ APU_CHECK_DB41("$check_places")
+ if test "$apu_db_version" != "4"; then
+ AC_MSG_ERROR(Berkeley db4 not found)
+ fi
+ ;;
+ db42)
+ APU_CHECK_DB42("$check_places")
+ if test "$apu_db_version" != "4"; then
+ AC_MSG_ERROR(Berkeley db4 not found)
+ fi
+ ;;
+ db43)
+ APU_CHECK_DB43("$check_places")
+ if test "$apu_db_version" != "4"; then
+ AC_MSG_ERROR(Berkeley db4 not found)
+ fi
+ ;;
+ default)
+ APU_CHECK_DB_ALL("$check_places")
+ ;;
+ esac
+])
+
+dnl
+dnl APU_CHECK_DB_ALL: Try all Berkeley DB versions, from 4.3 to 1.
+dnl
+AC_DEFUN([APU_CHECK_DB_ALL], [
+ all_places=$1
+
+ APU_CHECK_DB43("$all_places")
+ if test "$apu_db_version" != "4"; then
+ APU_CHECK_DB42("$all_places")
+ if test "$apu_db_version" != "4"; then
+ APU_CHECK_DB41("$all_places")
+ if test "$apu_db_version" != "4"; then
+ APU_CHECK_DB4("$all_places")
+ if test "$apu_db_version" != "4"; then
+ APU_CHECK_DB3("$all_places")
+ if test "$apu_db_version" != "3"; then
+ APU_CHECK_DB2("$all_places")
+ if test "$apu_db_version" != "2"; then
+ APU_CHECK_DB1("$all_places")
+ if test "$apu_db_version" != "1"; then
+ APU_CHECK_DB185("$all_places")
+ fi
+ fi
+ fi
+ fi
+ fi
+ fi
+ fi
+ AC_MSG_CHECKING(for Berkeley DB)
+ if test "$apu_have_db" = "1"; then
+ AC_MSG_RESULT(found db$apu_db_version)
+ else
+ AC_MSG_RESULT(not found)
+ fi
+])
+
+
+dnl
+dnl APU_CHECK_DBM: see what kind of DBM backend to use for apr_dbm.
+dnl
+AC_DEFUN([APU_CHECK_DBM], [
+ apu_use_sdbm=0
+ apu_use_ndbm=0
+ apu_use_gdbm=0
+ apu_use_db=0
+ dnl it's in our codebase
+ apu_have_sdbm=1
+ apu_have_gdbm=0
+ apu_have_ndbm=0
+ apu_have_db=0
+
+ apu_db_header=db.h # default so apu_select_dbm.h is syntactically correct
+ apu_db_version=0
+
+ AC_ARG_WITH(dbm, [
+ --with-dbm=DBM choose the DBM type to use.
+ DBM={sdbm,gdbm,ndbm,db,db1,db185,db2,db3,db4,db41,db42,db43}
+ ], [
+ if test "$withval" = "yes"; then
+ AC_MSG_ERROR([--with-dbm needs to specify a DBM type to use.
+ One of: sdbm, gdbm, ndbm, db, db1, db185, db2, db3, db4, db41, db42, db43])
+ fi
+ requested="$withval"
+ ], [
+ requested=default
+ ])
+
+ AC_ARG_WITH([gdbm], [
+ --with-gdbm=DIR specify GDBM location
+ ], [
+ apu_have_gdbm=0
+ if test "$withval" = "yes"; then
+ AC_CHECK_HEADER(gdbm.h, AC_CHECK_LIB(gdbm, gdbm_open, [apu_have_gdbm=1]))
+ elif test "$withval" = "no"; then
+ apu_have_gdbm=0
+ else
+ CPPFLAGS="-I$withval/include"
+ LIBS="-L$withval/lib "
+
+ AC_MSG_CHECKING(checking for gdbm in $withval)
+ AC_CHECK_HEADER(gdbm.h, AC_CHECK_LIB(gdbm, gdbm_open, [apu_have_gdbm=1]))
+ if test "$apu_have_gdbm" != "0"; then
+ APR_ADDTO(APRUTIL_LDFLAGS, [-L$withval/lib])
+ APR_ADDTO(APRUTIL_INCLUDES, [-I$withval/include])
+ fi
+ fi
+ ], [
+ apu_have_gdbm=0
+ AC_CHECK_HEADER(gdbm.h, AC_CHECK_LIB(gdbm, gdbm_open, [apu_have_gdbm=1]))
+ ])
+
+ AC_ARG_WITH([ndbm], [
+ --with-ndbm=PATH
+ Find the NDBM header and library in \`PATH/include' and
+ \`PATH/lib'. If PATH is of the form \`HEADER:LIB', then search
+ for header files in HEADER, and the library in LIB. If you omit
+ the \`=PATH' part completely, the configure script will search
+ for NDBM in a number of standard places.
+ ], [
+ apu_have_ndbm=0
+ if test "$withval" = "yes"; then
+ AC_MSG_CHECKING(checking for ndbm in the usual places)
+ apu_want_ndbm=1
+ NDBM_INC=""
+ NDBM_LDFLAGS=""
+ elif test "$withval" = "no"; then
+ apu_want_ndbm=0
+ else
+ apu_want_ndbm=1
+ case "$withval" in
+ *":"*)
+ NDBM_INC="-I`echo $withval |sed -e 's/:.*$//'`"
+ NDBM_LDFLAGS="-L`echo $withval |sed -e 's/^.*://'`"
+ AC_MSG_CHECKING(checking for ndbm includes with $NDBM_INC libs with $NDBM_LDFLAGS )
+ ;;
+ *)
+ NDBM_INC="-I$withval/include"
+ NDBM_LDFLAGS="-L$withval/lib"
+ AC_MSG_CHECKING(checking for ndbm includes in $withval)
+ ;;
+ esac
+ fi
+
+ save_cppflags="$CPPFLAGS"
+ save_ldflags="$LDFLAGS"
+ CPPFLAGS="$CPPFLAGS $NDBM_INC"
+ LDFLAGS="$LDFLAGS $NDBM_LDFLAGS"
+ dnl db_ndbm_open is what sleepcat's compatibility library actually has in it's lib
+ if test "$apu_want_ndbm" != "0"; then
+ AC_CHECK_HEADER(ndbm.h,
+ AC_CHECK_LIB(c, dbm_open, [apu_have_ndbm=1;apu_ndbm_lib=c],
+ AC_CHECK_LIB(dbm, dbm_open, [apu_have_ndbm=1;apu_ndbm_lib=dbm],
+ AC_CHECK_LIB(db, dbm_open, [apu_have_ndbm=1;apu_ndbm_lib=db],
+ AC_CHECK_LIB(db, __db_ndbm_open, [apu_have_ndbm=1;apu_ndbm_lib=db])
+ )
+ )
+ )
+ )
+ if test "$apu_have_ndbm" != "0"; then
+ if test "$withval" != "yes"; then
+ APR_ADDTO(APRUTIL_INCLUDES, [$NDBM_INC])
+ APR_ADDTO(APRUTIL_LDFLAGS, [$NDBM_LDFLAGS])
+ fi
+ elif test "$withval" != "yes"; then
+ AC_ERROR( NDBM not found in the specified directory)
+ fi
+ fi
+ CPPFLAGS="$save_cppflags"
+ LDFLAGS="$save_ldflags"
+ ], [
+ dnl don't check it no one has asked us for it
+ apu_have_ndbm=0
+ ])
+
+
+ if test -n "$apu_db_xtra_libs"; then
+ saveddbxtralibs="$LIBS"
+ LIBS="$apu_db_xtra_libs $LIBS"
+ fi
+
+ dnl We're going to try to find the highest version of Berkeley DB supported.
+ AC_ARG_WITH([berkeley-db], [
+ --with-berkeley-db=PATH
+ Find the Berkeley DB header and library in \`PATH/include' and
+ \`PATH/lib'. If PATH is of the form \`HEADER:LIB', then search
+ for header files in HEADER, and the library in LIB. If you omit
+ the \`=PATH' part completely, the configure script will search
+ for Berkeley DB in a number of standard places.
+ ], [
+ if test "$withval" = "yes"; then
+ apu_want_db=1
+ user_places=""
+ elif test "$withval" = "no"; then
+ apu_want_db=0
+ else
+ apu_want_db=1
+ user_places="$withval"
+ fi
+
+ if test "$apu_want_db" != "0"; then
+ APU_CHECK_DB($requested, $user_places)
+ if test "$apu_have_db" = "0"; then
+ AC_ERROR(Berkeley DB not found.)
+ fi
+ fi
+ ],[
+ APU_CHECK_DB($requested, "")
+ ])
+
+ if test -n "$apu_db_xtra_libs"; then
+ LIBS="$saveddbxtralibs"
+ fi
+
+ case "$requested" in
+ sdbm)
+ apu_use_sdbm=1
+ apu_default_dbm=sdbm
+ ;;
+ gdbm)
+ apu_use_gdbm=1
+ apu_default_dbm=gdbm
+ ;;
+ ndbm)
+ apu_use_ndbm=1
+ apu_default_dbm=ndbm
+ ;;
+ db)
+ apu_use_db=1
+ apu_default_dbm=db
+ ;;
+ db1)
+ apu_use_db=1
+ apu_default_dbm=db1
+ ;;
+ db185)
+ apu_use_db=1
+ apu_default_dbm=db185
+ ;;
+ db2)
+ apu_use_db=1
+ apu_default_dbm=db2
+ ;;
+ db3)
+ apu_use_db=1
+ apu_default_dbm=db3
+ ;;
+ db4)
+ apu_use_db=1
+ apu_default_dbm=db4
+ ;;
+ db41)
+ apu_use_db=1
+ apu_default_dbm=db4
+ ;;
+ db42)
+ apu_use_db=1
+ apu_default_dbm=db4
+ ;;
+ db43)
+ apu_use_db=1
+ apu_default_dbm=db4
+ ;;
+ default)
+ dnl ### use more sophisticated DBMs for the default?
+ apu_default_dbm="sdbm (default)"
+ apu_use_sdbm=1
+ ;;
+ *)
+ AC_MSG_ERROR([--with-dbm=$look_for is an unknown DBM type.
+ Use one of: sdbm, gdbm, ndbm, db, db1, db185, db2, db3, db4, db41, db42])
+ ;;
+ esac
+
+ dnl Yes, it'd be nice if we could collate the output in an order
+ dnl so that the AC_MSG_CHECKING would be output before the actual
+ dnl checks, but it isn't happening now.
+ AC_MSG_CHECKING(for default DBM)
+ AC_MSG_RESULT($apu_default_dbm)
+
+ AC_SUBST(apu_use_sdbm)
+ AC_SUBST(apu_use_gdbm)
+ AC_SUBST(apu_use_ndbm)
+ AC_SUBST(apu_use_db)
+
+ AC_SUBST(apu_have_sdbm)
+ AC_SUBST(apu_have_gdbm)
+ AC_SUBST(apu_have_ndbm)
+ AC_SUBST(apu_have_db)
+ AC_SUBST(apu_db_header)
+ AC_SUBST(apu_db_version)
+
+ dnl Since we have already done the AC_CHECK_LIB tests, if we have it,
+ dnl we know the library is there.
+ if test "$apu_have_gdbm" = "1"; then
+ APR_ADDTO(APRUTIL_EXPORT_LIBS,[-lgdbm])
+ APR_ADDTO(APRUTIL_LIBS,[-lgdbm])
+ fi
+
+ if test "$apu_have_ndbm" = "1"; then
+ APR_ADDTO(APRUTIL_EXPORT_LIBS,[-l$apu_ndbm_lib])
+ APR_ADDTO(APRUTIL_LIBS,[-l$apu_ndbm_lib])
+ fi
+
+ if test "$apu_have_db" = "1"; then
+ APR_ADDTO(APRUTIL_EXPORT_LIBS,[-l$apu_db_lib])
+ APR_ADDTO(APRUTIL_LIBS,[-l$apu_db_lib])
+ if test -n "apu_db_xtra_libs"; then
+ APR_ADDTO(APRUTIL_EXPORT_LIBS,[$apu_db_xtra_libs])
+ APR_ADDTO(APRUTIL_LIBS,[$apu_db_xtra_libs])
+ fi
+ fi
+])
+
--- /dev/null
+dnl -------------------------------------------------------- -*- autoconf -*-
+dnl Copyright 2002-2005 The Apache Software Foundation or its licensors, as
+dnl applicable.
+dnl
+dnl Licensed under the Apache License, Version 2.0 (the "License");
+dnl you may not use this file except in compliance with the License.
+dnl You may obtain a copy of the License at
+dnl
+dnl http://www.apache.org/licenses/LICENSE-2.0
+dnl
+dnl Unless required by applicable law or agreed to in writing, software
+dnl distributed under the License is distributed on an "AS IS" BASIS,
+dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+dnl See the License for the specific language governing permissions and
+dnl limitations under the License.
+
+dnl
+dnl find_apu.m4 : locate the APR-util (APU) include files and libraries
+dnl
+dnl This macro file can be used by applications to find and use the APU
+dnl library. It provides a standardized mechanism for using APU. It supports
+dnl embedding APU into the application source, or locating an installed
+dnl copy of APU.
+dnl
+dnl APR_FIND_APU(srcdir, builddir, implicit-install-check, acceptable-majors)
+dnl
+dnl where srcdir is the location of the bundled APU source directory, or
+dnl empty if source is not bundled.
+dnl
+dnl where builddir is the location where the bundled APU will be built,
+dnl or empty if the build will occur in the srcdir.
+dnl
+dnl where implicit-install-check set to 1 indicates if there is no
+dnl --with-apr-util option specified, we will look for installed copies.
+dnl
+dnl where acceptable-majors is a space separated list of acceptable major
+dnl version numbers. Often only a single major version will be acceptable.
+dnl If multiple versions are specified, and --with-apr-util=PREFIX or the
+dnl implicit installed search are used, then the first (leftmost) version
+dnl in the list that is found will be used. Currently defaults to [0 1].
+dnl
+dnl Sets the following variables on exit:
+dnl
+dnl apu_found : "yes", "no", "reconfig"
+dnl
+dnl apu_config : If the apu-config tool exists, this refers to it. If
+dnl apu_found is "reconfig", then the bundled directory
+dnl should be reconfigured *before* using apu_config.
+dnl
+dnl Note: this macro file assumes that apr-config has been installed; it
+dnl is normally considered a required part of an APR installation.
+dnl
+dnl Note: At this time, we cannot find *both* a source dir and a build dir.
+dnl If both are available, the build directory should be passed to
+dnl the --with-apr-util switch.
+dnl
+dnl Note: the installation layout is presumed to follow the standard
+dnl PREFIX/lib and PREFIX/include pattern. If the APU config file
+dnl is available (and can be found), then non-standard layouts are
+dnl possible, since it will be described in the config file.
+dnl
+dnl If a bundled source directory is available and needs to be (re)configured,
+dnl then apu_found is set to "reconfig". The caller should reconfigure the
+dnl (passed-in) source directory, placing the result in the build directory,
+dnl as appropriate.
+dnl
+dnl If apu_found is "yes" or "reconfig", then the caller should use the
+dnl value of apu_config to fetch any necessary build/link information.
+dnl
+
+AC_DEFUN([APR_FIND_APU], [
+ apu_found="no"
+
+ if test "$target_os" = "os2-emx"; then
+ # Scripts don't pass test -x on OS/2
+ TEST_X="test -f"
+ else
+ TEST_X="test -x"
+ fi
+
+ ifelse([$4], [],
+ [
+ ifdef(AC_WARNING,([$0: missing argument 4 (acceptable-majors): Defaulting to APU 0.x then APU 1.x]))
+ acceptable_majors="0 1"
+ ], [acceptable_majors="$4"])
+
+ apu_temp_acceptable_apu_config=""
+ for apu_temp_major in $acceptable_majors
+ do
+ case $apu_temp_major in
+ 0)
+ apu_temp_acceptable_apu_config="$apu_temp_acceptable_apu_config apu-config"
+ ;;
+ *)
+ apu_temp_acceptable_apu_config="$apu_temp_acceptable_apu_config apu-$apu_temp_major-config"
+ ;;
+ esac
+ done
+
+ AC_MSG_CHECKING(for APR-util)
+ AC_ARG_WITH(apr-util,
+ [ --with-apr-util=PATH prefix for installed APU, path to APU build tree,
+ or the full path to apu-config],
+ [
+ if test "$withval" = "no" || test "$withval" = "yes"; then
+ AC_MSG_ERROR([--with-apr-util requires a directory or file to be provided])
+ fi
+
+ for apu_temp_apu_config_file in $apu_temp_acceptable_apu_config
+ do
+ for lookdir in "$withval/bin" "$withval"
+ do
+ if $TEST_X "$lookdir/$apu_temp_apu_config_file"; then
+ apu_found="yes"
+ apu_config="$lookdir/$apu_temp_apu_config_file"
+ break 2
+ fi
+ done
+ done
+
+ if test "$apu_found" != "yes" && $TEST_X "$withval" && $withval --help > /dev/null 2>&1 ; then
+ apu_found="yes"
+ apu_config="$withval"
+ fi
+
+ dnl if --with-apr-util is used, it is a fatal error for its argument
+ dnl to be invalid
+ if test "$apu_found" != "yes"; then
+ AC_MSG_ERROR([the --with-apr-util parameter is incorrect. It must specify an install prefix, a build directory, or an apu-config file.])
+ fi
+ ],[
+ if test -n "$3" && test "$3" = "1"; then
+ for apu_temp_apu_config_file in $apu_temp_acceptable_apu_config
+ do
+ if $apu_temp_apu_config_file --help > /dev/null 2>&1 ; then
+ apu_found="yes"
+ apu_config="$apu_temp_apu_config_file"
+ break
+ else
+ dnl look in some standard places (apparently not in builtin/default)
+ for lookdir in /usr /usr/local /usr/local/apr /opt/apr /usr/local/apache2 ; do
+ if $TEST_X "$lookdir/bin/$apu_temp_apu_config_file"; then
+ apu_found="yes"
+ apu_config="$lookdir/bin/$apu_temp_apu_config_file"
+ break 2
+ fi
+ done
+ fi
+ done
+ fi
+ dnl if we have not found anything yet and have bundled source, use that
+ if test "$apu_found" = "no" && test -d "$1"; then
+ apu_temp_abs_srcdir="`cd $1 && pwd`"
+ apu_found="reconfig"
+ apu_bundled_major="`sed -n '/#define.*APU_MAJOR_VERSION/s/^[^0-9]*\([0-9]*\).*$/\1/p' \"$1/include/apu_version.h\"`"
+ case $apu_bundled_major in
+ "")
+ AC_MSG_ERROR([failed to find major version of bundled APU])
+ ;;
+ 0)
+ apu_temp_apu_config_file="apu-config"
+ ;;
+ *)
+ apu_temp_apu_config_file="apu-$apu_bundled_major-config"
+ ;;
+ esac
+ if test -n "$2"; then
+ apu_config="$2/$apu_temp_apu_config_file"
+ else
+ apu_config="$1/$apu_temp_apu_config_file"
+ fi
+ fi
+ ])
+
+ AC_MSG_RESULT($apu_found)
+])
--- /dev/null
+#!/bin/sh
+#
+# extract version numbers from a header file
+#
+# USAGE: get-version.sh CMD VERSION_HEADER PREFIX
+# where CMD is one of: all, major, libtool
+# where PREFIX is the prefix to {MAJOR|MINOR|PATCH}_VERSION defines
+#
+# get-version.sh all returns a dotted version number
+# get-version.sh major returns just the major version number
+# get-version.sh libtool returns a version "libtool -version-info" format
+#
+
+if test $# != 3; then
+ echo "USAGE: $0 CMD INCLUDEDIR PREFIX"
+ echo " where CMD is one of: all, major"
+ exit 1
+fi
+
+major_sed="/#define.*$3_MAJOR_VERSION/s/^.*\([0-9][0-9]*\).*$/\1/p"
+minor_sed="/#define.*$3_MINOR_VERSION/s/^.*\([0-9][0-9]*\).*$/\1/p"
+patch_sed="/#define.*$3_PATCH_VERSION/s/^.*\([0-9][0-9]*\).*$/\1/p"
+major="`sed -n $major_sed $2`"
+minor="`sed -n $minor_sed $2`"
+patch="`sed -n $patch_sed $2`"
+
+if test "$1" = "all"; then
+ echo ${major}.${minor}.${patch}
+elif test "$1" = "major"; then
+ echo ${major}
+elif test "$1" = "libtool"; then
+ # Yes, ${minor}:${patch}:${minor} is correct due to libtool idiocy.
+ echo ${minor}:${patch}:${minor}
+else
+ echo "ERROR: unknown version CMD ($1)"
+ exit 1
+fi
--- /dev/null
+#!/bin/sh
+##
+## mkdir.sh -- make directory hierarchy
+##
+## Based on `mkinstalldirs' from Noah Friedman <friedman@prep.ai.mit.edu>
+## as of 1994-03-25, which was placed in the Public Domain.
+## Cleaned up for Apache's Autoconf-style Interface (APACI)
+## by Ralf S. Engelschall <rse@apache.org>
+##
+#
+# This script falls under the Apache License.
+# See http://www.apache.org/docs/LICENSE
+
+
+umask 022
+errstatus=0
+for file in ${1+"$@"} ; do
+ set fnord `echo ":$file" |\
+ sed -e 's/^:\//%/' -e 's/^://' -e 's/\// /g' -e 's/^%/\//'`
+ shift
+ pathcomp=
+ for d in ${1+"$@"}; do
+ pathcomp="$pathcomp$d"
+ case "$pathcomp" in
+ -* ) pathcomp=./$pathcomp ;;
+ ?: ) pathcomp="$pathcomp/"
+ continue ;;
+ esac
+ if test ! -d "$pathcomp"; then
+ echo "mkdir $pathcomp" 1>&2
+ mkdir "$pathcomp" || errstatus=$?
+ fi
+ pathcomp="$pathcomp/"
+ done
+done
+exit $errstatus
+
--- /dev/null
+The script in this directory will attempt to build a Solaris package
+out of a source tree for APR-util.
+
+To build a package, make sure you are in the root of the source tree,
+and run:
+
+build/pkg/buildpkg.sh
+
+A Solaris package called apr-util-<version>-<architecture>-local.gz will be
+created in the root of the source tree.
+
+By default, if you attempt to build packages for apr-util, it will
+search for the sources for apr in:
+
+../apr
+
+You may override the location of apr like so:
+
+build/pkg/buildpkg.sh --with-apr=some/other/path
+
--- /dev/null
+#!/bin/sh
+# Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+# applicable.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+
+# buildpkg.sh: This script builds a Solaris PKG from the source tree
+# provided.
+
+PREFIX=/usr/local
+TEMPDIR=/var/tmp/$USER/apr-util-root
+rm -rf $TEMPDIR
+
+apr_util_src_dir=.
+apr_src_dir=../apr
+expat_dir=/usr
+
+while test $# -gt 0
+do
+ # Normalize
+ case "$1" in
+ -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) optarg= ;;
+ esac
+
+ case "$1" in
+ --with-apr=*)
+ apr_src_dir=$optarg
+ ;;
+ esac
+
+ case "$1" in
+ --with-apr-util=*)
+ apr_util_src_dir=$optarg
+ ;;
+ esac
+
+ case "$1" in
+ --with-expat=*)
+ expat_dir=$optarg
+ ;;
+ esac
+
+ shift
+done
+
+if [ -f "$apr_util_src_dir/configure.in" ]; then
+ cd $apr_util_src_dir
+else
+ echo "The apr-util source could not be found within $apr_util_src_dir"
+ echo "Usage: buildpkg [--with-apr=dir] [--with-apr-util=dir] [--with-expat=dir]"
+ exit 1
+fi
+
+if [ ! -f "$apr_src_dir/configure.in" ]; then
+ echo "The apr source could not be found within $apr_src_dir"
+ echo "Usage: buildpkg [--with-apr=dir] [--with-apr-util=dir] [--with-expat=dir]"
+ exit 1
+fi
+
+if [ ! -d "$expat_dir" ]; then
+ echo "The expat directory could not be found within $expat_dir"
+ echo "Usage: buildpkg [--with-apr=dir] [--with-apr-util=dir] [--with-expat=dir]"
+ exit 1
+fi
+
+./configure --prefix=$PREFIX --with-apr=$apr_src_dir \
+ --with-ldap --with-expat=$expat_dir
+make
+make install DESTDIR=$TEMPDIR
+rm $TEMPDIR$PREFIX/lib/aprutil.exp
+. build/pkg/pkginfo
+cp build/pkg/pkginfo $TEMPDIR$PREFIX
+
+current=`pwd`
+cd $TEMPDIR$PREFIX
+echo "i pkginfo=./pkginfo" > prototype
+find . -print | grep -v ./prototype | grep -v ./pkginfo | pkgproto | awk '{print $1" "$2" "$3" "$4" root bin"}' >> prototype
+mkdir $TEMPDIR/pkg
+pkgmk -r $TEMPDIR$PREFIX -d $TEMPDIR/pkg
+
+cd $current
+pkgtrans -s $TEMPDIR/pkg $current/$NAME-$VERSION-$ARCH-local
+gzip $current/$NAME-$VERSION-$ARCH-local
+
+rm -rf $TEMPDIR
+
--- /dev/null
+PKG="ASFapu-1"
+NAME="apr-util"
+ARCH="@target_cpu@"
+VERSION="@APRUTIL_DOTTED_VERSION@"
+CATEGORY="application"
+VENDOR="Apache Software Foundation"
+EMAIL="dev@apr.apache.org"
+PSTAMP="dev@apr.apache.org"
+BASEDIR="@prefix@"
+CLASSES="none"
+
--- /dev/null
+
+%define apuver 1
+
+Summary: Apache Portable Runtime Utility library
+Name: apr-util
+Version: APU_VERSION
+Release: APU_RELEASE
+License: Apache Software License
+Group: System Environment/Libraries
+URL: http://apr.apache.org/
+Source0: %{name}-%{version}.tar.gz
+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot
+BuildPrereq: autoconf, libtool, doxygen, apr-devel >= 0:{version}-{release}
+BuildPrereq: openldap-devel, db4-devel, expat-devel
+Conflicts: subversion < 0.20.1-2
+
+%description
+The mission of the Apache Portable Runtime (APR) is to provide a
+free library of C data structures and routines. This library
+contains additional utility interfaces for APR; including support
+for XML, LDAP, database interfaces, URI parsing and more.
+
+%package devel
+Group: Development/Libraries
+Summary: APR utility library development kit
+Requires: apr-util = %{version}-%{release}, apr-devel
+Requires: openldap-devel, db4-devel, expat-devel
+Conflicts: subversion-devel < 0.20.1-2
+
+%description devel
+This package provides the support files which can be used to
+build applications using the APR utility library. The mission
+of the Apache Portable Runtime (APR) is to provide a free
+library of C data structures and routines.
+
+%prep
+%setup -q
+
+%build
+%configure --with-apr=%{_prefix} \
+ --includedir=%{_includedir}/apr-%{apuver} \
+ --with-ldap --without-gdbm
+make %{?_smp_mflags} && make dox
+
+%check
+# Run non-interactive tests
+pushd test
+make %{?_smp_mflags} testall CFLAGS=-fno-strict-aliasing
+./testall -v || exit 1
+popd
+
+%install
+rm -rf $RPM_BUILD_ROOT
+make install DESTDIR=$RPM_BUILD_ROOT
+
+# Documentation
+mv docs/dox/html html
+
+# Unpackaged files
+rm -f $RPM_BUILD_ROOT%{_libdir}/aprutil.exp
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%post -p /sbin/ldconfig
+
+%postun -p /sbin/ldconfig
+
+%files
+%defattr(-,root,root,-)
+%doc CHANGES LICENSE NOTICE
+%{_libdir}/libaprutil-%{apuver}.so.*
+
+%files devel
+%defattr(-,root,root,-)
+%{_bindir}/apu-%{apuver}-config
+%{_libdir}/libaprutil-%{apuver}.*a
+%{_libdir}/libaprutil-%{apuver}.so
+%{_libdir}/pkgconfig/apr-util-%{apuver}.pc
+%{_includedir}/apr-%{apuver}/*.h
+%doc --parents html
+
+%changelog
+* Tue Jun 22 2004 Graham Leggett <minfrin@sharp.fm> 1.0.0-1
+- update to support v1.0.0 of APR
+
+* Tue Jun 22 2004 Graham Leggett <minfrin@sharp.fm> 1.0.0-1
+- derived from Fedora Core apr.spec
+
--- /dev/null
+#! perl -w
+#
+# w32locatedb.pl -- Build apr-util with Berkeley DB on Win32
+#
+# Usage: perl w32locatedb.pl <type> <incdir> <libdir>
+# type: Library type to link with ('lib' or 'dll')
+# incdir: BDB includes directory (for db.h)
+# libdir: Library directory (for libdbXY[s][d].lib)
+#
+# This script falls under the Apache License.
+# See http://www.apache.org/docs/LICENSE
+
+require 5.008;
+use strict;
+use File::Spec::Functions qw(canonpath rel2abs
+ splitpath catpath splitdir catdir);
+
+########
+# Subroutine prototypes
+sub usage();
+sub find_srcdir();
+sub get_lib_name($$);
+sub edit_header($$);
+sub edit_project($$);
+
+########
+# Parse program arguments and set globals
+die usage() unless scalar @ARGV >= 3;
+
+my $type = lc($ARGV[0]);
+die "Invalid library type '$type'\n"
+ unless $type eq 'lib' or $type eq 'dll';
+
+my $incdir = $ARGV[1];
+die "No 'db.h' in $incdir\n" unless -f "$incdir/db.h";
+
+my $libdir = $ARGV[2];
+die "$libdir: $!" unless -d $libdir;
+
+my $libname = get_lib_name($type, $incdir);
+die "No '$libname.lib' in $libdir" unless -f "$libdir/$libname.lib";
+die "No '${libname}d.lib' in $libdir" unless -f "$libdir/${libname}d.lib";
+
+my $srcdir = find_srcdir();
+my $apu_hw = canonpath("$srcdir/include/apu.hw");
+my $apu_want_hw = canonpath("$srcdir/include/apu_want.hw");
+my $apu_select_dbm_hw = canonpath("$srcdir/include/private/apu_select_dbm.hw");
+my $aprutil_dsp = canonpath("$srcdir/aprutil.dsp");
+my $libaprutil_dsp = canonpath("$srcdir/libaprutil.dsp");
+die "Can't find $apu_hw" unless -f $apu_hw;
+die "Can't find $apu_want_hw" unless -f $apu_want_hw;
+die "Can't find $apu_select_dbm_hw" unless -f $apu_select_dbm_hw;
+die "Can't find $aprutil_dsp" unless -f $aprutil_dsp;
+die "Can't find $libaprutil_dsp" unless -f $libaprutil_dsp;
+
+
+########
+# Edit the header file templates
+my $db_h = rel2abs(canonpath("$incdir/db.h"));
+$db_h =~ s/\\/\//g;
+edit_header($apu_hw,
+ [['^\s*\#\s*define\s+APU_HAVE_DB\s+0\s*$',
+ '#define APU_HAVE_DB 1']]);
+edit_header($apu_want_hw,
+ [['^\s*\#\s*include\s+\<db\.h\>\s*$',
+ "#include \"$db_h\""]]);
+edit_header($apu_select_dbm_hw,
+ [['^\s*\#\s*define\s+APU_USE_DB\s+0\s*$',
+ '#define APU_USE_DB 1'],
+ ['^\s*\#\s*include\s+\<db\.h\>\s*$',
+ "#include \"$db_h\""]]);
+
+########
+# Edit the .dsp files
+my $libpath = rel2abs(canonpath("$libdir/$libname"));
+edit_project($aprutil_dsp, $libpath);
+edit_project($libaprutil_dsp, $libpath);
+
+
+########
+# Print usage
+sub usage()
+{
+ return ("Usage: perl w32locatedb.pl <type> <incdir> <libdir>\n"
+ . " type: Library type to link with ('lib' or 'dll')\n"
+ . " incdir: BDB includes directory (for db.h)\n"
+ . " libdir: Library directory (for libdbXY[s][d].lib)\n");
+}
+
+########
+# Calculate the (possibly relative) path to the top of the apr-util
+# source dir.
+sub find_srcdir()
+{
+ my $srcdir = rel2abs(canonpath($0));
+ my ($vol, $dir, $file) = splitpath($srcdir);
+ my @dirs = splitdir($dir);
+ die if scalar @dirs < 1;
+ do { $_ = pop @dirs } while ($_ eq '');
+ return catpath($vol, catdir(@dirs), '');
+}
+
+########
+# Construct the name of the BDB library, based on the type and
+# version information in db.h
+sub get_lib_name($$)
+{
+ my ($type, $incdir) = @_;
+ my $major = undef;
+ my $minor = undef;
+ my $patch = undef;
+
+ open(DBH, "< $incdir/db.h")
+ or die "Can't open $incdir/db.h: $!";
+ while (<DBH>) {
+ chomp;
+ m/^\s*\#\s*define\s+DB_VERSION_(MAJOR|MINOR|PATCH)\s+(\d+)\s*$/;
+ next unless defined $1 and defined $2;
+ if ($1 eq 'MAJOR') { $major = $2; }
+ elsif ($1 eq 'MINOR') { $minor = $2; }
+ elsif ($1 eq 'PATCH') { $patch = $2; }
+ last if defined $major and defined $minor and defined $patch;
+ }
+ close(DBH);
+ die "Can't determine BDB version\n"
+ unless defined $major and defined $minor and defined $patch;
+
+ print "Using BDB version $major.$minor.$patch\n";
+
+ my $libname = "libdb$major$minor";
+ $libname .= 's' if $type eq 'lib';
+ return $libname;
+}
+
+########
+# Replace a file, keeping a backup copy
+sub maybe_rename_with_backup($$$)
+{
+ my ($tmpfile, $file, $maybe) = @_;
+ if ($maybe) {
+ # Make the file writable by the owner. On Windows, this removes
+ # any read-only bits.
+ chmod((stat($file))[2] | 0600, $file);
+ rename($file, "${file}~");
+ rename($tmpfile, $file);
+ } else {
+ print "No changes in $file\n";
+ unlink($tmpfile);
+ }
+}
+
+########
+# Edit a header template in-place.
+sub edit_header($$)
+{
+ my ($file, $pairs) = @_;
+ my $tmpfile = "$file.tmp";
+ my $substs = 0;
+
+ open(IN, "< $file") or die "Can't open $file: $!";
+ open(TMP, "> $tmpfile") or die "Can't open $tmpfile: $!";
+ while (<IN>) {
+ chomp;
+ foreach my $pair (@$pairs) {
+ $substs += s/${$pair}[0]/${$pair}[1]/;
+ }
+ print TMP $_, "\n";
+ }
+ close(IN);
+ close(TMP);
+
+ maybe_rename_with_backup($tmpfile, $file, $substs > 0);
+}
+
+########
+# Edit a project file in-place
+sub edit_project($$)
+{
+ my ($file, $libpath) = @_;
+ my $tmpfile = "$file.tmp";
+ my $substs = 0;
+ my ($prog, $debug) = (undef, undef);
+
+ my $libsearch = $libpath;
+ $libsearch =~ s/\\/\\\\/g;
+
+ open(IN, "< $file") or die "Can't open $file: $!";
+ open(TMP, "> $tmpfile") or die "Can't open $tmpfile: $!";
+ while (<IN>) {
+ chomp;
+
+ if (m/^\# TARGTYPE \"[^\"]+\" 0x([0-9A-Za-z]+)/
+ and defined $1) {
+ $prog = 'LINK32' if $1 eq '0102';
+ $prog = 'LIB32' if $1 eq '0104';
+ die "Unknown project type 0x$1" unless defined $prog;
+ } elsif (defined $prog
+ and m/^\# PROP Use_Debug_Libraries ([01])/
+ and defined $1) {
+ $debug = $1;
+ } elsif (defined $prog and defined $debug
+ and m/^\# ADD $prog (\"$libsearch)?/
+ and not defined $1) {
+ my $fullpath =
+ ($debug eq '1' ? "${libpath}d.lib" : "$libpath.lib");
+ $substs += s/^\# ADD $prog /\# ADD $prog \"$fullpath\" /;
+ } elsif (m/^\# ADD CPP/) {
+ $substs += s/APU_USE_SDBM/APU_USE_DB/g;
+ }
+
+ print TMP $_, "\n";
+ }
+ close(IN);
+ close(TMP);
+
+ maybe_rename_with_backup($tmpfile, $file, $substs > 0);
+}
--- /dev/null
+#!/bin/sh
+#
+# Copyright 1999-2004 The Apache Software Foundation
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+
+# Default place to look for apr source. Can be overridden with
+# --with-apr=[directory]
+apr_src_dir=../apr
+
+while test $# -gt 0
+do
+ # Normalize
+ case "$1" in
+ -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;;
+ *) optarg= ;;
+ esac
+
+ case "$1" in
+ --with-apr=*)
+ apr_src_dir=$optarg
+ ;;
+ esac
+
+ shift
+done
+
+if test -d "$apr_src_dir"
+then
+ echo ""
+ echo "Looking for apr source in $apr_src_dir"
+else
+ echo ""
+ echo "Problem finding apr source in $apr_src_dir."
+ echo "Use:"
+ echo " --with-apr=[directory]"
+ exit 1
+fi
+
+set -e
+
+# Remove some files, then copy them from apr source tree
+rm -f build/apr_common.m4 build/find_apr.m4 build/install.sh \
+ build/config.guess build/config.sub
+cp $apr_src_dir/build/apr_common.m4 $apr_src_dir/build/find_apr.m4 \
+ $apr_src_dir/build/install.sh $apr_src_dir/build/config.guess \
+ $apr_src_dir/build/config.sub build
+
+# Remove aclocal.m4 as it'll break some builds...
+rm -rf aclocal.m4 autom4te*.cache
+
+#
+# Generate the autoconf header (include/apu_config.h) and ./configure
+#
+echo "Creating include/private/apu_config.h ..."
+${AUTOHEADER:-autoheader}
+
+echo "Creating configure ..."
+### do some work to toss config.cache?
+if ${AUTOCONF:-autoconf}; then
+ :
+else
+ echo "autoconf failed"
+ exit 1
+fi
+
+#
+# Generate build-outputs.mk for the build systme
+#
+echo "Generating 'make' outputs ..."
+$apr_src_dir/build/gen-build.py make
+
+#
+# If apr-iconv, then go and configure it.
+#
+if test -d ../apr-iconv; then
+ echo "Invoking ../apr-iconv/buildconf.sh ..."
+ (cd ../apr-iconv; ./buildconf)
+fi
+
+#
+# If Expat has been bundled, then go and configure the thing
+#
+if test -d xml/expat; then
+ echo "Invoking xml/expat/buildconf.sh ..."
+ (cd xml/expat; ./buildconf.sh)
+fi
+
+# Remove autoconf cache again
+rm -rf autom4te*.cache
+
+# Create RPM Spec file
+if [ -f `which cut` ]; then
+ echo rebuilding rpm spec file
+ REVISION=`build/get-version.sh all include/apu_version.h APU`
+ VERSION=`echo $REVISION | cut -d- -s -f1`
+ RELEASE=`echo $REVISION | cut -d- -s -f2`
+ if [ "x$VERSION" = "x" ]; then
+ VERSION=$REVISION
+ RELEASE=1
+ fi
+ sed -e "s/APU_VERSION/$VERSION/" -e "s/APU_RELEASE/$RELEASE/" \
+ ./build/rpm/apr-util.spec.in > apr-util.spec
+fi
+
--- /dev/null
+##
+## config.layout -- Pre-defined Installation Path Layouts
+##
+## Hints:
+## - layouts can be loaded with configure's --enable-layout=ID option
+## - when no --enable-layout option is given, the default layout is `apr'
+## - a trailing plus character (`+') on paths is replaced with a
+## `/<target>' suffix where <target> is currently hardcoded to 'apr'.
+## (This may become a configurable parameter at some point.)
+##
+
+# Classical APR-util path layout designed for parallel installs.
+<Layout apr-util>
+ prefix: /usr/local/apr
+ exec_prefix: ${prefix}
+ bindir: ${exec_prefix}/bin
+ sbindir: ${exec_prefix}/bin
+ libdir: ${exec_prefix}/lib
+ libexecdir: ${exec_prefix}/modules
+ mandir: ${prefix}/man
+ sysconfdir: ${prefix}/conf
+ datadir: ${prefix}
+ installbuilddir: ${datadir}/build
+ includedir: ${prefix}/include/apr-${APRUTIL_MAJOR_VERSION}
+ localstatedir: ${prefix}
+ libsuffix: -${APRUTIL_MAJOR_VERSION}
+</Layout>
+
+# Classical single-installation APR path layout.
+<Layout classic>
+ prefix: /usr/local/apr
+ exec_prefix: ${prefix}
+ bindir: ${exec_prefix}/bin
+ sbindir: ${exec_prefix}/bin
+ libdir: ${exec_prefix}/lib
+ libexecdir: ${exec_prefix}/modules
+ mandir: ${prefix}/man
+ sysconfdir: ${prefix}/conf
+ datadir: ${prefix}
+ installbuilddir: ${datadir}/build
+ includedir: ${prefix}/include
+ localstatedir: ${prefix}
+</Layout>
+
+# GNU standards conforming path layout.
+# See FSF's GNU project `make-stds' document for details.
+<Layout GNU>
+ prefix: /usr/local
+ exec_prefix: ${prefix}
+ bindir: ${exec_prefix}/bin
+ sbindir: ${exec_prefix}/sbin
+ libdir: ${exec_prefix}/lib
+ libexecdir: ${exec_prefix}/libexec
+ mandir: ${prefix}/man
+ sysconfdir: ${prefix}/etc+
+ datadir: ${prefix}/share+
+ installbuilddir: ${datadir}/build
+ includedir: ${prefix}/include+
+ localstatedir: ${prefix}/var+
+ runtimedir: ${localstatedir}/run
+</Layout>
+
+# Mac OS X Server (Rhapsody)
+<Layout Mac OS X Server>
+ prefix: /Local/Library/WebServer
+ exec_prefix: /usr
+ bindir: ${exec_prefix}/bin
+ sbindir: ${exec_prefix}/sbin
+ libdir: ${exec_prefix}/lib
+ libexecdir: /System/Library/apr/Modules
+ mandir: ${exec_prefix}/share/man
+ sysconfdir: ${prefix}/Configuration
+ datadir: ${prefix}
+ installbuilddir: /System/Library/apr/Build
+ includedir: /System/Library/Frameworks/apr.framework/Versions/2.0/Headers
+ localstatedir: /var
+ runtimedir: ${prefix}/Logs
+</Layout>
+
+# Darwin/Mac OS Layout
+<Layout Darwin>
+ prefix: /usr
+ exec_prefix: ${prefix}
+ bindir: ${exec_prefix}/bin
+ sbindir: ${exec_prefix}/sbin
+ libdir: ${exec_prefix}/lib
+ libexecdir: ${exec_prefix}/libexec+
+ mandir: ${prefix}/share/man
+ datadir: /Library/WebServer
+ sysconfdir: /etc+
+ installbuilddir: ${prefix}/share/httpd/build
+ includedir: ${prefix}/include+
+ localstatedir: /var
+ runtimedir: ${localstatedir}/run
+</Layout>
+
+# Red Hat Linux 7.x layout
+<Layout RedHat>
+ prefix: /usr
+ exec_prefix: ${prefix}
+ bindir: ${prefix}/bin
+ sbindir: ${prefix}/sbin
+ libdir: ${prefix}/lib
+ libexecdir: ${prefix}/lib/apr
+ mandir: ${prefix}/man
+ sysconfdir: /etc/httpd/conf
+ datadir: /var/www
+ installbuilddir: ${datadir}/build
+ includedir: ${prefix}/include/apr
+ localstatedir: /var
+ runtimedir: ${localstatedir}/run
+</Layout>
+
+# According to the /opt filesystem conventions
+<Layout opt>
+ prefix: /opt/apr
+ exec_prefix: ${prefix}
+ bindir: ${exec_prefix}/bin
+ sbindir: ${exec_prefix}/sbin
+ libdir: ${exec_prefix}/lib
+ libexecdir: ${exec_prefix}/libexec
+ mandir: ${prefix}/man
+ sysconfdir: /etc${prefix}
+ datadir: ${prefix}/share
+ installbuilddir: ${datadir}/build
+ includedir: ${prefix}/include
+ localstatedir: /var${prefix}
+ runtimedir: ${localstatedir}/run
+</Layout>
+
+# BeOS layout...
+<Layout beos>
+ prefix: /boot/home/apr
+ exec_prefix: ${prefix}
+ bindir: ${exec_prefix}/bin
+ sbindir: ${exec_prefix}/bin
+ libdir: ${exec_prefix}/lib
+ libexecdir: ${exec_prefix}/libexec
+ mandir: ${prefix}/man
+ sysconfdir: ${prefix}/conf
+ datadir: ${prefix}
+ installbuilddir: ${datadir}/build
+ includedir: ${prefix}/include
+ localstatedir: ${prefix}
+ runtimedir: ${localstatedir}/logs
+</Layout>
+
+# SuSE 6.x layout
+<Layout SuSE>
+ prefix: /usr
+ exec_prefix: ${prefix}
+ bindir: ${prefix}/bin
+ sbindir: ${prefix}/sbin
+ libdir: ${prefix}/lib
+ libexecdir: ${prefix}/lib/apr
+ mandir: ${prefix}/share/man
+ sysconfdir: /etc/httpd
+ datadir: /usr/local/httpd
+ installbuilddir: ${datadir}/build
+ includedir: ${prefix}/include/apr
+ localstatedir: /var/lib/httpd
+ runtimedir: /var/run
+</Layout>
+
+# BSD/OS layout
+<Layout BSDI>
+ prefix: /var/www
+ exec_prefix: /usr/contrib
+ bindir: ${exec_prefix}/bin
+ sbindir: ${exec_prefix}/bin
+ libdir: ${exec_prefix}/lib
+ libexecdir: ${exec_prefix}/libexec/apr
+ mandir: ${exec_prefix}/man
+ sysconfdir: ${prefix}/conf
+ datadir: ${prefix}
+ installbuilddir: ${datadir}/build
+ includedir: ${exec_prefix}/include/apr
+ localstatedir: /var
+ runtimedir: ${localstatedir}/run
+</Layout>
+
+# Solaris 8 Layout
+<Layout Solaris>
+ prefix: /usr/apr
+ exec_prefix: ${prefix}
+ bindir: ${exec_prefix}/bin
+ sbindir: ${exec_prefix}/bin
+ libdir: ${exec_prefix}/lib
+ libexecdir: ${exec_prefix}/libexec
+ mandir: ${exec_prefix}/man
+ sysconfdir: /etc/apr
+ datadir: /var/apr
+ installbuilddir: ${datadir}/build
+ includedir: ${exec_prefix}/include
+ localstatedir: ${prefix}
+ runtimedir: /var/run
+</Layout>
+
+# OpenBSD Layout
+<Layout OpenBSD>
+ prefix: /var/www
+ exec_prefix: /usr
+ bindir: ${exec_prefix}/bin
+ sbindir: ${exec_prefix}/sbin
+ libdir: ${exec_prefix}/lib
+ libexecdir: ${exec_prefix}/lib/apr/modules
+ mandir: ${exec_prefix}/share/man
+ sysconfdir: ${prefix}/conf
+ datadir: ${prefix}
+ installbuilddir: ${prefix}/build
+ includedir: ${exec_prefix}/lib/apr/include
+ localstatedir: ${prefix}
+ runtimedir: ${prefix}/logs
+</Layout>
+
+# Debian layout
+<Layout Debian>
+ prefix:
+ exec_prefix: ${prefix}/usr
+ bindir: ${exec_prefix}/bin
+ sbindir: ${exec_prefix}/sbin
+ libdir: ${exec_prefix}/lib
+ libexecdir: ${exec_prefix}/lib/apr/modules
+ mandir: ${exec_prefix}/share/man
+ datadir: ${exec_prefix}/share/apr
+ includedir: ${exec_prefix}/include/apr-${APRUTIL_MAJOR_VERSION}
+ localstatedir: ${prefix}/var/run
+ runtimedir: ${prefix}/var/run
+ infodir: ${exec_prefix}/share/info
+ libsuffix: -${APRUTIL_MAJOR_VERSION}
+ installbuilddir: ${prefix}/usr/share/apache2/build
+</Layout>
--- /dev/null
+dnl
+dnl Process this file with autoconf to produce a configure script
+dnl
+
+AC_PREREQ(2.50)
+AC_INIT(export_vars.sh.in)
+
+AC_CONFIG_HEADER(include/private/apu_config.h)
+AC_CONFIG_AUX_DIR(build)
+
+sinclude(build/apu-conf.m4)
+sinclude(build/apu-iconv.m4)
+sinclude(build/apu-hints.m4)
+sinclude(build/apr_common.m4)
+sinclude(build/find_apr.m4)
+sinclude(build/dbm.m4)
+sinclude(build/dbd.m4)
+
+dnl Generate ./config.nice for reproducing runs of configure
+dnl
+APR_CONFIG_NICE(config.nice)
+
+dnl # Some initial steps for configuration. We setup the default directory
+dnl # and which files are to be configured.
+
+dnl Absolute source/build directory
+abs_srcdir=`(cd $srcdir && pwd)`
+abs_builddir=`pwd`
+
+if test "$abs_builddir" != "$abs_srcdir"; then
+ USE_VPATH=1
+ APU_CONFIG_LOCATION=build
+else
+ APU_CONFIG_LOCATION=source
+fi
+
+AC_SUBST(APU_CONFIG_LOCATION)
+
+AC_CANONICAL_SYSTEM
+
+AC_PROG_INSTALL
+
+dnl
+dnl compute the top directory of the build
+dnl note: this is needed for LIBTOOL and exporting the bundled Expat
+dnl
+top_builddir="$abs_builddir"
+AC_SUBST(top_builddir)
+AC_SUBST(abs_srcdir)
+AC_SUBST(abs_builddir)
+
+dnl Initialize mkdir -p functionality.
+APR_MKDIR_P_CHECK($abs_srcdir/build/mkdir.sh)
+
+dnl get our version information
+get_version="$abs_srcdir/build/get-version.sh"
+version_hdr="$abs_srcdir/include/apu_version.h"
+APRUTIL_MAJOR_VERSION="`$get_version major $version_hdr APU`"
+APRUTIL_DOTTED_VERSION="`$get_version all $version_hdr APU`"
+
+AC_SUBST(APRUTIL_DOTTED_VERSION)
+AC_SUBST(APRUTIL_MAJOR_VERSION)
+
+echo "APR-util Version: ${APRUTIL_DOTTED_VERSION}"
+
+dnl Enable the layout handling code, then reparse the prefix-style
+dnl arguments due to autoconf being a PITA.
+APR_ENABLE_LAYOUT(apr-util)
+APR_PARSE_ARGUMENTS
+
+dnl load os-specific hints for apr-util
+APU_PRELOAD
+
+dnl
+dnl set up the compilation flags and stuff
+dnl
+
+APRUTIL_INCLUDES=""
+APRUTIL_PRIV_INCLUDES="-I$top_builddir/include -I$top_builddir/include/private"
+if test -n "$USE_VPATH"; then
+ APRUTIL_PRIV_INCLUDES="$APRUTIL_PRIV_INCLUDES -I$abs_srcdir/include/private -I$abs_srcdir/include"
+fi
+
+dnl
+dnl Find the APR includes directory and (possibly) the source (base) dir.
+dnl
+APU_FIND_APR
+
+dnl
+dnl even though we use apr_rules.mk for building apr-util, we need
+dnl to grab CC and CPP ahead of time so that apr-util config tests
+dnl use the same compiler as APR; we need the same compiler options
+dnl and feature test macros as well
+dnl
+APR_SETIFNULL(CC, `$apr_config --cc`)
+APR_SETIFNULL(CPP, `$apr_config --cpp`)
+APR_ADDTO(CFLAGS, `$apr_config --cflags`)
+APR_ADDTO(CPPFLAGS, `$apr_config --cppflags`)
+
+dnl
+dnl Find the APR-ICONV directory.
+dnl
+if test -d ../apr-iconv; then
+ APR_SUBDIR_CONFIG(../apr-iconv,
+ [$apache_apr_flags --prefix=$prefix --exec-prefix=$exec_prefix --libdir=$libdir --includedir=$includedir --bindir=$bindir --datadir=$datadir --with-installbuilddir=$installbuilddir],
+ [--enable-layout=*|\'--enable-layout=*])
+ APRUTIL_EXPORT_LIBS="$abs_srcdir/../apr-iconv/lib/libapriconv.la $APRUTIL_EXPORT_LIBS"
+ APRUTIL_INCLUDES="-I$abs_srcdir/../apr-iconv/include $APRUTIL_INCLUDES"
+ APR_ICONV_DIR=../apr-iconv
+else
+ APR_ICONV_DIR=""
+fi
+AC_SUBST(APR_ICONV_DIR)
+
+dnl Find LDAP library
+dnl Determine what DBM backend type to use.
+dnl Find Expat
+dnl Find an iconv library
+APU_FIND_LDAP
+APU_CHECK_DBM
+APU_CHECK_DBD
+APU_CHECK_DBD_MYSQL
+APU_CHECK_DBD_SQLITE3
+APU_CHECK_DBD_SQLITE2
+APU_FIND_EXPAT
+APU_FIND_ICONV
+
+AC_SEARCH_LIBS(crypt, crypt ufc)
+AC_MSG_CHECKING(if system crypt() function is threadsafe)
+if test "x$apu_crypt_threadsafe" = "x1"; then
+ AC_DEFINE(APU_CRYPT_THREADSAFE, 1, [Define if the system crypt() function is threadsafe])
+ msg="yes"
+else
+ msg="no"
+fi
+AC_MSG_RESULT([$msg])
+
+AC_CHECK_FUNCS(crypt_r, [ crypt_r="1" ], [ crypt_r="0" ])
+if test "$crypt_r" = "1"; then
+ APU_CHECK_CRYPT_R_STYLE
+fi
+
+so_ext=$APR_SO_EXT
+lib_target=$APR_LIB_TARGET
+AC_SUBST(so_ext)
+AC_SUBST(lib_target)
+
+APRUTIL_LIBNAME="aprutil${libsuffix}"
+AC_SUBST(APRUTIL_LIBNAME)
+
+dnl
+dnl Prep all the flags and stuff for compilation and export to other builds
+dnl
+APR_ADDTO(APRUTIL_LIBS, [$APR_LIBS])
+
+AC_SUBST(APRUTIL_EXPORT_LIBS)
+AC_SUBST(APRUTIL_PRIV_INCLUDES)
+AC_SUBST(APRUTIL_INCLUDES)
+AC_SUBST(APRUTIL_LDFLAGS)
+AC_SUBST(APRUTIL_LIBS)
+AC_SUBST(LDFLAGS)
+
+dnl copy apr's rules.mk into our build directory.
+if test ! -d ./build; then
+ $mkdir_p build
+fi
+cp $APR_BUILD_DIR/apr_rules.mk $abs_builddir/build/rules.mk
+
+dnl
+dnl BSD/OS (BSDi) needs to use a different include syntax in the Makefiles
+dnl
+case "$host_alias" in
+*bsdi* | BSD/OS)
+ # Check whether they've installed GNU make
+ if make --version > /dev/null 2>&1; then
+ INCLUDE_RULES="include $abs_builddir/build/rules.mk"
+ INCLUDE_OUTPUTS="include $abs_srcdir/build-outputs.mk"
+ else
+ INCLUDE_RULES=".include \"$abs_builddir/build/rules.mk\""
+ INCLUDE_OUTPUTS=".include \"$abs_srcdir/build-outputs.mk\""
+ fi
+ ;;
+*)
+ INCLUDE_RULES="include $abs_builddir/build/rules.mk"
+ INCLUDE_OUTPUTS="include $abs_srcdir/build-outputs.mk"
+ ;;
+esac
+AC_SUBST(INCLUDE_RULES)
+AC_SUBST(INCLUDE_OUTPUTS)
+
+for d in include include/private; do
+ test -d $top_builddir/$d || mkdir $top_builddir/$d
+done
+
+AC_CONFIG_FILES([Makefile export_vars.sh
+ build/pkg/pkginfo apr-util.pc
+ apu-$APRUTIL_MAJOR_VERSION-config:apu-config.in
+ include/private/apu_select_dbm.h
+ include/apr_ldap.h
+ include/apu.h include/apu_want.h])
+
+AC_CONFIG_COMMANDS([default], [
+chmod +x apu-$APRUTIL_MAJOR_VERSION-config
+],[
+APRUTIL_MAJOR_VERSION=$APRUTIL_MAJOR_VERSION
+])
+
+if test -d $srcdir/test; then
+ AC_CONFIG_FILES([test/Makefile])
+fi
+
+AC_OUTPUT
--- /dev/null
+/* Copyright 2001-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * This is derived from material copyright RSA Data Security, Inc.
+ * Their notice is reproduced below in its entirety.
+ *
+ * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+ * rights reserved.
+ *
+ * License to copy and use this software is granted provided that it
+ * is identified as the "RSA Data Security, Inc. MD4 Message-Digest
+ * Algorithm" in all material mentioning or referencing this software
+ * or this function.
+ *
+ * License is also granted to make and use derivative works provided
+ * that such works are identified as "derived from the RSA Data
+ * Security, Inc. MD4 Message-Digest Algorithm" in all material
+ * mentioning or referencing the derived work.
+ *
+ * RSA Data Security, Inc. makes no representations concerning either
+ * the merchantability of this software or the suitability of this
+ * software for any particular purpose. It is provided "as is"
+ * without express or implied warranty of any kind.
+ *
+ * These notices must be retained in any copies of any part of this
+ * documentation and/or software.
+ */
+
+#include "apr_strings.h"
+#include "apr_md4.h"
+#include "apr_lib.h"
+
+#if APR_HAVE_STRING_H
+#include <string.h>
+#endif
+#if APR_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+/* Constants for MD4Transform routine.
+ */
+
+#define S11 3
+#define S12 7
+#define S13 11
+#define S14 19
+#define S21 3
+#define S22 5
+#define S23 9
+#define S24 13
+#define S31 3
+#define S32 9
+#define S33 11
+#define S34 15
+
+static void MD4Transform(apr_uint32_t state[4], const unsigned char block[64]);
+static void Encode(unsigned char *output, const apr_uint32_t *input,
+ unsigned int len);
+static void Decode(apr_uint32_t *output, const unsigned char *input,
+ unsigned int len);
+
+static unsigned char PADDING[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+#if APR_CHARSET_EBCDIC
+static apr_xlate_t *xlate_ebcdic_to_ascii; /* used in apr_md4_encode() */
+#endif
+
+/* F, G and I are basic MD4 functions.
+ */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+
+/* ROTATE_LEFT rotates x left n bits.
+ */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG and HH are transformations for rounds 1, 2 and 3 */
+/* Rotation is separate from addition to prevent recomputation */
+
+#define FF(a, b, c, d, x, s) { \
+ (a) += F ((b), (c), (d)) + (x); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ }
+#define GG(a, b, c, d, x, s) { \
+ (a) += G ((b), (c), (d)) + (x) + (apr_uint32_t)0x5a827999; \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ }
+#define HH(a, b, c, d, x, s) { \
+ (a) += H ((b), (c), (d)) + (x) + (apr_uint32_t)0x6ed9eba1; \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ }
+
+/* MD4 initialization. Begins an MD4 operation, writing a new context.
+ */
+APU_DECLARE(apr_status_t) apr_md4_init(apr_md4_ctx_t *context)
+{
+ context->count[0] = context->count[1] = 0;
+
+ /* Load magic initialization constants. */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xefcdab89;
+ context->state[2] = 0x98badcfe;
+ context->state[3] = 0x10325476;
+
+#if APR_HAS_XLATE
+ context->xlate = NULL;
+#endif
+
+ return APR_SUCCESS;
+}
+
+#if APR_HAS_XLATE
+/* MD4 translation setup. Provides the APR translation handle
+ * to be used for translating the content before calculating the
+ * digest.
+ */
+APU_DECLARE(apr_status_t) apr_md4_set_xlate(apr_md4_ctx_t *context,
+ apr_xlate_t *xlate)
+{
+ apr_status_t rv;
+ int is_sb;
+
+ /* TODO: remove the single-byte-only restriction from this code
+ */
+ rv = apr_xlate_sb_get(xlate, &is_sb);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+ if (!is_sb) {
+ return APR_EINVAL;
+ }
+ context->xlate = xlate;
+ return APR_SUCCESS;
+}
+#endif /* APR_HAS_XLATE */
+
+/* MD4 block update operation. Continues an MD4 message-digest
+ * operation, processing another message block, and updating the
+ * context.
+ */
+APU_DECLARE(apr_status_t) apr_md4_update(apr_md4_ctx_t *context,
+ const unsigned char *input,
+ apr_size_t inputLen)
+{
+ unsigned int i, idx, partLen;
+#if APR_HAS_XLATE
+ apr_size_t inbytes_left, outbytes_left;
+#endif
+
+ /* Compute number of bytes mod 64 */
+ idx = (unsigned int)((context->count[0] >> 3) & 0x3F);
+
+ /* Update number of bits */
+ if ((context->count[0] += ((apr_uint32_t)inputLen << 3))
+ < ((apr_uint32_t)inputLen << 3))
+ context->count[1]++;
+ context->count[1] += (apr_uint32_t)inputLen >> 29;
+
+ partLen = 64 - idx;
+
+ /* Transform as many times as possible. */
+#if !APR_HAS_XLATE
+ if (inputLen >= partLen) {
+ memcpy(&context->buffer[idx], input, partLen);
+ MD4Transform(context->state, context->buffer);
+
+ for (i = partLen; i + 63 < inputLen; i += 64)
+ MD4Transform(context->state, &input[i]);
+
+ idx = 0;
+ }
+ else
+ i = 0;
+
+ /* Buffer remaining input */
+ memcpy(&context->buffer[idx], &input[i], inputLen - i);
+#else /*APR_HAS_XLATE*/
+ if (inputLen >= partLen) {
+ if (context->xlate) {
+ inbytes_left = outbytes_left = partLen;
+ apr_xlate_conv_buffer(context->xlate, (const char *)input,
+ &inbytes_left,
+ (char *)&context->buffer[idx],
+ &outbytes_left);
+ }
+ else {
+ memcpy(&context->buffer[idx], input, partLen);
+ }
+ MD4Transform(context->state, context->buffer);
+
+ for (i = partLen; i + 63 < inputLen; i += 64) {
+ if (context->xlate) {
+ unsigned char inp_tmp[64];
+ inbytes_left = outbytes_left = 64;
+ apr_xlate_conv_buffer(context->xlate, (const char *)&input[i],
+ &inbytes_left,
+ (char *)inp_tmp, &outbytes_left);
+ MD4Transform(context->state, inp_tmp);
+ }
+ else {
+ MD4Transform(context->state, &input[i]);
+ }
+ }
+
+ idx = 0;
+ }
+ else
+ i = 0;
+
+ /* Buffer remaining input */
+ if (context->xlate) {
+ inbytes_left = outbytes_left = inputLen - i;
+ apr_xlate_conv_buffer(context->xlate, (const char *)&input[i],
+ &inbytes_left, (char *)&context->buffer[idx],
+ &outbytes_left);
+ }
+ else {
+ memcpy(&context->buffer[idx], &input[i], inputLen - i);
+ }
+#endif /*APR_HAS_XLATE*/
+ return APR_SUCCESS;
+}
+
+/* MD4 finalization. Ends an MD4 message-digest operation, writing the
+ * the message digest and zeroizing the context.
+ */
+APU_DECLARE(apr_status_t) apr_md4_final(
+ unsigned char digest[APR_MD4_DIGESTSIZE],
+ apr_md4_ctx_t *context)
+{
+ unsigned char bits[8];
+ unsigned int idx, padLen;
+
+ /* Save number of bits */
+ Encode(bits, context->count, 8);
+
+#if APR_HAS_XLATE
+ /* apr_md4_update() should not translate for this final round. */
+ context->xlate = NULL;
+#endif /*APR_HAS_XLATE*/
+
+ /* Pad out to 56 mod 64. */
+ idx = (unsigned int) ((context->count[0] >> 3) & 0x3f);
+ padLen = (idx < 56) ? (56 - idx) : (120 - idx);
+ apr_md4_update(context, PADDING, padLen);
+
+ /* Append length (before padding) */
+ apr_md4_update(context, bits, 8);
+
+ /* Store state in digest */
+ Encode(digest, context->state, APR_MD4_DIGESTSIZE);
+
+ /* Zeroize sensitive information. */
+ memset(context, 0, sizeof(*context));
+
+ return APR_SUCCESS;
+}
+
+/* MD4 computation in one step (init, update, final)
+ */
+APU_DECLARE(apr_status_t) apr_md4(unsigned char digest[APR_MD4_DIGESTSIZE],
+ const unsigned char *input,
+ apr_size_t inputLen)
+{
+ apr_md4_ctx_t ctx;
+ apr_status_t rv;
+
+ apr_md4_init(&ctx);
+
+ if ((rv = apr_md4_update(&ctx, input, inputLen)) != APR_SUCCESS)
+ return rv;
+
+ return apr_md4_final(digest, &ctx);
+}
+
+/* MD4 basic transformation. Transforms state based on block. */
+static void MD4Transform(apr_uint32_t state[4], const unsigned char block[64])
+{
+ apr_uint32_t a = state[0], b = state[1], c = state[2], d = state[3],
+ x[APR_MD4_DIGESTSIZE];
+
+ Decode(x, block, 64);
+
+ /* Round 1 */
+ FF (a, b, c, d, x[ 0], S11); /* 1 */
+ FF (d, a, b, c, x[ 1], S12); /* 2 */
+ FF (c, d, a, b, x[ 2], S13); /* 3 */
+ FF (b, c, d, a, x[ 3], S14); /* 4 */
+ FF (a, b, c, d, x[ 4], S11); /* 5 */
+ FF (d, a, b, c, x[ 5], S12); /* 6 */
+ FF (c, d, a, b, x[ 6], S13); /* 7 */
+ FF (b, c, d, a, x[ 7], S14); /* 8 */
+ FF (a, b, c, d, x[ 8], S11); /* 9 */
+ FF (d, a, b, c, x[ 9], S12); /* 10 */
+ FF (c, d, a, b, x[10], S13); /* 11 */
+ FF (b, c, d, a, x[11], S14); /* 12 */
+ FF (a, b, c, d, x[12], S11); /* 13 */
+ FF (d, a, b, c, x[13], S12); /* 14 */
+ FF (c, d, a, b, x[14], S13); /* 15 */
+ FF (b, c, d, a, x[15], S14); /* 16 */
+
+ /* Round 2 */
+ GG (a, b, c, d, x[ 0], S21); /* 17 */
+ GG (d, a, b, c, x[ 4], S22); /* 18 */
+ GG (c, d, a, b, x[ 8], S23); /* 19 */
+ GG (b, c, d, a, x[12], S24); /* 20 */
+ GG (a, b, c, d, x[ 1], S21); /* 21 */
+ GG (d, a, b, c, x[ 5], S22); /* 22 */
+ GG (c, d, a, b, x[ 9], S23); /* 23 */
+ GG (b, c, d, a, x[13], S24); /* 24 */
+ GG (a, b, c, d, x[ 2], S21); /* 25 */
+ GG (d, a, b, c, x[ 6], S22); /* 26 */
+ GG (c, d, a, b, x[10], S23); /* 27 */
+ GG (b, c, d, a, x[14], S24); /* 28 */
+ GG (a, b, c, d, x[ 3], S21); /* 29 */
+ GG (d, a, b, c, x[ 7], S22); /* 30 */
+ GG (c, d, a, b, x[11], S23); /* 31 */
+ GG (b, c, d, a, x[15], S24); /* 32 */
+
+ /* Round 3 */
+ HH (a, b, c, d, x[ 0], S31); /* 33 */
+ HH (d, a, b, c, x[ 8], S32); /* 34 */
+ HH (c, d, a, b, x[ 4], S33); /* 35 */
+ HH (b, c, d, a, x[12], S34); /* 36 */
+ HH (a, b, c, d, x[ 2], S31); /* 37 */
+ HH (d, a, b, c, x[10], S32); /* 38 */
+ HH (c, d, a, b, x[ 6], S33); /* 39 */
+ HH (b, c, d, a, x[14], S34); /* 40 */
+ HH (a, b, c, d, x[ 1], S31); /* 41 */
+ HH (d, a, b, c, x[ 9], S32); /* 42 */
+ HH (c, d, a, b, x[ 5], S33); /* 43 */
+ HH (b, c, d, a, x[13], S34); /* 44 */
+ HH (a, b, c, d, x[ 3], S31); /* 45 */
+ HH (d, a, b, c, x[11], S32); /* 46 */
+ HH (c, d, a, b, x[ 7], S33); /* 47 */
+ HH (b, c, d, a, x[15], S34); /* 48 */
+
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+
+ /* Zeroize sensitive information. */
+ memset(x, 0, sizeof(x));
+}
+
+/* Encodes input (apr_uint32_t) into output (unsigned char). Assumes len is
+ * a multiple of 4.
+ */
+static void Encode(unsigned char *output, const apr_uint32_t *input,
+ unsigned int len)
+{
+ unsigned int i, j;
+ apr_uint32_t k;
+
+ for (i = 0, j = 0; j < len; i++, j += 4) {
+ k = input[i];
+ output[j] = (unsigned char)(k & 0xff);
+ output[j + 1] = (unsigned char)((k >> 8) & 0xff);
+ output[j + 2] = (unsigned char)((k >> 16) & 0xff);
+ output[j + 3] = (unsigned char)((k >> 24) & 0xff);
+ }
+}
+
+/* Decodes input (unsigned char) into output (apr_uint32_t). Assumes len is
+ * a multiple of 4.
+ */
+static void Decode(apr_uint32_t *output, const unsigned char *input,
+ unsigned int len)
+{
+ unsigned int i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4)
+ output[i] = ((apr_uint32_t)input[j]) |
+ (((apr_uint32_t)input[j + 1]) << 8) |
+ (((apr_uint32_t)input[j + 2]) << 16) |
+ (((apr_uint32_t)input[j + 3]) << 24);
+}
+
+#if APR_CHARSET_EBCDIC
+APU_DECLARE(apr_status_t) apr_MD4InitEBCDIC(apr_xlate_t *xlate)
+{
+ xlate_ebcdic_to_ascii = xlate;
+ return APR_SUCCESS;
+}
+#endif
--- /dev/null
+/*
+ * This is work is derived from material Copyright RSA Data Security, Inc.
+ *
+ * The RSA copyright statement and Licence for that original material is
+ * included below. This is followed by the Apache copyright statement and
+ * licence for the modifications made to that material.
+ */
+
+/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
+ */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+ rights reserved.
+
+ License to copy and use this software is granted provided that it
+ is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+ Algorithm" in all material mentioning or referencing this software
+ or this function.
+
+ License is also granted to make and use derivative works provided
+ that such works are identified as "derived from the RSA Data
+ Security, Inc. MD5 Message-Digest Algorithm" in all material
+ mentioning or referencing the derived work.
+
+ RSA Data Security, Inc. makes no representations concerning either
+ the merchantability of this software or the suitability of this
+ software for any particular purpose. It is provided "as is"
+ without express or implied warranty of any kind.
+
+ These notices must be retained in any copies of any part of this
+ documentation and/or software.
+ */
+
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * The apr_md5_encode() routine uses much code obtained from the FreeBSD 3.0
+ * MD5 crypt() function, which is licenced as follows:
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@login.dknet.dk> wrote this file. As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
+ * ----------------------------------------------------------------------------
+ */
+#include "apr_strings.h"
+#include "apr_md5.h"
+#include "apr_lib.h"
+#include "apu_config.h"
+#include "apr_sha1.h"
+
+#if APR_HAVE_STRING_H
+#include <string.h>
+#endif
+#if APR_HAVE_CRYPT_H
+#include <crypt.h>
+#endif
+#if APR_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if APR_HAVE_PTHREAD_H
+#include <pthread.h>
+#endif
+
+/* Constants for MD5Transform routine.
+ */
+
+#define S11 7
+#define S12 12
+#define S13 17
+#define S14 22
+#define S21 5
+#define S22 9
+#define S23 14
+#define S24 20
+#define S31 4
+#define S32 11
+#define S33 16
+#define S34 23
+#define S41 6
+#define S42 10
+#define S43 15
+#define S44 21
+
+static void MD5Transform(apr_uint32_t state[4], const unsigned char block[64]);
+static void Encode(unsigned char *output, const apr_uint32_t *input,
+ unsigned int len);
+static void Decode(apr_uint32_t *output, const unsigned char *input,
+ unsigned int len);
+
+static unsigned char PADDING[64] =
+{
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+#if APR_CHARSET_EBCDIC
+static apr_xlate_t *xlate_ebcdic_to_ascii; /* used in apr_md5_encode() */
+#endif
+
+/* F, G, H and I are basic MD5 functions.
+ */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define I(x, y, z) ((y) ^ ((x) | (~z)))
+
+/* ROTATE_LEFT rotates x left n bits.
+ */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+ * Rotation is separate from addition to prevent recomputation.
+ */
+#define FF(a, b, c, d, x, s, ac) { \
+ (a) += F ((b), (c), (d)) + (x) + (apr_uint32_t)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define GG(a, b, c, d, x, s, ac) { \
+ (a) += G ((b), (c), (d)) + (x) + (apr_uint32_t)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define HH(a, b, c, d, x, s, ac) { \
+ (a) += H ((b), (c), (d)) + (x) + (apr_uint32_t)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+#define II(a, b, c, d, x, s, ac) { \
+ (a) += I ((b), (c), (d)) + (x) + (apr_uint32_t)(ac); \
+ (a) = ROTATE_LEFT ((a), (s)); \
+ (a) += (b); \
+ }
+
+/* MD5 initialization. Begins an MD5 operation, writing a new context.
+ */
+APU_DECLARE(apr_status_t) apr_md5_init(apr_md5_ctx_t *context)
+{
+ context->count[0] = context->count[1] = 0;
+
+ /* Load magic initialization constants. */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xefcdab89;
+ context->state[2] = 0x98badcfe;
+ context->state[3] = 0x10325476;
+ context->xlate = NULL;
+
+ return APR_SUCCESS;
+}
+
+/* MD5 translation setup. Provides the APR translation handle
+ * to be used for translating the content before calculating the
+ * digest.
+ */
+APU_DECLARE(apr_status_t) apr_md5_set_xlate(apr_md5_ctx_t *context,
+ apr_xlate_t *xlate)
+{
+#if APR_HAS_XLATE
+ apr_status_t rv;
+ int is_sb;
+
+ /* TODO: remove the single-byte-only restriction from this code
+ */
+ rv = apr_xlate_sb_get(xlate, &is_sb);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+ if (!is_sb) {
+ return APR_EINVAL;
+ }
+ context->xlate = xlate;
+ return APR_SUCCESS;
+#else
+ return APR_ENOTIMPL;
+#endif /* APR_HAS_XLATE */
+}
+
+/* MD5 block update operation. Continues an MD5 message-digest
+ * operation, processing another message block, and updating the
+ * context.
+ */
+APU_DECLARE(apr_status_t) apr_md5_update(apr_md5_ctx_t *context,
+ const void *_input,
+ apr_size_t inputLen)
+{
+ const unsigned char *input = _input;
+ unsigned int i, idx, partLen;
+#if APR_HAS_XLATE
+ apr_size_t inbytes_left, outbytes_left;
+#endif
+
+ /* Compute number of bytes mod 64 */
+ idx = (unsigned int)((context->count[0] >> 3) & 0x3F);
+
+ /* Update number of bits */
+ if ((context->count[0] += ((apr_uint32_t)inputLen << 3))
+ < ((apr_uint32_t)inputLen << 3))
+ context->count[1]++;
+ context->count[1] += (apr_uint32_t)inputLen >> 29;
+
+ partLen = 64 - idx;
+
+ /* Transform as many times as possible. */
+#if !APR_HAS_XLATE
+ if (inputLen >= partLen) {
+ memcpy(&context->buffer[idx], input, partLen);
+ MD5Transform(context->state, context->buffer);
+
+ for (i = partLen; i + 63 < inputLen; i += 64)
+ MD5Transform(context->state, &input[i]);
+
+ idx = 0;
+ }
+ else
+ i = 0;
+
+ /* Buffer remaining input */
+ memcpy(&context->buffer[idx], &input[i], inputLen - i);
+#else /*APR_HAS_XLATE*/
+ if (inputLen >= partLen) {
+ if (context->xlate) {
+ inbytes_left = outbytes_left = partLen;
+ apr_xlate_conv_buffer(context->xlate, (const char *)input,
+ &inbytes_left,
+ (char *)&context->buffer[idx],
+ &outbytes_left);
+ }
+ else {
+ memcpy(&context->buffer[idx], input, partLen);
+ }
+ MD5Transform(context->state, context->buffer);
+
+ for (i = partLen; i + 63 < inputLen; i += 64) {
+ if (context->xlate) {
+ unsigned char inp_tmp[64];
+ inbytes_left = outbytes_left = 64;
+ apr_xlate_conv_buffer(context->xlate, (const char *)&input[i],
+ &inbytes_left, (char *)inp_tmp,
+ &outbytes_left);
+ MD5Transform(context->state, inp_tmp);
+ }
+ else {
+ MD5Transform(context->state, &input[i]);
+ }
+ }
+
+ idx = 0;
+ }
+ else
+ i = 0;
+
+ /* Buffer remaining input */
+ if (context->xlate) {
+ inbytes_left = outbytes_left = inputLen - i;
+ apr_xlate_conv_buffer(context->xlate, (const char *)&input[i],
+ &inbytes_left, (char *)&context->buffer[idx],
+ &outbytes_left);
+ }
+ else {
+ memcpy(&context->buffer[idx], &input[i], inputLen - i);
+ }
+#endif /*APR_HAS_XLATE*/
+ return APR_SUCCESS;
+}
+
+/* MD5 finalization. Ends an MD5 message-digest operation, writing the
+ * the message digest and zeroizing the context.
+ */
+APU_DECLARE(apr_status_t) apr_md5_final(unsigned char digest[APR_MD5_DIGESTSIZE],
+ apr_md5_ctx_t *context)
+{
+ unsigned char bits[8];
+ unsigned int idx, padLen;
+
+ /* Save number of bits */
+ Encode(bits, context->count, 8);
+
+#if APR_HAS_XLATE
+ /* apr_md5_update() should not translate for this final round. */
+ context->xlate = NULL;
+#endif /*APR_HAS_XLATE*/
+
+ /* Pad out to 56 mod 64. */
+ idx = (unsigned int)((context->count[0] >> 3) & 0x3f);
+ padLen = (idx < 56) ? (56 - idx) : (120 - idx);
+ apr_md5_update(context, PADDING, padLen);
+
+ /* Append length (before padding) */
+ apr_md5_update(context, bits, 8);
+
+ /* Store state in digest */
+ Encode(digest, context->state, APR_MD5_DIGESTSIZE);
+
+ /* Zeroize sensitive information. */
+ memset(context, 0, sizeof(*context));
+
+ return APR_SUCCESS;
+}
+
+/* MD5 in one step (init, update, final)
+ */
+APU_DECLARE(apr_status_t) apr_md5(unsigned char digest[APR_MD5_DIGESTSIZE],
+ const void *_input,
+ apr_size_t inputLen)
+{
+ const unsigned char *input = _input;
+ apr_md5_ctx_t ctx;
+ apr_status_t rv;
+
+ apr_md5_init(&ctx);
+
+ if ((rv = apr_md5_update(&ctx, input, inputLen)) != APR_SUCCESS)
+ return rv;
+
+ return apr_md5_final(digest, &ctx);
+}
+
+/* MD5 basic transformation. Transforms state based on block. */
+static void MD5Transform(apr_uint32_t state[4], const unsigned char block[64])
+{
+ apr_uint32_t a = state[0], b = state[1], c = state[2], d = state[3],
+ x[APR_MD5_DIGESTSIZE];
+
+ Decode(x, block, 64);
+
+ /* Round 1 */
+ FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */
+ FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */
+ FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */
+ FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */
+ FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */
+ FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */
+ FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */
+ FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */
+ FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */
+ FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */
+ FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
+ FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
+ FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
+ FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
+ FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
+ FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
+
+ /* Round 2 */
+ GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */
+ GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */
+ GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
+ GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */
+ GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */
+ GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */
+ GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
+ GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */
+ GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */
+ GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
+ GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */
+ GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */
+ GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
+ GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */
+ GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */
+ GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
+
+ /* Round 3 */
+ HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */
+ HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */
+ HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
+ HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
+ HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */
+ HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */
+ HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */
+ HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
+ HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
+ HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */
+ HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */
+ HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */
+ HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */
+ HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
+ HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
+ HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */
+
+ /* Round 4 */
+ II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */
+ II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */
+ II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
+ II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */
+ II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
+ II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */
+ II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
+ II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */
+ II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */
+ II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
+ II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */
+ II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
+ II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */
+ II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
+ II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */
+ II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */
+
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+
+ /* Zeroize sensitive information. */
+ memset(x, 0, sizeof(x));
+}
+
+/* Encodes input (apr_uint32_t) into output (unsigned char). Assumes len is
+ * a multiple of 4.
+ */
+static void Encode(unsigned char *output, const apr_uint32_t *input,
+ unsigned int len)
+{
+ unsigned int i, j;
+ apr_uint32_t k;
+
+ for (i = 0, j = 0; j < len; i++, j += 4) {
+ k = input[i];
+ output[j] = (unsigned char)(k & 0xff);
+ output[j + 1] = (unsigned char)((k >> 8) & 0xff);
+ output[j + 2] = (unsigned char)((k >> 16) & 0xff);
+ output[j + 3] = (unsigned char)((k >> 24) & 0xff);
+ }
+}
+
+/* Decodes input (unsigned char) into output (apr_uint32_t). Assumes len is
+ * a multiple of 4.
+ */
+static void Decode(apr_uint32_t *output, const unsigned char *input,
+ unsigned int len)
+{
+ unsigned int i, j;
+
+ for (i = 0, j = 0; j < len; i++, j += 4)
+ output[i] = ((apr_uint32_t)input[j]) |
+ (((apr_uint32_t)input[j + 1]) << 8) |
+ (((apr_uint32_t)input[j + 2]) << 16) |
+ (((apr_uint32_t)input[j + 3]) << 24);
+}
+
+#if APR_CHARSET_EBCDIC
+APU_DECLARE(apr_status_t) apr_MD5InitEBCDIC(apr_xlate_t *xlate)
+{
+ xlate_ebcdic_to_ascii = xlate;
+ return APR_SUCCESS;
+}
+#endif
+
+/*
+ * Define the Magic String prefix that identifies a password as being
+ * hashed using our algorithm.
+ */
+static const char *apr1_id = "$apr1$";
+
+/*
+ * The following MD5 password encryption code was largely borrowed from
+ * the FreeBSD 3.0 /usr/src/lib/libcrypt/crypt.c file, which is
+ * licenced as stated at the top of this file.
+ */
+
+static void to64(char *s, unsigned long v, int n)
+{
+ static unsigned char itoa64[] = /* 0 ... 63 => ASCII - 64 */
+ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+ while (--n >= 0) {
+ *s++ = itoa64[v&0x3f];
+ v >>= 6;
+ }
+}
+
+APU_DECLARE(apr_status_t) apr_md5_encode(const char *pw, const char *salt,
+ char *result, apr_size_t nbytes)
+{
+ /*
+ * Minimum size is 8 bytes for salt, plus 1 for the trailing NUL,
+ * plus 4 for the '$' separators, plus the password hash itself.
+ * Let's leave a goodly amount of leeway.
+ */
+
+ char passwd[120], *p;
+ const char *sp, *ep;
+ unsigned char final[APR_MD5_DIGESTSIZE];
+ apr_ssize_t sl, pl, i;
+ apr_md5_ctx_t ctx, ctx1;
+ unsigned long l;
+
+ /*
+ * Refine the salt first. It's possible we were given an already-hashed
+ * string as the salt argument, so extract the actual salt value from it
+ * if so. Otherwise just use the string up to the first '$' as the salt.
+ */
+ sp = salt;
+
+ /*
+ * If it starts with the magic string, then skip that.
+ */
+ if (!strncmp(sp, apr1_id, strlen(apr1_id))) {
+ sp += strlen(apr1_id);
+ }
+
+ /*
+ * It stops at the first '$' or 8 chars, whichever comes first
+ */
+ for (ep = sp; (*ep != '\0') && (*ep != '$') && (ep < (sp + 8)); ep++) {
+ continue;
+ }
+
+ /*
+ * Get the length of the true salt
+ */
+ sl = ep - sp;
+
+ /*
+ * 'Time to make the doughnuts..'
+ */
+ apr_md5_init(&ctx);
+#if APR_CHARSET_EBCDIC
+ apr_md5_set_xlate(&ctx, xlate_ebcdic_to_ascii);
+#endif
+
+ /*
+ * The password first, since that is what is most unknown
+ */
+ apr_md5_update(&ctx, pw, strlen(pw));
+
+ /*
+ * Then our magic string
+ */
+ apr_md5_update(&ctx, apr1_id, strlen(apr1_id));
+
+ /*
+ * Then the raw salt
+ */
+ apr_md5_update(&ctx, sp, sl);
+
+ /*
+ * Then just as many characters of the MD5(pw, salt, pw)
+ */
+ apr_md5_init(&ctx1);
+ apr_md5_update(&ctx1, pw, strlen(pw));
+ apr_md5_update(&ctx1, sp, sl);
+ apr_md5_update(&ctx1, pw, strlen(pw));
+ apr_md5_final(final, &ctx1);
+ for (pl = strlen(pw); pl > 0; pl -= APR_MD5_DIGESTSIZE) {
+ apr_md5_update(&ctx, final,
+ (pl > APR_MD5_DIGESTSIZE) ? APR_MD5_DIGESTSIZE : pl);
+ }
+
+ /*
+ * Don't leave anything around in vm they could use.
+ */
+ memset(final, 0, sizeof(final));
+
+ /*
+ * Then something really weird...
+ */
+ for (i = strlen(pw); i != 0; i >>= 1) {
+ if (i & 1) {
+ apr_md5_update(&ctx, final, 1);
+ }
+ else {
+ apr_md5_update(&ctx, pw, 1);
+ }
+ }
+
+ /*
+ * Now make the output string. We know our limitations, so we
+ * can use the string routines without bounds checking.
+ */
+ strcpy(passwd, apr1_id);
+ strncat(passwd, sp, sl);
+ strcat(passwd, "$");
+
+ apr_md5_final(final, &ctx);
+
+ /*
+ * And now, just to make sure things don't run too fast..
+ * On a 60 Mhz Pentium this takes 34 msec, so you would
+ * need 30 seconds to build a 1000 entry dictionary...
+ */
+ for (i = 0; i < 1000; i++) {
+ apr_md5_init(&ctx1);
+ if (i & 1) {
+ apr_md5_update(&ctx1, pw, strlen(pw));
+ }
+ else {
+ apr_md5_update(&ctx1, final, APR_MD5_DIGESTSIZE);
+ }
+ if (i % 3) {
+ apr_md5_update(&ctx1, sp, sl);
+ }
+
+ if (i % 7) {
+ apr_md5_update(&ctx1, pw, strlen(pw));
+ }
+
+ if (i & 1) {
+ apr_md5_update(&ctx1, final, APR_MD5_DIGESTSIZE);
+ }
+ else {
+ apr_md5_update(&ctx1, pw, strlen(pw));
+ }
+ apr_md5_final(final,&ctx1);
+ }
+
+ p = passwd + strlen(passwd);
+
+ l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p, l, 4); p += 4;
+ l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p, l, 4); p += 4;
+ l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p, l, 4); p += 4;
+ l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p, l, 4); p += 4;
+ l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p, l, 4); p += 4;
+ l = final[11] ; to64(p, l, 2); p += 2;
+ *p = '\0';
+
+ /*
+ * Don't leave anything around in vm they could use.
+ */
+ memset(final, 0, sizeof(final));
+
+ apr_cpystrn(result, passwd, nbytes - 1);
+ return APR_SUCCESS;
+}
+
+#if !defined(WIN32) && !defined(BEOS) && !defined(NETWARE)
+#if defined(APU_CRYPT_THREADSAFE) || !APR_HAS_THREADS || \
+ defined(CRYPT_R_CRYPTD) || defined(CRYPT_R_STRUCT_CRYPT_DATA)
+
+#define crypt_mutex_lock()
+#define crypt_mutex_unlock()
+
+#elif APR_HAVE_PTHREAD_H && defined(PTHREAD_MUTEX_INITIALIZER)
+
+static pthread_mutex_t crypt_mutex = PTHREAD_MUTEX_INITIALIZER;
+static void crypt_mutex_lock(void)
+{
+ pthread_mutex_lock(&crypt_mutex);
+}
+
+static void crypt_mutex_unlock(void)
+{
+ pthread_mutex_unlock(&crypt_mutex);
+}
+
+#else
+
+#error apr_password_validate() is not threadsafe. rebuild APR without thread support.
+
+#endif
+#endif
+
+/*
+ * Validate a plaintext password against a smashed one. Uses either
+ * crypt() (if available) or apr_md5_encode() or apr_sha1_base64(), depending
+ * upon the format of the smashed input password. Returns APR_SUCCESS if
+ * they match, or APR_EMISMATCH if they don't. If the platform doesn't
+ * support crypt, then the default check is against a clear text string.
+ */
+APU_DECLARE(apr_status_t) apr_password_validate(const char *passwd,
+ const char *hash)
+{
+ char sample[120];
+#if !defined(WIN32) && !defined(BEOS) && !defined(NETWARE)
+ char *crypt_pw;
+#endif
+ if (!strncmp(hash, apr1_id, strlen(apr1_id))) {
+ /*
+ * The hash was created using our custom algorithm.
+ */
+ apr_md5_encode(passwd, hash, sample, sizeof(sample));
+ }
+ else if (!strncmp(hash, APR_SHA1PW_ID, APR_SHA1PW_IDLEN)) {
+ apr_sha1_base64(passwd, strlen(passwd), sample);
+ }
+ else {
+ /*
+ * It's not our algorithm, so feed it to crypt() if possible.
+ */
+#if defined(WIN32) || defined(BEOS) || defined(NETWARE)
+ apr_cpystrn(sample, passwd, sizeof(sample) - 1);
+#elif defined(CRYPT_R_CRYPTD)
+ CRYPTD buffer;
+
+ crypt_pw = crypt_r(passwd, hash, &buffer);
+ apr_cpystrn(sample, crypt_pw, sizeof(sample) - 1);
+#elif defined(CRYPT_R_STRUCT_CRYPT_DATA)
+ struct crypt_data buffer;
+
+ /* having to clear this seems bogus... GNU doc is
+ * confusing... user report found from google says
+ * the crypt_data struct had to be cleared to get
+ * the same result as plain crypt()
+ */
+ memset(&buffer, 0, sizeof(buffer));
+ crypt_pw = crypt_r(passwd, hash, &buffer);
+ apr_cpystrn(sample, crypt_pw, sizeof(sample) - 1);
+#else
+ /* Do a bit of sanity checking since we know that crypt_r()
+ * should always be used for threaded builds on AIX, and
+ * problems in configure logic can result in the wrong
+ * choice being made.
+ */
+#if defined(_AIX) && APR_HAS_THREADS
+#error Configuration error! crypt_r() should have been selected!
+#endif
+
+ /* Handle thread safety issues by holding a mutex around the
+ * call to crypt().
+ */
+ crypt_mutex_lock();
+ crypt_pw = crypt(passwd, hash);
+ apr_cpystrn(sample, crypt_pw, sizeof(sample) - 1);
+ crypt_mutex_unlock();
+#endif
+ }
+ return (strcmp(sample, hash) == 0) ? APR_SUCCESS : APR_EMISMATCH;
+}
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * The exported function:
+ *
+ * apr_sha1_base64(const char *clear, int len, char *out);
+ *
+ * provides a means to SHA1 crypt/encode a plaintext password in
+ * a way which makes password files compatible with those commonly
+ * used in netscape web and ldap installations. It was put together
+ * by Clinton Wong <clintdw@netcom.com>, who also notes that:
+ *
+ * Note: SHA1 support is useful for migration purposes, but is less
+ * secure than Apache's password format, since Apache's (MD5)
+ * password format uses a random eight character salt to generate
+ * one of many possible hashes for the same password. Netscape
+ * uses plain SHA1 without a salt, so the same password
+ * will always generate the same hash, making it easier
+ * to break since the search space is smaller.
+ *
+ * See also the documentation in support/SHA1 as to hints on how to
+ * migrate an existing netscape installation and other supplied utitlites.
+ *
+ * This software also makes use of the following component:
+ *
+ * NIST Secure Hash Algorithm
+ * heavily modified by Uwe Hollerbach uh@alumni.caltech edu
+ * from Peter C. Gutmann's implementation as found in
+ * Applied Cryptography by Bruce Schneier
+ * This code is hereby placed in the public domain
+ */
+
+#include "apr_sha1.h"
+#include "apr_base64.h"
+#include "apr_strings.h"
+#include "apr_lib.h"
+#if APR_CHARSET_EBCDIC
+#include "apr_xlate.h"
+#endif /*APR_CHARSET_EBCDIC*/
+#include <string.h>
+
+/* a bit faster & bigger, if defined */
+#define UNROLL_LOOPS
+
+/* NIST's proposed modification to SHA, 7/11/94 */
+#define USE_MODIFIED_SHA
+
+/* SHA f()-functions */
+#define f1(x,y,z) ((x & y) | (~x & z))
+#define f2(x,y,z) (x ^ y ^ z)
+#define f3(x,y,z) ((x & y) | (x & z) | (y & z))
+#define f4(x,y,z) (x ^ y ^ z)
+
+/* SHA constants */
+#define CONST1 0x5a827999L
+#define CONST2 0x6ed9eba1L
+#define CONST3 0x8f1bbcdcL
+#define CONST4 0xca62c1d6L
+
+/* 32-bit rotate */
+
+#define ROT32(x,n) ((x << n) | (x >> (32 - n)))
+
+#define FUNC(n,i) \
+ temp = ROT32(A,5) + f##n(B,C,D) + E + W[i] + CONST##n; \
+ E = D; D = C; C = ROT32(B,30); B = A; A = temp
+
+#define SHA_BLOCKSIZE 64
+
+#if APR_CHARSET_EBCDIC
+static apr_xlate_t *ebcdic2ascii_xlate;
+
+APU_DECLARE(apr_status_t) apr_SHA1InitEBCDIC(apr_xlate_t *x)
+{
+ apr_status_t rv;
+ int onoff;
+
+ /* Only single-byte conversion is supported.
+ */
+ rv = apr_xlate_sb_get(x, &onoff);
+ if (rv) {
+ return rv;
+ }
+ if (!onoff) { /* If conversion is not single-byte-only */
+ return APR_EINVAL;
+ }
+ ebcdic2ascii_xlate = x;
+ return APR_SUCCESS;
+}
+#endif
+
+/* do SHA transformation */
+static void sha_transform(apr_sha1_ctx_t *sha_info)
+{
+ int i;
+ apr_uint32_t temp, A, B, C, D, E, W[80];
+
+ for (i = 0; i < 16; ++i) {
+ W[i] = sha_info->data[i];
+ }
+ for (i = 16; i < 80; ++i) {
+ W[i] = W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16];
+#ifdef USE_MODIFIED_SHA
+ W[i] = ROT32(W[i], 1);
+#endif /* USE_MODIFIED_SHA */
+ }
+ A = sha_info->digest[0];
+ B = sha_info->digest[1];
+ C = sha_info->digest[2];
+ D = sha_info->digest[3];
+ E = sha_info->digest[4];
+#ifdef UNROLL_LOOPS
+ FUNC(1, 0); FUNC(1, 1); FUNC(1, 2); FUNC(1, 3); FUNC(1, 4);
+ FUNC(1, 5); FUNC(1, 6); FUNC(1, 7); FUNC(1, 8); FUNC(1, 9);
+ FUNC(1,10); FUNC(1,11); FUNC(1,12); FUNC(1,13); FUNC(1,14);
+ FUNC(1,15); FUNC(1,16); FUNC(1,17); FUNC(1,18); FUNC(1,19);
+
+ FUNC(2,20); FUNC(2,21); FUNC(2,22); FUNC(2,23); FUNC(2,24);
+ FUNC(2,25); FUNC(2,26); FUNC(2,27); FUNC(2,28); FUNC(2,29);
+ FUNC(2,30); FUNC(2,31); FUNC(2,32); FUNC(2,33); FUNC(2,34);
+ FUNC(2,35); FUNC(2,36); FUNC(2,37); FUNC(2,38); FUNC(2,39);
+
+ FUNC(3,40); FUNC(3,41); FUNC(3,42); FUNC(3,43); FUNC(3,44);
+ FUNC(3,45); FUNC(3,46); FUNC(3,47); FUNC(3,48); FUNC(3,49);
+ FUNC(3,50); FUNC(3,51); FUNC(3,52); FUNC(3,53); FUNC(3,54);
+ FUNC(3,55); FUNC(3,56); FUNC(3,57); FUNC(3,58); FUNC(3,59);
+
+ FUNC(4,60); FUNC(4,61); FUNC(4,62); FUNC(4,63); FUNC(4,64);
+ FUNC(4,65); FUNC(4,66); FUNC(4,67); FUNC(4,68); FUNC(4,69);
+ FUNC(4,70); FUNC(4,71); FUNC(4,72); FUNC(4,73); FUNC(4,74);
+ FUNC(4,75); FUNC(4,76); FUNC(4,77); FUNC(4,78); FUNC(4,79);
+#else /* !UNROLL_LOOPS */
+ for (i = 0; i < 20; ++i) {
+ FUNC(1,i);
+ }
+ for (i = 20; i < 40; ++i) {
+ FUNC(2,i);
+ }
+ for (i = 40; i < 60; ++i) {
+ FUNC(3,i);
+ }
+ for (i = 60; i < 80; ++i) {
+ FUNC(4,i);
+ }
+#endif /* !UNROLL_LOOPS */
+ sha_info->digest[0] += A;
+ sha_info->digest[1] += B;
+ sha_info->digest[2] += C;
+ sha_info->digest[3] += D;
+ sha_info->digest[4] += E;
+}
+
+union endianTest {
+ long Long;
+ char Char[sizeof(long)];
+};
+
+static char isLittleEndian(void)
+{
+ static union endianTest u;
+ u.Long = 1;
+ return (u.Char[0] == 1);
+}
+
+/* change endianness of data */
+
+/* count is the number of bytes to do an endian flip */
+static void maybe_byte_reverse(apr_uint32_t *buffer, int count)
+{
+ int i;
+ apr_byte_t ct[4], *cp;
+
+ if (isLittleEndian()) { /* do the swap only if it is little endian */
+ count /= sizeof(apr_uint32_t);
+ cp = (apr_byte_t *) buffer;
+ for (i = 0; i < count; ++i) {
+ ct[0] = cp[0];
+ ct[1] = cp[1];
+ ct[2] = cp[2];
+ ct[3] = cp[3];
+ cp[0] = ct[3];
+ cp[1] = ct[2];
+ cp[2] = ct[1];
+ cp[3] = ct[0];
+ cp += sizeof(apr_uint32_t);
+ }
+ }
+}
+
+/* initialize the SHA digest */
+
+APU_DECLARE(void) apr_sha1_init(apr_sha1_ctx_t *sha_info)
+{
+ sha_info->digest[0] = 0x67452301L;
+ sha_info->digest[1] = 0xefcdab89L;
+ sha_info->digest[2] = 0x98badcfeL;
+ sha_info->digest[3] = 0x10325476L;
+ sha_info->digest[4] = 0xc3d2e1f0L;
+ sha_info->count_lo = 0L;
+ sha_info->count_hi = 0L;
+ sha_info->local = 0;
+}
+
+/* update the SHA digest */
+
+APU_DECLARE(void) apr_sha1_update_binary(apr_sha1_ctx_t *sha_info,
+ const unsigned char *buffer,
+ unsigned int count)
+{
+ unsigned int i;
+
+ if ((sha_info->count_lo + ((apr_uint32_t) count << 3)) < sha_info->count_lo) {
+ ++sha_info->count_hi;
+ }
+ sha_info->count_lo += (apr_uint32_t) count << 3;
+ sha_info->count_hi += (apr_uint32_t) count >> 29;
+ if (sha_info->local) {
+ i = SHA_BLOCKSIZE - sha_info->local;
+ if (i > count) {
+ i = count;
+ }
+ memcpy(((apr_byte_t *) sha_info->data) + sha_info->local, buffer, i);
+ count -= i;
+ buffer += i;
+ sha_info->local += i;
+ if (sha_info->local == SHA_BLOCKSIZE) {
+ maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
+ sha_transform(sha_info);
+ }
+ else {
+ return;
+ }
+ }
+ while (count >= SHA_BLOCKSIZE) {
+ memcpy(sha_info->data, buffer, SHA_BLOCKSIZE);
+ buffer += SHA_BLOCKSIZE;
+ count -= SHA_BLOCKSIZE;
+ maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
+ sha_transform(sha_info);
+ }
+ memcpy(sha_info->data, buffer, count);
+ sha_info->local = count;
+}
+
+APU_DECLARE(void) apr_sha1_update(apr_sha1_ctx_t *sha_info, const char *buf,
+ unsigned int count)
+{
+#if APR_CHARSET_EBCDIC
+ int i;
+ const apr_byte_t *buffer = (const apr_byte_t *) buf;
+ apr_size_t inbytes_left, outbytes_left;
+
+ if ((sha_info->count_lo + ((apr_uint32_t) count << 3)) < sha_info->count_lo) {
+ ++sha_info->count_hi;
+ }
+ sha_info->count_lo += (apr_uint32_t) count << 3;
+ sha_info->count_hi += (apr_uint32_t) count >> 29;
+ /* Is there a remainder of the previous Update operation? */
+ if (sha_info->local) {
+ i = SHA_BLOCKSIZE - sha_info->local;
+ if (i > count) {
+ i = count;
+ }
+ inbytes_left = outbytes_left = i;
+ apr_xlate_conv_buffer(ebcdic2ascii_xlate, buffer, &inbytes_left,
+ ((apr_byte_t *) sha_info->data) + sha_info->local,
+ &outbytes_left);
+ count -= i;
+ buffer += i;
+ sha_info->local += i;
+ if (sha_info->local == SHA_BLOCKSIZE) {
+ maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
+ sha_transform(sha_info);
+ }
+ else {
+ return;
+ }
+ }
+ while (count >= SHA_BLOCKSIZE) {
+ inbytes_left = outbytes_left = SHA_BLOCKSIZE;
+ apr_xlate_conv_buffer(ebcdic2ascii_xlate, buffer, &inbytes_left,
+ (apr_byte_t *) sha_info->data, &outbytes_left);
+ buffer += SHA_BLOCKSIZE;
+ count -= SHA_BLOCKSIZE;
+ maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
+ sha_transform(sha_info);
+ }
+ inbytes_left = outbytes_left = count;
+ apr_xlate_conv_buffer(ebcdic2ascii_xlate, buffer, &inbytes_left,
+ (apr_byte_t *) sha_info->data, &outbytes_left);
+ sha_info->local = count;
+#else
+ apr_sha1_update_binary(sha_info, (const unsigned char *) buf, count);
+#endif
+}
+
+/* finish computing the SHA digest */
+
+APU_DECLARE(void) apr_sha1_final(unsigned char digest[APR_SHA1_DIGESTSIZE],
+ apr_sha1_ctx_t *sha_info)
+{
+ int count, i, j;
+ apr_uint32_t lo_bit_count, hi_bit_count, k;
+
+ lo_bit_count = sha_info->count_lo;
+ hi_bit_count = sha_info->count_hi;
+ count = (int) ((lo_bit_count >> 3) & 0x3f);
+ ((apr_byte_t *) sha_info->data)[count++] = 0x80;
+ if (count > SHA_BLOCKSIZE - 8) {
+ memset(((apr_byte_t *) sha_info->data) + count, 0, SHA_BLOCKSIZE - count);
+ maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
+ sha_transform(sha_info);
+ memset((apr_byte_t *) sha_info->data, 0, SHA_BLOCKSIZE - 8);
+ }
+ else {
+ memset(((apr_byte_t *) sha_info->data) + count, 0,
+ SHA_BLOCKSIZE - 8 - count);
+ }
+ maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
+ sha_info->data[14] = hi_bit_count;
+ sha_info->data[15] = lo_bit_count;
+ sha_transform(sha_info);
+
+ for (i = 0, j = 0; j < APR_SHA1_DIGESTSIZE; i++) {
+ k = sha_info->digest[i];
+ digest[j++] = (unsigned char) ((k >> 24) & 0xff);
+ digest[j++] = (unsigned char) ((k >> 16) & 0xff);
+ digest[j++] = (unsigned char) ((k >> 8) & 0xff);
+ digest[j++] = (unsigned char) (k & 0xff);
+ }
+}
+
+
+APU_DECLARE(void) apr_sha1_base64(const char *clear, int len, char *out)
+{
+ int l;
+ apr_sha1_ctx_t context;
+ apr_byte_t digest[APR_SHA1_DIGESTSIZE];
+
+ if (strncmp(clear, APR_SHA1PW_ID, APR_SHA1PW_IDLEN) == 0) {
+ clear += APR_SHA1PW_IDLEN;
+ }
+
+ apr_sha1_init(&context);
+ apr_sha1_update(&context, clear, len);
+ apr_sha1_final(digest, &context);
+
+ /* private marker. */
+ apr_cpystrn(out, APR_SHA1PW_ID, APR_SHA1PW_IDLEN + 1);
+
+ /* SHA1 hash is always 20 chars */
+ l = apr_base64_encode_binary(out + APR_SHA1PW_IDLEN, digest, sizeof(digest));
+ out[l + APR_SHA1PW_IDLEN] = '\0';
+
+ /*
+ * output of base64 encoded SHA1 is always 28 chars + APR_SHA1PW_IDLEN
+ */
+}
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This attempts to generate V1 UUIDs according to the Internet Draft
+ * located at http://www.webdav.org/specs/draft-leach-uuids-guids-01.txt
+ */
+#include "apr.h"
+#include "apr_uuid.h"
+#include "apr_md5.h"
+#include "apr_general.h"
+#include "apr_portable.h"
+
+
+#if APR_HAVE_UNISTD_H
+#include <unistd.h> /* for getpid, gethostname */
+#endif
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h> /* for rand, srand */
+#endif
+
+
+#if APR_HAVE_STRING_H
+#include <string.h>
+#endif
+#if APR_HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#if APR_HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#if APR_HAVE_SYS_TIME_H
+#include <sys/time.h> /* for gettimeofday */
+#endif
+
+#define NODE_LENGTH 6
+
+static int uuid_state_seqnum;
+static unsigned char uuid_state_node[NODE_LENGTH] = { 0 };
+
+
+static void get_random_info(unsigned char node[NODE_LENGTH])
+{
+#if APR_HAS_RANDOM
+
+ (void) apr_generate_random_bytes(node, NODE_LENGTH);
+
+#else
+
+ unsigned char seed[APR_MD5_DIGESTSIZE];
+ apr_md5_ctx_t c;
+
+ /* ### probably should revise some of this to be a bit more portable */
+
+ /* Leach & Salz use Linux-specific struct sysinfo;
+ * replace with pid/tid for portability (in the spirit of mod_unique_id) */
+ struct {
+ /* Add thread id here, if applicable, when we get to pthread or apr */
+ pid_t pid;
+#ifdef NETWARE
+ apr_uint64_t t;
+#else
+ struct timeval t;
+#endif
+ char hostname[257];
+
+ } r;
+
+ apr_md5_init(&c);
+#ifdef NETWARE
+ r.pid = NXThreadGetId();
+ NXGetTime(NX_SINCE_BOOT, NX_USECONDS, &(r.t));
+#else
+ r.pid = getpid();
+ gettimeofday(&r.t, (struct timezone *)0);
+#endif
+ gethostname(r.hostname, 256);
+ apr_md5_update(&c, (const unsigned char *)&r, sizeof(r));
+ apr_md5_final(seed, &c);
+
+ memcpy(node, seed, NODE_LENGTH); /* use a subset of the seed bytes */
+#endif
+}
+
+/* This implementation generates a random node ID instead of a
+ system-dependent call to get IEEE node ID. This is also more secure:
+ we aren't passing out our MAC address.
+*/
+static void get_pseudo_node_identifier(unsigned char *node)
+{
+ get_random_info(node);
+ node[0] |= 0x01; /* this designates a random node ID */
+}
+
+static void get_system_time(apr_uint64_t *uuid_time)
+{
+ /* ### fix this call to be more portable? */
+ *uuid_time = apr_time_now();
+
+ /* Offset between UUID formatted times and Unix formatted times.
+ UUID UTC base time is October 15, 1582.
+ Unix base time is January 1, 1970. */
+ *uuid_time = (*uuid_time * 10) + APR_TIME_C(0x01B21DD213814000);
+}
+
+/* true_random -- generate a crypto-quality random number. */
+static int true_random(void)
+{
+ apr_uint64_t time_now;
+
+#if APR_HAS_RANDOM
+ unsigned char buf[2];
+
+ if (apr_generate_random_bytes(buf, 2) == APR_SUCCESS) {
+ return (buf[0] << 8) | buf[1];
+ }
+#endif
+
+ /* crap. this isn't crypto quality, but it will be Good Enough */
+
+ get_system_time(&time_now);
+ srand((unsigned int)(((time_now >> 32) ^ time_now) & 0xffffffff));
+
+ return rand() & 0x0FFFF;
+}
+
+static void init_state(void)
+{
+ uuid_state_seqnum = true_random();
+ get_pseudo_node_identifier(uuid_state_node);
+}
+
+static void get_current_time(apr_uint64_t *timestamp)
+{
+ /* ### this needs to be made thread-safe! */
+
+ apr_time_t time_now;
+ static apr_interval_time_t time_last = 0;
+ static apr_interval_time_t fudge = 0;
+
+ time_now = apr_time_now();
+
+ /* if clock reading changed since last UUID generated... */
+ if (time_last != time_now) {
+ /* The clock reading has changed since the last UUID was generated.
+ Reset the fudge factor. if we are generating them too fast, then
+ the fudge may need to be reset to something greater than zero. */
+ if (time_last + fudge > time_now)
+ fudge = time_last + fudge - time_now + 1;
+ else
+ fudge = 0;
+ time_last = time_now;
+ }
+ else {
+ /* We generated two really fast. Bump the fudge factor. */
+ ++fudge;
+ }
+
+ *timestamp = time_now + fudge;
+}
+
+APU_DECLARE(void) apr_uuid_get(apr_uuid_t *uuid)
+{
+ apr_uint64_t timestamp;
+ unsigned char *d = uuid->data;
+
+#if APR_HAS_OS_UUID
+ if (apr_os_uuid_get(d) == APR_SUCCESS) {
+ return;
+ }
+#endif /* !APR_HAS_OS_UUID */
+
+ if (!uuid_state_node[0])
+ init_state();
+
+ get_current_time(×tamp);
+
+ d[0] = (unsigned char)timestamp;
+ d[1] = (unsigned char)(timestamp >> 8);
+ d[2] = (unsigned char)(timestamp >> 16);
+ d[3] = (unsigned char)(timestamp >> 24);
+ d[4] = (unsigned char)(timestamp >> 32);
+ d[5] = (unsigned char)(timestamp >> 40);
+ d[6] = (unsigned char)(timestamp >> 48);
+ d[7] = (unsigned char)(((timestamp >> 56) & 0x0F) | 0x10);
+
+ d[8] = (unsigned char)(((uuid_state_seqnum >> 8) & 0x3F) | 0x80);
+ d[9] = (unsigned char)uuid_state_seqnum;
+
+ memcpy(&d[10], uuid_state_node, NODE_LENGTH);
+}
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h> /* for sprintf */
+
+#include "apr.h"
+#include "apr_uuid.h"
+#include "apr_errno.h"
+#include "apr_lib.h"
+
+
+APU_DECLARE(void) apr_uuid_format(char *buffer, const apr_uuid_t *uuid)
+{
+ const unsigned char *d = uuid->data;
+
+ sprintf(buffer,
+ "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7],
+ d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
+}
+
+/* convert a pair of hex digits to an integer value [0,255] */
+#if 'A' == 65
+static unsigned char parse_hexpair(const char *s)
+{
+ int result;
+ int temp;
+
+ result = s[0] - '0';
+ if (result > 48)
+ result = (result - 39) << 4;
+ else if (result > 16)
+ result = (result - 7) << 4;
+ else
+ result = result << 4;
+
+ temp = s[1] - '0';
+ if (temp > 48)
+ result |= temp - 39;
+ else if (temp > 16)
+ result |= temp - 7;
+ else
+ result |= temp;
+
+ return (unsigned char)result;
+}
+#else
+static unsigned char parse_hexpair(const char *s)
+{
+ int result;
+
+ if (isdigit(*s)) {
+ result = (*s - '0') << 4;
+ }
+ else {
+ if (isupper(*s)) {
+ result = (*s - 'A' + 10) << 4;
+ }
+ else {
+ result = (*s - 'a' + 10) << 4;
+ }
+ }
+
+ ++s;
+ if (isdigit(*s)) {
+ result |= (*s - '0');
+ }
+ else {
+ if (isupper(*s)) {
+ result |= (*s - 'A' + 10);
+ }
+ else {
+ result |= (*s - 'a' + 10);
+ }
+ }
+
+ return (unsigned char)result;
+}
+#endif
+
+APU_DECLARE(apr_status_t) apr_uuid_parse(apr_uuid_t *uuid,
+ const char *uuid_str)
+{
+ int i;
+ unsigned char *d = uuid->data;
+
+ for (i = 0; i < 36; ++i) {
+ char c = uuid_str[i];
+ if (!apr_isxdigit(c) &&
+ !(c == '-' && (i == 8 || i == 13 || i == 18 || i == 23)))
+ /* ### need a better value */
+ return APR_BADARG;
+ }
+ if (uuid_str[36] != '\0') {
+ /* ### need a better value */
+ return APR_BADARG;
+ }
+
+ d[0] = parse_hexpair(&uuid_str[0]);
+ d[1] = parse_hexpair(&uuid_str[2]);
+ d[2] = parse_hexpair(&uuid_str[4]);
+ d[3] = parse_hexpair(&uuid_str[6]);
+
+ d[4] = parse_hexpair(&uuid_str[9]);
+ d[5] = parse_hexpair(&uuid_str[11]);
+
+ d[6] = parse_hexpair(&uuid_str[14]);
+ d[7] = parse_hexpair(&uuid_str[16]);
+
+ d[8] = parse_hexpair(&uuid_str[19]);
+ d[9] = parse_hexpair(&uuid_str[21]);
+
+ for (i = 6; i--;)
+ d[10 + i] = parse_hexpair(&uuid_str[i*2+24]);
+
+ return APR_SUCCESS;
+}
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+
+#include "apu.h"
+#include "apr_pools.h"
+#include "apr_dbd.h"
+#include "apr_hash.h"
+#include "apr_thread_mutex.h"
+#include "apr_dso.h"
+#include "apr_strings.h"
+
+static apr_hash_t *drivers = NULL;
+
+
+/* Once the autofoo supports building it for dynamic load, we can use
+ * #define APR_DSO_BUILD APR_HAS_DSO
+ */
+
+#if APR_DSO_BUILD
+#if APR_HAS_THREADS
+static apr_thread_mutex_t* mutex = NULL;
+#endif
+#else
+#define DRIVER_LOAD(name,driver,pool) \
+ { \
+ extern apr_dbd_driver_t driver; \
+ apr_hash_set(drivers,name,APR_HASH_KEY_STRING,&driver); \
+ if (driver.init) { \
+ driver.init(pool); \
+ } \
+ }
+#endif
+
+APU_DECLARE(apr_status_t) apr_dbd_init(apr_pool_t *pool)
+{
+ apr_status_t ret;
+ drivers = apr_hash_make(pool);
+
+#if APR_DSO_BUILD
+
+#if APR_HAS_THREADS
+ ret = apr_thread_mutex_create(&mutex, APR_THREAD_MUTEX_DEFAULT, pool);
+ apr_pool_cleanup_register(pool, mutex, (void*)apr_thread_mutex_destroy,
+ apr_pool_cleanup_null);
+#endif
+
+#else
+ ret = APR_SUCCESS;
+
+#if APU_HAVE_MYSQL
+ DRIVER_LOAD("mysql", apr_dbd_mysql_driver, pool);
+#endif
+#if APU_HAVE_PGSQL
+ DRIVER_LOAD("pgsql", apr_dbd_pgsql_driver, pool);
+#endif
+#if APU_HAVE_SQLITE3
+ DRIVER_LOAD("sqlite3", apr_dbd_sqlite3_driver, pool);
+#endif
+#if APU_HAVE_SQLITE2
+ DRIVER_LOAD("sqlite2", apr_dbd_sqlite2_driver, pool);
+#endif
+#if APU_HAVE_SOME_OTHER_BACKEND
+ DRIVER_LOAD("firebird", apr_dbd_other_driver, pool);
+#endif
+#endif
+ return ret;
+}
+APU_DECLARE(apr_status_t) apr_dbd_get_driver(apr_pool_t *pool, const char *name,
+ apr_dbd_driver_t **driver)
+{
+#if APR_DSO_BUILD
+ char path[80];
+ apr_dso_handle_t *dlhandle = NULL;
+#endif
+ apr_status_t rv;
+
+ *driver = apr_hash_get(drivers, name, APR_HASH_KEY_STRING);
+ if (*driver) {
+ return APR_SUCCESS;
+ }
+
+#if APR_DSO_BUILD
+
+#if APR_HAS_THREADS
+ rv = apr_thread_mutex_lock(mutex);
+ if (rv != APR_SUCCESS) {
+ goto unlock;
+ }
+ *driver = apr_hash_get(drivers, name, APR_HASH_KEY_STRING);
+ if (*driver) {
+ goto unlock;
+ }
+#endif
+
+ sprintf(path, "apr_dbd_%s.so", name);
+ rv = apr_dso_load(&dlhandle, path, pool);
+ if (rv != APR_SUCCESS) { /* APR_EDSOOPEN */
+ goto unlock;
+ }
+ sprintf(path, "apr_dbd_%s_driver", name);
+ rv = apr_dso_sym((void*)driver, dlhandle, path);
+ if (rv != APR_SUCCESS) { /* APR_ESYMNOTFOUND */
+ apr_dso_unload(dlhandle);
+ goto unlock;
+ }
+ if ((*driver)->init) {
+ (*driver)->init(pool);
+ }
+ apr_hash_set(drivers, name, APR_HASH_KEY_STRING, *driver);
+
+unlock:
+#if APR_HAS_THREADS
+ apr_thread_mutex_unlock(mutex);
+#endif
+
+#else /* APR_DSO_BUILD - so if it wasn't already loaded, it's NOTIMPL */
+ rv = APR_ENOTIMPL;
+#endif
+
+ return rv;
+}
+APU_DECLARE(apr_status_t) apr_dbd_open(apr_dbd_driver_t *driver,
+ apr_pool_t *pool, const char *params,
+ apr_dbd_t **handle)
+{
+
+ *handle = driver->open(pool, params);
+ if (*handle == NULL) {
+ return APR_EGENERAL;
+ }
+ if (apr_dbd_check_conn(driver, pool, *handle) != APR_SUCCESS) {
+ apr_dbd_close(driver, *handle);
+ return APR_EGENERAL;
+ }
+ return APR_SUCCESS;
+}
+APU_DECLARE(int) apr_dbd_transaction_start(apr_dbd_driver_t *driver,
+ apr_pool_t *pool, apr_dbd_t *handle,
+ apr_dbd_transaction_t **trans)
+{
+ int ret = driver->start_transaction(pool, handle, trans);
+ if (*trans) {
+ apr_pool_cleanup_register(pool, *trans, (void*)driver->end_transaction,
+ apr_pool_cleanup_null);
+ }
+ return ret;
+}
+APU_DECLARE(int) apr_dbd_transaction_end(apr_dbd_driver_t *driver,
+ apr_pool_t *pool,
+ apr_dbd_transaction_t *trans)
+{
+ apr_pool_cleanup_kill(pool, trans, (void*)driver->end_transaction);
+ return driver->end_transaction(trans);
+}
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apu.h"
+
+#if APU_HAVE_PGSQL
+
+#include <ctype.h>
+#include <stdlib.h>
+
+#include <libpq-fe.h>
+
+#include "apr_strings.h"
+#include "apr_time.h"
+
+#define QUERY_MAX_ARGS 40
+
+typedef struct apr_dbd_t apr_dbd_t;
+
+typedef struct {
+ int errnum;
+ apr_dbd_t *handle;
+} apr_dbd_transaction_t;
+
+struct apr_dbd_t {
+ PGconn *conn;
+ apr_dbd_transaction_t *trans;
+};
+
+typedef struct {
+ int random;
+ PGconn *handle;
+ PGresult *res;
+ size_t ntuples;
+ size_t sz;
+ size_t index;
+} apr_dbd_results_t;
+
+typedef struct {
+ int n;
+ apr_dbd_results_t *res;
+} apr_dbd_row_t;
+
+typedef struct {
+ const char *name;
+ int prepared;
+} apr_dbd_prepared_t;
+
+#define dbd_pgsql_is_success(x) (((x) == PGRES_EMPTY_QUERY) \
+ || ((x) == PGRES_COMMAND_OK) \
+ || ((x) == PGRES_TUPLES_OK))
+
+#define APR_DBD_INTERNAL
+#include "apr_dbd.h"
+
+static int dbd_pgsql_select(apr_pool_t *pool, apr_dbd_t *sql,
+ apr_dbd_results_t **results,
+ const char *query, int seek)
+{
+ PGresult *res;
+ int ret;
+ if ( sql->trans && sql->trans->errnum ) {
+ return sql->trans->errnum;
+ }
+ if (seek) { /* synchronous query */
+ res = PQexec(sql->conn, query);
+ if (res) {
+ ret = PQresultStatus(res);
+ if (dbd_pgsql_is_success(ret)) {
+ ret = 0;
+ } else {
+ PQclear(res);
+ }
+ } else {
+ ret = PGRES_FATAL_ERROR;
+ }
+ if (ret != 0) {
+ if (sql->trans) {
+ sql->trans->errnum = ret;
+ }
+ return ret;
+ }
+ if (!*results) {
+ *results = apr_pcalloc(pool, sizeof(apr_dbd_results_t));
+ }
+ (*results)->res = res;
+ (*results)->ntuples = PQntuples(res);
+ (*results)->sz = PQnfields(res);
+ (*results)->random = seek;
+ apr_pool_cleanup_register(pool, res, (void*)PQclear,
+ apr_pool_cleanup_null);
+ }
+ else {
+ if (PQsendQuery(sql->conn, query) == 0) {
+ if (sql->trans) {
+ sql->trans->errnum = 1;
+ }
+ return 1;
+ }
+ if (*results == NULL) {
+ *results = apr_pcalloc(pool, sizeof(apr_dbd_results_t));
+ }
+ (*results)->random = seek;
+ (*results)->handle = sql->conn;
+ }
+ return 0;
+}
+
+static int dbd_pgsql_get_row(apr_pool_t *pool, apr_dbd_results_t *res,
+ apr_dbd_row_t **rowp, int rownum)
+{
+ apr_dbd_row_t *row = *rowp;
+ int sequential = ((rownum >= 0) && res->random) ? 0 : 1;
+
+ if (row == NULL) {
+ row = apr_palloc(pool, sizeof(apr_dbd_row_t));
+ *rowp = row;
+ row->res = res;
+ row->n = sequential ? 0 : rownum;
+ }
+ else {
+ if ( sequential ) {
+ ++row->n;
+ }
+ else {
+ row->n = rownum;
+ }
+ }
+
+ if (res->random) {
+ if (row->n >= res->ntuples) {
+ *rowp = NULL;
+ apr_pool_cleanup_kill(pool, res->res, (void*)PQclear);
+ PQclear(res->res);
+ res->res = NULL;
+ return -1;
+ }
+ }
+ else {
+ if (row->n >= res->ntuples) {
+ /* no data; we have to fetch some */
+ row->n -= res->ntuples;
+ if (res->res != NULL) {
+ PQclear(res->res);
+ }
+ res->res = PQgetResult(res->handle);
+ if (res->res) {
+ res->ntuples = PQntuples(res->res);
+ while (res->ntuples == 0) {
+ /* if we got an empty result, clear it, wait a mo, try
+ * again */
+ PQclear(res->res);
+ apr_sleep(100000); /* 0.1 secs */
+ res->res = PQgetResult(res->handle);
+ if (res->res) {
+ res->ntuples = PQntuples(res->res);
+ }
+ else {
+ return -1;
+ }
+ }
+ if (res->sz == 0) {
+ res->sz = PQnfields(res->res);
+ }
+ }
+ else {
+ return -1;
+ }
+ }
+ }
+ return 0;
+}
+
+static const char *dbd_pgsql_get_entry(const apr_dbd_row_t *row, int n)
+{
+ return PQgetvalue(row->res->res, row->n, n);
+}
+
+static const char *dbd_pgsql_error(apr_dbd_t *sql, int n)
+{
+ return PQerrorMessage(sql->conn);
+}
+
+static int dbd_pgsql_query(apr_dbd_t *sql, int *nrows, const char *query)
+{
+ PGresult *res;
+ int ret;
+ if (sql->trans && sql->trans->errnum) {
+ return sql->trans->errnum;
+ }
+ res = PQexec(sql->conn, query);
+ if (res) {
+ ret = PQresultStatus(res);
+ if (dbd_pgsql_is_success(ret)) {
+ /* ugh, making 0 return-success doesn't fit */
+ ret = 0;
+ }
+ *nrows = atoi(PQcmdTuples(res));
+ PQclear(res);
+ }
+ else {
+ ret = PGRES_FATAL_ERROR;
+ }
+ if (sql->trans) {
+ sql->trans->errnum = ret;
+ }
+ return ret;
+}
+
+static const char *dbd_pgsql_escape(apr_pool_t *pool, const char *arg,
+ apr_dbd_t *sql)
+{
+ size_t len = strlen(arg);
+ char *ret = apr_palloc(pool, len + 1);
+ PQescapeString(ret, arg, len);
+ return ret;
+}
+
+static int dbd_pgsql_prepare(apr_pool_t *pool, apr_dbd_t *sql,
+ const char *query, const char *label,
+ apr_dbd_prepared_t **statement)
+{
+ char *sqlcmd;
+ char *sqlptr;
+ size_t length;
+ size_t i = 0;
+ const char *args[QUERY_MAX_ARGS];
+ size_t alen;
+ int nargs = 0;
+ int ret;
+ PGresult *res;
+ char *pgquery;
+ char *pgptr;
+
+ if (!*statement) {
+ *statement = apr_palloc(pool, sizeof(apr_dbd_prepared_t));
+ }
+ /* Translate from apr_dbd to native query format */
+ for (sqlptr = (char*)query; *sqlptr; ++sqlptr) {
+ if ((sqlptr[0] == '%') && isalpha(sqlptr[1])) {
+ ++nargs;
+ }
+ }
+ length = strlen(query) + 1;
+ if (nargs > 8) {
+ length += nargs - 8;
+ }
+ pgptr = pgquery = apr_palloc(pool, length) ;
+
+ for (sqlptr = (char*)query; *sqlptr; ++sqlptr) {
+ if ((sqlptr[0] == '%') && isalpha(sqlptr[1])) {
+ *pgptr++ = '$';
+ if (i < 9) {
+ *pgptr++ = '1' + i;
+ }
+ else {
+ *pgptr++ = '0' + ((i+1)/10);
+ *pgptr++ = '0' + ((i+1)%10);
+ }
+ switch (*++sqlptr) {
+ case 'd':
+ args[i] = "integer";
+ break;
+ case 's':
+ args[i] = "varchar";
+ break;
+ default:
+ args[i] = "varchar";
+ break;
+ }
+ length += 1 + strlen(args[i]);
+ ++i;
+ }
+ else if ((sqlptr[0] == '%') && (sqlptr[1] == '%')) {
+ /* reduce %% to % */
+ *pgptr++ = *sqlptr++;
+ }
+ else {
+ *pgptr++ = *sqlptr;
+ }
+ }
+ *pgptr = 0;
+
+ if (!label) {
+ /* don't really prepare; use in execParams instead */
+ (*statement)->prepared = 0;
+ (*statement)->name = apr_pstrdup(pool, pgquery);
+ return 0;
+ }
+ (*statement)->name = apr_pstrdup(pool, label);
+
+ /* length of SQL query that prepares this statement */
+ length = 8 + strlen(label) + 2 + 4 + length + 1;
+ sqlcmd = apr_palloc(pool, length);
+ sqlptr = sqlcmd;
+ memcpy(sqlptr, "PREPARE ", 8);
+ sqlptr += 8;
+ length = strlen(label);
+ memcpy(sqlptr, label, length);
+ sqlptr += length;
+ if (nargs > 0) {
+ memcpy(sqlptr, " (",2);
+ sqlptr += 2;
+ for (i=0; i<nargs; ++i) {
+ alen = strlen(args[i]);
+ memcpy(sqlptr, args[i], alen);
+ sqlptr += alen;
+ *sqlptr++ = ',';
+ }
+ sqlptr[-1] = ')';
+ }
+ memcpy(sqlptr, " AS ", 4);
+ sqlptr += 4;
+ memcpy(sqlptr, pgquery, strlen(pgquery));
+ sqlptr += strlen(pgquery);
+ *sqlptr = 0;
+
+ res = PQexec(sql->conn, sqlcmd);
+ if ( res ) {
+ ret = PQresultStatus(res);
+ if (dbd_pgsql_is_success(ret)) {
+ ret = 0;
+ }
+ /* Hmmm, do we do this here or register it on the pool? */
+ PQclear(res);
+ }
+ else {
+ ret = PGRES_FATAL_ERROR;
+ }
+ (*statement)->prepared = 1;
+
+ return ret;
+}
+
+static int dbd_pgsql_pquery(apr_pool_t *pool, apr_dbd_t *sql,
+ int *nrows, apr_dbd_prepared_t *statement,
+ int nargs, const char **values)
+{
+ int ret;
+ PGresult *res;
+ if (statement->prepared) {
+ res = PQexecPrepared(sql->conn, statement->name, nargs, values, 0, 0,
+ 0);
+ }
+ else {
+ res = PQexecParams(sql->conn, statement->name, nargs, 0, values, 0, 0,
+ 0);
+ }
+ if (res) {
+ ret = PQresultStatus(res);
+ if (dbd_pgsql_is_success(ret)) {
+ ret = 0;
+ }
+ PQclear(res);
+ }
+ else {
+ ret = PGRES_FATAL_ERROR;
+ }
+
+ if (sql->trans) {
+ sql->trans->errnum = ret;
+ }
+ return ret;
+}
+
+static int dbd_pgsql_pvquery(apr_pool_t *pool, apr_dbd_t *sql,
+ int *nrows, apr_dbd_prepared_t *statement, ...)
+{
+ const char *arg;
+ int nargs = 0;
+ va_list args;
+ const char *values[QUERY_MAX_ARGS];
+
+ if (sql->trans && sql->trans->errnum) {
+ return sql->trans->errnum;
+ }
+ va_start(args, statement);
+ while ( arg = va_arg(args, const char*), arg ) {
+ if ( nargs >= QUERY_MAX_ARGS) {
+ va_end(args);
+ return -1;
+ }
+ values[nargs++] = apr_pstrdup(pool, arg);
+ }
+ va_end(args);
+ values[nargs] = NULL;
+ return dbd_pgsql_pquery(pool, sql, nrows, statement, nargs, values);
+}
+
+static int dbd_pgsql_pselect(apr_pool_t *pool, apr_dbd_t *sql,
+ apr_dbd_results_t **results,
+ apr_dbd_prepared_t *statement,
+ int seek, int nargs, const char **values)
+{
+ PGresult *res;
+ int rv;
+ int ret = 0;
+ if (seek) { /* synchronous query */
+ if (statement->prepared) {
+ res = PQexecPrepared(sql->conn, statement->name, nargs, values, 0,
+ 0, 0);
+ }
+ else {
+ res = PQexecParams(sql->conn, statement->name, nargs, 0, values, 0,
+ 0, 0);
+ }
+ if (res) {
+ ret = PQresultStatus(res);
+ if (dbd_pgsql_is_success(ret)) {
+ ret = 0;
+ }
+ else {
+ PQclear(res);
+ }
+ }
+ else {
+ ret = PGRES_FATAL_ERROR;
+ }
+ if (ret != 0) {
+ if (sql->trans) {
+ sql->trans->errnum = ret;
+ }
+ return ret;
+ }
+ if (!*results) {
+ *results = apr_pcalloc(pool, sizeof(apr_dbd_results_t));
+ }
+ (*results)->res = res;
+ (*results)->ntuples = PQntuples(res);
+ (*results)->sz = PQnfields(res);
+ (*results)->random = seek;
+ apr_pool_cleanup_register(pool, res, (void*)PQclear,
+ apr_pool_cleanup_null);
+ }
+ else {
+ if (statement->prepared) {
+ rv = PQsendQueryPrepared(sql->conn, statement->name, nargs, values,
+ 0, 0, 0);
+ }
+ else {
+ rv = PQsendQueryParams(sql->conn, statement->name, nargs, 0,
+ values, 0, 0, 0);
+ }
+ if (rv == 0) {
+ if (sql->trans) {
+ sql->trans->errnum = 1;
+ }
+ return 1;
+ }
+ if (!*results) {
+ *results = apr_pcalloc(pool, sizeof(apr_dbd_results_t));
+ }
+ (*results)->random = seek;
+ (*results)->handle = sql->conn;
+ }
+
+ if (sql->trans) {
+ sql->trans->errnum = ret;
+ }
+ return ret;
+}
+
+static int dbd_pgsql_pvselect(apr_pool_t *pool, apr_dbd_t *sql,
+ apr_dbd_results_t **results,
+ apr_dbd_prepared_t *statement,
+ int seek, ...)
+{
+ const char *arg;
+ int nargs = 0;
+ va_list args;
+ const char *values[QUERY_MAX_ARGS];
+
+ if (sql->trans && sql->trans->errnum) {
+ return sql->trans->errnum;
+ }
+
+ va_start(args, seek);
+ while (arg = va_arg(args, const char*), arg) {
+ if ( nargs >= QUERY_MAX_ARGS) {
+ va_end(args);
+ return -1;
+ }
+ values[nargs++] = apr_pstrdup(pool, arg);
+ }
+ va_end(args);
+ return dbd_pgsql_pselect(pool, sql, results, statement,
+ seek, nargs, values) ;
+}
+
+static int dbd_pgsql_start_transaction(apr_pool_t *pool, apr_dbd_t *handle,
+ apr_dbd_transaction_t **trans)
+{
+ int ret = 0;
+ PGresult *res;
+
+ /* XXX handle recursive transactions here */
+
+ res = PQexec(handle->conn, "BEGIN TRANSACTION");
+ if (res) {
+ ret = PQresultStatus(res);
+ if (dbd_pgsql_is_success(ret)) {
+ ret = 0;
+ if (!*trans) {
+ *trans = apr_pcalloc(pool, sizeof(apr_dbd_transaction_t));
+ }
+ }
+ PQclear(res);
+ (*trans)->handle = handle;
+ handle->trans = *trans;
+ }
+ else {
+ ret = PGRES_FATAL_ERROR;
+ }
+ return ret;
+}
+
+static int dbd_pgsql_end_transaction(apr_dbd_transaction_t *trans)
+{
+ PGresult *res;
+ int ret = -1; /* no transaction is an error cond */
+ if (trans) {
+ if (trans->errnum) {
+ trans->errnum = 0;
+ res = PQexec(trans->handle->conn, "ROLLBACK");
+ }
+ else {
+ res = PQexec(trans->handle->conn, "COMMIT");
+ }
+ if (res) {
+ ret = PQresultStatus(res);
+ if (dbd_pgsql_is_success(ret)) {
+ ret = 0;
+ }
+ PQclear(res);
+ }
+ else {
+ ret = PGRES_FATAL_ERROR;
+ }
+ trans->handle->trans = NULL;
+ }
+ return ret;
+}
+
+static apr_dbd_t *dbd_pgsql_open(apr_pool_t *pool, const char *params)
+{
+ apr_dbd_t *sql;
+
+ PGconn *conn = PQconnectdb(params);
+
+ /* if there's an error in the connect string or something we get
+ * back a * bogus connection object, and things like PQreset are
+ * liable to segfault, so just close it out now. it would be nice
+ * if we could give an indication of why we failed to connect... */
+ if (PQstatus(conn) != CONNECTION_OK) {
+ PQfinish(conn);
+ return NULL;
+ }
+
+ sql = apr_pcalloc (pool, sizeof (*sql));
+
+ sql->conn = conn;
+
+ return sql;
+}
+
+static apr_status_t dbd_pgsql_close(apr_dbd_t *handle)
+{
+ PQfinish(handle->conn);
+ return APR_SUCCESS;
+}
+
+static apr_status_t dbd_pgsql_check_conn(apr_pool_t *pool,
+ apr_dbd_t *handle)
+{
+ if (PQstatus(handle->conn) != CONNECTION_OK) {
+ PQreset(handle->conn);
+ if (PQstatus(handle->conn) != CONNECTION_OK) {
+ return APR_EGENERAL;
+ }
+ }
+ return APR_SUCCESS;
+}
+
+static int dbd_pgsql_select_db(apr_pool_t *pool, apr_dbd_t *handle,
+ const char *name)
+{
+ return APR_ENOTIMPL;
+}
+
+static void *dbd_pgsql_native(apr_dbd_t *handle)
+{
+ return handle->conn;
+}
+
+static int dbd_pgsql_num_cols(apr_dbd_results_t* res)
+{
+ return res->sz;
+}
+
+static int dbd_pgsql_num_tuples(apr_dbd_results_t* res)
+{
+ if (res->random) {
+ return res->ntuples;
+ }
+ else {
+ return -1;
+ }
+}
+
+APU_DECLARE_DATA const apr_dbd_driver_t apr_dbd_pgsql_driver = {
+ "pgsql",
+ NULL,
+ dbd_pgsql_native,
+ dbd_pgsql_open,
+ dbd_pgsql_check_conn,
+ dbd_pgsql_close,
+ dbd_pgsql_select_db,
+ dbd_pgsql_start_transaction,
+ dbd_pgsql_end_transaction,
+ dbd_pgsql_query,
+ dbd_pgsql_select,
+ dbd_pgsql_num_cols,
+ dbd_pgsql_num_tuples,
+ dbd_pgsql_get_row,
+ dbd_pgsql_get_entry,
+ dbd_pgsql_error,
+ dbd_pgsql_escape,
+ dbd_pgsql_prepare,
+ dbd_pgsql_pvquery,
+ dbd_pgsql_pvselect,
+ dbd_pgsql_pquery,
+ dbd_pgsql_pselect,
+};
+#endif
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apu.h"
+
+#if APU_HAVE_SQLITE2
+
+#include <ctype.h>
+#include <stdlib.h>
+
+#include <sqlite.h>
+
+#include "apr_strings.h"
+#include "apr_time.h"
+
+typedef struct apr_dbd_t apr_dbd_t;
+
+typedef struct
+{
+ int errnum;
+ apr_dbd_t *handle;
+} apr_dbd_transaction_t;
+
+struct apr_dbd_t
+{
+ sqlite *conn;
+ char *errmsg;
+ apr_dbd_transaction_t *trans;
+};
+
+typedef struct
+{
+ int random;
+ sqlite *handle;
+ char **res;
+ size_t ntuples;
+ size_t sz;
+ size_t index;
+} apr_dbd_results_t;
+
+typedef struct
+{
+ int n;
+ char **data;
+ apr_dbd_results_t *res;
+} apr_dbd_row_t;
+
+typedef struct
+{
+ const char *name;
+ int prepared;
+} apr_dbd_prepared_t;
+
+#define APR_DBD_INTERNAL
+#include "apr_dbd.h"
+
+#define FREE_ERROR_MSG(dbd) \
+ do { \
+ if(dbd && dbd->errmsg) { \
+ free(dbd->errmsg); \
+ dbd->errmsg = NULL; \
+ } \
+ } while(0);
+
+
+static int dbd_sqlite_select(apr_pool_t * pool, apr_dbd_t * sql,
+ apr_dbd_results_t ** results, const char *query,
+ int seek)
+{
+ char **result;
+ int ret = 0;
+ int tuples = 0;
+ int fields = 0;
+
+ if (sql->trans && sql->trans->errnum) {
+ return sql->trans->errnum;
+ }
+
+ FREE_ERROR_MSG(sql);
+
+ ret = sqlite_get_table(sql->conn, query, &result, &tuples, &fields,
+ &sql->errmsg);
+
+ if (ret == SQLITE_OK) {
+ if (!*results) {
+ *results = apr_pcalloc(pool, sizeof(apr_dbd_results_t));
+ }
+
+ (*results)->res = result;
+ if (seek) {
+ (*results)->ntuples = tuples;
+ }
+ else {
+ (*results)->ntuples = -1;
+ }
+ (*results)->sz = fields;
+ (*results)->random = seek;
+
+ if (tuples > 0)
+ apr_pool_cleanup_register(pool, result, (void *) free,
+ apr_pool_cleanup_null);
+
+ ret = 0;
+ }
+ else {
+ sql->trans->errnum = ret;
+ }
+
+ return ret;
+}
+
+static int dbd_sqlite_get_row(apr_pool_t * pool, apr_dbd_results_t * res,
+ apr_dbd_row_t ** rowp, int rownum)
+{
+ apr_dbd_row_t *row = *rowp;
+ int sequential = ((rownum >= 0) && res->random) ? 0 : 1;
+
+ if (row == NULL) {
+ row = apr_palloc(pool, sizeof(apr_dbd_row_t));
+ *rowp = row;
+ row->res = res;
+ row->n = sequential ? 0 : rownum - 1;
+ }
+ else {
+ if (sequential) {
+ ++row->n;
+ }
+ else {
+ row->n = rownum - 1;
+ }
+ }
+
+ if (row->n >= res->ntuples) {
+ *rowp = NULL;
+ apr_pool_cleanup_kill(pool, res->res, (void *) free);
+ res->res = NULL;
+ return -1;
+ }
+
+ /* Pointer magic explanation:
+ * The sqlite result is an array such that the first res->sz elements are
+ * the column names and each tuple follows afterwards
+ * ex: (from the sqlite2 documentation)
+ SELECT employee_name, login, host FROM users WHERE login LIKE * 'd%';
+
+ nrow = 2
+ ncolumn = 3
+ result[0] = "employee_name"
+ result[1] = "login"
+ result[2] = "host"
+ result[3] = "dummy"
+ result[4] = "No such user"
+ result[5] = 0
+ result[6] = "D. Richard Hipp"
+ result[7] = "drh"
+ result[8] = "zadok"
+ */
+
+ row->data = res->res + res->sz + (res->sz * row->n);
+
+ return 0;
+}
+
+static const char *dbd_sqlite_get_entry(const apr_dbd_row_t * row, int n)
+{
+ return row->data[n];
+}
+
+static const char *dbd_sqlite_error(apr_dbd_t * sql, int n)
+{
+ return sql->errmsg;
+}
+
+static int dbd_sqlite_query(apr_dbd_t * sql, int *nrows, const char *query)
+{
+ char **result;
+ int ret;
+ int tuples = 0;
+ int fields = 0;
+
+ if (sql->trans && sql->trans->errnum) {
+ return sql->trans->errnum;
+ }
+
+ FREE_ERROR_MSG(sql);
+
+ ret =
+ sqlite_get_table(sql->conn, query, &result, &tuples, &fields,
+ &sql->errmsg);
+ if (ret == SQLITE_OK) {
+ *nrows = sqlite_changes(sql->conn);
+
+ if (tuples > 0)
+ free(result);
+
+ ret = 0;
+ }
+
+ if (sql->trans) {
+ sql->trans->errnum = ret;
+ }
+
+ return ret;
+}
+
+static const char *dbd_sqlite_escape(apr_pool_t * pool, const char *arg,
+ apr_dbd_t * sql)
+{
+ char *ret = sqlite_mprintf(arg);
+ apr_pool_cleanup_register(pool, ret, (void *) sqlite_freemem,
+ apr_pool_cleanup_null);
+ return ret;
+}
+
+static int dbd_sqlite_prepare(apr_pool_t * pool, apr_dbd_t * sql,
+ const char *query, const char *label,
+ apr_dbd_prepared_t ** statement)
+{
+ return APR_ENOTIMPL;
+}
+
+static int dbd_sqlite_pquery(apr_pool_t * pool, apr_dbd_t * sql,
+ int *nrows, apr_dbd_prepared_t * statement,
+ int nargs, const char **values)
+{
+ return APR_ENOTIMPL;
+}
+
+static int dbd_sqlite_pvquery(apr_pool_t * pool, apr_dbd_t * sql,
+ int *nrows, apr_dbd_prepared_t * statement, ...)
+{
+ return APR_ENOTIMPL;
+}
+
+static int dbd_sqlite_pselect(apr_pool_t * pool, apr_dbd_t * sql,
+ apr_dbd_results_t ** results,
+ apr_dbd_prepared_t * statement,
+ int seek, int nargs, const char **values)
+{
+ return APR_ENOTIMPL;
+}
+
+static int dbd_sqlite_pvselect(apr_pool_t * pool, apr_dbd_t * sql,
+ apr_dbd_results_t ** results,
+ apr_dbd_prepared_t * statement, int seek, ...)
+{
+ return APR_ENOTIMPL;
+}
+
+static int dbd_sqlite_start_transaction(apr_pool_t * pool, apr_dbd_t * handle,
+ apr_dbd_transaction_t ** trans)
+{
+ int ret, rows;
+
+ ret = dbd_sqlite_query(handle, &rows, "BEGIN TRANSACTION");
+ if (ret == 0) {
+ if (!*trans) {
+ *trans = apr_pcalloc(pool, sizeof(apr_dbd_transaction_t));
+ }
+ (*trans)->handle = handle;
+ handle->trans = *trans;
+ }
+ else {
+ ret = -1;
+ }
+ return ret;
+}
+
+static int dbd_sqlite_end_transaction(apr_dbd_transaction_t * trans)
+{
+ int rows;
+ int ret = -1; /* no transaction is an error cond */
+
+ if (trans) {
+ if (trans->errnum) {
+ trans->errnum = 0;
+ ret =
+ dbd_sqlite_query(trans->handle, &rows,
+ "ROLLBACK TRANSACTION");
+ }
+ else {
+ ret =
+ dbd_sqlite_query(trans->handle, &rows, "COMMIT TRANSACTION");
+ }
+ trans->handle->trans = NULL;
+ }
+
+ return ret;
+}
+
+static apr_dbd_t *dbd_sqlite_open(apr_pool_t * pool, const char *params_)
+{
+ apr_dbd_t *sql;
+ sqlite *conn = NULL;
+ char *filename, *perm;
+ int iperms = 600;
+ char* params = apr_pstrdup(pool, params_);
+ /* params = "[filename]:[permissions]"
+ * example: "shopping.db:600"
+ */
+
+ perm = strstr(params, ":");
+ if (perm) {
+ *(perm++) = '\x00'; // split the filename and permissions
+
+ if (strlen(perm) > 0)
+ iperms = atoi(perm);
+ }
+
+ conn = sqlite_open(params, iperms, NULL);
+
+ sql = apr_pcalloc(pool, sizeof(*sql));
+ sql->conn = conn;
+
+ return sql;
+}
+
+static apr_status_t dbd_sqlite_close(apr_dbd_t * handle)
+{
+ if (handle->conn) {
+ sqlite_close(handle->conn);
+ handle->conn = NULL;
+ }
+ return APR_SUCCESS;
+}
+
+static apr_status_t dbd_sqlite_check_conn(apr_pool_t * pool,
+ apr_dbd_t * handle)
+{
+ if (handle->conn == NULL)
+ return -1;
+ return APR_SUCCESS;
+}
+
+static int dbd_sqlite_select_db(apr_pool_t * pool, apr_dbd_t * handle,
+ const char *name)
+{
+ return APR_ENOTIMPL;
+}
+
+static void *dbd_sqlite_native(apr_dbd_t * handle)
+{
+ return handle->conn;
+}
+
+static int dbd_sqlite_num_cols(apr_dbd_results_t * res)
+{
+ return res->sz;
+}
+
+static int dbd_sqlite_num_tuples(apr_dbd_results_t * res)
+{
+ return res->ntuples;
+}
+
+APU_DECLARE_DATA const apr_dbd_driver_t apr_dbd_sqlite2_driver = {
+ "sqlite2",
+ NULL,
+ dbd_sqlite_native,
+ dbd_sqlite_open,
+ dbd_sqlite_check_conn,
+ dbd_sqlite_close,
+ dbd_sqlite_select_db,
+ dbd_sqlite_start_transaction,
+ dbd_sqlite_end_transaction,
+ dbd_sqlite_query,
+ dbd_sqlite_select,
+ dbd_sqlite_num_cols,
+ dbd_sqlite_num_tuples,
+ dbd_sqlite_get_row,
+ dbd_sqlite_get_entry,
+ dbd_sqlite_error,
+ dbd_sqlite_escape,
+ dbd_sqlite_prepare,
+ dbd_sqlite_pvquery,
+ dbd_sqlite_pvselect,
+ dbd_sqlite_pquery,
+ dbd_sqlite_pselect,
+};
+#endif
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apu.h"
+
+#if APU_HAVE_SQLITE3
+
+#include <ctype.h>
+#include <stdlib.h>
+
+#include <sqlite3.h>
+
+#include "apr_strings.h"
+#include "apr_time.h"
+
+#define MAX_RETRY_COUNT 15
+#define MAX_RETRY_SLEEP 100000
+
+typedef struct apr_dbd_t apr_dbd_t;
+typedef struct apr_dbd_results_t apr_dbd_results_t;
+typedef struct apr_dbd_column_t apr_dbd_column_t;
+typedef struct apr_dbd_row_t apr_dbd_row_t;
+typedef struct {
+ int errnum;
+ apr_dbd_t *handle;
+} apr_dbd_transaction_t;
+
+struct apr_dbd_t {
+ sqlite3 *conn;
+ apr_dbd_transaction_t *trans;
+ apr_thread_mutex_t *mutex;
+ apr_pool_t *pool;
+};
+
+struct apr_dbd_row_t {
+ apr_dbd_results_t *res;
+ apr_dbd_column_t **columns;
+ apr_dbd_row_t *next_row;
+ int columnCount;
+ int rownum;
+};
+
+struct apr_dbd_column_t {
+ char *name;
+ char *value;
+ int size;
+ int type;
+};
+
+struct apr_dbd_results_t {
+ int random;
+ sqlite3 *handle;
+ sqlite3_stmt *stmt;
+ apr_dbd_row_t *next_row;
+ size_t sz;
+ int tuples;
+};
+
+
+
+typedef struct {
+ const char *name;
+ int prepared;
+} apr_dbd_prepared_t;
+
+#define dbd_sqlite3_is_success(x) (((x) == SQLITE_DONE ) \
+ || ((x) == SQLITE_OK ))
+
+#define APR_DBD_INTERNAL
+#include "apr_dbd.h"
+
+static int dbd_sqlite3_select(apr_pool_t * pool, apr_dbd_t * sql, apr_dbd_results_t ** results, const char *query, int seek)
+{
+ sqlite3_stmt *stmt = NULL;
+ const char *tail = NULL;
+ int i, ret, retry_count;
+ size_t num_tuples = 0;
+ int increment = 0;
+ apr_dbd_row_t *row = NULL;
+ apr_dbd_row_t *lastrow = NULL;
+ apr_dbd_column_t *column;
+
+ char *hold = NULL;
+
+ apr_thread_mutex_lock(sql->mutex);
+
+ ret = sqlite3_prepare(sql->conn, query, strlen(query), &stmt, &tail);
+ if (!dbd_sqlite3_is_success(ret)) {
+ apr_thread_mutex_unlock(sql->mutex);
+ return ret;
+ } else {
+ int column_count;
+ column_count = sqlite3_column_count(stmt);
+ if (!*results) {
+ *results = apr_pcalloc(pool, sizeof(apr_dbd_results_t));
+ }
+ (*results)->stmt = stmt;
+ (*results)->sz = column_count;
+ (*results)->random = seek;
+ (*results)->next_row = 0;
+ (*results)->tuples = 0;
+ do {
+ ret = sqlite3_step((*results)->stmt);
+ if (ret == SQLITE_BUSY) {
+ if (retry_count++ > MAX_RETRY_COUNT) {
+ ret = SQLITE_ERROR;
+ } else {
+ apr_thread_mutex_unlock(sql->mutex);
+ apr_sleep(MAX_RETRY_SLEEP);
+ }
+ } else if (ret == SQLITE_ROW) {
+ int length;
+ apr_dbd_column_t *col;
+ row = apr_palloc(pool, sizeof(apr_dbd_row_t));
+ row->res = *results;
+ row->res->stmt = (*results)->stmt;
+ increment = sizeof(apr_dbd_column_t *);
+ length = increment * (*results)->sz;
+ row->columns = apr_palloc(pool, length);
+ row->columnCount = column_count;
+ for (i = 0; i < (*results)->sz; i++) {
+ column = apr_palloc(pool, sizeof(apr_dbd_column_t));
+ row->columns[i] = column;
+ column->name = (char *) sqlite3_column_name((*results)->stmt, i);
+ column->size = sqlite3_column_bytes((*results)->stmt, i);
+ column->type = sqlite3_column_type((*results)->stmt, i);
+ switch (column->type) {
+
+ case SQLITE_FLOAT:
+ break;
+ case SQLITE_INTEGER:
+ case SQLITE_TEXT:
+ hold = NULL;
+ hold = (char *) sqlite3_column_text((*results)->stmt, i);
+ if (hold) {
+ column->value = apr_palloc(pool, column->size + 1);
+ strncpy(column->value, hold, column->size + 1);
+ }
+ break;
+ case SQLITE_BLOB:
+ break;
+ case SQLITE_NULL:
+ break;
+ }
+ col = row->columns[i];
+ }
+ row->rownum = num_tuples++;
+ row->next_row = 0;
+ (*results)->tuples = num_tuples;
+ if ((*results)->next_row == 0) {
+ (*results)->next_row = row;
+ }
+ if (lastrow != 0) {
+ lastrow->next_row = row;
+ }
+ lastrow = row;
+ } else if (ret == SQLITE_DONE) {
+ ret = SQLITE_OK;
+ }
+ } while (ret == SQLITE_ROW || ret == SQLITE_BUSY);
+ }
+ ret = sqlite3_finalize(stmt);
+ apr_thread_mutex_unlock(sql->mutex);
+ return ret;
+}
+
+static int dbd_sqlite3_get_row(apr_pool_t * pool, apr_dbd_results_t * res, apr_dbd_row_t ** rowp, int rownum)
+{
+ int ret, retry_count, i = 0;
+ apr_dbd_row_t *row;
+ if (rownum == -1) {
+ *rowp = res->next_row;
+ if (*rowp == 0)
+ return -1;
+ res->next_row = (*rowp)->next_row;
+ return 0;
+ }
+ if (rownum > res->tuples) {
+ return -1;
+ }
+ rownum--;
+ *rowp = res->next_row;
+ for (; *rowp != 0; i++, *rowp = (*rowp)->next_row) {
+ if (i == rownum) {
+ return 0;
+ }
+ }
+
+ return -1;
+
+}
+
+static const char *dbd_sqlite3_get_entry(const apr_dbd_row_t * row, int n)
+{
+ apr_dbd_column_t *column;
+ const char *value;
+ if ((n + 1) > row->columnCount) {
+ return NULL;
+ }
+ column = row->columns[n];
+ value = column->value;
+ return value;
+}
+
+static const char *dbd_sqlite3_error(apr_dbd_t * sql, int n)
+{
+ return sqlite3_errmsg(sql->conn);
+}
+
+static int dbd_sqlite3_query(apr_dbd_t * sql, int *nrows, const char *query)
+{
+ sqlite3_stmt *stmt = NULL;
+ const char *tail = NULL;
+ int ret, retry_count = 0, length = 0;
+ apr_status_t res;
+ apr_pool_t *pool;
+
+ res = apr_pool_create(&pool, sql->pool);
+ if (res != APR_SUCCESS) {
+ return SQLITE_ERROR;
+ }
+ length = strlen(query);
+ apr_thread_mutex_lock(sql->mutex);
+
+ do {
+ ret = sqlite3_prepare(sql->conn, query, length, &stmt, &tail);
+ if (ret != SQLITE_OK) {
+ sqlite3_finalize(stmt);
+ apr_thread_mutex_unlock(sql->mutex);
+ return ret;
+ }
+
+ ret = sqlite3_step(stmt);
+ *nrows = sqlite3_changes(sql->conn);
+ sqlite3_finalize(stmt);
+ length -= (tail - query);
+ query = tail;
+ } while (length > 0);
+
+ if (dbd_sqlite3_is_success(ret)) {
+ ret = 0;
+ }
+ apr_thread_mutex_unlock(sql->mutex);
+ apr_pool_destroy(pool);
+ return ret;
+}
+
+static const char *dbd_sqlite3_escape(apr_pool_t * pool, const char *arg, apr_dbd_t * sql)
+{
+ char *ret = sqlite3_mprintf(arg);
+ apr_pool_cleanup_register(pool, ret, (void *) sqlite3_free, apr_pool_cleanup_null);
+ return ret;
+}
+
+static int dbd_sqlite3_prepare(apr_pool_t * pool, apr_dbd_t * sql,
+ const char *query, const char *label, apr_dbd_prepared_t ** statement)
+{
+ return APR_ENOTIMPL;
+}
+
+static int dbd_sqlite3_pquery(apr_pool_t * pool, apr_dbd_t * sql,
+ int *nrows, apr_dbd_prepared_t * statement, int nargs, const char **values)
+{
+ return APR_ENOTIMPL;
+}
+
+static int dbd_sqlite3_pvquery(apr_pool_t * pool, apr_dbd_t * sql, int *nrows, apr_dbd_prepared_t * statement, ...)
+{
+ return APR_ENOTIMPL;
+}
+
+static int dbd_sqlite3_pselect(apr_pool_t * pool, apr_dbd_t * sql,
+ apr_dbd_results_t ** results,
+ apr_dbd_prepared_t * statement, int seek, int nargs, const char **values)
+{
+ return APR_ENOTIMPL;
+}
+
+static int dbd_sqlite3_pvselect(apr_pool_t * pool, apr_dbd_t * sql,
+ apr_dbd_results_t ** results, apr_dbd_prepared_t * statement, int seek, ...)
+{
+ return APR_ENOTIMPL;
+}
+
+static int dbd_sqlite3_start_transaction(apr_pool_t * pool, apr_dbd_t * handle, apr_dbd_transaction_t ** trans)
+{
+ int ret = 0;
+ int nrows = 0;
+
+ ret = dbd_sqlite3_query(handle, &nrows, "BEGIN TRANSACTION;");
+ if (!*trans) {
+ *trans = apr_pcalloc(pool, sizeof(apr_dbd_transaction_t));
+ (*trans)->handle = handle;
+ handle->trans = *trans;
+ }
+
+ return ret;
+}
+
+static int dbd_sqlite3_end_transaction(apr_dbd_transaction_t * trans)
+{
+ int ret = 0;
+ int nrows = 0;
+
+ if (trans) {
+ ret = dbd_sqlite3_query(trans->handle, &nrows, "END TRANSACTION;");
+ if (trans->errnum) {
+ trans->errnum = 0;
+ ret = dbd_sqlite3_query(trans->handle, &nrows, "ROLLBACK;");
+ } else {
+ ret = dbd_sqlite3_query(trans->handle, &nrows, "COMMIT;");
+ }
+ trans->handle->trans = NULL;
+ }
+
+ return ret;
+}
+
+static apr_dbd_t *dbd_sqlite3_open(apr_pool_t * pool, const char *params)
+{
+ apr_dbd_t *sql = NULL;
+ sqlite3 *conn = NULL;
+ apr_status_t res;
+ int sqlres;
+ if (!params)
+ return NULL;
+ sqlres = sqlite3_open(params, &conn);
+ if (sqlres != SQLITE_OK) {
+ sqlite3_close(conn);
+ return NULL;
+ }
+ /* should we register rand or power functions to the sqlite VM? */
+ sql = apr_pcalloc(pool, sizeof(*sql));
+ sql->conn = conn;
+ sql->pool = pool;
+ /* Create a mutex */
+ res = apr_thread_mutex_create(&sql->mutex, APR_THREAD_MUTEX_DEFAULT, pool);
+ if (res != APR_SUCCESS) {
+ return NULL;
+ }
+
+ return sql;
+}
+
+static apr_status_t dbd_sqlite3_close(apr_dbd_t * handle)
+{
+ sqlite3_close(handle->conn);
+ apr_thread_mutex_destroy(handle->mutex);
+ return APR_SUCCESS;
+}
+
+static apr_status_t dbd_sqlite3_check_conn(apr_pool_t * pool, apr_dbd_t * handle)
+{
+ return (handle->conn != NULL) ? APR_SUCCESS : APR_EGENERAL;
+}
+
+static int dbd_sqlite3_select_db(apr_pool_t * pool, apr_dbd_t * handle, const char *name)
+{
+ return APR_ENOTIMPL;
+}
+
+static void *dbd_sqlite3_native(apr_dbd_t * handle)
+{
+ return handle->conn;
+}
+
+static int dbd_sqlite3_num_cols(apr_dbd_results_t * res)
+{
+ return res->sz;
+}
+
+static int dbd_sqlite3_num_tuples(apr_dbd_results_t * res)
+{
+ return res->tuples;
+}
+
+APU_DECLARE_DATA const apr_dbd_driver_t apr_dbd_sqlite3_driver = {
+ "sqlite3",
+ NULL,
+ dbd_sqlite3_native,
+ dbd_sqlite3_open,
+ dbd_sqlite3_check_conn,
+ dbd_sqlite3_close,
+ dbd_sqlite3_select_db,
+ dbd_sqlite3_start_transaction,
+ dbd_sqlite3_end_transaction,
+ dbd_sqlite3_query,
+ dbd_sqlite3_select,
+ dbd_sqlite3_num_cols,
+ dbd_sqlite3_num_tuples,
+ dbd_sqlite3_get_row,
+ dbd_sqlite3_get_entry,
+ dbd_sqlite3_error,
+ dbd_sqlite3_escape,
+ dbd_sqlite3_prepare,
+ dbd_sqlite3_pvquery,
+ dbd_sqlite3_pvselect,
+ dbd_sqlite3_pquery,
+ dbd_sqlite3_pselect,
+};
+#endif
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_errno.h"
+#include "apr_pools.h"
+#include "apr_strings.h"
+#define APR_WANT_MEMFUNC
+#define APR_WANT_STRFUNC
+#include "apr_want.h"
+#include "apr_general.h"
+
+#include "apu.h"
+#include "apu_select_dbm.h"
+#include "apr_dbm.h"
+#include "apr_dbm_private.h"
+
+/* ### note: the setting of DBM_VTABLE will go away once we have multiple
+ ### DBMs in here.
+ ### Well, that day is here. So, do we remove DBM_VTABLE and the old
+ ### API entirely? Oh, what to do. We need an APU_DEFAULT_DBM #define.
+ ### Sounds like a job for autoconf. */
+
+#if APU_USE_SDBM
+#define DBM_VTABLE apr_dbm_type_sdbm
+#elif APU_USE_GDBM
+#define DBM_VTABLE apr_dbm_type_gdbm
+#elif APU_USE_DB
+#define DBM_VTABLE apr_dbm_type_db
+#elif APU_USE_NDBM
+#define DBM_VTABLE apr_dbm_type_ndbm
+#else /* Not in the USE_xDBM list above */
+#error a DBM implementation was not specified
+#endif
+
+APU_DECLARE(apr_status_t) apr_dbm_open_ex(apr_dbm_t **pdb, const char*type,
+ const char *pathname,
+ apr_int32_t mode, apr_fileperms_t perm,
+ apr_pool_t *pool)
+{
+#if APU_HAVE_GDBM
+ if (!strcasecmp(type, "GDBM")) {
+ return (*apr_dbm_type_gdbm.open)(pdb, pathname, mode, perm, pool);
+ }
+#endif
+#if APU_HAVE_SDBM
+ if (!strcasecmp(type, "SDBM")) {
+ return (*apr_dbm_type_sdbm.open)(pdb, pathname, mode, perm, pool);
+ }
+#endif
+#if APU_HAVE_DB
+ if (!strcasecmp(type, "DB")) {
+ return (*apr_dbm_type_db.open)(pdb, pathname, mode, perm, pool);
+ }
+#endif
+#if APU_HAVE_NDBM
+ if (!strcasecmp(type, "NDBM")) {
+ return (*apr_dbm_type_ndbm.open)(pdb, pathname, mode, perm, pool);
+ }
+#endif
+
+ if (!strcasecmp(type, "default")) {
+ return (*DBM_VTABLE.open)(pdb, pathname, mode, perm, pool);
+ }
+
+ return APR_ENOTIMPL;
+}
+
+APU_DECLARE(apr_status_t) apr_dbm_open(apr_dbm_t **pdb, const char *pathname,
+ apr_int32_t mode, apr_fileperms_t perm,
+ apr_pool_t *pool)
+{
+ return (*DBM_VTABLE.open)(pdb, pathname, mode, perm, pool);
+}
+
+APU_DECLARE(void) apr_dbm_close(apr_dbm_t *dbm)
+{
+ (*dbm->type->close)(dbm);
+}
+
+APU_DECLARE(apr_status_t) apr_dbm_fetch(apr_dbm_t *dbm, apr_datum_t key,
+ apr_datum_t *pvalue)
+{
+ return (*dbm->type->fetch)(dbm, key, pvalue);
+}
+
+APU_DECLARE(apr_status_t) apr_dbm_store(apr_dbm_t *dbm, apr_datum_t key,
+ apr_datum_t value)
+{
+ return (*dbm->type->store)(dbm, key, value);
+}
+
+APU_DECLARE(apr_status_t) apr_dbm_delete(apr_dbm_t *dbm, apr_datum_t key)
+{
+ return (*dbm->type->del)(dbm, key);
+}
+
+APU_DECLARE(int) apr_dbm_exists(apr_dbm_t *dbm, apr_datum_t key)
+{
+ return (*dbm->type->exists)(dbm, key);
+}
+
+APU_DECLARE(apr_status_t) apr_dbm_firstkey(apr_dbm_t *dbm, apr_datum_t *pkey)
+{
+ return (*dbm->type->firstkey)(dbm, pkey);
+}
+
+APU_DECLARE(apr_status_t) apr_dbm_nextkey(apr_dbm_t *dbm, apr_datum_t *pkey)
+{
+ return (*dbm->type->nextkey)(dbm, pkey);
+}
+
+APU_DECLARE(void) apr_dbm_freedatum(apr_dbm_t *dbm, apr_datum_t data)
+{
+ (*dbm->type->freedatum)(dbm, data);
+}
+
+APU_DECLARE(char *) apr_dbm_geterror(apr_dbm_t *dbm, int *errcode,
+ char *errbuf, apr_size_t errbufsize)
+{
+ if (errcode != NULL)
+ *errcode = dbm->errcode;
+
+ /* assert: errbufsize > 0 */
+
+ if (dbm->errmsg == NULL)
+ *errbuf = '\0';
+ else
+ (void) apr_cpystrn(errbuf, dbm->errmsg, errbufsize);
+ return errbuf;
+}
+
+APU_DECLARE(apr_status_t) apr_dbm_get_usednames_ex(apr_pool_t *p,
+ const char *type,
+ const char *pathname,
+ const char **used1,
+ const char **used2)
+{
+#if APU_HAVE_GDBM
+ if (!strcasecmp(type, "GDBM")) {
+ (*apr_dbm_type_gdbm.getusednames)(p,pathname,used1,used2);
+ return APR_SUCCESS;
+ }
+#endif
+#if APU_HAVE_SDBM
+ if (!strcasecmp(type, "SDBM")) {
+ (*apr_dbm_type_sdbm.getusednames)(p,pathname,used1,used2);
+ return APR_SUCCESS;
+ }
+#endif
+#if APU_HAVE_DB
+ if (!strcasecmp(type, "DB")) {
+ (*apr_dbm_type_db.getusednames)(p,pathname,used1,used2);
+ return APR_SUCCESS;
+ }
+#endif
+#if APU_HAVE_NDBM
+ if (!strcasecmp(type, "NDBM")) {
+ (*apr_dbm_type_ndbm.getusednames)(p,pathname,used1,used2);
+ return APR_SUCCESS;
+ }
+#endif
+
+ if (!strcasecmp(type, "default")) {
+ (*DBM_VTABLE.getusednames)(p, pathname, used1, used2);
+ return APR_SUCCESS;
+ }
+
+ return APR_ENOTIMPL;
+}
+
+APU_DECLARE(void) apr_dbm_get_usednames(apr_pool_t *p,
+ const char *pathname,
+ const char **used1,
+ const char **used2)
+{
+ /* ### one day, a DBM type name will be passed and we'll need to look it
+ ### up. for now, it is constant. */
+
+ (*DBM_VTABLE.getusednames)(p, pathname, used1, used2);
+}
+
+/* Most DBM libraries take a POSIX mode for creating files. Don't trust
+ * the mode_t type, some platforms may not support it, int is safe.
+ */
+APU_DECLARE(int) apr_posix_perms2mode(apr_fileperms_t perm)
+{
+ int mode = 0;
+
+ mode |= 0700 & (perm >> 2); /* User is off-by-2 bits */
+ mode |= 0070 & (perm >> 1); /* Group is off-by-1 bit */
+ mode |= 0007 & (perm); /* World maps 1 for 1 */
+ return mode;
+}
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_strings.h"
+#define APR_WANT_MEMFUNC
+#include "apr_want.h"
+
+#define APU_WANT_DB
+#include "apu_want.h"
+
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h> /* for abort() */
+#endif
+
+#include "apu.h"
+
+#if APU_HAVE_DB
+#include "apr_dbm_private.h"
+
+/*
+ * We pick up all varieties of Berkeley DB through db.h (included through
+ * apu_select_dbm.h). This code has been compiled/tested against DB1,
+ * DB_185, DB2, DB3, and DB4.
+ */
+
+#if defined(DB_VERSION_MAJOR) && (DB_VERSION_MAJOR == 4)
+/* We will treat anything greater than 4.1 as DB4.
+ * We can treat 4.0 as DB3.
+ */
+#if defined(DB_VERSION_MINOR) && (DB_VERSION_MINOR >= 1)
+#define DB_VER 4
+#else
+#define DB_VER 3
+#endif
+#elif defined(DB_VERSION_MAJOR) && (DB_VERSION_MAJOR == 3)
+#define DB_VER 3
+#elif defined(DB_VERSION_MAJOR) && (DB_VERSION_MAJOR == 2)
+#define DB_VER 2
+#else
+#define DB_VER 1
+#endif
+
+typedef struct {
+ DB *bdb;
+#if DB_VER != 1
+ DBC *curs;
+#endif
+} real_file_t;
+
+
+#if DB_VER == 1
+#define TXN_ARG
+#else
+#define TXN_ARG NULL,
+#endif
+
+#define GET_BDB(f) (((real_file_t *)(f))->bdb)
+
+#define do_fetch(bdb, k, v) ((*(bdb)->get)(bdb, TXN_ARG &(k), &(v), 0))
+
+#if DB_VER == 1
+#include <sys/fcntl.h>
+#define APR_DBM_DBMODE_RO O_RDONLY
+#define APR_DBM_DBMODE_RW O_RDWR
+#define APR_DBM_DBMODE_RWCREATE (O_CREAT | O_RDWR)
+#define APR_DBM_DBMODE_RWTRUNC (O_CREAT | O_RDWR | O_TRUNC)
+#else
+#define APR_DBM_DBMODE_RO DB_RDONLY
+#define APR_DBM_DBMODE_RW 0
+#define APR_DBM_DBMODE_RWCREATE DB_CREATE
+#define APR_DBM_DBMODE_RWTRUNC DB_TRUNCATE
+#endif /* DBVER == 1 */
+
+/* --------------------------------------------------------------------------
+**
+** UTILITY FUNCTIONS
+*/
+
+/* map a DB error to an apr_status_t */
+static apr_status_t db2s(int dberr)
+{
+ if (dberr != 0) {
+ /* ### need to fix this */
+ return APR_OS_START_USEERR + dberr;
+ }
+
+ return APR_SUCCESS;
+}
+
+
+static apr_status_t set_error(apr_dbm_t *dbm, apr_status_t dbm_said)
+{
+ apr_status_t rv = APR_SUCCESS;
+
+ /* ### ignore whatever the DBM said (dbm_said); ask it explicitly */
+
+ if (dbm_said == APR_SUCCESS) {
+ dbm->errcode = 0;
+ dbm->errmsg = NULL;
+ }
+ else {
+ /* ### need to fix. dberr was tossed in db2s(). */
+ /* ### use db_strerror() */
+ dbm->errcode = dbm_said;
+#if DB_VER == 1 || DB_VER == 2
+ dbm->errmsg = NULL;
+#else
+ dbm->errmsg = db_strerror(dbm_said - APR_OS_START_USEERR);
+#endif
+ rv = dbm_said;
+ }
+
+ return rv;
+}
+
+/* --------------------------------------------------------------------------
+**
+** DEFINE THE VTABLE FUNCTIONS FOR BERKELEY DB
+**
+** ### we may need three sets of these: db1, db2, db3
+*/
+
+static apr_status_t vt_db_open(apr_dbm_t **pdb, const char *pathname,
+ apr_int32_t mode, apr_fileperms_t perm,
+ apr_pool_t *pool)
+{
+ real_file_t file;
+ int dbmode;
+
+ *pdb = NULL;
+
+ switch (mode) {
+ case APR_DBM_READONLY:
+ dbmode = APR_DBM_DBMODE_RO;
+ break;
+ case APR_DBM_READWRITE:
+ dbmode = APR_DBM_DBMODE_RW;
+ break;
+ case APR_DBM_RWCREATE:
+ dbmode = APR_DBM_DBMODE_RWCREATE;
+ break;
+ case APR_DBM_RWTRUNC:
+ dbmode = APR_DBM_DBMODE_RWTRUNC;
+ break;
+ default:
+ return APR_EINVAL;
+ }
+
+ {
+ int dberr;
+
+#if DB_VER >= 3
+ if ((dberr = db_create(&file.bdb, NULL, 0)) == 0) {
+ if ((dberr = (*file.bdb->open)(file.bdb,
+#if DB_VER == 4
+ NULL,
+#endif
+ pathname, NULL,
+ DB_HASH, dbmode,
+ apr_posix_perms2mode(perm))) != 0) {
+ /* close the DB handler */
+ (void) (*file.bdb->close)(file.bdb, 0);
+ }
+ }
+ file.curs = NULL;
+#elif DB_VER == 2
+ dberr = db_open(pathname, DB_HASH, dbmode, apr_posix_perms2mode(perm),
+ NULL, NULL, &file.bdb);
+ file.curs = NULL;
+#else
+ file.bdb = dbopen(pathname, dbmode, apr_posix_perms2mode(perm),
+ DB_HASH, NULL);
+ if (file.bdb == NULL)
+ return APR_EGENERAL; /* ### need a better error */
+ dberr = 0;
+#endif
+ if (dberr != 0)
+ return db2s(dberr);
+ }
+
+ /* we have an open database... return it */
+ *pdb = apr_pcalloc(pool, sizeof(**pdb));
+ (*pdb)->pool = pool;
+ (*pdb)->type = &apr_dbm_type_db;
+ (*pdb)->file = apr_pmemdup(pool, &file, sizeof(file));
+
+ /* ### register a cleanup to close the DBM? */
+
+ return APR_SUCCESS;
+}
+
+static void vt_db_close(apr_dbm_t *dbm)
+{
+ (*GET_BDB(dbm->file)->close)(GET_BDB(dbm->file)
+#if DB_VER != 1
+ , 0
+#endif
+ );
+}
+
+static apr_status_t vt_db_fetch(apr_dbm_t *dbm, apr_datum_t key,
+ apr_datum_t * pvalue)
+{
+ DBT ckey = { 0 };
+ DBT rd = { 0 };
+ int dberr;
+
+ ckey.data = key.dptr;
+ ckey.size = key.dsize;
+
+ dberr = do_fetch(GET_BDB(dbm->file), ckey, rd);
+
+ /* "not found" is not an error. return zero'd value. */
+ if (dberr ==
+#if DB_VER == 1
+ RET_SPECIAL
+#else
+ DB_NOTFOUND
+#endif
+ ) {
+ memset(&rd, 0, sizeof(rd));
+ dberr = 0;
+ }
+
+ pvalue->dptr = rd.data;
+ pvalue->dsize = rd.size;
+
+ /* store the error info into DBM, and return a status code. Also, note
+ that *pvalue should have been cleared on error. */
+ return set_error(dbm, db2s(dberr));
+}
+
+static apr_status_t vt_db_store(apr_dbm_t *dbm, apr_datum_t key,
+ apr_datum_t value)
+{
+ apr_status_t rv;
+ DBT ckey = { 0 };
+ DBT cvalue = { 0 };
+
+ ckey.data = key.dptr;
+ ckey.size = key.dsize;
+
+ cvalue.data = value.dptr;
+ cvalue.size = value.dsize;
+
+ rv = db2s((*GET_BDB(dbm->file)->put)(GET_BDB(dbm->file),
+ TXN_ARG
+ &ckey,
+ &cvalue,
+ 0));
+
+ /* store any error info into DBM, and return a status code. */
+ return set_error(dbm, rv);
+}
+
+static apr_status_t vt_db_del(apr_dbm_t *dbm, apr_datum_t key)
+{
+ apr_status_t rv;
+ DBT ckey = { 0 };
+
+ ckey.data = key.dptr;
+ ckey.size = key.dsize;
+
+ rv = db2s((*GET_BDB(dbm->file)->del)(GET_BDB(dbm->file),
+ TXN_ARG
+ &ckey,
+ 0));
+
+ /* store any error info into DBM, and return a status code. */
+ return set_error(dbm, rv);
+}
+
+static int vt_db_exists(apr_dbm_t *dbm, apr_datum_t key)
+{
+ DBT ckey = { 0 }; /* converted key */
+ DBT data = { 0 };
+ int dberr;
+
+ ckey.data = key.dptr;
+ ckey.size = key.dsize;
+
+ dberr = do_fetch(GET_BDB(dbm->file), ckey, data);
+
+ /* note: the result data is "loaned" to us; we don't need to free it */
+
+ /* DB returns DB_NOTFOUND if it doesn't exist. but we want to say
+ that *any* error means it doesn't exist. */
+ return dberr == 0;
+}
+
+static apr_status_t vt_db_firstkey(apr_dbm_t *dbm, apr_datum_t * pkey)
+{
+ real_file_t *f = dbm->file;
+ DBT first = { 0 };
+ DBT data = { 0 };
+ int dberr;
+
+#if DB_VER == 1
+ dberr = (*f->bdb->seq)(f->bdb, &first, &data, R_FIRST);
+#else
+ if ((dberr = (*f->bdb->cursor)(f->bdb, NULL, &f->curs
+#if DB_VER >= 3 || ((DB_VERSION_MAJOR == 2) && (DB_VERSION_MINOR > 5))
+ , 0
+#endif
+ )) == 0) {
+ dberr = (*f->curs->c_get)(f->curs, &first, &data, DB_FIRST);
+ if (dberr == DB_NOTFOUND) {
+ memset(&first, 0, sizeof(first));
+ (*f->curs->c_close)(f->curs);
+ f->curs = NULL;
+ dberr = 0;
+ }
+ }
+#endif
+
+ pkey->dptr = first.data;
+ pkey->dsize = first.size;
+
+ /* store any error info into DBM, and return a status code. */
+ return set_error(dbm, db2s(dberr));
+}
+
+static apr_status_t vt_db_nextkey(apr_dbm_t *dbm, apr_datum_t * pkey)
+{
+ real_file_t *f = dbm->file;
+ DBT ckey = { 0 };
+ DBT data = { 0 };
+ int dberr;
+
+ ckey.data = pkey->dptr;
+ ckey.size = pkey->dsize;
+
+#if DB_VER == 1
+ dberr = (*f->bdb->seq)(f->bdb, &ckey, &data, R_NEXT);
+ if (dberr == RET_SPECIAL) {
+ dberr = 0;
+ ckey.data = NULL;
+ ckey.size = 0;
+ }
+#else
+ if (f->curs == NULL)
+ return APR_EINVAL;
+
+ dberr = (*f->curs->c_get)(f->curs, &ckey, &data, DB_NEXT);
+ if (dberr == DB_NOTFOUND) {
+ (*f->curs->c_close)(f->curs);
+ f->curs = NULL;
+ dberr = 0;
+ ckey.data = NULL;
+ ckey.size = 0;
+ }
+#endif
+
+ pkey->dptr = ckey.data;
+ pkey->dsize = ckey.size;
+
+ /* store any error info into DBM, and return a status code. */
+ /* ### or use db2s(dberr) instead of APR_SUCCESS? */
+ return set_error(dbm, APR_SUCCESS);
+}
+
+static void vt_db_freedatum(apr_dbm_t *dbm, apr_datum_t data)
+{
+ /* nothing to do */
+}
+
+static void vt_db_usednames(apr_pool_t *pool, const char *pathname,
+ const char **used1, const char **used2)
+{
+ *used1 = apr_pstrdup(pool, pathname);
+ *used2 = NULL;
+}
+
+
+APU_DECLARE_DATA const apr_dbm_type_t apr_dbm_type_db = {
+ "db",
+
+ vt_db_open,
+ vt_db_close,
+ vt_db_fetch,
+ vt_db_store,
+ vt_db_del,
+ vt_db_exists,
+ vt_db_firstkey,
+ vt_db_nextkey,
+ vt_db_freedatum,
+ vt_db_usednames
+};
+
+#endif /* APU_HAVE_DB */
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_strings.h"
+
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h> /* for free() */
+#endif
+
+#include "apu.h"
+
+#if APU_HAVE_GDBM
+#include "apr_dbm_private.h"
+
+#include <gdbm.h>
+
+/* this is used in a few places to define a noop "function". it is needed
+ to stop "no effect" warnings from GCC. */
+#define NOOP_FUNCTION if (0) ; else
+
+/* ### define defaults for now; these will go away in a while */
+#define REGISTER_CLEANUP(dbm, pdatum) NOOP_FUNCTION
+#define SET_FILE(pdb, f) ((pdb)->file = (f))
+
+typedef GDBM_FILE real_file_t;
+
+typedef datum *cvt_datum_t;
+#define CONVERT_DATUM(cvt, pinput) ((cvt) = (datum *)(pinput))
+
+typedef datum result_datum_t;
+#define RETURN_DATUM(poutput, rd) (*(poutput) = *(apr_datum_t *)&(rd))
+
+#define APR_DBM_CLOSE(f) gdbm_close(f)
+#define APR_DBM_FETCH(f, k, v) ((v) = gdbm_fetch(f, *(k)), APR_SUCCESS)
+#define APR_DBM_STORE(f, k, v) g2s(gdbm_store(f, *(k), *(v), GDBM_REPLACE))
+#define APR_DBM_DELETE(f, k) g2s(gdbm_delete(f, *(k)))
+#define APR_DBM_FIRSTKEY(f, k) ((k) = gdbm_firstkey(f), APR_SUCCESS)
+#define APR_DBM_NEXTKEY(f, k, nk) ((nk) = gdbm_nextkey(f, *(k)), APR_SUCCESS)
+#define APR_DBM_FREEDPTR(dptr) ((dptr) ? free(dptr) : 0)
+
+#undef REGISTER_CLEANUP
+#define REGISTER_CLEANUP(dbm, pdatum) \
+ if ((pdatum)->dptr) \
+ apr_pool_cleanup_register((dbm)->pool, (pdatum)->dptr, \
+ datum_cleanup, apr_pool_cleanup_null); \
+ else
+
+#define APR_DBM_DBMODE_RO GDBM_READER
+#define APR_DBM_DBMODE_RW GDBM_WRITER
+#define APR_DBM_DBMODE_RWCREATE GDBM_WRCREAT
+#define APR_DBM_DBMODE_RWTRUNC GDBM_NEWDB
+
+/* map a GDBM error to an apr_status_t */
+static apr_status_t g2s(int gerr)
+{
+ if (gerr == -1) {
+ /* ### need to fix this */
+ return APR_EGENERAL;
+ }
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t datum_cleanup(void *dptr)
+{
+ if (dptr)
+ free(dptr);
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t set_error(apr_dbm_t *dbm, apr_status_t dbm_said)
+{
+ apr_status_t rv = APR_SUCCESS;
+
+ /* ### ignore whatever the DBM said (dbm_said); ask it explicitly */
+
+ if ((dbm->errcode = gdbm_errno) == GDBM_NO_ERROR) {
+ dbm->errmsg = NULL;
+ }
+ else {
+ dbm->errmsg = gdbm_strerror(gdbm_errno);
+ rv = APR_EGENERAL; /* ### need something better */
+ }
+
+ /* captured it. clear it now. */
+ gdbm_errno = GDBM_NO_ERROR;
+
+ return rv;
+}
+
+/* --------------------------------------------------------------------------
+**
+** DEFINE THE VTABLE FUNCTIONS FOR GDBM
+*/
+
+static apr_status_t vt_gdbm_open(apr_dbm_t **pdb, const char *pathname,
+ apr_int32_t mode, apr_fileperms_t perm,
+ apr_pool_t *pool)
+{
+ real_file_t file;
+ int dbmode;
+
+ *pdb = NULL;
+
+ switch (mode) {
+ case APR_DBM_READONLY:
+ dbmode = APR_DBM_DBMODE_RO;
+ break;
+ case APR_DBM_READWRITE:
+ dbmode = APR_DBM_DBMODE_RW;
+ break;
+ case APR_DBM_RWCREATE:
+ dbmode = APR_DBM_DBMODE_RWCREATE;
+ break;
+ case APR_DBM_RWTRUNC:
+ dbmode = APR_DBM_DBMODE_RWTRUNC;
+ break;
+ default:
+ return APR_EINVAL;
+ }
+
+ {
+ /* Note: stupid cast to get rid of "const" on the pathname */
+ file = gdbm_open((char *) pathname, 0, dbmode,
+ apr_posix_perms2mode(perm), NULL);
+ if (file == NULL)
+ return APR_EGENERAL; /* ### need a better error */
+ }
+
+ /* we have an open database... return it */
+ *pdb = apr_pcalloc(pool, sizeof(**pdb));
+ (*pdb)->pool = pool;
+ (*pdb)->type = &apr_dbm_type_gdbm;
+ SET_FILE(*pdb, file);
+
+ /* ### register a cleanup to close the DBM? */
+
+ return APR_SUCCESS;
+}
+
+static void vt_gdbm_close(apr_dbm_t *dbm)
+{
+ APR_DBM_CLOSE(dbm->file);
+}
+
+static apr_status_t vt_gdbm_fetch(apr_dbm_t *dbm, apr_datum_t key,
+ apr_datum_t * pvalue)
+{
+ apr_status_t rv;
+ cvt_datum_t ckey;
+ result_datum_t rd;
+
+ CONVERT_DATUM(ckey, &key);
+ rv = APR_DBM_FETCH(dbm->file, ckey, rd);
+ RETURN_DATUM(pvalue, rd);
+
+ REGISTER_CLEANUP(dbm, pvalue);
+
+ /* store the error info into DBM, and return a status code. Also, note
+ that *pvalue should have been cleared on error. */
+ return set_error(dbm, rv);
+}
+
+static apr_status_t vt_gdbm_store(apr_dbm_t *dbm, apr_datum_t key,
+ apr_datum_t value)
+{
+ apr_status_t rv;
+ cvt_datum_t ckey;
+ cvt_datum_t cvalue;
+
+ CONVERT_DATUM(ckey, &key);
+ CONVERT_DATUM(cvalue, &value);
+ rv = APR_DBM_STORE(dbm->file, ckey, cvalue);
+
+ /* store any error info into DBM, and return a status code. */
+ return set_error(dbm, rv);
+}
+
+static apr_status_t vt_gdbm_del(apr_dbm_t *dbm, apr_datum_t key)
+{
+ apr_status_t rv;
+ cvt_datum_t ckey;
+
+ CONVERT_DATUM(ckey, &key);
+ rv = APR_DBM_DELETE(dbm->file, ckey);
+
+ /* store any error info into DBM, and return a status code. */
+ return set_error(dbm, rv);
+}
+
+static int vt_gdbm_exists(apr_dbm_t *dbm, apr_datum_t key)
+{
+ datum *ckey = (datum *)&key;
+
+ return gdbm_exists(dbm->file, *ckey) != 0;
+}
+
+static apr_status_t vt_gdbm_firstkey(apr_dbm_t *dbm, apr_datum_t * pkey)
+{
+ apr_status_t rv;
+ result_datum_t rd;
+
+ rv = APR_DBM_FIRSTKEY(dbm->file, rd);
+ RETURN_DATUM(pkey, rd);
+
+ REGISTER_CLEANUP(dbm, pkey);
+
+ /* store any error info into DBM, and return a status code. */
+ return set_error(dbm, rv);
+}
+
+static apr_status_t vt_gdbm_nextkey(apr_dbm_t *dbm, apr_datum_t * pkey)
+{
+ apr_status_t rv;
+ cvt_datum_t ckey;
+ result_datum_t rd;
+
+ CONVERT_DATUM(ckey, pkey);
+ rv = APR_DBM_NEXTKEY(dbm->file, ckey, rd);
+ RETURN_DATUM(pkey, rd);
+
+ REGISTER_CLEANUP(dbm, pkey);
+
+ /* store any error info into DBM, and return a status code. */
+ return set_error(dbm, APR_SUCCESS);
+}
+
+static void vt_gdbm_freedatum(apr_dbm_t *dbm, apr_datum_t data)
+{
+ (void) apr_pool_cleanup_run(dbm->pool, data.dptr, datum_cleanup);
+}
+
+static void vt_gdbm_usednames(apr_pool_t *pool, const char *pathname,
+ const char **used1, const char **used2)
+{
+ *used1 = apr_pstrdup(pool, pathname);
+ *used2 = NULL;
+}
+
+
+APU_DECLARE_DATA const apr_dbm_type_t apr_dbm_type_gdbm = {
+ "gdbm",
+
+ vt_gdbm_open,
+ vt_gdbm_close,
+ vt_gdbm_fetch,
+ vt_gdbm_store,
+ vt_gdbm_del,
+ vt_gdbm_exists,
+ vt_gdbm_firstkey,
+ vt_gdbm_nextkey,
+ vt_gdbm_freedatum,
+ vt_gdbm_usednames
+};
+
+#endif /* APU_HAVE_GDBM */
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_strings.h"
+
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h> /* for free() */
+#endif
+
+#include "apu.h"
+
+#if APU_HAVE_NDBM
+#include "apr_dbm_private.h"
+
+#include <ndbm.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+/* this is used in a few places to define a noop "function". it is needed
+ to stop "no effect" warnings from GCC. */
+#define NOOP_FUNCTION if (0) ; else
+
+#define APR_DBM_DBMODE_RO O_RDONLY
+#define APR_DBM_DBMODE_RW O_RDWR
+#define APR_DBM_DBMODE_RWCREATE (O_RDWR|O_CREAT)
+#define APR_DBM_DBMODE_RWTRUNC (O_RDWR|O_CREAT|O_TRUNC)
+
+/* map a NDBM error to an apr_status_t */
+static apr_status_t ndbm2s(int ndbmerr)
+{
+ if (ndbmerr == -1) {
+ /* ### need to fix this */
+ return APR_EGENERAL;
+ }
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t set_error(apr_dbm_t *dbm, apr_status_t dbm_said)
+{
+ apr_status_t rv = APR_SUCCESS;
+
+ /* ### ignore whatever the DBM said (dbm_said); ask it explicitly */
+
+ dbm->errmsg = NULL;
+ if (dbm_error((DBM*)dbm->file)) {
+ dbm->errmsg = NULL;
+ rv = APR_EGENERAL; /* ### need something better */
+ }
+
+ /* captured it. clear it now. */
+ dbm_clearerr((DBM*)dbm->file);
+
+ return rv;
+}
+
+/* --------------------------------------------------------------------------
+**
+** DEFINE THE VTABLE FUNCTIONS FOR NDBM
+*/
+
+static apr_status_t vt_ndbm_open(apr_dbm_t **pdb, const char *pathname,
+ apr_int32_t mode, apr_fileperms_t perm,
+ apr_pool_t *pool)
+{
+ DBM *file;
+ int dbmode;
+
+ *pdb = NULL;
+
+ switch (mode) {
+ case APR_DBM_READONLY:
+ dbmode = APR_DBM_DBMODE_RO;
+ break;
+ case APR_DBM_READWRITE:
+ dbmode = APR_DBM_DBMODE_RW;
+ break;
+ case APR_DBM_RWCREATE:
+ dbmode = APR_DBM_DBMODE_RWCREATE;
+ break;
+ case APR_DBM_RWTRUNC:
+ dbmode = APR_DBM_DBMODE_RWTRUNC;
+ break;
+ default:
+ return APR_EINVAL;
+ }
+
+ {
+ file = dbm_open(pathname, dbmode, apr_posix_perms2mode(perm));
+ if (file == NULL)
+ return APR_EGENERAL; /* ### need a better error */
+ }
+
+ /* we have an open database... return it */
+ *pdb = apr_pcalloc(pool, sizeof(**pdb));
+ (*pdb)->pool = pool;
+ (*pdb)->type = &apr_dbm_type_ndbm;
+ (*pdb)->file = file;
+
+ /* ### register a cleanup to close the DBM? */
+
+ return APR_SUCCESS;
+}
+
+static void vt_ndbm_close(apr_dbm_t *dbm)
+{
+ dbm_close(dbm->file);
+}
+
+static apr_status_t vt_ndbm_fetch(apr_dbm_t *dbm, apr_datum_t key,
+ apr_datum_t * pvalue)
+{
+ datum *ckey;
+ datum rd;
+
+ ckey = (datum*)&key;
+ rd = dbm_fetch(dbm->file, *ckey);
+ *pvalue = *(apr_datum_t*)&rd;
+
+ /* store the error info into DBM, and return a status code. Also, note
+ that *pvalue should have been cleared on error. */
+ return set_error(dbm, APR_SUCCESS);
+}
+
+static apr_status_t vt_ndbm_store(apr_dbm_t *dbm, apr_datum_t key,
+ apr_datum_t value)
+{
+ apr_status_t rv;
+ datum *ckey;
+ datum *cvalue;
+
+ ckey = (datum*)&key;
+ cvalue = (datum*)&value;
+ rv = ndbm2s( dbm_store( dbm->file, *ckey, *cvalue, DBM_REPLACE));
+
+ /* store any error info into DBM, and return a status code. */
+ return set_error(dbm, rv);
+}
+
+static apr_status_t vt_ndbm_del(apr_dbm_t *dbm, apr_datum_t key)
+{
+ apr_status_t rv;
+ datum *ckey;
+
+ ckey = (datum*)&key;
+ rv = ndbm2s( dbm_delete(dbm->file, *ckey));
+
+ /* store any error info into DBM, and return a status code. */
+ return set_error(dbm, rv);
+}
+
+static int vt_ndbm_exists(apr_dbm_t *dbm, apr_datum_t key)
+{
+ datum *ckey = (datum *)&key;
+ datum value;
+
+ value = dbm_fetch( dbm->file, *ckey);
+
+ return value.dptr != NULL;
+}
+
+static apr_status_t vt_ndbm_firstkey(apr_dbm_t *dbm, apr_datum_t * pkey)
+{
+ datum rd;
+
+ rd = dbm_firstkey(dbm->file);
+ *pkey = *(apr_datum_t*)&rd;
+
+ /* store any error info into DBM, and return a status code. */
+ return set_error(dbm, APR_SUCCESS);
+}
+
+static apr_status_t vt_ndbm_nextkey(apr_dbm_t *dbm, apr_datum_t * pkey)
+{
+ datum *ckey;
+ datum rd;
+
+ ckey = (datum*)pkey;
+ rd = dbm_nextkey(dbm->file);
+ *pkey = *(apr_datum_t*)&rd;
+
+ /* store any error info into DBM, and return a status code. */
+ return set_error(dbm, APR_SUCCESS);
+}
+
+static void vt_ndbm_freedatum(apr_dbm_t *dbm, apr_datum_t data)
+{
+ /* nothing to do */
+}
+
+static void vt_ndbm_usednames(apr_pool_t *pool, const char *pathname,
+ const char **used1, const char **used2)
+{
+ *used1 = apr_pstrdup(pool, pathname);
+ *used2 = NULL;
+}
+
+
+APU_DECLARE_DATA const apr_dbm_type_t apr_dbm_type_ndbm = {
+ "ndbm",
+
+ vt_ndbm_open,
+ vt_ndbm_close,
+ vt_ndbm_fetch,
+ vt_ndbm_store,
+ vt_ndbm_del,
+ vt_ndbm_exists,
+ vt_ndbm_firstkey,
+ vt_ndbm_nextkey,
+ vt_ndbm_freedatum,
+ vt_ndbm_usednames
+};
+#endif /* APU_HAVE_NDBM */
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_strings.h"
+#define APR_WANT_MEMFUNC
+#define APR_WANT_STRFUNC
+#include "apr_want.h"
+
+#include "apu.h"
+
+#if APU_HAVE_SDBM
+
+#include "apr_dbm_private.h"
+
+#include "apr_sdbm.h"
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h> /* For abort() */
+#endif
+
+/* this is used in a few places to define a noop "function". it is needed
+ to stop "no effect" warnings from GCC. */
+#define NOOP_FUNCTION if (0) ; else
+
+/* ### define defaults for now; these will go away in a while */
+#define REGISTER_CLEANUP(dbm, pdatum) NOOP_FUNCTION
+#define SET_FILE(pdb, f) ((pdb)->file = (f))
+
+typedef apr_sdbm_t *real_file_t;
+
+typedef apr_sdbm_datum_t cvt_datum_t;
+#define CONVERT_DATUM(cvt, pinput) ((cvt).dptr = (pinput)->dptr, (cvt).dsize = (pinput)->dsize)
+
+typedef apr_sdbm_datum_t result_datum_t;
+#define RETURN_DATUM(poutput, rd) ((poutput)->dptr = (rd).dptr, (poutput)->dsize = (rd).dsize)
+
+#define APR_DBM_CLOSE(f) apr_sdbm_close(f)
+#define APR_DBM_FETCH(f, k, v) apr_sdbm_fetch(f, &(v), (k))
+#define APR_DBM_STORE(f, k, v) apr_sdbm_store(f, (k), (v), APR_SDBM_REPLACE)
+#define APR_DBM_DELETE(f, k) apr_sdbm_delete(f, (k))
+#define APR_DBM_FIRSTKEY(f, k) apr_sdbm_firstkey(f, &(k))
+#define APR_DBM_NEXTKEY(f, k, nk) apr_sdbm_nextkey(f, &(nk))
+#define APR_DBM_FREEDPTR(dptr) NOOP_FUNCTION
+
+#define APR_DBM_DBMODE_RO APR_READ
+#define APR_DBM_DBMODE_RW (APR_READ | APR_WRITE)
+#define APR_DBM_DBMODE_RWCREATE (APR_READ | APR_WRITE | APR_CREATE)
+#define APR_DBM_DBMODE_RWTRUNC (APR_READ | APR_WRITE | APR_CREATE | \
+ APR_TRUNCATE)
+
+static apr_status_t set_error(apr_dbm_t *dbm, apr_status_t dbm_said)
+{
+ apr_status_t rv = APR_SUCCESS;
+
+ /* ### ignore whatever the DBM said (dbm_said); ask it explicitly */
+
+ if ((dbm->errcode = dbm_said) == APR_SUCCESS) {
+ dbm->errmsg = NULL;
+ }
+ else {
+ dbm->errmsg = "I/O error occurred.";
+ rv = APR_EGENERAL; /* ### need something better */
+ }
+
+ return rv;
+}
+
+/* --------------------------------------------------------------------------
+**
+** DEFINE THE VTABLE FUNCTIONS FOR SDBM
+*/
+
+static apr_status_t vt_sdbm_open(apr_dbm_t **pdb, const char *pathname,
+ apr_int32_t mode, apr_fileperms_t perm,
+ apr_pool_t *pool)
+{
+ real_file_t file;
+ int dbmode;
+
+ *pdb = NULL;
+
+ switch (mode) {
+ case APR_DBM_READONLY:
+ dbmode = APR_DBM_DBMODE_RO;
+ break;
+ case APR_DBM_READWRITE:
+ dbmode = APR_DBM_DBMODE_RW;
+ break;
+ case APR_DBM_RWCREATE:
+ dbmode = APR_DBM_DBMODE_RWCREATE;
+ break;
+ case APR_DBM_RWTRUNC:
+ dbmode = APR_DBM_DBMODE_RWTRUNC;
+ break;
+ default:
+ return APR_EINVAL;
+ }
+
+ {
+ apr_status_t rv;
+
+ rv = apr_sdbm_open(&file, pathname, dbmode, perm, pool);
+ if (rv != APR_SUCCESS)
+ return rv;
+ }
+
+ /* we have an open database... return it */
+ *pdb = apr_pcalloc(pool, sizeof(**pdb));
+ (*pdb)->pool = pool;
+ (*pdb)->type = &apr_dbm_type_sdbm;
+ SET_FILE(*pdb, file);
+
+ /* ### register a cleanup to close the DBM? */
+
+ return APR_SUCCESS;
+}
+
+static void vt_sdbm_close(apr_dbm_t *dbm)
+{
+ APR_DBM_CLOSE(dbm->file);
+}
+
+static apr_status_t vt_sdbm_fetch(apr_dbm_t *dbm, apr_datum_t key,
+ apr_datum_t * pvalue)
+{
+ apr_status_t rv;
+ cvt_datum_t ckey;
+ result_datum_t rd;
+
+ CONVERT_DATUM(ckey, &key);
+ rv = APR_DBM_FETCH(dbm->file, ckey, rd);
+ RETURN_DATUM(pvalue, rd);
+
+ REGISTER_CLEANUP(dbm, pvalue);
+
+ /* store the error info into DBM, and return a status code. Also, note
+ that *pvalue should have been cleared on error. */
+ return set_error(dbm, rv);
+}
+
+static apr_status_t vt_sdbm_store(apr_dbm_t *dbm, apr_datum_t key,
+ apr_datum_t value)
+{
+ apr_status_t rv;
+ cvt_datum_t ckey;
+ cvt_datum_t cvalue;
+
+ CONVERT_DATUM(ckey, &key);
+ CONVERT_DATUM(cvalue, &value);
+ rv = APR_DBM_STORE(dbm->file, ckey, cvalue);
+
+ /* store any error info into DBM, and return a status code. */
+ return set_error(dbm, rv);
+}
+
+static apr_status_t vt_sdbm_del(apr_dbm_t *dbm, apr_datum_t key)
+{
+ apr_status_t rv;
+ cvt_datum_t ckey;
+
+ CONVERT_DATUM(ckey, &key);
+ rv = APR_DBM_DELETE(dbm->file, ckey);
+
+ /* store any error info into DBM, and return a status code. */
+ return set_error(dbm, rv);
+}
+
+static int vt_sdbm_exists(apr_dbm_t *dbm, apr_datum_t key)
+{
+ int exists;
+ apr_sdbm_datum_t ckey;
+
+ CONVERT_DATUM(ckey, &key);
+
+ {
+ apr_sdbm_datum_t value;
+ if (apr_sdbm_fetch(dbm->file, &value, ckey) != APR_SUCCESS) {
+ exists = 0;
+ }
+ else
+ exists = value.dptr != NULL;
+ }
+
+ return exists;
+}
+
+static apr_status_t vt_sdbm_firstkey(apr_dbm_t *dbm, apr_datum_t * pkey)
+{
+ apr_status_t rv;
+ result_datum_t rd;
+
+ rv = APR_DBM_FIRSTKEY(dbm->file, rd);
+ RETURN_DATUM(pkey, rd);
+
+ REGISTER_CLEANUP(dbm, pkey);
+
+ /* store any error info into DBM, and return a status code. */
+ return set_error(dbm, rv);
+}
+
+static apr_status_t vt_sdbm_nextkey(apr_dbm_t *dbm, apr_datum_t * pkey)
+{
+ apr_status_t rv;
+ cvt_datum_t ckey;
+ result_datum_t rd;
+
+ CONVERT_DATUM(ckey, pkey);
+ rv = APR_DBM_NEXTKEY(dbm->file, ckey, rd);
+ RETURN_DATUM(pkey, rd);
+
+ REGISTER_CLEANUP(dbm, pkey);
+
+ /* store any error info into DBM, and return a status code. */
+ return set_error(dbm, APR_SUCCESS);
+}
+
+static void vt_sdbm_freedatum(apr_dbm_t *dbm, apr_datum_t data)
+{
+ APR_DBM_FREEDPTR(data.dptr);
+}
+
+static void vt_sdbm_usednames(apr_pool_t *pool, const char *pathname,
+ const char **used1, const char **used2)
+{
+ char *work;
+
+ /* ### this could be optimized by computing strlen() once and using
+ ### memcpy and pmemdup instead. but why bother? */
+
+ *used1 = apr_pstrcat(pool, pathname, APR_SDBM_DIRFEXT, NULL);
+ *used2 = work = apr_pstrdup(pool, *used1);
+
+ /* we know the extension is 4 characters */
+ memcpy(&work[strlen(work) - 4], APR_SDBM_PAGFEXT, 4);
+}
+
+
+APU_DECLARE_DATA const apr_dbm_type_t apr_dbm_type_sdbm = {
+ "sdbm",
+
+ vt_sdbm_open,
+ vt_sdbm_close,
+ vt_sdbm_fetch,
+ vt_sdbm_store,
+ vt_sdbm_del,
+ vt_sdbm_exists,
+ vt_sdbm_firstkey,
+ vt_sdbm_nextkey,
+ vt_sdbm_freedatum,
+ vt_sdbm_usednames
+};
+
+#endif /* APU_HAVE_SDBM */
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * sdbm - ndbm work-alike hashed database library
+ * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
+ * author: oz@nexus.yorku.ca
+ * ex-public domain, ported to APR for Apache 2
+ * core routines
+ */
+
+#include "apr.h"
+#include "apr_file_io.h"
+#include "apr_strings.h"
+#include "apr_errno.h"
+#include "apr_sdbm.h"
+
+#include "sdbm_tune.h"
+#include "sdbm_pair.h"
+#include "sdbm_private.h"
+
+#include <string.h> /* for memset() */
+#include <stdlib.h> /* for malloc() and free() */
+
+/*
+ * forward
+ */
+static int getdbit (apr_sdbm_t *, long);
+static apr_status_t setdbit(apr_sdbm_t *, long);
+static apr_status_t getpage(apr_sdbm_t *db, long);
+static apr_status_t getnext(apr_sdbm_datum_t *key, apr_sdbm_t *db);
+static apr_status_t makroom(apr_sdbm_t *, long, int);
+
+/*
+ * useful macros
+ */
+#define bad(x) ((x).dptr == NULL || (x).dsize <= 0)
+#define exhash(item) sdbm_hash((item).dptr, (item).dsize)
+
+/* ### Does anything need these externally? */
+#define sdbm_dirfno(db) ((db)->dirf)
+#define sdbm_pagfno(db) ((db)->pagf)
+
+#define OFF_PAG(off) (apr_off_t) (off) * PBLKSIZ
+#define OFF_DIR(off) (apr_off_t) (off) * DBLKSIZ
+
+static long masks[] = {
+ 000000000000, 000000000001, 000000000003, 000000000007,
+ 000000000017, 000000000037, 000000000077, 000000000177,
+ 000000000377, 000000000777, 000000001777, 000000003777,
+ 000000007777, 000000017777, 000000037777, 000000077777,
+ 000000177777, 000000377777, 000000777777, 000001777777,
+ 000003777777, 000007777777, 000017777777, 000037777777,
+ 000077777777, 000177777777, 000377777777, 000777777777,
+ 001777777777, 003777777777, 007777777777, 017777777777
+};
+
+const apr_sdbm_datum_t sdbm_nullitem = { NULL, 0 };
+
+static apr_status_t database_cleanup(void *data)
+{
+ apr_sdbm_t *db = data;
+
+ /*
+ * Can't rely on apr_sdbm_unlock, since it will merely
+ * decrement the refcnt if several locks are held.
+ */
+ if (db->flags & (SDBM_SHARED_LOCK | SDBM_EXCLUSIVE_LOCK))
+ (void) apr_file_unlock(db->dirf);
+ (void) apr_file_close(db->dirf);
+ (void) apr_file_close(db->pagf);
+ free(db);
+
+ return APR_SUCCESS;
+}
+
+static apr_status_t prep(apr_sdbm_t **pdb, const char *dirname, const char *pagname,
+ apr_int32_t flags, apr_fileperms_t perms, apr_pool_t *p)
+{
+ apr_sdbm_t *db;
+ apr_status_t status;
+
+ *pdb = NULL;
+
+ db = malloc(sizeof(*db));
+ memset(db, 0, sizeof(*db));
+
+ db->pool = p;
+
+ /*
+ * adjust user flags so that WRONLY becomes RDWR,
+ * as required by this package. Also set our internal
+ * flag for RDONLY if needed.
+ */
+ if (!(flags & APR_WRITE)) {
+ db->flags |= SDBM_RDONLY;
+ }
+
+ /*
+ * adjust the file open flags so that we handle locking
+ * on our own (don't rely on any locking behavior within
+ * an apr_file_t, in case it's ever introduced, and set
+ * our own flag.
+ */
+ if (flags & APR_SHARELOCK) {
+ db->flags |= SDBM_SHARED;
+ flags &= ~APR_SHARELOCK;
+ }
+
+ flags |= APR_BINARY | APR_READ;
+
+ /*
+ * open the files in sequence, and stat the dirfile.
+ * If we fail anywhere, undo everything, return NULL.
+ */
+
+ if ((status = apr_file_open(&db->dirf, dirname, flags, perms, p))
+ != APR_SUCCESS)
+ goto error;
+
+ if ((status = apr_file_open(&db->pagf, pagname, flags, perms, p))
+ != APR_SUCCESS)
+ goto error;
+
+ if ((status = apr_sdbm_lock(db, (db->flags & SDBM_RDONLY)
+ ? APR_FLOCK_SHARED
+ : APR_FLOCK_EXCLUSIVE))
+ != APR_SUCCESS)
+ goto error;
+
+ /* apr_pcalloc zeroed the buffers
+ * apr_sdbm_lock stated the dirf->size and invalidated the cache
+ */
+
+ /*
+ * if we are opened in SHARED mode, unlock ourself
+ */
+ if (db->flags & SDBM_SHARED)
+ if ((status = apr_sdbm_unlock(db)) != APR_SUCCESS)
+ goto error;
+
+ /* make sure that we close the database at some point */
+ apr_pool_cleanup_register(p, db, database_cleanup, apr_pool_cleanup_null);
+
+ /* Done! */
+ *pdb = db;
+ return APR_SUCCESS;
+
+error:
+ if (db->dirf && db->pagf)
+ (void) apr_sdbm_unlock(db);
+ if (db->dirf != NULL)
+ (void) apr_file_close(db->dirf);
+ if (db->pagf != NULL) {
+ (void) apr_file_close(db->pagf);
+ }
+ free(db);
+ return status;
+}
+
+APU_DECLARE(apr_status_t) apr_sdbm_open(apr_sdbm_t **db, const char *file,
+ apr_int32_t flags,
+ apr_fileperms_t perms, apr_pool_t *p)
+{
+ char *dirname = apr_pstrcat(p, file, APR_SDBM_DIRFEXT, NULL);
+ char *pagname = apr_pstrcat(p, file, APR_SDBM_PAGFEXT, NULL);
+
+ return prep(db, dirname, pagname, flags, perms, p);
+}
+
+APU_DECLARE(apr_status_t) apr_sdbm_close(apr_sdbm_t *db)
+{
+ return apr_pool_cleanup_run(db->pool, db, database_cleanup);
+}
+
+APU_DECLARE(apr_status_t) apr_sdbm_fetch(apr_sdbm_t *db, apr_sdbm_datum_t *val,
+ apr_sdbm_datum_t key)
+{
+ apr_status_t status;
+
+ if (db == NULL || bad(key))
+ return APR_EINVAL;
+
+ if ((status = apr_sdbm_lock(db, APR_FLOCK_SHARED)) != APR_SUCCESS)
+ return status;
+
+ if ((status = getpage(db, exhash(key))) == APR_SUCCESS) {
+ *val = getpair(db->pagbuf, key);
+ /* ### do we want a not-found result? */
+ }
+
+ (void) apr_sdbm_unlock(db);
+
+ return status;
+}
+
+static apr_status_t write_page(apr_sdbm_t *db, const char *buf, long pagno)
+{
+ apr_status_t status;
+ apr_off_t off = OFF_PAG(pagno);
+
+ if ((status = apr_file_seek(db->pagf, APR_SET, &off)) == APR_SUCCESS)
+ status = apr_file_write_full(db->pagf, buf, PBLKSIZ, NULL);
+
+ return status;
+}
+
+APU_DECLARE(apr_status_t) apr_sdbm_delete(apr_sdbm_t *db,
+ const apr_sdbm_datum_t key)
+{
+ apr_status_t status;
+
+ if (db == NULL || bad(key))
+ return APR_EINVAL;
+ if (apr_sdbm_rdonly(db))
+ return APR_EINVAL;
+
+ if ((status = apr_sdbm_lock(db, APR_FLOCK_EXCLUSIVE)) != APR_SUCCESS)
+ return status;
+
+ if ((status = getpage(db, exhash(key))) == APR_SUCCESS) {
+ if (!delpair(db->pagbuf, key))
+ /* ### should we define some APRUTIL codes? */
+ status = APR_EGENERAL;
+ else
+ status = write_page(db, db->pagbuf, db->pagbno);
+ }
+
+ (void) apr_sdbm_unlock(db);
+
+ return status;
+}
+
+APU_DECLARE(apr_status_t) apr_sdbm_store(apr_sdbm_t *db, apr_sdbm_datum_t key,
+ apr_sdbm_datum_t val, int flags)
+{
+ int need;
+ register long hash;
+ apr_status_t status;
+
+ if (db == NULL || bad(key))
+ return APR_EINVAL;
+ if (apr_sdbm_rdonly(db))
+ return APR_EINVAL;
+ need = key.dsize + val.dsize;
+ /*
+ * is the pair too big (or too small) for this database ??
+ */
+ if (need < 0 || need > PAIRMAX)
+ return APR_EINVAL;
+
+ if ((status = apr_sdbm_lock(db, APR_FLOCK_EXCLUSIVE)) != APR_SUCCESS)
+ return status;
+
+ if ((status = getpage(db, (hash = exhash(key)))) == APR_SUCCESS) {
+
+ /*
+ * if we need to replace, delete the key/data pair
+ * first. If it is not there, ignore.
+ */
+ if (flags == APR_SDBM_REPLACE)
+ (void) delpair(db->pagbuf, key);
+ else if (!(flags & APR_SDBM_INSERTDUP) && duppair(db->pagbuf, key)) {
+ status = APR_EEXIST;
+ goto error;
+ }
+ /*
+ * if we do not have enough room, we have to split.
+ */
+ if (!fitpair(db->pagbuf, need))
+ if ((status = makroom(db, hash, need)) != APR_SUCCESS)
+ goto error;
+ /*
+ * we have enough room or split is successful. insert the key,
+ * and update the page file.
+ */
+ (void) putpair(db->pagbuf, key, val);
+
+ status = write_page(db, db->pagbuf, db->pagbno);
+ }
+
+error:
+ (void) apr_sdbm_unlock(db);
+
+ return status;
+}
+
+/*
+ * makroom - make room by splitting the overfull page
+ * this routine will attempt to make room for SPLTMAX times before
+ * giving up.
+ */
+static apr_status_t makroom(apr_sdbm_t *db, long hash, int need)
+{
+ long newp;
+ char twin[PBLKSIZ];
+ char *pag = db->pagbuf;
+ char *new = twin;
+ register int smax = SPLTMAX;
+ apr_status_t status;
+
+ do {
+ /*
+ * split the current page
+ */
+ (void) splpage(pag, new, db->hmask + 1);
+ /*
+ * address of the new page
+ */
+ newp = (hash & db->hmask) | (db->hmask + 1);
+
+ /*
+ * write delay, read avoidence/cache shuffle:
+ * select the page for incoming pair: if key is to go to the new page,
+ * write out the previous one, and copy the new one over, thus making
+ * it the current page. If not, simply write the new page, and we are
+ * still looking at the page of interest. current page is not updated
+ * here, as sdbm_store will do so, after it inserts the incoming pair.
+ */
+ if (hash & (db->hmask + 1)) {
+ if ((status = write_page(db, db->pagbuf, db->pagbno))
+ != APR_SUCCESS)
+ return status;
+
+ db->pagbno = newp;
+ (void) memcpy(pag, new, PBLKSIZ);
+ }
+ else {
+ if ((status = write_page(db, new, newp)) != APR_SUCCESS)
+ return status;
+ }
+
+ if ((status = setdbit(db, db->curbit)) != APR_SUCCESS)
+ return status;
+ /*
+ * see if we have enough room now
+ */
+ if (fitpair(pag, need))
+ return APR_SUCCESS;
+ /*
+ * try again... update curbit and hmask as getpage would have
+ * done. because of our update of the current page, we do not
+ * need to read in anything. BUT we have to write the current
+ * [deferred] page out, as the window of failure is too great.
+ */
+ db->curbit = 2 * db->curbit
+ + ((hash & (db->hmask + 1)) ? 2 : 1);
+ db->hmask |= db->hmask + 1;
+
+ if ((status = write_page(db, db->pagbuf, db->pagbno))
+ != APR_SUCCESS)
+ return status;
+
+ } while (--smax);
+
+ /*
+ * if we are here, this is real bad news. After SPLTMAX splits,
+ * we still cannot fit the key. say goodnight.
+ */
+#if 0
+ (void) write(2, "sdbm: cannot insert after SPLTMAX attempts.\n", 44);
+#endif
+ /* ### ENOSPC not really appropriate but better than nothing */
+ return APR_ENOSPC;
+
+}
+
+/* Reads 'len' bytes from file 'f' at offset 'off' into buf.
+ * 'off' is given relative to the start of the file.
+ * If EOF is returned while reading, this is taken as success.
+ */
+static apr_status_t read_from(apr_file_t *f, void *buf,
+ apr_off_t off, apr_size_t len)
+{
+ apr_status_t status;
+
+ if ((status = apr_file_seek(f, APR_SET, &off)) != APR_SUCCESS ||
+ ((status = apr_file_read_full(f, buf, len, NULL)) != APR_SUCCESS)) {
+ /* if EOF is reached, pretend we read all zero's */
+ if (status == APR_EOF) {
+ memset(buf, 0, len);
+ status = APR_SUCCESS;
+ }
+ }
+
+ return status;
+}
+
+/*
+ * the following two routines will break if
+ * deletions aren't taken into account. (ndbm bug)
+ */
+APU_DECLARE(apr_status_t) apr_sdbm_firstkey(apr_sdbm_t *db,
+ apr_sdbm_datum_t *key)
+{
+ apr_status_t status;
+
+ if ((status = apr_sdbm_lock(db, APR_FLOCK_SHARED)) != APR_SUCCESS)
+ return status;
+
+ /*
+ * start at page 0
+ */
+ if ((status = read_from(db->pagf, db->pagbuf, OFF_PAG(0), PBLKSIZ))
+ == APR_SUCCESS) {
+ db->pagbno = 0;
+ db->blkptr = 0;
+ db->keyptr = 0;
+ status = getnext(key, db);
+ }
+
+ (void) apr_sdbm_unlock(db);
+
+ return status;
+}
+
+APU_DECLARE(apr_status_t) apr_sdbm_nextkey(apr_sdbm_t *db,
+ apr_sdbm_datum_t *key)
+{
+ apr_status_t status;
+
+ if ((status = apr_sdbm_lock(db, APR_FLOCK_SHARED)) != APR_SUCCESS)
+ return status;
+
+ status = getnext(key, db);
+
+ (void) apr_sdbm_unlock(db);
+
+ return status;
+}
+
+/*
+ * all important binary tree traversal
+ */
+static apr_status_t getpage(apr_sdbm_t *db, long hash)
+{
+ register int hbit;
+ register long dbit;
+ register long pagb;
+ apr_status_t status;
+
+ dbit = 0;
+ hbit = 0;
+ while (dbit < db->maxbno && getdbit(db, dbit))
+ dbit = 2 * dbit + ((hash & (1 << hbit++)) ? 2 : 1);
+
+ debug(("dbit: %d...", dbit));
+
+ db->curbit = dbit;
+ db->hmask = masks[hbit];
+
+ pagb = hash & db->hmask;
+ /*
+ * see if the block we need is already in memory.
+ * note: this lookaside cache has about 10% hit rate.
+ */
+ if (pagb != db->pagbno) {
+ /*
+ * note: here, we assume a "hole" is read as 0s.
+ * if not, must zero pagbuf first.
+ * ### joe: this assumption was surely never correct? but
+ * ### we make it so in read_from anyway.
+ */
+ if ((status = read_from(db->pagf, db->pagbuf, OFF_PAG(pagb), PBLKSIZ))
+ != APR_SUCCESS)
+ return status;
+
+ if (!chkpage(db->pagbuf))
+ return APR_ENOSPC; /* ### better error? */
+ db->pagbno = pagb;
+
+ debug(("pag read: %d\n", pagb));
+ }
+ return APR_SUCCESS;
+}
+
+static int getdbit(apr_sdbm_t *db, long dbit)
+{
+ register long c;
+ register long dirb;
+
+ c = dbit / BYTESIZ;
+ dirb = c / DBLKSIZ;
+
+ if (dirb != db->dirbno) {
+ if (read_from(db->dirf, db->dirbuf, OFF_DIR(dirb), DBLKSIZ)
+ != APR_SUCCESS)
+ return 0;
+
+ db->dirbno = dirb;
+
+ debug(("dir read: %d\n", dirb));
+ }
+
+ return db->dirbuf[c % DBLKSIZ] & (1 << dbit % BYTESIZ);
+}
+
+static apr_status_t setdbit(apr_sdbm_t *db, long dbit)
+{
+ register long c;
+ register long dirb;
+ apr_status_t status;
+ apr_off_t off;
+
+ c = dbit / BYTESIZ;
+ dirb = c / DBLKSIZ;
+
+ if (dirb != db->dirbno) {
+ if ((status = read_from(db->dirf, db->dirbuf, OFF_DIR(dirb), DBLKSIZ))
+ != APR_SUCCESS)
+ return status;
+
+ db->dirbno = dirb;
+
+ debug(("dir read: %d\n", dirb));
+ }
+
+ db->dirbuf[c % DBLKSIZ] |= (1 << dbit % BYTESIZ);
+
+ if (dbit >= db->maxbno)
+ db->maxbno += DBLKSIZ * BYTESIZ;
+
+ off = OFF_DIR(dirb);
+ if ((status = apr_file_seek(db->dirf, APR_SET, &off)) == APR_SUCCESS)
+ status = apr_file_write_full(db->dirf, db->dirbuf, DBLKSIZ, NULL);
+
+ return status;
+}
+
+/*
+* getnext - get the next key in the page, and if done with
+* the page, try the next page in sequence
+*/
+static apr_status_t getnext(apr_sdbm_datum_t *key, apr_sdbm_t *db)
+{
+ apr_status_t status;
+ for (;;) {
+ db->keyptr++;
+ *key = getnkey(db->pagbuf, db->keyptr);
+ if (key->dptr != NULL)
+ return APR_SUCCESS;
+ /*
+ * we either run out, or there is nothing on this page..
+ * try the next one... If we lost our position on the
+ * file, we will have to seek.
+ */
+ db->keyptr = 0;
+ if (db->pagbno != db->blkptr++) {
+ apr_off_t off = OFF_PAG(db->blkptr);
+ if ((status = apr_file_seek(db->pagf, APR_SET, &off)
+ != APR_SUCCESS))
+ return status;
+ }
+
+ db->pagbno = db->blkptr;
+ /* ### EOF acceptable here too? */
+ if ((status = apr_file_read_full(db->pagf, db->pagbuf, PBLKSIZ, NULL))
+ != APR_SUCCESS)
+ return status;
+ if (!chkpage(db->pagbuf))
+ return APR_EGENERAL; /* ### need better error */
+ }
+
+ /* NOTREACHED */
+}
+
+
+APU_DECLARE(int) apr_sdbm_rdonly(apr_sdbm_t *db)
+{
+ /* ### Should we return true if the first lock is a share lock,
+ * to reflect that apr_sdbm_store and apr_sdbm_delete will fail?
+ */
+ return (db->flags & SDBM_RDONLY) != 0;
+}
+
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * sdbm - ndbm work-alike hashed database library
+ * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
+ * author: oz@nexus.yorku.ca
+ * status: ex-public domain. keep it that way.
+ *
+ * hashing routine
+ */
+
+#include "apr_sdbm.h"
+#include "sdbm_private.h"
+
+/*
+ * polynomial conversion ignoring overflows
+ * [this seems to work remarkably well, in fact better
+ * then the ndbm hash function. Replace at your own risk]
+ * use: 65599 nice.
+ * 65587 even better.
+ */
+long sdbm_hash(const char *str, int len)
+{
+ register unsigned long n = 0;
+
+#define DUFF /* go ahead and use the loop-unrolled version */
+#ifdef DUFF
+
+#define HASHC n = *str++ + 65599 * n
+
+ if (len > 0) {
+ register int loop = (len + 8 - 1) >> 3;
+
+ switch(len & (8 - 1)) {
+ case 0: do {
+ HASHC; case 7: HASHC;
+ case 6: HASHC; case 5: HASHC;
+ case 4: HASHC; case 3: HASHC;
+ case 2: HASHC; case 1: HASHC;
+ } while (--loop);
+ }
+
+ }
+#else
+ while (len--)
+ n = *str++ + 65599 * n;
+#endif
+ return n;
+}
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_file_info.h"
+#include "apr_file_io.h"
+#include "apr_sdbm.h"
+
+#include "sdbm_private.h"
+#include "sdbm_tune.h"
+
+/* NOTE: this function blocks until it acquires the lock */
+APU_DECLARE(apr_status_t) apr_sdbm_lock(apr_sdbm_t *db, int type)
+{
+ apr_status_t status;
+
+ if (!(type == APR_FLOCK_SHARED || type == APR_FLOCK_EXCLUSIVE))
+ return APR_EINVAL;
+
+ if (db->flags & SDBM_EXCLUSIVE_LOCK) {
+ ++db->lckcnt;
+ return APR_SUCCESS;
+ }
+ else if (db->flags & SDBM_SHARED_LOCK) {
+ /*
+ * Cannot promote a shared lock to an exlusive lock
+ * in a cross-platform compatibile manner.
+ */
+ if (type == APR_FLOCK_EXCLUSIVE)
+ return APR_EINVAL;
+ ++db->lckcnt;
+ return APR_SUCCESS;
+ }
+ /*
+ * zero size: either a fresh database, or one with a single,
+ * unsplit data page: dirpage is all zeros.
+ */
+ if ((status = apr_file_lock(db->dirf, type)) == APR_SUCCESS)
+ {
+ apr_finfo_t finfo;
+ if ((status = apr_file_info_get(&finfo, APR_FINFO_SIZE, db->dirf))
+ != APR_SUCCESS) {
+ (void) apr_file_unlock(db->dirf);
+ return status;
+ }
+
+ SDBM_INVALIDATE_CACHE(db, finfo);
+
+ ++db->lckcnt;
+ if (type == APR_FLOCK_SHARED)
+ db->flags |= SDBM_SHARED_LOCK;
+ else if (type == APR_FLOCK_EXCLUSIVE)
+ db->flags |= SDBM_EXCLUSIVE_LOCK;
+ }
+ return status;
+}
+
+APU_DECLARE(apr_status_t) apr_sdbm_unlock(apr_sdbm_t *db)
+{
+ if (!(db->flags & (SDBM_SHARED_LOCK | SDBM_EXCLUSIVE_LOCK)))
+ return APR_EINVAL;
+ if (--db->lckcnt > 0)
+ return APR_SUCCESS;
+ db->flags &= ~(SDBM_SHARED_LOCK | SDBM_EXCLUSIVE_LOCK);
+ return apr_file_unlock(db->dirf);
+}
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * sdbm - ndbm work-alike hashed database library
+ * based on Per-Aake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
+ * author: oz@nexus.yorku.ca
+ * status: ex-public domain.
+ *
+ * page-level routines
+ */
+
+#include "apr_sdbm.h"
+
+#include "sdbm_tune.h"
+#include "sdbm_pair.h"
+#include "sdbm_private.h"
+
+#include <string.h> /* for memset() */
+
+
+#define exhash(item) sdbm_hash((item).dptr, (item).dsize)
+
+/*
+ * forward
+ */
+static int seepair(char *, int, char *, int);
+
+/*
+ * page format:
+ * +------------------------------+
+ * ino | n | keyoff | datoff | keyoff |
+ * +------------+--------+--------+
+ * | datoff | - - - ----> |
+ * +--------+---------------------+
+ * | F R E E A R E A |
+ * +--------------+---------------+
+ * | <---- - - - | data |
+ * +--------+-----+----+----------+
+ * | key | data | key |
+ * +--------+----------+----------+
+ *
+ * calculating the offsets for free area: if the number
+ * of entries (ino[0]) is zero, the offset to the END of
+ * the free area is the block size. Otherwise, it is the
+ * nth (ino[ino[0]]) entry's offset.
+ */
+
+int
+fitpair(pag, need)
+char *pag;
+int need;
+{
+ register int n;
+ register int off;
+ register int avail;
+ register short *ino = (short *) pag;
+
+ off = ((n = ino[0]) > 0) ? ino[n] : PBLKSIZ;
+ avail = off - (n + 1) * sizeof(short);
+ need += 2 * sizeof(short);
+
+ debug(("avail %d need %d\n", avail, need));
+
+ return need <= avail;
+}
+
+void
+putpair(pag, key, val)
+char *pag;
+apr_sdbm_datum_t key;
+apr_sdbm_datum_t val;
+{
+ register int n;
+ register int off;
+ register short *ino = (short *) pag;
+
+ off = ((n = ino[0]) > 0) ? ino[n] : PBLKSIZ;
+/*
+ * enter the key first
+ */
+ off -= key.dsize;
+ (void) memcpy(pag + off, key.dptr, key.dsize);
+ ino[n + 1] = off;
+/*
+ * now the data
+ */
+ off -= val.dsize;
+ (void) memcpy(pag + off, val.dptr, val.dsize);
+ ino[n + 2] = off;
+/*
+ * adjust item count
+ */
+ ino[0] += 2;
+}
+
+apr_sdbm_datum_t
+getpair(pag, key)
+char *pag;
+apr_sdbm_datum_t key;
+{
+ register int i;
+ register int n;
+ apr_sdbm_datum_t val;
+ register short *ino = (short *) pag;
+
+ if ((n = ino[0]) == 0)
+ return sdbm_nullitem;
+
+ if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
+ return sdbm_nullitem;
+
+ val.dptr = pag + ino[i + 1];
+ val.dsize = ino[i] - ino[i + 1];
+ return val;
+}
+
+int
+duppair(pag, key)
+char *pag;
+apr_sdbm_datum_t key;
+{
+ register short *ino = (short *) pag;
+ return ino[0] > 0 && seepair(pag, ino[0], key.dptr, key.dsize) > 0;
+}
+
+apr_sdbm_datum_t
+getnkey(pag, num)
+char *pag;
+int num;
+{
+ apr_sdbm_datum_t key;
+ register int off;
+ register short *ino = (short *) pag;
+
+ num = num * 2 - 1;
+ if (ino[0] == 0 || num > ino[0])
+ return sdbm_nullitem;
+
+ off = (num > 1) ? ino[num - 1] : PBLKSIZ;
+
+ key.dptr = pag + ino[num];
+ key.dsize = off - ino[num];
+
+ return key;
+}
+
+int
+delpair(pag, key)
+char *pag;
+apr_sdbm_datum_t key;
+{
+ register int n;
+ register int i;
+ register short *ino = (short *) pag;
+
+ if ((n = ino[0]) == 0)
+ return 0;
+
+ if ((i = seepair(pag, n, key.dptr, key.dsize)) == 0)
+ return 0;
+/*
+ * found the key. if it is the last entry
+ * [i.e. i == n - 1] we just adjust the entry count.
+ * hard case: move all data down onto the deleted pair,
+ * shift offsets onto deleted offsets, and adjust them.
+ * [note: 0 < i < n]
+ */
+ if (i < n - 1) {
+ register int m;
+ register char *dst = pag + (i == 1 ? PBLKSIZ : ino[i - 1]);
+ register char *src = pag + ino[i + 1];
+ register int zoo = dst - src;
+
+ debug(("free-up %d ", zoo));
+/*
+ * shift data/keys down
+ */
+ m = ino[i + 1] - ino[n];
+
+#undef DUFF /* just use memmove. it should be plenty fast. */
+#ifdef DUFF
+#define MOVB *--dst = *--src
+
+ if (m > 0) {
+ register int loop = (m + 8 - 1) >> 3;
+
+ switch (m & (8 - 1)) {
+ case 0: do {
+ MOVB; case 7: MOVB;
+ case 6: MOVB; case 5: MOVB;
+ case 4: MOVB; case 3: MOVB;
+ case 2: MOVB; case 1: MOVB;
+ } while (--loop);
+ }
+ }
+#else
+ dst -= m;
+ src -= m;
+ memmove(dst, src, m);
+#endif
+
+/*
+ * adjust offset index up
+ */
+ while (i < n - 1) {
+ ino[i] = ino[i + 2] + zoo;
+ i++;
+ }
+ }
+ ino[0] -= 2;
+ return 1;
+}
+
+/*
+ * search for the key in the page.
+ * return offset index in the range 0 < i < n.
+ * return 0 if not found.
+ */
+static int
+seepair(pag, n, key, siz)
+char *pag;
+register int n;
+register char *key;
+register int siz;
+{
+ register int i;
+ register int off = PBLKSIZ;
+ register short *ino = (short *) pag;
+
+ for (i = 1; i < n; i += 2) {
+ if (siz == off - ino[i] &&
+ memcmp(key, pag + ino[i], siz) == 0)
+ return i;
+ off = ino[i + 1];
+ }
+ return 0;
+}
+
+void
+splpage(pag, new, sbit)
+char *pag;
+char *new;
+long sbit;
+{
+ apr_sdbm_datum_t key;
+ apr_sdbm_datum_t val;
+
+ register int n;
+ register int off = PBLKSIZ;
+ char cur[PBLKSIZ];
+ register short *ino = (short *) cur;
+
+ (void) memcpy(cur, pag, PBLKSIZ);
+ (void) memset(pag, 0, PBLKSIZ);
+ (void) memset(new, 0, PBLKSIZ);
+
+ n = ino[0];
+ for (ino++; n > 0; ino += 2) {
+ key.dptr = cur + ino[0];
+ key.dsize = off - ino[0];
+ val.dptr = cur + ino[1];
+ val.dsize = ino[0] - ino[1];
+/*
+ * select the page pointer (by looking at sbit) and insert
+ */
+ (void) putpair((exhash(key) & sbit) ? new : pag, key, val);
+
+ off = ino[1];
+ n -= 2;
+ }
+
+ debug(("%d split %d/%d\n", ((short *) cur)[0] / 2,
+ ((short *) new)[0] / 2,
+ ((short *) pag)[0] / 2));
+}
+
+/*
+ * check page sanity:
+ * number of entries should be something
+ * reasonable, and all offsets in the index should be in order.
+ * this could be made more rigorous.
+ */
+int
+chkpage(pag)
+char *pag;
+{
+ register int n;
+ register int off;
+ register short *ino = (short *) pag;
+
+ if ((n = ino[0]) < 0 || n > PBLKSIZ / sizeof(short))
+ return 0;
+
+ if (n > 0) {
+ off = PBLKSIZ;
+ for (ino++; n > 0; ino += 2) {
+ if (ino[0] > off || ino[1] > off ||
+ ino[1] > ino[0])
+ return 0;
+ off = ino[1];
+ n -= 2;
+ }
+ }
+ return 1;
+}
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SDBM_PAIR_H
+#define SDBM_PAIR_H
+
+/* Mini EMBED (pair.c) */
+#define chkpage apu__sdbm_chkpage
+#define delpair apu__sdbm_delpair
+#define duppair apu__sdbm_duppair
+#define fitpair apu__sdbm_fitpair
+#define getnkey apu__sdbm_getnkey
+#define getpair apu__sdbm_getpair
+#define putpair apu__sdbm_putpair
+#define splpage apu__sdbm_splpage
+
+int fitpair(char *, int);
+void putpair(char *, apr_sdbm_datum_t, apr_sdbm_datum_t);
+apr_sdbm_datum_t getpair(char *, apr_sdbm_datum_t);
+int delpair(char *, apr_sdbm_datum_t);
+int chkpage (char *);
+apr_sdbm_datum_t getnkey(char *, int);
+void splpage(char *, char *, long);
+int duppair(char *, apr_sdbm_datum_t);
+
+#endif /* SDBM_PAIR_H */
+
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * sdbm - ndbm work-alike hashed database library
+ * based on Per-Ake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
+ * author: oz@nexus.yorku.ca
+ */
+
+#ifndef SDBM_PRIVATE_H
+#define SDBM_PRIVATE_H
+
+#include "apr.h"
+#include "apr_pools.h"
+#include "apr_file_io.h"
+#include "apr_errno.h" /* for apr_status_t */
+
+#if 0
+/* if the block/page size is increased, it breaks perl apr_sdbm_t compatibility */
+#define DBLKSIZ 16384
+#define PBLKSIZ 8192
+#define PAIRMAX 8008 /* arbitrary on PBLKSIZ-N */
+#else
+#define DBLKSIZ 4096
+#define PBLKSIZ 1024
+#define PAIRMAX 1008 /* arbitrary on PBLKSIZ-N */
+#endif
+#define SPLTMAX 10 /* maximum allowed splits */
+
+/* for apr_sdbm_t.flags */
+#define SDBM_RDONLY 0x1 /* data base open read-only */
+#define SDBM_SHARED 0x2 /* data base open for sharing */
+#define SDBM_SHARED_LOCK 0x4 /* data base locked for shared read */
+#define SDBM_EXCLUSIVE_LOCK 0x8 /* data base locked for write */
+
+struct apr_sdbm_t {
+ apr_pool_t *pool;
+ apr_file_t *dirf; /* directory file descriptor */
+ apr_file_t *pagf; /* page file descriptor */
+ apr_int32_t flags; /* status/error flags, see below */
+ long maxbno; /* size of dirfile in bits */
+ long curbit; /* current bit number */
+ long hmask; /* current hash mask */
+ long blkptr; /* current block for nextkey */
+ int keyptr; /* current key for nextkey */
+ long blkno; /* current page to read/write */
+ long pagbno; /* current page in pagbuf */
+ char pagbuf[PBLKSIZ]; /* page file block buffer */
+ long dirbno; /* current block in dirbuf */
+ char dirbuf[DBLKSIZ]; /* directory file block buffer */
+ int lckcnt; /* number of calls to sdbm_lock */
+};
+
+
+#define sdbm_hash apu__sdbm_hash
+#define sdbm_nullitem apu__sdbm_nullitem
+
+extern const apr_sdbm_datum_t sdbm_nullitem;
+
+long sdbm_hash(const char *str, int len);
+
+/*
+ * zero the cache
+ */
+#define SDBM_INVALIDATE_CACHE(db, finfo) \
+ do { db->dirbno = (!finfo.size) ? 0 : -1; \
+ db->pagbno = -1; \
+ db->maxbno = (long)(finfo.size * BYTESIZ); \
+ } while (0);
+
+#endif /* SDBM_PRIVATE_H */
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * sdbm - ndbm work-alike hashed database library
+ * tuning and portability constructs [not nearly enough]
+ * author: oz@nexus.yorku.ca
+ */
+
+#ifndef SDBM_TUNE_H
+#define SDBM_TUNE_H
+
+#include "apr_errno.h"
+
+/* ### this might be better off as sizeof(char *) */
+#define BYTESIZ 8
+
+/*
+ * misc
+ */
+#ifdef DEBUG
+#define debug(x) printf x
+#else
+#define debug(x)
+#endif
+
+#endif /* SDBM_TUNE_H */
--- /dev/null
+PROJECT_NAME="Apache Portable Runtime Utility Library"
+
+INPUT=.
+QUIET=YES
+RECURSIVE=YES
+FILE_PATTERNS=*.h
+
+OUTPUT_DIRECTORY=docs/dox
+
+MACRO_EXPANSION=YES
+EXPAND_ONLY_PREDEF=YES
+#EXPAND_AS_DEFINED=
+# not sure why this doesn't work as EXPAND_AS_DEFINED, it should!
+PREDEFINED="APU_DECLARE(x)=x" \
+ "APU_DECLARE_NONSTD(x)=x" \
+ "APU_DECLARE_DATA" \
+ "APR_HAS_MMAP" \
+ "APR_HAS_THREADS" \
+ "APR_HAS_XLATE" \
+ "__attribute__(x)=" \
+ DOXYGEN=
+
+OPTIMIZE_OUTPUT_FOR_C=YES
+
+FULL_PATH_NAMES=YES
+CASE_SENSE_NAMES=NO
+# some autoconf guru needs to make configure set this correctly...
+#STRIP_FROM_PATH=/root/apache/httpd-2.0-8/srclib/apr-util
+
+GENERATE_TAGFILE=docs/dox/apu.tag
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* base64 encoder/decoder. Originally part of main/util.c
+ * but moved here so that support/ab and apr_sha1.c could
+ * use it. This meant removing the apr_palloc()s and adding
+ * ugly 'len' functions, which is quite a nasty cost.
+ */
+
+#include "apr_base64.h"
+#if APR_CHARSET_EBCDIC
+#include "apr_xlate.h"
+#endif /* APR_CHARSET_EBCDIC */
+
+/* aaaack but it's fast and const should make it shared text page. */
+static const unsigned char pr2six[256] =
+{
+#if !APR_CHARSET_EBCDIC
+ /* ASCII table */
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
+ 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
+ 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
+#else /*APR_CHARSET_EBCDIC*/
+ /* EBCDIC table */
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 63, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 64, 64, 64, 64, 64, 64,
+ 64, 35, 36, 37, 38, 39, 40, 41, 42, 43, 64, 64, 64, 64, 64, 64,
+ 64, 64, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, 64,
+ 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
+ 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 64, 64, 64, 64, 64, 64,
+ 64, 9, 10, 11, 12, 13, 14, 15, 16, 17, 64, 64, 64, 64, 64, 64,
+ 64, 64, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64, 64,
+ 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64
+#endif /*APR_CHARSET_EBCDIC*/
+};
+
+#if APR_CHARSET_EBCDIC
+static apr_xlate_t *xlate_to_ebcdic;
+static unsigned char os_toascii[256];
+
+APU_DECLARE(apr_status_t) apr_base64init_ebcdic(apr_xlate_t *to_ascii,
+ apr_xlate_t *to_ebcdic)
+{
+ int i;
+ apr_size_t inbytes_left, outbytes_left;
+ apr_status_t rv;
+ int onoff;
+
+ /* Only single-byte conversion is supported.
+ */
+ rv = apr_xlate_sb_get(to_ascii, &onoff);
+ if (rv) {
+ return rv;
+ }
+ if (!onoff) { /* If conversion is not single-byte-only */
+ return APR_EINVAL;
+ }
+ rv = apr_xlate_sb_get(to_ebcdic, &onoff);
+ if (rv) {
+ return rv;
+ }
+ if (!onoff) { /* If conversion is not single-byte-only */
+ return APR_EINVAL;
+ }
+ xlate_to_ebcdic = to_ebcdic;
+ for (i = 0; i < sizeof(os_toascii); i++) {
+ os_toascii[i] = i;
+ }
+ inbytes_left = outbytes_left = sizeof(os_toascii);
+ apr_xlate_conv_buffer(to_ascii, os_toascii, &inbytes_left,
+ os_toascii, &outbytes_left);
+
+ return APR_SUCCESS;
+}
+#endif /*APR_CHARSET_EBCDIC*/
+
+APU_DECLARE(int) apr_base64_decode_len(const char *bufcoded)
+{
+ int nbytesdecoded;
+ register const unsigned char *bufin;
+ register int nprbytes;
+
+ bufin = (const unsigned char *) bufcoded;
+ while (pr2six[*(bufin++)] <= 63);
+
+ nprbytes = (bufin - (const unsigned char *) bufcoded) - 1;
+ nbytesdecoded = ((nprbytes + 3) / 4) * 3;
+
+ return nbytesdecoded + 1;
+}
+
+APU_DECLARE(int) apr_base64_decode(char *bufplain, const char *bufcoded)
+{
+#if APR_CHARSET_EBCDIC
+ apr_size_t inbytes_left, outbytes_left;
+#endif /* APR_CHARSET_EBCDIC */
+ int len;
+
+ len = apr_base64_decode_binary((unsigned char *) bufplain, bufcoded);
+#if APR_CHARSET_EBCDIC
+ inbytes_left = outbytes_left = len;
+ apr_xlate_conv_buffer(xlate_to_ebcdic, bufplain, &inbytes_left,
+ bufplain, &outbytes_left);
+#endif /* APR_CHARSET_EBCDIC */
+ bufplain[len] = '\0';
+ return len;
+}
+
+/* This is the same as apr_base64_decode() except on EBCDIC machines, where
+ * the conversion of the output to ebcdic is left out.
+ */
+APU_DECLARE(int) apr_base64_decode_binary(unsigned char *bufplain,
+ const char *bufcoded)
+{
+ int nbytesdecoded;
+ register const unsigned char *bufin;
+ register unsigned char *bufout;
+ register int nprbytes;
+
+ bufin = (const unsigned char *) bufcoded;
+ while (pr2six[*(bufin++)] <= 63);
+ nprbytes = (bufin - (const unsigned char *) bufcoded) - 1;
+ nbytesdecoded = ((nprbytes + 3) / 4) * 3;
+
+ bufout = (unsigned char *) bufplain;
+ bufin = (const unsigned char *) bufcoded;
+
+ while (nprbytes > 4) {
+ *(bufout++) =
+ (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
+ *(bufout++) =
+ (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
+ *(bufout++) =
+ (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
+ bufin += 4;
+ nprbytes -= 4;
+ }
+
+ /* Note: (nprbytes == 1) would be an error, so just ingore that case */
+ if (nprbytes > 1) {
+ *(bufout++) =
+ (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
+ }
+ if (nprbytes > 2) {
+ *(bufout++) =
+ (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
+ }
+ if (nprbytes > 3) {
+ *(bufout++) =
+ (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
+ }
+
+ nbytesdecoded -= (4 - nprbytes) & 3;
+ return nbytesdecoded;
+}
+
+static const char basis_64[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+APU_DECLARE(int) apr_base64_encode_len(int len)
+{
+ return ((len + 2) / 3 * 4) + 1;
+}
+
+APU_DECLARE(int) apr_base64_encode(char *encoded, const char *string, int len)
+{
+#if !APR_CHARSET_EBCDIC
+ return apr_base64_encode_binary(encoded, (const unsigned char *) string, len);
+#else /* APR_CHARSET_EBCDIC */
+ int i;
+ char *p;
+
+ p = encoded;
+ for (i = 0; i < len - 2; i += 3) {
+ *p++ = basis_64[(os_toascii[string[i]] >> 2) & 0x3F];
+ *p++ = basis_64[((os_toascii[string[i]] & 0x3) << 4) |
+ ((int) (os_toascii[string[i + 1]] & 0xF0) >> 4)];
+ *p++ = basis_64[((os_toascii[string[i + 1]] & 0xF) << 2) |
+ ((int) (os_toascii[string[i + 2]] & 0xC0) >> 6)];
+ *p++ = basis_64[os_toascii[string[i + 2]] & 0x3F];
+ }
+ if (i < len) {
+ *p++ = basis_64[(os_toascii[string[i]] >> 2) & 0x3F];
+ if (i == (len - 1)) {
+ *p++ = basis_64[((os_toascii[string[i]] & 0x3) << 4)];
+ *p++ = '=';
+ }
+ else {
+ *p++ = basis_64[((os_toascii[string[i]] & 0x3) << 4) |
+ ((int) (os_toascii[string[i + 1]] & 0xF0) >> 4)];
+ *p++ = basis_64[((os_toascii[string[i + 1]] & 0xF) << 2)];
+ }
+ *p++ = '=';
+ }
+
+ *p++ = '\0';
+ return p - encoded;
+#endif /* APR_CHARSET_EBCDIC */
+}
+
+/* This is the same as apr_base64_encode() except on EBCDIC machines, where
+ * the conversion of the input to ascii is left out.
+ */
+APU_DECLARE(int) apr_base64_encode_binary(char *encoded,
+ const unsigned char *string, int len)
+{
+ int i;
+ char *p;
+
+ p = encoded;
+ for (i = 0; i < len - 2; i += 3) {
+ *p++ = basis_64[(string[i] >> 2) & 0x3F];
+ *p++ = basis_64[((string[i] & 0x3) << 4) |
+ ((int) (string[i + 1] & 0xF0) >> 4)];
+ *p++ = basis_64[((string[i + 1] & 0xF) << 2) |
+ ((int) (string[i + 2] & 0xC0) >> 6)];
+ *p++ = basis_64[string[i + 2] & 0x3F];
+ }
+ if (i < len) {
+ *p++ = basis_64[(string[i] >> 2) & 0x3F];
+ if (i == (len - 1)) {
+ *p++ = basis_64[((string[i] & 0x3) << 4)];
+ *p++ = '=';
+ }
+ else {
+ *p++ = basis_64[((string[i] & 0x3) << 4) |
+ ((int) (string[i + 1] & 0xF0) >> 4)];
+ *p++ = basis_64[((string[i + 1] & 0xF) << 2)];
+ }
+ *p++ = '=';
+ }
+
+ *p++ = '\0';
+ return p - encoded;
+}
--- /dev/null
+#
+# export_vars.sh
+#
+# This shell script is used to export vars to the application using the
+# APRUTIL library. This script should be "sourced" to ensure the variable
+# values are set within the calling script's context. For example:
+#
+# $ . path/to/apr-util/export_vars.sh
+#
+
+APRUTIL_EXPORT_INCLUDES="@APRUTIL_INCLUDES@"
+APRUTIL_EXPORT_LIBS="@APRUTIL_EXPORT_LIBS@"
+APRUTIL_LDFLAGS="@APRUTIL_LDFLAGS@"
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "apr_pools.h"
+#include "apr_tables.h"
+#include "apr.h"
+#include "apr_hooks.h"
+#include "apr_hash.h"
+#include "apr_optional_hooks.h"
+#include "apr_optional.h"
+#define APR_WANT_MEMFUNC
+#define APR_WANT_STRFUNC
+#include "apr_want.h"
+
+#if 0
+#define apr_palloc(pool,size) malloc(size)
+#endif
+
+APU_DECLARE_DATA apr_pool_t *apr_hook_global_pool = NULL;
+APU_DECLARE_DATA int apr_hook_debug_enabled = 0;
+APU_DECLARE_DATA const char *apr_hook_debug_current = NULL;
+
+/** @deprecated @see apr_hook_global_pool */
+APU_DECLARE_DATA apr_pool_t *apr_global_hook_pool = NULL;
+
+/** @deprecated @see apr_hook_debug_enabled */
+APU_DECLARE_DATA int apr_debug_module_hooks = 0;
+
+/** @deprecated @see apr_hook_debug_current */
+APU_DECLARE_DATA const char *apr_current_hooking_module = NULL;
+
+/* NB: This must echo the LINK_##name structure */
+typedef struct
+{
+ void (*dummy)(void *);
+ const char *szName;
+ const char * const *aszPredecessors;
+ const char * const *aszSuccessors;
+ int nOrder;
+} TSortData;
+
+typedef struct tsort_
+{
+ void *pData;
+ int nPredecessors;
+ struct tsort_ **ppPredecessors;
+ struct tsort_ *pNext;
+} TSort;
+
+#ifdef NETWARE
+#include "apr_private.h"
+#define get_apd APP_DATA* apd = (APP_DATA*)get_app_data(gLibId);
+#define s_aHooksToSort ((apr_array_header_t *)(apd->gs_aHooksToSort))
+#define s_phOptionalHooks ((apr_hash_t *)(apd->gs_phOptionalHooks))
+#define s_phOptionalFunctions ((apr_hash_t *)(apd->gs_phOptionalFunctions))
+#endif
+
+static int crude_order(const void *a_,const void *b_)
+{
+ const TSortData *a=a_;
+ const TSortData *b=b_;
+
+ return a->nOrder-b->nOrder;
+}
+
+static TSort *prepare(apr_pool_t *p,TSortData *pItems,int nItems)
+{
+ TSort *pData=apr_palloc(p,nItems*sizeof *pData);
+ int n;
+
+ qsort(pItems,nItems,sizeof *pItems,crude_order);
+ for(n=0 ; n < nItems ; ++n) {
+ pData[n].nPredecessors=0;
+ pData[n].ppPredecessors=apr_pcalloc(p,nItems*sizeof *pData[n].ppPredecessors);
+ pData[n].pNext=NULL;
+ pData[n].pData=&pItems[n];
+ }
+
+ for(n=0 ; n < nItems ; ++n) {
+ int i,k;
+
+ for(i=0 ; pItems[n].aszPredecessors && pItems[n].aszPredecessors[i] ; ++i)
+ for(k=0 ; k < nItems ; ++k)
+ if(!strcmp(pItems[k].szName,pItems[n].aszPredecessors[i])) {
+ int l;
+
+ for(l=0 ; l < pData[n].nPredecessors ; ++l)
+ if(pData[n].ppPredecessors[l] == &pData[k])
+ goto got_it;
+ pData[n].ppPredecessors[pData[n].nPredecessors]=&pData[k];
+ ++pData[n].nPredecessors;
+ got_it:
+ break;
+ }
+ for(i=0 ; pItems[n].aszSuccessors && pItems[n].aszSuccessors[i] ; ++i)
+ for(k=0 ; k < nItems ; ++k)
+ if(!strcmp(pItems[k].szName,pItems[n].aszSuccessors[i])) {
+ int l;
+
+ for(l=0 ; l < pData[k].nPredecessors ; ++l)
+ if(pData[k].ppPredecessors[l] == &pData[n])
+ goto got_it2;
+ pData[k].ppPredecessors[pData[k].nPredecessors]=&pData[n];
+ ++pData[k].nPredecessors;
+ got_it2:
+ break;
+ }
+ }
+
+ return pData;
+}
+
+/* Topologically sort, dragging out-of-order items to the front. Note that
+ this tends to preserve things that want to be near the front better, and
+ changing that behaviour might compromise some of Apache's behaviour (in
+ particular, mod_log_forensic might otherwise get pushed to the end, and
+ core.c's log open function used to end up at the end when pushing items
+ to the back was the methedology). Also note that the algorithm could
+ go back to its original simplicity by sorting from the back instead of
+ the front.
+*/
+static TSort *tsort(TSort *pData,int nItems)
+{
+ int nTotal;
+ TSort *pHead=NULL;
+ TSort *pTail=NULL;
+
+ for(nTotal=0 ; nTotal < nItems ; ++nTotal) {
+ int n,i,k;
+
+ for(n=0 ; ; ++n) {
+ if(n == nItems)
+ assert(0); /* we have a loop... */
+ if(!pData[n].pNext) {
+ if(pData[n].nPredecessors) {
+ for(k=0 ; ; ++k) {
+ assert(k < nItems);
+ if(pData[n].ppPredecessors[k])
+ break;
+ }
+ for(i=0 ; ; ++i) {
+ assert(i < nItems);
+ if(&pData[i] == pData[n].ppPredecessors[k]) {
+ n=i-1;
+ break;
+ }
+ }
+ } else
+ break;
+ }
+ }
+ if(pTail)
+ pTail->pNext=&pData[n];
+ else
+ pHead=&pData[n];
+ pTail=&pData[n];
+ pTail->pNext=pTail; /* fudge it so it looks linked */
+ for(i=0 ; i < nItems ; ++i)
+ for(k=0 ; k < nItems ; ++k)
+ if(pData[i].ppPredecessors[k] == &pData[n]) {
+ --pData[i].nPredecessors;
+ pData[i].ppPredecessors[k]=NULL;
+ break;
+ }
+ }
+ pTail->pNext=NULL; /* unfudge the tail */
+ return pHead;
+}
+
+static apr_array_header_t *sort_hook(apr_array_header_t *pHooks,
+ const char *szName)
+{
+ apr_pool_t *p;
+ TSort *pSort;
+ apr_array_header_t *pNew;
+ int n;
+
+ apr_pool_create(&p, apr_hook_global_pool);
+ pSort=prepare(p,(TSortData *)pHooks->elts,pHooks->nelts);
+ pSort=tsort(pSort,pHooks->nelts);
+ pNew=apr_array_make(apr_hook_global_pool,pHooks->nelts,sizeof(TSortData));
+ if(apr_hook_debug_enabled)
+ printf("Sorting %s:",szName);
+ for(n=0 ; pSort ; pSort=pSort->pNext,++n) {
+ TSortData *pHook;
+ assert(n < pHooks->nelts);
+ pHook=apr_array_push(pNew);
+ memcpy(pHook,pSort->pData,sizeof *pHook);
+ if(apr_hook_debug_enabled)
+ printf(" %s",pHook->szName);
+ }
+ if(apr_hook_debug_enabled)
+ fputc('\n',stdout);
+ return pNew;
+}
+
+#ifndef NETWARE
+static apr_array_header_t *s_aHooksToSort;
+#endif
+
+typedef struct
+{
+ const char *szHookName;
+ apr_array_header_t **paHooks;
+} HookSortEntry;
+
+APU_DECLARE(void) apr_hook_sort_register(const char *szHookName,
+ apr_array_header_t **paHooks)
+{
+#ifdef NETWARE
+ get_apd
+#endif
+ HookSortEntry *pEntry;
+
+ if(!s_aHooksToSort)
+ s_aHooksToSort=apr_array_make(apr_hook_global_pool,1,sizeof(HookSortEntry));
+ pEntry=apr_array_push(s_aHooksToSort);
+ pEntry->szHookName=szHookName;
+ pEntry->paHooks=paHooks;
+}
+
+APU_DECLARE(void) apr_hook_sort_all(void)
+{
+#ifdef NETWARE
+ get_apd
+#endif
+ int n;
+
+ for(n=0 ; n < s_aHooksToSort->nelts ; ++n) {
+ HookSortEntry *pEntry=&((HookSortEntry *)s_aHooksToSort->elts)[n];
+ *pEntry->paHooks=sort_hook(*pEntry->paHooks,pEntry->szHookName);
+ }
+}
+
+#ifndef NETWARE
+static apr_hash_t *s_phOptionalHooks;
+static apr_hash_t *s_phOptionalFunctions;
+#endif
+
+APU_DECLARE(void) apr_hook_deregister_all(void)
+{
+#ifdef NETWARE
+ get_apd
+#endif
+ int n;
+
+ for(n=0 ; n < s_aHooksToSort->nelts ; ++n) {
+ HookSortEntry *pEntry=&((HookSortEntry *)s_aHooksToSort->elts)[n];
+ *pEntry->paHooks=NULL;
+ }
+ s_aHooksToSort=NULL;
+ s_phOptionalHooks=NULL;
+ s_phOptionalFunctions=NULL;
+}
+
+APU_DECLARE(void) apr_hook_debug_show(const char *szName,
+ const char * const *aszPre,
+ const char * const *aszSucc)
+{
+ int nFirst;
+
+ printf(" Hooked %s",szName);
+ if(aszPre) {
+ fputs(" pre(",stdout);
+ nFirst=1;
+ while(*aszPre) {
+ if(!nFirst)
+ fputc(',',stdout);
+ nFirst=0;
+ fputs(*aszPre,stdout);
+ ++aszPre;
+ }
+ fputc(')',stdout);
+ }
+ if(aszSucc) {
+ fputs(" succ(",stdout);
+ nFirst=1;
+ while(*aszSucc) {
+ if(!nFirst)
+ fputc(',',stdout);
+ nFirst=0;
+ fputs(*aszSucc,stdout);
+ ++aszSucc;
+ }
+ fputc(')',stdout);
+ }
+ fputc('\n',stdout);
+}
+
+/* Optional hook support */
+
+APR_DECLARE_EXTERNAL_HOOK(apr,APU,void,_optional,(void))
+
+APU_DECLARE(apr_array_header_t *) apr_optional_hook_get(const char *szName)
+{
+#ifdef NETWARE
+ get_apd
+#endif
+ apr_array_header_t **ppArray;
+
+ if(!s_phOptionalHooks)
+ return NULL;
+ ppArray=apr_hash_get(s_phOptionalHooks,szName,strlen(szName));
+ if(!ppArray)
+ return NULL;
+ return *ppArray;
+}
+
+APU_DECLARE(void) apr_optional_hook_add(const char *szName,void (*pfn)(void),
+ const char * const *aszPre,
+ const char * const *aszSucc,int nOrder)
+{
+#ifdef NETWARE
+ get_apd
+#endif
+ apr_array_header_t *pArray=apr_optional_hook_get(szName);
+ apr_LINK__optional_t *pHook;
+
+ if(!pArray) {
+ apr_array_header_t **ppArray;
+
+ pArray=apr_array_make(apr_hook_global_pool,1,
+ sizeof(apr_LINK__optional_t));
+ if(!s_phOptionalHooks)
+ s_phOptionalHooks=apr_hash_make(apr_hook_global_pool);
+ ppArray=apr_palloc(apr_hook_global_pool,sizeof *ppArray);
+ *ppArray=pArray;
+ apr_hash_set(s_phOptionalHooks,szName,strlen(szName),ppArray);
+ apr_hook_sort_register(szName,ppArray);
+ }
+ pHook=apr_array_push(pArray);
+ pHook->pFunc=pfn;
+ pHook->aszPredecessors=aszPre;
+ pHook->aszSuccessors=aszSucc;
+ pHook->nOrder=nOrder;
+ pHook->szName=apr_hook_debug_current;
+ if(apr_hook_debug_enabled)
+ apr_hook_debug_show(szName,aszPre,aszSucc);
+}
+
+/* optional function support */
+
+APU_DECLARE(apr_opt_fn_t *) apr_dynamic_fn_retrieve(const char *szName)
+{
+#ifdef NETWARE
+ get_apd
+#endif
+ if(!s_phOptionalFunctions)
+ return NULL;
+ return (void(*)(void))apr_hash_get(s_phOptionalFunctions,szName,strlen(szName));
+}
+
+/* Deprecated */
+APU_DECLARE_NONSTD(void) apr_dynamic_fn_register(const char *szName,
+ apr_opt_fn_t *pfn)
+{
+#ifdef NETWARE
+ get_apd
+#endif
+ if(!s_phOptionalFunctions)
+ s_phOptionalFunctions=apr_hash_make(apr_hook_global_pool);
+ apr_hash_set(s_phOptionalFunctions,szName,strlen(szName),(void *)pfn);
+}
+
+#if 0
+void main()
+{
+ const char *aszAPre[]={"b","c",NULL};
+ const char *aszBPost[]={"a",NULL};
+ const char *aszCPost[]={"b",NULL};
+ TSortData t1[]=
+ {
+ { "a",aszAPre,NULL },
+ { "b",NULL,aszBPost },
+ { "c",NULL,aszCPost }
+ };
+ TSort *pResult;
+
+ pResult=prepare(t1,3);
+ pResult=tsort(pResult,3);
+
+ for( ; pResult ; pResult=pResult->pNext)
+ printf("%s\n",pResult->pData->szName);
+}
+#endif
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file apr_anylock.h
+ * @brief APR-Util transparent any lock flavor wrapper
+ */
+#ifndef APR_ANYLOCK_H
+#define APR_ANYLOCK_H
+
+#include "apr_proc_mutex.h"
+#include "apr_thread_mutex.h"
+#include "apr_thread_rwlock.h"
+
+/** Structure that may contain any APR lock type */
+typedef struct apr_anylock_t {
+ /** Indicates what type of lock is in lock */
+ enum tm_lock {
+ apr_anylock_none, /**< None */
+ apr_anylock_procmutex, /**< Process-based */
+ apr_anylock_threadmutex, /**< Thread-based */
+ apr_anylock_readlock, /**< Read lock */
+ apr_anylock_writelock /**< Write lock */
+ } type;
+ /** Union of all possible APR locks */
+ union apr_anylock_u_t {
+ apr_proc_mutex_t *pm; /**< Process mutex */
+#if APR_HAS_THREADS
+ apr_thread_mutex_t *tm; /**< Thread mutex */
+ apr_thread_rwlock_t *rw; /**< Read-write lock */
+#endif
+ } lock;
+} apr_anylock_t;
+
+#if APR_HAS_THREADS
+
+/** Lock an apr_anylock_t structure */
+#define APR_ANYLOCK_LOCK(lck) \
+ (((lck)->type == apr_anylock_none) \
+ ? APR_SUCCESS \
+ : (((lck)->type == apr_anylock_threadmutex) \
+ ? apr_thread_mutex_lock((lck)->lock.tm) \
+ : (((lck)->type == apr_anylock_procmutex) \
+ ? apr_proc_mutex_lock((lck)->lock.pm) \
+ : (((lck)->type == apr_anylock_readlock) \
+ ? apr_thread_rwlock_rdlock((lck)->lock.rw) \
+ : (((lck)->type == apr_anylock_writelock) \
+ ? apr_thread_rwlock_wrlock((lck)->lock.rw) \
+ : APR_EINVAL)))))
+
+#else /* APR_HAS_THREADS */
+
+#define APR_ANYLOCK_LOCK(lck) \
+ (((lck)->type == apr_anylock_none) \
+ ? APR_SUCCESS \
+ : (((lck)->type == apr_anylock_procmutex) \
+ ? apr_proc_mutex_lock((lck)->lock.pm) \
+ : APR_EINVAL))
+
+#endif /* APR_HAS_THREADS */
+
+#if APR_HAS_THREADS
+
+/** Try to lock an apr_anylock_t structure */
+#define APR_ANYLOCK_TRYLOCK(lck) \
+ (((lck)->type == apr_anylock_none) \
+ ? APR_SUCCESS \
+ : (((lck)->type == apr_anylock_threadmutex) \
+ ? apr_thread_mutex_trylock((lck)->lock.tm) \
+ : (((lck)->type == apr_anylock_procmutex) \
+ ? apr_proc_mutex_trylock((lck)->lock.pm) \
+ : (((lck)->type == apr_anylock_readlock) \
+ ? apr_thread_rwlock_tryrdlock((lck)->lock.rw) \
+ : (((lck)->type == apr_anylock_writelock) \
+ ? apr_thread_rwlock_trywrlock((lck)->lock.rw) \
+ : APR_EINVAL)))))
+
+#else /* APR_HAS_THREADS */
+
+#define APR_ANYLOCK_TRYLOCK(lck) \
+ (((lck)->type == apr_anylock_none) \
+ ? APR_SUCCESS \
+ : (((lck)->type == apr_anylock_procmutex) \
+ ? apr_proc_mutex_trylock((lck)->lock.pm) \
+ : APR_EINVAL))
+
+#endif /* APR_HAS_THREADS */
+
+#if APR_HAS_THREADS
+
+/** Unlock an apr_anylock_t structure */
+#define APR_ANYLOCK_UNLOCK(lck) \
+ (((lck)->type == apr_anylock_none) \
+ ? APR_SUCCESS \
+ : (((lck)->type == apr_anylock_threadmutex) \
+ ? apr_thread_mutex_unlock((lck)->lock.tm) \
+ : (((lck)->type == apr_anylock_procmutex) \
+ ? apr_proc_mutex_unlock((lck)->lock.pm) \
+ : ((((lck)->type == apr_anylock_readlock) || \
+ ((lck)->type == apr_anylock_writelock)) \
+ ? apr_thread_rwlock_unlock((lck)->lock.rw) \
+ : APR_EINVAL))))
+
+#else /* APR_HAS_THREADS */
+
+#define APR_ANYLOCK_UNLOCK(lck) \
+ (((lck)->type == apr_anylock_none) \
+ ? APR_SUCCESS \
+ : (((lck)->type == apr_anylock_procmutex) \
+ ? apr_proc_mutex_unlock((lck)->lock.pm) \
+ : APR_EINVAL))
+
+#endif /* APR_HAS_THREADS */
+
+#endif /* !APR_ANYLOCK_H */
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * The apr_vsnprintf/apr_snprintf functions are based on, and used with the
+ * permission of, the SIO stdio-replacement strx_* functions by Panos
+ * Tsirigotis <panos@alumni.cs.colorado.edu> for xinetd.
+ */
+
+/**
+ * @file apr_base64.h
+ * @brief APR-UTIL Base64 Encoding
+ */
+#ifndef APR_BASE64_H
+#define APR_BASE64_H
+
+#include "apu.h"
+#include "apr_general.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup APR_Util_Base64 Base64 Encoding
+ * @ingroup APR_Util
+ * @{
+ */
+
+/* Simple BASE64 encode/decode functions.
+ *
+ * As we might encode binary strings, hence we require the length of
+ * the incoming plain source. And return the length of what we decoded.
+ *
+ * The decoding function takes any non valid char (i.e. whitespace, \0
+ * or anything non A-Z,0-9 etc as terminal.
+ *
+ * plain strings/binary sequences are not assumed '\0' terminated. Encoded
+ * strings are neither. But probably should.
+ *
+ */
+
+/**
+ * Given the length of an un-encrypted string, get the length of the
+ * encrypted string.
+ * @param len the length of an unencrypted string.
+ * @return the length of the string after it is encrypted
+ */
+APU_DECLARE(int) apr_base64_encode_len(int len);
+
+/**
+ * Encode a text string using base64encoding.
+ * @param coded_dst The destination string for the encoded string.
+ * @param plain_src The original string in plain text
+ * @param len_plain_src The length of the plain text string
+ * @return the length of the encoded string
+ */
+APU_DECLARE(int) apr_base64_encode(char * coded_dst, const char *plain_src,
+ int len_plain_src);
+
+/**
+ * Encode an EBCDIC string using base64encoding.
+ * @param coded_dst The destination string for the encoded string.
+ * @param plain_src The original string in plain text
+ * @param len_plain_src The length of the plain text string
+ * @return the length of the encoded string
+ */
+APU_DECLARE(int) apr_base64_encode_binary(char * coded_dst,
+ const unsigned char *plain_src,
+ int len_plain_src);
+
+/**
+ * Determine the length of a plain text string given the encoded version
+ * @param coded_src The encoded string
+ * @return the length of the plain text string
+ */
+APU_DECLARE(int) apr_base64_decode_len(const char * coded_src);
+
+/**
+ * Decode a string to plain text
+ * @param plain_dst The destination string for the plain text
+ * @param coded_src The encoded string
+ * @return the length of the plain text string
+ */
+APU_DECLARE(int) apr_base64_decode(char * plain_dst, const char *coded_src);
+
+/**
+ * Decode an EBCDIC string to plain text
+ * @param plain_dst The destination string for the plain text
+ * @param coded_src The encoded string
+ * @return the length of the plain text string
+ */
+APU_DECLARE(int) apr_base64_decode_binary(unsigned char * plain_dst,
+ const char *coded_src);
+
+/** @} */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !APR_BASE64_H */
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @file apr_buckets.h
+ * @brief APR-UTIL Buckets/Bucket Brigades
+ */
+
+#ifndef APR_BUCKETS_H
+#define APR_BUCKETS_H
+
+#if defined(APR_BUCKET_DEBUG) && !defined(APR_RING_DEBUG)
+#define APR_RING_DEBUG
+#endif
+
+#include "apu.h"
+#include "apr_network_io.h"
+#include "apr_file_io.h"
+#include "apr_general.h"
+#include "apr_mmap.h"
+#include "apr_errno.h"
+#include "apr_ring.h"
+#include "apr.h"
+#if APR_HAVE_SYS_UIO_H
+#include <sys/uio.h> /* for struct iovec */
+#endif
+#if APR_HAVE_STDARG_H
+#include <stdarg.h>
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup APR_Util_Bucket_Brigades Bucket Brigades
+ * @ingroup APR_Util
+ * @{
+ */
+
+/** default bucket buffer size - 8KB minus room for memory allocator headers */
+#define APR_BUCKET_BUFF_SIZE 8000
+
+/** Determines how a bucket or brigade should be read */
+typedef enum {
+ APR_BLOCK_READ, /**< block until data becomes available */
+ APR_NONBLOCK_READ /**< return immediately if no data is available */
+} apr_read_type_e;
+
+/**
+ * The one-sentence buzzword-laden overview: Bucket brigades represent
+ * a complex data stream that can be passed through a layered IO
+ * system without unnecessary copying. A longer overview follows...
+ *
+ * A bucket brigade is a doubly linked list (ring) of buckets, so we
+ * aren't limited to inserting at the front and removing at the end.
+ * Buckets are only passed around as members of a brigade, although
+ * singleton buckets can occur for short periods of time.
+ *
+ * Buckets are data stores of various types. They can refer to data in
+ * memory, or part of a file or mmap area, or the output of a process,
+ * etc. Buckets also have some type-dependent accessor functions:
+ * read, split, copy, setaside, and destroy.
+ *
+ * read returns the address and size of the data in the bucket. If the
+ * data isn't in memory then it is read in and the bucket changes type
+ * so that it can refer to the new location of the data. If all the
+ * data doesn't fit in the bucket then a new bucket is inserted into
+ * the brigade to hold the rest of it.
+ *
+ * split divides the data in a bucket into two regions. After a split
+ * the original bucket refers to the first part of the data and a new
+ * bucket inserted into the brigade after the original bucket refers
+ * to the second part of the data. Reference counts are maintained as
+ * necessary.
+ *
+ * setaside ensures that the data in the bucket has a long enough
+ * lifetime. Sometimes it is convenient to create a bucket referring
+ * to data on the stack in the expectation that it will be consumed
+ * (output to the network) before the stack is unwound. If that
+ * expectation turns out not to be valid, the setaside function is
+ * called to move the data somewhere safer.
+ *
+ * copy makes a duplicate of the bucket structure as long as it's
+ * possible to have multiple references to a single copy of the
+ * data itself. Not all bucket types can be copied.
+ *
+ * destroy maintains the reference counts on the resources used by a
+ * bucket and frees them if necessary.
+ *
+ * Note: all of the above functions have wrapper macros (apr_bucket_read(),
+ * apr_bucket_destroy(), etc), and those macros should be used rather
+ * than using the function pointers directly.
+ *
+ * To write a bucket brigade, they are first made into an iovec, so that we
+ * don't write too little data at one time. Currently we ignore compacting the
+ * buckets into as few buckets as possible, but if we really want good
+ * performance, then we need to compact the buckets before we convert to an
+ * iovec, or possibly while we are converting to an iovec.
+ */
+
+/*
+ * Forward declaration of the main types.
+ */
+
+/** @see apr_bucket_brigade */
+typedef struct apr_bucket_brigade apr_bucket_brigade;
+/** @see apr_bucket */
+typedef struct apr_bucket apr_bucket;
+/** @see apr_bucket_alloc_t */
+typedef struct apr_bucket_alloc_t apr_bucket_alloc_t;
+
+/** @see apr_bucket_type_t */
+typedef struct apr_bucket_type_t apr_bucket_type_t;
+
+/**
+ * Basic bucket type
+ */
+struct apr_bucket_type_t {
+ /**
+ * The name of the bucket type
+ */
+ const char *name;
+ /**
+ * The number of functions this bucket understands. Can not be less than
+ * five.
+ */
+ int num_func;
+ /**
+ * Whether the bucket contains metadata (ie, information that
+ * describes the regular contents of the brigade). The metadata
+ * is not returned by apr_bucket_read() and is not indicated by
+ * the ->length of the apr_bucket itself. In other words, an
+ * empty bucket is safe to arbitrarily remove if and only if it
+ * contains no metadata. In this sense, "data" is just raw bytes
+ * that are the "content" of the brigade and "metadata" describes
+ * that data but is not a proper part of it.
+ */
+ enum {
+ /** This bucket type represents actual data to send to the client. */
+ APR_BUCKET_DATA = 0,
+ /** This bucket type represents metadata. */
+ APR_BUCKET_METADATA = 1
+ } is_metadata;
+ /**
+ * Free the private data and any resources used by the bucket (if they
+ * aren't shared with another bucket). This function is required to be
+ * implemented for all bucket types, though it might be a no-op on some
+ * of them (namely ones that never allocate any private data structures).
+ * @param data The private data pointer from the bucket to be destroyed
+ */
+ void (*destroy)(void *data);
+
+ /**
+ * Read the data from the bucket. This is required to be implemented
+ * for all bucket types.
+ * @param b The bucket to read from
+ * @param str A place to store the data read. Allocation should only be
+ * done if absolutely necessary.
+ * @param len The amount of data read.
+ * @param block Should this read function block if there is more data that
+ * cannot be read immediately.
+ */
+ apr_status_t (*read)(apr_bucket *b, const char **str, apr_size_t *len,
+ apr_read_type_e block);
+
+ /**
+ * Make it possible to set aside the data for at least as long as the
+ * given pool. Buckets containing data that could potentially die before
+ * this pool (e.g. the data resides on the stack, in a child pool of
+ * the given pool, or in a disjoint pool) must somehow copy, shift, or
+ * transform the data to have the proper lifetime.
+ * @param e The bucket to convert
+ * @remark Some bucket types contain data that will always outlive the
+ * bucket itself. For example no data (EOS and FLUSH), or the data
+ * resides in global, constant memory (IMMORTAL), or the data is on
+ * the heap (HEAP). For these buckets, apr_bucket_setaside_noop can
+ * be used.
+ */
+ apr_status_t (*setaside)(apr_bucket *e, apr_pool_t *pool);
+
+ /**
+ * Split one bucket in two at the specified position by duplicating
+ * the bucket structure (not the data) and modifying any necessary
+ * start/end/offset information. If it's not possible to do this
+ * for the bucket type (perhaps the length of the data is indeterminate,
+ * as with pipe and socket buckets), then APR_ENOTIMPL is returned.
+ * @param e The bucket to split
+ * @param point The offset of the first byte in the new bucket
+ */
+ apr_status_t (*split)(apr_bucket *e, apr_size_t point);
+
+ /**
+ * Copy the bucket structure (not the data), assuming that this is
+ * possible for the bucket type. If it's not, APR_ENOTIMPL is returned.
+ * @param e The bucket to copy
+ * @param c Returns a pointer to the new bucket
+ */
+ apr_status_t (*copy)(apr_bucket *e, apr_bucket **c);
+
+};
+
+/**
+ * apr_bucket structures are allocated on the malloc() heap and
+ * their lifetime is controlled by the parent apr_bucket_brigade
+ * structure. Buckets can move from one brigade to another e.g. by
+ * calling APR_BRIGADE_CONCAT(). In general the data in a bucket has
+ * the same lifetime as the bucket and is freed when the bucket is
+ * destroyed; if the data is shared by more than one bucket (e.g.
+ * after a split) the data is freed when the last bucket goes away.
+ */
+struct apr_bucket {
+ /** Links to the rest of the brigade */
+ APR_RING_ENTRY(apr_bucket) link;
+ /** The type of bucket. */
+ const apr_bucket_type_t *type;
+ /** The length of the data in the bucket. This could have been implemented
+ * with a function, but this is an optimization, because the most
+ * common thing to do will be to get the length. If the length is unknown,
+ * the value of this field will be (apr_size_t)(-1).
+ */
+ apr_size_t length;
+ /** The start of the data in the bucket relative to the private base
+ * pointer. The vast majority of bucket types allow a fixed block of
+ * data to be referenced by multiple buckets, each bucket pointing to
+ * a different segment of the data. That segment starts at base+start
+ * and ends at base+start+length.
+ * If the length == (apr_size_t)(-1), then start == -1.
+ */
+ apr_off_t start;
+ /** type-dependent data hangs off this pointer */
+ void *data;
+ /**
+ * Pointer to function used to free the bucket. This function should
+ * always be defined and it should be consistent with the memory
+ * function used to allocate the bucket. For example, if malloc() is
+ * used to allocate the bucket, this pointer should point to free().
+ * @param e Pointer to the bucket being freed
+ */
+ void (*free)(void *e);
+ /** The freelist from which this bucket was allocated */
+ apr_bucket_alloc_t *list;
+};
+
+/** A list of buckets */
+struct apr_bucket_brigade {
+ /** The pool to associate the brigade with. The data is not allocated out
+ * of the pool, but a cleanup is registered with this pool. If the
+ * brigade is destroyed by some mechanism other than pool destruction,
+ * the destroying function is responsible for killing the cleanup.
+ */
+ apr_pool_t *p;
+ /** The buckets in the brigade are on this list. */
+ /*
+ * The apr_bucket_list structure doesn't actually need a name tag
+ * because it has no existence independent of struct apr_bucket_brigade;
+ * the ring macros are designed so that you can leave the name tag
+ * argument empty in this situation but apparently the Windows compiler
+ * doesn't like that.
+ */
+ APR_RING_HEAD(apr_bucket_list, apr_bucket) list;
+ /** The freelist from which this bucket was allocated */
+ apr_bucket_alloc_t *bucket_alloc;
+};
+
+
+/**
+ * Function called when a brigade should be flushed
+ */
+typedef apr_status_t (*apr_brigade_flush)(apr_bucket_brigade *bb, void *ctx);
+
+/*
+ * define APR_BUCKET_DEBUG if you want your brigades to be checked for
+ * validity at every possible instant. this will slow your code down
+ * substantially but is a very useful debugging tool.
+ */
+#ifdef APR_BUCKET_DEBUG
+
+#define APR_BRIGADE_CHECK_CONSISTENCY(b) \
+ APR_RING_CHECK_CONSISTENCY(&(b)->list, apr_bucket, link)
+
+#define APR_BUCKET_CHECK_CONSISTENCY(e) \
+ APR_RING_CHECK_ELEM_CONSISTENCY((e), apr_bucket, link)
+
+#else
+/**
+ * checks the ring pointers in a bucket brigade for consistency. an
+ * abort() will be triggered if any inconsistencies are found.
+ * note: this is a no-op unless APR_BUCKET_DEBUG is defined.
+ * @param b The brigade
+ */
+#define APR_BRIGADE_CHECK_CONSISTENCY(b)
+/**
+ * checks the brigade a bucket is in for ring consistency. an
+ * abort() will be triggered if any inconsistencies are found.
+ * note: this is a no-op unless APR_BUCKET_DEBUG is defined.
+ * @param e The bucket
+ */
+#define APR_BUCKET_CHECK_CONSISTENCY(e)
+#endif
+
+
+/**
+ * Wrappers around the RING macros to reduce the verbosity of the code
+ * that handles bucket brigades.
+ */
+/**
+ * The magic pointer value that indicates the head of the brigade
+ * @remark This is used to find the beginning and end of the brigade, eg:
+ * <pre>
+ * while (e != APR_BRIGADE_SENTINEL(b)) {
+ * ...
+ * e = APR_BUCKET_NEXT(e);
+ * }
+ * </pre>
+ * @param b The brigade
+ * @return The magic pointer value
+ */
+#define APR_BRIGADE_SENTINEL(b) APR_RING_SENTINEL(&(b)->list, apr_bucket, link)
+
+/**
+ * Determine if the bucket brigade is empty
+ * @param b The brigade to check
+ * @return true or false
+ */
+#define APR_BRIGADE_EMPTY(b) APR_RING_EMPTY(&(b)->list, apr_bucket, link)
+
+/**
+ * Return the first bucket in a brigade
+ * @param b The brigade to query
+ * @return The first bucket in the brigade
+ */
+#define APR_BRIGADE_FIRST(b) APR_RING_FIRST(&(b)->list)
+/**
+ * Return the last bucket in a brigade
+ * @param b The brigade to query
+ * @return The last bucket in the brigade
+ */
+#define APR_BRIGADE_LAST(b) APR_RING_LAST(&(b)->list)
+
+/**
+ * Insert a list of buckets at the front of a brigade
+ * @param b The brigade to add to
+ * @param e The first bucket in a list of buckets to insert
+ */
+#define APR_BRIGADE_INSERT_HEAD(b, e) do { \
+ apr_bucket *ap__b = (e); \
+ APR_RING_INSERT_HEAD(&(b)->list, ap__b, apr_bucket, link); \
+ APR_BRIGADE_CHECK_CONSISTENCY((b)); \
+ } while (0)
+
+/**
+ * Insert a list of buckets at the end of a brigade
+ * @param b The brigade to add to
+ * @param e The first bucket in a list of buckets to insert
+ */
+#define APR_BRIGADE_INSERT_TAIL(b, e) do { \
+ apr_bucket *ap__b = (e); \
+ APR_RING_INSERT_TAIL(&(b)->list, ap__b, apr_bucket, link); \
+ APR_BRIGADE_CHECK_CONSISTENCY((b)); \
+ } while (0)
+
+/**
+ * Concatenate brigade b onto the end of brigade a, leaving brigade b empty
+ * @param a The first brigade
+ * @param b The second brigade
+ */
+#define APR_BRIGADE_CONCAT(a, b) do { \
+ APR_RING_CONCAT(&(a)->list, &(b)->list, apr_bucket, link); \
+ APR_BRIGADE_CHECK_CONSISTENCY((a)); \
+ } while (0)
+
+/**
+ * Prepend brigade b onto the beginning of brigade a, leaving brigade b empty
+ * @param a The first brigade
+ * @param b The second brigade
+ */
+#define APR_BRIGADE_PREPEND(a, b) do { \
+ APR_RING_PREPEND(&(a)->list, &(b)->list, apr_bucket, link); \
+ APR_BRIGADE_CHECK_CONSISTENCY((a)); \
+ } while (0)
+
+/**
+ * Insert a list of buckets before a specified bucket
+ * @param a The bucket to insert before
+ * @param b The buckets to insert
+ */
+#define APR_BUCKET_INSERT_BEFORE(a, b) do { \
+ apr_bucket *ap__a = (a), *ap__b = (b); \
+ APR_RING_INSERT_BEFORE(ap__a, ap__b, link); \
+ APR_BUCKET_CHECK_CONSISTENCY(ap__a); \
+ } while (0)
+
+/**
+ * Insert a list of buckets after a specified bucket
+ * @param a The bucket to insert after
+ * @param b The buckets to insert
+ */
+#define APR_BUCKET_INSERT_AFTER(a, b) do { \
+ apr_bucket *ap__a = (a), *ap__b = (b); \
+ APR_RING_INSERT_AFTER(ap__a, ap__b, link); \
+ APR_BUCKET_CHECK_CONSISTENCY(ap__a); \
+ } while (0)
+
+/**
+ * Get the next bucket in the list
+ * @param e The current bucket
+ * @return The next bucket
+ */
+#define APR_BUCKET_NEXT(e) APR_RING_NEXT((e), link)
+/**
+ * Get the previous bucket in the list
+ * @param e The current bucket
+ * @return The previous bucket
+ */
+#define APR_BUCKET_PREV(e) APR_RING_PREV((e), link)
+
+/**
+ * Remove a bucket from its bucket brigade
+ * @param e The bucket to remove
+ */
+#define APR_BUCKET_REMOVE(e) APR_RING_REMOVE((e), link)
+
+/**
+ * Initialize a new bucket's prev/next pointers
+ * @param e The bucket to initialize
+ */
+#define APR_BUCKET_INIT(e) APR_RING_ELEM_INIT((e), link)
+
+/**
+ * Determine if a bucket contains metadata. An empty bucket is
+ * safe to arbitrarily remove if and only if this is false.
+ * @param e The bucket to inspect
+ * @return true or false
+ */
+#define APR_BUCKET_IS_METADATA(e) ((e)->type->is_metadata)
+
+/**
+ * Determine if a bucket is a FLUSH bucket
+ * @param e The bucket to inspect
+ * @return true or false
+ */
+#define APR_BUCKET_IS_FLUSH(e) ((e)->type == &apr_bucket_type_flush)
+/**
+ * Determine if a bucket is an EOS bucket
+ * @param e The bucket to inspect
+ * @return true or false
+ */
+#define APR_BUCKET_IS_EOS(e) ((e)->type == &apr_bucket_type_eos)
+/**
+ * Determine if a bucket is a FILE bucket
+ * @param e The bucket to inspect
+ * @return true or false
+ */
+#define APR_BUCKET_IS_FILE(e) ((e)->type == &apr_bucket_type_file)
+/**
+ * Determine if a bucket is a PIPE bucket
+ * @param e The bucket to inspect
+ * @return true or false
+ */
+#define APR_BUCKET_IS_PIPE(e) ((e)->type == &apr_bucket_type_pipe)
+/**
+ * Determine if a bucket is a SOCKET bucket
+ * @param e The bucket to inspect
+ * @return true or false
+ */
+#define APR_BUCKET_IS_SOCKET(e) ((e)->type == &apr_bucket_type_socket)
+/**
+ * Determine if a bucket is a HEAP bucket
+ * @param e The bucket to inspect
+ * @return true or false
+ */
+#define APR_BUCKET_IS_HEAP(e) ((e)->type == &apr_bucket_type_heap)
+/**
+ * Determine if a bucket is a TRANSIENT bucket
+ * @param e The bucket to inspect
+ * @return true or false
+ */
+#define APR_BUCKET_IS_TRANSIENT(e) ((e)->type == &apr_bucket_type_transient)
+/**
+ * Determine if a bucket is a IMMORTAL bucket
+ * @param e The bucket to inspect
+ * @return true or false
+ */
+#define APR_BUCKET_IS_IMMORTAL(e) ((e)->type == &apr_bucket_type_immortal)
+#if APR_HAS_MMAP
+/**
+ * Determine if a bucket is a MMAP bucket
+ * @param e The bucket to inspect
+ * @return true or false
+ */
+#define APR_BUCKET_IS_MMAP(e) ((e)->type == &apr_bucket_type_mmap)
+#endif
+/**
+ * Determine if a bucket is a POOL bucket
+ * @param e The bucket to inspect
+ * @return true or false
+ */
+#define APR_BUCKET_IS_POOL(e) ((e)->type == &apr_bucket_type_pool)
+
+/*
+ * General-purpose reference counting for the various bucket types.
+ *
+ * Any bucket type that keeps track of the resources it uses (i.e.
+ * most of them except for IMMORTAL, TRANSIENT, and EOS) needs to
+ * attach a reference count to the resource so that it can be freed
+ * when the last bucket that uses it goes away. Resource-sharing may
+ * occur because of bucket splits or buckets that refer to globally
+ * cached data. */
+
+/** @see apr_bucket_refcount */
+typedef struct apr_bucket_refcount apr_bucket_refcount;
+/**
+ * The structure used to manage the shared resource must start with an
+ * apr_bucket_refcount which is updated by the general-purpose refcount
+ * code. A pointer to the bucket-type-dependent private data structure
+ * can be cast to a pointer to an apr_bucket_refcount and vice versa.
+ */
+struct apr_bucket_refcount {
+ /** The number of references to this bucket */
+ int refcount;
+};
+
+/* ***** Reference-counted bucket types ***** */
+
+/** @see apr_bucket_heap */
+typedef struct apr_bucket_heap apr_bucket_heap;
+/**
+ * A bucket referring to data allocated off the heap.
+ */
+struct apr_bucket_heap {
+ /** Number of buckets using this memory */
+ apr_bucket_refcount refcount;
+ /** The start of the data actually allocated. This should never be
+ * modified, it is only used to free the bucket.
+ */
+ char *base;
+ /** how much memory was allocated */
+ apr_size_t alloc_len;
+ /** function to use to delete the data */
+ void (*free_func)(void *data);
+};
+
+/** @see apr_bucket_pool */
+typedef struct apr_bucket_pool apr_bucket_pool;
+/**
+ * A bucket referring to data allocated from a pool
+ */
+struct apr_bucket_pool {
+ /** The pool bucket must be able to be easily morphed to a heap
+ * bucket if the pool gets cleaned up before all references are
+ * destroyed. This apr_bucket_heap structure is populated automatically
+ * when the pool gets cleaned up, and subsequent calls to pool_read()
+ * will result in the apr_bucket in question being morphed into a
+ * regular heap bucket. (To avoid having to do many extra refcount
+ * manipulations and b->data manipulations, the apr_bucket_pool
+ * struct actually *contains* the apr_bucket_heap struct that it
+ * will become as its first element; the two share their
+ * apr_bucket_refcount members.)
+ */
+ apr_bucket_heap heap;
+ /** The block of data actually allocated from the pool.
+ * Segments of this block are referenced by adjusting
+ * the start and length of the apr_bucket accordingly.
+ * This will be NULL after the pool gets cleaned up.
+ */
+ const char *base;
+ /** The pool the data was allocated from. When the pool
+ * is cleaned up, this gets set to NULL as an indicator
+ * to pool_read() that the data is now on the heap and
+ * so it should morph the bucket into a regular heap
+ * bucket before continuing.
+ */
+ apr_pool_t *pool;
+ /** The freelist this structure was allocated from, which is
+ * needed in the cleanup phase in order to allocate space on the heap
+ */
+ apr_bucket_alloc_t *list;
+};
+
+#if APR_HAS_MMAP
+/** @see apr_bucket_mmap */
+typedef struct apr_bucket_mmap apr_bucket_mmap;
+/**
+ * A bucket referring to an mmap()ed file
+ */
+struct apr_bucket_mmap {
+ /** Number of buckets using this memory */
+ apr_bucket_refcount refcount;
+ /** The mmap this sub_bucket refers to */
+ apr_mmap_t *mmap;
+};
+#endif
+
+/** @see apr_bucket_file */
+typedef struct apr_bucket_file apr_bucket_file;
+/**
+ * A bucket referring to an file
+ */
+struct apr_bucket_file {
+ /** Number of buckets using this memory */
+ apr_bucket_refcount refcount;
+ /** The file this bucket refers to */
+ apr_file_t *fd;
+ /** The pool into which any needed structures should
+ * be created while reading from this file bucket */
+ apr_pool_t *readpool;
+#if APR_HAS_MMAP
+ /** Whether this bucket should be memory-mapped if
+ * a caller tries to read from it */
+ int can_mmap;
+#endif /* APR_HAS_MMAP */
+};
+
+/** @see apr_bucket_structs */
+typedef union apr_bucket_structs apr_bucket_structs;
+/**
+ * A union of all bucket structures so we know what
+ * the max size is.
+ */
+union apr_bucket_structs {
+ apr_bucket b; /**< Bucket */
+ apr_bucket_heap heap; /**< Heap */
+ apr_bucket_pool pool; /**< Pool */
+#if APR_HAS_MMAP
+ apr_bucket_mmap mmap; /**< MMap */
+#endif
+ apr_bucket_file file; /**< File */
+};
+
+/**
+ * The amount that apr_bucket_alloc() should allocate in the common case.
+ * Note: this is twice as big as apr_bucket_structs to allow breathing
+ * room for third-party bucket types.
+ */
+#define APR_BUCKET_ALLOC_SIZE APR_ALIGN_DEFAULT(2*sizeof(apr_bucket_structs))
+
+/* ***** Bucket Brigade Functions ***** */
+/**
+ * Create a new bucket brigade. The bucket brigade is originally empty.
+ * @param p The pool to associate with the brigade. Data is not allocated out
+ * of the pool, but a cleanup is registered.
+ * @param list The bucket allocator to use
+ * @return The empty bucket brigade
+ */
+APU_DECLARE(apr_bucket_brigade *) apr_brigade_create(apr_pool_t *p,
+ apr_bucket_alloc_t *list);
+
+/**
+ * destroy an entire bucket brigade. This includes destroying all of the
+ * buckets within the bucket brigade's bucket list.
+ * @param b The bucket brigade to destroy
+ */
+APU_DECLARE(apr_status_t) apr_brigade_destroy(apr_bucket_brigade *b);
+
+/**
+ * empty out an entire bucket brigade. This includes destroying all of the
+ * buckets within the bucket brigade's bucket list. This is similar to
+ * apr_brigade_destroy(), except that it does not deregister the brigade's
+ * pool cleanup function.
+ * @param data The bucket brigade to clean up
+ * @remark Generally, you should use apr_brigade_destroy(). This function
+ * can be useful in situations where you have a single brigade that
+ * you wish to reuse many times by destroying all of the buckets in
+ * the brigade and putting new buckets into it later.
+ */
+APU_DECLARE(apr_status_t) apr_brigade_cleanup(void *data);
+
+/**
+ * Split a bucket brigade into two, such that the given bucket is the
+ * first in the new bucket brigade. This function is useful when a
+ * filter wants to pass only the initial part of a brigade to the next
+ * filter.
+ * @param b The brigade to split
+ * @param e The first element of the new brigade
+ * @return The new brigade
+ */
+APU_DECLARE(apr_bucket_brigade *) apr_brigade_split(apr_bucket_brigade *b,
+ apr_bucket *e);
+
+/**
+ * Partition a bucket brigade at a given offset (in bytes from the start of
+ * the brigade). This is useful whenever a filter wants to use known ranges
+ * of bytes from the brigade; the ranges can even overlap.
+ * @param b The brigade to partition
+ * @param point The offset at which to partition the brigade
+ * @param after_point Returns a pointer to the first bucket after the partition
+ */
+APU_DECLARE(apr_status_t) apr_brigade_partition(apr_bucket_brigade *b,
+ apr_off_t point,
+ apr_bucket **after_point);
+
+/**
+ * Return the total length of the brigade.
+ * @param bb The brigade to compute the length of
+ * @param read_all Read unknown-length buckets to force a size
+ * @param length Returns the length of the brigade, or -1 if the brigade has
+ * buckets of indeterminate length and read_all is 0.
+ */
+APU_DECLARE(apr_status_t) apr_brigade_length(apr_bucket_brigade *bb,
+ int read_all,
+ apr_off_t *length);
+
+/**
+ * Take a bucket brigade and store the data in a flat char*
+ * @param bb The bucket brigade to create the char* from
+ * @param c The char* to write into
+ * @param len The maximum length of the char array. On return, it is the
+ * actual length of the char array.
+ */
+APU_DECLARE(apr_status_t) apr_brigade_flatten(apr_bucket_brigade *bb,
+ char *c,
+ apr_size_t *len);
+
+/**
+ * Creates a pool-allocated string representing a flat bucket brigade
+ * @param bb The bucket brigade to create the char array from
+ * @param c On return, the allocated char array
+ * @param len On return, the length of the char array.
+ * @param pool The pool to allocate the string from.
+ */
+APU_DECLARE(apr_status_t) apr_brigade_pflatten(apr_bucket_brigade *bb,
+ char **c,
+ apr_size_t *len,
+ apr_pool_t *pool);
+
+/**
+ * Split a brigade to represent one LF line.
+ * @param bbOut The bucket brigade that will have the LF line appended to.
+ * @param bbIn The input bucket brigade to search for a LF-line.
+ * @param block The blocking mode to be used to split the line.
+ * @param maxbytes The maximum bytes to read. If this many bytes are seen
+ * without a LF, the brigade will contain a partial line.
+ */
+APU_DECLARE(apr_status_t) apr_brigade_split_line(apr_bucket_brigade *bbOut,
+ apr_bucket_brigade *bbIn,
+ apr_read_type_e block,
+ apr_off_t maxbytes);
+
+/**
+ * create an iovec of the elements in a bucket_brigade... return number
+ * of elements used. This is useful for writing to a file or to the
+ * network efficiently.
+ * @param b The bucket brigade to create the iovec from
+ * @param vec The iovec to create
+ * @param nvec The number of elements in the iovec. On return, it is the
+ * number of iovec elements actually filled out.
+ */
+APU_DECLARE(apr_status_t) apr_brigade_to_iovec(apr_bucket_brigade *b,
+ struct iovec *vec, int *nvec);
+
+/**
+ * This function writes a list of strings into a bucket brigade.
+ * @param b The bucket brigade to add to
+ * @param flush The flush function to use if the brigade is full
+ * @param ctx The structure to pass to the flush function
+ * @param va A list of strings to add
+ * @return APR_SUCCESS or error code.
+ */
+APU_DECLARE(apr_status_t) apr_brigade_vputstrs(apr_bucket_brigade *b,
+ apr_brigade_flush flush,
+ void *ctx,
+ va_list va);
+
+/**
+ * This function writes a string into a bucket brigade.
+ * @param b The bucket brigade to add to
+ * @param flush The flush function to use if the brigade is full
+ * @param ctx The structure to pass to the flush function
+ * @param str The string to add
+ * @param nbyte The number of bytes to write
+ * @return APR_SUCCESS or error code
+ */
+APU_DECLARE(apr_status_t) apr_brigade_write(apr_bucket_brigade *b,
+ apr_brigade_flush flush, void *ctx,
+ const char *str, apr_size_t nbyte);
+
+/**
+ * This function writes multiple strings into a bucket brigade.
+ * @param b The bucket brigade to add to
+ * @param flush The flush function to use if the brigade is full
+ * @param ctx The structure to pass to the flush function
+ * @param vec The strings to add (address plus length for each)
+ * @param nvec The number of entries in iovec
+ * @return APR_SUCCESS or error code
+ */
+APU_DECLARE(apr_status_t) apr_brigade_writev(apr_bucket_brigade *b,
+ apr_brigade_flush flush,
+ void *ctx,
+ const struct iovec *vec,
+ apr_size_t nvec);
+
+/**
+ * This function writes a string into a bucket brigade.
+ * @param bb The bucket brigade to add to
+ * @param flush The flush function to use if the brigade is full
+ * @param ctx The structure to pass to the flush function
+ * @param str The string to add
+ * @return APR_SUCCESS or error code
+ */
+APU_DECLARE(apr_status_t) apr_brigade_puts(apr_bucket_brigade *bb,
+ apr_brigade_flush flush, void *ctx,
+ const char *str);
+
+/**
+ * This function writes a character into a bucket brigade.
+ * @param b The bucket brigade to add to
+ * @param flush The flush function to use if the brigade is full
+ * @param ctx The structure to pass to the flush function
+ * @param c The character to add
+ * @return APR_SUCCESS or error code
+ */
+APU_DECLARE(apr_status_t) apr_brigade_putc(apr_bucket_brigade *b,
+ apr_brigade_flush flush, void *ctx,
+ const char c);
+
+/**
+ * This function writes an unspecified number of strings into a bucket brigade.
+ * @param b The bucket brigade to add to
+ * @param flush The flush function to use if the brigade is full
+ * @param ctx The structure to pass to the flush function
+ * @param ... The strings to add
+ * @return APR_SUCCESS or error code
+ */
+APU_DECLARE_NONSTD(apr_status_t) apr_brigade_putstrs(apr_bucket_brigade *b,
+ apr_brigade_flush flush,
+ void *ctx, ...);
+
+/**
+ * Evaluate a printf and put the resulting string at the end
+ * of the bucket brigade.
+ * @param b The brigade to write to
+ * @param flush The flush function to use if the brigade is full
+ * @param ctx The structure to pass to the flush function
+ * @param fmt The format of the string to write
+ * @param ... The arguments to fill out the format
+ * @return APR_SUCCESS or error code
+ */
+APU_DECLARE_NONSTD(apr_status_t) apr_brigade_printf(apr_bucket_brigade *b,
+ apr_brigade_flush flush,
+ void *ctx,
+ const char *fmt, ...)
+ __attribute__((format(printf,4,5)));
+
+/**
+ * Evaluate a printf and put the resulting string at the end
+ * of the bucket brigade.
+ * @param b The brigade to write to
+ * @param flush The flush function to use if the brigade is full
+ * @param ctx The structure to pass to the flush function
+ * @param fmt The format of the string to write
+ * @param va The arguments to fill out the format
+ * @return APR_SUCCESS or error code
+ */
+APU_DECLARE(apr_status_t) apr_brigade_vprintf(apr_bucket_brigade *b,
+ apr_brigade_flush flush,
+ void *ctx,
+ const char *fmt, va_list va);
+
+/**
+ * Utility function to insert a file (or a segment of a file) onto the
+ * end of the brigade. The file is split into multiple buckets if it
+ * is larger than the maximum size which can be represented by a
+ * single bucket.
+ * @param bb the brigade to insert into
+ * @param f the file to insert
+ * @param start the offset of the start of the segment
+ * @param len the length of the segment of the file to insert
+ * @param p pool from which file buckets are allocated
+ * @return the last bucket inserted
+ */
+APU_DECLARE(apr_bucket *) apr_brigade_insert_file(apr_bucket_brigade *bb,
+ apr_file_t *f,
+ apr_off_t start,
+ apr_off_t len,
+ apr_pool_t *p);
+
+
+
+/* ***** Bucket freelist functions ***** */
+/**
+ * Create a bucket allocator.
+ * @param p This pool's underlying apr_allocator_t is used to allocate memory
+ * for the bucket allocator. When the pool is destroyed, the bucket
+ * allocator's cleanup routine will free all memory that has been
+ * allocated from it.
+ * @remark The reason the allocator gets its memory from the pool's
+ * apr_allocator_t rather than from the pool itself is because
+ * the bucket allocator will free large memory blocks back to the
+ * allocator when it's done with them, thereby preventing memory
+ * footprint growth that would occur if we allocated from the pool.
+ * @warning The allocator must never be used by more than one thread at a time.
+ */
+APU_DECLARE_NONSTD(apr_bucket_alloc_t *) apr_bucket_alloc_create(apr_pool_t *p);
+
+/**
+ * Create a bucket allocator.
+ * @param allocator This apr_allocator_t is used to allocate both the bucket
+ * allocator and all memory handed out by the bucket allocator. The
+ * caller is responsible for destroying the bucket allocator and the
+ * apr_allocator_t -- no automatic cleanups will happen.
+ * @warning The allocator must never be used by more than one thread at a time.
+ */
+APU_DECLARE_NONSTD(apr_bucket_alloc_t *) apr_bucket_alloc_create_ex(apr_allocator_t *allocator);
+
+/**
+ * Destroy a bucket allocator.
+ * @param list The allocator to be destroyed
+ */
+APU_DECLARE_NONSTD(void) apr_bucket_alloc_destroy(apr_bucket_alloc_t *list);
+
+/**
+ * Allocate memory for use by the buckets.
+ * @param size The amount to allocate.
+ * @param list The allocator from which to allocate the memory.
+ */
+APU_DECLARE_NONSTD(void *) apr_bucket_alloc(apr_size_t size, apr_bucket_alloc_t *list);
+
+/**
+ * Free memory previously allocated with apr_bucket_alloc().
+ * @param block The block of memory to be freed.
+ */
+APU_DECLARE_NONSTD(void) apr_bucket_free(void *block);
+
+
+/* ***** Bucket Functions ***** */
+/**
+ * Free the resources used by a bucket. If multiple buckets refer to
+ * the same resource it is freed when the last one goes away.
+ * @see apr_bucket_delete()
+ * @param e The bucket to destroy
+ */
+#define apr_bucket_destroy(e) do { \
+ (e)->type->destroy((e)->data); \
+ (e)->free(e); \
+ } while (0)
+
+/**
+ * Delete a bucket by removing it from its brigade (if any) and then
+ * destroying it.
+ * @remark This mainly acts as an aid in avoiding code verbosity. It is
+ * the preferred exact equivalent to:
+ * <pre>
+ * APR_BUCKET_REMOVE(e);
+ * apr_bucket_destroy(e);
+ * </pre>
+ * @param e The bucket to delete
+ */
+#define apr_bucket_delete(e) do { \
+ APR_BUCKET_REMOVE(e); \
+ apr_bucket_destroy(e); \
+ } while (0)
+
+/**
+ * read the data from the bucket
+ * @param e The bucket to read from
+ * @param str The location to store the data in
+ * @param len The amount of data read
+ * @param block Whether the read function blocks
+ */
+#define apr_bucket_read(e,str,len,block) (e)->type->read(e, str, len, block)
+
+/**
+ * Setaside data so that stack data is not destroyed on returning from
+ * the function
+ * @param e The bucket to setaside
+ * @param p The pool to setaside into
+ */
+#define apr_bucket_setaside(e,p) (e)->type->setaside(e,p)
+
+/**
+ * Split one bucket in two.
+ * @param e The bucket to split
+ * @param point The offset to split the bucket at
+ */
+#define apr_bucket_split(e,point) (e)->type->split(e, point)
+
+/**
+ * Copy a bucket.
+ * @param e The bucket to copy
+ * @param c Returns a pointer to the new bucket
+ */
+#define apr_bucket_copy(e,c) (e)->type->copy(e, c)
+
+/* Bucket type handling */
+
+/**
+ * This function simply returns APR_SUCCESS to denote that the bucket does
+ * not require anything to happen for its setaside() function. This is
+ * appropriate for buckets that have "immortal" data -- the data will live
+ * at least as long as the bucket.
+ * @param data The bucket to setaside
+ * @param pool The pool defining the desired lifetime of the bucket data
+ * @return APR_SUCCESS
+ */
+APU_DECLARE_NONSTD(apr_status_t) apr_bucket_setaside_noop(apr_bucket *data,
+ apr_pool_t *pool);
+
+/**
+ * A place holder function that signifies that the setaside function was not
+ * implemented for this bucket
+ * @param data The bucket to setaside
+ * @param pool The pool defining the desired lifetime of the bucket data
+ * @return APR_ENOTIMPL
+ */
+APU_DECLARE_NONSTD(apr_status_t) apr_bucket_setaside_notimpl(apr_bucket *data,
+ apr_pool_t *pool);
+
+/**
+ * A place holder function that signifies that the split function was not
+ * implemented for this bucket
+ * @param data The bucket to split
+ * @param point The location to split the bucket
+ * @return APR_ENOTIMPL
+ */
+APU_DECLARE_NONSTD(apr_status_t) apr_bucket_split_notimpl(apr_bucket *data,
+ apr_size_t point);
+
+/**
+ * A place holder function that signifies that the copy function was not
+ * implemented for this bucket
+ * @param e The bucket to copy
+ * @param c Returns a pointer to the new bucket
+ * @return APR_ENOTIMPL
+ */
+APU_DECLARE_NONSTD(apr_status_t) apr_bucket_copy_notimpl(apr_bucket *e,
+ apr_bucket **c);
+
+/**
+ * A place holder function that signifies that this bucket does not need
+ * to do anything special to be destroyed. That's only the case for buckets
+ * that either have no data (metadata buckets) or buckets whose data pointer
+ * points to something that's not a bucket-type-specific structure, as with
+ * simple buckets where data points to a string and pipe buckets where data
+ * points directly to the apr_file_t.
+ * @param data The bucket data to destroy
+ */
+APU_DECLARE_NONSTD(void) apr_bucket_destroy_noop(void *data);
+
+/**
+ * There is no apr_bucket_destroy_notimpl, because destruction is required
+ * to be implemented (it could be a noop, but only if that makes sense for
+ * the bucket type)
+ */
+
+/* There is no apr_bucket_read_notimpl, because it is a required function
+ */
+
+
+/* All of the bucket types implemented by the core */
+/**
+ * The flush bucket type. This signifies that all data should be flushed to
+ * the next filter. The flush bucket should be sent with the other buckets.
+ */
+APU_DECLARE_DATA extern const apr_bucket_type_t apr_bucket_type_flush;
+/**
+ * The EOS bucket type. This signifies that there will be no more data, ever.
+ * All filters MUST send all data to the next filter when they receive a
+ * bucket of this type
+ */
+APU_DECLARE_DATA extern const apr_bucket_type_t apr_bucket_type_eos;
+/**
+ * The FILE bucket type. This bucket represents a file on disk
+ */
+APU_DECLARE_DATA extern const apr_bucket_type_t apr_bucket_type_file;
+/**
+ * The HEAP bucket type. This bucket represents a data allocated from the
+ * heap.
+ */
+APU_DECLARE_DATA extern const apr_bucket_type_t apr_bucket_type_heap;
+#if APR_HAS_MMAP
+/**
+ * The MMAP bucket type. This bucket represents an MMAP'ed file
+ */
+APU_DECLARE_DATA extern const apr_bucket_type_t apr_bucket_type_mmap;
+#endif
+/**
+ * The POOL bucket type. This bucket represents a data that was allocated
+ * from a pool. IF this bucket is still available when the pool is cleared,
+ * the data is copied on to the heap.
+ */
+APU_DECLARE_DATA extern const apr_bucket_type_t apr_bucket_type_pool;
+/**
+ * The PIPE bucket type. This bucket represents a pipe to another program.
+ */
+APU_DECLARE_DATA extern const apr_bucket_type_t apr_bucket_type_pipe;
+/**
+ * The IMMORTAL bucket type. This bucket represents a segment of data that
+ * the creator is willing to take responsibility for. The core will do
+ * nothing with the data in an immortal bucket
+ */
+APU_DECLARE_DATA extern const apr_bucket_type_t apr_bucket_type_immortal;
+/**
+ * The TRANSIENT bucket type. This bucket represents a data allocated off
+ * the stack. When the setaside function is called, this data is copied on
+ * to the heap
+ */
+APU_DECLARE_DATA extern const apr_bucket_type_t apr_bucket_type_transient;
+/**
+ * The SOCKET bucket type. This bucket represents a socket to another machine
+ */
+APU_DECLARE_DATA extern const apr_bucket_type_t apr_bucket_type_socket;
+
+
+/* ***** Simple buckets ***** */
+
+/**
+ * Split a simple bucket into two at the given point. Most non-reference
+ * counting buckets that allow multiple references to the same block of
+ * data (eg transient and immortal) will use this as their split function
+ * without any additional type-specific handling.
+ * @param b The bucket to be split
+ * @param point The offset of the first byte in the new bucket
+ * @return APR_EINVAL if the point is not within the bucket;
+ * APR_ENOMEM if allocation failed;
+ * or APR_SUCCESS
+ */
+APU_DECLARE_NONSTD(apr_status_t) apr_bucket_simple_split(apr_bucket *b,
+ apr_size_t point);
+
+/**
+ * Copy a simple bucket. Most non-reference-counting buckets that allow
+ * multiple references to the same block of data (eg transient and immortal)
+ * will use this as their copy function without any additional type-specific
+ * handling.
+ * @param a The bucket to copy
+ * @param b Returns a pointer to the new bucket
+ * @return APR_ENOMEM if allocation failed;
+ * or APR_SUCCESS
+ */
+APU_DECLARE_NONSTD(apr_status_t) apr_bucket_simple_copy(apr_bucket *a,
+ apr_bucket **b);
+
+
+/* ***** Shared, reference-counted buckets ***** */
+
+/**
+ * Initialize a bucket containing reference-counted data that may be
+ * shared. The caller must allocate the bucket if necessary and
+ * initialize its type-dependent fields, and allocate and initialize
+ * its own private data structure. This function should only be called
+ * by type-specific bucket creation functions.
+ * @param b The bucket to initialize
+ * @param data A pointer to the private data structure
+ * with the reference count at the start
+ * @param start The start of the data in the bucket
+ * relative to the private base pointer
+ * @param length The length of the data in the bucket
+ * @return The new bucket, or NULL if allocation failed
+ */
+APU_DECLARE(apr_bucket *) apr_bucket_shared_make(apr_bucket *b, void *data,
+ apr_off_t start,
+ apr_size_t length);
+
+/**
+ * Decrement the refcount of the data in the bucket. This function
+ * should only be called by type-specific bucket destruction functions.
+ * @param data The private data pointer from the bucket to be destroyed
+ * @return TRUE or FALSE; TRUE if the reference count is now
+ * zero, indicating that the shared resource itself can
+ * be destroyed by the caller.
+ */
+APU_DECLARE(int) apr_bucket_shared_destroy(void *data);
+
+/**
+ * Split a bucket into two at the given point, and adjust the refcount
+ * to the underlying data. Most reference-counting bucket types will
+ * be able to use this function as their split function without any
+ * additional type-specific handling.
+ * @param b The bucket to be split
+ * @param point The offset of the first byte in the new bucket
+ * @return APR_EINVAL if the point is not within the bucket;
+ * APR_ENOMEM if allocation failed;
+ * or APR_SUCCESS
+ */
+APU_DECLARE_NONSTD(apr_status_t) apr_bucket_shared_split(apr_bucket *b,
+ apr_size_t point);
+
+/**
+ * Copy a refcounted bucket, incrementing the reference count. Most
+ * reference-counting bucket types will be able to use this function
+ * as their copy function without any additional type-specific handling.
+ * @param a The bucket to copy
+ * @param b Returns a pointer to the new bucket
+ * @return APR_ENOMEM if allocation failed;
+ or APR_SUCCESS
+ */
+APU_DECLARE_NONSTD(apr_status_t) apr_bucket_shared_copy(apr_bucket *a,
+ apr_bucket **b);
+
+
+/* ***** Functions to Create Buckets of varying types ***** */
+/*
+ * Each bucket type foo has two initialization functions:
+ * apr_bucket_foo_make which sets up some already-allocated memory as a
+ * bucket of type foo; and apr_bucket_foo_create which allocates memory
+ * for the bucket, calls apr_bucket_make_foo, and initializes the
+ * bucket's list pointers. The apr_bucket_foo_make functions are used
+ * inside the bucket code to change the type of buckets in place;
+ * other code should call apr_bucket_foo_create. All the initialization
+ * functions change nothing if they fail.
+ */
+
+/**
+ * Create an End of Stream bucket. This indicates that there is no more data
+ * coming from down the filter stack. All filters should flush at this point.
+ * @param list The freelist from which this bucket should be allocated
+ * @return The new bucket, or NULL if allocation failed
+ */
+APU_DECLARE(apr_bucket *) apr_bucket_eos_create(apr_bucket_alloc_t *list);
+
+/**
+ * Make the bucket passed in an EOS bucket. This indicates that there is no
+ * more data coming from down the filter stack. All filters should flush at
+ * this point.
+ * @param b The bucket to make into an EOS bucket
+ * @return The new bucket, or NULL if allocation failed
+ */
+APU_DECLARE(apr_bucket *) apr_bucket_eos_make(apr_bucket *b);
+
+/**
+ * Create a flush bucket. This indicates that filters should flush their
+ * data. There is no guarantee that they will flush it, but this is the
+ * best we can do.
+ * @param list The freelist from which this bucket should be allocated
+ * @return The new bucket, or NULL if allocation failed
+ */
+APU_DECLARE(apr_bucket *) apr_bucket_flush_create(apr_bucket_alloc_t *list);
+
+/**
+ * Make the bucket passed in a FLUSH bucket. This indicates that filters
+ * should flush their data. There is no guarantee that they will flush it,
+ * but this is the best we can do.
+ * @param b The bucket to make into a FLUSH bucket
+ * @return The new bucket, or NULL if allocation failed
+ */
+APU_DECLARE(apr_bucket *) apr_bucket_flush_make(apr_bucket *b);
+
+/**
+ * Create a bucket referring to long-lived data.
+ * @param buf The data to insert into the bucket
+ * @param nbyte The size of the data to insert.
+ * @param list The freelist from which this bucket should be allocated
+ * @return The new bucket, or NULL if allocation failed
+ */
+APU_DECLARE(apr_bucket *) apr_bucket_immortal_create(const char *buf,
+ apr_size_t nbyte,
+ apr_bucket_alloc_t *list);
+
+/**
+ * Make the bucket passed in a bucket refer to long-lived data
+ * @param b The bucket to make into a IMMORTAL bucket
+ * @param buf The data to insert into the bucket
+ * @param nbyte The size of the data to insert.
+ * @return The new bucket, or NULL if allocation failed
+ */
+APU_DECLARE(apr_bucket *) apr_bucket_immortal_make(apr_bucket *b,
+ const char *buf,
+ apr_size_t nbyte);
+
+/**
+ * Create a bucket referring to data on the stack.
+ * @param buf The data to insert into the bucket
+ * @param nbyte The size of the data to insert.
+ * @param list The freelist from which this bucket should be allocated
+ * @return The new bucket, or NULL if allocation failed
+ */
+APU_DECLARE(apr_bucket *) apr_bucket_transient_create(const char *buf,
+ apr_size_t nbyte,
+ apr_bucket_alloc_t *list);
+
+/**
+ * Make the bucket passed in a bucket refer to stack data
+ * @param b The bucket to make into a TRANSIENT bucket
+ * @param buf The data to insert into the bucket
+ * @param nbyte The size of the data to insert.
+ * @return The new bucket, or NULL if allocation failed
+ */
+APU_DECLARE(apr_bucket *) apr_bucket_transient_make(apr_bucket *b,
+ const char *buf,
+ apr_size_t nbyte);
+
+/**
+ * Create a bucket referring to memory on the heap. If the caller asks
+ * for the data to be copied, this function always allocates 4K of
+ * memory so that more data can be added to the bucket without
+ * requiring another allocation. Therefore not all the data may be put
+ * into the bucket. If copying is not requested then the bucket takes
+ * over responsibility for free()ing the memory.
+ * @param buf The buffer to insert into the bucket
+ * @param nbyte The size of the buffer to insert.
+ * @param free_func Function to use to free the data; NULL indicates that the
+ * bucket should make a copy of the data
+ * @param list The freelist from which this bucket should be allocated
+ * @return The new bucket, or NULL if allocation failed
+ */
+APU_DECLARE(apr_bucket *) apr_bucket_heap_create(const char *buf,
+ apr_size_t nbyte,
+ void (*free_func)(void *data),
+ apr_bucket_alloc_t *list);
+/**
+ * Make the bucket passed in a bucket refer to heap data
+ * @param b The bucket to make into a HEAP bucket
+ * @param buf The buffer to insert into the bucket
+ * @param nbyte The size of the buffer to insert.
+ * @param free_func Function to use to free the data; NULL indicates that the
+ * bucket should make a copy of the data
+ * @return The new bucket, or NULL if allocation failed
+ */
+APU_DECLARE(apr_bucket *) apr_bucket_heap_make(apr_bucket *b, const char *buf,
+ apr_size_t nbyte,
+ void (*free_func)(void *data));
+
+/**
+ * Create a bucket referring to memory allocated from a pool.
+ *
+ * @param buf The buffer to insert into the bucket
+ * @param length The number of bytes referred to by this bucket
+ * @param pool The pool the memory was allocated from
+ * @param list The freelist from which this bucket should be allocated
+ * @return The new bucket, or NULL if allocation failed
+ */
+APU_DECLARE(apr_bucket *) apr_bucket_pool_create(const char *buf,
+ apr_size_t length,
+ apr_pool_t *pool,
+ apr_bucket_alloc_t *list);
+
+/**
+ * Make the bucket passed in a bucket refer to pool data
+ * @param b The bucket to make into a pool bucket
+ * @param buf The buffer to insert into the bucket
+ * @param length The number of bytes referred to by this bucket
+ * @param pool The pool the memory was allocated from
+ * @return The new bucket, or NULL if allocation failed
+ */
+APU_DECLARE(apr_bucket *) apr_bucket_pool_make(apr_bucket *b, const char *buf,
+ apr_size_t length,
+ apr_pool_t *pool);
+
+#if APR_HAS_MMAP
+/**
+ * Create a bucket referring to mmap()ed memory.
+ * @param mm The mmap to insert into the bucket
+ * @param start The offset of the first byte in the mmap
+ * that this bucket refers to
+ * @param length The number of bytes referred to by this bucket
+ * @param list The freelist from which this bucket should be allocated
+ * @return The new bucket, or NULL if allocation failed
+ */
+APU_DECLARE(apr_bucket *) apr_bucket_mmap_create(apr_mmap_t *mm,
+ apr_off_t start,
+ apr_size_t length,
+ apr_bucket_alloc_t *list);
+
+/**
+ * Make the bucket passed in a bucket refer to an MMAP'ed file
+ * @param b The bucket to make into a MMAP bucket
+ * @param mm The mmap to insert into the bucket
+ * @param start The offset of the first byte in the mmap
+ * that this bucket refers to
+ * @param length The number of bytes referred to by this bucket
+ * @return The new bucket, or NULL if allocation failed
+ */
+APU_DECLARE(apr_bucket *) apr_bucket_mmap_make(apr_bucket *b, apr_mmap_t *mm,
+ apr_off_t start,
+ apr_size_t length);
+#endif
+
+/**
+ * Create a bucket referring to a socket.
+ * @param thissock The socket to put in the bucket
+ * @param list The freelist from which this bucket should be allocated
+ * @return The new bucket, or NULL if allocation failed
+ */
+APU_DECLARE(apr_bucket *) apr_bucket_socket_create(apr_socket_t *thissock,
+ apr_bucket_alloc_t *list);
+/**
+ * Make the bucket passed in a bucket refer to a socket
+ * @param b The bucket to make into a SOCKET bucket
+ * @param thissock The socket to put in the bucket
+ * @return The new bucket, or NULL if allocation failed
+ */
+APU_DECLARE(apr_bucket *) apr_bucket_socket_make(apr_bucket *b,
+ apr_socket_t *thissock);
+
+/**
+ * Create a bucket referring to a pipe.
+ * @param thispipe The pipe to put in the bucket
+ * @param list The freelist from which this bucket should be allocated
+ * @return The new bucket, or NULL if allocation failed
+ */
+APU_DECLARE(apr_bucket *) apr_bucket_pipe_create(apr_file_t *thispipe,
+ apr_bucket_alloc_t *list);
+
+/**
+ * Make the bucket passed in a bucket refer to a pipe
+ * @param b The bucket to make into a PIPE bucket
+ * @param thispipe The pipe to put in the bucket
+ * @return The new bucket, or NULL if allocation failed
+ */
+APU_DECLARE(apr_bucket *) apr_bucket_pipe_make(apr_bucket *b,
+ apr_file_t *thispipe);
+
+/**
+ * Create a bucket referring to a file.
+ * @param fd The file to put in the bucket
+ * @param offset The offset where the data of interest begins in the file
+ * @param len The amount of data in the file we are interested in
+ * @param p The pool into which any needed structures should be created
+ * while reading from this file bucket
+ * @param list The freelist from which this bucket should be allocated
+ * @return The new bucket, or NULL if allocation failed
+ */
+APU_DECLARE(apr_bucket *) apr_bucket_file_create(apr_file_t *fd,
+ apr_off_t offset,
+ apr_size_t len,
+ apr_pool_t *p,
+ apr_bucket_alloc_t *list);
+
+/**
+ * Make the bucket passed in a bucket refer to a file
+ * @param b The bucket to make into a FILE bucket
+ * @param fd The file to put in the bucket
+ * @param offset The offset where the data of interest begins in the file
+ * @param len The amount of data in the file we are interested in
+ * @param p The pool into which any needed structures should be created
+ * while reading from this file bucket
+ * @return The new bucket, or NULL if allocation failed
+ */
+APU_DECLARE(apr_bucket *) apr_bucket_file_make(apr_bucket *b, apr_file_t *fd,
+ apr_off_t offset,
+ apr_size_t len, apr_pool_t *p);
+
+/**
+ * Enable or disable memory-mapping for a FILE bucket (default is enabled)
+ * @param b The bucket
+ * @param enabled Whether memory-mapping should be enabled
+ * @return APR_SUCCESS normally, or an error code if the operation fails
+ */
+APU_DECLARE(apr_status_t) apr_bucket_file_enable_mmap(apr_bucket *b,
+ int enabled);
+
+/** @} */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !APR_BUCKETS_H */
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APR_DATE_H
+#define APR_DATE_H
+
+/**
+ * @file apr_date.h
+ * @brief APR-UTIL date routines
+ */
+
+/**
+ * @defgroup APR_Util_Date Date routines
+ * @ingroup APR_Util
+ * @{
+ */
+
+/*
+ * apr_date.h: prototypes for date parsing utility routines
+ */
+
+#include "apu.h"
+#include "apr_time.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** A bad date. */
+#define APR_DATE_BAD ((apr_time_t)0)
+
+/**
+ * Compare a string to a mask
+ * @param data The string to compare
+ * @param mask Mask characters (arbitrary maximum is 256 characters):
+ * <PRE>
+ * '\@' - uppercase letter
+ * '\$' - lowercase letter
+ * '\&' - hex digit
+ * '#' - digit
+ * '~' - digit or space
+ * '*' - swallow remaining characters
+ * </PRE>
+ * @remark The mask tests for an exact match for any other character
+ * @return 1 if the string matches, 0 otherwise
+ */
+APU_DECLARE(int) apr_date_checkmask(const char *data, const char *mask);
+
+/**
+ * Parses an HTTP date in one of three standard forms:
+ * <PRE>
+ * Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123
+ * Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
+ * Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format
+ * </PRE>
+ * @param date The date in one of the three formats above
+ * @return the apr_time_t number of microseconds since 1 Jan 1970 GMT, or
+ * 0 if this would be out of range or if the date is invalid.
+ */
+APU_DECLARE(apr_time_t) apr_date_parse_http(const char *date);
+
+/**
+ * Parses a string resembling an RFC 822 date. This is meant to be
+ * leinent in its parsing of dates. Hence, this will parse a wider
+ * range of dates than apr_date_parse_http.
+ *
+ * The prominent mailer (or poster, if mailer is unknown) that has
+ * been seen in the wild is included for the unknown formats.
+ * <PRE>
+ * Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123
+ * Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
+ * Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format
+ * Sun, 6 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123
+ * Sun, 06 Nov 94 08:49:37 GMT ; RFC 822
+ * Sun, 6 Nov 94 08:49:37 GMT ; RFC 822
+ * Sun, 06 Nov 94 08:49 GMT ; Unknown [drtr\@ast.cam.ac.uk]
+ * Sun, 6 Nov 94 08:49 GMT ; Unknown [drtr\@ast.cam.ac.uk]
+ * Sun, 06 Nov 94 8:49:37 GMT ; Unknown [Elm 70.85]
+ * Sun, 6 Nov 94 8:49:37 GMT ; Unknown [Elm 70.85]
+ * </PRE>
+ *
+ * @param date The date in one of the formats above
+ * @return the apr_time_t number of microseconds since 1 Jan 1970 GMT, or
+ * 0 if this would be out of range or if the date is invalid.
+ */
+APU_DECLARE(apr_time_t) apr_date_parse_rfc(const char *date);
+
+/** @} */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !APR_DATE_H */
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Overview of what this is and does:
+ * http://www.apache.org/~niq/dbd.html
+ */
+
+#ifndef APR_DBD_H
+#define APR_DBD_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* These are opaque structs. Instantiation is up to each backend */
+#ifndef APR_DBD_INTERNAL
+typedef struct apr_dbd_t apr_dbd_t;
+typedef struct apr_dbd_transaction_t apr_dbd_transaction_t;
+typedef struct apr_dbd_results_t apr_dbd_results_t;
+typedef struct apr_dbd_row_t apr_dbd_row_t;
+typedef struct apr_dbd_prepared_t apr_dbd_prepared_t;
+#endif
+
+typedef struct apr_dbd_driver_t {
+ /** name */
+ const char *name;
+
+ /** init: allow driver to perform once-only initialisation.
+ * Called once only. May be NULL
+ */
+ void (*init)(apr_pool_t *pool);
+
+ /** native_handle: return the native database handle of the underlying db
+ *
+ * @param handle - apr_dbd handle
+ * @return - native handle
+ */
+ void *(*native_handle)(apr_dbd_t *handle);
+
+ /** open: obtain a database connection from the server rec.
+ * Must be explicitly closed when you're finished with it.
+ * WARNING: only use this when you need a connection with
+ * a lifetime other than a request
+ *
+ * @param pool - a pool to use for error messages (if any).
+ * @param s - server rec managing the underlying connection/pool.
+ * @return database handle, or NULL on error.
+ */
+ apr_dbd_t *(*open)(apr_pool_t *pool, const char *params);
+
+ /** check_conn: check status of a database connection
+ *
+ * @param pool - a pool to use for error messages (if any).
+ * @param handle - the connection to check
+ * @return APR_SUCCESS or error
+ */
+ apr_status_t (*check_conn)(apr_pool_t *pool, apr_dbd_t *handle);
+
+ /** close: close/release a connection obtained from open()
+ *
+ * @param handle - the connection to release
+ * @return APR_SUCCESS or error
+ */
+ apr_status_t (*close)(apr_dbd_t *handle);
+
+ /** set_dbname: select database name. May be a no-op if not supported.
+ *
+ * @param pool - working pool
+ * @param handle - the connection
+ * @param name - the database to select
+ * @return 0 for success or error code
+ */
+ int (*set_dbname)(apr_pool_t* pool, apr_dbd_t *handle, const char *name);
+
+ /** transaction: start a transaction. May be a no-op.
+ *
+ * @param pool - a pool to use for error messages (if any).
+ * @param handle - the connection
+ * @param transaction - ptr to a transaction. May be null on entry
+ * @return 0 for success or error code
+ */
+ int (*start_transaction)(apr_pool_t *pool, apr_dbd_t *handle,
+ apr_dbd_transaction_t **trans);
+
+ /** end_transaction: end a transaction
+ * (commit on success, rollback on error).
+ * May be a no-op.
+ *
+ * @param transaction - the transaction.
+ * @return 0 for success or error code
+ */
+ int (*end_transaction)(apr_dbd_transaction_t *trans);
+
+ /** query: execute an SQL query that doesn't return a result set
+ *
+ * @param handle - the connection
+ * @param nrows - number of rows affected.
+ * @param statement - the SQL statement to execute
+ * @return 0 for success or error code
+ */
+ int (*query)(apr_dbd_t *handle, int *nrows, const char *statement);
+
+ /** select: execute an SQL query that returns a result set
+ *
+ * @param pool - pool to allocate the result set
+ * @param handle - the connection
+ * @param res - pointer to result set pointer. May point to NULL on entry
+ * @param statement - the SQL statement to execute
+ * @param random - 1 to support random access to results (seek any row);
+ * 0 to support only looping through results in order
+ * (async access - faster)
+ * @return 0 for success or error code
+ */
+ int (*select)(apr_pool_t *pool, apr_dbd_t *handle, apr_dbd_results_t **res,
+ const char *statement, int random);
+
+ /** num_cols: get the number of columns in a results set
+ *
+ * @param res - result set.
+ * @return number of columns
+ */
+ int (*num_cols)(apr_dbd_results_t *res);
+
+ /** num_tuples: get the number of rows in a results set
+ * of a synchronous select
+ *
+ * @param res - result set.
+ * @return number of rows, or -1 if the results are asynchronous
+ */
+ int (*num_tuples)(apr_dbd_results_t *res);
+
+ /** get_row: get a row from a result set
+ *
+ * @param pool - pool to allocate the row
+ * @param res - result set pointer
+ * @param row - pointer to row pointer. May point to NULL on entry
+ * @param rownum - row number, or -1 for "next row". Ignored if random
+ * access is not supported.
+ * @return 0 for success, -1 for rownum out of range or data finished
+ */
+ int (*get_row)(apr_pool_t *pool, apr_dbd_results_t *res,
+ apr_dbd_row_t **row, int rownum);
+
+ /** get_entry: get an entry from a row
+ *
+ * @param row - row pointer
+ * @param col - entry number
+ * @return value from the row, or NULL if col is out of bounds.
+ */
+ const char *(*get_entry)(const apr_dbd_row_t *row, int col);
+
+ /** error: get current error message (if any)
+ *
+ * @param handle - the connection
+ * @param errnum - error code from operation that returned an error
+ * @return the database current error message, or message for errnum
+ * (implementation-dependent whether errnum is ignored)
+ */
+ const char *(*error)(apr_dbd_t *handle, int errnum);
+
+ /** escape: escape a string so it is safe for use in query/select
+ *
+ * @param pool - pool to alloc the result from
+ * @param string - the string to escape
+ * @param handle - the connection
+ * @return the escaped, safe string
+ */
+ const char *(*escape)(apr_pool_t *pool, const char *string,
+ apr_dbd_t *handle);
+
+ /** prepare: prepare a statement
+ *
+ * @param pool - pool to alloc the result from
+ * @param handle - the connection
+ * @param query - the SQL query
+ * @param label - A label for the prepared statement.
+ * use NULL for temporary prepared statements
+ * (eg within a Request in httpd)
+ * @param statement - statement to prepare. May point to null on entry.
+ * @return 0 for success or error code
+ */
+ int (*prepare)(apr_pool_t *pool, apr_dbd_t *handle, const char *query,
+ const char *label, apr_dbd_prepared_t **statement);
+
+ /** pvquery: query using a prepared statement + args
+ *
+ * @param pool - working pool
+ * @param handle - the connection
+ * @param nrows - number of rows affected.
+ * @param statement - the prepared statement to execute
+ * @param ... - args to prepared statement
+ * @return 0 for success or error code
+ */
+ int (*pvquery)(apr_pool_t *pool, apr_dbd_t *handle, int *nrows,
+ apr_dbd_prepared_t *statement, ...);
+
+ /** pvselect: select using a prepared statement + args
+ *
+ * @param pool - working pool
+ * @param handle - the connection
+ * @param res - pointer to query results. May point to NULL on entry
+ * @param statement - the prepared statement to execute
+ * @param random - Whether to support random-access to results
+ * @param ... - args to prepared statement
+ * @return 0 for success or error code
+ */
+ int (*pvselect)(apr_pool_t *pool, apr_dbd_t *handle,
+ apr_dbd_results_t **res,
+ apr_dbd_prepared_t *statement, int random, ...);
+
+ /** pquery: query using a prepared statement + args
+ *
+ * @param pool - working pool
+ * @param handle - the connection
+ * @param nrows - number of rows affected.
+ * @param statement - the prepared statement to execute
+ * @param nargs - number of args to prepared statement
+ * @param args - args to prepared statement
+ * @return 0 for success or error code
+ */
+ int (*pquery)(apr_pool_t *pool, apr_dbd_t *handle, int *nrows,
+ apr_dbd_prepared_t *statement, int nargs, const char **args);
+
+ /** pselect: select using a prepared statement + args
+ *
+ * @param pool - working pool
+ * @param handle - the connection
+ * @param res - pointer to query results. May point to NULL on entry
+ * @param statement - the prepared statement to execute
+ * @param random - Whether to support random-access to results
+ * @param nargs - number of args to prepared statement
+ * @param args - args to prepared statement
+ * @return 0 for success or error code
+ */
+ int (*pselect)(apr_pool_t *pool, apr_dbd_t *handle,
+ apr_dbd_results_t **res, apr_dbd_prepared_t *statement,
+ int random, int nargs, const char **args);
+
+
+} apr_dbd_driver_t;
+
+/** apr_dbd_init: perform once-only initialisation. Call once only.
+ *
+ * @param pool - pool to register any shutdown cleanups, etc
+ */
+APU_DECLARE(apr_status_t) apr_dbd_init(apr_pool_t *pool);
+
+/** apr_dbd_get_driver: get the driver struct for a name
+ *
+ * @param pool - (process) pool to register cleanup
+ * @param name - driver name
+ * @param driver - pointer to driver struct.
+ * @return APR_SUCCESS for success
+ * @return APR_ENOTIMPL for no driver (when DSO not enabled)
+ * @return APR_EDSOOPEN if DSO driver file can't be opened
+ * @return APR_ESYMNOTFOUND if the driver file doesn't contain a driver
+ */
+APU_DECLARE(apr_status_t) apr_dbd_get_driver(apr_pool_t *pool, const char *name,
+ apr_dbd_driver_t **driver);
+
+/** apr_dbd_open: open a connection to a backend
+ *
+ * @param ptmp - working pool
+ * @param params - arguments to driver (implementation-dependent)
+ * @param handle - pointer to handle to return
+ * @param driver - driver struct.
+ * @return APR_SUCCESS for success
+ * @return APR_EGENERAL if driver exists but connection failed
+ */
+APU_DECLARE(apr_status_t) apr_dbd_open(apr_dbd_driver_t *driver,
+ apr_pool_t *ptmp, const char *params,
+ apr_dbd_t **handle);
+
+#ifdef DOXYGEN
+/** apr_dbd_close: close a connection to a backend.
+ * Only required for explicit close or
+ *
+ * @param handle - handle to close
+ * @param driver - driver struct.
+ * @return APR_SUCCESS for success or error status
+ */
+APU_DECLARE(apr_status_t) apr_dbd_close(apr_dbd_driver_t *driver,
+ apr_dbd_t *handle);
+#else
+#define apr_dbd_close(driver,handle) (driver)->close((handle))
+#endif
+
+/* apr-function-shaped versions of things */
+
+#ifdef DOXYGEN
+/** apr_dbd_name: get the name of the driver
+ *
+ * @param driver - the driver
+ * @return - name
+ */
+APU_DECLARE(const char*) apr_dbd_name(apr_dbd_driver_t *driver);
+#else
+#define apr_dbd_name(driver) \
+ (driver)->name
+#endif
+
+#ifdef DOXYGEN
+/** apr_dbd_native_handle: get native database handle of the underlying db
+ *
+ * @param driver - the driver
+ * @param handle - apr_dbd handle
+ * @return - native handle
+ */
+APU_DECLARE(void*) apr_dbd_native_handle(apr_dbd_driver_t *driver,
+ apr_dbd_t *handle);
+#else
+#define apr_dbd_native_handle(driver,handler) \
+ (driver)->native_handle(handler)
+#endif
+
+#ifdef DOXYGEN
+/** check_conn: check status of a database connection
+ *
+ * @param driver - the driver
+ * @param pool - working pool
+ * @param handle - the connection to check
+ * @return APR_SUCCESS or error
+ */
+APU_DECLARE(int) apr_dbd_check_conn(apr_dbd_driver_t *driver, apr_pool_t *pool,
+ apr_dbd_t *handle);
+#else
+#define apr_dbd_check_conn(driver,pool,handle) \
+ (driver)->check_conn((pool),(handle))
+#endif
+
+#ifdef DOXYGEN
+/** apr_dbd_set_dbname: select database name. May be a no-op if not supported.
+ *
+ * @param driver - the driver
+ * @param pool - working pool
+ * @param handle - the connection
+ * @param name - the database to select
+ * @return 0 for success or error code
+ */
+APU_DECLARE(int) apr_dbd_set_dbname(apr_dbd_driver_t *driver, apr_pool_t *pool,
+ apr_dbd_t *handle, const char *name);
+#else
+#define apr_dbd_set_dbname(driver,pool,handle,name) \
+ (driver)->set_dbname((pool),(handle),(name))
+#endif
+
+/** apr_dbd_transaction_start: start a transaction. May be a no-op.
+ *
+ * @param driver - the driver
+ * @param pool - a pool to use for error messages (if any).
+ * @param handle - the db connection
+ * @param transaction - ptr to a transaction. May be null on entry
+ * @return 0 for success or error code
+ */
+APU_DECLARE(int) apr_dbd_transaction_start(apr_dbd_driver_t *driver,
+ apr_pool_t *pool,
+ apr_dbd_t *handle,
+ apr_dbd_transaction_t **trans);
+
+/** apr_dbd_transaction_end: end a transaction
+ * (commit on success, rollback on error).
+ * May be a no-op.
+ *
+ * @param driver - the driver
+ * @param handle - the db connection
+ * @param transaction - the transaction.
+ * @return 0 for success or error code
+ */
+APU_DECLARE(int) apr_dbd_transaction_end(apr_dbd_driver_t *driver,
+ apr_pool_t *pool,
+ apr_dbd_transaction_t *trans);
+
+#ifdef DOXYGEN
+/** apr_dbd_query: execute an SQL query that doesn't return a result set
+ *
+ * @param driver - the driver
+ * @param handle - the connection
+ * @param nrows - number of rows affected.
+ * @param statement - the SQL statement to execute
+ * @return 0 for success or error code
+ */
+APU_DECLARE(int) apr_dbd_query(apr_dbd_driver_t *driver, apr_dbd_t *handle,
+ int *nrows, const char *statement);
+#else
+#define apr_dbd_query(driver,handle,nrows,statement) \
+ (driver)->query((handle),(nrows),(statement))
+#endif
+
+#ifdef DOXYGEN
+/** apr_dbd_select: execute an SQL query that returns a result set
+ *
+ * @param driver - the driver
+ * @param pool - pool to allocate the result set
+ * @param handle - the connection
+ * @param res - pointer to result set pointer. May point to NULL on entry
+ * @param statement - the SQL statement to execute
+ * @param random - 1 to support random access to results (seek any row);
+ * 0 to support only looping through results in order
+ * (async access - faster)
+ * @return 0 for success or error code
+ */
+APU_DECLARE(int) apr_dbd_select(apr_dbd_driver_t *driver, apr_pool_t *pool,
+ apr_dbd_t *handle, apr_dbd_results_t *res,
+ const char *statement, int random);
+#else
+#define apr_dbd_select(driver,pool,handle,res,statement,random) \
+ (driver)->select((pool),(handle),(res),(statement),(random))
+#endif
+
+#ifdef DOXYGEN
+/** apr_dbd_num_cols: get the number of columns in a results set
+ *
+ * @param driver - the driver
+ * @param res - result set.
+ * @return number of columns
+ */
+APU_DECLARE(int) apr_dbd_num_cols(apr_dbd_driver_t *driver,
+ apr_dbd_results_t *res);
+#else
+#define apr_dbd_num_cols(driver,res) \
+ (driver)->num_cols((res))
+#endif
+
+#ifdef DOXYGEN
+/** apr_dbd_num_tuples: get the number of rows in a results set
+ * of a synchronous select
+ *
+ * @param driver - the driver
+ * @param res - result set.
+ * @return number of rows, or -1 if the results are asynchronous
+ */
+APU_DECLARE(int) apr_dbd_num_tuples(apr_dbd_driver_t *driver,
+ apr_dbd_results_t *res);
+#else
+#define apr_dbd_num_tuples(driver,res) \
+ (driver)->num_tuples((res))
+#endif
+
+#ifdef DOXYGEN
+/** apr_dbd_get_row: get a row from a result set
+ *
+ * @param driver - the driver
+ * @param pool - pool to allocate the row
+ * @param res - result set pointer
+ * @param row - pointer to row pointer. May point to NULL on entry
+ * @param rownum - row number, or -1 for "next row". Ignored if random
+ * access is not supported.
+ * @return 0 for success, -1 for rownum out of range or data finished
+ */
+APU_DECLARE(int) apr_dbd_get_row(apr_dbd_driver_t *driver, apr_pool_t *pool,
+ apr_dbd_results_t *res, apr_dbd_row_t **row,
+ int rownum);
+#else
+#define apr_dbd_get_row(driver,pool,res,row,rownum) \
+ (driver)->get_row((pool),(res),(row),(rownum))
+#endif
+
+#ifdef DOXYGEN
+/** apr_dbd_get_entry: get an entry from a row
+ *
+ * @param driver - the driver
+ * @param row - row pointer
+ * @param col - entry number
+ * @return value from the row, or NULL if col is out of bounds.
+ */
+APU_DECLARE(const char*) apr_dbd_get_entry(apr_dbd_driver_t *driver,
+ apr_dbd_row_t *row, int col);
+#else
+#define apr_dbd_get_entry(driver,row,col) \
+ (driver)->get_entry((row),(col))
+#endif
+
+#ifdef DOXYGEN
+/** apr_dbd_error: get current error message (if any)
+ *
+ * @param driver - the driver
+ * @param handle - the connection
+ * @param errnum - error code from operation that returned an error
+ * @return the database current error message, or message for errnum
+ * (implementation-dependent whether errnum is ignored)
+ */
+APU_DECLARE(const char*) apr_dbd_error(apr_dbd_driver_t *driver,
+ apr_dbd_t *handle, int errnum);
+#else
+#define apr_dbd_error(driver,handle,errnum) \
+ (driver)->error((handle),(errnum))
+#endif
+
+#ifdef DOXYGEN
+/** apr_dbd_escape: escape a string so it is safe for use in query/select
+ *
+ * @param driver - the driver
+ * @param pool - pool to alloc the result from
+ * @param string - the string to escape
+ * @param handle - the connection
+ * @return the escaped, safe string
+ */
+APU_DECLARE(const char*) apr_dbd_escape(apr_dbd_driver_t *driver,
+ apr_pool_t *pool, const char *string,
+ apr_dbd_t *handle);
+#else
+#define apr_dbd_escape(driver,pool,string,handle) \
+ (driver)->escape((pool),(string),(handle))
+#endif
+
+#ifdef DOXYGEN
+/** apr_dbd_prepare: prepare a statement
+ *
+ * @param driver - the driver
+ * @param pool - pool to alloc the result from
+ * @param handle - the connection
+ * @param query - the SQL query
+ * @param label - A label for the prepared statement.
+ * use NULL for temporary prepared statements
+ * (eg within a Request in httpd)
+ * @param statement - statement to prepare. May point to null on entry.
+ * @return 0 for success or error code
+ */
+APU_DECLARE(int) apr_dbd_prepare(apr_dbd_driver_t *driver, apr_pool_t *pool,
+ apr_dbd_t *handle, const char *query,
+ const char *label,
+ apr_dbd_prepared_t **statement);
+#else
+#define apr_dbd_prepare(driver,pool,handle,query,label,statement) \
+ (driver)->prepare((pool),(handle),(query),(label),(statement))
+#endif
+
+
+
+/* need macros that do varargs to deal with pvquery and pvselect :-) */
+
+#ifdef DOXYGEN
+/** apr_dbd_pquery: query using a prepared statement + args
+ *
+ * @param driver - the driver
+ * @param pool - working pool
+ * @param handle - the connection
+ * @param nrows - number of rows affected.
+ * @param statement - the prepared statement to execute
+ * @param nargs - number of args to prepared statement
+ * @param args - args to prepared statement
+ * @return 0 for success or error code
+ */
+APU_DECLARE(int) apr_dbd_pquery(apr_dbd_driver_t *driver, apr_pool_t *pool,
+ apr_dbd_t *handle, int *nrows,
+ apr_dbd_prepared_t *statement, int nargs,
+ const char **args);
+#else
+#define apr_dbd_pquery(driver,pool,handle,nrows,statement,nargs,args) \
+ (driver)->pquery((pool),(handle),(nrows),(statement), \
+ (nargs),(args))
+#endif
+
+#ifdef DOXYGEN
+/** apr_dbd_pselect: select using a prepared statement + args
+ *
+ * @param driver - the driver
+ * @param pool - working pool
+ * @param handle - the connection
+ * @param res - pointer to query results. May point to NULL on entry
+ * @param statement - the prepared statement to execute
+ * @param random - Whether to support random-access to results
+ * @param nargs - number of args to prepared statement
+ * @param args - args to prepared statement
+ * @return 0 for success or error code
+ */
+APU_DECLARE(int) apr_dbd_pselect(apr_dbd_driver_t *driver, apr_pool_t *pool,
+ apr_dbd_t *handle, apr_dbd_results_t **res,
+ apr_dbd_prepared_t *statement, int random,
+ int nargs, const char **args);
+#else
+#define apr_dbd_pselect(driver,pool,handle,res,statement,random,nargs,args) \
+ (driver)->pselect((pool),(handle),(res),(statement), \
+ (random),(nargs),(args))
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APR_DBM_H
+#define APR_DBM_H
+
+#include "apu.h"
+#include "apr.h"
+#include "apr_errno.h"
+#include "apr_pools.h"
+#include "apr_file_info.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @file apr_dbm.h
+ * @brief APR-UTIL DBM library
+ */
+/**
+ * @defgroup APR_Util_DBM DBM routines
+ * @ingroup APR_Util
+ * @{
+ */
+/**
+ * Structure for referencing a dbm
+ */
+typedef struct apr_dbm_t apr_dbm_t;
+
+/**
+ * Structure for referencing the datum record within a dbm
+ */
+typedef struct
+{
+ /** pointer to the 'data' to retrieve/store in the DBM */
+ char *dptr;
+ /** size of the 'data' to retrieve/store in the DBM */
+ apr_size_t dsize;
+} apr_datum_t;
+
+/* modes to open the DB */
+#define APR_DBM_READONLY 1 /**< open for read-only access */
+#define APR_DBM_READWRITE 2 /**< open for read-write access */
+#define APR_DBM_RWCREATE 3 /**< open for r/w, create if needed */
+#define APR_DBM_RWTRUNC 4 /**< open for r/w, truncating an existing
+ DB if present */
+/**
+ * Open a dbm file by file name and type of DBM
+ * @param dbm The newly opened database
+ * @param type The type of the DBM (not all may be available at run time)
+ * <pre>
+ * GDBM for GDBM files
+ * SDBM for SDBM files
+ * DB for berkeley DB files
+ * NDBM for NDBM files
+ * default for the default DBM type
+ * </pre>
+ * @param name The dbm file name to open
+ * @param mode The flag value
+ * <PRE>
+ * APR_DBM_READONLY open for read-only access
+ * APR_DBM_READWRITE open for read-write access
+ * APR_DBM_RWCREATE open for r/w, create if needed
+ * APR_DBM_RWTRUNC open for r/w, truncate if already there
+ * </PRE>
+ * @param perm Permissions to apply to if created
+ * @param cntxt The pool to use when creating the dbm
+ * @remark The dbm name may not be a true file name, as many dbm packages
+ * append suffixes for seperate data and index files.
+ */
+
+APU_DECLARE(apr_status_t) apr_dbm_open_ex(apr_dbm_t **dbm, const char* type,
+ const char *name,
+ apr_int32_t mode, apr_fileperms_t perm,
+ apr_pool_t *cntxt);
+
+
+/**
+ * Open a dbm file by file name
+ * @param dbm The newly opened database
+ * @param name The dbm file name to open
+ * @param mode The flag value
+ * <PRE>
+ * APR_DBM_READONLY open for read-only access
+ * APR_DBM_READWRITE open for read-write access
+ * APR_DBM_RWCREATE open for r/w, create if needed
+ * APR_DBM_RWTRUNC open for r/w, truncate if already there
+ * </PRE>
+ * @param perm Permissions to apply to if created
+ * @param cntxt The pool to use when creating the dbm
+ * @remark The dbm name may not be a true file name, as many dbm packages
+ * append suffixes for seperate data and index files.
+ */
+APU_DECLARE(apr_status_t) apr_dbm_open(apr_dbm_t **dbm, const char *name,
+ apr_int32_t mode, apr_fileperms_t perm,
+ apr_pool_t *cntxt);
+
+/**
+ * Close a dbm file previously opened by apr_dbm_open
+ * @param dbm The database to close
+ */
+APU_DECLARE(void) apr_dbm_close(apr_dbm_t *dbm);
+
+/**
+ * Fetch a dbm record value by key
+ * @param dbm The database
+ * @param key The key datum to find this record
+ * @param pvalue The value datum retrieved for this record
+ */
+APU_DECLARE(apr_status_t) apr_dbm_fetch(apr_dbm_t *dbm, apr_datum_t key,
+ apr_datum_t *pvalue);
+/**
+ * Store a dbm record value by key
+ * @param dbm The database
+ * @param key The key datum to store this record by
+ * @param value The value datum to store in this record
+ */
+APU_DECLARE(apr_status_t) apr_dbm_store(apr_dbm_t *dbm, apr_datum_t key,
+ apr_datum_t value);
+
+/**
+ * Delete a dbm record value by key
+ * @param dbm The database
+ * @param key The key datum of the record to delete
+ * @remark It is not an error to delete a non-existent record.
+ */
+APU_DECLARE(apr_status_t) apr_dbm_delete(apr_dbm_t *dbm, apr_datum_t key);
+
+/**
+ * Search for a key within the dbm
+ * @param dbm The database
+ * @param key The datum describing a key to test
+ */
+APU_DECLARE(int) apr_dbm_exists(apr_dbm_t *dbm, apr_datum_t key);
+
+/**
+ * Retrieve the first record key from a dbm
+ * @param dbm The database
+ * @param pkey The key datum of the first record
+ */
+APU_DECLARE(apr_status_t) apr_dbm_firstkey(apr_dbm_t *dbm, apr_datum_t *pkey);
+
+/**
+ * Retrieve the next record key from a dbm
+ * @param dbm The database
+ * @param pkey The key datum of the next record
+ */
+APU_DECLARE(apr_status_t) apr_dbm_nextkey(apr_dbm_t *dbm, apr_datum_t *pkey);
+
+/**
+ * Proactively toss any memory associated with the apr_datum_t.
+ * @param dbm The database
+ * @param data The datum to free.
+ */
+APU_DECLARE(void) apr_dbm_freedatum(apr_dbm_t *dbm, apr_datum_t data);
+
+/**
+ * Report more information when an apr_dbm function fails.
+ * @param dbm The database
+ * @param errcode A DBM-specific value for the error (for logging). If this
+ * isn't needed, it may be NULL.
+ * @param errbuf Location to store the error text
+ * @param errbufsize The size of the provided buffer
+ * @return The errbuf parameter, for convenience.
+ */
+APU_DECLARE(char *) apr_dbm_geterror(apr_dbm_t *dbm, int *errcode,
+ char *errbuf, apr_size_t errbufsize);
+/**
+ * If the specified file/path were passed to apr_dbm_open(), return the
+ * actual file/path names which would be (created and) used. At most, two
+ * files may be used; used2 may be NULL if only one file is used.
+ * @param pool The pool for allocating used1 and used2.
+ * @param type The type of DBM you require info on
+ * @param pathname The path name to generate used-names from.
+ * @param used1 The first pathname used by the apr_dbm implementation.
+ * @param used2 The second pathname used by apr_dbm. If only one file is
+ * used by the specific implementation, this will be set to NULL.
+ * @return An error if the specified type is invalid.
+ * @remark The dbm file(s) don't need to exist. This function only manipulates
+ * the pathnames.
+ */
+APU_DECLARE(apr_status_t) apr_dbm_get_usednames_ex(apr_pool_t *pool,
+ const char *type,
+ const char *pathname,
+ const char **used1,
+ const char **used2);
+
+/**
+ * If the specified file/path were passed to apr_dbm_open(), return the
+ * actual file/path names which would be (created and) used. At most, two
+ * files may be used; used2 may be NULL if only one file is used.
+ * @param pool The pool for allocating used1 and used2.
+ * @param pathname The path name to generate used-names from.
+ * @param used1 The first pathname used by the apr_dbm implementation.
+ * @param used2 The second pathname used by apr_dbm. If only one file is
+ * used by the specific implementation, this will be set to NULL.
+ * @remark The dbm file(s) don't need to exist. This function only manipulates
+ * the pathnames.
+ */
+APU_DECLARE(void) apr_dbm_get_usednames(apr_pool_t *pool,
+ const char *pathname,
+ const char **used1,
+ const char **used2);
+
+/** @} */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !APR_DBM_H */
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APR_HOOKS_H
+#define APR_HOOKS_H
+
+#include "apu.h"
+/* For apr_array_header_t */
+#include "apr_tables.h"
+
+/**
+ * @file apr_hooks.h
+ * @brief Apache hook functions
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/**
+ * @defgroup APR_Util_Hook Hook Functions
+ * @ingroup APR_Util
+ * @{
+ */
+/** macro to return the prototype of the hook function */
+#define APR_IMPLEMENT_HOOK_GET_PROTO(ns,link,name) \
+link##_DECLARE(apr_array_header_t *) ns##_hook_get_##name(void)
+
+/** macro to declare the hook correctly */
+#define APR_DECLARE_EXTERNAL_HOOK(ns,link,ret,name,args) \
+typedef ret ns##_HOOK_##name##_t args; \
+link##_DECLARE(void) ns##_hook_##name(ns##_HOOK_##name##_t *pf, \
+ const char * const *aszPre, \
+ const char * const *aszSucc, int nOrder); \
+link##_DECLARE(ret) ns##_run_##name args; \
+APR_IMPLEMENT_HOOK_GET_PROTO(ns,link,name); \
+typedef struct ns##_LINK_##name##_t \
+ { \
+ ns##_HOOK_##name##_t *pFunc; \
+ const char *szName; \
+ const char * const *aszPredecessors; \
+ const char * const *aszSuccessors; \
+ int nOrder; \
+ } ns##_LINK_##name##_t;
+
+/** macro to declare the hook structure */
+#define APR_HOOK_STRUCT(members) \
+static struct { members } _hooks;
+
+/** macro to link the hook structure */
+#define APR_HOOK_LINK(name) \
+ apr_array_header_t *link_##name;
+
+/** macro to implement the hook */
+#define APR_IMPLEMENT_EXTERNAL_HOOK_BASE(ns,link,name) \
+link##_DECLARE(void) ns##_hook_##name(ns##_HOOK_##name##_t *pf,const char * const *aszPre, \
+ const char * const *aszSucc,int nOrder) \
+ { \
+ ns##_LINK_##name##_t *pHook; \
+ if(!_hooks.link_##name) \
+ { \
+ _hooks.link_##name=apr_array_make(apr_hook_global_pool,1,sizeof(ns##_LINK_##name##_t)); \
+ apr_hook_sort_register(#name,&_hooks.link_##name); \
+ } \
+ pHook=apr_array_push(_hooks.link_##name); \
+ pHook->pFunc=pf; \
+ pHook->aszPredecessors=aszPre; \
+ pHook->aszSuccessors=aszSucc; \
+ pHook->nOrder=nOrder; \
+ pHook->szName=apr_hook_debug_current; \
+ if(apr_hook_debug_enabled) \
+ apr_hook_debug_show(#name,aszPre,aszSucc); \
+ } \
+ APR_IMPLEMENT_HOOK_GET_PROTO(ns,link,name) \
+ { \
+ return _hooks.link_##name; \
+ }
+
+/**
+ * Implement a hook that has no return code, and therefore runs all of the
+ * registered functions
+ * @param ns The namespace prefix of the hook functions
+ * @param link The linkage declaration prefix of the hook
+ * @param name The name of the hook
+ * @param args_decl The declaration of the arguments for the hook
+ * @param args_use The names for the arguments for the hook
+ * @note The link prefix FOO corresponds to FOO_DECLARE() macros, which
+ * provide export linkage from the module that IMPLEMENTs the hook, and
+ * import linkage from external modules that link to the hook's module.
+ */
+#define APR_IMPLEMENT_EXTERNAL_HOOK_VOID(ns,link,name,args_decl,args_use) \
+APR_IMPLEMENT_EXTERNAL_HOOK_BASE(ns,link,name) \
+link##_DECLARE(void) ns##_run_##name args_decl \
+ { \
+ ns##_LINK_##name##_t *pHook; \
+ int n; \
+\
+ if(!_hooks.link_##name) \
+ return; \
+\
+ pHook=(ns##_LINK_##name##_t *)_hooks.link_##name->elts; \
+ for(n=0 ; n < _hooks.link_##name->nelts ; ++n) \
+ pHook[n].pFunc args_use; \
+ }
+
+/* FIXME: note that this returns ok when nothing is run. I suspect it should
+ really return decline, but that breaks Apache currently - Ben
+*/
+/**
+ * Implement a hook that runs until one of the functions returns something
+ * other than OK or DECLINE
+ * @param ns The namespace prefix of the hook functions
+ * @param link The linkage declaration prefix of the hook
+ * @param ret Type to return
+ * @param name The name of the hook
+ * @param args_decl The declaration of the arguments for the hook
+ * @param args_use The names for the arguments for the hook
+ * @param ok Success value
+ * @param decline Decline value
+ * @note The link prefix FOO corresponds to FOO_DECLARE() macros, which
+ * provide export linkage from the module that IMPLEMENTs the hook, and
+ * import linkage from external modules that link to the hook's module.
+ */
+#define APR_IMPLEMENT_EXTERNAL_HOOK_RUN_ALL(ns,link,ret,name,args_decl,args_use,ok,decline) \
+APR_IMPLEMENT_EXTERNAL_HOOK_BASE(ns,link,name) \
+link##_DECLARE(ret) ns##_run_##name args_decl \
+ { \
+ ns##_LINK_##name##_t *pHook; \
+ int n; \
+ ret rv; \
+\
+ if(!_hooks.link_##name) \
+ return ok; \
+\
+ pHook=(ns##_LINK_##name##_t *)_hooks.link_##name->elts; \
+ for(n=0 ; n < _hooks.link_##name->nelts ; ++n) \
+ { \
+ rv=pHook[n].pFunc args_use; \
+\
+ if(rv != ok && rv != decline) \
+ return rv; \
+ } \
+ return ok; \
+ }
+
+
+/**
+ * Implement a hook that runs until the first function returns something
+ * other than the value of decline
+ * @param ns The namespace prefix of the hook functions
+ * @param link The linkage declaration prefix of the hook
+ * @param name The name of the hook
+ * @param ret Type to return
+ * @param args_decl The declaration of the arguments for the hook
+ * @param args_use The names for the arguments for the hook
+ * @param decline Decline value
+ * @note The link prefix FOO corresponds to FOO_DECLARE() macros, which
+ * provide export linkage from the module that IMPLEMENTs the hook, and
+ * import linkage from external modules that link to the hook's module.
+ */
+#define APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(ns,link,ret,name,args_decl,args_use,decline) \
+APR_IMPLEMENT_EXTERNAL_HOOK_BASE(ns,link,name) \
+link##_DECLARE(ret) ns##_run_##name args_decl \
+ { \
+ ns##_LINK_##name##_t *pHook; \
+ int n; \
+ ret rv; \
+\
+ if(!_hooks.link_##name) \
+ return decline; \
+\
+ pHook=(ns##_LINK_##name##_t *)_hooks.link_##name->elts; \
+ for(n=0 ; n < _hooks.link_##name->nelts ; ++n) \
+ { \
+ rv=pHook[n].pFunc args_use; \
+\
+ if(rv != decline) \
+ return rv; \
+ } \
+ return decline; \
+ }
+
+ /* Hook orderings */
+/** run this hook first, before ANYTHING */
+#define APR_HOOK_REALLY_FIRST (-10)
+/** run this hook first */
+#define APR_HOOK_FIRST 0
+/** run this hook somewhere */
+#define APR_HOOK_MIDDLE 10
+/** run this hook after every other hook which is defined*/
+#define APR_HOOK_LAST 20
+/** run this hook last, after EVERYTHING */
+#define APR_HOOK_REALLY_LAST 30
+
+/**
+ * The global pool used to allocate any memory needed by the hooks.
+ */
+APU_DECLARE_DATA extern apr_pool_t *apr_hook_global_pool;
+
+/**
+ * A global variable to determine if debugging information about the
+ * hooks functions should be printed
+ */
+APU_DECLARE_DATA extern int apr_hook_debug_enabled;
+
+/**
+ * The name of the module that is currently registering a function
+ */
+APU_DECLARE_DATA extern const char *apr_hook_debug_current;
+
+/**
+ * Register a hook function to be sorted
+ * @param szHookName The name of the Hook the function is registered for
+ * @param aHooks The array which stores all of the functions for this hook
+ */
+APU_DECLARE(void) apr_hook_sort_register(const char *szHookName,
+ apr_array_header_t **aHooks);
+/**
+ * Sort all of the registerd functions for a given hook
+ */
+APU_DECLARE(void) apr_hook_sort_all(void);
+
+/**
+ * Print all of the information about the current hook. This is used for
+ * debugging purposes.
+ * @param szName The name of the hook
+ * @param aszPre All of the functions in the predecessor array
+ * @param aszSucc All of the functions in the successor array
+ */
+APU_DECLARE(void) apr_hook_debug_show(const char *szName,
+ const char * const *aszPre,
+ const char * const *aszSucc);
+
+/**
+ * Remove all currently registered functions.
+ */
+APU_DECLARE(void) apr_hook_deregister_all(void);
+
+/** @} */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* APR_HOOKS_H */
--- /dev/null
+/* Copyright 2002-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * apr_ldap.h is generated from apr_ldap.h.in by configure -- do not edit apr_ldap.h
+ */
+/**
+ * @file apr_ldap.h
+ * @brief APR-UTIL LDAP
+ */
+#ifndef APU_LDAP_H
+#define APU_LDAP_H
+
+/**
+ * @defgroup APR_Util_LDAP LDAP
+ * @ingroup APR_Util
+ * @{
+ */
+
+/* this will be defined if LDAP support was compiled into apr-util */
+#define APR_HAS_LDAP @apu_has_ldap@
+
+/* identify the LDAP toolkit used */
+#define APR_HAS_NETSCAPE_LDAPSDK @apu_has_ldap_netscape@
+#define APR_HAS_SOLARIS_LDAPSDK @apu_has_ldap_solaris@
+#define APR_HAS_NOVELL_LDAPSDK @apu_has_ldap_novell@
+#define APR_HAS_MOZILLA_LDAPSDK @apu_has_ldap_mozilla@
+#define APR_HAS_OPENLDAP_LDAPSDK @apu_has_ldap_openldap@
+#define APR_HAS_MICROSOFT_LDAPSDK @apu_has_ldap_microsoft@
+#define APR_HAS_OTHER_LDAPSDK @apu_has_ldap_other@
+
+
+/*
+ * Handle the case when LDAP is enabled
+ */
+#if APR_HAS_LDAP
+
+/*
+ * The following #defines are DEPRECATED and should not be used for
+ * anything. They remain to maintain binary compatibility.
+ * The original code defined the OPENLDAP SDK as present regardless
+ * of what really was there, which was way bogus. In addition, the
+ * apr_ldap_url_parse*() functions have been rewritten specifically for
+ * APR, so the APR_HAS_LDAP_URL_PARSE macro is forced to zero.
+ */
+#define APR_HAS_LDAP_SSL 1
+#define APR_HAS_LDAP_URL_PARSE 0
+
+
+/*
+ * Include the standard LDAP header files.
+ */
+
+@lber_h@
+@ldap_h@
+@ldap_ssl_h@
+
+
+/*
+ * Detected standard functions
+ */
+#define APR_HAS_LDAPSSL_CLIENT_INIT @apu_has_ldapssl_client_init@
+#define APR_HAS_LDAPSSL_CLIENT_DEINIT @apu_has_ldapssl_client_deinit@
+#define APR_HAS_LDAPSSL_ADD_TRUSTED_CERT @apu_has_ldapssl_add_trusted_cert@
+#define APR_HAS_LDAP_START_TLS_S @apu_has_ldap_start_tls_s@
+#define APR_HAS_LDAP_SSLINIT @apu_has_ldap_sslinit@
+#define APR_HAS_LDAPSSL_INIT @apu_has_ldapssl_init@
+#define APR_HAS_LDAPSSL_INSTALL_ROUTINES @apu_has_ldapssl_install_routines@
+
+/*
+ * Make sure the secure LDAP port is defined
+ */
+#ifndef LDAPS_PORT
+#define LDAPS_PORT 636 /* ldaps:/// default LDAP over TLS port */
+#endif
+
+
+/* Note: Macros defining const casting has been removed in APR v1.0,
+ * pending real support for LDAP v2.0 toolkits.
+ *
+ * In the mean time, please use an LDAP v3.0 toolkit.
+ */
+#if LDAP_VERSION_MAX <= 2
+#error Support for LDAP v2.0 toolkits has been removed from apr-util. Please use an LDAP v3.0 toolkit.
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * This structure allows the C LDAP API error codes to be returned
+ * along with plain text error messages that explain to us mere mortals
+ * what really happened.
+ */
+typedef struct apr_ldap_err_t {
+ const char *reason;
+ const char *msg;
+ int rc;
+} apr_ldap_err_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#include "apr_ldap_url.h"
+#include "apr_ldap_init.h"
+#include "apr_ldap_option.h"
+
+/** @} */
+#endif /* APR_HAS_LDAP */
+#endif /* APU_LDAP_H */
--- /dev/null
+/* Copyright 2002-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * apr_ldap.h is generated from apr_ldap.h.in by configure -- do not edit apr_ldap.h
+ */
+/**
+ * @file apr_ldap.h
+ * @brief APR-UTIL LDAP
+ */
+#ifndef APU_LDAP_H
+#define APU_LDAP_H
+
+/**
+ * @defgroup APR_Util_LDAP LDAP
+ * @ingroup APR_Util
+ * @{
+ */
+
+/* this will be defined if LDAP support was compiled into apr-util */
+#define APR_HAS_LDAP 1
+
+/* identify the LDAP toolkit used */
+#define APR_HAS_NETSCAPE_LDAPSDK 0
+#define APR_HAS_SOLARIS_LDAPSDK 0
+#define APR_HAS_NOVELL_LDAPSDK 1
+#define APR_HAS_MOZILLA_LDAPSDK 0
+#define APR_HAS_OPENLDAP_LDAPSDK 0
+#define APR_HAS_MICROSOFT_LDAPSDK 0
+#define APR_HAS_OTHER_LDAPSDK 0
+
+
+/*
+ * Handle the case when LDAP is enabled
+ */
+#if APR_HAS_LDAP
+
+/*
+ * The following #defines are DEPRECATED and should not be used for
+ * anything. They remain to maintain binary compatibility.
+ * The original code defined the OPENLDAP SDK as present regardless
+ * of what really was there, which was way bogus. In addition, the
+ * apr_ldap_url_parse*() functions have been rewritten specifically for
+ * APR, so the APR_HAS_LDAP_URL_PARSE macro is forced to zero.
+ */
+#define APR_HAS_LDAP_SSL 1
+#define APR_HAS_LDAP_URL_PARSE 0
+
+
+/*
+ * Include the standard LDAP header files.
+ */
+
+#ifdef GENEXPORTS
+#define LDAP_VERSION_MAX 3
+#else
+#include <lber.h>
+#include <ldap.h>
+#if APR_HAS_LDAP_SSL
+#include <ldap_ssl.h>
+#endif
+#endif
+
+
+/*
+ * Detected standard functions
+ */
+#define APR_HAS_LDAPSSL_CLIENT_INIT 1
+#define APR_HAS_LDAPSSL_CLIENT_DEINIT 1
+#define APR_HAS_LDAPSSL_ADD_TRUSTED_CERT 1
+#define APR_HAS_LDAP_START_TLS_S 0
+#define APR_HAS_LDAP_SSLINIT 0
+#define APR_HAS_LDAPSSL_INIT 1
+#define APR_HAS_LDAPSSL_INSTALL_ROUTINES 0
+
+
+/*
+ * Make sure the secure LDAP port is defined
+ */
+#ifndef LDAPS_PORT
+#define LDAPS_PORT 636 /* ldaps:/// default LDAP over TLS port */
+#endif
+
+
+/* Note: Macros defining const casting has been removed in APR v1.0,
+ * pending real support for LDAP v2.0 toolkits.
+ *
+ * In the mean time, please use an LDAP v3.0 toolkit.
+ */
+#if LDAP_VERSION_MAX <= 2
+#error Support for LDAP v2.0 toolkits has been removed from apr-util. Please use an LDAP v3.0 toolkit.
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * This structure allows the C LDAP API error codes to be returned
+ * along with plain text error messages that explain to us mere mortals
+ * what really happened.
+ */
+typedef struct apr_ldap_err_t {
+ const char *reason;
+ const char *msg;
+ int rc;
+} apr_ldap_err_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#include "apr_ldap_url.h"
+#include "apr_ldap_init.h"
+#include "apr_ldap_option.h"
+
+/** @} */
+#endif /* APR_HAS_LDAP */
+#endif /* APU_LDAP_H */
+
--- /dev/null
+/* Copyright 2002-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * apr_ldap.h is generated from apr_ldap.h.in by configure -- do not edit apr_ldap.h
+ */
+/**
+ * @file apr_ldap.h
+ * @brief APR-UTIL LDAP
+ */
+#ifndef APU_LDAP_H
+#define APU_LDAP_H
+
+/**
+ * @defgroup APR_Util_LDAP LDAP
+ * @ingroup APR_Util
+ * @{
+ */
+
+/* this will be defined if LDAP support was compiled into apr-util */
+#define APR_HAS_LDAP 1
+
+/* identify the LDAP toolkit used */
+#define APR_HAS_NETSCAPE_LDAPSDK 0
+#define APR_HAS_SOLARIS_LDAPSDK 0
+#define APR_HAS_NOVELL_LDAPSDK 0
+#define APR_HAS_MOZILLA_LDAPSDK 0
+#define APR_HAS_OPENLDAP_LDAPSDK 0
+#define APR_HAS_MICROSOFT_LDAPSDK 1
+#define APR_HAS_OTHER_LDAPSDK 0
+
+
+/*
+ * Handle the case when LDAP is enabled
+ */
+#if APR_HAS_LDAP
+
+/*
+ * The following #defines are DEPRECATED and should not be used for
+ * anything. They remain to maintain binary compatibility.
+ * The original code defined the OPENLDAP SDK as present regardless
+ * of what really was there, which was way bogus. In addition, the
+ * apr_ldap_url_parse*() functions have been rewritten specifically for
+ * APR, so the APR_HAS_LDAP_URL_PARSE macro is forced to zero.
+ */
+#define APR_HAS_LDAP_SSL 1
+#define APR_HAS_LDAP_URL_PARSE 0
+
+
+/*
+ * Include the standard LDAP header files.
+ */
+
+#include <winldap.h>
+
+
+/*
+ * Detected standard functions
+ */
+#define APR_HAS_LDAPSSL_CLIENT_INIT 0
+#define APR_HAS_LDAPSSL_CLIENT_DEINIT 0
+#define APR_HAS_LDAPSSL_ADD_TRUSTED_CERT 0
+#define APR_HAS_LDAP_START_TLS_S 0
+#define APR_HAS_LDAP_SSLINIT 1
+#define APR_HAS_LDAPSSL_INIT 0
+#define APR_HAS_LDAPSSL_INSTALL_ROUTINES 0
+
+
+/*
+ * Make sure the secure LDAP port is defined
+ */
+#ifndef LDAPS_PORT
+#define LDAPS_PORT 636 /* ldaps:/// default LDAP over TLS port */
+#endif
+
+
+/* Note: Macros defining const casting has been removed in APR v1.0,
+ * pending real support for LDAP v2.0 toolkits.
+ *
+ * In the mean time, please use an LDAP v3.0 toolkit.
+ */
+#if LDAP_VERSION_MAX <= 2
+#error Support for LDAP v2.0 toolkits has been removed from apr-util. Please use an LDAP v3.0 toolkit.
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * This structure allows the C LDAP API error codes to be returned
+ * along with plain text error messages that explain to us mere mortals
+ * what really happened.
+ */
+typedef struct apr_ldap_err_t {
+ const char *reason;
+ const char *msg;
+ int rc;
+} apr_ldap_err_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#include "apr_ldap_url.h"
+#include "apr_ldap_init.h"
+#include "apr_ldap_option.h"
+
+/** @} */
+#endif /* APR_HAS_LDAP */
+#endif /* APU_LDAP_H */
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file apr_ldap_init.h
+ * @brief APR-UTIL LDAP ldap_init() functions
+ */
+#ifndef APR_LDAP_INIT_H
+#define APR_LDAP_INIT_H
+
+/**
+ * @defgroup APR_Util_LDAP LDAP
+ * @ingroup APR_Util
+ * @{
+ */
+
+#include "apr_ldap.h"
+
+#if APR_HAS_LDAP
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * APR LDAP SSL Initialise function
+ *
+ * This function initialises SSL on the underlying LDAP toolkit
+ * if this is necessary.
+ *
+ * If a CA certificate is provided, this is set, however the setting
+ * of certificates via this method has been deprecated and will be removed in
+ * APR v2.0.
+ *
+ * The apr_ldap_set_option() function with the APR_LDAP_OPT_TLS_CERT option
+ * should be used instead to set certificates.
+ *
+ * If SSL support is not available on this platform, or a problem
+ * was encountered while trying to set the certificate, the function
+ * will return APR_EGENERAL. Further LDAP specific error information
+ * can be found in result_err.
+ * @param pool The pool to use
+ * @param cert_auth_file The name of the certificate to use, can be NULL
+ * @param cert_file_type The type of certificate specified. See the
+ * apr_ldap_set_option() APR_LDAP_OPT_TLS_CERT option for details.
+ * @param result_err The returned result
+ */
+APU_DECLARE(int) apr_ldap_ssl_init(apr_pool_t *pool,
+ const char *cert_auth_file,
+ int cert_file_type,
+ apr_ldap_err_t **result_err);
+
+/**
+ * APR LDAP SSL De-Initialise function
+ *
+ * This function tears down any SSL certificate setup previously
+ * set using apr_ldap_ssl_init(). It should be called to clean
+ * up if a graceful restart of a service is attempted.
+ * @todo currently we do not check whether apr_ldap_ssl_init()
+ * has been called first - we probably should.
+ */
+APU_DECLARE(int) apr_ldap_ssl_deinit(void);
+
+/**
+ * APR LDAP initialise function
+ *
+ * This function is responsible for initialising an LDAP
+ * connection in a toolkit independant way. It does the
+ * job of ldap_init() from the C api.
+ *
+ * It handles both the SSL and non-SSL case, and attempts
+ * to hide the complexity setup from the user. This function
+ * assumes that any certificate setup necessary has already
+ * been done.
+ *
+ * If SSL or STARTTLS needs to be enabled, and the underlying
+ * toolkit supports it, the following values are accepted for
+ * secure:
+ *
+ * APR_LDAP_NONE: No encryption
+ * APR_LDAP_SSL: SSL encryption (ldaps://)
+ * APR_LDAP_STARTTLS: Force STARTTLS on ldap://
+ * @remark The Novell toolkit is only able to set the SSL mode via this
+ * function. To work around this limitation, set the SSL mode here if no
+ * per connection client certificates are present, otherwise set secure
+ * APR_LDAP_NONE here, then set the per connection client certificates,
+ * followed by setting the SSL mode via apr_ldap_set_option(). As Novell
+ * does not support per connection client certificates, this problem is
+ * worked around while still being compatible with other LDAP toolkits.
+ * @param pool The pool to use
+ * @param ldap The LDAP handle
+ * @param hostname The name of the host to connect to. This can be either a
+ * DNS name, or an IP address.
+ * @param portno The port to connect to
+ * @param secure The security mode to set
+ * @param result_err The returned result
+ */
+APU_DECLARE(int) apr_ldap_init(apr_pool_t *pool,
+ LDAP **ldap,
+ const char *hostname,
+ int portno,
+ int secure,
+ apr_ldap_err_t **result_err);
+
+/**
+ * APR LDAP info function
+ *
+ * This function returns a string describing the LDAP toolkit
+ * currently in use. The string is placed inside result_err->reason.
+ * @param pool The pool to use
+ * @param result_err The returned result
+ */
+APU_DECLARE(int) apr_ldap_info(apr_pool_t *pool,
+ apr_ldap_err_t **result_err);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* APR_HAS_LDAP */
+
+/** @} */
+
+#endif /* APR_LDAP_URL_H */
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file apr_ldap_option.h
+ * @brief APR-UTIL LDAP ldap_*_option() functions
+ */
+#ifndef APR_LDAP_OPTION_H
+#define APR_LDAP_OPTION_H
+
+/**
+ * @defgroup APR_Util_LDAP LDAP
+ * @ingroup APR_Util
+ * @{
+ */
+
+#include "apr_ldap.h"
+
+#if APR_HAS_LDAP
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/*
+ * The following defines handle the different TLS certificate
+ * options available. If these options are missing, APR will try and
+ * emulate support for this using the deprecated ldap_start_tls_s()
+ * function.
+ */
+/**
+ * Set SSL mode to one of APR_LDAP_NONE, APR_LDAP_SSL, APR_LDAP_STARTTLS
+ * or APR_LDAP_STOPTLS.
+ */
+#define APR_LDAP_OPT_TLS 0x6fff
+/**
+ * Set zero or more CA certificates, client certificates or private
+ * keys globally, or per connection (where supported).
+ */
+#define APR_LDAP_OPT_TLS_CERT 0x6ffe
+/**
+ * Set the LDAP library to no verify the server certificate. This means
+ * all servers are considered trusted.
+ */
+#define APR_LDAP_OPT_VERIFY_CERT 0x6ffd
+
+/**
+ * Structures for the apr_set_option() cases
+ */
+
+/**
+ * APR_LDAP_OPT_TLS_CERT
+ *
+ * This structure includes possible options to set certificates on
+ * system initialisation. Different SDKs have different certificate
+ * requirements, and to achieve this multiple certificates must be
+ * specified at once passed as an (apr_array_header_t *).
+ *
+ * Netscape:
+ * Needs the CA cert database (cert7.db), the client cert database (key3.db)
+ * and the security module file (secmod.db) set at the system initialisation
+ * time. Three types are supported: APR_LDAP_CERT7_DB, APR_LDAP_KEY3_DB and
+ * APR_LDAP_SECMOD.
+ *
+ * To specify a client cert connection, a certificate nickname needs to be
+ * provided with a type of APR_LDAP_CERT.
+ * int ldapssl_enable_clientauth( LDAP *ld, char *keynickname,
+ * char *keypasswd, char *certnickname );
+ * keynickname is currently not used, and should be set to ""
+ *
+ * Novell:
+ * Needs CA certificates and client certificates set at system initialisation
+ * time. Three types are supported: APR_LDAP_CA*, APR_LDAP_CERT* and
+ * APR_LDAP_KEY*.
+ *
+ * Certificates cannot be specified per connection.
+ *
+ * The functions used are:
+ * ldapssl_add_trusted_cert(serverTrustedRoot, serverTrustedRootEncoding);
+ * Clients certs and keys are set at system initialisation time with
+ * int ldapssl_set_client_cert (
+ * void *cert,
+ * int type
+ * void *password);
+ * type can be LDAPSSL_CERT_FILETYPE_B64 or LDAPSSL_CERT_FILETYPE_DER
+ * ldapssl_set_client_private_key(clientPrivateKey,
+ * clientPrivateKeyEncoding,
+ * clientPrivateKeyPassword);
+ *
+ * OpenSSL:
+ * Needs one or more CA certificates to be set at system initialisation time
+ * with a type of APR_LDAP_CA*.
+ *
+ * May have one or more client certificates set per connection with a type of
+ * APR_LDAP_CERT*, and keys with APR_LDAP_KEY*.
+ */
+/** CA certificate type unknown */
+#define APR_LDAP_CA_TYPE_UNKNOWN 0
+/** binary DER encoded CA certificate */
+#define APR_LDAP_CA_TYPE_DER 1
+/** PEM encoded CA certificate */
+#define APR_LDAP_CA_TYPE_BASE64 2
+/** Netscape/Mozilla cert7.db CA certificate database */
+#define APR_LDAP_CA_TYPE_CERT7_DB 3
+/** Netscape/Mozilla secmod file */
+#define APR_LDAP_CA_TYPE_SECMOD 4
+/** Client certificate type unknown */
+#define APR_LDAP_CERT_TYPE_UNKNOWN 5
+/** binary DER encoded client certificate */
+#define APR_LDAP_CERT_TYPE_DER 6
+/** PEM encoded client certificate */
+#define APR_LDAP_CERT_TYPE_BASE64 7
+/** Netscape/Mozilla key3.db client certificate database */
+#define APR_LDAP_CERT_TYPE_KEY3_DB 8
+/** Netscape/Mozilla client certificate nickname */
+#define APR_LDAP_CERT_TYPE_NICKNAME 9
+/** Private key type unknown */
+#define APR_LDAP_KEY_TYPE_UNKNOWN 10
+/** binary DER encoded private key */
+#define APR_LDAP_KEY_TYPE_DER 11
+/** PEM encoded private key */
+#define APR_LDAP_KEY_TYPE_BASE64 12
+/** PKCS#12 encoded client certificate */
+#define APR_LDAP_CERT_TYPE_PFX 13
+/** PKCS#12 encoded private key */
+#define APR_LDAP_KEY_TYPE_PFX 14
+
+/**
+ * Certificate structure.
+ *
+ * This structure is used to store certificate details. An array of
+ * these structures is passed to apr_ldap_set_option() to set CA
+ * and client certificates.
+ * @param type Type of certificate APR_LDAP_*_TYPE_*
+ * @param path Path, file or nickname of the certificate
+ * @param password Optional password, can be NULL
+ */
+typedef struct apr_ldap_opt_tls_cert_t apr_ldap_opt_tls_cert_t;
+struct apr_ldap_opt_tls_cert_t {
+ int type;
+ const char *path;
+ const char *password;
+};
+
+/**
+ * APR_LDAP_OPT_TLS
+ *
+ * This sets the SSL level on the LDAP handle.
+ *
+ * Netscape/Mozilla:
+ * Supports SSL, but not STARTTLS
+ * SSL is enabled by calling ldapssl_install_routines().
+ *
+ * Novell:
+ * Supports SSL and STARTTLS.
+ * SSL is enabled by calling ldapssl_install_routines(). Note that calling
+ * other ldap functions before ldapssl_install_routines() may cause this
+ * function to fail.
+ * STARTTLS is enabled by calling ldapssl_start_tls_s() after calling
+ * ldapssl_install_routines() (check this).
+ *
+ * OpenLDAP:
+ * Supports SSL and supports STARTTLS, but none of this is documented:
+ * http://www.openldap.org/lists/openldap-software/200409/msg00618.html
+ * Documentation for both SSL support and STARTTLS has been deleted from
+ * the OpenLDAP documentation and website.
+ */
+
+/** No encryption */
+#define APR_LDAP_NONE 0
+/** SSL encryption (ldaps://) */
+#define APR_LDAP_SSL 1
+/** TLS encryption (STARTTLS) */
+#define APR_LDAP_STARTTLS 2
+/** end TLS encryption (STOPTLS) */
+#define APR_LDAP_STOPTLS 3
+
+/**
+ * APR LDAP get option function
+ *
+ * This function gets option values from a given LDAP session if
+ * one was specified. It maps to the native ldap_get_option() function.
+ * @param pool The pool to use
+ * @param ldap The LDAP handle
+ * @param option The LDAP_OPT_* option to return
+ * @param outvalue The value returned (if any)
+ * @param result_err The apr_ldap_err_t structure contained detailed results
+ * of the operation.
+ */
+APU_DECLARE(int) apr_ldap_get_option(apr_pool_t *pool,
+ LDAP *ldap,
+ int option,
+ void *outvalue,
+ apr_ldap_err_t **result_err);
+
+/**
+ * APR LDAP set option function
+ *
+ * This function sets option values to a given LDAP session if
+ * one was specified. It maps to the native ldap_set_option() function.
+ *
+ * Where an option is not supported by an LDAP toolkit, this function
+ * will try and apply legacy functions to achieve the same effect,
+ * depending on the platform.
+ * @param pool The pool to use
+ * @param ldap The LDAP handle
+ * @param option The LDAP_OPT_* option to set
+ * @param invalue The value to set
+ * @param result_err The apr_ldap_err_t structure contained detailed results
+ * of the operation.
+ */
+APU_DECLARE(int) apr_ldap_set_option(apr_pool_t *pool,
+ LDAP *ldap,
+ int option,
+ const void *invalue,
+ apr_ldap_err_t **result_err);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* APR_HAS_LDAP */
+
+/** @} */
+
+#endif /* APR_LDAP_OPTION_H */
+
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file apr_ldap_url.h
+ * @brief APR-UTIL LDAP ldap_init() functions
+ */
+#ifndef APR_LDAP_URL_H
+#define APR_LDAP_URL_H
+
+/**
+ * @defgroup APR_Util_LDAP LDAP
+ * @ingroup APR_Util
+ * @{
+ */
+
+#if APR_HAS_LDAP
+
+#include "apu.h"
+#include "apr_pools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/** Structure to access an exploded LDAP URL */
+typedef struct apr_ldap_url_desc_t {
+ struct apr_ldap_url_desc_t *lud_next;
+ char *lud_scheme;
+ char *lud_host;
+ int lud_port;
+ char *lud_dn;
+ char **lud_attrs;
+ int lud_scope;
+ char *lud_filter;
+ char **lud_exts;
+ int lud_crit_exts;
+} apr_ldap_url_desc_t;
+
+#ifndef APR_LDAP_URL_SUCCESS
+#define APR_LDAP_URL_SUCCESS 0x00 /* Success */
+#define APR_LDAP_URL_ERR_MEM 0x01 /* can't allocate memory space */
+#define APR_LDAP_URL_ERR_PARAM 0x02 /* parameter is bad */
+#define APR_LDAP_URL_ERR_BADSCHEME 0x03 /* URL doesn't begin with "ldap[si]://" */
+#define APR_LDAP_URL_ERR_BADENCLOSURE 0x04 /* URL is missing trailing ">" */
+#define APR_LDAP_URL_ERR_BADURL 0x05 /* URL is bad */
+#define APR_LDAP_URL_ERR_BADHOST 0x06 /* host port is bad */
+#define APR_LDAP_URL_ERR_BADATTRS 0x07 /* bad (or missing) attributes */
+#define APR_LDAP_URL_ERR_BADSCOPE 0x08 /* scope string is invalid (or missing) */
+#define APR_LDAP_URL_ERR_BADFILTER 0x09 /* bad or missing filter */
+#define APR_LDAP_URL_ERR_BADEXTS 0x0a /* bad or missing extensions */
+#endif
+
+/**
+ * Is this URL an ldap url? ldap://
+ * @param url The url to test
+ */
+APU_DECLARE(int) apr_ldap_is_ldap_url(const char *url);
+
+/**
+ * Is this URL an SSL ldap url? ldaps://
+ * @param url The url to test
+ */
+APU_DECLARE(int) apr_ldap_is_ldaps_url(const char *url);
+
+/**
+ * Is this URL an ldap socket url? ldapi://
+ * @param url The url to test
+ */
+APU_DECLARE(int) apr_ldap_is_ldapi_url(const char *url);
+
+/**
+ * Parse an LDAP URL.
+ * @param pool The pool to use
+ * @param url_in The URL to parse
+ * @param ludpp The structure to return the exploded URL
+ * @param result_err The result structure of the operation
+ */
+APU_DECLARE(int) apr_ldap_url_parse_ext(apr_pool_t *pool,
+ const char *url_in,
+ apr_ldap_url_desc_t **ludpp,
+ apr_ldap_err_t **result_err);
+
+/**
+ * Parse an LDAP URL.
+ * @param pool The pool to use
+ * @param url_in The URL to parse
+ * @param ludpp The structure to return the exploded URL
+ * @param result_err The result structure of the operation
+ */
+APU_DECLARE(int) apr_ldap_url_parse(apr_pool_t *pool,
+ const char *url_in,
+ apr_ldap_url_desc_t **ludpp,
+ apr_ldap_err_t **result_err);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* APR_HAS_LDAP */
+
+/** @} */
+
+#endif /* APR_LDAP_URL_H */
--- /dev/null
+/* Copyright 2001-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/* This is derived from material copyright RSA Data Security, Inc.
+ * Their notice is reproduced below in its entirety.
+ *
+ * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+ * rights reserved.
+ *
+ * License to copy and use this software is granted provided that it
+ * is identified as the "RSA Data Security, Inc. MD4 Message-Digest
+ * Algorithm" in all material mentioning or referencing this software
+ * or this function.
+ *
+ * License is also granted to make and use derivative works provided
+ * that such works are identified as "derived from the RSA Data
+ * Security, Inc. MD4 Message-Digest Algorithm" in all material
+ * mentioning or referencing the derived work.
+ *
+ * RSA Data Security, Inc. makes no representations concerning either
+ * the merchantability of this software or the suitability of this
+ * software for any particular purpose. It is provided "as is"
+ * without express or implied warranty of any kind.
+ *
+ * These notices must be retained in any copies of any part of this
+ * documentation and/or software.
+ */
+
+#ifndef APR_MD4_H
+#define APR_MD4_H
+
+#include "apu.h"
+#include "apr_xlate.h"
+/**
+ * @file apr_md4.h
+ * @brief APR-UTIL MD4 Library
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup APR_Util_MD4 MD4 Library
+ * @ingroup APR_Util
+ * @{
+ */
+
+/** The digestsize for MD4 */
+#define APR_MD4_DIGESTSIZE 16
+
+/** @see apr_md4_ctx_t */
+typedef struct apr_md4_ctx_t apr_md4_ctx_t;
+
+/** MD4 context. */
+struct apr_md4_ctx_t {
+ /** state (ABCD) */
+ apr_uint32_t state[4];
+ /** number of bits, modulo 2^64 (lsb first) */
+ apr_uint32_t count[2];
+ /** input buffer */
+ unsigned char buffer[64];
+#if APR_HAS_XLATE
+ /** translation handle */
+ apr_xlate_t *xlate;
+#endif
+};
+
+/**
+ * MD4 Initialize. Begins an MD4 operation, writing a new context.
+ * @param context The MD4 context to initialize.
+ */
+APU_DECLARE(apr_status_t) apr_md4_init(apr_md4_ctx_t *context);
+
+#if APR_HAS_XLATE
+/**
+ * MDr4 translation setup. Provides the APR translation handle to be used
+ * for translating the content before calculating the digest.
+ * @param context The MD4 content to set the translation for.
+ * @param xlate The translation handle to use for this MD4 context
+ */
+APU_DECLARE(apr_status_t) apr_md4_set_xlate(apr_md4_ctx_t *context,
+ apr_xlate_t *xlate);
+#else
+#define apr_md4_set_xlate(context, xlate) APR_ENOTIMPL
+#endif
+
+/**
+ * MD4 block update operation. Continue an MD4 message-digest operation,
+ * processing another message block, and updating the context.
+ * @param context The MD4 content to update.
+ * @param input next message block to update
+ * @param inputLen The length of the next message block
+ */
+APU_DECLARE(apr_status_t) apr_md4_update(apr_md4_ctx_t *context,
+ const unsigned char *input,
+ apr_size_t inputLen);
+
+/**
+ * MD4 finalization. Ends an MD4 message-digest operation, writing the
+ * message digest and zeroing the context
+ * @param digest The final MD4 digest
+ * @param context The MD4 content we are finalizing.
+ */
+APU_DECLARE(apr_status_t) apr_md4_final(
+ unsigned char digest[APR_MD4_DIGESTSIZE],
+ apr_md4_ctx_t *context);
+
+/**
+ * MD4 digest computation
+ * @param digest The MD4 digest
+ * @param input message block to use
+ * @param inputLen The length of the message block
+ */
+APU_DECLARE(apr_status_t) apr_md4(unsigned char digest[APR_MD4_DIGESTSIZE],
+ const unsigned char *input,
+ apr_size_t inputLen);
+
+/** @} */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !APR_MD4_H */
--- /dev/null
+/*
+ * This is work is derived from material Copyright RSA Data Security, Inc.
+ *
+ * The RSA copyright statement and Licence for that original material is
+ * included below. This is followed by the Apache copyright statement and
+ * licence for the modifications made to that material.
+ */
+
+/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
+ rights reserved.
+
+ License to copy and use this software is granted provided that it
+ is identified as the "RSA Data Security, Inc. MD5 Message-Digest
+ Algorithm" in all material mentioning or referencing this software
+ or this function.
+
+ License is also granted to make and use derivative works provided
+ that such works are identified as "derived from the RSA Data
+ Security, Inc. MD5 Message-Digest Algorithm" in all material
+ mentioning or referencing the derived work.
+
+ RSA Data Security, Inc. makes no representations concerning either
+ the merchantability of this software or the suitability of this
+ software for any particular purpose. It is provided "as is"
+ without express or implied warranty of any kind.
+
+ These notices must be retained in any copies of any part of this
+ documentation and/or software.
+ */
+
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APR_MD5_H
+#define APR_MD5_H
+
+#include "apu.h"
+#include "apr_xlate.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/**
+ * @file apr_md5.h
+ * @brief APR MD5 Routines
+ */
+
+/**
+ * @defgroup APR_MD5 MD5 Routines
+ * @ingroup APR
+ * @{
+ */
+
+/** The MD5 digest size */
+#define APR_MD5_DIGESTSIZE 16
+
+/** @see apr_md5_ctx_t */
+typedef struct apr_md5_ctx_t apr_md5_ctx_t;
+
+/** MD5 context. */
+struct apr_md5_ctx_t {
+ /** state (ABCD) */
+ apr_uint32_t state[4];
+ /** number of bits, modulo 2^64 (lsb first) */
+ apr_uint32_t count[2];
+ /** input buffer */
+ unsigned char buffer[64];
+ /** translation handle
+ * ignored if xlate is unsupported
+ */
+ apr_xlate_t *xlate;
+};
+
+/**
+ * MD5 Initialize. Begins an MD5 operation, writing a new context.
+ * @param context The MD5 context to initialize.
+ */
+APU_DECLARE(apr_status_t) apr_md5_init(apr_md5_ctx_t *context);
+
+/**
+ * MD5 translation setup. Provides the APR translation handle to be used
+ * for translating the content before calculating the digest.
+ * @param context The MD5 content to set the translation for.
+ * @param xlate The translation handle to use for this MD5 context
+ */
+APU_DECLARE(apr_status_t) apr_md5_set_xlate(apr_md5_ctx_t *context,
+ apr_xlate_t *xlate);
+
+/**
+ * MD5 block update operation. Continue an MD5 message-digest operation,
+ * processing another message block, and updating the context.
+ * @param context The MD5 content to update.
+ * @param input next message block to update
+ * @param inputLen The length of the next message block
+ */
+APU_DECLARE(apr_status_t) apr_md5_update(apr_md5_ctx_t *context,
+ const void *input,
+ apr_size_t inputLen);
+
+/**
+ * MD5 finalization. Ends an MD5 message-digest operation, writing the
+ * message digest and zeroing the context
+ * @param digest The final MD5 digest
+ * @param context The MD5 content we are finalizing.
+ */
+APU_DECLARE(apr_status_t) apr_md5_final(unsigned char digest[APR_MD5_DIGESTSIZE],
+ apr_md5_ctx_t *context);
+
+/**
+ * MD5 in one step
+ * @param digest The final MD5 digest
+ * @param input The message block to use
+ * @param inputLen The length of the message block
+ */
+APU_DECLARE(apr_status_t) apr_md5(unsigned char digest[APR_MD5_DIGESTSIZE],
+ const void *input,
+ apr_size_t inputLen);
+
+/**
+ * Encode a password using an MD5 algorithm
+ * @param password The password to encode
+ * @param salt The salt to use for the encoding
+ * @param result The string to store the encoded password in
+ * @param nbytes The size of the result buffer
+ */
+APU_DECLARE(apr_status_t) apr_md5_encode(const char *password, const char *salt,
+ char *result, apr_size_t nbytes);
+
+
+/**
+ * Validate hashes created by APR-supported algorithms: md5 and sha1.
+ * hashes created by crypt are supported only on platforms that provide
+ * crypt(3), so don't rely on that function unless you know that your
+ * application will be run only on platforms that support it. On platforms
+ * that don't support crypt(3), this falls back to a clear text string
+ * comparison.
+ * @param passwd The password to validate
+ * @param hash The password to validate against
+ */
+APU_DECLARE(apr_status_t) apr_password_validate(const char *passwd,
+ const char *hash);
+
+
+/** @} */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !APR_MD5_H */
--- /dev/null
+/* Copyright 2001-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APR_OPTIONAL_H
+#define APR_OPTIONAL_H
+
+#include "apu.h"
+/**
+ * @file apr_optional.h
+ * @brief APR-UTIL registration of functions exported by modules
+ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup APR_Util_Opt Optional Functions
+ * @ingroup APR_Util
+ *
+ * Typesafe registration and retrieval of functions that may not be present
+ * (i.e. functions exported by optional modules)
+ * @{
+ */
+
+/**
+ * The type of an optional function.
+ * @param name The name of the function
+ */
+#define APR_OPTIONAL_FN_TYPE(name) apr_OFN_##name##_t
+
+/**
+ * Declare an optional function.
+ * @param ret The return type of the function
+ * @param name The name of the function
+ * @param args The function arguments (including brackets)
+ */
+#define APR_DECLARE_OPTIONAL_FN(ret,name,args) \
+typedef ret (APR_OPTIONAL_FN_TYPE(name)) args
+
+/**
+ * XXX: This doesn't belong here, then!
+ * Private function! DO NOT USE!
+ * @internal
+ */
+
+typedef void (apr_opt_fn_t)(void);
+/** @internal */
+APU_DECLARE_NONSTD(void) apr_dynamic_fn_register(const char *szName,
+ apr_opt_fn_t *pfn);
+
+/**
+ * Register an optional function. This can be later retrieved, type-safely, by
+ * name. Like all global functions, the name must be unique. Note that,
+ * confusingly but correctly, the function itself can be static!
+ * @param name The name of the function
+ */
+#define APR_REGISTER_OPTIONAL_FN(name) do { \
+ APR_OPTIONAL_FN_TYPE(name) *apu__opt = name; \
+ apr_dynamic_fn_register(#name,(apr_opt_fn_t *)apu__opt); \
+} while (0)
+
+/** @internal
+ * Private function! DO NOT USE!
+ */
+APU_DECLARE(apr_opt_fn_t *) apr_dynamic_fn_retrieve(const char *szName);
+
+/**
+ * Retrieve an optional function. Returns NULL if the function is not present.
+ * @param name The name of the function
+ */
+#define APR_RETRIEVE_OPTIONAL_FN(name) \
+ (APR_OPTIONAL_FN_TYPE(name) *)apr_dynamic_fn_retrieve(#name)
+
+/** @} */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* APR_OPTIONAL_H */
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @file apr_optional_hooks.h
+ * @brief Apache optional hook functions
+ */
+
+
+#ifndef APR_OPTIONAL_HOOK_H
+#define APR_OPTIONAL_HOOK_H
+
+#include "apr_tables.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/**
+ * @defgroup APR_Util_OPT_HOOK Optional Hook Functions
+ * @ingroup APR_Util_Hook
+ * @{
+ */
+/**
+ * Function to implemnt the APR_OPTIONAL_HOOK Macro
+ * @internal
+ * @see APR_OPTIONAL_HOOK
+ *
+ * @param name The name of the hook
+ * @param pfn A pointer to a function that will be called
+ * @param aszPre a NULL-terminated array of strings that name modules whose hooks should precede this one
+ * @param aszSucc a NULL-terminated array of strings that name modules whose hooks should succeed this one
+ * @param nOrder an integer determining order before honouring aszPre and aszSucc (for example HOOK_MIDDLE)
+ */
+
+
+APU_DECLARE(void) apr_optional_hook_add(const char *szName,void (*pfn)(void),
+ const char * const *aszPre,
+ const char * const *aszSucc,
+ int nOrder);
+
+/**
+ * Hook to an optional hook.
+ *
+ * @param ns The namespace prefix of the hook functions
+ * @param name The name of the hook
+ * @param pfn A pointer to a function that will be called
+ * @param aszPre a NULL-terminated array of strings that name modules whose hooks should precede this one
+ * @param aszSucc a NULL-terminated array of strings that name modules whose hooks should succeed this one
+ * @param nOrder an integer determining order before honouring aszPre and aszSucc (for example HOOK_MIDDLE)
+ */
+
+#define APR_OPTIONAL_HOOK(ns,name,pfn,aszPre,aszSucc,nOrder) do { \
+ ns##_HOOK_##name##_t *apu__hook = pfn; \
+ apr_optional_hook_add(#name,(void (*)(void))apu__hook,aszPre, aszSucc, nOrder); \
+} while (0)
+
+/**
+ * @internal
+ * @param szName - the name of the function
+ * @return the hook structure for a given hook
+ */
+APU_DECLARE(apr_array_header_t *) apr_optional_hook_get(const char *szName);
+
+/**
+ * Implement an optional hook that runs until one of the functions
+ * returns something other than OK or DECLINE.
+ *
+ * @param ns The namespace prefix of the hook functions
+ * @param link The linkage declaration prefix of the hook
+ * @param ret The type of the return value of the hook
+ * @param ret The type of the return value of the hook
+ * @param name The name of the hook
+ * @param args_decl The declaration of the arguments for the hook
+ * @param args_use The names for the arguments for the hook
+ * @param ok Success value
+ * @param decline Decline value
+ */
+#define APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(ns,link,ret,name,args_decl,args_use,ok,decline) \
+link##_DECLARE(ret) ns##_run_##name args_decl \
+ { \
+ ns##_LINK_##name##_t *pHook; \
+ int n; \
+ ret rv; \
+ apr_array_header_t *pHookArray=apr_optional_hook_get(#name); \
+\
+ if(!pHookArray) \
+ return ok; \
+\
+ pHook=(ns##_LINK_##name##_t *)pHookArray->elts; \
+ for(n=0 ; n < pHookArray->nelts ; ++n) \
+ { \
+ rv=(pHook[n].pFunc)args_use; \
+\
+ if(rv != ok && rv != decline) \
+ return rv; \
+ } \
+ return ok; \
+ }
+
+/** @} */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* APR_OPTIONAL_HOOK_H */
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APR_QUEUE_H
+#define APR_QUEUE_H
+
+#if APR_HAS_THREADS
+/**
+ * @file apr_queue.h
+ * @brief Thread Safe FIFO bounded queue
+ * @note Since most implementations of the queue are backed by a condition
+ * variable implementation, it isn't available on systems without threads.
+ * Although condition variables are some times available without threads.
+ */
+
+#include "apu.h"
+#include "apr_errno.h"
+#include "apr_pools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup APR_Util_FIFO Thread Safe FIFO bounded queue
+ * @ingroup APR_Util
+ * @{
+ */
+
+/**
+ * opaque structure
+ */
+typedef struct apr_queue_t apr_queue_t;
+
+/**
+ * create a FIFO queue
+ * @param queue The new queue
+ * @param queue_capacity maximum size of the queue
+ * @param a pool to allocate queue from
+ */
+APU_DECLARE(apr_status_t) apr_queue_create(apr_queue_t **queue,
+ unsigned int queue_capacity,
+ apr_pool_t *a);
+
+/**
+ * push/add a object to the queue, blocking if the queue is already full
+ *
+ * @param queue the queue
+ * @param data the data
+ * @returns APR_EINTR the blocking was interrupted (try again)
+ * @returns APR_EOF the queue has been terminated
+ * @returns APR_SUCCESS on a successfull push
+ */
+APU_DECLARE(apr_status_t) apr_queue_push(apr_queue_t *queue, void *data);
+
+/**
+ * pop/get an object from the queue, blocking if the queue is already empty
+ *
+ * @param queue the queue
+ * @param data the data
+ * @returns APR_EINTR the blocking was interrupted (try again)
+ * @returns APR_EOF if the queue has been terminated
+ * @returns APR_SUCCESS on a successfull pop
+ */
+APU_DECLARE(apr_status_t) apr_queue_pop(apr_queue_t *queue, void **data);
+
+/**
+ * push/add a object to the queue, returning immediatly if the queue is full
+ *
+ * @param queue the queue
+ * @param data the data
+ * @returns APR_EINTR the blocking operation was interrupted (try again)
+ * @returns APR_EAGAIN the queue is full
+ * @returns APR_EOF the queue has been terminated
+ * @returns APR_SUCCESS on a successfull push
+ */
+APU_DECLARE(apr_status_t) apr_queue_trypush(apr_queue_t *queue, void *data);
+
+/**
+ * pop/get an object to the queue, returning immediatly if the queue is empty
+ *
+ * @param queue the queue
+ * @param data the data
+ * @returns APR_EINTR the blocking operation was interrupted (try again)
+ * @returns APR_EAGAIN the queue is empty
+ * @returns APR_EOF the queue has been terminated
+ * @returns APR_SUCCESS on a successfull push
+ */
+APU_DECLARE(apr_status_t) apr_queue_trypop(apr_queue_t *queue, void **data);
+
+/**
+ * returns the size of the queue.
+ *
+ * @warning this is not threadsafe, and is intended for reporting/monitoring
+ * of the queue.
+ * @param queue the queue
+ * @returns the size of the queue
+ */
+APU_DECLARE(unsigned int) apr_queue_size(apr_queue_t *queue);
+
+/**
+ * interrupt all the threads blocking on this queue.
+ *
+ * @param queue the queue
+ */
+APU_DECLARE(apr_status_t) apr_queue_interrupt_all(apr_queue_t *queue);
+
+/**
+ * terminate all queue, sendinging a interupt to all the
+ * blocking threads
+ *
+ * @param queue the queue
+ */
+APU_DECLARE(apr_status_t) apr_queue_term(apr_queue_t *queue);
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
+
+#endif /* APR_HAS_THREADS */
+
+#endif /* APRQUEUE_H */
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APR_RESLIST_H
+#define APR_RESLIST_H
+
+/**
+ * @file apr_reslist.h
+ * @brief APR-UTIL Resource List Routines
+ */
+
+#include "apr.h"
+#include "apu.h"
+#include "apr_pools.h"
+#include "apr_errno.h"
+#include "apr_time.h"
+
+#if APR_HAS_THREADS
+
+/**
+ * @defgroup APR_Util_RL Resource List Routines
+ * @ingroup APR_Util
+ * @{
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/** Opaque resource list object */
+typedef struct apr_reslist_t apr_reslist_t;
+
+/* Generic constructor called by resource list when it needs to create a
+ * resource.
+ * @param resource opaque resource
+ * @param param flags
+ * @param pool Pool
+ */
+typedef apr_status_t (*apr_reslist_constructor)(void **resource, void *params,
+ apr_pool_t *pool);
+
+/* Generic destructor called by resource list when it needs to destroy a
+ * resource.
+ * @param resource opaque resource
+ * @param param flags
+ * @param pool Pool
+ */
+typedef apr_status_t (*apr_reslist_destructor)(void *resource, void *params,
+ apr_pool_t *pool);
+
+/**
+ * Create a new resource list with the following parameters:
+ * @param reslist An address where the pointer to the new resource
+ * list will be stored.
+ * @param pool The pool to use for local storage and management
+ * @param min Allowed minimum number of available resources. Zero
+ * creates new resources only when needed.
+ * @param smax Resources will be destroyed to meet this maximum
+ * restriction as they expire.
+ * @param hmax Absolute maximum limit on the number of total resources.
+ * @param ttl If non-zero, sets the maximum amount of time a resource
+ * may be available while exceeding the soft limit.
+ * @param con Constructor routine that is called to create a new resource.
+ * @param de Destructor routine that is called to destroy an expired resource.
+ * @param params Passed to constructor and deconstructor
+ * @param pool The pool from which to create this resoure list. Also the
+ * same pool that is passed to the constructor and destructor
+ * routines.
+ */
+APU_DECLARE(apr_status_t) apr_reslist_create(apr_reslist_t **reslist,
+ int min, int smax, int hmax,
+ apr_interval_time_t ttl,
+ apr_reslist_constructor con,
+ apr_reslist_destructor de,
+ void *params,
+ apr_pool_t *pool);
+
+/**
+ * Destroy the given resource list and all resources controlled by
+ * this list.
+ * FIXME: Should this block until all resources become available,
+ * or maybe just destroy all the free ones, or maybe destroy
+ * them even though they might be in use by something else?
+ * Currently it will abort if there are resources that haven't
+ * been released, so there is an assumption that all resources
+ * have been released to the list before calling this function.
+ * @param reslist The reslist to destroy
+ */
+APU_DECLARE(apr_status_t) apr_reslist_destroy(apr_reslist_t *reslist);
+
+/**
+ * Retrieve a resource from the list, creating a new one if necessary.
+ * If we have met our maximum number of resources, we will block
+ * until one becomes available.
+ */
+APU_DECLARE(apr_status_t) apr_reslist_acquire(apr_reslist_t *reslist,
+ void **resource);
+
+/**
+ * Return a resource back to the list of available resources.
+ */
+APU_DECLARE(apr_status_t) apr_reslist_release(apr_reslist_t *reslist,
+ void *resource);
+
+/**
+ * Set the timeout the acquire will wait for a free resource
+ * when the maximum number of resources is exceeded.
+ * @param reslist The resource list.
+ * @param timeout Timeout to wait. The zero waits forewer.
+ */
+APU_DECLARE(void) apr_reslist_timeout_set(apr_reslist_t *reslist,
+ apr_interval_time_t timeout);
+
+/**
+ * Invalidate a resource in the pool - e.g. a database connection
+ * that returns a "lost connection" error and can't be restored.
+ * Use this instead of apr_reslist_release if the resource is bad.
+ */
+APU_DECLARE(apr_status_t) apr_reslist_invalidate(apr_reslist_t *reslist,
+ void *resource);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
+
+#endif /* APR_HAS_THREADS */
+
+#endif /* ! APR_RESLIST_H */
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APR_RMM_H
+#define APR_RMM_H
+/**
+ * @file apr_rmm.h
+ * @brief APR-UTIL Relocatable Memory Management Routines
+ */
+/**
+ * @defgroup APR_Util_RMM Relocatable Memory Management Routines
+ * @ingroup APR_Util
+ * @{
+ */
+
+#include "apr.h"
+#include "apr_pools.h"
+#include "apr_errno.h"
+#include "apu.h"
+#include "apr_anylock.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/** Structure to access Relocatable, Managed Memory */
+typedef struct apr_rmm_t apr_rmm_t;
+
+/** Fundemental allocation unit, within a spcific apr_rmm_off_t */
+typedef apr_size_t apr_rmm_off_t;
+
+/**
+ * Initialize a relocatable memory block to be managed by the apr_rmm API.
+ * @param rmm The relocatable memory block
+ * @param lock An apr_anylock_t of the appropriate type of lock
+ * @param membuf The block of relocateable memory to be managed
+ * @param memsize The size of relocateable memory block to be managed
+ * @param cont The pool to use for local storage and management
+ * @remark Both @param membuf and @param memsize must be aligned
+ * (for instance using APR_ALIGN_DEFAULT).
+ */
+APU_DECLARE(apr_status_t) apr_rmm_init(apr_rmm_t **rmm, apr_anylock_t *lock,
+ void* membuf, apr_size_t memsize,
+ apr_pool_t *cont);
+
+/**
+ * Destroy a managed memory block.
+ * @param rmm The relocatable memory block to destroy
+ */
+APU_DECLARE(apr_status_t) apr_rmm_destroy(apr_rmm_t *rmm);
+
+/**
+ * Attach to a relocatable memory block already managed by the apr_rmm API.
+ * @param rmm The relocatable memory block
+ * @param lock An apr_anylock_t of the appropriate type of lock
+ * @param membuf The block of relocateable memory already under management
+ * @param cont The pool to use for local storage and management
+ */
+APU_DECLARE(apr_status_t) apr_rmm_attach(apr_rmm_t **rmm, apr_anylock_t *lock,
+ void* membuf, apr_pool_t *cont);
+
+/**
+ * Detach from the managed block of memory.
+ * @param rmm The relocatable memory block to detach from
+ */
+APU_DECLARE(apr_status_t) apr_rmm_detach(apr_rmm_t *rmm);
+
+/**
+ * Allocate memory from the block of relocatable memory.
+ * @param rmm The relocatable memory block
+ * @param reqsize How much memory to allocate
+ */
+APU_DECLARE(apr_rmm_off_t) apr_rmm_malloc(apr_rmm_t *rmm, apr_size_t reqsize);
+
+/**
+ * Realloc memory from the block of relocatable memory.
+ * @param rmm The relocatable memory block
+ * @param entity The memory allocation to realloc
+ * @param reqsize The new size
+ */
+APU_DECLARE(apr_rmm_off_t) apr_rmm_realloc(apr_rmm_t *rmm, void *entity, apr_size_t reqsize);
+
+/**
+ * Allocate memory from the block of relocatable memory and initialize it to zero.
+ * @param rmm The relocatable memory block
+ * @param reqsize How much memory to allocate
+ */
+APU_DECLARE(apr_rmm_off_t) apr_rmm_calloc(apr_rmm_t *rmm, apr_size_t reqsize);
+
+/**
+ * Free allocation returned by apr_rmm_malloc or apr_rmm_calloc.
+ * @param rmm The relocatable memory block
+ * @param entity The memory allocation to free
+ */
+APU_DECLARE(apr_status_t) apr_rmm_free(apr_rmm_t *rmm, apr_rmm_off_t entity);
+
+/**
+ * Retrieve the physical address of a relocatable allocation of memory
+ * @param rmm The relocatable memory block
+ * @param entity The memory allocation to free
+ * @return address The address, aligned with APR_ALIGN_DEFAULT.
+ */
+APU_DECLARE(void *) apr_rmm_addr_get(apr_rmm_t *rmm, apr_rmm_off_t entity);
+
+/**
+ * Compute the offset of a relocatable allocation of memory
+ * @param rmm The relocatable memory block
+ * @param entity The physical address to convert to an offset
+ */
+APU_DECLARE(apr_rmm_off_t) apr_rmm_offset_get(apr_rmm_t *rmm, void* entity);
+
+/**
+ * Compute the required overallocation of memory needed to fit n allocs
+ * @param n The number of alloc/calloc regions desired
+ */
+APU_DECLARE(apr_size_t) apr_rmm_overhead_get(int n);
+
+#ifdef __cplusplus
+}
+#endif
+/** @} */
+#endif /* ! APR_RMM_H */
+
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * sdbm - ndbm work-alike hashed database library
+ * based on Per-Ake Larson's Dynamic Hashing algorithms. BIT 18 (1978).
+ * author: oz@nexus.yorku.ca
+ * status: ex-public domain
+ */
+
+#ifndef APR_SDBM_H
+#define APR_SDBM_H
+
+#include "apu.h"
+#include "apr_errno.h"
+#include "apr_file_io.h" /* for apr_fileperms_t */
+
+/**
+ * @file apr_sdbm.h
+ * @brief apr-util SDBM library
+ */
+/**
+ * @defgroup APR_Util_DBM_SDBM SDBM library
+ * @ingroup APR_Util_DBM
+ * @{
+ */
+
+/**
+ * Structure for referencing an sdbm
+ */
+typedef struct apr_sdbm_t apr_sdbm_t;
+
+/**
+ * Structure for referencing the datum record within an sdbm
+ */
+typedef struct {
+ /** pointer to the data stored/retrieved */
+ char *dptr;
+ /** size of data */
+ int dsize;
+} apr_sdbm_datum_t;
+
+/* The extensions used for the database files */
+/** SDBM Directory file extension */
+#define APR_SDBM_DIRFEXT ".dir"
+/** SDBM page file extension */
+#define APR_SDBM_PAGFEXT ".pag"
+
+/* flags to sdbm_store */
+#define APR_SDBM_INSERT 0 /**< Insert */
+#define APR_SDBM_REPLACE 1 /**< Replace */
+#define APR_SDBM_INSERTDUP 2 /**< Insert with duplicates */
+
+/**
+ * Open an sdbm database by file name
+ * @param db The newly opened database
+ * @param name The sdbm file to open
+ * @param mode The flag values (APR_READ and APR_BINARY flags are implicit)
+ * <PRE>
+ * APR_WRITE open for read-write access
+ * APR_CREATE create the sdbm if it does not exist
+ * APR_TRUNCATE empty the contents of the sdbm
+ * APR_EXCL fail for APR_CREATE if the file exists
+ * APR_DELONCLOSE delete the sdbm when closed
+ * APR_SHARELOCK support locking across process/machines
+ * </PRE>
+ * @param perms Permissions to apply to if created
+ * @param p The pool to use when creating the sdbm
+ * @remark The sdbm name is not a true file name, as sdbm appends suffixes
+ * for seperate data and index files.
+ */
+APU_DECLARE(apr_status_t) apr_sdbm_open(apr_sdbm_t **db, const char *name,
+ apr_int32_t mode,
+ apr_fileperms_t perms, apr_pool_t *p);
+
+/**
+ * Close an sdbm file previously opened by apr_sdbm_open
+ * @param db The database to close
+ */
+APU_DECLARE(apr_status_t) apr_sdbm_close(apr_sdbm_t *db);
+
+/**
+ * Lock an sdbm database for concurency of multiple operations
+ * @param db The database to lock
+ * @param type The lock type
+ * <PRE>
+ * APR_FLOCK_SHARED
+ * APR_FLOCK_EXCLUSIVE
+ * </PRE>
+ * @remark Calls to apr_sdbm_lock may be nested. All apr_sdbm functions
+ * perform implicit locking. Since an APR_FLOCK_SHARED lock cannot be
+ * portably promoted to an APR_FLOCK_EXCLUSIVE lock, apr_sdbm_store and
+ * apr_sdbm_delete calls will fail if an APR_FLOCK_SHARED lock is held.
+ * The apr_sdbm_lock call requires the database to be opened with the
+ * APR_SHARELOCK mode value.
+ */
+APU_DECLARE(apr_status_t) apr_sdbm_lock(apr_sdbm_t *db, int type);
+
+/**
+ * Release an sdbm lock previously aquired by apr_sdbm_lock
+ * @param db The database to unlock
+ */
+APU_DECLARE(apr_status_t) apr_sdbm_unlock(apr_sdbm_t *db);
+
+/**
+ * Fetch an sdbm record value by key
+ * @param db The database
+ * @param value The value datum retrieved for this record
+ * @param key The key datum to find this record
+ */
+APU_DECLARE(apr_status_t) apr_sdbm_fetch(apr_sdbm_t *db,
+ apr_sdbm_datum_t *value,
+ apr_sdbm_datum_t key);
+
+/**
+ * Store an sdbm record value by key
+ * @param db The database
+ * @param key The key datum to store this record by
+ * @param value The value datum to store in this record
+ * @param opt The method used to store the record
+ * <PRE>
+ * APR_SDBM_INSERT return an error if the record exists
+ * APR_SDBM_REPLACE overwrite any existing record for key
+ * </PRE>
+ */
+APU_DECLARE(apr_status_t) apr_sdbm_store(apr_sdbm_t *db, apr_sdbm_datum_t key,
+ apr_sdbm_datum_t value, int opt);
+
+/**
+ * Delete an sdbm record value by key
+ * @param db The database
+ * @param key The key datum of the record to delete
+ * @remark It is not an error to delete a non-existent record.
+ */
+APU_DECLARE(apr_status_t) apr_sdbm_delete(apr_sdbm_t *db,
+ const apr_sdbm_datum_t key);
+
+/**
+ * Retrieve the first record key from a dbm
+ * @param db The database
+ * @param key The key datum of the first record
+ * @remark The keys returned are not ordered. To traverse the list of keys
+ * for an sdbm opened with APR_SHARELOCK, the caller must use apr_sdbm_lock
+ * prior to retrieving the first record, and hold the lock until after the
+ * last call to apr_sdbm_nextkey.
+ */
+APU_DECLARE(apr_status_t) apr_sdbm_firstkey(apr_sdbm_t *db, apr_sdbm_datum_t *key);
+
+/**
+ * Retrieve the next record key from an sdbm
+ * @param db The database
+ * @param key The key datum of the next record
+ */
+APU_DECLARE(apr_status_t) apr_sdbm_nextkey(apr_sdbm_t *db, apr_sdbm_datum_t *key);
+
+/**
+ * Returns true if the sdbm database opened for read-only access
+ * @param db The database to test
+ */
+APU_DECLARE(int) apr_sdbm_rdonly(apr_sdbm_t *db);
+/** @} */
+#endif /* APR_SDBM_H */
--- /dev/null
+/* Copyright 2001-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/* NIST Secure Hash Algorithm
+ * heavily modified by Uwe Hollerbach uh@alumni.caltech edu
+ * from Peter C. Gutmann's implementation as found in
+ * Applied Cryptography by Bruce Schneier
+ * This code is hereby placed in the public domain
+ */
+
+#ifndef APR_SHA1_H
+#define APR_SHA1_H
+
+#include "apu.h"
+#include "apr_general.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @file apr_sha1.h
+ * @brief APR-UTIL SHA1 library
+ */
+
+/** size of the SHA1 DIGEST */
+#define APR_SHA1_DIGESTSIZE 20
+
+/**
+ * Define the Magic String prefix that identifies a password as being
+ * hashed using our algorithm.
+ */
+#define APR_SHA1PW_ID "{SHA}"
+
+/** length of the SHA Password */
+#define APR_SHA1PW_IDLEN 5
+
+/** @see apr_sha1_ctx_t */
+typedef struct apr_sha1_ctx_t apr_sha1_ctx_t;
+
+/**
+ * SHA1 context structure
+ */
+struct apr_sha1_ctx_t {
+ /** message digest */
+ apr_uint32_t digest[5];
+ /** 64-bit bit counts */
+ apr_uint32_t count_lo, count_hi;
+ /** SHA data buffer */
+ apr_uint32_t data[16];
+ /** unprocessed amount in data */
+ int local;
+};
+
+/**
+ * Provide a means to SHA1 crypt/encode a plaintext password in a way which
+ * makes password file compatible with those commonly use in netscape web
+ * and ldap installations.
+ * @param clear The plaintext password
+ * @param len The length of the plaintext password
+ * @param out The encrypted/encoded password
+ * @note SHA1 support is useful for migration purposes, but is less
+ * secure than Apache's password format, since Apache's (MD5)
+ * password format uses a random eight character salt to generate
+ * one of many possible hashes for the same password. Netscape
+ * uses plain SHA1 without a salt, so the same password
+ * will always generate the same hash, making it easier
+ * to break since the search space is smaller.
+ */
+APU_DECLARE(void) apr_sha1_base64(const char *clear, int len, char *out);
+
+/**
+ * Initialize the SHA digest
+ * @param context The SHA context to initialize
+ */
+APU_DECLARE(void) apr_sha1_init(apr_sha1_ctx_t *context);
+
+/**
+ * Update the SHA digest
+ * @param context The SHA1 context to update
+ * @param input The buffer to add to the SHA digest
+ * @param inputLen The length of the input buffer
+ */
+APU_DECLARE(void) apr_sha1_update(apr_sha1_ctx_t *context, const char *input,
+ unsigned int inputLen);
+
+/**
+ * Update the SHA digest with binary data
+ * @param context The SHA1 context to update
+ * @param input The buffer to add to the SHA digest
+ * @param inputLen The length of the input buffer
+ */
+APU_DECLARE(void) apr_sha1_update_binary(apr_sha1_ctx_t *context,
+ const unsigned char *input,
+ unsigned int inputLen);
+
+/**
+ * Finish computing the SHA digest
+ * @param digest the output buffer in which to store the digest
+ * @param context The context to finalize
+ */
+APU_DECLARE(void) apr_sha1_final(unsigned char digest[APR_SHA1_DIGESTSIZE],
+ apr_sha1_ctx_t *context);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* APR_SHA1_H */
--- /dev/null
+/* Copyright 2002-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APR_STRMATCH_H
+#define APR_STRMATCH_H
+/**
+ * @file apr_strmatch.h
+ * @brief APR-UTIL string matching routines
+ */
+
+#include "apu.h"
+#include "apr_pools.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup APR_Util_StrMatch String matching routines
+ * @ingroup APR_Util
+ * @{
+ */
+
+/** @see apr_strmatch_pattern */
+typedef struct apr_strmatch_pattern apr_strmatch_pattern;
+
+/**
+ * Precompiled search pattern
+ */
+struct apr_strmatch_pattern {
+ /** Function called to compare */
+ const char *(*compare)(const apr_strmatch_pattern *this_pattern,
+ const char *s, apr_size_t slen);
+ const char *pattern; /**< Current pattern */
+ apr_size_t length; /**< Current length */
+ void *context; /**< hook to add precomputed metadata */
+};
+
+#if defined(DOXYGEN)
+/**
+ * Search for a precompiled pattern within a string
+ * @param pattern The pattern
+ * @param s The string in which to search for the pattern
+ * @param slen The length of s (excluding null terminator)
+ * @return A pointer to the first instance of the pattern in s, or
+ * NULL if not found
+ */
+APU_DECLARE(const char *) apr_strmatch(const apr_strmatch_pattern *pattern,
+ const char *s, apr_size_t slen);
+#else
+#define apr_strmatch(pattern, s, slen) (*((pattern)->compare))((pattern), (s), (slen))
+#endif
+
+/**
+ * Precompile a pattern for matching using the Boyer-Moore-Horspool algorithm
+ * @param p The pool from which to allocate the pattern
+ * @param s The pattern string
+ * @param case_sensitive Whether the matching should be case-sensitive
+ * @return a pointer to the compiled pattern, or NULL if compilation fails
+ */
+APU_DECLARE(const apr_strmatch_pattern *) apr_strmatch_precompile(apr_pool_t *p, const char *s, int case_sensitive);
+
+/** @} */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !APR_STRMATCH_H */
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * apr_uri.h: External Interface of apr_uri.c
+ */
+
+/**
+ * @file apr_uri.h
+ * @brief APR-UTIL URI Routines
+ */
+
+#ifndef APR_URI_H
+#define APR_URI_H
+
+#include "apu.h"
+
+#include "apr_network_io.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @defgroup APR_Util_URI URI
+ * @ingroup APR_Util
+ * @{
+ */
+
+#define APR_URI_FTP_DEFAULT_PORT 21 /**< default FTP port */
+#define APR_URI_SSH_DEFAULT_PORT 22 /**< default SSH port */
+#define APR_URI_TELNET_DEFAULT_PORT 23 /**< default telnet port */
+#define APR_URI_GOPHER_DEFAULT_PORT 70 /**< default Gopher port */
+#define APR_URI_HTTP_DEFAULT_PORT 80 /**< default HTTP port */
+#define APR_URI_POP_DEFAULT_PORT 110 /**< default POP port */
+#define APR_URI_NNTP_DEFAULT_PORT 119 /**< default NNTP port */
+#define APR_URI_IMAP_DEFAULT_PORT 143 /**< default IMAP port */
+#define APR_URI_PROSPERO_DEFAULT_PORT 191 /**< default Prospero port */
+#define APR_URI_WAIS_DEFAULT_PORT 210 /**< default WAIS port */
+#define APR_URI_LDAP_DEFAULT_PORT 389 /**< default LDAP port */
+#define APR_URI_HTTPS_DEFAULT_PORT 443 /**< default HTTPS port */
+#define APR_URI_RTSP_DEFAULT_PORT 554 /**< default RTSP port */
+#define APR_URI_SNEWS_DEFAULT_PORT 563 /**< default SNEWS port */
+#define APR_URI_ACAP_DEFAULT_PORT 674 /**< default ACAP port */
+#define APR_URI_NFS_DEFAULT_PORT 2049 /**< default NFS port */
+#define APR_URI_TIP_DEFAULT_PORT 3372 /**< default TIP port */
+#define APR_URI_SIP_DEFAULT_PORT 5060 /**< default SIP port */
+
+/** Flags passed to unparse_uri_components(): */
+/** suppress "scheme://user\@site:port" */
+#define APR_URI_UNP_OMITSITEPART (1U<<0)
+/** Just omit user */
+#define APR_URI_UNP_OMITUSER (1U<<1)
+/** Just omit password */
+#define APR_URI_UNP_OMITPASSWORD (1U<<2)
+/** omit "user:password\@" part */
+#define APR_URI_UNP_OMITUSERINFO (APR_URI_UNP_OMITUSER | \
+ APR_URI_UNP_OMITPASSWORD)
+/** Show plain text password (default: show XXXXXXXX) */
+#define APR_URI_UNP_REVEALPASSWORD (1U<<3)
+/** Show "scheme://user\@site:port" only */
+#define APR_URI_UNP_OMITPATHINFO (1U<<4)
+/** Omit the "?queryarg" from the path */
+#define APR_URI_UNP_OMITQUERY (1U<<5)
+
+/** @see apr_uri_t */
+typedef struct apr_uri_t apr_uri_t;
+
+/**
+ * A structure to encompass all of the fields in a uri
+ */
+struct apr_uri_t {
+ /** scheme ("http"/"ftp"/...) */
+ char *scheme;
+ /** combined [user[:password]\@]host[:port] */
+ char *hostinfo;
+ /** user name, as in http://user:passwd\@host:port/ */
+ char *user;
+ /** password, as in http://user:passwd\@host:port/ */
+ char *password;
+ /** hostname from URI (or from Host: header) */
+ char *hostname;
+ /** port string (integer representation is in "port") */
+ char *port_str;
+ /** the request path (or "/" if only scheme://host was given) */
+ char *path;
+ /** Everything after a '?' in the path, if present */
+ char *query;
+ /** Trailing "#fragment" string, if present */
+ char *fragment;
+
+ /** structure returned from gethostbyname() */
+ struct hostent *hostent;
+
+ /** The port number, numeric, valid only if port_str != NULL */
+ apr_port_t port;
+
+ /** has the structure been initialized */
+ unsigned is_initialized:1;
+
+ /** has the DNS been looked up yet */
+ unsigned dns_looked_up:1;
+ /** has the dns been resolved yet */
+ unsigned dns_resolved:1;
+};
+
+/* apr_uri.c */
+/**
+ * Return the default port for a given scheme. The schemes recognized are
+ * http, ftp, https, gopher, wais, nntp, snews, and prospero
+ * @param scheme_str The string that contains the current scheme
+ * @return The default port for this scheme
+ */
+APU_DECLARE(apr_port_t) apr_uri_port_of_scheme(const char *scheme_str);
+
+/**
+ * Unparse a apr_uri_t structure to an URI string. Optionally
+ * suppress the password for security reasons.
+ * @param p The pool to allocate out of
+ * @param uptr All of the parts of the uri
+ * @param flags How to unparse the uri. One of:
+ * <PRE>
+ * APR_URI_UNP_OMITSITEPART Suppress "scheme://user\@site:port"
+ * APR_URI_UNP_OMITUSER Just omit user
+ * APR_URI_UNP_OMITPASSWORD Just omit password
+ * APR_URI_UNP_OMITUSERINFO Omit "user:password\@" part
+ * APR_URI_UNP_REVEALPASSWORD Show plain text password (default: show XXXXXXXX)
+ * APR_URI_UNP_OMITPATHINFO Show "scheme://user\@site:port" only
+ * APR_URI_UNP_OMITQUERY Omit "?queryarg" or "#fragment"
+ * </PRE>
+ * @return The uri as a string
+ */
+APU_DECLARE(char *) apr_uri_unparse(apr_pool_t *p,
+ const apr_uri_t *uptr,
+ unsigned flags);
+
+/**
+ * Parse a given URI, fill in all supplied fields of a apr_uri_t
+ * structure. This eliminates the necessity of extracting host, port,
+ * path, query info repeatedly in the modules.
+ * @param p The pool to allocate out of
+ * @param uri The uri to parse
+ * @param uptr The apr_uri_t to fill out
+ * @return 0 for success or error code
+ */
+APU_DECLARE(int) apr_uri_parse(apr_pool_t *p, const char *uri,
+ apr_uri_t *uptr);
+
+/**
+ * Special case for CONNECT parsing: it comes with the hostinfo part only
+ * @param p The pool to allocate out of
+ * @param hostinfo The hostinfo string to parse
+ * @param uptr The apr_uri_t to fill out
+ * @return 0 for success or error code
+ */
+APU_DECLARE(int) apr_uri_parse_hostinfo(apr_pool_t *p,
+ const char *hostinfo,
+ apr_uri_t *uptr);
+
+/** @} */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* APR_URI_H */
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file apr_uuid.h
+ * @brief APR UUID library
+ */
+#ifndef APR_UUID_H
+#define APR_UUID_H
+
+#include "apu.h"
+#include "apr_errno.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup APR_UUID UUID Handling
+ * @ingroup APR
+ * @{
+ */
+
+/**
+ * we represent a UUID as a block of 16 bytes.
+ */
+
+typedef struct {
+ unsigned char data[16]; /**< the actual UUID */
+} apr_uuid_t;
+
+/** UUIDs are formatted as: 00112233-4455-6677-8899-AABBCCDDEEFF */
+#define APR_UUID_FORMATTED_LENGTH 36
+
+
+/**
+ * Generate and return a (new) UUID
+ * @param uuid The resulting UUID
+ */
+APU_DECLARE(void) apr_uuid_get(apr_uuid_t *uuid);
+
+/**
+ * Format a UUID into a string, following the standard format
+ * @param buffer The buffer to place the formatted UUID string into. It must
+ * be at least APR_UUID_FORMATTED_LENGTH + 1 bytes long to hold
+ * the formatted UUID and a null terminator
+ * @param uuid The UUID to format
+ */
+APU_DECLARE(void) apr_uuid_format(char *buffer, const apr_uuid_t *uuid);
+
+/**
+ * Parse a standard-format string into a UUID
+ * @param uuid The resulting UUID
+ * @param uuid_str The formatted UUID
+ */
+APU_DECLARE(apr_status_t) apr_uuid_parse(apr_uuid_t *uuid, const char *uuid_str);
+
+/** @} */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* APR_UUID_H */
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APR_XLATE_H
+#define APR_XLATE_H
+
+#include "apu.h"
+#include "apr_pools.h"
+#include "apr_errno.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @file apr_xlate.h
+ * @brief APR I18N translation library
+ */
+
+/**
+ * @defgroup APR_XLATE I18N translation library
+ * @ingroup APR
+ * @{
+ */
+/** Opaque translation buffer */
+typedef struct apr_xlate_t apr_xlate_t;
+
+/**
+ * Set up for converting text from one charset to another.
+ * @param convset The handle to be filled in by this function
+ * @param topage The name of the target charset
+ * @param frompage The name of the source charset
+ * @param pool The pool to use
+ * @remark
+ * Specify APR_DEFAULT_CHARSET for one of the charset
+ * names to indicate the charset of the source code at
+ * compile time. This is useful if there are literal
+ * strings in the source code which must be translated
+ * according to the charset of the source code.
+ * APR_DEFAULT_CHARSET is not useful if the source code
+ * of the caller was not encoded in the same charset as
+ * APR at compile time.
+ *
+ * @remark
+ * Specify APR_LOCALE_CHARSET for one of the charset
+ * names to indicate the charset of the current locale.
+ *
+ * @remark
+ * Return APR_EINVAL if unable to procure a convset, or APR_ENOTIMPL
+ * if charset transcoding is not available in this instance of
+ * apr-util at all (i.e., APR_HAS_XLATE is undefined).
+ */
+APU_DECLARE(apr_status_t) apr_xlate_open(apr_xlate_t **convset,
+ const char *topage,
+ const char *frompage,
+ apr_pool_t *pool);
+
+/**
+ * This is to indicate the charset of the sourcecode at compile time
+ * names to indicate the charset of the source code at
+ * compile time. This is useful if there are literal
+ * strings in the source code which must be translated
+ * according to the charset of the source code.
+ */
+#define APR_DEFAULT_CHARSET (const char *)0
+/**
+ * To indicate charset names of the current locale
+ */
+#define APR_LOCALE_CHARSET (const char *)1
+
+/**
+ * Find out whether or not the specified conversion is single-byte-only.
+ * @param convset The handle allocated by apr_xlate_open, specifying the
+ * parameters of conversion
+ * @param onoff Output: whether or not the conversion is single-byte-only
+ * @remark
+ * Return APR_ENOTIMPL if charset transcoding is not available
+ * in this instance of apr-util (i.e., APR_HAS_XLATE is undefined).
+ */
+APU_DECLARE(apr_status_t) apr_xlate_sb_get(apr_xlate_t *convset, int *onoff);
+
+/**
+ * Convert a buffer of text from one codepage to another.
+ * @param convset The handle allocated by apr_xlate_open, specifying
+ * the parameters of conversion
+ * @param inbuf The address of the source buffer
+ * @param inbytes_left Input: the amount of input data to be translated
+ * Output: the amount of input data not yet translated
+ * @param outbuf The address of the destination buffer
+ * @param outbytes_left Input: the size of the output buffer
+ * Output: the amount of the output buffer not yet used
+ * @remark
+ * Returns APR_ENOTIMPL if charset transcoding is not available
+ * in this instance of apr-util (i.e., APR_HAS_XLATE is undefined).
+ * Returns APR_INCOMPLETE if the input buffer ends in an incomplete
+ * multi-byte character.
+ *
+ * To correctly terminate the output buffer for some multi-byte
+ * character set encodings, a final call must be made to this function
+ * after the complete input string has been converted, passing
+ * the inbuf and inbytes_left parameters as NULL. (Note that this
+ * mode only works from version 1.1.0 onwards)
+ */
+APU_DECLARE(apr_status_t) apr_xlate_conv_buffer(apr_xlate_t *convset,
+ const char *inbuf,
+ apr_size_t *inbytes_left,
+ char *outbuf,
+ apr_size_t *outbytes_left);
+
+/* @see apr_file_io.h the comment in apr_file_io.h about this hack */
+#ifdef APR_NOT_DONE_YET
+/**
+ * The purpose of apr_xlate_conv_char is to translate one character
+ * at a time. This needs to be written carefully so that it works
+ * with double-byte character sets.
+ * @param convset The handle allocated by apr_xlate_open, specifying the
+ * parameters of conversion
+ * @param inchar The character to convert
+ * @param outchar The converted character
+ */
+APU_DECLARE(apr_status_t) apr_xlate_conv_char(apr_xlate_t *convset,
+ char inchar, char outchar);
+#endif
+
+/**
+ * Convert a single-byte character from one charset to another.
+ * @param convset The handle allocated by apr_xlate_open, specifying the
+ * parameters of conversion
+ * @param inchar The single-byte character to convert.
+ * @warning This only works when converting between single-byte character sets.
+ * -1 will be returned if the conversion can't be performed.
+ */
+APU_DECLARE(apr_int32_t) apr_xlate_conv_byte(apr_xlate_t *convset,
+ unsigned char inchar);
+
+/**
+ * Close a codepage translation handle.
+ * @param convset The codepage translation handle to close
+ * @remark
+ * Return APR_ENOTIMPL if charset transcoding is not available
+ * in this instance of apr-util (i.e., APR_HAS_XLATE is undefined).
+ */
+APU_DECLARE(apr_status_t) apr_xlate_close(apr_xlate_t *convset);
+
+/** @} */
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ! APR_XLATE_H */
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @file apr_xml.h
+ * @brief APR-UTIL XML Library
+ */
+#ifndef APR_XML_H
+#define APR_XML_H
+
+/**
+ * @defgroup APR_Util_XML XML
+ * @ingroup APR_Util
+ * @{
+ */
+#include "apr_pools.h"
+#include "apr_tables.h"
+#include "apr_file_io.h"
+
+#include "apu.h"
+#if APR_CHARSET_EBCDIC
+#include "apr_xlate.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @package Apache XML library
+ */
+
+/* -------------------------------------------------------------------- */
+
+/* ### these will need to move at some point to a more logical spot */
+
+/** @see apr_text */
+typedef struct apr_text apr_text;
+
+/** Structure to keep a linked list of pieces of text */
+struct apr_text {
+ /** The current piece of text */
+ const char *text;
+ /** a pointer to the next piece of text */
+ struct apr_text *next;
+};
+
+/** @see apr_text_header */
+typedef struct apr_text_header apr_text_header;
+
+/** A list of pieces of text */
+struct apr_text_header {
+ /** The first piece of text in the list */
+ apr_text *first;
+ /** The last piece of text in the list */
+ apr_text *last;
+};
+
+/**
+ * Append a piece of text to the end of a list
+ * @param p The pool to allocate out of
+ * @param hdr The text header to append to
+ * @param text The new text to append
+ */
+APU_DECLARE(void) apr_text_append(apr_pool_t *p, apr_text_header *hdr,
+ const char *text);
+
+
+/* --------------------------------------------------------------------
+**
+** XML PARSING
+*/
+
+/*
+** Qualified namespace values
+**
+** APR_XML_NS_DAV_ID
+** We always insert the "DAV:" namespace URI at the head of the
+** namespace array. This means that it will always be at ID==0,
+** making it much easier to test for.
+**
+** APR_XML_NS_NONE
+** This special ID is used for two situations:
+**
+** 1) The namespace prefix begins with "xml" (and we do not know
+** what it means). Namespace prefixes with "xml" (any case) as
+** their first three characters are reserved by the XML Namespaces
+** specification for future use. mod_dav will pass these through
+** unchanged. When this identifier is used, the prefix is LEFT in
+** the element/attribute name. Downstream processing should not
+** prepend another prefix.
+**
+** 2) The element/attribute does not have a namespace.
+**
+** a) No prefix was used, and a default namespace has not been
+** defined.
+** b) No prefix was used, and the default namespace was specified
+** to mean "no namespace". This is done with a namespace
+** declaration of: xmlns=""
+** (this declaration is typically used to override a previous
+** specification for the default namespace)
+**
+** In these cases, we need to record that the elem/attr has no
+** namespace so that we will not attempt to prepend a prefix.
+** All namespaces that are used will have a prefix assigned to
+** them -- mod_dav will never set or use the default namespace
+** when generating XML. This means that "no prefix" will always
+** mean "no namespace".
+**
+** In both cases, the XML generation will avoid prepending a prefix.
+** For the first case, this means the original prefix/name will be
+** inserted into the output stream. For the latter case, it means
+** the name will have no prefix, and since we never define a default
+** namespace, this means it will have no namespace.
+**
+** Note: currently, mod_dav understands the "xmlns" prefix and the
+** "xml:lang" attribute. These are handled specially (they aren't
+** left within the XML tree), so the APR_XML_NS_NONE value won't ever
+** really apply to these values.
+*/
+#define APR_XML_NS_DAV_ID 0 /**< namespace ID for "DAV:" */
+#define APR_XML_NS_NONE -10 /**< no namespace for this elem/attr */
+
+#define APR_XML_NS_ERROR_BASE -100 /**< used only during processing */
+/** Is this namespace an error? */
+#define APR_XML_NS_IS_ERROR(e) ((e) <= APR_XML_NS_ERROR_BASE)
+
+/** @see apr_xml_attr */
+typedef struct apr_xml_attr apr_xml_attr;
+/** @see apr_xml_elem */
+typedef struct apr_xml_elem apr_xml_elem;
+/** @see apr_xml_doc */
+typedef struct apr_xml_doc apr_xml_doc;
+
+/** apr_xml_attr: holds a parsed XML attribute */
+struct apr_xml_attr {
+ /** attribute name */
+ const char *name;
+ /** index into namespace array */
+ int ns;
+
+ /** attribute value */
+ const char *value;
+
+ /** next attribute */
+ struct apr_xml_attr *next;
+};
+
+/** apr_xml_elem: holds a parsed XML element */
+struct apr_xml_elem {
+ /** element name */
+ const char *name;
+ /** index into namespace array */
+ int ns;
+ /** xml:lang for attrs/contents */
+ const char *lang;
+
+ /** cdata right after start tag */
+ apr_text_header first_cdata;
+ /** cdata after MY end tag */
+ apr_text_header following_cdata;
+
+ /** parent element */
+ struct apr_xml_elem *parent;
+ /** next (sibling) element */
+ struct apr_xml_elem *next;
+ /** first child element */
+ struct apr_xml_elem *first_child;
+ /** first attribute */
+ struct apr_xml_attr *attr;
+
+ /* used only during parsing */
+ /** last child element */
+ struct apr_xml_elem *last_child;
+ /** namespaces scoped by this elem */
+ struct apr_xml_ns_scope *ns_scope;
+
+ /* used by modules during request processing */
+ /** Place for modules to store private data */
+ void *priv;
+};
+
+/** Is this XML element empty? */
+#define APR_XML_ELEM_IS_EMPTY(e) ((e)->first_child == NULL && \
+ (e)->first_cdata.first == NULL)
+
+/** apr_xml_doc: holds a parsed XML document */
+struct apr_xml_doc {
+ /** root element */
+ apr_xml_elem *root;
+ /** array of namespaces used */
+ apr_array_header_t *namespaces;
+};
+
+/** Opaque XML parser structure */
+typedef struct apr_xml_parser apr_xml_parser;
+
+/**
+ * Create an XML parser
+ * @param pool The pool for allocating the parser and the parse results.
+ * @return The new parser.
+ */
+APU_DECLARE(apr_xml_parser *) apr_xml_parser_create(apr_pool_t *pool);
+
+/**
+ * Parse a File, producing a xml_doc
+ * @param p The pool for allocating the parse results.
+ * @param parser A pointer to *parser (needed so calling function can get
+ * errors), will be set to NULL on successfull completion.
+ * @param ppdoc A pointer to *apr_xml_doc (which has the parsed results in it)
+ * @param xmlfd A file to read from.
+ * @param buffer_length Buffer length which would be suitable
+ * @return Any errors found during parsing.
+ */
+APU_DECLARE(apr_status_t) apr_xml_parse_file(apr_pool_t *p,
+ apr_xml_parser **parser,
+ apr_xml_doc **ppdoc,
+ apr_file_t *xmlfd,
+ apr_size_t buffer_length);
+
+
+/**
+ * Feed input into the parser
+ * @param parser The XML parser for parsing this data.
+ * @param data The data to parse.
+ * @param len The length of the data.
+ * @return Any errors found during parsing.
+ * @remark Use apr_xml_parser_geterror() to get more error information.
+ */
+APU_DECLARE(apr_status_t) apr_xml_parser_feed(apr_xml_parser *parser,
+ const char *data,
+ apr_size_t len);
+
+/**
+ * Terminate the parsing and return the result
+ * @param parser The XML parser for parsing this data.
+ * @param pdoc The resulting parse information. May be NULL to simply
+ * terminate the parsing without fetching the info.
+ * @return Any errors found during the final stage of parsing.
+ * @remark Use apr_xml_parser_geterror() to get more error information.
+ */
+APU_DECLARE(apr_status_t) apr_xml_parser_done(apr_xml_parser *parser,
+ apr_xml_doc **pdoc);
+
+/**
+ * Fetch additional error information from the parser.
+ * @param parser The XML parser to query for errors.
+ * @param errbuf A buffer for storing error text.
+ * @param errbufsize The length of the error text buffer.
+ * @return The error buffer
+ */
+APU_DECLARE(char *) apr_xml_parser_geterror(apr_xml_parser *parser,
+ char *errbuf,
+ apr_size_t errbufsize);
+
+
+/**
+ * Converts an XML element tree to flat text
+ * @param p The pool to allocate out of
+ * @param elem The XML element to convert
+ * @param style How to covert the XML. One of:
+ * <PRE>
+ * APR_XML_X2T_FULL start tag, contents, end tag
+ * APR_XML_X2T_INNER contents only
+ * APR_XML_X2T_LANG_INNER xml:lang + inner contents
+ * APR_XML_X2T_FULL_NS_LANG FULL + ns defns + xml:lang
+ * </PRE>
+ * @param namespaces The namespace of the current XML element
+ * @param ns_map Namespace mapping
+ * @param pbuf Buffer to put the converted text into
+ * @param psize Size of the converted text
+ */
+APU_DECLARE(void) apr_xml_to_text(apr_pool_t *p, const apr_xml_elem *elem,
+ int style, apr_array_header_t *namespaces,
+ int *ns_map, const char **pbuf,
+ apr_size_t *psize);
+
+/* style argument values: */
+#define APR_XML_X2T_FULL 0 /**< start tag, contents, end tag */
+#define APR_XML_X2T_INNER 1 /**< contents only */
+#define APR_XML_X2T_LANG_INNER 2 /**< xml:lang + inner contents */
+#define APR_XML_X2T_FULL_NS_LANG 3 /**< FULL + ns defns + xml:lang */
+
+/**
+ * empty XML element
+ * @param p The pool to allocate out of
+ * @param elem The XML element to empty
+ * @return the string that was stored in the XML element
+ */
+APU_DECLARE(const char *) apr_xml_empty_elem(apr_pool_t *p,
+ const apr_xml_elem *elem);
+
+/**
+ * quote an XML string
+ * Replace '<', '>', and '&' with '<', '>', and '&'.
+ * @param p The pool to allocate out of
+ * @param s The string to quote
+ * @param quotes If quotes is true, then replace '"' with '"'.
+ * @return The quoted string
+ * @note If the string does not contain special characters, it is not
+ * duplicated into the pool and the original string is returned.
+ */
+APU_DECLARE(const char *) apr_xml_quote_string(apr_pool_t *p, const char *s,
+ int quotes);
+
+/**
+ * Quote an XML element
+ * @param p The pool to allocate out of
+ * @param elem The element to quote
+ */
+APU_DECLARE(void) apr_xml_quote_elem(apr_pool_t *p, apr_xml_elem *elem);
+
+/* manage an array of unique URIs: apr_xml_insert_uri() and APR_XML_URI_ITEM() */
+
+/**
+ * return the URI's (existing) index, or insert it and return a new index
+ * @param uri_array array to insert into
+ * @param uri The uri to insert
+ * @return int The uri's index
+ */
+APU_DECLARE(int) apr_xml_insert_uri(apr_array_header_t *uri_array,
+ const char *uri);
+
+/** Get the URI item for this XML element */
+#define APR_XML_GET_URI_ITEM(ary, i) (((const char * const *)(ary)->elts)[i])
+
+#if APR_CHARSET_EBCDIC
+/**
+ * Convert parsed tree in EBCDIC
+ * @param p The pool to allocate out of
+ * @param pdoc The apr_xml_doc to convert.
+ * @param xlate The translation handle to use.
+ * @return Any errors found during conversion.
+ */
+APU_DECLARE(apr_status_t) apr_xml_parser_convert_doc(apr_pool_t *p,
+ apr_xml_doc *pdoc,
+ apr_xlate_t *convset);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+/** @} */
+#endif /* APR_XML_H */
--- /dev/null
+/* Copyright 2000-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * apu.h is generated from apu.h.in by configure -- do not edit apu.h
+ */
+/* @file apu.h
+ * @brief APR-Utility main file
+ */
+/**
+ * @defgroup APR_Util APR Utility Functions
+ * @{
+ */
+
+
+#ifndef APU_H
+#define APU_H
+
+/**
+ * APU_DECLARE_EXPORT is defined when building the APR-UTIL dynamic library,
+ * so that all public symbols are exported.
+ *
+ * APU_DECLARE_STATIC is defined when including the APR-UTIL public headers,
+ * to provide static linkage when the dynamic library may be unavailable.
+ *
+ * APU_DECLARE_STATIC and APU_DECLARE_EXPORT are left undefined when
+ * including the APR-UTIL public headers, to import and link the symbols from
+ * the dynamic APR-UTIL library and assure appropriate indirection and calling
+ * conventions at compile time.
+ */
+
+/**
+ * The public APR-UTIL functions are declared with APU_DECLARE(), so they may
+ * use the most appropriate calling convention. Public APR functions with
+ * variable arguments must use APU_DECLARE_NONSTD().
+ *
+ * @deffunc APU_DECLARE(rettype) apr_func(args);
+ */
+#define APU_DECLARE(type) type
+/**
+ * The public APR-UTIL functions using variable arguments are declared with
+ * APU_DECLARE_NONSTD(), as they must use the C language calling convention.
+ *
+ * @deffunc APU_DECLARE_NONSTD(rettype) apr_func(args, ...);
+ */
+#define APU_DECLARE_NONSTD(type) type
+/**
+ * The public APR-UTIL variables are declared with APU_DECLARE_DATA.
+ * This assures the appropriate indirection is invoked at compile time.
+ *
+ * @deffunc APU_DECLARE_DATA type apr_variable;
+ * @tip APU_DECLARE_DATA extern type apr_variable; syntax is required for
+ * declarations within headers to properly import the variable.
+ */
+#define APU_DECLARE_DATA
+/*
+ * we always have SDBM (it's in our codebase)
+ */
+#define APU_HAVE_SDBM @apu_have_sdbm@
+#define APU_HAVE_GDBM @apu_have_gdbm@
+#define APU_HAVE_NDBM @apu_have_ndbm@
+#define APU_HAVE_DB @apu_have_db@
+
+#if APU_HAVE_DB
+#define APU_HAVE_DB_VERSION @apu_db_version@
+#endif /* APU_HAVE_DB */
+
+#define APU_HAVE_PGSQL @apu_have_pgsql@
+#define APU_HAVE_MYSQL @apu_have_mysql@
+#define APU_HAVE_SQLITE3 @apu_have_sqlite3@
+#define APU_HAVE_SQLITE2 @apu_have_sqlite2@
+
+#define APU_HAVE_APR_ICONV @have_apr_iconv@
+#define APU_HAVE_ICONV @have_iconv@
+#define APR_HAS_XLATE (APU_HAVE_APR_ICONV || APU_HAVE_ICONV)
+
+#endif /* APU_H */
+/** @} */
--- /dev/null
+/* Copyright 2000-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Note: This is a NetWare specific version of apu.h. It is renamed to
+ * apu.h at the start of a NetWare build.
+ */
+/* @file apu.h
+ * @brief APR-Utility main file
+ */
+/**
+ * @defgroup APR_Util APR Utility Functions
+ * @{
+ */
+
+
+#ifndef APU_H
+#define APU_H
+
+/**
+ * APU_DECLARE_EXPORT is defined when building the APR-UTIL dynamic library,
+ * so that all public symbols are exported.
+ *
+ * APU_DECLARE_STATIC is defined when including the APR-UTIL public headers,
+ * to provide static linkage when the dynamic library may be unavailable.
+ *
+ * APU_DECLARE_STATIC and APU_DECLARE_EXPORT are left undefined when
+ * including the APR-UTIL public headers, to import and link the symbols from
+ * the dynamic APR-UTIL library and assure appropriate indirection and calling
+ * conventions at compile time.
+ */
+
+/**
+ * The public APR-UTIL functions are declared with APU_DECLARE(), so they may
+ * use the most appropriate calling convention. Public APR functions with
+ * variable arguments must use APU_DECLARE_NONSTD().
+ *
+ * @deffunc APU_DECLARE(rettype) apr_func(args);
+ */
+#define APU_DECLARE(type) type
+/**
+ * The public APR-UTIL functions using variable arguments are declared with
+ * APU_DECLARE_NONSTD(), as they must use the C language calling convention.
+ *
+ * @deffunc APU_DECLARE_NONSTD(rettype) apr_func(args, ...);
+ */
+#define APU_DECLARE_NONSTD(type) type
+/**
+ * The public APR-UTIL variables are declared with APU_DECLARE_DATA.
+ * This assures the appropriate indirection is invoked at compile time.
+ *
+ * @deffunc APU_DECLARE_DATA type apr_variable;
+ * @tip APU_DECLARE_DATA extern type apr_variable; syntax is required for
+ * declarations within headers to properly import the variable.
+ */
+#define APU_DECLARE_DATA
+/*
+ * we always have SDBM (it's in our codebase)
+ */
+#define APU_HAVE_SDBM 1
+#define APU_HAVE_GDBM 0
+#define APU_HAVE_DB 0
+
+
+#define HAVE_ICONV_H 1
+#define APU_HAVE_APR_ICONV 0
+#define APU_HAVE_ICONV 1
+#define APR_HAS_XLATE (APU_HAVE_APR_ICONV || APU_HAVE_ICONV)
+
+#endif /* APU_H */
+/** @} */
--- /dev/null
+/* Copyright 2000-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Note: This is a Windows specific version of apu.h. It is renamed to
+ * apu.h at the start of a Windows build.
+ */
+/* @file apu.h
+ * @brief APR-Utility main file
+ */
+
+#ifdef WIN32
+#ifndef APU_H
+#define APU_H
+/**
+ * @defgroup APR_Util APR Utility Functions
+ * @{
+ */
+
+
+/**
+ * APU_DECLARE_EXPORT is defined when building the APR-UTIL dynamic library,
+ * so that all public symbols are exported.
+ *
+ * APU_DECLARE_STATIC is defined when including the APR-UTIL public headers,
+ * to provide static linkage when the dynamic library may be unavailable.
+ *
+ * APU_DECLARE_STATIC and APU_DECLARE_EXPORT are left undefined when
+ * including the APR-UTIL public headers, to import and link the symbols from
+ * the dynamic APR-UTIL library and assure appropriate indirection and calling
+ * conventions at compile time.
+ */
+
+#if defined(DOXYGEN) || !defined(WIN32)
+/**
+ * The public APR-UTIL functions are declared with APU_DECLARE(), so they may
+ * use the most appropriate calling convention. Public APR functions with
+ * variable arguments must use APU_DECLARE_NONSTD().
+ *
+ * @deffunc APU_DECLARE(rettype) apr_func(args);
+ */
+#define APU_DECLARE(type) type
+/**
+ * The public APR-UTIL functions using variable arguments are declared with
+ * APU_DECLARE_NONSTD(), as they must use the C language calling convention.
+ *
+ * @deffunc APU_DECLARE_NONSTD(rettype) apr_func(args, ...);
+ */
+#define APU_DECLARE_NONSTD(type) type
+/**
+ * The public APR-UTIL variables are declared with APU_DECLARE_DATA.
+ * This assures the appropriate indirection is invoked at compile time.
+ *
+ * @deffunc APU_DECLARE_DATA type apr_variable;
+ * @tip extern APU_DECLARE_DATA type apr_variable; syntax is required for
+ * declarations within headers to properly import the variable.
+ */
+#define APU_DECLARE_DATA
+#elif defined(APU_DECLARE_STATIC)
+#define APU_DECLARE(type) type __stdcall
+#define APU_DECLARE_NONSTD(type) type __cdecl
+#define APU_DECLARE_DATA
+#elif defined(APU_DECLARE_EXPORT)
+#define APU_DECLARE(type) __declspec(dllexport) type __stdcall
+#define APU_DECLARE_NONSTD(type) __declspec(dllexport) type __cdecl
+#define APU_DECLARE_DATA __declspec(dllexport)
+#else
+#define APU_DECLARE(type) __declspec(dllimport) type __stdcall
+#define APU_DECLARE_NONSTD(type) __declspec(dllimport) type __cdecl
+#define APU_DECLARE_DATA __declspec(dllimport)
+#endif
+/** @} */
+/*
+ * we always have SDBM (it's in our codebase)
+ */
+#define APU_HAVE_SDBM 1
+#define APU_HAVE_GDBM 0
+
+/* Allow external override */
+#if !defined(APU_HAVE_DB)
+#define APU_HAVE_DB 0
+#endif
+
+
+#define APU_HAVE_APR_ICONV 1
+#define APU_HAVE_ICONV 0
+#define APR_HAS_XLATE (APU_HAVE_APR_ICONV || APU_HAVE_ICONV)
+
+#endif /* APU_H */
+#endif /* WIN32 */
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APU_VERSION_H
+#define APU_VERSION_H
+
+/**
+ * @file apu_version.h
+ * @brief APR-util Versioning Interface
+ *
+ * APR-util's Version
+ *
+ * There are several different mechanisms for accessing the version. There
+ * is a string form, and a set of numbers; in addition, there are constants
+ * which can be compiled into your application, and you can query the library
+ * being used for its actual version.
+ *
+ * Note that it is possible for an application to detect that it has been
+ * compiled against a different version of APU by use of the compile-time
+ * constants and the use of the run-time query function.
+ *
+ * APU version numbering follows the guidelines specified in:
+ *
+ * http://apr.apache.org/versioning.html
+ */
+
+
+/* The numeric compile-time version constants. These constants are the
+ * authoritative version numbers for APU.
+ */
+
+/** major version
+ * Major API changes that could cause compatibility problems for older
+ * programs such as structure size changes. No binary compatibility is
+ * possible across a change in the major version.
+ */
+#define APU_MAJOR_VERSION 1
+
+/** minor version
+ * Minor API changes that do not cause binary compatibility problems.
+ * Reset to 0 when upgrading APU_MAJOR_VERSION
+ */
+#define APU_MINOR_VERSION 2
+
+/** patch level
+ * The Patch Level never includes API changes, simply bug fixes.
+ * Reset to 0 when upgrading APR_MINOR_VERSION
+ */
+#define APU_PATCH_VERSION 0
+
+/**
+ * The symbol APU_IS_DEV_VERSION is only defined for internal,
+ * "development" copies of APU. It is undefined for released versions
+ * of APU.
+ */
+#define APU_IS_DEV_VERSION
+
+
+#if defined(APU_IS_DEV_VERSION) || defined(DOXYGEN)
+/** Internal: string form of the "is dev" flag */
+#define APU_IS_DEV_STRING "-dev"
+#else
+#define APU_IS_DEV_STRING ""
+#endif
+
+
+#ifndef APU_STRINGIFY
+/** Properly quote a value as a string in the C preprocessor */
+#define APU_STRINGIFY(n) APU_STRINGIFY_HELPER(n)
+/** Helper macro for APU_STRINGIFY */
+#define APU_STRINGIFY_HELPER(n) #n
+#endif
+
+/** The formatted string of APU's version */
+#define APU_VERSION_STRING \
+ APU_STRINGIFY(APU_MAJOR_VERSION) "." \
+ APU_STRINGIFY(APU_MINOR_VERSION) "." \
+ APU_STRINGIFY(APU_PATCH_VERSION) \
+ APU_IS_DEV_STRING
+
+/** An alternative formatted string of APR's version */
+/* macro for Win32 .rc files using numeric csv representation */
+#define APU_VERSION_STRING_CSV APU_MAJOR_VERSION ##, \
+ ##APU_MINOR_VERSION ##, \
+ ##APU_PATCH_VERSION
+
+
+#ifndef APU_VERSION_ONLY
+
+/* The C language API to access the version at run time,
+ * as opposed to compile time. APU_VERSION_ONLY may be defined
+ * externally when preprocessing apr_version.h to obtain strictly
+ * the C Preprocessor macro declarations.
+ */
+
+#include "apr_version.h"
+
+#include "apu.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Return APR-util's version information information in a numeric form.
+ *
+ * @param pvsn Pointer to a version structure for returning the version
+ * information.
+ */
+APU_DECLARE(void) apu_version(apr_version_t *pvsn);
+
+/** Return APU's version information as a string. */
+APU_DECLARE(const char *) apu_version_string(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ndef APU_VERSION_ONLY */
+
+#endif /* ndef APU_VERSION_H */
--- /dev/null
+/* Copyright 2000-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apu.h" /* configuration data */
+
+/**
+ * @file apu_want.h
+ * @brief APR Standard Headers Support
+ *
+ * <PRE>
+ * Features:
+ *
+ * APU_WANT_DB: <@apu_db_header@>
+ *
+ * Typical usage:
+ *
+ * #define APU_WANT_DB
+ * #include "apu_want.h"
+ *
+ * The appropriate headers will be included.
+ *
+ * Note: it is safe to use this in a header (it won't interfere with other
+ * headers' or source files' use of apu_want.h)
+ * </PRE>
+ */
+
+/* --------------------------------------------------------------------- */
+
+#ifdef APU_WANT_DB
+
+#if APU_HAVE_DB
+#include <@apu_db_header@>
+#endif
+
+#undef APU_WANT_DB
+#endif
+
+/* --------------------------------------------------------------------- */
--- /dev/null
+/* Copyright 2000-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apu.h" /* configuration data */
+
+/**
+ * @file apu_want.h
+ * @brief APR Standard Headers Support
+ *
+ * <PRE>
+ * Features:
+ *
+ * APU_WANT_DB: <@apu_db_header>
+ *
+ * Typical usage:
+ *
+ * #define APU_WANT_DB
+ * #include "apu_want.h"
+ *
+ * The appropriate headers will be included.
+ *
+ * Note: it is safe to use this in a header (it won't interfere with other
+ * headers' or source files' use of apu_want.h)
+ * </PRE>
+ */
+
+/* --------------------------------------------------------------------- */
+
+#ifdef APU_WANT_DB
+
+#if APU_HAVE_DB
+/* win32 note.. you will need to change this for db1 */
+#include <db.h>
+#endif
+
+#undef APU_WANT_DB
+#endif
+
+/* --------------------------------------------------------------------- */
--- /dev/null
+/* Copyright 2000-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apu.h" /* configuration data */
+
+/**
+ * @file apu_want.h
+ * @brief APR Standard Headers Support
+ *
+ * <PRE>
+ * Features:
+ *
+ * APU_WANT_DB: <@apu_db_header>
+ *
+ * Typical usage:
+ *
+ * #define APU_WANT_DB
+ * #include "apu_want.h"
+ *
+ * The appropriate headers will be included.
+ *
+ * Note: it is safe to use this in a header (it won't interfere with other
+ * headers' or source files' use of apu_want.h)
+ * </PRE>
+ */
+
+/* --------------------------------------------------------------------- */
+
+#ifdef APU_WANT_DB
+
+#if APU_HAVE_DB
+/* win32 note.. you will need to change this for db1 */
+#include <db.h>
+#endif
+
+#undef APU_WANT_DB
+#endif
+
+/* --------------------------------------------------------------------- */
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APR_DBM_PRIVATE_H
+#define APR_DBM_PRIVATE_H
+
+#include "apr.h"
+#include "apr_errno.h"
+#include "apr_pools.h"
+#include "apr_dbm.h"
+#include "apr_file_io.h"
+
+#include "apu.h"
+
+/* ### for now, include the DBM selection; this will go away once we start
+ ### building and linking all of the DBMs at once. */
+#include "apu_select_dbm.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** @internal */
+
+/**
+ * Most DBM libraries take a POSIX mode for creating files. Don't trust
+ * the mode_t type, some platforms may not support it, int is safe.
+ */
+APU_DECLARE(int) apr_posix_perms2mode(apr_fileperms_t perm);
+
+/**
+ * Structure to describe the operations of the DBM
+ */
+typedef struct {
+ /** The name of the DBM Type */
+ const char *name;
+
+ /** Open the DBM */
+ apr_status_t (*open)(apr_dbm_t **pdb, const char *pathname,
+ apr_int32_t mode, apr_fileperms_t perm,
+ apr_pool_t *pool);
+
+ /** Close the DBM */
+ void (*close)(apr_dbm_t *dbm);
+
+ /** Fetch a dbm record value by key */
+ apr_status_t (*fetch)(apr_dbm_t *dbm, apr_datum_t key,
+ apr_datum_t * pvalue);
+
+ /** Store a dbm record value by key */
+ apr_status_t (*store)(apr_dbm_t *dbm, apr_datum_t key, apr_datum_t value);
+
+ /** Delete a dbm record value by key */
+ apr_status_t (*del)(apr_dbm_t *dbm, apr_datum_t key);
+
+ /** Search for a key within the dbm */
+ int (*exists)(apr_dbm_t *dbm, apr_datum_t key);
+
+ /** Retrieve the first record key from a dbm */
+ apr_status_t (*firstkey)(apr_dbm_t *dbm, apr_datum_t * pkey);
+
+ /** Retrieve the next record key from a dbm */
+ apr_status_t (*nextkey)(apr_dbm_t *dbm, apr_datum_t * pkey);
+
+ /** Proactively toss any memory associated with the apr_datum_t. */
+ void (*freedatum)(apr_dbm_t *dbm, apr_datum_t data);
+
+ /** Get the names that the DBM will use for a given pathname. */
+ void (*getusednames)(apr_pool_t *pool,
+ const char *pathname,
+ const char **used1,
+ const char **used2);
+
+} apr_dbm_type_t;
+
+
+/**
+ * The actual DBM
+ */
+struct apr_dbm_t
+{
+ /** Associated pool */
+ apr_pool_t *pool;
+
+ /** pointer to DB Implementation Specific data */
+ void *file;
+
+ /** Current integer error code */
+ int errcode;
+ /** Current string error code */
+ const char *errmsg;
+
+ /** the type of DBM */
+ const apr_dbm_type_t *type;
+};
+
+
+/* Declare all of the builtin DBM providers */
+APU_DECLARE_DATA extern const apr_dbm_type_t apr_dbm_type_sdbm;
+APU_DECLARE_DATA extern const apr_dbm_type_t apr_dbm_type_gdbm;
+APU_DECLARE_DATA extern const apr_dbm_type_t apr_dbm_type_ndbm;
+APU_DECLARE_DATA extern const apr_dbm_type_t apr_dbm_type_db1;
+APU_DECLARE_DATA extern const apr_dbm_type_t apr_dbm_type_db2;
+APU_DECLARE_DATA extern const apr_dbm_type_t apr_dbm_type_db3;
+APU_DECLARE_DATA extern const apr_dbm_type_t apr_dbm_type_db4;
+APU_DECLARE_DATA extern const apr_dbm_type_t apr_dbm_type_db;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* APR_DBM_PRIVATE_H */
--- /dev/null
+/* Copyright 2000-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Note: This is a Windows specific version of apu_config.hw. It is copied
+ * as apu_config.h at the start of a Windows build.
+ */
+
+#ifdef WIN32
+
+#ifndef APU_CONFIG_H
+#define APU_CONFIG_H
+
+/*
+ * Windows does not have GDBM, and we always use the bundled (new) Expat
+ */
+
+/* Define if you have the gdbm library (-lgdbm). */
+/* #undef HAVE_LIBGDBM */
+
+/* define if Expat 1.0 or 1.1 was found */
+/* #undef APR_HAVE_OLD_EXPAT */
+
+
+#endif /* APU_CONFIG_H */
+#endif /* WIN32 */
--- /dev/null
+/* Copyright 2000-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APU_SELECT_DBM_H
+#define APU_SELECT_DBM_H
+
+/*
+** The following macros control what features APRUTIL will use
+*/
+#define APU_USE_SDBM @apu_use_sdbm@
+#define APU_USE_NDBM @apu_use_ndbm@
+#define APU_USE_GDBM @apu_use_gdbm@
+#define APU_USE_DB @apu_use_db@
+
+#endif /* !APU_SELECT_DBM_H */
--- /dev/null
+/* Copyright 2000-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APU_SELECT_DBM_H
+#define APU_SELECT_DBM_H
+
+/*
+** The following macros control what features APRUTIL will use
+*/
+#define APU_USE_SDBM 1
+#define APU_USE_GDBM 0
+#define APU_USE_NDBM 0
+#define APU_USE_DB 0
+
+#if APU_USE_DB
+#include <db.h>
+#endif
+
+#endif /* !APU_SELECT_DBM_H */
--- /dev/null
+#
+# Declare the sub-directories to be built here
+#
+
+SUBDIRS = \
+ $(EOLIST)
+
+#
+# Get the 'head' of the build environment. This includes default targets and
+# paths to tools
+#
+
+include $(APR_WORK)\build\NWGNUhead.inc
+
+#
+# build this level's files
+
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(APR)/include \
+ $(APR)/include/arch/NetWare \
+ $(APRUTIL)/include \
+ $(LDAPSDK)/inc \
+ $(EOLIST)
+
+#
+# These flags will come after CFLAGS
+#
+XCFLAGS += \
+ $(EOLIST)
+
+#
+# These defines will come after DEFINES
+#
+XDEFINES += \
+ $(EOLIST)
+
+#
+#LDAP client requires the use of Winsock
+#
+ifdef USE_STDSOCKETS
+XDEFINES += -DUSE_WINSOCK \
+ $(EOLIST)
+endif
+
+#
+# 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 =
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION =
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME =
+#
+# If this is specified, it will override VERSION value in
+# $(APR_WORK)\build\NWGNUenvironment.inc
+#
+NLM_VERSION =
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE =
+
+#
+# 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 this is 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 $(APR)/misc/netware/apache.xdc. XDCData can
+# be disabled by setting APACHE_UNIPROC in the environment
+#
+XDCDATA =
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+ $(OBJDIR)/apuldap.lib \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+ $(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 = \
+ $(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 = \
+ $(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 the default copyright.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+ $(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+ $(OBJDIR)/apr_ldap_init.o \
+ $(OBJDIR)/apr_ldap_option.o \
+ $(OBJDIR)/apr_ldap_url.o \
+ $(EOLIST)
+
+#
+# implement targets and dependancies (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 $(APR_WORK)\build\NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(APR_WORK)\build\NWGNUtail.inc
+
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * apr_ldap_init.c: LDAP v2/v3 common initialise
+ *
+ * Original code from auth_ldap module for Apache v1.3:
+ * Copyright 1998, 1999 Enbridge Pipelines Inc.
+ * Copyright 1999-2001 Dave Carrigan
+ */
+
+#include "apr.h"
+#include "apu.h"
+#include "apr_ldap.h"
+#include "apr_errno.h"
+#include "apr_pools.h"
+#include "apr_strings.h"
+
+#if APR_HAS_LDAP
+
+/**
+ * APR LDAP SSL Initialise function
+ *
+ * This function initialises SSL on the underlying LDAP toolkit
+ * if this is necessary.
+ *
+ * If a CA certificate is provided, this is set, however the setting
+ * of certificates via this method has been deprecated and will be removed in
+ * APR v2.0.
+ *
+ * The apr_ldap_set_option() function with the APR_LDAP_OPT_TLS_CERT option
+ * should be used instead to set certificates.
+ *
+ * If SSL support is not available on this platform, or a problem
+ * was encountered while trying to set the certificate, the function
+ * will return APR_EGENERAL. Further LDAP specific error information
+ * can be found in result_err.
+ */
+APU_DECLARE(int) apr_ldap_ssl_init(apr_pool_t *pool,
+ const char *cert_auth_file,
+ int cert_file_type,
+ apr_ldap_err_t **result_err) {
+
+ apr_ldap_err_t *result = (apr_ldap_err_t *)apr_pcalloc(pool, sizeof(apr_ldap_err_t));
+ *result_err = result;
+
+#if APR_HAS_LDAP_SSL /* compiled with ssl support */
+
+ /* Novell */
+#if APR_HAS_NOVELL_LDAPSDK
+ ldapssl_client_init(NULL, NULL);
+#endif
+
+ /* if a certificate was specified, set it */
+ if (cert_auth_file) {
+ apr_ldap_opt_tls_cert_t *cert = (apr_ldap_opt_tls_cert_t *)apr_pcalloc(pool, sizeof(apr_ldap_opt_tls_cert_t));
+ cert->type = cert_file_type;
+ cert->path = cert_auth_file;
+ return apr_ldap_set_option(pool, NULL, APR_LDAP_OPT_TLS_CERT, (void *)cert, result_err);
+ }
+
+#else /* not compiled with SSL Support */
+ if (cert_auth_file) {
+ result->reason = "LDAP: Attempt to set certificate store failed. "
+ "Not built with SSL support";
+ result->rc = -1;
+ }
+#endif /* APR_HAS_LDAP_SSL */
+
+ if (result->rc != -1) {
+ result->msg = ldap_err2string(result->rc);
+ }
+
+ if (LDAP_SUCCESS != result->rc) {
+ return APR_EGENERAL;
+ }
+
+ return APR_SUCCESS;
+
+}
+
+
+/**
+ * APR LDAP SSL De-Initialise function
+ *
+ * This function tears down any SSL certificate setup previously
+ * set using apr_ldap_ssl_init(). It should be called to clean
+ * up if a graceful restart of a service is attempted.
+ *
+ * This function only does anything on Netware.
+ *
+ * @todo currently we do not check whether apr_ldap_ssl_init()
+ * has been called first - should we?
+ */
+APU_DECLARE(int) apr_ldap_ssl_deinit(void) {
+
+#if APR_HAS_LDAP_SSL && APR_HAS_LDAPSSL_CLIENT_DEINIT
+ ldapssl_client_deinit();
+#endif
+ return APR_SUCCESS;
+
+}
+
+
+/**
+ * APR LDAP initialise function
+ *
+ * This function is responsible for initialising an LDAP
+ * connection in a toolkit independant way. It does the
+ * job of ldap_init() from the C api.
+ *
+ * It handles both the SSL and non-SSL case, and attempts
+ * to hide the complexity setup from the user. This function
+ * assumes that any certificate setup necessary has already
+ * been done.
+ *
+ * If SSL or STARTTLS needs to be enabled, and the underlying
+ * toolkit supports it, the following values are accepted for
+ * secure:
+ *
+ * APR_LDAP_NONE: No encryption
+ * APR_LDAP_SSL: SSL encryption (ldaps://)
+ * APR_LDAP_STARTTLS: Force STARTTLS on ldap://
+ */
+APU_DECLARE(int) apr_ldap_init(apr_pool_t *pool,
+ LDAP **ldap,
+ const char *hostname,
+ int portno,
+ int secure,
+ apr_ldap_err_t **result_err) {
+
+ apr_ldap_err_t *result = (apr_ldap_err_t *)apr_pcalloc(pool, sizeof(apr_ldap_err_t));
+ *result_err = result;
+
+#if APR_HAS_NOVELL_LDAPSDK
+ *ldap = ldapssl_init(hostname, portno, 0);
+#else
+ *ldap = ldap_init((char *)hostname, portno);
+#endif
+ if (*ldap != NULL) {
+ return apr_ldap_set_option(pool, *ldap, APR_LDAP_OPT_TLS, &secure, result_err);
+ }
+ else {
+ /* handle the error case */
+ apr_ldap_err_t *result = (apr_ldap_err_t *)apr_pcalloc(pool, sizeof(apr_ldap_err_t));
+ *result_err = result;
+
+ result->reason = "APR LDAP: Unable to initialize the LDAP connection";
+ result->rc = -1;
+ return APR_EGENERAL;
+ }
+
+}
+
+
+/**
+ * APR LDAP info function
+ *
+ * This function returns a string describing the LDAP toolkit
+ * currently in use. The string is placed inside result_err->reason.
+ */
+APU_DECLARE(int) apr_ldap_info(apr_pool_t *pool, apr_ldap_err_t **result_err)
+{
+ apr_ldap_err_t *result = (apr_ldap_err_t *)apr_pcalloc(pool, sizeof(apr_ldap_err_t));
+ *result_err = result;
+
+ result->reason = "APR LDAP: Built with "
+ LDAP_VENDOR_NAME
+ " LDAP SDK";
+ return APR_SUCCESS;
+
+}
+
+#endif /* APR_HAS_LDAP */
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* apr_ldap_option.c -- LDAP options
+ *
+ * The LDAP SDK allows the getting and setting of options on an LDAP
+ * connection.
+ *
+ */
+
+#include "apr.h"
+#include "apu.h"
+#include "apr_ldap.h"
+#include "apr_errno.h"
+#include "apr_pools.h"
+#include "apr_strings.h"
+#include "apr_tables.h"
+
+#if APR_HAS_LDAP
+
+static void option_set_cert(apr_pool_t *pool, LDAP *ldap, const void *invalue,
+ apr_ldap_err_t *result);
+static void option_set_tls(apr_pool_t *pool, LDAP *ldap, const void *invalue,
+ apr_ldap_err_t *result);
+
+/**
+ * APR LDAP get option function
+ *
+ * This function gets option values from a given LDAP session if
+ * one was specified.
+ */
+APU_DECLARE(int) apr_ldap_get_option(apr_pool_t *pool,
+ LDAP *ldap,
+ int option,
+ void *outvalue,
+ apr_ldap_err_t **result_err)
+{
+ apr_ldap_err_t *result;
+
+ result = apr_pcalloc(pool, sizeof(apr_ldap_err_t));
+ *result_err = result;
+ if (!result) {
+ return APR_ENOMEM;
+ }
+
+ /* get the option specified using the native LDAP function */
+ result->rc = ldap_get_option(ldap, option, outvalue);
+
+ /* handle the error case */
+ if (result->rc != LDAP_SUCCESS) {
+ result->msg = ldap_err2string(result-> rc);
+ result->reason = apr_pstrdup(pool, "LDAP: Could not get an option");
+ return APR_EGENERAL;
+ }
+
+ return APR_SUCCESS;
+
+}
+
+/**
+ * APR LDAP set option function
+ *
+ * This function sets option values to a given LDAP session if
+ * one was specified.
+ *
+ * Where an option is not supported by an LDAP toolkit, this function
+ * will try and apply legacy functions to achieve the same effect,
+ * depending on the platform.
+ */
+APU_DECLARE(int) apr_ldap_set_option(apr_pool_t *pool,
+ LDAP *ldap,
+ int option,
+ const void *invalue,
+ apr_ldap_err_t **result_err)
+{
+ apr_ldap_err_t *result;
+
+ result = apr_pcalloc(pool, sizeof(apr_ldap_err_t));
+ *result_err = result;
+ if (!result) {
+ return APR_ENOMEM;
+ }
+
+ switch (option) {
+ case APR_LDAP_OPT_TLS_CERT:
+ option_set_cert(pool, ldap, invalue, result);
+ break;
+
+ case APR_LDAP_OPT_TLS:
+ option_set_tls(pool, ldap, invalue, result);
+ break;
+
+ case APR_LDAP_OPT_VERIFY_CERT:
+#if APR_HAS_NETSCAPE_LDAPSDK || APR_HAS_SOLARIS_LDAPSDK || APR_HAS_MOZILLA_LDAPSK
+ result->reason = "LDAP: Verify certificate not yet supported by APR on the "
+ "Netscape, Solaris or Mozilla LDAP SDKs";
+ result->rc = -1;
+ return APR_EGENERAL;
+#endif
+#if APR_HAS_NOVELL_LDAPSDK
+ if (*((int*)invalue)) {
+ result->rc = ldapssl_set_verify_mode(LDAPSSL_VERIFY_SERVER);
+ }
+ else {
+ result->rc = ldapssl_set_verify_mode(LDAPSSL_VERIFY_NONE);
+ }
+#endif
+#if APR_HAS_OPENLDAP_LDAPSDK
+#ifdef LDAP_OPT_X_TLS
+ /* This is not a per-connection setting so just pass NULL for the
+ Ldap connection handle */
+ if (*((int*)invalue)) {
+ int i = LDAP_OPT_X_TLS_DEMAND;
+ result->rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &i);
+ }
+ else {
+ int i = LDAP_OPT_X_TLS_NEVER;
+ result->rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &i);
+ }
+#else
+ result->reason = "LDAP: SSL/TLS not yet supported by APR on this "
+ "version of the OpenLDAP toolkit";
+ result->rc = -1;
+ return APR_EGENERAL;
+#endif
+#endif
+
+ /* handle the error case */
+ if (result->rc != LDAP_SUCCESS) {
+ result->msg = ldap_err2string(result->rc);
+ result->reason = "LDAP: Could not set verify mode";
+ }
+ break;
+
+ default:
+ /* set the option specified using the native LDAP function */
+ result->rc = ldap_set_option(ldap, option, (void *)invalue);
+
+ /* handle the error case */
+ if (result->rc != LDAP_SUCCESS) {
+ result->msg = ldap_err2string(result->rc);
+ result->reason = "LDAP: Could not set an option";
+ }
+ break;
+ }
+
+ /* handle the error case */
+ if (result->rc != LDAP_SUCCESS) {
+ return APR_EGENERAL;
+ }
+
+ return APR_SUCCESS;
+
+}
+
+/**
+ * Handle APR_LDAP_OPT_TLS
+ *
+ * This function sets the type of TLS to be applied to this connection.
+ * The options are:
+ * APR_LDAP_NONE: no encryption
+ * APR_LDAP_SSL: SSL encryption (ldaps://)
+ * APR_LDAP_STARTTLS: STARTTLS encryption
+ * APR_LDAP_STOPTLS: Stop existing TLS connecttion
+ */
+static void option_set_tls(apr_pool_t *pool, LDAP *ldap, const void *invalue,
+ apr_ldap_err_t *result)
+{
+ int tls = * (const int *)invalue;
+
+#if APR_HAS_LDAP_SSL /* compiled with ssl support */
+
+ /* Netscape/Mozilla/Solaris SDK */
+#if APR_HAS_NETSCAPE_LDAPSDK || APR_HAS_SOLARIS_LDAPSDK || APR_HAS_MOZILLA_LDAPSK
+#if APR_HAS_LDAPSSL_INSTALL_ROUTINES
+ if (tls == APR_LDAP_SSL) {
+ result->rc = ldapssl_install_routines(ldap);
+#ifdef LDAP_OPT_SSL
+ /* apparently Netscape and Mozilla need this too, Solaris doesn't */
+ if (result->rc == LDAP_SUCCESS) {
+ result->rc = ldap_set_option(ldap, LDAP_OPT_SSL, LDAP_OPT_ON);
+ }
+#endif
+ if (result->rc != LDAP_SUCCESS) {
+ result->msg = ldap_err2string(result->rc);
+ result->reason = "LDAP: Could not switch SSL on for this "
+ "connection.";
+ }
+ }
+ else if (tls == APR_LDAP_STARTTLS) {
+ result->reason = "LDAP: STARTTLS is not supported by the "
+ "Netscape/Mozilla/Solaris SDK";
+ result->rc = -1;
+ }
+ else if (tls == APR_LDAP_STOPTLS) {
+ result->reason = "LDAP: STOPTLS is not supported by the "
+ "Netscape/Mozilla/Solaris SDK";
+ result->rc = -1;
+ }
+#else
+ if (tls != APR_LDAP_NONE) {
+ result->reason = "LDAP: SSL/TLS is not supported by this version "
+ "of the Netscape/Mozilla/Solaris SDK";
+ result->rc = -1;
+ }
+#endif
+#endif
+
+ /* Novell SDK */
+#if APR_HAS_NOVELL_LDAPSDK
+ /* ldapssl_install_routines(ldap)
+ * Behavior is unpredictable when other LDAP functions are called
+ * between the ldap_init function and the ldapssl_install_routines
+ * function.
+ *
+ * STARTTLS is supported by the ldap_start_tls_s() method
+ */
+ if (tls == APR_LDAP_SSL) {
+ result->rc = ldapssl_install_routines(ldap);
+ if (result->rc != LDAP_SUCCESS) {
+ result->msg = ldap_err2string(result->rc);
+ result->reason = "LDAP: Could not switch SSL on for this "
+ "connection.";
+ }
+ }
+ if (tls == APR_LDAP_STARTTLS) {
+ result->rc = ldapssl_start_tls(ldap);
+ if (result->rc != LDAP_SUCCESS) {
+ result->msg = ldap_err2string(result->rc);
+ result->reason = "LDAP: Could not start TLS on this connection";
+ }
+ }
+ else if (tls == APR_LDAP_STOPTLS) {
+ result->rc = ldapssl_stop_tls(ldap);
+ if (result->rc != LDAP_SUCCESS) {
+ result->msg = ldap_err2string(result->rc);
+ result->reason = "LDAP: Could not stop TLS on this connection";
+ }
+ }
+#endif
+
+ /* OpenLDAP SDK */
+#if APR_HAS_OPENLDAP_LDAPSDK
+#ifdef LDAP_OPT_X_TLS
+ if (tls == APR_LDAP_SSL) {
+ int SSLmode = LDAP_OPT_X_TLS_HARD;
+ result->rc = ldap_set_option(ldap, LDAP_OPT_X_TLS, &SSLmode);
+ if (result->rc != LDAP_SUCCESS) {
+ result->reason = "LDAP: ldap_set_option failed. "
+ "Could not set LDAP_OPT_X_TLS to "
+ "LDAP_OPT_X_TLS_HARD";
+ result->msg = ldap_err2string(result->rc);
+ }
+ }
+ else if (tls == APR_LDAP_STARTTLS) {
+ result->rc = ldap_start_tls_s(ldap, NULL, NULL);
+ if (result->rc != LDAP_SUCCESS) {
+ result->reason = "LDAP: ldap_start_tls_s() failed";
+ result->msg = ldap_err2string(result->rc);
+ }
+ }
+ else if (tls == APR_LDAP_STOPTLS) {
+ result->reason = "LDAP: STOPTLS is not supported by the "
+ "OpenLDAP SDK";
+ result->rc = -1;
+ }
+#else
+ if (tls != APR_LDAP_NONE) {
+ result->reason = "LDAP: SSL/TLS not yet supported by APR on this "
+ "version of the OpenLDAP toolkit";
+ result->rc = -1;
+ }
+#endif
+#endif
+
+ /* Microsoft SDK */
+#if APR_HAS_MICROSOFT_LDAPSDK
+ if (tls == APR_LDAP_NONE) {
+ result->rc = ldap_set_option(ldap, LDAP_OPT_SSL, LDAP_OPT_OFF);
+ if (result->rc != LDAP_SUCCESS) {
+ result->reason = "LDAP: an attempt to set LDAP_OPT_SSL off "
+ "failed.";
+ result->msg = ldap_err2string(result->rc);
+ }
+ }
+ else if (tls == APR_LDAP_SSL) {
+ result->rc = ldap_set_option(ldap, LDAP_OPT_SSL, LDAP_OPT_ON);
+ if (result->rc != LDAP_SUCCESS) {
+ result->reason = "LDAP: an attempt to set LDAP_OPT_SSL on "
+ "failed.";
+ result->msg = ldap_err2string(result->rc);
+ }
+ }
+ else if (tls == APR_LDAP_STARTTLS) {
+ result->rc = ldap_start_tls_s(ldap, NULL, NULL, NULL, NULL);
+ if (result->rc != LDAP_SUCCESS) {
+ result->reason = "LDAP: ldap_start_tls_s() failed";
+ result->msg = ldap_err2string(result->rc);
+ }
+ }
+ else if (tls == APR_LDAP_STOPTLS) {
+ result->rc = ldap_stop_tls_s(ldap);
+ if (result->rc != LDAP_SUCCESS) {
+ result->reason = "LDAP: ldap_stop_tls_s() failed";
+ result->msg = ldap_err2string(result->rc);
+ }
+ }
+#endif
+
+#if APR_HAS_OTHER_LDAPSDK
+ if (tls != APR_LDAP_NONE) {
+ result->reason = "LDAP: SSL/TLS is currently not supported by "
+ "APR on this LDAP SDK";
+ result->rc = -1;
+ }
+#endif
+
+#endif /* APR_HAS_LDAP_SSL */
+
+}
+
+/**
+ * Handle APR_LDAP_OPT_TLS_CACERTFILE
+ *
+ * This function sets the CA certificate for further SSL/TLS connections.
+ *
+ * The file provided are in different formats depending on the toolkit used:
+ *
+ * Netscape: cert7.db file
+ * Novell: PEM or DER
+ * OpenLDAP: PEM (others supported?)
+ * Microsoft: unknown
+ * Solaris: unknown
+ */
+static void option_set_cert(apr_pool_t *pool, LDAP *ldap,
+ const void *invalue, apr_ldap_err_t *result)
+{
+ apr_array_header_t *certs = (apr_array_header_t *)invalue;
+ struct apr_ldap_opt_tls_cert_t *ents = (struct apr_ldap_opt_tls_cert_t *)certs->elts;
+ int i = 0;
+
+#if APR_HAS_LDAP_SSL
+
+ /* Netscape/Mozilla/Solaris SDK */
+#if APR_HAS_NETSCAPE_LDAPSDK || APR_HAS_SOLARIS_LDAPSDK || APR_HAS_MOZILLA_LDAPSDK
+#if APR_HAS_LDAPSSL_CLIENT_INIT
+ const char *nickname = NULL;
+ const char *secmod = NULL;
+ const char *key3db = NULL;
+ const char *cert7db = NULL;
+ const char *password = NULL;
+
+ /* set up cert7.db, key3.db and secmod parameters */
+ for (i = 0; i < certs->nelts; i++) {
+ switch (ents[i].type) {
+ case APR_LDAP_CA_TYPE_CERT7_DB:
+ cert7db = ents[i].path;
+ break;
+ case APR_LDAP_CA_TYPE_SECMOD:
+ secmod = ents[i].path;
+ break;
+ case APR_LDAP_CERT_TYPE_KEY3_DB:
+ key3db = ents[i].path;
+ break;
+ case APR_LDAP_CERT_TYPE_NICKNAME:
+ nickname = ents[i].path;
+ password = ents[i].password;
+ break;
+ default:
+ result->rc = -1;
+ result->reason = "LDAP: The Netscape/Mozilla LDAP SDK only "
+ "understands the CERT7, KEY3 and SECMOD "
+ "file types.";
+ break;
+ }
+ if (result->rc != LDAP_SUCCESS) {
+ break;
+ }
+ }
+
+ /* actually set the certificate parameters */
+ if (result->rc == LDAP_SUCCESS) {
+ if (nickname) {
+ result->rc = ldapssl_enable_clientauth(ldap, "",
+ (char *)password,
+ (char *)nickname);
+ if (result->rc != LDAP_SUCCESS) {
+ result->reason = "LDAP: could not set client certificate: "
+ "ldapssl_enable_clientauth() failed.";
+ result->msg = ldap_err2string(result->rc);
+ }
+ }
+ else if (secmod) {
+ result->rc = ldapssl_advclientauth_init(cert7db, NULL,
+ key3db ? 1 : 0, key3db, NULL,
+ 1, secmod, LDAPSSL_AUTH_CNCHECK);
+ if (result->rc != LDAP_SUCCESS) {
+ result->reason = "LDAP: ldapssl_advclientauth_init() failed.";
+ result->msg = ldap_err2string(result->rc);
+ }
+ }
+ else if (key3db) {
+ result->rc = ldapssl_clientauth_init(cert7db, NULL,
+ 1, key3db, NULL);
+ if (result->rc != LDAP_SUCCESS) {
+ result->reason = "LDAP: ldapssl_clientauth_init() failed.";
+ result->msg = ldap_err2string(result->rc);
+ }
+ }
+ else {
+ result->rc = ldapssl_client_init(cert7db, NULL);
+ if (result->rc != LDAP_SUCCESS) {
+ result->reason = "LDAP: ldapssl_client_init() failed.";
+ result->msg = ldap_err2string(result->rc);
+ }
+ }
+ }
+#else
+ result->reason = "LDAP: SSL/TLS ldapssl_client_init() function not "
+ "supported by this Netscape/Mozilla/Solaris SDK. "
+ "Certificate authority file not set";
+ result->rc = -1;
+#endif
+#endif
+
+ /* Novell SDK */
+#if APR_HAS_NOVELL_LDAPSDK
+#if APR_HAS_LDAPSSL_CLIENT_INIT && APR_HAS_LDAPSSL_ADD_TRUSTED_CERT && APR_HAS_LDAPSSL_CLIENT_DEINIT
+ /* The Novell library cannot support per connection certificates. Error
+ * out if the ldap handle is provided.
+ */
+ if (ldap) {
+ result->rc = -1;
+ result->reason = "LDAP: The Novell LDAP SDK cannot support the setting "
+ "of certificates or keys on a per connection basis.";
+ }
+ /* Novell's library needs to be initialised first */
+ else {
+ result->rc = ldapssl_client_init(NULL, NULL);
+ if (result->rc != LDAP_SUCCESS) {
+ result->msg = ldap_err2string(result-> rc);
+ result->reason = apr_pstrdup(pool, "LDAP: Could not "
+ "initialize SSL");
+ }
+ }
+ /* set one or more certificates */
+ for (i = 0; LDAP_SUCCESS == result->rc && i < certs->nelts; i++) {
+ /* Novell SDK supports DER or BASE64 files. */
+ switch (ents[i].type) {
+ case APR_LDAP_CA_TYPE_DER:
+ result->rc = ldapssl_add_trusted_cert((void *)ents[i].path,
+ LDAPSSL_CERT_FILETYPE_DER);
+ result->msg = ldap_err2string(result->rc);
+ break;
+ case APR_LDAP_CA_TYPE_BASE64:
+ result->rc = ldapssl_add_trusted_cert((void *)ents[i].path,
+ LDAPSSL_CERT_FILETYPE_B64);
+ result->msg = ldap_err2string(result->rc);
+ break;
+ case APR_LDAP_CERT_TYPE_DER:
+ result->rc = ldapssl_set_client_cert((void *)ents[i].path,
+ LDAPSSL_CERT_FILETYPE_DER,
+ (void*)ents[i].password);
+ result->msg = ldap_err2string(result->rc);
+ break;
+ case APR_LDAP_CERT_TYPE_BASE64:
+ result->rc = ldapssl_set_client_cert((void *)ents[i].path,
+ LDAPSSL_CERT_FILETYPE_B64,
+ (void*)ents[i].password);
+ result->msg = ldap_err2string(result->rc);
+ break;
+ case APR_LDAP_CERT_TYPE_PFX:
+ result->rc = ldapssl_set_client_cert((void *)ents[i].path,
+ LDAPSSL_FILETYPE_P12,
+ (void*)ents[i].password);
+ result->msg = ldap_err2string(result->rc);
+ break;
+ case APR_LDAP_KEY_TYPE_DER:
+ result->rc = ldapssl_set_client_private_key((void *)ents[i].path,
+ LDAPSSL_CERT_FILETYPE_DER,
+ (void*)ents[i].password);
+ result->msg = ldap_err2string(result->rc);
+ break;
+ case APR_LDAP_KEY_TYPE_BASE64:
+ result->rc = ldapssl_set_client_private_key((void *)ents[i].path,
+ LDAPSSL_CERT_FILETYPE_B64,
+ (void*)ents[i].password);
+ result->msg = ldap_err2string(result->rc);
+ break;
+ case APR_LDAP_KEY_TYPE_PFX:
+ result->rc = ldapssl_set_client_private_key((void *)ents[i].path,
+ LDAPSSL_FILETYPE_P12,
+ (void*)ents[i].password);
+ result->msg = ldap_err2string(result->rc);
+ break;
+ default:
+ result->rc = -1;
+ result->reason = "LDAP: The Novell LDAP SDK only understands the "
+ "DER and PEM (BASE64) file types.";
+ break;
+ }
+ if (result->rc != LDAP_SUCCESS) {
+ break;
+ }
+ }
+#else
+ result->reason = "LDAP: ldapssl_client_init(), "
+ "ldapssl_add_trusted_cert() or "
+ "ldapssl_client_deinit() functions not supported "
+ "by this Novell SDK. Certificate authority file "
+ "not set";
+ result->rc = -1;
+#endif
+#endif
+
+ /* OpenLDAP SDK */
+#if APR_HAS_OPENLDAP_LDAPSDK
+#ifdef LDAP_OPT_X_TLS_CACERTFILE
+ /* set one or more certificates */
+ /* FIXME: make it support setting directories as well as files */
+ for (i = 0; i < certs->nelts; i++) {
+ /* OpenLDAP SDK supports BASE64 files. */
+ switch (ents[i].type) {
+ case APR_LDAP_CA_TYPE_BASE64:
+ result->rc = ldap_set_option(ldap, LDAP_OPT_X_TLS_CACERTFILE,
+ (void *)ents[i].path);
+ result->msg = ldap_err2string(result->rc);
+ break;
+ case APR_LDAP_CERT_TYPE_BASE64:
+ result->rc = ldap_set_option(ldap, LDAP_OPT_X_TLS_CERTFILE,
+ (void *)ents[i].path);
+ result->msg = ldap_err2string(result->rc);
+ break;
+ case APR_LDAP_KEY_TYPE_BASE64:
+ result->rc = ldap_set_option(ldap, LDAP_OPT_X_TLS_KEYFILE,
+ (void *)ents[i].path);
+ result->msg = ldap_err2string(result->rc);
+ break;
+ default:
+ result->rc = -1;
+ result->reason = "LDAP: The OpenLDAP SDK only understands the "
+ "PEM (BASE64) file type.";
+ break;
+ }
+ if (result->rc != LDAP_SUCCESS) {
+ break;
+ }
+ }
+#else
+ result->reason = "LDAP: LDAP_OPT_X_TLS_CACERTFILE not "
+ "defined by this OpenLDAP SDK. Certificate "
+ "authority file not set";
+ result->rc = -1;
+#endif
+#endif
+
+ /* Microsoft SDK */
+#if APR_HAS_MICROSOFT_LDAPSDK
+ /* Microsoft SDK use the registry certificate store - error out
+ * here with a message explaining this. */
+ result->reason = "LDAP: CA certificates cannot be set using this method, "
+ "as they are stored in the registry instead.";
+ result->rc = -1;
+#endif
+
+ /* SDK not recognised */
+#if APR_HAS_OTHER_LDAPSDK
+ result->reason = "LDAP: LDAP_OPT_X_TLS_CACERTFILE not "
+ "defined by this LDAP SDK. Certificate "
+ "authority file not set";
+ result->rc = -1;
+#endif
+
+#else /* not compiled with SSL Support */
+ result->reason = "LDAP: Attempt to set certificate(s) failed. "
+ "Not built with SSL support";
+ result->rc = -1;
+#endif /* APR_HAS_LDAP_SSL */
+
+}
+
+#endif /* APR_HAS_LDAP */
+
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Portions Copyright 1998-2002 The OpenLDAP Foundation
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted only as authorized by the OpenLDAP
+ * Public License. A copy of this license is available at
+ * http://www.OpenLDAP.org/license.html or in file LICENSE in the
+ * top-level directory of the distribution.
+ *
+ * OpenLDAP is a registered trademark of the OpenLDAP Foundation.
+ *
+ * Individual files and/or contributed packages may be copyright by
+ * other parties and subject to additional restrictions.
+ *
+ * This work is derived from the University of Michigan LDAP v3.3
+ * distribution. Information concerning this software is available
+ * at: http://www.umich.edu/~dirsvcs/ldap/
+ *
+ * This work also contains materials derived from public sources.
+ *
+ * Additional information about OpenLDAP can be obtained at:
+ * http://www.openldap.org/
+ */
+
+/*
+ * Portions Copyright (c) 1992-1996 Regents of the University of Michigan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of Michigan at Ann Arbor. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+
+/* apr_ldap_url.c -- LDAP URL (RFC 2255) related routines
+ *
+ * Win32 and perhaps other non-OpenLDAP based ldap libraries may be
+ * missing ldap_url_* APIs. We focus here on the one significant
+ * aspect, which is parsing. We have [for the time being] omitted
+ * the ldap_url_search APIs.
+ *
+ * LDAP URLs look like this:
+ * ldap[is]://host:port[/[dn[?[attributes][?[scope][?[filter][?exts]]]]]]
+ *
+ * where:
+ * attributes is a comma separated list
+ * scope is one of these three strings: base one sub (default=base)
+ * filter is an string-represented filter as in RFC 2254
+ *
+ * e.g., ldap://host:port/dc=com?o,cn?base?o=openldap?extension
+ *
+ * Tolerates URLs that look like: <ldapurl> and <URL:ldapurl>
+ */
+
+#include "apu.h"
+#include "apr_pools.h"
+#include "apr_strings.h"
+#include "apr_ldap.h"
+
+#if APR_HAS_LDAP
+
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifndef LDAPS_PORT
+#define LDAPS_PORT 636 /* ldaps:/// default LDAP over TLS port */
+#endif
+
+#define APR_LDAP_URL_PREFIX "ldap://"
+#define APR_LDAP_URL_PREFIX_LEN (sizeof(APR_LDAP_URL_PREFIX)-1)
+#define APR_LDAPS_URL_PREFIX "ldaps://"
+#define APR_LDAPS_URL_PREFIX_LEN (sizeof(APR_LDAPS_URL_PREFIX)-1)
+#define APR_LDAPI_URL_PREFIX "ldapi://"
+#define APR_LDAPI_URL_PREFIX_LEN (sizeof(APR_LDAPI_URL_PREFIX)-1)
+#define APR_LDAP_URL_URLCOLON "URL:"
+#define APR_LDAP_URL_URLCOLON_LEN (sizeof(APR_LDAP_URL_URLCOLON)-1)
+
+
+/* local functions */
+static const char* skip_url_prefix(const char *url,
+ int *enclosedp,
+ const char **scheme);
+
+static void apr_ldap_pvt_hex_unescape(char *s);
+
+static int apr_ldap_pvt_unhex(int c);
+
+static char **apr_ldap_str2charray(apr_pool_t *pool,
+ const char *str,
+ const char *brkstr);
+
+
+/**
+ * Is this URL an ldap url?
+ *
+ */
+APU_DECLARE(int) apr_ldap_is_ldap_url(const char *url)
+{
+ int enclosed;
+ const char * scheme;
+
+ if( url == NULL ) {
+ return 0;
+ }
+
+ if( skip_url_prefix( url, &enclosed, &scheme ) == NULL ) {
+ return 0;
+ }
+
+ return 1;
+}
+
+/**
+ * Is this URL a secure ldap url?
+ *
+ */
+APU_DECLARE(int) apr_ldap_is_ldaps_url(const char *url)
+{
+ int enclosed;
+ const char * scheme;
+
+ if( url == NULL ) {
+ return 0;
+ }
+
+ if( skip_url_prefix( url, &enclosed, &scheme ) == NULL ) {
+ return 0;
+ }
+
+ return strcmp(scheme, "ldaps") == 0;
+}
+
+/**
+ * Is this URL an ldap socket url?
+ *
+ */
+APU_DECLARE(int) apr_ldap_is_ldapi_url(const char *url)
+{
+ int enclosed;
+ const char * scheme;
+
+ if( url == NULL ) {
+ return 0;
+ }
+
+ if( skip_url_prefix( url, &enclosed, &scheme ) == NULL ) {
+ return 0;
+ }
+
+ return strcmp(scheme, "ldapi") == 0;
+}
+
+
+static const char *skip_url_prefix(const char *url, int *enclosedp,
+ const char **scheme)
+{
+ /*
+ * return non-zero if this looks like a LDAP URL; zero if not
+ * if non-zero returned, *urlp will be moved past "ldap://" part of URL
+ */
+ const char *p;
+
+ if ( url == NULL ) {
+ return( NULL );
+ }
+
+ p = url;
+
+ /* skip leading '<' (if any) */
+ if ( *p == '<' ) {
+ *enclosedp = 1;
+ ++p;
+ } else {
+ *enclosedp = 0;
+ }
+
+ /* skip leading "URL:" (if any) */
+ if ( strncasecmp( p, APR_LDAP_URL_URLCOLON, APR_LDAP_URL_URLCOLON_LEN ) == 0 ) {
+ p += APR_LDAP_URL_URLCOLON_LEN;
+ }
+
+ /* check for "ldap://" prefix */
+ if ( strncasecmp( p, APR_LDAP_URL_PREFIX, APR_LDAP_URL_PREFIX_LEN ) == 0 ) {
+ /* skip over "ldap://" prefix and return success */
+ p += APR_LDAP_URL_PREFIX_LEN;
+ *scheme = "ldap";
+ return( p );
+ }
+
+ /* check for "ldaps://" prefix */
+ if ( strncasecmp( p, APR_LDAPS_URL_PREFIX, APR_LDAPS_URL_PREFIX_LEN ) == 0 ) {
+ /* skip over "ldaps://" prefix and return success */
+ p += APR_LDAPS_URL_PREFIX_LEN;
+ *scheme = "ldaps";
+ return( p );
+ }
+
+ /* check for "ldapi://" prefix */
+ if ( strncasecmp( p, APR_LDAPI_URL_PREFIX, APR_LDAPI_URL_PREFIX_LEN ) == 0 ) {
+ /* skip over "ldapi://" prefix and return success */
+ p += APR_LDAPI_URL_PREFIX_LEN;
+ *scheme = "ldapi";
+ return( p );
+ }
+
+ return( NULL );
+}
+
+
+static int str2scope(const char *p)
+{
+ if ( strcasecmp( p, "one" ) == 0 ) {
+ return LDAP_SCOPE_ONELEVEL;
+
+ } else if ( strcasecmp( p, "onetree" ) == 0 ) {
+ return LDAP_SCOPE_ONELEVEL;
+
+ } else if ( strcasecmp( p, "base" ) == 0 ) {
+ return LDAP_SCOPE_BASE;
+
+ } else if ( strcasecmp( p, "sub" ) == 0 ) {
+ return LDAP_SCOPE_SUBTREE;
+
+ } else if ( strcasecmp( p, "subtree" ) == 0 ) {
+ return LDAP_SCOPE_SUBTREE;
+ }
+
+ return( -1 );
+}
+
+
+/**
+ * Parse the URL provided into an apr_ldap_url_desc_t object.
+ *
+ * APR_SUCCESS is returned on success, APR_EGENERAL on failure.
+ * The LDAP result code and reason string is returned in the
+ * apr_ldap_err_t structure.
+ */
+APU_DECLARE(int) apr_ldap_url_parse_ext(apr_pool_t *pool,
+ const char *url_in,
+ apr_ldap_url_desc_t **ludpp,
+ apr_ldap_err_t **result_err)
+{
+ apr_ldap_url_desc_t *ludp;
+ char *p, *q, *r;
+ int i, enclosed;
+ const char *scheme = NULL;
+ const char *url_tmp;
+ char *url;
+
+ apr_ldap_err_t *result = (apr_ldap_err_t *)apr_pcalloc(pool, sizeof(apr_ldap_err_t));
+ *result_err = result;
+
+ /* sanity check our parameters */
+ if( url_in == NULL || ludpp == NULL ) {
+ result->reason = "Either the LDAP URL, or the URL structure was NULL. Oops.";
+ result->rc = APR_LDAP_URL_ERR_PARAM;
+ return APR_EGENERAL;
+ }
+
+ *ludpp = NULL; /* pessimistic */
+
+ url_tmp = skip_url_prefix( url_in, &enclosed, &scheme );
+ if ( url_tmp == NULL ) {
+ result->reason = "The scheme was not recognised as a valid LDAP URL scheme.";
+ result->rc = APR_LDAP_URL_ERR_BADSCHEME;
+ return APR_EGENERAL;
+ }
+
+ /* make working copy of the remainder of the URL */
+ url = (char *)apr_pstrdup(pool, url_tmp);
+ if ( url == NULL ) {
+ result->reason = "Out of memory parsing LDAP URL.";
+ result->rc = APR_LDAP_URL_ERR_MEM;
+ return APR_EGENERAL;
+ }
+
+ if ( enclosed ) {
+ p = &url[strlen(url)-1];
+
+ if( *p != '>' ) {
+ result->reason = "Bad enclosure error while parsing LDAP URL.";
+ result->rc = APR_LDAP_URL_ERR_BADENCLOSURE;
+ return APR_EGENERAL;
+ }
+
+ *p = '\0';
+ }
+
+ /* allocate return struct */
+ ludp = (apr_ldap_url_desc_t *)apr_pcalloc(pool, sizeof(apr_ldap_url_desc_t));
+ if ( ludp == NULL ) {
+ result->reason = "Out of memory parsing LDAP URL.";
+ result->rc = APR_LDAP_URL_ERR_MEM;
+ return APR_EGENERAL;
+ }
+
+ ludp->lud_next = NULL;
+ ludp->lud_host = NULL;
+ ludp->lud_port = LDAP_PORT;
+ ludp->lud_dn = NULL;
+ ludp->lud_attrs = NULL;
+ ludp->lud_filter = NULL;
+ ludp->lud_scope = -1;
+ ludp->lud_filter = NULL;
+ ludp->lud_exts = NULL;
+
+ ludp->lud_scheme = (char *)apr_pstrdup(pool, scheme);
+ if ( ludp->lud_scheme == NULL ) {
+ result->reason = "Out of memory parsing LDAP URL.";
+ result->rc = APR_LDAP_URL_ERR_MEM;
+ return APR_EGENERAL;
+ }
+
+ if( strcasecmp( ludp->lud_scheme, "ldaps" ) == 0 ) {
+ ludp->lud_port = LDAPS_PORT;
+ }
+
+ /* scan forward for '/' that marks end of hostport and begin. of dn */
+ p = strchr( url, '/' );
+
+ if( p != NULL ) {
+ /* terminate hostport; point to start of dn */
+ *p++ = '\0';
+ }
+
+ /* IPv6 syntax with [ip address]:port */
+ if ( *url == '[' ) {
+ r = strchr( url, ']' );
+ if ( r == NULL ) {
+ result->reason = "Bad LDAP URL while parsing IPV6 syntax.";
+ result->rc = APR_LDAP_URL_ERR_BADURL;
+ return APR_EGENERAL;
+ }
+ *r++ = '\0';
+ q = strrchr( r, ':' );
+ } else {
+ q = strrchr( url, ':' );
+ }
+
+ if ( q != NULL ) {
+ apr_ldap_pvt_hex_unescape( ++q );
+
+ if( *q == '\0' ) {
+ result->reason = "Bad LDAP URL while parsing.";
+ result->rc = APR_LDAP_URL_ERR_BADURL;
+ return APR_EGENERAL;
+ }
+
+ ludp->lud_port = atoi( q );
+ }
+
+ apr_ldap_pvt_hex_unescape( url );
+
+ /* If [ip address]:port syntax, url is [ip and we skip the [ */
+ ludp->lud_host = (char *)apr_pstrdup(pool, url + ( *url == '[' ));
+ if( ludp->lud_host == NULL ) {
+ result->reason = "Out of memory parsing LDAP URL.";
+ result->rc = APR_LDAP_URL_ERR_MEM;
+ return APR_EGENERAL;
+ }
+
+ /*
+ * Kludge. ldap://111.222.333.444:389??cn=abc,o=company
+ *
+ * On early Novell releases, search references/referrals were returned
+ * in this format, i.e., the dn was kind of in the scope position,
+ * but the required slash is missing. The whole thing is illegal syntax,
+ * but we need to account for it. Fortunately it can't be confused with
+ * anything real.
+ */
+ if( (p == NULL) && (q != NULL) && ((q = strchr( q, '?')) != NULL)) {
+ q++;
+ /* ? immediately followed by question */
+ if( *q == '?') {
+ q++;
+ if( *q != '\0' ) {
+ /* parse dn part */
+ apr_ldap_pvt_hex_unescape( q );
+ ludp->lud_dn = (char *)apr_pstrdup(pool, q);
+ } else {
+ ludp->lud_dn = (char *)apr_pstrdup(pool, "");
+ }
+
+ if( ludp->lud_dn == NULL ) {
+ result->reason = "Out of memory parsing LDAP URL.";
+ result->rc = APR_LDAP_URL_ERR_MEM;
+ return APR_EGENERAL;
+ }
+ }
+ }
+
+ if( p == NULL ) {
+ *ludpp = ludp;
+ return APR_SUCCESS;
+ }
+
+ /* scan forward for '?' that may marks end of dn */
+ q = strchr( p, '?' );
+
+ if( q != NULL ) {
+ /* terminate dn part */
+ *q++ = '\0';
+ }
+
+ if( *p != '\0' ) {
+ /* parse dn part */
+ apr_ldap_pvt_hex_unescape( p );
+ ludp->lud_dn = (char *)apr_pstrdup(pool, p);
+ } else {
+ ludp->lud_dn = (char *)apr_pstrdup(pool, "");
+ }
+
+ if( ludp->lud_dn == NULL ) {
+ result->reason = "Out of memory parsing LDAP URL.";
+ result->rc = APR_LDAP_URL_ERR_MEM;
+ return APR_EGENERAL;
+ }
+
+ if( q == NULL ) {
+ /* no more */
+ *ludpp = ludp;
+ return APR_SUCCESS;
+ }
+
+ /* scan forward for '?' that may marks end of attributes */
+ p = q;
+ q = strchr( p, '?' );
+
+ if( q != NULL ) {
+ /* terminate attributes part */
+ *q++ = '\0';
+ }
+
+ if( *p != '\0' ) {
+ /* parse attributes */
+ apr_ldap_pvt_hex_unescape( p );
+ ludp->lud_attrs = apr_ldap_str2charray(pool, p, ",");
+
+ if( ludp->lud_attrs == NULL ) {
+ result->reason = "Bad attributes encountered while parsing LDAP URL.";
+ result->rc = APR_LDAP_URL_ERR_BADATTRS;
+ return APR_EGENERAL;
+ }
+ }
+
+ if ( q == NULL ) {
+ /* no more */
+ *ludpp = ludp;
+ return APR_SUCCESS;
+ }
+
+ /* scan forward for '?' that may marks end of scope */
+ p = q;
+ q = strchr( p, '?' );
+
+ if( q != NULL ) {
+ /* terminate the scope part */
+ *q++ = '\0';
+ }
+
+ if( *p != '\0' ) {
+ /* parse the scope */
+ apr_ldap_pvt_hex_unescape( p );
+ ludp->lud_scope = str2scope( p );
+
+ if( ludp->lud_scope == -1 ) {
+ result->reason = "Bad scope encountered while parsing LDAP URL.";
+ result->rc = APR_LDAP_URL_ERR_BADSCOPE;
+ return APR_EGENERAL;
+ }
+ }
+
+ if ( q == NULL ) {
+ /* no more */
+ *ludpp = ludp;
+ return APR_SUCCESS;
+ }
+
+ /* scan forward for '?' that may marks end of filter */
+ p = q;
+ q = strchr( p, '?' );
+
+ if( q != NULL ) {
+ /* terminate the filter part */
+ *q++ = '\0';
+ }
+
+ if( *p != '\0' ) {
+ /* parse the filter */
+ apr_ldap_pvt_hex_unescape( p );
+
+ if( ! *p ) {
+ /* missing filter */
+ result->reason = "Bad filter encountered while parsing LDAP URL.";
+ result->rc = APR_LDAP_URL_ERR_BADFILTER;
+ return APR_EGENERAL;
+ }
+
+ ludp->lud_filter = (char *)apr_pstrdup(pool, p);
+ if( ludp->lud_filter == NULL ) {
+ result->reason = "Out of memory parsing LDAP URL.";
+ result->rc = APR_LDAP_URL_ERR_MEM;
+ return APR_EGENERAL;
+ }
+ }
+
+ if ( q == NULL ) {
+ /* no more */
+ *ludpp = ludp;
+ return APR_SUCCESS;
+ }
+
+ /* scan forward for '?' that may marks end of extensions */
+ p = q;
+ q = strchr( p, '?' );
+
+ if( q != NULL ) {
+ /* extra '?' */
+ result->reason = "Bad URL encountered while parsing LDAP URL.";
+ result->rc = APR_LDAP_URL_ERR_BADURL;
+ return APR_EGENERAL;
+ }
+
+ /* parse the extensions */
+ ludp->lud_exts = apr_ldap_str2charray(pool, p, ",");
+ if( ludp->lud_exts == NULL ) {
+ result->reason = "Bad extensions encountered while parsing LDAP URL.";
+ result->rc = APR_LDAP_URL_ERR_BADEXTS;
+ return APR_EGENERAL;
+ }
+
+ for( i=0; ludp->lud_exts[i] != NULL; i++ ) {
+ apr_ldap_pvt_hex_unescape( ludp->lud_exts[i] );
+
+ if( *ludp->lud_exts[i] == '!' ) {
+ /* count the number of critical extensions */
+ ludp->lud_crit_exts++;
+ }
+ }
+
+ if( i == 0 ) {
+ /* must have 1 or more */
+ result->reason = "Bad extensions encountered while parsing LDAP URL.";
+ result->rc = APR_LDAP_URL_ERR_BADEXTS;
+ return APR_EGENERAL;
+ }
+
+ /* no more */
+ *ludpp = ludp;
+ return APR_SUCCESS;
+}
+
+
+/**
+ * Parse the URL provided into an apr_ldap_url_desc_t object.
+ *
+ * APR_SUCCESS is returned on success, APR_EGENERAL on failure.
+ * The LDAP result code and reason string is returned in the
+ * apr_ldap_err_t structure.
+ */
+APU_DECLARE(int) apr_ldap_url_parse(apr_pool_t *pool,
+ const char *url_in,
+ apr_ldap_url_desc_t **ludpp,
+ apr_ldap_err_t **result_err)
+{
+
+ int rc = apr_ldap_url_parse_ext(pool, url_in, ludpp, result_err);
+ if( rc != APR_SUCCESS ) {
+ return rc;
+ }
+
+ if ((*ludpp)->lud_scope == -1) {
+ (*ludpp)->lud_scope = LDAP_SCOPE_BASE;
+ }
+
+ if ((*ludpp)->lud_host != NULL && *(*ludpp)->lud_host == '\0') {
+ (*ludpp)->lud_host = NULL;
+ }
+
+ return rc;
+
+}
+
+
+static void apr_ldap_pvt_hex_unescape(char *s)
+{
+ /*
+ * Remove URL hex escapes from s... done in place. The basic concept for
+ * this routine is borrowed from the WWW library HTUnEscape() routine.
+ */
+ char *p;
+
+ for ( p = s; *s != '\0'; ++s ) {
+ if ( *s == '%' ) {
+ if ( *++s == '\0' ) {
+ break;
+ }
+ *p = apr_ldap_pvt_unhex( *s ) << 4;
+ if ( *++s == '\0' ) {
+ break;
+ }
+ *p++ += apr_ldap_pvt_unhex( *s );
+ } else {
+ *p++ = *s;
+ }
+ }
+
+ *p = '\0';
+}
+
+
+static int apr_ldap_pvt_unhex(int c)
+{
+ return( c >= '0' && c <= '9' ? c - '0'
+ : c >= 'A' && c <= 'F' ? c - 'A' + 10
+ : c - 'a' + 10 );
+}
+
+
+/**
+ * Convert a string to a character array
+ */
+static char **apr_ldap_str2charray(apr_pool_t *pool,
+ const char *str_in,
+ const char *brkstr)
+{
+ char **res;
+ char *str, *s;
+ char *lasts;
+ int i;
+
+ /* protect the input string from strtok */
+ str = (char *)apr_pstrdup(pool, str_in);
+ if( str == NULL ) {
+ return NULL;
+ }
+
+ i = 1;
+ for ( s = str; *s; s++ ) {
+ /* Warning: this strchr was previously ldap_utf8_strchr(), check
+ * whether this particular code has any charset issues.
+ */
+ if ( strchr( brkstr, *s ) != NULL ) {
+ i++;
+ }
+ }
+
+ res = (char **) apr_pcalloc(pool, (i + 1) * sizeof(char *));
+ if( res == NULL ) {
+ return NULL;
+ }
+
+ i = 0;
+
+ for ( s = (char *)apr_strtok( str, brkstr, &lasts );
+ s != NULL;
+ s = (char *)apr_strtok( NULL, brkstr, &lasts ) ) {
+
+ res[i] = (char *)apr_pstrdup(pool, s);
+ if(res[i] == NULL) {
+ return NULL;
+ }
+
+ i++;
+ }
+
+ res[i] = NULL;
+
+ return( res );
+
+}
+
+#endif /* APR_HAS_LDAP */
--- /dev/null
+# Microsoft Developer Studio Project File - Name="libaprutil" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=libaprutil - 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 "libaprutil.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 "libaprutil.mak" CFG="libaprutil - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "libaprutil - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "libaprutil - 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)" == "libaprutil - 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" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "./include" /I "../apr/include" /I "./include/private" /I "../apr-iconv/include" /I "./dbm/sdbm" /I "./xml/expat/lib" /D "NDEBUG" /D "APU_DECLARE_EXPORT" /D "APU_USE_SDBM" /D "WIN32" /D "_WINDOWS" /Fd"Release\libaprutil_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 /d "NDEBUG" /d "APU_VERSION_ONLY" /I "./include" /I "../apr/include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib wldap32.lib ole32.lib /nologo /base:"0x6EE60000" /subsystem:windows /dll /incremental:no /debug /machine:I386 /opt:ref
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib wldap32.lib ole32.lib /nologo /base:"0x6EE60000" /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/libaprutil-1.dll" /opt:ref
+
+!ELSEIF "$(CFG)" == "libaprutil - 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 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "./include" /I "../apr/include" /I "./include/private" /I "../apr-iconv/include" /I "./dbm/sdbm" /I "./xml/expat/lib" /D "_DEBUG" /D "APU_DECLARE_EXPORT" /D "APU_USE_SDBM" /D "WIN32" /D "_WINDOWS" /Fd"Debug\libaprutil_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 /d "_DEBUG" /d "APU_VERSION_ONLY" /I "./include" /I "../apr/include"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib wldap32.lib ole32.lib /nologo /base:"0x6EE60000" /subsystem:windows /dll /incremental:no /debug /machine:I386
+# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib wldap32.lib ole32.lib /nologo /base:"0x6EE60000" /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/libaprutil-1.dll"
+
+!ENDIF
+
+# Begin Target
+
+# Name "libaprutil - Win32 Release"
+# Name "libaprutil - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter ""
+# Begin Group "buckets"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\buckets\apr_brigade.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_alloc.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_eos.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_file.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_flush.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_heap.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_mmap.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_pipe.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_pool.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_refcount.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_simple.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\buckets\apr_buckets_socket.c
+# End Source File
+# End Group
+# Begin Group "crypto"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\crypto\apr_md4.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\crypto\apr_md5.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\crypto\apr_sha1.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\crypto\getuuid.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\crypto\uuid.c
+# End Source File
+# End Group
+# Begin Group "dbm"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\dbm\apr_dbm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbm\apr_dbm_berkeleydb.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbm\apr_dbm_gdbm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbm\apr_dbm_sdbm.c
+# End Source File
+# End Group
+# Begin Group "encoding"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\encoding\apr_base64.c
+# End Source File
+# End Group
+# Begin Group "hooks"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\hooks\apr_hooks.c
+# End Source File
+# End Group
+# Begin Group "ldap"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\ldap\apr_ldap_init.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ldap\apr_ldap_url.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ldap\apr_ldap_option.c
+# End Source File
+# End Group
+# Begin Group "misc"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\misc\apr_date.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\misc\apr_queue.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\misc\apr_reslist.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\misc\apr_rmm.c
+# End Source File
+# End Group
+# Begin Group "sdbm"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\dbm\sdbm\sdbm.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbm\sdbm\sdbm_hash.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbm\sdbm\sdbm_lock.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbm\sdbm\sdbm_pair.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbm\sdbm\sdbm_pair.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbm\sdbm\sdbm_private.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\dbm\sdbm\sdbm_tune.h
+# End Source File
+# End Group
+# Begin Group "strmatch"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\strmatch\apr_strmatch.c
+# End Source File
+# End Group
+# Begin Group "uri"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\uri\apr_uri.c
+# End Source File
+# End Group
+# Begin Group "xlate"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\xlate\xlate.c
+# End Source File
+# End Group
+# Begin Group "xml"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\xml\apr_xml.c
+# End Source File
+# End Group
+# End Group
+# Begin Group "Generated Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\include\apr_ldap.h.in
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_ldap.hnw
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_ldap.hw
+
+!IF "$(CFG)" == "libaprutil - Win32 Release"
+
+# Begin Custom Build - Creating apr_ldap.h from apr_ldap.hw
+InputPath=.\include\apr_ldap.hw
+
+".\include\apr_ldap.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ type .\include\apr_ldap.hw > .\include\apr_ldap.h
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "libaprutil - Win32 Debug"
+
+# Begin Custom Build - Creating apr_ldap.h from apr_ldap.hw
+InputPath=.\include\apr_ldap.hw
+
+".\include\apr_ldap.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ type .\include\apr_ldap.hw > .\include\apr_ldap.h
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apu.h.in
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apu.hnw
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apu.hw
+
+!IF "$(CFG)" == "libaprutil - Win32 Release"
+
+# Begin Custom Build - Creating apu.h from apu.hw
+InputPath=.\include\apu.hw
+
+".\include\apu.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ type .\include\apu.hw > .\include\apu.h
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "libaprutil - Win32 Debug"
+
+# Begin Custom Build - Creating apu.h from apu.hw
+InputPath=.\include\apu.hw
+
+".\include\apu.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ type .\include\apu.hw > .\include\apu.h
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\private\apu_config.h.in
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\private\apu_config.hw
+
+!IF "$(CFG)" == "libaprutil - Win32 Release"
+
+# Begin Custom Build - Creating apu_config.h from apu_config.hw
+InputPath=.\include\private\apu_config.hw
+
+".\include\private\apu_config.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ type .\include\private\apu_config.hw > .\include\private\apu_config.h
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "libaprutil - Win32 Debug"
+
+# Begin Custom Build - Creating apu_config.h from apu_config.hw
+InputPath=.\include\private\apu_config.hw
+
+".\include\private\apu_config.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ type .\include\private\apu_config.hw > .\include\private\apu_config.h
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\private\apu_select_dbm.h.in
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\private\apu_select_dbm.hw
+
+!IF "$(CFG)" == "libaprutil - Win32 Release"
+
+# Begin Custom Build - Creating apu_select_dbm.h from apu_select_dbm.hw
+InputPath=.\include\private\apu_select_dbm.hw
+
+".\include\private\apu_select_dbm.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ type .\include\private\apu_select_dbm.hw > .\include\private\apu_select_dbm.h
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "libaprutil - Win32 Debug"
+
+# Begin Custom Build - Creating apu_select_dbm.h from apu_select_dbm.hw
+InputPath=.\include\private\apu_select_dbm.hw
+
+".\include\private\apu_select_dbm.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ type .\include\private\apu_select_dbm.hw > .\include\private\apu_select_dbm.h
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apu_want.h.in
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apu_want.hnw
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apu_want.hw
+
+!IF "$(CFG)" == "libaprutil - Win32 Release"
+
+# Begin Custom Build - Creating apu_want.h from apu_want.hw
+InputPath=.\include\apu_want.hw
+
+".\include\apu_want.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ type .\include\apu_want.hw > .\include\apu_want.h
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "libaprutil - Win32 Debug"
+
+# Begin Custom Build - Creating apu_want.h from apu_want.hw
+InputPath=.\include\apu_want.hw
+
+".\include\apu_want.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ type .\include\apu_want.hw > .\include\apu_want.h
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\uri\gen_uri_delims.exe
+
+!IF "$(CFG)" == "libaprutil - Win32 Release"
+
+# Begin Custom Build - Generating uri_delims.h
+InputPath=.\uri\gen_uri_delims.exe
+
+".\uri\uri_delims.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ .\uri\gen_uri_delims.exe >.\uri\uri_delims.h
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "libaprutil - Win32 Debug"
+
+# Begin Custom Build - Generating uri_delims.h
+InputPath=.\uri\gen_uri_delims.exe
+
+".\uri\uri_delims.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ .\uri\gen_uri_delims.exe >.\uri\uri_delims.h
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# End Group
+# Begin Group "Public Header Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\include\apr_anylock.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_base64.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_buckets.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_date.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_dbm.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_hooks.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_ldap_url.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_md4.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_md5.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_optional.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_optional_hooks.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_queue.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_reslist.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_rmm.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_sdbm.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_sha1.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_strmatch.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_uri.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_uuid.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_xlate.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apr_xml.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\include\apu_version.h
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\libaprutil.rc
+# End Source File
+
+# End Target
+# End Project
--- /dev/null
+#include "apu_version.h"\r
+\r
+#define APU_COPYRIGHT "Copyright 2000-2005 The Apache Software " \\r
+ "Foundation or its licensors, as applicable."\r
+\r
+#define APU_LICENSE "Licensed under the Apache License, Version 2.0 " \\r
+ "(the ""License""); you may not use this file except " \\r
+ "in compliance with the License. You may obtain a " \\r
+ "copy of the License at\r\n\r\n" \\r
+ "http://www.apache.org/licenses/LICENSE-2.0\r\n\r\n" \\r
+ "Unless required by applicable law or agreed to in " \\r
+ "writing, software distributed under the License is " \\r
+ "distributed on an ""AS IS"" BASIS, WITHOUT " \\r
+ "WARRANTIES OR CONDITIONS OF ANY KIND, either " \\r
+ "express or implied. See the License for the " \\r
+ "specific language governing permissions and " \\r
+ "limitations under the License."\r
+\r
+#define APU_DLL_BASENAME "libaprutil-" APU_STRINGIFY(APU_MAJOR_VERSION)\r
+\r
+\r
+1 VERSIONINFO\r
+ FILEVERSION APU_VERSION_STRING_CSV,0\r
+ PRODUCTVERSION APU_VERSION_STRING_CSV,0\r
+ FILEFLAGSMASK 0x3fL\r
+#if defined(_DEBUG)\r
+ FILEFLAGS 0x01L\r
+#else\r
+ FILEFLAGS 0x00L\r
+#endif\r
+ FILEOS 0x40004L\r
+ FILETYPE 0x1L\r
+ FILESUBTYPE 0x0L\r
+BEGIN\r
+ BLOCK "StringFileInfo"\r
+ BEGIN\r
+ BLOCK "040904b0"\r
+ BEGIN\r
+ VALUE "Comments", APU_LICENSE "\0"\r
+ VALUE "CompanyName", "Apache Software Foundation\0"\r
+ VALUE "FileDescription", "Apache Portable Runtime Library\0"\r
+ VALUE "FileVersion", APU_VERSION_STRING "\0"\r
+ VALUE "InternalName", APU_DLL_BASENAME "\0"\r
+ VALUE "LegalCopyright", APU_COPYRIGHT "\0"\r
+ VALUE "OriginalFilename", APU_DLL_BASENAME ".dll\0"\r
+ VALUE "ProductName", "Apache Portable Runtime Project\0"\r
+ VALUE "ProductVersion", APU_VERSION_STRING "\0"\r
+ END\r
+ END\r
+ BLOCK "VarFileInfo"\r
+ BEGIN\r
+ VALUE "Translation", 0x409, 1200\r
+ END\r
+END\r
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * apr_date.c: date parsing utility routines
+ * These routines are (hopefully) platform independent.
+ *
+ * 27 Oct 1996 Roy Fielding
+ * Extracted (with many modifications) from mod_proxy.c and
+ * tested with over 50,000 randomly chosen valid date strings
+ * and several hundred variations of invalid date strings.
+ *
+ */
+
+#include "apr.h"
+#include "apr_lib.h"
+
+#define APR_WANT_STRFUNC
+#include "apr_want.h"
+
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#if APR_HAVE_CTYPE_H
+#include <ctype.h>
+#endif
+
+#include "apr_date.h"
+
+/*
+ * Compare a string to a mask
+ * Mask characters (arbitrary maximum is 256 characters, just in case):
+ * @ - uppercase letter
+ * $ - lowercase letter
+ * & - hex digit
+ * # - digit
+ * ~ - digit or space
+ * * - swallow remaining characters
+ * <x> - exact match for any other character
+ */
+APU_DECLARE(int) apr_date_checkmask(const char *data, const char *mask)
+{
+ int i;
+ char d;
+
+ for (i = 0; i < 256; i++) {
+ d = data[i];
+ switch (mask[i]) {
+ case '\0':
+ return (d == '\0');
+
+ case '*':
+ return 1;
+
+ case '@':
+ if (!apr_isupper(d))
+ return 0;
+ break;
+ case '$':
+ if (!apr_islower(d))
+ return 0;
+ break;
+ case '#':
+ if (!apr_isdigit(d))
+ return 0;
+ break;
+ case '&':
+ if (!apr_isxdigit(d))
+ return 0;
+ break;
+ case '~':
+ if ((d != ' ') && !apr_isdigit(d))
+ return 0;
+ break;
+ default:
+ if (mask[i] != d)
+ return 0;
+ break;
+ }
+ }
+ return 0; /* We only get here if mask is corrupted (exceeds 256) */
+}
+
+/*
+ * Parses an HTTP date in one of three standard forms:
+ *
+ * Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123
+ * Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
+ * Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format
+ *
+ * and returns the apr_time_t number of microseconds since 1 Jan 1970 GMT,
+ * or APR_DATE_BAD if this would be out of range or if the date is invalid.
+ *
+ * The restricted HTTP syntax is
+ *
+ * HTTP-date = rfc1123-date | rfc850-date | asctime-date
+ *
+ * rfc1123-date = wkday "," SP date1 SP time SP "GMT"
+ * rfc850-date = weekday "," SP date2 SP time SP "GMT"
+ * asctime-date = wkday SP date3 SP time SP 4DIGIT
+ *
+ * date1 = 2DIGIT SP month SP 4DIGIT
+ * ; day month year (e.g., 02 Jun 1982)
+ * date2 = 2DIGIT "-" month "-" 2DIGIT
+ * ; day-month-year (e.g., 02-Jun-82)
+ * date3 = month SP ( 2DIGIT | ( SP 1DIGIT ))
+ * ; month day (e.g., Jun 2)
+ *
+ * time = 2DIGIT ":" 2DIGIT ":" 2DIGIT
+ * ; 00:00:00 - 23:59:59
+ *
+ * wkday = "Mon" | "Tue" | "Wed"
+ * | "Thu" | "Fri" | "Sat" | "Sun"
+ *
+ * weekday = "Monday" | "Tuesday" | "Wednesday"
+ * | "Thursday" | "Friday" | "Saturday" | "Sunday"
+ *
+ * month = "Jan" | "Feb" | "Mar" | "Apr"
+ * | "May" | "Jun" | "Jul" | "Aug"
+ * | "Sep" | "Oct" | "Nov" | "Dec"
+ *
+ * However, for the sake of robustness (and Netscapeness), we ignore the
+ * weekday and anything after the time field (including the timezone).
+ *
+ * This routine is intended to be very fast; 10x faster than using sscanf.
+ *
+ * Originally from Andrew Daviel <andrew@vancouver-webpages.com>, 29 Jul 96
+ * but many changes since then.
+ *
+ */
+APU_DECLARE(apr_time_t) apr_date_parse_http(const char *date)
+{
+ apr_time_exp_t ds;
+ apr_time_t result;
+ int mint, mon;
+ const char *monstr, *timstr;
+ static const int months[12] =
+ {
+ ('J' << 16) | ('a' << 8) | 'n', ('F' << 16) | ('e' << 8) | 'b',
+ ('M' << 16) | ('a' << 8) | 'r', ('A' << 16) | ('p' << 8) | 'r',
+ ('M' << 16) | ('a' << 8) | 'y', ('J' << 16) | ('u' << 8) | 'n',
+ ('J' << 16) | ('u' << 8) | 'l', ('A' << 16) | ('u' << 8) | 'g',
+ ('S' << 16) | ('e' << 8) | 'p', ('O' << 16) | ('c' << 8) | 't',
+ ('N' << 16) | ('o' << 8) | 'v', ('D' << 16) | ('e' << 8) | 'c'};
+
+ if (!date)
+ return APR_DATE_BAD;
+
+ while (*date && apr_isspace(*date)) /* Find first non-whitespace char */
+ ++date;
+
+ if (*date == '\0')
+ return APR_DATE_BAD;
+
+ if ((date = strchr(date, ' ')) == NULL) /* Find space after weekday */
+ return APR_DATE_BAD;
+
+ ++date; /* Now pointing to first char after space, which should be */
+
+ /* start of the actual date information for all 4 formats. */
+
+ if (apr_date_checkmask(date, "## @$$ #### ##:##:## *")) {
+ /* RFC 1123 format with two days */
+ ds.tm_year = ((date[7] - '0') * 10 + (date[8] - '0') - 19) * 100;
+ if (ds.tm_year < 0)
+ return APR_DATE_BAD;
+
+ ds.tm_year += ((date[9] - '0') * 10) + (date[10] - '0');
+
+ ds.tm_mday = ((date[0] - '0') * 10) + (date[1] - '0');
+
+ monstr = date + 3;
+ timstr = date + 12;
+ }
+ else if (apr_date_checkmask(date, "##-@$$-## ##:##:## *")) {
+ /* RFC 850 format */
+ ds.tm_year = ((date[7] - '0') * 10) + (date[8] - '0');
+ if (ds.tm_year < 70)
+ ds.tm_year += 100;
+
+ ds.tm_mday = ((date[0] - '0') * 10) + (date[1] - '0');
+
+ monstr = date + 3;
+ timstr = date + 10;
+ }
+ else if (apr_date_checkmask(date, "@$$ ~# ##:##:## ####*")) {
+ /* asctime format */
+ ds.tm_year = ((date[16] - '0') * 10 + (date[17] - '0') - 19) * 100;
+ if (ds.tm_year < 0)
+ return APR_DATE_BAD;
+
+ ds.tm_year += ((date[18] - '0') * 10) + (date[19] - '0');
+
+ if (date[4] == ' ')
+ ds.tm_mday = 0;
+ else
+ ds.tm_mday = (date[4] - '0') * 10;
+
+ ds.tm_mday += (date[5] - '0');
+
+ monstr = date;
+ timstr = date + 7;
+ }
+ else if (apr_date_checkmask(date, "# @$$ #### ##:##:## *")) {
+ /* RFC 1123 format with one day */
+ ds.tm_year = ((date[6] - '0') * 10 + (date[7] - '0') - 19) * 100;
+ if (ds.tm_year < 0)
+ return APR_DATE_BAD;
+
+ ds.tm_year += ((date[8] - '0') * 10) + (date[9] - '0');
+
+ ds.tm_mday = (date[0] - '0');
+
+ monstr = date + 2;
+ timstr = date + 11;
+ }
+ else
+ return APR_DATE_BAD;
+
+ if (ds.tm_mday <= 0 || ds.tm_mday > 31)
+ return APR_DATE_BAD;
+
+ ds.tm_hour = ((timstr[0] - '0') * 10) + (timstr[1] - '0');
+ ds.tm_min = ((timstr[3] - '0') * 10) + (timstr[4] - '0');
+ ds.tm_sec = ((timstr[6] - '0') * 10) + (timstr[7] - '0');
+
+ if ((ds.tm_hour > 23) || (ds.tm_min > 59) || (ds.tm_sec > 61))
+ return APR_DATE_BAD;
+
+ mint = (monstr[0] << 16) | (monstr[1] << 8) | monstr[2];
+ for (mon = 0; mon < 12; mon++)
+ if (mint == months[mon])
+ break;
+
+ if (mon == 12)
+ return APR_DATE_BAD;
+
+ if ((ds.tm_mday == 31) && (mon == 3 || mon == 5 || mon == 8 || mon == 10))
+ return APR_DATE_BAD;
+
+ /* February gets special check for leapyear */
+ if ((mon == 1) &&
+ ((ds.tm_mday > 29) ||
+ ((ds.tm_mday == 29)
+ && ((ds.tm_year & 3)
+ || (((ds.tm_year % 100) == 0)
+ && (((ds.tm_year % 400) != 100)))))))
+ return APR_DATE_BAD;
+
+ ds.tm_mon = mon;
+
+ /* ap_mplode_time uses tm_usec and tm_gmtoff fields, but they haven't
+ * been set yet.
+ * It should be safe to just zero out these values.
+ * tm_usec is the number of microseconds into the second. HTTP only
+ * cares about second granularity.
+ * tm_gmtoff is the number of seconds off of GMT the time is. By
+ * definition all times going through this function are in GMT, so this
+ * is zero.
+ */
+ ds.tm_usec = 0;
+ ds.tm_gmtoff = 0;
+ if (apr_time_exp_get(&result, &ds) != APR_SUCCESS)
+ return APR_DATE_BAD;
+
+ return result;
+}
+
+/*
+ * Parses a string resembling an RFC 822 date. This is meant to be
+ * leinent in its parsing of dates. Hence, this will parse a wider
+ * range of dates than apr_date_parse_http.
+ *
+ * The prominent mailer (or poster, if mailer is unknown) that has
+ * been seen in the wild is included for the unknown formats.
+ *
+ * Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123
+ * Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036
+ * Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format
+ * Sun, 6 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123
+ * Sun, 06 Nov 94 08:49:37 GMT ; RFC 822
+ * Sun, 6 Nov 94 08:49:37 GMT ; RFC 822
+ * Sun, 06 Nov 94 08:49 GMT ; Unknown [drtr@ast.cam.ac.uk]
+ * Sun, 6 Nov 94 08:49 GMT ; Unknown [drtr@ast.cam.ac.uk]
+ * Sun, 06 Nov 94 8:49:37 GMT ; Unknown [Elm 70.85]
+ * Sun, 6 Nov 94 8:49:37 GMT ; Unknown [Elm 70.85]
+ * Mon, 7 Jan 2002 07:21:22 GMT ; Unknown [Postfix]
+ * Sun, 06-Nov-1994 08:49:37 GMT ; RFC 850 with four digit years
+ *
+ */
+
+#define TIMEPARSE(ds,hr10,hr1,min10,min1,sec10,sec1) \
+ { \
+ ds.tm_hour = ((hr10 - '0') * 10) + (hr1 - '0'); \
+ ds.tm_min = ((min10 - '0') * 10) + (min1 - '0'); \
+ ds.tm_sec = ((sec10 - '0') * 10) + (sec1 - '0'); \
+ }
+#define TIMEPARSE_STD(ds,timstr) \
+ { \
+ TIMEPARSE(ds, timstr[0],timstr[1], \
+ timstr[3],timstr[4], \
+ timstr[6],timstr[7]); \
+ }
+
+APU_DECLARE(apr_time_t) apr_date_parse_rfc(const char *date)
+{
+ apr_time_exp_t ds;
+ apr_time_t result;
+ int mint, mon;
+ const char *monstr, *timstr, *gmtstr;
+ static const int months[12] =
+ {
+ ('J' << 16) | ('a' << 8) | 'n', ('F' << 16) | ('e' << 8) | 'b',
+ ('M' << 16) | ('a' << 8) | 'r', ('A' << 16) | ('p' << 8) | 'r',
+ ('M' << 16) | ('a' << 8) | 'y', ('J' << 16) | ('u' << 8) | 'n',
+ ('J' << 16) | ('u' << 8) | 'l', ('A' << 16) | ('u' << 8) | 'g',
+ ('S' << 16) | ('e' << 8) | 'p', ('O' << 16) | ('c' << 8) | 't',
+ ('N' << 16) | ('o' << 8) | 'v', ('D' << 16) | ('e' << 8) | 'c' };
+
+ if (!date)
+ return APR_DATE_BAD;
+
+ /* Not all dates have text months at the beginning. */
+ if (!apr_isdigit(date[0]))
+ {
+ while (*date && apr_isspace(*date)) /* Find first non-whitespace char */
+ ++date;
+
+ if (*date == '\0')
+ return APR_DATE_BAD;
+
+ if ((date = strchr(date, ' ')) == NULL) /* Find space after weekday */
+ return APR_DATE_BAD;
+
+ ++date; /* Now pointing to first char after space, which should be */ }
+
+ /* start of the actual date information for all 11 formats. */
+ if (apr_date_checkmask(date, "## @$$ #### ##:##:## *")) { /* RFC 1123 format */
+ ds.tm_year = ((date[7] - '0') * 10 + (date[8] - '0') - 19) * 100;
+
+ if (ds.tm_year < 0)
+ return APR_DATE_BAD;
+
+ ds.tm_year += ((date[9] - '0') * 10) + (date[10] - '0');
+
+ ds.tm_mday = ((date[0] - '0') * 10) + (date[1] - '0');
+
+ monstr = date + 3;
+ timstr = date + 12;
+ gmtstr = date + 20;
+
+ TIMEPARSE_STD(ds, timstr);
+ }
+ else if (apr_date_checkmask(date, "##-@$$-## ##:##:## *")) {/* RFC 850 format */
+ ds.tm_year = ((date[7] - '0') * 10) + (date[8] - '0');
+
+ if (ds.tm_year < 70)
+ ds.tm_year += 100;
+
+ ds.tm_mday = ((date[0] - '0') * 10) + (date[1] - '0');
+
+ monstr = date + 3;
+ timstr = date + 10;
+ gmtstr = date + 19;
+
+ TIMEPARSE_STD(ds, timstr);
+ }
+ else if (apr_date_checkmask(date, "@$$ ~# ##:##:## ####*")) {
+ /* asctime format */
+ ds.tm_year = ((date[16] - '0') * 10 + (date[17] - '0') - 19) * 100;
+ if (ds.tm_year < 0)
+ return APR_DATE_BAD;
+
+ ds.tm_year += ((date[18] - '0') * 10) + (date[19] - '0');
+
+ if (date[4] == ' ')
+ ds.tm_mday = 0;
+ else
+ ds.tm_mday = (date[4] - '0') * 10;
+
+ ds.tm_mday += (date[5] - '0');
+
+ monstr = date;
+ timstr = date + 7;
+ gmtstr = NULL;
+
+ TIMEPARSE_STD(ds, timstr);
+ }
+ else if (apr_date_checkmask(date, "# @$$ #### ##:##:## *")) {
+ /* RFC 1123 format*/
+ ds.tm_year = ((date[6] - '0') * 10 + (date[7] - '0') - 19) * 100;
+
+ if (ds.tm_year < 0)
+ return APR_DATE_BAD;
+
+ ds.tm_year += ((date[8] - '0') * 10) + (date[9] - '0');
+ ds.tm_mday = (date[0] - '0');
+
+ monstr = date + 2;
+ timstr = date + 11;
+ gmtstr = date + 20;
+
+ TIMEPARSE_STD(ds, timstr);
+ }
+ else if (apr_date_checkmask(date, "## @$$ ## ##:##:## *")) {
+ /* This is the old RFC 1123 date format - many many years ago, people
+ * used two-digit years. Oh, how foolish. */
+ ds.tm_year = ((date[7] - '0') * 10) + (date[8] - '0');
+
+ if (ds.tm_year < 70)
+ ds.tm_year += 100;
+
+ ds.tm_mday = ((date[0] - '0') * 10) + (date[1] - '0');
+
+ monstr = date + 3;
+ timstr = date + 10;
+ gmtstr = date + 19;
+
+ TIMEPARSE_STD(ds, timstr);
+ }
+ else if (apr_date_checkmask(date, "# @$$ ## ##:##:## *")) {
+ /* This is the old RFC 1123 date format - many many years ago, people
+ * used two-digit years. Oh, how foolish. */
+ ds.tm_year = ((date[6] - '0') * 10) + (date[7] - '0');
+
+ if (ds.tm_year < 70)
+ ds.tm_year += 100;
+
+ ds.tm_mday = (date[0] - '0');
+
+ monstr = date + 2;
+ timstr = date + 9;
+ gmtstr = date + 18;
+
+ TIMEPARSE_STD(ds, timstr);
+ }
+ else if (apr_date_checkmask(date, "## @$$ ## ##:## *")) {
+ /* Loser format. This is quite bogus. */
+ ds.tm_year = ((date[7] - '0') * 10) + (date[8] - '0');
+
+ if (ds.tm_year < 70)
+ ds.tm_year += 100;
+
+ ds.tm_mday = ((date[0] - '0') * 10) + (date[1] - '0');
+
+ monstr = date + 3;
+ timstr = date + 10;
+ gmtstr = NULL;
+
+ TIMEPARSE(ds, timstr[0],timstr[1], timstr[3],timstr[4], '0','0');
+ }
+ else if (apr_date_checkmask(date, "# @$$ ## ##:## *")) {
+ /* Loser format. This is quite bogus. */
+ ds.tm_year = ((date[6] - '0') * 10) + (date[7] - '0');
+
+ if (ds.tm_year < 70)
+ ds.tm_year += 100;
+
+ ds.tm_mday = (date[0] - '0');
+
+ monstr = date + 2;
+ timstr = date + 9;
+ gmtstr = NULL;
+
+ TIMEPARSE(ds, timstr[0],timstr[1], timstr[3],timstr[4], '0','0');
+ }
+ else if (apr_date_checkmask(date, "## @$$ ## #:##:## *")) {
+ /* Loser format. This is quite bogus. */
+ ds.tm_year = ((date[7] - '0') * 10) + (date[8] - '0');
+
+ if (ds.tm_year < 70)
+ ds.tm_year += 100;
+
+ ds.tm_mday = ((date[0] - '0') * 10) + (date[1] - '0');
+
+ monstr = date + 3;
+ timstr = date + 9;
+ gmtstr = date + 18;
+
+ TIMEPARSE(ds, '0',timstr[1], timstr[3],timstr[4], timstr[6],timstr[7]);
+ }
+ else if (apr_date_checkmask(date, "# @$$ ## #:##:## *")) {
+ /* Loser format. This is quite bogus. */
+ ds.tm_year = ((date[6] - '0') * 10) + (date[7] - '0');
+
+ if (ds.tm_year < 70)
+ ds.tm_year += 100;
+
+ ds.tm_mday = (date[0] - '0');
+
+ monstr = date + 2;
+ timstr = date + 8;
+ gmtstr = date + 17;
+
+ TIMEPARSE(ds, '0',timstr[1], timstr[3],timstr[4], timstr[6],timstr[7]);
+ }
+ else if (apr_date_checkmask(date, " # @$$ #### ##:##:## *")) {
+ /* RFC 1123 format with a space instead of a leading zero. */
+ ds.tm_year = ((date[7] - '0') * 10 + (date[8] - '0') - 19) * 100;
+
+ if (ds.tm_year < 0)
+ return APR_DATE_BAD;
+
+ ds.tm_year += ((date[9] - '0') * 10) + (date[10] - '0');
+
+ ds.tm_mday = (date[1] - '0');
+
+ monstr = date + 3;
+ timstr = date + 12;
+ gmtstr = date + 20;
+
+ TIMEPARSE_STD(ds, timstr);
+ }
+ else if (apr_date_checkmask(date, "##-@$$-#### ##:##:## *")) {
+ /* RFC 1123 with dashes instead of spaces between date/month/year
+ * This also looks like RFC 850 with four digit years.
+ */
+ ds.tm_year = ((date[7] - '0') * 10 + (date[8] - '0') - 19) * 100;
+ if (ds.tm_year < 0)
+ return APR_DATE_BAD;
+
+ ds.tm_year += ((date[9] - '0') * 10) + (date[10] - '0');
+
+ ds.tm_mday = ((date[0] - '0') * 10) + (date[1] - '0');
+
+ monstr = date + 3;
+ timstr = date + 12;
+ gmtstr = date + 21;
+
+ TIMEPARSE_STD(ds, timstr);
+ }
+ else
+ return APR_DATE_BAD;
+
+ if (ds.tm_mday <= 0 || ds.tm_mday > 31)
+ return APR_DATE_BAD;
+
+ if ((ds.tm_hour > 23) || (ds.tm_min > 59) || (ds.tm_sec > 61))
+ return APR_DATE_BAD;
+
+ mint = (monstr[0] << 16) | (monstr[1] << 8) | monstr[2];
+ for (mon = 0; mon < 12; mon++)
+ if (mint == months[mon])
+ break;
+
+ if (mon == 12)
+ return APR_DATE_BAD;
+
+ if ((ds.tm_mday == 31) && (mon == 3 || mon == 5 || mon == 8 || mon == 10))
+ return APR_DATE_BAD;
+
+ /* February gets special check for leapyear */
+
+ if ((mon == 1) &&
+ ((ds.tm_mday > 29)
+ || ((ds.tm_mday == 29)
+ && ((ds.tm_year & 3)
+ || (((ds.tm_year % 100) == 0)
+ && (((ds.tm_year % 400) != 100)))))))
+ return APR_DATE_BAD;
+
+ ds.tm_mon = mon;
+
+ /* tm_gmtoff is the number of seconds off of GMT the time is.
+ *
+ * We only currently support: [+-]ZZZZ where Z is the offset in
+ * hours from GMT.
+ *
+ * If there is any confusion, tm_gmtoff will remain 0.
+ */
+ ds.tm_gmtoff = 0;
+ if (gmtstr && *gmtstr != '\0') {
+ /* Do we have a GMT? */
+ if (*(++gmtstr) != '\0') {
+ int offset;
+ switch (*(gmtstr++)) {
+ case '-':
+ offset = atoi(gmtstr);
+ ds.tm_gmtoff -= (offset / 100) * 60 * 60;
+ ds.tm_gmtoff -= (offset % 100) * 60;
+ break;
+ case '+':
+ offset = atoi(gmtstr);
+ ds.tm_gmtoff += (offset / 100) * 60 * 60;
+ ds.tm_gmtoff += (offset % 100) * 60;
+ break;
+ }
+ }
+ }
+
+ /* apr_time_exp_get uses tm_usec field, but it hasn't been set yet.
+ * It should be safe to just zero out this value.
+ * tm_usec is the number of microseconds into the second. HTTP only
+ * cares about second granularity.
+ */
+ ds.tm_usec = 0;
+
+ if (apr_time_exp_gmt_get(&result, &ds) != APR_SUCCESS)
+ return APR_DATE_BAD;
+
+ return result;
+}
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+
+#if APR_HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if APR_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "apu.h"
+#include "apr_portable.h"
+#include "apr_thread_mutex.h"
+#include "apr_thread_cond.h"
+#include "apr_errno.h"
+#include "apr_queue.h"
+
+#if APR_HAS_THREADS
+/*
+ * define this to get debug messages
+ *
+#define QUEUE_DEBUG
+ */
+
+struct apr_queue_t {
+ void **data;
+ unsigned int nelts; /**< # elements */
+ unsigned int in; /**< next empty location */
+ unsigned int out; /**< next filled location */
+ unsigned int bounds;/**< max size of queue */
+ unsigned int full_waiters;
+ unsigned int empty_waiters;
+ apr_thread_mutex_t *one_big_mutex;
+ apr_thread_cond_t *not_empty;
+ apr_thread_cond_t *not_full;
+ int terminated;
+};
+
+#ifdef QUEUE_DEBUG
+static void Q_DBG(char*msg, apr_queue_t *q) {
+ fprintf(stderr, "%ld\t#%d in %d out %d\t%s\n",
+ apr_os_thread_current(),
+ q->nelts, q->in, q->out,
+ msg
+ );
+}
+#else
+#define Q_DBG(x,y)
+#endif
+
+/**
+ * Detects when the apr_queue_t is full. This utility function is expected
+ * to be called from within critical sections, and is not threadsafe.
+ */
+#define apr_queue_full(queue) ((queue)->nelts == (queue)->bounds)
+
+/**
+ * Detects when the apr_queue_t is empty. This utility function is expected
+ * to be called from within critical sections, and is not threadsafe.
+ */
+#define apr_queue_empty(queue) ((queue)->nelts == 0)
+
+/**
+ * Callback routine that is called to destroy this
+ * apr_queue_t when its pool is destroyed.
+ */
+static apr_status_t queue_destroy(void *data)
+{
+ apr_queue_t *queue = data;
+
+ /* Ignore errors here, we can't do anything about them anyway. */
+
+ apr_thread_cond_destroy(queue->not_empty);
+ apr_thread_cond_destroy(queue->not_full);
+ apr_thread_mutex_destroy(queue->one_big_mutex);
+
+ return APR_SUCCESS;
+}
+
+/**
+ * Initialize the apr_queue_t.
+ */
+APU_DECLARE(apr_status_t) apr_queue_create(apr_queue_t **q,
+ unsigned int queue_capacity,
+ apr_pool_t *a)
+{
+ apr_status_t rv;
+ apr_queue_t *queue;
+ queue = apr_palloc(a, sizeof(apr_queue_t));
+ *q = queue;
+
+ /* nested doesn't work ;( */
+ rv = apr_thread_mutex_create(&queue->one_big_mutex,
+ APR_THREAD_MUTEX_UNNESTED,
+ a);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ rv = apr_thread_cond_create(&queue->not_empty, a);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ rv = apr_thread_cond_create(&queue->not_full, a);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ /* Set all the data in the queue to NULL */
+ queue->data = apr_pcalloc(a, queue_capacity * sizeof(void*));
+ queue->bounds = queue_capacity;
+ queue->nelts = 0;
+ queue->in = 0;
+ queue->out = 0;
+ queue->terminated = 0;
+ queue->full_waiters = 0;
+ queue->empty_waiters = 0;
+
+ apr_pool_cleanup_register(a, queue, queue_destroy, apr_pool_cleanup_null);
+
+ return APR_SUCCESS;
+}
+
+/**
+ * Push new data onto the queue. Blocks if the queue is full. Once
+ * the push operation has completed, it signals other threads waiting
+ * in apr_queue_pop() that they may continue consuming sockets.
+ */
+APU_DECLARE(apr_status_t) apr_queue_push(apr_queue_t *queue, void *data)
+{
+ apr_status_t rv;
+
+ if (queue->terminated) {
+ return APR_EOF; /* no more elements ever again */
+ }
+
+ rv = apr_thread_mutex_lock(queue->one_big_mutex);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ if (apr_queue_full(queue)) {
+ if (!queue->terminated) {
+ queue->full_waiters++;
+ rv = apr_thread_cond_wait(queue->not_full, queue->one_big_mutex);
+ queue->full_waiters--;
+ if (rv != APR_SUCCESS) {
+ apr_thread_mutex_unlock(queue->one_big_mutex);
+ return rv;
+ }
+ }
+ /* If we wake up and it's still empty, then we were interrupted */
+ if (apr_queue_full(queue)) {
+ Q_DBG("queue full (intr)", queue);
+ rv = apr_thread_mutex_unlock(queue->one_big_mutex);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+ if (queue->terminated) {
+ return APR_EOF; /* no more elements ever again */
+ }
+ else {
+ return APR_EINTR;
+ }
+ }
+ }
+
+ queue->data[queue->in] = data;
+ queue->in = (queue->in + 1) % queue->bounds;
+ queue->nelts++;
+
+ if (queue->empty_waiters) {
+ Q_DBG("sig !empty", queue);
+ rv = apr_thread_cond_signal(queue->not_empty);
+ if (rv != APR_SUCCESS) {
+ apr_thread_mutex_unlock(queue->one_big_mutex);
+ return rv;
+ }
+ }
+
+ rv = apr_thread_mutex_unlock(queue->one_big_mutex);
+ return rv;
+}
+
+/**
+ * Push new data onto the queue. Blocks if the queue is full. Once
+ * the push operation has completed, it signals other threads waiting
+ * in apr_queue_pop() that they may continue consuming sockets.
+ */
+APU_DECLARE(apr_status_t) apr_queue_trypush(apr_queue_t *queue, void *data)
+{
+ apr_status_t rv;
+
+ if (queue->terminated) {
+ return APR_EOF; /* no more elements ever again */
+ }
+
+ rv = apr_thread_mutex_lock(queue->one_big_mutex);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ if (apr_queue_full(queue)) {
+ rv = apr_thread_mutex_unlock(queue->one_big_mutex);
+ return APR_EAGAIN;
+ }
+
+ queue->data[queue->in] = data;
+ queue->in = (queue->in + 1) % queue->bounds;
+ queue->nelts++;
+
+ if (queue->empty_waiters) {
+ Q_DBG("sig !empty", queue);
+ rv = apr_thread_cond_signal(queue->not_empty);
+ if (rv != APR_SUCCESS) {
+ apr_thread_mutex_unlock(queue->one_big_mutex);
+ return rv;
+ }
+ }
+
+ rv = apr_thread_mutex_unlock(queue->one_big_mutex);
+ return rv;
+}
+
+/**
+ * not thread safe
+ */
+APU_DECLARE(unsigned int) apr_queue_size(apr_queue_t *queue) {
+ return queue->nelts;
+}
+
+/**
+ * Retrieves the next item from the queue. If there are no
+ * items available, it will block until one becomes available.
+ * Once retrieved, the item is placed into the address specified by
+ * 'data'.
+ */
+APU_DECLARE(apr_status_t) apr_queue_pop(apr_queue_t *queue, void **data)
+{
+ apr_status_t rv;
+
+ if (queue->terminated) {
+ return APR_EOF; /* no more elements ever again */
+ }
+
+ rv = apr_thread_mutex_lock(queue->one_big_mutex);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ /* Keep waiting until we wake up and find that the queue is not empty. */
+ if (apr_queue_empty(queue)) {
+ if (!queue->terminated) {
+ queue->empty_waiters++;
+ rv = apr_thread_cond_wait(queue->not_empty, queue->one_big_mutex);
+ queue->empty_waiters--;
+ if (rv != APR_SUCCESS) {
+ apr_thread_mutex_unlock(queue->one_big_mutex);
+ return rv;
+ }
+ }
+ /* If we wake up and it's still empty, then we were interrupted */
+ if (apr_queue_empty(queue)) {
+ Q_DBG("queue empty (intr)", queue);
+ rv = apr_thread_mutex_unlock(queue->one_big_mutex);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+ if (queue->terminated) {
+ return APR_EOF; /* no more elements ever again */
+ }
+ else {
+ return APR_EINTR;
+ }
+ }
+ }
+
+ *data = queue->data[queue->out];
+ queue->nelts--;
+
+ queue->out = (queue->out + 1) % queue->bounds;
+ if (queue->full_waiters) {
+ Q_DBG("signal !full", queue);
+ rv = apr_thread_cond_signal(queue->not_full);
+ if (rv != APR_SUCCESS) {
+ apr_thread_mutex_unlock(queue->one_big_mutex);
+ return rv;
+ }
+ }
+
+ rv = apr_thread_mutex_unlock(queue->one_big_mutex);
+ return rv;
+}
+
+/**
+ * Retrieves the next item from the queue. If there are no
+ * items available, return APR_EAGAIN. Once retrieved,
+ * the item is placed into the address specified by 'data'.
+ */
+APU_DECLARE(apr_status_t) apr_queue_trypop(apr_queue_t *queue, void **data)
+{
+ apr_status_t rv;
+
+ if (queue->terminated) {
+ return APR_EOF; /* no more elements ever again */
+ }
+
+ rv = apr_thread_mutex_lock(queue->one_big_mutex);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ if (apr_queue_empty(queue)) {
+ rv = apr_thread_mutex_unlock(queue->one_big_mutex);
+ return APR_EAGAIN;
+ }
+
+ *data = queue->data[queue->out];
+ queue->nelts--;
+
+ queue->out = (queue->out + 1) % queue->bounds;
+ if (queue->full_waiters) {
+ Q_DBG("signal !full", queue);
+ rv = apr_thread_cond_signal(queue->not_full);
+ if (rv != APR_SUCCESS) {
+ apr_thread_mutex_unlock(queue->one_big_mutex);
+ return rv;
+ }
+ }
+
+ rv = apr_thread_mutex_unlock(queue->one_big_mutex);
+ return rv;
+}
+
+APU_DECLARE(apr_status_t) apr_queue_interrupt_all(apr_queue_t *queue)
+{
+ apr_status_t rv;
+ Q_DBG("intr all", queue);
+ if ((rv = apr_thread_mutex_lock(queue->one_big_mutex)) != APR_SUCCESS) {
+ return rv;
+ }
+ apr_thread_cond_broadcast(queue->not_empty);
+ apr_thread_cond_broadcast(queue->not_full);
+
+ if ((rv = apr_thread_mutex_unlock(queue->one_big_mutex)) != APR_SUCCESS) {
+ return rv;
+ }
+
+ return APR_SUCCESS;
+}
+
+APU_DECLARE(apr_status_t) apr_queue_term(apr_queue_t *queue)
+{
+ apr_status_t rv;
+
+ if ((rv = apr_thread_mutex_lock(queue->one_big_mutex)) != APR_SUCCESS) {
+ return rv;
+ }
+
+ /* we must hold one_big_mutex when setting this... otherwise,
+ * we could end up setting it and waking everybody up just after a
+ * would-be popper checks it but right before they block
+ */
+ queue->terminated = 1;
+ if ((rv = apr_thread_mutex_unlock(queue->one_big_mutex)) != APR_SUCCESS) {
+ return rv;
+ }
+ return apr_queue_interrupt_all(queue);
+}
+
+#endif /* APR_HAS_THREADS */
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <assert.h>
+
+#include "apu.h"
+#include "apr_reslist.h"
+#include "apr_errno.h"
+#include "apr_strings.h"
+#include "apr_thread_mutex.h"
+#include "apr_thread_cond.h"
+#include "apr_ring.h"
+
+#if APR_HAS_THREADS
+
+/**
+ * A single resource element.
+ */
+struct apr_res_t {
+ apr_time_t freed;
+ void *opaque;
+ APR_RING_ENTRY(apr_res_t) link;
+};
+typedef struct apr_res_t apr_res_t;
+
+/**
+ * A ring of resources representing the list of available resources.
+ */
+APR_RING_HEAD(apr_resring_t, apr_res_t);
+typedef struct apr_resring_t apr_resring_t;
+
+struct apr_reslist_t {
+ apr_pool_t *pool; /* the pool used in constructor and destructor calls */
+ int ntotal; /* total number of resources managed by this list */
+ int nidle; /* number of available resources */
+ int min; /* desired minimum number of available resources */
+ int smax; /* soft maximum on the total number of resources */
+ int hmax; /* hard maximum on the total number of resources */
+ apr_interval_time_t ttl; /* TTL when we have too many resources */
+ apr_interval_time_t timeout; /* Timeout for waiting on resource */
+ apr_reslist_constructor constructor;
+ apr_reslist_destructor destructor;
+ void *params; /* opaque data passed to constructor and destructor calls */
+ apr_resring_t avail_list;
+ apr_resring_t free_list;
+ apr_thread_mutex_t *listlock;
+ apr_thread_cond_t *avail;
+};
+
+/**
+ * Grab a resource from the front of the resource list.
+ * Assumes: that the reslist is locked.
+ */
+static apr_res_t *pop_resource(apr_reslist_t *reslist)
+{
+ apr_res_t *res;
+ res = APR_RING_FIRST(&reslist->avail_list);
+ APR_RING_REMOVE(res, link);
+ reslist->nidle--;
+ return res;
+}
+
+/**
+ * Add a resource to the end of the list, set the time at which
+ * it was added to the list.
+ * Assumes: that the reslist is locked.
+ */
+static void push_resource(apr_reslist_t *reslist, apr_res_t *resource)
+{
+ APR_RING_INSERT_TAIL(&reslist->avail_list, resource, apr_res_t, link);
+ resource->freed = apr_time_now();
+ reslist->nidle++;
+}
+
+/**
+ * Get an resource container from the free list or create a new one.
+ */
+static apr_res_t *get_container(apr_reslist_t *reslist)
+{
+ apr_res_t *res;
+
+ if (!APR_RING_EMPTY(&reslist->free_list, apr_res_t, link)) {
+ res = APR_RING_FIRST(&reslist->free_list);
+ APR_RING_REMOVE(res, link);
+ }
+ else
+ res = apr_pcalloc(reslist->pool, sizeof(*res));
+ return res;
+}
+
+/**
+ * Free up a resource container by placing it on the free list.
+ */
+static void free_container(apr_reslist_t *reslist, apr_res_t *container)
+{
+ APR_RING_INSERT_TAIL(&reslist->free_list, container, apr_res_t, link);
+}
+
+/**
+ * Create a new resource and return it.
+ * Assumes: that the reslist is locked.
+ */
+static apr_status_t create_resource(apr_reslist_t *reslist, apr_res_t **ret_res)
+{
+ apr_status_t rv;
+ apr_res_t *res;
+
+ res = get_container(reslist);
+
+ rv = reslist->constructor(&res->opaque, reslist->params, reslist->pool);
+
+ *ret_res = res;
+ return rv;
+}
+
+/**
+ * Destroy a single idle resource.
+ * Assumes: that the reslist is locked.
+ */
+static apr_status_t destroy_resource(apr_reslist_t *reslist, apr_res_t *res)
+{
+ return reslist->destructor(res->opaque, reslist->params, reslist->pool);
+}
+
+static apr_status_t reslist_cleanup(void *data_)
+{
+ apr_status_t rv;
+ apr_reslist_t *rl = data_;
+ apr_res_t *res;
+
+ apr_thread_mutex_lock(rl->listlock);
+
+ while (rl->nidle > 0) {
+ res = pop_resource(rl);
+ rl->ntotal--;
+ rv = destroy_resource(rl, res);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+ free_container(rl, res);
+ }
+
+ assert(rl->nidle == 0);
+ assert(rl->ntotal == 0);
+
+ apr_thread_mutex_destroy(rl->listlock);
+ apr_thread_cond_destroy(rl->avail);
+
+ return APR_SUCCESS;
+}
+
+/**
+ * Perform routine maintenance on the resource list. This call
+ * may instantiate new resources or expire old resources.
+ */
+static apr_status_t reslist_maint(apr_reslist_t *reslist)
+{
+ apr_time_t now;
+ apr_status_t rv;
+ apr_res_t *res;
+ int created_one = 0;
+
+ apr_thread_mutex_lock(reslist->listlock);
+
+ /* Check if we need to create more resources, and if we are allowed to. */
+ while (reslist->nidle < reslist->min && reslist->ntotal <= reslist->hmax) {
+ /* Create the resource */
+ rv = create_resource(reslist, &res);
+ if (rv != APR_SUCCESS) {
+ free_container(reslist, res);
+ apr_thread_mutex_unlock(reslist->listlock);
+ return rv;
+ }
+ /* Add it to the list */
+ push_resource(reslist, res);
+ /* Update our counters */
+ reslist->ntotal++;
+ /* If someone is waiting on that guy, wake them up. */
+ rv = apr_thread_cond_signal(reslist->avail);
+ if (rv != APR_SUCCESS) {
+ apr_thread_mutex_unlock(reslist->listlock);
+ return rv;
+ }
+ created_one++;
+ }
+
+ /* We don't need to see if we're over the max if we were under it before */
+ if (created_one) {
+ apr_thread_mutex_unlock(reslist->listlock);
+ return APR_SUCCESS;
+ }
+
+ /* Check if we need to expire old resources */
+ now = apr_time_now();
+ while (reslist->nidle > reslist->smax && reslist->nidle > 0) {
+ /* Peak at the first resource in the list */
+ res = APR_RING_FIRST(&reslist->avail_list);
+ /* See if the oldest entry should be expired */
+ if (now - res->freed < reslist->ttl) {
+ /* If this entry is too young, none of the others
+ * will be ready to be expired either, so we are done. */
+ break;
+ }
+ res = pop_resource(reslist);
+ reslist->ntotal--;
+ rv = destroy_resource(reslist, res);
+ free_container(reslist, res);
+ if (rv != APR_SUCCESS) {
+ apr_thread_mutex_unlock(reslist->listlock);
+ return rv;
+ }
+ }
+
+ apr_thread_mutex_unlock(reslist->listlock);
+ return APR_SUCCESS;
+}
+
+APU_DECLARE(apr_status_t) apr_reslist_create(apr_reslist_t **reslist,
+ int min, int smax, int hmax,
+ apr_interval_time_t ttl,
+ apr_reslist_constructor con,
+ apr_reslist_destructor de,
+ void *params,
+ apr_pool_t *pool)
+{
+ apr_status_t rv;
+ apr_reslist_t *rl;
+
+ /* Do some sanity checks so we don't thrash around in the
+ * maintenance routine later. */
+ if (min > smax || min > hmax || smax > hmax || ttl < 0) {
+ return APR_EINVAL;
+ }
+
+ rl = apr_pcalloc(pool, sizeof(*rl));
+ rl->pool = pool;
+ rl->min = min;
+ rl->smax = smax;
+ rl->hmax = hmax;
+ rl->ttl = ttl;
+ rl->constructor = con;
+ rl->destructor = de;
+ rl->params = params;
+
+ APR_RING_INIT(&rl->avail_list, apr_res_t, link);
+ APR_RING_INIT(&rl->free_list, apr_res_t, link);
+
+ rv = apr_thread_mutex_create(&rl->listlock, APR_THREAD_MUTEX_DEFAULT,
+ pool);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+ rv = apr_thread_cond_create(&rl->avail, pool);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ rv = reslist_maint(rl);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ apr_pool_cleanup_register(rl->pool, rl, reslist_cleanup,
+ apr_pool_cleanup_null);
+
+ *reslist = rl;
+
+ return APR_SUCCESS;
+}
+
+APU_DECLARE(apr_status_t) apr_reslist_destroy(apr_reslist_t *reslist)
+{
+ return apr_pool_cleanup_run(reslist->pool, reslist, reslist_cleanup);
+}
+
+APU_DECLARE(apr_status_t) apr_reslist_acquire(apr_reslist_t *reslist,
+ void **resource)
+{
+ apr_status_t rv;
+ apr_res_t *res;
+
+ apr_thread_mutex_lock(reslist->listlock);
+ /* If there are idle resources on the available list, use
+ * them right away. */
+ if (reslist->nidle > 0) {
+ /* Pop off the first resource */
+ res = pop_resource(reslist);
+ *resource = res->opaque;
+ free_container(reslist, res);
+ apr_thread_mutex_unlock(reslist->listlock);
+ return APR_SUCCESS;
+ }
+ /* If we've hit our max, block until we're allowed to create
+ * a new one, or something becomes free. */
+ else while (reslist->ntotal >= reslist->hmax
+ && reslist->nidle <= 0) {
+ if (reslist->timeout) {
+ if ((rv = apr_thread_cond_timedwait(reslist->avail,
+ reslist->listlock, reslist->timeout)) != APR_SUCCESS) {
+ apr_thread_mutex_unlock(reslist->listlock);
+ return rv;
+ }
+ }
+ else
+ apr_thread_cond_wait(reslist->avail, reslist->listlock);
+ }
+ /* If we popped out of the loop, first try to see if there
+ * are new resources available for immediate use. */
+ if (reslist->nidle > 0) {
+ res = pop_resource(reslist);
+ *resource = res->opaque;
+ free_container(reslist, res);
+ apr_thread_mutex_unlock(reslist->listlock);
+ return APR_SUCCESS;
+ }
+ /* Otherwise the reason we dropped out of the loop
+ * was because there is a new slot available, so create
+ * a resource to fill the slot and use it. */
+ else {
+ rv = create_resource(reslist, &res);
+ if (rv == APR_SUCCESS) {
+ reslist->ntotal++;
+ *resource = res->opaque;
+ }
+ free_container(reslist, res);
+ apr_thread_mutex_unlock(reslist->listlock);
+ return rv;
+ }
+}
+
+APU_DECLARE(apr_status_t) apr_reslist_release(apr_reslist_t *reslist,
+ void *resource)
+{
+ apr_res_t *res;
+
+ apr_thread_mutex_lock(reslist->listlock);
+ res = get_container(reslist);
+ res->opaque = resource;
+ push_resource(reslist, res);
+ apr_thread_cond_signal(reslist->avail);
+ apr_thread_mutex_unlock(reslist->listlock);
+
+ return reslist_maint(reslist);
+}
+
+APU_DECLARE(void) apr_reslist_timeout_set(apr_reslist_t *reslist,
+ apr_interval_time_t timeout)
+{
+ reslist->timeout = timeout;
+}
+
+APU_DECLARE(apr_status_t) apr_reslist_invalidate(apr_reslist_t *reslist,
+ void *resource)
+{
+ apr_status_t ret;
+ apr_thread_mutex_lock(reslist->listlock);
+ ret = reslist->destructor(resource, reslist->params, reslist->pool);
+ reslist->ntotal--;
+ apr_thread_mutex_unlock(reslist->listlock);
+ return ret;
+}
+
+#endif /* APR_HAS_THREADS */
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_general.h"
+#include "apr_rmm.h"
+#include "apr_errno.h"
+#include "apr_lib.h"
+#include "apr_strings.h"
+
+typedef struct rmm_block_t {
+ apr_size_t size;
+ apr_rmm_off_t prev;
+ apr_rmm_off_t next;
+} rmm_block_t;
+
+/* Always at our apr_rmm_off(0):
+ */
+typedef struct rmm_hdr_block_t {
+ apr_size_t abssize;
+ apr_rmm_off_t /* rmm_block_t */ firstused;
+ apr_rmm_off_t /* rmm_block_t */ firstfree;
+} rmm_hdr_block_t;
+
+#define RMM_HDR_BLOCK_SIZE (APR_ALIGN_DEFAULT(sizeof(rmm_hdr_block_t)))
+#define RMM_BLOCK_SIZE (APR_ALIGN_DEFAULT(sizeof(rmm_block_t)))
+
+struct apr_rmm_t {
+ apr_pool_t *p;
+ rmm_hdr_block_t *base;
+ apr_size_t size;
+ apr_anylock_t lock;
+};
+
+static apr_rmm_off_t find_block_by_offset(apr_rmm_t *rmm, apr_rmm_off_t next,
+ apr_rmm_off_t find, int includes)
+{
+ apr_rmm_off_t prev = 0;
+
+ while (next) {
+ struct rmm_block_t *blk = (rmm_block_t*)((char*)rmm->base + next);
+
+ if (find == next)
+ return next;
+
+ /* Overshot? */
+ if (find < next)
+ return includes ? prev : 0;
+
+ prev = next;
+ next = blk->next;
+ }
+ return includes ? prev : 0;
+}
+
+static apr_rmm_off_t find_block_of_size(apr_rmm_t *rmm, apr_size_t size)
+{
+ apr_rmm_off_t next = rmm->base->firstfree;
+ apr_rmm_off_t best = 0;
+ apr_rmm_off_t bestsize = 0;
+
+ while (next) {
+ struct rmm_block_t *blk = (rmm_block_t*)((char*)rmm->base + next);
+
+ if (blk->size == size)
+ return next;
+
+ if (blk->size >= size) {
+ /* XXX: sub optimal algorithm
+ * We need the most thorough best-fit logic, since we can
+ * never grow our rmm, we are SOL when we hit the wall.
+ */
+ if (!bestsize || (blk->size < bestsize)) {
+ bestsize = blk->size;
+ best = next;
+ }
+ }
+
+ next = blk->next;
+ }
+
+ if (bestsize > RMM_BLOCK_SIZE + size) {
+ struct rmm_block_t *blk = (rmm_block_t*)((char*)rmm->base + best);
+ struct rmm_block_t *new = (rmm_block_t*)((char*)rmm->base + best + size);
+
+ new->size = blk->size - size;
+ new->next = blk->next;
+ new->prev = best;
+
+ blk->size = size;
+ blk->next = best + size;
+
+ if (new->next) {
+ blk = (rmm_block_t*)((char*)rmm->base + new->next);
+ blk->prev = best + size;
+ }
+ }
+
+ return best;
+}
+
+static void move_block(apr_rmm_t *rmm, apr_rmm_off_t this, int free)
+{
+ struct rmm_block_t *blk = (rmm_block_t*)((char*)rmm->base + this);
+
+ /* close the gap */
+ if (blk->prev) {
+ struct rmm_block_t *prev = (rmm_block_t*)((char*)rmm->base + blk->prev);
+ prev->next = blk->next;
+ }
+ else {
+ if (free) {
+ rmm->base->firstused = blk->next;
+ }
+ else {
+ rmm->base->firstfree = blk->next;
+ }
+ }
+ if (blk->next) {
+ struct rmm_block_t *next = (rmm_block_t*)((char*)rmm->base + blk->next);
+ next->prev = blk->prev;
+ }
+
+ /* now find it in the other list, pushing it to the head if required */
+ if (free) {
+ blk->prev = find_block_by_offset(rmm, rmm->base->firstfree, this, 1);
+ if (!blk->prev) {
+ blk->next = rmm->base->firstfree;
+ rmm->base->firstfree = this;
+ }
+ }
+ else {
+ blk->prev = find_block_by_offset(rmm, rmm->base->firstused, this, 1);
+ if (!blk->prev) {
+ blk->next = rmm->base->firstused;
+ rmm->base->firstused = this;
+ }
+ }
+
+ /* and open it up */
+ if (blk->prev) {
+ struct rmm_block_t *prev = (rmm_block_t*)((char*)rmm->base + blk->prev);
+ if (free && (blk->prev + prev->size == this)) {
+ /* Collapse us into our predecessor */
+ prev->size += blk->size;
+ this = blk->prev;
+ blk = prev;
+ }
+ else {
+ blk->next = prev->next;
+ prev->next = this;
+ }
+ }
+
+ if (blk->next) {
+ struct rmm_block_t *next = (rmm_block_t*)((char*)rmm->base + blk->next);
+ if (free && (this + blk->size == blk->next)) {
+ /* Collapse us into our successor */
+ blk->size += next->size;
+ blk->next = next->next;
+ if (blk->next) {
+ next = (rmm_block_t*)((char*)rmm->base + blk->next);
+ next->prev = this;
+ }
+ }
+ else {
+ next->prev = this;
+ }
+ }
+}
+
+APU_DECLARE(apr_status_t) apr_rmm_init(apr_rmm_t **rmm, apr_anylock_t *lock,
+ void *base, apr_size_t size,
+ apr_pool_t *p)
+{
+ apr_status_t rv;
+ rmm_block_t *blk;
+ apr_anylock_t nulllock;
+
+ if (!lock) {
+ nulllock.type = apr_anylock_none;
+ nulllock.lock.pm = NULL;
+ lock = &nulllock;
+ }
+ if ((rv = APR_ANYLOCK_LOCK(lock)) != APR_SUCCESS)
+ return rv;
+
+ (*rmm) = (apr_rmm_t *)apr_pcalloc(p, sizeof(apr_rmm_t));
+ (*rmm)->p = p;
+ (*rmm)->base = base;
+ (*rmm)->size = size;
+ (*rmm)->lock = *lock;
+
+ (*rmm)->base->abssize = size;
+ (*rmm)->base->firstused = 0;
+ (*rmm)->base->firstfree = RMM_HDR_BLOCK_SIZE;
+
+ blk = (rmm_block_t *)((char*)base + (*rmm)->base->firstfree);
+
+ blk->size = size - (*rmm)->base->firstfree;
+ blk->prev = 0;
+ blk->next = 0;
+
+ return APR_ANYLOCK_UNLOCK(lock);
+}
+
+APU_DECLARE(apr_status_t) apr_rmm_destroy(apr_rmm_t *rmm)
+{
+ apr_status_t rv;
+ rmm_block_t *blk;
+
+ if ((rv = APR_ANYLOCK_LOCK(&rmm->lock)) != APR_SUCCESS) {
+ return rv;
+ }
+ /* Blast it all --- no going back :) */
+ if (rmm->base->firstused) {
+ apr_rmm_off_t this = rmm->base->firstused;
+ do {
+ blk = (rmm_block_t *)((char*)rmm->base + this);
+ this = blk->next;
+ blk->next = blk->prev = 0;
+ } while (this);
+ rmm->base->firstused = 0;
+ }
+ if (rmm->base->firstfree) {
+ apr_rmm_off_t this = rmm->base->firstfree;
+ do {
+ blk = (rmm_block_t *)((char*)rmm->base + this);
+ this = blk->next;
+ blk->next = blk->prev = 0;
+ } while (this);
+ rmm->base->firstfree = 0;
+ }
+ rmm->base->abssize = 0;
+ rmm->size = 0;
+
+ return APR_ANYLOCK_UNLOCK(&rmm->lock);
+}
+
+APU_DECLARE(apr_status_t) apr_rmm_attach(apr_rmm_t **rmm, apr_anylock_t *lock,
+ void *base, apr_pool_t *p)
+{
+ apr_anylock_t nulllock;
+
+ if (!lock) {
+ nulllock.type = apr_anylock_none;
+ nulllock.lock.pm = NULL;
+ lock = &nulllock;
+ }
+
+ /* sanity would be good here */
+ (*rmm) = (apr_rmm_t *)apr_pcalloc(p, sizeof(apr_rmm_t));
+ (*rmm)->p = p;
+ (*rmm)->base = base;
+ (*rmm)->size = (*rmm)->base->abssize;
+ (*rmm)->lock = *lock;
+ return APR_SUCCESS;
+}
+
+APU_DECLARE(apr_status_t) apr_rmm_detach(apr_rmm_t *rmm)
+{
+ /* A noop until we introduce locked/refcounts */
+ return APR_SUCCESS;
+}
+
+APU_DECLARE(apr_rmm_off_t) apr_rmm_malloc(apr_rmm_t *rmm, apr_size_t reqsize)
+{
+ apr_rmm_off_t this;
+
+ reqsize = APR_ALIGN_DEFAULT(reqsize) + RMM_BLOCK_SIZE;
+
+ APR_ANYLOCK_LOCK(&rmm->lock);
+
+ this = find_block_of_size(rmm, reqsize);
+
+ if (this) {
+ move_block(rmm, this, 0);
+ this += RMM_BLOCK_SIZE;
+ }
+
+ APR_ANYLOCK_UNLOCK(&rmm->lock);
+ return this;
+}
+
+APU_DECLARE(apr_rmm_off_t) apr_rmm_calloc(apr_rmm_t *rmm, apr_size_t reqsize)
+{
+ apr_rmm_off_t this;
+
+ reqsize = APR_ALIGN_DEFAULT(reqsize) + RMM_BLOCK_SIZE;
+
+ APR_ANYLOCK_LOCK(&rmm->lock);
+
+ this = find_block_of_size(rmm, reqsize);
+
+ if (this) {
+ move_block(rmm, this, 0);
+ this += RMM_BLOCK_SIZE;
+ memset((char*)rmm->base + this, 0, reqsize - RMM_BLOCK_SIZE);
+ }
+
+ APR_ANYLOCK_UNLOCK(&rmm->lock);
+ return this;
+}
+
+APU_DECLARE(apr_rmm_off_t) apr_rmm_realloc(apr_rmm_t *rmm, void *entity,
+ apr_size_t reqsize)
+{
+ apr_rmm_off_t this;
+ apr_rmm_off_t old;
+ struct rmm_block_t *blk;
+ apr_size_t oldsize;
+
+ if (!entity) {
+ return apr_rmm_malloc(rmm, reqsize);
+ }
+
+ reqsize = APR_ALIGN_DEFAULT(reqsize);
+ old = apr_rmm_offset_get(rmm, entity);
+
+ if ((this = apr_rmm_malloc(rmm, reqsize)) == 0) {
+ return 0;
+ }
+
+ blk = (rmm_block_t*)((char*)rmm->base + old);
+ oldsize = blk->size;
+
+ memcpy(apr_rmm_addr_get(rmm, this),
+ apr_rmm_addr_get(rmm, old), oldsize < reqsize ? oldsize : reqsize);
+ apr_rmm_free(rmm, old);
+
+ return this;
+}
+
+APU_DECLARE(apr_status_t) apr_rmm_free(apr_rmm_t *rmm, apr_rmm_off_t this)
+{
+ apr_status_t rv;
+ struct rmm_block_t *blk;
+
+ /* A little sanity check is always healthy, especially here.
+ * If we really cared, we could make this compile-time
+ */
+ if (this < RMM_HDR_BLOCK_SIZE + RMM_BLOCK_SIZE) {
+ return APR_EINVAL;
+ }
+
+ this -= RMM_BLOCK_SIZE;
+
+ blk = (rmm_block_t*)((char*)rmm->base + this);
+
+ if ((rv = APR_ANYLOCK_LOCK(&rmm->lock)) != APR_SUCCESS) {
+ return rv;
+ }
+ if (blk->prev) {
+ struct rmm_block_t *prev = (rmm_block_t*)((char*)rmm->base + blk->prev);
+ if (prev->next != this) {
+ APR_ANYLOCK_UNLOCK(&rmm->lock);
+ return APR_EINVAL;
+ }
+ }
+ else {
+ if (rmm->base->firstused != this) {
+ APR_ANYLOCK_UNLOCK(&rmm->lock);
+ return APR_EINVAL;
+ }
+ }
+
+ if (blk->next) {
+ struct rmm_block_t *next = (rmm_block_t*)((char*)rmm->base + blk->next);
+ if (next->prev != this) {
+ APR_ANYLOCK_UNLOCK(&rmm->lock);
+ return APR_EINVAL;
+ }
+ }
+
+ /* Ok, it remained [apparently] sane, so unlink it
+ */
+ move_block(rmm, this, 1);
+
+ return APR_ANYLOCK_UNLOCK(&rmm->lock);
+}
+
+APU_DECLARE(void *) apr_rmm_addr_get(apr_rmm_t *rmm, apr_rmm_off_t entity)
+{
+ /* debug-sanity checking here would be good
+ */
+ return (void*)((char*)rmm->base + entity);
+}
+
+APU_DECLARE(apr_rmm_off_t) apr_rmm_offset_get(apr_rmm_t *rmm, void* entity)
+{
+ /* debug, or always, sanity checking here would be good
+ * since the primitive is apr_rmm_off_t, I don't mind penalizing
+ * inverse conversions for safety, unless someone can prove that
+ * there is no choice in some cases.
+ */
+ return ((char*)entity - (char*)rmm->base);
+}
+
+APU_DECLARE(apr_size_t) apr_rmm_overhead_get(int n)
+{
+ /* overhead per block is at most APR_ALIGN_DEFAULT(1) wasted bytes
+ * for alignment overhead, plus the size of the rmm_block_t
+ * structure. */
+ return RMM_HDR_BLOCK_SIZE + n * (RMM_BLOCK_SIZE + APR_ALIGN_DEFAULT(1));
+}
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_general.h" /* for APR_STRINGIFY */
+
+#include "apu.h"
+#include "apu_version.h"
+
+APU_DECLARE(void) apu_version(apr_version_t *pvsn)
+{
+ pvsn->major = APU_MAJOR_VERSION;
+ pvsn->minor = APU_MINOR_VERSION;
+ pvsn->patch = APU_PATCH_VERSION;
+#ifdef APU_IS_DEV_VERSION
+ pvsn->is_dev = 1;
+#else
+ pvsn->is_dev = 0;
+#endif
+}
+
+APU_DECLARE(const char *) apu_version_string(void)
+{
+ return APU_VERSION_STRING;
+}
--- /dev/null
+Symbol renames pending for apr-util (keep ordered and complete, please!)
+
--- /dev/null
+/* Copyright 2002-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_strmatch.h"
+#include "apr_lib.h"
+#define APR_WANT_STRFUNC
+#include "apr_want.h"
+
+
+#define NUM_CHARS 256
+
+/*
+ * String searching functions
+ */
+static const char *match_no_op(const apr_strmatch_pattern *this_pattern,
+ const char *s, apr_size_t slen)
+{
+ return s;
+}
+
+static const char *match_boyer_moore_horspool(
+ const apr_strmatch_pattern *this_pattern,
+ const char *s, apr_size_t slen)
+{
+ const char *s_end = s + slen;
+ int *shift = (int *)(this_pattern->context);
+ const char *s_next = s + this_pattern->length - 1;
+ const char *p_start = this_pattern->pattern;
+ const char *p_end = p_start + this_pattern->length - 1;
+ while (s_next < s_end) {
+ const char *s_tmp = s_next;
+ const char *p_tmp = p_end;
+ while (*s_tmp == *p_tmp) {
+ p_tmp--;
+ if (p_tmp < p_start) {
+ return s_tmp;
+ }
+ s_tmp--;
+ }
+ s_next += shift[(int)*((const unsigned char *)s_next)];
+ }
+ return NULL;
+}
+
+static const char *match_boyer_moore_horspool_nocase(
+ const apr_strmatch_pattern *this_pattern,
+ const char *s, apr_size_t slen)
+{
+ const char *s_end = s + slen;
+ int *shift = (int *)(this_pattern->context);
+ const char *s_next = s + this_pattern->length - 1;
+ const char *p_start = this_pattern->pattern;
+ const char *p_end = p_start + this_pattern->length - 1;
+ while (s_next < s_end) {
+ const char *s_tmp = s_next;
+ const char *p_tmp = p_end;
+ while (apr_tolower(*s_tmp) == apr_tolower(*p_tmp)) {
+ p_tmp--;
+ if (p_tmp < p_start) {
+ return s_tmp;
+ }
+ s_tmp--;
+ }
+ s_next += shift[apr_tolower(*s_next)];
+ }
+ return NULL;
+}
+
+APU_DECLARE(const apr_strmatch_pattern *) apr_strmatch_precompile(
+ apr_pool_t *p, const char *s,
+ int case_sensitive)
+{
+ apr_strmatch_pattern *pattern;
+ apr_size_t i;
+ int *shift;
+
+ pattern = apr_palloc(p, sizeof(*pattern));
+ pattern->pattern = s;
+ pattern->length = strlen(s);
+ if (pattern->length == 0) {
+ pattern->compare = match_no_op;
+ pattern->context = NULL;
+ return pattern;
+ }
+
+ shift = (int *)apr_palloc(p, sizeof(int) * NUM_CHARS);
+ for (i = 0; i < NUM_CHARS; i++) {
+ shift[i] = pattern->length;
+ }
+ if (case_sensitive) {
+ pattern->compare = match_boyer_moore_horspool;
+ for (i = 0; i < pattern->length - 1; i++) {
+ shift[(int)s[i]] = pattern->length - i - 1;
+ }
+ }
+ else {
+ pattern->compare = match_boyer_moore_horspool_nocase;
+ for (i = 0; i < pattern->length - 1; i++) {
+ shift[apr_tolower(s[i])] = pattern->length - i - 1;
+ }
+ }
+ pattern->context = shift;
+
+ return pattern;
+}
--- /dev/null
+VPATH = @srcdir@
+
+INCLUDES = @APRUTIL_PRIV_INCLUDES@ @APR_INCLUDES@ @APRUTIL_INCLUDES@
+
+PROGRAMS = testall testdbm testdate testxml testrmm \
+ testreslist testqueue testxlate dbd
+TARGETS = $(PROGRAMS)
+
+APRUTIL_DOTTED_VERSION=@APRUTIL_DOTTED_VERSION@
+APRUTIL_MAJOR_VERSION=@APRUTIL_MAJOR_VERSION@
+TARGET_LIB_PATH = ../lib@APRUTIL_LIBNAME@.la
+
+CLEAN_TARGETS = manyfile.bin testfile.txt
+
+# bring in rules.mk for standard functionality
+@INCLUDE_RULES@
+PROGRAM_DEPENDENCIES = @APRUTIL_LIBS@
+APRUTIL_LDFLAGS = -no-install @APRUTIL_LDFLAGS@
+
+all: $(PROGRAMS)
+
+check: $(PROGRAMS)
+ for prog in $(PROGRAMS); do \
+ ./$$prog ;\
+ if test $$? = 255; then \
+ echo "$$prog failed"; \
+ break; \
+ fi; \
+ done
+
+testdbm_OBJECTS = testdbm.lo
+testdbm_LDADD = $(TARGET_LIB_PATH)
+testdbm: $(testdbm_OBJECTS) $(testdbm_LDADD)
+ $(LINK) $(APRUTIL_LDFLAGS) $(testdbm_OBJECTS) $(testdbm_LDADD) $(PROGRAM_DEPENDENCIES)
+
+dbd_OBJECTS = dbd.lo
+dbd_LDADD = $(TARGET_LIB_PATH)
+dbd: $(dbd_OBJECTS) $(dbd_LDADD)
+ $(LINK) $(APRUTIL_LDFLAGS) $(dbd_OBJECTS) $(dbd_LDADD) $(PROGRAM_DEPENDENCIES)
+
+testdbd_OBJECTS = testdbd.lo
+testdbd_LDADD = $(TARGET_LIB_PATH)
+testdbd: $(testdbd_OBJECTS) $(testdbd_LDADD)
+ $(LINK) $(APRUTIL_LDFLAGS) $(testdbd_OBJECTS) $(testdbd_LDADD) $(PROGRAM_DEPENDENCIES)
+
+testdate_OBJECTS = testdate.lo
+testdate_LDADD = $(TARGET_LIB_PATH)
+testdate: $(testdate_OBJECTS) $(testdate_LDADD)
+ $(LINK) $(APRUTIL_LDFLAGS) $(testdate_OBJECTS) $(testdate_LDADD) $(PROGRAM_DEPENDENCIES)
+
+testxml_OBJECTS = testxml.lo
+testxml_LDADD = $(TARGET_LIB_PATH)
+testxml: $(testxml_OBJECTS) $(testxml_LDADD)
+ $(LINK) $(APRUTIL_LDFLAGS) $(testxml_OBJECTS) $(testxml_LDADD) $(PROGRAM_DEPENDENCIES)
+
+testrmm_OBJECTS = testrmm.lo
+testrmm_LDADD = $(TARGET_LIB_PATH)
+testrmm: $(testrmm_OBJECTS) $(testrmm_LDADD)
+ $(LINK) $(APRUTIL_LDFLAGS) $(testrmm_OBJECTS) $(testrmm_LDADD) $(PROGRAM_DEPENDENCIES)
+
+testreslist_OBJECTS = testreslist.lo
+testreslist_LDADD = $(TARGET_LIB_PATH)
+testreslist: $(testreslist_OBJECTS) $(testreslist_LDADD)
+ $(LINK) $(APRUTIL_LDFLAGS) $(testreslist_OBJECTS) $(testreslist_LDADD) $(PROGRAM_DEPENDENCIES)
+
+testqueue_OBJECTS = testqueue.lo
+testqueue_LDADD = $(TARGET_LIB_PATH)
+testqueue: $(testqueue_OBJECTS) $(testqueue_LDADD)
+ $(LINK) $(APRUTIL_LDFLAGS) $(testqueue_OBJECTS) $(testqueue_LDADD) $(PROGRAM_DEPENDENCIES)
+
+testxlate_OBJECTS = testxlate.lo
+testxlate_LDADD = $(TARGET_LIB_PATH)
+testxlate: $(testxlate_OBJECTS) $(testxlate_LDADD)
+ $(LINK) $(APRUTIL_LDFLAGS) $(testxlate_OBJECTS) $(testxlate_LDADD) $(PROGRAM_DEPENDENCIES)
+
+testall_OBJECTS = teststrmatch.lo testuri.lo testuuid.lo abts.lo testutil.lo \
+ testbuckets.lo testpass.lo testmd4.lo testmd5.lo testldap.lo testdbd.lo
+testall_LDADD = $(TARGET_LIB_PATH)
+testall: $(testall_OBJECTS) $(testall_LDADD)
+ $(LINK) $(APRUTIL_LDFLAGS) $(testall_OBJECTS) $(testall_LDADD) $(PROGRAM_DEPENDENCIES)
+
--- /dev/null
+# -*- Makefile -*-
+!IF "$(OS)" == "Windows_NT"
+NULL=
+rmdir=rd /s /q
+!ELSE
+NULL=nul
+rmdir=deltree /y
+!ENDIF
+
+SILENT=@
+
+# Default build and bind modes
+BUILD_MODE = release
+BIND_MODE = shared
+
+!IF "$(BUILD_MODE)" == "release" || "$(BUILD_MODE)" == "Release"
+!IF "$(BIND_MODE)" == "shared"
+# release shared
+APR_LIB_PFX = $(APR_SOURCE)\Release\lib
+APU_LIB_PFX = $(APU_SOURCE)\Release\lib
+API_LIB_PFX = $(API_SOURCE)\Release\lib
+CFG_CFLAGS = /MD /O2
+CFG_DEFINES = /D "NDEBUG"
+CFG_OUTPUT = Release
+
+!ELSE
+!IF "$(BIND_MODE)" == "static"
+# release static
+APR_LIB_PFX = $(APR_SOURCE)\LibR\ # no line continuation
+APU_LIB_PFX = $(APU_SOURCE)\LibR\ # no line continuation
+API_LIB_PFX = $(API_SOURCE)\LibR\ # no line continuation
+CFG_CFLAGS = /MD /O2
+CFG_DEFINES = /D "NDEBUG" /D "APR_DECLARE_STATIC" \
+ /D "APU_DECLARE_STATIC" /D "API_DECLARE_STATIC"
+CFG_API_LIB = $(API_LIB_PFX)apriconv-1.lib
+CFG_OUTPUT = LibR
+
+!ELSE
+!ERROR Unknown bind mode "$(BIND_MODE)"
+!ENDIF
+!ENDIF
+
+!ELSE
+!IF "$(BUILD_MODE)" == "debug" || "$(BUILD_MODE)" == "Debug"
+!IF "$(BIND_MODE)" == "shared"
+# debug shared
+APR_LIB_PFX = $(APR_SOURCE)\Debug\lib
+APU_LIB_PFX = $(APU_SOURCE)\Debug\lib
+API_LIB_PFX = $(API_SOURCE)\Debug\lib
+CFG_CFLAGS = /MDd /Zi /Od
+CFG_DEFINES = /D "_DEBUG"
+CFG_LDFLAGS = /DEBUG
+CFG_OUTPUT = Debug
+
+!ELSE
+!IF "$(BIND_MODE)" == "static"
+# debug static
+APR_LIB_PFX = $(APR_SOURCE)\LibD\ # no line continuation
+APU_LIB_PFX = $(APU_SOURCE)\LibD\ # no line continuation
+API_LIB_PFX = $(API_SOURCE)\LibD\ # no line continuation
+CFG_CFLAGS = /MDd /Zi /Od
+CFG_DEFINES = /D "_DEBUG" /D "APR_DECLARE_STATIC" \
+ /D "APU_DECLARE_STATIC" /D "API_DECLARE_STATIC"
+CFG_LDFLAGS = /DEBUG
+CFG_API_LIB = $(API_LIB_PFX)apriconv-1.lib
+CFG_OUTPUT = LibD
+
+!ELSE
+!ERROR Unknown bind mode "$(BIND_MODE)"
+!ENDIF
+!ENDIF
+
+!ELSE
+!ERROR Unknown build mode "$(BUILD_MODE)"
+!ENDIF
+!ENDIF
+
+
+APR_SOURCE = ..\..\apr
+APU_SOURCE = ..
+API_SOURCE = ..\..\apr-iconv
+OUTPUT_DIR = .\$(CFG_OUTPUT)
+
+INT_CFLAGS = /nologo $(CFG_CFLAGS) /Fp"$(OUTPUT_DIR)\iconv.pch" /YX"iconv.h"
+INT_INCLUDES = /I "$(APU_SOURCE)\include" /I "$(APR_SOURCE)\include"
+# /I "$(API_SOURCE)\include"
+INT_DEFINES = /D "WIN32" /D "_CONSOLE" /D "_MBCS" $(CFG_DEFINES)
+INT_LDFLAGS = /nologo /incremental:no /subsystem:console $(CFG_LDFLAGS)
+
+CFLAGS = /W3
+ALL_CFLAGS = $(INT_CFLAGS) $(INT_INCLUDES) $(INT_DEFINES) $(CFLAGS)
+
+LDFLAGS = /WARN:0
+ALL_LDFLAGS = $(INT_LDFLAGS) $(LDFLAGS)
+
+.c{$(OUTPUT_DIR)}.exe:
+ -$(SILENT)if not exist "$(OUTPUT_DIR)\$(NULL)" mkdir "$(OUTPUT_DIR)"
+ $(SILENT)echo Compiling and linking $@...
+ $(SILENT)cl $(ALL_CFLAGS) /Fo"$*.obj" /Fd"$*" $< \
+ /link $(ALL_LDFLAGS) /out:$@ \
+ "$(APU_LIB_PFX)aprutil-1.lib" \
+ "$(APR_LIB_PFX)apr-1.lib" \
+ "$(CFG_API)" \
+ kernel32.lib advapi32.lib ws2_32.lib mswsock.lib
+
+
+##!ALL_TARGETS = $(OUTPUT_DIR)\testdate.exe \
+##! $(OUTPUT_DIR)\testdbm.exe \
+##! $(OUTPUT_DIR)\testmd4.exe \
+##! $(OUTPUT_DIR)\testmd5.exe \
+##! $(OUTPUT_DIR)\testqueue.exe \
+##! $(OUTPUT_DIR)\testreslist.exe \
+##! $(OUTPUT_DIR)\testrmm.exe \
+##! $(OUTPUT_DIR)\teststrmatch.exe \
+##! $(OUTPUT_DIR)\testuri.exe \
+##! $(OUTPUT_DIR)\testuuid.exe \
+##! $(OUTPUT_DIR)\testxlate.exe \
+##! $(OUTPUT_DIR)\testxml.exe
+
+ALL_TARGETS = $(OUTPUT_DIR)\testxlate.exe \
+ $(OUTPUT_DIR)\testdbm.exe \
+ $(OUTPUT_DIR)\testqueue.exe \
+ $(OUTPUT_DIR)\testrmm.exe \
+ $(OUTPUT_DIR)\testmd4.exe \
+ $(OUTPUT_DIR)\testmd5.exe \
+ $(OUTPUT_DIR)\testxml.exe
+
+all: $(ALL_TARGETS)
+
+clean:
+ -$(SILENT)if exist "$(OUTPUT_DIR)/$(NULL)" $(rmdir) $(OUTPUT_DIR)
--- /dev/null
+#
+# Declare the sub-directories to be built here
+#
+
+SUBDIRS = \
+ $(EOLIST)
+
+#
+# Get the 'head' of the build environment. This includes default targets and
+# paths to tools
+#
+
+include $(APR_WORK)\build\NWGNUhead.inc
+
+#
+# build this level's files
+
+#
+# Make sure all needed macro's are defined
+#
+
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(APR)/include \
+ $(APR)/include/arch/NetWare \
+ $(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 =
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION = NLM is to test the apu layer
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME =
+
+#
+# This is used by the '-screenname' directive. If left blank,
+# 'Apache for NetWare' Thread will be used.
+#
+NLM_SCREEN_NAME =
+
+#
+# If this is specified, it will override VERSION value in
+# $(APR_WORK)\build\NWGNUenvironment.inc
+#
+NLM_VERSION =
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE =
+
+#
+# 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 this is 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 $(APR)/misc/netware/apache.xdc. XDCData can
+# be disabled by setting APACHE_UNIPROC in the environment
+#
+XDCDATA =
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(OBJDIR)/aputest.nlm \
+ $(OBJDIR)/testdate.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 = \
+ $(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 = \
+ $(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 \
+ $(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 the default copyright.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+ $(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ $(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 dependancies (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 $(APR_WORK)\build\NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+ copy $(OBJDIR)\*.nlm $(INSTALL)\Apache2
+
+#
+# Any specialized rules here
+#
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(APR_WORK)\build\NWGNUtail.inc
+
--- /dev/null
+/* Copyright 2000-2004 Ryan Bloom
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * Portions of this file were taken from testall.c in the APR test suite,
+ * written by members of the Apache Software Foundation.
+ */
+
+#include "abts.h"
+#include "abts_tests.h"
+#include "testutil.h"
+
+#define ABTS_STAT_SIZE 6
+static char status[ABTS_STAT_SIZE] = {'|', '/', '-', '|', '\\', '-'};
+static int curr_char;
+static int verbose = 0;
+static int exclude = 0;
+static int quiet = 0;
+static int list_tests = 0;
+
+const char **testlist = NULL;
+
+static int find_test_name(const char *testname) {
+ int i;
+ for (i = 0; testlist[i] != NULL; i++) {
+ if (!strcmp(testlist[i], testname)) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/* Determine if the test should be run at all */
+static int should_test_run(const char *testname) {
+ int found = 0;
+ if (list_tests == 1) {
+ return 0;
+ }
+ if (testlist == NULL) {
+ return 1;
+ }
+ found = find_test_name(testname);
+ if ((found && !exclude) || (!found && exclude)) {
+ return 1;
+ }
+ return 0;
+}
+
+static void reset_status(void)
+{
+ curr_char = 0;
+}
+
+static void update_status(void)
+{
+ if (!quiet) {
+ curr_char = (curr_char + 1) % ABTS_STAT_SIZE;
+ fprintf(stdout, "\b%c", status[curr_char]);
+ fflush(stdout);
+ }
+}
+
+static void end_suite(abts_suite *suite)
+{
+ if (suite != NULL) {
+ sub_suite *last = suite->tail;
+ if (!quiet) {
+ fprintf(stdout, "\b");
+ fflush(stdout);
+ }
+ if (last->failed == 0) {
+ fprintf(stdout, "SUCCESS\n");
+ fflush(stdout);
+ }
+ else {
+ fprintf(stdout, "FAILED %d of %d\n", last->failed, last->num_test);
+ fflush(stdout);
+ }
+ }
+}
+
+abts_suite *abts_add_suite(abts_suite *suite, const char *suite_name_full)
+{
+ sub_suite *subsuite;
+ char *p;
+ const char *suite_name;
+ curr_char = 0;
+
+ /* Only end the suite if we actually ran it */
+ if (suite && suite->tail &&!suite->tail->not_run) {
+ end_suite(suite);
+ }
+
+ subsuite = malloc(sizeof(*subsuite));
+ subsuite->num_test = 0;
+ subsuite->failed = 0;
+ subsuite->next = NULL;
+ /* suite_name_full may be an absolute path depending on __FILE__
+ * expansion */
+ suite_name = strrchr(suite_name_full, '/');
+ if (suite_name) {
+ suite_name++;
+ } else {
+ suite_name = suite_name_full;
+ }
+ p = strrchr(suite_name, '.');
+ if (p) {
+ subsuite->name = memcpy(calloc(p - suite_name + 1, 1),
+ suite_name, p - suite_name);
+ }
+ else {
+ subsuite->name = suite_name;
+ }
+
+ if (list_tests) {
+ fprintf(stdout, "%s\n", subsuite->name);
+ }
+
+ subsuite->not_run = 0;
+
+ if (suite == NULL) {
+ suite = malloc(sizeof(*suite));
+ suite->head = subsuite;
+ suite->tail = subsuite;
+ }
+ else {
+ suite->tail->next = subsuite;
+ suite->tail = subsuite;
+ }
+
+ if (!should_test_run(subsuite->name)) {
+ subsuite->not_run = 1;
+ return suite;
+ }
+
+ reset_status();
+ fprintf(stdout, "%-20s: ", subsuite->name);
+ update_status();
+ fflush(stdout);
+
+ return suite;
+}
+
+void abts_run_test(abts_suite *ts, test_func f, void *value)
+{
+ abts_case *tc;
+ sub_suite *ss;
+
+ if (!should_test_run(ts->tail->name)) {
+ return;
+ }
+ ss = ts->tail;
+
+ tc = malloc(sizeof(*tc));
+ tc->failed = 0;
+ tc->suite = ss;
+
+ ss->num_test++;
+ update_status();
+
+ f(tc, value);
+
+ if (tc->failed) {
+ ss->failed++;
+ }
+ free(tc);
+}
+
+static int report(abts_suite *suite)
+{
+ int count = 0;
+ sub_suite *dptr;
+
+ if (suite && suite->tail &&!suite->tail->not_run) {
+ end_suite(suite);
+ }
+
+ for (dptr = suite->head; dptr; dptr = dptr->next) {
+ count += dptr->failed;
+ }
+
+ if (list_tests) {
+ return 0;
+ }
+
+ if (count == 0) {
+ printf("All tests passed.\n");
+ return 0;
+ }
+
+ dptr = suite->head;
+ fprintf(stdout, "%-15s\t\tTotal\tFail\tFailed %%\n", "Failed Tests");
+ fprintf(stdout, "===================================================\n");
+ while (dptr != NULL) {
+ if (dptr->failed != 0) {
+ float percent = ((float)dptr->failed / (float)dptr->num_test);
+ fprintf(stdout, "%-15s\t\t%5d\t%4d\t%6.2f%%\n", dptr->name,
+ dptr->num_test, dptr->failed, percent * 100);
+ }
+ dptr = dptr->next;
+ }
+ return 1;
+}
+
+void abts_log_message(const char *fmt, ...)
+{
+ va_list args;
+ update_status();
+
+ if (verbose) {
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+ fprintf(stderr, "\n");
+ fflush(stderr);
+ }
+}
+
+void abts_int_equal(abts_case *tc, const int expected, const int actual, int lineno)
+{
+ update_status();
+ if (tc->failed) return;
+
+ if (expected == actual) return;
+
+ tc->failed = TRUE;
+ if (verbose) {
+ fprintf(stderr, "Line %d: expected <%d>, but saw <%d>\n", lineno, expected, actual);
+ fflush(stderr);
+ }
+}
+
+void abts_int_nequal(abts_case *tc, const int expected, const int actual, int lineno)
+{
+ update_status();
+ if (tc->failed) return;
+
+ if (expected != actual) return;
+
+ tc->failed = TRUE;
+ if (verbose) {
+ fprintf(stderr, "Line %d: expected <%d>, but saw <%d>\n", lineno, expected, actual);
+ fflush(stderr);
+ }
+}
+
+void abts_str_equal(abts_case *tc, const char *expected, const char *actual, int lineno)
+{
+ update_status();
+ if (tc->failed) return;
+
+ /* If both are NULL, match is good */
+ if (!expected && !actual) return;
+ if (expected && actual)
+ if (!strcmp(expected, actual)) return;
+
+ tc->failed = TRUE;
+ if (verbose) {
+ fprintf(stderr, "Line %d: expected <%s>, but saw <%s>\n", lineno, expected, actual);
+ fflush(stderr);
+ }
+}
+
+void abts_str_nequal(abts_case *tc, const char *expected, const char *actual,
+ size_t n, int lineno)
+{
+ update_status();
+ if (tc->failed) return;
+
+ if (!strncmp(expected, actual, n)) return;
+
+ tc->failed = TRUE;
+ if (verbose) {
+ fprintf(stderr, "Line %d: expected <%s>, but saw <%s>\n", lineno, expected, actual);
+ fflush(stderr);
+ }
+}
+
+void abts_ptr_notnull(abts_case *tc, const void *ptr, int lineno)
+{
+ update_status();
+ if (tc->failed) return;
+
+ if (ptr != NULL) return;
+
+ tc->failed = TRUE;
+ if (verbose) {
+ fprintf(stderr, "Line %d: Expected NULL, but saw <%p>\n", lineno, ptr);
+ fflush(stderr);
+ }
+}
+
+void abts_ptr_equal(abts_case *tc, const void *expected, const void *actual, int lineno)
+{
+ update_status();
+ if (tc->failed) return;
+
+ if (expected == actual) return;
+
+ tc->failed = TRUE;
+ if (verbose) {
+ fprintf(stderr, "Line %d: expected <%p>, but saw <%p>\n", lineno, expected, actual);
+ fflush(stderr);
+ }
+}
+
+void abts_fail(abts_case *tc, const char *message, int lineno)
+{
+ update_status();
+ if (tc->failed) return;
+
+ tc->failed = TRUE;
+ if (verbose) {
+ fprintf(stderr, "Line %d: %s\n", lineno, message);
+ fflush(stderr);
+ }
+}
+
+void abts_assert(abts_case *tc, const char *message, int condition, int lineno)
+{
+ update_status();
+ if (tc->failed) return;
+
+ if (condition) return;
+
+ tc->failed = TRUE;
+ if (verbose) {
+ fprintf(stderr, "Line %d: %s\n", lineno, message);
+ fflush(stderr);
+ }
+}
+
+void abts_true(abts_case *tc, int condition, int lineno)
+{
+ update_status();
+ if (tc->failed) return;
+
+ if (condition) return;
+
+ tc->failed = TRUE;
+ if (verbose) {
+ fprintf(stderr, "Line %d: Condition is false, but expected true\n", lineno);
+ fflush(stderr);
+ }
+}
+
+void abts_not_impl(abts_case *tc, const char *message, int lineno)
+{
+ update_status();
+
+ tc->suite->not_impl++;
+ if (verbose) {
+ fprintf(stderr, "Line %d: %s\n", lineno, message);
+ fflush(stderr);
+ }
+}
+
+int main(int argc, const char *const argv[]) {
+ int i;
+ int rv;
+ int list_provided = 0;
+ abts_suite *suite = NULL;
+
+ initialize();
+ for (i = 1; i < argc; i++) {
+ if (!strcmp(argv[i], "-v")) {
+ verbose = 1;
+ continue;
+ }
+ if (!strcmp(argv[i], "-x")) {
+ exclude = 1;
+ continue;
+ }
+ if (!strcmp(argv[i], "-l")) {
+ list_tests = 1;
+ continue;
+ }
+ if (!strcmp(argv[i], "-q")) {
+ quiet = 1;
+ continue;
+ }
+ if (argv[i][0] == '-') {
+ fprintf(stderr, "Invalid option: `%s'\n", argv[i]);
+ exit(1);
+ }
+ list_provided = 1;
+ }
+
+ if (list_provided) {
+ /* Waste a little space here, because it is easier than counting the
+ * number of tests listed. Besides it is at most three char *.
+ */
+ testlist = calloc(argc + 1, sizeof(char *));
+ for (i = 1; i < argc; i++) {
+ testlist[i - 1] = argv[i];
+ }
+ }
+
+ for (i = 0; i < (sizeof(alltests) / sizeof(struct testlist *)); i++) {
+ suite = alltests[i].func(suite);
+ }
+
+ rv = report(suite);
+ return rv;
+}
+
--- /dev/null
+/* Copyright 2000-2004 Ryan Bloom
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef ABTS_H
+#define ABTS_H
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+struct sub_suite {
+ const char *name;
+ int num_test;
+ int failed;
+ int not_run;
+ int not_impl;
+ struct sub_suite *next;
+};
+typedef struct sub_suite sub_suite;
+
+struct abts_suite {
+ sub_suite *head;
+ sub_suite *tail;
+};
+typedef struct abts_suite abts_suite;
+
+struct abts_case {
+ int failed;
+ sub_suite *suite;
+};
+typedef struct abts_case abts_case;
+
+typedef void (*test_func)(abts_case *tc, void *data);
+
+#define ADD_SUITE(suite) abts_add_suite(suite, __FILE__);
+
+abts_suite *abts_add_suite(abts_suite *suite, const char *suite_name);
+void abts_run_test(abts_suite *ts, test_func f, void *value);
+void abts_log_message(const char *fmt, ...);
+
+void abts_int_equal(abts_case *tc, const int expected, const int actual, int lineno);
+void abts_int_nequal(abts_case *tc, const int expected, const int actual, int lineno);
+void abts_str_equal(abts_case *tc, const char *expected, const char *actual, int lineno);
+void abts_str_nequal(abts_case *tc, const char *expected, const char *actual,
+ size_t n, int lineno);
+void abts_ptr_notnull(abts_case *tc, const void *ptr, int lineno);
+void abts_ptr_equal(abts_case *tc, const void *expected, const void *actual, int lineno);
+void abts_true(abts_case *tc, int condition, int lineno);
+void abts_fail(abts_case *tc, const char *message, int lineno);
+void abts_not_impl(abts_case *tc, const char *message, int lineno);
+void abts_assert(abts_case *tc, const char *message, int condition, int lineno);
+
+/* Convenience macros. Ryan hates these! */
+#define ABTS_INT_EQUAL(a, b, c) abts_int_equal(a, b, c, __LINE__)
+#define ABTS_INT_NEQUAL(a, b, c) abts_int_nequal(a, b, c, __LINE__)
+#define ABTS_STR_EQUAL(a, b, c) abts_str_equal(a, b, c, __LINE__)
+#define ABTS_STR_NEQUAL(a, b, c, d) abts_str_nequal(a, b, c, d, __LINE__)
+#define ABTS_PTR_NOTNULL(a, b) abts_ptr_notnull(a, b, __LINE__)
+#define ABTS_PTR_EQUAL(a, b, c) abts_ptr_equal(a, b, c, __LINE__)
+#define ABTS_TRUE(a, b) abts_true(a, b, __LINE__);
+#define ABTS_FAIL(a, b) abts_fail(a, b, __LINE__);
+#define ABTS_NOT_IMPL(a, b) abts_not_impl(a, b, __LINE__);
+#define ABTS_ASSERT(a, b, c) abts_assert(a, b, c, __LINE__);
+
+abts_suite *run_tests(abts_suite *suite);
+abts_suite *run_tests1(abts_suite *suite);
+
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef APR_TEST_INCLUDES
+#define APR_TEST_INCLUDES
+
+#include "abts.h"
+#include "testutil.h"
+
+const struct testlist {
+ abts_suite *(*func)(abts_suite *suite);
+} alltests[] = {
+ {teststrmatch},
+ {testuri},
+ {testuuid},
+ {testbuckets},
+ {testpass},
+ {testmd4},
+ {testmd5},
+ {testldap},
+ {testdbd}
+};
+
+#endif /* APR_TEST_INCLUDES */
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apu.h"
+#include "apr_pools.h"
+#include "apr_dbd.h"
+
+#include <stdio.h>
+
+#define TEST(msg,func) \
+ printf("======== %s ========\n", msg); \
+ rv = func(pool, sql, driver); \
+ if (rv != 0) { \
+ printf("Error in %s: rc=%d\n\n", msg, rv); \
+ } \
+ else { \
+ printf("%s test successful\n\n", msg); \
+ } \
+ fflush(stdout);
+
+static int create_table(apr_pool_t* pool, apr_dbd_t* handle,
+ apr_dbd_driver_t* driver)
+{
+ int rv = 0;
+ int nrows;
+ const char *statement = "CREATE TABLE apr_dbd_test ("
+ "col1 varchar(40) not null,"
+ "col2 varchar(40),"
+ "col3 integer)" ;
+ rv = apr_dbd_query(driver, handle, &nrows, statement);
+ return rv;
+}
+static int drop_table(apr_pool_t* pool, apr_dbd_t* handle,
+ apr_dbd_driver_t* driver)
+{
+ int rv = 0;
+ int nrows;
+ const char *statement = "DROP TABLE apr_dbd_test" ;
+ rv = apr_dbd_query(driver, handle, &nrows, statement);
+ return rv;
+}
+static int insert_rows(apr_pool_t* pool, apr_dbd_t* handle,
+ apr_dbd_driver_t* driver)
+{
+ int i;
+ int rv = 0;
+ int nrows;
+ int nerrors = 0;
+ const char *statement =
+ "INSERT into apr_dbd_test (col1) values ('foo');"
+ "INSERT into apr_dbd_test values ('wibble', 'other', 5);"
+ "INSERT into apr_dbd_test values ('wibble', 'nothing', 5);"
+ "INSERT into apr_dbd_test values ('qwerty', 'foo', 0);"
+ "INSERT into apr_dbd_test values ('asdfgh', 'bar', 1);"
+ ;
+ rv = apr_dbd_query(driver, handle, &nrows, statement);
+ if (rv) {
+ const char* stmt[] = {
+ "INSERT into apr_dbd_test (col1) values ('foo');",
+ "INSERT into apr_dbd_test values ('wibble', 'other', 5);",
+ "INSERT into apr_dbd_test values ('wibble', 'nothing', 5);",
+ "INSERT into apr_dbd_test values ('qwerty', 'foo', 0);",
+ "INSERT into apr_dbd_test values ('asdfgh', 'bar', 1);",
+ NULL
+ };
+ printf("Compound insert failed; trying statements one-by-one\n") ;
+ for (i=0; stmt[i] != NULL; ++i) {
+ statement = stmt[i];
+ rv = apr_dbd_query(driver, handle, &nrows, statement);
+ if (rv) {
+ nerrors++;
+ }
+ }
+ if (nerrors) {
+ printf("%d single inserts failed too.\n", nerrors) ;
+ }
+ }
+ return rv;
+}
+static int invalid_op(apr_pool_t* pool, apr_dbd_t* handle,
+ apr_dbd_driver_t* driver)
+{
+ int rv = 0;
+ int nrows;
+ const char *statement = "INSERT into apr_dbd_test1 (col2) values ('foo')" ;
+ rv = apr_dbd_query(driver, handle, &nrows, statement);
+ printf("invalid op returned %d (should be nonzero). Error msg follows\n", rv);
+ printf("'%s'\n", apr_dbd_error(driver, handle, rv));
+ statement = "INSERT into apr_dbd_test (col1, col2) values ('bar', 'foo')" ;
+ rv = apr_dbd_query(driver, handle, &nrows, statement);
+ printf("valid op returned %d (should be zero; error shouldn't affect subsequent ops)\n", rv);
+ return rv;
+}
+static int select_sequential(apr_pool_t* pool, apr_dbd_t* handle,
+ apr_dbd_driver_t* driver)
+{
+ int rv = 0;
+ int i = 0;
+ int n;
+ const char* entry;
+ const char* statement = "SELECT * FROM apr_dbd_test ORDER BY col1, col2";
+ apr_dbd_results_t *res = NULL;
+ apr_dbd_row_t *row = NULL;
+ rv = apr_dbd_select(driver,pool,handle,&res,statement,0);
+ if (rv) {
+ printf("Select failed: %s", apr_dbd_error(driver, handle, rv));
+ return rv;
+ }
+ for (rv = apr_dbd_get_row(driver, pool, res, &row, -1);
+ rv == 0;
+ rv = apr_dbd_get_row(driver, pool, res, &row, -1)) {
+ printf("ROW %d: ", i++) ;
+ for (n = 0; n < apr_dbd_num_cols(driver, res); ++n) {
+ entry = apr_dbd_get_entry(driver, row, n);
+ if (entry == NULL) {
+ printf("(null) ") ;
+ }
+ else {
+ printf("%s ", entry);
+ }
+ }
+ fputs("\n", stdout);
+ }
+ return (rv == -1) ? 0 : 1;
+}
+static int select_random(apr_pool_t* pool, apr_dbd_t* handle,
+ apr_dbd_driver_t* driver)
+{
+ int rv = 0;
+ int n;
+ const char* entry;
+ const char* statement = "SELECT * FROM apr_dbd_test ORDER BY col1, col2";
+ apr_dbd_results_t *res = NULL;
+ apr_dbd_row_t *row = NULL;
+ rv = apr_dbd_select(driver,pool,handle,&res,statement,1);
+ if (rv) {
+ printf("Select failed: %s", apr_dbd_error(driver, handle, rv));
+ return rv;
+ }
+ rv = apr_dbd_get_row(driver, pool, res, &row, 5) ;
+ if (rv) {
+ printf("get_row failed: %s", apr_dbd_error(driver, handle, rv));
+ return rv;
+ }
+ printf("ROW 5: ");
+ for (n = 0; n < apr_dbd_num_cols(driver, res); ++n) {
+ entry = apr_dbd_get_entry(driver, row, n);
+ if (entry == NULL) {
+ printf("(null) ") ;
+ }
+ else {
+ printf("%s ", entry);
+ }
+ }
+ fputs("\n", stdout);
+ rv = apr_dbd_get_row(driver, pool, res, &row, 1) ;
+ if (rv) {
+ printf("get_row failed: %s", apr_dbd_error(driver, handle, rv));
+ return rv;
+ }
+ printf("ROW 1: ");
+ for (n = 0; n < apr_dbd_num_cols(driver, res); ++n) {
+ entry = apr_dbd_get_entry(driver, row, n);
+ if (entry == NULL) {
+ printf("(null) ") ;
+ }
+ else {
+ printf("%s ", entry);
+ }
+ }
+ fputs("\n", stdout);
+ rv = apr_dbd_get_row(driver, pool, res, &row, 11) ;
+ if (rv != -1) {
+ printf("Oops! get_row out of range but thinks it succeeded!\n%s\n",
+ apr_dbd_error(driver, handle, rv));
+ return -1;
+ }
+ rv = 0;
+
+ return rv;
+}
+static int test_transactions(apr_pool_t* pool, apr_dbd_t* handle,
+ apr_dbd_driver_t* driver)
+{
+ int rv = 0;
+ int nrows;
+ apr_dbd_transaction_t *trans = NULL;
+ const char* statement;
+
+ /* trans 1 - error out early */
+ printf("Transaction 1\n");
+ rv = apr_dbd_transaction_start(driver, pool, handle, &trans);
+ if (rv) {
+ printf("Start transaction failed!\n%s\n",
+ apr_dbd_error(driver, handle, rv));
+ return rv;
+ }
+ statement = "UPDATE apr_dbd_test SET col2 = 'failed'";
+ rv = apr_dbd_query(driver, handle, &nrows, statement);
+ if (rv) {
+ printf("Update failed: '%s'\n", apr_dbd_error(driver, handle, rv));
+ apr_dbd_transaction_end(driver, pool, trans);
+ return rv;
+ }
+ printf("%d rows updated\n", nrows);
+
+ statement = "INSERT INTO apr_dbd_test1 (col3) values (3)";
+ rv = apr_dbd_query(driver, handle, &nrows, statement);
+ if (!rv) {
+ printf("Oops, invalid op succeeded but shouldn't!\n");
+ }
+ statement = "INSERT INTO apr_dbd_test values ('zzz', 'aaa', 3)";
+ rv = apr_dbd_query(driver, handle, &nrows, statement);
+ printf("Valid insert returned %d. Should be nonzero (fail) because transaction is bad\n", rv) ;
+
+ rv = apr_dbd_transaction_end(driver, pool, trans);
+ if (rv) {
+ printf("End transaction failed!\n%s\n",
+ apr_dbd_error(driver, handle, rv));
+ return rv;
+ }
+ printf("Transaction ended (should be rollback) - viewing table\n"
+ "A column of \"failed\" indicates transaction failed (no rollback)\n");
+ select_sequential(pool, handle, driver);
+
+ /* trans 2 - complete successfully */
+ printf("Transaction 2\n");
+ rv = apr_dbd_transaction_start(driver, pool, handle, &trans);
+ if (rv) {
+ printf("Start transaction failed!\n%s\n",
+ apr_dbd_error(driver, handle, rv));
+ return rv;
+ }
+ statement = "UPDATE apr_dbd_test SET col2 = 'success'";
+ rv = apr_dbd_query(driver, handle, &nrows, statement);
+ if (rv) {
+ printf("Update failed: '%s'\n", apr_dbd_error(driver, handle, rv));
+ apr_dbd_transaction_end(driver, pool, trans);
+ return rv;
+ }
+ printf("%d rows updated\n", nrows);
+ statement = "INSERT INTO apr_dbd_test values ('aaa', 'zzz', 3)";
+ rv = apr_dbd_query(driver, handle, &nrows, statement);
+ printf("Valid insert returned %d. Should be zero (OK)\n", rv) ;
+ rv = apr_dbd_transaction_end(driver, pool, trans);
+ if (rv) {
+ printf("End transaction failed!\n%s\n",
+ apr_dbd_error(driver, handle, rv));
+ return rv;
+ }
+ printf("Transaction ended (should be commit) - viewing table\n");
+ select_sequential(pool, handle, driver);
+ return rv;
+}
+static int test_pselect(apr_pool_t* pool, apr_dbd_t* handle,
+ apr_dbd_driver_t* driver)
+{
+ int rv = 0;
+ int i, n;
+ const char *query =
+ "SELECT * FROM apr_dbd_test WHERE col3 <= %s or col1 = 'bar'" ;
+ const char *label = "lowvalues";
+ apr_dbd_prepared_t *statement = NULL;
+ apr_dbd_results_t *res = NULL;
+ apr_dbd_row_t *row = NULL;
+ const char *entry = NULL;
+
+ rv = apr_dbd_prepare(driver, pool, handle, query, label, &statement);
+ if (rv) {
+ printf("Prepare statement failed!\n%s\n",
+ apr_dbd_error(driver, handle, rv));
+ return rv;
+ }
+ rv = driver->pvselect(pool, handle, &res, statement, 0, "3", NULL);
+ if (rv) {
+ printf("Exec of prepared statement failed!\n%s\n",
+ apr_dbd_error(driver, handle, rv));
+ return rv;
+ }
+ i = 0;
+ printf("Selecting rows where col3 <= 3 and bar row where it's unset.\nShould show four rows.\n");
+ for (rv = apr_dbd_get_row(driver, pool, res, &row, -1);
+ rv == 0;
+ rv = apr_dbd_get_row(driver, pool, res, &row, -1)) {
+ printf("ROW %d: ", i++) ;
+ for (n = 0; n < apr_dbd_num_cols(driver, res); ++n) {
+ entry = apr_dbd_get_entry(driver, row, n);
+ if (entry == NULL) {
+ printf("(null) ") ;
+ }
+ else {
+ printf("%s ", entry);
+ }
+ }
+ fputs("\n", stdout);
+ }
+ return (rv == -1) ? 0 : 1;
+}
+static int test_pquery(apr_pool_t* pool, apr_dbd_t* handle,
+ apr_dbd_driver_t* driver)
+{
+ int rv = 0;
+ const char *query = "INSERT INTO apr_dbd_test VALUES (%s, %s, %d)";
+ apr_dbd_prepared_t *statement = NULL;
+ const char *label = "testpquery";
+ int nrows;
+ apr_dbd_transaction_t *trans =0;
+
+ rv = apr_dbd_prepare(driver, pool, handle, query, label, &statement);
+ /* rv = apr_dbd_prepare(driver, pool, handle, query, NULL, &statement); */
+ if (rv) {
+ printf("Prepare statement failed!\n%s\n",
+ apr_dbd_error(driver, handle, rv));
+ return rv;
+ }
+ apr_dbd_transaction_start(driver, pool, handle, &trans);
+ rv = driver->pvquery(pool, handle, &nrows, statement,
+ "prepared", "insert", "2", NULL);
+ apr_dbd_transaction_end(driver, pool, trans);
+ if (rv) {
+ printf("Exec of prepared statement failed!\n%s\n",
+ apr_dbd_error(driver, handle, rv));
+ return rv;
+ }
+ printf("Showing table (should now contain row \"prepared insert 2\")\n");
+ select_sequential(pool, handle, driver);
+ return rv;
+}
+int main(int argc, char** argv)
+{
+ const char *name;
+ const char *params;
+ apr_pool_t *pool = NULL;
+ apr_dbd_t *sql = NULL;
+ apr_dbd_driver_t *driver = NULL;
+ int rv;
+
+ apr_initialize();
+ apr_pool_create(&pool, NULL);
+
+ if (argc >= 2 && argc <= 3) {
+ name = argv[1];
+ params = ( argc == 3 ) ? argv[2] : "";
+ apr_dbd_init(pool);
+ setbuf(stdout,NULL);
+ rv = apr_dbd_get_driver(pool, name, &driver);
+ switch (rv) {
+ case APR_SUCCESS:
+ printf("Loaded %s driver OK.\n", name);
+ break;
+ case APR_EDSOOPEN:
+ printf("Failed to load driver file apr_dbd_%s.so\n", name);
+ goto finish;
+ case APR_ESYMNOTFOUND:
+ printf("Failed to load driver apr_dbd_%s_driver.\n", name);
+ goto finish;
+ case APR_ENOTIMPL:
+ printf("No driver available for %s.\n", name);
+ goto finish;
+ default: /* it's a bug if none of the above happen */
+ printf("Internal error loading %s.\n", name);
+ goto finish;
+ }
+ rv = apr_dbd_open(driver, pool, params, &sql);
+ switch (rv) {
+ case APR_SUCCESS:
+ printf("Opened %s[%s] OK\n", name, params);
+ break;
+ case APR_EGENERAL:
+ printf("Failed to open %s[%s]\n", name, params);
+ goto finish;
+ default: /* it's a bug if none of the above happen */
+ printf("Internal error opening %s[%s]\n", name, params);
+ goto finish;
+ }
+ TEST("create table", create_table);
+ TEST("insert rows", insert_rows);
+ TEST("invalid op", invalid_op);
+ TEST("select random", select_random);
+ TEST("select sequential", select_sequential);
+ TEST("transactions", test_transactions);
+ TEST("prepared select", test_pselect);
+ TEST("prepared query", test_pquery);
+ TEST("drop table", drop_table);
+ apr_dbd_close(driver, sql);
+ }
+ else {
+ fprintf(stderr, "Usage: %s driver-name [params]\n", argv[0]);
+ }
+finish:
+ apr_pool_destroy(pool);
+ apr_terminate();
+ return 0;
+}
--- /dev/null
+#include <netware.h>
+#include <screen.h>
+#include "testutil.h"
+
+void _NonAppStop( void )
+{
+ pressanykey();
+}
+
+/*
+static void test_not_impl(CuTest *tc)
+{
+ CuNotImpl(tc, "Test not implemented on this platform yet");
+}
+*/
+
--- /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 $(APR_WORK)\build\NWGNUhead.inc
+endif
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(APR)/include \
+ $(APR)/include/arch/NetWare \
+ $(APRUTIL)/include \
+ $(LDAPSDK)/inc \
+ $(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 =aputest
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION = NLM is to test the apu layer
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME = aputest
+
+#
+# This is used by the '-screenname' directive. If left blank,
+# 'Apache for NetWare' Thread will be used.
+#
+NLM_SCREEN_NAME = aputest
+
+#
+# If this is specified, it will override VERSION value in
+# $(APR_WORK)\build\NWGNUenvironment.inc
+#
+NLM_VERSION = 1,0,0
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE = 524288
+
+#
+# If this is specified it will be used by the link '-entry' directive
+#
+NLM_ENTRY_SYM = _LibCPrelude
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM = _LibCPostlude
+
+#
+# If this is specified it will be used by the link '-check' directive
+#
+NLM_CHECK_SYM =
+
+#
+# If this is specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS = AUTOUNLOAD, PSEUDOPREEMPTION
+
+#
+# If this is specified it will be linked in with the XDCData option in the def
+# file instead of the default of $(APR)/misc/netware/apache.xdc. XDCData can
+# be disabled by setting APACHE_UNIPROC in the environment
+#
+XDCDATA =
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(OBJDIR)/aputest.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)/abts.o \
+ $(OBJDIR)/teststrmatch.o \
+ $(OBJDIR)/testuri.o \
+ $(OBJDIR)/testuuid.o \
+ $(OBJDIR)/testbuckets.o \
+ $(OBJDIR)/testpass.o \
+ $(OBJDIR)/testmd4.o \
+ $(OBJDIR)/testmd5.o \
+ $(OBJDIR)/testldap.o \
+ $(OBJDIR)/testutil.o \
+ $(OBJDIR)/nw_misc.o \
+ $(EOLIST)
+
+# Pending tests
+
+#
+# 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 = \
+ libcpre.o \
+ $(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 = \
+ Libc \
+ APRLIB \
+ lldapsdk \
+ lldapssl \
+ lldapx \
+ $(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 the default copyright.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+ @libc.imp \
+ @$(APR)/aprlib.imp \
+ @$(LDAPSDK)/imports/lldapsdk.imp \
+ @$(LDAPSDK)/imports/lldapssl.imp \
+ $(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ $(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 dependancies (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 $(APR_WORK)\build\NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(APR_WORK)\build\NWGNUtail.inc
+
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Some simple functions to make the test apps easier to write and
+ * a bit more consistent...
+ * this is a >copy< of apr_test.h
+ */
+
+/* Things to bear in mind when using these...
+ *
+ * If you include '\t' within the string passed in it won't be included
+ * in the spacing, so use spaces instead :)
+ *
+ */
+
+#ifndef APU_TEST_INCLUDES
+#define APU_TEST_INCLUDES
+
+#include "apr_strings.h"
+#include "apr_time.h"
+
+#define TEST_EQ(str, func, value, good, bad) \
+ printf("%-60s", str); \
+ { \
+ apr_status_t rv; \
+ if ((rv = func) == value){ \
+ char errmsg[200]; \
+ printf("%s\n", bad); \
+ fprintf(stderr, "Error was %d : %s\n", rv, \
+ apr_strerror(rv, (char*)&errmsg, 200)); \
+ exit(-1); \
+ } \
+ printf("%s\n", good); \
+ }
+
+#define TEST_NEQ(str, func, value, good, bad) \
+ printf("%-60s", str); \
+ { \
+ apr_status_t rv; \
+ if ((rv = func) != value){ \
+ char errmsg[200]; \
+ printf("%s\n", bad); \
+ fprintf(stderr, "Error was %d : %s\n", rv, \
+ apr_strerror(rv, (char*)&errmsg, 200)); \
+ exit(-1); \
+ } \
+ printf("%s\n", good); \
+ }
+
+#define TEST_STATUS(str, func, testmacro, good, bad) \
+ printf("%-60s", str); \
+ { \
+ apr_status_t rv = func; \
+ if (!testmacro(rv)) { \
+ char errmsg[200]; \
+ printf("%s\n", bad); \
+ fprintf(stderr, "Error was %d : %s\n", rv, \
+ apr_strerror(rv, (char*)&errmsg, 200)); \
+ exit(-1); \
+ } \
+ printf("%s\n", good); \
+ }
+
+#define STD_TEST_NEQ(str, func) \
+ TEST_NEQ(str, func, APR_SUCCESS, "OK", "Failed");
+
+#define PRINT_ERROR(rv) \
+ { \
+ char errmsg[200]; \
+ fprintf(stderr, "Error was %d : %s\n", rv, \
+ apr_strerror(rv, (char*)&errmsg, 200)); \
+ exit(-1); \
+ }
+
+#define MSG_AND_EXIT(msg) \
+ printf("%s\n", msg); \
+ exit (-1);
+
+#define TIME_FUNCTION(time, function) \
+ { \
+ apr_time_t tt = apr_time_now(); \
+ function; \
+ time = apr_time_now() - tt; \
+ }
+
+
+#endif /* APU_TEST_INCLUDES */
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "abts.h"
+#include "testutil.h"
+#include "apr_buckets.h"
+#include "apr_strings.h"
+
+static void test_create(abts_case *tc, void *data)
+{
+ apr_bucket_alloc_t *ba;
+ apr_bucket_brigade *bb;
+
+ ba = apr_bucket_alloc_create(p);
+ bb = apr_brigade_create(p, ba);
+
+ ABTS_ASSERT(tc, "new brigade not NULL", bb != NULL);
+ ABTS_ASSERT(tc, "new brigade is empty", APR_BRIGADE_EMPTY(bb));
+
+ apr_brigade_destroy(bb);
+ apr_bucket_alloc_destroy(ba);
+}
+
+static void test_simple(abts_case *tc, void *data)
+{
+ apr_bucket_alloc_t *ba;
+ apr_bucket_brigade *bb;
+ apr_bucket *fb, *tb;
+
+ ba = apr_bucket_alloc_create(p);
+ bb = apr_brigade_create(p, ba);
+
+ fb = APR_BRIGADE_FIRST(bb);
+ ABTS_ASSERT(tc, "first bucket of empty brigade is sentinel",
+ fb == APR_BRIGADE_SENTINEL(bb));
+
+ fb = apr_bucket_flush_create(ba);
+ APR_BRIGADE_INSERT_HEAD(bb, fb);
+
+ ABTS_ASSERT(tc, "first bucket of brigade is flush",
+ APR_BRIGADE_FIRST(bb) == fb);
+
+ ABTS_ASSERT(tc, "bucket after flush is sentinel",
+ APR_BUCKET_NEXT(fb) == APR_BRIGADE_SENTINEL(bb));
+
+ tb = apr_bucket_transient_create("aaa", 3, ba);
+ APR_BUCKET_INSERT_BEFORE(fb, tb);
+
+ ABTS_ASSERT(tc, "bucket before flush now transient",
+ APR_BUCKET_PREV(fb) == tb);
+ ABTS_ASSERT(tc, "bucket after transient is flush",
+ APR_BUCKET_NEXT(tb) == fb);
+ ABTS_ASSERT(tc, "bucket before transient is sentinel",
+ APR_BUCKET_PREV(tb) == APR_BRIGADE_SENTINEL(bb));
+
+ apr_brigade_cleanup(bb);
+
+ ABTS_ASSERT(tc, "cleaned up brigade was empty", APR_BRIGADE_EMPTY(bb));
+
+ apr_brigade_destroy(bb);
+ apr_bucket_alloc_destroy(ba);
+}
+
+static apr_bucket_brigade *make_simple_brigade(apr_bucket_alloc_t *ba,
+ const char *first,
+ const char *second)
+{
+ apr_bucket_brigade *bb = apr_brigade_create(p, ba);
+ apr_bucket *e;
+
+ e = apr_bucket_transient_create(first, strlen(first), ba);
+ APR_BRIGADE_INSERT_TAIL(bb, e);
+
+ e = apr_bucket_transient_create(second, strlen(second), ba);
+ APR_BRIGADE_INSERT_TAIL(bb, e);
+
+ return bb;
+}
+
+/* tests that 'bb' flattens to string 'expect'. */
+static void flatten_match(abts_case *tc, const char *ctx,
+ apr_bucket_brigade *bb,
+ const char *expect)
+{
+ apr_size_t elen = strlen(expect);
+ char *buf = malloc(elen);
+ apr_size_t len = elen;
+ char msg[200];
+
+ sprintf(msg, "%s: flatten brigade", ctx);
+ apr_assert_success(tc, msg, apr_brigade_flatten(bb, buf, &len));
+ sprintf(msg, "%s: length match (%ld not %ld)", ctx,
+ (long)len, (long)elen);
+ ABTS_ASSERT(tc, msg, len == elen);
+ sprintf(msg, "%s: result match", msg);
+ ABTS_STR_NEQUAL(tc, expect, buf, len);
+ free(buf);
+}
+
+static void test_flatten(abts_case *tc, void *data)
+{
+ apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
+ apr_bucket_brigade *bb;
+
+ bb = make_simple_brigade(ba, "hello, ", "world");
+
+ flatten_match(tc, "flatten brigade", bb, "hello, world");
+
+ apr_brigade_destroy(bb);
+ apr_bucket_alloc_destroy(ba);
+}
+
+static int count_buckets(apr_bucket_brigade *bb)
+{
+ apr_bucket *e;
+ int count = 0;
+
+ for (e = APR_BRIGADE_FIRST(bb);
+ e != APR_BRIGADE_SENTINEL(bb);
+ e = APR_BUCKET_NEXT(e)) {
+ count++;
+ }
+
+ return count;
+}
+
+static void test_split(abts_case *tc, void *data)
+{
+ apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
+ apr_bucket_brigade *bb, *bb2;
+ apr_bucket *e;
+
+ bb = make_simple_brigade(ba, "hello, ", "world");
+
+ /* split at the "world" bucket */
+ e = APR_BRIGADE_LAST(bb);
+ bb2 = apr_brigade_split(bb, e);
+
+ ABTS_ASSERT(tc, "split brigade contains one bucket",
+ count_buckets(bb2) == 1);
+ ABTS_ASSERT(tc, "original brigade contains one bucket",
+ count_buckets(bb) == 1);
+
+ flatten_match(tc, "match original brigade", bb, "hello, ");
+ flatten_match(tc, "match split brigade", bb2, "world");
+
+ apr_brigade_destroy(bb2);
+ apr_brigade_destroy(bb);
+ apr_bucket_alloc_destroy(ba);
+}
+
+#define COUNT 3000
+#define THESTR "hello"
+
+static void test_bwrite(abts_case *tc, void *data)
+{
+ apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
+ apr_bucket_brigade *bb = apr_brigade_create(p, ba);
+ apr_off_t length;
+ int n;
+
+ for (n = 0; n < COUNT; n++) {
+ apr_assert_success(tc, "brigade_write",
+ apr_brigade_write(bb, NULL, NULL,
+ THESTR, sizeof THESTR));
+ }
+
+ apr_assert_success(tc, "determine brigade length",
+ apr_brigade_length(bb, 1, &length));
+
+ ABTS_ASSERT(tc, "brigade has correct length",
+ length == (COUNT * sizeof THESTR));
+
+ apr_brigade_destroy(bb);
+ apr_bucket_alloc_destroy(ba);
+}
+
+static void test_splitline(abts_case *tc, void *data)
+{
+ apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
+ apr_bucket_brigade *bin, *bout;
+
+ bin = make_simple_brigade(ba, "blah blah blah-",
+ "end of line.\nfoo foo foo");
+ bout = apr_brigade_create(p, ba);
+
+ apr_assert_success(tc, "split line",
+ apr_brigade_split_line(bout, bin,
+ APR_BLOCK_READ, 100));
+
+ flatten_match(tc, "split line", bout, "blah blah blah-end of line.\n");
+ flatten_match(tc, "remainder", bin, "foo foo foo");
+
+ apr_brigade_destroy(bout);
+ apr_brigade_destroy(bin);
+ apr_bucket_alloc_destroy(ba);
+}
+
+
+static void test_splits(abts_case *tc, void *ctx)
+{
+ apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
+ apr_bucket_brigade *bb;
+ apr_bucket *e;
+ char *str = "alphabeta";
+ int n;
+
+ bb = apr_brigade_create(p, ba);
+
+ APR_BRIGADE_INSERT_TAIL(bb,
+ apr_bucket_immortal_create(str, 9, ba));
+ APR_BRIGADE_INSERT_TAIL(bb,
+ apr_bucket_transient_create(str, 9, ba));
+ APR_BRIGADE_INSERT_TAIL(bb,
+ apr_bucket_heap_create(strdup(str), 9, free, ba));
+ APR_BRIGADE_INSERT_TAIL(bb,
+ apr_bucket_pool_create(apr_pstrdup(p, str), 9, p,
+ ba));
+
+ ABTS_ASSERT(tc, "four buckets inserted", count_buckets(bb) == 4);
+
+ /* now split each of the buckets after byte 5 */
+ for (n = 0, e = APR_BRIGADE_FIRST(bb); n < 4; n++) {
+ ABTS_ASSERT(tc, "reached end of brigade",
+ e != APR_BRIGADE_SENTINEL(bb));
+ ABTS_ASSERT(tc, "split bucket OK",
+ apr_bucket_split(e, 5) == APR_SUCCESS);
+ e = APR_BUCKET_NEXT(e);
+ ABTS_ASSERT(tc, "split OK", e != APR_BRIGADE_SENTINEL(bb));
+ e = APR_BUCKET_NEXT(e);
+ }
+
+ ABTS_ASSERT(tc, "four buckets split into eight",
+ count_buckets(bb) == 8);
+
+ for (n = 0, e = APR_BRIGADE_FIRST(bb); n < 4; n++) {
+ const char *data;
+ apr_size_t len;
+
+ apr_assert_success(tc, "read alpha from bucket",
+ apr_bucket_read(e, &data, &len, APR_BLOCK_READ));
+ ABTS_ASSERT(tc, "read 5 bytes", len == 5);
+ ABTS_STR_NEQUAL(tc, "alpha", data, 5);
+
+ e = APR_BUCKET_NEXT(e);
+
+ apr_assert_success(tc, "read beta from bucket",
+ apr_bucket_read(e, &data, &len, APR_BLOCK_READ));
+ ABTS_ASSERT(tc, "read 4 bytes", len == 4);
+ ABTS_STR_NEQUAL(tc, "beta", data, 5);
+
+ e = APR_BUCKET_NEXT(e);
+ }
+
+ /* now delete the "alpha" buckets */
+ for (n = 0, e = APR_BRIGADE_FIRST(bb); n < 4; n++) {
+ apr_bucket *f;
+
+ ABTS_ASSERT(tc, "reached end of brigade",
+ e != APR_BRIGADE_SENTINEL(bb));
+ f = APR_BUCKET_NEXT(e);
+ apr_bucket_delete(e);
+ e = APR_BUCKET_NEXT(f);
+ }
+
+ ABTS_ASSERT(tc, "eight buckets reduced to four",
+ count_buckets(bb) == 4);
+
+ flatten_match(tc, "flatten beta brigade", bb,
+ "beta" "beta" "beta" "beta");
+
+ apr_brigade_destroy(bb);
+ apr_bucket_alloc_destroy(ba);
+}
+
+#define TIF_FNAME "testfile.txt"
+
+static void test_insertfile(abts_case *tc, void *ctx)
+{
+ apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
+ apr_bucket_brigade *bb;
+ const apr_off_t bignum = (APR_INT64_C(2) << 32) + 424242;
+ apr_off_t count;
+ apr_file_t *f;
+ apr_bucket *e;
+
+ ABTS_ASSERT(tc, "open test file",
+ apr_file_open(&f, TIF_FNAME,
+ APR_WRITE|APR_TRUNCATE|APR_CREATE,
+ APR_OS_DEFAULT, p) == APR_SUCCESS);
+
+ if (apr_file_trunc(f, bignum)) {
+ apr_file_close(f);
+ apr_file_remove(TIF_FNAME, p);
+ ABTS_NOT_IMPL(tc, "Skipped: could not create large file");
+ return;
+ }
+
+ bb = apr_brigade_create(p, ba);
+
+ e = apr_brigade_insert_file(bb, f, 0, bignum, p);
+
+ ABTS_ASSERT(tc, "inserted file was not at end of brigade",
+ e == APR_BRIGADE_LAST(bb));
+
+ /* check that the total size of inserted buckets is equal to the
+ * total size of the file. */
+ count = 0;
+
+ for (e = APR_BRIGADE_FIRST(bb);
+ e != APR_BRIGADE_SENTINEL(bb);
+ e = APR_BUCKET_NEXT(e)) {
+ ABTS_ASSERT(tc, "bucket size sane", e->length != (apr_size_t)-1);
+ count += e->length;
+ }
+
+ ABTS_ASSERT(tc, "total size of buckets incorrect", count == bignum);
+
+ apr_brigade_destroy(bb);
+ apr_file_close(f);
+ apr_bucket_alloc_destroy(ba);
+ apr_file_remove(TIF_FNAME, p);
+}
+
+/* Make a test file named FNAME, and write CONTENTS to it. */
+static apr_file_t *make_test_file(abts_case *tc, const char *fname,
+ const char *contents)
+{
+ apr_file_t *f;
+
+ ABTS_ASSERT(tc, "create test file",
+ apr_file_open(&f, fname,
+ APR_READ|APR_WRITE|APR_TRUNCATE|APR_CREATE,
+ APR_OS_DEFAULT, p) == APR_SUCCESS);
+
+ ABTS_ASSERT(tc, "write test file contents",
+ apr_file_puts(contents, f) == APR_SUCCESS);
+
+ return f;
+}
+
+static void test_manyfile(abts_case *tc, void *data)
+{
+ apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
+ apr_bucket_brigade *bb = apr_brigade_create(p, ba);
+ apr_file_t *f;
+
+ f = make_test_file(tc, "manyfile.bin",
+ "world" "hello" "brave" " ,\n");
+
+ apr_brigade_insert_file(bb, f, 5, 5, p);
+ apr_brigade_insert_file(bb, f, 16, 1, p);
+ apr_brigade_insert_file(bb, f, 15, 1, p);
+ apr_brigade_insert_file(bb, f, 10, 5, p);
+ apr_brigade_insert_file(bb, f, 15, 1, p);
+ apr_brigade_insert_file(bb, f, 0, 5, p);
+ apr_brigade_insert_file(bb, f, 17, 1, p);
+
+ /* can you tell what it is yet? */
+ flatten_match(tc, "file seek test", bb,
+ "hello, brave world\n");
+
+ apr_file_close(f);
+ apr_brigade_destroy(bb);
+ apr_bucket_alloc_destroy(ba);
+}
+
+/* Regression test for PR 34708, where a file bucket will keep
+ * duplicating itself on being read() when EOF is reached
+ * prematurely. */
+static void test_truncfile(abts_case *tc, void *data)
+{
+ apr_bucket_alloc_t *ba = apr_bucket_alloc_create(p);
+ apr_bucket_brigade *bb = apr_brigade_create(p, ba);
+ apr_file_t *f = make_test_file(tc, "testfile.txt", "hello");
+ apr_bucket *e;
+ const char *buf;
+ apr_size_t len;
+
+ apr_brigade_insert_file(bb, f, 0, 5, p);
+
+ apr_file_trunc(f, 0);
+
+ e = APR_BRIGADE_FIRST(bb);
+
+ ABTS_ASSERT(tc, "single bucket in brigade",
+ APR_BUCKET_NEXT(e) == APR_BRIGADE_SENTINEL(bb));
+
+ apr_bucket_file_enable_mmap(e, 0);
+
+ ABTS_ASSERT(tc, "read gave APR_EOF",
+ apr_bucket_read(e, &buf, &len, APR_BLOCK_READ) == APR_EOF);
+
+ ABTS_ASSERT(tc, "read length 0", len == 0);
+
+ ABTS_ASSERT(tc, "still a single bucket in brigade",
+ APR_BUCKET_NEXT(e) == APR_BRIGADE_SENTINEL(bb));
+
+ apr_file_close(f);
+ apr_brigade_destroy(bb);
+ apr_bucket_alloc_destroy(ba);
+}
+
+abts_suite *testbuckets(abts_suite *suite)
+{
+ suite = ADD_SUITE(suite);
+
+ abts_run_test(suite, test_create, NULL);
+ abts_run_test(suite, test_simple, NULL);
+ abts_run_test(suite, test_flatten, NULL);
+ abts_run_test(suite, test_split, NULL);
+ abts_run_test(suite, test_bwrite, NULL);
+ abts_run_test(suite, test_splitline, NULL);
+ abts_run_test(suite, test_splits, NULL);
+ abts_run_test(suite, test_insertfile, NULL);
+ abts_run_test(suite, test_manyfile, NULL);
+ abts_run_test(suite, test_truncfile, NULL);
+
+ return suite;
+}
+
+
--- /dev/null
+/* This program tests the date_parse_http routine in ../main/util_date.c.
+ *
+ * It is only semiautomated in that I would run it, modify the code to
+ * use a different algorithm or seed, recompile and run again, etc.
+ * Obviously it should use an argument for that, but I never got around
+ * to changing the implementation.
+ *
+ * gcc -g -O2 -I../main -o test_date ../main/util_date.o test_date.c
+ * test_date | egrep '^No '
+ *
+ * Roy Fielding, 1996
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include "apr_date.h"
+
+#ifndef srand48
+#define srand48 srandom
+#endif
+
+#ifndef mrand48
+#define mrand48 random
+#endif
+
+void gm_timestr_822(char *ts, apr_time_t sec);
+void gm_timestr_850(char *ts, apr_time_t sec);
+void gm_timestr_ccc(char *ts, apr_time_t sec);
+
+static const apr_time_t year2secs[] = {
+ 0LL, /* 1970 */
+ 31536000LL, /* 1971 */
+ 63072000LL, /* 1972 */
+ 94694400LL, /* 1973 */
+ 126230400LL, /* 1974 */
+ 157766400LL, /* 1975 */
+ 189302400LL, /* 1976 */
+ 220924800LL, /* 1977 */
+ 252460800LL, /* 1978 */
+ 283996800LL, /* 1979 */
+ 315532800LL, /* 1980 */
+ 347155200LL, /* 1981 */
+ 378691200LL, /* 1982 */
+ 410227200LL, /* 1983 */
+ 441763200LL, /* 1984 */
+ 473385600LL, /* 1985 */
+ 504921600LL, /* 1986 */
+ 536457600LL, /* 1987 */
+ 567993600LL, /* 1988 */
+ 599616000LL, /* 1989 */
+ 631152000LL, /* 1990 */
+ 662688000LL, /* 1991 */
+ 694224000LL, /* 1992 */
+ 725846400LL, /* 1993 */
+ 757382400LL, /* 1994 */
+ 788918400LL, /* 1995 */
+ 820454400LL, /* 1996 */
+ 852076800LL, /* 1997 */
+ 883612800LL, /* 1998 */
+ 915148800LL, /* 1999 */
+ 946684800LL, /* 2000 */
+ 978307200LL, /* 2001 */
+ 1009843200LL, /* 2002 */
+ 1041379200LL, /* 2003 */
+ 1072915200LL, /* 2004 */
+ 1104537600LL, /* 2005 */
+ 1136073600LL, /* 2006 */
+ 1167609600LL, /* 2007 */
+ 1199145600LL, /* 2008 */
+ 1230768000LL, /* 2009 */
+ 1262304000LL, /* 2010 */
+ 1293840000LL, /* 2011 */
+ 1325376000LL, /* 2012 */
+ 1356998400LL, /* 2013 */
+ 1388534400LL, /* 2014 */
+ 1420070400LL, /* 2015 */
+ 1451606400LL, /* 2016 */
+ 1483228800LL, /* 2017 */
+ 1514764800LL, /* 2018 */
+ 1546300800LL, /* 2019 */
+ 1577836800LL, /* 2020 */
+ 1609459200LL, /* 2021 */
+ 1640995200LL, /* 2022 */
+ 1672531200LL, /* 2023 */
+ 1704067200LL, /* 2024 */
+ 1735689600LL, /* 2025 */
+ 1767225600LL, /* 2026 */
+ 1798761600LL, /* 2027 */
+ 1830297600LL, /* 2028 */
+ 1861920000LL, /* 2029 */
+ 1893456000LL, /* 2030 */
+ 1924992000LL, /* 2031 */
+ 1956528000LL, /* 2032 */
+ 1988150400LL, /* 2033 */
+ 2019686400LL, /* 2034 */
+ 2051222400LL, /* 2035 */
+ 2082758400LL, /* 2036 */
+ 2114380800LL, /* 2037 */
+ 2145916800LL /* 2038 */
+};
+
+const char month_snames[12][4] = {
+ "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
+};
+
+void gm_timestr_822(char *ts, apr_time_t sec)
+{
+ static const char *const days[7]=
+ {"Sun","Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
+ struct tm *tms;
+ time_t ls = (time_t)sec;
+
+ tms = gmtime(&ls);
+
+ sprintf(ts, "%s, %.2d %s %d %.2d:%.2d:%.2d GMT", days[tms->tm_wday],
+ tms->tm_mday, month_snames[tms->tm_mon], tms->tm_year + 1900,
+ tms->tm_hour, tms->tm_min, tms->tm_sec);
+}
+
+void gm_timestr_850(char *ts, apr_time_t sec)
+{
+ static const char *const days[7]=
+ {"Sunday","Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
+ "Saturday"};
+ struct tm *tms;
+ int year;
+ time_t ls = (time_t)sec;
+
+ tms = gmtime(&ls);
+
+ year = tms->tm_year;
+ if (year >= 100) year -= 100;
+
+ sprintf(ts, "%s, %.2d-%s-%.2d %.2d:%.2d:%.2d GMT", days[tms->tm_wday],
+ tms->tm_mday, month_snames[tms->tm_mon], year,
+ tms->tm_hour, tms->tm_min, tms->tm_sec);
+}
+
+void gm_timestr_ccc(char *ts, apr_time_t sec)
+{
+ static const char *const days[7]=
+ {"Sun","Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
+ struct tm *tms;
+ time_t ls = (time_t)sec;
+
+ tms = gmtime(&ls);
+
+ sprintf(ts, "%s %s %2d %.2d:%.2d:%.2d %d", days[tms->tm_wday],
+ month_snames[tms->tm_mon], tms->tm_mday,
+ tms->tm_hour, tms->tm_min, tms->tm_sec, tms->tm_year + 1900);
+}
+
+int main (void)
+{
+ int year, i;
+ apr_time_t guess;
+ apr_time_t offset = 0;
+ /* apr_time_t offset = 0; */
+ /* apr_time_t offset = ((31 + 28) * 24 * 3600) - 1; */
+ apr_time_t secstodate, newsecs;
+ char datestr[50];
+
+ for (year = 1970; year < 2038; ++year) {
+ secstodate = year2secs[year - 1970] + offset;
+ gm_timestr_822(datestr, secstodate);
+ secstodate *= APR_USEC_PER_SEC;
+ newsecs = apr_date_parse_http(datestr);
+ if (secstodate == newsecs)
+ printf("Yes %4d %19" APR_TIME_T_FMT " %s\n", year, secstodate, datestr);
+ else if (newsecs == APR_DATE_BAD)
+ printf("No %4d %19" APR_TIME_T_FMT " %19" APR_TIME_T_FMT " %s\n",
+ year, secstodate, newsecs, datestr);
+ else
+ printf("No* %4d %19" APR_TIME_T_FMT " %19" APR_TIME_T_FMT " %s\n",
+ year, secstodate, newsecs, datestr);
+ }
+
+ srand48(978245L);
+
+ for (i = 0; i < 10000; ++i) {
+ guess = (time_t)mrand48();
+ if (guess < 0) guess *= -1;
+ secstodate = guess + offset;
+ gm_timestr_822(datestr, secstodate);
+ secstodate *= APR_USEC_PER_SEC;
+ newsecs = apr_date_parse_http(datestr);
+ if (secstodate == newsecs)
+ printf("Yes %" APR_TIME_T_FMT " %s\n", secstodate, datestr);
+ else if (newsecs == APR_DATE_BAD)
+ printf("No %" APR_TIME_T_FMT " %" APR_TIME_T_FMT " %s\n",
+ secstodate, newsecs, datestr);
+ else
+ printf("No* %" APR_TIME_T_FMT " %" APR_TIME_T_FMT " %s\n",
+ secstodate, newsecs, datestr);
+ }
+ exit(0);
+}
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "testutil.h"
+#include "apr.h"
+#include "apu.h"
+#include "apr_pools.h"
+#include "apr_dbd.h"
+#include "apr_strings.h"
+
+static void test_dbd_init(abts_case *tc, void *data)
+{
+ apr_pool_t *pool = p;
+ apr_status_t rv;
+
+ rv = apr_dbd_init(pool);
+ ABTS_ASSERT(tc, "failed to init apr_dbd", rv == APR_SUCCESS);
+}
+
+#if APU_HAVE_SQLITE2 || APU_HAVE_SQLITE3
+static void test_statement(abts_case *tc, apr_dbd_t* handle,
+ apr_dbd_driver_t* driver, const char* sql)
+{
+ int nrows;
+ apr_status_t rv;
+
+ rv = apr_dbd_query(driver, handle, &nrows, sql);
+
+ ABTS_ASSERT(tc, sql, rv == APR_SUCCESS);
+}
+
+static void create_table(abts_case *tc, apr_dbd_t* handle,
+ apr_dbd_driver_t* driver)
+{
+ const char *sql = "CREATE TABLE apr_dbd_test ("
+ "col1 varchar(40) not null,"
+ "col2 varchar(40),"
+ "col3 integer)";
+
+ test_statement(tc, handle, driver, sql);
+}
+
+static void drop_table(abts_case *tc, apr_dbd_t* handle,
+ apr_dbd_driver_t* driver)
+{
+ const char *sql = "DROP TABLE apr_dbd_test";
+ test_statement(tc, handle, driver, sql);
+}
+
+static void delete_rows(abts_case *tc, apr_dbd_t* handle,
+ apr_dbd_driver_t* driver)
+{
+ const char *sql = "DELETE FROM apr_dbd_test";
+ test_statement(tc, handle, driver, sql);
+}
+
+
+static void insert_data(abts_case *tc, apr_dbd_t* handle,
+ apr_dbd_driver_t* driver, int count)
+{
+ apr_pool_t* pool = p;
+ const char* sql = "INSERT INTO apr_dbd_test VALUES('%d', '%d', %d)";
+ char* sqf = NULL;
+ int i;
+ int nrows;
+ apr_status_t rv;
+
+ for (i=0; i<count; i++) {
+ sqf = apr_psprintf(pool, sql, i, i, i);
+ rv = apr_dbd_query(driver, handle, &nrows, sqf);
+ ABTS_ASSERT(tc, sqf, rv == APR_SUCCESS);
+ ABTS_ASSERT(tc, sqf, 1 == nrows);
+ }
+}
+
+static void select_rows(abts_case *tc, apr_dbd_t* handle,
+ apr_dbd_driver_t* driver, int count)
+{
+ apr_status_t rv;
+ apr_pool_t* pool = p;
+ apr_pool_t* tpool;
+ const char* sql = "SELECT * FROM apr_dbd_test ORDER BY col1";
+ apr_dbd_results_t *res = NULL;
+ apr_dbd_row_t *row = NULL;
+ int i;
+
+ rv = apr_dbd_select(driver, pool, handle, &res, sql, 0);
+ ABTS_ASSERT(tc, sql, rv == APR_SUCCESS);
+ ABTS_PTR_NOTNULL(tc, res);
+
+ apr_pool_create(&tpool, pool);
+ i = count;
+ while (i > 0) {
+ row = NULL;
+ rv = apr_dbd_get_row(driver, pool, res, &row, -1);
+ ABTS_ASSERT(tc, sql, rv == APR_SUCCESS);
+ ABTS_PTR_NOTNULL(tc, row);
+ apr_pool_clear(tpool);
+ i--;
+ }
+ ABTS_ASSERT(tc, "Missing Rows!", i == 0);
+
+ res = NULL;
+ i = count;
+
+ rv = apr_dbd_select(driver, pool, handle, &res, sql, 1);
+ ABTS_ASSERT(tc, sql, rv == APR_SUCCESS);
+ ABTS_PTR_NOTNULL(tc, res);
+
+ rv = apr_dbd_num_tuples(driver, res);
+ ABTS_ASSERT(tc, "invalid row count", rv == count);
+
+ while (i > 0) {
+ row = NULL;
+ rv = apr_dbd_get_row(driver, pool, res, &row, i);
+ ABTS_ASSERT(tc, sql, rv == APR_SUCCESS);
+ ABTS_PTR_NOTNULL(tc, row);
+ apr_pool_clear(tpool);
+ i--;
+ }
+ ABTS_ASSERT(tc, "Missing Rows!", i == 0);
+ rv = apr_dbd_get_row(driver, pool, res, &row, count+100);
+ ABTS_ASSERT(tc, "If we overseek, get_row should return -1", rv == -1);
+}
+
+static void test_dbd_generic(abts_case *tc, apr_dbd_t* handle,
+ apr_dbd_driver_t* driver)
+{
+ void* native;
+ apr_pool_t *pool = p;
+ apr_status_t rv;
+
+ native = apr_dbd_native_handle(driver, handle);
+ ABTS_PTR_NOTNULL(tc, native);
+
+ rv = apr_dbd_check_conn(driver, pool, handle);
+
+ create_table(tc, handle, driver);
+ select_rows(tc, handle, driver, 0);
+ insert_data(tc, handle, driver, 5);
+ select_rows(tc, handle, driver, 5);
+ delete_rows(tc, handle, driver);
+ select_rows(tc, handle, driver, 0);
+ drop_table(tc, handle, driver);
+
+ rv = apr_dbd_close(driver, handle);
+ ABTS_ASSERT(tc, "failed to close database", rv == APR_SUCCESS);
+}
+#endif
+
+#if APU_HAVE_SQLITE2
+static void test_dbd_sqlite2(abts_case *tc, void *data)
+{
+ apr_pool_t *pool = p;
+ apr_status_t rv;
+ apr_dbd_driver_t* driver = NULL;
+ apr_dbd_t* handle = NULL;
+
+ rv = apr_dbd_get_driver(pool, "sqlite2", &driver);
+ ABTS_ASSERT(tc, "failed to fetch driver", rv == APR_SUCCESS);
+ ABTS_PTR_NOTNULL(tc, driver);
+
+ ABTS_STR_EQUAL(tc, apr_dbd_name(driver), "sqlite2");
+
+ rv = apr_dbd_open(driver, pool, "data/sqlite2.db:600", &handle);
+ ABTS_ASSERT(tc, "failed to open database", rv == APR_SUCCESS);
+ ABTS_PTR_NOTNULL(tc, handle);
+
+ test_dbd_generic(tc, handle, driver);
+}
+#endif
+
+#if APU_HAVE_SQLITE3
+static void test_dbd_sqlite3(abts_case *tc, void *data)
+{
+ apr_pool_t *pool = p;
+ apr_status_t rv;
+ apr_dbd_driver_t* driver = NULL;
+ apr_dbd_t* handle = NULL;
+
+ rv = apr_dbd_get_driver(pool, "sqlite3", &driver);
+ ABTS_ASSERT(tc, "failed to fetch driver", rv == APR_SUCCESS);
+ ABTS_PTR_NOTNULL(tc, driver);
+
+ ABTS_STR_EQUAL(tc, apr_dbd_name(driver), "sqlite3");
+
+ rv = apr_dbd_open(driver, pool, "data/sqlite3.db", &handle);
+ ABTS_ASSERT(tc, "failed to open database", rv == APR_SUCCESS);
+ ABTS_PTR_NOTNULL(tc, handle);
+
+ test_dbd_generic(tc, handle, driver);
+}
+#endif
+
+abts_suite *testdbd(abts_suite *suite)
+{
+ suite = ADD_SUITE(suite);
+
+
+ abts_run_test(suite, test_dbd_init, NULL);
+
+#if APU_HAVE_SQLITE2
+ abts_run_test(suite, test_dbd_sqlite2, NULL);
+#endif
+
+#if APU_HAVE_SQLITE3
+ abts_run_test(suite, test_dbd_sqlite3, NULL);
+#endif
+ return suite;
+}
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/* This file came from the SDBM package (written by oz@nexus.yorku.ca).
+ * That package was under public domain. This file has been ported to
+ * APR, updated to ANSI C and other, newer idioms, and added to the Apache
+ * codebase under the above copyright and license.
+ */
+
+/*
+ * testdbm: Simple APR dbm tester.
+ * Automatic test case: ./testdbm auto foo
+ * - Attempts to store and fetch values from the DBM.
+ *
+ * Run the program for more help.
+ */
+
+#include "apr.h"
+#include "apr_general.h"
+#include "apr_pools.h"
+#include "apr_errno.h"
+#include "apr_getopt.h"
+#include "apr_time.h"
+#define APR_WANT_STRFUNC
+#include "apr_want.h"
+
+#if APR_HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#if APR_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <stdlib.h> /* for atexit(), malloc() */
+#include <string.h>
+
+#include "apr_dbm.h"
+
+static const char *progname;
+static int rflag;
+
+#define DERROR 0
+#define DLOOK 1
+
+#define DDELETE 3
+#define DCAT 4
+#define DBUILD 5
+#define DPRESS 6
+#define DCREAT 7
+#define DNAME 8
+#define DTRUNC 9
+#define DAUTO 10
+
+#define LINEMAX 8192
+
+typedef struct {
+ const char *sname;
+ int scode;
+ int flags;
+} cmd;
+
+static const cmd cmds[] = {
+
+ { "fetch", DLOOK, APR_DBM_READONLY },
+ { "get", DLOOK, APR_DBM_READONLY },
+ { "look", DLOOK, APR_DBM_READONLY },
+ { "add", DBUILD, APR_DBM_READWRITE },
+ { "insert", DBUILD, APR_DBM_READWRITE },
+ { "store", DBUILD, APR_DBM_READWRITE },
+ { "delete", DDELETE, APR_DBM_READWRITE },
+ { "remove", DDELETE, APR_DBM_READWRITE },
+ { "dump", DCAT, APR_DBM_READONLY },
+ { "list", DCAT, APR_DBM_READONLY },
+ { "cat", DCAT, APR_DBM_READONLY },
+ { "build", DBUILD, APR_DBM_RWCREATE }, /** this one creates the DB */
+ { "creat", DCREAT, APR_DBM_RWCREATE },
+ { "trunc", DTRUNC, APR_DBM_RWTRUNC },
+ { "new", DCREAT, APR_DBM_RWCREATE },
+ { "names", DNAME, APR_DBM_READONLY },
+#if 0
+ {"squash", DPRESS, APR_DBM_READWRITE, },
+ {"compact", DPRESS, APR_DBM_READWRITE, },
+ {"compress", DPRESS, APR_DBM_READWRITE, },
+#endif
+ { "auto", DAUTO, APR_DBM_RWCREATE },
+};
+
+#define CMD_SIZE (sizeof(cmds)/sizeof(cmd))
+
+static void doit(const cmd *act, const char*type, const char *file, apr_pool_t *pool);
+static const cmd *parse_command(const char *str);
+static void prdatum(FILE *stream, apr_datum_t d);
+static void oops(apr_dbm_t *dbm, apr_status_t rv, const char *s1,
+ const char *s2);
+static void show_usage(void);
+
+int main(int argc, const char * const * argv)
+{
+ apr_pool_t *pool;
+ const cmd *act;
+ apr_getopt_t *os;
+ char optch;
+ const char *optarg;
+ const char*dbtype;
+
+ (void) apr_initialize();
+ apr_pool_create(&pool, NULL);
+ atexit(apr_terminate);
+
+ (void) apr_getopt_init(&os, pool, argc, argv);
+
+ progname = argv[0];
+ dbtype = "default";
+
+ while (apr_getopt(os, "Rt:", &optch, &optarg) == APR_SUCCESS) {
+ switch (optch) {
+ case 'R': /* raw processing */
+ rflag++;
+ break;
+ case 't':
+ dbtype = optarg;
+ break;
+ default:
+ show_usage();
+ fputs("unknown option.",stderr);
+ exit(-1);
+ break;
+ }
+ }
+
+ if (argc <= os->ind) {
+ show_usage();
+ fputs("Note: If you have no clue what this program is, start with:\n", stderr);
+ fputs(" ./testdbm auto foo\n", stderr);
+ fputs(" where foo is the DBM prefix.\n", stderr);
+ exit(-2);
+ }
+
+ if ((act = parse_command(argv[os->ind])) == NULL) {
+ show_usage();
+ fprintf(stderr, "unrecognized command: %s\n", argv[os->ind]);
+ exit(-3);
+ }
+
+ if (++os->ind >= argc) {
+ show_usage();
+ fputs("please supply a DB file to use (may be created)\n", stderr);
+ exit(-4);
+ }
+
+ doit(act, dbtype, argv[os->ind], pool);
+
+ apr_pool_destroy(pool);
+
+ return 0;
+}
+
+static void doit(const cmd *act, const char*type, const char *file,
+ apr_pool_t *pool)
+{
+ apr_status_t rv;
+ apr_datum_t key;
+ apr_datum_t val;
+ apr_dbm_t *db;
+ char *op;
+ int n;
+ char *line;
+ const char *use1;
+ const char *use2;
+#ifdef TIME
+ long start;
+ extern long time();
+#endif
+
+ rv = apr_dbm_open_ex(&db, type, file, act->flags, APR_OS_DEFAULT, pool);
+ if (rv != APR_SUCCESS)
+ oops(db, rv, "cannot open: %s", file);
+
+ line = (char *) apr_palloc(pool,LINEMAX);
+
+ switch (act->scode) {
+
+ case DLOOK:
+ while (fgets(line, LINEMAX, stdin) != NULL) {
+ n = strlen(line) - 1;
+ line[n] = 0;
+ if (n == 0)
+ break;
+
+ key.dptr = line;
+ key.dsize = n;
+ rv = apr_dbm_fetch(db, key, &val);
+ if (rv == APR_SUCCESS) {
+ prdatum(stdout, val);
+ putchar('\n');
+ continue;
+ }
+ prdatum(stderr, key);
+ fprintf(stderr, ": not found.\n");
+ }
+ break;
+
+ case DDELETE:
+ while (fgets(line, LINEMAX, stdin) != NULL) {
+ n = strlen(line) - 1;
+ line[n] = 0;
+ if (n == 0)
+ break;
+
+ key.dptr = line;
+ key.dsize = n;
+ if (apr_dbm_delete(db, key) != APR_SUCCESS) {
+ prdatum(stderr, key);
+ fprintf(stderr, ": not found.\n");
+ }
+ }
+ break;
+ case DCAT:
+ rv = apr_dbm_firstkey(db, &key);
+ if (rv != APR_SUCCESS)
+ oops(db, rv, "could not fetch first key: %s", file);
+
+ while (key.dptr != NULL) {
+ prdatum(stdout, key);
+ putchar('\t');
+ rv = apr_dbm_fetch(db, key, &val);
+ if (rv != APR_SUCCESS)
+ oops(db, rv, "apr_dbm_fetch", "failure");
+ prdatum(stdout, val);
+ putchar('\n');
+ rv = apr_dbm_nextkey(db, &key);
+ if (rv != APR_SUCCESS)
+ oops(db, rv, "NextKey", "failure");
+ }
+ break;
+ case DBUILD:
+#ifdef TIME
+ start = time(0);
+#endif
+ while (fgets(line, LINEMAX, stdin) != NULL) {
+ n = strlen(line) - 1;
+ line[n] = 0;
+ if (n == 0)
+ break;
+
+ key.dptr = line;
+ if ((op = strchr(line, '\t')) != 0) {
+ key.dsize = op - line;
+ *op++ = 0;
+ val.dptr = op;
+ val.dsize = line + n - op;
+ }
+ else
+ oops(NULL, APR_EGENERAL, "bad input: %s", line);
+
+ rv = apr_dbm_store(db, key, val);
+ if (rv != APR_SUCCESS) {
+ prdatum(stderr, key);
+ fprintf(stderr, ": ");
+ oops(db, rv, "store: %s", "failed");
+ }
+ }
+#ifdef TIME
+ printf("done: %d seconds.\n", time(0) - start);
+#endif
+ break;
+ case DPRESS:
+ break;
+ case DCREAT:
+ break;
+ case DTRUNC:
+ break;
+ case DNAME:
+ apr_dbm_get_usednames(pool, file, &use1, &use2);
+ fprintf(stderr, "%s %s\n", use1, use2);
+ break;
+ case DAUTO:
+ {
+ int i;
+ char *valdata = "0123456789";
+ fprintf(stderr, "Generating data: ");
+ for (i = 0; i < 10; i++) {
+ int j;
+ char c, keydata[10];
+ for (j = 0, c = 'A' + (i % 16); j < 10; j++, c++) {
+ keydata[j] = c;
+ }
+ key.dptr = keydata;
+ key.dsize = 10;
+ val.dptr = valdata;
+ val.dsize = 10;
+ rv = apr_dbm_store(db, key, val);
+ if (rv != APR_SUCCESS) {
+ prdatum(stderr, key);
+ fprintf(stderr, ": ");
+ oops(db, rv, "store: %s", "failed");
+ }
+ }
+ fputs("OK\n", stderr);
+ fputs("Testing existence/retrieval: ", stderr);
+ for (i = 0; i < 10; i++) {
+ int j;
+ char c, keydata[10];
+ for (j = 0, c = 'A' + (i % 16); j < 10; j++, c++) {
+ keydata[j] = c;
+ }
+ key.dptr = keydata;
+ key.dsize = 10;
+ if (!apr_dbm_exists(db, key)) {
+ prdatum(stderr, key);
+ oops(db, 0, "exists: %s", "failed");
+ }
+ rv = apr_dbm_fetch(db, key, &val);
+ if (rv != APR_SUCCESS || val.dsize != 10 ||
+ (strncmp(val.dptr, valdata, 10) != 0) ) {
+ prdatum(stderr, key);
+ fprintf(stderr, ": ");
+ oops(db, rv, "fetch: %s", "failed");
+ }
+ }
+ fputs("OK\n", stderr);
+ }
+ break;
+ }
+
+ apr_dbm_close(db);
+}
+
+static const cmd *parse_command(const char *str)
+{
+ int i;
+
+ for (i = 0; i < CMD_SIZE; i++)
+ if (strcasecmp(cmds[i].sname, str) == 0)
+ return &cmds[i];
+
+ return NULL;
+}
+
+static void prdatum(FILE *stream, apr_datum_t d)
+{
+ int c;
+ const char *p = d.dptr;
+ int n = d.dsize;
+
+ while (n--) {
+ c = *p++ & 0377;
+ if (c & 0200) {
+ fprintf(stream, "M-");
+ c &= 0177;
+ }
+ if (c == 0177 || c < ' ')
+ fprintf(stream, "^%c", (c == 0177) ? '?' : c + '@');
+ else
+ putc(c, stream);
+ }
+}
+
+static void oops(apr_dbm_t * dbm, apr_status_t rv, const char *s1,
+ const char *s2)
+{
+ char errbuf[200];
+
+ if (progname) {
+ fprintf(stderr, "%s: ", progname);
+ }
+ fprintf(stderr, s1, s2);
+ fprintf(stderr, "\n");
+
+ if (rv != APR_SUCCESS) {
+ apr_strerror(rv, errbuf, sizeof(errbuf));
+ fprintf(stderr, "APR Error %d - %s\n", rv, errbuf);
+
+ if (dbm) {
+ apr_dbm_geterror(dbm, &rv, errbuf, sizeof(errbuf));
+ fprintf(stderr, "APR_DB Error %d - %s\n", rv, errbuf);
+ }
+ }
+ exit(1);
+}
+
+static void show_usage(void)
+{
+ int i;
+
+ if (!progname) {
+ progname = "testdbm";
+ }
+
+ fprintf(stderr, "%s [-t DBM-type] [-R] [commands] dbm-file-path\n",
+ progname);
+
+ fputs("Available DBM-types:", stderr);
+#if APU_HAVE_GDBM
+ fputs(" GDBM", stderr);
+#endif
+#if APU_HAVE_NDBM
+ fputs(" NDBM", stderr);
+#endif
+#if APU_HAVE_SDBM
+ fputs(" SDBM", stderr);
+#endif
+#if APU_HAVE_DB
+ fputs(" DB", stderr);
+#endif
+ fputs(" default\n", stderr);
+
+ fputs("Available commands:\n", stderr);
+ for (i = 0; i < CMD_SIZE; i++) {
+ fprintf(stderr, "%-8s%c", cmds[i].sname,
+ ((i + 1) % 6 == 0) ? '\n' : ' ');
+ }
+ fputs("\n", stderr);
+}
--- /dev/null
+/* Copyright 2002-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+ /* Setup:
+ * - Create or edit the file data/host.data and add an
+ * ldap server DN. Multiple DNs may be listed on
+ * a single line.
+ * - Copy the server certificates to the data/ directory.
+ * All DER type certificates must have the .der extention.
+ * All BASE64 or PEM certificates must have the .b64
+ * extension. All certificate files copied to the /data
+ * directory will be added to the ldap certificate store.
+ */
+
+ /* This test covers the following three types of connections:
+ * - Unsecure ldap://
+ * - Secure ldaps://
+ * - Secure ldap://+Start_TLS
+ *
+ * - (TBD) Mutual authentication
+ *
+ * There are other variations that should be tested:
+ * - All of the above with multiple redundant LDAP servers
+ * This can be done by listing more than one server DN
+ * in the host.data file. The DNs should all be listed
+ * on one line separated by a space.
+ * - All of the above with multiple certificates
+ * If more than one certificate is found in the data/
+ * directory, each certificate found will be added
+ * to the certificate store.
+ * - All of the above on alternate ports
+ * An alternate port can be specified as part of the
+ * host in the host.data file. The ":port" should
+ * follow each DN listed. Default is 389 and 636.
+ * - Secure connections with mutual authentication
+ */
+
+#include "testutil.h"
+
+#include "apr.h"
+#include "apr_general.h"
+#include "apr_ldap.h"
+#include "apr_file_io.h"
+#include "apr_file_info.h"
+#include "apr_strings.h"
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#define APR_WANT_STDIO
+#define APR_WANT_STRFUNC
+#include "apr_want.h"
+
+#define DIRNAME "data"
+#define FILENAME DIRNAME "/host.data"
+#define CERTFILEDER DIRNAME "/*.der"
+#define CERTFILEB64 DIRNAME "/*.b64"
+
+#if APR_HAS_LDAP
+
+static char ldap_host[256];
+
+static int get_ldap_host(void)
+{
+ apr_status_t rv;
+ apr_file_t *thefile = NULL;
+ char *ptr;
+
+ ldap_host[0] = '\0';
+ rv = apr_file_open(&thefile, FILENAME,
+ APR_READ,
+ APR_UREAD | APR_UWRITE | APR_GREAD, p);
+ if (rv != APR_SUCCESS) {
+ return 0;
+ }
+
+ rv = apr_file_gets(ldap_host, sizeof(ldap_host), thefile);
+ if (rv != APR_SUCCESS) {
+ return 0;
+ }
+
+ ptr = strstr (ldap_host, "\r\n");
+ if (ptr) {
+ *ptr = '\0';
+ }
+ apr_file_close(thefile);
+
+ return 1;
+
+}
+
+static int add_ldap_certs(abts_case *tc)
+{
+ apr_status_t status;
+ apr_dir_t *thedir;
+ apr_finfo_t dirent;
+ apr_ldap_err_t *result = NULL;
+
+ if ((status = apr_dir_open(&thedir, DIRNAME, p)) == APR_SUCCESS) {
+ apr_ldap_opt_tls_cert_t *cert = (apr_ldap_opt_tls_cert_t *)apr_pcalloc(p, sizeof(apr_ldap_opt_tls_cert_t));
+
+ do {
+ status = apr_dir_read(&dirent, APR_FINFO_MIN | APR_FINFO_NAME, thedir);
+ if (APR_STATUS_IS_INCOMPLETE(status)) {
+ continue; /* ignore un-stat()able files */
+ }
+ else if (status != APR_SUCCESS) {
+ break;
+ }
+
+ if (strstr(dirent.name, ".der")) {
+ cert->type = APR_LDAP_CA_TYPE_DER;
+ cert->path = apr_pstrcat (p, DIRNAME, "/", dirent.name, NULL);
+ apr_ldap_set_option(p, NULL, APR_LDAP_OPT_TLS_CERT, (void *)cert, &result);
+ ABTS_TRUE(tc, result->rc == LDAP_SUCCESS);
+ }
+ if (strstr(dirent.name, ".b64")) {
+ cert->type = APR_LDAP_CA_TYPE_BASE64;
+ cert->path = apr_pstrcat (p, DIRNAME, "/", dirent.name, NULL);
+ apr_ldap_set_option(p, NULL, APR_LDAP_OPT_TLS_CERT, (void *)cert, &result);
+ ABTS_TRUE(tc, result->rc == LDAP_SUCCESS);
+ }
+
+ } while (1);
+
+ apr_dir_close(thedir);
+ }
+ return 0;
+}
+
+static void test_ldap_connection(abts_case *tc, LDAP *ldap)
+{
+ int version = LDAP_VERSION3;
+ int failures, result;
+
+ /* always default to LDAP V3 */
+ ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &version);
+
+ for (failures=0; failures<10; failures++)
+ {
+ result = ldap_simple_bind_s(ldap,
+ (char *)NULL,
+ (char *)NULL);
+ if (LDAP_SERVER_DOWN != result)
+ break;
+ }
+
+ ABTS_TRUE(tc, result == LDAP_SUCCESS);
+ if (result != LDAP_SUCCESS) {
+ abts_log_message("%s\n", ldap_err2string(result));
+ }
+
+ ldap_unbind_s(ldap);
+
+ return;
+}
+
+static void test_ldap(abts_case *tc, void *data)
+{
+ apr_pool_t *pool = p;
+ LDAP *ldap;
+ apr_ldap_err_t *result = NULL;
+
+
+ ABTS_ASSERT(tc, "failed to get host", ldap_host[0] != '\0');
+
+ apr_ldap_init(pool, &ldap,
+ ldap_host, LDAP_PORT,
+ APR_LDAP_NONE, &(result));
+
+ ABTS_TRUE(tc, ldap != NULL);
+ ABTS_PTR_NOTNULL(tc, result);
+
+ if (result->rc == LDAP_SUCCESS) {
+ test_ldap_connection(tc, ldap);
+ }
+}
+
+static void test_ldaps(abts_case *tc, void *data)
+{
+ apr_pool_t *pool = p;
+ LDAP *ldap;
+ apr_ldap_err_t *result = NULL;
+
+ apr_ldap_init(pool, &ldap,
+ ldap_host, LDAPS_PORT,
+ APR_LDAP_SSL, &(result));
+
+ ABTS_TRUE(tc, ldap != NULL);
+ ABTS_PTR_NOTNULL(tc, result);
+
+ if (result->rc == LDAP_SUCCESS) {
+ add_ldap_certs(tc);
+
+ test_ldap_connection(tc, ldap);
+ }
+}
+
+static void test_ldap_tls(abts_case *tc, void *data)
+{
+ apr_pool_t *pool = p;
+ LDAP *ldap;
+ apr_ldap_err_t *result = NULL;
+
+ apr_ldap_init(pool, &ldap,
+ ldap_host, LDAP_PORT,
+ APR_LDAP_STARTTLS, &(result));
+
+ ABTS_TRUE(tc, ldap != NULL);
+ ABTS_PTR_NOTNULL(tc, result);
+
+ if (result->rc == LDAP_SUCCESS) {
+ add_ldap_certs(tc);
+
+ test_ldap_connection(tc, ldap);
+ }
+}
+
+#endif /* APR_HAS_LDAP */
+
+abts_suite *testldap(abts_suite *suite)
+{
+#if APR_HAS_LDAP
+ apr_ldap_err_t *result = NULL;
+ suite = ADD_SUITE(suite);
+
+ apr_ldap_ssl_init(p, NULL, 0, &result);
+
+ if (get_ldap_host()) {
+ abts_run_test(suite, test_ldap, NULL);
+ abts_run_test(suite, test_ldaps, NULL);
+ abts_run_test(suite, test_ldap_tls, NULL);
+ }
+#endif /* APR_HAS_LDAP */
+
+ return suite;
+}
+
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/* This is derived from material copyright RSA Data Security, Inc.
+ * Their notice is reproduced below in its entirety.
+ *
+ * Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All
+ * rights reserved.
+ *
+ * RSA Data Security, Inc. makes no representations concerning either
+ * the merchantability of this software or the suitability of this
+ * software for any particular purpose. It is provided "as is"
+ * without express or implied warranty of any kind.
+ *
+ * These notices must be retained in any copies of any part of this
+ * documentation and/or software.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "apr_errno.h"
+#include "apr_md4.h"
+#include "apr_file_io.h"
+
+#include "abts.h"
+#include "testutil.h"
+
+static struct {
+ const char *string;
+ const char *md4sum;
+} md4sums[] =
+{
+/*
+* Taken from the old md4 test suite.
+* MD4 ("") = 31d6cfe0d16ae931b73c59d7e0c089c0
+* MD4 ("a") = bde52cb31de33e46245e05fbdbd6fb24
+* MD4 ("abc") = a448017aaf21d8525fc10ae87aa6729d
+* MD4 ("message digest") = d9130a8164549fe818874806e1c7014b
+* MD4 ("abcdefghijklmnopqrstuvwxyz") = d79e1c308aa5bbcdeea8ed63df412da9
+* MD4 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
+* MD4 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = e33b4ddc9c38f2199c3e7b164fcc0536
+*
+*/
+ {"",
+ "\x31\xd6\xcf\xe0\xd1\x6a\xe9\x31\xb7\x3c\x59\xd7\xe0\xc0\x89\xc0"},
+ {"a",
+ "\xbd\xe5\x2c\xb3\x1d\xe3\x3e\x46\x24\x5e\x05\xfb\xdb\xd6\xfb\x24"},
+ {"abc",
+ "\xa4\x48\x01\x7a\xaf\x21\xd8\x52\x5f\xc1\x0a\xe8\x7a\xa6\x72\x9d"},
+ {"message digest",
+ "\xd9\x13\x0a\x81\x64\x54\x9f\xe8\x18\x87\x48\x06\xe1\xc7\x01\x4b"},
+ {"abcdefghijklmnopqrstuvwxyz",
+ "\xd7\x9e\x1c\x30\x8a\xa5\xbb\xcd\xee\xa8\xed\x63\xdf\x41\x2d\xa9"},
+ {"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
+ "\x04\x3f\x85\x82\xf2\x41\xdb\x35\x1c\xe6\x27\xe1\x53\xe7\xf0\xe4"},
+ {"12345678901234567890123456789012345678901234567890123456789012345678901234567890",
+ "\xe3\x3b\x4d\xdc\x9c\x38\xf2\x19\x9c\x3e\x7b\x16\x4f\xcc\x05\x36"}
+};
+
+static int num_sums = sizeof(md4sums) / sizeof(md4sums[0]);
+static int count;
+
+#if 0
+static int MDStringComp(const void *string, const void *sum)
+{
+ apr_md4_ctx_t context;
+ unsigned char digest[APR_MD4_DIGESTSIZE];
+ unsigned int len = strlen(string);
+
+ apr_md4_init(&context);
+ apr_md4_update(&context, (unsigned char *)string, len);
+ apr_md4_final(digest, &context);
+ return (memcmp(digest, sum, APR_MD4_DIGESTSIZE));
+
+}
+#endif
+
+static void test_md4sum(abts_case *tc, void *data)
+{
+ apr_md4_ctx_t context;
+ unsigned char digest[APR_MD4_DIGESTSIZE];
+ const void *string = md4sums[count].string;
+ const void *sum = md4sums[count].md4sum;
+ unsigned int len = strlen(string);
+
+ ABTS_ASSERT(tc, "apr_md4_init", (apr_md4_init(&context) == 0));
+ ABTS_ASSERT(tc, "apr_md4_update",
+ (apr_md4_update(&context,
+ (unsigned char *)string, len) == 0));
+
+ ABTS_ASSERT(tc, "apr_md4_final", (apr_md4_final(digest, &context) ==0));
+ ABTS_ASSERT(tc, "check for correct md4 digest",
+ (memcmp(digest, sum, APR_MD4_DIGESTSIZE) == 0));
+}
+
+abts_suite *testmd4(abts_suite *suite)
+{
+ suite = ADD_SUITE(suite);
+
+ for (count=0; count < num_sums; count++) {
+ abts_run_test(suite, test_md4sum, NULL);
+ }
+
+ return suite;
+}
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "apr_md5.h"
+#include "apr_xlate.h"
+#include "apr_general.h"
+
+#include "abts.h"
+#include "testutil.h"
+
+static struct {
+ const char *string;
+ const char *digest;
+} md5sums[] =
+{
+ {"Jeff was here!",
+ "\xa5\x25\x8a\x89\x11\xb2\x9d\x1f\x81\x75\x96\x3b\x60\x94\x49\xc0"},
+ {"01234567890aBcDeFASDFGHJKLPOIUYTR"
+ "POIUYTREWQZXCVBN LLLLLLLLLLLLLLL",
+ "\xd4\x1a\x06\x2c\xc5\xfd\x6f\x24\x67\x68\x56\x7c\x40\x8a\xd5\x69"},
+ {"111111118888888888888888*******%%%%%%%%%%#####"
+ "142134u8097289720432098409289nkjlfkjlmn,m.. ",
+ "\xb6\xea\x5b\xe8\xca\x45\x8a\x33\xf0\xf1\x84\x6f\xf9\x65\xa8\xe1"},
+ {"01234567890aBcDeFASDFGHJKLPOIUYTR"
+ "POIUYTREWQZXCVBN LLLLLLLLLLLLLLL"
+ "01234567890aBcDeFASDFGHJKLPOIUYTR"
+ "POIUYTREWQZXCVBN LLLLLLLLLLLLLLL"
+ "1",
+ "\xd1\xa1\xc0\x97\x8a\x60\xbb\xfb\x2a\x25\x46\x9d\xa5\xae\xd0\xb0"}
+};
+
+static int num_sums = sizeof(md5sums) / sizeof(md5sums[0]);
+static int count;
+
+static void test_md5sum(abts_case *tc, void *data)
+{
+ apr_md5_ctx_t context;
+ unsigned char digest[APR_MD5_DIGESTSIZE];
+ const void *string = md5sums[count].string;
+ const void *sum = md5sums[count].digest;
+ unsigned int len = strlen(string);
+
+ ABTS_ASSERT(tc, "apr_md5_init", (apr_md5_init(&context) == 0));
+ ABTS_ASSERT(tc, "apr_md5_update",
+ (apr_md5_update(&context, string, len) == 0));
+ ABTS_ASSERT(tc, "apr_md5_final", (apr_md5_final(digest, &context)
+ == 0));
+ ABTS_ASSERT(tc, "check for correct md5 digest",
+ (memcmp(digest, sum, APR_MD5_DIGESTSIZE) == 0));
+}
+
+abts_suite *testmd5(abts_suite *suite)
+{
+ suite = ADD_SUITE(suite);
+
+ for (count=0; count < num_sums; count++) {
+ abts_run_test(suite, test_md5sum, NULL);
+ }
+
+ return suite;
+}
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "apr_errno.h"
+#include "apr_strings.h"
+#include "apr_file_io.h"
+#include "apr_thread_proc.h"
+#include "apr_md5.h"
+#include "apr_sha1.h"
+
+#include "abts.h"
+#include "testutil.h"
+
+static struct {
+ const char *password;
+ const char *hash;
+} passwords[] =
+{
+/*
+ passwords and hashes created with Apache's htpasswd utility like this:
+
+ htpasswd -c -b passwords pass1 pass1
+ htpasswd -b passwords pass2 pass2
+ htpasswd -b passwords pass3 pass3
+ htpasswd -b passwords pass4 pass4
+ htpasswd -b passwords pass5 pass5
+ htpasswd -b passwords pass6 pass6
+ htpasswd -b passwords pass7 pass7
+ htpasswd -b passwords pass8 pass8
+ (insert Perl one-liner to convert to initializer :) )
+ */
+ {"pass1", "1fWDc9QWYCWrQ"},
+ {"pass2", "1fiGx3u7QoXaM"},
+ {"pass3", "1fzijMylTiwCs"},
+ {"pass4", "nHUYc8U2UOP7s"},
+ {"pass5", "nHpETGLGPwAmA"},
+ {"pass6", "nHbsbWmJ3uyhc"},
+ {"pass7", "nHQ3BbF0Y9vpI"},
+ {"pass8", "nHZA1rViSldQk"}
+};
+static int num_passwords = sizeof(passwords) / sizeof(passwords[0]);
+
+static void test_crypt(abts_case *tc, void *data)
+{
+ int i;
+
+ for (i = 0; i < num_passwords; i++) {
+ apr_assert_success(tc, "check for valid password",
+ apr_password_validate(passwords[i].password,
+ passwords[i].hash));
+ }
+}
+
+#if APR_HAS_THREADS
+
+static void * APR_THREAD_FUNC testing_thread(apr_thread_t *thd,
+ void *data)
+{
+ abts_case *tc = data;
+ int i;
+
+ for (i = 0; i < 100; i++) {
+ test_crypt(tc, NULL);
+ }
+
+ return APR_SUCCESS;
+}
+
+/* test for threadsafe crypt() */
+static void test_threadsafe(abts_case *tc, void *data)
+{
+#define NUM_THR 20
+ apr_thread_t *my_threads[NUM_THR];
+ int i;
+ apr_status_t rv;
+
+ for (i = 0; i < NUM_THR; i++) {
+ apr_assert_success(tc, "create test thread",
+ apr_thread_create(&my_threads[i], NULL,
+ testing_thread, tc, p));
+ }
+
+ for (i = 0; i < NUM_THR; i++) {
+ apr_thread_join(&rv, my_threads[i]);
+ }
+}
+#endif
+
+static void test_shapass(abts_case *tc, void *data)
+{
+ const char *pass = "hellojed";
+ char hash[100];
+
+ apr_sha1_base64(pass, strlen(pass), hash);
+
+ apr_assert_success(tc, "SHA1 password validated",
+ apr_password_validate(pass, hash));
+}
+
+static void test_md5pass(abts_case *tc, void *data)
+{
+ const char *pass = "hellojed", *salt = "sardine";
+ char hash[100];
+
+ apr_md5_encode(pass, salt, hash, sizeof hash);
+
+ apr_assert_success(tc, "MD5 password validated",
+ apr_password_validate(pass, hash));
+}
+
+abts_suite *testpass(abts_suite *suite)
+{
+ suite = ADD_SUITE(suite);
+
+ abts_run_test(suite, test_crypt, NULL);
+#if APR_HAS_THREADS
+ abts_run_test(suite, test_threadsafe, NULL);
+#endif
+ abts_run_test(suite, test_shapass, NULL);
+ abts_run_test(suite, test_md5pass, NULL);
+
+ return suite;
+}
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <apr_thread_proc.h>
+#include <apr_errno.h>
+#include <apr_general.h>
+#include <apr_getopt.h>
+#include <apr_strings.h>
+#include "errno.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <apr_time.h>
+#if APR_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <apr_portable.h>
+#include "apr_queue.h"
+
+#if !APR_HAS_THREADS
+int main(void)
+{
+ fprintf(stderr,
+ "This program won't work on this platform because there is no "
+ "support for threads.\n");
+ return 0;
+}
+#else /* !APR_HAS_THREADS */
+
+apr_pool_t *context;
+int consumer_activity=400;
+int producer_activity=300;
+int verbose=0;
+static void * APR_THREAD_FUNC consumer(apr_thread_t *thd, void *data);
+static void * APR_THREAD_FUNC producer(apr_thread_t *thd, void *data);
+static void usage(void);
+
+static void * APR_THREAD_FUNC consumer(apr_thread_t *thd, void *data)
+{
+ long sleeprate;
+ apr_queue_t *q = (apr_queue_t*)data;
+ apr_status_t rv;
+ int val;
+ void *v;
+ char current_thread_str[30];
+ apr_os_thread_t current_thread = apr_os_thread_current();
+
+ apr_snprintf(current_thread_str, sizeof current_thread_str,
+ "%pT", ¤t_thread);
+
+ sleeprate = 1000000/consumer_activity;
+ apr_sleep( (rand() % 4 ) * 1000000 ); /* sleep random seconds */
+ while (1) {
+ do {
+ rv = apr_queue_pop(q, &v);
+ if (rv == APR_EINTR) {
+ fprintf(stderr, "%s\tconsumer intr\n", current_thread_str);
+ }
+
+ } while (rv == APR_EINTR) ;
+ if (rv != APR_SUCCESS) {
+ if (rv == APR_EOF) {
+ fprintf(stderr, "%s\tconsumer:queue terminated APR_EOF\n", current_thread_str);
+ rv=APR_SUCCESS;
+ }
+ else
+ fprintf(stderr, "%s\tconsumer thread exit rv %d\n", current_thread_str, rv);
+ apr_thread_exit(thd, rv);
+ return NULL;
+ }
+ val = *(int*)v;
+ if (verbose)
+ fprintf(stderr, "%s\tpop %d\n", current_thread_str, val);
+ apr_sleep( sleeprate ); /* sleep this long to acheive our rate */
+ }
+ /* not reached */
+ return NULL;
+}
+
+static void * APR_THREAD_FUNC producer(apr_thread_t *thd, void *data)
+{
+ int i=0;
+ long sleeprate;
+ apr_queue_t *q = (apr_queue_t*)data;
+ apr_status_t rv;
+ int *val;
+ char current_thread_str[30];
+ apr_os_thread_t current_thread = apr_os_thread_current();
+
+ apr_snprintf(current_thread_str, sizeof current_thread_str,
+ "%pT", ¤t_thread);
+
+ sleeprate = 1000000/producer_activity;
+ apr_sleep( (rand() % 4 ) * 1000000 ); /* sleep random seconds */
+
+ while(1) {
+ val = apr_palloc(context, sizeof(int));
+ *val=i;
+ if (verbose)
+ fprintf(stderr, "%s\tpush %d\n", current_thread_str, *val);
+ do {
+ rv = apr_queue_push(q, val);
+ if (rv == APR_EINTR)
+ fprintf(stderr, "%s\tproducer intr\n", current_thread_str);
+ } while (rv == APR_EINTR);
+
+ if (rv != APR_SUCCESS) {
+ if (rv == APR_EOF) {
+ fprintf(stderr, "%s\tproducer: queue terminated APR_EOF\n", current_thread_str);
+ rv = APR_SUCCESS;
+ }
+ else
+ fprintf(stderr, "%s\tproducer thread exit rv %d\n", current_thread_str, rv);
+ apr_thread_exit(thd, rv);
+ return NULL;
+ }
+ i++;
+ apr_sleep( sleeprate ); /* sleep this long to acheive our rate */
+ }
+ /* not reached */
+ return NULL;
+}
+
+static void usage(void)
+{
+ fprintf(stderr,"usage: testqueue -p n -P n -c n -C n -q n -s n\n");
+ fprintf(stderr,"-c # of consumer\n");
+ fprintf(stderr,"-C amount they consumer before dying\n");
+ fprintf(stderr,"-p # of producers\n");
+ fprintf(stderr,"-P amount they produce before dying\n");
+ fprintf(stderr,"-q queue size\n");
+ fprintf(stderr,"-s amount of time to sleep before killing it\n");
+ fprintf(stderr,"-v verbose\n");
+}
+
+int main(int argc, const char* const argv[])
+{
+ apr_thread_t **t;
+ apr_queue_t *queue;
+ int i;
+ apr_status_t rv;
+ apr_getopt_t *opt;
+ const char *optarg;
+ char c;
+ int numconsumers=3;
+ int numproducers=4;
+ int queuesize=100;
+ int sleeptime=30;
+ char errorbuf[200];
+
+ apr_initialize();
+ srand((unsigned int)apr_time_now());
+ printf("APR Queue Test\n======================\n\n");
+
+ printf("%-60s", "Initializing the context");
+ if (apr_pool_create(&context, NULL) != APR_SUCCESS) {
+ fflush(stdout);
+ fprintf(stderr, "Failed.\nCould not initialize\n");
+ exit(-1);
+ }
+ printf("OK\n");
+
+ apr_getopt_init(&opt, context, argc, argv);
+ while ((rv = apr_getopt(opt, "p:c:P:C:q:s:v", &c, &optarg))
+ == APR_SUCCESS) {
+ switch (c) {
+ case 'c':
+ numconsumers = atoi( optarg);
+ break;
+ case 'p':
+ numproducers = atoi( optarg);
+ break;
+ case 'C':
+ consumer_activity = atoi( optarg);
+ break;
+ case 'P':
+ producer_activity = atoi( optarg);
+ break;
+ case 's':
+ sleeptime= atoi(optarg);
+ break;
+ case 'q':
+ queuesize = atoi(optarg);
+ break;
+ case 'v':
+ verbose= 1;
+ break;
+ default:
+ usage();
+ exit(-1);
+ }
+ }
+ /* bad cmdline option? then we die */
+ if (rv != APR_EOF || opt->ind < opt->argc) {
+ usage();
+ exit(-1);
+ }
+
+
+
+ printf("test stats %d consumers (rate %d/sec) %d producers (rate %d/sec) queue size %d sleep %d\n",
+ numconsumers,consumer_activity, numproducers, producer_activity, queuesize,sleeptime);
+ printf("%-60s", "Initializing the queue");
+ rv = apr_queue_create(&queue, queuesize, context);
+
+ if (rv != APR_SUCCESS) {
+ fflush(stdout);
+ fprintf(stderr, "Failed\nCould not create queue %d\n",rv);
+ apr_strerror(rv, errorbuf,200);
+ fprintf(stderr,"%s\n",errorbuf);
+ exit(-1);
+ }
+ printf("OK\n");
+
+ t = apr_palloc( context, sizeof(apr_thread_t*) * (numconsumers+numproducers));
+ printf("%-60s", "Starting consumers");
+ for (i=0;i<numconsumers;i++) {
+ rv = apr_thread_create(&t[i], NULL, consumer, queue, context);
+ if (rv != APR_SUCCESS) {
+ apr_strerror(rv, errorbuf,200);
+ fprintf(stderr, "Failed\nError starting consumer thread (%d) rv=%d:%s\n",i, rv,errorbuf);
+ exit(-1);
+
+ }
+ }
+ for (i=numconsumers;i<(numconsumers+numproducers);i++) {
+ rv = apr_thread_create(&t[i], NULL, producer, queue, context);
+ if (rv != APR_SUCCESS) {
+ apr_strerror(rv, errorbuf,200);
+ fprintf(stderr, "Failed\nError starting producer thread (%d) rv=%d:%s\n",i, rv,errorbuf);
+ exit(-1);
+
+ }
+ }
+
+ printf("OK\n");
+ printf("%-60s", "Sleeping\n");
+ apr_sleep( sleeptime * 1000000 ); /* sleep 10 seconds */
+ printf("OK\n");
+
+ printf("%-60s", "Terminating queue");
+ rv = apr_queue_term(queue);
+ if (rv != APR_SUCCESS) {
+ apr_strerror(rv, errorbuf,200);
+ fprintf( stderr, "apr_queue_term failed %d:%s\n",rv,errorbuf);
+ }
+ printf("OK\n");
+
+
+ printf("%-60s", "Waiting for threads to exit\n");
+ fflush(stdout);
+ for (i=0;i<numconsumers+numproducers;i++) {
+ apr_thread_join(&rv, t[i]);
+ if (rv != 0 ) {
+ apr_strerror(rv, errorbuf,200);
+ if (i<numconsumers)
+ fprintf( stderr, "consumer thread %d failed rv %d:%s\n",i,rv,errorbuf);
+ else
+ fprintf( stderr, "producer thread %d failed rv %d:%s\n",i,rv,errorbuf);
+ }
+ }
+
+ printf("OK\n");
+
+ apr_terminate();
+
+ return 0;
+}
+
+#endif /* !APR_HAS_THREADS */
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include "apr_reslist.h"
+#include "apr_thread_proc.h"
+
+#if APR_HAVE_TIME_H
+#include <time.h>
+#endif /* APR_HAVE_TIME_H */
+
+#if !APR_HAS_THREADS
+
+int main(void)
+{
+ fprintf(stderr, "this program requires APR thread support\n");
+ return 0;
+}
+
+#else
+
+#define RESLIST_MIN 3
+#define RESLIST_SMAX 10
+#define RESLIST_HMAX 20
+#define RESLIST_TTL APR_TIME_C(350000) /* 35 ms */
+#define CONSUMER_THREADS 25
+#define CONSUMER_ITERATIONS 250
+#define CONSTRUCT_SLEEP_TIME APR_TIME_C(250000) /* 25 ms */
+#define DESTRUCT_SLEEP_TIME APR_TIME_C(100000) /* 10 ms */
+#define WORK_DELAY_SLEEP_TIME APR_TIME_C(150000) /* 15 ms */
+
+typedef struct {
+ apr_interval_time_t sleep_upon_construct;
+ apr_interval_time_t sleep_upon_destruct;
+ int c_count;
+ int d_count;
+} my_parameters_t;
+
+typedef struct {
+ int id;
+} my_resource_t;
+
+static apr_status_t my_constructor(void **resource, void *params,
+ apr_pool_t *pool)
+{
+ my_resource_t *res;
+ my_parameters_t *my_params = params;
+
+ /* Create some resource */
+ res = apr_palloc(pool, sizeof(*res));
+ res->id = my_params->c_count++;
+
+ printf("++ constructing new resource [id:%d, #%d/%d]\n", res->id,
+ my_params->c_count, my_params->d_count);
+
+ /* Sleep for awhile, to simulate construction overhead. */
+ apr_sleep(my_params->sleep_upon_construct);
+
+ /* Set the resource so it can be managed by the reslist */
+ *resource = res;
+ return APR_SUCCESS;
+}
+
+static apr_status_t my_destructor(void *resource, void *params,
+ apr_pool_t *pool)
+{
+ my_resource_t *res = resource;
+ my_parameters_t *my_params = params;
+
+ printf("-- destructing old resource [id:%d, #%d/%d]\n", res->id,
+ my_params->c_count, ++my_params->d_count);
+
+ apr_sleep(my_params->sleep_upon_destruct);
+
+ return APR_SUCCESS;
+}
+
+typedef struct {
+ int tid;
+ apr_reslist_t *reslist;
+ apr_interval_time_t work_delay_sleep;
+} my_thread_info_t;
+
+static void * APR_THREAD_FUNC resource_consuming_thread(apr_thread_t *thd,
+ void *data)
+{
+ apr_status_t rv;
+ my_thread_info_t *thread_info = data;
+ apr_reslist_t *rl = thread_info->reslist;
+ int i;
+
+ for (i = 0; i < CONSUMER_ITERATIONS; i++) {
+ my_resource_t *res;
+ void *vp;
+ rv = apr_reslist_acquire(rl, &vp);
+ if (rv != APR_SUCCESS) {
+ fprintf(stderr, "Failed to retrieve resource from reslist\n");
+ apr_thread_exit(thd, rv);
+ return NULL;
+ }
+ res = vp;
+ printf(" [tid:%d,iter:%d] using resource id:%d\n", thread_info->tid,
+ i, res->id);
+ apr_sleep(thread_info->work_delay_sleep);
+/* simulate a 5% chance of the resource being bad */
+ if ( drand48() < 0.95 ) {
+ rv = apr_reslist_release(rl, res);
+ if (rv != APR_SUCCESS) {
+ fprintf(stderr, "Failed to return resource to reslist\n");
+ apr_thread_exit(thd, rv);
+ return NULL;
+ }
+ } else {
+ printf("invalidating resource id:%d\n", res->id) ;
+ rv = apr_reslist_invalidate(rl, res);
+ if (rv != APR_SUCCESS) {
+ fprintf(stderr, "Failed to invalidate resource\n");
+ apr_thread_exit(thd, rv);
+ return NULL;
+ }
+ }
+ }
+
+ return APR_SUCCESS;
+}
+
+static void test_timeout(apr_reslist_t *rl)
+{
+ apr_status_t rv;
+ my_resource_t *resources[RESLIST_HMAX];
+ my_resource_t *res;
+ void *vp;
+ int i;
+
+ printf("Setting timeout to 1000us: ");
+ apr_reslist_timeout_set(rl, 1000);
+ fprintf(stdout, "OK\n");
+
+ /* deplete all possible resources from the resource list
+ * so that the next call will block until timeout is reached
+ * (since there are no other threads to make a resource
+ * available)
+ */
+
+ for (i = 0; i < RESLIST_HMAX; i++) {
+ rv = apr_reslist_acquire(rl, (void**)&resources[i]);
+ if (rv != APR_SUCCESS) {
+ fprintf(stderr, "couldn't acquire resource: %d\n", rv);
+ exit(1);
+ }
+ }
+
+ /* next call will block until timeout is reached */
+ rv = apr_reslist_acquire(rl, &vp);
+ if (!APR_STATUS_IS_TIMEUP(rv)) {
+ fprintf(stderr, "apr_reslist_acquire()->%d instead of TIMEUP\n",
+ rv);
+ exit(1);
+ }
+ res = vp;
+
+ /* release the resources; otherwise the destroy operation
+ * will blow
+ */
+ for (i = 0; i < RESLIST_HMAX; i++) {
+ rv = apr_reslist_release(rl, &resources[i]);
+ if (rv != APR_SUCCESS) {
+ fprintf(stderr, "couldn't release resource: %d\n", rv);
+ exit(1);
+ }
+ }
+}
+
+static apr_status_t test_reslist(apr_pool_t *parpool)
+{
+ apr_status_t rv;
+ apr_pool_t *pool;
+ apr_reslist_t *rl;
+ my_parameters_t *params;
+ int i;
+ apr_thread_t *my_threads[CONSUMER_THREADS];
+ my_thread_info_t my_thread_info[CONSUMER_THREADS];
+ srand48(time(0)) ;
+
+ printf("Creating child pool.......................");
+ rv = apr_pool_create(&pool, parpool);
+ if (rv != APR_SUCCESS) {
+ fprintf(stderr, "Error creating child pool\n");
+ return rv;
+ }
+ printf("OK\n");
+
+ /* Create some parameters that will be passed into each
+ * constructor and destructor call. */
+ params = apr_pcalloc(pool, sizeof(*params));
+ params->sleep_upon_construct = CONSTRUCT_SLEEP_TIME;
+ params->sleep_upon_destruct = DESTRUCT_SLEEP_TIME;
+
+ /* We're going to want 10 blocks of data from our target rmm. */
+ printf("Creating resource list:\n"
+ " min/smax/hmax: %d/%d/%d\n"
+ " ttl: %" APR_TIME_T_FMT "\n", RESLIST_MIN, RESLIST_SMAX,
+ RESLIST_HMAX, RESLIST_TTL);
+ rv = apr_reslist_create(&rl, RESLIST_MIN, RESLIST_SMAX, RESLIST_HMAX,
+ RESLIST_TTL, my_constructor, my_destructor,
+ params, pool);
+ if (rv != APR_SUCCESS) {
+ fprintf(stderr, "Error allocating shared memory block\n");
+ return rv;
+ }
+ fprintf(stdout, "OK\n");
+
+ printf("Creating %d threads", CONSUMER_THREADS);
+ for (i = 0; i < CONSUMER_THREADS; i++) {
+ putchar('.');
+ my_thread_info[i].tid = i;
+ my_thread_info[i].reslist = rl;
+ my_thread_info[i].work_delay_sleep = WORK_DELAY_SLEEP_TIME;
+ rv = apr_thread_create(&my_threads[i], NULL,
+ resource_consuming_thread, &my_thread_info[i],
+ pool);
+ if (rv != APR_SUCCESS) {
+ fprintf(stderr, "Failed to create thread %d\n", i);
+ return rv;
+ }
+ }
+ printf("\nDone!\n");
+
+ printf("Waiting for threads to finish");
+ for (i = 0; i < CONSUMER_THREADS; i++) {
+ apr_status_t thread_rv;
+ putchar('.');
+ apr_thread_join(&thread_rv, my_threads[i]);
+ if (rv != APR_SUCCESS) {
+ fprintf(stderr, "Failed to join thread %d\n", i);
+ return rv;
+ }
+ }
+ printf("\nDone!\n");
+
+ test_timeout(rl);
+
+ printf("Destroying resource list.................");
+ rv = apr_reslist_destroy(rl);
+ if (rv != APR_SUCCESS) {
+ printf("FAILED\n");
+ return rv;
+ }
+ printf("OK\n");
+
+ apr_pool_destroy(pool);
+
+ return APR_SUCCESS;
+}
+
+
+int main(void)
+{
+ apr_status_t rv;
+ apr_pool_t *pool;
+ char errmsg[200];
+
+ apr_initialize();
+
+ printf("APR Resource List Test\n");
+ printf("======================\n\n");
+
+ printf("Initializing the pool............................");
+ if (apr_pool_create(&pool, NULL) != APR_SUCCESS) {
+ printf("could not initialize pool\n");
+ exit(-1);
+ }
+ printf("OK\n");
+
+ rv = test_reslist(pool);
+ if (rv != APR_SUCCESS) {
+ printf("Resource list test FAILED: [%d] %s\n",
+ rv, apr_strerror(rv, errmsg, sizeof(errmsg)));
+ exit(-2);
+ }
+ printf("Resource list test passed!\n");
+
+ return 0;
+}
+
+#endif /* APR_HAS_THREADS */
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_shm.h"
+#include "apr_rmm.h"
+#include "apr_errno.h"
+#include "apr_general.h"
+#include "apr_lib.h"
+#include "apr_strings.h"
+#include "apr_time.h"
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#if APR_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#if APR_HAS_SHARED_MEMORY
+
+#define FRAG_SIZE 80
+#define FRAG_COUNT 10
+#define SHARED_SIZE (apr_size_t)(FRAG_SIZE * FRAG_COUNT * sizeof(char*))
+
+static apr_status_t test_rmm(apr_pool_t *parpool)
+{
+ apr_status_t rv;
+ apr_pool_t *pool;
+ apr_shm_t *shm;
+ apr_rmm_t *rmm;
+ apr_size_t size, fragsize;
+ apr_rmm_off_t *off;
+ int i;
+ void *entity;
+
+ rv = apr_pool_create(&pool, parpool);
+ if (rv != APR_SUCCESS) {
+ fprintf(stderr, "Error creating child pool\n");
+ return rv;
+ }
+
+ /* We're going to want 10 blocks of data from our target rmm. */
+ size = SHARED_SIZE + apr_rmm_overhead_get(FRAG_COUNT + 1);
+ printf("Creating anonymous shared memory (%"
+ APR_SIZE_T_FMT " bytes).....", size);
+ rv = apr_shm_create(&shm, size, NULL, pool);
+ if (rv != APR_SUCCESS) {
+ fprintf(stderr, "Error allocating shared memory block\n");
+ return rv;
+ }
+ fprintf(stdout, "OK\n");
+
+ printf("Creating rmm segment.............................");
+ rv = apr_rmm_init(&rmm, NULL, apr_shm_baseaddr_get(shm), size,
+ pool);
+
+ if (rv != APR_SUCCESS) {
+ fprintf(stderr, "Error allocating rmm..............\n");
+ return rv;
+ }
+ fprintf(stdout, "OK\n");
+
+ fragsize = SHARED_SIZE / FRAG_COUNT;
+ printf("Creating each fragment of size %" APR_SIZE_T_FMT "................",
+ fragsize);
+ off = apr_palloc(pool, FRAG_COUNT * sizeof(apr_rmm_off_t));
+ for (i = 0; i < FRAG_COUNT; i++) {
+ off[i] = apr_rmm_malloc(rmm, fragsize);
+ }
+ fprintf(stdout, "OK\n");
+
+ printf("Checking for out of memory allocation............");
+ if (apr_rmm_malloc(rmm, FRAG_SIZE * FRAG_COUNT) == 0) {
+ fprintf(stdout, "OK\n");
+ }
+ else {
+ return APR_EGENERAL;
+ }
+
+ printf("Checking each fragment for address alignment.....");
+ for (i = 0; i < FRAG_COUNT; i++) {
+ char *c = apr_rmm_addr_get(rmm, off[i]);
+ apr_size_t sc = (apr_size_t)c;
+
+ if (off[i] == 0) {
+ printf("allocation failed for offset %d\n", i);
+ return APR_ENOMEM;
+ }
+
+ if (sc & 7) {
+ printf("Bad alignment for fragment %d; %p not %p!\n",
+ i, c, (void *)APR_ALIGN_DEFAULT((apr_size_t)c));
+ return APR_EGENERAL;
+ }
+ }
+ fprintf(stdout, "OK\n");
+
+ printf("Setting each fragment to a unique value..........");
+ for (i = 0; i < FRAG_COUNT; i++) {
+ int j;
+ char **c = apr_rmm_addr_get(rmm, off[i]);
+ for (j = 0; j < FRAG_SIZE; j++, c++) {
+ *c = apr_itoa(pool, i + j);
+ }
+ }
+ fprintf(stdout, "OK\n");
+
+ printf("Checking each fragment for its unique value......");
+ for (i = 0; i < FRAG_COUNT; i++) {
+ int j;
+ char **c = apr_rmm_addr_get(rmm, off[i]);
+ for (j = 0; j < FRAG_SIZE; j++, c++) {
+ char *d = apr_itoa(pool, i + j);
+ if (strcmp(*c, d) != 0) {
+ return APR_EGENERAL;
+ }
+ }
+ }
+ fprintf(stdout, "OK\n");
+
+ printf("Freeing each fragment............................");
+ for (i = 0; i < FRAG_COUNT; i++) {
+ rv = apr_rmm_free(rmm, off[i]);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+ }
+ fprintf(stdout, "OK\n");
+
+ printf("Creating one large segment.......................");
+ off[0] = apr_rmm_calloc(rmm, SHARED_SIZE);
+ fprintf(stdout, "OK\n");
+
+ printf("Setting large segment............................");
+ for (i = 0; i < FRAG_COUNT * FRAG_SIZE; i++) {
+ char **c = apr_rmm_addr_get(rmm, off[0]);
+ c[i] = apr_itoa(pool, i);
+ }
+ fprintf(stdout, "OK\n");
+
+ printf("Freeing large segment............................");
+ apr_rmm_free(rmm, off[0]);
+ fprintf(stdout, "OK\n");
+
+ printf("Creating each fragment of size %" APR_SIZE_T_FMT " (again)........",
+ fragsize);
+ for (i = 0; i < FRAG_COUNT; i++) {
+ off[i] = apr_rmm_malloc(rmm, fragsize);
+ }
+ fprintf(stdout, "OK\n");
+
+ printf("Freeing each fragment backwards..................");
+ for (i = FRAG_COUNT - 1; i >= 0; i--) {
+ rv = apr_rmm_free(rmm, off[i]);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+ }
+ fprintf(stdout, "OK\n");
+
+ printf("Creating one large segment (again)...............");
+ off[0] = apr_rmm_calloc(rmm, SHARED_SIZE);
+ fprintf(stdout, "OK\n");
+
+ printf("Freeing large segment............................");
+ apr_rmm_free(rmm, off[0]);
+ fprintf(stdout, "OK\n");
+
+ printf("Checking realloc.................................");
+ off[0] = apr_rmm_calloc(rmm, SHARED_SIZE - 100);
+ off[1] = apr_rmm_calloc(rmm, 100);
+ if (off[0] == 0 || off[1] == 0) {
+ printf("FAILED\n");
+ return APR_EINVAL;
+ }
+ entity = apr_rmm_addr_get(rmm, off[1]);
+ rv = apr_rmm_free(rmm, off[0]);
+ if (rv != APR_SUCCESS) {
+ printf("FAILED\n");
+ return rv;
+ }
+ /* now we can realloc off[1] and get many more bytes */
+ off[0] = apr_rmm_realloc(rmm, entity, SHARED_SIZE - 100);
+ if (off[0] == 0) {
+ printf("FAILED\n");
+ return APR_EINVAL;
+ }
+ fprintf(stdout, "OK\n");
+
+ printf("Destroying rmm segment...........................");
+ rv = apr_rmm_destroy(rmm);
+ if (rv != APR_SUCCESS) {
+ printf("FAILED\n");
+ return rv;
+ }
+ printf("OK\n");
+
+ printf("Destroying shared memory segment.................");
+ rv = apr_shm_destroy(shm);
+ if (rv != APR_SUCCESS) {
+ printf("FAILED\n");
+ return rv;
+ }
+ printf("OK\n");
+
+ apr_pool_destroy(pool);
+
+ return APR_SUCCESS;
+}
+
+
+int main(void)
+{
+ apr_status_t rv;
+ apr_pool_t *pool;
+ char errmsg[200];
+
+ apr_initialize();
+
+ printf("APR RMM Memory Test\n");
+ printf("======================\n\n");
+
+ printf("Initializing the pool............................");
+ if (apr_pool_create(&pool, NULL) != APR_SUCCESS) {
+ printf("could not initialize pool\n");
+ exit(-1);
+ }
+ printf("OK\n");
+
+ rv = test_rmm(pool);
+ if (rv != APR_SUCCESS) {
+ printf("Anonymous shared memory test FAILED: [%d] %s\n",
+ rv, apr_strerror(rv, errmsg, sizeof(errmsg)));
+ exit(-2);
+ }
+ printf("RMM test passed!\n");
+
+ return 0;
+}
+
+#else /* APR_HAS_SHARED_MEMORY */
+#error shmem is not supported on this platform
+#endif /* APR_HAS_SHARED_MEMORY */
+
--- /dev/null
+/* Copyright 2002-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "testutil.h"
+
+#include "apr.h"
+#include "apr_general.h"
+#include "apr_strmatch.h"
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#define APR_WANT_STDIO
+#define APR_WANT_STRFUNC
+#include "apr_want.h"
+
+static void test_str(abts_case *tc, void *data)
+{
+ apr_pool_t *pool = p;
+ const apr_strmatch_pattern *pattern;
+ const apr_strmatch_pattern *pattern_nocase;
+ const apr_strmatch_pattern *pattern_onechar;
+ const apr_strmatch_pattern *pattern_zero;
+ const char *match = NULL;
+ const char *input1 = "string that contains a patterN...";
+ const char *input2 = "string that contains a pattern...";
+ const char *input3 = "pattern at the start of a string";
+ const char *input4 = "string that ends with a pattern";
+ const char *input5 = "patter\200n not found, negative chars in input";
+ const char *input6 = "patter\200n, negative chars, contains pattern...";
+
+ pattern = apr_strmatch_precompile(pool, "pattern", 1);
+ ABTS_PTR_NOTNULL(tc, pattern);
+
+ pattern_nocase = apr_strmatch_precompile(pool, "pattern", 0);
+ ABTS_PTR_NOTNULL(tc, pattern_nocase);
+
+ pattern_onechar = apr_strmatch_precompile(pool, "g", 0);
+ ABTS_PTR_NOTNULL(tc, pattern_onechar);
+
+ pattern_zero = apr_strmatch_precompile(pool, "", 0);
+ ABTS_PTR_NOTNULL(tc, pattern_zero);
+
+ match = apr_strmatch(pattern, input1, strlen(input1));
+ ABTS_PTR_EQUAL(tc, match, NULL);
+
+ match = apr_strmatch(pattern, input2, strlen(input2));
+ ABTS_PTR_EQUAL(tc, match, input2 + 23);
+
+ match = apr_strmatch(pattern_onechar, input1, strlen(input1));
+ ABTS_PTR_EQUAL(tc, match, input1 + 5);
+
+ match = apr_strmatch(pattern_zero, input1, strlen(input1));
+ ABTS_PTR_EQUAL(tc, match, input1);
+
+ match = apr_strmatch(pattern_nocase, input1, strlen(input1));
+ ABTS_PTR_EQUAL(tc, match, input1 + 23);
+
+ match = apr_strmatch(pattern, input3, strlen(input3));
+ ABTS_PTR_EQUAL(tc, match, input3);
+
+ match = apr_strmatch(pattern, input4, strlen(input4));
+ ABTS_PTR_EQUAL(tc, match, input4 + 24);
+
+ match = apr_strmatch(pattern, input5, strlen(input5));
+ ABTS_PTR_EQUAL(tc, match, NULL);
+
+ match = apr_strmatch(pattern, input6, strlen(input6));
+ ABTS_PTR_EQUAL(tc, match, input6 + 35);
+}
+
+abts_suite *teststrmatch(abts_suite *suite)
+{
+ suite = ADD_SUITE(suite);
+
+ abts_run_test(suite, test_str, NULL);
+
+ return suite;
+}
+
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "testutil.h"
+#include "apr_general.h"
+#include "apr_strings.h"
+#include "apr_uri.h"
+
+struct aup_test {
+ const char *uri;
+ apr_status_t rv;
+ const char *scheme;
+ const char *hostinfo;
+ const char *user;
+ const char *password;
+ const char *hostname;
+ const char *port_str;
+ const char *path;
+ const char *query;
+ const char *fragment;
+ apr_port_t port;
+};
+
+struct aup_test aup_tests[] =
+{
+ { "http://[/::1]/index.html", APR_EGENERAL },
+ { "http://[", APR_EGENERAL },
+ { "http://[?::1]/index.html", APR_EGENERAL },
+
+ {
+ "http://127.0.0.1:9999/asdf.html",
+ 0, "http", "127.0.0.1:9999", NULL, NULL, "127.0.0.1", "9999", "/asdf.html", NULL, NULL, 9999
+ },
+ {
+ "http://127.0.0.1:9999a/asdf.html",
+ APR_EGENERAL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+ },
+ {
+ "http://[::127.0.0.1]:9999/asdf.html",
+ 0, "http", "[::127.0.0.1]:9999", NULL, NULL, "::127.0.0.1", "9999", "/asdf.html", NULL, NULL, 9999
+ },
+ {
+ "http://[::127.0.0.1]:9999a/asdf.html",
+ APR_EGENERAL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0
+ },
+ {
+ "/error/include/top.html",
+ 0, NULL, NULL, NULL, NULL, NULL, NULL, "/error/include/top.html", NULL, NULL, 0
+ },
+ {
+ "/error/include/../contact.html.var",
+ 0, NULL, NULL, NULL, NULL, NULL, NULL, "/error/include/../contact.html.var", NULL, NULL, 0
+ },
+ {
+ "/",
+ 0, NULL, NULL, NULL, NULL, NULL, NULL, "/", NULL, NULL, 0
+ },
+ {
+ "/manual/",
+ 0, NULL, NULL, NULL, NULL, NULL, NULL, "/manual/", NULL, NULL, 0
+ },
+ {
+ "/cocoon/developing/graphics/Using%20Databases-label_over.jpg",
+ 0, NULL, NULL, NULL, NULL, NULL, NULL, "/cocoon/developing/graphics/Using%20Databases-label_over.jpg", NULL, NULL, 0
+ },
+ {
+ "http://sonyamt:garbage@127.0.0.1/filespace/",
+ 0, "http", "sonyamt:garbage@127.0.0.1", "sonyamt", "garbage", "127.0.0.1", NULL, "/filespace/", NULL, NULL, 0
+ },
+ {
+ "http://sonyamt:garbage@[fe80::1]/filespace/",
+ 0, "http", "sonyamt:garbage@[fe80::1]", "sonyamt", "garbage", "fe80::1", NULL, "/filespace/", NULL, NULL, 0
+ },
+ {
+ "http://sonyamt@[fe80::1]/filespace/?arg1=store",
+ 0, "http", "sonyamt@[fe80::1]", "sonyamt", NULL, "fe80::1", NULL, "/filespace/", "arg1=store", NULL, 0
+ },
+ {
+ "//www.apache.org/",
+ 0, NULL, "www.apache.org", NULL, NULL, "www.apache.org", NULL, "/", NULL, NULL, 0
+ },
+};
+
+struct uph_test {
+ const char *hostinfo;
+ apr_status_t rv;
+ const char *hostname;
+ const char *port_str;
+ apr_port_t port;
+};
+
+struct uph_test uph_tests[] =
+{
+ {
+ "www.ibm.com:443",
+ 0, "www.ibm.com", "443", 443
+ },
+ {
+ "[fe80::1]:443",
+ 0, "fe80::1", "443", 443
+ },
+ {
+ "127.0.0.1:443",
+ 0, "127.0.0.1", "443", 443
+ },
+ {
+ "127.0.0.1",
+ APR_EGENERAL, NULL, NULL, 0
+ },
+ {
+ "[fe80:80",
+ APR_EGENERAL, NULL, NULL, 0
+ },
+ {
+ "fe80::80]:443",
+ APR_EGENERAL, NULL, NULL, 0
+ }
+};
+
+#if 0
+static void show_info(apr_status_t rv, apr_status_t expected, const apr_uri_t *info)
+{
+ if (rv != expected) {
+ fprintf(stderr, " actual rv: %d expected rv: %d\n", rv, expected);
+ }
+ else {
+ fprintf(stderr,
+ " scheme: %s\n"
+ " hostinfo: %s\n"
+ " user: %s\n"
+ " password: %s\n"
+ " hostname: %s\n"
+ " port_str: %s\n"
+ " path: %s\n"
+ " query: %s\n"
+ " fragment: %s\n"
+ " hostent: %p\n"
+ " port: %u\n"
+ " is_initialized: %u\n"
+ " dns_looked_up: %u\n"
+ " dns_resolved: %u\n",
+ info->scheme, info->hostinfo, info->user, info->password,
+ info->hostname, info->port_str, info->path, info->query,
+ info->fragment, info->hostent, info->port, info->is_initialized,
+ info->dns_looked_up, info->dns_resolved);
+ }
+}
+#endif
+
+static void test_aup(abts_case *tc, void *data)
+{
+ int i;
+ apr_status_t rv;
+ apr_uri_t info;
+ struct aup_test *t;
+ const char *s = NULL;
+
+ for (i = 0; i < sizeof(aup_tests) / sizeof(aup_tests[0]); i++) {
+ char msg[256];
+
+ memset(&info, 0, sizeof(info));
+ t = &aup_tests[i];
+ rv = apr_uri_parse(p, t->uri, &info);
+ apr_snprintf(msg, sizeof msg, "uri '%s': rv=%d not %d", t->uri,
+ rv, t->rv);
+ ABTS_ASSERT(tc, msg, rv == t->rv);
+ if (t->rv == APR_SUCCESS) {
+ ABTS_STR_EQUAL(tc, info.scheme, t->scheme);
+ ABTS_STR_EQUAL(tc, info.hostinfo, t->hostinfo);
+ ABTS_STR_EQUAL(tc, info.user, t->user);
+ ABTS_STR_EQUAL(tc, info.password, t->password);
+ ABTS_STR_EQUAL(tc, info.hostname, t->hostname);
+ ABTS_STR_EQUAL(tc, info.port_str, t->port_str);
+ ABTS_STR_EQUAL(tc, info.path, t->path);
+ ABTS_STR_EQUAL(tc, info.query, t->query);
+ ABTS_STR_EQUAL(tc, info.user, t->user);
+ ABTS_INT_EQUAL(tc, info.port, t->port);
+
+ s = apr_uri_unparse(p, &info, APR_URI_UNP_REVEALPASSWORD);
+ ABTS_STR_EQUAL(tc, s, t->uri);
+ }
+ }
+}
+
+static void test_uph(abts_case *tc, void *data)
+{
+ int i;
+ apr_status_t rv;
+ apr_uri_t info;
+ struct uph_test *t;
+
+ for (i = 0; i < sizeof(uph_tests) / sizeof(uph_tests[0]); i++) {
+ memset(&info, 0, sizeof(info));
+ t = &uph_tests[i];
+ rv = apr_uri_parse_hostinfo(p, t->hostinfo, &info);
+ ABTS_INT_EQUAL(tc, rv, t->rv);
+ if (t->rv == APR_SUCCESS) {
+ ABTS_STR_EQUAL(tc, info.hostname, t->hostname);
+ ABTS_STR_EQUAL(tc, info.port_str, t->port_str);
+ ABTS_INT_EQUAL(tc, info.port, t->port);
+ }
+ }
+}
+
+abts_suite *testuri(abts_suite *suite)
+{
+ suite = ADD_SUITE(suite);
+
+ abts_run_test(suite, test_aup, NULL);
+ abts_run_test(suite, test_uph, NULL);
+
+ return suite;
+}
+
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "abts.h"
+#include "testutil.h"
+#include "apr_pools.h"
+
+apr_pool_t *p;
+
+void apr_assert_success(abts_case* tc, const char* context, apr_status_t rv)
+{
+ if (rv == APR_ENOTIMPL) {
+ ABTS_NOT_IMPL(tc, context);
+ }
+
+ if (rv != APR_SUCCESS) {
+ char buf[STRING_MAX], ebuf[128];
+ sprintf(buf, "%s (%d): %s\n", context, rv,
+ apr_strerror(rv, ebuf, sizeof ebuf));
+ ABTS_FAIL(tc, buf);
+ }
+}
+
+void initialize(void) {
+ if (apr_initialize() != APR_SUCCESS) {
+ abort();
+ }
+ atexit(apr_terminate);
+
+ apr_pool_create(&p, NULL);
+ apr_pool_tag(p, "apr-util global test pool");
+}
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr_pools.h"
+#include "abts.h"
+
+#ifndef APR_TEST_UTIL
+#define APR_TEST_UTIL
+
+/* XXX FIXME */
+#ifdef WIN32
+#define EXTENSION ".exe"
+#elif NETWARE
+#define EXTENSION ".nlm"
+#else
+#define EXTENSION
+#endif
+
+#define STRING_MAX 8096
+
+/* Some simple functions to make the test apps easier to write and
+ * a bit more consistent...
+ */
+
+extern apr_pool_t *p;
+
+/* Assert that RV is an APR_SUCCESS value; else fail giving strerror
+ * for RV and CONTEXT message. */
+void apr_assert_success(abts_case* tc, const char *context, apr_status_t rv);
+
+void initialize(void);
+
+abts_suite *teststrmatch(abts_suite *suite);
+abts_suite *testuri(abts_suite *suite);
+abts_suite *testuuid(abts_suite *suite);
+abts_suite *testbuckets(abts_suite *suite);
+abts_suite *testpass(abts_suite *suite);
+abts_suite *testmd4(abts_suite *suite);
+abts_suite *testmd5(abts_suite *suite);
+abts_suite *testldap(abts_suite *suite);
+abts_suite *testdbd(abts_suite *suite);
+
+#endif /* APR_TEST_INCLUDES */
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "testutil.h"
+#include "apr_general.h"
+#include "apr_uuid.h"
+
+static void test_uuid_parse(abts_case *tc, void *data)
+{
+ apr_uuid_t uuid;
+ apr_uuid_t uuid2;
+ char buf[APR_UUID_FORMATTED_LENGTH + 1];
+
+ apr_uuid_get(&uuid);
+ apr_uuid_format(buf, &uuid);
+
+ apr_uuid_parse(&uuid2, buf);
+ ABTS_ASSERT(tc, "parse produced a different UUID",
+ memcmp(&uuid, &uuid2, sizeof(uuid)) == 0);
+}
+
+static void test_gen2(abts_case *tc, void *data)
+{
+ apr_uuid_t uuid;
+ apr_uuid_t uuid2;
+
+ /* generate two of them quickly */
+ apr_uuid_get(&uuid);
+ apr_uuid_get(&uuid2);
+
+ ABTS_ASSERT(tc, "generated the same UUID twice",
+ memcmp(&uuid, &uuid2, sizeof(uuid)) != 0);
+}
+
+abts_suite *testuuid(abts_suite *suite)
+{
+ suite = ADD_SUITE(suite);
+
+ abts_run_test(suite, test_uuid_parse, NULL);
+ abts_run_test(suite, test_gen2, NULL);
+
+ return suite;
+}
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "apr.h"
+#include "apr_errno.h"
+#include "apr_general.h"
+#include "apr_strings.h"
+#include "apr_xlate.h"
+
+static const char test_utf8[] = "Edelwei\xc3\x9f";
+static const char test_utf7[] = "Edelwei+AN8-";
+static const char test_latin1[] = "Edelwei\xdf";
+static const char test_latin2[] = "Edelwei\xdf";
+
+
+static int check_status (apr_status_t status, const char *msg)
+{
+ if (status)
+ {
+ static char buf[1024];
+ printf("ERROR: %s\n %s\n", msg,
+ apr_strerror(status, buf, sizeof(buf)));
+ return 1;
+ }
+ return 0;
+}
+
+static int test_conversion (apr_xlate_t *convset,
+ const char *inbuf,
+ const char *expected)
+{
+ static char buf[1024];
+ int retcode = 0;
+ apr_size_t inbytes_left = strlen(inbuf);
+ apr_size_t outbytes_left = sizeof(buf) - 1;
+ apr_status_t status = apr_xlate_conv_buffer(convset,
+ inbuf,
+ &inbytes_left,
+ buf,
+ &outbytes_left);
+ if (status == APR_SUCCESS) {
+ status = apr_xlate_conv_buffer(convset, NULL, NULL,
+ buf + sizeof(buf) - outbytes_left - 1,
+ &outbytes_left);
+ }
+ buf[sizeof(buf) - outbytes_left - 1] = '\0';
+ retcode |= check_status(status, "apr_xlate_conv_buffer");
+ if ((!status || APR_STATUS_IS_INCOMPLETE(status))
+ && strcmp(buf, expected))
+ {
+ printf("ERROR: expected: '%s'\n actual: '%s'"
+ "\n inbytes_left: %"APR_SIZE_T_FMT"\n",
+ expected, buf, inbytes_left);
+ retcode |= 1;
+ }
+ return retcode;
+}
+
+static int one_test (const char *cs1, const char *cs2,
+ const char *str1, const char *str2,
+ apr_pool_t *pool)
+{
+ apr_xlate_t *convset;
+ const char *msg = apr_psprintf(pool, "apr_xlate_open(%s, %s)", cs2, cs1);
+ int retcode = check_status(apr_xlate_open(&convset, cs2, cs1, pool), msg);
+ if (!retcode)
+ {
+ retcode |= test_conversion(convset, str1, str2);
+ retcode |= check_status(apr_xlate_close(convset), "apr_xlate_close");
+ }
+ printf("%s: %s -> %s\n", (retcode ? "FAIL" : "PASS"), cs1, cs2);
+ return retcode;
+}
+
+
+int main (int argc, char **argv)
+{
+ apr_pool_t *pool;
+ int retcode = 0;
+
+#ifndef APR_HAS_XLATE
+ puts("SKIP: apr_xlate not implemented");
+ return 0;
+#endif
+
+ apr_initialize();
+ atexit(apr_terminate);
+ apr_pool_create(&pool, NULL);
+
+ /* 1. Identity transformation: UTF-8 -> UTF-8 */
+ retcode |= one_test("UTF-8", "UTF-8", test_utf8, test_utf8, pool);
+
+ /* 2. UTF-8 <-> ISO-8859-1 */
+ retcode |= one_test("UTF-8", "ISO-8859-1", test_utf8, test_latin1, pool);
+ retcode |= one_test("ISO-8859-1", "UTF-8", test_latin1, test_utf8, pool);
+
+ /* 3. ISO-8859-1 <-> ISO-8859-2, identity */
+ retcode |= one_test("ISO-8859-1", "ISO-8859-2",
+ test_latin1, test_latin2, pool);
+ retcode |= one_test("ISO-8859-2", "ISO-8859-1",
+ test_latin2, test_latin1, pool);
+
+ /* 4. Transformation using charset aliases */
+ retcode |= one_test("UTF-8", "UTF-7", test_utf8, test_utf7, pool);
+ retcode |= one_test("UTF-7", "UTF-8", test_utf7, test_utf8, pool);
+
+ return retcode;
+}
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_general.h"
+#include "apr_xml.h"
+
+#if APR_HAVE_STDLIB_H
+#include <stdlib.h> /* for exit() */
+#endif
+
+static const char *progname;
+static const char *usage = "%s [xmlfile]\nIt will create "
+ "a dummy XML file if none is supplied";
+/*
+ * If our platform knows about the tmpnam() external buffer size, create
+ * a buffer to pass in. This is needed in a threaded environment, or
+ * one that thinks it is (like HP-UX).
+ */
+
+#ifdef L_tmpnam
+static char tname_buf[L_tmpnam];
+#else
+static char *tname_buf = NULL;
+#endif
+
+static apr_status_t create_dummy_file_error(apr_pool_t *p, apr_file_t **fd)
+{
+ apr_status_t rv;
+ char *tmpfile;
+ int i;
+ apr_off_t off = 0L;
+ tmpfile = tmpnam(tname_buf);
+
+ if ((tmpfile == NULL) || (*tmpfile == '\0')) {
+ fprintf(stderr, "unable to generate temporary filename\n");
+ if (errno == 0) {
+ errno = ENOENT;
+ }
+ perror("tmpnam");
+ return APR_ENOENT;
+ }
+ rv = apr_file_open(fd, tmpfile, APR_CREATE|APR_TRUNCATE|APR_DELONCLOSE|
+ APR_READ|APR_WRITE|APR_EXCL, APR_OS_DEFAULT, p);
+
+ if (rv != APR_SUCCESS)
+ return rv;
+ rv = apr_file_puts("<?xml version=\"1.0\" ?>\n<maryx>"
+ "<had a=\"little\"/><lamb its='fleece "
+ "was white as snow' />\n", *fd);
+ if (rv != APR_SUCCESS)
+ return rv;
+
+ for (i = 0; i < 5000; i++) {
+ rv = apr_file_puts("<hmm roast=\"lamb\" "
+ "for=\"dinner\">yummy</hmm>\n", *fd);
+ if (rv != APR_SUCCESS)
+ return rv;
+ }
+ rv = apr_file_puts("</mary>\n", *fd);
+ if (rv != APR_SUCCESS)
+ return rv;
+
+ return apr_file_seek(*fd, APR_SET, &off);
+}
+
+static apr_status_t create_dummy_file(apr_pool_t *p, apr_file_t **fd)
+{
+ apr_status_t rv;
+ char *tmpfile;
+ int i;
+ apr_off_t off = 0L;
+ tmpfile = tmpnam(tname_buf);
+
+ if ((tmpfile == NULL) || (*tmpfile == '\0')) {
+ fprintf(stderr, "unable to generate temporary filename\n");
+ if (errno == 0) {
+ errno = ENOENT;
+ }
+ perror("tmpnam");
+ return APR_ENOENT;
+ }
+ rv = apr_file_open(fd, tmpfile, APR_CREATE|APR_TRUNCATE|APR_DELONCLOSE|
+ APR_READ|APR_WRITE|APR_EXCL, APR_OS_DEFAULT, p);
+
+ if (rv != APR_SUCCESS)
+ return rv;
+ rv = apr_file_puts("<?xml version=\"1.0\" ?>\n<mary>"
+ "<had a=\"little\"/><lamb its='fleece "
+ "was white as snow' />\n", *fd);
+ if (rv != APR_SUCCESS)
+ return rv;
+
+ for (i = 0; i < 5000; i++) {
+ rv = apr_file_puts("<hmm roast=\"lamb\" "
+ "for=\"dinner\">yummy</hmm>\n", *fd);
+ if (rv != APR_SUCCESS)
+ return rv;
+ }
+ rv = apr_file_puts("</mary>\n", *fd);
+ if (rv != APR_SUCCESS)
+ return rv;
+
+ rv = apr_file_seek(*fd, APR_SET, &off);
+ return rv;
+}
+
+static void dump_xml(apr_xml_elem *e, int level)
+{
+ apr_xml_attr *a;
+ apr_xml_elem *ec;
+
+ printf("%d: element %s\n", level, e->name);
+ if (e->attr) {
+ a = e->attr;
+ printf("%d:\tattrs\t", level);
+ while (a) {
+ printf("%s=%s\t", a->name, a->value);
+ a = a->next;
+ }
+ printf("\n");
+ }
+ if (e->first_child) {
+ ec = e->first_child;
+ while (ec) {
+ dump_xml(ec, level + 1);
+ ec = ec->next;
+ }
+ }
+}
+
+static void oops(const char *s1, const char *s2, apr_status_t rv)
+{
+ if (progname)
+ fprintf(stderr, "%s: ", progname);
+ fprintf(stderr, s1, s2);
+ if (rv != APR_SUCCESS) {
+ char buf[120];
+
+ fprintf(stderr, " (%s)", apr_strerror(rv, buf, sizeof buf));
+ }
+ fprintf(stderr, "\n");
+ exit(1);
+}
+
+int main(int argc, const char *const * argv)
+{
+ apr_pool_t *pool;
+ apr_file_t *fd;
+ apr_xml_parser *parser;
+ apr_xml_doc *doc;
+ apr_status_t rv;
+ char errbuf[2000];
+ char errbufXML[2000];
+
+ (void) apr_initialize();
+ apr_pool_create(&pool, NULL);
+ progname = argv[0];
+ if (argc == 1) {
+ rv = create_dummy_file(pool, &fd);
+ if (rv != APR_SUCCESS) {
+ oops("cannot create dummy file", "oops", rv);
+ }
+ }
+ else {
+ if (argc == 2) {
+ rv = apr_file_open(&fd, argv[1], APR_READ, APR_OS_DEFAULT, pool);
+ if (rv != APR_SUCCESS) {
+ oops("cannot open: %s", argv[1], rv);
+ }
+ }
+ else {
+ oops("usage: %s", usage, 0);
+ }
+ }
+ rv = apr_xml_parse_file(pool, &parser, &doc, fd, 2000);
+ if (rv != APR_SUCCESS) {
+ fprintf(stderr, "APR Error %s\nXML Error: %s\n",
+ apr_strerror(rv, errbuf, sizeof(errbuf)),
+ apr_xml_parser_geterror(parser, errbufXML, sizeof(errbufXML)));
+ return rv;
+ }
+ dump_xml(doc->root, 0);
+ apr_file_close(fd);
+ if (argc == 1) {
+ rv = create_dummy_file_error(pool, &fd);
+ if (rv != APR_SUCCESS) {
+ oops("cannot create error dummy file", "oops", rv);
+ }
+ rv = apr_xml_parse_file(pool, &parser, &doc, fd, 2000);
+ if (rv != APR_SUCCESS) {
+ fprintf(stdout, "APR Error %s\nXML Error: %s "
+ "(EXPECTED) This is good.\n",
+ apr_strerror(rv, errbuf, sizeof(errbuf)),
+ apr_xml_parser_geterror(parser, errbufXML, sizeof(errbufXML)));
+ rv = APR_SUCCESS; /* reset the return code, as the test is supposed to get this error */
+ }
+ else {
+ fprintf(stderr, "Expected an error, but didn't get one ;( ");
+ return APR_EGENERAL;
+ }
+ }
+ apr_pool_destroy(pool);
+ apr_terminate();
+ return rv;
+}
--- /dev/null
+#
+# NWGNUmakefile for GenUri.nlm (Apache2)
+# Declare the sub-directories to be built here
+#
+
+SUBDIRS = \
+ $(EOLIST)
+
+#
+# Get the 'head' of the build environment. This includes default targets and
+# paths to tools
+#
+
+include $(APR_WORK)\build\NWGNUhead.inc
+
+#
+# build this level's files
+
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(APR)/include/arch/NetWare \
+ $(APR)/include \
+ $(APRUTIL)/include \
+ $(APRUTIL)/include/private \
+ $(APRUTIL)/xml/expat/lib \
+ $(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 = Genuri
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION = Generate URI Delimiters
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME = genuri
+
+#
+# If this is specified, it will override VERSION value in
+# $(APR_WORK)\build\NWGNUenvironment.inc
+#
+NLM_VERSION = 1,0,0
+
+#
+# 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 =_LibCPrelude
+
+#
+# If this is specified it will be used by the link '-exit' directive
+#
+NLM_EXIT_SYM =_LibCPostlude
+
+#
+# If this is specified it will be used by the link '-check' directive
+#
+NLM_CHECK_SYM =
+
+#
+# If this is specified it will be used by the link '-flags' directive
+#
+NLM_FLAGS = PSEUDOPREEMPTION
+
+#
+# If this is specified it will be linked in with the XDCData option in the def
+# file instead of the default of $(APR)/misc/netware/apr.xdc. XDCData can
+# be disabled by setting APACHE_UNIPROC in the environment
+#
+XDCDATA =
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+$(OBJDIR)/Genuri.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)/gen_uri_delims.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 = \
+ libcpre.o \
+ $(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 = \
+ 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 = \
+ @libc.imp \
+ $(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ $(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 dependancies (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 $(APR_WORK)\build\NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(APR_WORK)\build\NWGNUtail.inc
+
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * apr_uri.c: URI related utility things
+ *
+ */
+
+#include <stdlib.h>
+
+#include "apu.h"
+#include "apr.h"
+#include "apr_general.h"
+#include "apr_strings.h"
+
+#define APR_WANT_STRFUNC
+#include "apr_want.h"
+
+#include "apr_uri.h"
+
+typedef struct schemes_t schemes_t;
+
+/** Structure to store various schemes and their default ports */
+struct schemes_t {
+ /** The name of the scheme */
+ const char *name;
+ /** The default port for the scheme */
+ apr_port_t default_port;
+};
+
+/* Some WWW schemes and their default ports; this is basically /etc/services */
+/* This will become global when the protocol abstraction comes */
+/* As the schemes are searched by a linear search, */
+/* they are sorted by their expected frequency */
+static schemes_t schemes[] =
+{
+ {"http", APR_URI_HTTP_DEFAULT_PORT},
+ {"ftp", APR_URI_FTP_DEFAULT_PORT},
+ {"https", APR_URI_HTTPS_DEFAULT_PORT},
+ {"gopher", APR_URI_GOPHER_DEFAULT_PORT},
+ {"ldap", APR_URI_LDAP_DEFAULT_PORT},
+ {"nntp", APR_URI_NNTP_DEFAULT_PORT},
+ {"snews", APR_URI_SNEWS_DEFAULT_PORT},
+ {"imap", APR_URI_IMAP_DEFAULT_PORT},
+ {"pop", APR_URI_POP_DEFAULT_PORT},
+ {"sip", APR_URI_SIP_DEFAULT_PORT},
+ {"rtsp", APR_URI_RTSP_DEFAULT_PORT},
+ {"wais", APR_URI_WAIS_DEFAULT_PORT},
+ {"z39.50r", APR_URI_WAIS_DEFAULT_PORT},
+ {"z39.50s", APR_URI_WAIS_DEFAULT_PORT},
+ {"prospero", APR_URI_PROSPERO_DEFAULT_PORT},
+ {"nfs", APR_URI_NFS_DEFAULT_PORT},
+ {"tip", APR_URI_TIP_DEFAULT_PORT},
+ {"acap", APR_URI_ACAP_DEFAULT_PORT},
+ {"telnet", APR_URI_TELNET_DEFAULT_PORT},
+ {"ssh", APR_URI_SSH_DEFAULT_PORT},
+ { NULL, 0xFFFF } /* unknown port */
+};
+
+APU_DECLARE(apr_port_t) apr_uri_port_of_scheme(const char *scheme_str)
+{
+ schemes_t *scheme;
+
+ if (scheme_str) {
+ for (scheme = schemes; scheme->name != NULL; ++scheme) {
+ if (strcasecmp(scheme_str, scheme->name) == 0) {
+ return scheme->default_port;
+ }
+ }
+ }
+ return 0;
+}
+
+/* Unparse a apr_uri_t structure to an URI string.
+ * Optionally suppress the password for security reasons.
+ */
+APU_DECLARE(char *) apr_uri_unparse(apr_pool_t *p,
+ const apr_uri_t *uptr,
+ unsigned flags)
+{
+ char *ret = "";
+
+ /* If suppressing the site part, omit both user name & scheme://hostname */
+ if (!(flags & APR_URI_UNP_OMITSITEPART)) {
+
+ /* Construct a "user:password@" string, honoring the passed
+ * APR_URI_UNP_ flags: */
+ if (uptr->user || uptr->password) {
+ ret = apr_pstrcat(p,
+ (uptr->user && !(flags & APR_URI_UNP_OMITUSER))
+ ? uptr->user : "",
+ (uptr->password && !(flags & APR_URI_UNP_OMITPASSWORD))
+ ? ":" : "",
+ (uptr->password && !(flags & APR_URI_UNP_OMITPASSWORD))
+ ? ((flags & APR_URI_UNP_REVEALPASSWORD)
+ ? uptr->password : "XXXXXXXX")
+ : "",
+ ((uptr->user && !(flags & APR_URI_UNP_OMITUSER)) ||
+ (uptr->password && !(flags & APR_URI_UNP_OMITPASSWORD)))
+ ? "@" : "",
+ NULL);
+ }
+
+ /* Construct scheme://site string */
+ if (uptr->hostname) {
+ int is_default_port;
+ const char *lbrk = "", *rbrk = "";
+
+ if (strchr(uptr->hostname, ':')) { /* v6 literal */
+ lbrk = "[";
+ rbrk = "]";
+ }
+
+ is_default_port =
+ (uptr->port_str == NULL ||
+ uptr->port == 0 ||
+ uptr->port == apr_uri_port_of_scheme(uptr->scheme));
+
+ if (uptr->scheme) {
+ ret = apr_pstrcat(p,
+ uptr->scheme, "://", ret,
+ lbrk, uptr->hostname, rbrk,
+ is_default_port ? "" : ":",
+ is_default_port ? "" : uptr->port_str,
+ NULL);
+ }
+ else {
+ /* A violation of RFC2396, but it is clear from section 3.2
+ * that the : belongs above to the scheme, while // belongs
+ * to the authority, so include the authority prefix while
+ * omitting the "scheme:" that the user neglected to pass us.
+ */
+ ret = apr_pstrcat(p,
+ "//", ret, lbrk, uptr->hostname, rbrk,
+ is_default_port ? "" : ":",
+ is_default_port ? "" : uptr->port_str,
+ NULL);
+ }
+ }
+ }
+
+ /* Should we suppress all path info? */
+ if (!(flags & APR_URI_UNP_OMITPATHINFO)) {
+ /* Append path, query and fragment strings: */
+ ret = apr_pstrcat(p,
+ ret,
+ (uptr->path)
+ ? uptr->path : "",
+ (uptr->query && !(flags & APR_URI_UNP_OMITQUERY))
+ ? "?" : "",
+ (uptr->query && !(flags & APR_URI_UNP_OMITQUERY))
+ ? uptr->query : "",
+ (uptr->fragment && !(flags & APR_URI_UNP_OMITQUERY))
+ ? "#" : NULL,
+ (uptr->fragment && !(flags & APR_URI_UNP_OMITQUERY))
+ ? uptr->fragment : NULL,
+ NULL);
+ }
+ return ret;
+}
+
+/* Here is the hand-optimized parse_uri_components(). There are some wild
+ * tricks we could pull in assembly language that we don't pull here... like we
+ * can do word-at-time scans for delimiter characters using the same technique
+ * that fast memchr()s use. But that would be way non-portable. -djg
+ */
+
+/* We have a apr_table_t that we can index by character and it tells us if the
+ * character is one of the interesting delimiters. Note that we even get
+ * compares for NUL for free -- it's just another delimiter.
+ */
+
+#define T_COLON 0x01 /* ':' */
+#define T_SLASH 0x02 /* '/' */
+#define T_QUESTION 0x04 /* '?' */
+#define T_HASH 0x08 /* '#' */
+#define T_NUL 0x80 /* '\0' */
+
+#if APR_CHARSET_EBCDIC
+/* Delimiter table for the EBCDIC character set */
+static const unsigned char uri_delims[256] = {
+ T_NUL,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,T_SLASH,0,0,0,0,0,0,0,0,0,0,0,0,0,T_QUESTION,
+ 0,0,0,0,0,0,0,0,0,0,T_COLON,T_HASH,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+};
+#else
+/* Delimiter table for the ASCII character set */
+static const unsigned char uri_delims[256] = {
+ T_NUL,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,T_HASH,0,0,0,0,0,0,0,0,0,0,0,T_SLASH,
+ 0,0,0,0,0,0,0,0,0,0,T_COLON,0,0,0,0,T_QUESTION,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+};
+#endif
+
+
+/* it works like this:
+ if (uri_delims[ch] & NOTEND_foobar) {
+ then we're not at a delimiter for foobar
+ }
+*/
+
+/* Note that we optimize the scheme scanning here, we cheat and let the
+ * compiler know that it doesn't have to do the & masking.
+ */
+#define NOTEND_SCHEME (0xff)
+#define NOTEND_HOSTINFO (T_SLASH | T_QUESTION | T_HASH | T_NUL)
+#define NOTEND_PATH (T_QUESTION | T_HASH | T_NUL)
+
+/* parse_uri_components():
+ * Parse a given URI, fill in all supplied fields of a uri_components
+ * structure. This eliminates the necessity of extracting host, port,
+ * path, query info repeatedly in the modules.
+ * Side effects:
+ * - fills in fields of uri_components *uptr
+ * - none on any of the r->* fields
+ */
+APU_DECLARE(int) apr_uri_parse(apr_pool_t *p, const char *uri,
+ apr_uri_t *uptr)
+{
+ const char *s;
+ const char *s1;
+ const char *hostinfo;
+ char *endstr;
+ int port;
+ int v6_offset1 = 0, v6_offset2 = 0;
+
+ /* Initialize the structure. parse_uri() and parse_uri_components()
+ * can be called more than once per request.
+ */
+ memset (uptr, '\0', sizeof(*uptr));
+ uptr->is_initialized = 1;
+
+ /* We assume the processor has a branch predictor like most --
+ * it assumes forward branches are untaken and backwards are taken. That's
+ * the reason for the gotos. -djg
+ */
+ if (uri[0] == '/') {
+ /* RFC2396 #4.3 says that two leading slashes mean we have an
+ * authority component, not a path! Fixing this looks scary
+ * with the gotos here. But if the existing logic is valid,
+ * then presumably a goto pointing to deal_with_authority works.
+ *
+ * RFC2396 describes this as resolving an ambiguity. In the
+ * case of three or more slashes there would seem to be no
+ * ambiguity, so it is a path after all.
+ */
+ if (uri[1] == '/' && uri[2] != '/') {
+ s = uri + 2 ;
+ goto deal_with_authority ;
+ }
+
+deal_with_path:
+ /* we expect uri to point to first character of path ... remember
+ * that the path could be empty -- http://foobar?query for example
+ */
+ s = uri;
+ while ((uri_delims[*(unsigned char *)s] & NOTEND_PATH) == 0) {
+ ++s;
+ }
+ if (s != uri) {
+ uptr->path = apr_pstrmemdup(p, uri, s - uri);
+ }
+ if (*s == 0) {
+ return APR_SUCCESS;
+ }
+ if (*s == '?') {
+ ++s;
+ s1 = strchr(s, '#');
+ if (s1) {
+ uptr->fragment = apr_pstrdup(p, s1 + 1);
+ uptr->query = apr_pstrmemdup(p, s, s1 - s);
+ }
+ else {
+ uptr->query = apr_pstrdup(p, s);
+ }
+ return APR_SUCCESS;
+ }
+ /* otherwise it's a fragment */
+ uptr->fragment = apr_pstrdup(p, s + 1);
+ return APR_SUCCESS;
+ }
+
+ /* find the scheme: */
+ s = uri;
+ while ((uri_delims[*(unsigned char *)s] & NOTEND_SCHEME) == 0) {
+ ++s;
+ }
+ /* scheme must be non-empty and followed by :// */
+ if (s == uri || s[0] != ':' || s[1] != '/' || s[2] != '/') {
+ goto deal_with_path; /* backwards predicted taken! */
+ }
+
+ uptr->scheme = apr_pstrmemdup(p, uri, s - uri);
+ s += 3;
+
+deal_with_authority:
+ hostinfo = s;
+ while ((uri_delims[*(unsigned char *)s] & NOTEND_HOSTINFO) == 0) {
+ ++s;
+ }
+ uri = s; /* whatever follows hostinfo is start of uri */
+ uptr->hostinfo = apr_pstrmemdup(p, hostinfo, uri - hostinfo);
+
+ /* If there's a username:password@host:port, the @ we want is the last @...
+ * too bad there's no memrchr()... For the C purists, note that hostinfo
+ * is definately not the first character of the original uri so therefore
+ * &hostinfo[-1] < &hostinfo[0] ... and this loop is valid C.
+ */
+ do {
+ --s;
+ } while (s >= hostinfo && *s != '@');
+ if (s < hostinfo) {
+ /* again we want the common case to be fall through */
+deal_with_host:
+ /* We expect hostinfo to point to the first character of
+ * the hostname. If there's a port it is the first colon,
+ * except with IPv6.
+ */
+ if (*hostinfo == '[') {
+ v6_offset1 = 1;
+ v6_offset2 = 2;
+ s = memchr(hostinfo, ']', uri - hostinfo);
+ if (s == NULL) {
+ return APR_EGENERAL;
+ }
+ if (*++s != ':') {
+ s = NULL; /* no port */
+ }
+ }
+ else {
+ s = memchr(hostinfo, ':', uri - hostinfo);
+ }
+ if (s == NULL) {
+ /* we expect the common case to have no port */
+ uptr->hostname = apr_pstrmemdup(p,
+ hostinfo + v6_offset1,
+ uri - hostinfo - v6_offset2);
+ goto deal_with_path;
+ }
+ uptr->hostname = apr_pstrmemdup(p,
+ hostinfo + v6_offset1,
+ s - hostinfo - v6_offset2);
+ ++s;
+ uptr->port_str = apr_pstrmemdup(p, s, uri - s);
+ if (uri != s) {
+ port = strtol(uptr->port_str, &endstr, 10);
+ uptr->port = port;
+ if (*endstr == '\0') {
+ goto deal_with_path;
+ }
+ /* Invalid characters after ':' found */
+ return APR_EGENERAL;
+ }
+ uptr->port = apr_uri_port_of_scheme(uptr->scheme);
+ goto deal_with_path;
+ }
+
+ /* first colon delimits username:password */
+ s1 = memchr(hostinfo, ':', s - hostinfo);
+ if (s1) {
+ uptr->user = apr_pstrmemdup(p, hostinfo, s1 - hostinfo);
+ ++s1;
+ uptr->password = apr_pstrmemdup(p, s1, s - s1);
+ }
+ else {
+ uptr->user = apr_pstrmemdup(p, hostinfo, s - hostinfo);
+ }
+ hostinfo = s + 1;
+ goto deal_with_host;
+}
+
+/* Special case for CONNECT parsing: it comes with the hostinfo part only */
+/* See the INTERNET-DRAFT document "Tunneling SSL Through a WWW Proxy"
+ * currently at http://www.mcom.com/newsref/std/tunneling_ssl.html
+ * for the format of the "CONNECT host:port HTTP/1.0" request
+ */
+APU_DECLARE(int) apr_uri_parse_hostinfo(apr_pool_t *p,
+ const char *hostinfo,
+ apr_uri_t *uptr)
+{
+ const char *s;
+ char *endstr;
+ const char *rsb;
+ int v6_offset1 = 0;
+
+ /* Initialize the structure. parse_uri() and parse_uri_components()
+ * can be called more than once per request.
+ */
+ memset(uptr, '\0', sizeof(*uptr));
+ uptr->is_initialized = 1;
+ uptr->hostinfo = apr_pstrdup(p, hostinfo);
+
+ /* We expect hostinfo to point to the first character of
+ * the hostname. There must be a port, separated by a colon
+ */
+ if (*hostinfo == '[') {
+ if ((rsb = strchr(hostinfo, ']')) == NULL ||
+ *(rsb + 1) != ':') {
+ return APR_EGENERAL;
+ }
+ /* literal IPv6 address */
+ s = rsb + 1;
+ ++hostinfo;
+ v6_offset1 = 1;
+ }
+ else {
+ s = strchr(hostinfo, ':');
+ }
+ if (s == NULL) {
+ return APR_EGENERAL;
+ }
+ uptr->hostname = apr_pstrndup(p, hostinfo, s - hostinfo - v6_offset1);
+ ++s;
+ uptr->port_str = apr_pstrdup(p, s);
+ if (*s != '\0') {
+ uptr->port = (unsigned short) strtol(uptr->port_str, &endstr, 10);
+ if (*endstr == '\0') {
+ return APR_SUCCESS;
+ }
+ /* Invalid characters after ':' found */
+ }
+ return APR_EGENERAL;
+}
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+
+/* generate a apr_table_t of 256 values, where certain characters are
+ * marked "interesting"... for the uri parsing process.
+ */
+
+int main(int argc, char *argv[])
+{
+ int i;
+ char *value;
+
+ printf("/* this file is automatically generated by "
+ "gen_uri_delims, do not edit */\n");
+ printf("static const unsigned char uri_delims[256] = {");
+ for (i = 0; i < 256; ++i) {
+ if (i % 20 == 0)
+ printf("\n ");
+ switch (i) {
+ case ':': value = "T_COLON"; break;
+ case '/': value = "T_SLASH"; break;
+ case '?': value = "T_QUESTION"; break;
+ case '#': value = "T_HASH"; break;
+ case '\0': value = "T_NUL"; break;
+ default: value = "0"; break;
+ }
+ printf("%s%c", value, (i < 255) ? ',' : ' ');
+ }
+ printf("\n};\n");
+
+ return 0;
+}
--- /dev/null
+# Microsoft Developer Studio Project File - Name="gen_uri_delims" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=gen_uri_delims - 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 "gen_uri_delims.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 "gen_uri_delims.mak" CFG="gen_uri_delims - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "gen_uri_delims - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE "gen_uri_delims - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "gen_uri_delims - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ""
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /Fd"Release\gen_uri_delims" /FD /c
+# ADD BASE RSC /l 0x809 /d "NDEBUG"
+# ADD RSC /l 0x809 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:console /pdb:"Release\gen_uri_delims.pdb" /machine:I386
+# SUBTRACT BASE LINK32 /pdb:none
+# ADD LINK32 kernel32.lib /nologo /subsystem:console /pdb:"Release\gen_uri_delims.pdb" /machine:I386
+# SUBTRACT LINK32 /pdb:none
+
+!ELSEIF "$(CFG)" == "gen_uri_delims - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ""
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /Fd"Debug\gen_uri_delims" /FD /c
+# ADD BASE RSC /l 0x809 /d "_DEBUG"
+# ADD RSC /l 0x809 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib /nologo /subsystem:console /incremental:no /pdb:"Debug\gen_uri_delims.pdb" /debug /machine:I386
+# SUBTRACT BASE LINK32 /pdb:none
+# ADD LINK32 kernel32.lib /nologo /subsystem:console /incremental:no /pdb:"Debug\gen_uri_delims.pdb" /debug /machine:I386
+# SUBTRACT LINK32 /pdb:none
+
+!ENDIF
+
+# Begin Target
+
+# Name "gen_uri_delims - Win32 Release"
+# Name "gen_uri_delims - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\gen_uri_delims.c
+# End Source File
+# End Target
+# End Project
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apu.h"
+#include "apu_config.h"
+#include "apr_lib.h"
+#include "apr_strings.h"
+#include "apr_portable.h"
+#include "apr_xlate.h"
+
+/* If no implementation is available, don't generate code here since
+ * apr_xlate.h emitted macros which return APR_ENOTIMPL.
+ */
+
+#if APR_HAS_XLATE
+
+#ifdef HAVE_STDDEF_H
+#include <stddef.h> /* for NULL */
+#endif
+#if APR_HAVE_STRING_H
+#include <string.h>
+#endif
+#if APR_HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#ifdef HAVE_ICONV_H
+#include <iconv.h>
+#endif
+#if APU_HAVE_APR_ICONV
+#include <apr_iconv.h>
+#endif
+
+#if defined(APU_ICONV_INBUF_CONST) || APU_HAVE_APR_ICONV
+#define ICONV_INBUF_TYPE const char **
+#else
+#define ICONV_INBUF_TYPE char **
+#endif
+
+#ifndef min
+#define min(x,y) ((x) <= (y) ? (x) : (y))
+#endif
+
+struct apr_xlate_t {
+ apr_pool_t *pool;
+ char *frompage;
+ char *topage;
+ char *sbcs_table;
+#if APU_HAVE_ICONV
+ iconv_t ich;
+#elif APU_HAVE_APR_ICONV
+ apr_iconv_t ich;
+#endif
+};
+
+
+static const char *handle_special_names(const char *page, apr_pool_t *pool)
+{
+ if (page == APR_DEFAULT_CHARSET) {
+ return apr_os_default_encoding(pool);
+ }
+ else if (page == APR_LOCALE_CHARSET) {
+ return apr_os_locale_encoding(pool);
+ }
+ else {
+ return page;
+ }
+}
+
+static apr_status_t apr_xlate_cleanup(void *convset)
+{
+ apr_xlate_t *old = convset;
+
+#if APU_HAVE_APR_ICONV
+ if (old->ich != (apr_iconv_t)-1) {
+ return apr_iconv_close(old->ich, old->pool);
+ }
+
+#elif APU_HAVE_ICONV
+ if (old->ich != (iconv_t)-1) {
+ if (iconv_close(old->ich)) {
+ int rv = errno;
+
+ /* Sometimes, iconv is not good about setting errno. */
+ return rv ? rv : APR_EINVAL;
+ }
+ }
+#endif
+
+ return APR_SUCCESS;
+}
+
+#if APU_HAVE_ICONV
+static void check_sbcs(apr_xlate_t *convset)
+{
+ char inbuf[256], outbuf[256];
+ char *inbufptr = inbuf;
+ char *outbufptr = outbuf;
+ apr_size_t inbytes_left, outbytes_left;
+ int i;
+ apr_size_t translated;
+
+ for (i = 0; i < sizeof(inbuf); i++) {
+ inbuf[i] = i;
+ }
+
+ inbytes_left = outbytes_left = sizeof(inbuf);
+ translated = iconv(convset->ich, (ICONV_INBUF_TYPE)&inbufptr,
+ &inbytes_left, &outbufptr, &outbytes_left);
+
+ if (translated != (apr_size_t)-1
+ && inbytes_left == 0
+ && outbytes_left == 0) {
+ /* hurray... this is simple translation; save the table,
+ * close the iconv descriptor
+ */
+
+ convset->sbcs_table = apr_palloc(convset->pool, sizeof(outbuf));
+ memcpy(convset->sbcs_table, outbuf, sizeof(outbuf));
+ iconv_close(convset->ich);
+ convset->ich = (iconv_t)-1;
+
+ /* TODO: add the table to the cache */
+ }
+ else {
+ /* reset the iconv descriptor, since it's now in an undefined
+ * state. */
+ iconv_close(convset->ich);
+ convset->ich = iconv_open(convset->topage, convset->frompage);
+ }
+}
+#elif APU_HAVE_APR_ICONV
+static void check_sbcs(apr_xlate_t *convset)
+{
+ char inbuf[256], outbuf[256];
+ char *inbufptr = inbuf;
+ char *outbufptr = outbuf;
+ apr_size_t inbytes_left, outbytes_left;
+ int i;
+ apr_size_t translated;
+ apr_status_t rv;
+
+ for (i = 0; i < sizeof(inbuf); i++) {
+ inbuf[i] = i;
+ }
+
+ inbytes_left = outbytes_left = sizeof(inbuf);
+ rv = apr_iconv(convset->ich, (ICONV_INBUF_TYPE)&inbufptr,
+ &inbytes_left, &outbufptr, &outbytes_left,
+ &translated);
+
+ if ((rv == APR_SUCCESS)
+ && (translated != (apr_size_t)-1)
+ && inbytes_left == 0
+ && outbytes_left == 0) {
+ /* hurray... this is simple translation; save the table,
+ * close the iconv descriptor
+ */
+
+ convset->sbcs_table = apr_palloc(convset->pool, sizeof(outbuf));
+ memcpy(convset->sbcs_table, outbuf, sizeof(outbuf));
+ apr_iconv_close(convset->ich, convset->pool);
+ convset->ich = (apr_iconv_t)-1;
+
+ /* TODO: add the table to the cache */
+ }
+ else {
+ /* reset the iconv descriptor, since it's now in an undefined
+ * state. */
+ apr_iconv_close(convset->ich, convset->pool);
+ rv = apr_iconv_open(convset->topage, convset->frompage,
+ convset->pool, &convset->ich);
+ }
+}
+#endif /* APU_HAVE_APR_ICONV */
+
+static void make_identity_table(apr_xlate_t *convset)
+{
+ int i;
+
+ convset->sbcs_table = apr_palloc(convset->pool, 256);
+ for (i = 0; i < 256; i++)
+ convset->sbcs_table[i] = i;
+}
+
+APU_DECLARE(apr_status_t) apr_xlate_open(apr_xlate_t **convset,
+ const char *topage,
+ const char *frompage,
+ apr_pool_t *pool)
+{
+ apr_status_t rv;
+ apr_xlate_t *new;
+ int found = 0;
+
+ *convset = NULL;
+
+ topage = handle_special_names(topage, pool);
+ frompage = handle_special_names(frompage, pool);
+
+ new = (apr_xlate_t *)apr_pcalloc(pool, sizeof(apr_xlate_t));
+ if (!new) {
+ return APR_ENOMEM;
+ }
+
+ new->pool = pool;
+ new->topage = apr_pstrdup(pool, topage);
+ new->frompage = apr_pstrdup(pool, frompage);
+ if (!new->topage || !new->frompage) {
+ return APR_ENOMEM;
+ }
+
+#ifdef TODO
+ /* search cache of codepage pairs; we may be able to avoid the
+ * expensive iconv_open()
+ */
+
+ set found to non-zero if found in the cache
+#endif
+
+ if ((! found) && (strcmp(topage, frompage) == 0)) {
+ /* to and from are the same */
+ found = 1;
+ make_identity_table(new);
+ }
+
+#if APU_HAVE_APR_ICONV
+ if (!found) {
+ rv = apr_iconv_open(topage, frompage, pool, &new->ich);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+ found = 1;
+ check_sbcs(new);
+ } else
+ new->ich = (apr_iconv_t)-1;
+
+#elif APU_HAVE_ICONV
+ if (!found) {
+ new->ich = iconv_open(topage, frompage);
+ if (new->ich == (iconv_t)-1) {
+ int rv = errno;
+ /* Sometimes, iconv is not good about setting errno. */
+ return rv ? rv : APR_EINVAL;
+ }
+ found = 1;
+ check_sbcs(new);
+ } else
+ new->ich = (iconv_t)-1;
+#endif /* APU_HAVE_ICONV */
+
+ if (found) {
+ *convset = new;
+ apr_pool_cleanup_register(pool, (void *)new, apr_xlate_cleanup,
+ apr_pool_cleanup_null);
+ rv = APR_SUCCESS;
+ }
+ else {
+ rv = APR_EINVAL; /* iconv() would return EINVAL if it
+ couldn't handle the pair */
+ }
+
+ return rv;
+}
+
+APU_DECLARE(apr_status_t) apr_xlate_sb_get(apr_xlate_t *convset, int *onoff)
+{
+ *onoff = convset->sbcs_table != NULL;
+ return APR_SUCCESS;
+}
+
+APU_DECLARE(apr_status_t) apr_xlate_conv_buffer(apr_xlate_t *convset,
+ const char *inbuf,
+ apr_size_t *inbytes_left,
+ char *outbuf,
+ apr_size_t *outbytes_left)
+{
+ apr_status_t status = APR_SUCCESS;
+
+#if APU_HAVE_APR_ICONV
+ if (convset->ich != (apr_iconv_t)-1) {
+ const char *inbufptr = inbuf;
+ apr_size_t translated;
+ char *outbufptr = outbuf;
+ status = apr_iconv(convset->ich, &inbufptr, inbytes_left,
+ &outbufptr, outbytes_left, &translated);
+
+ /* If everything went fine but we ran out of buffer, don't
+ * report it as an error. Caller needs to look at the two
+ * bytes-left values anyway.
+ *
+ * There are three expected cases where rc is -1. In each of
+ * these cases, *inbytes_left != 0.
+ * a) the non-error condition where we ran out of output
+ * buffer
+ * b) the non-error condition where we ran out of input (i.e.,
+ * the last input character is incomplete)
+ * c) the error condition where the input is invalid
+ */
+ switch (status) {
+
+ case E2BIG: /* out of space on output */
+ status = 0; /* change table lookup code below if you
+ make this an error */
+ break;
+
+ case EINVAL: /* input character not complete (yet) */
+ status = APR_INCOMPLETE;
+ break;
+
+ case EILSEQ: /* bad input byte */
+ status = APR_EINVAL;
+ break;
+
+ /* Sometimes, iconv is not good about setting errno. */
+ case 0:
+ if (*inbytes_left)
+ status = APR_INCOMPLETE;
+ break;
+
+ default:
+ break;
+ }
+ }
+ else
+
+#elif APU_HAVE_ICONV
+ if (convset->ich != (iconv_t)-1) {
+ const char *inbufptr = inbuf;
+ char *outbufptr = outbuf;
+ apr_size_t translated;
+ translated = iconv(convset->ich, (ICONV_INBUF_TYPE)&inbufptr,
+ inbytes_left, &outbufptr, outbytes_left);
+
+ /* If everything went fine but we ran out of buffer, don't
+ * report it as an error. Caller needs to look at the two
+ * bytes-left values anyway.
+ *
+ * There are three expected cases where rc is -1. In each of
+ * these cases, *inbytes_left != 0.
+ * a) the non-error condition where we ran out of output
+ * buffer
+ * b) the non-error condition where we ran out of input (i.e.,
+ * the last input character is incomplete)
+ * c) the error condition where the input is invalid
+ */
+ if (translated == (apr_size_t)-1) {
+ int rv = errno;
+ switch (rv) {
+
+ case E2BIG: /* out of space on output */
+ status = 0; /* change table lookup code below if you
+ make this an error */
+ break;
+
+ case EINVAL: /* input character not complete (yet) */
+ status = APR_INCOMPLETE;
+ break;
+
+ case EILSEQ: /* bad input byte */
+ status = APR_EINVAL;
+ break;
+
+ /* Sometimes, iconv is not good about setting errno. */
+ case 0:
+ status = APR_INCOMPLETE;
+ break;
+
+ default:
+ status = rv;
+ break;
+ }
+ }
+ }
+ else
+#endif
+
+ if (inbuf) {
+ int to_convert = min(*inbytes_left, *outbytes_left);
+ int converted = to_convert;
+ char *table = convset->sbcs_table;
+
+ while (to_convert) {
+ *outbuf = table[(unsigned char)*inbuf];
+ ++outbuf;
+ ++inbuf;
+ --to_convert;
+ }
+ *inbytes_left -= converted;
+ *outbytes_left -= converted;
+ }
+
+ return status;
+}
+
+APU_DECLARE(apr_int32_t) apr_xlate_conv_byte(apr_xlate_t *convset,
+ unsigned char inchar)
+{
+ if (convset->sbcs_table) {
+ return convset->sbcs_table[inchar];
+ }
+ else {
+ return -1;
+ }
+}
+
+APU_DECLARE(apr_status_t) apr_xlate_close(apr_xlate_t *convset)
+{
+ return apr_pool_cleanup_run(convset->pool, convset, apr_xlate_cleanup);
+}
+
+#else /* !APR_HAS_XLATE */
+
+APU_DECLARE(apr_status_t) apr_xlate_open(apr_xlate_t **convset,
+ const char *topage,
+ const char *frompage,
+ apr_pool_t *pool)
+{
+ return APR_ENOTIMPL;
+}
+
+APU_DECLARE(apr_status_t) apr_xlate_sb_get(apr_xlate_t *convset, int *onoff)
+{
+ return APR_ENOTIMPL;
+}
+
+APU_DECLARE(apr_int32_t) apr_xlate_conv_byte(apr_xlate_t *convset,
+ unsigned char inchar)
+{
+ return (-1);
+}
+
+APU_DECLARE(apr_status_t) apr_xlate_conv_buffer(apr_xlate_t *convset,
+ const char *inbuf,
+ apr_size_t *inbytes_left,
+ char *outbuf,
+ apr_size_t *outbytes_left)
+{
+ return APR_ENOTIMPL;
+}
+
+APU_DECLARE(apr_status_t) apr_xlate_close(apr_xlate_t *convset)
+{
+ return APR_ENOTIMPL;
+}
+
+#endif /* APR_HAS_XLATE */
--- /dev/null
+#
+# Declare the sub-directories to be built here
+#
+
+SUBDIRS = \
+ $(EOLIST)
+
+#
+# Get the 'head' of the build environment. This includes default targets and
+# paths to tools
+#
+
+include $(APR_WORK)\build\NWGNUhead.inc
+
+#
+# build this level's files
+
+#
+# Make sure all needed macro's are defined
+#
+
+#
+# These directories will be at the beginning of the include list, followed by
+# INCDIRS
+#
+XINCDIRS += \
+ $(APR)/include \
+ $(APR)/include/arch/NetWare \
+ $(APRUTIL)/include \
+ $(APRUTIL)/uri \
+ $(APRUTIL)/dbm/sdbm \
+ $(APRUTIL)/include/private \
+ $(APRUTIL)/xml/expat/lib \
+ $(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 =
+
+#
+# This is used by the link '-desc ' directive.
+# If left blank, NLM_NAME will be used.
+#
+NLM_DESCRIPTION =
+
+#
+# This is used by the '-threadname' directive. If left blank,
+# NLM_NAME Thread will be used.
+#
+NLM_THREAD_NAME =
+#
+# If this is specified, it will override VERSION value in
+# $(APR_WORK)\build\NWGNUenvironment.inc
+#
+NLM_VERSION =
+
+#
+# If this is specified, it will override the default of 64K
+#
+NLM_STACK_SIZE =
+
+#
+# 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 this is 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 $(APR)/misc/netware/apache.xdc. XDCData can
+# be disabled by setting APACHE_UNIPROC in the environment
+#
+XDCDATA =
+
+#
+# Declare all target files (you must add your files here)
+#
+
+#
+# If there is an NLM target, put it here
+#
+TARGET_nlm = \
+ $(EOLIST)
+
+#
+# If there is an LIB target, put it here
+#
+TARGET_lib = \
+ $(OBJDIR)/xmllib.lib \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the NLM target above.
+# Paths must all use the '/' character
+#
+FILES_nlm_objs = \
+ $(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 = \
+ $(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 = \
+ $(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 the default copyright.
+#
+FILE_nlm_copyright =
+
+#
+# Any additional imports go here
+#
+FILES_nlm_Ximports = \
+ $(EOLIST)
+
+#
+# Any symbols exported to here
+#
+FILES_nlm_exports = \
+ $(EOLIST)
+
+#
+# These are the OBJ files needed to create the LIB target above.
+# Paths must all use the '/' character
+#
+FILES_lib_objs = \
+ $(OBJDIR)/apr_xml.o \
+ $(OBJDIR)/xmlparse.o \
+ $(OBJDIR)/xmlrole.o \
+ $(OBJDIR)/xmltok.o \
+ $(EOLIST)
+
+#
+# implement targets and dependancies (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 $(APR_WORK)\build\NWGNUhead.inc for examples)
+#
+install :: nlms FORCE
+
+#
+# Any specialized rules here
+#
+
+vpath %.c expat/lib
+
+#
+# Include the 'tail' makefile that has targets that depend on variables defined
+# in this makefile
+#
+
+include $(APR_WORK)\build\NWGNUtail.inc
+
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "apr.h"
+#include "apr_strings.h"
+
+#define APR_WANT_STDIO /* for sprintf() */
+#define APR_WANT_STRFUNC
+#include "apr_want.h"
+
+#include "apr_xml.h"
+
+#include "apu_config.h"
+
+#ifdef APR_HAVE_OLD_EXPAT
+#include "xmlparse.h"
+#else
+#include "expat.h"
+#endif
+
+#define DEBUG_CR "\r\n"
+
+static const char APR_KW_xmlns[] = { 0x78, 0x6D, 0x6C, 0x6E, 0x73, '\0' };
+static const char APR_KW_xmlns_lang[] = { 0x78, 0x6D, 0x6C, 0x3A, 0x6C, 0x61, 0x6E, 0x67, '\0' };
+static const char APR_KW_DAV[] = { 0x44, 0x41, 0x56, 0x3A, '\0' };
+
+/* errors related to namespace processing */
+#define APR_XML_NS_ERROR_UNKNOWN_PREFIX (-1000)
+#define APR_XML_NS_ERROR_INVALID_DECL (-1001)
+
+/* test for a namespace prefix that begins with [Xx][Mm][Ll] */
+#define APR_XML_NS_IS_RESERVED(name) \
+ ( (name[0] == 0x58 || name[0] == 0x78) && \
+ (name[1] == 0x4D || name[1] == 0x6D) && \
+ (name[2] == 0x4C || name[2] == 0x6C) )
+
+
+/* the real (internal) definition of the parser context */
+struct apr_xml_parser {
+ apr_xml_doc *doc; /* the doc we're parsing */
+ apr_pool_t *p; /* the pool we allocate from */
+ apr_xml_elem *cur_elem; /* current element */
+
+ int error; /* an error has occurred */
+#define APR_XML_ERROR_EXPAT 1
+#define APR_XML_ERROR_PARSE_DONE 2
+/* also: public APR_XML_NS_ERROR_* values (if any) */
+
+ XML_Parser xp; /* the actual (Expat) XML parser */
+ enum XML_Error xp_err; /* stored Expat error code */
+};
+
+/* struct for scoping namespace declarations */
+typedef struct apr_xml_ns_scope {
+ const char *prefix; /* prefix used for this ns */
+ int ns; /* index into namespace table */
+ int emptyURI; /* the namespace URI is the empty string */
+ struct apr_xml_ns_scope *next; /* next scoped namespace */
+} apr_xml_ns_scope;
+
+
+/* return namespace table index for a given prefix */
+static int find_prefix(apr_xml_parser *parser, const char *prefix)
+{
+ apr_xml_elem *elem = parser->cur_elem;
+
+ /*
+ ** Walk up the tree, looking for a namespace scope that defines this
+ ** prefix.
+ */
+ for (; elem; elem = elem->parent) {
+ apr_xml_ns_scope *ns_scope = elem->ns_scope;
+
+ for (ns_scope = elem->ns_scope; ns_scope; ns_scope = ns_scope->next) {
+ if (strcmp(prefix, ns_scope->prefix) == 0) {
+ if (ns_scope->emptyURI) {
+ /*
+ ** It is possible to set the default namespace to an
+ ** empty URI string; this resets the default namespace
+ ** to mean "no namespace." We just found the prefix
+ ** refers to an empty URI, so return "no namespace."
+ */
+ return APR_XML_NS_NONE;
+ }
+
+ return ns_scope->ns;
+ }
+ }
+ }
+
+ /*
+ * If the prefix is empty (""), this means that a prefix was not
+ * specified in the element/attribute. The search that was performed
+ * just above did not locate a default namespace URI (which is stored
+ * into ns_scope with an empty prefix). This means the element/attribute
+ * has "no namespace". We have a reserved value for this.
+ */
+ if (*prefix == '\0') {
+ return APR_XML_NS_NONE;
+ }
+
+ /* not found */
+ return APR_XML_NS_ERROR_UNKNOWN_PREFIX;
+}
+
+static void start_handler(void *userdata, const char *name, const char **attrs)
+{
+ apr_xml_parser *parser = userdata;
+ apr_xml_elem *elem;
+ apr_xml_attr *attr;
+ apr_xml_attr *prev;
+ char *colon;
+ const char *quoted;
+ char *elem_name;
+
+ /* punt once we find an error */
+ if (parser->error)
+ return;
+
+ elem = apr_pcalloc(parser->p, sizeof(*elem));
+
+ /* prep the element */
+ elem->name = elem_name = apr_pstrdup(parser->p, name);
+
+ /* fill in the attributes (note: ends up in reverse order) */
+ while (*attrs) {
+ attr = apr_palloc(parser->p, sizeof(*attr));
+ attr->name = apr_pstrdup(parser->p, *attrs++);
+ attr->value = apr_pstrdup(parser->p, *attrs++);
+ attr->next = elem->attr;
+ elem->attr = attr;
+ }
+
+ /* hook the element into the tree */
+ if (parser->cur_elem == NULL) {
+ /* no current element; this also becomes the root */
+ parser->cur_elem = parser->doc->root = elem;
+ }
+ else {
+ /* this element appeared within the current elem */
+ elem->parent = parser->cur_elem;
+
+ /* set up the child/sibling links */
+ if (elem->parent->last_child == NULL) {
+ /* no first child either */
+ elem->parent->first_child = elem->parent->last_child = elem;
+ }
+ else {
+ /* hook onto the end of the parent's children */
+ elem->parent->last_child->next = elem;
+ elem->parent->last_child = elem;
+ }
+
+ /* this element is now the current element */
+ parser->cur_elem = elem;
+ }
+
+ /* scan the attributes for namespace declarations */
+ for (prev = NULL, attr = elem->attr;
+ attr;
+ attr = attr->next) {
+ if (strncmp(attr->name, APR_KW_xmlns, 5) == 0) {
+ const char *prefix = &attr->name[5];
+ apr_xml_ns_scope *ns_scope;
+
+ /* test for xmlns:foo= form and xmlns= form */
+ if (*prefix == 0x3A) {
+ /* a namespace prefix declaration must have a
+ non-empty value. */
+ if (attr->value[0] == '\0') {
+ parser->error = APR_XML_NS_ERROR_INVALID_DECL;
+ return;
+ }
+ ++prefix;
+ }
+ else if (*prefix != '\0') {
+ /* advance "prev" since "attr" is still present */
+ prev = attr;
+ continue;
+ }
+
+ /* quote the URI before we ever start working with it */
+ quoted = apr_xml_quote_string(parser->p, attr->value, 1);
+
+ /* build and insert the new scope */
+ ns_scope = apr_pcalloc(parser->p, sizeof(*ns_scope));
+ ns_scope->prefix = prefix;
+ ns_scope->ns = apr_xml_insert_uri(parser->doc->namespaces, quoted);
+ ns_scope->emptyURI = *quoted == '\0';
+ ns_scope->next = elem->ns_scope;
+ elem->ns_scope = ns_scope;
+
+ /* remove this attribute from the element */
+ if (prev == NULL)
+ elem->attr = attr->next;
+ else
+ prev->next = attr->next;
+
+ /* Note: prev will not be advanced since we just removed "attr" */
+ }
+ else if (strcmp(attr->name, APR_KW_xmlns_lang) == 0) {
+ /* save away the language (in quoted form) */
+ elem->lang = apr_xml_quote_string(parser->p, attr->value, 1);
+
+ /* remove this attribute from the element */
+ if (prev == NULL)
+ elem->attr = attr->next;
+ else
+ prev->next = attr->next;
+
+ /* Note: prev will not be advanced since we just removed "attr" */
+ }
+ else {
+ /* advance "prev" since "attr" is still present */
+ prev = attr;
+ }
+ }
+
+ /*
+ ** If an xml:lang attribute didn't exist (lang==NULL), then copy the
+ ** language from the parent element (if present).
+ **
+ ** NOTE: elem_size() *depends* upon this pointer equality.
+ */
+ if (elem->lang == NULL && elem->parent != NULL)
+ elem->lang = elem->parent->lang;
+
+ /* adjust the element's namespace */
+ colon = strchr(elem_name, 0x3A);
+ if (colon == NULL) {
+ /*
+ * The element is using the default namespace, which will always
+ * be found. Either it will be "no namespace", or a default
+ * namespace URI has been specified at some point.
+ */
+ elem->ns = find_prefix(parser, "");
+ }
+ else if (APR_XML_NS_IS_RESERVED(elem->name)) {
+ elem->ns = APR_XML_NS_NONE;
+ }
+ else {
+ *colon = '\0';
+ elem->ns = find_prefix(parser, elem->name);
+ elem->name = colon + 1;
+
+ if (APR_XML_NS_IS_ERROR(elem->ns)) {
+ parser->error = elem->ns;
+ return;
+ }
+ }
+
+ /* adjust all remaining attributes' namespaces */
+ for (attr = elem->attr; attr; attr = attr->next) {
+ /*
+ * apr_xml_attr defines this as "const" but we dup'd it, so we
+ * know that we can change it. a bit hacky, but the existing
+ * structure def is best.
+ */
+ char *attr_name = (char *)attr->name;
+
+ colon = strchr(attr_name, 0x3A);
+ if (colon == NULL) {
+ /*
+ * Attributes do NOT use the default namespace. Therefore,
+ * we place them into the "no namespace" category.
+ */
+ attr->ns = APR_XML_NS_NONE;
+ }
+ else if (APR_XML_NS_IS_RESERVED(attr->name)) {
+ attr->ns = APR_XML_NS_NONE;
+ }
+ else {
+ *colon = '\0';
+ attr->ns = find_prefix(parser, attr->name);
+ attr->name = colon + 1;
+
+ if (APR_XML_NS_IS_ERROR(attr->ns)) {
+ parser->error = attr->ns;
+ return;
+ }
+ }
+ }
+}
+
+static void end_handler(void *userdata, const char *name)
+{
+ apr_xml_parser *parser = userdata;
+
+ /* punt once we find an error */
+ if (parser->error)
+ return;
+
+ /* pop up one level */
+ parser->cur_elem = parser->cur_elem->parent;
+}
+
+static void cdata_handler(void *userdata, const char *data, int len)
+{
+ apr_xml_parser *parser = userdata;
+ apr_xml_elem *elem;
+ apr_text_header *hdr;
+ const char *s;
+
+ /* punt once we find an error */
+ if (parser->error)
+ return;
+
+ elem = parser->cur_elem;
+ s = apr_pstrndup(parser->p, data, len);
+
+ if (elem->last_child == NULL) {
+ /* no children yet. this cdata follows the start tag */
+ hdr = &elem->first_cdata;
+ }
+ else {
+ /* child elements exist. this cdata follows the last child. */
+ hdr = &elem->last_child->following_cdata;
+ }
+
+ apr_text_append(parser->p, hdr, s);
+}
+
+static apr_status_t cleanup_parser(void *ctx)
+{
+ apr_xml_parser *parser = ctx;
+
+ XML_ParserFree(parser->xp);
+ parser->xp = NULL;
+
+ return APR_SUCCESS;
+}
+
+APU_DECLARE(apr_xml_parser *) apr_xml_parser_create(apr_pool_t *pool)
+{
+ apr_xml_parser *parser = apr_pcalloc(pool, sizeof(*parser));
+
+ parser->p = pool;
+ parser->doc = apr_pcalloc(pool, sizeof(*parser->doc));
+
+ parser->doc->namespaces = apr_array_make(pool, 5, sizeof(const char *));
+
+ /* ### is there a way to avoid hard-coding this? */
+ apr_xml_insert_uri(parser->doc->namespaces, APR_KW_DAV);
+
+ parser->xp = XML_ParserCreate(NULL);
+ if (parser->xp == NULL) {
+ (*apr_pool_abort_get(pool))(APR_ENOMEM);
+ return NULL;
+ }
+
+ apr_pool_cleanup_register(pool, parser, cleanup_parser,
+ apr_pool_cleanup_null);
+
+ XML_SetUserData(parser->xp, parser);
+ XML_SetElementHandler(parser->xp, start_handler, end_handler);
+ XML_SetCharacterDataHandler(parser->xp, cdata_handler);
+
+ return parser;
+}
+
+static apr_status_t do_parse(apr_xml_parser *parser,
+ const char *data, apr_size_t len,
+ int is_final)
+{
+ if (parser->xp == NULL) {
+ parser->error = APR_XML_ERROR_PARSE_DONE;
+ }
+ else {
+ int rv = XML_Parse(parser->xp, data, len, is_final);
+
+ if (rv == 0) {
+ parser->error = APR_XML_ERROR_EXPAT;
+ parser->xp_err = XML_GetErrorCode(parser->xp);
+ }
+ }
+
+ /* ### better error code? */
+ return parser->error ? APR_EGENERAL : APR_SUCCESS;
+}
+
+APU_DECLARE(apr_status_t) apr_xml_parser_feed(apr_xml_parser *parser,
+ const char *data,
+ apr_size_t len)
+{
+ return do_parse(parser, data, len, 0 /* is_final */);
+}
+
+APU_DECLARE(apr_status_t) apr_xml_parser_done(apr_xml_parser *parser,
+ apr_xml_doc **pdoc)
+{
+ char end;
+ apr_status_t status = do_parse(parser, &end, 0, 1 /* is_final */);
+
+ /* get rid of the parser */
+ (void) apr_pool_cleanup_run(parser->p, parser, cleanup_parser);
+
+ if (status)
+ return status;
+
+ if (pdoc != NULL)
+ *pdoc = parser->doc;
+ return APR_SUCCESS;
+}
+
+APU_DECLARE(char *) apr_xml_parser_geterror(apr_xml_parser *parser,
+ char *errbuf,
+ apr_size_t errbufsize)
+{
+ int error = parser->error;
+ const char *msg;
+
+ /* clear our record of an error */
+ parser->error = 0;
+
+ switch (error) {
+ case 0:
+ msg = "No error.";
+ break;
+
+ case APR_XML_NS_ERROR_UNKNOWN_PREFIX:
+ msg = "An undefined namespace prefix was used.";
+ break;
+
+ case APR_XML_NS_ERROR_INVALID_DECL:
+ msg = "A namespace prefix was defined with an empty URI.";
+ break;
+
+ case APR_XML_ERROR_EXPAT:
+ (void) apr_snprintf(errbuf, errbufsize,
+ "XML parser error code: %s (%d)",
+ XML_ErrorString(parser->xp_err), parser->xp_err);
+ return errbuf;
+
+ case APR_XML_ERROR_PARSE_DONE:
+ msg = "The parser is not active.";
+ break;
+
+ default:
+ msg = "There was an unknown error within the XML body.";
+ break;
+ }
+
+ (void) apr_cpystrn(errbuf, msg, errbufsize);
+ return errbuf;
+}
+
+APU_DECLARE(apr_status_t) apr_xml_parse_file(apr_pool_t *p,
+ apr_xml_parser **parser,
+ apr_xml_doc **ppdoc,
+ apr_file_t *xmlfd,
+ apr_size_t buffer_length)
+{
+ apr_status_t rv;
+ char *buffer;
+ apr_size_t length;
+
+ *parser = apr_xml_parser_create(p);
+ if (*parser == NULL) {
+ /* FIXME: returning an error code would be nice,
+ * but we dont get one ;( */
+ return APR_EGENERAL;
+ }
+ buffer = apr_palloc(p, buffer_length);
+ length = buffer_length;
+
+ rv = apr_file_read(xmlfd, buffer, &length);
+
+ while (rv == APR_SUCCESS) {
+ rv = apr_xml_parser_feed(*parser, buffer, length);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ length = buffer_length;
+ rv = apr_file_read(xmlfd, buffer, &length);
+ }
+ if (rv != APR_EOF) {
+ return rv;
+ }
+ rv = apr_xml_parser_done(*parser, ppdoc);
+ *parser = NULL;
+ return rv;
+}
+
+APU_DECLARE(void) apr_text_append(apr_pool_t * p, apr_text_header *hdr,
+ const char *text)
+{
+ apr_text *t = apr_palloc(p, sizeof(*t));
+
+ t->text = text;
+ t->next = NULL;
+
+ if (hdr->first == NULL) {
+ /* no text elements yet */
+ hdr->first = hdr->last = t;
+ }
+ else {
+ /* append to the last text element */
+ hdr->last->next = t;
+ hdr->last = t;
+ }
+}
+
+
+/* ---------------------------------------------------------------
+**
+** XML UTILITY FUNCTIONS
+*/
+
+/*
+** apr_xml_quote_string: quote an XML string
+**
+** Replace '<', '>', and '&' with '<', '>', and '&'.
+** If quotes is true, then replace '"' with '"'.
+**
+** quotes is typically set to true for XML strings that will occur within
+** double quotes -- attribute values.
+*/
+APU_DECLARE(const char *) apr_xml_quote_string(apr_pool_t *p, const char *s,
+ int quotes)
+{
+ const char *scan;
+ apr_size_t len = 0;
+ apr_size_t extra = 0;
+ char *qstr;
+ char *qscan;
+ char c;
+
+ for (scan = s; (c = *scan) != '\0'; ++scan, ++len) {
+ if (c == '<' || c == '>')
+ extra += 3; /* < or > */
+ else if (c == '&')
+ extra += 4; /* & */
+ else if (quotes && c == '"')
+ extra += 5; /* " */
+ }
+
+ /* nothing to do? */
+ if (extra == 0)
+ return s;
+
+ qstr = apr_palloc(p, len + extra + 1);
+ for (scan = s, qscan = qstr; (c = *scan) != '\0'; ++scan) {
+ if (c == '<') {
+ *qscan++ = '&';
+ *qscan++ = 'l';
+ *qscan++ = 't';
+ *qscan++ = ';';
+ }
+ else if (c == '>') {
+ *qscan++ = '&';
+ *qscan++ = 'g';
+ *qscan++ = 't';
+ *qscan++ = ';';
+ }
+ else if (c == '&') {
+ *qscan++ = '&';
+ *qscan++ = 'a';
+ *qscan++ = 'm';
+ *qscan++ = 'p';
+ *qscan++ = ';';
+ }
+ else if (quotes && c == '"') {
+ *qscan++ = '&';
+ *qscan++ = 'q';
+ *qscan++ = 'u';
+ *qscan++ = 'o';
+ *qscan++ = 't';
+ *qscan++ = ';';
+ }
+ else {
+ *qscan++ = c;
+ }
+ }
+
+ *qscan = '\0';
+ return qstr;
+}
+
+/* how many characters for the given integer? */
+#define APR_XML_NS_LEN(ns) ((ns) < 10 ? 1 : (ns) < 100 ? 2 : (ns) < 1000 ? 3 : \
+ (ns) < 10000 ? 4 : (ns) < 100000 ? 5 : \
+ (ns) < 1000000 ? 6 : (ns) < 10000000 ? 7 : \
+ (ns) < 100000000 ? 8 : (ns) < 1000000000 ? 9 : 10)
+
+static apr_size_t text_size(const apr_text *t)
+{
+ apr_size_t size = 0;
+
+ for (; t; t = t->next)
+ size += strlen(t->text);
+ return size;
+}
+
+static apr_size_t elem_size(const apr_xml_elem *elem, int style,
+ apr_array_header_t *namespaces, int *ns_map)
+{
+ apr_size_t size;
+
+ if (style == APR_XML_X2T_FULL || style == APR_XML_X2T_FULL_NS_LANG) {
+ const apr_xml_attr *attr;
+
+ size = 0;
+
+ if (style == APR_XML_X2T_FULL_NS_LANG) {
+ int i;
+
+ /*
+ ** The outer element will contain xmlns:ns%d="%s" attributes
+ ** and an xml:lang attribute, if applicable.
+ */
+
+ for (i = namespaces->nelts; i--;) {
+ /* compute size of: ' xmlns:ns%d="%s"' */
+ size += (9 + APR_XML_NS_LEN(i) + 2 +
+ strlen(APR_XML_GET_URI_ITEM(namespaces, i)) + 1);
+ }
+
+ if (elem->lang != NULL) {
+ /* compute size of: ' xml:lang="%s"' */
+ size += 11 + strlen(elem->lang) + 1;
+ }
+ }
+
+ if (elem->ns == APR_XML_NS_NONE) {
+ /* compute size of: <%s> */
+ size += 1 + strlen(elem->name) + 1;
+ }
+ else {
+ int ns = ns_map ? ns_map[elem->ns] : elem->ns;
+
+ /* compute size of: <ns%d:%s> */
+ size += 3 + APR_XML_NS_LEN(ns) + 1 + strlen(elem->name) + 1;
+ }
+
+ if (APR_XML_ELEM_IS_EMPTY(elem)) {
+ /* insert a closing "/" */
+ size += 1;
+ }
+ else {
+ /*
+ * two of above plus "/":
+ * <ns%d:%s> ... </ns%d:%s>
+ * OR <%s> ... </%s>
+ */
+ size = 2 * size + 1;
+ }
+
+ for (attr = elem->attr; attr; attr = attr->next) {
+ if (attr->ns == APR_XML_NS_NONE) {
+ /* compute size of: ' %s="%s"' */
+ size += 1 + strlen(attr->name) + 2 + strlen(attr->value) + 1;
+ }
+ else {
+ /* compute size of: ' ns%d:%s="%s"' */
+ size += 3 + APR_XML_NS_LEN(attr->ns) + 1 + strlen(attr->name) + 2 + strlen(attr->value) + 1;
+ }
+ }
+
+ /*
+ ** If the element has an xml:lang value that is *different* from
+ ** its parent, then add the thing in: ' xml:lang="%s"'.
+ **
+ ** NOTE: we take advantage of the pointer equality established by
+ ** the parsing for "inheriting" the xml:lang values from parents.
+ */
+ if (elem->lang != NULL &&
+ (elem->parent == NULL || elem->lang != elem->parent->lang)) {
+ size += 11 + strlen(elem->lang) + 1;
+ }
+ }
+ else if (style == APR_XML_X2T_LANG_INNER) {
+ /*
+ * This style prepends the xml:lang value plus a null terminator.
+ * If a lang value is not present, then we insert a null term.
+ */
+ size = elem->lang ? strlen(elem->lang) + 1 : 1;
+ }
+ else
+ size = 0;
+
+ size += text_size(elem->first_cdata.first);
+
+ for (elem = elem->first_child; elem; elem = elem->next) {
+ /* the size of the child element plus the CDATA that follows it */
+ size += (elem_size(elem, APR_XML_X2T_FULL, NULL, ns_map) +
+ text_size(elem->following_cdata.first));
+ }
+
+ return size;
+}
+
+static char *write_text(char *s, const apr_text *t)
+{
+ for (; t; t = t->next) {
+ apr_size_t len = strlen(t->text);
+ memcpy(s, t->text, len);
+ s += len;
+ }
+ return s;
+}
+
+static char *write_elem(char *s, const apr_xml_elem *elem, int style,
+ apr_array_header_t *namespaces, int *ns_map)
+{
+ const apr_xml_elem *child;
+ apr_size_t len;
+ int ns;
+
+ if (style == APR_XML_X2T_FULL || style == APR_XML_X2T_FULL_NS_LANG) {
+ int empty = APR_XML_ELEM_IS_EMPTY(elem);
+ const apr_xml_attr *attr;
+
+ if (elem->ns == APR_XML_NS_NONE) {
+ len = sprintf(s, "<%s", elem->name);
+ }
+ else {
+ ns = ns_map ? ns_map[elem->ns] : elem->ns;
+ len = sprintf(s, "<ns%d:%s", ns, elem->name);
+ }
+ s += len;
+
+ for (attr = elem->attr; attr; attr = attr->next) {
+ if (attr->ns == APR_XML_NS_NONE)
+ len = sprintf(s, " %s=\"%s\"", attr->name, attr->value);
+ else
+ len = sprintf(s, " ns%d:%s=\"%s\"", attr->ns, attr->name, attr->value);
+ s += len;
+ }
+
+ /* add the xml:lang value if necessary */
+ if (elem->lang != NULL &&
+ (style == APR_XML_X2T_FULL_NS_LANG ||
+ elem->parent == NULL ||
+ elem->lang != elem->parent->lang)) {
+ len = sprintf(s, " xml:lang=\"%s\"", elem->lang);
+ s += len;
+ }
+
+ /* add namespace definitions, if required */
+ if (style == APR_XML_X2T_FULL_NS_LANG) {
+ int i;
+
+ for (i = namespaces->nelts; i--;) {
+ len = sprintf(s, " xmlns:ns%d=\"%s\"", i,
+ APR_XML_GET_URI_ITEM(namespaces, i));
+ s += len;
+ }
+ }
+
+ /* no more to do. close it up and go. */
+ if (empty) {
+ *s++ = '/';
+ *s++ = '>';
+ return s;
+ }
+
+ /* just close it */
+ *s++ = '>';
+ }
+ else if (style == APR_XML_X2T_LANG_INNER) {
+ /* prepend the xml:lang value */
+ if (elem->lang != NULL) {
+ len = strlen(elem->lang);
+ memcpy(s, elem->lang, len);
+ s += len;
+ }
+ *s++ = '\0';
+ }
+
+ s = write_text(s, elem->first_cdata.first);
+
+ for (child = elem->first_child; child; child = child->next) {
+ s = write_elem(s, child, APR_XML_X2T_FULL, NULL, ns_map);
+ s = write_text(s, child->following_cdata.first);
+ }
+
+ if (style == APR_XML_X2T_FULL || style == APR_XML_X2T_FULL_NS_LANG) {
+ if (elem->ns == APR_XML_NS_NONE) {
+ len = sprintf(s, "</%s>", elem->name);
+ }
+ else {
+ ns = ns_map ? ns_map[elem->ns] : elem->ns;
+ len = sprintf(s, "</ns%d:%s>", ns, elem->name);
+ }
+ s += len;
+ }
+
+ return s;
+}
+
+APU_DECLARE(void) apr_xml_quote_elem(apr_pool_t *p, apr_xml_elem *elem)
+{
+ apr_text *scan_txt;
+ apr_xml_attr *scan_attr;
+ apr_xml_elem *scan_elem;
+
+ /* convert the element's text */
+ for (scan_txt = elem->first_cdata.first;
+ scan_txt != NULL;
+ scan_txt = scan_txt->next) {
+ scan_txt->text = apr_xml_quote_string(p, scan_txt->text, 0);
+ }
+ for (scan_txt = elem->following_cdata.first;
+ scan_txt != NULL;
+ scan_txt = scan_txt->next) {
+ scan_txt->text = apr_xml_quote_string(p, scan_txt->text, 0);
+ }
+
+ /* convert the attribute values */
+ for (scan_attr = elem->attr;
+ scan_attr != NULL;
+ scan_attr = scan_attr->next) {
+ scan_attr->value = apr_xml_quote_string(p, scan_attr->value, 1);
+ }
+
+ /* convert the child elements */
+ for (scan_elem = elem->first_child;
+ scan_elem != NULL;
+ scan_elem = scan_elem->next) {
+ apr_xml_quote_elem(p, scan_elem);
+ }
+}
+
+/* convert an element to a text string */
+APU_DECLARE(void) apr_xml_to_text(apr_pool_t * p, const apr_xml_elem *elem,
+ int style, apr_array_header_t *namespaces,
+ int *ns_map, const char **pbuf,
+ apr_size_t *psize)
+{
+ /* get the exact size, plus a null terminator */
+ apr_size_t size = elem_size(elem, style, namespaces, ns_map) + 1;
+ char *s = apr_palloc(p, size);
+
+ (void) write_elem(s, elem, style, namespaces, ns_map);
+ s[size - 1] = '\0';
+
+ *pbuf = s;
+ if (psize)
+ *psize = size;
+}
+
+APU_DECLARE(const char *) apr_xml_empty_elem(apr_pool_t * p,
+ const apr_xml_elem *elem)
+{
+ if (elem->ns == APR_XML_NS_NONE) {
+ /*
+ * The prefix (xml...) is already within the prop name, or
+ * the element simply has no prefix.
+ */
+ return apr_psprintf(p, "<%s/>" DEBUG_CR, elem->name);
+ }
+
+ return apr_psprintf(p, "<ns%d:%s/>" DEBUG_CR, elem->ns, elem->name);
+}
+
+/* return the URI's (existing) index, or insert it and return a new index */
+APU_DECLARE(int) apr_xml_insert_uri(apr_array_header_t *uri_array,
+ const char *uri)
+{
+ int i;
+ const char **pelt;
+
+ /* never insert an empty URI; this index is always APR_XML_NS_NONE */
+ if (*uri == '\0')
+ return APR_XML_NS_NONE;
+
+ for (i = uri_array->nelts; i--;) {
+ if (strcmp(uri, APR_XML_GET_URI_ITEM(uri_array, i)) == 0)
+ return i;
+ }
+
+ pelt = apr_array_push(uri_array);
+ *pelt = uri; /* assume uri is const or in a pool */
+ return uri_array->nelts - 1;
+}
+
+/* convert the element to EBCDIC */
+#if APR_CHARSET_EBCDIC
+static apr_status_t apr_xml_parser_convert_elem(apr_xml_elem *e,
+ apr_xlate_t *convset)
+{
+ apr_xml_attr *a;
+ apr_xml_elem *ec;
+ apr_text *t;
+ apr_size_t inbytes_left, outbytes_left;
+ apr_status_t status;
+
+ inbytes_left = outbytes_left = strlen(e->name);
+ status = apr_xlate_conv_buffer(convset, e->name, &inbytes_left, (char *) e->name, &outbytes_left);
+ if (status) {
+ return status;
+ }
+
+ for (t = e->first_cdata.first; t != NULL; t = t->next) {
+ inbytes_left = outbytes_left = strlen(t->text);
+ status = apr_xlate_conv_buffer(convset, t->text, &inbytes_left, (char *) t->text, &outbytes_left);
+ if (status) {
+ return status;
+ }
+ }
+
+ for (t = e->following_cdata.first; t != NULL; t = t->next) {
+ inbytes_left = outbytes_left = strlen(t->text);
+ status = apr_xlate_conv_buffer(convset, t->text, &inbytes_left, (char *) t->text, &outbytes_left);
+ if (status) {
+ return status;
+ }
+ }
+
+ for (a = e->attr; a != NULL; a = a->next) {
+ inbytes_left = outbytes_left = strlen(a->name);
+ status = apr_xlate_conv_buffer(convset, a->name, &inbytes_left, (char *) a->name, &outbytes_left);
+ if (status) {
+ return status;
+ }
+ inbytes_left = outbytes_left = strlen(a->value);
+ status = apr_xlate_conv_buffer(convset, a->value, &inbytes_left, (char *) a->value, &outbytes_left);
+ if (status) {
+ return status;
+ }
+ }
+
+ for (ec = e->first_child; ec != NULL; ec = ec->next) {
+ status = apr_xml_parser_convert_elem(ec, convset);
+ if (status) {
+ return status;
+ }
+ }
+ return APR_SUCCESS;
+}
+
+/* convert the whole document to EBCDIC */
+APU_DECLARE(apr_status_t) apr_xml_parser_convert_doc(apr_pool_t *pool,
+ apr_xml_doc *pdoc,
+ apr_xlate_t *convset)
+{
+ apr_status_t status;
+ /* Don't convert the namespaces: they are constant! */
+ if (pdoc->namespaces != NULL) {
+ int i;
+ apr_array_header_t *namespaces;
+ namespaces = apr_array_make(pool, pdoc->namespaces->nelts, sizeof(const char *));
+ if (namespaces == NULL)
+ return APR_ENOMEM;
+ for (i = 0; i < pdoc->namespaces->nelts; i++) {
+ apr_size_t inbytes_left, outbytes_left;
+ char *ptr = (char *) APR_XML_GET_URI_ITEM(pdoc->namespaces, i);
+ ptr = apr_pstrdup(pool, ptr);
+ if ( ptr == NULL)
+ return APR_ENOMEM;
+ inbytes_left = outbytes_left = strlen(ptr);
+ status = apr_xlate_conv_buffer(convset, ptr, &inbytes_left, ptr, &outbytes_left);
+ if (status) {
+ return status;
+ }
+ apr_xml_insert_uri(namespaces, ptr);
+ }
+ pdoc->namespaces = namespaces;
+ }
+ return apr_xml_parser_convert_elem(pdoc->root, convset);
+}
+#endif
--- /dev/null
+Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+ and Clark Cooper
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--- /dev/null
+################################################################
+# Process this file with top-level configure script to produce Makefile
+#
+# Copyright 2000 Clark Cooper
+#
+# This file is part of EXPAT.
+#
+# EXPAT is free software; you can redistribute it and/or modify it
+# under the terms of the License (based on the MIT/X license) contained
+# in the file COPYING that comes with this distribution.
+#
+# EXPAT IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN EXPAT.
+#
+# ---
+# I started using automake, but
+# 1) it seemed like overkill
+# 2) I don't want all the GNU policies
+# 3) I wanted more explicit control over what gets built
+#
+# So I'm doing my Makefile.in files manually. But a fair part is based
+# on what I learned from perusing the Makefile.in's generated by automake,
+# and the automake authors still get my kudos.
+#
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+top_builddir = .
+
+
+AUTOCONF = autoconf
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+host_alias = @host_alias@
+host_triplet = @host@
+
+CC = @CC@
+
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+PACKAGE = @PACKAGE@
+RANLIB = @RANLIB@
+VERSION = @VERSION@
+
+SUBDIRS = lib
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+CONFIG_HEADERS = config.h
+
+DISTDIR = $(PACKAGE)-$(VERSION)
+DISTRIBUTION = $(DISTDIR).tar.gz
+
+all: build-subdirs
+
+.PHONY: all build-subdirs clean distclean extraclean maintainer-clean dist install \
+ uninstall distdir
+
+Makefile: Makefile.in config.status
+ CONFIG_FILES=$@ CONFIG_HEADERS= $(SHELL) config.status
+
+config.status: configure
+ @if test -f $@; then \
+ $(SHELL) config.status --recheck ; \
+ else \
+ $(SHELL) configure ; \
+ fi
+
+configure: configure.in
+ $(AUTOCONF)
+
+config.h: config.h.in config.status
+ CONFIG_FILES= CONFIG_HEADERS=$(CONFIG_HEADERS) \
+ $(SHELL) ./config.status
+
+build-subdirs:
+ @list='$(SUBDIRS)'; \
+ for dir in $$list; do \
+ cd $$dir; $(MAKE); cd ..; \
+ done
+
+clean:
+ @list='$(SUBDIRS)'; for dir in $$list; do \
+ cd $$dir; $(MAKE) clean; cd ..; \
+ done
+ rm -f core *~
+
+distclean:
+ @list='$(SUBDIRS)'; for dir in $$list; do \
+ cd $$dir; $(MAKE) distclean; cd ..; \
+ done
+ rm -f config.h config.status config.log libtool examples/Makefile xmlwf/Makefile Makefile
+
+extraclean: distclean
+ rm -f configure aclocal.m4
+
+maintainer-clean: distclean
+ rm -f $(DISTRIBUTION)
+ rm -rf $(DISTDIR)
+
+distdir: MANIFEST
+ test -d $(DISTDIR) && rm -rf $(DISTDIR); \
+ mkdir $(DISTDIR); \
+ flist=`sed -e "s/[ ]:.*$$//" MANIFEST`; for file in $$flist; do \
+ cp -P $$file $(DISTDIR); \
+ done
+
+$(DISTRIBUTION): distdir
+ tar cfz $(DISTRIBUTION) $(DISTDIR)
+
+dist: $(DISTRIBUTION)
+
+install:
+ @list='$(SUBDIRS)'; for dir in $$list; do \
+ cd $$dir; $(MAKE) install; cd ..; \
+ done
+
+uninstall:
+ @list='$(SUBDIRS)'; for dir in $$list; do \
+ cd $$dir; $(MAKE) uninstall; cd ..; \
+ done
+
+depend:
+ echo SOMEONE SHOULD MAKE THIS DO SOMETHING!!!
--- /dev/null
+
+ Expat, Release 1.95.1
+
+This is expat, the C library for parsing XML, written by James Clark. Expat
+is a stream oriented XML parser. This means that you register handlers with
+the parser prior to starting the parse. These handlers are called when
+the parser discovers the associated structures in the document being parsed.
+A start tag is an example of the kind of structures for which you may
+register handlers.
+
+Expat is free software. You may copy, distribute, and modify it under the
+terms of the License contained in the file, COPYING, distributed with this
+package. This license is the same as the MIT/X Consortium license.
+
+Versions of expat that have an odd minor version (the middle number in the
+release above), are development releases and should be considered as
+beta software. Releases with even minor version numbers are intended to be
+production grade software.
+
+To build expat, you first run the configuration shell script in the top
+level distribution directory:
+
+ ./configure
+
+There are many options which you may provide to configure (which you can
+discover by running configure with the --help option.) But the one of most
+interest is the one that sets the installation directory. By default,
+the configure script will set things up to install libexpat into
+/usr/local/lib and expat.h into /usr/local/include. If, for example, you'd
+prefer to install into /home/me/mystuff/lib and /home/me/mystuff/include,
+you can tell configure about that with:
+
+ ./configure --prefix=/home/me/mystuff
+
+After running the configure script, the "make" command will build things and
+"make install" will install things into their proper location. Note that
+you need to have write permission into the directories into which things
+will be installed.
+
+Note for Solaris users: The "ar" command is usually located in
+"/usr/ccs/bin", which is not in the default PATH. You will need to
+add this to your path for the "make" command. If you're using ksh or
+bash, use this command to build:
+
+ PATH=/usr/ccs/bin:$PATH make
+
+Alternatively, on Win32 systems with Microsoft's Developer's Studio installed,
+you can simply double-click on lib/expat.dsp from Windows Explorer and build
+and install in the usual way from with DevStudio.
+
+As a third alternative you may choose to download expat_win32bin which has
+a pre-compiled dll in it.
+
+A reference manual is available in the doc/reference.html in this
+distribution.
+
+The homepage for this project is http://expat.sourceforge.net. There are
+links there to connect you to the bug reports page. If you need to report
+a bug when you don't have access to a browser, you may also send a bug
+report by email to expat-bugs@lists.sourceforge.net.
+
+Discussion related to the direction of future expat development takes place
+on expat-discuss@lists.sourceforge.net. Archives of this list may be found
+at http://www.geocrawler.com/redir-sf.php3?list=expat-discuss.
--- /dev/null
+/* This file is used by autoheader to add items to expat_config.h.in */
+
+#ifdef WORDS_BIGENDIAN
+#define XML_BYTE_ORDER 21
+#else
+#define XML_BYTE_ORDER 12
+#endif
+
+@BOTTOM@
+
+#define XML_NS
+#define XML_DTD
+
+#define XML_CONTEXT_BYTES 1024
+
+#ifndef HAVE_MEMMOVE
+#ifdef HAVE_BCOPY
+#define memmove(d,s,l) bcopy((s),(d),(l))
+#else
+#define memmove(d,s,l) ;punting on memmove;
+#endif
+
+#endif
--- /dev/null
+#! /bin/sh
+
+#
+# Find libtoolize
+#
+libtoolize=`conftools/PrintPath glibtoolize libtoolize libtoolize15 libtoolize14`
+if [ "x$libtoolize" = "x" ]; then
+ echo "libtoolize not found in path"
+ exit 1
+fi
+
+#
+# Create the libtool helper files
+#
+# Note: we copy (rather than link) the files.
+#
+# Note: This bundled version of expat will not always replace the
+# files since we have a special config.guess/config.sub that we
+# want to ensure is used.
+echo "Copying libtool helper files ..."
+
+# Remove any libtool files so one can switch between libtool 1.3
+# and libtool 1.4 by simply rerunning the buildconf script.
+(cd conftools ; rm -f ltconfig ltmain.sh)
+rm -f aclocal.m4 libtool.m4 ltsugar.m4
+
+$libtoolize --copy --automake
+
+#
+# Build aclocal.m4 from libtool's libtool.m4
+#
+if [ -f libtool.m4 ]; then
+ ltfile=libtool.m4
+else
+ ltpath=`dirname $libtoolize`
+ ltfile=${LIBTOOL_M4-`cd $ltpath/../share/aclocal ; pwd`/libtool.m4}
+fi
+echo "Incorporating $ltfile into aclocal.m4 ..."
+echo "dnl THIS FILE IS AUTOMATICALLY GENERATED BY buildconf.sh" > aclocal.m4
+echo "dnl edits here will be lost" >> aclocal.m4
+cat $ltfile >> aclocal.m4
+
+if [ -f ltsugar.m4 ]; then
+ echo "Incorporating ltsugar.m4 into aclocal.m4 ..."
+ cat ltsugar.m4 >> aclocal.m4
+fi
+
+# Clean up again
+rm -f libtool.m4 ltsugar.m4
+
+cross_compile_warning="warning: AC_TRY_RUN called without default to allow cross compiling"
+
+#
+# Generate the autoconf header template (config.h.in) and ./configure
+#
+echo "Creating config.h.in ..."
+${AUTOHEADER:-autoheader} 2>&1 | grep -v "$cross_compile_warning"
+
+echo "Creating configure ..."
+### do some work to toss config.cache?
+${AUTOCONF:-autoconf} 2>&1 | grep -v "$cross_compile_warning"
+
+# Remove autoconf caches
+rm -rf autom4te*.cache
+
+exit 0
--- /dev/null
+dnl configuration script for expat
+dnl Process this file with autoconf to produce a configure script.
+dnl
+dnl Copyright 2000 Clark Cooper
+dnl
+dnl This file is part of EXPAT.
+dnl
+dnl EXPAT is free software; you can redistribute it and/or modify it
+dnl under the terms of the License (based on the MIT/X license) contained
+dnl in the file COPYING that comes with this distribution.
+dnl
+
+AC_INIT(Makefile.in)
+AC_CONFIG_AUX_DIR(conftools)
+
+dnl
+dnl Follow the GNU/Linux convention of odd number minor version for
+dnl beta/development releases and even number minor version for stable
+dnl releases. Edit is bumped with each release and set to 0 with
+dnl change to major or minor version.
+dnl
+
+EXPAT_MAJOR_VERSION=1
+EXPAT_MINOR_VERSION=95
+EXPAT_EDIT=2
+
+EXPAT_VERSION=$EXPAT_MAJOR_VERSION.$EXPAT_MINOR_VERSION.$EXPAT_EDIT
+VERSION=$EXPAT_VERSION
+PACKAGE=expat
+
+dnl
+dnl Increment LIBREVISION if source code has changed at all
+dnl
+dnl If the API has changed, increment LIBCURRENT and set LIBREVISION to 0
+dnl
+dnl If the API changes compatibly (i.e. simply adding a new function
+dnl without changing or removing earlier interfaces), then increment LIBAGE.
+dnl
+dnl If the API changes incompatibly set LIBAGE back to 0
+dnl
+
+LIBCURRENT=1
+LIBREVISION=0
+LIBAGE=1
+
+AC_CONFIG_HEADER(config.h)
+
+AC_CANONICAL_SYSTEM
+case "$host_os" in
+*os2*)
+ # Use a custom made libtool replacement
+ echo Using aplibtool
+ LIBTOOL="$srcdir/../../../apr/build/aplibtool"
+ ;;
+*)
+ AC_LIBTOOL_WIN32_DLL
+AC_PROG_LIBTOOL
+ ;;
+esac
+
+blddir=`pwd`
+AC_SUBST(blddir)
+
+AC_SUBST(PACKAGE)
+AC_SUBST(VERSION)
+AC_SUBST(EXPAT_MAJOR_VERSION)
+AC_SUBST(EXPAT_MINOR_VERSION)
+AC_SUBST(EXPAT_EDIT)
+
+AC_SUBST(LIBCURRENT)
+AC_SUBST(LIBREVISION)
+AC_SUBST(LIBAGE)
+
+dnl Checks for programs.
+AC_PROG_CC
+AC_PROG_INSTALL
+
+dnl Checks for libraries.
+
+dnl Checks for header files.
+AC_HEADER_STDC
+AC_CHECK_HEADERS(fcntl.h unistd.h string.h)
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+dnl check for endianness
+if test "$cross_compiling" = "no"; then
+ AC_C_BIGENDIAN
+else
+ AC_DEFINE(AP_UNKNOWN_BYTE_ORDER,1,
+ [byte order is unknown due to cross-compilation])
+fi
+AC_C_CONST
+AC_TYPE_OFF_T
+AC_TYPE_SIZE_T
+
+dnl Checks for library functions.
+
+AC_FUNC_MEMCMP
+AC_FUNC_MMAP
+AC_SUBST(FILEMAP_OBJ)
+if test -z "$HAVE_MMAP"; then
+FILEMAP_OBJ=unixfilemap.o
+else
+FILEMAP_OBJ=readfilemap.o
+fi
+
+AC_CHECK_FUNCS(memmove bcopy)
+
+AC_OUTPUT(Makefile lib/Makefile lib/expat.h)
--- /dev/null
+#!/bin/sh
+# Look for program[s] somewhere in $PATH.
+#
+# Options:
+# -s
+# Do not print out full pathname. (silent)
+# -pPATHNAME
+# Look in PATHNAME instead of $PATH
+#
+# Usage:
+# PrintPath [-s] [-pPATHNAME] program [program ...]
+#
+# Initially written by Jim Jagielski for the Apache configuration mechanism
+# (with kudos to Kernighan/Pike)
+#
+# This script falls under the Apache License.
+# See http://www.apache.org/docs/LICENSE
+
+##
+# Some "constants"
+##
+pathname=$PATH
+echo="yes"
+
+##
+# Find out what OS we are running for later on
+##
+os=`(uname) 2>/dev/null`
+
+##
+# Parse command line
+##
+for args in $*
+do
+ case $args in
+ -s ) echo="no" ;;
+ -p* ) pathname="`echo $args | sed 's/^..//'`" ;;
+ * ) programs="$programs $args" ;;
+ esac
+done
+
+##
+# Now we make the adjustments required for OS/2 and everyone
+# else :)
+#
+# First of all, all OS/2 programs have the '.exe' extension.
+# Next, we adjust PATH (or what was given to us as PATH) to
+# be whitespace seperated directories.
+# Finally, we try to determine the best flag to use for
+# test/[] to look for an executable file. OS/2 just has '-r'
+# but with other OSs, we do some funny stuff to check to see
+# if test/[] knows about -x, which is the prefered flag.
+##
+
+if [ "x$os" = "xOS/2" ]
+then
+ ext=".exe"
+ pathname=`echo -E $pathname |
+ sed 's/^;/.;/
+ s/;;/;.;/g
+ s/;$/;./
+ s/;/ /g
+ s/\\\\/\\//g' `
+ test_exec_flag="-r"
+else
+ ext="" # No default extensions
+ pathname=`echo $pathname |
+ sed 's/^:/.:/
+ s/::/:.:/g
+ s/:$/:./
+ s/:/ /g' `
+ # Here is how we test to see if test/[] can handle -x
+ testfile="pp.t.$$"
+
+ cat > $testfile <<ENDTEST
+#!/bin/sh
+if [ -x / ] || [ -x /bin ] || [ -x /bin/ls ]; then
+ exit 0
+fi
+exit 1
+ENDTEST
+
+ if `/bin/sh $testfile 2>/dev/null`; then
+ test_exec_flag="-x"
+ else
+ test_exec_flag="-r"
+ fi
+ rm -f $testfile
+fi
+
+for program in $programs
+do
+ for path in $pathname
+ do
+ if [ $test_exec_flag $path/${program}${ext} ] && \
+ [ ! -d $path/${program}${ext} ]; then
+ if [ "x$echo" = "xyes" ]; then
+ echo $path/${program}${ext}
+ fi
+ exit 0
+ fi
+
+# Next try without extension (if one was used above)
+ if [ "x$ext" != "x" ]; then
+ if [ $test_exec_flag $path/${program} ] && \
+ [ ! -d $path/${program} ]; then
+ if [ "x$echo" = "xyes" ]; then
+ echo $path/${program}
+ fi
+ exit 0
+ fi
+ fi
+ done
+done
+exit 1
+
--- /dev/null
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002 Free Software Foundation, Inc.
+
+timestamp='2002-03-20'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+#####################################################################
+# This file contains changes for Apache, clearly marked below.
+# These changes are hereby donated to the public domain.
+#####################################################################
+
+# Originally written by Per Bothner <per@bothner.com>.
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# This script attempts to guess a canonical system name similar to
+# config.sub. If it succeeds, it prints the system name on stdout, and
+# exits with 0. Otherwise, it exits with 1.
+#
+# The plan is that this can be called by configure scripts if you
+# don't specify an explicit build system type.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit 0 ;;
+ --version | -v )
+ echo "$version" ; exit 0 ;;
+ --help | --h* | -h )
+ echo "$usage"; exit 0 ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+
+dummy=dummy-$$
+trap 'rm -f $dummy.c $dummy.o $dummy.rel $dummy; exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script.
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+set_cc_for_build='case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,) echo "int dummy(){}" > $dummy.c ;
+ for c in cc gcc c89 c99 ; do
+ ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ;
+ if test $? = 0 ; then
+ CC_FOR_BUILD="$c"; break ;
+ fi ;
+ done ;
+ rm -f $dummy.c $dummy.o $dummy.rel ;
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found ;
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+esac'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ sysctl="sysctl -n hw.machine_arch"
+ UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
+ /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+ case "${UNAME_MACHINE_ARCH}" in
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently, or will in the future.
+ case "${UNAME_MACHINE_ARCH}" in
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval $set_cc_for_build
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep __ELF__ >/dev/null
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # The OS release
+ release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "${machine}-${os}${release}"
+ exit 0 ;;
+ amiga:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ arc:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ hp300:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mac68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ macppc:OpenBSD:*:*)
+ echo powerpc-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme68k:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvme88k:OpenBSD:*:*)
+ echo m88k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ mvmeppc:OpenBSD:*:*)
+ echo powerpc-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ pmax:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sgi:OpenBSD:*:*)
+ echo mipseb-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ sun3:OpenBSD:*:*)
+ echo m68k-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ wgrisc:OpenBSD:*:*)
+ echo mipsel-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ *:OpenBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE}
+ exit 0 ;;
+ alpha:OSF1:*:*)
+ if test $UNAME_RELEASE = "V4.0"; then
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ fi
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ cat <<EOF >$dummy.s
+ .data
+\$Lformat:
+ .byte 37,100,45,37,120,10,0 # "%d-%x\n"
+
+ .text
+ .globl main
+ .align 4
+ .ent main
+main:
+ .frame \$30,16,\$26,0
+ ldgp \$29,0(\$27)
+ .prologue 1
+ .long 0x47e03d80 # implver \$0
+ lda \$2,-1
+ .long 0x47e20c21 # amask \$2,\$1
+ lda \$16,\$Lformat
+ mov \$0,\$17
+ not \$1,\$18
+ jsr \$26,printf
+ ldgp \$29,0(\$26)
+ mov 0,\$16
+ jsr \$26,exit
+ .end main
+EOF
+ eval $set_cc_for_build
+ $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null
+ if test "$?" = 0 ; then
+ case `./$dummy` in
+ 0-0)
+ UNAME_MACHINE="alpha"
+ ;;
+ 1-0)
+ UNAME_MACHINE="alphaev5"
+ ;;
+ 1-1)
+ UNAME_MACHINE="alphaev56"
+ ;;
+ 1-101)
+ UNAME_MACHINE="alphapca56"
+ ;;
+ 2-303)
+ UNAME_MACHINE="alphaev6"
+ ;;
+ 2-307)
+ UNAME_MACHINE="alphaev67"
+ ;;
+ 2-1307)
+ UNAME_MACHINE="alphaev68"
+ ;;
+ esac
+ fi
+ rm -f $dummy.s $dummy
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ exit 0 ;;
+ Alpha\ *:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # Should we change UNAME_MACHINE based on the output of uname instead
+ # of the specific Alpha model?
+ echo alpha-pc-interix
+ exit 0 ;;
+ 21064:Windows_NT:50:3)
+ echo alpha-dec-winnt3.5
+ exit 0 ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit 0;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-amigaos
+ exit 0 ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo ${UNAME_MACHINE}-unknown-morphos
+ exit 0 ;;
+#########################
+# Apache changes
+#
+# *:OS/390:*:*)
+# echo i370-ibm-openedition
+# exit 0 ;;
+ *:OS390:*:* | *:OS/390:*:*)
+ echo s390-ibm-os390
+ exit 0 ;;
+ *:OS400:*:* | *:OS/400:*:*)
+ echo as400-ibm-os400
+ exit 0 ;;
+ *:OS/2:*:*)
+ echo "i386-pc-os2_emx"
+ exit 0;;
+#
+# end Apache changes
+#########################
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit 0 ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix${UNAME_RELEASE}
+ exit 0;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit 0;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit 0 ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit 0 ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ i86pc:SunOS:5.*:*)
+ echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+ exit 0 ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos${UNAME_RELEASE}
+ ;;
+ sun4)
+ echo sparc-sun-sunos${UNAME_RELEASE}
+ ;;
+ esac
+ exit 0 ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos${UNAME_RELEASE}
+ exit 0 ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint${UNAME_RELEASE}
+ exit 0 ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint${UNAME_RELEASE}
+ exit 0 ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint${UNAME_RELEASE}
+ exit 0 ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint${UNAME_RELEASE}
+ exit 0 ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten${UNAME_RELEASE}
+ exit 0 ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit 0 ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix${UNAME_RELEASE}
+ exit 0 ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix${UNAME_RELEASE}
+ exit 0 ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD $dummy.c -o $dummy \
+ && ./$dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \
+ && rm -f $dummy.c $dummy && exit 0
+ rm -f $dummy.c $dummy
+ echo mips-mips-riscos${UNAME_RELEASE}
+ exit 0 ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit 0 ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit 0 ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit 0 ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit 0 ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+ then
+ if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+ [ ${TARGET_BINARY_INTERFACE}x = x ]
+ then
+ echo m88k-dg-dgux${UNAME_RELEASE}
+ else
+ echo m88k-dg-dguxbcs${UNAME_RELEASE}
+ fi
+ else
+ echo i586-dg-dgux${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit 0 ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit 0 ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit 0 ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit 0 ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+ exit 0 ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit 0 ;;
+ ia64:AIX:*:*)
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+ exit 0 ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0
+ rm -f $dummy.c $dummy
+ echo rs6000-ibm-aix3.2.5
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit 0 ;;
+ *:AIX:*:[45])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+ fi
+ echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+ exit 0 ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit 0 ;;
+ ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+ echo romp-ibm-bsd4.4
+ exit 0 ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to
+ exit 0 ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit 0 ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit 0 ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit 0 ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit 0 ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ case "${UNAME_MACHINE}" in
+ 9000/31? ) HP_ARCH=m68000 ;;
+ 9000/[34]?? ) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "${sc_cpu_version}" in
+ 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "${sc_kernel_bits}" in
+ 32) HP_ARCH="hppa2.0n" ;;
+ 64) HP_ARCH="hppa2.0w" ;;
+ '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if [ "${HP_ARCH}" = "" ]; then
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null) && HP_ARCH=`./$dummy`
+ if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi
+ rm -f $dummy.c $dummy
+ fi ;;
+ esac
+ echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux${HPUX_REV}
+ exit 0 ;;
+ 3050*:HI-UX:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD $dummy.c -o $dummy && ./$dummy && rm -f $dummy.c $dummy && exit 0
+ rm -f $dummy.c $dummy
+ echo unknown-hitachi-hiuxwe2
+ exit 0 ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+ echo hppa1.1-hp-bsd
+ exit 0 ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit 0 ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit 0 ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+ echo hppa1.1-hp-osf
+ exit 0 ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit 0 ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo ${UNAME_MACHINE}-unknown-osf1mk
+ else
+ echo ${UNAME_MACHINE}-unknown-osf1
+ fi
+ exit 0 ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit 0 ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*T3D:*:*:*)
+ echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+ exit 0 ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit 0 ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:BSD/OS:*:*)
+ echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+ exit 0 ;;
+ *:FreeBSD:*:*)
+ echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+ exit 0 ;;
+ i*:CYGWIN*:*)
+ echo ${UNAME_MACHINE}-pc-cygwin
+ exit 0 ;;
+ i*:MINGW*:*)
+ echo ${UNAME_MACHINE}-pc-mingw32
+ exit 0 ;;
+ i*:PW*:*)
+ echo ${UNAME_MACHINE}-pc-pw32
+ exit 0 ;;
+ x86:Interix*:3*)
+ echo i386-pc-interix3
+ exit 0 ;;
+ i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+ # How do we know it's Interix rather than the generic POSIX subsystem?
+ # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+ # UNAME_MACHINE based on the output of uname instead of i386?
+ echo i386-pc-interix
+ exit 0 ;;
+ i*:UWIN*:*)
+ echo ${UNAME_MACHINE}-pc-uwin
+ exit 0 ;;
+ p*:CYGWIN*:*)
+ echo powerpcle-unknown-cygwin
+ exit 0 ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+ exit 0 ;;
+ *:GNU:*:*)
+ echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+ exit 0 ;;
+ i*86:Minix:*:*)
+ echo ${UNAME_MACHINE}-pc-minix
+ exit 0 ;;
+ arm*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ ia64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ m68*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ mips:Linux:*:*)
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #undef CPU
+ #undef mips
+ #undef mipsel
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=mipsel
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=mips
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=`
+ rm -f $dummy.c
+ test x"${CPU}" != x && echo "${CPU}-pc-linux-gnu" && exit 0
+ ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-gnu
+ exit 0 ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-gnu
+ exit 0 ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
+ if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
+ echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
+ exit 0 ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) echo hppa1.1-unknown-linux-gnu ;;
+ PA8*) echo hppa2.0-unknown-linux-gnu ;;
+ *) echo hppa-unknown-linux-gnu ;;
+ esac
+ exit 0 ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-gnu
+ exit 0 ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo ${UNAME_MACHINE}-ibm-linux
+ exit 0 ;;
+ sh*:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
+ exit 0 ;;
+ x86_64:Linux:*:*)
+ echo x86_64-unknown-linux-gnu
+ exit 0 ;;
+ i*86:Linux:*:*)
+ # The BFD linker knows what the default object file format is, so
+ # first see if it will tell us. cd to the root directory to prevent
+ # problems with other programs or directories called `ld' in the path.
+ # Set LC_ALL=C to ensure ld outputs messages in English.
+ ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
+ | sed -ne '/supported targets:/!d
+ s/[ ][ ]*/ /g
+ s/.*supported targets: *//
+ s/ .*//
+ p'`
+ case "$ld_supported_targets" in
+ elf32-i386)
+ TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
+ ;;
+ a.out-i386-linux)
+ echo "${UNAME_MACHINE}-pc-linux-gnuaout"
+ exit 0 ;;
+ coff-i386)
+ echo "${UNAME_MACHINE}-pc-linux-gnucoff"
+ exit 0 ;;
+ "")
+ # Either a pre-BFD a.out linker (linux-gnuoldld) or
+ # one that does not give us useful --help.
+ echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
+ exit 0 ;;
+ esac
+ # Determine whether the default compiler is a.out or elf
+ eval $set_cc_for_build
+ sed 's/^ //' << EOF >$dummy.c
+ #include <features.h>
+ #ifdef __ELF__
+ # ifdef __GLIBC__
+ # if __GLIBC__ >= 2
+ LIBC=gnu
+ # else
+ LIBC=gnulibc1
+ # endif
+ # else
+ LIBC=gnulibc1
+ # endif
+ #else
+ #ifdef __INTEL_COMPILER
+ LIBC=gnu
+ #else
+ LIBC=gnuaout
+ #endif
+ #endif
+EOF
+ eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=`
+ rm -f $dummy.c
+ test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0
+ test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0
+ ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ echo i386-sequent-sysv4
+ exit 0 ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+ exit 0 ;;
+ i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+ UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+ else
+ echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+ fi
+ exit 0 ;;
+ i*86:*:5:[78]*)
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+ exit 0 ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|egrep '^Machine.*Pent ?II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|egrep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+ else
+ echo ${UNAME_MACHINE}-pc-sysv32
+ fi
+ exit 0 ;;
+ i*86:*DOS:*:*)
+ echo ${UNAME_MACHINE}-pc-msdosdjgpp
+ exit 0 ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i386.
+ echo i386-pc-msdosdjgpp
+ exit 0 ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit 0 ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit 0 ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4
+ fi
+ exit 0 ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit 0 ;;
+ M68*:*:R3V[567]*:*)
+ test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;;
+ 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4.3${OS_REL} && exit 0
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && echo i486-ncr-sysv4 && exit 0 ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit 0 ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
+ echo i386-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
+ echo powerpc-unknown-lynxos${UNAME_RELEASE}
+ exit 0 ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv${UNAME_RELEASE}
+ exit 0 ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit 0 ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo ${UNAME_MACHINE}-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit 0 ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit 0 ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit 0 ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit 0 ;;
+ *:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo hppa1.1-stratus-vos
+ exit 0 ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux${UNAME_RELEASE}
+ exit 0 ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit 0 ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv${UNAME_RELEASE}
+ else
+ echo mips-unknown-sysv${UNAME_RELEASE}
+ fi
+ exit 0 ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit 0 ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit 0 ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit 0 ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux${UNAME_RELEASE}
+ exit 0 ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody${UNAME_RELEASE}
+ exit 0 ;;
+ *:Rhapsody:*:*)
+ echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+ exit 0 ;;
+ *:Darwin:*:*)
+ echo `uname -p`-apple-darwin${UNAME_RELEASE}
+ exit 0 ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = "x86"; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+ exit 0 ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit 0 ;;
+ NSR-[GKLNPTVW]:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk${UNAME_RELEASE}
+ exit 0 ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit 0 ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit 0 ;;
+ DS/*:UNIX_System_V:*:*)
+ echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+ exit 0 ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "$cputype" = "386"; then
+ UNAME_MACHINE=i386
+ else
+ UNAME_MACHINE="$cputype"
+ fi
+ echo ${UNAME_MACHINE}-unknown-plan9
+ exit 0 ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ echo ${UNAME_MACHINE}-pc-os2-emx
+ exit 0 ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit 0 ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit 0 ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit 0 ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit 0 ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit 0 ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit 0 ;;
+ i*86:XTS-300:*:STOP)
+ echo ${UNAME_MACHINE}-unknown-stop
+ exit 0 ;;
+ i*86:atheos:*:*)
+ echo ${UNAME_MACHINE}-unknown-atheos
+ exit 0 ;;
+esac
+
+#echo '(No uname command or uname output not recognized.)' 1>&2
+#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2
+
+eval $set_cc_for_build
+cat >$dummy.c <<EOF
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/utsname.h>
+#endif
+main ()
+{
+#if defined (sony)
+#if defined (MIPSEB)
+ /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed,
+ I don't know.... */
+ printf ("mips-sony-bsd\n"); exit (0);
+#else
+#include <sys/param.h>
+ printf ("m68k-sony-newsos%s\n",
+#ifdef NEWSOS4
+ "4"
+#else
+ ""
+#endif
+ ); exit (0);
+#endif
+#endif
+
+#if defined (__arm) && defined (__acorn) && defined (__unix)
+ printf ("arm-acorn-riscix"); exit (0);
+#endif
+
+#if defined (hp300) && !defined (hpux)
+ printf ("m68k-hp-bsd\n"); exit (0);
+#endif
+
+#if defined (NeXT)
+#if !defined (__ARCHITECTURE__)
+#define __ARCHITECTURE__ "m68k"
+#endif
+ int version;
+ version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
+ if (version < 4)
+ printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
+ else
+ printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
+ exit (0);
+#endif
+
+#if defined (MULTIMAX) || defined (n16)
+#if defined (UMAXV)
+ printf ("ns32k-encore-sysv\n"); exit (0);
+#else
+#if defined (CMU)
+ printf ("ns32k-encore-mach\n"); exit (0);
+#else
+ printf ("ns32k-encore-bsd\n"); exit (0);
+#endif
+#endif
+#endif
+
+#if defined (__386BSD__)
+ printf ("i386-pc-bsd\n"); exit (0);
+#endif
+
+#if defined (sequent)
+#if defined (i386)
+ printf ("i386-sequent-dynix\n"); exit (0);
+#endif
+#if defined (ns32000)
+ printf ("ns32k-sequent-dynix\n"); exit (0);
+#endif
+#endif
+
+#if defined (_SEQUENT_)
+ struct utsname un;
+
+ uname(&un);
+
+ if (strncmp(un.version, "V2", 2) == 0) {
+ printf ("i386-sequent-ptx2\n"); exit (0);
+ }
+ if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
+ printf ("i386-sequent-ptx1\n"); exit (0);
+ }
+ printf ("i386-sequent-ptx\n"); exit (0);
+
+#endif
+
+#if defined (vax)
+# if !defined (ultrix)
+# include <sys/param.h>
+# if defined (BSD)
+# if BSD == 43
+ printf ("vax-dec-bsd4.3\n"); exit (0);
+# else
+# if BSD == 199006
+ printf ("vax-dec-bsd4.3reno\n"); exit (0);
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# endif
+# else
+ printf ("vax-dec-bsd\n"); exit (0);
+# endif
+# else
+ printf ("vax-dec-ultrix\n"); exit (0);
+# endif
+#endif
+
+#if defined (alliant) && defined (i860)
+ printf ("i860-alliant-bsd\n"); exit (0);
+#endif
+
+ exit (1);
+}
+EOF
+
+$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && ./$dummy && rm -f $dummy.c $dummy && exit 0
+rm -f $dummy.c $dummy
+
+# Apollos put the system type in the environment.
+
+test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; }
+
+# Convex versions that predate uname can use getsysinfo(1)
+
+if [ -x /usr/convex/getsysinfo ]
+then
+ case `getsysinfo -f cpu_type` in
+ c1*)
+ echo c1-convex-bsd
+ exit 0 ;;
+ c2*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit 0 ;;
+ c34*)
+ echo c34-convex-bsd
+ exit 0 ;;
+ c38*)
+ echo c38-convex-bsd
+ exit 0 ;;
+ c4*)
+ echo c4-convex-bsd
+ exit 0 ;;
+ esac
+fi
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script, last modified $timestamp, has failed to recognize
+the operating system you are using. It is advised that you
+download the most up to date version of the config scripts from
+
+ ftp://ftp.gnu.org/pub/gnu/config/
+
+If the version you run ($0) is already up to date, please
+send the following data and any information you think might be
+pertinent to <config-patches@gnu.org> in order to provide the needed
+information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
--- /dev/null
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+# 2000, 2001, 2002 Free Software Foundation, Inc.
+
+timestamp='2002-03-07'
+
+# This file is (in principle) common to ALL GNU software.
+# The presence of a machine in this file suggests that SOME GNU software
+# can handle that machine. It does not imply ALL GNU software can.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+#####################################################################
+# This file contains changes for Apache, clearly marked below.
+# These changes are hereby donated to the public domain.
+#####################################################################
+
+# Please send patches to <config-patches@gnu.org>. Submit a context
+# diff and a properly formatted ChangeLog entry.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS
+ $0 [OPTION] ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
+Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit 0 ;;
+ --version | -v )
+ echo "$version" ; exit 0 ;;
+ --help | --h* | -h )
+ echo "$usage"; exit 0 ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help"
+ exit 1 ;;
+
+ *local*)
+ # First pass through any local machine types.
+ echo $1
+ exit 0;;
+
+ * )
+ break ;;
+ esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+ exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+ exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+ nto-qnx* | linux-gnu* | storm-chaos* | os2-emx* | windows32-* | rtmk-nova*)
+ os=-$maybe_os
+ basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+ ;;
+########################
+# changes for Apache
+#
+ tpf | os390 | vmcms)
+ os=-$maybe_os
+ basic_machine=s390;
+ ;;
+ os400)
+ os=-$maybe_os
+ basic_machine=as400;
+ ;;
+ mvs)
+ os=-mvs
+ basic_machine=i370;
+ ;;
+#
+# end Apache changes
+########################
+ *)
+ basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+ if [ $basic_machine != $1 ]
+ then os=`echo $1 | sed 's/.*-/-/'`
+ else os=; fi
+ ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work. We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+ -sun*os*)
+ # Prevent following clause from handling this invalid input.
+ ;;
+ -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+ -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+ -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+ -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+ -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+ -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+ -apple | -axis)
+ os=
+ basic_machine=$1
+ ;;
+ -sim | -cisco | -oki | -wec | -winbond)
+ os=
+ basic_machine=$1
+ ;;
+ -scout)
+ ;;
+ -wrs)
+ os=-vxworks
+ basic_machine=$1
+ ;;
+ -chorusos*)
+ os=-chorusos
+ basic_machine=$1
+ ;;
+ -chorusrdb)
+ os=-chorusrdb
+ basic_machine=$1
+ ;;
+ -hiux*)
+ os=-hiuxwe2
+ ;;
+ -sco5)
+ os=-sco3.2v5
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco4)
+ os=-sco3.2v4
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco3.2v[4-9]*)
+ # Don't forget version if it is 3.2v4 or newer.
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -sco*)
+ os=-sco3.2v2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -udk*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -isc)
+ os=-isc2.2
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -clix*)
+ basic_machine=clipper-intergraph
+ ;;
+ -isc*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+ ;;
+ -lynx*)
+ os=-lynxos
+ ;;
+ -ptx*)
+ basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+ ;;
+ -windowsnt*)
+ os=`echo $os | sed -e 's/windowsnt/winnt/'`
+ ;;
+ -psos*)
+ os=-psos
+ ;;
+ -mint | -mint[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ 1750a | 580 \
+ | a29k \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
+ | c4x | clipper \
+ | d10v | d30v | dsp16xx \
+ | fr30 \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | i370 | i860 | i960 | ia64 \
+ | m32r | m68000 | m68k | m88k | mcore \
+ | mips | mips16 | mips64 | mips64el | mips64orion | mips64orionel \
+ | mips64vr4100 | mips64vr4100el | mips64vr4300 \
+ | mips64vr4300el | mips64vr5000 | mips64vr5000el \
+ | mipsbe | mipseb | mipsel | mipsle | mipstx39 | mipstx39el \
+ | mipsisa32 | mipsisa64 \
+ | mn10200 | mn10300 \
+ | ns16k | ns32k \
+ | openrisc | or32 \
+ | pdp10 | pdp11 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
+ | pyramid \
+ | sh | sh[34] | sh[34]eb | shbe | shle | sh64 \
+ | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \
+ | strongarm \
+ | tahoe | thumb | tic80 | tron \
+ | v850 | v850e \
+ | we32k \
+ | x86 | xscale | xstormy16 | xtensa \
+ | z8k)
+ basic_machine=$basic_machine-unknown
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12)
+ # Motorola 68HC11/12.
+ basic_machine=$basic_machine-unknown
+ os=-none
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+ ;;
+
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Object if more than one company name word.
+ *-*-*)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+ # Recognize the basic CPU types with company name.
+ 580-* \
+ | a29k-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
+ | arm-* | armbe-* | armle-* | armv*-* \
+ | avr-* \
+ | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c54x-* \
+ | clipper-* | cydra-* \
+ | d10v-* | d30v-* \
+ | elxsi-* \
+ | f30[01]-* | f700-* | fr30-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | i*86-* | i860-* | i960-* | ia64-* \
+ | m32r-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | mcore-* \
+ | mips-* | mips16-* | mips64-* | mips64el-* | mips64orion-* \
+ | mips64orionel-* | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* | mipsbe-* | mipseb-* \
+ | mipsle-* | mipsel-* | mipstx39-* | mipstx39el-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
+ | pyramid-* \
+ | romp-* | rs6000-* \
+ | sh-* | sh[34]-* | sh[34]eb-* | shbe-* | shle-* | sh64-* \
+ | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \
+ | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
+ | tahoe-* | thumb-* | tic30-* | tic54x-* | tic80-* | tron-* \
+ | v850-* | v850e-* | vax-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \
+ | xtensa-* \
+ | ymp-* \
+ | z8k-*)
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 386bsd)
+ basic_machine=i386-unknown
+ os=-bsd
+ ;;
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ os=-scout
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=-bsd
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=-sysv
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-unknown
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ os=-amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ os=-sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=-sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ os=-bsd
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=-aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=-dynix
+ ;;
+ c90)
+ basic_machine=c90-cray
+ os=-unicos
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=-bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=-bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=-bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=-bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=-bsd
+ ;;
+ cray | j90)
+ basic_machine=j90-cray
+ os=-unicos
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ decsystem10* | dec10*)
+ basic_machine=pdp10-dec
+ os=-tops10
+ ;;
+ decsystem20* | dec20*)
+ basic_machine=pdp10-dec
+ os=-tops20
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=-sysv3
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=-bosx
+ ;;
+ dpx2* | dpx2*-bull)
+ basic_machine=m68k-bull
+ os=-sysv3
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=-ebmon
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=-bsd
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ os=-ose
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=-sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ os=-go32
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=-hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ os=-xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ os=-hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=-sysv3
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=-bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=-hpux
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hppa-next)
+ os=-nextstep3
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=-osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=-proelf
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ ;;
+# I'm not sure what "Sysv32" means. Should this be sysv3.2?
+ i*86v32)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv32
+ ;;
+ i*86v4*)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv4
+ ;;
+ i*86v)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-sysv
+ ;;
+ i*86sol2)
+ basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+ os=-solaris2
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ os=-mach
+ ;;
+ i386-vsta | vsta)
+ basic_machine=i386-unknown
+ os=-vsta
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ -irix*)
+ ;;
+ *)
+ os=-irix4
+ ;;
+ esac
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=-sysv
+ ;;
+ m88k-omron*)
+ basic_machine=m88k-omron
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=-sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=-sysv
+ ;;
+ mingw32)
+ basic_machine=i386-pc
+ os=-mingw32
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ basic_machine=m68k-atari
+ os=-mint
+ ;;
+ mips3*-*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ mmix*)
+ basic_machine=mmix-knuth
+ os=-mmixware
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=-morphos
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=-msdos
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=-mvs
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=-sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-unknown
+ os=-netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ os=-linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=-newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=-newsos
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=-newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ os=-sysv
+ ;;
+ next | m*-next )
+ basic_machine=m68k-next
+ case $os in
+ -nextstep* )
+ ;;
+ -ns2*)
+ os=-nextstep2
+ ;;
+ *)
+ os=-nextstep3
+ ;;
+ esac
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=-cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=-cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=-nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ os=-mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ os=-nonstopux
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=-proelf
+ ;;
+ or32 | or32-*)
+ basic_machine=or32-unknown
+ os=-coff
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=-ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ os=-os68k
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=-hiuxwe2
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=-osf
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pentium | p5 | k5 | k6 | nexgen | viac3)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86 | athlon)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2)
+ basic_machine=i686-pc
+ ;;
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-* | 6x86-* | athlon-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pentiumii-* | pentium2-*)
+ basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=power-ibm
+ ;;
+ ppc) basic_machine=powerpc-unknown
+ ;;
+ ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle | ppc-le | powerpc-little)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64) basic_machine=powerpc64-unknown
+ ;;
+ ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ppc64le | powerpc64little | ppc64-le | powerpc64-little)
+ basic_machine=powerpc64le-unknown
+ ;;
+ ppc64le-* | powerpc64little-*)
+ basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ os=-pw32
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ os=-coff
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ s390 | s390-*)
+ basic_machine=s390-ibm
+ ;;
+ s390x | s390x-*)
+ basic_machine=s390x-ibm
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+########################
+# changes for Apache
+#
+ as400*)
+ basic_machine=as400-ibm
+ ;;
+#
+# end Apache changes
+########################
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh)
+ basic_machine=sh-hitachi
+ os=-hms
+ ;;
+ sparclite-wrs | simso-wrs)
+ basic_machine=sparclite-wrs
+ os=-vxworks
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=-sysv2
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ os=-sysv4
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=-sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=-sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=-sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=-sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=-sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=-sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=-solaris2
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ os=-unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=-dynix
+ ;;
+ t3d)
+ basic_machine=alpha-cray
+ os=-unicos
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ os=-unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ os=-unicos
+ ;;
+ tic54x | c54x*)
+ basic_machine=tic54x-unknown
+ os=-coff
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=-tops20
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=-udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=-sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ os=-none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=-sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=-vms
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=-vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=-vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=-vxworks
+ ;;
+ w65*)
+ basic_machine=w65-wdc
+ os=-none
+ ;;
+ w89k-*)
+ basic_machine=hppa1.1-winbond
+ os=-proelf
+ ;;
+ windows32)
+ basic_machine=i386-pc
+ os=-windows32-msvcrt
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=-unicos
+ ;;
+ z8k-*-coff)
+ basic_machine=z8k-unknown
+ os=-sim
+ ;;
+ none)
+ basic_machine=none-none
+ os=-none
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ basic_machine=hppa1.1-winbond
+ ;;
+ op50n)
+ basic_machine=hppa1.1-oki
+ ;;
+ op60c)
+ basic_machine=hppa1.1-oki
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp10)
+ # there are many clones, so DEC is not a safe bet
+ basic_machine=pdp10-unknown
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sh3 | sh4 | sh3eb | sh4eb)
+ basic_machine=sh-unknown
+ ;;
+ sh64)
+ basic_machine=sh64-unknown
+ ;;
+ sparc | sparcv9 | sparcv9b)
+ basic_machine=sparc-sun
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ basic_machine=m68k-apple
+ ;;
+ pmac | pmac-mpw)
+ basic_machine=powerpc-apple
+ ;;
+ c4x*)
+ basic_machine=c4x-none
+ os=-coff
+ ;;
+ *-unknown)
+ # Make sure to match an already-canonicalized machine name.
+ ;;
+ *)
+ echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+ # First match some system type aliases
+ # that might get confused with valid system types.
+ # -solaris* is a basic system type, with this one exception.
+ -solaris1 | -solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ -solaris)
+ os=-solaris2
+ ;;
+ -svr4*)
+ os=-sysv4
+ ;;
+ -unixware*)
+ os=-sysv4.2uw
+ ;;
+ -gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+########################
+# changes for Apache
+#
+ -os2_emx | -tpf* | -os390* | -vmcms* | -os400* )
+ ;;
+#
+# end Apache changes
+########################
+ # First accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST END IN A *, to match a version number.
+ # -sysv* is not here because it comes later, after sysvr4.
+ -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+ | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
+ | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
+ | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+ | -aos* \
+ | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+ | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+ | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \
+ | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+ | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+ | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+ | -chorusos* | -chorusrdb* \
+ | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+ | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \
+ | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \
+ | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+ | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+ | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+ | -morphos* | -superux* | -rtmk* | -rtmk-nova*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ -qnx*)
+ case $basic_machine in
+ x86-* | i*86-*)
+ ;;
+ *)
+ os=-nto$os
+ ;;
+ esac
+ ;;
+ -nto*)
+ os=-nto-qnx
+ ;;
+ -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+ | -windows* | -osx | -abug | -netware* | -os9* | -beos* \
+ | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+ ;;
+ -mac*)
+ os=`echo $os | sed -e 's|mac|macos|'`
+ ;;
+ -linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ -sunos5*)
+ os=`echo $os | sed -e 's|sunos5|solaris2|'`
+ ;;
+ -sunos6*)
+ os=`echo $os | sed -e 's|sunos6|solaris3|'`
+ ;;
+ -opened*)
+ os=-openedition
+ ;;
+ -wince*)
+ os=-wince
+ ;;
+ -osfrose*)
+ os=-osfrose
+ ;;
+ -osf*)
+ os=-osf
+ ;;
+ -utek*)
+ os=-bsd
+ ;;
+ -dynix*)
+ os=-bsd
+ ;;
+ -acis*)
+ os=-aos
+ ;;
+ -atheos*)
+ os=-atheos
+ ;;
+ -386bsd)
+ os=-bsd
+ ;;
+ -ctix* | -uts*)
+ os=-sysv
+ ;;
+ -nova*)
+ os=-rtmk-nova
+ ;;
+ -ns2 )
+ os=-nextstep2
+ ;;
+ -nsk*)
+ os=-nsk
+ ;;
+ # Preserve the version number of sinix5.
+ -sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ -sinix*)
+ os=-sysv4
+ ;;
+ -triton*)
+ os=-sysv3
+ ;;
+ -oss*)
+ os=-sysv3
+ ;;
+ -svr4)
+ os=-sysv4
+ ;;
+ -svr3)
+ os=-sysv3
+ ;;
+ -sysvr4)
+ os=-sysv4
+ ;;
+ # This must come after -sysvr4.
+ -sysv*)
+ ;;
+ -ose*)
+ os=-ose
+ ;;
+ -es1800*)
+ os=-ose
+ ;;
+ -xenix)
+ os=-xenix
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ os=-mint
+ ;;
+ -none)
+ ;;
+ *)
+ # Get rid of the `-' at the beginning of $os.
+ os=`echo $os | sed 's/[^-]*-//'`
+ echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ *-acorn)
+ os=-riscix1.2
+ ;;
+ arm*-rebel)
+ os=-linux
+ ;;
+ arm*-semi)
+ os=-aout
+ ;;
+ # This must come before the *-dec entry.
+ pdp10-*)
+ os=-tops20
+ ;;
+ pdp11-*)
+ os=-none
+ ;;
+ *-dec | vax-*)
+ os=-ultrix4.2
+ ;;
+ m68*-apollo)
+ os=-domain
+ ;;
+ i386-sun)
+ os=-sunos4.0.2
+ ;;
+ m68000-sun)
+ os=-sunos3
+ # This also exists in the configure program, but was not the
+ # default.
+ # os=-sunos4
+ ;;
+ m68*-cisco)
+ os=-aout
+ ;;
+ mips*-cisco)
+ os=-elf
+ ;;
+ mips*-*)
+ os=-elf
+ ;;
+ or32-*)
+ os=-coff
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=-sysv3
+ ;;
+ sparc-* | *-sun)
+ os=-sunos4.1.1
+ ;;
+ *-be)
+ os=-beos
+ ;;
+########################
+# changes for Apache
+#
+# *-ibm)
+# os=-aix
+# ;;
+#
+ *-ibm)
+ case $basic_machine in
+ s390*)
+ os=-os390;
+ ;;
+ i370*)
+ os=-mvs;
+ ;;
+ as400*)
+ os=-os400;
+ ;;
+ *)
+ os=-aix
+ ;;
+ esac
+ ;;
+#
+# end Apache changes
+########################
+
+ *-wec)
+ os=-proelf
+ ;;
+ *-winbond)
+ os=-proelf
+ ;;
+ *-oki)
+ os=-proelf
+ ;;
+ *-hp)
+ os=-hpux
+ ;;
+ *-hitachi)
+ os=-hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=-sysv
+ ;;
+ *-cbm)
+ os=-amigaos
+ ;;
+ *-dg)
+ os=-dgux
+ ;;
+ *-dolphin)
+ os=-sysv3
+ ;;
+ m68k-ccur)
+ os=-rtu
+ ;;
+ m88k-omron*)
+ os=-luna
+ ;;
+ *-next )
+ os=-nextstep
+ ;;
+ *-sequent)
+ os=-ptx
+ ;;
+ *-crds)
+ os=-unos
+ ;;
+ *-ns)
+ os=-genix
+ ;;
+ i370-*)
+ os=-mvs
+ ;;
+ *-next)
+ os=-nextstep3
+ ;;
+ *-gould)
+ os=-sysv
+ ;;
+ *-highlevel)
+ os=-bsd
+ ;;
+ *-encore)
+ os=-bsd
+ ;;
+ *-sgi)
+ os=-irix
+ ;;
+ *-siemens)
+ os=-sysv4
+ ;;
+ *-masscomp)
+ os=-rtu
+ ;;
+ f30[01]-fujitsu | f700-fujitsu)
+ os=-uxpv
+ ;;
+ *-rom68k)
+ os=-coff
+ ;;
+ *-*bug)
+ os=-coff
+ ;;
+ *-apple)
+ os=-macos
+ ;;
+ *-atari*)
+ os=-mint
+ ;;
+ *)
+ os=-none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ -riscix*)
+ vendor=acorn
+ ;;
+ -sunos*)
+ vendor=sun
+ ;;
+ -aix*)
+ vendor=ibm
+ ;;
+ -beos*)
+ vendor=be
+ ;;
+ -hpux*)
+ vendor=hp
+ ;;
+ -mpeix*)
+ vendor=hp
+ ;;
+ -hiux*)
+ vendor=hitachi
+ ;;
+ -unos*)
+ vendor=crds
+ ;;
+ -dgux*)
+ vendor=dg
+ ;;
+ -luna*)
+ vendor=omron
+ ;;
+ -genix*)
+ vendor=ns
+ ;;
+ -mvs* | -opened*)
+ vendor=ibm
+ ;;
+ -ptx*)
+ vendor=sequent
+ ;;
+ -vxsim* | -vxworks*)
+ vendor=wrs
+ ;;
+ -aux*)
+ vendor=apple
+ ;;
+ -hms*)
+ vendor=hitachi
+ ;;
+ -mpw* | -macos*)
+ vendor=apple
+ ;;
+ -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+ vendor=atari
+ ;;
+ -vos*)
+ vendor=stratus
+ ;;
+ esac
+ basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo $basic_machine$os
+exit 0
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
--- /dev/null
+#!/bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission. M.I.T. makes no representations about the
+# suitability of this software for any purpose. It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch. It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ true
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ chmodcmd=""
+ else
+ instcmd=mkdir
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ true
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ true
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ true
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ true
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ true
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
--- /dev/null
+#! /bin/sh
+# Common stub for a few missing GNU programs while installing.
+# Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+# Franc,ois Pinard <pinard@iro.umontreal.ca>, 1996.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA.
+
+if test $# -eq 0; then
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+fi
+
+case "$1" in
+
+ -h|--h|--he|--hel|--help)
+ echo "\
+$0 [OPTION]... PROGRAM [ARGUMENT]...
+
+Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an
+error status if there is no known handling for PROGRAM.
+
+Options:
+ -h, --help display this help and exit
+ -v, --version output version information and exit
+
+Supported PROGRAM values:
+ aclocal touch file \`aclocal.m4'
+ autoconf touch file \`configure'
+ autoheader touch file \`config.h.in'
+ automake touch all \`Makefile.in' files
+ bison create \`y.tab.[ch]', if possible, from existing .[ch]
+ flex create \`lex.yy.c', if possible, from existing .c
+ lex create \`lex.yy.c', if possible, from existing .c
+ makeinfo touch the output file
+ yacc create \`y.tab.[ch]', if possible, from existing .[ch]"
+ ;;
+
+ -v|--v|--ve|--ver|--vers|--versi|--versio|--version)
+ echo "missing - GNU libit 0.0"
+ ;;
+
+ -*)
+ echo 1>&2 "$0: Unknown \`$1' option"
+ echo 1>&2 "Try \`$0 --help' for more information"
+ exit 1
+ ;;
+
+ aclocal)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`acinclude.m4' or \`configure.in'. You might want
+ to install the \`Automake' and \`Perl' packages. Grab them from
+ any GNU archive site."
+ touch aclocal.m4
+ ;;
+
+ autoconf)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`configure.in'. You might want to install the
+ \`Autoconf' and \`GNU m4' packages. Grab them from any GNU
+ archive site."
+ touch configure
+ ;;
+
+ autoheader)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`acconfig.h' or \`configure.in'. You might want
+ to install the \`Autoconf' and \`GNU m4' packages. Grab them
+ from any GNU archive site."
+ files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' configure.in`
+ test -z "$files" && files="config.h"
+ touch_files=
+ for f in $files; do
+ case "$f" in
+ *:*) touch_files="$touch_files "`echo "$f" |
+ sed -e 's/^[^:]*://' -e 's/:.*//'`;;
+ *) touch_files="$touch_files $f.in";;
+ esac
+ done
+ touch $touch_files
+ ;;
+
+ automake)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified \`Makefile.am', \`acinclude.m4' or \`configure.in'.
+ You might want to install the \`Automake' and \`Perl' packages.
+ Grab them from any GNU archive site."
+ find . -type f -name Makefile.am -print |
+ sed 's/\.am$/.in/' |
+ while read f; do touch "$f"; done
+ ;;
+
+ bison|yacc)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a \`.y' file. You may need the \`Bison' package
+ in order for those modifications to take effect. You can get
+ \`Bison' from any GNU archive site."
+ rm -f y.tab.c y.tab.h
+ if [ $# -ne 1 ]; then
+ eval LASTARG="\${$#}"
+ case "$LASTARG" in
+ *.y)
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" y.tab.c
+ fi
+ SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" y.tab.h
+ fi
+ ;;
+ esac
+ fi
+ if [ ! -f y.tab.h ]; then
+ echo >y.tab.h
+ fi
+ if [ ! -f y.tab.c ]; then
+ echo 'main() { return 0; }' >y.tab.c
+ fi
+ ;;
+
+ lex|flex)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a \`.l' file. You may need the \`Flex' package
+ in order for those modifications to take effect. You can get
+ \`Flex' from any GNU archive site."
+ rm -f lex.yy.c
+ if [ $# -ne 1 ]; then
+ eval LASTARG="\${$#}"
+ case "$LASTARG" in
+ *.l)
+ SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'`
+ if [ -f "$SRCFILE" ]; then
+ cp "$SRCFILE" lex.yy.c
+ fi
+ ;;
+ esac
+ fi
+ if [ ! -f lex.yy.c ]; then
+ echo 'main() { return 0; }' >lex.yy.c
+ fi
+ ;;
+
+ makeinfo)
+ echo 1>&2 "\
+WARNING: \`$1' is missing on your system. You should only need it if
+ you modified a \`.texi' or \`.texinfo' file, or any other file
+ indirectly affecting the aspect of the manual. The spurious
+ call might also be the consequence of using a buggy \`make' (AIX,
+ DU, IRIX). You might want to install the \`Texinfo' package or
+ the \`GNU make' package. Grab either from any GNU archive site."
+ file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'`
+ if test -z "$file"; then
+ file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'`
+ file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file`
+ fi
+ touch $file
+ ;;
+
+ *)
+ echo 1>&2 "\
+WARNING: \`$1' is needed, and you do not seem to have it handy on your
+ system. You might have modified some files without having the
+ proper tools for further handling them. Check the \`README' file,
+ it often tells you about the needed prerequirements for installing
+ this package. You may also peek at any GNU archive site, in case
+ some other package would contain this missing \`$1' program."
+ exit 1
+ ;;
+esac
+
+exit 0
--- /dev/null
+#! /bin/sh
+# mkinstalldirs --- make directory hierarchy
+# Author: Noah Friedman <friedman@prep.ai.mit.edu>
+# Created: 1993-05-16
+# Public domain
+
+# $Id$
+
+errstatus=0
+
+for file
+do
+ set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
+ shift
+
+ pathcomp=
+ for d
+ do
+ pathcomp="$pathcomp$d"
+ case "$pathcomp" in
+ -* ) pathcomp=./$pathcomp ;;
+ esac
+
+ if test ! -d "$pathcomp"; then
+ echo "mkdir $pathcomp"
+
+ mkdir "$pathcomp" || lasterr=$?
+
+ if test ! -d "$pathcomp"; then
+ errstatus=$lasterr
+ fi
+ fi
+
+ pathcomp="$pathcomp/"
+ done
+done
+
+exit $errstatus
+
+# mkinstalldirs ends here
--- /dev/null
+################################################################
+# Process this file with top-level configure script to produce Makefile
+#
+# Copyright 2000 Clark Cooper
+#
+# This file is part of EXPAT.
+#
+# EXPAT is free software; you can redistribute it and/or modify it
+# under the terms of the License (based on the MIT/X license) contained
+# in the file COPYING that comes with this distribution.
+#
+# EXPAT IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+# SOFTWARE OR THE USE OR OTHER DEALINGS IN EXPAT.
+#
+
+
+SHELL = @SHELL@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+
+blddir = @blddir@/lib
+bindir = @bindir@
+sbindir = @sbindir@
+libexecdir = @libexecdir@
+datadir = @datadir@
+sysconfdir = @sysconfdir@
+sharedstatedir = @sharedstatedir@
+localstatedir = @localstatedir@
+libdir = @libdir@
+infodir = @infodir@
+mandir = @mandir@
+includedir = @includedir@
+oldincludedir = /usr/include
+
+subdir = lib
+
+top_builddir = ..
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_DATA = @INSTALL_DATA@
+
+host_alias = @host_alias@
+host_triplet = @host@
+AS = @AS@
+CC = @CC@
+DLLTOOL = @DLLTOOL@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+OBJDUMP = @OBJDUMP@
+PACKAGE = @PACKAGE@
+RANLIB = @RANLIB@
+VERSION = @VERSION@
+
+LIBRARY = libexpat.la
+SOURCES = xmlparse.c xmltok.c xmlrole.c
+OBJECTS = $(SOURCES:.c=.o)
+LTOBJECTS = $(SOURCES:.c=.lo)
+
+TEMPLATES = xmltok_impl.c xmltok_ns.c
+APIHEADER = expat.h
+HEADERS = ascii.h iasciitab.h utf8tab.h xmltok.h asciitab.h latin1tab.h \
+ nametab.h xmldef.h xmlrole.h xmltok_impl.h
+
+mkinstalldirs = $(SHELL) $(top_srcdir)/conftools/mkinstalldirs
+CONFIG_HEADER = ../config.h
+CONFIG_CLEAN_FILES =
+
+INCLUDES = -I$(srcdir) -I.. -I$(blddir)
+DEFS = @DEFS@ -DPACKAGE='"$(PACKAGE)"' -DVERSION='"$(PACKAGE)_$(VERSION)"'
+
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS = @LDFLAGS@
+LIBS = @LIBS@
+CFLAGS = @CFLAGS@
+
+LIBREVISION = @LIBREVISION@
+LIBCURRENT = @LIBCURRENT@
+LIBAGE = @LIBAGE@
+
+COMPILE = $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --mode=link $(CCLD) -version-info $(LIBCURRENT):$(LIBREVISION):$(LIBAGE) $(CFLAGS) $(LDFLAGS) -o $@
+DIST_COMMON = Makefile.in
+
+
+DISTFILES = $(DIST_COMMON) $(SOURCES) $(TEMPLATES) $(APIHEADER) $(HEADERS)
+
+TAR = gtar
+GZIP_ENV = --best
+
+all: $(LIBRARY)
+
+.SUFFIXES: .c .lo .o
+.PHONY: all clean distclean maintainer-clean
+
+.c.o:
+ $(COMPILE) -c $<
+
+.c.lo:
+ $(LTCOMPILE) -c $<
+
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ cd $(top_builddir) \
+ && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status
+
+$(top_builddir)/config.status: $(top_builddir)/configure
+ cd $(top_builddir) && $(MAKE) config.status
+
+$(top_builddir)/config.h: $(top_builddir)/config.h.in
+ cd $(top_builddir) && $(MAKE) config.h
+
+clean:
+ rm -f $(LIBRARY) *.o *.lo *~
+ rm -rf .libs _libs
+
+distclean: clean
+ rm -f Makefile expat.h
+
+maintainer-clean: distclean
+
+install: $(LIBRARY) $(APIHEADER)
+ $(mkinstalldirs) $(DESTDIR)$(libdir) $(DESTDIR)$(includedir)
+ $(LIBTOOL) --mode=install $(INSTALL) $(LIBRARY) $(DESTDIR)$(libdir)/$(LIBRARY)
+ $(INSTALL_DATA) $(APIHEADER) $(DESTDIR)$(includedir)
+
+uninstall:
+ $(LIBTOOL) --mode=uninstall rm -f $(DESTDIR)$(libdir)/$(LIBRARY);
+ rm -f $(DESTDIR)$(libdir)/$(APIHEADER)
+
+$(LIBRARY): $(LTOBJECTS)
+ $(LINK) -rpath $(libdir) $(LDFLAGS) $(LTOBJECTS)
+
+xmlparse.o \
+xmlparse.lo: xmlparse.c expat.h xmlrole.h xmltok.h $(top_builddir)/config.h
+
+xmlrole.o \
+xmlrole.lo: xmlrole.c ascii.h xmlrole.h $(top_builddir)/config.h
+
+xmltok.o \
+xmltok.lo: xmltok.c xmltok_impl.c xmltok_ns.c \
+ ascii.h asciitab.h iasciitab.h latin1tab.h nametab.h utf8tab.h \
+ xmltok.h xmltok_impl.h $(top_builddir)/config.h
--- /dev/null
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file COPYING for copying permission.
+*/
+
+#define ASCII_A 0x41
+#define ASCII_B 0x42
+#define ASCII_C 0x43
+#define ASCII_D 0x44
+#define ASCII_E 0x45
+#define ASCII_F 0x46
+#define ASCII_G 0x47
+#define ASCII_H 0x48
+#define ASCII_I 0x49
+#define ASCII_J 0x4A
+#define ASCII_K 0x4B
+#define ASCII_L 0x4C
+#define ASCII_M 0x4D
+#define ASCII_N 0x4E
+#define ASCII_O 0x4F
+#define ASCII_P 0x50
+#define ASCII_Q 0x51
+#define ASCII_R 0x52
+#define ASCII_S 0x53
+#define ASCII_T 0x54
+#define ASCII_U 0x55
+#define ASCII_V 0x56
+#define ASCII_W 0x57
+#define ASCII_X 0x58
+#define ASCII_Y 0x59
+#define ASCII_Z 0x5A
+
+#define ASCII_a 0x61
+#define ASCII_b 0x62
+#define ASCII_c 0x63
+#define ASCII_d 0x64
+#define ASCII_e 0x65
+#define ASCII_f 0x66
+#define ASCII_g 0x67
+#define ASCII_h 0x68
+#define ASCII_i 0x69
+#define ASCII_j 0x6A
+#define ASCII_k 0x6B
+#define ASCII_l 0x6C
+#define ASCII_m 0x6D
+#define ASCII_n 0x6E
+#define ASCII_o 0x6F
+#define ASCII_p 0x70
+#define ASCII_q 0x71
+#define ASCII_r 0x72
+#define ASCII_s 0x73
+#define ASCII_t 0x74
+#define ASCII_u 0x75
+#define ASCII_v 0x76
+#define ASCII_w 0x77
+#define ASCII_x 0x78
+#define ASCII_y 0x79
+#define ASCII_z 0x7A
+
+#define ASCII_0 0x30
+#define ASCII_1 0x31
+#define ASCII_2 0x32
+#define ASCII_3 0x33
+#define ASCII_4 0x34
+#define ASCII_5 0x35
+#define ASCII_6 0x36
+#define ASCII_7 0x37
+#define ASCII_8 0x38
+#define ASCII_9 0x39
+
+#define ASCII_TAB 0x09
+#define ASCII_SPACE 0x20
+#define ASCII_EXCL 0x21
+#define ASCII_QUOT 0x22
+#define ASCII_AMP 0x26
+#define ASCII_APOS 0x27
+#define ASCII_MINUS 0x2D
+#define ASCII_PERIOD 0x2E
+#define ASCII_COLON 0x3A
+#define ASCII_SEMI 0x3B
+#define ASCII_LT 0x3C
+#define ASCII_EQUALS 0x3D
+#define ASCII_GT 0x3E
+#define ASCII_LSQB 0x5B
+#define ASCII_RSQB 0x5D
+#define ASCII_UNDERSCORE 0x5F
--- /dev/null
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file COPYING for copying permission.
+*/
+
+/* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML,
+/* 0x0C */ BT_NONXML, BT_CR, BT_NONXML, BT_NONXML,
+/* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM,
+/* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS,
+/* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS,
+/* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL,
+/* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
+/* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
+/* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI,
+/* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST,
+/* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
+/* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
+/* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB,
+/* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT,
+/* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
+/* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
+/* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
+/* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER,
--- /dev/null
+/*================================================================
+** Copyright 2000, Clark Cooper
+** All rights reserved.
+**
+** This is free software. You are permitted to copy, distribute, or modify
+** it under the terms of the MIT/X license (contained in the COPYING file
+** with this distribution.)
+**
+**
+*/
+
+#ifndef CONFIG_HNW
+#define CONFIG_HNW
+
+#include <memory.h>
+#include <string.h>
+
+#define XML_NS 1
+#define XML_DTD 1
+#define XML_BYTE_ORDER 12
+#define XML_CONTEXT_BYTES 1024
+
+#endif /* ndef CONFIG_HNW */
--- /dev/null
+# Microsoft Developer Studio Project File - Name="expat" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=expat - 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 "expat.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 "expat.mak" CFG="expat - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "expat - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "expat - 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)" == "expat - 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 Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXPAT_EXPORTS" /Yu"stdafx.h" /FD /c
+# ADD CPP /nologo /MT /W3 /GX /O2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXPAT_EXPORTS" /D "COMPILED_FROM_DSP" /Yu"stdafx.h" /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+
+!ELSEIF "$(CFG)" == "expat - 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 /MTd /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXPAT_EXPORTS" /Yu"stdafx.h" /FD /GZ /c
+# ADD CPP /nologo /MTd /W3 /GX /Zi /Od /D "_DEBUG" /D "COMPILED_FROM_DSP" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "EXPAT_EXPORTS" /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+
+!ENDIF
+
+# Begin Target
+
+# Name "expat - Win32 Release"
+# Name "expat - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\xmlparse.c
+
+!IF "$(CFG)" == "expat - Win32 Release"
+
+# ADD CPP /D VERSION=\"expat_1.95.1\"
+
+!ELSEIF "$(CFG)" == "expat - Win32 Debug"
+
+# ADD CPP /GX- /Od /D VERSION=\"expat_1.95.1\"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\xmlrole.c
+
+!IF "$(CFG)" == "expat - Win32 Release"
+
+# ADD CPP /D VERSION=\"expat_1.95.1\"
+
+!ELSEIF "$(CFG)" == "expat - Win32 Debug"
+
+# ADD CPP /D VERSION=\"expat_1.95.1\"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\xmltok.c
+
+!IF "$(CFG)" == "expat - Win32 Release"
+
+# ADD CPP /D VERSION=\"expat_1.95.1\"
+
+!ELSEIF "$(CFG)" == "expat - Win32 Debug"
+
+# ADD CPP /D VERSION=\"expat_1.95.1\"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=xmltok_impl.c
+
+!IF "$(CFG)" == "expat - Win32 Release"
+
+# ADD CPP /D VERSION=\"expat_1.95.1\"
+
+!ELSEIF "$(CFG)" == "expat - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+# ADD CPP /D VERSION=\"expat_1.95.1\"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=xmltok_ns.c
+
+!IF "$(CFG)" == "expat - Win32 Release"
+
+# ADD CPP /D VERSION=\"expat_1.95.1\"
+
+!ELSEIF "$(CFG)" == "expat - Win32 Debug"
+
+# PROP Exclude_From_Build 1
+# ADD CPP /D VERSION=\"expat_1.95.1\"
+
+!ENDIF
+
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\ascii.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\asciitab.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\config.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\expat.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\iasciitab.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\latin1tab.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\nametab.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\utf8tab.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\xmlrole.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\xmltok.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\xmltok_impl.h
+# End Source File
+# End Group
+# Begin Group "Resource Files"
+
+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+# End Group
+# Begin Source File
+
+SOURCE=.\ReadMe.txt
+# End Source File
+# End Target
+# End Project
--- /dev/null
+/*
+Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+See the file COPYING for copying permission.
+*/
+
+#ifndef XmlParse_INCLUDED
+#define XmlParse_INCLUDED 1
+
+#include <stdlib.h>
+
+#ifndef XMLPARSEAPI
+# if defined(__declspec) && !defined(__CYGWIN__)
+# define XMLPARSEAPI __declspec(dllimport)
+# else
+# define XMLPARSEAPI /* nothing */
+# endif
+#endif /* not defined XMLPARSEAPI */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef void *XML_Parser;
+
+/* Information is UTF-8 encoded. */
+typedef char XML_Char;
+typedef char XML_LChar;
+
+enum XML_Content_Type {
+ XML_CTYPE_EMPTY = 1,
+ XML_CTYPE_ANY,
+ XML_CTYPE_MIXED,
+ XML_CTYPE_NAME,
+ XML_CTYPE_CHOICE,
+ XML_CTYPE_SEQ
+};
+
+enum XML_Content_Quant {
+ XML_CQUANT_NONE,
+ XML_CQUANT_OPT,
+ XML_CQUANT_REP,
+ XML_CQUANT_PLUS
+};
+
+/* If type == XML_CTYPE_EMPTY or XML_CTYPE_ANY, then quant will be
+ XML_CQUANT_NONE, and the other fields will be zero or NULL.
+ If type == XML_CTYPE_MIXED, then quant will be NONE or REP and
+ numchildren will contain number of elements that may be mixed in
+ and children point to an array of XML_Content cells that will be
+ all of XML_CTYPE_NAME type with no quantification.
+
+ If type == XML_CTYPE_NAME, then the name points to the name, and
+ the numchildren field will be zero and children will be NULL. The
+ quant fields indicates any quantifiers placed on the name.
+
+ CHOICE and SEQ will have name NULL, the number of children in
+ numchildren and children will point, recursively, to an array
+ of XML_Content cells.
+
+ The EMPTY, ANY, and MIXED types will only occur at top level.
+*/
+
+typedef struct XML_cp XML_Content;
+
+struct XML_cp {
+ enum XML_Content_Type type;
+ enum XML_Content_Quant quant;
+ const XML_Char * name;
+ unsigned int numchildren;
+ XML_Content * children;
+};
+
+
+/* This is called for an element declaration. See above for
+ description of the model argument. It's the caller's responsibility
+ to free model when finished with it.
+*/
+
+typedef void (*XML_ElementDeclHandler) (void *userData,
+ const XML_Char *name,
+ XML_Content *model);
+
+void XMLPARSEAPI
+XML_SetElementDeclHandler(XML_Parser parser,
+ XML_ElementDeclHandler eldecl);
+
+/*
+ The Attlist declaration handler is called for *each* attribute. So
+ a single Attlist declaration with multiple attributes declared will
+ generate multiple calls to this handler. The "default" parameter
+ may be NULL in the case of the "#IMPLIED" or "#REQUIRED" keyword.
+ The "isrequired" parameter will be true and the default value will
+ be NULL in the case of "#REQUIRED". If "isrequired" is true and
+ default is non-NULL, then this is a "#FIXED" default.
+ */
+
+typedef void (*XML_AttlistDeclHandler) (void *userData,
+ const XML_Char *elname,
+ const XML_Char *attname,
+ const XML_Char *att_type,
+ const XML_Char *dflt,
+ int isrequired);
+
+void XMLPARSEAPI
+XML_SetAttlistDeclHandler(XML_Parser parser,
+ XML_AttlistDeclHandler attdecl);
+
+
+ /* The XML declaration handler is called for *both* XML declarations and
+ text declarations. The way to distinguish is that the version parameter
+ will be null for text declarations. The encoding parameter may be null
+ for XML declarations. The standalone parameter will be -1, 0, or 1
+ indicating respectively that there was no standalone parameter in
+ the declaration, that it was given as no, or that it was given as yes.
+ */
+
+typedef void (*XML_XmlDeclHandler) (void *userData,
+ const XML_Char *version,
+ const XML_Char *encoding,
+ int standalone);
+
+void XMLPARSEAPI
+XML_SetXmlDeclHandler(XML_Parser parser,
+ XML_XmlDeclHandler xmldecl);
+
+
+typedef struct {
+ void *(*malloc_fcn)(size_t size);
+ void *(*realloc_fcn)(void *ptr, size_t size);
+ void (*free_fcn)(void *ptr);
+} XML_Memory_Handling_Suite;
+
+/* Constructs a new parser; encoding is the encoding specified by the
+external protocol or null if there is none specified. */
+
+XML_Parser XMLPARSEAPI
+XML_ParserCreate(const XML_Char *encoding);
+
+/* Constructs a new parser and namespace processor. Element type
+names and attribute names that belong to a namespace will be expanded;
+unprefixed attribute names are never expanded; unprefixed element type
+names are expanded only if there is a default namespace. The expanded
+name is the concatenation of the namespace URI, the namespace
+separator character, and the local part of the name. If the namespace
+separator is '\0' then the namespace URI and the local part will be
+concatenated without any separator. When a namespace is not declared,
+the name and prefix will be passed through without expansion. */
+
+XML_Parser XMLPARSEAPI
+XML_ParserCreateNS(const XML_Char *encoding, XML_Char namespaceSeparator);
+
+
+/* Constructs a new parser using the memory management suit referred to
+ by memsuite. If memsuite is NULL, then use the standard library memory
+ suite. If namespaceSeparator is non-NULL it creates a parser with
+ namespace processing as described above. The character pointed at
+ will serve as the namespace separator.
+
+ All further memory operations used for the created parser will come from
+ the given suite.
+*/
+
+XML_Parser XMLPARSEAPI
+XML_ParserCreate_MM(const XML_Char *encoding,
+ const XML_Memory_Handling_Suite *memsuite,
+ const XML_Char *namespaceSeparator);
+
+/* atts is array of name/value pairs, terminated by 0;
+ names and values are 0 terminated. */
+
+typedef void (*XML_StartElementHandler)(void *userData,
+ const XML_Char *name,
+ const XML_Char **atts);
+
+typedef void (*XML_EndElementHandler)(void *userData,
+ const XML_Char *name);
+
+
+/* s is not 0 terminated. */
+typedef void (*XML_CharacterDataHandler)(void *userData,
+ const XML_Char *s,
+ int len);
+
+/* target and data are 0 terminated */
+typedef void (*XML_ProcessingInstructionHandler)(void *userData,
+ const XML_Char *target,
+ const XML_Char *data);
+
+/* data is 0 terminated */
+typedef void (*XML_CommentHandler)(void *userData, const XML_Char *data);
+
+typedef void (*XML_StartCdataSectionHandler)(void *userData);
+typedef void (*XML_EndCdataSectionHandler)(void *userData);
+
+/* This is called for any characters in the XML document for
+which there is no applicable handler. This includes both
+characters that are part of markup which is of a kind that is
+not reported (comments, markup declarations), or characters
+that are part of a construct which could be reported but
+for which no handler has been supplied. The characters are passed
+exactly as they were in the XML document except that
+they will be encoded in UTF-8. Line boundaries are not normalized.
+Note that a byte order mark character is not passed to the default handler.
+There are no guarantees about how characters are divided between calls
+to the default handler: for example, a comment might be split between
+multiple calls. */
+
+typedef void (*XML_DefaultHandler)(void *userData,
+ const XML_Char *s,
+ int len);
+
+/* This is called for the start of the DOCTYPE declaration, before
+ any DTD or internal subset is parsed. */
+
+typedef void (*XML_StartDoctypeDeclHandler)(void *userData,
+ const XML_Char *doctypeName,
+ const XML_Char *sysid,
+ const XML_Char *pubid,
+ int has_internal_subset
+ );
+
+/* This is called for the start of the DOCTYPE declaration when the
+closing > is encountered, but after processing any external subset. */
+typedef void (*XML_EndDoctypeDeclHandler)(void *userData);
+
+/* This is called for entity declarations. The is_parameter_entity
+ argument will be non-zero if the entity is a parameter entity, zero
+ otherwise.
+
+ For internal entities (<!ENTITY foo "bar">), value will
+ be non-null and systemId, publicID, and notationName will be null.
+ The value string is NOT null terminated; the length is provided in
+ the value_length argument. Since it is legal to have zero-length
+ values, do not use this argument to test for internal entities.
+
+ For external entities, value will be null and systemId will be non-null.
+ The publicId argument will be null unless a public identifier was
+ provided. The notationName argument will have a non-null value only
+ for unparsed entity declarations.
+*/
+
+typedef void (*XML_EntityDeclHandler) (void *userData,
+ const XML_Char *entityName,
+ int is_parameter_entity,
+ const XML_Char *value,
+ int value_length,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId,
+ const XML_Char *notationName);
+
+void XMLPARSEAPI
+XML_SetEntityDeclHandler(XML_Parser parser,
+ XML_EntityDeclHandler handler);
+
+/* OBSOLETE -- OBSOLETE -- OBSOLETE
+ This handler has been superceded by the EntityDeclHandler above.
+ It is provided here for backward compatibility.
+This is called for a declaration of an unparsed (NDATA)
+entity. The base argument is whatever was set by XML_SetBase.
+The entityName, systemId and notationName arguments will never be null.
+The other arguments may be. */
+
+typedef void (*XML_UnparsedEntityDeclHandler)(void *userData,
+ const XML_Char *entityName,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId,
+ const XML_Char *notationName);
+
+/* This is called for a declaration of notation.
+The base argument is whatever was set by XML_SetBase.
+The notationName will never be null. The other arguments can be. */
+
+typedef void (*XML_NotationDeclHandler)(void *userData,
+ const XML_Char *notationName,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId);
+
+/* When namespace processing is enabled, these are called once for
+each namespace declaration. The call to the start and end element
+handlers occur between the calls to the start and end namespace
+declaration handlers. For an xmlns attribute, prefix will be null.
+For an xmlns="" attribute, uri will be null. */
+
+typedef void (*XML_StartNamespaceDeclHandler)(void *userData,
+ const XML_Char *prefix,
+ const XML_Char *uri);
+
+typedef void (*XML_EndNamespaceDeclHandler)(void *userData,
+ const XML_Char *prefix);
+
+/* This is called if the document is not standalone (it has an
+external subset or a reference to a parameter entity, but does not
+have standalone="yes"). If this handler returns 0, then processing
+will not continue, and the parser will return a
+XML_ERROR_NOT_STANDALONE error. */
+
+typedef int (*XML_NotStandaloneHandler)(void *userData);
+
+/* This is called for a reference to an external parsed general entity.
+The referenced entity is not automatically parsed.
+The application can parse it immediately or later using
+XML_ExternalEntityParserCreate.
+The parser argument is the parser parsing the entity containing the reference;
+it can be passed as the parser argument to XML_ExternalEntityParserCreate.
+The systemId argument is the system identifier as specified in the entity
+declaration; it will not be null.
+The base argument is the system identifier that should be used as the base for
+resolving systemId if systemId was relative; this is set by XML_SetBase;
+it may be null.
+The publicId argument is the public identifier as specified in the entity
+declaration, or null if none was specified; the whitespace in the public
+identifier will have been normalized as required by the XML spec.
+The context argument specifies the parsing context in the format
+expected by the context argument to
+XML_ExternalEntityParserCreate; context is valid only until the handler
+returns, so if the referenced entity is to be parsed later, it must be copied.
+The handler should return 0 if processing should not continue because of
+a fatal error in the handling of the external entity.
+In this case the calling parser will return an
+XML_ERROR_EXTERNAL_ENTITY_HANDLING error.
+Note that unlike other handlers the first argument is the parser, not
+userData. */
+
+typedef int (*XML_ExternalEntityRefHandler)(XML_Parser parser,
+ const XML_Char *context,
+ const XML_Char *base,
+ const XML_Char *systemId,
+ const XML_Char *publicId);
+
+/* This structure is filled in by the XML_UnknownEncodingHandler
+to provide information to the parser about encodings that are unknown
+to the parser.
+The map[b] member gives information about byte sequences
+whose first byte is b.
+If map[b] is c where c is >= 0, then b by itself encodes the Unicode scalar
+value c.
+If map[b] is -1, then the byte sequence is malformed.
+If map[b] is -n, where n >= 2, then b is the first byte of an n-byte
+sequence that encodes a single Unicode scalar value.
+The data member will be passed as the first argument to the convert function.
+The convert function is used to convert multibyte sequences;
+s will point to a n-byte sequence where map[(unsigned char)*s] == -n.
+The convert function must return the Unicode scalar value
+represented by this byte sequence or -1 if the byte sequence is malformed.
+The convert function may be null if the encoding is a single-byte encoding,
+that is if map[b] >= -1 for all bytes b.
+When the parser is finished with the encoding, then if release is not null,
+it will call release passing it the data member;
+once release has been called, the convert function will not be called again.
+
+Expat places certain restrictions on the encodings that are supported
+using this mechanism.
+
+1. Every ASCII character that can appear in a well-formed XML document,
+other than the characters
+
+ $@\^`{}~
+
+must be represented by a single byte, and that byte must be the
+same byte that represents that character in ASCII.
+
+2. No character may require more than 4 bytes to encode.
+
+3. All characters encoded must have Unicode scalar values <= 0xFFFF,
+(ie characters that would be encoded by surrogates in UTF-16
+are not allowed). Note that this restriction doesn't apply to
+the built-in support for UTF-8 and UTF-16.
+
+4. No Unicode character may be encoded by more than one distinct sequence
+of bytes. */
+
+typedef struct {
+ int map[256];
+ void *data;
+ int (*convert)(void *data, const char *s);
+ void (*release)(void *data);
+} XML_Encoding;
+
+/* This is called for an encoding that is unknown to the parser.
+The encodingHandlerData argument is that which was passed as the
+second argument to XML_SetUnknownEncodingHandler.
+The name argument gives the name of the encoding as specified in
+the encoding declaration.
+If the callback can provide information about the encoding,
+it must fill in the XML_Encoding structure, and return 1.
+Otherwise it must return 0.
+If info does not describe a suitable encoding,
+then the parser will return an XML_UNKNOWN_ENCODING error. */
+
+typedef int (*XML_UnknownEncodingHandler)(void *encodingHandlerData,
+ const XML_Char *name,
+ XML_Encoding *info);
+
+void XMLPARSEAPI
+XML_SetElementHandler(XML_Parser parser,
+ XML_StartElementHandler start,
+ XML_EndElementHandler end);
+
+void XMLPARSEAPI
+XML_SetStartElementHandler(XML_Parser, XML_StartElementHandler);
+
+void XMLPARSEAPI
+XML_SetEndElementHandler(XML_Parser, XML_EndElementHandler);
+
+void XMLPARSEAPI
+XML_SetCharacterDataHandler(XML_Parser parser,
+ XML_CharacterDataHandler handler);
+
+void XMLPARSEAPI
+XML_SetProcessingInstructionHandler(XML_Parser parser,
+ XML_ProcessingInstructionHandler handler);
+void XMLPARSEAPI
+XML_SetCommentHandler(XML_Parser parser,
+ XML_CommentHandler handler);
+
+void XMLPARSEAPI
+XML_SetCdataSectionHandler(XML_Parser parser,
+ XML_StartCdataSectionHandler start,
+ XML_EndCdataSectionHandler end);
+
+void XMLPARSEAPI
+XML_SetStartCdataSectionHandler(XML_Parser parser,
+ XML_StartCdataSectionHandler start);
+
+void XMLPARSEAPI
+XML_SetEndCdataSectionHandler(XML_Parser parser,
+ XML_EndCdataSectionHandler end);
+
+/* This sets the default handler and also inhibits expansion of
+internal entities. The entity reference will be passed to the default
+handler. */
+
+void XMLPARSEAPI
+XML_SetDefaultHandler(XML_Parser parser,
+ XML_DefaultHandler handler);
+
+/* This sets the default handler but does not inhibit expansion of
+internal entities. The entity reference will not be passed to the
+default handler. */
+
+void XMLPARSEAPI
+XML_SetDefaultHandlerExpand(XML_Parser parser,
+ XML_DefaultHandler handler);
+
+void XMLPARSEAPI
+XML_SetDoctypeDeclHandler(XML_Parser parser,
+ XML_StartDoctypeDeclHandler start,
+ XML_EndDoctypeDeclHandler end);
+
+void XMLPARSEAPI
+XML_SetStartDoctypeDeclHandler(XML_Parser parser,
+ XML_StartDoctypeDeclHandler start);
+
+void XMLPARSEAPI
+XML_SetEndDoctypeDeclHandler(XML_Parser parser,
+ XML_EndDoctypeDeclHandler end);
+
+void XMLPARSEAPI
+XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
+ XML_UnparsedEntityDeclHandler handler);
+
+void XMLPARSEAPI
+XML_SetNotationDeclHandler(XML_Parser parser,
+ XML_NotationDeclHandler handler);
+
+void XMLPARSEAPI
+XML_SetNamespaceDeclHandler(XML_Parser parser,
+ XML_StartNamespaceDeclHandler start,
+ XML_EndNamespaceDeclHandler end);
+
+void XMLPARSEAPI
+XML_SetStartNamespaceDeclHandler(XML_Parser parser,
+ XML_StartNamespaceDeclHandler start);
+
+void XMLPARSEAPI
+XML_SetEndNamespaceDeclHandler(XML_Parser parser,
+ XML_EndNamespaceDeclHandler end);
+
+void XMLPARSEAPI
+XML_SetNotStandaloneHandler(XML_Parser parser,
+ XML_NotStandaloneHandler handler);
+
+void XMLPARSEAPI
+XML_SetExternalEntityRefHandler(XML_Parser parser,
+ XML_ExternalEntityRefHandler handler);
+
+/* If a non-null value for arg is specified here, then it will be passed
+as the first argument to the external entity ref handler instead
+of the parser object. */
+void XMLPARSEAPI
+XML_SetExternalEntityRefHandlerArg(XML_Parser, void *arg);
+
+void XMLPARSEAPI
+XML_SetUnknownEncodingHandler(XML_Parser parser,
+ XML_UnknownEncodingHandler handler,
+ void *encodingHandlerData);
+
+/* This can be called within a handler for a start element, end element,
+processing instruction or character data. It causes the corresponding
+markup to be passed to the default handler. */
+void XMLPARSEAPI
+XML_DefaultCurrent(XML_Parser parser);
+
+/* If do_nst is non-zero, and namespace processing is in effect, and
+ a name has a prefix (i.e. an explicit namespace qualifier) then
+ that name is returned as a triplet in a single
+ string separated by the separator character specified when the parser
+ was created: URI + sep + local_name + sep + prefix.
+
+ If do_nst is zero, then namespace information is returned in the
+ default manner (URI + sep + local_name) whether or not the names
+ has a prefix.
+*/
+
+void XMLPARSEAPI
+XML_SetReturnNSTriplet(XML_Parser parser, int do_nst);
+
+/* This value is passed as the userData argument to callbacks. */
+void XMLPARSEAPI
+XML_SetUserData(XML_Parser parser, void *userData);
+
+/* Returns the last value set by XML_SetUserData or null. */
+#define XML_GetUserData(parser) (*(void **)(parser))
+
+/* This is equivalent to supplying an encoding argument
+to XML_ParserCreate. It must not be called after XML_Parse
+or XML_ParseBuffer. */
+
+int XMLPARSEAPI
+XML_SetEncoding(XML_Parser parser, const XML_Char *encoding);
+
+/* If this function is called, then the parser will be passed
+as the first argument to callbacks instead of userData.
+The userData will still be accessible using XML_GetUserData. */
+
+void XMLPARSEAPI
+XML_UseParserAsHandlerArg(XML_Parser parser);
+
+/* Sets the base to be used for resolving relative URIs in system
+identifiers in declarations. Resolving relative identifiers is left
+to the application: this value will be passed through as the base
+argument to the XML_ExternalEntityRefHandler, XML_NotationDeclHandler
+and XML_UnparsedEntityDeclHandler. The base argument will be copied.
+Returns zero if out of memory, non-zero otherwise. */
+
+int XMLPARSEAPI
+XML_SetBase(XML_Parser parser, const XML_Char *base);
+
+const XML_Char XMLPARSEAPI *
+XML_GetBase(XML_Parser parser);
+
+/* Returns the number of the attribute/value pairs passed in last call
+to the XML_StartElementHandler that were specified in the start-tag
+rather than defaulted. Each attribute/value pair counts as 2; thus
+this correspondds to an index into the atts array passed to the
+XML_StartElementHandler. */
+
+int XMLPARSEAPI
+XML_GetSpecifiedAttributeCount(XML_Parser parser);
+
+/* Returns the index of the ID attribute passed in the last call to
+XML_StartElementHandler, or -1 if there is no ID attribute. Each
+attribute/value pair counts as 2; thus this correspondds to an index
+into the atts array passed to the XML_StartElementHandler. */
+
+int XMLPARSEAPI
+XML_GetIdAttributeIndex(XML_Parser parser);
+
+/* Parses some input. Returns 0 if a fatal error is detected.
+The last call to XML_Parse must have isFinal true;
+len may be zero for this call (or any other). */
+int XMLPARSEAPI
+XML_Parse(XML_Parser parser, const char *s, int len, int isFinal);
+
+void XMLPARSEAPI *
+XML_GetBuffer(XML_Parser parser, int len);
+
+int XMLPARSEAPI
+XML_ParseBuffer(XML_Parser parser, int len, int isFinal);
+
+/* Creates an XML_Parser object that can parse an external general
+entity; context is a '\0'-terminated string specifying the parse
+context; encoding is a '\0'-terminated string giving the name of the
+externally specified encoding, or null if there is no externally
+specified encoding. The context string consists of a sequence of
+tokens separated by formfeeds (\f); a token consisting of a name
+specifies that the general entity of the name is open; a token of the
+form prefix=uri specifies the namespace for a particular prefix; a
+token of the form =uri specifies the default namespace. This can be
+called at any point after the first call to an
+ExternalEntityRefHandler so longer as the parser has not yet been
+freed. The new parser is completely independent and may safely be
+used in a separate thread. The handlers and userData are initialized
+from the parser argument. Returns 0 if out of memory. Otherwise
+returns a new XML_Parser object. */
+XML_Parser XMLPARSEAPI
+XML_ExternalEntityParserCreate(XML_Parser parser,
+ const XML_Char *context,
+ const XML_Char *encoding);
+
+enum XML_ParamEntityParsing {
+ XML_PARAM_ENTITY_PARSING_NEVER,
+ XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE,
+ XML_PARAM_ENTITY_PARSING_ALWAYS
+};
+
+/* Controls parsing of parameter entities (including the external DTD
+subset). If parsing of parameter entities is enabled, then references
+to external parameter entities (including the external DTD subset)
+will be passed to the handler set with
+XML_SetExternalEntityRefHandler. The context passed will be 0.
+Unlike external general entities, external parameter entities can only
+be parsed synchronously. If the external parameter entity is to be
+parsed, it must be parsed during the call to the external entity ref
+handler: the complete sequence of XML_ExternalEntityParserCreate,
+XML_Parse/XML_ParseBuffer and XML_ParserFree calls must be made during
+this call. After XML_ExternalEntityParserCreate has been called to
+create the parser for the external parameter entity (context must be 0
+for this call), it is illegal to make any calls on the old parser
+until XML_ParserFree has been called on the newly created parser. If
+the library has been compiled without support for parameter entity
+parsing (ie without XML_DTD being defined), then
+XML_SetParamEntityParsing will return 0 if parsing of parameter
+entities is requested; otherwise it will return non-zero. */
+
+int XMLPARSEAPI
+XML_SetParamEntityParsing(XML_Parser parser,
+ enum XML_ParamEntityParsing parsing);
+
+enum XML_Error {
+ XML_ERROR_NONE,
+ XML_ERROR_NO_MEMORY,
+ XML_ERROR_SYNTAX,
+ XML_ERROR_NO_ELEMENTS,
+ XML_ERROR_INVALID_TOKEN,
+ XML_ERROR_UNCLOSED_TOKEN,
+ XML_ERROR_PARTIAL_CHAR,
+ XML_ERROR_TAG_MISMATCH,
+ XML_ERROR_DUPLICATE_ATTRIBUTE,
+ XML_ERROR_JUNK_AFTER_DOC_ELEMENT,
+ XML_ERROR_PARAM_ENTITY_REF,
+ XML_ERROR_UNDEFINED_ENTITY,
+ XML_ERROR_RECURSIVE_ENTITY_REF,
+ XML_ERROR_ASYNC_ENTITY,
+ XML_ERROR_BAD_CHAR_REF,
+ XML_ERROR_BINARY_ENTITY_REF,
+ XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF,
+ XML_ERROR_MISPLACED_XML_PI,
+ XML_ERROR_UNKNOWN_ENCODING,
+ XML_ERROR_INCORRECT_ENCODING,
+ XML_ERROR_UNCLOSED_CDATA_SECTION,
+ XML_ERROR_EXTERNAL_ENTITY_HANDLING,
+ XML_ERROR_NOT_STANDALONE,
+ XML_ERROR_UNEXPECTED_STATE
+};
+
+/* If XML_Parse or XML_ParseBuffer have returned 0, then XML_GetErrorCode
+returns information about the error. */
+
+enum XML_Error XMLPARSEAPI
+XML_GetErrorCode(XML_Parser parser);
+
+/* These functions return information about the current parse location.
+They may be called when XML_Parse or XML_ParseBuffer return 0;
+in this case the location is the location of the character at which
+the error was detected.
+They may also be called from any other callback called to report
+some parse event; in this the location is the location of the first
+of the sequence of characters that generated the event. */
+
+int XMLPARSEAPI XML_GetCurrentLineNumber(XML_Parser parser);
+int XMLPARSEAPI XML_GetCurrentColumnNumber(XML_Parser parser);
+long XMLPARSEAPI XML_GetCurrentByteIndex(XML_Parser parser);
+
+/* Return the number of bytes in the current event.
+Returns 0 if the event is in an internal entity. */
+
+int XMLPARSEAPI
+XML_GetCurrentByteCount(XML_Parser parser);
+
+/* If XML_CONTEXT_BYTES is defined, returns the input buffer, sets
+ the integer pointed to by offset to the offset within this buffer
+ of the current parse position, and sets the integer pointed to by size
+ to the size of this buffer (the number of input bytes). Otherwise
+ returns a null pointer. Also returns a null pointer if a parse isn't
+ active.
+
+ NOTE: The character pointer returned should not be used outside
+ the handler that makes the call. */
+
+const char XMLPARSEAPI *
+XML_GetInputContext(XML_Parser parser,
+ int *offset,
+ int *size);
+
+/* For backwards compatibility with previous versions. */
+#define XML_GetErrorLineNumber XML_GetCurrentLineNumber
+#define XML_GetErrorColumnNumber XML_GetCurrentColumnNumber
+#define XML_GetErrorByteIndex XML_GetCurrentByteIndex
+
+/* Frees memory used by the parser. */
+void XMLPARSEAPI
+XML_ParserFree(XML_Parser parser);
+
+/* Returns a string describing the error. */
+const XML_LChar XMLPARSEAPI *
+XML_ErrorString(int code);
+
+/* Return a string containing the version number of this expat */
+const XML_LChar XMLPARSEAPI *
+XML_ExpatVersion(void);
+
+typedef struct {
+ int major;
+ int minor;
+ int micro;
+} XML_Expat_Version;
+
+/* Return an XML_Expat_Version structure containing numeric version
+ number information for this version of expat */
+
+XML_Expat_Version XMLPARSEAPI
+XML_ExpatVersionInfo(void);
+
+#ifndef XML_MAJOR_VERSION
+#define XML_MAJOR_VERSION @EXPAT_MAJOR_VERSION@
+#endif
+#ifndef XML_MINOR_VERSION
+#define XML_MINOR_VERSION @EXPAT_MINOR_VERSION@
+#endif
+#ifndef XML_MICRO_VERSION
+#define XML_MICRO_VERSION @EXPAT_EDIT@
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* not XmlParse_INCLUDED */
--- /dev/null
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file COPYING for copying permission.
+*/
+
+/* Like asciitab.h, except that 0xD has code BT_S rather than BT_CR */
+/* 0x00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x04 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x08 */ BT_NONXML, BT_S, BT_LF, BT_NONXML,
+/* 0x0C */ BT_NONXML, BT_S, BT_NONXML, BT_NONXML,
+/* 0x10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x14 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x18 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x1C */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0x20 */ BT_S, BT_EXCL, BT_QUOT, BT_NUM,
+/* 0x24 */ BT_OTHER, BT_PERCNT, BT_AMP, BT_APOS,
+/* 0x28 */ BT_LPAR, BT_RPAR, BT_AST, BT_PLUS,
+/* 0x2C */ BT_COMMA, BT_MINUS, BT_NAME, BT_SOL,
+/* 0x30 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
+/* 0x34 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
+/* 0x38 */ BT_DIGIT, BT_DIGIT, BT_COLON, BT_SEMI,
+/* 0x3C */ BT_LT, BT_EQUALS, BT_GT, BT_QUEST,
+/* 0x40 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
+/* 0x44 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
+/* 0x48 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x4C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x50 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x58 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_LSQB,
+/* 0x5C */ BT_OTHER, BT_RSQB, BT_OTHER, BT_NMSTRT,
+/* 0x60 */ BT_OTHER, BT_HEX, BT_HEX, BT_HEX,
+/* 0x64 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
+/* 0x68 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x6C */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0x78 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
+/* 0x7C */ BT_VERBAR, BT_OTHER, BT_OTHER, BT_OTHER,
--- /dev/null
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file COPYING for copying permission.
+*/
+
+/* 0x80 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x84 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x88 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x8C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x90 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x94 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x98 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0x9C */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xA0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xA4 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xA8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER,
+/* 0xAC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xB0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xB4 */ BT_OTHER, BT_NMSTRT, BT_OTHER, BT_NAME,
+/* 0xB8 */ BT_OTHER, BT_OTHER, BT_NMSTRT, BT_OTHER,
+/* 0xBC */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 0xC0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xC4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xC8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xCC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xD0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xD4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
+/* 0xD8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xDC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xE0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xE4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xE8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xEC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xF0 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xF4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
+/* 0xF8 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 0xFC */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
--- /dev/null
+static unsigned char ebcdic[] = {
+/* 00 */ 0x00 ,0x01 ,0x02 ,0x03 ,0x85 ,0x09 ,0x86 ,0x7f ,0x87 ,0x8d ,0x8e ,0x0b ,0x0c ,0x0d ,0x0e ,0x0f ,
+/* 10 */ 0x10 ,0x11 ,0x12 ,0x13 ,0x8f ,0x0a ,0x08 ,0x97 ,0x18 ,0x19 ,0x9c ,0x9d ,0x1c ,0x1d ,0x1e ,0x1f ,
+/* 20 */ 0x80 ,0x81 ,0x82 ,0x83 ,0x84 ,0x92 ,0x17 ,0x1b ,0x88 ,0x89 ,0x8a ,0x8b ,0x8c ,0x05 ,0x06 ,0x07 ,
+/* 30 */ 0x90 ,0x91 ,0x16 ,0x93 ,0x94 ,0x95 ,0x96 ,0x04 ,0x98 ,0x99 ,0x9a ,0x9b ,0x14 ,0x15 ,0x9e ,0x1a ,
+/* 40 */ 0x20 ,0xa0 ,0xe2 ,0xe4 ,0xe0 ,0xe1 ,0xe3 ,0xe5 ,0xe7 ,0xf1 ,0x60 ,0x2e ,0x3c ,0x28 ,0x2b ,0x7c ,
+/* 50 */ 0x26 ,0xe9 ,0xea ,0xeb ,0xe8 ,0xed ,0xee ,0xef ,0xec ,0xdf ,0x21 ,0x24 ,0x2a ,0x29 ,0x3b ,0x9f ,
+/* 60 */ 0x2d ,0x2f ,0xc2 ,0xc4 ,0xc0 ,0xc1 ,0xc3 ,0xc5 ,0xc7 ,0xd1 ,0x5e ,0x2c ,0x25 ,0x5f ,0x3e ,0x3f ,
+/* 70 */ 0xf8 ,0xc9 ,0xca ,0xcb ,0xc8 ,0xcd ,0xce ,0xcf ,0xcc ,0xa8 ,0x3a ,0x23 ,0x40 ,0x27 ,0x3d ,0x22 ,
+/* 80 */ 0xd8 ,0x61 ,0x62 ,0x63 ,0x64 ,0x65 ,0x66 ,0x67 ,0x68 ,0x69 ,0xab ,0xbb ,0xf0 ,0xfd ,0xfe ,0xb1 ,
+/* 90 */ 0xb0 ,0x6a ,0x6b ,0x6c ,0x6d ,0x6e ,0x6f ,0x70 ,0x71 ,0x72 ,0xaa ,0xba ,0xe6 ,0xb8 ,0xc6 ,0xa4 ,
+/* a0 */ 0xb5 ,0xaf ,0x73 ,0x74 ,0x75 ,0x76 ,0x77 ,0x78 ,0x79 ,0x7a ,0xa1 ,0xbf ,0xd0 ,0xdd ,0xde ,0xae ,
+/* b0 */ 0xa2 ,0xa3 ,0xa5 ,0xb7 ,0xa9 ,0xa7 ,0xb6 ,0xbc ,0xbd ,0xbe ,0xac ,0x5b ,0x5c ,0x5d ,0xb4 ,0xd7 ,
+/* c0 */ 0xf9 ,0x41 ,0x42 ,0x43 ,0x44 ,0x45 ,0x46 ,0x47 ,0x48 ,0x49 ,0xad ,0xf4 ,0xf6 ,0xf2 ,0xf3 ,0xf5 ,
+/* d0 */ 0xa6 ,0x4a ,0x4b ,0x4c ,0x4d ,0x4e ,0x4f ,0x50 ,0x51 ,0x52 ,0xb9 ,0xfb ,0xfc ,0xdb ,0xfa ,0xff ,
+/* e0 */ 0xd9 ,0xf7 ,0x53 ,0x54 ,0x55 ,0x56 ,0x57 ,0x58 ,0x59 ,0x5a ,0xb2 ,0xd4 ,0xd6 ,0xd2 ,0xd3 ,0xd5 ,
+/* f0 */ 0x30 ,0x31 ,0x32 ,0x33 ,0x34 ,0x35 ,0x36 ,0x37 ,0x38 ,0x39 ,0xb3 ,0x7b ,0xdc ,0x7d ,0xda ,0x7e
+};
--- /dev/null
+static const unsigned namingBitmap[] = {
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+0x00000000, 0x04000000, 0x87FFFFFE, 0x07FFFFFE,
+0x00000000, 0x00000000, 0xFF7FFFFF, 0xFF7FFFFF,
+0xFFFFFFFF, 0x7FF3FFFF, 0xFFFFFDFE, 0x7FFFFFFF,
+0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFE00F, 0xFC31FFFF,
+0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF,
+0xFFFFFFFF, 0xF80001FF, 0x00000003, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0xFFFFD740, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD,
+0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF,
+0xFFFF0003, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF,
+0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE,
+0x0000007F, 0x00000000, 0xFFFF0000, 0x000707FF,
+0x00000000, 0x07FFFFFE, 0x000007FE, 0xFFFE0000,
+0xFFFFFFFF, 0x7CFFFFFF, 0x002F7FFF, 0x00000060,
+0xFFFFFFE0, 0x23FFFFFF, 0xFF000000, 0x00000003,
+0xFFF99FE0, 0x03C5FDFF, 0xB0000000, 0x00030003,
+0xFFF987E0, 0x036DFDFF, 0x5E000000, 0x001C0000,
+0xFFFBAFE0, 0x23EDFDFF, 0x00000000, 0x00000001,
+0xFFF99FE0, 0x23CDFDFF, 0xB0000000, 0x00000003,
+0xD63DC7E0, 0x03BFC718, 0x00000000, 0x00000000,
+0xFFFDDFE0, 0x03EFFDFF, 0x00000000, 0x00000003,
+0xFFFDDFE0, 0x03EFFDFF, 0x40000000, 0x00000003,
+0xFFFDDFE0, 0x03FFFDFF, 0x00000000, 0x00000003,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0xFFFFFFFE, 0x000D7FFF, 0x0000003F, 0x00000000,
+0xFEF02596, 0x200D6CAE, 0x0000001F, 0x00000000,
+0x00000000, 0x00000000, 0xFFFFFEFF, 0x000003FF,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0xFFFFFFFF, 0xFFFF003F, 0x007FFFFF,
+0x0007DAED, 0x50000000, 0x82315001, 0x002C62AB,
+0x40000000, 0xF580C900, 0x00000007, 0x02010800,
+0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+0x0FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x03FFFFFF,
+0x3F3FFFFF, 0xFFFFFFFF, 0xAAFF3F3F, 0x3FFFFFFF,
+0xFFFFFFFF, 0x5FDFFFFF, 0x0FCF1FDC, 0x1FDC1FFF,
+0x00000000, 0x00004C40, 0x00000000, 0x00000000,
+0x00000007, 0x00000000, 0x00000000, 0x00000000,
+0x00000080, 0x000003FE, 0xFFFFFFFE, 0xFFFFFFFF,
+0x001FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x07FFFFFF,
+0xFFFFFFE0, 0x00001FFF, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+0xFFFFFFFF, 0x0000003F, 0x00000000, 0x00000000,
+0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+0xFFFFFFFF, 0x0000000F, 0x00000000, 0x00000000,
+0x00000000, 0x07FF6000, 0x87FFFFFE, 0x07FFFFFE,
+0x00000000, 0x00800000, 0xFF7FFFFF, 0xFF7FFFFF,
+0x00FFFFFF, 0x00000000, 0xFFFF0000, 0xFFFFFFFF,
+0xFFFFFFFF, 0xF80001FF, 0x00030003, 0x00000000,
+0xFFFFFFFF, 0xFFFFFFFF, 0x0000003F, 0x00000003,
+0xFFFFD7C0, 0xFFFFFFFB, 0x547F7FFF, 0x000FFFFD,
+0xFFFFDFFE, 0xFFFFFFFF, 0xDFFEFFFF, 0xFFFFFFFF,
+0xFFFF007B, 0xFFFFFFFF, 0xFFFF199F, 0x033FCFFF,
+0x00000000, 0xFFFE0000, 0x027FFFFF, 0xFFFFFFFE,
+0xFFFE007F, 0xBBFFFFFB, 0xFFFF0016, 0x000707FF,
+0x00000000, 0x07FFFFFE, 0x0007FFFF, 0xFFFF03FF,
+0xFFFFFFFF, 0x7CFFFFFF, 0xFFEF7FFF, 0x03FF3DFF,
+0xFFFFFFEE, 0xF3FFFFFF, 0xFF1E3FFF, 0x0000FFCF,
+0xFFF99FEE, 0xD3C5FDFF, 0xB080399F, 0x0003FFCF,
+0xFFF987E4, 0xD36DFDFF, 0x5E003987, 0x001FFFC0,
+0xFFFBAFEE, 0xF3EDFDFF, 0x00003BBF, 0x0000FFC1,
+0xFFF99FEE, 0xF3CDFDFF, 0xB0C0398F, 0x0000FFC3,
+0xD63DC7EC, 0xC3BFC718, 0x00803DC7, 0x0000FF80,
+0xFFFDDFEE, 0xC3EFFDFF, 0x00603DDF, 0x0000FFC3,
+0xFFFDDFEC, 0xC3EFFDFF, 0x40603DDF, 0x0000FFC3,
+0xFFFDDFEC, 0xC3FFFDFF, 0x00803DCF, 0x0000FFC3,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0xFFFFFFFE, 0x07FF7FFF, 0x03FF7FFF, 0x00000000,
+0xFEF02596, 0x3BFF6CAE, 0x03FF3F5F, 0x00000000,
+0x03000000, 0xC2A003FF, 0xFFFFFEFF, 0xFFFE03FF,
+0xFEBF0FDF, 0x02FE3FFF, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x00000000, 0x00000000,
+0x00000000, 0x00000000, 0x1FFF0000, 0x00000002,
+0x000000A0, 0x003EFFFE, 0xFFFFFFFE, 0xFFFFFFFF,
+0x661FFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0x77FFFFFF,
+};
+static const unsigned char nmstrtPages[] = {
+0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x00,
+0x00, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13,
+0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x15, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+static const unsigned char namePages[] = {
+0x19, 0x03, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x00,
+0x00, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
+0x10, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x13,
+0x26, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x27, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x17,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
--- /dev/null
+/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
+ * applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/* Table for the OSD_EBCDIC_DF04_1 encoding */
+
+/* 00 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 04 */ BT_OTHER, BT_S, BT_OTHER, BT_OTHER,
+/* 08 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_NONXML,
+/* 0c */ BT_NONXML, BT_CR, BT_NONXML, BT_NONXML,
+/* 10 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 14 */ BT_OTHER, BT_LF, BT_NONXML, BT_OTHER,
+/* 18 */ BT_NONXML, BT_NONXML, BT_OTHER, BT_OTHER,
+/* 1c */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 20 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 24 */ BT_OTHER, BT_OTHER, BT_NONXML, BT_NONXML,
+/* 28 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 2c */ BT_OTHER, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 30 */ BT_OTHER, BT_OTHER, BT_NONXML, BT_OTHER,
+/* 34 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_NONXML,
+/* 38 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* 3c */ BT_NONXML, BT_NONXML, BT_OTHER, BT_NONXML,
+/* 40 */ BT_S, BT_OTHER, BT_NMSTRT, BT_NMSTRT,
+/* 44 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 48 */ BT_NMSTRT, BT_NMSTRT, BT_OTHER, BT_NAME,
+/* 4c */ BT_LT, BT_LPAR, BT_PLUS, BT_VERBAR,
+/* 50 */ BT_AMP, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 54 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 58 */ BT_NMSTRT, BT_NMSTRT, BT_EXCL, BT_OTHER,
+/* 5c */ BT_AST, BT_RPAR, BT_SEMI, BT_OTHER,
+/* 60 */ BT_MINUS, BT_SOL, BT_NMSTRT, BT_NMSTRT,
+/* 64 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 68 */ BT_NMSTRT, BT_NMSTRT, BT_OTHER, BT_COMMA,
+/* 6c */ BT_PERCNT, BT_NMSTRT, BT_GT, BT_QUEST,
+/* 70 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 74 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 78 */ BT_NMSTRT, BT_OTHER, BT_COLON, BT_NUM,
+/* 7c */ BT_OTHER, BT_APOS, BT_EQUALS, BT_QUOT,
+/* 80 */ BT_NMSTRT, BT_HEX, BT_HEX, BT_HEX,
+/* 84 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
+/* 88 */ BT_NMSTRT, BT_NMSTRT, BT_OTHER, BT_OTHER,
+/* 8c */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
+/* 90 */ BT_OTHER, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 94 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 98 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* 9c */ BT_NMSTRT, BT_OTHER, BT_NMSTRT, BT_OTHER,
+/* a0 */ BT_NMSTRT, BT_OTHER, BT_NMSTRT, BT_NMSTRT,
+/* a4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* a8 */ BT_NMSTRT, BT_NMSTRT, BT_OTHER, BT_OTHER,
+/* ac */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_OTHER,
+/* b0 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_NAME,
+/* b4 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_OTHER,
+/* b8 */ BT_OTHER, BT_OTHER, BT_OTHER, BT_LSQB,
+/* bc */ BT_OTHER, BT_RSQB, BT_OTHER, BT_OTHER,
+/* c0 */ BT_NMSTRT, BT_HEX, BT_HEX, BT_HEX,
+/* c4 */ BT_HEX, BT_HEX, BT_HEX, BT_NMSTRT,
+/* c8 */ BT_NMSTRT, BT_NMSTRT, BT_OTHER, BT_NMSTRT,
+/* cc */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* d0 */ BT_OTHER, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* d4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* d8 */ BT_NMSTRT, BT_NMSTRT, BT_OTHER, BT_NMSTRT,
+/* dc */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* e0 */ BT_NMSTRT, BT_OTHER, BT_NMSTRT, BT_NMSTRT,
+/* e4 */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* e8 */ BT_NMSTRT, BT_NMSTRT, BT_OTHER, BT_NMSTRT,
+/* ec */ BT_NMSTRT, BT_NMSTRT, BT_NMSTRT, BT_NMSTRT,
+/* f0 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
+/* f4 */ BT_DIGIT, BT_DIGIT, BT_DIGIT, BT_DIGIT,
+/* f8 */ BT_DIGIT, BT_DIGIT, BT_OTHER, BT_OTHER,
+/* fc */ BT_NMSTRT, BT_OTHER, BT_NMSTRT, BT_OTHER,
--- /dev/null
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file COPYING for copying permission.
+*/
+
+
+/* 0x80 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x84 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x88 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x8C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x90 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x94 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x98 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0x9C */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xA0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xA4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xA8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xAC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xB0 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xB4 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xB8 */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xBC */ BT_TRAIL, BT_TRAIL, BT_TRAIL, BT_TRAIL,
+/* 0xC0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xC4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xC8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xCC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xD0 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xD4 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xD8 */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xDC */ BT_LEAD2, BT_LEAD2, BT_LEAD2, BT_LEAD2,
+/* 0xE0 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
+/* 0xE4 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
+/* 0xE8 */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
+/* 0xEC */ BT_LEAD3, BT_LEAD3, BT_LEAD3, BT_LEAD3,
+/* 0xF0 */ BT_LEAD4, BT_LEAD4, BT_LEAD4, BT_LEAD4,
+/* 0xF4 */ BT_LEAD4, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0xF8 */ BT_NONXML, BT_NONXML, BT_NONXML, BT_NONXML,
+/* 0xFC */ BT_NONXML, BT_NONXML, BT_MALFORM, BT_MALFORM,
--- /dev/null
+/*================================================================
+** Copyright 2000, Clark Cooper
+** All rights reserved.
+**
+** This is free software. You are permitted to copy, distribute, or modify
+** it under the terms of the MIT/X license (contained in the COPYING file
+** with this distribution.)
+**
+**
+*/
+
+#ifndef WINCONFIG_H
+#define WINCONFIG_H
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+
+#include <memory.h>
+#include <string.h>
+
+#define XML_NS 1
+#define XML_DTD 1
+#define XML_BYTE_ORDER 12
+#define XML_CONTEXT_BYTES 1024
+
+#endif /* ndef WINCONFIG_H */
--- /dev/null
+# Microsoft Developer Studio Project File - Name="xml" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=xml - 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 "xml.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 "xml.mak" CFG="xml - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "xml - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "xml - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "xml - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "LibR"
+# PROP BASE Intermediate_Dir "LibR"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "LibR"
+# PROP Intermediate_Dir "LibR"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /FD /c
+# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "." /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D VERSION=\"expat_1.95.1\" /D XML_MAJOR_VERSION=1 /D XML_MINOR_VERSION=95 /D XML_MICRO_VERSION=1 /Fd"LibR\xml_src" /FD /c
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ELSEIF "$(CFG)" == "xml - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "LibD"
+# PROP BASE Intermediate_Dir "LibD"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "LibD"
+# PROP Intermediate_Dir "LibD"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /FD /c
+# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "." /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D VERSION=\"expat_1.95.1\" /D XML_MAJOR_VERSION=1 /D XML_MINOR_VERSION=95 /D XML_MICRO_VERSION=1 /Fd"LibD\xml_src" /FD /c
+# ADD BASE RSC /l 0x409
+# ADD RSC /l 0x409
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo
+
+!ENDIF
+
+# Begin Target
+
+# Name "xml - Win32 Release"
+# Name "xml - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\xmlparse.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\xmlrole.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\xmltok.c
+# End Source File
+# Begin Source File
+
+SOURCE=xmltok_impl.c
+# PROP Exclude_From_Build 1
+# End Source File
+# Begin Source File
+
+SOURCE=xmltok_ns.c
+# PROP Exclude_From_Build 1
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\ascii.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\asciitab.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\config.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\expat.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\iasciitab.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\latin1tab.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\nametab.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\utf8tab.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\xmlrole.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\xmltok.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\xmltok_impl.h
+# End Source File
+# End Group
+# Begin Group "Generated Header Files"
+
+# PROP Default_Filter ""
+# Begin Source File
+
+SOURCE=.\expat.h.in
+
+!IF "$(CFG)" == "xml - Win32 Release"
+
+# Begin Custom Build - Creating expat.h from expat.h.in
+InputPath=.\expat.h.in
+
+".\expat.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ type .\expat.h.in > .\expat.h
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "xml - Win32 Debug"
+
+# Begin Custom Build - Creating expat.h from expat.h.in
+InputPath=.\expat.h.in
+
+".\expat.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ type .\expat.h.in > .\expat.h
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\winconfig.h
+
+!IF "$(CFG)" == "xml - Win32 Release"
+
+# Begin Custom Build - Creating config.h from winconfig.h
+InputPath=.\winconfig.h
+
+".\config.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ type .\winconfig.h > .\config.h
+
+# End Custom Build
+
+!ELSEIF "$(CFG)" == "xml - Win32 Debug"
+
+# Begin Custom Build - Creating config.h from winconfig.h
+InputPath=.\winconfig.h
+
+".\config.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+ type .\winconfig.h > .\config.h
+
+# End Custom Build
+
+!ENDIF
+
+# End Source File
+# End Group
+# Begin Source File
+
+SOURCE=.\ReadMe.txt
+# End Source File
+# End Target
+# End Project
--- /dev/null
+/*
+Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
+See the file COPYING for copying permission.
+*/
+
+static char RCSId[]
+ = "$Header: /home/cvs/apr-util/xml/expat/lib/xmlparse.c,v 1.4 2001/08/30 05:44:18 wrowe Exp $";
+
+#ifdef COMPILED_FROM_DSP
+# include "winconfig.h"
+# define XMLPARSEAPI __declspec(dllexport)
+# include "expat.h"
+# undef XMLPARSEAPI
+#else
+#include <config.h>
+
+#ifdef HAVE_STRING_H
+# include <string.h>
+#endif
+
+#ifndef __CYGWIN__
+#ifdef __declspec
+# define XMLPARSEAPI __declspec(dllexport)
+#endif
+#endif
+
+#include "expat.h"
+
+#ifdef __declspec
+# undef XMLPARSEAPI
+#endif
+#endif /* ndef COMPILED_FROM_DSP */
+
+#include <stddef.h>
+
+#ifdef XML_UNICODE
+#define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX
+#define XmlConvert XmlUtf16Convert
+#define XmlGetInternalEncoding XmlGetUtf16InternalEncoding
+#define XmlGetInternalEncodingNS XmlGetUtf16InternalEncodingNS
+#define XmlEncode XmlUtf16Encode
+#define MUST_CONVERT(enc, s) (!(enc)->isUtf16 || (((unsigned long)s) & 1))
+typedef unsigned short ICHAR;
+#else
+#define XML_ENCODE_MAX XML_UTF8_ENCODE_MAX
+#define XmlConvert XmlUtf8Convert
+#define XmlGetInternalEncoding XmlGetUtf8InternalEncoding
+#define XmlGetInternalEncodingNS XmlGetUtf8InternalEncodingNS
+#define XmlEncode XmlUtf8Encode
+#define MUST_CONVERT(enc, s) (!(enc)->isUtf8)
+typedef char ICHAR;
+#endif
+
+
+#ifndef XML_NS
+
+#define XmlInitEncodingNS XmlInitEncoding
+#define XmlInitUnknownEncodingNS XmlInitUnknownEncoding
+#undef XmlGetInternalEncodingNS
+#define XmlGetInternalEncodingNS XmlGetInternalEncoding
+#define XmlParseXmlDeclNS XmlParseXmlDecl
+
+#endif
+
+#ifdef XML_UNICODE_WCHAR_T
+#define XML_T(x) L ## x
+#else
+#define XML_T(x) x
+#endif
+
+/* Round up n to be a multiple of sz, where sz is a power of 2. */
+#define ROUND_UP(n, sz) (((n) + ((sz) - 1)) & ~((sz) - 1))
+
+#include "xmltok.h"
+#include "xmlrole.h"
+
+typedef const XML_Char *KEY;
+
+typedef struct {
+ KEY name;
+} NAMED;
+
+typedef struct {
+ NAMED **v;
+ size_t size;
+ size_t used;
+ size_t usedLim;
+ XML_Memory_Handling_Suite *mem;
+} HASH_TABLE;
+
+typedef struct {
+ NAMED **p;
+ NAMED **end;
+} HASH_TABLE_ITER;
+
+#define INIT_TAG_BUF_SIZE 32 /* must be a multiple of sizeof(XML_Char) */
+#define INIT_DATA_BUF_SIZE 1024
+#define INIT_ATTS_SIZE 16
+#define INIT_BLOCK_SIZE 1024
+#define INIT_BUFFER_SIZE 1024
+
+#define EXPAND_SPARE 24
+
+typedef struct binding {
+ struct prefix *prefix;
+ struct binding *nextTagBinding;
+ struct binding *prevPrefixBinding;
+ const struct attribute_id *attId;
+ XML_Char *uri;
+ int uriLen;
+ int uriAlloc;
+} BINDING;
+
+typedef struct prefix {
+ const XML_Char *name;
+ BINDING *binding;
+} PREFIX;
+
+typedef struct {
+ const XML_Char *str;
+ const XML_Char *localPart;
+ int uriLen;
+} TAG_NAME;
+
+typedef struct tag {
+ struct tag *parent;
+ const char *rawName;
+ int rawNameLength;
+ TAG_NAME name;
+ char *buf;
+ char *bufEnd;
+ BINDING *bindings;
+} TAG;
+
+typedef struct {
+ const XML_Char *name;
+ const XML_Char *textPtr;
+ int textLen;
+ const XML_Char *systemId;
+ const XML_Char *base;
+ const XML_Char *publicId;
+ const XML_Char *notation;
+ char open;
+ char is_param;
+} ENTITY;
+
+typedef struct {
+ enum XML_Content_Type type;
+ enum XML_Content_Quant quant;
+ const XML_Char * name;
+ int firstchild;
+ int lastchild;
+ int childcnt;
+ int nextsib;
+} CONTENT_SCAFFOLD;
+
+typedef struct block {
+ struct block *next;
+ int size;
+ XML_Char s[1];
+} BLOCK;
+
+typedef struct {
+ BLOCK *blocks;
+ BLOCK *freeBlocks;
+ const XML_Char *end;
+ XML_Char *ptr;
+ XML_Char *start;
+ XML_Memory_Handling_Suite *mem;
+} STRING_POOL;
+
+/* The XML_Char before the name is used to determine whether
+an attribute has been specified. */
+typedef struct attribute_id {
+ XML_Char *name;
+ PREFIX *prefix;
+ char maybeTokenized;
+ char xmlns;
+} ATTRIBUTE_ID;
+
+typedef struct {
+ const ATTRIBUTE_ID *id;
+ char isCdata;
+ const XML_Char *value;
+} DEFAULT_ATTRIBUTE;
+
+typedef struct {
+ const XML_Char *name;
+ PREFIX *prefix;
+ const ATTRIBUTE_ID *idAtt;
+ int nDefaultAtts;
+ int allocDefaultAtts;
+ DEFAULT_ATTRIBUTE *defaultAtts;
+} ELEMENT_TYPE;
+
+typedef struct {
+ HASH_TABLE generalEntities;
+ HASH_TABLE elementTypes;
+ HASH_TABLE attributeIds;
+ HASH_TABLE prefixes;
+ STRING_POOL pool;
+ int complete;
+ int standalone;
+#ifdef XML_DTD
+ HASH_TABLE paramEntities;
+#endif /* XML_DTD */
+ PREFIX defaultPrefix;
+ /* === scaffolding for building content model === */
+ int in_eldecl;
+ CONTENT_SCAFFOLD *scaffold;
+ unsigned contentStringLen;
+ unsigned scaffSize;
+ unsigned scaffCount;
+ int scaffLevel;
+ int *scaffIndex;
+} DTD;
+
+typedef struct open_internal_entity {
+ const char *internalEventPtr;
+ const char *internalEventEndPtr;
+ struct open_internal_entity *next;
+ ENTITY *entity;
+} OPEN_INTERNAL_ENTITY;
+
+typedef enum XML_Error Processor(XML_Parser parser,
+ const char *start,
+ const char *end,
+ const char **endPtr);
+
+static Processor prologProcessor;
+static Processor prologInitProcessor;
+static Processor contentProcessor;
+static Processor cdataSectionProcessor;
+#ifdef XML_DTD
+static Processor ignoreSectionProcessor;
+#endif /* XML_DTD */
+static Processor epilogProcessor;
+static Processor errorProcessor;
+static Processor externalEntityInitProcessor;
+static Processor externalEntityInitProcessor2;
+static Processor externalEntityInitProcessor3;
+static Processor externalEntityContentProcessor;
+
+static enum XML_Error
+handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName);
+static enum XML_Error
+processXmlDecl(XML_Parser parser, int isGeneralTextEntity, const char *, const char *);
+static enum XML_Error
+initializeEncoding(XML_Parser parser);
+static enum XML_Error
+doProlog(XML_Parser parser, const ENCODING *enc, const char *s,
+ const char *end, int tok, const char *next, const char **nextPtr);
+static enum XML_Error
+processInternalParamEntity(XML_Parser parser, ENTITY *entity);
+static enum XML_Error
+doContent(XML_Parser parser, int startTagLevel, const ENCODING *enc,
+ const char *start, const char *end, const char **endPtr);
+static enum XML_Error
+doCdataSection(XML_Parser parser, const ENCODING *, const char **startPtr, const char *end, const char **nextPtr);
+#ifdef XML_DTD
+static enum XML_Error
+doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr, const char *end, const char **nextPtr);
+#endif /* XML_DTD */
+static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *, const char *s,
+ TAG_NAME *tagNamePtr, BINDING **bindingsPtr);
+static
+int addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, const XML_Char *uri, BINDING **bindingsPtr);
+
+static int
+defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *,
+ int isCdata, int isId, const XML_Char *dfltValue,
+ XML_Parser parser);
+
+static enum XML_Error
+storeAttributeValue(XML_Parser parser, const ENCODING *, int isCdata, const char *, const char *,
+ STRING_POOL *);
+static enum XML_Error
+appendAttributeValue(XML_Parser parser, const ENCODING *, int isCdata, const char *, const char *,
+ STRING_POOL *);
+static ATTRIBUTE_ID *
+getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
+static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *);
+static enum XML_Error
+storeEntityValue(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
+static int
+reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
+static int
+reportComment(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
+static void
+reportDefault(XML_Parser parser, const ENCODING *enc, const char *start, const char *end);
+
+static const XML_Char *getContext(XML_Parser parser);
+static int setContext(XML_Parser parser, const XML_Char *context);
+static void normalizePublicId(XML_Char *s);
+static int dtdInit(DTD *, XML_Parser parser);
+
+static void dtdDestroy(DTD *, XML_Parser parser);
+
+static int dtdCopy(DTD *newDtd, const DTD *oldDtd, XML_Parser parser);
+
+static int copyEntityTable(HASH_TABLE *, STRING_POOL *, const HASH_TABLE *,
+ XML_Parser parser);
+
+#ifdef XML_DTD
+static void dtdSwap(DTD *, DTD *);
+#endif /* XML_DTD */
+
+static NAMED *lookup(HASH_TABLE *table, KEY name, size_t createSize);
+
+static void hashTableInit(HASH_TABLE *, XML_Memory_Handling_Suite *ms);
+
+static void hashTableDestroy(HASH_TABLE *);
+static void hashTableIterInit(HASH_TABLE_ITER *, const HASH_TABLE *);
+static NAMED *hashTableIterNext(HASH_TABLE_ITER *);
+static void poolInit(STRING_POOL *, XML_Memory_Handling_Suite *ms);
+static void poolClear(STRING_POOL *);
+static void poolDestroy(STRING_POOL *);
+static XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc,
+ const char *ptr, const char *end);
+static XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc,
+ const char *ptr, const char *end);
+
+static int poolGrow(STRING_POOL *pool);
+
+static int nextScaffoldPart(XML_Parser parser);
+static XML_Content *build_model(XML_Parser parser);
+
+static const XML_Char *poolCopyString(STRING_POOL *pool, const XML_Char *s);
+static const XML_Char *poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n);
+static const XML_Char *poolAppendString(STRING_POOL *pool, const XML_Char *s);
+static ELEMENT_TYPE * getElementType(XML_Parser Paraser,
+ const ENCODING *enc,
+ const char *ptr,
+ const char *end);
+
+#define poolStart(pool) ((pool)->start)
+#define poolEnd(pool) ((pool)->ptr)
+#define poolLength(pool) ((pool)->ptr - (pool)->start)
+#define poolChop(pool) ((void)--(pool->ptr))
+#define poolLastChar(pool) (((pool)->ptr)[-1])
+#define poolDiscard(pool) ((pool)->ptr = (pool)->start)
+#define poolFinish(pool) ((pool)->start = (pool)->ptr)
+#define poolAppendChar(pool, c) \
+ (((pool)->ptr == (pool)->end && !poolGrow(pool)) \
+ ? 0 \
+ : ((*((pool)->ptr)++ = c), 1))
+
+typedef struct {
+ /* The first member must be userData so that the XML_GetUserData macro works. */
+ void *m_userData;
+ void *m_handlerArg;
+ char *m_buffer;
+ XML_Memory_Handling_Suite m_mem;
+ /* first character to be parsed */
+ const char *m_bufferPtr;
+ /* past last character to be parsed */
+ char *m_bufferEnd;
+ /* allocated end of buffer */
+ const char *m_bufferLim;
+ long m_parseEndByteIndex;
+ const char *m_parseEndPtr;
+ XML_Char *m_dataBuf;
+ XML_Char *m_dataBufEnd;
+ XML_StartElementHandler m_startElementHandler;
+ XML_EndElementHandler m_endElementHandler;
+ XML_CharacterDataHandler m_characterDataHandler;
+ XML_ProcessingInstructionHandler m_processingInstructionHandler;
+ XML_CommentHandler m_commentHandler;
+ XML_StartCdataSectionHandler m_startCdataSectionHandler;
+ XML_EndCdataSectionHandler m_endCdataSectionHandler;
+ XML_DefaultHandler m_defaultHandler;
+ XML_StartDoctypeDeclHandler m_startDoctypeDeclHandler;
+ XML_EndDoctypeDeclHandler m_endDoctypeDeclHandler;
+ XML_UnparsedEntityDeclHandler m_unparsedEntityDeclHandler;
+ XML_NotationDeclHandler m_notationDeclHandler;
+ XML_StartNamespaceDeclHandler m_startNamespaceDeclHandler;
+ XML_EndNamespaceDeclHandler m_endNamespaceDeclHandler;
+ XML_NotStandaloneHandler m_notStandaloneHandler;
+ XML_ExternalEntityRefHandler m_externalEntityRefHandler;
+ void *m_externalEntityRefHandlerArg;
+ XML_UnknownEncodingHandler m_unknownEncodingHandler;
+ XML_ElementDeclHandler m_elementDeclHandler;
+ XML_AttlistDeclHandler m_attlistDeclHandler;
+ XML_EntityDeclHandler m_entityDeclHandler;
+ XML_XmlDeclHandler m_xmlDeclHandler;
+ const ENCODING *m_encoding;
+ INIT_ENCODING m_initEncoding;
+ const ENCODING *m_internalEncoding;
+ const XML_Char *m_protocolEncodingName;
+ int m_ns;
+ int m_ns_triplets;
+ void *m_unknownEncodingMem;
+ void *m_unknownEncodingData;
+ void *m_unknownEncodingHandlerData;
+ void (*m_unknownEncodingRelease)(void *);
+ PROLOG_STATE m_prologState;
+ Processor *m_processor;
+ enum XML_Error m_errorCode;
+ const char *m_eventPtr;
+ const char *m_eventEndPtr;
+ const char *m_positionPtr;
+ OPEN_INTERNAL_ENTITY *m_openInternalEntities;
+ int m_defaultExpandInternalEntities;
+ int m_tagLevel;
+ ENTITY *m_declEntity;
+ const XML_Char *m_doctypeName;
+ const XML_Char *m_doctypeSysid;
+ const XML_Char *m_doctypePubid;
+ const XML_Char *m_declAttributeType;
+ const XML_Char *m_declNotationName;
+ const XML_Char *m_declNotationPublicId;
+ ELEMENT_TYPE *m_declElementType;
+ ATTRIBUTE_ID *m_declAttributeId;
+ char m_declAttributeIsCdata;
+ char m_declAttributeIsId;
+ DTD m_dtd;
+ const XML_Char *m_curBase;
+ TAG *m_tagStack;
+ TAG *m_freeTagList;
+ BINDING *m_inheritedBindings;
+ BINDING *m_freeBindingList;
+ int m_attsSize;
+ int m_nSpecifiedAtts;
+ int m_idAttIndex;
+ ATTRIBUTE *m_atts;
+ POSITION m_position;
+ STRING_POOL m_tempPool;
+ STRING_POOL m_temp2Pool;
+ char *m_groupConnector;
+ unsigned m_groupSize;
+ int m_hadExternalDoctype;
+ XML_Char m_namespaceSeparator;
+#ifdef XML_DTD
+ enum XML_ParamEntityParsing m_paramEntityParsing;
+ XML_Parser m_parentParser;
+#endif
+} Parser;
+
+#define MALLOC(s) (((Parser *)parser)->m_mem.malloc_fcn((s)))
+#define REALLOC(p,s) (((Parser *)parser)->m_mem.realloc_fcn((p),(s)))
+#define FREE(p) (((Parser *)parser)->m_mem.free_fcn((p)))
+
+#define userData (((Parser *)parser)->m_userData)
+#define handlerArg (((Parser *)parser)->m_handlerArg)
+#define startElementHandler (((Parser *)parser)->m_startElementHandler)
+#define endElementHandler (((Parser *)parser)->m_endElementHandler)
+#define characterDataHandler (((Parser *)parser)->m_characterDataHandler)
+#define processingInstructionHandler (((Parser *)parser)->m_processingInstructionHandler)
+#define commentHandler (((Parser *)parser)->m_commentHandler)
+#define startCdataSectionHandler (((Parser *)parser)->m_startCdataSectionHandler)
+#define endCdataSectionHandler (((Parser *)parser)->m_endCdataSectionHandler)
+#define defaultHandler (((Parser *)parser)->m_defaultHandler)
+#define startDoctypeDeclHandler (((Parser *)parser)->m_startDoctypeDeclHandler)
+#define endDoctypeDeclHandler (((Parser *)parser)->m_endDoctypeDeclHandler)
+#define unparsedEntityDeclHandler (((Parser *)parser)->m_unparsedEntityDeclHandler)
+#define notationDeclHandler (((Parser *)parser)->m_notationDeclHandler)
+#define startNamespaceDeclHandler (((Parser *)parser)->m_startNamespaceDeclHandler)
+#define endNamespaceDeclHandler (((Parser *)parser)->m_endNamespaceDeclHandler)
+#define notStandaloneHandler (((Parser *)parser)->m_notStandaloneHandler)
+#define externalEntityRefHandler (((Parser *)parser)->m_externalEntityRefHandler)
+#define externalEntityRefHandlerArg (((Parser *)parser)->m_externalEntityRefHandlerArg)
+#define unknownEncodingHandler (((Parser *)parser)->m_unknownEncodingHandler)
+#define elementDeclHandler (((Parser *)parser)->m_elementDeclHandler)
+#define attlistDeclHandler (((Parser *)parser)->m_attlistDeclHandler)
+#define entityDeclHandler (((Parser *)parser)->m_entityDeclHandler)
+#define xmlDeclHandler (((Parser *)parser)->m_xmlDeclHandler)
+#define encoding (((Parser *)parser)->m_encoding)
+#define initEncoding (((Parser *)parser)->m_initEncoding)
+#define internalEncoding (((Parser *)parser)->m_internalEncoding)
+#define unknownEncodingMem (((Parser *)parser)->m_unknownEncodingMem)
+#define unknownEncodingData (((Parser *)parser)->m_unknownEncodingData)
+#define unknownEncodingHandlerData \
+ (((Parser *)parser)->m_unknownEncodingHandlerData)
+#define unknownEncodingRelease (((Parser *)parser)->m_unknownEncodingRelease)
+#define protocolEncodingName (((Parser *)parser)->m_protocolEncodingName)
+#define ns (((Parser *)parser)->m_ns)
+#define ns_triplets (((Parser *)parser)->m_ns_triplets)
+#define prologState (((Parser *)parser)->m_prologState)
+#define processor (((Parser *)parser)->m_processor)
+#define errorCode (((Parser *)parser)->m_errorCode)
+#define eventPtr (((Parser *)parser)->m_eventPtr)
+#define eventEndPtr (((Parser *)parser)->m_eventEndPtr)
+#define positionPtr (((Parser *)parser)->m_positionPtr)
+#define position (((Parser *)parser)->m_position)
+#define openInternalEntities (((Parser *)parser)->m_openInternalEntities)
+#define defaultExpandInternalEntities (((Parser *)parser)->m_defaultExpandInternalEntities)
+#define tagLevel (((Parser *)parser)->m_tagLevel)
+#define buffer (((Parser *)parser)->m_buffer)
+#define bufferPtr (((Parser *)parser)->m_bufferPtr)
+#define bufferEnd (((Parser *)parser)->m_bufferEnd)
+#define parseEndByteIndex (((Parser *)parser)->m_parseEndByteIndex)
+#define parseEndPtr (((Parser *)parser)->m_parseEndPtr)
+#define bufferLim (((Parser *)parser)->m_bufferLim)
+#define dataBuf (((Parser *)parser)->m_dataBuf)
+#define dataBufEnd (((Parser *)parser)->m_dataBufEnd)
+#define dtd (((Parser *)parser)->m_dtd)
+#define curBase (((Parser *)parser)->m_curBase)
+#define declEntity (((Parser *)parser)->m_declEntity)
+#define doctypeName (((Parser *)parser)->m_doctypeName)
+#define doctypeSysid (((Parser *)parser)->m_doctypeSysid)
+#define doctypePubid (((Parser *)parser)->m_doctypePubid)
+#define declAttributeType (((Parser *)parser)->m_declAttributeType)
+#define declNotationName (((Parser *)parser)->m_declNotationName)
+#define declNotationPublicId (((Parser *)parser)->m_declNotationPublicId)
+#define declElementType (((Parser *)parser)->m_declElementType)
+#define declAttributeId (((Parser *)parser)->m_declAttributeId)
+#define declAttributeIsCdata (((Parser *)parser)->m_declAttributeIsCdata)
+#define declAttributeIsId (((Parser *)parser)->m_declAttributeIsId)
+#define freeTagList (((Parser *)parser)->m_freeTagList)
+#define freeBindingList (((Parser *)parser)->m_freeBindingList)
+#define inheritedBindings (((Parser *)parser)->m_inheritedBindings)
+#define tagStack (((Parser *)parser)->m_tagStack)
+#define atts (((Parser *)parser)->m_atts)
+#define attsSize (((Parser *)parser)->m_attsSize)
+#define nSpecifiedAtts (((Parser *)parser)->m_nSpecifiedAtts)
+#define idAttIndex (((Parser *)parser)->m_idAttIndex)
+#define tempPool (((Parser *)parser)->m_tempPool)
+#define temp2Pool (((Parser *)parser)->m_temp2Pool)
+#define groupConnector (((Parser *)parser)->m_groupConnector)
+#define groupSize (((Parser *)parser)->m_groupSize)
+#define hadExternalDoctype (((Parser *)parser)->m_hadExternalDoctype)
+#define namespaceSeparator (((Parser *)parser)->m_namespaceSeparator)
+#ifdef XML_DTD
+#define parentParser (((Parser *)parser)->m_parentParser)
+#define paramEntityParsing (((Parser *)parser)->m_paramEntityParsing)
+#endif /* XML_DTD */
+
+#ifdef COMPILED_FROM_DSP
+BOOL WINAPI DllMain(HINSTANCE h, DWORD r, LPVOID p) {
+ return TRUE;
+}
+#endif /* def COMPILED_FROM_DSP */
+
+#ifdef _MSC_VER
+#ifdef _DEBUG
+Parser *asParser(XML_Parser parser)
+{
+ return parser;
+}
+#endif
+#endif
+
+XML_Parser XML_ParserCreate(const XML_Char *encodingName)
+{
+ return XML_ParserCreate_MM(encodingName, NULL, NULL);
+}
+
+XML_Parser XML_ParserCreateNS(const XML_Char *encodingName, XML_Char nsSep)
+{
+ XML_Char tmp[2];
+ *tmp = nsSep;
+ return XML_ParserCreate_MM(encodingName, NULL, tmp);
+}
+
+XML_Parser
+XML_ParserCreate_MM(const XML_Char *encodingName,
+ const XML_Memory_Handling_Suite *memsuite,
+ const XML_Char *nameSep) {
+
+ XML_Parser parser;
+ static
+ const XML_Char implicitContext[] = {
+ XML_T('x'), XML_T('m'), XML_T('l'), XML_T('='),
+ XML_T('h'), XML_T('t'), XML_T('t'), XML_T('p'), XML_T(':'),
+ XML_T('/'), XML_T('/'), XML_T('w'), XML_T('w'), XML_T('w'),
+ XML_T('.'), XML_T('w'), XML_T('3'),
+ XML_T('.'), XML_T('o'), XML_T('r'), XML_T('g'),
+ XML_T('/'), XML_T('X'), XML_T('M'), XML_T('L'),
+ XML_T('/'), XML_T('1'), XML_T('9'), XML_T('9'), XML_T('8'),
+ XML_T('/'), XML_T('n'), XML_T('a'), XML_T('m'), XML_T('e'),
+ XML_T('s'), XML_T('p'), XML_T('a'), XML_T('c'), XML_T('e'),
+ XML_T('\0')
+ };
+
+
+ if (memsuite) {
+ XML_Memory_Handling_Suite *mtemp;
+ parser = memsuite->malloc_fcn(sizeof(Parser));
+ mtemp = &(((Parser *) parser)->m_mem);
+ mtemp->malloc_fcn = memsuite->malloc_fcn;
+ mtemp->realloc_fcn = memsuite->realloc_fcn;
+ mtemp->free_fcn = memsuite->free_fcn;
+ }
+ else {
+ XML_Memory_Handling_Suite *mtemp;
+ parser = malloc(sizeof(Parser));
+ mtemp = &(((Parser *) parser)->m_mem);
+ mtemp->malloc_fcn = malloc;
+ mtemp->realloc_fcn = realloc;
+ mtemp->free_fcn = free;
+ }
+
+ if (!parser)
+ return parser;
+ processor = prologInitProcessor;
+ XmlPrologStateInit(&prologState);
+ userData = 0;
+ handlerArg = 0;
+ startElementHandler = 0;
+ endElementHandler = 0;
+ characterDataHandler = 0;
+ processingInstructionHandler = 0;
+ commentHandler = 0;
+ startCdataSectionHandler = 0;
+ endCdataSectionHandler = 0;
+ defaultHandler = 0;
+ startDoctypeDeclHandler = 0;
+ endDoctypeDeclHandler = 0;
+ unparsedEntityDeclHandler = 0;
+ notationDeclHandler = 0;
+ startNamespaceDeclHandler = 0;
+ endNamespaceDeclHandler = 0;
+ notStandaloneHandler = 0;
+ externalEntityRefHandler = 0;
+ externalEntityRefHandlerArg = parser;
+ unknownEncodingHandler = 0;
+ elementDeclHandler = 0;
+ attlistDeclHandler = 0;
+ entityDeclHandler = 0;
+ xmlDeclHandler = 0;
+ buffer = 0;
+ bufferPtr = 0;
+ bufferEnd = 0;
+ parseEndByteIndex = 0;
+ parseEndPtr = 0;
+ bufferLim = 0;
+ declElementType = 0;
+ declAttributeId = 0;
+ declEntity = 0;
+ doctypeName = 0;
+ doctypeSysid = 0;
+ doctypePubid = 0;
+ declAttributeType = 0;
+ declNotationName = 0;
+ declNotationPublicId = 0;
+ memset(&position, 0, sizeof(POSITION));
+ errorCode = XML_ERROR_NONE;
+ eventPtr = 0;
+ eventEndPtr = 0;
+ positionPtr = 0;
+ openInternalEntities = 0;
+ tagLevel = 0;
+ tagStack = 0;
+ freeTagList = 0;
+ freeBindingList = 0;
+ inheritedBindings = 0;
+ attsSize = INIT_ATTS_SIZE;
+ atts = MALLOC(attsSize * sizeof(ATTRIBUTE));
+ nSpecifiedAtts = 0;
+ dataBuf = MALLOC(INIT_DATA_BUF_SIZE * sizeof(XML_Char));
+ groupSize = 0;
+ groupConnector = 0;
+ hadExternalDoctype = 0;
+ unknownEncodingMem = 0;
+ unknownEncodingRelease = 0;
+ unknownEncodingData = 0;
+ unknownEncodingHandlerData = 0;
+ namespaceSeparator = '!';
+#ifdef XML_DTD
+ parentParser = 0;
+ paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
+#endif
+ ns = 0;
+ ns_triplets = 0;
+ poolInit(&tempPool, &(((Parser *) parser)->m_mem));
+ poolInit(&temp2Pool, &(((Parser *) parser)->m_mem));
+ protocolEncodingName = encodingName ? poolCopyString(&tempPool, encodingName) : 0;
+ curBase = 0;
+ if (!dtdInit(&dtd, parser) || !atts || !dataBuf
+ || (encodingName && !protocolEncodingName)) {
+ XML_ParserFree(parser);
+ return 0;
+ }
+ dataBufEnd = dataBuf + INIT_DATA_BUF_SIZE;
+
+ if (nameSep) {
+ XmlInitEncodingNS(&initEncoding, &encoding, 0);
+ ns = 1;
+ internalEncoding = XmlGetInternalEncodingNS();
+ namespaceSeparator = *nameSep;
+
+ if (! setContext(parser, implicitContext)) {
+ XML_ParserFree(parser);
+ return 0;
+ }
+ }
+ else {
+ XmlInitEncoding(&initEncoding, &encoding, 0);
+ internalEncoding = XmlGetInternalEncoding();
+ }
+
+ return parser;
+} /* End XML_ParserCreate_MM */
+
+int XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName)
+{
+ if (!encodingName)
+ protocolEncodingName = 0;
+ else {
+ protocolEncodingName = poolCopyString(&tempPool, encodingName);
+ if (!protocolEncodingName)
+ return 0;
+ }
+ return 1;
+}
+
+XML_Parser XML_ExternalEntityParserCreate(XML_Parser oldParser,
+ const XML_Char *context,
+ const XML_Char *encodingName)
+{
+ XML_Parser parser = oldParser;
+ DTD *oldDtd = &dtd;
+ XML_StartElementHandler oldStartElementHandler = startElementHandler;
+ XML_EndElementHandler oldEndElementHandler = endElementHandler;
+ XML_CharacterDataHandler oldCharacterDataHandler = characterDataHandler;
+ XML_ProcessingInstructionHandler oldProcessingInstructionHandler = processingInstructionHandler;
+ XML_CommentHandler oldCommentHandler = commentHandler;
+ XML_StartCdataSectionHandler oldStartCdataSectionHandler = startCdataSectionHandler;
+ XML_EndCdataSectionHandler oldEndCdataSectionHandler = endCdataSectionHandler;
+ XML_DefaultHandler oldDefaultHandler = defaultHandler;
+ XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler = unparsedEntityDeclHandler;
+ XML_NotationDeclHandler oldNotationDeclHandler = notationDeclHandler;
+ XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler = startNamespaceDeclHandler;
+ XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler = endNamespaceDeclHandler;
+ XML_NotStandaloneHandler oldNotStandaloneHandler = notStandaloneHandler;
+ XML_ExternalEntityRefHandler oldExternalEntityRefHandler = externalEntityRefHandler;
+ XML_UnknownEncodingHandler oldUnknownEncodingHandler = unknownEncodingHandler;
+ XML_ElementDeclHandler oldElementDeclHandler = elementDeclHandler;
+ XML_AttlistDeclHandler oldAttlistDeclHandler = attlistDeclHandler;
+ XML_EntityDeclHandler oldEntityDeclHandler = entityDeclHandler;
+ XML_XmlDeclHandler oldXmlDeclHandler = xmlDeclHandler;
+ ELEMENT_TYPE * oldDeclElementType = declElementType;
+
+ void *oldUserData = userData;
+ void *oldHandlerArg = handlerArg;
+ int oldDefaultExpandInternalEntities = defaultExpandInternalEntities;
+ void *oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg;
+#ifdef XML_DTD
+ int oldParamEntityParsing = paramEntityParsing;
+#endif
+ int oldns_triplets = ns_triplets;
+
+ if (ns) {
+ XML_Char tmp[2];
+
+ *tmp = namespaceSeparator;
+ parser = XML_ParserCreate_MM(encodingName, &((Parser *)parser)->m_mem,
+ tmp);
+ }
+ else {
+ parser = XML_ParserCreate_MM(encodingName, &((Parser *)parser)->m_mem,
+ NULL);
+ }
+
+ if (!parser)
+ return 0;
+
+ startElementHandler = oldStartElementHandler;
+ endElementHandler = oldEndElementHandler;
+ characterDataHandler = oldCharacterDataHandler;
+ processingInstructionHandler = oldProcessingInstructionHandler;
+ commentHandler = oldCommentHandler;
+ startCdataSectionHandler = oldStartCdataSectionHandler;
+ endCdataSectionHandler = oldEndCdataSectionHandler;
+ defaultHandler = oldDefaultHandler;
+ unparsedEntityDeclHandler = oldUnparsedEntityDeclHandler;
+ notationDeclHandler = oldNotationDeclHandler;
+ startNamespaceDeclHandler = oldStartNamespaceDeclHandler;
+ endNamespaceDeclHandler = oldEndNamespaceDeclHandler;
+ notStandaloneHandler = oldNotStandaloneHandler;
+ externalEntityRefHandler = oldExternalEntityRefHandler;
+ unknownEncodingHandler = oldUnknownEncodingHandler;
+ elementDeclHandler = oldElementDeclHandler;
+ attlistDeclHandler = oldAttlistDeclHandler;
+ entityDeclHandler = oldEntityDeclHandler;
+ xmlDeclHandler = oldXmlDeclHandler;
+ declElementType = oldDeclElementType;
+ userData = oldUserData;
+ if (oldUserData == oldHandlerArg)
+ handlerArg = userData;
+ else
+ handlerArg = parser;
+ if (oldExternalEntityRefHandlerArg != oldParser)
+ externalEntityRefHandlerArg = oldExternalEntityRefHandlerArg;
+ defaultExpandInternalEntities = oldDefaultExpandInternalEntities;
+ ns_triplets = oldns_triplets;
+#ifdef XML_DTD
+ paramEntityParsing = oldParamEntityParsing;
+ if (context) {
+#endif /* XML_DTD */
+ if (!dtdCopy(&dtd, oldDtd, parser) || !setContext(parser, context)) {
+ XML_ParserFree(parser);
+ return 0;
+ }
+ processor = externalEntityInitProcessor;
+#ifdef XML_DTD
+ }
+ else {
+ dtdSwap(&dtd, oldDtd);
+ parentParser = oldParser;
+ XmlPrologStateInitExternalEntity(&prologState);
+ dtd.complete = 1;
+ hadExternalDoctype = 1;
+ }
+#endif /* XML_DTD */
+ return parser;
+}
+
+static
+void destroyBindings(BINDING *bindings, XML_Parser parser)
+{
+ for (;;) {
+ BINDING *b = bindings;
+ if (!b)
+ break;
+ bindings = b->nextTagBinding;
+ FREE(b->uri);
+ FREE(b);
+ }
+}
+
+void XML_ParserFree(XML_Parser parser)
+{
+ for (;;) {
+ TAG *p;
+ if (tagStack == 0) {
+ if (freeTagList == 0)
+ break;
+ tagStack = freeTagList;
+ freeTagList = 0;
+ }
+ p = tagStack;
+ tagStack = tagStack->parent;
+ FREE(p->buf);
+ destroyBindings(p->bindings, parser);
+ FREE(p);
+ }
+ destroyBindings(freeBindingList, parser);
+ destroyBindings(inheritedBindings, parser);
+ poolDestroy(&tempPool);
+ poolDestroy(&temp2Pool);
+#ifdef XML_DTD
+ if (parentParser) {
+ if (hadExternalDoctype)
+ dtd.complete = 0;
+ dtdSwap(&dtd, &((Parser *)parentParser)->m_dtd);
+ }
+#endif /* XML_DTD */
+ dtdDestroy(&dtd, parser);
+ FREE((void *)atts);
+ if (groupConnector)
+ FREE(groupConnector);
+ if (buffer)
+ FREE(buffer);
+ FREE(dataBuf);
+ if (unknownEncodingMem)
+ FREE(unknownEncodingMem);
+ if (unknownEncodingRelease)
+ unknownEncodingRelease(unknownEncodingData);
+ FREE(parser);
+}
+
+void XML_UseParserAsHandlerArg(XML_Parser parser)
+{
+ handlerArg = parser;
+}
+
+void
+XML_SetReturnNSTriplet(XML_Parser parser, int do_nst) {
+ ns_triplets = do_nst;
+}
+
+void XML_SetUserData(XML_Parser parser, void *p)
+{
+ if (handlerArg == userData)
+ handlerArg = userData = p;
+ else
+ userData = p;
+}
+
+int XML_SetBase(XML_Parser parser, const XML_Char *p)
+{
+ if (p) {
+ p = poolCopyString(&dtd.pool, p);
+ if (!p)
+ return 0;
+ curBase = p;
+ }
+ else
+ curBase = 0;
+ return 1;
+}
+
+const XML_Char *XML_GetBase(XML_Parser parser)
+{
+ return curBase;
+}
+
+int XML_GetSpecifiedAttributeCount(XML_Parser parser)
+{
+ return nSpecifiedAtts;
+}
+
+int XML_GetIdAttributeIndex(XML_Parser parser)
+{
+ return idAttIndex;
+}
+
+void XML_SetElementHandler(XML_Parser parser,
+ XML_StartElementHandler start,
+ XML_EndElementHandler end)
+{
+ startElementHandler = start;
+ endElementHandler = end;
+}
+
+void XML_SetStartElementHandler(XML_Parser parser,
+ XML_StartElementHandler start) {
+ startElementHandler = start;
+}
+
+void XML_SetEndElementHandler(XML_Parser parser,
+ XML_EndElementHandler end) {
+ endElementHandler = end;
+}
+
+void XML_SetCharacterDataHandler(XML_Parser parser,
+ XML_CharacterDataHandler handler)
+{
+ characterDataHandler = handler;
+}
+
+void XML_SetProcessingInstructionHandler(XML_Parser parser,
+ XML_ProcessingInstructionHandler handler)
+{
+ processingInstructionHandler = handler;
+}
+
+void XML_SetCommentHandler(XML_Parser parser,
+ XML_CommentHandler handler)
+{
+ commentHandler = handler;
+}
+
+void XML_SetCdataSectionHandler(XML_Parser parser,
+ XML_StartCdataSectionHandler start,
+ XML_EndCdataSectionHandler end)
+{
+ startCdataSectionHandler = start;
+ endCdataSectionHandler = end;
+}
+
+void XML_SetStartCdataSectionHandler(XML_Parser parser,
+ XML_StartCdataSectionHandler start) {
+ startCdataSectionHandler = start;
+}
+
+void XML_SetEndCdataSectionHandler(XML_Parser parser,
+ XML_EndCdataSectionHandler end) {
+ endCdataSectionHandler = end;
+}
+
+void XML_SetDefaultHandler(XML_Parser parser,
+ XML_DefaultHandler handler)
+{
+ defaultHandler = handler;
+ defaultExpandInternalEntities = 0;
+}
+
+void XML_SetDefaultHandlerExpand(XML_Parser parser,
+ XML_DefaultHandler handler)
+{
+ defaultHandler = handler;
+ defaultExpandInternalEntities = 1;
+}
+
+void XML_SetDoctypeDeclHandler(XML_Parser parser,
+ XML_StartDoctypeDeclHandler start,
+ XML_EndDoctypeDeclHandler end)
+{
+ startDoctypeDeclHandler = start;
+ endDoctypeDeclHandler = end;
+}
+
+void XML_SetStartDoctypeDeclHandler(XML_Parser parser,
+ XML_StartDoctypeDeclHandler start) {
+ startDoctypeDeclHandler = start;
+}
+
+void XML_SetEndDoctypeDeclHandler(XML_Parser parser,
+ XML_EndDoctypeDeclHandler end) {
+ endDoctypeDeclHandler = end;
+}
+
+void XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
+ XML_UnparsedEntityDeclHandler handler)
+{
+ unparsedEntityDeclHandler = handler;
+}
+
+void XML_SetNotationDeclHandler(XML_Parser parser,
+ XML_NotationDeclHandler handler)
+{
+ notationDeclHandler = handler;
+}
+
+void XML_SetNamespaceDeclHandler(XML_Parser parser,
+ XML_StartNamespaceDeclHandler start,
+ XML_EndNamespaceDeclHandler end)
+{
+ startNamespaceDeclHandler = start;
+ endNamespaceDeclHandler = end;
+}
+
+void XML_SetStartNamespaceDeclHandler(XML_Parser parser,
+ XML_StartNamespaceDeclHandler start) {
+ startNamespaceDeclHandler = start;
+}
+
+void XML_SetEndNamespaceDeclHandler(XML_Parser parser,
+ XML_EndNamespaceDeclHandler end) {
+ endNamespaceDeclHandler = end;
+}
+
+
+void XML_SetNotStandaloneHandler(XML_Parser parser,
+ XML_NotStandaloneHandler handler)
+{
+ notStandaloneHandler = handler;
+}
+
+void XML_SetExternalEntityRefHandler(XML_Parser parser,
+ XML_ExternalEntityRefHandler handler)
+{
+ externalEntityRefHandler = handler;
+}
+
+void XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg)
+{
+ if (arg)
+ externalEntityRefHandlerArg = arg;
+ else
+ externalEntityRefHandlerArg = parser;
+}
+
+void XML_SetUnknownEncodingHandler(XML_Parser parser,
+ XML_UnknownEncodingHandler handler,
+ void *data)
+{
+ unknownEncodingHandler = handler;
+ unknownEncodingHandlerData = data;
+}
+
+void XML_SetElementDeclHandler(XML_Parser parser,
+ XML_ElementDeclHandler eldecl)
+{
+ elementDeclHandler = eldecl;
+}
+
+void XML_SetAttlistDeclHandler(XML_Parser parser,
+ XML_AttlistDeclHandler attdecl)
+{
+ attlistDeclHandler = attdecl;
+}
+
+void XML_SetEntityDeclHandler(XML_Parser parser,
+ XML_EntityDeclHandler handler)
+{
+ entityDeclHandler = handler;
+}
+
+void XML_SetXmlDeclHandler(XML_Parser parser,
+ XML_XmlDeclHandler handler) {
+ xmlDeclHandler = handler;
+}
+
+int XML_SetParamEntityParsing(XML_Parser parser,
+ enum XML_ParamEntityParsing parsing)
+{
+#ifdef XML_DTD
+ paramEntityParsing = parsing;
+ return 1;
+#else
+ return parsing == XML_PARAM_ENTITY_PARSING_NEVER;
+#endif
+}
+
+int XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
+{
+ if (len == 0) {
+ if (!isFinal)
+ return 1;
+ positionPtr = bufferPtr;
+ errorCode = processor(parser, bufferPtr, parseEndPtr = bufferEnd, 0);
+ if (errorCode == XML_ERROR_NONE)
+ return 1;
+ eventEndPtr = eventPtr;
+ processor = errorProcessor;
+ return 0;
+ }
+#ifndef XML_CONTEXT_BYTES
+ else if (bufferPtr == bufferEnd) {
+ const char *end;
+ int nLeftOver;
+ parseEndByteIndex += len;
+ positionPtr = s;
+ if (isFinal) {
+ errorCode = processor(parser, s, parseEndPtr = s + len, 0);
+ if (errorCode == XML_ERROR_NONE)
+ return 1;
+ eventEndPtr = eventPtr;
+ processor = errorProcessor;
+ return 0;
+ }
+ errorCode = processor(parser, s, parseEndPtr = s + len, &end);
+ if (errorCode != XML_ERROR_NONE) {
+ eventEndPtr = eventPtr;
+ processor = errorProcessor;
+ return 0;
+ }
+ XmlUpdatePosition(encoding, positionPtr, end, &position);
+ nLeftOver = s + len - end;
+ if (nLeftOver) {
+ if (buffer == 0 || nLeftOver > bufferLim - buffer) {
+ /* FIXME avoid integer overflow */
+ buffer = buffer == 0 ? MALLOC(len * 2) : REALLOC(buffer, len * 2);
+ /* FIXME storage leak if realloc fails */
+ if (!buffer) {
+ errorCode = XML_ERROR_NO_MEMORY;
+ eventPtr = eventEndPtr = 0;
+ processor = errorProcessor;
+ return 0;
+ }
+ bufferLim = buffer + len * 2;
+ }
+ memcpy(buffer, end, nLeftOver);
+ bufferPtr = buffer;
+ bufferEnd = buffer + nLeftOver;
+ }
+ return 1;
+ }
+#endif /* not defined XML_CONTEXT_BYTES */
+ else {
+ memcpy(XML_GetBuffer(parser, len), s, len);
+ return XML_ParseBuffer(parser, len, isFinal);
+ }
+}
+
+int XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
+{
+ const char *start = bufferPtr;
+ positionPtr = start;
+ bufferEnd += len;
+ parseEndByteIndex += len;
+ errorCode = processor(parser, start, parseEndPtr = bufferEnd,
+ isFinal ? (const char **)0 : &bufferPtr);
+ if (errorCode == XML_ERROR_NONE) {
+ if (!isFinal)
+ XmlUpdatePosition(encoding, positionPtr, bufferPtr, &position);
+ return 1;
+ }
+ else {
+ eventEndPtr = eventPtr;
+ processor = errorProcessor;
+ return 0;
+ }
+}
+
+void *XML_GetBuffer(XML_Parser parser, int len)
+{
+ if (len > bufferLim - bufferEnd) {
+ /* FIXME avoid integer overflow */
+ int neededSize = len + (bufferEnd - bufferPtr);
+#ifdef XML_CONTEXT_BYTES
+ int keep = bufferPtr - buffer;
+
+ if (keep > XML_CONTEXT_BYTES)
+ keep = XML_CONTEXT_BYTES;
+ neededSize += keep;
+#endif /* defined XML_CONTEXT_BYTES */
+ if (neededSize <= bufferLim - buffer) {
+#ifdef XML_CONTEXT_BYTES
+ if (keep < bufferPtr - buffer) {
+ int offset = (bufferPtr - buffer) - keep;
+ memmove(buffer, &buffer[offset], bufferEnd - bufferPtr + keep);
+ bufferEnd -= offset;
+ bufferPtr -= offset;
+ }
+#else
+ memmove(buffer, bufferPtr, bufferEnd - bufferPtr);
+ bufferEnd = buffer + (bufferEnd - bufferPtr);
+ bufferPtr = buffer;
+#endif /* not defined XML_CONTEXT_BYTES */
+ }
+ else {
+ char *newBuf;
+ int bufferSize = bufferLim - bufferPtr;
+ if (bufferSize == 0)
+ bufferSize = INIT_BUFFER_SIZE;
+ do {
+ bufferSize *= 2;
+ } while (bufferSize < neededSize);
+ newBuf = MALLOC(bufferSize);
+ if (newBuf == 0) {
+ errorCode = XML_ERROR_NO_MEMORY;
+ return 0;
+ }
+ bufferLim = newBuf + bufferSize;
+#ifdef XML_CONTEXT_BYTES
+ if (bufferPtr) {
+ int keep = bufferPtr - buffer;
+ if (keep > XML_CONTEXT_BYTES)
+ keep = XML_CONTEXT_BYTES;
+ memcpy(newBuf, &bufferPtr[-keep], bufferEnd - bufferPtr + keep);
+ FREE(buffer);
+ buffer = newBuf;
+ bufferEnd = buffer + (bufferEnd - bufferPtr) + keep;
+ bufferPtr = buffer + keep;
+ }
+ else {
+ bufferEnd = newBuf + (bufferEnd - bufferPtr);
+ bufferPtr = buffer = newBuf;
+ }
+#else
+ if (bufferPtr) {
+ memcpy(newBuf, bufferPtr, bufferEnd - bufferPtr);
+ FREE(buffer);
+ }
+ bufferEnd = newBuf + (bufferEnd - bufferPtr);
+ bufferPtr = buffer = newBuf;
+#endif /* not defined XML_CONTEXT_BYTES */
+ }
+ }
+ return bufferEnd;
+}
+
+enum XML_Error XML_GetErrorCode(XML_Parser parser)
+{
+ return errorCode;
+}
+
+long XML_GetCurrentByteIndex(XML_Parser parser)
+{
+ if (eventPtr)
+ return parseEndByteIndex - (parseEndPtr - eventPtr);
+ return -1;
+}
+
+int XML_GetCurrentByteCount(XML_Parser parser)
+{
+ if (eventEndPtr && eventPtr)
+ return eventEndPtr - eventPtr;
+ return 0;
+}
+
+const char * XML_GetInputContext(XML_Parser parser, int *offset, int *size)
+{
+#ifdef XML_CONTEXT_BYTES
+ if (eventPtr && buffer) {
+ *offset = eventPtr - buffer;
+ *size = bufferEnd - buffer;
+ return buffer;
+ }
+#endif /* defined XML_CONTEXT_BYTES */
+ return (char *) 0;
+}
+
+int XML_GetCurrentLineNumber(XML_Parser parser)
+{
+ if (eventPtr) {
+ XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
+ positionPtr = eventPtr;
+ }
+ return position.lineNumber + 1;
+}
+
+int XML_GetCurrentColumnNumber(XML_Parser parser)
+{
+ if (eventPtr) {
+ XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
+ positionPtr = eventPtr;
+ }
+ return position.columnNumber;
+}
+
+void XML_DefaultCurrent(XML_Parser parser)
+{
+ if (defaultHandler) {
+ if (openInternalEntities)
+ reportDefault(parser,
+ internalEncoding,
+ openInternalEntities->internalEventPtr,
+ openInternalEntities->internalEventEndPtr);
+ else
+ reportDefault(parser, encoding, eventPtr, eventEndPtr);
+ }
+}
+
+const XML_LChar *XML_ErrorString(int code)
+{
+ static const XML_LChar *message[] = {
+ 0,
+ XML_T("out of memory"),
+ XML_T("syntax error"),
+ XML_T("no element found"),
+ XML_T("not well-formed (invalid token)"),
+ XML_T("unclosed token"),
+ XML_T("unclosed token"),
+ XML_T("mismatched tag"),
+ XML_T("duplicate attribute"),
+ XML_T("junk after document element"),
+ XML_T("illegal parameter entity reference"),
+ XML_T("undefined entity"),
+ XML_T("recursive entity reference"),
+ XML_T("asynchronous entity"),
+ XML_T("reference to invalid character number"),
+ XML_T("reference to binary entity"),
+ XML_T("reference to external entity in attribute"),
+ XML_T("xml processing instruction not at start of external entity"),
+ XML_T("unknown encoding"),
+ XML_T("encoding specified in XML declaration is incorrect"),
+ XML_T("unclosed CDATA section"),
+ XML_T("error in processing external entity reference"),
+ XML_T("document is not standalone"),
+ XML_T("unexpected parser state - please send a bug report")
+ };
+ if (code > 0 && code < sizeof(message)/sizeof(message[0]))
+ return message[code];
+ return 0;
+}
+
+const XML_LChar *
+XML_ExpatVersion(void) {
+ return VERSION;
+}
+
+XML_Expat_Version
+XML_ExpatVersionInfo(void) {
+ XML_Expat_Version version;
+
+ version.major = XML_MAJOR_VERSION;
+ version.minor = XML_MINOR_VERSION;
+ version.micro = XML_MICRO_VERSION;
+
+ return version;
+}
+
+static
+enum XML_Error contentProcessor(XML_Parser parser,
+ const char *start,
+ const char *end,
+ const char **endPtr)
+{
+ return doContent(parser, 0, encoding, start, end, endPtr);
+}
+
+static
+enum XML_Error externalEntityInitProcessor(XML_Parser parser,
+ const char *start,
+ const char *end,
+ const char **endPtr)
+{
+ enum XML_Error result = initializeEncoding(parser);
+ if (result != XML_ERROR_NONE)
+ return result;
+ processor = externalEntityInitProcessor2;
+ return externalEntityInitProcessor2(parser, start, end, endPtr);
+}
+
+static
+enum XML_Error externalEntityInitProcessor2(XML_Parser parser,
+ const char *start,
+ const char *end,
+ const char **endPtr)
+{
+ const char *next;
+ int tok = XmlContentTok(encoding, start, end, &next);
+ switch (tok) {
+ case XML_TOK_BOM:
+ start = next;
+ break;
+ case XML_TOK_PARTIAL:
+ if (endPtr) {
+ *endPtr = start;
+ return XML_ERROR_NONE;
+ }
+ eventPtr = start;
+ return XML_ERROR_UNCLOSED_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ if (endPtr) {
+ *endPtr = start;
+ return XML_ERROR_NONE;
+ }
+ eventPtr = start;
+ return XML_ERROR_PARTIAL_CHAR;
+ }
+ processor = externalEntityInitProcessor3;
+ return externalEntityInitProcessor3(parser, start, end, endPtr);
+}
+
+static
+enum XML_Error externalEntityInitProcessor3(XML_Parser parser,
+ const char *start,
+ const char *end,
+ const char **endPtr)
+{
+ const char *next;
+ int tok = XmlContentTok(encoding, start, end, &next);
+ switch (tok) {
+ case XML_TOK_XML_DECL:
+ {
+ enum XML_Error result = processXmlDecl(parser, 1, start, next);
+ if (result != XML_ERROR_NONE)
+ return result;
+ start = next;
+ }
+ break;
+ case XML_TOK_PARTIAL:
+ if (endPtr) {
+ *endPtr = start;
+ return XML_ERROR_NONE;
+ }
+ eventPtr = start;
+ return XML_ERROR_UNCLOSED_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ if (endPtr) {
+ *endPtr = start;
+ return XML_ERROR_NONE;
+ }
+ eventPtr = start;
+ return XML_ERROR_PARTIAL_CHAR;
+ }
+ processor = externalEntityContentProcessor;
+ tagLevel = 1;
+ return doContent(parser, 1, encoding, start, end, endPtr);
+}
+
+static
+enum XML_Error externalEntityContentProcessor(XML_Parser parser,
+ const char *start,
+ const char *end,
+ const char **endPtr)
+{
+ return doContent(parser, 1, encoding, start, end, endPtr);
+}
+
+static enum XML_Error
+doContent(XML_Parser parser,
+ int startTagLevel,
+ const ENCODING *enc,
+ const char *s,
+ const char *end,
+ const char **nextPtr)
+{
+ const char **eventPP;
+ const char **eventEndPP;
+ if (enc == encoding) {
+ eventPP = &eventPtr;
+ eventEndPP = &eventEndPtr;
+ }
+ else {
+ eventPP = &(openInternalEntities->internalEventPtr);
+ eventEndPP = &(openInternalEntities->internalEventEndPtr);
+ }
+ *eventPP = s;
+ for (;;) {
+ const char *next = s; /* XmlContentTok doesn't always set the last arg */
+ int tok = XmlContentTok(enc, s, end, &next);
+ *eventEndPP = next;
+ switch (tok) {
+ case XML_TOK_TRAILING_CR:
+ if (nextPtr) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ *eventEndPP = end;
+ if (characterDataHandler) {
+ XML_Char c = 0xA;
+ characterDataHandler(handlerArg, &c, 1);
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, end);
+ if (startTagLevel == 0)
+ return XML_ERROR_NO_ELEMENTS;
+ if (tagLevel != startTagLevel)
+ return XML_ERROR_ASYNC_ENTITY;
+ return XML_ERROR_NONE;
+ case XML_TOK_NONE:
+ if (nextPtr) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ if (startTagLevel > 0) {
+ if (tagLevel != startTagLevel)
+ return XML_ERROR_ASYNC_ENTITY;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_NO_ELEMENTS;
+ case XML_TOK_INVALID:
+ *eventPP = next;
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_PARTIAL:
+ if (nextPtr) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_UNCLOSED_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ if (nextPtr) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_PARTIAL_CHAR;
+ case XML_TOK_ENTITY_REF:
+ {
+ const XML_Char *name;
+ ENTITY *entity;
+ XML_Char ch = XmlPredefinedEntityName(enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (ch) {
+ if (characterDataHandler)
+ characterDataHandler(handlerArg, &ch, 1);
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+ }
+ name = poolStoreString(&dtd.pool, enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (!name)
+ return XML_ERROR_NO_MEMORY;
+ entity = (ENTITY *)lookup(&dtd.generalEntities, name, 0);
+ poolDiscard(&dtd.pool);
+ if (!entity) {
+ if (dtd.complete || dtd.standalone)
+ return XML_ERROR_UNDEFINED_ENTITY;
+ if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+ }
+ if (entity->open)
+ return XML_ERROR_RECURSIVE_ENTITY_REF;
+ if (entity->notation)
+ return XML_ERROR_BINARY_ENTITY_REF;
+ if (entity) {
+ if (entity->textPtr) {
+ enum XML_Error result;
+ OPEN_INTERNAL_ENTITY openEntity;
+ if (defaultHandler && !defaultExpandInternalEntities) {
+ reportDefault(parser, enc, s, next);
+ break;
+ }
+ entity->open = 1;
+ openEntity.next = openInternalEntities;
+ openInternalEntities = &openEntity;
+ openEntity.entity = entity;
+ openEntity.internalEventPtr = 0;
+ openEntity.internalEventEndPtr = 0;
+ result = doContent(parser,
+ tagLevel,
+ internalEncoding,
+ (char *)entity->textPtr,
+ (char *)(entity->textPtr + entity->textLen),
+ 0);
+ entity->open = 0;
+ openInternalEntities = openEntity.next;
+ if (result)
+ return result;
+ }
+ else if (externalEntityRefHandler) {
+ const XML_Char *context;
+ entity->open = 1;
+ context = getContext(parser);
+ entity->open = 0;
+ if (!context)
+ return XML_ERROR_NO_MEMORY;
+ if (!externalEntityRefHandler(externalEntityRefHandlerArg,
+ context,
+ entity->base,
+ entity->systemId,
+ entity->publicId))
+ return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
+ poolDiscard(&tempPool);
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ }
+ break;
+ }
+ case XML_TOK_START_TAG_WITH_ATTS:
+ if (!startElementHandler) {
+ enum XML_Error result = storeAtts(parser, enc, s, 0, 0);
+ if (result)
+ return result;
+ }
+ /* fall through */
+ case XML_TOK_START_TAG_NO_ATTS:
+ {
+ TAG *tag;
+ if (freeTagList) {
+ tag = freeTagList;
+ freeTagList = freeTagList->parent;
+ }
+ else {
+ tag = MALLOC(sizeof(TAG));
+ if (!tag)
+ return XML_ERROR_NO_MEMORY;
+ tag->buf = MALLOC(INIT_TAG_BUF_SIZE);
+ if (!tag->buf)
+ return XML_ERROR_NO_MEMORY;
+ tag->bufEnd = tag->buf + INIT_TAG_BUF_SIZE;
+ }
+ tag->bindings = 0;
+ tag->parent = tagStack;
+ tagStack = tag;
+ tag->name.localPart = 0;
+ tag->rawName = s + enc->minBytesPerChar;
+ tag->rawNameLength = XmlNameLength(enc, tag->rawName);
+ if (nextPtr) {
+ /* Need to guarantee that:
+ tag->buf + ROUND_UP(tag->rawNameLength, sizeof(XML_Char)) <= tag->bufEnd - sizeof(XML_Char) */
+ if (tag->rawNameLength + (int)(sizeof(XML_Char) - 1) + (int)sizeof(XML_Char) > tag->bufEnd - tag->buf) {
+ int bufSize = tag->rawNameLength * 4;
+ bufSize = ROUND_UP(bufSize, sizeof(XML_Char));
+ tag->buf = REALLOC(tag->buf, bufSize);
+ if (!tag->buf)
+ return XML_ERROR_NO_MEMORY;
+ tag->bufEnd = tag->buf + bufSize;
+ }
+ memcpy(tag->buf, tag->rawName, tag->rawNameLength);
+ tag->rawName = tag->buf;
+ }
+ ++tagLevel;
+ if (startElementHandler) {
+ enum XML_Error result;
+ XML_Char *toPtr;
+ for (;;) {
+ const char *rawNameEnd = tag->rawName + tag->rawNameLength;
+ const char *fromPtr = tag->rawName;
+ int bufSize;
+ if (nextPtr)
+ toPtr = (XML_Char *)(tag->buf + ROUND_UP(tag->rawNameLength, sizeof(XML_Char)));
+ else
+ toPtr = (XML_Char *)tag->buf;
+ tag->name.str = toPtr;
+ XmlConvert(enc,
+ &fromPtr, rawNameEnd,
+ (ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1);
+ if (fromPtr == rawNameEnd)
+ break;
+ bufSize = (tag->bufEnd - tag->buf) << 1;
+ tag->buf = REALLOC(tag->buf, bufSize);
+ if (!tag->buf)
+ return XML_ERROR_NO_MEMORY;
+ tag->bufEnd = tag->buf + bufSize;
+ if (nextPtr)
+ tag->rawName = tag->buf;
+ }
+ *toPtr = XML_T('\0');
+ result = storeAtts(parser, enc, s, &(tag->name), &(tag->bindings));
+ if (result)
+ return result;
+ startElementHandler(handlerArg, tag->name.str, (const XML_Char **)atts);
+ poolClear(&tempPool);
+ }
+ else {
+ tag->name.str = 0;
+ if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ }
+ break;
+ }
+ case XML_TOK_EMPTY_ELEMENT_WITH_ATTS:
+ if (!startElementHandler) {
+ enum XML_Error result = storeAtts(parser, enc, s, 0, 0);
+ if (result)
+ return result;
+ }
+ /* fall through */
+ case XML_TOK_EMPTY_ELEMENT_NO_ATTS:
+ if (startElementHandler || endElementHandler) {
+ const char *rawName = s + enc->minBytesPerChar;
+ enum XML_Error result;
+ BINDING *bindings = 0;
+ TAG_NAME name;
+ name.str = poolStoreString(&tempPool, enc, rawName,
+ rawName + XmlNameLength(enc, rawName));
+ if (!name.str)
+ return XML_ERROR_NO_MEMORY;
+ poolFinish(&tempPool);
+ result = storeAtts(parser, enc, s, &name, &bindings);
+ if (result)
+ return result;
+ poolFinish(&tempPool);
+ if (startElementHandler)
+ startElementHandler(handlerArg, name.str, (const XML_Char **)atts);
+ if (endElementHandler) {
+ if (startElementHandler)
+ *eventPP = *eventEndPP;
+ endElementHandler(handlerArg, name.str);
+ }
+ poolClear(&tempPool);
+ while (bindings) {
+ BINDING *b = bindings;
+ if (endNamespaceDeclHandler)
+ endNamespaceDeclHandler(handlerArg, b->prefix->name);
+ bindings = bindings->nextTagBinding;
+ b->nextTagBinding = freeBindingList;
+ freeBindingList = b;
+ b->prefix->binding = b->prevPrefixBinding;
+ }
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ if (tagLevel == 0)
+ return epilogProcessor(parser, next, end, nextPtr);
+ break;
+ case XML_TOK_END_TAG:
+ if (tagLevel == startTagLevel)
+ return XML_ERROR_ASYNC_ENTITY;
+ else {
+ int len;
+ const char *rawName;
+ TAG *tag = tagStack;
+ tagStack = tag->parent;
+ tag->parent = freeTagList;
+ freeTagList = tag;
+ rawName = s + enc->minBytesPerChar*2;
+ len = XmlNameLength(enc, rawName);
+ if (len != tag->rawNameLength
+ || memcmp(tag->rawName, rawName, len) != 0) {
+ *eventPP = rawName;
+ return XML_ERROR_TAG_MISMATCH;
+ }
+ --tagLevel;
+ if (endElementHandler && tag->name.str) {
+ if (tag->name.localPart) {
+ XML_Char *to = (XML_Char *)tag->name.str + tag->name.uriLen;
+ const XML_Char *from = tag->name.localPart;
+ while ((*to++ = *from++) != 0)
+ ;
+ }
+ endElementHandler(handlerArg, tag->name.str);
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ while (tag->bindings) {
+ BINDING *b = tag->bindings;
+ if (endNamespaceDeclHandler)
+ endNamespaceDeclHandler(handlerArg, b->prefix->name);
+ tag->bindings = tag->bindings->nextTagBinding;
+ b->nextTagBinding = freeBindingList;
+ freeBindingList = b;
+ b->prefix->binding = b->prevPrefixBinding;
+ }
+ if (tagLevel == 0)
+ return epilogProcessor(parser, next, end, nextPtr);
+ }
+ break;
+ case XML_TOK_CHAR_REF:
+ {
+ int n = XmlCharRefNumber(enc, s);
+ if (n < 0)
+ return XML_ERROR_BAD_CHAR_REF;
+ if (characterDataHandler) {
+ XML_Char buf[XML_ENCODE_MAX];
+ characterDataHandler(handlerArg, buf, XmlEncode(n, (ICHAR *)buf));
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ }
+ break;
+ case XML_TOK_XML_DECL:
+ return XML_ERROR_MISPLACED_XML_PI;
+ case XML_TOK_DATA_NEWLINE:
+ if (characterDataHandler) {
+ XML_Char c = 0xA;
+ characterDataHandler(handlerArg, &c, 1);
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+ case XML_TOK_CDATA_SECT_OPEN:
+ {
+ enum XML_Error result;
+ if (startCdataSectionHandler)
+ startCdataSectionHandler(handlerArg);
+#if 0
+ /* Suppose you doing a transformation on a document that involves
+ changing only the character data. You set up a defaultHandler
+ and a characterDataHandler. The defaultHandler simply copies
+ characters through. The characterDataHandler does the transformation
+ and writes the characters out escaping them as necessary. This case
+ will fail to work if we leave out the following two lines (because &
+ and < inside CDATA sections will be incorrectly escaped).
+
+ However, now we have a start/endCdataSectionHandler, so it seems
+ easier to let the user deal with this. */
+
+ else if (characterDataHandler)
+ characterDataHandler(handlerArg, dataBuf, 0);
+#endif
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ result = doCdataSection(parser, enc, &next, end, nextPtr);
+ if (!next) {
+ processor = cdataSectionProcessor;
+ return result;
+ }
+ }
+ break;
+ case XML_TOK_TRAILING_RSQB:
+ if (nextPtr) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ if (characterDataHandler) {
+ if (MUST_CONVERT(enc, s)) {
+ ICHAR *dataPtr = (ICHAR *)dataBuf;
+ XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
+ characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
+ }
+ else
+ characterDataHandler(handlerArg,
+ (XML_Char *)s,
+ (XML_Char *)end - (XML_Char *)s);
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, end);
+ if (startTagLevel == 0) {
+ *eventPP = end;
+ return XML_ERROR_NO_ELEMENTS;
+ }
+ if (tagLevel != startTagLevel) {
+ *eventPP = end;
+ return XML_ERROR_ASYNC_ENTITY;
+ }
+ return XML_ERROR_NONE;
+ case XML_TOK_DATA_CHARS:
+ if (characterDataHandler) {
+ if (MUST_CONVERT(enc, s)) {
+ for (;;) {
+ ICHAR *dataPtr = (ICHAR *)dataBuf;
+ XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
+ *eventEndPP = s;
+ characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
+ if (s == next)
+ break;
+ *eventPP = s;
+ }
+ }
+ else
+ characterDataHandler(handlerArg,
+ (XML_Char *)s,
+ (XML_Char *)next - (XML_Char *)s);
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+ case XML_TOK_PI:
+ if (!reportProcessingInstruction(parser, enc, s, next))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ case XML_TOK_COMMENT:
+ if (!reportComment(parser, enc, s, next))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ default:
+ if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+ }
+ *eventPP = s = next;
+ }
+ /* not reached */
+}
+
+/* If tagNamePtr is non-null, build a real list of attributes,
+otherwise just check the attributes for well-formedness. */
+
+static enum XML_Error storeAtts(XML_Parser parser, const ENCODING *enc,
+ const char *attStr, TAG_NAME *tagNamePtr,
+ BINDING **bindingsPtr)
+{
+ ELEMENT_TYPE *elementType = 0;
+ int nDefaultAtts = 0;
+ const XML_Char **appAtts; /* the attribute list to pass to the application */
+ int attIndex = 0;
+ int i;
+ int n;
+ int nPrefixes = 0;
+ BINDING *binding;
+ const XML_Char *localPart;
+
+ /* lookup the element type name */
+ if (tagNamePtr) {
+ elementType = (ELEMENT_TYPE *)lookup(&dtd.elementTypes, tagNamePtr->str,0);
+ if (!elementType) {
+ tagNamePtr->str = poolCopyString(&dtd.pool, tagNamePtr->str);
+ if (!tagNamePtr->str)
+ return XML_ERROR_NO_MEMORY;
+ elementType = (ELEMENT_TYPE *)lookup(&dtd.elementTypes, tagNamePtr->str, sizeof(ELEMENT_TYPE));
+ if (!elementType)
+ return XML_ERROR_NO_MEMORY;
+ if (ns && !setElementTypePrefix(parser, elementType))
+ return XML_ERROR_NO_MEMORY;
+ }
+ nDefaultAtts = elementType->nDefaultAtts;
+ }
+ /* get the attributes from the tokenizer */
+ n = XmlGetAttributes(enc, attStr, attsSize, atts);
+ if (n + nDefaultAtts > attsSize) {
+ int oldAttsSize = attsSize;
+ attsSize = n + nDefaultAtts + INIT_ATTS_SIZE;
+ atts = REALLOC((void *)atts, attsSize * sizeof(ATTRIBUTE));
+ if (!atts)
+ return XML_ERROR_NO_MEMORY;
+ if (n > oldAttsSize)
+ XmlGetAttributes(enc, attStr, n, atts);
+ }
+ appAtts = (const XML_Char **)atts;
+ for (i = 0; i < n; i++) {
+ /* add the name and value to the attribute list */
+ ATTRIBUTE_ID *attId = getAttributeId(parser, enc, atts[i].name,
+ atts[i].name
+ + XmlNameLength(enc, atts[i].name));
+ if (!attId)
+ return XML_ERROR_NO_MEMORY;
+ /* detect duplicate attributes */
+ if ((attId->name)[-1]) {
+ if (enc == encoding)
+ eventPtr = atts[i].name;
+ return XML_ERROR_DUPLICATE_ATTRIBUTE;
+ }
+ (attId->name)[-1] = 1;
+ appAtts[attIndex++] = attId->name;
+ if (!atts[i].normalized) {
+ enum XML_Error result;
+ int isCdata = 1;
+
+ /* figure out whether declared as other than CDATA */
+ if (attId->maybeTokenized) {
+ int j;
+ for (j = 0; j < nDefaultAtts; j++) {
+ if (attId == elementType->defaultAtts[j].id) {
+ isCdata = elementType->defaultAtts[j].isCdata;
+ break;
+ }
+ }
+ }
+
+ /* normalize the attribute value */
+ result = storeAttributeValue(parser, enc, isCdata,
+ atts[i].valuePtr, atts[i].valueEnd,
+ &tempPool);
+ if (result)
+ return result;
+ if (tagNamePtr) {
+ appAtts[attIndex] = poolStart(&tempPool);
+ poolFinish(&tempPool);
+ }
+ else
+ poolDiscard(&tempPool);
+ }
+ else if (tagNamePtr) {
+ /* the value did not need normalizing */
+ appAtts[attIndex] = poolStoreString(&tempPool, enc, atts[i].valuePtr, atts[i].valueEnd);
+ if (appAtts[attIndex] == 0)
+ return XML_ERROR_NO_MEMORY;
+ poolFinish(&tempPool);
+ }
+ /* handle prefixed attribute names */
+ if (attId->prefix && tagNamePtr) {
+ if (attId->xmlns) {
+ /* deal with namespace declarations here */
+ if (!addBinding(parser, attId->prefix, attId, appAtts[attIndex], bindingsPtr))
+ return XML_ERROR_NO_MEMORY;
+ --attIndex;
+ }
+ else {
+ /* deal with other prefixed names later */
+ attIndex++;
+ nPrefixes++;
+ (attId->name)[-1] = 2;
+ }
+ }
+ else
+ attIndex++;
+ }
+ if (tagNamePtr) {
+ int j;
+ nSpecifiedAtts = attIndex;
+ if (elementType->idAtt && (elementType->idAtt->name)[-1]) {
+ for (i = 0; i < attIndex; i += 2)
+ if (appAtts[i] == elementType->idAtt->name) {
+ idAttIndex = i;
+ break;
+ }
+ }
+ else
+ idAttIndex = -1;
+ /* do attribute defaulting */
+ for (j = 0; j < nDefaultAtts; j++) {
+ const DEFAULT_ATTRIBUTE *da = elementType->defaultAtts + j;
+ if (!(da->id->name)[-1] && da->value) {
+ if (da->id->prefix) {
+ if (da->id->xmlns) {
+ if (!addBinding(parser, da->id->prefix, da->id, da->value, bindingsPtr))
+ return XML_ERROR_NO_MEMORY;
+ }
+ else {
+ (da->id->name)[-1] = 2;
+ nPrefixes++;
+ appAtts[attIndex++] = da->id->name;
+ appAtts[attIndex++] = da->value;
+ }
+ }
+ else {
+ (da->id->name)[-1] = 1;
+ appAtts[attIndex++] = da->id->name;
+ appAtts[attIndex++] = da->value;
+ }
+ }
+ }
+ appAtts[attIndex] = 0;
+ }
+ i = 0;
+ if (nPrefixes) {
+ /* expand prefixed attribute names */
+ for (; i < attIndex; i += 2) {
+ if (appAtts[i][-1] == 2) {
+ ATTRIBUTE_ID *id;
+ ((XML_Char *)(appAtts[i]))[-1] = 0;
+ id = (ATTRIBUTE_ID *)lookup(&dtd.attributeIds, appAtts[i], 0);
+ if (id->prefix->binding) {
+ int j;
+ const BINDING *b = id->prefix->binding;
+ const XML_Char *s = appAtts[i];
+ for (j = 0; j < b->uriLen; j++) {
+ if (!poolAppendChar(&tempPool, b->uri[j]))
+ return XML_ERROR_NO_MEMORY;
+ }
+ while (*s++ != ':')
+ ;
+ do {
+ if (!poolAppendChar(&tempPool, *s))
+ return XML_ERROR_NO_MEMORY;
+ } while (*s++);
+ if (ns_triplets) {
+ tempPool.ptr[-1] = namespaceSeparator;
+ s = b->prefix->name;
+ do {
+ if (!poolAppendChar(&tempPool, *s))
+ return XML_ERROR_NO_MEMORY;
+ } while (*s++);
+ }
+
+ appAtts[i] = poolStart(&tempPool);
+ poolFinish(&tempPool);
+ }
+ if (!--nPrefixes)
+ break;
+ }
+ else
+ ((XML_Char *)(appAtts[i]))[-1] = 0;
+ }
+ }
+ /* clear the flags that say whether attributes were specified */
+ for (; i < attIndex; i += 2)
+ ((XML_Char *)(appAtts[i]))[-1] = 0;
+ if (!tagNamePtr)
+ return XML_ERROR_NONE;
+ for (binding = *bindingsPtr; binding; binding = binding->nextTagBinding)
+ binding->attId->name[-1] = 0;
+ /* expand the element type name */
+ if (elementType->prefix) {
+ binding = elementType->prefix->binding;
+ if (!binding)
+ return XML_ERROR_NONE;
+ localPart = tagNamePtr->str;
+ while (*localPart++ != XML_T(':'))
+ ;
+ }
+ else if (dtd.defaultPrefix.binding) {
+ binding = dtd.defaultPrefix.binding;
+ localPart = tagNamePtr->str;
+ }
+ else
+ return XML_ERROR_NONE;
+ tagNamePtr->localPart = localPart;
+ tagNamePtr->uriLen = binding->uriLen;
+ for (i = 0; localPart[i++];)
+ ;
+ n = i + binding->uriLen;
+ if (n > binding->uriAlloc) {
+ TAG *p;
+ XML_Char *uri = MALLOC((n + EXPAND_SPARE) * sizeof(XML_Char));
+ if (!uri)
+ return XML_ERROR_NO_MEMORY;
+ binding->uriAlloc = n + EXPAND_SPARE;
+ memcpy(uri, binding->uri, binding->uriLen * sizeof(XML_Char));
+ for (p = tagStack; p; p = p->parent)
+ if (p->name.str == binding->uri)
+ p->name.str = uri;
+ FREE(binding->uri);
+ binding->uri = uri;
+ }
+ memcpy(binding->uri + binding->uriLen, localPart, i * sizeof(XML_Char));
+ tagNamePtr->str = binding->uri;
+ return XML_ERROR_NONE;
+}
+
+static
+int addBinding(XML_Parser parser, PREFIX *prefix, const ATTRIBUTE_ID *attId, const XML_Char *uri, BINDING **bindingsPtr)
+{
+ BINDING *b;
+ int len;
+ for (len = 0; uri[len]; len++)
+ ;
+ if (namespaceSeparator)
+ len++;
+ if (freeBindingList) {
+ b = freeBindingList;
+ if (len > b->uriAlloc) {
+ b->uri = REALLOC(b->uri, sizeof(XML_Char) * (len + EXPAND_SPARE));
+ if (!b->uri)
+ return 0;
+ b->uriAlloc = len + EXPAND_SPARE;
+ }
+ freeBindingList = b->nextTagBinding;
+ }
+ else {
+ b = MALLOC(sizeof(BINDING));
+ if (!b)
+ return 0;
+ b->uri = MALLOC(sizeof(XML_Char) * (len + EXPAND_SPARE));
+ if (!b->uri) {
+ FREE(b);
+ return 0;
+ }
+ b->uriAlloc = len + EXPAND_SPARE;
+ }
+ b->uriLen = len;
+ memcpy(b->uri, uri, len * sizeof(XML_Char));
+ if (namespaceSeparator)
+ b->uri[len - 1] = namespaceSeparator;
+ b->prefix = prefix;
+ b->attId = attId;
+ b->prevPrefixBinding = prefix->binding;
+ if (*uri == XML_T('\0') && prefix == &dtd.defaultPrefix)
+ prefix->binding = 0;
+ else
+ prefix->binding = b;
+ b->nextTagBinding = *bindingsPtr;
+ *bindingsPtr = b;
+ if (startNamespaceDeclHandler)
+ startNamespaceDeclHandler(handlerArg, prefix->name,
+ prefix->binding ? uri : 0);
+ return 1;
+}
+
+/* The idea here is to avoid using stack for each CDATA section when
+the whole file is parsed with one call. */
+
+static
+enum XML_Error cdataSectionProcessor(XML_Parser parser,
+ const char *start,
+ const char *end,
+ const char **endPtr)
+{
+ enum XML_Error result = doCdataSection(parser, encoding, &start, end, endPtr);
+ if (start) {
+ processor = contentProcessor;
+ return contentProcessor(parser, start, end, endPtr);
+ }
+ return result;
+}
+
+/* startPtr gets set to non-null is the section is closed, and to null if
+the section is not yet closed. */
+
+static
+enum XML_Error doCdataSection(XML_Parser parser,
+ const ENCODING *enc,
+ const char **startPtr,
+ const char *end,
+ const char **nextPtr)
+{
+ const char *s = *startPtr;
+ const char **eventPP;
+ const char **eventEndPP;
+ if (enc == encoding) {
+ eventPP = &eventPtr;
+ *eventPP = s;
+ eventEndPP = &eventEndPtr;
+ }
+ else {
+ eventPP = &(openInternalEntities->internalEventPtr);
+ eventEndPP = &(openInternalEntities->internalEventEndPtr);
+ }
+ *eventPP = s;
+ *startPtr = 0;
+ for (;;) {
+ const char *next;
+ int tok = XmlCdataSectionTok(enc, s, end, &next);
+ *eventEndPP = next;
+ switch (tok) {
+ case XML_TOK_CDATA_SECT_CLOSE:
+ if (endCdataSectionHandler)
+ endCdataSectionHandler(handlerArg);
+#if 0
+ /* see comment under XML_TOK_CDATA_SECT_OPEN */
+ else if (characterDataHandler)
+ characterDataHandler(handlerArg, dataBuf, 0);
+#endif
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ *startPtr = next;
+ return XML_ERROR_NONE;
+ case XML_TOK_DATA_NEWLINE:
+ if (characterDataHandler) {
+ XML_Char c = 0xA;
+ characterDataHandler(handlerArg, &c, 1);
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+ case XML_TOK_DATA_CHARS:
+ if (characterDataHandler) {
+ if (MUST_CONVERT(enc, s)) {
+ for (;;) {
+ ICHAR *dataPtr = (ICHAR *)dataBuf;
+ XmlConvert(enc, &s, next, &dataPtr, (ICHAR *)dataBufEnd);
+ *eventEndPP = next;
+ characterDataHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
+ if (s == next)
+ break;
+ *eventPP = s;
+ }
+ }
+ else
+ characterDataHandler(handlerArg,
+ (XML_Char *)s,
+ (XML_Char *)next - (XML_Char *)s);
+ }
+ else if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+ case XML_TOK_INVALID:
+ *eventPP = next;
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ if (nextPtr) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_PARTIAL_CHAR;
+ case XML_TOK_PARTIAL:
+ case XML_TOK_NONE:
+ if (nextPtr) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_UNCLOSED_CDATA_SECTION;
+ default:
+ *eventPP = next;
+ return XML_ERROR_UNEXPECTED_STATE;
+ }
+ *eventPP = s = next;
+ }
+ /* not reached */
+}
+
+#ifdef XML_DTD
+
+/* The idea here is to avoid using stack for each IGNORE section when
+the whole file is parsed with one call. */
+
+static
+enum XML_Error ignoreSectionProcessor(XML_Parser parser,
+ const char *start,
+ const char *end,
+ const char **endPtr)
+{
+ enum XML_Error result = doIgnoreSection(parser, encoding, &start, end, endPtr);
+ if (start) {
+ processor = prologProcessor;
+ return prologProcessor(parser, start, end, endPtr);
+ }
+ return result;
+}
+
+/* startPtr gets set to non-null is the section is closed, and to null if
+the section is not yet closed. */
+
+static
+enum XML_Error doIgnoreSection(XML_Parser parser,
+ const ENCODING *enc,
+ const char **startPtr,
+ const char *end,
+ const char **nextPtr)
+{
+ const char *next;
+ int tok;
+ const char *s = *startPtr;
+ const char **eventPP;
+ const char **eventEndPP;
+ if (enc == encoding) {
+ eventPP = &eventPtr;
+ *eventPP = s;
+ eventEndPP = &eventEndPtr;
+ }
+ else {
+ eventPP = &(openInternalEntities->internalEventPtr);
+ eventEndPP = &(openInternalEntities->internalEventEndPtr);
+ }
+ *eventPP = s;
+ *startPtr = 0;
+ tok = XmlIgnoreSectionTok(enc, s, end, &next);
+ *eventEndPP = next;
+ switch (tok) {
+ case XML_TOK_IGNORE_SECT:
+ if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ *startPtr = next;
+ return XML_ERROR_NONE;
+ case XML_TOK_INVALID:
+ *eventPP = next;
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ if (nextPtr) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_PARTIAL_CHAR;
+ case XML_TOK_PARTIAL:
+ case XML_TOK_NONE:
+ if (nextPtr) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_SYNTAX; /* XML_ERROR_UNCLOSED_IGNORE_SECTION */
+ default:
+ *eventPP = next;
+ return XML_ERROR_UNEXPECTED_STATE;
+ }
+ /* not reached */
+}
+
+#endif /* XML_DTD */
+
+static enum XML_Error
+initializeEncoding(XML_Parser parser)
+{
+ const char *s;
+#ifdef XML_UNICODE
+ char encodingBuf[128];
+ if (!protocolEncodingName)
+ s = 0;
+ else {
+ int i;
+ for (i = 0; protocolEncodingName[i]; i++) {
+ if (i == sizeof(encodingBuf) - 1
+ || (protocolEncodingName[i] & ~0x7f) != 0) {
+ encodingBuf[0] = '\0';
+ break;
+ }
+ encodingBuf[i] = (char)protocolEncodingName[i];
+ }
+ encodingBuf[i] = '\0';
+ s = encodingBuf;
+ }
+#else
+ s = protocolEncodingName;
+#endif
+ if ((ns ? XmlInitEncodingNS : XmlInitEncoding)(&initEncoding, &encoding, s))
+ return XML_ERROR_NONE;
+ return handleUnknownEncoding(parser, protocolEncodingName);
+}
+
+static enum XML_Error
+processXmlDecl(XML_Parser parser, int isGeneralTextEntity,
+ const char *s, const char *next)
+{
+ const char *encodingName = 0;
+ const char *storedEncName = 0;
+ const ENCODING *newEncoding = 0;
+ const char *version = 0;
+ const char *versionend;
+ const char *storedversion = 0;
+ int standalone = -1;
+ if (!(ns
+ ? XmlParseXmlDeclNS
+ : XmlParseXmlDecl)(isGeneralTextEntity,
+ encoding,
+ s,
+ next,
+ &eventPtr,
+ &version,
+ &versionend,
+ &encodingName,
+ &newEncoding,
+ &standalone))
+ return XML_ERROR_SYNTAX;
+ if (!isGeneralTextEntity && standalone == 1) {
+ dtd.standalone = 1;
+#ifdef XML_DTD
+ if (paramEntityParsing == XML_PARAM_ENTITY_PARSING_UNLESS_STANDALONE)
+ paramEntityParsing = XML_PARAM_ENTITY_PARSING_NEVER;
+#endif /* XML_DTD */
+ }
+ if (xmlDeclHandler) {
+ if (encodingName) {
+ storedEncName = poolStoreString(&temp2Pool,
+ encoding,
+ encodingName,
+ encodingName
+ + XmlNameLength(encoding, encodingName));
+ if (! storedEncName)
+ return XML_ERROR_NO_MEMORY;
+ poolFinish(&temp2Pool);
+ }
+ if (version) {
+ storedversion = poolStoreString(&temp2Pool,
+ encoding,
+ version,
+ versionend - encoding->minBytesPerChar);
+ if (! storedversion)
+ return XML_ERROR_NO_MEMORY;
+ }
+ xmlDeclHandler(handlerArg, storedversion, storedEncName, standalone);
+ }
+ else if (defaultHandler)
+ reportDefault(parser, encoding, s, next);
+ if (!protocolEncodingName) {
+ if (newEncoding) {
+ if (newEncoding->minBytesPerChar != encoding->minBytesPerChar) {
+ eventPtr = encodingName;
+ return XML_ERROR_INCORRECT_ENCODING;
+ }
+ encoding = newEncoding;
+ }
+ else if (encodingName) {
+ enum XML_Error result;
+ if (! storedEncName) {
+ storedEncName = poolStoreString(&temp2Pool,
+ encoding,
+ encodingName,
+ encodingName
+ + XmlNameLength(encoding, encodingName));
+ if (! storedEncName)
+ return XML_ERROR_NO_MEMORY;
+ }
+ result = handleUnknownEncoding(parser, storedEncName);
+ poolClear(&tempPool);
+ if (result == XML_ERROR_UNKNOWN_ENCODING)
+ eventPtr = encodingName;
+ return result;
+ }
+ }
+
+ if (storedEncName || storedversion)
+ poolClear(&temp2Pool);
+
+ return XML_ERROR_NONE;
+}
+
+static enum XML_Error
+handleUnknownEncoding(XML_Parser parser, const XML_Char *encodingName)
+{
+ if (unknownEncodingHandler) {
+ XML_Encoding info;
+ int i;
+ for (i = 0; i < 256; i++)
+ info.map[i] = -1;
+ info.convert = 0;
+ info.data = 0;
+ info.release = 0;
+ if (unknownEncodingHandler(unknownEncodingHandlerData, encodingName, &info)) {
+ ENCODING *enc;
+ unknownEncodingMem = MALLOC(XmlSizeOfUnknownEncoding());
+ if (!unknownEncodingMem) {
+ if (info.release)
+ info.release(info.data);
+ return XML_ERROR_NO_MEMORY;
+ }
+ enc = (ns
+ ? XmlInitUnknownEncodingNS
+ : XmlInitUnknownEncoding)(unknownEncodingMem,
+ info.map,
+ info.convert,
+ info.data);
+ if (enc) {
+ unknownEncodingData = info.data;
+ unknownEncodingRelease = info.release;
+ encoding = enc;
+ return XML_ERROR_NONE;
+ }
+ }
+ if (info.release)
+ info.release(info.data);
+ }
+ return XML_ERROR_UNKNOWN_ENCODING;
+}
+
+static enum XML_Error
+prologInitProcessor(XML_Parser parser,
+ const char *s,
+ const char *end,
+ const char **nextPtr)
+{
+ enum XML_Error result = initializeEncoding(parser);
+ if (result != XML_ERROR_NONE)
+ return result;
+ processor = prologProcessor;
+ return prologProcessor(parser, s, end, nextPtr);
+}
+
+static enum XML_Error
+prologProcessor(XML_Parser parser,
+ const char *s,
+ const char *end,
+ const char **nextPtr)
+{
+ const char *next;
+ int tok = XmlPrologTok(encoding, s, end, &next);
+ return doProlog(parser, encoding, s, end, tok, next, nextPtr);
+}
+
+static enum XML_Error
+doProlog(XML_Parser parser,
+ const ENCODING *enc,
+ const char *s,
+ const char *end,
+ int tok,
+ const char *next,
+ const char **nextPtr)
+{
+#ifdef XML_DTD
+ static const XML_Char externalSubsetName[] = { '#' , '\0' };
+#endif /* XML_DTD */
+
+ const char **eventPP;
+ const char **eventEndPP;
+ enum XML_Content_Quant quant;
+
+ if (enc == encoding) {
+ eventPP = &eventPtr;
+ eventEndPP = &eventEndPtr;
+ }
+ else {
+ eventPP = &(openInternalEntities->internalEventPtr);
+ eventEndPP = &(openInternalEntities->internalEventEndPtr);
+ }
+ for (;;) {
+ int role;
+ *eventPP = s;
+ *eventEndPP = next;
+ if (tok <= 0) {
+ if (nextPtr != 0 && tok != XML_TOK_INVALID) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ switch (tok) {
+ case XML_TOK_INVALID:
+ *eventPP = next;
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_PARTIAL:
+ return XML_ERROR_UNCLOSED_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ return XML_ERROR_PARTIAL_CHAR;
+ case XML_TOK_NONE:
+#ifdef XML_DTD
+ if (enc != encoding)
+ return XML_ERROR_NONE;
+ if (parentParser) {
+ if (XmlTokenRole(&prologState, XML_TOK_NONE, end, end, enc)
+ == XML_ROLE_ERROR)
+ return XML_ERROR_SYNTAX;
+ hadExternalDoctype = 0;
+ return XML_ERROR_NONE;
+ }
+#endif /* XML_DTD */
+ return XML_ERROR_NO_ELEMENTS;
+ default:
+ tok = -tok;
+ next = end;
+ break;
+ }
+ }
+ role = XmlTokenRole(&prologState, tok, s, next, enc);
+ switch (role) {
+ case XML_ROLE_XML_DECL:
+ {
+ enum XML_Error result = processXmlDecl(parser, 0, s, next);
+ if (result != XML_ERROR_NONE)
+ return result;
+ enc = encoding;
+ }
+ break;
+ case XML_ROLE_DOCTYPE_NAME:
+ if (startDoctypeDeclHandler) {
+ doctypeName = poolStoreString(&tempPool, enc, s, next);
+ if (! doctypeName)
+ return XML_ERROR_NO_MEMORY;
+ poolFinish(&tempPool);
+ doctypeSysid = 0;
+ doctypePubid = 0;
+ }
+ break;
+ case XML_ROLE_DOCTYPE_INTERNAL_SUBSET:
+ if (startDoctypeDeclHandler) {
+ startDoctypeDeclHandler(handlerArg, doctypeName, doctypeSysid,
+ doctypePubid, 1);
+ doctypeName = 0;
+ poolClear(&tempPool);
+ }
+ break;
+#ifdef XML_DTD
+ case XML_ROLE_TEXT_DECL:
+ {
+ enum XML_Error result = processXmlDecl(parser, 1, s, next);
+ if (result != XML_ERROR_NONE)
+ return result;
+ enc = encoding;
+ }
+ break;
+#endif /* XML_DTD */
+ case XML_ROLE_DOCTYPE_PUBLIC_ID:
+ if (startDoctypeDeclHandler) {
+ doctypePubid = poolStoreString(&tempPool, enc, s + 1, next - 1);
+ if (! doctypePubid)
+ return XML_ERROR_NO_MEMORY;
+ poolFinish(&tempPool);
+ }
+#ifdef XML_DTD
+ declEntity = (ENTITY *)lookup(&dtd.paramEntities,
+ externalSubsetName,
+ sizeof(ENTITY));
+ if (!declEntity)
+ return XML_ERROR_NO_MEMORY;
+#endif /* XML_DTD */
+ /* fall through */
+ case XML_ROLE_ENTITY_PUBLIC_ID:
+ if (!XmlIsPublicId(enc, s, next, eventPP))
+ return XML_ERROR_SYNTAX;
+ if (declEntity) {
+ XML_Char *tem = poolStoreString(&dtd.pool,
+ enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (!tem)
+ return XML_ERROR_NO_MEMORY;
+ normalizePublicId(tem);
+ declEntity->publicId = tem;
+ poolFinish(&dtd.pool);
+ }
+ break;
+ case XML_ROLE_DOCTYPE_CLOSE:
+ if (doctypeName) {
+ startDoctypeDeclHandler(handlerArg, doctypeName,
+ doctypeSysid, doctypePubid, 0);
+ poolClear(&tempPool);
+ }
+ if (dtd.complete && hadExternalDoctype) {
+ dtd.complete = 0;
+#ifdef XML_DTD
+ if (paramEntityParsing && externalEntityRefHandler) {
+ ENTITY *entity = (ENTITY *)lookup(&dtd.paramEntities,
+ externalSubsetName,
+ 0);
+ if (!externalEntityRefHandler(externalEntityRefHandlerArg,
+ 0,
+ entity->base,
+ entity->systemId,
+ entity->publicId))
+ return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
+ }
+#endif /* XML_DTD */
+ if (!dtd.complete
+ && !dtd.standalone
+ && notStandaloneHandler
+ && !notStandaloneHandler(handlerArg))
+ return XML_ERROR_NOT_STANDALONE;
+ }
+ if (endDoctypeDeclHandler)
+ endDoctypeDeclHandler(handlerArg);
+ break;
+ case XML_ROLE_INSTANCE_START:
+ processor = contentProcessor;
+ return contentProcessor(parser, s, end, nextPtr);
+ case XML_ROLE_ATTLIST_ELEMENT_NAME:
+ declElementType = getElementType(parser, enc, s, next);
+ if (!declElementType)
+ return XML_ERROR_NO_MEMORY;
+ break;
+ case XML_ROLE_ATTRIBUTE_NAME:
+ declAttributeId = getAttributeId(parser, enc, s, next);
+ if (!declAttributeId)
+ return XML_ERROR_NO_MEMORY;
+ declAttributeIsCdata = 0;
+ declAttributeType = 0;
+ declAttributeIsId = 0;
+ break;
+ case XML_ROLE_ATTRIBUTE_TYPE_CDATA:
+ declAttributeIsCdata = 1;
+ declAttributeType = "CDATA";
+ break;
+ case XML_ROLE_ATTRIBUTE_TYPE_ID:
+ declAttributeIsId = 1;
+ declAttributeType = "ID";
+ break;
+ case XML_ROLE_ATTRIBUTE_TYPE_IDREF:
+ declAttributeType = "IDREF";
+ break;
+ case XML_ROLE_ATTRIBUTE_TYPE_IDREFS:
+ declAttributeType = "IDREFS";
+ break;
+ case XML_ROLE_ATTRIBUTE_TYPE_ENTITY:
+ declAttributeType = "ENTITY";
+ break;
+ case XML_ROLE_ATTRIBUTE_TYPE_ENTITIES:
+ declAttributeType = "ENTITIES";
+ break;
+ case XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN:
+ declAttributeType = "NMTOKEN";
+ break;
+ case XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS:
+ declAttributeType = "NMTOKENS";
+ break;
+
+ case XML_ROLE_ATTRIBUTE_ENUM_VALUE:
+ case XML_ROLE_ATTRIBUTE_NOTATION_VALUE:
+ if (attlistDeclHandler)
+ {
+ char *prefix;
+ if (declAttributeType) {
+ prefix = "|";
+ }
+ else {
+ prefix = (role == XML_ROLE_ATTRIBUTE_NOTATION_VALUE
+ ? "NOTATION("
+ : "(");
+ }
+ if (! poolAppendString(&tempPool, prefix))
+ return XML_ERROR_NO_MEMORY;
+ if (! poolAppend(&tempPool, enc, s, next))
+ return XML_ERROR_NO_MEMORY;
+ declAttributeType = tempPool.start;
+ }
+ break;
+ case XML_ROLE_IMPLIED_ATTRIBUTE_VALUE:
+ case XML_ROLE_REQUIRED_ATTRIBUTE_VALUE:
+ if (dtd.complete
+ && !defineAttribute(declElementType, declAttributeId,
+ declAttributeIsCdata, declAttributeIsId, 0,
+ parser))
+ return XML_ERROR_NO_MEMORY;
+ if (attlistDeclHandler && declAttributeType) {
+ if (*declAttributeType == '('
+ || (*declAttributeType == 'N' && declAttributeType[1] == 'O')) {
+ /* Enumerated or Notation type */
+ if (! poolAppendChar(&tempPool, ')')
+ || ! poolAppendChar(&tempPool, '\0'))
+ return XML_ERROR_NO_MEMORY;
+ declAttributeType = tempPool.start;
+ poolFinish(&tempPool);
+ }
+ *eventEndPP = s;
+ attlistDeclHandler(handlerArg, declElementType->name,
+ declAttributeId->name, declAttributeType,
+ 0, role == XML_ROLE_REQUIRED_ATTRIBUTE_VALUE);
+ poolClear(&tempPool);
+ }
+ break;
+ case XML_ROLE_DEFAULT_ATTRIBUTE_VALUE:
+ case XML_ROLE_FIXED_ATTRIBUTE_VALUE:
+ {
+ const XML_Char *attVal;
+ enum XML_Error result
+ = storeAttributeValue(parser, enc, declAttributeIsCdata,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar,
+ &dtd.pool);
+ if (result)
+ return result;
+ attVal = poolStart(&dtd.pool);
+ poolFinish(&dtd.pool);
+ if (dtd.complete
+ /* ID attributes aren't allowed to have a default */
+ && !defineAttribute(declElementType, declAttributeId, declAttributeIsCdata, 0, attVal, parser))
+ return XML_ERROR_NO_MEMORY;
+ if (attlistDeclHandler && declAttributeType) {
+ if (*declAttributeType == '('
+ || (*declAttributeType == 'N' && declAttributeType[1] == 'O')) {
+ /* Enumerated or Notation type */
+ if (! poolAppendChar(&tempPool, ')')
+ || ! poolAppendChar(&tempPool, '\0'))
+ return XML_ERROR_NO_MEMORY;
+ declAttributeType = tempPool.start;
+ poolFinish(&tempPool);
+ }
+ *eventEndPP = s;
+ attlistDeclHandler(handlerArg, declElementType->name,
+ declAttributeId->name, declAttributeType,
+ attVal,
+ role == XML_ROLE_FIXED_ATTRIBUTE_VALUE);
+ poolClear(&tempPool);
+ }
+ break;
+ }
+ case XML_ROLE_ENTITY_VALUE:
+ {
+ enum XML_Error result = storeEntityValue(parser, enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (declEntity) {
+ declEntity->textPtr = poolStart(&dtd.pool);
+ declEntity->textLen = poolLength(&dtd.pool);
+ poolFinish(&dtd.pool);
+ if (entityDeclHandler) {
+ *eventEndPP = s;
+ entityDeclHandler(handlerArg,
+ declEntity->name,
+ declEntity->is_param,
+ declEntity->textPtr,
+ declEntity->textLen,
+ curBase, 0, 0, 0);
+ }
+ }
+ else
+ poolDiscard(&dtd.pool);
+ if (result != XML_ERROR_NONE)
+ return result;
+ }
+ break;
+ case XML_ROLE_DOCTYPE_SYSTEM_ID:
+ if (startDoctypeDeclHandler) {
+ doctypeSysid = poolStoreString(&tempPool, enc, s + 1, next - 1);
+ if (! doctypeSysid)
+ return XML_ERROR_NO_MEMORY;
+ poolFinish(&tempPool);
+ }
+ if (!dtd.standalone
+#ifdef XML_DTD
+ && !paramEntityParsing
+#endif /* XML_DTD */
+ && notStandaloneHandler
+ && !notStandaloneHandler(handlerArg))
+ return XML_ERROR_NOT_STANDALONE;
+ hadExternalDoctype = 1;
+#ifndef XML_DTD
+ break;
+#else /* XML_DTD */
+ if (!declEntity) {
+ declEntity = (ENTITY *)lookup(&dtd.paramEntities,
+ externalSubsetName,
+ sizeof(ENTITY));
+ declEntity->publicId = 0;
+ if (!declEntity)
+ return XML_ERROR_NO_MEMORY;
+ }
+ /* fall through */
+#endif /* XML_DTD */
+ case XML_ROLE_ENTITY_SYSTEM_ID:
+ if (declEntity) {
+ declEntity->systemId = poolStoreString(&dtd.pool, enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (!declEntity->systemId)
+ return XML_ERROR_NO_MEMORY;
+ declEntity->base = curBase;
+ poolFinish(&dtd.pool);
+ }
+ break;
+ case XML_ROLE_ENTITY_COMPLETE:
+ if (declEntity && entityDeclHandler) {
+ *eventEndPP = s;
+ entityDeclHandler(handlerArg,
+ declEntity->name,
+ 0,0,0,
+ declEntity->base,
+ declEntity->systemId,
+ declEntity->publicId,
+ 0);
+ }
+ break;
+ case XML_ROLE_ENTITY_NOTATION_NAME:
+ if (declEntity) {
+ declEntity->notation = poolStoreString(&dtd.pool, enc, s, next);
+ if (!declEntity->notation)
+ return XML_ERROR_NO_MEMORY;
+ poolFinish(&dtd.pool);
+ if (unparsedEntityDeclHandler) {
+ *eventEndPP = s;
+ unparsedEntityDeclHandler(handlerArg,
+ declEntity->name,
+ declEntity->base,
+ declEntity->systemId,
+ declEntity->publicId,
+ declEntity->notation);
+ }
+ else if (entityDeclHandler) {
+ *eventEndPP = s;
+ entityDeclHandler(handlerArg,
+ declEntity->name,
+ 0,0,0,
+ declEntity->base,
+ declEntity->systemId,
+ declEntity->publicId,
+ declEntity->notation);
+ }
+ }
+ break;
+ case XML_ROLE_GENERAL_ENTITY_NAME:
+ {
+ const XML_Char *name;
+ if (XmlPredefinedEntityName(enc, s, next)) {
+ declEntity = 0;
+ break;
+ }
+ name = poolStoreString(&dtd.pool, enc, s, next);
+ if (!name)
+ return XML_ERROR_NO_MEMORY;
+ if (dtd.complete) {
+ declEntity = (ENTITY *)lookup(&dtd.generalEntities, name, sizeof(ENTITY));
+ if (!declEntity)
+ return XML_ERROR_NO_MEMORY;
+ if (declEntity->name != name) {
+ poolDiscard(&dtd.pool);
+ declEntity = 0;
+ }
+ else {
+ poolFinish(&dtd.pool);
+ declEntity->publicId = 0;
+ declEntity->is_param = 0;
+ }
+ }
+ else {
+ poolDiscard(&dtd.pool);
+ declEntity = 0;
+ }
+ }
+ break;
+ case XML_ROLE_PARAM_ENTITY_NAME:
+#ifdef XML_DTD
+ if (dtd.complete) {
+ const XML_Char *name = poolStoreString(&dtd.pool, enc, s, next);
+ if (!name)
+ return XML_ERROR_NO_MEMORY;
+ declEntity = (ENTITY *)lookup(&dtd.paramEntities,
+ name, sizeof(ENTITY));
+ if (!declEntity)
+ return XML_ERROR_NO_MEMORY;
+ if (declEntity->name != name) {
+ poolDiscard(&dtd.pool);
+ declEntity = 0;
+ }
+ else {
+ poolFinish(&dtd.pool);
+ declEntity->publicId = 0;
+ declEntity->is_param = 1;
+ }
+ }
+#else /* not XML_DTD */
+ declEntity = 0;
+#endif /* not XML_DTD */
+ break;
+ case XML_ROLE_NOTATION_NAME:
+ declNotationPublicId = 0;
+ declNotationName = 0;
+ if (notationDeclHandler) {
+ declNotationName = poolStoreString(&tempPool, enc, s, next);
+ if (!declNotationName)
+ return XML_ERROR_NO_MEMORY;
+ poolFinish(&tempPool);
+ }
+ break;
+ case XML_ROLE_NOTATION_PUBLIC_ID:
+ if (!XmlIsPublicId(enc, s, next, eventPP))
+ return XML_ERROR_SYNTAX;
+ if (declNotationName) {
+ XML_Char *tem = poolStoreString(&tempPool,
+ enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (!tem)
+ return XML_ERROR_NO_MEMORY;
+ normalizePublicId(tem);
+ declNotationPublicId = tem;
+ poolFinish(&tempPool);
+ }
+ break;
+ case XML_ROLE_NOTATION_SYSTEM_ID:
+ if (declNotationName && notationDeclHandler) {
+ const XML_Char *systemId
+ = poolStoreString(&tempPool, enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (!systemId)
+ return XML_ERROR_NO_MEMORY;
+ *eventEndPP = s;
+ notationDeclHandler(handlerArg,
+ declNotationName,
+ curBase,
+ systemId,
+ declNotationPublicId);
+ }
+ poolClear(&tempPool);
+ break;
+ case XML_ROLE_NOTATION_NO_SYSTEM_ID:
+ if (declNotationPublicId && notationDeclHandler) {
+ *eventEndPP = s;
+ notationDeclHandler(handlerArg,
+ declNotationName,
+ curBase,
+ 0,
+ declNotationPublicId);
+ }
+ poolClear(&tempPool);
+ break;
+ case XML_ROLE_ERROR:
+ switch (tok) {
+ case XML_TOK_PARAM_ENTITY_REF:
+ return XML_ERROR_PARAM_ENTITY_REF;
+ case XML_TOK_XML_DECL:
+ return XML_ERROR_MISPLACED_XML_PI;
+ default:
+ return XML_ERROR_SYNTAX;
+ }
+#ifdef XML_DTD
+ case XML_ROLE_IGNORE_SECT:
+ {
+ enum XML_Error result;
+ if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ result = doIgnoreSection(parser, enc, &next, end, nextPtr);
+ if (!next) {
+ processor = ignoreSectionProcessor;
+ return result;
+ }
+ }
+ break;
+#endif /* XML_DTD */
+ case XML_ROLE_GROUP_OPEN:
+ if (prologState.level >= groupSize) {
+ if (groupSize) {
+ groupConnector = REALLOC(groupConnector, groupSize *= 2);
+ if (dtd.scaffIndex)
+ dtd.scaffIndex = REALLOC(dtd.scaffIndex, groupSize * sizeof(int));
+ }
+ else
+ groupConnector = MALLOC(groupSize = 32);
+ if (!groupConnector)
+ return XML_ERROR_NO_MEMORY;
+ }
+ groupConnector[prologState.level] = 0;
+ if (dtd.in_eldecl) {
+ int myindex = nextScaffoldPart(parser);
+ if (myindex < 0)
+ return XML_ERROR_NO_MEMORY;
+ dtd.scaffIndex[dtd.scaffLevel] = myindex;
+ dtd.scaffLevel++;
+ dtd.scaffold[myindex].type = XML_CTYPE_SEQ;
+ }
+ break;
+ case XML_ROLE_GROUP_SEQUENCE:
+ if (groupConnector[prologState.level] == '|')
+ return XML_ERROR_SYNTAX;
+ groupConnector[prologState.level] = ',';
+ break;
+ case XML_ROLE_GROUP_CHOICE:
+ if (groupConnector[prologState.level] == ',')
+ return XML_ERROR_SYNTAX;
+ if (dtd.in_eldecl
+ && ! groupConnector[prologState.level]
+ && dtd.scaffold[dtd.scaffIndex[dtd.scaffLevel - 1]].type != XML_CTYPE_MIXED
+ ) {
+ dtd.scaffold[dtd.scaffIndex[dtd.scaffLevel - 1]].type = XML_CTYPE_CHOICE;
+ }
+ groupConnector[prologState.level] = '|';
+ break;
+ case XML_ROLE_PARAM_ENTITY_REF:
+#ifdef XML_DTD
+ case XML_ROLE_INNER_PARAM_ENTITY_REF:
+ if (paramEntityParsing
+ && (dtd.complete || role == XML_ROLE_INNER_PARAM_ENTITY_REF)) {
+ const XML_Char *name;
+ ENTITY *entity;
+ name = poolStoreString(&dtd.pool, enc,
+ s + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (!name)
+ return XML_ERROR_NO_MEMORY;
+ entity = (ENTITY *)lookup(&dtd.paramEntities, name, 0);
+ poolDiscard(&dtd.pool);
+ if (!entity) {
+ /* FIXME what to do if !dtd.complete? */
+ return XML_ERROR_UNDEFINED_ENTITY;
+ }
+ if (entity->open)
+ return XML_ERROR_RECURSIVE_ENTITY_REF;
+ if (entity->textPtr) {
+ enum XML_Error result;
+ result = processInternalParamEntity(parser, entity);
+ if (result != XML_ERROR_NONE)
+ return result;
+ break;
+ }
+ if (role == XML_ROLE_INNER_PARAM_ENTITY_REF)
+ return XML_ERROR_PARAM_ENTITY_REF;
+ if (externalEntityRefHandler) {
+ dtd.complete = 0;
+ entity->open = 1;
+ if (!externalEntityRefHandler(externalEntityRefHandlerArg,
+ 0,
+ entity->base,
+ entity->systemId,
+ entity->publicId)) {
+ entity->open = 0;
+ return XML_ERROR_EXTERNAL_ENTITY_HANDLING;
+ }
+ entity->open = 0;
+ if (dtd.complete)
+ break;
+ }
+ }
+#endif /* XML_DTD */
+ if (!dtd.standalone
+ && notStandaloneHandler
+ && !notStandaloneHandler(handlerArg))
+ return XML_ERROR_NOT_STANDALONE;
+ dtd.complete = 0;
+ if (defaultHandler)
+ reportDefault(parser, enc, s, next);
+ break;
+
+ /* Element declaration stuff */
+
+ case XML_ROLE_ELEMENT_NAME:
+ if (elementDeclHandler) {
+ declElementType = getElementType(parser, enc, s, next);
+ if (! declElementType)
+ return XML_ERROR_NO_MEMORY;
+ dtd.scaffLevel = 0;
+ dtd.scaffCount = 0;
+ dtd.in_eldecl = 1;
+ }
+ break;
+
+ case XML_ROLE_CONTENT_ANY:
+ case XML_ROLE_CONTENT_EMPTY:
+ if (dtd.in_eldecl) {
+ if (elementDeclHandler) {
+ XML_Content * content = (XML_Content *) MALLOC(sizeof(XML_Content));
+ if (! content)
+ return XML_ERROR_NO_MEMORY;
+ content->quant = XML_CQUANT_NONE;
+ content->name = 0;
+ content->numchildren = 0;
+ content->children = 0;
+ content->type = ((role == XML_ROLE_CONTENT_ANY) ?
+ XML_CTYPE_ANY :
+ XML_CTYPE_EMPTY);
+ *eventEndPP = s;
+ elementDeclHandler(handlerArg, declElementType->name, content);
+ }
+ dtd.in_eldecl = 0;
+ }
+ break;
+
+ case XML_ROLE_CONTENT_PCDATA:
+ if (dtd.in_eldecl) {
+ dtd.scaffold[dtd.scaffIndex[dtd.scaffLevel - 1]].type = XML_CTYPE_MIXED;
+ }
+ break;
+
+ case XML_ROLE_CONTENT_ELEMENT:
+ quant = XML_CQUANT_NONE;
+ goto elementContent;
+ case XML_ROLE_CONTENT_ELEMENT_OPT:
+ quant = XML_CQUANT_OPT;
+ goto elementContent;
+ case XML_ROLE_CONTENT_ELEMENT_REP:
+ quant = XML_CQUANT_REP;
+ goto elementContent;
+ case XML_ROLE_CONTENT_ELEMENT_PLUS:
+ quant = XML_CQUANT_PLUS;
+ elementContent:
+ if (dtd.in_eldecl)
+ {
+ ELEMENT_TYPE *el;
+ const char *nxt = quant == XML_CQUANT_NONE ? next : next - 1;
+ int myindex = nextScaffoldPart(parser);
+ if (myindex < 0)
+ return XML_ERROR_NO_MEMORY;
+ dtd.scaffold[myindex].type = XML_CTYPE_NAME;
+ dtd.scaffold[myindex].quant = quant;
+ el = getElementType(parser, enc, s, nxt);
+ if (! el)
+ return XML_ERROR_NO_MEMORY;
+ dtd.scaffold[myindex].name = el->name;
+ dtd.contentStringLen += nxt - s + 1;
+ }
+ break;
+
+ case XML_ROLE_GROUP_CLOSE:
+ quant = XML_CQUANT_NONE;
+ goto closeGroup;
+ case XML_ROLE_GROUP_CLOSE_OPT:
+ quant = XML_CQUANT_OPT;
+ goto closeGroup;
+ case XML_ROLE_GROUP_CLOSE_REP:
+ quant = XML_CQUANT_REP;
+ goto closeGroup;
+ case XML_ROLE_GROUP_CLOSE_PLUS:
+ quant = XML_CQUANT_PLUS;
+ closeGroup:
+ if (dtd.in_eldecl) {
+ dtd.scaffLevel--;
+ dtd.scaffold[dtd.scaffIndex[dtd.scaffLevel]].quant = quant;
+ if (dtd.scaffLevel == 0) {
+ if (elementDeclHandler) {
+ XML_Content *model = build_model(parser);
+ if (! model)
+ return XML_ERROR_NO_MEMORY;
+ *eventEndPP = s;
+ elementDeclHandler(handlerArg, declElementType->name, model);
+ }
+ dtd.in_eldecl = 0;
+ dtd.contentStringLen = 0;
+ }
+ }
+ break;
+ /* End element declaration stuff */
+
+ case XML_ROLE_NONE:
+ switch (tok) {
+ case XML_TOK_PI:
+ if (!reportProcessingInstruction(parser, enc, s, next))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ case XML_TOK_COMMENT:
+ if (!reportComment(parser, enc, s, next))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ }
+ break;
+ }
+ if (defaultHandler) {
+ switch (tok) {
+ case XML_TOK_PI:
+ case XML_TOK_COMMENT:
+ case XML_TOK_BOM:
+ case XML_TOK_XML_DECL:
+#ifdef XML_DTD
+ case XML_TOK_IGNORE_SECT:
+#endif /* XML_DTD */
+ case XML_TOK_PARAM_ENTITY_REF:
+ break;
+ default:
+#ifdef XML_DTD
+ if (role != XML_ROLE_IGNORE_SECT)
+#endif /* XML_DTD */
+ reportDefault(parser, enc, s, next);
+ }
+ }
+ s = next;
+ tok = XmlPrologTok(enc, s, end, &next);
+ }
+ /* not reached */
+}
+
+static
+enum XML_Error epilogProcessor(XML_Parser parser,
+ const char *s,
+ const char *end,
+ const char **nextPtr)
+{
+ processor = epilogProcessor;
+ eventPtr = s;
+ for (;;) {
+ const char *next;
+ int tok = XmlPrologTok(encoding, s, end, &next);
+ eventEndPtr = next;
+ switch (tok) {
+ case -XML_TOK_PROLOG_S:
+ if (defaultHandler) {
+ eventEndPtr = end;
+ reportDefault(parser, encoding, s, end);
+ }
+ /* fall through */
+ case XML_TOK_NONE:
+ if (nextPtr)
+ *nextPtr = end;
+ return XML_ERROR_NONE;
+ case XML_TOK_PROLOG_S:
+ if (defaultHandler)
+ reportDefault(parser, encoding, s, next);
+ break;
+ case XML_TOK_PI:
+ if (!reportProcessingInstruction(parser, encoding, s, next))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ case XML_TOK_COMMENT:
+ if (!reportComment(parser, encoding, s, next))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ case XML_TOK_INVALID:
+ eventPtr = next;
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_PARTIAL:
+ if (nextPtr) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_UNCLOSED_TOKEN;
+ case XML_TOK_PARTIAL_CHAR:
+ if (nextPtr) {
+ *nextPtr = s;
+ return XML_ERROR_NONE;
+ }
+ return XML_ERROR_PARTIAL_CHAR;
+ default:
+ return XML_ERROR_JUNK_AFTER_DOC_ELEMENT;
+ }
+ eventPtr = s = next;
+ }
+}
+
+#ifdef XML_DTD
+
+static enum XML_Error
+processInternalParamEntity(XML_Parser parser, ENTITY *entity)
+{
+ const char *s, *end, *next;
+ int tok;
+ enum XML_Error result;
+ OPEN_INTERNAL_ENTITY openEntity;
+ entity->open = 1;
+ openEntity.next = openInternalEntities;
+ openInternalEntities = &openEntity;
+ openEntity.entity = entity;
+ openEntity.internalEventPtr = 0;
+ openEntity.internalEventEndPtr = 0;
+ s = (char *)entity->textPtr;
+ end = (char *)(entity->textPtr + entity->textLen);
+ tok = XmlPrologTok(internalEncoding, s, end, &next);
+ result = doProlog(parser, internalEncoding, s, end, tok, next, 0);
+ entity->open = 0;
+ openInternalEntities = openEntity.next;
+ return result;
+}
+
+#endif /* XML_DTD */
+
+static
+enum XML_Error errorProcessor(XML_Parser parser,
+ const char *s,
+ const char *end,
+ const char **nextPtr)
+{
+ return errorCode;
+}
+
+static enum XML_Error
+storeAttributeValue(XML_Parser parser, const ENCODING *enc, int isCdata,
+ const char *ptr, const char *end,
+ STRING_POOL *pool)
+{
+ enum XML_Error result = appendAttributeValue(parser, enc, isCdata, ptr, end, pool);
+ if (result)
+ return result;
+ if (!isCdata && poolLength(pool) && poolLastChar(pool) == 0x20)
+ poolChop(pool);
+ if (!poolAppendChar(pool, XML_T('\0')))
+ return XML_ERROR_NO_MEMORY;
+ return XML_ERROR_NONE;
+}
+
+static enum XML_Error
+appendAttributeValue(XML_Parser parser, const ENCODING *enc, int isCdata,
+ const char *ptr, const char *end,
+ STRING_POOL *pool)
+{
+ for (;;) {
+ const char *next;
+ int tok = XmlAttributeValueTok(enc, ptr, end, &next);
+ switch (tok) {
+ case XML_TOK_NONE:
+ return XML_ERROR_NONE;
+ case XML_TOK_INVALID:
+ if (enc == encoding)
+ eventPtr = next;
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_PARTIAL:
+ if (enc == encoding)
+ eventPtr = ptr;
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_CHAR_REF:
+ {
+ XML_Char buf[XML_ENCODE_MAX];
+ int i;
+ int n = XmlCharRefNumber(enc, ptr);
+ if (n < 0) {
+ if (enc == encoding)
+ eventPtr = ptr;
+ return XML_ERROR_BAD_CHAR_REF;
+ }
+ if (!isCdata
+ && n == 0x20 /* space */
+ && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
+ break;
+ n = XmlEncode(n, (ICHAR *)buf);
+ if (!n) {
+ if (enc == encoding)
+ eventPtr = ptr;
+ return XML_ERROR_BAD_CHAR_REF;
+ }
+ for (i = 0; i < n; i++) {
+ if (!poolAppendChar(pool, buf[i]))
+ return XML_ERROR_NO_MEMORY;
+ }
+ }
+ break;
+ case XML_TOK_DATA_CHARS:
+ if (!poolAppend(pool, enc, ptr, next))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ break;
+ case XML_TOK_TRAILING_CR:
+ next = ptr + enc->minBytesPerChar;
+ /* fall through */
+ case XML_TOK_ATTRIBUTE_VALUE_S:
+ case XML_TOK_DATA_NEWLINE:
+ if (!isCdata && (poolLength(pool) == 0 || poolLastChar(pool) == 0x20))
+ break;
+ if (!poolAppendChar(pool, 0x20))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ case XML_TOK_ENTITY_REF:
+ {
+ const XML_Char *name;
+ ENTITY *entity;
+ XML_Char ch = XmlPredefinedEntityName(enc,
+ ptr + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (ch) {
+ if (!poolAppendChar(pool, ch))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ }
+ name = poolStoreString(&temp2Pool, enc,
+ ptr + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (!name)
+ return XML_ERROR_NO_MEMORY;
+ entity = (ENTITY *)lookup(&dtd.generalEntities, name, 0);
+ poolDiscard(&temp2Pool);
+ if (!entity) {
+ if (dtd.complete) {
+ if (enc == encoding)
+ eventPtr = ptr;
+ return XML_ERROR_UNDEFINED_ENTITY;
+ }
+ }
+ else if (entity->open) {
+ if (enc == encoding)
+ eventPtr = ptr;
+ return XML_ERROR_RECURSIVE_ENTITY_REF;
+ }
+ else if (entity->notation) {
+ if (enc == encoding)
+ eventPtr = ptr;
+ return XML_ERROR_BINARY_ENTITY_REF;
+ }
+ else if (!entity->textPtr) {
+ if (enc == encoding)
+ eventPtr = ptr;
+ return XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF;
+ }
+ else {
+ enum XML_Error result;
+ const XML_Char *textEnd = entity->textPtr + entity->textLen;
+ entity->open = 1;
+ result = appendAttributeValue(parser, internalEncoding, isCdata, (char *)entity->textPtr, (char *)textEnd, pool);
+ entity->open = 0;
+ if (result)
+ return result;
+ }
+ }
+ break;
+ default:
+ if (enc == encoding)
+ eventPtr = ptr;
+ return XML_ERROR_UNEXPECTED_STATE;
+ }
+ ptr = next;
+ }
+ /* not reached */
+}
+
+static
+enum XML_Error storeEntityValue(XML_Parser parser,
+ const ENCODING *enc,
+ const char *entityTextPtr,
+ const char *entityTextEnd)
+{
+ STRING_POOL *pool = &(dtd.pool);
+ for (;;) {
+ const char *next;
+ int tok = XmlEntityValueTok(enc, entityTextPtr, entityTextEnd, &next);
+ switch (tok) {
+ case XML_TOK_PARAM_ENTITY_REF:
+#ifdef XML_DTD
+ if (parentParser || enc != encoding) {
+ enum XML_Error result;
+ const XML_Char *name;
+ ENTITY *entity;
+ name = poolStoreString(&tempPool, enc,
+ entityTextPtr + enc->minBytesPerChar,
+ next - enc->minBytesPerChar);
+ if (!name)
+ return XML_ERROR_NO_MEMORY;
+ entity = (ENTITY *)lookup(&dtd.paramEntities, name, 0);
+ poolDiscard(&tempPool);
+ if (!entity) {
+ if (enc == encoding)
+ eventPtr = entityTextPtr;
+ return XML_ERROR_UNDEFINED_ENTITY;
+ }
+ if (entity->open) {
+ if (enc == encoding)
+ eventPtr = entityTextPtr;
+ return XML_ERROR_RECURSIVE_ENTITY_REF;
+ }
+ if (entity->systemId) {
+ if (enc == encoding)
+ eventPtr = entityTextPtr;
+ return XML_ERROR_PARAM_ENTITY_REF;
+ }
+ entity->open = 1;
+ result = storeEntityValue(parser,
+ internalEncoding,
+ (char *)entity->textPtr,
+ (char *)(entity->textPtr + entity->textLen));
+ entity->open = 0;
+ if (result)
+ return result;
+ break;
+ }
+#endif /* XML_DTD */
+ eventPtr = entityTextPtr;
+ return XML_ERROR_SYNTAX;
+ case XML_TOK_NONE:
+ return XML_ERROR_NONE;
+ case XML_TOK_ENTITY_REF:
+ case XML_TOK_DATA_CHARS:
+ if (!poolAppend(pool, enc, entityTextPtr, next))
+ return XML_ERROR_NO_MEMORY;
+ break;
+ case XML_TOK_TRAILING_CR:
+ next = entityTextPtr + enc->minBytesPerChar;
+ /* fall through */
+ case XML_TOK_DATA_NEWLINE:
+ if (pool->end == pool->ptr && !poolGrow(pool))
+ return XML_ERROR_NO_MEMORY;
+ *(pool->ptr)++ = 0xA;
+ break;
+ case XML_TOK_CHAR_REF:
+ {
+ XML_Char buf[XML_ENCODE_MAX];
+ int i;
+ int n = XmlCharRefNumber(enc, entityTextPtr);
+ if (n < 0) {
+ if (enc == encoding)
+ eventPtr = entityTextPtr;
+ return XML_ERROR_BAD_CHAR_REF;
+ }
+ n = XmlEncode(n, (ICHAR *)buf);
+ if (!n) {
+ if (enc == encoding)
+ eventPtr = entityTextPtr;
+ return XML_ERROR_BAD_CHAR_REF;
+ }
+ for (i = 0; i < n; i++) {
+ if (pool->end == pool->ptr && !poolGrow(pool))
+ return XML_ERROR_NO_MEMORY;
+ *(pool->ptr)++ = buf[i];
+ }
+ }
+ break;
+ case XML_TOK_PARTIAL:
+ if (enc == encoding)
+ eventPtr = entityTextPtr;
+ return XML_ERROR_INVALID_TOKEN;
+ case XML_TOK_INVALID:
+ if (enc == encoding)
+ eventPtr = next;
+ return XML_ERROR_INVALID_TOKEN;
+ default:
+ if (enc == encoding)
+ eventPtr = entityTextPtr;
+ return XML_ERROR_UNEXPECTED_STATE;
+ }
+ entityTextPtr = next;
+ }
+ /* not reached */
+}
+
+static void
+normalizeLines(XML_Char *s)
+{
+ XML_Char *p;
+ for (;; s++) {
+ if (*s == XML_T('\0'))
+ return;
+ if (*s == 0xD)
+ break;
+ }
+ p = s;
+ do {
+ if (*s == 0xD) {
+ *p++ = 0xA;
+ if (*++s == 0xA)
+ s++;
+ }
+ else
+ *p++ = *s++;
+ } while (*s);
+ *p = XML_T('\0');
+}
+
+static int
+reportProcessingInstruction(XML_Parser parser, const ENCODING *enc, const char *start, const char *end)
+{
+ const XML_Char *target;
+ XML_Char *data;
+ const char *tem;
+ if (!processingInstructionHandler) {
+ if (defaultHandler)
+ reportDefault(parser, enc, start, end);
+ return 1;
+ }
+ start += enc->minBytesPerChar * 2;
+ tem = start + XmlNameLength(enc, start);
+ target = poolStoreString(&tempPool, enc, start, tem);
+ if (!target)
+ return 0;
+ poolFinish(&tempPool);
+ data = poolStoreString(&tempPool, enc,
+ XmlSkipS(enc, tem),
+ end - enc->minBytesPerChar*2);
+ if (!data)
+ return 0;
+ normalizeLines(data);
+ processingInstructionHandler(handlerArg, target, data);
+ poolClear(&tempPool);
+ return 1;
+}
+
+static int
+reportComment(XML_Parser parser, const ENCODING *enc, const char *start, const char *end)
+{
+ XML_Char *data;
+ if (!commentHandler) {
+ if (defaultHandler)
+ reportDefault(parser, enc, start, end);
+ return 1;
+ }
+ data = poolStoreString(&tempPool,
+ enc,
+ start + enc->minBytesPerChar * 4,
+ end - enc->minBytesPerChar * 3);
+ if (!data)
+ return 0;
+ normalizeLines(data);
+ commentHandler(handlerArg, data);
+ poolClear(&tempPool);
+ return 1;
+}
+
+static void
+reportDefault(XML_Parser parser, const ENCODING *enc, const char *s, const char *end)
+{
+ if (MUST_CONVERT(enc, s)) {
+ const char **eventPP;
+ const char **eventEndPP;
+ if (enc == encoding) {
+ eventPP = &eventPtr;
+ eventEndPP = &eventEndPtr;
+ }
+ else {
+ eventPP = &(openInternalEntities->internalEventPtr);
+ eventEndPP = &(openInternalEntities->internalEventEndPtr);
+ }
+ do {
+ ICHAR *dataPtr = (ICHAR *)dataBuf;
+ XmlConvert(enc, &s, end, &dataPtr, (ICHAR *)dataBufEnd);
+ *eventEndPP = s;
+ defaultHandler(handlerArg, dataBuf, dataPtr - (ICHAR *)dataBuf);
+ *eventPP = s;
+ } while (s != end);
+ }
+ else
+ defaultHandler(handlerArg, (XML_Char *)s, (XML_Char *)end - (XML_Char *)s);
+}
+
+
+static int
+defineAttribute(ELEMENT_TYPE *type, ATTRIBUTE_ID *attId, int isCdata,
+ int isId, const XML_Char *value, XML_Parser parser)
+{
+ DEFAULT_ATTRIBUTE *att;
+ if (value || isId) {
+ /* The handling of default attributes gets messed up if we have
+ a default which duplicates a non-default. */
+ int i;
+ for (i = 0; i < type->nDefaultAtts; i++)
+ if (attId == type->defaultAtts[i].id)
+ return 1;
+ if (isId && !type->idAtt && !attId->xmlns)
+ type->idAtt = attId;
+ }
+ if (type->nDefaultAtts == type->allocDefaultAtts) {
+ if (type->allocDefaultAtts == 0) {
+ type->allocDefaultAtts = 8;
+ type->defaultAtts = MALLOC(type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE));
+ }
+ else {
+ type->allocDefaultAtts *= 2;
+ type->defaultAtts = REALLOC(type->defaultAtts,
+ type->allocDefaultAtts*sizeof(DEFAULT_ATTRIBUTE));
+ }
+ if (!type->defaultAtts)
+ return 0;
+ }
+ att = type->defaultAtts + type->nDefaultAtts;
+ att->id = attId;
+ att->value = value;
+ att->isCdata = isCdata;
+ if (!isCdata)
+ attId->maybeTokenized = 1;
+ type->nDefaultAtts += 1;
+ return 1;
+}
+
+static int setElementTypePrefix(XML_Parser parser, ELEMENT_TYPE *elementType)
+{
+ const XML_Char *name;
+ for (name = elementType->name; *name; name++) {
+ if (*name == XML_T(':')) {
+ PREFIX *prefix;
+ const XML_Char *s;
+ for (s = elementType->name; s != name; s++) {
+ if (!poolAppendChar(&dtd.pool, *s))
+ return 0;
+ }
+ if (!poolAppendChar(&dtd.pool, XML_T('\0')))
+ return 0;
+ prefix = (PREFIX *)lookup(&dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX));
+ if (!prefix)
+ return 0;
+ if (prefix->name == poolStart(&dtd.pool))
+ poolFinish(&dtd.pool);
+ else
+ poolDiscard(&dtd.pool);
+ elementType->prefix = prefix;
+
+ }
+ }
+ return 1;
+}
+
+static ATTRIBUTE_ID *
+getAttributeId(XML_Parser parser, const ENCODING *enc, const char *start, const char *end)
+{
+ ATTRIBUTE_ID *id;
+ const XML_Char *name;
+ if (!poolAppendChar(&dtd.pool, XML_T('\0')))
+ return 0;
+ name = poolStoreString(&dtd.pool, enc, start, end);
+ if (!name)
+ return 0;
+ ++name;
+ id = (ATTRIBUTE_ID *)lookup(&dtd.attributeIds, name, sizeof(ATTRIBUTE_ID));
+ if (!id)
+ return 0;
+ if (id->name != name)
+ poolDiscard(&dtd.pool);
+ else {
+ poolFinish(&dtd.pool);
+ if (!ns)
+ ;
+ else if (name[0] == 'x'
+ && name[1] == 'm'
+ && name[2] == 'l'
+ && name[3] == 'n'
+ && name[4] == 's'
+ && (name[5] == XML_T('\0') || name[5] == XML_T(':'))) {
+ if (name[5] == '\0')
+ id->prefix = &dtd.defaultPrefix;
+ else
+ id->prefix = (PREFIX *)lookup(&dtd.prefixes, name + 6, sizeof(PREFIX));
+ id->xmlns = 1;
+ }
+ else {
+ int i;
+ for (i = 0; name[i]; i++) {
+ if (name[i] == XML_T(':')) {
+ int j;
+ for (j = 0; j < i; j++) {
+ if (!poolAppendChar(&dtd.pool, name[j]))
+ return 0;
+ }
+ if (!poolAppendChar(&dtd.pool, XML_T('\0')))
+ return 0;
+ id->prefix = (PREFIX *)lookup(&dtd.prefixes, poolStart(&dtd.pool), sizeof(PREFIX));
+ if (id->prefix->name == poolStart(&dtd.pool))
+ poolFinish(&dtd.pool);
+ else
+ poolDiscard(&dtd.pool);
+ break;
+ }
+ }
+ }
+ }
+ return id;
+}
+
+#define CONTEXT_SEP XML_T('\f')
+
+static
+const XML_Char *getContext(XML_Parser parser)
+{
+ HASH_TABLE_ITER iter;
+ int needSep = 0;
+
+ if (dtd.defaultPrefix.binding) {
+ int i;
+ int len;
+ if (!poolAppendChar(&tempPool, XML_T('=')))
+ return 0;
+ len = dtd.defaultPrefix.binding->uriLen;
+ if (namespaceSeparator != XML_T('\0'))
+ len--;
+ for (i = 0; i < len; i++)
+ if (!poolAppendChar(&tempPool, dtd.defaultPrefix.binding->uri[i]))
+ return 0;
+ needSep = 1;
+ }
+
+ hashTableIterInit(&iter, &(dtd.prefixes));
+ for (;;) {
+ int i;
+ int len;
+ const XML_Char *s;
+ PREFIX *prefix = (PREFIX *)hashTableIterNext(&iter);
+ if (!prefix)
+ break;
+ if (!prefix->binding)
+ continue;
+ if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
+ return 0;
+ for (s = prefix->name; *s; s++)
+ if (!poolAppendChar(&tempPool, *s))
+ return 0;
+ if (!poolAppendChar(&tempPool, XML_T('=')))
+ return 0;
+ len = prefix->binding->uriLen;
+ if (namespaceSeparator != XML_T('\0'))
+ len--;
+ for (i = 0; i < len; i++)
+ if (!poolAppendChar(&tempPool, prefix->binding->uri[i]))
+ return 0;
+ needSep = 1;
+ }
+
+
+ hashTableIterInit(&iter, &(dtd.generalEntities));
+ for (;;) {
+ const XML_Char *s;
+ ENTITY *e = (ENTITY *)hashTableIterNext(&iter);
+ if (!e)
+ break;
+ if (!e->open)
+ continue;
+ if (needSep && !poolAppendChar(&tempPool, CONTEXT_SEP))
+ return 0;
+ for (s = e->name; *s; s++)
+ if (!poolAppendChar(&tempPool, *s))
+ return 0;
+ needSep = 1;
+ }
+
+ if (!poolAppendChar(&tempPool, XML_T('\0')))
+ return 0;
+ return tempPool.start;
+}
+
+static
+int setContext(XML_Parser parser, const XML_Char *context)
+{
+ const XML_Char *s = context;
+
+ while (*context != XML_T('\0')) {
+ if (*s == CONTEXT_SEP || *s == XML_T('\0')) {
+ ENTITY *e;
+ if (!poolAppendChar(&tempPool, XML_T('\0')))
+ return 0;
+ e = (ENTITY *)lookup(&dtd.generalEntities, poolStart(&tempPool), 0);
+ if (e)
+ e->open = 1;
+ if (*s != XML_T('\0'))
+ s++;
+ context = s;
+ poolDiscard(&tempPool);
+ }
+ else if (*s == '=') {
+ PREFIX *prefix;
+ if (poolLength(&tempPool) == 0)
+ prefix = &dtd.defaultPrefix;
+ else {
+ if (!poolAppendChar(&tempPool, XML_T('\0')))
+ return 0;
+ prefix = (PREFIX *)lookup(&dtd.prefixes, poolStart(&tempPool), sizeof(PREFIX));
+ if (!prefix)
+ return 0;
+ if (prefix->name == poolStart(&tempPool)) {
+ prefix->name = poolCopyString(&dtd.pool, prefix->name);
+ if (!prefix->name)
+ return 0;
+ }
+ poolDiscard(&tempPool);
+ }
+ for (context = s + 1; *context != CONTEXT_SEP && *context != XML_T('\0'); context++)
+ if (!poolAppendChar(&tempPool, *context))
+ return 0;
+ if (!poolAppendChar(&tempPool, XML_T('\0')))
+ return 0;
+ if (!addBinding(parser, prefix, 0, poolStart(&tempPool), &inheritedBindings))
+ return 0;
+ poolDiscard(&tempPool);
+ if (*context != XML_T('\0'))
+ ++context;
+ s = context;
+ }
+ else {
+ if (!poolAppendChar(&tempPool, *s))
+ return 0;
+ s++;
+ }
+ }
+ return 1;
+}
+
+
+static
+void normalizePublicId(XML_Char *publicId)
+{
+ XML_Char *p = publicId;
+ XML_Char *s;
+ for (s = publicId; *s; s++) {
+ switch (*s) {
+ case 0x20:
+ case 0xD:
+ case 0xA:
+ if (p != publicId && p[-1] != 0x20)
+ *p++ = 0x20;
+ break;
+ default:
+ *p++ = *s;
+ }
+ }
+ if (p != publicId && p[-1] == 0x20)
+ --p;
+ *p = XML_T('\0');
+}
+
+static int dtdInit(DTD *p, XML_Parser parser)
+{
+ XML_Memory_Handling_Suite *ms = &((Parser *) parser)->m_mem;
+ poolInit(&(p->pool), ms);
+ hashTableInit(&(p->generalEntities), ms);
+ hashTableInit(&(p->elementTypes), ms);
+ hashTableInit(&(p->attributeIds), ms);
+ hashTableInit(&(p->prefixes), ms);
+ p->complete = 1;
+ p->standalone = 0;
+#ifdef XML_DTD
+ hashTableInit(&(p->paramEntities), ms);
+#endif /* XML_DTD */
+ p->defaultPrefix.name = 0;
+ p->defaultPrefix.binding = 0;
+
+ p->in_eldecl = 0;
+ p->scaffIndex = 0;
+ p->scaffLevel = 0;
+ p->scaffold = 0;
+ p->contentStringLen = 0;
+ p->scaffSize = 0;
+ p->scaffCount = 0;
+
+ return 1;
+}
+
+#ifdef XML_DTD
+
+static void dtdSwap(DTD *p1, DTD *p2)
+{
+ DTD tem;
+ memcpy(&tem, p1, sizeof(DTD));
+ memcpy(p1, p2, sizeof(DTD));
+ memcpy(p2, &tem, sizeof(DTD));
+}
+
+#endif /* XML_DTD */
+
+static void dtdDestroy(DTD *p, XML_Parser parser)
+{
+ HASH_TABLE_ITER iter;
+ hashTableIterInit(&iter, &(p->elementTypes));
+ for (;;) {
+ ELEMENT_TYPE *e = (ELEMENT_TYPE *)hashTableIterNext(&iter);
+ if (!e)
+ break;
+ if (e->allocDefaultAtts != 0)
+ FREE(e->defaultAtts);
+ }
+ hashTableDestroy(&(p->generalEntities));
+#ifdef XML_DTD
+ hashTableDestroy(&(p->paramEntities));
+#endif /* XML_DTD */
+ hashTableDestroy(&(p->elementTypes));
+ hashTableDestroy(&(p->attributeIds));
+ hashTableDestroy(&(p->prefixes));
+ poolDestroy(&(p->pool));
+ if (p->scaffIndex)
+ FREE(p->scaffIndex);
+ if (p->scaffold)
+ FREE(p->scaffold);
+}
+
+/* Do a deep copy of the DTD. Return 0 for out of memory; non-zero otherwise.
+The new DTD has already been initialized. */
+
+static int dtdCopy(DTD *newDtd, const DTD *oldDtd, XML_Parser parser)
+{
+ HASH_TABLE_ITER iter;
+
+ /* Copy the prefix table. */
+
+ hashTableIterInit(&iter, &(oldDtd->prefixes));
+ for (;;) {
+ const XML_Char *name;
+ const PREFIX *oldP = (PREFIX *)hashTableIterNext(&iter);
+ if (!oldP)
+ break;
+ name = poolCopyString(&(newDtd->pool), oldP->name);
+ if (!name)
+ return 0;
+ if (!lookup(&(newDtd->prefixes), name, sizeof(PREFIX)))
+ return 0;
+ }
+
+ hashTableIterInit(&iter, &(oldDtd->attributeIds));
+
+ /* Copy the attribute id table. */
+
+ for (;;) {
+ ATTRIBUTE_ID *newA;
+ const XML_Char *name;
+ const ATTRIBUTE_ID *oldA = (ATTRIBUTE_ID *)hashTableIterNext(&iter);
+
+ if (!oldA)
+ break;
+ /* Remember to allocate the scratch byte before the name. */
+ if (!poolAppendChar(&(newDtd->pool), XML_T('\0')))
+ return 0;
+ name = poolCopyString(&(newDtd->pool), oldA->name);
+ if (!name)
+ return 0;
+ ++name;
+ newA = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), name, sizeof(ATTRIBUTE_ID));
+ if (!newA)
+ return 0;
+ newA->maybeTokenized = oldA->maybeTokenized;
+ if (oldA->prefix) {
+ newA->xmlns = oldA->xmlns;
+ if (oldA->prefix == &oldDtd->defaultPrefix)
+ newA->prefix = &newDtd->defaultPrefix;
+ else
+ newA->prefix = (PREFIX *)lookup(&(newDtd->prefixes), oldA->prefix->name, 0);
+ }
+ }
+
+ /* Copy the element type table. */
+
+ hashTableIterInit(&iter, &(oldDtd->elementTypes));
+
+ for (;;) {
+ int i;
+ ELEMENT_TYPE *newE;
+ const XML_Char *name;
+ const ELEMENT_TYPE *oldE = (ELEMENT_TYPE *)hashTableIterNext(&iter);
+ if (!oldE)
+ break;
+ name = poolCopyString(&(newDtd->pool), oldE->name);
+ if (!name)
+ return 0;
+ newE = (ELEMENT_TYPE *)lookup(&(newDtd->elementTypes), name, sizeof(ELEMENT_TYPE));
+ if (!newE)
+ return 0;
+ if (oldE->nDefaultAtts) {
+ newE->defaultAtts = (DEFAULT_ATTRIBUTE *)MALLOC(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
+ if (!newE->defaultAtts)
+ return 0;
+ }
+ if (oldE->idAtt)
+ newE->idAtt = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), oldE->idAtt->name, 0);
+ newE->allocDefaultAtts = newE->nDefaultAtts = oldE->nDefaultAtts;
+ if (oldE->prefix)
+ newE->prefix = (PREFIX *)lookup(&(newDtd->prefixes), oldE->prefix->name, 0);
+ for (i = 0; i < newE->nDefaultAtts; i++) {
+ newE->defaultAtts[i].id = (ATTRIBUTE_ID *)lookup(&(newDtd->attributeIds), oldE->defaultAtts[i].id->name, 0);
+ newE->defaultAtts[i].isCdata = oldE->defaultAtts[i].isCdata;
+ if (oldE->defaultAtts[i].value) {
+ newE->defaultAtts[i].value = poolCopyString(&(newDtd->pool), oldE->defaultAtts[i].value);
+ if (!newE->defaultAtts[i].value)
+ return 0;
+ }
+ else
+ newE->defaultAtts[i].value = 0;
+ }
+ }
+
+ /* Copy the entity tables. */
+ if (!copyEntityTable(&(newDtd->generalEntities),
+ &(newDtd->pool),
+ &(oldDtd->generalEntities), parser))
+ return 0;
+
+#ifdef XML_DTD
+ if (!copyEntityTable(&(newDtd->paramEntities),
+ &(newDtd->pool),
+ &(oldDtd->paramEntities), parser))
+ return 0;
+#endif /* XML_DTD */
+
+ newDtd->complete = oldDtd->complete;
+ newDtd->standalone = oldDtd->standalone;
+
+ /* Don't want deep copying for scaffolding */
+ newDtd->in_eldecl = oldDtd->in_eldecl;
+ newDtd->scaffold = oldDtd->scaffold;
+ newDtd->contentStringLen = oldDtd->contentStringLen;
+ newDtd->scaffSize = oldDtd->scaffSize;
+ newDtd->scaffLevel = oldDtd->scaffLevel;
+ newDtd->scaffIndex = oldDtd->scaffIndex;
+
+ return 1;
+} /* End dtdCopy */
+
+static int copyEntityTable(HASH_TABLE *newTable,
+ STRING_POOL *newPool,
+ const HASH_TABLE *oldTable,
+ XML_Parser parser)
+{
+ HASH_TABLE_ITER iter;
+ const XML_Char *cachedOldBase = 0;
+ const XML_Char *cachedNewBase = 0;
+
+ hashTableIterInit(&iter, oldTable);
+
+ for (;;) {
+ ENTITY *newE;
+ const XML_Char *name;
+ const ENTITY *oldE = (ENTITY *)hashTableIterNext(&iter);
+ if (!oldE)
+ break;
+ name = poolCopyString(newPool, oldE->name);
+ if (!name)
+ return 0;
+ newE = (ENTITY *)lookup(newTable, name, sizeof(ENTITY));
+ if (!newE)
+ return 0;
+ if (oldE->systemId) {
+ const XML_Char *tem = poolCopyString(newPool, oldE->systemId);
+ if (!tem)
+ return 0;
+ newE->systemId = tem;
+ if (oldE->base) {
+ if (oldE->base == cachedOldBase)
+ newE->base = cachedNewBase;
+ else {
+ cachedOldBase = oldE->base;
+ tem = poolCopyString(newPool, cachedOldBase);
+ if (!tem)
+ return 0;
+ cachedNewBase = newE->base = tem;
+ }
+ }
+ }
+ else {
+ const XML_Char *tem = poolCopyStringN(newPool, oldE->textPtr, oldE->textLen);
+ if (!tem)
+ return 0;
+ newE->textPtr = tem;
+ newE->textLen = oldE->textLen;
+ }
+ if (oldE->notation) {
+ const XML_Char *tem = poolCopyString(newPool, oldE->notation);
+ if (!tem)
+ return 0;
+ newE->notation = tem;
+ }
+ }
+ return 1;
+}
+
+#define INIT_SIZE 64
+
+static
+int keyeq(KEY s1, KEY s2)
+{
+ for (; *s1 == *s2; s1++, s2++)
+ if (*s1 == 0)
+ return 1;
+ return 0;
+}
+
+static
+unsigned long hash(KEY s)
+{
+ unsigned long h = 0;
+ while (*s)
+ h = (h << 5) + h + (unsigned char)*s++;
+ return h;
+}
+
+static
+NAMED *lookup(HASH_TABLE *table, KEY name, size_t createSize)
+{
+ size_t i;
+ if (table->size == 0) {
+ size_t tsize;
+
+ if (!createSize)
+ return 0;
+ tsize = INIT_SIZE * sizeof(NAMED *);
+ table->v = table->mem->malloc_fcn(tsize);
+ if (!table->v)
+ return 0;
+ memset(table->v, 0, tsize);
+ table->size = INIT_SIZE;
+ table->usedLim = INIT_SIZE / 2;
+ i = hash(name) & (table->size - 1);
+ }
+ else {
+ unsigned long h = hash(name);
+ for (i = h & (table->size - 1);
+ table->v[i];
+ i == 0 ? i = table->size - 1 : --i) {
+ if (keyeq(name, table->v[i]->name))
+ return table->v[i];
+ }
+ if (!createSize)
+ return 0;
+ if (table->used == table->usedLim) {
+ /* check for overflow */
+ size_t newSize = table->size * 2;
+ size_t tsize = newSize * sizeof(NAMED *);
+ NAMED **newV = table->mem->malloc_fcn(tsize);
+ if (!newV)
+ return 0;
+ memset(newV, 0, tsize);
+ for (i = 0; i < table->size; i++)
+ if (table->v[i]) {
+ size_t j;
+ for (j = hash(table->v[i]->name) & (newSize - 1);
+ newV[j];
+ j == 0 ? j = newSize - 1 : --j)
+ ;
+ newV[j] = table->v[i];
+ }
+ table->mem->free_fcn(table->v);
+ table->v = newV;
+ table->size = newSize;
+ table->usedLim = newSize/2;
+ for (i = h & (table->size - 1);
+ table->v[i];
+ i == 0 ? i = table->size - 1 : --i)
+ ;
+ }
+ }
+ table->v[i] = table->mem->malloc_fcn(createSize);
+ if (!table->v[i])
+ return 0;
+ memset(table->v[i], 0, createSize);
+ table->v[i]->name = name;
+ (table->used)++;
+ return table->v[i];
+}
+
+static
+void hashTableDestroy(HASH_TABLE *table)
+{
+ size_t i;
+ for (i = 0; i < table->size; i++) {
+ NAMED *p = table->v[i];
+ if (p)
+ table->mem->free_fcn(p);
+ }
+ if (table->v)
+ table->mem->free_fcn(table->v);
+}
+
+static
+void hashTableInit(HASH_TABLE *p, XML_Memory_Handling_Suite *ms)
+{
+ p->size = 0;
+ p->usedLim = 0;
+ p->used = 0;
+ p->v = 0;
+ p->mem = ms;
+}
+
+static
+void hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table)
+{
+ iter->p = table->v;
+ iter->end = iter->p + table->size;
+}
+
+static
+NAMED *hashTableIterNext(HASH_TABLE_ITER *iter)
+{
+ while (iter->p != iter->end) {
+ NAMED *tem = *(iter->p)++;
+ if (tem)
+ return tem;
+ }
+ return 0;
+}
+
+
+static
+void poolInit(STRING_POOL *pool, XML_Memory_Handling_Suite *ms)
+{
+ pool->blocks = 0;
+ pool->freeBlocks = 0;
+ pool->start = 0;
+ pool->ptr = 0;
+ pool->end = 0;
+ pool->mem = ms;
+}
+
+static
+void poolClear(STRING_POOL *pool)
+{
+ if (!pool->freeBlocks)
+ pool->freeBlocks = pool->blocks;
+ else {
+ BLOCK *p = pool->blocks;
+ while (p) {
+ BLOCK *tem = p->next;
+ p->next = pool->freeBlocks;
+ pool->freeBlocks = p;
+ p = tem;
+ }
+ }
+ pool->blocks = 0;
+ pool->start = 0;
+ pool->ptr = 0;
+ pool->end = 0;
+}
+
+static
+void poolDestroy(STRING_POOL *pool)
+{
+ BLOCK *p = pool->blocks;
+ while (p) {
+ BLOCK *tem = p->next;
+ pool->mem->free_fcn(p);
+ p = tem;
+ }
+ pool->blocks = 0;
+ p = pool->freeBlocks;
+ while (p) {
+ BLOCK *tem = p->next;
+ pool->mem->free_fcn(p);
+ p = tem;
+ }
+ pool->freeBlocks = 0;
+ pool->ptr = 0;
+ pool->start = 0;
+ pool->end = 0;
+}
+
+static
+XML_Char *poolAppend(STRING_POOL *pool, const ENCODING *enc,
+ const char *ptr, const char *end)
+{
+ if (!pool->ptr && !poolGrow(pool))
+ return 0;
+ for (;;) {
+ XmlConvert(enc, &ptr, end, (ICHAR **)&(pool->ptr), (ICHAR *)pool->end);
+ if (ptr == end)
+ break;
+ if (!poolGrow(pool))
+ return 0;
+ }
+ return pool->start;
+}
+
+static const XML_Char *poolCopyString(STRING_POOL *pool, const XML_Char *s)
+{
+ do {
+ if (!poolAppendChar(pool, *s))
+ return 0;
+ } while (*s++);
+ s = pool->start;
+ poolFinish(pool);
+ return s;
+}
+
+static const XML_Char *poolCopyStringN(STRING_POOL *pool, const XML_Char *s, int n)
+{
+ if (!pool->ptr && !poolGrow(pool))
+ return 0;
+ for (; n > 0; --n, s++) {
+ if (!poolAppendChar(pool, *s))
+ return 0;
+
+ }
+ s = pool->start;
+ poolFinish(pool);
+ return s;
+}
+
+static
+const XML_Char *poolAppendString(STRING_POOL *pool, const XML_Char *s)
+{
+ while (*s) {
+ if (!poolAppendChar(pool, *s))
+ return 0;
+ s++;
+ }
+ return pool->start;
+} /* End poolAppendString */
+
+static
+XML_Char *poolStoreString(STRING_POOL *pool, const ENCODING *enc,
+ const char *ptr, const char *end)
+{
+ if (!poolAppend(pool, enc, ptr, end))
+ return 0;
+ if (pool->ptr == pool->end && !poolGrow(pool))
+ return 0;
+ *(pool->ptr)++ = 0;
+ return pool->start;
+}
+
+static
+int poolGrow(STRING_POOL *pool)
+{
+ if (pool->freeBlocks) {
+ if (pool->start == 0) {
+ pool->blocks = pool->freeBlocks;
+ pool->freeBlocks = pool->freeBlocks->next;
+ pool->blocks->next = 0;
+ pool->start = pool->blocks->s;
+ pool->end = pool->start + pool->blocks->size;
+ pool->ptr = pool->start;
+ return 1;
+ }
+ if (pool->end - pool->start < pool->freeBlocks->size) {
+ BLOCK *tem = pool->freeBlocks->next;
+ pool->freeBlocks->next = pool->blocks;
+ pool->blocks = pool->freeBlocks;
+ pool->freeBlocks = tem;
+ memcpy(pool->blocks->s, pool->start, (pool->end - pool->start) * sizeof(XML_Char));
+ pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
+ pool->start = pool->blocks->s;
+ pool->end = pool->start + pool->blocks->size;
+ return 1;
+ }
+ }
+ if (pool->blocks && pool->start == pool->blocks->s) {
+ int blockSize = (pool->end - pool->start)*2;
+ pool->blocks = pool->mem->realloc_fcn(pool->blocks, offsetof(BLOCK, s) + blockSize * sizeof(XML_Char));
+ if (!pool->blocks)
+ return 0;
+ pool->blocks->size = blockSize;
+ pool->ptr = pool->blocks->s + (pool->ptr - pool->start);
+ pool->start = pool->blocks->s;
+ pool->end = pool->start + blockSize;
+ }
+ else {
+ BLOCK *tem;
+ int blockSize = pool->end - pool->start;
+ if (blockSize < INIT_BLOCK_SIZE)
+ blockSize = INIT_BLOCK_SIZE;
+ else
+ blockSize *= 2;
+ tem = pool->mem->malloc_fcn(offsetof(BLOCK, s) + blockSize * sizeof(XML_Char));
+ if (!tem)
+ return 0;
+ tem->size = blockSize;
+ tem->next = pool->blocks;
+ pool->blocks = tem;
+ if (pool->ptr != pool->start)
+ memcpy(tem->s, pool->start, (pool->ptr - pool->start) * sizeof(XML_Char));
+ pool->ptr = tem->s + (pool->ptr - pool->start);
+ pool->start = tem->s;
+ pool->end = tem->s + blockSize;
+ }
+ return 1;
+}
+
+static int
+nextScaffoldPart(XML_Parser parser)
+{
+ CONTENT_SCAFFOLD * me;
+ int next;
+
+ if (! dtd.scaffIndex) {
+ dtd.scaffIndex = MALLOC(groupSize * sizeof(int));
+ if (! dtd.scaffIndex)
+ return -1;
+ dtd.scaffIndex[0] = 0;
+ }
+
+ if (dtd.scaffCount >= dtd.scaffSize) {
+ if (dtd.scaffold) {
+ dtd.scaffSize *= 2;
+ dtd.scaffold = (CONTENT_SCAFFOLD *) REALLOC(dtd.scaffold,
+ dtd.scaffSize * sizeof(CONTENT_SCAFFOLD));
+ }
+ else {
+ dtd.scaffSize = 32;
+ dtd.scaffold = (CONTENT_SCAFFOLD *) MALLOC(dtd.scaffSize * sizeof(CONTENT_SCAFFOLD));
+ }
+ if (! dtd.scaffold)
+ return -1;
+ }
+ next = dtd.scaffCount++;
+ me = &dtd.scaffold[next];
+ if (dtd.scaffLevel) {
+ CONTENT_SCAFFOLD *parent = &dtd.scaffold[dtd.scaffIndex[dtd.scaffLevel - 1]];
+ if (parent->lastchild) {
+ dtd.scaffold[parent->lastchild].nextsib = next;
+ }
+ if (! parent->childcnt)
+ parent->firstchild = next;
+ parent->lastchild = next;
+ parent->childcnt++;
+ }
+ me->firstchild = me->lastchild = me->childcnt = me->nextsib = 0;
+ return next;
+} /* End nextScaffoldPart */
+
+static void
+build_node (XML_Parser parser,
+ int src_node,
+ XML_Content *dest,
+ XML_Content **contpos,
+ char **strpos)
+{
+ dest->type = dtd.scaffold[src_node].type;
+ dest->quant = dtd.scaffold[src_node].quant;
+ if (dest->type == XML_CTYPE_NAME) {
+ const char *src;
+ dest->name = *strpos;
+ src = dtd.scaffold[src_node].name;
+ for (;;) {
+ *(*strpos)++ = *src;
+ if (! *src)
+ break;
+ src++;
+ }
+ dest->numchildren = 0;
+ dest->children = 0;
+ }
+ else {
+ unsigned int i;
+ int cn;
+ dest->numchildren = dtd.scaffold[src_node].childcnt;
+ dest->children = *contpos;
+ *contpos += dest->numchildren;
+ for (i = 0, cn = dtd.scaffold[src_node].firstchild;
+ i < dest->numchildren;
+ i++, cn = dtd.scaffold[cn].nextsib) {
+ build_node(parser, cn, &(dest->children[i]), contpos, strpos);
+ }
+ dest->name = 0;
+ }
+} /* End build_node */
+
+static XML_Content *
+build_model (XML_Parser parser)
+{
+ XML_Content *ret;
+ XML_Content *cpos;
+ char * str;
+ int allocsize = dtd.scaffCount * sizeof(XML_Content) + dtd.contentStringLen;
+
+ ret = MALLOC(allocsize);
+ if (! ret)
+ return 0;
+
+ str = (char *) (&ret[dtd.scaffCount]);
+ cpos = &ret[1];
+
+ build_node(parser, 0, ret, &cpos, &str);
+ return ret;
+} /* End build_model */
+
+static ELEMENT_TYPE *
+getElementType(XML_Parser parser,
+ const ENCODING *enc,
+ const char *ptr,
+ const char *end)
+{
+ const XML_Char *name = poolStoreString(&dtd.pool, enc, ptr, end);
+ ELEMENT_TYPE *ret;
+
+ if (! name)
+ return 0;
+ ret = (ELEMENT_TYPE *) lookup(&dtd.elementTypes, name, sizeof(ELEMENT_TYPE));
+ if (! ret)
+ return 0;
+ if (ret->name != name)
+ poolDiscard(&dtd.pool);
+ else {
+ poolFinish(&dtd.pool);
+ if (!setElementTypePrefix(parser, ret))
+ return 0;
+ }
+ return ret;
+} /* End getElementType */
--- /dev/null
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file COPYING for copying permission.
+*/
+
+static char RCSId[]
+ = "$Header: /home/cvs/apr-util/xml/expat/lib/xmlrole.c,v 1.1 2001/02/28 14:41:26 gstein Exp $";
+
+#ifdef COMPILED_FROM_DSP
+# include "winconfig.h"
+#else
+# include <config.h>
+#endif /* ndef COMPILED_FROM_DSP */
+
+#include "xmlrole.h"
+#include "ascii.h"
+
+/* Doesn't check:
+
+ that ,| are not mixed in a model group
+ content of literals
+
+*/
+
+static const char KW_ANY[] = { ASCII_A, ASCII_N, ASCII_Y, '\0' };
+static const char KW_ATTLIST[] = { ASCII_A, ASCII_T, ASCII_T, ASCII_L, ASCII_I, ASCII_S, ASCII_T, '\0' };
+static const char KW_CDATA[] = { ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' };
+static const char KW_DOCTYPE[] = { ASCII_D, ASCII_O, ASCII_C, ASCII_T, ASCII_Y, ASCII_P, ASCII_E, '\0' };
+static const char KW_ELEMENT[] = { ASCII_E, ASCII_L, ASCII_E, ASCII_M, ASCII_E, ASCII_N, ASCII_T, '\0' };
+static const char KW_EMPTY[] = { ASCII_E, ASCII_M, ASCII_P, ASCII_T, ASCII_Y, '\0' };
+static const char KW_ENTITIES[] = { ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_I, ASCII_E, ASCII_S, '\0' };
+static const char KW_ENTITY[] = { ASCII_E, ASCII_N, ASCII_T, ASCII_I, ASCII_T, ASCII_Y, '\0' };
+static const char KW_FIXED[] = { ASCII_F, ASCII_I, ASCII_X, ASCII_E, ASCII_D, '\0' };
+static const char KW_ID[] = { ASCII_I, ASCII_D, '\0' };
+static const char KW_IDREF[] = { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, '\0' };
+static const char KW_IDREFS[] = { ASCII_I, ASCII_D, ASCII_R, ASCII_E, ASCII_F, ASCII_S, '\0' };
+static const char KW_IGNORE[] = { ASCII_I, ASCII_G, ASCII_N, ASCII_O, ASCII_R, ASCII_E, '\0' };
+static const char KW_IMPLIED[] = { ASCII_I, ASCII_M, ASCII_P, ASCII_L, ASCII_I, ASCII_E, ASCII_D, '\0' };
+static const char KW_INCLUDE[] = { ASCII_I, ASCII_N, ASCII_C, ASCII_L, ASCII_U, ASCII_D, ASCII_E, '\0' };
+static const char KW_NDATA[] = { ASCII_N, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' };
+static const char KW_NMTOKEN[] = { ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, '\0' };
+static const char KW_NMTOKENS[] = { ASCII_N, ASCII_M, ASCII_T, ASCII_O, ASCII_K, ASCII_E, ASCII_N, ASCII_S, '\0' };
+static const char KW_NOTATION[] = { ASCII_N, ASCII_O, ASCII_T, ASCII_A, ASCII_T, ASCII_I, ASCII_O, ASCII_N, '\0' };
+static const char KW_PCDATA[] = { ASCII_P, ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, '\0' };
+static const char KW_PUBLIC[] = { ASCII_P, ASCII_U, ASCII_B, ASCII_L, ASCII_I, ASCII_C, '\0' };
+static const char KW_REQUIRED[] = { ASCII_R, ASCII_E, ASCII_Q, ASCII_U, ASCII_I, ASCII_R, ASCII_E, ASCII_D, '\0' };
+static const char KW_SYSTEM[] = { ASCII_S, ASCII_Y, ASCII_S, ASCII_T, ASCII_E, ASCII_M, '\0' };
+
+#ifndef MIN_BYTES_PER_CHAR
+#define MIN_BYTES_PER_CHAR(enc) ((enc)->minBytesPerChar)
+#endif
+
+#ifdef XML_DTD
+#define setTopLevel(state) \
+ ((state)->handler = ((state)->documentEntity \
+ ? internalSubset \
+ : externalSubset1))
+#else /* not XML_DTD */
+#define setTopLevel(state) ((state)->handler = internalSubset)
+#endif /* not XML_DTD */
+
+typedef int PROLOG_HANDLER(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc);
+
+static PROLOG_HANDLER
+ prolog0, prolog1, prolog2,
+ doctype0, doctype1, doctype2, doctype3, doctype4, doctype5,
+ internalSubset,
+ entity0, entity1, entity2, entity3, entity4, entity5, entity6,
+ entity7, entity8, entity9,
+ notation0, notation1, notation2, notation3, notation4,
+ attlist0, attlist1, attlist2, attlist3, attlist4, attlist5, attlist6,
+ attlist7, attlist8, attlist9,
+ element0, element1, element2, element3, element4, element5, element6,
+ element7,
+#ifdef XML_DTD
+ externalSubset0, externalSubset1,
+ condSect0, condSect1, condSect2,
+#endif /* XML_DTD */
+ declClose,
+ error;
+
+static
+int common(PROLOG_STATE *state, int tok);
+
+static
+int prolog0(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ state->handler = prolog1;
+ return XML_ROLE_NONE;
+ case XML_TOK_XML_DECL:
+ state->handler = prolog1;
+ return XML_ROLE_XML_DECL;
+ case XML_TOK_PI:
+ state->handler = prolog1;
+ return XML_ROLE_NONE;
+ case XML_TOK_COMMENT:
+ state->handler = prolog1;
+ case XML_TOK_BOM:
+ return XML_ROLE_NONE;
+ case XML_TOK_DECL_OPEN:
+ if (!XmlNameMatchesAscii(enc,
+ ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+ end,
+ KW_DOCTYPE))
+ break;
+ state->handler = doctype0;
+ return XML_ROLE_NONE;
+ case XML_TOK_INSTANCE_START:
+ state->handler = error;
+ return XML_ROLE_INSTANCE_START;
+ }
+ return common(state, tok);
+}
+
+static
+int prolog1(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_PI:
+ case XML_TOK_COMMENT:
+ case XML_TOK_BOM:
+ return XML_ROLE_NONE;
+ case XML_TOK_DECL_OPEN:
+ if (!XmlNameMatchesAscii(enc,
+ ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+ end,
+ KW_DOCTYPE))
+ break;
+ state->handler = doctype0;
+ return XML_ROLE_NONE;
+ case XML_TOK_INSTANCE_START:
+ state->handler = error;
+ return XML_ROLE_INSTANCE_START;
+ }
+ return common(state, tok);
+}
+
+static
+int prolog2(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_PI:
+ case XML_TOK_COMMENT:
+ return XML_ROLE_NONE;
+ case XML_TOK_INSTANCE_START:
+ state->handler = error;
+ return XML_ROLE_INSTANCE_START;
+ }
+ return common(state, tok);
+}
+
+static
+int doctype0(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = doctype1;
+ return XML_ROLE_DOCTYPE_NAME;
+ }
+ return common(state, tok);
+}
+
+static
+int doctype1(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_OPEN_BRACKET:
+ state->handler = internalSubset;
+ return XML_ROLE_DOCTYPE_INTERNAL_SUBSET;
+ case XML_TOK_DECL_CLOSE:
+ state->handler = prolog2;
+ return XML_ROLE_DOCTYPE_CLOSE;
+ case XML_TOK_NAME:
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) {
+ state->handler = doctype3;
+ return XML_ROLE_NONE;
+ }
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) {
+ state->handler = doctype2;
+ return XML_ROLE_NONE;
+ }
+ break;
+ }
+ return common(state, tok);
+}
+
+static
+int doctype2(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = doctype3;
+ return XML_ROLE_DOCTYPE_PUBLIC_ID;
+ }
+ return common(state, tok);
+}
+
+static
+int doctype3(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = doctype4;
+ return XML_ROLE_DOCTYPE_SYSTEM_ID;
+ }
+ return common(state, tok);
+}
+
+static
+int doctype4(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_OPEN_BRACKET:
+ state->handler = internalSubset;
+ return XML_ROLE_DOCTYPE_INTERNAL_SUBSET;
+ case XML_TOK_DECL_CLOSE:
+ state->handler = prolog2;
+ return XML_ROLE_DOCTYPE_CLOSE;
+ }
+ return common(state, tok);
+}
+
+static
+int doctype5(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_DECL_CLOSE:
+ state->handler = prolog2;
+ return XML_ROLE_DOCTYPE_CLOSE;
+ }
+ return common(state, tok);
+}
+
+static
+int internalSubset(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_DECL_OPEN:
+ if (XmlNameMatchesAscii(enc,
+ ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+ end,
+ KW_ENTITY)) {
+ state->handler = entity0;
+ return XML_ROLE_NONE;
+ }
+ if (XmlNameMatchesAscii(enc,
+ ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+ end,
+ KW_ATTLIST)) {
+ state->handler = attlist0;
+ return XML_ROLE_NONE;
+ }
+ if (XmlNameMatchesAscii(enc,
+ ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+ end,
+ KW_ELEMENT)) {
+ state->handler = element0;
+ return XML_ROLE_NONE;
+ }
+ if (XmlNameMatchesAscii(enc,
+ ptr + 2 * MIN_BYTES_PER_CHAR(enc),
+ end,
+ KW_NOTATION)) {
+ state->handler = notation0;
+ return XML_ROLE_NONE;
+ }
+ break;
+ case XML_TOK_PI:
+ case XML_TOK_COMMENT:
+ return XML_ROLE_NONE;
+ case XML_TOK_PARAM_ENTITY_REF:
+ return XML_ROLE_PARAM_ENTITY_REF;
+ case XML_TOK_CLOSE_BRACKET:
+ state->handler = doctype5;
+ return XML_ROLE_NONE;
+ }
+ return common(state, tok);
+}
+
+#ifdef XML_DTD
+
+static
+int externalSubset0(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ state->handler = externalSubset1;
+ if (tok == XML_TOK_XML_DECL)
+ return XML_ROLE_TEXT_DECL;
+ return externalSubset1(state, tok, ptr, end, enc);
+}
+
+static
+int externalSubset1(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_COND_SECT_OPEN:
+ state->handler = condSect0;
+ return XML_ROLE_NONE;
+ case XML_TOK_COND_SECT_CLOSE:
+ if (state->includeLevel == 0)
+ break;
+ state->includeLevel -= 1;
+ return XML_ROLE_NONE;
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_CLOSE_BRACKET:
+ break;
+ case XML_TOK_NONE:
+ if (state->includeLevel)
+ break;
+ return XML_ROLE_NONE;
+ default:
+ return internalSubset(state, tok, ptr, end, enc);
+ }
+ return common(state, tok);
+}
+
+#endif /* XML_DTD */
+
+static
+int entity0(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_PERCENT:
+ state->handler = entity1;
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ state->handler = entity2;
+ return XML_ROLE_GENERAL_ENTITY_NAME;
+ }
+ return common(state, tok);
+}
+
+static
+int entity1(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ state->handler = entity7;
+ return XML_ROLE_PARAM_ENTITY_NAME;
+ }
+ return common(state, tok);
+}
+
+static
+int entity2(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) {
+ state->handler = entity4;
+ return XML_ROLE_NONE;
+ }
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) {
+ state->handler = entity3;
+ return XML_ROLE_NONE;
+ }
+ break;
+ case XML_TOK_LITERAL:
+ state->handler = declClose;
+ return XML_ROLE_ENTITY_VALUE;
+ }
+ return common(state, tok);
+}
+
+static
+int entity3(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = entity4;
+ return XML_ROLE_ENTITY_PUBLIC_ID;
+ }
+ return common(state, tok);
+}
+
+
+static
+int entity4(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = entity5;
+ return XML_ROLE_ENTITY_SYSTEM_ID;
+ }
+ return common(state, tok);
+}
+
+static
+int entity5(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_DECL_CLOSE:
+ setTopLevel(state);
+ return XML_ROLE_ENTITY_COMPLETE;
+ case XML_TOK_NAME:
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_NDATA)) {
+ state->handler = entity6;
+ return XML_ROLE_NONE;
+ }
+ break;
+ }
+ return common(state, tok);
+}
+
+static
+int entity6(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ state->handler = declClose;
+ return XML_ROLE_ENTITY_NOTATION_NAME;
+ }
+ return common(state, tok);
+}
+
+static
+int entity7(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) {
+ state->handler = entity9;
+ return XML_ROLE_NONE;
+ }
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) {
+ state->handler = entity8;
+ return XML_ROLE_NONE;
+ }
+ break;
+ case XML_TOK_LITERAL:
+ state->handler = declClose;
+ return XML_ROLE_ENTITY_VALUE;
+ }
+ return common(state, tok);
+}
+
+static
+int entity8(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = entity9;
+ return XML_ROLE_ENTITY_PUBLIC_ID;
+ }
+ return common(state, tok);
+}
+
+static
+int entity9(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = declClose;
+ return XML_ROLE_ENTITY_SYSTEM_ID;
+ }
+ return common(state, tok);
+}
+
+static
+int notation0(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ state->handler = notation1;
+ return XML_ROLE_NOTATION_NAME;
+ }
+ return common(state, tok);
+}
+
+static
+int notation1(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_SYSTEM)) {
+ state->handler = notation3;
+ return XML_ROLE_NONE;
+ }
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_PUBLIC)) {
+ state->handler = notation2;
+ return XML_ROLE_NONE;
+ }
+ break;
+ }
+ return common(state, tok);
+}
+
+static
+int notation2(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = notation4;
+ return XML_ROLE_NOTATION_PUBLIC_ID;
+ }
+ return common(state, tok);
+}
+
+static
+int notation3(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = declClose;
+ return XML_ROLE_NOTATION_SYSTEM_ID;
+ }
+ return common(state, tok);
+}
+
+static
+int notation4(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = declClose;
+ return XML_ROLE_NOTATION_SYSTEM_ID;
+ case XML_TOK_DECL_CLOSE:
+ setTopLevel(state);
+ return XML_ROLE_NOTATION_NO_SYSTEM_ID;
+ }
+ return common(state, tok);
+}
+
+static
+int attlist0(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = attlist1;
+ return XML_ROLE_ATTLIST_ELEMENT_NAME;
+ }
+ return common(state, tok);
+}
+
+static
+int attlist1(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_DECL_CLOSE:
+ setTopLevel(state);
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = attlist2;
+ return XML_ROLE_ATTRIBUTE_NAME;
+ }
+ return common(state, tok);
+}
+
+static
+int attlist2(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ {
+ static const char *types[] = {
+ KW_CDATA,
+ KW_ID,
+ KW_IDREF,
+ KW_IDREFS,
+ KW_ENTITY,
+ KW_ENTITIES,
+ KW_NMTOKEN,
+ KW_NMTOKENS,
+ };
+ int i;
+ for (i = 0; i < (int)(sizeof(types)/sizeof(types[0])); i++)
+ if (XmlNameMatchesAscii(enc, ptr, end, types[i])) {
+ state->handler = attlist8;
+ return XML_ROLE_ATTRIBUTE_TYPE_CDATA + i;
+ }
+ }
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_NOTATION)) {
+ state->handler = attlist5;
+ return XML_ROLE_NONE;
+ }
+ break;
+ case XML_TOK_OPEN_PAREN:
+ state->handler = attlist3;
+ return XML_ROLE_NONE;
+ }
+ return common(state, tok);
+}
+
+static
+int attlist3(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NMTOKEN:
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = attlist4;
+ return XML_ROLE_ATTRIBUTE_ENUM_VALUE;
+ }
+ return common(state, tok);
+}
+
+static
+int attlist4(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_CLOSE_PAREN:
+ state->handler = attlist8;
+ return XML_ROLE_NONE;
+ case XML_TOK_OR:
+ state->handler = attlist3;
+ return XML_ROLE_NONE;
+ }
+ return common(state, tok);
+}
+
+static
+int attlist5(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_OPEN_PAREN:
+ state->handler = attlist6;
+ return XML_ROLE_NONE;
+ }
+ return common(state, tok);
+}
+
+
+static
+int attlist6(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ state->handler = attlist7;
+ return XML_ROLE_ATTRIBUTE_NOTATION_VALUE;
+ }
+ return common(state, tok);
+}
+
+static
+int attlist7(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_CLOSE_PAREN:
+ state->handler = attlist8;
+ return XML_ROLE_NONE;
+ case XML_TOK_OR:
+ state->handler = attlist6;
+ return XML_ROLE_NONE;
+ }
+ return common(state, tok);
+}
+
+/* default value */
+static
+int attlist8(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_POUND_NAME:
+ if (XmlNameMatchesAscii(enc,
+ ptr + MIN_BYTES_PER_CHAR(enc),
+ end,
+ KW_IMPLIED)) {
+ state->handler = attlist1;
+ return XML_ROLE_IMPLIED_ATTRIBUTE_VALUE;
+ }
+ if (XmlNameMatchesAscii(enc,
+ ptr + MIN_BYTES_PER_CHAR(enc),
+ end,
+ KW_REQUIRED)) {
+ state->handler = attlist1;
+ return XML_ROLE_REQUIRED_ATTRIBUTE_VALUE;
+ }
+ if (XmlNameMatchesAscii(enc,
+ ptr + MIN_BYTES_PER_CHAR(enc),
+ end,
+ KW_FIXED)) {
+ state->handler = attlist9;
+ return XML_ROLE_NONE;
+ }
+ break;
+ case XML_TOK_LITERAL:
+ state->handler = attlist1;
+ return XML_ROLE_DEFAULT_ATTRIBUTE_VALUE;
+ }
+ return common(state, tok);
+}
+
+static
+int attlist9(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_LITERAL:
+ state->handler = attlist1;
+ return XML_ROLE_FIXED_ATTRIBUTE_VALUE;
+ }
+ return common(state, tok);
+}
+
+static
+int element0(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = element1;
+ return XML_ROLE_ELEMENT_NAME;
+ }
+ return common(state, tok);
+}
+
+static
+int element1(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_EMPTY)) {
+ state->handler = declClose;
+ return XML_ROLE_CONTENT_EMPTY;
+ }
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_ANY)) {
+ state->handler = declClose;
+ return XML_ROLE_CONTENT_ANY;
+ }
+ break;
+ case XML_TOK_OPEN_PAREN:
+ state->handler = element2;
+ state->level = 1;
+ return XML_ROLE_GROUP_OPEN;
+ }
+ return common(state, tok);
+}
+
+static
+int element2(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_POUND_NAME:
+ if (XmlNameMatchesAscii(enc,
+ ptr + MIN_BYTES_PER_CHAR(enc),
+ end,
+ KW_PCDATA)) {
+ state->handler = element3;
+ return XML_ROLE_CONTENT_PCDATA;
+ }
+ break;
+ case XML_TOK_OPEN_PAREN:
+ state->level = 2;
+ state->handler = element6;
+ return XML_ROLE_GROUP_OPEN;
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT;
+ case XML_TOK_NAME_QUESTION:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT_OPT;
+ case XML_TOK_NAME_ASTERISK:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT_REP;
+ case XML_TOK_NAME_PLUS:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT_PLUS;
+ }
+ return common(state, tok);
+}
+
+static
+int element3(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_CLOSE_PAREN:
+ state->handler = declClose;
+ return XML_ROLE_GROUP_CLOSE;
+ case XML_TOK_CLOSE_PAREN_ASTERISK:
+ state->handler = declClose;
+ return XML_ROLE_GROUP_CLOSE_REP;
+ case XML_TOK_OR:
+ state->handler = element4;
+ return XML_ROLE_NONE;
+ }
+ return common(state, tok);
+}
+
+static
+int element4(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = element5;
+ return XML_ROLE_CONTENT_ELEMENT;
+ }
+ return common(state, tok);
+}
+
+static
+int element5(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_CLOSE_PAREN_ASTERISK:
+ state->handler = declClose;
+ return XML_ROLE_GROUP_CLOSE_REP;
+ case XML_TOK_OR:
+ state->handler = element4;
+ return XML_ROLE_NONE;
+ }
+ return common(state, tok);
+}
+
+static
+int element6(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_OPEN_PAREN:
+ state->level += 1;
+ return XML_ROLE_GROUP_OPEN;
+ case XML_TOK_NAME:
+ case XML_TOK_PREFIXED_NAME:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT;
+ case XML_TOK_NAME_QUESTION:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT_OPT;
+ case XML_TOK_NAME_ASTERISK:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT_REP;
+ case XML_TOK_NAME_PLUS:
+ state->handler = element7;
+ return XML_ROLE_CONTENT_ELEMENT_PLUS;
+ }
+ return common(state, tok);
+}
+
+static
+int element7(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_CLOSE_PAREN:
+ state->level -= 1;
+ if (state->level == 0)
+ state->handler = declClose;
+ return XML_ROLE_GROUP_CLOSE;
+ case XML_TOK_CLOSE_PAREN_ASTERISK:
+ state->level -= 1;
+ if (state->level == 0)
+ state->handler = declClose;
+ return XML_ROLE_GROUP_CLOSE_REP;
+ case XML_TOK_CLOSE_PAREN_QUESTION:
+ state->level -= 1;
+ if (state->level == 0)
+ state->handler = declClose;
+ return XML_ROLE_GROUP_CLOSE_OPT;
+ case XML_TOK_CLOSE_PAREN_PLUS:
+ state->level -= 1;
+ if (state->level == 0)
+ state->handler = declClose;
+ return XML_ROLE_GROUP_CLOSE_PLUS;
+ case XML_TOK_COMMA:
+ state->handler = element6;
+ return XML_ROLE_GROUP_SEQUENCE;
+ case XML_TOK_OR:
+ state->handler = element6;
+ return XML_ROLE_GROUP_CHOICE;
+ }
+ return common(state, tok);
+}
+
+#ifdef XML_DTD
+
+static
+int condSect0(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_NAME:
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_INCLUDE)) {
+ state->handler = condSect1;
+ return XML_ROLE_NONE;
+ }
+ if (XmlNameMatchesAscii(enc, ptr, end, KW_IGNORE)) {
+ state->handler = condSect2;
+ return XML_ROLE_NONE;
+ }
+ break;
+ }
+ return common(state, tok);
+}
+
+static
+int condSect1(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_OPEN_BRACKET:
+ state->handler = externalSubset1;
+ state->includeLevel += 1;
+ return XML_ROLE_NONE;
+ }
+ return common(state, tok);
+}
+
+static
+int condSect2(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_OPEN_BRACKET:
+ state->handler = externalSubset1;
+ return XML_ROLE_IGNORE_SECT;
+ }
+ return common(state, tok);
+}
+
+#endif /* XML_DTD */
+
+static
+int declClose(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_PROLOG_S:
+ return XML_ROLE_NONE;
+ case XML_TOK_DECL_CLOSE:
+ setTopLevel(state);
+ return XML_ROLE_NONE;
+ }
+ return common(state, tok);
+}
+
+#if 0
+
+static
+int ignore(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ switch (tok) {
+ case XML_TOK_DECL_CLOSE:
+ state->handler = internalSubset;
+ return 0;
+ default:
+ return XML_ROLE_NONE;
+ }
+ return common(state, tok);
+}
+#endif
+
+static
+int error(PROLOG_STATE *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc)
+{
+ return XML_ROLE_NONE;
+}
+
+static
+int common(PROLOG_STATE *state, int tok)
+{
+#ifdef XML_DTD
+ if (!state->documentEntity && tok == XML_TOK_PARAM_ENTITY_REF)
+ return XML_ROLE_INNER_PARAM_ENTITY_REF;
+#endif
+ state->handler = error;
+ return XML_ROLE_ERROR;
+}
+
+void XmlPrologStateInit(PROLOG_STATE *state)
+{
+ state->handler = prolog0;
+#ifdef XML_DTD
+ state->documentEntity = 1;
+ state->includeLevel = 0;
+#endif /* XML_DTD */
+}
+
+#ifdef XML_DTD
+
+void XmlPrologStateInitExternalEntity(PROLOG_STATE *state)
+{
+ state->handler = externalSubset0;
+ state->documentEntity = 0;
+ state->includeLevel = 0;
+}
+
+#endif /* XML_DTD */
--- /dev/null
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file COPYING for copying permission.
+*/
+
+#ifndef XmlRole_INCLUDED
+#define XmlRole_INCLUDED 1
+
+#include "xmltok.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+ XML_ROLE_ERROR = -1,
+ XML_ROLE_NONE = 0,
+ XML_ROLE_XML_DECL,
+ XML_ROLE_INSTANCE_START,
+ XML_ROLE_DOCTYPE_NAME,
+ XML_ROLE_DOCTYPE_SYSTEM_ID,
+ XML_ROLE_DOCTYPE_PUBLIC_ID,
+ XML_ROLE_DOCTYPE_INTERNAL_SUBSET,
+ XML_ROLE_DOCTYPE_CLOSE,
+ XML_ROLE_GENERAL_ENTITY_NAME,
+ XML_ROLE_PARAM_ENTITY_NAME,
+ XML_ROLE_ENTITY_VALUE,
+ XML_ROLE_ENTITY_SYSTEM_ID,
+ XML_ROLE_ENTITY_PUBLIC_ID,
+ XML_ROLE_ENTITY_COMPLETE,
+ XML_ROLE_ENTITY_NOTATION_NAME,
+ XML_ROLE_NOTATION_NAME,
+ XML_ROLE_NOTATION_SYSTEM_ID,
+ XML_ROLE_NOTATION_NO_SYSTEM_ID,
+ XML_ROLE_NOTATION_PUBLIC_ID,
+ XML_ROLE_ATTRIBUTE_NAME,
+ XML_ROLE_ATTRIBUTE_TYPE_CDATA,
+ XML_ROLE_ATTRIBUTE_TYPE_ID,
+ XML_ROLE_ATTRIBUTE_TYPE_IDREF,
+ XML_ROLE_ATTRIBUTE_TYPE_IDREFS,
+ XML_ROLE_ATTRIBUTE_TYPE_ENTITY,
+ XML_ROLE_ATTRIBUTE_TYPE_ENTITIES,
+ XML_ROLE_ATTRIBUTE_TYPE_NMTOKEN,
+ XML_ROLE_ATTRIBUTE_TYPE_NMTOKENS,
+ XML_ROLE_ATTRIBUTE_ENUM_VALUE,
+ XML_ROLE_ATTRIBUTE_NOTATION_VALUE,
+ XML_ROLE_ATTLIST_ELEMENT_NAME,
+ XML_ROLE_IMPLIED_ATTRIBUTE_VALUE,
+ XML_ROLE_REQUIRED_ATTRIBUTE_VALUE,
+ XML_ROLE_DEFAULT_ATTRIBUTE_VALUE,
+ XML_ROLE_FIXED_ATTRIBUTE_VALUE,
+ XML_ROLE_ELEMENT_NAME,
+ XML_ROLE_CONTENT_ANY,
+ XML_ROLE_CONTENT_EMPTY,
+ XML_ROLE_CONTENT_PCDATA,
+ XML_ROLE_GROUP_OPEN,
+ XML_ROLE_GROUP_CLOSE,
+ XML_ROLE_GROUP_CLOSE_REP,
+ XML_ROLE_GROUP_CLOSE_OPT,
+ XML_ROLE_GROUP_CLOSE_PLUS,
+ XML_ROLE_GROUP_CHOICE,
+ XML_ROLE_GROUP_SEQUENCE,
+ XML_ROLE_CONTENT_ELEMENT,
+ XML_ROLE_CONTENT_ELEMENT_REP,
+ XML_ROLE_CONTENT_ELEMENT_OPT,
+ XML_ROLE_CONTENT_ELEMENT_PLUS,
+#ifdef XML_DTD
+ XML_ROLE_TEXT_DECL,
+ XML_ROLE_IGNORE_SECT,
+ XML_ROLE_INNER_PARAM_ENTITY_REF,
+#endif /* XML_DTD */
+ XML_ROLE_PARAM_ENTITY_REF
+};
+
+typedef struct prolog_state {
+ int (*handler)(struct prolog_state *state,
+ int tok,
+ const char *ptr,
+ const char *end,
+ const ENCODING *enc);
+ unsigned level;
+#ifdef XML_DTD
+ unsigned includeLevel;
+ int documentEntity;
+#endif /* XML_DTD */
+} PROLOG_STATE;
+
+void XmlPrologStateInit(PROLOG_STATE *);
+#ifdef XML_DTD
+void XmlPrologStateInitExternalEntity(PROLOG_STATE *);
+#endif /* XML_DTD */
+
+#define XmlTokenRole(state, tok, ptr, end, enc) \
+ (((state)->handler)(state, tok, ptr, end, enc))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* not XmlRole_INCLUDED */
--- /dev/null
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file COPYING for copying permission.
+*/
+
+static char RCSId[]
+ = "$Header: /home/cvs/apr-util/xml/expat/lib/xmltok.c,v 1.1 2001/02/28 14:41:26 gstein Exp $";
+
+#ifdef COMPILED_FROM_DSP
+# include "winconfig.h"
+#else
+# include <config.h>
+#endif /* ndef COMPILED_FROM_DSP */
+
+#include "xmltok.h"
+#include "nametab.h"
+
+#ifdef XML_DTD
+#define IGNORE_SECTION_TOK_VTABLE , PREFIX(ignoreSectionTok)
+#else
+#define IGNORE_SECTION_TOK_VTABLE /* as nothing */
+#endif
+
+#define VTABLE1 \
+ { PREFIX(prologTok), PREFIX(contentTok), \
+ PREFIX(cdataSectionTok) IGNORE_SECTION_TOK_VTABLE }, \
+ { PREFIX(attributeValueTok), PREFIX(entityValueTok) }, \
+ PREFIX(sameName), \
+ PREFIX(nameMatchesAscii), \
+ PREFIX(nameLength), \
+ PREFIX(skipS), \
+ PREFIX(getAtts), \
+ PREFIX(charRefNumber), \
+ PREFIX(predefinedEntityName), \
+ PREFIX(updatePosition), \
+ PREFIX(isPublicId)
+
+#define VTABLE VTABLE1, PREFIX(toUtf8), PREFIX(toUtf16)
+
+#define UCS2_GET_NAMING(pages, hi, lo) \
+ (namingBitmap[(pages[hi] << 3) + ((lo) >> 5)] & (1 << ((lo) & 0x1F)))
+
+/* A 2 byte UTF-8 representation splits the characters 11 bits
+between the bottom 5 and 6 bits of the bytes.
+We need 8 bits to index into pages, 3 bits to add to that index and
+5 bits to generate the mask. */
+#define UTF8_GET_NAMING2(pages, byte) \
+ (namingBitmap[((pages)[(((byte)[0]) >> 2) & 7] << 3) \
+ + ((((byte)[0]) & 3) << 1) \
+ + ((((byte)[1]) >> 5) & 1)] \
+ & (1 << (((byte)[1]) & 0x1F)))
+
+/* A 3 byte UTF-8 representation splits the characters 16 bits
+between the bottom 4, 6 and 6 bits of the bytes.
+We need 8 bits to index into pages, 3 bits to add to that index and
+5 bits to generate the mask. */
+#define UTF8_GET_NAMING3(pages, byte) \
+ (namingBitmap[((pages)[((((byte)[0]) & 0xF) << 4) \
+ + ((((byte)[1]) >> 2) & 0xF)] \
+ << 3) \
+ + ((((byte)[1]) & 3) << 1) \
+ + ((((byte)[2]) >> 5) & 1)] \
+ & (1 << (((byte)[2]) & 0x1F)))
+
+#define UTF8_GET_NAMING(pages, p, n) \
+ ((n) == 2 \
+ ? UTF8_GET_NAMING2(pages, (const unsigned char *)(p)) \
+ : ((n) == 3 \
+ ? UTF8_GET_NAMING3(pages, (const unsigned char *)(p)) \
+ : 0))
+
+#define UTF8_INVALID3(p) \
+ ((*p) == 0xED \
+ ? (((p)[1] & 0x20) != 0) \
+ : ((*p) == 0xEF \
+ ? ((p)[1] == 0xBF && ((p)[2] == 0xBF || (p)[2] == 0xBE)) \
+ : 0))
+
+#define UTF8_INVALID4(p) ((*p) == 0xF4 && ((p)[1] & 0x30) != 0)
+
+static
+int isNever(const ENCODING *enc, const char *p)
+{
+ return 0;
+}
+
+static
+int utf8_isName2(const ENCODING *enc, const char *p)
+{
+ return UTF8_GET_NAMING2(namePages, (const unsigned char *)p);
+}
+
+static
+int utf8_isName3(const ENCODING *enc, const char *p)
+{
+ return UTF8_GET_NAMING3(namePages, (const unsigned char *)p);
+}
+
+#define utf8_isName4 isNever
+
+static
+int utf8_isNmstrt2(const ENCODING *enc, const char *p)
+{
+ return UTF8_GET_NAMING2(nmstrtPages, (const unsigned char *)p);
+}
+
+static
+int utf8_isNmstrt3(const ENCODING *enc, const char *p)
+{
+ return UTF8_GET_NAMING3(nmstrtPages, (const unsigned char *)p);
+}
+
+#define utf8_isNmstrt4 isNever
+
+#define utf8_isInvalid2 isNever
+
+static
+int utf8_isInvalid3(const ENCODING *enc, const char *p)
+{
+ return UTF8_INVALID3((const unsigned char *)p);
+}
+
+static
+int utf8_isInvalid4(const ENCODING *enc, const char *p)
+{
+ return UTF8_INVALID4((const unsigned char *)p);
+}
+
+struct normal_encoding {
+ ENCODING enc;
+ unsigned char type[256];
+#ifdef XML_MIN_SIZE
+ int (*byteType)(const ENCODING *, const char *);
+ int (*isNameMin)(const ENCODING *, const char *);
+ int (*isNmstrtMin)(const ENCODING *, const char *);
+ int (*byteToAscii)(const ENCODING *, const char *);
+ int (*charMatches)(const ENCODING *, const char *, int);
+#endif /* XML_MIN_SIZE */
+ int (*isName2)(const ENCODING *, const char *);
+ int (*isName3)(const ENCODING *, const char *);
+ int (*isName4)(const ENCODING *, const char *);
+ int (*isNmstrt2)(const ENCODING *, const char *);
+ int (*isNmstrt3)(const ENCODING *, const char *);
+ int (*isNmstrt4)(const ENCODING *, const char *);
+ int (*isInvalid2)(const ENCODING *, const char *);
+ int (*isInvalid3)(const ENCODING *, const char *);
+ int (*isInvalid4)(const ENCODING *, const char *);
+};
+
+#ifdef XML_MIN_SIZE
+
+#define STANDARD_VTABLE(E) \
+ E ## byteType, \
+ E ## isNameMin, \
+ E ## isNmstrtMin, \
+ E ## byteToAscii, \
+ E ## charMatches,
+
+#else
+
+#define STANDARD_VTABLE(E) /* as nothing */
+
+#endif
+
+#define NORMAL_VTABLE(E) \
+ E ## isName2, \
+ E ## isName3, \
+ E ## isName4, \
+ E ## isNmstrt2, \
+ E ## isNmstrt3, \
+ E ## isNmstrt4, \
+ E ## isInvalid2, \
+ E ## isInvalid3, \
+ E ## isInvalid4
+
+static int checkCharRefNumber(int);
+
+#include "xmltok_impl.h"
+#include "ascii.h"
+
+#ifdef XML_MIN_SIZE
+#define sb_isNameMin isNever
+#define sb_isNmstrtMin isNever
+#endif
+
+#ifdef XML_MIN_SIZE
+#define MINBPC(enc) ((enc)->minBytesPerChar)
+#else
+/* minimum bytes per character */
+#define MINBPC(enc) 1
+#endif
+
+#define SB_BYTE_TYPE(enc, p) \
+ (((struct normal_encoding *)(enc))->type[(unsigned char)*(p)])
+
+#ifdef XML_MIN_SIZE
+static
+int sb_byteType(const ENCODING *enc, const char *p)
+{
+ return SB_BYTE_TYPE(enc, p);
+}
+#define BYTE_TYPE(enc, p) \
+ (((const struct normal_encoding *)(enc))->byteType(enc, p))
+#else
+#define BYTE_TYPE(enc, p) SB_BYTE_TYPE(enc, p)
+#endif
+
+#ifdef XML_MIN_SIZE
+#define BYTE_TO_ASCII(enc, p) \
+ (((const struct normal_encoding *)(enc))->byteToAscii(enc, p))
+static
+int sb_byteToAscii(const ENCODING *enc, const char *p)
+{
+ return *p;
+}
+#else
+#define BYTE_TO_ASCII(enc, p) (*(p))
+#endif
+
+#define IS_NAME_CHAR(enc, p, n) \
+ (((const struct normal_encoding *)(enc))->isName ## n(enc, p))
+#define IS_NMSTRT_CHAR(enc, p, n) \
+ (((const struct normal_encoding *)(enc))->isNmstrt ## n(enc, p))
+#define IS_INVALID_CHAR(enc, p, n) \
+ (((const struct normal_encoding *)(enc))->isInvalid ## n(enc, p))
+
+#ifdef XML_MIN_SIZE
+#define IS_NAME_CHAR_MINBPC(enc, p) \
+ (((const struct normal_encoding *)(enc))->isNameMin(enc, p))
+#define IS_NMSTRT_CHAR_MINBPC(enc, p) \
+ (((const struct normal_encoding *)(enc))->isNmstrtMin(enc, p))
+#else
+#define IS_NAME_CHAR_MINBPC(enc, p) (0)
+#define IS_NMSTRT_CHAR_MINBPC(enc, p) (0)
+#endif
+
+#ifdef XML_MIN_SIZE
+#define CHAR_MATCHES(enc, p, c) \
+ (((const struct normal_encoding *)(enc))->charMatches(enc, p, c))
+static
+int sb_charMatches(const ENCODING *enc, const char *p, int c)
+{
+ return *p == c;
+}
+#else
+/* c is an ASCII character */
+#define CHAR_MATCHES(enc, p, c) (*(p) == c)
+#endif
+
+#define PREFIX(ident) normal_ ## ident
+#include "xmltok_impl.c"
+
+#undef MINBPC
+#undef BYTE_TYPE
+#undef BYTE_TO_ASCII
+#undef CHAR_MATCHES
+#undef IS_NAME_CHAR
+#undef IS_NAME_CHAR_MINBPC
+#undef IS_NMSTRT_CHAR
+#undef IS_NMSTRT_CHAR_MINBPC
+#undef IS_INVALID_CHAR
+
+enum { /* UTF8_cvalN is value of masked first byte of N byte sequence */
+ UTF8_cval1 = 0x00,
+ UTF8_cval2 = 0xc0,
+ UTF8_cval3 = 0xe0,
+ UTF8_cval4 = 0xf0
+};
+
+static
+void utf8_toUtf8(const ENCODING *enc,
+ const char **fromP, const char *fromLim,
+ char **toP, const char *toLim)
+{
+ char *to;
+ const char *from;
+ if (fromLim - *fromP > toLim - *toP) {
+ /* Avoid copying partial characters. */
+ for (fromLim = *fromP + (toLim - *toP); fromLim > *fromP; fromLim--)
+ if (((unsigned char)fromLim[-1] & 0xc0) != 0x80)
+ break;
+ }
+ for (to = *toP, from = *fromP; from != fromLim; from++, to++)
+ *to = *from;
+ *fromP = from;
+ *toP = to;
+}
+
+static
+void utf8_toUtf16(const ENCODING *enc,
+ const char **fromP, const char *fromLim,
+ unsigned short **toP, const unsigned short *toLim)
+{
+ unsigned short *to = *toP;
+ const char *from = *fromP;
+ while (from != fromLim && to != toLim) {
+ switch (((struct normal_encoding *)enc)->type[(unsigned char)*from]) {
+ case BT_LEAD2:
+ *to++ = ((from[0] & 0x1f) << 6) | (from[1] & 0x3f);
+ from += 2;
+ break;
+ case BT_LEAD3:
+ *to++ = ((from[0] & 0xf) << 12) | ((from[1] & 0x3f) << 6) | (from[2] & 0x3f);
+ from += 3;
+ break;
+ case BT_LEAD4:
+ {
+ unsigned long n;
+ if (to + 1 == toLim)
+ break;
+ n = ((from[0] & 0x7) << 18) | ((from[1] & 0x3f) << 12) | ((from[2] & 0x3f) << 6) | (from[3] & 0x3f);
+ n -= 0x10000;
+ to[0] = (unsigned short)((n >> 10) | 0xD800);
+ to[1] = (unsigned short)((n & 0x3FF) | 0xDC00);
+ to += 2;
+ from += 4;
+ }
+ break;
+ default:
+ *to++ = *from++;
+ break;
+ }
+ }
+ *fromP = from;
+ *toP = to;
+}
+
+#ifdef XML_NS
+static const struct normal_encoding utf8_encoding_ns = {
+ { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
+ {
+#include "asciitab.h"
+#include "utf8tab.h"
+ },
+ STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
+};
+#endif
+
+static const struct normal_encoding utf8_encoding = {
+ { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
+ {
+#define BT_COLON BT_NMSTRT
+#include "asciitab.h"
+#undef BT_COLON
+#include "utf8tab.h"
+ },
+ STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
+};
+
+#ifdef XML_NS
+
+static const struct normal_encoding internal_utf8_encoding_ns = {
+ { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
+ {
+#include "iasciitab.h"
+#include "utf8tab.h"
+ },
+ STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
+};
+
+#endif
+
+static const struct normal_encoding internal_utf8_encoding = {
+ { VTABLE1, utf8_toUtf8, utf8_toUtf16, 1, 1, 0 },
+ {
+#define BT_COLON BT_NMSTRT
+#include "iasciitab.h"
+#undef BT_COLON
+#include "utf8tab.h"
+ },
+ STANDARD_VTABLE(sb_) NORMAL_VTABLE(utf8_)
+};
+
+static
+void latin1_toUtf8(const ENCODING *enc,
+ const char **fromP, const char *fromLim,
+ char **toP, const char *toLim)
+{
+ for (;;) {
+ unsigned char c;
+ if (*fromP == fromLim)
+ break;
+ c = (unsigned char)**fromP;
+ if (c & 0x80) {
+ if (toLim - *toP < 2)
+ break;
+ *(*toP)++ = ((c >> 6) | UTF8_cval2);
+ *(*toP)++ = ((c & 0x3f) | 0x80);
+ (*fromP)++;
+ }
+ else {
+ if (*toP == toLim)
+ break;
+ *(*toP)++ = *(*fromP)++;
+ }
+ }
+}
+
+static
+void latin1_toUtf16(const ENCODING *enc,
+ const char **fromP, const char *fromLim,
+ unsigned short **toP, const unsigned short *toLim)
+{
+ while (*fromP != fromLim && *toP != toLim)
+ *(*toP)++ = (unsigned char)*(*fromP)++;
+}
+
+#ifdef XML_NS
+
+static const struct normal_encoding latin1_encoding_ns = {
+ { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 },
+ {
+#include "asciitab.h"
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(sb_)
+};
+
+#endif
+
+static const struct normal_encoding latin1_encoding = {
+ { VTABLE1, latin1_toUtf8, latin1_toUtf16, 1, 0, 0 },
+ {
+#define BT_COLON BT_NMSTRT
+#include "asciitab.h"
+#undef BT_COLON
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(sb_)
+};
+
+static
+void ascii_toUtf8(const ENCODING *enc,
+ const char **fromP, const char *fromLim,
+ char **toP, const char *toLim)
+{
+ while (*fromP != fromLim && *toP != toLim)
+ *(*toP)++ = *(*fromP)++;
+}
+
+#ifdef XML_NS
+
+static const struct normal_encoding ascii_encoding_ns = {
+ { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 },
+ {
+#include "asciitab.h"
+/* BT_NONXML == 0 */
+ },
+ STANDARD_VTABLE(sb_)
+};
+
+#endif
+
+static const struct normal_encoding ascii_encoding = {
+ { VTABLE1, ascii_toUtf8, latin1_toUtf16, 1, 1, 0 },
+ {
+#define BT_COLON BT_NMSTRT
+#include "asciitab.h"
+#undef BT_COLON
+/* BT_NONXML == 0 */
+ },
+ STANDARD_VTABLE(sb_)
+};
+
+static int unicode_byte_type(char hi, char lo)
+{
+ switch ((unsigned char)hi) {
+ case 0xD8: case 0xD9: case 0xDA: case 0xDB:
+ return BT_LEAD4;
+ case 0xDC: case 0xDD: case 0xDE: case 0xDF:
+ return BT_TRAIL;
+ case 0xFF:
+ switch ((unsigned char)lo) {
+ case 0xFF:
+ case 0xFE:
+ return BT_NONXML;
+ }
+ break;
+ }
+ return BT_NONASCII;
+}
+
+#define DEFINE_UTF16_TO_UTF8(E) \
+static \
+void E ## toUtf8(const ENCODING *enc, \
+ const char **fromP, const char *fromLim, \
+ char **toP, const char *toLim) \
+{ \
+ const char *from; \
+ for (from = *fromP; from != fromLim; from += 2) { \
+ int plane; \
+ unsigned char lo2; \
+ unsigned char lo = GET_LO(from); \
+ unsigned char hi = GET_HI(from); \
+ switch (hi) { \
+ case 0: \
+ if (lo < 0x80) { \
+ if (*toP == toLim) { \
+ *fromP = from; \
+ return; \
+ } \
+ *(*toP)++ = lo; \
+ break; \
+ } \
+ /* fall through */ \
+ case 0x1: case 0x2: case 0x3: \
+ case 0x4: case 0x5: case 0x6: case 0x7: \
+ if (toLim - *toP < 2) { \
+ *fromP = from; \
+ return; \
+ } \
+ *(*toP)++ = ((lo >> 6) | (hi << 2) | UTF8_cval2); \
+ *(*toP)++ = ((lo & 0x3f) | 0x80); \
+ break; \
+ default: \
+ if (toLim - *toP < 3) { \
+ *fromP = from; \
+ return; \
+ } \
+ /* 16 bits divided 4, 6, 6 amongst 3 bytes */ \
+ *(*toP)++ = ((hi >> 4) | UTF8_cval3); \
+ *(*toP)++ = (((hi & 0xf) << 2) | (lo >> 6) | 0x80); \
+ *(*toP)++ = ((lo & 0x3f) | 0x80); \
+ break; \
+ case 0xD8: case 0xD9: case 0xDA: case 0xDB: \
+ if (toLim - *toP < 4) { \
+ *fromP = from; \
+ return; \
+ } \
+ plane = (((hi & 0x3) << 2) | ((lo >> 6) & 0x3)) + 1; \
+ *(*toP)++ = ((plane >> 2) | UTF8_cval4); \
+ *(*toP)++ = (((lo >> 2) & 0xF) | ((plane & 0x3) << 4) | 0x80); \
+ from += 2; \
+ lo2 = GET_LO(from); \
+ *(*toP)++ = (((lo & 0x3) << 4) \
+ | ((GET_HI(from) & 0x3) << 2) \
+ | (lo2 >> 6) \
+ | 0x80); \
+ *(*toP)++ = ((lo2 & 0x3f) | 0x80); \
+ break; \
+ } \
+ } \
+ *fromP = from; \
+}
+
+#define DEFINE_UTF16_TO_UTF16(E) \
+static \
+void E ## toUtf16(const ENCODING *enc, \
+ const char **fromP, const char *fromLim, \
+ unsigned short **toP, const unsigned short *toLim) \
+{ \
+ /* Avoid copying first half only of surrogate */ \
+ if (fromLim - *fromP > ((toLim - *toP) << 1) \
+ && (GET_HI(fromLim - 2) & 0xF8) == 0xD8) \
+ fromLim -= 2; \
+ for (; *fromP != fromLim && *toP != toLim; *fromP += 2) \
+ *(*toP)++ = (GET_HI(*fromP) << 8) | GET_LO(*fromP); \
+}
+
+#define SET2(ptr, ch) \
+ (((ptr)[0] = ((ch) & 0xff)), ((ptr)[1] = ((ch) >> 8)))
+#define GET_LO(ptr) ((unsigned char)(ptr)[0])
+#define GET_HI(ptr) ((unsigned char)(ptr)[1])
+
+DEFINE_UTF16_TO_UTF8(little2_)
+DEFINE_UTF16_TO_UTF16(little2_)
+
+#undef SET2
+#undef GET_LO
+#undef GET_HI
+
+#define SET2(ptr, ch) \
+ (((ptr)[0] = ((ch) >> 8)), ((ptr)[1] = ((ch) & 0xFF)))
+#define GET_LO(ptr) ((unsigned char)(ptr)[1])
+#define GET_HI(ptr) ((unsigned char)(ptr)[0])
+
+DEFINE_UTF16_TO_UTF8(big2_)
+DEFINE_UTF16_TO_UTF16(big2_)
+
+#undef SET2
+#undef GET_LO
+#undef GET_HI
+
+#define LITTLE2_BYTE_TYPE(enc, p) \
+ ((p)[1] == 0 \
+ ? ((struct normal_encoding *)(enc))->type[(unsigned char)*(p)] \
+ : unicode_byte_type((p)[1], (p)[0]))
+#define LITTLE2_BYTE_TO_ASCII(enc, p) ((p)[1] == 0 ? (p)[0] : -1)
+#define LITTLE2_CHAR_MATCHES(enc, p, c) ((p)[1] == 0 && (p)[0] == c)
+#define LITTLE2_IS_NAME_CHAR_MINBPC(enc, p) \
+ UCS2_GET_NAMING(namePages, (unsigned char)p[1], (unsigned char)p[0])
+#define LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p) \
+ UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[1], (unsigned char)p[0])
+
+#ifdef XML_MIN_SIZE
+
+static
+int little2_byteType(const ENCODING *enc, const char *p)
+{
+ return LITTLE2_BYTE_TYPE(enc, p);
+}
+
+static
+int little2_byteToAscii(const ENCODING *enc, const char *p)
+{
+ return LITTLE2_BYTE_TO_ASCII(enc, p);
+}
+
+static
+int little2_charMatches(const ENCODING *enc, const char *p, int c)
+{
+ return LITTLE2_CHAR_MATCHES(enc, p, c);
+}
+
+static
+int little2_isNameMin(const ENCODING *enc, const char *p)
+{
+ return LITTLE2_IS_NAME_CHAR_MINBPC(enc, p);
+}
+
+static
+int little2_isNmstrtMin(const ENCODING *enc, const char *p)
+{
+ return LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p);
+}
+
+#undef VTABLE
+#define VTABLE VTABLE1, little2_toUtf8, little2_toUtf16
+
+#else /* not XML_MIN_SIZE */
+
+#undef PREFIX
+#define PREFIX(ident) little2_ ## ident
+#define MINBPC(enc) 2
+/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */
+#define BYTE_TYPE(enc, p) LITTLE2_BYTE_TYPE(enc, p)
+#define BYTE_TO_ASCII(enc, p) LITTLE2_BYTE_TO_ASCII(enc, p)
+#define CHAR_MATCHES(enc, p, c) LITTLE2_CHAR_MATCHES(enc, p, c)
+#define IS_NAME_CHAR(enc, p, n) 0
+#define IS_NAME_CHAR_MINBPC(enc, p) LITTLE2_IS_NAME_CHAR_MINBPC(enc, p)
+#define IS_NMSTRT_CHAR(enc, p, n) (0)
+#define IS_NMSTRT_CHAR_MINBPC(enc, p) LITTLE2_IS_NMSTRT_CHAR_MINBPC(enc, p)
+
+#include "xmltok_impl.c"
+
+#undef MINBPC
+#undef BYTE_TYPE
+#undef BYTE_TO_ASCII
+#undef CHAR_MATCHES
+#undef IS_NAME_CHAR
+#undef IS_NAME_CHAR_MINBPC
+#undef IS_NMSTRT_CHAR
+#undef IS_NMSTRT_CHAR_MINBPC
+#undef IS_INVALID_CHAR
+
+#endif /* not XML_MIN_SIZE */
+
+#ifdef XML_NS
+
+static const struct normal_encoding little2_encoding_ns = {
+ { VTABLE, 2, 0,
+#if XML_BYTE_ORDER == 12
+ 1
+#else
+ 0
+#endif
+ },
+ {
+#include "asciitab.h"
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(little2_)
+};
+
+#endif
+
+static const struct normal_encoding little2_encoding = {
+ { VTABLE, 2, 0,
+#if XML_BYTE_ORDER == 12
+ 1
+#else
+ 0
+#endif
+ },
+ {
+#define BT_COLON BT_NMSTRT
+#include "asciitab.h"
+#undef BT_COLON
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(little2_)
+};
+
+#if XML_BYTE_ORDER != 21
+
+#ifdef XML_NS
+
+static const struct normal_encoding internal_little2_encoding_ns = {
+ { VTABLE, 2, 0, 1 },
+ {
+#include "iasciitab.h"
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(little2_)
+};
+
+#endif
+
+static const struct normal_encoding internal_little2_encoding = {
+ { VTABLE, 2, 0, 1 },
+ {
+#define BT_COLON BT_NMSTRT
+#include "iasciitab.h"
+#undef BT_COLON
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(little2_)
+};
+
+#endif
+
+
+#define BIG2_BYTE_TYPE(enc, p) \
+ ((p)[0] == 0 \
+ ? ((struct normal_encoding *)(enc))->type[(unsigned char)(p)[1]] \
+ : unicode_byte_type((p)[0], (p)[1]))
+#define BIG2_BYTE_TO_ASCII(enc, p) ((p)[0] == 0 ? (p)[1] : -1)
+#define BIG2_CHAR_MATCHES(enc, p, c) ((p)[0] == 0 && (p)[1] == c)
+#define BIG2_IS_NAME_CHAR_MINBPC(enc, p) \
+ UCS2_GET_NAMING(namePages, (unsigned char)p[0], (unsigned char)p[1])
+#define BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p) \
+ UCS2_GET_NAMING(nmstrtPages, (unsigned char)p[0], (unsigned char)p[1])
+
+#ifdef XML_MIN_SIZE
+
+static
+int big2_byteType(const ENCODING *enc, const char *p)
+{
+ return BIG2_BYTE_TYPE(enc, p);
+}
+
+static
+int big2_byteToAscii(const ENCODING *enc, const char *p)
+{
+ return BIG2_BYTE_TO_ASCII(enc, p);
+}
+
+static
+int big2_charMatches(const ENCODING *enc, const char *p, int c)
+{
+ return BIG2_CHAR_MATCHES(enc, p, c);
+}
+
+static
+int big2_isNameMin(const ENCODING *enc, const char *p)
+{
+ return BIG2_IS_NAME_CHAR_MINBPC(enc, p);
+}
+
+static
+int big2_isNmstrtMin(const ENCODING *enc, const char *p)
+{
+ return BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p);
+}
+
+#undef VTABLE
+#define VTABLE VTABLE1, big2_toUtf8, big2_toUtf16
+
+#else /* not XML_MIN_SIZE */
+
+#undef PREFIX
+#define PREFIX(ident) big2_ ## ident
+#define MINBPC(enc) 2
+/* CHAR_MATCHES is guaranteed to have MINBPC bytes available. */
+#define BYTE_TYPE(enc, p) BIG2_BYTE_TYPE(enc, p)
+#define BYTE_TO_ASCII(enc, p) BIG2_BYTE_TO_ASCII(enc, p)
+#define CHAR_MATCHES(enc, p, c) BIG2_CHAR_MATCHES(enc, p, c)
+#define IS_NAME_CHAR(enc, p, n) 0
+#define IS_NAME_CHAR_MINBPC(enc, p) BIG2_IS_NAME_CHAR_MINBPC(enc, p)
+#define IS_NMSTRT_CHAR(enc, p, n) (0)
+#define IS_NMSTRT_CHAR_MINBPC(enc, p) BIG2_IS_NMSTRT_CHAR_MINBPC(enc, p)
+
+#include "xmltok_impl.c"
+
+#undef MINBPC
+#undef BYTE_TYPE
+#undef BYTE_TO_ASCII
+#undef CHAR_MATCHES
+#undef IS_NAME_CHAR
+#undef IS_NAME_CHAR_MINBPC
+#undef IS_NMSTRT_CHAR
+#undef IS_NMSTRT_CHAR_MINBPC
+#undef IS_INVALID_CHAR
+
+#endif /* not XML_MIN_SIZE */
+
+#ifdef XML_NS
+
+static const struct normal_encoding big2_encoding_ns = {
+ { VTABLE, 2, 0,
+#if XML_BYTE_ORDER == 21
+ 1
+#else
+ 0
+#endif
+ },
+ {
+#include "asciitab.h"
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(big2_)
+};
+
+#endif
+
+static const struct normal_encoding big2_encoding = {
+ { VTABLE, 2, 0,
+#if XML_BYTE_ORDER == 21
+ 1
+#else
+ 0
+#endif
+ },
+ {
+#define BT_COLON BT_NMSTRT
+#include "asciitab.h"
+#undef BT_COLON
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(big2_)
+};
+
+#if XML_BYTE_ORDER != 12
+
+#ifdef XML_NS
+
+static const struct normal_encoding internal_big2_encoding_ns = {
+ { VTABLE, 2, 0, 1 },
+ {
+#include "iasciitab.h"
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(big2_)
+};
+
+#endif
+
+static const struct normal_encoding internal_big2_encoding = {
+ { VTABLE, 2, 0, 1 },
+ {
+#define BT_COLON BT_NMSTRT
+#include "iasciitab.h"
+#undef BT_COLON
+#include "latin1tab.h"
+ },
+ STANDARD_VTABLE(big2_)
+};
+
+#endif
+
+#undef PREFIX
+
+static
+int streqci(const char *s1, const char *s2)
+{
+ for (;;) {
+ char c1 = *s1++;
+ char c2 = *s2++;
+ if (ASCII_a <= c1 && c1 <= ASCII_z)
+ c1 += ASCII_A - ASCII_a;
+ if (ASCII_a <= c2 && c2 <= ASCII_z)
+ c2 += ASCII_A - ASCII_a;
+ if (c1 != c2)
+ return 0;
+ if (!c1)
+ break;
+ }
+ return 1;
+}
+
+static
+void initUpdatePosition(const ENCODING *enc, const char *ptr,
+ const char *end, POSITION *pos)
+{
+ normal_updatePosition(&utf8_encoding.enc, ptr, end, pos);
+}
+
+static
+int toAscii(const ENCODING *enc, const char *ptr, const char *end)
+{
+ char buf[1];
+ char *p = buf;
+ XmlUtf8Convert(enc, &ptr, end, &p, p + 1);
+ if (p == buf)
+ return -1;
+ else
+ return buf[0];
+}
+
+static
+int isSpace(int c)
+{
+ switch (c) {
+ case 0x20:
+ case 0xD:
+ case 0xA:
+ case 0x9:
+ return 1;
+ }
+ return 0;
+}
+
+/* Return 1 if there's just optional white space
+or there's an S followed by name=val. */
+static
+int parsePseudoAttribute(const ENCODING *enc,
+ const char *ptr,
+ const char *end,
+ const char **namePtr,
+ const char **nameEndPtr,
+ const char **valPtr,
+ const char **nextTokPtr)
+{
+ int c;
+ char open;
+ if (ptr == end) {
+ *namePtr = 0;
+ return 1;
+ }
+ if (!isSpace(toAscii(enc, ptr, end))) {
+ *nextTokPtr = ptr;
+ return 0;
+ }
+ do {
+ ptr += enc->minBytesPerChar;
+ } while (isSpace(toAscii(enc, ptr, end)));
+ if (ptr == end) {
+ *namePtr = 0;
+ return 1;
+ }
+ *namePtr = ptr;
+ for (;;) {
+ c = toAscii(enc, ptr, end);
+ if (c == -1) {
+ *nextTokPtr = ptr;
+ return 0;
+ }
+ if (c == ASCII_EQUALS) {
+ *nameEndPtr = ptr;
+ break;
+ }
+ if (isSpace(c)) {
+ *nameEndPtr = ptr;
+ do {
+ ptr += enc->minBytesPerChar;
+ } while (isSpace(c = toAscii(enc, ptr, end)));
+ if (c != ASCII_EQUALS) {
+ *nextTokPtr = ptr;
+ return 0;
+ }
+ break;
+ }
+ ptr += enc->minBytesPerChar;
+ }
+ if (ptr == *namePtr) {
+ *nextTokPtr = ptr;
+ return 0;
+ }
+ ptr += enc->minBytesPerChar;
+ c = toAscii(enc, ptr, end);
+ while (isSpace(c)) {
+ ptr += enc->minBytesPerChar;
+ c = toAscii(enc, ptr, end);
+ }
+ if (c != ASCII_QUOT && c != ASCII_APOS) {
+ *nextTokPtr = ptr;
+ return 0;
+ }
+ open = c;
+ ptr += enc->minBytesPerChar;
+ *valPtr = ptr;
+ for (;; ptr += enc->minBytesPerChar) {
+ c = toAscii(enc, ptr, end);
+ if (c == open)
+ break;
+ if (!(ASCII_a <= c && c <= ASCII_z)
+ && !(ASCII_A <= c && c <= ASCII_Z)
+ && !(ASCII_0 <= c && c <= ASCII_9)
+ && c != ASCII_PERIOD
+ && c != ASCII_MINUS
+ && c != ASCII_UNDERSCORE) {
+ *nextTokPtr = ptr;
+ return 0;
+ }
+ }
+ *nextTokPtr = ptr + enc->minBytesPerChar;
+ return 1;
+}
+
+static const char KW_version[] = {
+ ASCII_v, ASCII_e, ASCII_r, ASCII_s, ASCII_i, ASCII_o, ASCII_n, '\0'
+};
+
+static const char KW_encoding[] = {
+ ASCII_e, ASCII_n, ASCII_c, ASCII_o, ASCII_d, ASCII_i, ASCII_n, ASCII_g, '\0'
+};
+
+static const char KW_standalone[] = {
+ ASCII_s, ASCII_t, ASCII_a, ASCII_n, ASCII_d, ASCII_a, ASCII_l, ASCII_o, ASCII_n, ASCII_e, '\0'
+};
+
+static const char KW_yes[] = {
+ ASCII_y, ASCII_e, ASCII_s, '\0'
+};
+
+static const char KW_no[] = {
+ ASCII_n, ASCII_o, '\0'
+};
+
+static
+int doParseXmlDecl(const ENCODING *(*encodingFinder)(const ENCODING *,
+ const char *,
+ const char *),
+ int isGeneralTextEntity,
+ const ENCODING *enc,
+ const char *ptr,
+ const char *end,
+ const char **badPtr,
+ const char **versionPtr,
+ const char **versionEndPtr,
+ const char **encodingName,
+ const ENCODING **encoding,
+ int *standalone)
+{
+ const char *val = 0;
+ const char *name = 0;
+ const char *nameEnd = 0;
+ ptr += 5 * enc->minBytesPerChar;
+ end -= 2 * enc->minBytesPerChar;
+ if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr) || !name) {
+ *badPtr = ptr;
+ return 0;
+ }
+ if (!XmlNameMatchesAscii(enc, name, nameEnd, KW_version)) {
+ if (!isGeneralTextEntity) {
+ *badPtr = name;
+ return 0;
+ }
+ }
+ else {
+ if (versionPtr)
+ *versionPtr = val;
+ if (versionEndPtr)
+ *versionEndPtr = ptr;
+ if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) {
+ *badPtr = ptr;
+ return 0;
+ }
+ if (!name) {
+ if (isGeneralTextEntity) {
+ /* a TextDecl must have an EncodingDecl */
+ *badPtr = ptr;
+ return 0;
+ }
+ return 1;
+ }
+ }
+ if (XmlNameMatchesAscii(enc, name, nameEnd, KW_encoding)) {
+ int c = toAscii(enc, val, end);
+ if (!(ASCII_a <= c && c <= ASCII_z) && !(ASCII_A <= c && c <= ASCII_Z)) {
+ *badPtr = val;
+ return 0;
+ }
+ if (encodingName)
+ *encodingName = val;
+ if (encoding)
+ *encoding = encodingFinder(enc, val, ptr - enc->minBytesPerChar);
+ if (!parsePseudoAttribute(enc, ptr, end, &name, &nameEnd, &val, &ptr)) {
+ *badPtr = ptr;
+ return 0;
+ }
+ if (!name)
+ return 1;
+ }
+ if (!XmlNameMatchesAscii(enc, name, nameEnd, KW_standalone) || isGeneralTextEntity) {
+ *badPtr = name;
+ return 0;
+ }
+ if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_yes)) {
+ if (standalone)
+ *standalone = 1;
+ }
+ else if (XmlNameMatchesAscii(enc, val, ptr - enc->minBytesPerChar, KW_no)) {
+ if (standalone)
+ *standalone = 0;
+ }
+ else {
+ *badPtr = val;
+ return 0;
+ }
+ while (isSpace(toAscii(enc, ptr, end)))
+ ptr += enc->minBytesPerChar;
+ if (ptr != end) {
+ *badPtr = ptr;
+ return 0;
+ }
+ return 1;
+}
+
+static
+int checkCharRefNumber(int result)
+{
+ switch (result >> 8) {
+ case 0xD8: case 0xD9: case 0xDA: case 0xDB:
+ case 0xDC: case 0xDD: case 0xDE: case 0xDF:
+ return -1;
+ case 0:
+ if (latin1_encoding.type[result] == BT_NONXML)
+ return -1;
+ break;
+ case 0xFF:
+ if (result == 0xFFFE || result == 0xFFFF)
+ return -1;
+ break;
+ }
+ return result;
+}
+
+int XmlUtf8Encode(int c, char *buf)
+{
+ enum {
+ /* minN is minimum legal resulting value for N byte sequence */
+ min2 = 0x80,
+ min3 = 0x800,
+ min4 = 0x10000
+ };
+
+ if (c < 0)
+ return 0;
+ if (c < min2) {
+ buf[0] = (c | UTF8_cval1);
+ return 1;
+ }
+ if (c < min3) {
+ buf[0] = ((c >> 6) | UTF8_cval2);
+ buf[1] = ((c & 0x3f) | 0x80);
+ return 2;
+ }
+ if (c < min4) {
+ buf[0] = ((c >> 12) | UTF8_cval3);
+ buf[1] = (((c >> 6) & 0x3f) | 0x80);
+ buf[2] = ((c & 0x3f) | 0x80);
+ return 3;
+ }
+ if (c < 0x110000) {
+ buf[0] = ((c >> 18) | UTF8_cval4);
+ buf[1] = (((c >> 12) & 0x3f) | 0x80);
+ buf[2] = (((c >> 6) & 0x3f) | 0x80);
+ buf[3] = ((c & 0x3f) | 0x80);
+ return 4;
+ }
+ return 0;
+}
+
+int XmlUtf16Encode(int charNum, unsigned short *buf)
+{
+ if (charNum < 0)
+ return 0;
+ if (charNum < 0x10000) {
+ buf[0] = charNum;
+ return 1;
+ }
+ if (charNum < 0x110000) {
+ charNum -= 0x10000;
+ buf[0] = (charNum >> 10) + 0xD800;
+ buf[1] = (charNum & 0x3FF) + 0xDC00;
+ return 2;
+ }
+ return 0;
+}
+
+struct unknown_encoding {
+ struct normal_encoding normal;
+ int (*convert)(void *userData, const char *p);
+ void *userData;
+ unsigned short utf16[256];
+ char utf8[256][4];
+};
+
+int XmlSizeOfUnknownEncoding(void)
+{
+ return sizeof(struct unknown_encoding);
+}
+
+static
+int unknown_isName(const ENCODING *enc, const char *p)
+{
+ int c = ((const struct unknown_encoding *)enc)
+ ->convert(((const struct unknown_encoding *)enc)->userData, p);
+ if (c & ~0xFFFF)
+ return 0;
+ return UCS2_GET_NAMING(namePages, c >> 8, c & 0xFF);
+}
+
+static
+int unknown_isNmstrt(const ENCODING *enc, const char *p)
+{
+ int c = ((const struct unknown_encoding *)enc)
+ ->convert(((const struct unknown_encoding *)enc)->userData, p);
+ if (c & ~0xFFFF)
+ return 0;
+ return UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xFF);
+}
+
+static
+int unknown_isInvalid(const ENCODING *enc, const char *p)
+{
+ int c = ((const struct unknown_encoding *)enc)
+ ->convert(((const struct unknown_encoding *)enc)->userData, p);
+ return (c & ~0xFFFF) || checkCharRefNumber(c) < 0;
+}
+
+static
+void unknown_toUtf8(const ENCODING *enc,
+ const char **fromP, const char *fromLim,
+ char **toP, const char *toLim)
+{
+ char buf[XML_UTF8_ENCODE_MAX];
+ for (;;) {
+ const char *utf8;
+ int n;
+ if (*fromP == fromLim)
+ break;
+ utf8 = ((const struct unknown_encoding *)enc)->utf8[(unsigned char)**fromP];
+ n = *utf8++;
+ if (n == 0) {
+ int c = ((const struct unknown_encoding *)enc)
+ ->convert(((const struct unknown_encoding *)enc)->userData, *fromP);
+ n = XmlUtf8Encode(c, buf);
+ if (n > toLim - *toP)
+ break;
+ utf8 = buf;
+ *fromP += ((const struct normal_encoding *)enc)->type[(unsigned char)**fromP]
+ - (BT_LEAD2 - 2);
+ }
+ else {
+ if (n > toLim - *toP)
+ break;
+ (*fromP)++;
+ }
+ do {
+ *(*toP)++ = *utf8++;
+ } while (--n != 0);
+ }
+}
+
+static
+void unknown_toUtf16(const ENCODING *enc,
+ const char **fromP, const char *fromLim,
+ unsigned short **toP, const unsigned short *toLim)
+{
+ while (*fromP != fromLim && *toP != toLim) {
+ unsigned short c
+ = ((const struct unknown_encoding *)enc)->utf16[(unsigned char)**fromP];
+ if (c == 0) {
+ c = (unsigned short)((const struct unknown_encoding *)enc)
+ ->convert(((const struct unknown_encoding *)enc)->userData, *fromP);
+ *fromP += ((const struct normal_encoding *)enc)->type[(unsigned char)**fromP]
+ - (BT_LEAD2 - 2);
+ }
+ else
+ (*fromP)++;
+ *(*toP)++ = c;
+ }
+}
+
+ENCODING *
+XmlInitUnknownEncoding(void *mem,
+ int *table,
+ int (*convert)(void *userData, const char *p),
+ void *userData)
+{
+ int i;
+ struct unknown_encoding *e = mem;
+ for (i = 0; i < (int)sizeof(struct normal_encoding); i++)
+ ((char *)mem)[i] = ((char *)&latin1_encoding)[i];
+ for (i = 0; i < 128; i++)
+ if (latin1_encoding.type[i] != BT_OTHER
+ && latin1_encoding.type[i] != BT_NONXML
+ && table[i] != i)
+ return 0;
+ for (i = 0; i < 256; i++) {
+ int c = table[i];
+ if (c == -1) {
+ e->normal.type[i] = BT_MALFORM;
+ /* This shouldn't really get used. */
+ e->utf16[i] = 0xFFFF;
+ e->utf8[i][0] = 1;
+ e->utf8[i][1] = 0;
+ }
+ else if (c < 0) {
+ if (c < -4)
+ return 0;
+ e->normal.type[i] = BT_LEAD2 - (c + 2);
+ e->utf8[i][0] = 0;
+ e->utf16[i] = 0;
+ }
+ else if (c < 0x80) {
+ if (latin1_encoding.type[c] != BT_OTHER
+ && latin1_encoding.type[c] != BT_NONXML
+ && c != i)
+ return 0;
+ e->normal.type[i] = latin1_encoding.type[c];
+ e->utf8[i][0] = 1;
+ e->utf8[i][1] = (char)c;
+ e->utf16[i] = c == 0 ? 0xFFFF : c;
+ }
+ else if (checkCharRefNumber(c) < 0) {
+ e->normal.type[i] = BT_NONXML;
+ /* This shouldn't really get used. */
+ e->utf16[i] = 0xFFFF;
+ e->utf8[i][0] = 1;
+ e->utf8[i][1] = 0;
+ }
+ else {
+ if (c > 0xFFFF)
+ return 0;
+ if (UCS2_GET_NAMING(nmstrtPages, c >> 8, c & 0xff))
+ e->normal.type[i] = BT_NMSTRT;
+ else if (UCS2_GET_NAMING(namePages, c >> 8, c & 0xff))
+ e->normal.type[i] = BT_NAME;
+ else
+ e->normal.type[i] = BT_OTHER;
+ e->utf8[i][0] = (char)XmlUtf8Encode(c, e->utf8[i] + 1);
+ e->utf16[i] = c;
+ }
+ }
+ e->userData = userData;
+ e->convert = convert;
+ if (convert) {
+ e->normal.isName2 = unknown_isName;
+ e->normal.isName3 = unknown_isName;
+ e->normal.isName4 = unknown_isName;
+ e->normal.isNmstrt2 = unknown_isNmstrt;
+ e->normal.isNmstrt3 = unknown_isNmstrt;
+ e->normal.isNmstrt4 = unknown_isNmstrt;
+ e->normal.isInvalid2 = unknown_isInvalid;
+ e->normal.isInvalid3 = unknown_isInvalid;
+ e->normal.isInvalid4 = unknown_isInvalid;
+ }
+ e->normal.enc.utf8Convert = unknown_toUtf8;
+ e->normal.enc.utf16Convert = unknown_toUtf16;
+ return &(e->normal.enc);
+}
+
+/* If this enumeration is changed, getEncodingIndex and encodings
+must also be changed. */
+enum {
+ UNKNOWN_ENC = -1,
+ ISO_8859_1_ENC = 0,
+ US_ASCII_ENC,
+ UTF_8_ENC,
+ UTF_16_ENC,
+ UTF_16BE_ENC,
+ UTF_16LE_ENC,
+ /* must match encodingNames up to here */
+ NO_ENC
+};
+
+static const char KW_ISO_8859_1[] = {
+ ASCII_I, ASCII_S, ASCII_O, ASCII_MINUS, ASCII_8, ASCII_8, ASCII_5, ASCII_9, ASCII_MINUS, ASCII_1, '\0'
+};
+static const char KW_US_ASCII[] = {
+ ASCII_U, ASCII_S, ASCII_MINUS, ASCII_A, ASCII_S, ASCII_C, ASCII_I, ASCII_I, '\0'
+};
+static const char KW_UTF_8[] = {
+ ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_8, '\0'
+};
+static const char KW_UTF_16[] = {
+ ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, '\0'
+};
+static const char KW_UTF_16BE[] = {
+ ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, ASCII_B, ASCII_E, '\0'
+};
+static const char KW_UTF_16LE[] = {
+ ASCII_U, ASCII_T, ASCII_F, ASCII_MINUS, ASCII_1, ASCII_6, ASCII_L, ASCII_E, '\0'
+};
+
+static
+int getEncodingIndex(const char *name)
+{
+ static const char *encodingNames[] = {
+ KW_ISO_8859_1,
+ KW_US_ASCII,
+ KW_UTF_8,
+ KW_UTF_16,
+ KW_UTF_16BE,
+ KW_UTF_16LE,
+ };
+ int i;
+ if (name == 0)
+ return NO_ENC;
+ for (i = 0; i < (int)(sizeof(encodingNames)/sizeof(encodingNames[0])); i++)
+ if (streqci(name, encodingNames[i]))
+ return i;
+ return UNKNOWN_ENC;
+}
+
+/* For binary compatibility, we store the index of the encoding specified
+at initialization in the isUtf16 member. */
+
+#define INIT_ENC_INDEX(enc) ((int)(enc)->initEnc.isUtf16)
+#define SET_INIT_ENC_INDEX(enc, i) ((enc)->initEnc.isUtf16 = (char)i)
+
+/* This is what detects the encoding.
+encodingTable maps from encoding indices to encodings;
+INIT_ENC_INDEX(enc) is the index of the external (protocol) specified encoding;
+state is XML_CONTENT_STATE if we're parsing an external text entity,
+and XML_PROLOG_STATE otherwise.
+*/
+
+
+static
+int initScan(const ENCODING **encodingTable,
+ const INIT_ENCODING *enc,
+ int state,
+ const char *ptr,
+ const char *end,
+ const char **nextTokPtr)
+{
+ const ENCODING **encPtr;
+
+ if (ptr == end)
+ return XML_TOK_NONE;
+ encPtr = enc->encPtr;
+ if (ptr + 1 == end) {
+ /* only a single byte available for auto-detection */
+#ifndef XML_DTD /* FIXME */
+ /* a well-formed document entity must have more than one byte */
+ if (state != XML_CONTENT_STATE)
+ return XML_TOK_PARTIAL;
+#endif
+ /* so we're parsing an external text entity... */
+ /* if UTF-16 was externally specified, then we need at least 2 bytes */
+ switch (INIT_ENC_INDEX(enc)) {
+ case UTF_16_ENC:
+ case UTF_16LE_ENC:
+ case UTF_16BE_ENC:
+ return XML_TOK_PARTIAL;
+ }
+ switch ((unsigned char)*ptr) {
+ case 0xFE:
+ case 0xFF:
+ case 0xEF: /* possibly first byte of UTF-8 BOM */
+ if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC
+ && state == XML_CONTENT_STATE)
+ break;
+ /* fall through */
+ case 0x00:
+ case 0x3C:
+ return XML_TOK_PARTIAL;
+ }
+ }
+ else {
+ switch (((unsigned char)ptr[0] << 8) | (unsigned char)ptr[1]) {
+ case 0xFEFF:
+ if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC
+ && state == XML_CONTENT_STATE)
+ break;
+ *nextTokPtr = ptr + 2;
+ *encPtr = encodingTable[UTF_16BE_ENC];
+ return XML_TOK_BOM;
+ /* 00 3C is handled in the default case */
+ case 0x3C00:
+ if ((INIT_ENC_INDEX(enc) == UTF_16BE_ENC
+ || INIT_ENC_INDEX(enc) == UTF_16_ENC)
+ && state == XML_CONTENT_STATE)
+ break;
+ *encPtr = encodingTable[UTF_16LE_ENC];
+ return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
+ case 0xFFFE:
+ if (INIT_ENC_INDEX(enc) == ISO_8859_1_ENC
+ && state == XML_CONTENT_STATE)
+ break;
+ *nextTokPtr = ptr + 2;
+ *encPtr = encodingTable[UTF_16LE_ENC];
+ return XML_TOK_BOM;
+ case 0xEFBB:
+ /* Maybe a UTF-8 BOM (EF BB BF) */
+ /* If there's an explicitly specified (external) encoding
+ of ISO-8859-1 or some flavour of UTF-16
+ and this is an external text entity,
+ don't look for the BOM,
+ because it might be a legal data. */
+ if (state == XML_CONTENT_STATE) {
+ int e = INIT_ENC_INDEX(enc);
+ if (e == ISO_8859_1_ENC || e == UTF_16BE_ENC || e == UTF_16LE_ENC || e == UTF_16_ENC)
+ break;
+ }
+ if (ptr + 2 == end)
+ return XML_TOK_PARTIAL;
+ if ((unsigned char)ptr[2] == 0xBF) {
+ *nextTokPtr = ptr + 3;
+ *encPtr = encodingTable[UTF_8_ENC];
+ return XML_TOK_BOM;
+ }
+ break;
+ default:
+ if (ptr[0] == '\0') {
+ /* 0 isn't a legal data character. Furthermore a document entity can only
+ start with ASCII characters. So the only way this can fail to be big-endian
+ UTF-16 if it it's an external parsed general entity that's labelled as
+ UTF-16LE. */
+ if (state == XML_CONTENT_STATE && INIT_ENC_INDEX(enc) == UTF_16LE_ENC)
+ break;
+ *encPtr = encodingTable[UTF_16BE_ENC];
+ return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
+ }
+ else if (ptr[1] == '\0') {
+ /* We could recover here in the case:
+ - parsing an external entity
+ - second byte is 0
+ - no externally specified encoding
+ - no encoding declaration
+ by assuming UTF-16LE. But we don't, because this would mean when
+ presented just with a single byte, we couldn't reliably determine
+ whether we needed further bytes. */
+ if (state == XML_CONTENT_STATE)
+ break;
+ *encPtr = encodingTable[UTF_16LE_ENC];
+ return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
+ }
+ break;
+ }
+ }
+ *encPtr = encodingTable[INIT_ENC_INDEX(enc)];
+ return XmlTok(*encPtr, state, ptr, end, nextTokPtr);
+}
+
+
+#define NS(x) x
+#define ns(x) x
+#include "xmltok_ns.c"
+#undef NS
+#undef ns
+
+#ifdef XML_NS
+
+#define NS(x) x ## NS
+#define ns(x) x ## _ns
+
+#include "xmltok_ns.c"
+
+#undef NS
+#undef ns
+
+ENCODING *
+XmlInitUnknownEncodingNS(void *mem,
+ int *table,
+ int (*convert)(void *userData, const char *p),
+ void *userData)
+{
+ ENCODING *enc = XmlInitUnknownEncoding(mem, table, convert, userData);
+ if (enc)
+ ((struct normal_encoding *)enc)->type[ASCII_COLON] = BT_COLON;
+ return enc;
+}
+
+#endif /* XML_NS */
--- /dev/null
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file COPYING for copying permission.
+*/
+
+#ifndef XmlTok_INCLUDED
+#define XmlTok_INCLUDED 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The following token may be returned by XmlContentTok */
+#define XML_TOK_TRAILING_RSQB -5 /* ] or ]] at the end of the scan; might be start of
+ illegal ]]> sequence */
+/* The following tokens may be returned by both XmlPrologTok and XmlContentTok */
+#define XML_TOK_NONE -4 /* The string to be scanned is empty */
+#define XML_TOK_TRAILING_CR -3 /* A CR at the end of the scan;
+ might be part of CRLF sequence */
+#define XML_TOK_PARTIAL_CHAR -2 /* only part of a multibyte sequence */
+#define XML_TOK_PARTIAL -1 /* only part of a token */
+#define XML_TOK_INVALID 0
+
+/* The following tokens are returned by XmlContentTok; some are also
+ returned by XmlAttributeValueTok, XmlEntityTok, XmlCdataSectionTok */
+
+#define XML_TOK_START_TAG_WITH_ATTS 1
+#define XML_TOK_START_TAG_NO_ATTS 2
+#define XML_TOK_EMPTY_ELEMENT_WITH_ATTS 3 /* empty element tag <e/> */
+#define XML_TOK_EMPTY_ELEMENT_NO_ATTS 4
+#define XML_TOK_END_TAG 5
+#define XML_TOK_DATA_CHARS 6
+#define XML_TOK_DATA_NEWLINE 7
+#define XML_TOK_CDATA_SECT_OPEN 8
+#define XML_TOK_ENTITY_REF 9
+#define XML_TOK_CHAR_REF 10 /* numeric character reference */
+
+/* The following tokens may be returned by both XmlPrologTok and XmlContentTok */
+#define XML_TOK_PI 11 /* processing instruction */
+#define XML_TOK_XML_DECL 12 /* XML decl or text decl */
+#define XML_TOK_COMMENT 13
+#define XML_TOK_BOM 14 /* Byte order mark */
+
+/* The following tokens are returned only by XmlPrologTok */
+#define XML_TOK_PROLOG_S 15
+#define XML_TOK_DECL_OPEN 16 /* <!foo */
+#define XML_TOK_DECL_CLOSE 17 /* > */
+#define XML_TOK_NAME 18
+#define XML_TOK_NMTOKEN 19
+#define XML_TOK_POUND_NAME 20 /* #name */
+#define XML_TOK_OR 21 /* | */
+#define XML_TOK_PERCENT 22
+#define XML_TOK_OPEN_PAREN 23
+#define XML_TOK_CLOSE_PAREN 24
+#define XML_TOK_OPEN_BRACKET 25
+#define XML_TOK_CLOSE_BRACKET 26
+#define XML_TOK_LITERAL 27
+#define XML_TOK_PARAM_ENTITY_REF 28
+#define XML_TOK_INSTANCE_START 29
+
+/* The following occur only in element type declarations */
+#define XML_TOK_NAME_QUESTION 30 /* name? */
+#define XML_TOK_NAME_ASTERISK 31 /* name* */
+#define XML_TOK_NAME_PLUS 32 /* name+ */
+#define XML_TOK_COND_SECT_OPEN 33 /* <![ */
+#define XML_TOK_COND_SECT_CLOSE 34 /* ]]> */
+#define XML_TOK_CLOSE_PAREN_QUESTION 35 /* )? */
+#define XML_TOK_CLOSE_PAREN_ASTERISK 36 /* )* */
+#define XML_TOK_CLOSE_PAREN_PLUS 37 /* )+ */
+#define XML_TOK_COMMA 38
+
+/* The following token is returned only by XmlAttributeValueTok */
+#define XML_TOK_ATTRIBUTE_VALUE_S 39
+
+/* The following token is returned only by XmlCdataSectionTok */
+#define XML_TOK_CDATA_SECT_CLOSE 40
+
+/* With namespace processing this is returned by XmlPrologTok
+ for a name with a colon. */
+#define XML_TOK_PREFIXED_NAME 41
+
+#ifdef XML_DTD
+#define XML_TOK_IGNORE_SECT 42
+#endif /* XML_DTD */
+
+#ifdef XML_DTD
+#define XML_N_STATES 4
+#else /* not XML_DTD */
+#define XML_N_STATES 3
+#endif /* not XML_DTD */
+
+#define XML_PROLOG_STATE 0
+#define XML_CONTENT_STATE 1
+#define XML_CDATA_SECTION_STATE 2
+#ifdef XML_DTD
+#define XML_IGNORE_SECTION_STATE 3
+#endif /* XML_DTD */
+
+#define XML_N_LITERAL_TYPES 2
+#define XML_ATTRIBUTE_VALUE_LITERAL 0
+#define XML_ENTITY_VALUE_LITERAL 1
+
+/* The size of the buffer passed to XmlUtf8Encode must be at least this. */
+#define XML_UTF8_ENCODE_MAX 4
+/* The size of the buffer passed to XmlUtf16Encode must be at least this. */
+#define XML_UTF16_ENCODE_MAX 2
+
+typedef struct position {
+ /* first line and first column are 0 not 1 */
+ unsigned long lineNumber;
+ unsigned long columnNumber;
+} POSITION;
+
+typedef struct {
+ const char *name;
+ const char *valuePtr;
+ const char *valueEnd;
+ char normalized;
+} ATTRIBUTE;
+
+struct encoding;
+typedef struct encoding ENCODING;
+
+struct encoding {
+ int (*scanners[XML_N_STATES])(const ENCODING *,
+ const char *,
+ const char *,
+ const char **);
+ int (*literalScanners[XML_N_LITERAL_TYPES])(const ENCODING *,
+ const char *,
+ const char *,
+ const char **);
+ int (*sameName)(const ENCODING *,
+ const char *, const char *);
+ int (*nameMatchesAscii)(const ENCODING *,
+ const char *, const char *, const char *);
+ int (*nameLength)(const ENCODING *, const char *);
+ const char *(*skipS)(const ENCODING *, const char *);
+ int (*getAtts)(const ENCODING *enc, const char *ptr,
+ int attsMax, ATTRIBUTE *atts);
+ int (*charRefNumber)(const ENCODING *enc, const char *ptr);
+ int (*predefinedEntityName)(const ENCODING *, const char *, const char *);
+ void (*updatePosition)(const ENCODING *,
+ const char *ptr,
+ const char *end,
+ POSITION *);
+ int (*isPublicId)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **badPtr);
+ void (*utf8Convert)(const ENCODING *enc,
+ const char **fromP,
+ const char *fromLim,
+ char **toP,
+ const char *toLim);
+ void (*utf16Convert)(const ENCODING *enc,
+ const char **fromP,
+ const char *fromLim,
+ unsigned short **toP,
+ const unsigned short *toLim);
+ int minBytesPerChar;
+ char isUtf8;
+ char isUtf16;
+};
+
+/*
+Scan the string starting at ptr until the end of the next complete token,
+but do not scan past eptr. Return an integer giving the type of token.
+
+Return XML_TOK_NONE when ptr == eptr; nextTokPtr will not be set.
+
+Return XML_TOK_PARTIAL when the string does not contain a complete token;
+nextTokPtr will not be set.
+
+Return XML_TOK_INVALID when the string does not start a valid token; nextTokPtr
+will be set to point to the character which made the token invalid.
+
+Otherwise the string starts with a valid token; nextTokPtr will be set to point
+to the character following the end of that token.
+
+Each data character counts as a single token, but adjacent data characters
+may be returned together. Similarly for characters in the prolog outside
+literals, comments and processing instructions.
+*/
+
+
+#define XmlTok(enc, state, ptr, end, nextTokPtr) \
+ (((enc)->scanners[state])(enc, ptr, end, nextTokPtr))
+
+#define XmlPrologTok(enc, ptr, end, nextTokPtr) \
+ XmlTok(enc, XML_PROLOG_STATE, ptr, end, nextTokPtr)
+
+#define XmlContentTok(enc, ptr, end, nextTokPtr) \
+ XmlTok(enc, XML_CONTENT_STATE, ptr, end, nextTokPtr)
+
+#define XmlCdataSectionTok(enc, ptr, end, nextTokPtr) \
+ XmlTok(enc, XML_CDATA_SECTION_STATE, ptr, end, nextTokPtr)
+
+#ifdef XML_DTD
+
+#define XmlIgnoreSectionTok(enc, ptr, end, nextTokPtr) \
+ XmlTok(enc, XML_IGNORE_SECTION_STATE, ptr, end, nextTokPtr)
+
+#endif /* XML_DTD */
+
+/* This is used for performing a 2nd-level tokenization on
+the content of a literal that has already been returned by XmlTok. */
+
+#define XmlLiteralTok(enc, literalType, ptr, end, nextTokPtr) \
+ (((enc)->literalScanners[literalType])(enc, ptr, end, nextTokPtr))
+
+#define XmlAttributeValueTok(enc, ptr, end, nextTokPtr) \
+ XmlLiteralTok(enc, XML_ATTRIBUTE_VALUE_LITERAL, ptr, end, nextTokPtr)
+
+#define XmlEntityValueTok(enc, ptr, end, nextTokPtr) \
+ XmlLiteralTok(enc, XML_ENTITY_VALUE_LITERAL, ptr, end, nextTokPtr)
+
+#define XmlSameName(enc, ptr1, ptr2) (((enc)->sameName)(enc, ptr1, ptr2))
+
+#define XmlNameMatchesAscii(enc, ptr1, end1, ptr2) \
+ (((enc)->nameMatchesAscii)(enc, ptr1, end1, ptr2))
+
+#define XmlNameLength(enc, ptr) \
+ (((enc)->nameLength)(enc, ptr))
+
+#define XmlSkipS(enc, ptr) \
+ (((enc)->skipS)(enc, ptr))
+
+#define XmlGetAttributes(enc, ptr, attsMax, atts) \
+ (((enc)->getAtts)(enc, ptr, attsMax, atts))
+
+#define XmlCharRefNumber(enc, ptr) \
+ (((enc)->charRefNumber)(enc, ptr))
+
+#define XmlPredefinedEntityName(enc, ptr, end) \
+ (((enc)->predefinedEntityName)(enc, ptr, end))
+
+#define XmlUpdatePosition(enc, ptr, end, pos) \
+ (((enc)->updatePosition)(enc, ptr, end, pos))
+
+#define XmlIsPublicId(enc, ptr, end, badPtr) \
+ (((enc)->isPublicId)(enc, ptr, end, badPtr))
+
+#define XmlUtf8Convert(enc, fromP, fromLim, toP, toLim) \
+ (((enc)->utf8Convert)(enc, fromP, fromLim, toP, toLim))
+
+#define XmlUtf16Convert(enc, fromP, fromLim, toP, toLim) \
+ (((enc)->utf16Convert)(enc, fromP, fromLim, toP, toLim))
+
+typedef struct {
+ ENCODING initEnc;
+ const ENCODING **encPtr;
+} INIT_ENCODING;
+
+int XmlParseXmlDecl(int isGeneralTextEntity,
+ const ENCODING *enc,
+ const char *ptr,
+ const char *end,
+ const char **badPtr,
+ const char **versionPtr,
+ const char **versionEndPtr,
+ const char **encodingNamePtr,
+ const ENCODING **namedEncodingPtr,
+ int *standalonePtr);
+
+int XmlInitEncoding(INIT_ENCODING *, const ENCODING **, const char *name);
+const ENCODING *XmlGetUtf8InternalEncoding(void);
+const ENCODING *XmlGetUtf16InternalEncoding(void);
+int XmlUtf8Encode(int charNumber, char *buf);
+int XmlUtf16Encode(int charNumber, unsigned short *buf);
+
+int XmlSizeOfUnknownEncoding(void);
+ENCODING *
+XmlInitUnknownEncoding(void *mem,
+ int *table,
+ int (*conv)(void *userData, const char *p),
+ void *userData);
+
+int XmlParseXmlDeclNS(int isGeneralTextEntity,
+ const ENCODING *enc,
+ const char *ptr,
+ const char *end,
+ const char **badPtr,
+ const char **versionPtr,
+ const char **versionEndPtr,
+ const char **encodingNamePtr,
+ const ENCODING **namedEncodingPtr,
+ int *standalonePtr);
+int XmlInitEncodingNS(INIT_ENCODING *, const ENCODING **, const char *name);
+const ENCODING *XmlGetUtf8InternalEncodingNS(void);
+const ENCODING *XmlGetUtf16InternalEncodingNS(void);
+ENCODING *
+XmlInitUnknownEncodingNS(void *mem,
+ int *table,
+ int (*conv)(void *userData, const char *p),
+ void *userData);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* not XmlTok_INCLUDED */
--- /dev/null
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file COPYING for copying permission.
+*/
+
+#ifndef IS_INVALID_CHAR
+#define IS_INVALID_CHAR(enc, ptr, n) (0)
+#endif
+
+#define INVALID_LEAD_CASE(n, ptr, nextTokPtr) \
+ case BT_LEAD ## n: \
+ if (end - ptr < n) \
+ return XML_TOK_PARTIAL_CHAR; \
+ if (IS_INVALID_CHAR(enc, ptr, n)) { \
+ *(nextTokPtr) = (ptr); \
+ return XML_TOK_INVALID; \
+ } \
+ ptr += n; \
+ break;
+
+#define INVALID_CASES(ptr, nextTokPtr) \
+ INVALID_LEAD_CASE(2, ptr, nextTokPtr) \
+ INVALID_LEAD_CASE(3, ptr, nextTokPtr) \
+ INVALID_LEAD_CASE(4, ptr, nextTokPtr) \
+ case BT_NONXML: \
+ case BT_MALFORM: \
+ case BT_TRAIL: \
+ *(nextTokPtr) = (ptr); \
+ return XML_TOK_INVALID;
+
+#define CHECK_NAME_CASE(n, enc, ptr, end, nextTokPtr) \
+ case BT_LEAD ## n: \
+ if (end - ptr < n) \
+ return XML_TOK_PARTIAL_CHAR; \
+ if (!IS_NAME_CHAR(enc, ptr, n)) { \
+ *nextTokPtr = ptr; \
+ return XML_TOK_INVALID; \
+ } \
+ ptr += n; \
+ break;
+
+#define CHECK_NAME_CASES(enc, ptr, end, nextTokPtr) \
+ case BT_NONASCII: \
+ if (!IS_NAME_CHAR_MINBPC(enc, ptr)) { \
+ *nextTokPtr = ptr; \
+ return XML_TOK_INVALID; \
+ } \
+ case BT_NMSTRT: \
+ case BT_HEX: \
+ case BT_DIGIT: \
+ case BT_NAME: \
+ case BT_MINUS: \
+ ptr += MINBPC(enc); \
+ break; \
+ CHECK_NAME_CASE(2, enc, ptr, end, nextTokPtr) \
+ CHECK_NAME_CASE(3, enc, ptr, end, nextTokPtr) \
+ CHECK_NAME_CASE(4, enc, ptr, end, nextTokPtr)
+
+#define CHECK_NMSTRT_CASE(n, enc, ptr, end, nextTokPtr) \
+ case BT_LEAD ## n: \
+ if (end - ptr < n) \
+ return XML_TOK_PARTIAL_CHAR; \
+ if (!IS_NMSTRT_CHAR(enc, ptr, n)) { \
+ *nextTokPtr = ptr; \
+ return XML_TOK_INVALID; \
+ } \
+ ptr += n; \
+ break;
+
+#define CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr) \
+ case BT_NONASCII: \
+ if (!IS_NMSTRT_CHAR_MINBPC(enc, ptr)) { \
+ *nextTokPtr = ptr; \
+ return XML_TOK_INVALID; \
+ } \
+ case BT_NMSTRT: \
+ case BT_HEX: \
+ ptr += MINBPC(enc); \
+ break; \
+ CHECK_NMSTRT_CASE(2, enc, ptr, end, nextTokPtr) \
+ CHECK_NMSTRT_CASE(3, enc, ptr, end, nextTokPtr) \
+ CHECK_NMSTRT_CASE(4, enc, ptr, end, nextTokPtr)
+
+#ifndef PREFIX
+#define PREFIX(ident) ident
+#endif
+
+/* ptr points to character following "<!-" */
+
+static
+int PREFIX(scanComment)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ if (ptr != end) {
+ if (!CHAR_MATCHES(enc, ptr, ASCII_MINUS)) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ ptr += MINBPC(enc);
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ INVALID_CASES(ptr, nextTokPtr)
+ case BT_MINUS:
+ if ((ptr += MINBPC(enc)) == end)
+ return XML_TOK_PARTIAL;
+ if (CHAR_MATCHES(enc, ptr, ASCII_MINUS)) {
+ if ((ptr += MINBPC(enc)) == end)
+ return XML_TOK_PARTIAL;
+ if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_COMMENT;
+ }
+ break;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "<!" */
+
+static
+int PREFIX(scanDecl)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_MINUS:
+ return PREFIX(scanComment)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_LSQB:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_COND_SECT_OPEN;
+ case BT_NMSTRT:
+ case BT_HEX:
+ ptr += MINBPC(enc);
+ break;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_PERCNT:
+ if (ptr + MINBPC(enc) == end)
+ return XML_TOK_PARTIAL;
+ /* don't allow <!ENTITY% foo "whatever"> */
+ switch (BYTE_TYPE(enc, ptr + MINBPC(enc))) {
+ case BT_S: case BT_CR: case BT_LF: case BT_PERCNT:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ /* fall through */
+ case BT_S: case BT_CR: case BT_LF:
+ *nextTokPtr = ptr;
+ return XML_TOK_DECL_OPEN;
+ case BT_NMSTRT:
+ case BT_HEX:
+ ptr += MINBPC(enc);
+ break;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+static
+int PREFIX(checkPiTarget)(const ENCODING *enc, const char *ptr, const char *end, int *tokPtr)
+{
+ int upper = 0;
+ *tokPtr = XML_TOK_PI;
+ if (end - ptr != MINBPC(enc)*3)
+ return 1;
+ switch (BYTE_TO_ASCII(enc, ptr)) {
+ case ASCII_x:
+ break;
+ case ASCII_X:
+ upper = 1;
+ break;
+ default:
+ return 1;
+ }
+ ptr += MINBPC(enc);
+ switch (BYTE_TO_ASCII(enc, ptr)) {
+ case ASCII_m:
+ break;
+ case ASCII_M:
+ upper = 1;
+ break;
+ default:
+ return 1;
+ }
+ ptr += MINBPC(enc);
+ switch (BYTE_TO_ASCII(enc, ptr)) {
+ case ASCII_l:
+ break;
+ case ASCII_L:
+ upper = 1;
+ break;
+ default:
+ return 1;
+ }
+ if (upper)
+ return 0;
+ *tokPtr = XML_TOK_XML_DECL;
+ return 1;
+}
+
+/* ptr points to character following "<?" */
+
+static
+int PREFIX(scanPi)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ int tok;
+ const char *target = ptr;
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ case BT_S: case BT_CR: case BT_LF:
+ if (!PREFIX(checkPiTarget)(enc, target, ptr, &tok)) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ ptr += MINBPC(enc);
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ INVALID_CASES(ptr, nextTokPtr)
+ case BT_QUEST:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ if (CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+ *nextTokPtr = ptr + MINBPC(enc);
+ return tok;
+ }
+ break;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ return XML_TOK_PARTIAL;
+ case BT_QUEST:
+ if (!PREFIX(checkPiTarget)(enc, target, ptr, &tok)) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ if (CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+ *nextTokPtr = ptr + MINBPC(enc);
+ return tok;
+ }
+ /* fall through */
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+
+static
+int PREFIX(scanCdataSection)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ static const char CDATA_LSQB[] = { ASCII_C, ASCII_D, ASCII_A, ASCII_T, ASCII_A, ASCII_LSQB };
+ int i;
+ /* CDATA[ */
+ if (end - ptr < 6 * MINBPC(enc))
+ return XML_TOK_PARTIAL;
+ for (i = 0; i < 6; i++, ptr += MINBPC(enc)) {
+ if (!CHAR_MATCHES(enc, ptr, CDATA_LSQB[i])) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_CDATA_SECT_OPEN;
+}
+
+static
+int PREFIX(cdataSectionTok)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ if (ptr == end)
+ return XML_TOK_NONE;
+ if (MINBPC(enc) > 1) {
+ size_t n = end - ptr;
+ if (n & (MINBPC(enc) - 1)) {
+ n &= ~(MINBPC(enc) - 1);
+ if (n == 0)
+ return XML_TOK_PARTIAL;
+ end = ptr + n;
+ }
+ }
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_RSQB:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ if (!CHAR_MATCHES(enc, ptr, ASCII_RSQB))
+ break;
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+ ptr -= MINBPC(enc);
+ break;
+ }
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_CDATA_SECT_CLOSE;
+ case BT_CR:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ if (BYTE_TYPE(enc, ptr) == BT_LF)
+ ptr += MINBPC(enc);
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_NEWLINE;
+ case BT_LF:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_DATA_NEWLINE;
+ INVALID_CASES(ptr, nextTokPtr)
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: \
+ if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \
+ *nextTokPtr = ptr; \
+ return XML_TOK_DATA_CHARS; \
+ } \
+ ptr += n; \
+ break;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_NONXML:
+ case BT_MALFORM:
+ case BT_TRAIL:
+ case BT_CR:
+ case BT_LF:
+ case BT_RSQB:
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+}
+
+/* ptr points to character following "</" */
+
+static
+int PREFIX(scanEndTag)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ case BT_S: case BT_CR: case BT_LF:
+ for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_S: case BT_CR: case BT_LF:
+ break;
+ case BT_GT:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_END_TAG;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+#ifdef XML_NS
+ case BT_COLON:
+ /* no need to check qname syntax here, since end-tag must match exactly */
+ ptr += MINBPC(enc);
+ break;
+#endif
+ case BT_GT:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_END_TAG;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "&#X" */
+
+static
+int PREFIX(scanHexCharRef)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ if (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_DIGIT:
+ case BT_HEX:
+ break;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_DIGIT:
+ case BT_HEX:
+ break;
+ case BT_SEMI:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_CHAR_REF;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "&#" */
+
+static
+int PREFIX(scanCharRef)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ if (ptr != end) {
+ if (CHAR_MATCHES(enc, ptr, ASCII_x))
+ return PREFIX(scanHexCharRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_DIGIT:
+ break;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ for (ptr += MINBPC(enc); ptr != end; ptr += MINBPC(enc)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_DIGIT:
+ break;
+ case BT_SEMI:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_CHAR_REF;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "&" */
+
+static
+int PREFIX(scanRef)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ case BT_NUM:
+ return PREFIX(scanCharRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ case BT_SEMI:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_ENTITY_REF;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following first character of attribute name */
+
+static
+int PREFIX(scanAtts)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+#ifdef XML_NS
+ int hadColon = 0;
+#endif
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+#ifdef XML_NS
+ case BT_COLON:
+ if (hadColon) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ hadColon = 1;
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ break;
+#endif
+ case BT_S: case BT_CR: case BT_LF:
+ for (;;) {
+ int t;
+
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ t = BYTE_TYPE(enc, ptr);
+ if (t == BT_EQUALS)
+ break;
+ switch (t) {
+ case BT_S:
+ case BT_LF:
+ case BT_CR:
+ break;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ /* fall through */
+ case BT_EQUALS:
+ {
+ int open;
+#ifdef XML_NS
+ hadColon = 0;
+#endif
+ for (;;) {
+
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ open = BYTE_TYPE(enc, ptr);
+ if (open == BT_QUOT || open == BT_APOS)
+ break;
+ switch (open) {
+ case BT_S:
+ case BT_LF:
+ case BT_CR:
+ break;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ ptr += MINBPC(enc);
+ /* in attribute value */
+ for (;;) {
+ int t;
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ t = BYTE_TYPE(enc, ptr);
+ if (t == open)
+ break;
+ switch (t) {
+ INVALID_CASES(ptr, nextTokPtr)
+ case BT_AMP:
+ {
+ int tok = PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, &ptr);
+ if (tok <= 0) {
+ if (tok == XML_TOK_INVALID)
+ *nextTokPtr = ptr;
+ return tok;
+ }
+ break;
+ }
+ case BT_LT:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_S:
+ case BT_CR:
+ case BT_LF:
+ break;
+ case BT_SOL:
+ goto sol;
+ case BT_GT:
+ goto gt;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ /* ptr points to closing quote */
+ for (;;) {
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ case BT_S: case BT_CR: case BT_LF:
+ continue;
+ case BT_GT:
+ gt:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_START_TAG_WITH_ATTS;
+ case BT_SOL:
+ sol:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_EMPTY_ELEMENT_WITH_ATTS;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ break;
+ }
+ break;
+ }
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+/* ptr points to character following "<" */
+
+static
+int PREFIX(scanLt)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+#ifdef XML_NS
+ int hadColon;
+#endif
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ case BT_EXCL:
+ if ((ptr += MINBPC(enc)) == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_MINUS:
+ return PREFIX(scanComment)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_LSQB:
+ return PREFIX(scanCdataSection)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ case BT_QUEST:
+ return PREFIX(scanPi)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_SOL:
+ return PREFIX(scanEndTag)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+#ifdef XML_NS
+ hadColon = 0;
+#endif
+ /* we have a start-tag */
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+#ifdef XML_NS
+ case BT_COLON:
+ if (hadColon) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ hadColon = 1;
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ break;
+#endif
+ case BT_S: case BT_CR: case BT_LF:
+ {
+ ptr += MINBPC(enc);
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ case BT_GT:
+ goto gt;
+ case BT_SOL:
+ goto sol;
+ case BT_S: case BT_CR: case BT_LF:
+ ptr += MINBPC(enc);
+ continue;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ return PREFIX(scanAtts)(enc, ptr, end, nextTokPtr);
+ }
+ return XML_TOK_PARTIAL;
+ }
+ case BT_GT:
+ gt:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_START_TAG_NO_ATTS;
+ case BT_SOL:
+ sol:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_EMPTY_ELEMENT_NO_ATTS;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+static
+int PREFIX(contentTok)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ if (ptr == end)
+ return XML_TOK_NONE;
+ if (MINBPC(enc) > 1) {
+ size_t n = end - ptr;
+ if (n & (MINBPC(enc) - 1)) {
+ n &= ~(MINBPC(enc) - 1);
+ if (n == 0)
+ return XML_TOK_PARTIAL;
+ end = ptr + n;
+ }
+ }
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_LT:
+ return PREFIX(scanLt)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_AMP:
+ return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_CR:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_TRAILING_CR;
+ if (BYTE_TYPE(enc, ptr) == BT_LF)
+ ptr += MINBPC(enc);
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_NEWLINE;
+ case BT_LF:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_DATA_NEWLINE;
+ case BT_RSQB:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_TRAILING_RSQB;
+ if (!CHAR_MATCHES(enc, ptr, ASCII_RSQB))
+ break;
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_TRAILING_RSQB;
+ if (!CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+ ptr -= MINBPC(enc);
+ break;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ INVALID_CASES(ptr, nextTokPtr)
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: \
+ if (end - ptr < n || IS_INVALID_CHAR(enc, ptr, n)) { \
+ *nextTokPtr = ptr; \
+ return XML_TOK_DATA_CHARS; \
+ } \
+ ptr += n; \
+ break;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_RSQB:
+ if (ptr + MINBPC(enc) != end) {
+ if (!CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_RSQB)) {
+ ptr += MINBPC(enc);
+ break;
+ }
+ if (ptr + 2*MINBPC(enc) != end) {
+ if (!CHAR_MATCHES(enc, ptr + 2*MINBPC(enc), ASCII_GT)) {
+ ptr += MINBPC(enc);
+ break;
+ }
+ *nextTokPtr = ptr + 2*MINBPC(enc);
+ return XML_TOK_INVALID;
+ }
+ }
+ /* fall through */
+ case BT_AMP:
+ case BT_LT:
+ case BT_NONXML:
+ case BT_MALFORM:
+ case BT_TRAIL:
+ case BT_CR:
+ case BT_LF:
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+}
+
+/* ptr points to character following "%" */
+
+static
+int PREFIX(scanPercent)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ case BT_S: case BT_LF: case BT_CR: case BT_PERCNT:
+ *nextTokPtr = ptr;
+ return XML_TOK_PERCENT;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ case BT_SEMI:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_PARAM_ENTITY_REF;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+static
+int PREFIX(scanPoundName)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NMSTRT_CASES(enc, ptr, end, nextTokPtr)
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ case BT_CR: case BT_LF: case BT_S:
+ case BT_RPAR: case BT_GT: case BT_PERCNT: case BT_VERBAR:
+ *nextTokPtr = ptr;
+ return XML_TOK_POUND_NAME;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return -XML_TOK_POUND_NAME;
+}
+
+static
+int PREFIX(scanLit)(int open, const ENCODING *enc,
+ const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ while (ptr != end) {
+ int t = BYTE_TYPE(enc, ptr);
+ switch (t) {
+ INVALID_CASES(ptr, nextTokPtr)
+ case BT_QUOT:
+ case BT_APOS:
+ ptr += MINBPC(enc);
+ if (t != open)
+ break;
+ if (ptr == end)
+ return -XML_TOK_LITERAL;
+ *nextTokPtr = ptr;
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_S: case BT_CR: case BT_LF:
+ case BT_GT: case BT_PERCNT: case BT_LSQB:
+ return XML_TOK_LITERAL;
+ default:
+ return XML_TOK_INVALID;
+ }
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+static
+int PREFIX(prologTok)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ int tok;
+ if (ptr == end)
+ return XML_TOK_NONE;
+ if (MINBPC(enc) > 1) {
+ size_t n = end - ptr;
+ if (n & (MINBPC(enc) - 1)) {
+ n &= ~(MINBPC(enc) - 1);
+ if (n == 0)
+ return XML_TOK_PARTIAL;
+ end = ptr + n;
+ }
+ }
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_QUOT:
+ return PREFIX(scanLit)(BT_QUOT, enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_APOS:
+ return PREFIX(scanLit)(BT_APOS, enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_LT:
+ {
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_EXCL:
+ return PREFIX(scanDecl)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_QUEST:
+ return PREFIX(scanPi)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_NMSTRT:
+ case BT_HEX:
+ case BT_NONASCII:
+ case BT_LEAD2:
+ case BT_LEAD3:
+ case BT_LEAD4:
+ *nextTokPtr = ptr - MINBPC(enc);
+ return XML_TOK_INSTANCE_START;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ case BT_CR:
+ if (ptr + MINBPC(enc) == end)
+ return -XML_TOK_PROLOG_S;
+ /* fall through */
+ case BT_S: case BT_LF:
+ for (;;) {
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ break;
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_S: case BT_LF:
+ break;
+ case BT_CR:
+ /* don't split CR/LF pair */
+ if (ptr + MINBPC(enc) != end)
+ break;
+ /* fall through */
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_PROLOG_S;
+ }
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_PROLOG_S;
+ case BT_PERCNT:
+ return PREFIX(scanPercent)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ case BT_COMMA:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_COMMA;
+ case BT_LSQB:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_OPEN_BRACKET;
+ case BT_RSQB:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return -XML_TOK_CLOSE_BRACKET;
+ if (CHAR_MATCHES(enc, ptr, ASCII_RSQB)) {
+ if (ptr + MINBPC(enc) == end)
+ return XML_TOK_PARTIAL;
+ if (CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_GT)) {
+ *nextTokPtr = ptr + 2*MINBPC(enc);
+ return XML_TOK_COND_SECT_CLOSE;
+ }
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_CLOSE_BRACKET;
+ case BT_LPAR:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_OPEN_PAREN;
+ case BT_RPAR:
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return -XML_TOK_CLOSE_PAREN;
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_AST:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_CLOSE_PAREN_ASTERISK;
+ case BT_QUEST:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_CLOSE_PAREN_QUESTION;
+ case BT_PLUS:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_CLOSE_PAREN_PLUS;
+ case BT_CR: case BT_LF: case BT_S:
+ case BT_GT: case BT_COMMA: case BT_VERBAR:
+ case BT_RPAR:
+ *nextTokPtr = ptr;
+ return XML_TOK_CLOSE_PAREN;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ case BT_VERBAR:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_OR;
+ case BT_GT:
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_DECL_CLOSE;
+ case BT_NUM:
+ return PREFIX(scanPoundName)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: \
+ if (end - ptr < n) \
+ return XML_TOK_PARTIAL_CHAR; \
+ if (IS_NMSTRT_CHAR(enc, ptr, n)) { \
+ ptr += n; \
+ tok = XML_TOK_NAME; \
+ break; \
+ } \
+ if (IS_NAME_CHAR(enc, ptr, n)) { \
+ ptr += n; \
+ tok = XML_TOK_NMTOKEN; \
+ break; \
+ } \
+ *nextTokPtr = ptr; \
+ return XML_TOK_INVALID;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_NMSTRT:
+ case BT_HEX:
+ tok = XML_TOK_NAME;
+ ptr += MINBPC(enc);
+ break;
+ case BT_DIGIT:
+ case BT_NAME:
+ case BT_MINUS:
+#ifdef XML_NS
+ case BT_COLON:
+#endif
+ tok = XML_TOK_NMTOKEN;
+ ptr += MINBPC(enc);
+ break;
+ case BT_NONASCII:
+ if (IS_NMSTRT_CHAR_MINBPC(enc, ptr)) {
+ ptr += MINBPC(enc);
+ tok = XML_TOK_NAME;
+ break;
+ }
+ if (IS_NAME_CHAR_MINBPC(enc, ptr)) {
+ ptr += MINBPC(enc);
+ tok = XML_TOK_NMTOKEN;
+ break;
+ }
+ /* fall through */
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ case BT_GT: case BT_RPAR: case BT_COMMA:
+ case BT_VERBAR: case BT_LSQB: case BT_PERCNT:
+ case BT_S: case BT_CR: case BT_LF:
+ *nextTokPtr = ptr;
+ return tok;
+#ifdef XML_NS
+ case BT_COLON:
+ ptr += MINBPC(enc);
+ switch (tok) {
+ case XML_TOK_NAME:
+ if (ptr == end)
+ return XML_TOK_PARTIAL;
+ tok = XML_TOK_PREFIXED_NAME;
+ switch (BYTE_TYPE(enc, ptr)) {
+ CHECK_NAME_CASES(enc, ptr, end, nextTokPtr)
+ default:
+ tok = XML_TOK_NMTOKEN;
+ break;
+ }
+ break;
+ case XML_TOK_PREFIXED_NAME:
+ tok = XML_TOK_NMTOKEN;
+ break;
+ }
+ break;
+#endif
+ case BT_PLUS:
+ if (tok == XML_TOK_NMTOKEN) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_NAME_PLUS;
+ case BT_AST:
+ if (tok == XML_TOK_NMTOKEN) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_NAME_ASTERISK;
+ case BT_QUEST:
+ if (tok == XML_TOK_NMTOKEN) {
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_NAME_QUESTION;
+ default:
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ }
+ }
+ return -tok;
+}
+
+static
+int PREFIX(attributeValueTok)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ const char *start;
+ if (ptr == end)
+ return XML_TOK_NONE;
+ start = ptr;
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: ptr += n; break;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_AMP:
+ if (ptr == start)
+ return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ case BT_LT:
+ /* this is for inside entity references */
+ *nextTokPtr = ptr;
+ return XML_TOK_INVALID;
+ case BT_LF:
+ if (ptr == start) {
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_DATA_NEWLINE;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ case BT_CR:
+ if (ptr == start) {
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_TRAILING_CR;
+ if (BYTE_TYPE(enc, ptr) == BT_LF)
+ ptr += MINBPC(enc);
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_NEWLINE;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ case BT_S:
+ if (ptr == start) {
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_ATTRIBUTE_VALUE_S;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+}
+
+static
+int PREFIX(entityValueTok)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ const char *start;
+ if (ptr == end)
+ return XML_TOK_NONE;
+ start = ptr;
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: ptr += n; break;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_AMP:
+ if (ptr == start)
+ return PREFIX(scanRef)(enc, ptr + MINBPC(enc), end, nextTokPtr);
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ case BT_PERCNT:
+ if (ptr == start) {
+ int tok = PREFIX(scanPercent)(enc, ptr + MINBPC(enc),
+ end, nextTokPtr);
+ return (tok == XML_TOK_PERCENT) ? XML_TOK_INVALID : tok;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ case BT_LF:
+ if (ptr == start) {
+ *nextTokPtr = ptr + MINBPC(enc);
+ return XML_TOK_DATA_NEWLINE;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ case BT_CR:
+ if (ptr == start) {
+ ptr += MINBPC(enc);
+ if (ptr == end)
+ return XML_TOK_TRAILING_CR;
+ if (BYTE_TYPE(enc, ptr) == BT_LF)
+ ptr += MINBPC(enc);
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_NEWLINE;
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ *nextTokPtr = ptr;
+ return XML_TOK_DATA_CHARS;
+}
+
+#ifdef XML_DTD
+
+static
+int PREFIX(ignoreSectionTok)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ int level = 0;
+ if (MINBPC(enc) > 1) {
+ size_t n = end - ptr;
+ if (n & (MINBPC(enc) - 1)) {
+ n &= ~(MINBPC(enc) - 1);
+ end = ptr + n;
+ }
+ }
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ INVALID_CASES(ptr, nextTokPtr)
+ case BT_LT:
+ if ((ptr += MINBPC(enc)) == end)
+ return XML_TOK_PARTIAL;
+ if (CHAR_MATCHES(enc, ptr, ASCII_EXCL)) {
+ if ((ptr += MINBPC(enc)) == end)
+ return XML_TOK_PARTIAL;
+ if (CHAR_MATCHES(enc, ptr, ASCII_LSQB)) {
+ ++level;
+ ptr += MINBPC(enc);
+ }
+ }
+ break;
+ case BT_RSQB:
+ if ((ptr += MINBPC(enc)) == end)
+ return XML_TOK_PARTIAL;
+ if (CHAR_MATCHES(enc, ptr, ASCII_RSQB)) {
+ if ((ptr += MINBPC(enc)) == end)
+ return XML_TOK_PARTIAL;
+ if (CHAR_MATCHES(enc, ptr, ASCII_GT)) {
+ ptr += MINBPC(enc);
+ if (level == 0) {
+ *nextTokPtr = ptr;
+ return XML_TOK_IGNORE_SECT;
+ }
+ --level;
+ }
+ }
+ break;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ }
+ return XML_TOK_PARTIAL;
+}
+
+#endif /* XML_DTD */
+
+static
+int PREFIX(isPublicId)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **badPtr)
+{
+ ptr += MINBPC(enc);
+ end -= MINBPC(enc);
+ for (; ptr != end; ptr += MINBPC(enc)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_DIGIT:
+ case BT_HEX:
+ case BT_MINUS:
+ case BT_APOS:
+ case BT_LPAR:
+ case BT_RPAR:
+ case BT_PLUS:
+ case BT_COMMA:
+ case BT_SOL:
+ case BT_EQUALS:
+ case BT_QUEST:
+ case BT_CR:
+ case BT_LF:
+ case BT_SEMI:
+ case BT_EXCL:
+ case BT_AST:
+ case BT_PERCNT:
+ case BT_NUM:
+#ifdef XML_NS
+ case BT_COLON:
+#endif
+ break;
+ case BT_S:
+ if (CHAR_MATCHES(enc, ptr, ASCII_TAB)) {
+ *badPtr = ptr;
+ return 0;
+ }
+ break;
+ case BT_NAME:
+ case BT_NMSTRT:
+ if (!(BYTE_TO_ASCII(enc, ptr) & ~0x7f))
+ break;
+ default:
+ switch (BYTE_TO_ASCII(enc, ptr)) {
+ case 0x24: /* $ */
+ case 0x40: /* @ */
+ break;
+ default:
+ *badPtr = ptr;
+ return 0;
+ }
+ break;
+ }
+ }
+ return 1;
+}
+
+/* This must only be called for a well-formed start-tag or empty element tag.
+Returns the number of attributes. Pointers to the first attsMax attributes
+are stored in atts. */
+
+static
+int PREFIX(getAtts)(const ENCODING *enc, const char *ptr,
+ int attsMax, ATTRIBUTE *atts)
+{
+ enum { other, inName, inValue } state = inName;
+ int nAtts = 0;
+ int open = 0; /* defined when state == inValue;
+ initialization just to shut up compilers */
+
+ for (ptr += MINBPC(enc);; ptr += MINBPC(enc)) {
+ switch (BYTE_TYPE(enc, ptr)) {
+#define START_NAME \
+ if (state == other) { \
+ if (nAtts < attsMax) { \
+ atts[nAtts].name = ptr; \
+ atts[nAtts].normalized = 1; \
+ } \
+ state = inName; \
+ }
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: START_NAME ptr += (n - MINBPC(enc)); break;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_NONASCII:
+ case BT_NMSTRT:
+ case BT_HEX:
+ START_NAME
+ break;
+#undef START_NAME
+ case BT_QUOT:
+ if (state != inValue) {
+ if (nAtts < attsMax)
+ atts[nAtts].valuePtr = ptr + MINBPC(enc);
+ state = inValue;
+ open = BT_QUOT;
+ }
+ else if (open == BT_QUOT) {
+ state = other;
+ if (nAtts < attsMax)
+ atts[nAtts].valueEnd = ptr;
+ nAtts++;
+ }
+ break;
+ case BT_APOS:
+ if (state != inValue) {
+ if (nAtts < attsMax)
+ atts[nAtts].valuePtr = ptr + MINBPC(enc);
+ state = inValue;
+ open = BT_APOS;
+ }
+ else if (open == BT_APOS) {
+ state = other;
+ if (nAtts < attsMax)
+ atts[nAtts].valueEnd = ptr;
+ nAtts++;
+ }
+ break;
+ case BT_AMP:
+ if (nAtts < attsMax)
+ atts[nAtts].normalized = 0;
+ break;
+ case BT_S:
+ if (state == inName)
+ state = other;
+ else if (state == inValue
+ && nAtts < attsMax
+ && atts[nAtts].normalized
+ && (ptr == atts[nAtts].valuePtr
+ || BYTE_TO_ASCII(enc, ptr) != ASCII_SPACE
+ || BYTE_TO_ASCII(enc, ptr + MINBPC(enc)) == ASCII_SPACE
+ || BYTE_TYPE(enc, ptr + MINBPC(enc)) == open))
+ atts[nAtts].normalized = 0;
+ break;
+ case BT_CR: case BT_LF:
+ /* This case ensures that the first attribute name is counted
+ Apart from that we could just change state on the quote. */
+ if (state == inName)
+ state = other;
+ else if (state == inValue && nAtts < attsMax)
+ atts[nAtts].normalized = 0;
+ break;
+ case BT_GT:
+ case BT_SOL:
+ if (state != inValue)
+ return nAtts;
+ break;
+ default:
+ break;
+ }
+ }
+ /* not reached */
+}
+
+static
+int PREFIX(charRefNumber)(const ENCODING *enc, const char *ptr)
+{
+ int result = 0;
+ /* skip &# */
+ ptr += 2*MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, ASCII_x)) {
+ for (ptr += MINBPC(enc); !CHAR_MATCHES(enc, ptr, ASCII_SEMI); ptr += MINBPC(enc)) {
+ int c = BYTE_TO_ASCII(enc, ptr);
+ switch (c) {
+ case ASCII_0: case ASCII_1: case ASCII_2: case ASCII_3: case ASCII_4:
+ case ASCII_5: case ASCII_6: case ASCII_7: case ASCII_8: case ASCII_9:
+ result <<= 4;
+ result |= (c - ASCII_0);
+ break;
+ case ASCII_A: case ASCII_B: case ASCII_C: case ASCII_D: case ASCII_E: case ASCII_F:
+ result <<= 4;
+ result += 10 + (c - ASCII_A);
+ break;
+ case ASCII_a: case ASCII_b: case ASCII_c: case ASCII_d: case ASCII_e: case ASCII_f:
+ result <<= 4;
+ result += 10 + (c - ASCII_a);
+ break;
+ }
+ if (result >= 0x110000)
+ return -1;
+ }
+ }
+ else {
+ for (; !CHAR_MATCHES(enc, ptr, ASCII_SEMI); ptr += MINBPC(enc)) {
+ int c = BYTE_TO_ASCII(enc, ptr);
+ result *= 10;
+ result += (c - ASCII_0);
+ if (result >= 0x110000)
+ return -1;
+ }
+ }
+ return checkCharRefNumber(result);
+}
+
+static
+int PREFIX(predefinedEntityName)(const ENCODING *enc, const char *ptr, const char *end)
+{
+ switch ((end - ptr)/MINBPC(enc)) {
+ case 2:
+ if (CHAR_MATCHES(enc, ptr + MINBPC(enc), ASCII_t)) {
+ switch (BYTE_TO_ASCII(enc, ptr)) {
+ case ASCII_l:
+ return ASCII_LT;
+ case ASCII_g:
+ return ASCII_GT;
+ }
+ }
+ break;
+ case 3:
+ if (CHAR_MATCHES(enc, ptr, ASCII_a)) {
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, ASCII_m)) {
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, ASCII_p))
+ return ASCII_AMP;
+ }
+ }
+ break;
+ case 4:
+ switch (BYTE_TO_ASCII(enc, ptr)) {
+ case ASCII_q:
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, ASCII_u)) {
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, ASCII_o)) {
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, ASCII_t))
+ return ASCII_QUOT;
+ }
+ }
+ break;
+ case ASCII_a:
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, ASCII_p)) {
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, ASCII_o)) {
+ ptr += MINBPC(enc);
+ if (CHAR_MATCHES(enc, ptr, ASCII_s))
+ return ASCII_APOS;
+ }
+ }
+ break;
+ }
+ }
+ return 0;
+}
+
+static
+int PREFIX(sameName)(const ENCODING *enc, const char *ptr1, const char *ptr2)
+{
+ for (;;) {
+ switch (BYTE_TYPE(enc, ptr1)) {
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: \
+ if (*ptr1++ != *ptr2++) \
+ return 0;
+ LEAD_CASE(4) LEAD_CASE(3) LEAD_CASE(2)
+#undef LEAD_CASE
+ /* fall through */
+ if (*ptr1++ != *ptr2++)
+ return 0;
+ break;
+ case BT_NONASCII:
+ case BT_NMSTRT:
+#ifdef XML_NS
+ case BT_COLON:
+#endif
+ case BT_HEX:
+ case BT_DIGIT:
+ case BT_NAME:
+ case BT_MINUS:
+ if (*ptr2++ != *ptr1++)
+ return 0;
+ if (MINBPC(enc) > 1) {
+ if (*ptr2++ != *ptr1++)
+ return 0;
+ if (MINBPC(enc) > 2) {
+ if (*ptr2++ != *ptr1++)
+ return 0;
+ if (MINBPC(enc) > 3) {
+ if (*ptr2++ != *ptr1++)
+ return 0;
+ }
+ }
+ }
+ break;
+ default:
+ if (MINBPC(enc) == 1 && *ptr1 == *ptr2)
+ return 1;
+ switch (BYTE_TYPE(enc, ptr2)) {
+ case BT_LEAD2:
+ case BT_LEAD3:
+ case BT_LEAD4:
+ case BT_NONASCII:
+ case BT_NMSTRT:
+#ifdef XML_NS
+ case BT_COLON:
+#endif
+ case BT_HEX:
+ case BT_DIGIT:
+ case BT_NAME:
+ case BT_MINUS:
+ return 0;
+ default:
+ return 1;
+ }
+ }
+ }
+ /* not reached */
+}
+
+static
+int PREFIX(nameMatchesAscii)(const ENCODING *enc, const char *ptr1,
+ const char *end1, const char *ptr2)
+{
+ for (; *ptr2; ptr1 += MINBPC(enc), ptr2++) {
+ if (ptr1 == end1)
+ return 0;
+ if (!CHAR_MATCHES(enc, ptr1, *ptr2))
+ return 0;
+ }
+ return ptr1 == end1;
+}
+
+static
+int PREFIX(nameLength)(const ENCODING *enc, const char *ptr)
+{
+ const char *start = ptr;
+ for (;;) {
+ switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: ptr += n; break;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_NONASCII:
+ case BT_NMSTRT:
+#ifdef XML_NS
+ case BT_COLON:
+#endif
+ case BT_HEX:
+ case BT_DIGIT:
+ case BT_NAME:
+ case BT_MINUS:
+ ptr += MINBPC(enc);
+ break;
+ default:
+ return ptr - start;
+ }
+ }
+}
+
+static
+const char *PREFIX(skipS)(const ENCODING *enc, const char *ptr)
+{
+ for (;;) {
+ switch (BYTE_TYPE(enc, ptr)) {
+ case BT_LF:
+ case BT_CR:
+ case BT_S:
+ ptr += MINBPC(enc);
+ break;
+ default:
+ return ptr;
+ }
+ }
+}
+
+static
+void PREFIX(updatePosition)(const ENCODING *enc,
+ const char *ptr,
+ const char *end,
+ POSITION *pos)
+{
+ while (ptr != end) {
+ switch (BYTE_TYPE(enc, ptr)) {
+#define LEAD_CASE(n) \
+ case BT_LEAD ## n: \
+ ptr += n; \
+ break;
+ LEAD_CASE(2) LEAD_CASE(3) LEAD_CASE(4)
+#undef LEAD_CASE
+ case BT_LF:
+ pos->columnNumber = (unsigned)-1;
+ pos->lineNumber++;
+ ptr += MINBPC(enc);
+ break;
+ case BT_CR:
+ pos->lineNumber++;
+ ptr += MINBPC(enc);
+ if (ptr != end && BYTE_TYPE(enc, ptr) == BT_LF)
+ ptr += MINBPC(enc);
+ pos->columnNumber = (unsigned)-1;
+ break;
+ default:
+ ptr += MINBPC(enc);
+ break;
+ }
+ pos->columnNumber++;
+ }
+}
+
+#undef DO_LEAD_CASE
+#undef MULTIBYTE_CASES
+#undef INVALID_CASES
+#undef CHECK_NAME_CASE
+#undef CHECK_NAME_CASES
+#undef CHECK_NMSTRT_CASE
+#undef CHECK_NMSTRT_CASES
--- /dev/null
+/*
+Copyright (c) 1998, 1999 Thai Open Source Software Center Ltd
+See the file COPYING for copying permission.
+*/
+
+enum {
+ BT_NONXML,
+ BT_MALFORM,
+ BT_LT,
+ BT_AMP,
+ BT_RSQB,
+ BT_LEAD2,
+ BT_LEAD3,
+ BT_LEAD4,
+ BT_TRAIL,
+ BT_CR,
+ BT_LF,
+ BT_GT,
+ BT_QUOT,
+ BT_APOS,
+ BT_EQUALS,
+ BT_QUEST,
+ BT_EXCL,
+ BT_SOL,
+ BT_SEMI,
+ BT_NUM,
+ BT_LSQB,
+ BT_S,
+ BT_NMSTRT,
+ BT_COLON,
+ BT_HEX,
+ BT_DIGIT,
+ BT_NAME,
+ BT_MINUS,
+ BT_OTHER, /* known not to be a name or name start character */
+ BT_NONASCII, /* might be a name or name start character */
+ BT_PERCNT,
+ BT_LPAR,
+ BT_RPAR,
+ BT_AST,
+ BT_PLUS,
+ BT_COMMA,
+ BT_VERBAR
+};
+
+#include <stddef.h>
--- /dev/null
+const ENCODING *NS(XmlGetUtf8InternalEncoding)(void)
+{
+ return &ns(internal_utf8_encoding).enc;
+}
+
+const ENCODING *NS(XmlGetUtf16InternalEncoding)(void)
+{
+#if XML_BYTE_ORDER == 12
+ return &ns(internal_little2_encoding).enc;
+#elif XML_BYTE_ORDER == 21
+ return &ns(internal_big2_encoding).enc;
+#else
+ const short n = 1;
+ return *(const char *)&n ? &ns(internal_little2_encoding).enc : &ns(internal_big2_encoding).enc;
+#endif
+}
+
+static
+const ENCODING *NS(encodings)[] = {
+ &ns(latin1_encoding).enc,
+ &ns(ascii_encoding).enc,
+ &ns(utf8_encoding).enc,
+ &ns(big2_encoding).enc,
+ &ns(big2_encoding).enc,
+ &ns(little2_encoding).enc,
+ &ns(utf8_encoding).enc /* NO_ENC */
+};
+
+static
+int NS(initScanProlog)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ return initScan(NS(encodings), (const INIT_ENCODING *)enc, XML_PROLOG_STATE, ptr, end, nextTokPtr);
+}
+
+static
+int NS(initScanContent)(const ENCODING *enc, const char *ptr, const char *end,
+ const char **nextTokPtr)
+{
+ return initScan(NS(encodings), (const INIT_ENCODING *)enc, XML_CONTENT_STATE, ptr, end, nextTokPtr);
+}
+
+int NS(XmlInitEncoding)(INIT_ENCODING *p, const ENCODING **encPtr, const char *name)
+{
+ int i = getEncodingIndex(name);
+ if (i == UNKNOWN_ENC)
+ return 0;
+ SET_INIT_ENC_INDEX(p, i);
+ p->initEnc.scanners[XML_PROLOG_STATE] = NS(initScanProlog);
+ p->initEnc.scanners[XML_CONTENT_STATE] = NS(initScanContent);
+ p->initEnc.updatePosition = initUpdatePosition;
+ p->encPtr = encPtr;
+ *encPtr = &(p->initEnc);
+ return 1;
+}
+
+static
+const ENCODING *NS(findEncoding)(const ENCODING *enc, const char *ptr, const char *end)
+{
+#define ENCODING_MAX 128
+ char buf[ENCODING_MAX];
+ char *p = buf;
+ int i;
+ XmlUtf8Convert(enc, &ptr, end, &p, p + ENCODING_MAX - 1);
+ if (ptr != end)
+ return 0;
+ *p = 0;
+ if (streqci(buf, KW_UTF_16) && enc->minBytesPerChar == 2)
+ return enc;
+ i = getEncodingIndex(buf);
+ if (i == UNKNOWN_ENC)
+ return 0;
+ return NS(encodings)[i];
+}
+
+int NS(XmlParseXmlDecl)(int isGeneralTextEntity,
+ const ENCODING *enc,
+ const char *ptr,
+ const char *end,
+ const char **badPtr,
+ const char **versionPtr,
+ const char **versionEndPtr,
+ const char **encodingName,
+ const ENCODING **encoding,
+ int *standalone)
+{
+ return doParseXmlDecl(NS(findEncoding),
+ isGeneralTextEntity,
+ enc,
+ ptr,
+ end,
+ badPtr,
+ versionPtr,
+ versionEndPtr,
+ encodingName,
+ encoding,
+ standalone);
+}