2_0_13 release branch
git-svn-id: https://svn.apache.org/repos/asf/perl/modperl/branches/release@1913168 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/2_0_13/BRANCHING b/2_0_13/BRANCHING
new file mode 100644
index 0000000..ccb962f
--- /dev/null
+++ b/2_0_13/BRANCHING
@@ -0,0 +1,81 @@
+This doc explains how to create/work/re-merge svn branches
+
+#######################################
+### PREREQUISITE ###
+#######################################
+
+You need to have svnmerge installed and working
+before you can proceed with rest of the instructions.
+
+You can find it here:
+
+http://www.orcaware.com/svn/wiki/Svnmerge.py
+
+#######################################
+### make a new branch ###
+#######################################
+
+we will create a branch mybranch
+
+branch:
+
+ svn copy https://svn.apache.org/repos/asf/perl/modperl/trunk \
+ https://svn.apache.org/repos/asf/perl/modperl/branches/mybranch \
+ -m "creating mybranch"
+
+check out:
+
+ svn co https://svn.apache.org/repos/asf/perl/modperl/branches/mybranch
+
+change externals to point to the new A-T branch (if one was done)
+
+ svn propedit svn:externals .
+
+initialize svnmerge tracking in the branch (if you plan to pull trunk/ changes into the branch)
+
+mybranch/ $> svnmerge init
+property 'svnmerge-integrated' set on '.'
+mybranch/ $> svn ci -F svnmerge-commit-message.txt
+
+
+initialize svnmerge tracking on the trunk:
+
+trunk/ $> svnmerge init https://svn.apache.org/repos/asf/perl/modperl/branches/mybranch
+property 'svnmerge-integrated' set on '.'
+mybranch/ $> svn ci -F svnmerge-commit-message.txt
+
+
+##############################################
+### merging changes from branch to brahch ###
+##############################################
+
+Work from a clean checkout of the branch you want to merge *to*
+
+Check on the availability of changes to merge
+
+$> svnmerge avail -b -l
+
+------------------------------------------------------------------------
+r584362 | gozer | 2007-10-12 21:00:47 -0700 (Fri, 12 Oct 2007) | 1 line
+Changed paths:
+ A /perl/modperl/branches/mybranch (from /perl/modperl/trunk:584361)
+
+creating mybranch
+------------------------------------------------------------------------
+r584363 | gozer | 2007-10-12 21:05:32 -0700 (Fri, 12 Oct 2007) | 3 lines
+Changed paths:
+ M /perl/modperl/branches/mybranch
+
+Initialized merge tracking via "svnmerge" with revisions "1-584361" from
+https://svn.apache.org/repos/asf/perl/modperl/trunk
+
+Then merge the ones you want to merge
+
+$> svnmerge -r 584362-584363
+
+review the changes, fix conflicts, etc
+
+Check in the merged version
+
+$> svn ci -F svnmerge-commit-message.txt
+
diff --git a/2_0_13/CONTRIBUTING.md b/2_0_13/CONTRIBUTING.md
new file mode 100644
index 0000000..b507419
--- /dev/null
+++ b/2_0_13/CONTRIBUTING.md
@@ -0,0 +1,59 @@
+# How to Contribute
+
+Help with mod_perl is always welcome. You do not have to know any code
+to help out - we also need help testing, answering questions, improving
+documentation, etc.
+
+
+## Issues
+
+Bugs and problems can be reported at:
+
+https://rt.cpan.org/Dist/Display.html?Name=mod_perl
+
+which can be accessed from the "Issues" link in the left-hand menu on
+the metacpan.org page, https://metacpan.org/pod/mod_perl2 .
+
+(Note: You will need to log in to https://rt.cpan.org in order to get
+the "Report a new bug" button on the bug tracker page.)
+
+
+### Discussions
+
+There is a low-volume mailing list for mod_perl users and developers to
+share ideas, solve problems and discuss things related to mod_perl and
+the Apache::* modules.
+
+Send an email to <modperl@perl.apache.org>. Before doing so, you should
+subscribe by sending an email to <modperl-subscribe@perl.apache.org>.
+Send an email to <modperl-unsubscribe@perl.apache.org> to unsubscribe.
+
+There is also a low-volume mailing list for discussions about the
+development of the core mod_perl.
+
+Send an email to <dev@perl.apache.org>. Before doing so, you should
+subscribe by sending an email to <dev-subscribe@perl.apache.org>.
+Send an email to <dev-unsubscribe@perl.apache.org> to unsubscribe.
+
+
+## Testing
+
+You can help by testing mod_perl as widely as possible. Running the
+tests on a wide variety of platforms, Apache httpd versions, Perl
+versions and other factors is a great help in uncovering problems and
+improving mod_perl.
+
+
+## Code development
+
+Development happens in a Subversion repo. The canonical location is
+currently at:
+
+https://svn.apache.org/repos/asf/perl/
+
+The current mod_perl 2.0 development branch is at modperl/trunk under
+the above URL.
+
+Create your own copy of that branch by running:
+
+svn co https://svn.apache.org/repos/asf/perl/modperl/trunk/ mod_perl2
diff --git a/2_0_13/Changes b/2_0_13/Changes
new file mode 100644
index 0000000..19bfa2d
--- /dev/null
+++ b/2_0_13/Changes
@@ -0,0 +1,3007 @@
+=encoding utf8
+
+=head1 NAME
+
+Changes - Apache mod_perl changes logfile
+
+=head1 CHANGES
+
+all changes without author attribution are by Doug MacEachern
+
+Also refer to the Apache::Test changes log file, at Apache-Test/Changes
+
+=over 3
+
+=item 2.0.13 October 21, 2023
+
+Use get_server_banner() instead of deprecated get_server_version() in
+Apache2::Status. [Petr Písař <ppisar@redhat.com]
+
+Avoid generating APR precompiled headers. [Sam James <sam@gentoo.org>]
+
+Fix build for perl >= 5.37.1. [Jitka Plesnikova <jplesnik@redhat.com>]
+
+=item 2.0.12 January 30, 2022
+
+Add bug tracker information to README, and add CONTRIBUTING.md. [Steve Hay]
+
+Fix detection of APR's threading support on RHEL 8. [Petr Písař
+<ppisar@redhat.com>]
+
+Fix build for perl >= 5.33.7. [Leon Timmermans <fawaka@gmail.com>]
+
+Fix SIGSEGV crash due to wrong use of perl_parse(). [Charles Pigott
+<cpigott@rapitasystems.com>]
+
+Improve installation instructions for AIX. [Rainer Tammer
+<rainer.tammer@schulergroup.com>]
+
+=item 2.0.11 October 5, 2019
+
+Fix t/modules/apache_resource.t failures [Steve Hay]
+
+Fix [CVE-2011-2767] Arbitrary Perl code execution in the context of the user
+account via a user-owned .htaccess. Patch from bugs.debian.org #644169. [Jan
+Ingvoldstad <jani+debian-2011+@ifi.uio.no>]
+
+Fix potential test suite hangs due to pipelined response deadlocks. Patch
+from rt.cpan.org #82409. [Zefram <zefram@fysh.org>]
+
+Fix t/compat/request.t failures [Steve Hay]
+
+Fix use-after-free segfault in ap_server_config_defines seen on start-up on
+OpenBSD. [Found/fixed by Sam Vaughan/Joe Orton]
+
+Fix build with Perls earlier than 5.13.6. [Rainer Jung
+<rainer.jung@kippdata.de>]
+
+Fix filter/in_bbs_inject_header.t test failure with Apache 2.4.25+. [Stefan
+Fritsch <sf@sfritsch.de>]
+
+Fix apache/read.t test failure with Apache 2.4.25+. [Niko Tyni
+<ntyni@debian.org>]
+
+=item 2.0.10 October 27, 2016
+
+Declare MP_vtbl_env and MP_vtbl_envelem as 'extern' to fix linker errors on
+OSX/Darwin. [Michael Schout <mschout@gkg.net>]
+
+Automatically select the appropriate c89 option when modperl is being
+built with either gcc 5 or clang. [Klaus S. Madsen <ksm@jobindex.dk>]
+
+Fix non-threaded Perl 5.22.x build and tests. [Klaus S. Madsen
+<ksm@jobindex.dk>]
+
+Add support for Perl 5.22.x. [Niko Tyni <ntyni@iki.fi>, Steve Hay]
+
+=item 2.0.9 June 18, 2015
+
+Add note to README about MP_INLINE problem when building with GCC 5.
+[Niko Tyni <ntyni@debian.org>]
+
+Fix t/api/aplog.t for apr-1.5.2. [Steve Hay]
+
+Note that Perl 5.22.x is currently not supported. This is logged as
+CPAN RT#101962 and will hopefully be addressed in 2.0.10. [Steve Hay]
+
+Fix unthreaded build, which was broken in 2.0.9-rc2. [Steve Hay]
+
+Remove PerlInterpScope. This has not been working properly with threaded
+MPMs with httpd-2.4.x and the use-case of this directive was questionable.
+[Jan Kaluza]
+
+Allow running the test suite with httpd-2.4.x when mod_access_compat is not
+loaded. [Steve Hay]
+
+Add support for Apache httpd-2.4.x. [Torsten Foertsch, Jan Kaluza,
+Steve Hay, Gozer]
+
+Don't call modperl_threaded_mpm() et al. from XS code. Fixes Debian Bug
+#765174. [Niko Tyni <ntyni@debian.org>]
+
+Make sure modperl_interp_select uses r->server rather than the passed s
+parameter to find the interpreter pool to pull an interpreter from. This
+fixes an issue with vhosts with a separate interpreter pool and runtime
+dir-config merges that used to pull the interpreter from the wrong pool.
+[Torsten Foertsch]
+
+PerlInterpScope is now more advisory. Using $(c|r)->pnotes will bind
+the current interpreter to that object for it's lifetime.
+$(c|r)->pnotes_kill() can be used to prematurely drop pnotes and
+remove this binding. [Torsten Foertsch]
+
+Now correctly invokes PerlCleanupHandlers, even if they are the only
+handler type configured for that request [Torsten Foertsch]
+
+For threaded MPMs, change interpreter managment to a new, reference-counted
+allocation model. [Torsten Foertsch]
+
+Expose modperl_interp_pool_t via ModPerl::InterpPool, modperl_tipool_t
+via ModPerl::TiPool and modperl_tipool_config_t via ModPerl::TiPoolConfig
+[Torsten Foertsch]
+
+Expose modperl_interp_t via ModPerl::Interpreter [Torsten Foertsch]
+
+Fix t/compat/apache_file.t on Windows. Apache::File->tmpfile() wants TMPDIR
+or TEMP from the environment, or else defaults to /tmp. The latter is no
+good on Windows, so make sure the environment variables are passed through.
+(TEMP should be set to something suitable on Windows.) [Steve Hay]
+
+Fix t/api/err_headers_out.t with HTTP::Headers > 6.00. [Rolando
+<rolosworld@gmail.com>]
+
+Fix the build with VC++ and dmake (rather than nmake) on Windows. The
+Makefile generated by Apache2::Build uses shell commands for the manifest
+file, but neglected to tell dmake to use the shell. [Steve Hay]
+
+Don't write an 'rpm' target into the Makefile on Windows. It isn't relevant
+on Windows, and the (hard-coded, not MakeMaker-generated) recipe group has
+syntax which dmake doesn't understand. [Steve Hay]
+
+=item 2.0.8 April 17, 2013
+
+Perl 5.16.3's fix for a rehash-based DoS makes it more difficult to invoke
+the workaround for the old hash collision attack, which breaks mod_perl's
+t/perl/hash_attack.t. Patch from rt.cpan.org #83916 improves the fix
+previously applied as revision 1455340. [Zefram]
+
+On Perl 5.17.6 and above, hash seeding has changed, and HvREHASH has
+disappeared. Patch to update mod_perl accordingly from rt.cpan.org #83921.
+[Zefram]
+
+Restore build with Perl 5.8.1, 5.8.2 etc: take care to use
+$Config{useithreads} rather than $Config{usethreads}, and supply definitions
+of Newx and Newxz as necessary. [Steve Hay]
+
+On Perl 5.17.9, t/apache/read2.t fails because an "uninitialized value"
+warning is generated for the buffer being autovivified. This is because
+the sv_setpvn() that's meant to vivify the buffer doesn't perform set
+magic; the warning is generated by the immediately following SvPV_force().
+Patch to fix this from rt.cpan.org #83922. [Zefram]
+
+Fix t/perl/hash_attack.t to work with Perl 5.14.4, 5.16.3 etc, which
+contain a fix for CVE-2013-1667 (memory exhaustion with arbitrary hash
+keys). This resolves rt.perl.org #116863, from where the patch was taken.
+[Hugo van der Sanden]
+
+use APR::Finfo instead of Perl's stat() in ModPerl::RegistryCooker to
+generate HTTP code 404 even if the requested filename contains newlines
+[Torsten]
+
+Remove all uses of deprecated core perl symbols. [Steve Hay]
+
+Add branch release tag to 'make tag' target. [Phred]
+
+=item 2.0.7 June 5, 2012
+
+Fix breakage caused by removal of PL_uid et al from perl 5.16.0. Patch from
+rt.cpan.org #77129. [Zefram]
+
+=item 2.0.6 April 24, 2012
+
+Preserve 5.8 compatibility surrounding use of MUTABLE_CV [Adam Prime]
+
+Move code after declarations to keep MSVC++ compiler happy. [Steve Hay]
+
+Adopt modperl_pcw.c changes from httpd24 branch. [Torsten Foertsch]
+
+Pool cleanup functions must not longjmp. Catch these exceptions and turn
+them into warnings. [Torsten Foertsch]
+
+Fix a race condition in our tipool management.
+See http://www.gossamer-threads.com/lists/modperl/dev/104026
+Patch submitted by: SalusaSecondus <salusa@nationstates.net>
+Reviewed by: Torsten Foertsch
+
+Ensure that MP_APXS is set when building on Win32 with MP_AP_PREFIX,
+otherwise the bundled Reload and SizeLimit builds will fail to find a
+properly configured Test environment.
+[Steve Hay]
+
+Fix a few REFCNT bugs.
+Patch submitted by: Niko Tyni <ntyni@debian.org>
+Reviewed by: Torsten Foertsch
+
+Correct the initialization of the build config in ModPerl::MM. The global
+variable was only being set once on loading the module, which was before
+Apache2::BuildConfig.pm had been written, leading to cwd and MP_LIBNAME
+being unset when writing the Reload and SizeLimit makefiles.
+[Steve Hay]
+
+Discover apr-2-config from Apache 2.4 onwards. [Gozer]
+
+Apache 2.4 and onwards doesn't require linking the MPM module directly in
+the httpd binary anymore. APXS lost the MPM_NAME query, so we can't assume
+a given MPM anymore. Introduce a fake MPM 'dynamic' to represent this.
+[Torsten Foertsch, Gozer]
+
+Perl 5.14 brought a few changes in Perl_sv_dup() that made a threaded apache
+segfault while cloning interpreters.
+[Torsten Foertsch]
+
+PerlIOApache_flush() and mpxs_Apache2__RequestRec_rflush() now no longer throw
+exceptions when modperl_wbucket_flush() fails if the failure was just a reset
+connection or an aborted connection. The failure is simply logged to the error
+log instead. This should fix cases of httpd.exe crashing when users press the
+Stop button in their web browsers.
+[Steve Hay]
+
+Fixed a few issues that came up with LWP 6.00:
+- t/response/TestAPI/request_rec.pm assumes HTTP/1.0 but LWP 6 uses 1.1
+- t/api/err_headers_out.t fails due to a bug somewhere in LWP 6
+- t/filter/TestFilter/out_str_reverse.pm sends the wrong content-length header
+[Torsten Foertsch]
+
+Bugfix: Apache2::ServerUtil::get_server{description,banner,version} cannot
+be declared as perl constants or they won't reflect added version components
+if Apache2::ServerUtil is loaded before the PostConfig phase. Now, they
+are ordinary perl functions. [Torsten Foertsch]
+
+Check for the right ExtUtils::Embed version during build [Torsten Foertsch]
+
+Take a lesson from rt.cpan.org #66085 and pass LD_LIBRARY_PATH if mod_env
+is present. Should prevent test failures on some platforms.
+[Fred Moyer]
+
+
+=item 2.0.5 February 7, 2011
+
+The mod_perl PMC dedicates this release of mod_perl to Randy Kobes, who
+passed away in September 2010. Randy was a member of the mod_perl project
+management committee and a co-author of the mod_perl Developer's Cookbook.
+His work helped many Windows mod_perl users. His work with ppm files, and
+Win32 perl users will be sorely missed. He was kind, bright, and always
+willing to lend a hand on the mod_perl user's list.
+
+Prepare modperl for the upcoming perl 5.14 [Torsten Foertsch]
+
+Add lib/ModPerl/MethodLookup.pm to MANIFEST via lib/ModPerl/Manifest.pm
+RT #48103 reported by MARKLE@cpan.org
+[Fred Moyer]
+
+PerlIOApache_write() now throws an APR::Error object, rather than just a string
+error, if modperl_wbucket_write() fails.
+[Steve Hay]
+
+Authentication tests fail with LWP 5.815 and later
+[Doug Schrag]
+
+Concise test won't perform unless StatusTerse is set to ON
+[Doug Schrag]
+
+Look for a usable apxs in $ENV{PATH} if all other options fail, then prompt the user for one.
+[Phred]
+
+Work around bootstrap warnings when Apache2::BuildConfig has not been created yet.
+[Phred]
+
+Remove Apache::test compatibility (part of mod_perl 1.2.7), that code causes build issues and is 4 versions out of date.
+[Phred]
+
+Make sure perl is built either with multiplicity and ithreads or without
+both [Theory, Torsten]
+
+Support for "install_vendor" and "install_site" make targets [Torsten]
+
+Run tests on bundled pure perl Apache::* modules [Gozer, Phred]
+
+Implement a mini-preprocess language for map-files in xs/maps.
+[Torsten Foertsch]
+
+Implement APR::Socket::fileno [Torsten Foertsch]
+
+Export PROXYREQ_RESPONSE, a missing PROXYREQ_* constant [Gozer]
+
+Make sure standard file descriptors are preserved by the perl-script
+handler [Torsten Foertsch]
+
+Fix the filter init handler attribute check in
+modperl_filter_resolve_init_handler() [Torsten Foertsch]
+
+Make sure buffer is a valid SV in modperl_filter_read() [Torsten Foertsch]
+
+Move modperl_response_finish() out of modperl_response_handler_run in
+mod_perl.c [Torsten Foertsch]
+
+"MODPERL_INC= now correctly supported as an argument to Makefile.PL"
+[Torsten Foertsch]
+
+Fix an XSS issue in Apache2::Status reported by Richard J. Brain
+<richard@procheckup.com>. [Torsten Foertsch]
+
+Add NOTICE file to the distribution. [Joe Schaefer]
+
+Make sure Apache2::RequestIO::read doesn't clear the buffer on end of
+file and handle negative offsets and offsets that are larger than
+the current string length. [Torsten Foertsch]
+
+Fix a problem that could make APR::XSLoader and Apache2::XSLoader
+load the wrong shared library. [Torsten Foertsch]
+
+Fix compilation when using a non-threaded APR.
+[Gozer, Philip M. Gollucci]
+
+Make sure mod_perl's own ChildInitHandlers are run before user
+supplied ones. This fixes the incorrectly reported value of $$
+at ChildInit time [Gozer]
+
+=item 2.0.4 April 16, 2008
+
+Fix $r->location corruption under certain conditions
+[Gozer]
+
+Fix a crash when spawning Perl threads under Perl 5.10
+[Gozer]
+
+Fix erratic behaviour when filters were used with Perl 5.10
+[Gozer]
+
+Fix problems with redefinitions of perl_free as free and perl_malloc
+as malloc on Win32, as described at
+ http://marc.info/?l=apache-modperl&m=119896407510526&w=2
+[Tom Donovan]
+
+Fix a crash when running a sub-request from within a filter where
+mod_perl was not the content handler. [Gozer]
+
+Refactor tests to use keepalives instead of same_interp [Gozer, Phred]
+
+Apache2::Reload has been moved to an externally maintained
+CPAN distribution [Fred Moyer <fred@redhotpenguin.com>]
+
+PerlCleanupHandler are now registered with a subpool of $r->pool,
+instead of $r->pool itself, ensuring they run _before_ any other
+$r->pool cleanups [Torsten Foertsch]
+
+Fix a bug that would prevent pnotes from being cleaned up properly
+at the end of the request [Torsten Foertsch]
+
+On Win32, embed the manifest file, if present, in mod_perl.so,
+so as to work with VC 8 [Steve Hay, Randy Kobes]
+
+Expose apr_thread_rwlock_t with the APR::ThreadRWLock module
+[Torsten Foertsch]
+
+Don't waste an extra interpreter anymore under threaded MPMs when using a
+modperl handler [Torsten Foertsch]
+
+Fix a bug that could cause a crash when using $r->push_handlers() multiple
+times for a phase that has no configured handlers [Torsten Foertsch]
+
+Catch up with some httpd API changes
+ 2.2.4:
+ The full server version information is now included in the error log at
+startup as well as server status reports, irrespective of the setting
+of the ServerTokens directive. ap_get_server_version() is now
+deprecated, and is replaced by ap_get_server_banner() and
+ap_get_server_description(). [Jeff Trawick]
+
+ 2.3.0:
+ap_get_server_version() has been removed. Third-party modules must
+now use ap_get_server_banner() or ap_get_server_description().
+[Gozer]
+
+fixed Apache2::compat Apache2::ServerUtil::server_root() resolution
+issues [Joshua Hoblitt]
+
+*) SECURITY: CVE-2007-1349 (cve.mitre.org)
+fix unescaped variable interprolation in regular expression
+[Randal L. Schwartz <merlyn@stonehenge.com>, Fred Moyer <fred@redhotpenguin.com>]
+
+Make $r->the_request() writeable
+[Fred Moyer <fred@redhotpenguin.com>]
+
+fix ModPerl::RegistryCooker::read_script to handle all possible
+errors, previously there was a case where Apache2::Const::OK was
+returned on an error. [Eivind Eklund <eeklund@gmail.com>]
+
+a minor compilation warning resolved in modperl_handler_new_from_sv
+[Stas]
+
+a minor compilation warning resolved in modperl_gtop_size_string
+[Stas]
+
+Prevent direct use of _deprecated_ Apache2::ReadConfig in
+<Perl> sections with httpd Alias directives from
+incorrectly generating
+'The Alias directive in xxxxx at line y will probably never match'
+messages.
+[Philip M. Gollucci <pgollucci@p6m78g.com>]
+
+Prevent Apache2::PerSections::symdump() from returning invalid
+httpd.conf snippets like 'Alias undef'
+[Philip M. Gollucci <pgollucci@p6m78g.com>]
+
+Require B-Size 0.9 for Apache2::Status which fixes
+Can't call method "script_name" on an undefined value
+[Philip M. Gollucci <pgollucci@p6m78g.com>]
+
+-march=pentium4 or anything with an = in it in CCFLAGS or @ARGV
+that gets passed to xs/APR/APR/Makefile.PL broke the @ARGV
+parsing. I.E. FreeBSD port builds when users had CPUTYPE
+set in /etc/make.conf.
+[Philip M. Gollucci <pgollucci@p6m7g8.com>]
+
+Fixes to get bleed-ithread (5.9.5+) to comile again.
+[Philip M. Gollucci <pgollucci@p6m7g8.com>]
+
+=item 2.0.3 November 28, 2006
+
+Prevent things in %INC that are not stat() able
+from breaking Apache2::Status 'Loaded Modules'
+under fatal warnings.
+[Philip M. Gollucci <pgollucci@p6m7g8.com>]
+
+When using MP_AP_PREFIX on WIN32 make sure that its
+a valid directory.
+[Nikolay Ananiev <ananiev@thegdb.com>]
+
+Fix bug concerning 'error-notes' having no value on
+errordocument redirect.
+[Guy Albertelli II <guy@albertelli.com>]
+
+Multi-line $PerlConfig is now working [Gozer]
+
+PerlOptions None was previously incorrectly reported as invalid
+inside <VirtualHost> or <Directory> blocks.
+[Philip M. Gollucci]
+
+Require B::Size 0.07 and B::TerseSize 0.07 for Apache2::Status
+[Philip M. Gollucci]
+
+Apache2::Status was expecting B::TerseSize to return
+an op count for things that it didn't causing
+requests like http://localhost/perl-status/main?noh_b_package_size
+to cause 405s
+[Philip M. Gollucci]
+
+Updates for Win32 to allow building and testing on Apache/2.2:
+- use httpd.exe as the Apache binary name when installing apxs
+- use new apr library names (libapr-1.lib and libaprutil-1.lib)
+[Randy Kobes]
+
+Make sure that additional library paths are included in the build flags
+so that mod_perl will use the same versions of libraries that APR does.
+[Mike Smith <mike@mailchannels.com>]
+
+Added $r->connection->pnotes, identical to $r->pnotes, but
+for the entire lifetime of the connection
+[Geoffrey Young, Gozer]
+
+Fixed problems with add_config() and thread-safety: [Gozer]
+- $s->add_config is not allowed anymore after server startup
+- $r->add_config can only affect configuration for the current
+ request, just like .htaccess files do
+
+Make sure that LIBS and other MakeMaker command line flags are not
+ignored by the top level Makefile.PL and xs/APR/APR/Makefile.PL [Stas]
+
+Corrected a typo that would cause the corruption of $), the
+effective group id as Perl sees it [Gozer]
+
+Added support for httpd-2.2's new override_opts in Apache2::Access.
+Calls to add_config() now accept an override_opts value as the 4th
+argument. [Torsten Foertsch <torsten.foertsch@gmx.net>, Gozer]
+
+Fix 'PerlSwitches +inherit' that got broken somewhere along
+the way to 2.0. You can also use 'PerlOptions +InheritSwitches'
+for the same result. [Gozer]
+
+Add perl API corresponding to User and Group directives in httpd.conf:
+Apache2::ServerUtil->user_id and Apache2::ServerUtil->group_id
+[Stas]
+
+Apache2::Reload now first unloads all modified modules before
+trying to reload them. This way, inter-module dependencies
+are more likely to be correctly satisfied when reloaded
+[Javier Uruen Val <juruen@warp.es>, Gozer]
+
+$r->add_config() can now take an optionnal 3rd argument that
+specifies what pseudo <Location $path> the configuration is
+evaluated into [Torsten Foertsch <torsten.foertsch@gmx.net>]
+
+remove -DAP_HAVE_DESIGNATED_INITIALIZER and -DAP_DEBUG from
+MP_MAINTAINER mode to avoid collisions [Joe Orton]
+
+Back out r280262 which was causing Apache2::Reload to misbehave.
+[JT Smith <jt@plainblack.com>]
+
+Perl_do_open/close fixes to make mod_perl 2.0 compile with
+blead-perl@25889+ (5.9.3+) [Stas]
+
+Added Apache2::PerlSections->server, returning the server
+into which the <Perl> section is defined [Gozer]
+
+Require B::Size and B::TerseSize v0.06 for Apache2::Status
+options StatusTerse and StatusTerseSize which has now been
+updated to support the new mod_perl2 api post RC5.
+[Philip M. Gollucci]
+
+When using Apache2::PerlSections->dump, the configuration
+would print out in the correct order, but when the configuration was
+passed off to Apache the ordering was lost.
+[Scott Wessels <swessels@usgn.net>]
+
+=item 2.0.2 - October 20, 2005
+
+add :proxy import tag to Apache2::Const which exposes new
+constants PROXYREQ_NONE, PROXYREQ_PROXY, and PROXYREQ_REVERSE
+[Geoffrey Young]
+
+$0 Fixes : [Gozer]
+- Setting $0 works on Linux again
+- HP-UX and *BSDes show the correct process name instead of '-e'
+
+Fix a critical but trivial bug that would cause MP_MAINTAINER=1
+or MP_TRACE=1 builds to fail if not building against a threaded APR.
+Functions such as apr_os_thread_current() would not be linked in,
+but were expected to be.
+[Philip M. Gollucci]
+
+Add the output of ldd(unix/cygwin) and otool -L (darwin)
+for httpd to the mp2bug report script.
+[Philip M. Gollucci]
+
+Prevent tools such as Apache2::Status's Loaded Modules screen
+from displaying erroneous information about mod_perl.pm being loaded.
+[Stas, Philip M. Gollucci]
+
+Correctly set the version of ModPerl::MethodLookup, previously,
+it was not set because of the way it was Generating via ModPerl::WrapXS.
+[Philip M. Gollucci]
+
+Improve the detection of whether or not we are in an mp2 build tree.
+This allows usage of ExtUtils::MakeMaker options such as PREFIX to
+not break the probe of mp2 build trees.
+[Stas, Philip M. Gollucci]
+
+Add support for the newer Smaps (/proc/self/statm) on Linux
+systems that support it (i.e. linux-2.6.13-rc4-mm1)
+to accurately count the amount of shared memory.
+[Torsten Foertsch <torsten.foertsch gmx.net>]
+
+On cygwin some dlls might happen to be with identical base addresses
+and if you try to load both of them you'll get an error and you'll
+have to use the rebase utility to fix them. this fix should prevent
+this. [Nikolay Ananiev <ananiev@thegdb.com>]
+
+Fix an undefined warning in DSO builds when not using MP_APXS.
+[Nikolay Ananiev <ananiev@thegdb.com>]
+
+When running Makefile.PL with the MP_MAINTAINER=1 option
+add -Wdeclaration-after-statement if we are using gcc
+version 3.3.2 or higher and its not already part of the ccopts.
+[Philip M. Gollucci, Gozer]
+
+Several fixes to Apache2::Status
+[Philip M. Gollucci]
+
+When using Apache2::Reload and ReloadDebug is set to 'On',
+sort the output alphabetically [Philip M. Gollucci]
+
+croak in case a filter returns DECLINED after calling $f->read (as it
+is not supposed to happen) [Stas]
+
+another round of cygwin fixes [Nikolay Ananiev <ananiev@thegdb.com>]
+
+Multiple fixes to make mod_perl 2.0 work with blead-perl (5.9.3+)
+[Stas]
+
+t/modules/reload.t would fail if run more than 3 times, breaking
+smokes [Gozer]
+
+filter flushing now doesn't croak on connection reset
+(ECONNRESET/ECONNABORTED), but just logs the event on the 'info'
+level. [Stas]
+
+RPM Friendly builds : [Gozer]
+- make dist tarballs can now be built directly into RPMs with rpmbuild
+- Added a new target 'make rpm' to directly build rpms from a checkout
+
+
+
+=item 2.0.1 - June 17, 2005
+
+B::Terse has problems with XS code, so adjust Apache::Status to eval
+{} the code doing Syntax Tree Dump: syntax and execution order options
+[Stas]
+
+Fix a broken regexp in Apache2::Build::dir() on win32 that would
+incorrectly attempt to fully-qualify paths like c:/some/path
+[Nikolay Ananiev <ananiev@thegdb.com>]
+
+Fix the "No library found" warnings when building on win32 without
+apxs and MP_AP_PREFIX [Nikolay Ananiev <ananiev@thegdb.com>]
+
+The pure-perl ModPerl::Util::unload_package implementation was
+accidently deleting sub-stashes [Gozer]
+
+If running Makefile.PL unnatended (STDIN isn't a terminal or
+MP_PROMPT_DEFAULT=1), break out of potentially infinite prompt
+loops [Gozer]
+
+fix ModPerl::TestReport used by t/REPORT and mp2bug to use
+ExtUtils::MakeMaker's MM->parse_version to get the interesting
+packages version number, w/o trying to load them (which may fail if
+the environment is not right) [Stas]
+
+fix a bug in ModPerl::RegistryCooker: now stripping __(END|DATA)__
+only at the beginning of the line [Stas]
+
+APR::Base64 : [Torsten Foertsch <torsten.foertsch@gmx.net>]
+- fix encode_len() to return the length without accounting for the
+terminating '\0' as the C API does.
+- fix encode() to create the string of the correct length (previously
+was creating one too many)
+
+in mod_perl callbacks merge error-notes entries rather than store just
+the newest error [Mark <mark@immermail.com>]
+
+Expose Apache2::Const::EXEC_ON_READ (added to the :override group)
+[Stas]
+
+Fix a bug in custom directive implementation, where the code called
+from modperl_module_config_merge() was setting the global context
+after selecting the new interpreter which was leading to a segfault in
+any handler called thereafter, whose context was different
+beforehand. [Stas]
+
+
+
+=item 2.0.0 - May 20, 2005
+
+fix global anon_cnt double-initialization bug that was causing
+startup segfaults on OSX. [Gozer]
+
+fix the ap_install target in the top-level Makefile (used for static
+build) [Stas]
+
+Reintroduce a pure-Perl version of ModPerl::Util::unload_package()
+The problematic XS version is now called unload_package_xs() and
+not used by default [Gozer]
+
+More APR::Status wrappers: [Stas, Randy Kobes]
+- is_EOF
+- is_ECONNABORTED
+- is_ECONNRESET
+- is_TIMEUP
+
+make sure that the build picks up the include directories based on the
+apxs queries and only search the httpd source if $self->{MP_AP_PREFIX}
+was set. Earlier it was always picking the headers from the httpd
+source if it was available, which was resulting in the wrong headers
+if the installed httpd was different than the source that was found
+[Stas]
+
+introduce ModPerl::RegistryPrefork and ModPerl::PerlRunPrefork, which
+behave the same as ModPerl::Registry and ModPerl::PerlRun,
+respectively, but chdir to the script's directory like mod_cgi
+does. These two new handlers will refuse to load under threaded MPMs
+where chdir can't be used as it will affect all running threads [Stas]
+
+ModPerl::RegistryCooker::chdir_file_normal() now chdirs to the current
+script's directory or the specified directory as an argument, as it
+was planned in first place. Therefore switch ModPerl::Registry and
+ModPerl::PerlRun to us NOP for this method call. If chdir_file is
+mapped to chdir_file_normal(), then run() and
+convert_script_to_compiled_handler() now call chdir to the script's
+directory and at before returning go back to the server root. [Stas]
+
+prevent undef warnings in catfile() calls in Apache2::Build when
+called from the ModPerl-Registry tree [Stas]
+
+fix modperl_brigade_dump to use apr_file_printf() instead of
+fprintf(), which doesn't work everywhere [Stas]
+
+Fix a warning triggered by `ln` on Cygwin, when running perl
+Makefile.PL for a second time without previously running make
+clean. [Nikolay Ananiev <ananiev@thegdb.com>]
+
+When compiling a static mod_perl and
+MP_AP_CONFIGURE="--with-apr=/some/path" argument is given, Apache will
+use the apr-config at the given path, but mod_perl was using the
+default at "srclib/apr/.libs". Fix that [Nikolay Ananiev <ananiev@thegdb.com>]
+
+Show MP_APU_CONFIG as an argument to Makefile.PL in the Usage
+menu. [Nikolay Ananiev <ananiev@thegdb.com>]
+
+Makefile.PL: fix the pre-rename mp2 install diagnostics code, to use
+the mp version of 1.999xx and not 1.999_xx, as the latter is
+unsuitable for numerical comparison, also fix the name of the reported
+conflicting directory [Stas].
+
+add APR::Status::is_(EACCES|ENOENT), and use in ModPerl::RegistryCooker
+to return, as appropriate, Apache2::Const::(FORBIDDEN|NOT_FOUND),
+based on $@. Also remove a check in modperl_slurp_filename
+of src/modules/perl/modperl_util.c to enable $@ to be set when
+opening or reading a file fails. This fixes a bug on Win32, revealed
+in 404.t and redirect.t of the ModPerl-Registry tests, as reported
+by Steve Hay and Markus Wichitill [Stas, Randy Kobes]
+
+link Apache2::* and ModPerl::* to mod_perl.a and DynaLoader.a, but
+-lmod_perl and -lDynaLoader don't work, and we can't supply the full
+paths, because MakeMaker doesn't allow this. I workaround this by
+making a symlink to mod_perl.a (called libmod_perl.a) and copy
+DynaLoader.a to libDynaLoader.a (I don't create a symlink, because,
+when running make clean, the real DynaLoader.a may get deleted). The
+APR::* extensions are not affected, because in both cases we link them
+against aprext. Also other small fixes are added. [Nikolay Ananiev
+<ananiev@thegdb.com>]
+
+
+
+
+=item 1.999_23 - May 3, 2005
+
+fix Apache2::Build::dynamic_link_MSWin32 to generate a new line after
+dynamic_link code in Makefile [Nikolay Ananiev <ananiev@thegdb.com>]
+
+fix a warning in Apache2::Build::build_config() when building
+with MP_STATIC_EXTS=1 [Nikolay Ananiev <ananiev@thegdb.com>]
+
+improving DSO support on cygwin. The problem with cygwin is that it
+behaves like windows (it's a posix layer over windows after
+all). That's why we need to supply all symbols during linking time
+just like on win32, by adding -lapr-0 -laprutil-0 and -lhttpd. On
+windows, Apache supplies all the three libraries and it's easy to
+link, but on cygwin apache doesn't play nice and doesn't supply
+libhttpd. This change adds libapr and libaprutil. [Nikolay Ananiev
+<ananiev@thegdb.com>]
+
+improve the diagnostics when detecting mp2 < 1.999022, tell the user
+which files and/or dirs need to be removed [Stas]
+
+restore the DESTDIR support partially nuked by the apache2 rename
+branch [Torsten Förtsch <torsten.foertsch gmx.net>]
+
+add APR::Status to provide functions corresponding to the
+APR_STATUS_IS_* macros of apr_errno.h, especially those composites
+like APR_STATUS_IS_EAGAIN(s) which are satisfied by more than one
+specific error condition. Presently only APR_STATUS_IS_EAGAIN is
+provided [Randy Kobes]
+
+fix the generation of the manpages for .pm files from sub-projects
+like ModPerl-Registry (previously was creating manpage files like
+.::ModPerl::PerlRun.3) [Stas]
+
+fix the pod2man'ification part of 'make install' (using POD2MAN_EXE
+instead of POD2MAN Makefile macro) [Stas]
+
+
+=item 1.999_22 - April 14, 2005
+
+ ******************** IMPORTANT ********************
+ this version of mod_perl is completely incompatible
+ with prior versions of mod_perl, both 1.XX and
+ 1.99_XX. Please read the below changes carefully.
+ ***************************************************
+
+remove MP_INST_APACHE2 installation option and Apache2.pm - all
+mod_perl related files will now be installed so they are visible
+via standard @INC. also, refuse to install over mod_perl 2 versions
+less than 1.999_22. [Geoffrey Young]
+
+s/Apache::/Apache2::/g and s/mod_perl/mod_perl2/g in all module
+APIs. so, Apache::RequestRec is now Apache2::RequestRec,
+Apache::compat is now Apache2::compat, and so on. [joes]
+
+move all Apache:: constants to Apache2::Const and all APR:: constants
+to APR::Const. for example, Apache:OK is now Apache2::Const::OK and
+APR::SUCCESS is now APR::Const::SUCCESS. [Geoffrey Young]
+
+add $ENV{MOD_PERL_API_VERSION} as something that clearly distinguishes
+which mod_perl version is being used at request time. [Geoffrey Young]
+
+rename Apache->request() to Apache2::RequestUtil->request(), and
+Apache->server() to Apache2::ServerUtil->server()
+[Geoffrey Young]
+
+fix Apache2::Status which was bailing out on trying to load modules
+with dev versions like 2.121_02 [Stas]
+
+When parsing Makefile.PL MP_* options, handle correctly the MP_FOO=0
+entries [Philip M. Gollucci <pgollucci@p6m7g8.com>]
+
+init the anonsub hash for base perl and each vhost +Parent (previously
+was init'ed only for the base perl) [Stas]
+
+fix a bug when a non-threaded perl is used and anonymous sub is pushed
+at the server startup (the CV wasn't surviving) [Stas]
+
+Make sure that CPAN shell doesn't triple over usage of
+$ExtUtils::MakeMaker::VERSION [Randy Kobes]
+
+Apache2::RequestRec->new now sets $r->request_time [Stas]
+
+remove CGI.pm and Apache::Request dependencies from Apache2::Status
+since they weren't used at all [Geoffrey Young]
+
+Fixes for Apache2::Reload's touchfile feature (return Apache2::Const::OK
+instead of 1) [Chris Warren <chwarren@cisco.com>]
+
+cygwin fixes: [Nikolay Ananiev <ananiev@thegdb.com>]
+- doesn't like XS wrapper starting with 'static'
+- need to compile everything with -DCYGWIN
+
+ModPerl::RegistryCooker API change: s/rewrite_shebang/shebang_to_perl/
+the new API now returns the string to prepend before the rest of the
+script, instead of rewriting the content, which is both faster and
+doesn't mislead the perl debugger [Dominique Quatravaux
+<dom@idealx.com>]
+
+Starting from ExtUtils::MakeMaker 6.26 went back to pm_to_blib target
+from pm_to_blib.ts introduced in 6.22, so needed to fix the glue_pod
+target, so install will work correctly [Stas]
+
+Syntax errors in <Perl> sections were not correctly caught and
+reported. [Gozer]
+
+when building mp2 EU::MM looks into Apache-Test/MANIFEST and complains
+about the missing Apache-Test/META.yml (which is indeed not included
+in the modperl package due to the PAUSE problems of dealing with more
+than one META.yml. Solution: Exclude Apache-Test/MANIFEST from
+mod_perl distribution package. [Stas]
+
+ModPerl::Registry no longer checks for -x bit (we don't executed
+scripts anyway), and thus works on acl-based filesystems. Also
+replaced the -r check with a proper error handling when the file is
+read in. [Damon Buckwalter <buckwad@gmail.com>]
+
+Apache2::RequestUtil::slurp_filename now throws an APR::Error exception
+object (before it was just croaking). [Stas]
+
+fix APR::Error's overload of '==' (it was always returning true
+before), and add the corresponding '!=' [Stas]
+
+if $r->document_root was modified, restore it at the end of request
+[joes]
+
+Apache2::ServerRec method which set the non-integer fields in the
+server_rec, now copy the value from the perl scalar, so if it changes
+or goes out of scope the C struct is not affected. Using internal perl
+variables to preserve the value, since using the server pool to
+allocate the memory will mean a memory leak [Stas]
+
+add the escape_url entry in the ModPerl::MethodLookup knowledgebase
+[Stas]
+
+Apache2::SubProcess::spawn_proc_prog now can be called in a void
+context, in which case all the communication std pipes will be closed
+[Stas]
+
+fix a bug in $r->document_root, which previously weren't copying the
+new string away [Stas]
+
+introduce a new build option MP_AP_DESTDIR to aid package builders
+direct the Apache-specific files to the right place. [Cory Omand
+<Cory.Omand@Sun.COM>]
+
+Fix bug in modperl_package_clear_stash() segfaulting when
+encountering declared but not yet defined subroutines.
+[Steve Hay <steve.hay@uk.radan.com>, Gozer]
+
+win32 needs PERL_SYS_INIT3/PERL_SYS_TERM calls [Steve Hay
+<steve.hay@uk.radan.com>]
+
+Fix broken MP_STATIC_EXTS=1 build. [Gozer]
+
+Perl -Duse64bit fix. Pointers can't just be generically
+casted from/to IVs. Use PTR2IV/INT2PTR instead. [Gozer]
+
+Perl -Duse64bit fix. apr_size_t pointers can't just be generically
+casted from/to UVs. Use PTR2UV/INT2PTR instead. [Gozer]
+
+fix a bug in Apache2::Build::dir: If the right directory isn't found in
+the for loop $dir still contains a > value, so the ||= has no
+effect. [Nick Wellnhofer <wellnhofer@aevum.de>]
+
+
+
+=item 1.999_21 - January 22, 2005
+
+PerlPostConfigRequire was trying to detect missing files early on,
+but without searching thru @INC, causing false negatives. Better off
+skipping that check and leave it to modperl_require_file() to report
+problems with finding the file. [Patrick LeBoutillier
+<patrick.leboutillier@gmail.com>, Gozer]
+
+add a perl bug workaround: with USE_ITHREADS perl leaks pthread_key_t
+on every reload of libperl.{a,so} (it's allocated on the very first
+perl_alloc() and never freed). This becomes a problem on apache
+restart: if the OS limit is 1024, 1024 restarts later things will
+start crashing [Gisle Aas <gisle@ActiveState.com>, Stas]
+
+on Irix mod_perl.so needs to see the libperl.so symbols, which
+requires the -exports option immediately before -lperl. [Gordon Lack
+<gml4410@ggr.co.uk>]
+
+pool arguments to startup and connection callbacks must be blessed
+into APR::Pool and not Apache::Pool class [joes]
+
+Make PerlSetEnv, PerlPassEnv and %ENV in PerlRequre, PerlModule,
+PerlConfigRequire and PerlPostConfigRequire affect each other, so a
+change in one of these is immediately seen in the others. [Pratik
+<pratiknaik gmail.com>, Stas]
+
+
+
+=item 1.999_20 - January 5, 2005
+
+the autogenerated modules (and some implemented in xs/ modules) are
+now getting the same version number as $mod_perl::VERSION (the
+exception are APR modules which get 0.009_000 for now). [Stas]
+
+until we figure out how to tell PAUSE index about versions of the
+autogenerated modules, create a fake module which lists all the
+autogenerated modules and their versions and include that in the
+distro. [Stas]
+
+moving to the triplet version notation, which requires us to bump 1.99
+=> 1.999 so 1.999020 (mp2) > 1.29 (mp1). [Stas]
+Now we are gong to have:
+ $mod_perl::VERSION : "1.099020"
+ int $mod_perl::VERSION : 1.09902
+ $mod_perl::VERSION_TRIPLET: 1.99.20
+
+<Perl> and PerlPostConfigRequires were leaking some memory at
+startup. Use parms->temp_pool instead of parms->pool for temporary
+memory allocations. [Gozer]
+
+deal with a situation where an object is used to construct another
+object, but it's then auto-DESTROYed by perl rendering the object that
+used it corrupted. the solution is to make the newly created objects
+refer to the underlying object via magic attachment. only objects
+using objects that have DESTROY are effected. This concerns some of
+the methods accepting the custom APR::Pool object (not native pools
+like $r->pool). [Stas]
+Adjusted:
+- APR::Brigade: new
+- APR::Finfo: stat
+- APR::IpSubnet: new
+- APR::Table: copy, overlay, make
+- APR::ThreadMutex: new
+- APR::URI: parse
+- Apache::RequestUtil: new
+- APR::Pool: new
+- APR::BucketAlloc: new
+
+APR::Bucket::alloc_create moved to APR::BucketAlloc::new
+APR::Bucket::alloc_destroy moved to APR::BucketAlloc::destroy [Stas]
+
+prefork handlers optimisation: don't dup the handler struct unless
+this is a threaded-mpm [Stas]
+
+speed up the 'perl Makefile.PL' stage [Randy Kobes]:
+ - reduce the number of calls to build_config() of
+ Apache::Build within ModPerl::BuildMM
+ - cache the results of the calls to apxs_cflags, apxs_extra_cflags,
+ and apxs_extra_cppflags in Apache::Build
+ - in apxs of Apache::Build, return a cached result only when defined
+
+move ModPerl::Util::exit() into mod_perl.so, since it needs to work,
+even if ModPerl::Util wasn't loaded [Stas]
+
+
+
+=item 1.99_19 - December 23, 2004
+
+$r->hostname is now writable [Gozer]
+
+Static build with a Perl without ithreads and a non-threaded MPM
+would segfault on startup. Caused by a bug in perl's perl_shutdown()
+code. Fixed in Perl 5.8.2, so it's now a build requirement [Gozer]
+
+replace the added in 1.99_17 code on resetting/restoring PL_tainted,
+with explicit reset before and after each each callback. This solves a
+complicated tainting issues caused when perl exception object is
+thrown. rgs suggested that it should be safe, similar to perl's own
+pp_nextstate which says: /* Each statement is presumed innocent */
+[Stas]
+
+New configuration directives: [Gozer]
+ - PerlConfigRequire
+ Just like PerlRequire, but _always_ triggers an immediate
+ interpreter startup
+ - PerlPostConfigRequire
+ A delayed form of PerlRequire, that waits until the post_config
+ phase before require'ing files
+
+fix a warning in Apache::Status [John Williams <williams tni.com>]
+
+Ignore Apache-Test/META.yml in distribution tarballs until PAUSE
+is capable of handling multiple META.yml files in one distro [Gozer]
+
+modperl_exports.c now wraps all exported functions in a #ifndef
+function_name wrapper to help in weeding out functions that only make
+sense for certain Perl configurations (perlio, threads) (which also
+fixes static build against perlio-disabled perls, like 5.6.x) [Gozer]
+
+for make test, skip configuring fastcgi if it's found in the global
+httpd.conf, as it causes crashes in the test suite [Stas]
+
+fix Makefile.PL arguments parser to support more than one MP_foo
+option on the same line (including .makepl_args.mod_perl2 file) [Stas]
+
+fix compilation issues in ModPerl::Util::current_perl_id (on some
+builds newSVpvf can't be resolved but Perl_newSVpvf works just
+fine). [Stas, Markus Wichitill <mawic@gmx.de>]
+
+fix APR::Error::str to return a lexical variable, rather than a
+string. This function is called by SvTRUE in modperl_errsv() via
+overload and on win32 (and randomly on linux) causes crashes via:
+"Attempt to free temp prematurely" warning, where this 'temp' is the
+string returned by this function. Making it a lexical variable before
+returning it, resolves the problem. [Steve Hay]
+
+fix META.yaml s/private/no_index/ (to hide the bundled Apache-Test
+from PAUSE indexer) [Randy Kobes]
+
+
+
+=item 1.99_18 - December 12, 2004
+
+Fix x86_64 warnings in modperl_restart_count_*, due to casting between
+integers and pointer types [Joe Orton]
+
+open_logs and post_config handlers require the Apache::OK return code
+or the server aborts, so we need to log an error in case the handler
+didn't fail but returned something different from Apache::OK [Stas]
+
+new function ModPerl::Util::current_perl_id() which returns something
+like (.e.g 0x92ac760) (aTHX) under threaded mpm and 0 under
+non-threaded perl (0x0). Useful for debugging modperl under threaded
+perls. [Stas]
+
+make sure that modperl's internal post_config callback, which amongst
+other things, cloning perl interpreters is running as
+modperl_hook_post_config_last APR_HOOK_REALLY_LAST, which ensures that
+user's post_config callbacks are run before the cloning. now the code
+from config phase's startup.pl can be safely moved to the post_config
+phase's equivalent. [Stas]
+
+Further sync with libapr constants changes: [Stas]
+- the constants
+ APR::(READ|WRITE|CREATE|APPEND|TRUNCATE|BINARY|EXCL|BUFFERED|DELONCLOSE)
+ now have a prefix APR::FOPEN_ and moved group s/filemode/fopen/
+- constants from the fileprot group moved to the fprot group and the
+ prefix has changed: from APR::FILEPROT_ to APR::FPROT_
+- this also fixes the import of APR_EXCL as an error constant
+
+$r->print() and tied print() now return 0E0 (zero but true) when the
+call was successful but for zero bytes. [Geoffrey Young]
+
+a new function Apache::ServerUtil::server_shutdown_cleanup_register to
+register cleanups to be run at server shutdown. [Stas]
+
+$bb->cleanup is no more segfaulting (was segfaulting due to a broken
+prototype in APR, and consequently invalid XS glue code) [Randy Kobes,
+Stas]
+
+make sure that ABSPERLRUN and ABSPERLRUN are defined in
+src/modules/perl/Makefile (needed by win32 build) [Stas]
+
+For static builds, mod_perl header files were being installed
+into apache's source tree instead of where apache installed it's
+own headers [Gozer]
+
+modperl_threads_started() wasn't working under static worker build,
+due to MP_threads_started static variable not being reset on
+restart. Now resetting it. [Stas]
+
+@INC shrinking efforts: [Stas]
+1) when adding $ServerRoot don't add the trailing / (as it ends up
+twice when added by A-T w/o trailing /)
+2) add $ServerRoot/lib/perl only if it actually exists
+
+For static builds, we now run 'make clean' in httpd's source
+tree before running ./configure if the source tree has been
+configured before [Gozer]
+
+Apache::SizeLimit ported [Perrin Harkins <perrin elem.com>]
+
+create a new subpool modperl_server_user_pool (from
+modperl_server_pool), which is used internally by
+Apache::ServerUtil::server_restart_register. This ensures that
+user-registered cleanups are run *before* perl's internals cleanups
+are run. (previously there was a problem with non-threaded perls which
+were segfaulting on user cleanups, since perl was already gone by that
+time). [Stas]
+
+Starting from ExtUtils::MakeMaker 6.22 it no longer generates
+pm_to_blib target, but pm_to_blib.ts, so needed to fix the glue_pod
+target, so install will work correctly [Stas]
+
+Apache::RequestUtil : $r->child_terminate() implemented for
+non-threaded MPMs. [Gozer]
+
+new API Apache::ServerUtil::restart_count() which can be used to tell
+whether the server is starting/restarting/gracefully
+restarting/etc. Based on this feature implement
+$Apache::Server::Starting and $Apache::Server::ReStarting in
+Apache::compat [Stas]
+
+Apache::Resource ported to mp2 [Stas]
+
+If none of MP_APXS, MP_AP_PREFIX and MP_USE_STATIC were specified when
+configuring Makefile.PL, we now prompt for APXS path first and only if
+that fails ask for MP_AP_PREFIX. This is a requirement to get 'make
+test' find httpd. [Stas]
+
+Dynamically prompt and add MP_INST_APACHE2=1 when installing on
+systems with mod_perl 1 preinstalled. [Stas]
+
+fix the logging call in RegistryCooker [Lars Eggert <lars.eggert
+netlab.nec.de>]
+
+fix $r->filename in Apache::compat to update the finfo struct (which
+is how it worked in mp1) [Stas]
+
+enclose all occurences of eval_* with ENTER;SAVETMPS;
+... FREETMPS;LEAVE; previously things just happened to work, due to
+external scopes which was not very reliable and some change could
+introduce obsure bugs. [Stas]
+
+in case a native apache response filter is configured outside the
+<Location> block with PerlSet*Filter directive, make sure that
+mod_perl doesn't try to add it as connection filter (previously was
+logging an error like: [error] a content filter was added without a
+request: includes) [Stas]
+
+replace the slow implementation of anon handlers using B::Deparse,
+with per-interpreter cache of compiled CODE refs (sort of emulating
+named subroutines for anonymous handlers) [Stas].
+
+avoid segfaults when a bogus $r object is used [Stas]
+
+Remove magicness of PerlLoadModule and implement Apache::Module::add()
+for modules that implement their own configuration directives [Gozer]
+
+Apache::Connection::remote_ip is now settable (needed to set the
+remote_ip record based on proxy's X-Forwarded-For header) [Stas]
+
+Fix Modperl::Util::unload_package() [Gozer]
+ - Mistakenly skipping small entries of size 2 and less
+ - Leave entries from other packages alone
+
+$filter->remove now works with native (non-modperl) filters + test
+[Torsten Förtsch <torsten.foertsch gmx.net>]
+
+
+
+=item 1.99_17 - October 22, 2004
+
+Implement Apache->unescape_url_info in Apache::compat and drop it
+from the official API for CGI::Util::unescape() as a suggested
+replacement [Gozer]
+
+fix xs_generate to croak on duplicate entries in xs/maps files
+[Christian Krause <chkr plauener.de>]
+
+Workaround a possible bug in Perl_load_module() [Gozer]
+
+Fix a problem building with non-GNU make (can't make target dynamic
+in xs/APR/aprext) [Gozer]
+
+escape HTML in dumped variables by Apache::Status [Markus Wichitill
+<mawic@gmx.de>]
+
+$r->document_root can now be changed when safe to do so [Gozer]
+
+APR::Bucket->new now requires an APR::BucketAlloc as its first argument.
+New subs added: APR::Bucket::setaside, APR::Bucket::alloc_create,
+APR::Bucket::alloc_destroy, APR::Brigade::bucket_alloc. [joes]
+
+reimplement APR::Pool life-scope handling, (the previous
+implementation had problems) [joes]
+
+make sure that Apache::Filter::read, APR::Socket::recv,
+Apache::RequestIO::read, APR::Brigade::flatten, and APR::Bucket::read
+all return tainted data under -T [Stas]
+
+tag the custom pools created by mod_perl for easier pools debug [Joe
+Orton]
+
+fix a bug in non-ithreaded-perl implementation where the cached
+compiled CODE refs of httpd.conf-inlined one-liner handlers like:
+PerlFixupHandler 'sub { use Apache::Const qw(DECLINED); DECLINED }'
+didn't have the reference count right. [Stas]
+
+per-server PerlSetEnv and PerlPassEnv values are properly added
+to %ENV when only a per-directory handler is configured.
+[Geoffrey Young]
+
+resolve several 'Use of uninitialized value in...' warnings in
+Apache::Status [Stas].
+
+make install and static build now correctly installs mod_perl as
+well as the statically built apache [Gozer]
+
+if some code changes the current interpreter's tainted state to on,
+the return value from the handler callback will be tainted, and we
+fail to deal with that. So revert to coercing any return value, but
+undef (a special case for exit()). to IV, so that tainted values are
+handled correctly as well. [Stas]
+
+make sure that each handler callback starts with a pristine
+tainted-ness state, so that previous callback calls won't affect the
+consequent ones. Without this change any handler triggering eval or
+another function call, that checks TAINT_PROPER, will crash mod_perl
+with: "Insecure dependency in eval while running setgid. Callback
+called exit." farewell message [Stas]
+
+make sure that 'make distclean' cleans all the autogenerated files
+[Stas]
+
+$r->log_reason has been ported and moved out of Apache::compat
+[Gozer]
+
+APR::OS::thread_current renamed APR::OS::current_thread_id and
+now returns the actual thread_id instead of an object that
+needed to be dereferenced to get at the thread_id [Gozer]
+
+change a bunch of the APR:: constants to have a better prefix
+(APR::FILETYPE_* and APR::FILEPROT_). libapr will be changed soon too
+[Stas]
+
+Generate modperl_exports.c for static builds to prevent the
+linker from stripping needed but unused symbols [Gozer]
+
+Add .libs/ as part of the library search path when building
+against httpd's source tree [Gozer]
+
+In the static build, run make in httpd's srclib/ early to have
+generated files present at mod_perl configure time [Gozer]
+
+When searching for ap(r|u)-config in httpd's source tree, search
+into srclib/apr-util as well as srclib/apr [Gozer]
+
+Remove APR::Finfo::pool as it has no use to us [Stas]
+
+get PerlSetVar and PerlAddVar multi-level merges to (finally) work
+properly. [Rici Lake <rici ricilake.net>]
+
+MP_AP_BUILD configure option removed. Now implicit when MP_USE_STATIC
+is specified [Gozer]
+
+Apache::Module $mod->version() and $mod->minor_version() renamed
+to $mod->ap_api_major_version() and $mod->ap_api_minor_version
+for clarity [Gozer]
+
+Apache::Log changes: [Stas]
+ - moved to compat: Apache::warn, Apache->warn, Apache::Server->warn,
+ Apache::Server::warn
+ - re-enabled $r->warn
+ - removed support for Apache::ServerRec->warn
+ (Apache::ServerRec::warn is still there)
+
+Apache::Directive conftree() changed from class method to
+regular subroutine [Gozer]
+
+Apache::Module top_module() and get_config() as class methods
+added to Apache::compat for backwards compatibility [Gozer]
+
+Apache::Module top_module() and get_config() changed from class
+methods to regular subroutines [Gozer]
+
+Added Apache::CmdParms::add_config() to work around a memory
+leak discovered with <Perl> sections in .htaccess files [Gozer]
+
+Added ModPerl::Util::unload_package() to remove a loaded package
+as thoroughly as possible by clearing it's stash. [Gozer]
+
+fix Apache->request($r) to be set-able even w/: PerlOptions
+-GlobalRequest [Stas]
+
+Add Apache::Reload->unregister_module() to explicitely remove a
+module from Apache::Reload's monitoring list [Gozer]
+
+introduce a custom modperl error message for failing filter handlers
+(previously 'unknown error' coming from rc=500 was logged) [Stas]
+
+Fix Apache::Log methods/functions to log into the vhost's error_log
+file (if there is one). ( $s->log->*, $s->log_error, $s->log_serror,
+Apache::ServerRec::warn, etc.). Apache::ServerRec can now export its
+warn function to override CORE::warn [Stas]
+
+Fix $s->log->*, $s->log_error and $s->log_serror to again log into the
+vhost's error_log file (if there is one). [Stas]
+
+$s->log->warn and other $s->log->foo are now logging to the right
+vhost server and not the global one. modperl_sv2server_rec was
+broken. [Stas]
+
+Fix a glue_pod make target bug, when .pm file doesn't exist,
+e.g. ThreadMutex.pm is not created on unless
+$apr_config->{HAS_THREADS} [Stas]
+
+Introduce APR::Socket::poll to poll a non-blocking socket [Ken Simpson
+<ksimpson@larch.mailchannels.com>]
+
+Fix the error message when the minimal required httpd version is not
+satisfied [Pratik <pratiknaik@gmail.com>]
+
+Fix interactive prompting at perl Makefile.PL, when no APXS or
+MP_AP_PREFIX were provided. now asking for an alternative location if
+the suggested choices weren't selected. [Stas]
+
+Added APR::URI->rpath method. Returns the path of an uri minus
+path_info, if any. [Gozer]
+
+moved Apache::current_callback() to ModPerl::Util::current_callback
+where it belongs [Gozer]
+
+modperl_perl_module_loaded() fixed to use %INC to determine if a module
+is loaded instead of checking for the existence of a stash [Gozer]
+
+fix the modperl build, where httpd has been built against separate
+installations of apr-util and apr, where apr-util has been installed
+with a different includedir to apr. [Joe Orton]
+
+$Apache::Server::SaveConfig is now $Apache::PerlSections::Save
+[Geoffrey Young]
+
+
+
+=item 1.99_16 - Aug 22, 2004
+
+Fix a compilation problem breaking 1.99_15 (sv_copypv was added in
+perl 5.7.3) [Jason Woodward <woodwardj@jaos.org>]
+
+Added $r->content_languages in Apache::RequestRec [Gozer]
+
+APR::Bucket: add delete() and destroy() methods [Stas]
+
+
+
+=item 1.99_15 - Aug 20, 2004
+
+replace the memory allocation for modperl filter handlers to use a
+temporary subpool of the ap_filter_t object. previously using perl's
+safemalloc had problems on win32 (randomly my_perl == NULL) [Stas]
+
+Disable Apache::HookRun::run_create_request -- it's already run
+internally by Apache::RequestRec->new [Stas]
+
+Update Apache::RequestRec->new() to initialize members of request_rec
+which were added some time ago (without it we were getting segfaults
+in the new pseudo_http test. [Stas]
+
+Apache::CmdParms->limited member replaced by is_method_limited()
+method [Gozer]
+
+Apache::Module changes [Gozer]
+- readwrite => readonly:
+ cmds, next, name, module_index, minor_version, version
+- removed: remove_module
+
+ensure that a sub-dir Apache-Test exists in the source distro (this is
+a requirement, since the test suite relies on the particular
+Apache-Test version distributed with the mod_perl source) [Stas]
+
+combine handler resolving failure error with the actual error, so
+there is only one logged entry [Stas]
+
+pod manpages are now glued to all .pm files for which .pod exists at
+'make install' phase [Stas]
+
+Apache::RequestIO::sendfile() now indicates which file it has failed
+to open on failure. [Stas]
+
+fix Apache::SubRequest's methods: lookup_file, lookup_uri,
+lookup_method_uri to default the last argument to
+r->proto_output_filters (no request filters for the subrequest) and
+not r->output_filters->next as it was before (one filter was getting
+skipped and the rest of the filters were applied *twice*). [Stas]
+
+Apache::CmdParms changes [Gozer]
+- readwrite => readonly:
+ override, limited, directive, pool, temp_pool, server, path,
+ cmd, context, err_directive
+
+- removed: limited_xmethods, xlimited, config_file, err_directive
+
+Fix a bug in APR::Bucket->new when a passed argument was of type
+PADTMP [Stas]
+
+Apache::Connection changes [Stas, "Fred Moyer" <fred /about/
+taperfriendlymusic.org>]
+- readwrite => readonly:
+
+ pool, base_server, local_addr, remote_addr, remote_ip, remote_host,
+ aborted, local_ip, local_host, id, conn_config, sbh, bucket_alloc
+
+- removed: logname
+
+Move check_cmd_context from Apache::Command to Apache::CmdParms.
+[Gozer]
+
+Add :context group of constants for check_cmd_context().
+NOT_IN_VIRTUALHOST, NOT_IN_LIMIT, NOT_IN_DIRECTORY, NOT_IN_LOCATION,
+NOT_IN_FILES, NOT_IN_DIR_LOC_FILE & GLOBAL_ONLY [Gozer]
+
+Removed Apache::Command method soak_end_container [Gozer]
+
+Removed Apache::Module methods (dynamic_load_handle and
+find_module_name) [Gozer]
+
+All Apache::Command methods are now read-only [Gozer]
+
+Removed Apache::Command methods (func and cmd_data) [Gozer]
+
+Removed Apache::Directive methods (data & walk_config) [Gozer]
+
+All Apache::Directive methods are now read-only [Gozer]
+
+Filters should not reset $@ if it was already set before
+invocation [Gozer]
+
+Apache::compat server_root_relative now correctly handles absolute
+paths like ap_server_root_relative does [Gozer]
+
+Fix a bug in <Perl> sections with multiple aliases in a
+virtualhost container. [Gozer]
+
+PerlModule, PerlRequire, Perl and <Perl> is now supported in
+.htaccess. They will run for each request. [Gozer]
+
+removed support for httpd 2.0.46. httpd 2.0.47 is now the minimum
+supported version. [Geoffrey Young]
+
+Static builds for httpd >= 2.0.51 available. With the new MP_AP_BUILD
+option, configure and compile an httpd with mod_perl statically linked
+in [Gozer]
+
+Apache::RequestRec methods changes [Stas]
+- readwrite => readonly:
+
+ connection, canonical_filename, header_only, main, next, prev,
+ pool, per_dir_config, request_config, proto_num, protocol,
+ request_time, server, the_request, unparsed_uri
+
+- removed:
+
+ remaining - this method is not needed if the deprecated
+ $r->client_block methods aren't used, (use $r->read
+ $r->instead)
+ canonical_filename - it's a private member
+
+The func Apache::SubProcess::spawn_proc_prog is now a method:
+$r->spawn_proc_prog [Stas]
+
+Apache::Process methods (pool, pconf and short_name) are now read-only
+[Stas]
+
+($r|$c|$s)->server_root_relative were removed. Now only an explicit
+and somewhat deprecated function API remains:
+Apache::ServerUtil::server_root_relative($pool, $path); it's too easy
+to cause memory leak with this method, and it's inefficient as it
+duplicates the return value, to avoid potential segfaults if the pool
+it was allocated from gets destroyed and the value is attempted to be
+used. Instead of this method use the equivalent:
+File::Spec->catfile(Apache::ServerUtil::server_root, $fname); [Stas]
+
+$r->psignature now lives in the package it belongs to:
+Apache::RequestUtil (previously lived in Apache::ServerUtil). [Stas]
+
+A few functions moved namespace from Apache:: to Apache::ServerUtil::
+(to make it easier to find the container of the function): [Stas]
+ - exists_config_define
+ - server_root
+ - get_server_built
+ - get_server_version
+
+fix an old outstanding bug in the APR::Table's TIE interface with
+each()/values() over tables with multi-values keys. Now the produced
+order is correct and consistent with keys(). Though, values() works
+correctly only with perl 5.8.x and higher. [Joe Schaefer]
+
+require Perl 5.6.1, 5.6.0 isn't supported for a long time, but we
+weren't aborting at the Makefile.PL stage [Stas]
+
+Apache::RequestUtil::method_register($s->process->pconf, 'FOO'); is
+now $s->method_register('FOO').
+Apache::RequestUtil::add_version_component($s->process->pconf, 'BAR/0.1');
+is now $s->add_version_component('BAR/0.1'). [Stas]
+
+Remove $Apache::Server::StrictPerlSections. Now, all <Perl>
+sections errors are fatal by default and cause server startup to
+abort on error. [Gozer]
+
+Fix ($r|$filter|$bucket)->read() functions to run the set magic logic,
+to handle cases when a passed buffer to fill is not a regular
+scalar. [Stas]
+
+Apache::ServerRec accessors changes: [Stas]
+- readonly accessors:
+
+ process, next, is_virtual, module_config, lookup_defaults and
+ addrs
+
+- readwrite accessors with the exception of threaded mpms, where the
+ accessors are writable only before the child_init phase (i.e. before
+ threads are spawned):
+
+ server_admin, server_hostname, port, error_fname, error_log,
+ loglevel, timeout, keep_alive_timeout, keep_alive_max, keep_alive,
+ names, wild_names, limit_req_line, limit_req_fieldsize,
+ limit_req_fields, and path
+
+supports a new type of struct accessor, which is just like read/write
+one, but doesn't allow write access starting at the ChildInit phase
+under threaded mpm (to avoid thread-safely issues) [Stas]
+
+In order to be consistent with Apache::RequestRec, Apache::Server is
+now Apache::ServerRec and all methods/functions from Apache::Server
+now live in Apache::ServerRec. [Stas]
+
+Use a context-specific Perl_load_module() instead of load_module(), to
+avoid the problem with 'load_module' symbol resolution on certain
+platforms, where for some reason it doesn't get resolved at compile
+time to Perl_load_module_nocontext [Stas]
+
+Make it possible to disable mod_perl for the base server, but enable
+it for the virtual hosts [Stas]
+
+Removed the deprecated path argument to $r->add_config() [Gozer]
+
+Created a META.yml for CPAN and friends, including Apache-Test as
+a private resource to keep CPAN from installing mod_perl when a
+user just wants Apache::Test [Gozer]
+
+Moving HTTP specific functions get_status_line, method_register from
+Apache:: to Apache::RequestUtil:: to match their container [Stas]
+
+Adjust the list of mod_perl header files installed into the Apache2
+include/ directory, made necessary from the renaming and refactoring
+arising from the decoupling of APR and APR::* from mod_perl.so.
+Also include modperl_apr_perlio.h under xs/APR/PerlIO/ in
+the list of such files installed [Stas, Randy Kobes]
+
+$r->read()/READ now throw exceptions [Stas]
+
+$r->rflush now returns nothing (was always returning APR::SUCCESS
+before) [Stas]
+
+bug reports generating code: [Stas]
+- add (apr|apu)-config linking info
+- show the full path to the config file used to get the data for the
+ report
+
+The APR and APR::* family of modules can now be used without having
+to load mod_perl.so. On *nix, this is done by compiling the needed
+functions from the appropriate sources used to build mod_perl.so
+into APR.so, and then arranging for APR::* to 'use APR ()'. On Win32,
+a static library of needed functions is built, and APR/APR::*
+then link into this library [Stas, Joe Schaefer, Randy Kobes]
+
+APR::RequestIO::sendfile() now flushes any buffered output before
+sending the file contents out. If the return status is not checked and
+an error happens it'll throw an exception. Fix offset handling. [Stas]
+
+Registry: remove the misleading prefix "$$: $class:" in the logged
+error message, since not only registry errors will get logged if $@ is
+set [Stas]
+
+change t/REPORT to suggest to post bug reports to the modperl users
+list, to be consistent with the documentation [Stas]
+
+amd64 fixes [Joe Schaefer <joe+gmane@sunstarsys.com>]
+ - use IV insteaf of int where a pointer is used
+ - mpxs_APR__Bucket_new needs to use apr_size_t/off_set_t types
+
+APR::Socket::recv() now returns the length of the read data [Stas]
+
+APR::Bucket's read() returns "" instead of undef when there is no data
+to read. [Stas]
+
+fix a bug in Registry handlers, where the same error was logged twice
+and potentially a wrong error code returned [Stas]
+
+Apache::RequestIO: print(), printf(), puts(), write(), rflush() throw
+an exception on failure [Stas]
+
+Apache::SubRequest: run() throw an exception on failure [Stas]
+
+Apache::Filter: [Stas]
+ - remove unneeded methods: remove_input_filter() and
+ remove_output_filter(), fputs()
+ - frec() accessor is made read-only
+ - fflush(), get_brigade() and pass_brigade() now throw exceptions if
+ called in the void context
+ - read, print() and puts() throw an exception on failure
+
+Apache::FilterRec: [Stas]
+ - remove the next() accessor since it's not used by Apache at the
+ moment
+ - name() is made read-only
+
+APR::URI: [Stas]
+ - removed accessors
+ o is_initialized() (internal apr_uri flag)
+ o dns_looked_up() and dns_resolved() (they are not
+ used by apache/apr)
+ - all remaining accessors now accept undef value, which unsets the
+ field
+
+Extended WrapXS code to support a new type of accessor: char * which
+accepts undef to set the C pointer to NULL and as such unset the
+member of the struct. [Stas]
+
+Exception error messages now include the error id along with the error
+message (as they did in first place). [Stas]
+
+$r->finfo now accepts APR::Finfo object as an optional
+argument. [Stas]
+
+APR::Finfo [Stas]
+ - change stat() to return finfo
+ - make all field accessors readonly
+
+ARP::password_validate is now ARP::Util::password_validate [Stas]
+
+APR::IpSubnet::new() now throws APR::Error exception (not returning
+rc) [Stas]
+
+rename package APR::NetLib -> APR::IpSubnet to match the class name
+[Stas]
+
+APR::BucketType: [Stas]
+ - name is readonly
+
+APR::Brigade [Stas]
+ - destroy() now throws APR::Error exception (not returning rc)
+ - rename empty => is_empty
+ - added the method cleanup()
+ - flatten() now returns the number of bytes read (and passed the
+ buffer by the argument) and throws APR::Error exception
+
+APR::Bucket: [Stas]
+ - read() now returns the length of the read data and throws
+ APR::Error exception (not returning rc). The returned scalar is
+ now TAINTED.
+ - type->name now has a module APR::BucketType
+ - type(), length(), start(), data() are now all readonly
+ - new() fix a bug in offset handling
+
+
+
+=item 1.99_14 - May 21, 2004
+
+APR::SockAddr::port() accessor is now read-only [Stas]
+
+APR::Pool now has destroy() and clear() available [Stas]
+
+now logging the errors happening in pool cleanup callbacks [Stas]
+
+use the new Apache-Test attribute -minclient in the test suites. Now
+along with the default maxclients = minclients+1, we no longer should
+get 'server reached MaxClients setting' errors. [Stas]
+
+new API for APR::Socket recv() and send() + updated tests [Stas]
+
+add infrastructure for new ModPerl::Const constants and the first
+constant ModPerl::EXIT. [Stas]
+
+re-implement ModPerl::Util::exit to use exception objects, so it's
+possible to detect exit called in eval context and call it again
+outside the eval context. [Stas]
+
+add the perl interface for the new exception handling code (mod_perl,
+apache and apr methods will now throw exceptions with $@ being an
+object). New class APR::Error was added, to handle the exception
+objects with overload methods. Also added confess and croak
+equivalents of Carp's methods, since at the moment the Carp's ones
+don't work as is. The following perl and C methods have been renamed:
+ modperl_apr_strerror => modperl_error_strerror
+ APR::strerror => APR::Error::strerr
+[Stas]
+
+set the 'error-notes' table to the error message on
+HTTP_INTERNAL_SERVER_ERROR [Stas]
+
+fix the apxs build function to not handle empty lookups as errors
+[Randy Kobes, Steve Hay]
+
+fix type casting problems in the io functions [Stas]
+
+add support for libgtop 2.5.0+ (maintenance mode) [Stas]
+
+APR::Socket::timeout_set now croaks on failure [Stas]
+
+significantly speedup the startup of threaded mpm test suite, by
+configuring only the minimal number of perl interpreters to start
+[Stas]
+
+make APR::Socket::opt_(set|get) working (and change the previous
+behavior) [Stas]
+
+make sure that our protocol module tests that interact with the socket
+use a blocking read [Joe Orton]
+
+Use a better approach to figure out whether we need to strip perl's
+LargeFilesSource flag, by checking whether libapr was compiled with
+-D_FILE_OFFSET_BITS=64 or not. Checking for APR_HAS_LARGE_FILES is
+useless since it doesn't tell whether 32 vs 64 bits off_t and similar
+types are used [Joe Orton]
+
+'SetHandler perl-script' no longer grabs any newly encountered END
+blocks, and removes them from PL_endav, but only if they are
+explicitly registered via ModPerl::Global::special_list_register(END
+=> $package_name) (this is a new function). It's now possible to have
+a complete control of when END blocks are run from the user space, not
+only in the registry handlers [Stas]
+
+END blocks encountered by child processes and not hijacked by
+ModPerl::Global::special_list_register() are now executed at the
+server shutdown (previously they weren't executed at all). [Stas]
+
+Added test to ensure <Perl> sections can have things like %Location
+tied [Gozer]
+
+Fix the installation on Win32 so that an appropriate Apache2
+subdirectory under the Perl tree is used when MP_INST_APACHE2 is
+specified [Randy Kobes]
+
+Fix a redefined warning in Apache::Status [Stas]
+
+Fix Apache::Status, to lookup the Apache::Request version without
+loading it. Only if a suitable (2.x) version is found -- load and use
+it. Previously loading the 1.x version was affecting Apache::compat.
+[Stas]
+
+Fix a bug in special blocks handling (like END), which until now was
+dropping on the floor all blocks but the last one (mainly affecting
+registry handlers). [Stas]
+
+The filter streaming API print() function, now correctly handles a
+binary data [Stas]
+
+Fix Registry handlers, not to lose the execution errors, when they
+include END blocks [Stas]
+
+
+
+=item 1.99_13 - March 8, 2004
+
+respect $ENV{APACHE_TEST_STARTUP_TIMEOUT} settings if any [Stas]
+
+Added tests for issuing subrequests from filters [Geoffrey Young]
+
+Updated to the new Apache License Version 2.0 [Gozer]
+
+Drop the support for making GATEWAY_INTERFACE special. It's not needed
+as $ENV{MOD_PERL}, available in both mod_perl generations, should be
+used to test whether the code is running under mod_perl. [Stas]
+
+Handle correctly the situation when response HTTP headers are printed
+from the handler and the response body starts with \000, which is the
+case with some images like .ico. [Stas]
+
+Apache::PerlSections->dump() and store(filename) [Gozer]
+
+expose $c->keepalive related constants and $c->keepalives counter
+[Stas]
+
+Perl handlers are now guaranteed to run before core C handlers for
+all request phases. [Geoffrey Young]
+
+Fix the STDIN/OUT overriding process to handle gracefully cases, when
+either or both are closed/bogus (the problem was only with useperlio
+enabled perl) [Stas]
+
+copy apr_table_compress logic from later httpd versions in case mod_perl
+is built against 2.0.46, as mod_perl now requires it internally. users
+should be aware that 2.0.47 may become the oldest supported httpd version
+in the near future. [Geoffrey Young]
+
+Fix the corruption of the httpd process argv[0], caused by $0
+manipulating [Stas]
+
+ModPerl::MethodLookup::lookup_method now handles sub-classed objects
+[Stas]
+
+standard %ENV population with CGI variables and contents of the
+subprocess_env table (such as SetEnv and PassEnv) has been delayed
+until the last possible moment before content-generation runs.
+PerlSetEnv and PerlPassEnv are each an exception to this and are
+placed in both %ENV and the subprocess_env table immediately,
+regardless of the current [+-]SetupEnv setting.
+[Geoffrey Young]
+
+fix PerlAddVar configuration merging [Geoffrey Young]
+
+Anonymous subs are now supported in push_handlers, set_handlers,
+add_input_filter, etc. A fast cached cv is used with non-ithreaded
+perl. A slower deparse/eval approach (via B::Deparse) is used with
+ithreads enabled perls. Further optimizations are planned for the
+latter case. [Stas]
+
+ht_time w/o the pool is now available only via override/restore compat
+API. format_time, has been renamed back to ht_time, and the default
+values for fmt, time and gmt are now supported. [Stas]
+
+it's now possible to push new handlers into the same phase that is
+running at the moment [Stas].
+
+when $r->handler($new_handler) is called from a response phase, it now
+checks that the response handler type is not switched (e.g. from
+'modperl' to 'perl-script') from the currently used one [Stas]
+
+Since Apache::SubProcess is now part of the mp2 API, add
+$r->cleanup_for_exec as a noop in Apache::compat. That function is no
+longer needed in Apache2. [Stas]
+
+When 'perl Makefile.PL PREFIX=/foo/bar' is used and mod_perl 1 is
+found, but at different prefix no longer require
+MP_INST_APACHE2=1. [Stas]
+
+modperl_mgv_resolve now croaks when a module scheduled for autoloading
+fails to load. AutoLoaded modules shouldn't silently fail. [Stas]
+
+Perl(Input|Output)FilterHandler handlers are now always AutoLoaded, as
+if '+' prefix was used. This must be performed to get the access to
+filter attributes long before the filter itself is executed. [Stas]
+
+APR/Pool.xs has been reimplemented. The problem with the previous
+implementation is that a dead perl pool object could hijack a newly
+created pool, which didn't belong to that object, but which happened
+to be allocated at the same memory location. The problem is that
+apr_pool_user_data_set/get has no mechanism to check whether the pool
+has changed since it was last assigned to (it does but only in the
+debug mode). It really needs some signature mechanism which can be
+verified that the pool is still the same pool. Since apr_pool doesn't
+have this feature, the reference counting has been reimplemented using
+a plain sv reference. Several new (mainly hijacking) tests which badly
+fail with the previous impelementation have been added. [Stas]
+
+fix calling $r->subprocess_env() in a void context so that it only
+populates %ENV if also called with no arguments. also, make sure it
+can be called more than once and still populate %ENV.
+[Geoffrey Young]
+
+add APR::Brigade::pool() to allow access to the pool associated with
+the brigade [Geoffrey Young]
+
+make 't/TEST -startup_timeout secs' working (previously user's value
+was ignored) [Stas]
+
+ModPerl::Registry and friends now support non-parsed headers scripts,
+whose filename =~ /^nph-/, identically to mod_cgi. + test [Stas]
+
+implement APR::Brigade::length() and APR::Brigade::flatten() (the
+latter implements a wrapper for apr_brigade_flatten, but also includes
+an emulation of apr_brigade_pflatten) as [Geoffrey Young]
+
+($r|$s)->add_config() now die if failed (previously returned the
+error) [Stas]
+
+fix context problems in <perl> sections and
+PerlModule/PerlLoadModule/PerlRequre under threaded mpms w/
+PerlOptions +Parent/+Clone in Vhosts + TestVhost::config test. [Stas]
+
+Implemented Apache::get_server_version and Apache::get_server_built
+as constant subroutines [Geoffrey Young]
+
+Moved some functions out of the Apache:: namespace:
+ Apache::unescape_url() is now Apache::URI::unescape_url()
+ Apache::log_pid() is now Apache::Log::log_pid()
+ Apache::LOG_MARK() is now Apache::Log::LOG_MARK()
+[Geoffrey Young]
+
+if MP_AP_PREFIX is used apxs and apr-config from the apache build tree
+won't work, so it can't co-exist with MP_APXS and MP_APR_CONFIG build
+options - ensure that this doesn't happen. [Stas]
+
+server_root_relative() now requires either a valid pool or an $r, $s,
+or $c object as a first argument. also, the returned result is a
+copy, protecting against cases where the pool would go out of scope
+before the result. [Geoffrey Young]
+
+Check the success of sysopen in tmpfile() in compat [Geoffrey Young]
+
+make sure DynaLoader is loaded before XSLoader, not only with perl
+5.6.1, but always because of the issues with <Perl> sections are
+loaded from +Parent vhost [Stas]
+
+added ($r|$s)->is_perl_option_enabled($option_name), to test for
+PerlOptions + tests [Stas]
+
+On Solaris add a workaround for xs/APR/APR/Makefile.PL to build
+APR.so, correctly linked against apr and apr-util libs, by addding the
+missing -R paths corresponding to -L flags. EU::MM was adding them via
+LD_RUN_PATH instead of using -R, but since perl's lddflags may have -R
+it overrides LD_RUN_PATH. So explicitly add anything that may go into
+LD_RUN_PATH via -R. Also make sure that -R coming from Apache will
+appear first. [Brad Lanam <bll@gentoo.com>]
+
+'make dist' now generates and picks Apache-Test/META.yml which was
+always reported missing, as it was included in Apache-Test/MANIFEST
+[Stas]
+
+fix the $r->read function to return undef on failure similar to the
+core perl function and make $! available for those who test for read()
+failures. [Stas]
+
+Make sure that pnotes are destroyed after PerlCleanup handlers are
+finished and not before + test. [Stas]
+
+
+
+=item 1.99_12 - December 22, 2003
+
+Restore a proper behavior of all Registry handlers, but PerlRun, not
+to reset %INC to forget any .pl files required during the script's
+execution. [Stas]
+
+<Perl> are now evaluating code into one distinct namespace per
+container, similar to ModPerl::Registry scripts. [Philippe M. Chiasson]
+
+Fix ModPerl::MM::WriteMakefile to use the MODPERL_CCOPTS entry from
+Apache::BuildConfig, as it contains some flags added by mod_perl,
+which aren't in perl_ccopts and ap_ccopts. [Stas]
+
+Add the implementation of Apache::Connection::local_addr and
+Apache::Connection::remote_addr to the Apache::compat overridable
+functions. [Stas]
+
+Apache::compat's implementation of APR::URI::unparse,
+Apache::RequestRec::finfo and Apache::RequestRec::notes is now
+overridable and not enabled by default. [Stas]
+
+Apache::compat no longer enables functions which collide with mp2 API
+by default. It provides two new functions: override_mp2_api and
+restore_mp2_api to override and restore the original mp2 API. [Stas]
+
+For Win32, add a .bat extension to candidates for the apxs and
+apr-config utilities used in Apache::Build, so that the -x file
+test can potentially succeed [Randy Kobes]
+
+Plug a memory leak with 'perl-script' not cleaning up the temp vars
+created during the override of STDIN/STDOUT to use the :Apache IO
+layer [Stas]
+
+libgtop config (needed for enabling MOD_PERL_TRACE=m) is now searched
+using the gnome packaging tools if available (pkg-config for gnome-2.x
+and gnome-config for gnome-1.x) [Stas]
+
+Prevent a problem where an autovivified package (stash) prevents from
+modperl_mgv to load the file with that package (until now it was
+checking whether the stash existed already and skipped the loading if
+that was the case). Now checking %INC and attempting to load the
+module. Reporting the failure only if the module has failed to load
+and the stash is not defined (so that it's possible to autovivify
+packages without loading them from an external file). [Stas]
+
+MaxClients is now overridable from the t/TEST -maxclients command line
+option (it was hardcoded before). [Stas]
+
+Postpone the allocation of the wbucket in filters till the moment it's
+needed (if at all). Since non-streaming filters aren't going to use
+that buffer, it's a waste to allocate/free it. [Stas]
+
+Extend the autogenerated bug report to include information about
+installed modules of special interest (which may aid in understanding
+the bug report), such as CGI.pm, Apache::Request, LWP, etc. [Stas]
+
+As the test suite keeps on growing, it takes longer time to
+startup. Change the main test suite timeout to 180 secs for threaded
+mpms and 120 secs for non-threaded ones. [Stas]
+
+use plain malloc/free to allocate filter structs, since they could be
+invoked hundreds of times during a single request, causing huge memory
+demands if the memory is allocated from the pool, which gets destroyed
+only at the end of a request. [Stas]
+
+Fix a compilation error in APX.xs when MP_HAVE_APR_LIBS is not defined
+[Fred Moyer <fred@taperfriendlymusic.org>]
+
+fix a memory leak when $filter->ctx is used [Stas]
+
+fix buglet on Win32 (and potentially other non-Unix platforms)
+where not all files were being installed under a relative Apache2
+subdirectory when MP_INST_APACHE2 was specified [Randy Kobes].
+
+deprecated APR::SockAddr::port_get()/APR::SockAddr::port_set()
+replaced with direct access to the port record via
+APR::SockAddr::port(). [Geoffrey Young, Stas]
+
+deprecated APR::URI::default_port_for_scheme() replaced with
+APR::URI::port_of_scheme() [Geoffrey Young]
+
+deprecated APR::SockAddr::ip_set() and APR::NO_TIMEOUT removed.
+[Geoffrey Young]
+
+Apache::MPM->is_threaded() replaces Apache::MPM_IS_THREADED
+[Geoffrey Young]
+
+fix "PerlSetVar Foo 0" so that $r->dir_config('Foo') returns 0, not undef
+[Geoffrey Young]
+
+add Apache::MPM class, along with show() and query() class methods
+[Geoffrey Young]
+
+add :mpmq import tag to Apache::Const [Geoffrey Young]
+
+Fix ModPerl::Registry handlers family to modify $0 only for the
+duration of the handler, by localizing it [Stas]
+
+Fix :Apache perlio's STDOUT to be reentrant + modules/include_subreq
+test [Stas]
+
+fix slurp_filename to always open the file and not try to guess
+whether filename has been already opened, as there is no reliable way
+to accomplish that [Stas]
+
+Apache->can_stack_handlers is now in Apache::compat (mp2 always can
+stack handlers) [Stas]
+
+add access to $r->finfo() and related APR::Finfo methods,
+such as $r->finfo->size(), $r->finfo->mtime(), and
+$r->finfo->stat() [Geoffrey Young]
+
+add :filetype import tag to APR::Const [Geoffrey Young]
+
+<Perl> sections now properly set $0 to the name of the configuration
+file they are in. [Philippe M. Chiasson]
+
+Apache::Status: provide a workaround for Config::myconfig() which
+fails under threads with (5.8.0 < perl < 5.8.3) [Elizabeth Mattijsen
+<liz@dijkmat.nl>]
+
+Fix Apache::Status::handler to return 'Apache::OK' [Juanma Barranquero
+<lektu@terra.es>]
+
+<Perl> sections now properly set filename and line number information,
+making error messages report the correct location. [Philippe M. Chiasson]
+
+
+
+=item 1.99_11 - November 10, 2003
+
+add a build/win32_fetch_apxs script (called within the top-level
+Makefile.PL) to offer to fetch and install a Win32 development
+version of apxs and (apr|apu)-config [Randy Kobes]
+
+rewrite $r->read() and perlio read functions to use the same function,
+which completely satisfies the read request if possible, on the way
+getting rid of get_client_block and its supporting functions which
+have problems and will most likely will be removed from the httpd-API
+in the future. Directly manipulate bucket brigades instead. [Stas]
+
+Since Apache2.pm pops /foo/Apache2 dirs to the top of @INC, it now
+also takes care of keeping lib and blib dirs before the system dirs,
+so that previously installed libraries won't get loaded instead of the
+currently uninstalled libraries that are under test. [Stas]
+
+When 'make test' fails we now print the info on what to do next [Stas]
+
+At the end of 'make install' we now print the info how to proceed with
+mod_perl and what to do in the case of post-install problems
+[Geoffrey Young]
+
+Adjust the source to properly work with 5.8.2's new algorithm of
+dynamic re-hashing of hashes on hash collision attack. [Nicholas Clark
+<nick@ccl4.org>, Stas]. Add a test that mounts such an attack so we
+can verify that we can survive this rehashing. [Scott A Crosby
+<scrosby@cs.rice.edu>, Nicholas Clark <nick@ccl4.org>, Tels
+<perl_dummy@bloodgate.com>, Mark Jason Dominus <mjd@plover.com>, Stas]
+
+Standardize the Apache::PerlSections package name to it's plural form for
+clarity and so that the pod gets glued in it's proper place.
+[Philippe M. Chiasson <gozer@cpan.org>]
+
+return value from Perl callbacks are now passed directly to Apache
+without additional post-call manipulations (such as assuming HTTP_OK
+should really be OK). [Geoffrey Young]
+
+perl 5.8.1 w/ ithreads has a bug where it reports the wrong parent pid
+(as if the process was never forked), provide a local workaround (+ new
+test). [Rafael Garcia-Suarez <rgarciasuarez@free.fr>]
+
+overridden STD* streams now can be further overridden and will be
+properly restored, which allows functions like $r->internal_redirect
+work (+add tests) [Stas]
+
+implement perlio's getarg hook, which now allows duping STD* streams
+overloaded by modperl [Stas]
+
+Add PerlMapToStorageHandler [Geoffrey Young]
+
+callbacks are now expected to return a meaningful value
+(OK, SERVER_ERROR, etc) or return via an official API
+(exit, die, etc). relying on implicit returns from the
+last call evaluated by a subroutine may result in server
+errors. [Stas, Geoffrey Young]
+
+in the MP_MAINTAINER mode add the -Werror compilation flag when perl
+v5.6.2 or higher is used, so that we don't miss compilation
+warnings. [Stas]
+
+fix the Makefile.PL option parser to support overriding of certain
+build options, in addition to appending to them (.e.g. now MP_LIBNAME
+is overridable) [Andrew Wyllie <wyllie@dilex.net>]
+
+make sure that connection filters won't be inserted as request filters
+[Stas]
+
+Prevent the 'Use of uninitialized value.' warning when
+ModPerl::Util::exit is used. [Stas]
+
+To make the test-suite sandbox-friendly, which break when things try to
+run off /tmp, use t/logs as the location of the mod_cgid socket and
+TMPDIR env var [Haroon Rafique <haroon.rafique@utoronto.ca>]
+
+
+
+=item 1.99_10 - September 29, 2003
+
+added Apache::CRLF, Apache::CR, and Apache::LF to
+Apache::Const's :platform group [Geoffrey Young]
+
+make sure that the custom pools are destroyed only once and only when
+all references went out of scope [Stas]
+
+($r|$c)->add_(input|output)_filter(\&handler) now verify that the
+filter of the right kind is passed and will refuse to add a request
+filter as a connection filter and vice versa. The request filter
+handler is not required to have the FilterRequestHandler attribute as
+long as it doesn't have any other attributes. The connection filter
+handler is required to have the FilterConnectionHandler
+attribute. [Stas]
+
+fix tracing with (PerlTrace/MOD_PERL_TRACE) on win32 (the error_log
+filehandle was invalid after the open_logs phase) [Stas]
+
+fix a bug where %ENV vars set via subprocess_env persist across
+requests. (e.g. a Cookie incoming header which ends up in
+$ENV{HTTP_COOKIE} would persist to the next request which has no
+Cookie header at all). Now we unset all the %ENV vars set from
+subprocess_env. Improve and extend the tests to cover this bug. [Stas]
+
+it is invalid to return HTTP_INTERNAL_SERVER_ERROR or any other HTTP
+response code from modperl_wbucket_pass, therefore set the error code
+into r->status and return APR_SUCCESS. Until now response handler
+with messed up response headers, were causing no response what so ever
+to the client. LWP was assuming 500, and it was all fine, testing
+without LWP has immediately revealed that there was a problem in the
+handling of this case. [Stas]
+
+put the end to the 'Not a CODE reference' errors, instead provide an
+intelligent error message, hopefully telling which function can't be
+found. at the same time improve the tracing to include the pid/tid of
+the server that has encountered this problem, to make it easier to
+debug. [Stas]
+
+mod_perl handler must be duped for any mpm which runs within
+USE_ITHREAD. Until now there was a big problem with prefork mpm if
+any of its vhosts was using PerlOptions +(Parent|Clone) and happened
+to load handlers before the main server. When that was happening the
+main server will see that the handler was resolved (since it sees the
+handler struct from the vhost that loaded this module, instead of its
+own), which in fact it wasn't, causing the failure to run the handler
+with the infamous 'Not a CODE reference' error. [Stas]
+
+Make sure that the static mod_perl library is built after the dynamic
+(a requirement on win32) [Steve Hay <steve.hay@uk.radan.com>]
+
+Apache::Status now generates HTML 4.01 Strict (and in many cases, also
+ISO-HTML) compliant output. Also add a simple CSS to make the reports
+look nicer. [Ville Skyttä <ville.skytta@iki.fi>]
+
+APR::Pool::DESTROY implemented and tweaked to only
+destroy pools created via APR::Pool->new() [Geoffrey Young]
+
+$r->slurp_filename is now implemented in C. [Stas]
+
+remove support for httpd 2.0.45/apr 0.9.3 and lower.
+httpd 2.0.46 is now the minimum supported version.
+[Geoffrey Young]
+
+APR::PerlIO now accepts the pool object instead of a request/server
+objects, so it can be used anywhere, including outside mod_perl [Stas]
+
+when perl is built with perlio enabled (5.8+) the new PerlIO Apache
+layer is used, so now one can push layers onto STDIN, STDOUT handles
+e.g. binmode(STDOUT, ':utf8'); [Stas]
+
+add ap_table_compress() to APR::Table [Geoffrey Young]
+
+alter stacked handler interface so that mod_perl follows Apache
+as closely as possible with respect to VOID/RUN_FIRST/RUN_ALL
+handler types. now, for phases where OK ends the Apache
+call list (RUN_FIRST handlers, such as the PerlTransHandler),
+mod_perl follows suit and leaves some handlers uncalled.
+[Geoffrey Young]
+
+Apache::Build now tries to use the new APR_BINDIR query string to find
+the location of apr-config. [Stas]
+
+new package Apache::porting to make it easier to port mp1 code to mp2
+[Stas]
+
+new Apache::Build methods: mpm_name(), mpm_is_threaded(). use them in
+the top-level Makefile.PL to require 5.8.0/ithreads if mpm requires
+threads. [Stas]
+
+add the missing XS methods to ModPerl::MethodLookup, add support for
+mp1 methods that are no longer in the mod_perl 2.0 API. [Stas]
+
+mod_perl now refuses to build against threaded mpms (non-prefork)
+unless perl 5.8+ w/ithreads is used [Stas]
+
+don't try to read PERL_HASH_SEED env var, where apr_env_get is not
+available (apr < 0.9.3) [Stas]
+
+APR.so now can be loaded and used outside mod_perl (all the way back
+to httpd 2.0.36) [Stas]
+
+perl 5.8.1 randomizes the hash seed, because we precalculate the hash
+values of mgv elements the hash seed has to be the same across all
+perl interpreters. So mod_perl now intercepts cases where perl would
+have randomize it, do the seed randomization by itself and tell perl
+to use that value. [Stas]
+
+fix APR::PerlIO layer to pop itself if open() has failed. [Stas]
+
+move the definition of DEFINE='-DMP_HAVE_APR_LIBS' to the top level
+Makefile.PL, since it overrides MY::pasthru target which makes it
+impossible to define local DEFINE in subdirs. [Stas]
+
+make APR perl functions work outside mod_perl: several libraries
+weren't linked. Also LIBS needs to receive all libs in one
+string. [Stas]
+
+Apache::compat: $r->cgi_env, $r->cgi_var are now aliases to
+$r->subprocess_env [Stas]
+
+For Win32, generate .pdb files for debugging when built with
+MP_DEBUG. These will get installed into the same directory as
+the associated dll/so libs. As well, install mod_perl.lib
+into MP_AP_PREFIX/lib/ for use by 3rd party modules [Randy Kobes].
+
+Apache2.pm is now autogenerated and will adjust @INC to include
+Apache2/ subdirs only if built with MP_INST_APACHE2=1 [Stas]
+
+Change the default value for the argument 'readbytes' for
+ap_get_brigade(), from 0 to 8192. other than being useless, 0 always
+triggers an assert in httpd internal filters and 8192 is a good
+default. [Stas]
+
+Fix DynaLoader breakage when using DL_GLOBAL on OpenBSD
+[Philippe M. Chiasson <gozer@cpan.org>]
+
+renamed the private modperl_module_config_get_obj function to
+modperl_module_config_create_obj, since the logic creates
+the object but doesn't dig it out if it already exists. then,
+moved logic from mpxs_Apache__Module_get_config into a new public
+C function that reused the old name, modperl_module_config_get_obj.
+while Apache::Module->get_config exists as a wrapper to return the
+object to Perl space, now C/XS folks can also access the object
+directly with the public function.
+[Geoffrey Young]
+
+Apache::Reload: add a new config variable:
+ReloadConstantRedefineWarnings to optionally shut off the constant sub
+redefine warnings [Stas]
+
+implement $parms->info. directive handlers should now be complete.
+[Geoffrey Young]
+
+MP_GTOP now works with modern GCC
+[Philippe M. Chiasson <gozer@cpan.org]
+
+add missing dependencies to Apache::PerlSections
+[Geoffrey Young]
+
+$r->get_client_block is bogus in httpd-2.0.45 (and ealier), as it
+can't handle EOS buckets arriving in the same bucket brigade with
+data. so rewrite ModPerl::Test::read_post to use an explicit read
+through all bucket brigades till it sees eos and then it stops. The
+code is longer but it works correctly. [Stas]
+
+an attempt to resolve the binary compatibility problem in
+PerlIOAPR_seek API when APR_HAS_LARGE_FILES=0 [Stas]
+
+perl 5.8.0 forgets to export PerlIOBase_noop_fail, causing problems on
+win32 and aix. reimplement this function locally to solve the
+problem. APR::PerlIO should now be useful on win32 and aix [Stas]
+
+implement DECLINE_CMD and DIR_MAGIC_TYPE constants
+[Geoffrey Young]
+
+allow init filter handlers to call other methods than just $f->ctx [Stas]
+
+Fix Apache::Reload to gracefully handle the case with empty Touchfiles
+[Dmitri Tikhonov <dmitri@netilla.com>]
+
+PerlRequire entried should be executed before PerlModule entries in
+VirtualHost containers, just like in the base server [Stas]
+
+
+
+=item 1.99_09 - April 28, 2003
+
+$filter->seen_eos() now accepts 1/0 to set/unset the flag so streaming
+filters can control the sending of EOS. [Stas]
+
+support systems where apr header files are installed separately from
+httpd header files ["Andres Salomon" <dilinger@voxel.net>]
+
+implement init filter handlers + tests [Stas]
+
+improving ModPerl::MethodLookup to:
+- handle more aliased perl XS functions
+- sort the methods map struct so one can use the autogenerated map as is
+- add lookup_module, tells which methods are defined by a given module
+- add lookup_object, tells which methods can be called on a given object
+- provide autoexported wrappers print_method, print_module and
+ print_object for easy deployment from the command line
+[Stas]
+
+add Perl glue for functions: APR::Socket::timeout_get
+APR::Socket::timeout_set [Stas]
+
+similar to SetEnv, upcase the env keys for PassEnv on platforms with
+caseless env (e.g. win32) [steve.sparling@ps.ge.com]
+
+Add a backcompat wrapper for $r->notes (mp2 supports only the
+APR::Table API) [Stas]
+
+Add a script mp2bug and a target 'make bugreport', so people can use
+bugreporting during the build and after modperl is installed. [Stas]
+
+Add a script mp2doc as a replacement for perldoc (due to 2.0 modules
+living under Apache2, which won't be looked at by perldoc). [Stas]
+
+Add a constant APR::PerlIO::PERLIO_LAYERS_ARE_ENABLED and use it in
+tests [Stas]
+
+Require perl 5.8 or higher when building mod_perl on OSes requiring
+ithreads (e.g., win32), since 5.6.x ithreads aren't good. [Stas]
+
+MP_COMPAT_1X=0 now can be passed to Makefile.PL to disable
+mp1-back-compat compile-time features + adjust tests. [Stas]
+
+<SERVER_ROOT> and <SERVER_ROOT>/lib/perl are now added to @INC, just
+like mod_perl 1.0 with MP_COMPAT_1X=1 (currently enabled by
+default). [Stas]
+
+The Perl-5.8.0 crypt() workaround is now used only if 5.8.0 is used,
+since 5.8.1-tobe/5.9.0-tobe(blead-perl) won't compile with
+it. [Geoffrey Young]
+
+new directives PerlSetInputFilter and PerlSetOutputFilter, which are
+the same as SetInputFilter and SetOutputFilter respectively, but allow
+to insert non-mod_perl filters before, between or after mod_perl
+filters. + tests [Stas]
+
+improved filters debug tracing [Stas]
+
+implement $filter->remove (filter self-removal) + tests [Stas]
+
+remove the second-guessing code that was trying to guess the package
+name to load from the handler configuration (by stripping ::string and
+trying to load the package). fall back to using explicit PerlModule to
+load modules whose handler sub name is not called 'handler' + adjust
+tests. [Stas]
+
+set the magic taint flags before modules are required [Stas]
+
+make sure to set base server's mip before any of the
+PerlRequire/PerlModule directives are called, since they may add
+add_config(), which in turn runs Perl sections or PerlLoadModule,
+which may need the scfg->mip to be set. [Stas]
+
+ModPerl::MM is now ready to be used in Makefile.PL of 3rd party
+mod_perl modules [Stas and Geoff]
+
+fix a segfault caused by PerlModule in $s->add_config, due to setting
+the MP_init_done flag before init was done + add test [Stas]
+
+adjust the generated Makefile's to properly build on aix (tested on
+powerpc-ibm-aix5.1.0.0) [Stas]
+
+the build now automatically glues the .pod files to the respective .pm
+files, so one can use perldoc on .pm files to read the
+documentation. [Stas]
+
+provide a workaround for ExtUtils::MakeMaker::mv_all_methods, so
+ModPerl::BuildMM and ModPerl::MM can override EU::MM methods behind
+the scenes. [Stas]
+
+adding ModPerl::BuildMM, which is now used for building mod_perl.
+ModPerl::MM will be used for 3rd party modules. ModPerl::BuildMM
+reuses ModPerl::MM where possible. [Stas]
+
+drop the glue code for apr_generate_random_bytes, since it's not
+available on all platforms. [Stas]
+
+Since non-threaded mpms don't use tipools in mips, don't create and
+destroy them. [Stas]
+
+re-use the workaround for glibc/Perl-5.8.0 crypt() bug for the
+main/vhost base perl interpreters as well. This solves the problem for
+the buggy glibc on RH8.0. [Stas]
+
+send_cgi_header now turns the header parsing off and can send any data
+attached after the response headers as a response body. [Stas]
+
+move the check that print/printf/puts/write/etc are called in the
+response phase into the functions themselves so 1) we can print a more
+useful error message 2) this check is not always needed in
+modperl_wbucket_write, when called internally, so we save some cycles.
+[Stas]
+
+add checks that print/printf/puts/write/etc are called in the response
+phase. move the check into the functions themselves so we can print a
+more useful error message [Stas]
+
+'make install' now installs mod_perl*h files under httpd's include
+tree [Stas]
+
+When PerlOptions +ParseHeaders is an effect, the CGI headers parsing
+won't be done if any *mod_perl* handler before and including the
+response phase, sets $r->content_type. (similar behavior to mp1's
+send_http_header() [Stas]
+
+Registry: make sure that $r is not in the scope when the script is
+compiled [Stas]
+
+$Apache::Server::SaveConfig added. When set to a true value,
+will not clear the content of Apache::ReadConfig:: once <Perl >
+sections are processed. [Philippe M. Chiasson <gozer@cpan.org]
+
+Apache::compat: support 1.0's Apache->push_handlers,
+Apache->set_handlers and Apache->get_handlers [Stas]
+
+revamp the code handling output flushing and flush bucket
+sending. Namelly modperl_wbucket_flush and modperl_wbucket_pass now
+can be told to send a flush bucket by themselves, attaching it to the
+data bb they are already sending. This halfs the number of output
+filter invocations when the response handler flushes output via $| or
+rflush. adjust tests, which were counting the number of invocations.
+[Stas]
+
+move ModPerl::RegistryCooker to use a hash as object (similar to mp1),
+to make it easier to subclass. [Nathan Byrd <nathan@byrd.net>]
+
+$r->rflush has to flush internal modperl buffer before calling
+ap_rflush, so implement rflush, instead of autogenerating the xs code
+for it. [Stas]
+
+fix the input filters handling of DECLINED handlers (consume the data,
+on behalf of the handler) + tests [Stas]
+
+fix the code that autogenerates modperl_largefiles.h not to define
+macros matching m/^-/ (was a problem on aix-4.3.3) [Stas]
+
+$Apache::Server::StrictPerlSections added. When set to a true
+value, will abort server startup if there are syntax errors
+in <Perl > sections [Philippe M. Chiasson <gozer@cpan.org]
+
+Use Win32::GetShortPathName for Win32 to handle cases when
+the supplied MP_AP_PREFIX contains spaces. [Randy Kobes]
+
+Bump up ThreadsPerChild for mpm_winnt in httpd.conf, which seems
+to help avoid server startup problems when running the tests.
+[Randy Kobes]
+
+implement a new helper module ModPerl::MethodLookup to help figure out
+which module should be loaded when a certain method is reported to be
+missing. [Stas]
+
+fix a bug for apr < 0.9.3, where it segfaults in apr_uri_unparse, if
+hostname is set, but not the scheme. In case the hostname is defined
+but scheme is not Apache::compat will default to the 'http' scheme,
+whereas APR::URI::unparse provides no default [Stas]
+
+move $r->send_http_header implementation to Apache::compat. This
+allows the 1.0 code to run unmodified if $r->send_http_header is
+called before the response change. we already handle the check whether
+content_type was set, when deciding whether the headers are to be
+parsed inside modperl_wbucket_pass(). [Stas]
+
+fixes to Apache::compat. make $r->connection->auth_type interface
+with r->ap_auth_type. make both $r->connection->auth_type and
+$r->connection->user writable. [Geoffrey Young]
+
+Open up r->ap_auth_type, making it possible to write custom
+authen handlers that don't rely on Basic authentication or
+it's associated ap_* functions.
+[Geoffrey Young]
+
+add Apache::Bundle2 [Stas]
+
+Apache::Reload now supports the PerlPreConnectionHandler invocation
+mode, so connection filter and protocol modules can be automatically
+reloaded on change. [Stas]
+
+implement Apache::current_callback + $r->current_callback goes into
+Apache::compat, since now we have a way too many callbacks unrelated
+to $r [Stas]
+
+Add Apache::compat methods: $r->connection->auth_type and
+$r->connection->user (requires 'PerlOptions +GlobalRequest') + tests
+[Stas]
+
+Several issues resolved with parsing headers, including making work
+the handlers calling $r->content_type() and not sending raw headers,
+when the headers scanning is turned on. Lots of tests added to
+exercise different situations. [Stas]
+
+warn on using -T in ModPerl::Registry scripts when mod_perl is not
+running with -T [Stas]
+
+perl 5.7.3+ has a built-in ${^TAINT} to test whether it's running
+under -(T|t). Backport ${^TAINT} for mod_perl running under
+5.6.0-5.7.3, (what used to be $Apache::__T. $Apache::__T is available
+too, but deprecated. [Stas]
+
+add PerlChildExitHandler implementation [Stas]
+
+add PerlCleanupHandler implementation + test [Stas]
+
+die when Apache->request returns nothing ('PerlOptions -GlobalRequest'
+or 'SetHandler modperl') [Stas]
+
+New Apache::Directive methods: as_hash(), lookup() + tests + docs
+[Philippe M. Chiasson <gozer@cpan.org>]
+
+Stacked handlers chain execution is now aborted when a handler returns
+something other than OK or DECLINED [Stas]
+
+make $filter->read() in input streaming filters, use the same number
+of arguments as read() in the output filters. [Stas]
+
+Implement $r->add_input_filter and $r->add_output_filter
+ $c->add_input_filter and $c->add_output_filter
+and add tests [Stas]
+
+Skip the handler package::func resolving error, only when the error
+message matches "Can't locate .*? in @INC", rather than just "Can't
+locate", since there are many other errors that start with that
+string. [Stas]
+
+the top level 'make test' now descends into the ModPerl-Registry dir
+to run 'make test' there [Stas]
+
+All response functions are now returning status and the callers check
+and croak on failure or progate them further. [Stas]
+
+OPEN, CLOSE and FILENO implementation for Apache::RequestRec [Stas]
+
+Another fix for the handling of the return status in
+ModPerl::RegistryCooker: reset the status to the original one only if
+it was changed by the script, otherwise return the execution status
+[Stas]
+
+prevent segfault in $r->print / $filter->print (in output filter) and
+related functions when they are called before the response phase
+[Stas]
+
+prevent segfault in send_http_header when it's called before the
+response phase [Stas]
+
+input stream filtering support was added + tests (plus renaming filter
+tests so we can know from the test name what kind of filter is tested)
+[Stas]
+
+Add proper support for mis-behaved feeding filters that send more than
+one EOS bucket in streaming filters + test. [Stas]
+
+prevent a segfault when push_handlers are used to push a handler into
+the currently phase and switching the handler (perl-script/modperl) +
+tests [Stas]
+
+Add $filter->seen_eos to the streaming filter api to know when eos has
+been seen, so special signatures can be passed and any data stored in
+the context flushed + tests. [Stas]
+
+Add $filter->ctx to maintain state between filter invocation + tests
+[Stas]
+
+Request input and output filters are now getting the EOS bucket, which
+wasn't passed through before. Now the context can be flushed on
+EOS. [Stas]
+
+
+
+=item 1.99_08 - January 10, 2003
+
+Correct ModPerl::RegistryCooker to reset %INC, after compile for .pl
+files which don't declare the package + add tests to check that [Stas]
+
+Log the real error message when Foo::Bar::sub_name fails to resolve,
+because of a problem in Foo::Bar, when Foo::Bar *was* found [Stas]
+
+Add PerlPreConnectionHandler support in Apache::Test [Stas]
+
+Enable PerlPreConnectionHandler [Stas]
+
+Support the Host: request header in Apache::TestClient [Stas]
+
+restore the ModPerl::RegistryLoader::new() method for backwards
+compatibility [Stas]
+
+port the support for NameWithVirtualHost in ModPerl::RegistryCooker
+and ModPerl::RegistryLoader [Stas]
+
+fix the handling of the return status in ModPerl::RegistryCooker, add
+a test to verify that [Stas]
+
+under non-threaded perl need to check whether mod_perl is running,
+when modperl_vhost_is_running check is done. [Stas]
+
+fix $r->read to read all the requested amount of data if possible,
+adjust the test TestApache::read to verify that [Stas]
+
+fix the method content() in Apache::compat to read a whole request
+body. same for ModPerl::Test::read_post. add tests. [Stas]
+
+Adjust the reverse filter test to work on win32 (remove trailing \r)
+[Randy Kobes <randy@theoryx5.uwinnipeg.ca>]
+
+Strongly suggest win32 users to upgrade to 5.8.0, if they run 5.6.x
+[Randy Kobes <randy@theoryx5.uwinnipeg.ca>]
+
+When installing the mod_perl shared object, first need to check
+whether the directory 'modules' already exists, and create it if not.
+[Randy Kobes <randy@theoryx5.uwinnipeg.ca>]
+
+Add a capability to tune the test configuration sections ordering
+in Apache::TestConfigPerl [Stas Bekman]
+
+fix the complaining code about late PerlSwitches when PerlLoadModule
+is used before it [Stas Bekman]
+
+add various tests that exercise PerlLoadModule and vhosts
+[Stas Bekman]
+
+handle correctly PerlLoadModules (directives) with vhosts:
+ - handle gracefully cases when things are undef/NULL
+ - handle the case when scfg==NULL, by stealing the base_servers's config
+[Stas Bekman]
+
+make mod_perl work with vhosts when the server is started prior to
+ post_config():
+ - call modperl_init_globals as early as possible, because the main server
+ record is needed during the configuration parsing, for perlloadmodule
+ and vhosts
+ - also make sure that we are using a real base_server, when dealing
+ with modperl_init, and if not retrieve it from the global record
+[Stas Bekman]
+
+prevent segfaults, when scfg is NULL in Apache::Module->get_config();
+[Stas Bekman]
+
+ensure that a core file is a file indeed, before complaining [Philippe
+M. Chiasson <gozer@cpan.org>]
+
+add $r->as_string [Geoffrey Young]
+
+add backcompat vars: $Apache::Server::CWD and
+$Apache::Server::AddPerlVersion [Stas Bekman]
+
+env var MOD_PERL_TRACE is working again [Stas Bekman]
+
+add a new test TestDirective::perlloadmodule2, which performs a more
+evolved merging. [Stas Bekman]
+
+fix Apache::TestConfigPerl under mod_perl 1.0, need to require
+mod_perl.pm before using $mod_perl::VERSION [Geoffrey Young]
+
+add an Apache::SIG backcompat stub to Apache::compat [Stas Bekman]
+
+fix the Apache::TestConfigPerl's run_apache_test_config() function
+where test packages are scanned for the magic APACHE_TEST_CONFIGURE
+and if found get require()'d. Apache2 needs to be run for mod_perl
+2.0. [Stas Bekman]
+
+move the custom mod_perl 2.0 configuration bits out of the
+ModPerl::TestRun, where they don't belong, into a special config file
+which is included at the very end of httpd.conf [Stas Bekman]
+
+extend Apache::Test to allow extra configuration files to be included
+at the very end of httpd.conf, when everything was loaded and
+configured [Stas Bekman]
+
+resolve a segfault in Apache::Module::get_config() for the edge case
+when the package name is bogus. [Stas Bekman]
+
+Apache::Reload: add support for watching and reloading modules only in
+specified sub-dirs [Harry Danilevsky <harry@deerfieldcapital.com>]
+
+enable APR.pm's linking for apr 0.9.2 and higher, which uses a new lib
+naming scheme, such as libapr-0.so.0.9.2, only if apr-config and
+apu-config scripts exist. [Stas Bekman]
+
+define IoTYPE_RDONLY/IoTYPE_WRONLY for perl-5.6.0 so the project
+compiles again under 5.6.0 [Stas Bekman]
+
+allow output streaming filters to append data to the end of the stream
+[Stas Bekman]
+
+fixes to compile with ActivePerl 5.8 beta
+[Randy Kobes <randy@theoryx5.uwinnipeg.ca>]
+
+fix for directive handlers within vhosts using threaded MPMs
+[Stephen Clouse <stephenc@theiqgroup.com>]
+
+fix <IfDefine MODPERL2> support
+
+default AuthType to Basic if not set in $r->get_basic_auth_pw()
+[Philippe M. Chiasson <gozer@cpan.org>]
+
+workaround glibc/Perl-5.8.0 crypt() bug (seen with threaded MPMs)
+
+fix delete $ENV{$key} bug
+
+fix parse_args compat method to support non-ascii characters and tr/+/ /
+[Walery Studennikov <despair@sama.ru>]
+
+fix post_connection compat method to behave as it did in 1.x
+[Geoffrey Young]
+
+add support for setting $r->auth_name and $r->auth_type
+[Philippe M. Chiasson <gozer@cpan.org>]
+
+add Apache->httpd_conf compat method
+[Philippe M. Chiasson <gozer@cpan.org>]
+
+add default <Perl> handler Apache::PerlSection.
+make <Perl> blocks to be EXEC_ON_READ so apache does not parse the contents.
+add "Perl" directive for general use and for which <Perl> sections are
+stuffed into.
+[Philippe M. Chiasson <gozer@cpan.org>]
+
+rename overloaded LoadModule directive to PerlLoadModule and adjust
+the test naming
+
+
+
+=item 1.99_07 - September 25, 2002
+
+fix =pod directive test config problem
+[Philippe M. Chiasson <gozer@cpan.org>]
+
+
+
+=item 1.99_06 - September 25, 2002
+
+add support for pod directives (=pod,=back,=cut) and __END__ directive
+[Philippe M. Chiasson <gozer@cpan.org>]
+
+tweaks to support Test.pm 1.21 [Philippe M. Chiasson <gozer@cpan.org>]
+
+add $r->add_config method to add dynamic configuration at request time
+
+add Apache::DIR_MAGIC_TYPE constant
+
+add support for directive handlers
+
+fix source_scan to run with current httpd/apr
+
+add Apache::Server->add_config method to add dynamic configuration at
+server startup time
+
+add Apache::Directive->to_string method
+
+add support for pluggable <Perl> sections
+
+fix compilation probs with get_remote_host() that had a wrong
+prototype [Stas Bekman]
+
+Apache::SubProcess now has a manpage [Stas Bekman]
+
+fix the Apache::SubProcess tests to work with perlio-disabled Perl
+[Stas Bekman]
+
+fix the filehandle leak in APR::PerlIO (both perlio-disabled and
+perlio-enabled Perl) [Stas Bekman]
+
+remove dup() when converting filehandles from apr_file_t to FILE*
+under perlio-disabled Perl (APR::PerlIO) [Stas Bekman]
+
+fix compilation if apache/apr do not have thread support
+
+
+
+=item 1.99_05 - August 20, 2002
+
+fix PerlOptions +ParseHeaders to only parse once per-request
+
+add external redirects Registry tests [Stas Bekman]
+
+get rid of the compat layer in ModPerl-Registry [Stas Bekman]
+
+ModPerl::RegistryLoader is now fully operational and tested [Stas Bekman]
+
+Registry method handlers are now working [Stas Bekman]
+
+core Registry packages all compile the scripts into
+ModPerl::RegistryROOT:: namespace and cache them in
+%ModPerl::RegistryCache. Both overridable by the sub-classes. [Stas Bekman]
+
+compat tests were split into groups by functionality, send_fd test
+moved to compat. [Stas Bekman]
+
+added $c->get_remote_host and a compat wrapper $r->get_remote_host +
+tests [Stas Bekman]
+
+adjust the build system to support mod_perl build from the source
+tree. [Stas Bekman]
+
+ModPerl::RegistryCooker syncs with mod_perl 1.0's registry:
+ - prototypes defined checks in flush_namespace
+ [Yair Lenga <yair.lenga@citigroup.com>]
+ - set error-notes on error [Geoffrey Young]
+ - preserve status in Registry scripts [Geoffrey Young]
+
+apr_table_t is now an opaque type, use apr_table_elts() to get the array
+record [Stas Bekman]
+
+add support for redirects with PerlOptions +ParseHeaders
+
+backport to 2.0.35
+
+adjust to filter register api change
+
+added APR::ThreadMutex module
+
+
+
+=item 1.99_04 - June 21, 2002
+
+various APR PerlIO updates [Stas Bekman]
+
+stop using an apr_pool_t to allocate items for the interpreter pool,
+safer for threaded MPMs and prevents "leaks" when interpreters are
+removed from due to PerlInterpMax{Requests,Spare}
+
+implement modperl_sys_dlclose() to avoid apr/pool overhead/thread issues
+
+get the -DPERL_CORE optimization working again
+
+PERL_SET_CONTEXT to the parent interpreter when cloning interpreters at
+request time, else dTHX might be NULL during clone in the given thread,
+which would crash the server.
+
+
+
+=item 1.99_03 - June 15, 2002
+
+win32 fix for the global Apache->request object to make sure it uses
+the thread local storage mechanism
+
+add a reference count mechanism to interpreters for use in threaded MPMs,
+so if APR::Pool cleanups have been registered the interpreter is not
+putback into the interpreter pool until all cleanups have run.
+
+unbuffer STDERR (by turning on autoflush by default)
+
+add support for Perl*Handler +Apache::Foo
+
+fix open_logs,post_config,child_init hooks to run in the proper order
+
+adjust to apr_bucket_type_t changes in 2.0.37-dev
+[Mladen Turk <mturk@mappingsoft.com>]
+
+add MODPERL2 config define, as if the server had been started with -DMODPERL2
+
+compat additions and fixes: $r->lookup_{file,uri}, $r->is_main, Apache->define
+
+added compat for Apache::log_error [Stas Bekman]
+
+
+
+=item 1.99_02 - June 1, 2002
+
+pass the PATH and TZ environment variables at startup by default as 1.xx did
+
+fix ModPerl::Util::exit segv with 5.6.0
+
+no longer support 5.7.x perl development versions
+
+added compat for Apache::Table->new
+
+various fixes to compile/run on darwin
+
+server-scope Perl{Set,Pass}Env config now propagated to %ENV at startup
+
+use SvOK(sv) instead of sv == &PL_sv_undef to detect undef values in xs
+[Stephen Clouse <stephenc@theiqgroup.com>]
+
+complete Apache::Util 1.x compat
+
+added Apache::MPM_IS_THREADED constant
+
+added compat function for Apache::Constants::SERVER_VERSION
+
+added Apache::Constants::export stub for compat
+
+added noop stubs for timeout functions removed from 2.0:
+$r->{soft,hard,reset,kill}_timeout
+
+turned on PerlOptions +GlobalRequest by default for perl-script handler
+unless it is explicitly turned off with PerlOptions -GlobalRequest
+
+added APR::OS::thread_current function
+
+added support for 1.x $r->subprocess_env functionality
+
+added support for $r->push_handlers(PerlHandler => ...)
+
+added support for $r->proxyreq to detect proxy requests
+
+$r->content_type($val) now calls ap_set_content_type underneath
+
+add the err_header_out() wrapper to Apache::compat + corresponding tests
+[Stas Bekman]
+
+fix $r->dir_config lookup of values set in the server context
+
+added Apache::REDIRECT shortcut constant
+
+various fixes for method handlers
+
+use Apache::ServerUtil in Apache::compat so Apache->server works in compat
+mode [Dave Rolsky <autarch@urth.org>]
+
+add Apache::Util::unescape_uri alias to Apache::unescape_url in Apache::compat
+
+change Apache::unescape_url to return the escaped url as 1.x does
+
+disabled term coloring by default (enable with env var APACHE_TEST_COLOR=1)
+
+fix for APR::IpSubnet->new to check return status apr_ipsubnet_create
+
+enabled APR::SockAddr module
+
+turn on binmode for filehandle used in $r->send_fd
+
+get MP_{TRACE,DEBUG} Makefile.PL options working on win32
+
+various fixes to build/run with bleedperl
+
+various fixes for win32 to get make test passing
+
+moved constuct_{url,server} methods to Apache::URI module
+
+implement Apache::URI::parse in Apache::compat
+
+give Perl*Handlers precedence over other handlers by using APR_HOOK_FIRST
+rather than APR_HOOK_LAST
+
+workaround bug in 5.6.1 when XSLoader loads DynaLoader, wiping out any
+dl handles it had been keeping track of.
+
+tidy up test to run standalone (without modperl test config)
+[Stas Bekman]
+
+override T_PTROBJ INPUT typemap to croak if object is not a blessed
+reference, to prevent possible segv from e.g. Apache::Server->process
+
+apr_lock.h is gone; disable APR::Lock for the moment
+
+enabled the Apache::Process module
+
+fix ModPerl::Util::exit to clear $@ before calling Perl_croak
+
+cut down on some build noise
+
+fix 'PerlOptions +GlobalRequest' when used within subrequests
+
+get rid of some "subroutine redefined" warnings in ModPerl::MM that
+show up with newer bleedperls.
+
+a few fixes for Apache::compat [Dave Rolsky <autarch@urth.org>]
+
+
+
+=item 1.99_01 - April 6, 2002
+
+First public release of mod_perl-2.0-tobe.
+
+=back
+
+=cut
diff --git a/2_0_13/INSTALL b/2_0_13/INSTALL
new file mode 100644
index 0000000..e8c110b
--- /dev/null
+++ b/2_0_13/INSTALL
@@ -0,0 +1,40 @@
+Simple install:
+
+ % perl Makefile.PL MP_APXS=/usr/local/apache2/bin/apxs
+ % make && make test
+ % make install
+
+Simple install on AIX:
+
+ You will need GNU make to compile mod_perl. The AIX make does not work.
+ If you have installed GNU make from the AIX Toolbox:
+
+ % export MAKE="/opt/freeware/bin/gmake"
+ % perl Makefile.PL MP_APXS=/usr/local/apache2/bin/apxs
+ % gmake && gmake test
+ % gmake install
+
+Simple config:
+
+ LoadModule perl_module modules/mod_perl.so
+ #PerlModule Apache::compat
+ # your config comes here
+
+For a more detailed version (including more options) refer to:
+
+ docs/user/intro/start_fast.pod
+
+or online:
+
+ http://perl.apache.org/docs/2.0/user/intro/start_fast.html
+
+For an even more detailed documentation refer to:
+
+ docs/user/install/install.pod
+ docs/user/config/config.pod
+
+or online:
+
+ http://perl.apache.org/docs/2.0/user/install/install.pod
+ http://perl.apache.org/docs/2.0/user/config/config.pod
+
diff --git a/2_0_13/LICENSE b/2_0_13/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/2_0_13/LICENSE
@@ -0,0 +1,202 @@
+
+ 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.
diff --git a/2_0_13/META.yml b/2_0_13/META.yml
new file mode 100644
index 0000000..d652de7
--- /dev/null
+++ b/2_0_13/META.yml
@@ -0,0 +1,24 @@
+name: mod_perl
+version: 2.0.13
+installdirs: site
+distribution_type: module
+no_index:
+ directory:
+ # A-T and others have their own CPAN distros
+ - Apache-Test
+ - Apache-Reload
+ - Apache-SizeLimit
+ package:
+ # Internally redefined module
+ - C::Preprocessed
+ # Fake packages
+ - Apache::Status::_version
+ - perlrun_decl
+ # Apache::compat redefines
+ - Apache
+ - Apache::Constants
+ - Apache::File
+ - Apache::SIG
+ - Apache::Server
+ - Apache::Table
+ - Apache::Util
diff --git a/2_0_13/Makefile.PL b/2_0_13/Makefile.PL
new file mode 100644
index 0000000..2ceb943
--- /dev/null
+++ b/2_0_13/Makefile.PL
@@ -0,0 +1,947 @@
+use 5.006;
+use strict;
+use warnings FATAL => 'all';
+
+# useful for sub-Makefile.PL's to know whether they are invoked
+# directly or via the top level Makefile.PL
+$ENV{MOD_PERL_2_BUILD} = 1;
+
+use constant MIN_HTTPD_VERSION_DYNAMIC => '2.0.47';
+use constant MIN_HTTPD_VERSION_STATIC => '2.0.51';
+use constant MIN_HTTPD_24_VERSION => '2.4.0';
+
+my($old_modperl_version, $old_modperl_pm, $old_Apache2_pm);
+
+BEGIN {
+ eval {
+ my $old_mp2 = eval { require Apache2 };
+ require mod_perl;
+ if ($mod_perl::VERSION < 1.999_22 && $old_mp2) {
+ $old_modperl_version = $mod_perl::VERSION;
+ $old_modperl_pm = delete $INC{'mod_perl.pm'};
+ $old_Apache2_pm = delete $INC{'Apache2.pm'};
+ }
+ };
+
+}
+
+use lib qw(lib Apache-Test/lib);
+
+use Config;
+use File::Spec::Functions;
+use File::Spec;
+use DirHandle ();
+use File::Copy 'cp';
+use File::Basename qw(basename dirname);
+use File::Find ();
+
+use Apache2::Build ();
+use Apache::TestSmokePerl ();
+use Apache::TestTrace;
+use ModPerl::TestReport ();
+use ModPerl::TestRun ();
+use ModPerl::Code ();
+use ModPerl::BuildMM ();
+
+use constant WIN32 => Apache2::Build::WIN32;
+use constant BUILD_APREXT => Apache2::Build::BUILD_APREXT;
+
+our $VERSION;
+
+my $build = Apache2::Build->new(init => 1);
+my $code = ModPerl::Code->new;
+
+sub UNATTENDED() { $build->{MP_PROMPT_DEFAULT} || ! -t STDIN }
+
+# may populate $build->{MP_APXS}
+win32_fetch_apxs() if WIN32;
+
+configure();
+perl_version_check($build);
+
+local %ModPerl::BuildMM::PM = (
+ 'lib/typemap' => 'blib/lib/Apache2/typemap',
+);
+
+# these h files need to be installed system-wide so 3rd party XS
+# extensions can use them
+my @xs_h_files = map catfile("xs", $_),
+ qw(modperl_xs_sv_convert.h modperl_xs_typedefs.h modperl_xs_util.h
+ APR/PerlIO/modperl_apr_perlio.h);
+my @exe_files = map "bin/$_", qw(mp2bug);
+
+ModPerl::BuildMM::WriteMakefile(
+ NAME => 'mod_perl2',
+ VERSION => $VERSION,
+ DISTNAME => 'mod_perl',
+ NO_META => 1,
+ ABSTRACT_FROM => 'lib/mod_perl2.pm',
+ EXE_FILES => \@exe_files,
+ DEFINE => get_DEFINE(),
+ macro => {
+ MODPERL_SRC => $code->path,
+ MODPERL_MAKEFILE => basename($build->default_file('makefile')),
+ PERL => $build->perl_config('perlpath'),
+ MOD_INSTALL => ModPerl::BuildMM::mod_install(),
+ MODPERL_AP_INCLUDEDIR =>
+ $build->ap_destdir($build->install_headers_dir),
+ MODPERL_XS_H_FILES => join(" \\\n\t", @xs_h_files),
+ },
+ clean => {
+ FILES => "@{ clean_files() }",
+ },
+ dist => {
+ DIST_DEFAULT => 'mydist',
+ COMPRESS => 'gzip -9f', SUFFIX=>'gz',
+ PREOP => 'find $(DISTVNAME) -type d -print|xargs chmod 0755 && ' .
+ 'find $(DISTVNAME) -type f -print|xargs chmod 0644',
+ TO_UNIX => 'find $(DISTVNAME) -type f -print|xargs dos2unix'
+ },
+);
+
+post_configure();
+
+sub get_DEFINE {
+
+ my $opt_define = '';
+
+ # do we have apr libs?
+ # XXX: this define is really needed in xs/APR/APR/Makefile.PL, but this
+ # top-level Makefile.PL overrides MY::pasthru, and defines DEFINE= which
+ # overrides any local definition, not sure what's the right fix, for
+ # now just define it here (should it define PASTHRU_DEFINE instead?)
+ $opt_define = '-DMP_HAVE_APR_LIBS' if $build->apru_link_flags;
+
+ # preserve any DEFINE opts from outside and combine them with our
+ # local DEFINE
+ @ARGV = grep defined,
+ map { (/^DEFINE=(.*)/ && ($opt_define .= " $1")) ? undef : $_ } @ARGV;
+
+ return $opt_define;
+}
+
+sub configure {
+
+ # mod_perl test suite relies on having Apache-Test bundled with
+ # the mod_perl source, since any pre-installed version may not do
+ # the right thing
+ unless (-d "Apache-Test") {
+ error "Can't find a sub-directory Apache-Test. " .
+ "Make sure that you are using a complete source distribution";
+ exit 1;
+ }
+
+ set_modperl_version();
+
+ if ($old_modperl_version) {
+ (my $old_modperl_version_str = $old_modperl_version)
+ =~ s/(\d\d\d?)(\d\d)/$1_$2/;
+ my $vstring = "mod_perl/$old_modperl_version_str";
+ print "$vstring installation detected...";
+
+ my $prefix;
+ /^PREFIX=(.*)/ && $1 && ($prefix = canonpath glob($1)) for @ARGV;
+
+ # check that it's a full path
+ my $path = canonpath $old_modperl_pm;
+ # XXX: doesn't handle relative paths yet
+ # if PREFIX=/foo/bar is used, and it's not the same as the
+ # path where mod_perl < 1.999_22 is installed
+ if ($prefix && $path !~ /^$prefix/) {
+ print "ok (will install mod_perl/$VERSION into PREFIX=$prefix, " .
+ "no collision)\n";
+ }
+ else {
+ my $note = '';
+ if ($old_Apache2_pm) {
+ $note .= "Conflicting file: $old_Apache2_pm\n";
+ }
+ if ($path =~ /Apache2/ or $old_modperl_version > 1.99) {
+ my $dir = dirname $path;
+ # was it installed into the top-level?
+ $dir = catdir $dir, 'Apache' unless $path =~ /Apache2/;
+ $note .= "Conflicting dir: $dir\n" if -d $dir;
+ }
+
+ print " not ok\n\n";
+ print <<EOI;
+Cannot install mod_perl/$VERSION on top of $vstring
+due to a major API change between mod_perl 1.999_21 and 1.999_22.
+
+$note
+Please nuke the prior mod_perl installation from your site_lib,
+use a different perl to run the installation process, or use the
+PREFIX option when creating your Makefile. See:
+
+ http://perl.apache.org/docs/2.0/rename.html
+
+for more details.
+
+aborting...
+EOI
+ exit 1;
+ }
+ }
+ else {
+ print "no conflicting prior mod_perl version found - good.\n";
+
+ }
+
+ # On Win32, in order to decouple APR::* from mod_perl.so, we
+ # make up a static library MP_APR_LIB of the symbols required from
+ # src/modules/perl/*.c (see xs/APR/aprext/Makefile.PL), and
+ # then link APR/APR::* against this library. The reason for
+ # this is that, unlike Unix, if we had linked APR/APR::* against
+ # the mod_perl lib, then use of APR/APR::* would demand mod_perl.so
+ # be available, even if these symbols are supplied by another
+ # loaded library (which is done for unix by APR.so - see
+ # xs/APR/APR/Makefile.PL). This also means we must ensure the
+ # MP_APR_LIB lib is built before any of the APR/APR::* modules
+ # (see the aprext target in the MY::top_targets sub below), as
+ # symbols must get resolved at link time.
+
+ if (BUILD_APREXT()) {
+ require File::Path;
+ #Makefile.PL's in WrapXS/ just need to pass the -e mod_perl.lib test
+ #the real mod_perl.lib will be in place when WrapXS/ dll's are
+ #actually linked
+ # this must also be done for aprext.lib, build in xs/APR/aprext/;
+ # we must create a dummy aprext.lib to pass the -e test.
+ my $lib1 = catfile qw(src modules perl),
+ $build->{MP_LIBNAME} . $Config{lib_ext};
+ my ($apr_blib, $full_libname) = $build->mp_apr_blib();
+ my $lib2 = catfile $apr_blib, $full_libname;
+ unless (-d $apr_blib) {
+ File::Path::mkpath($apr_blib) or die "mkdir $apr_blib failed: $!";
+ }
+ foreach my $lib ($lib1, $lib2) {
+ unless (-e $lib) {
+ open my $fh, '>', $lib or die "open $lib: $!";
+ print $fh "#this is a dummy file to trick MakeMaker";
+ close $fh;
+ }
+ }
+ }
+
+ system_sanity_check();
+
+ my $min_httpd_version = $build->should_build_apache
+ ? MIN_HTTPD_VERSION_STATIC
+ : MIN_HTTPD_VERSION_DYNAMIC;
+
+ if ($build->{MP_APXS}) {
+ print "Using APXS => $build->{MP_APXS}\n";
+ }
+ elsif ($build->{MP_AP_PREFIX}) {
+ if (my $reason = $build->ap_prefix_invalid) {
+ error "invalid MP_AP_PREFIX: $reason";
+ exit 1;
+ }
+ print "Using Apache prefix => $build->{MP_AP_PREFIX}\n";
+ }
+ else {
+ unless ($build->{MP_USE_STATIC}) {
+ # may populate $build->{MP_APXS}
+ prompt_for_apxs($build);
+ }
+ }
+
+ $build->{$_} and $ENV{$_} = $build->{$_} for (qw/MP_APXS MP_AP_PREFIX/);
+
+ unless ($build->{MP_APXS} or $build->{MP_AP_PREFIX}) {
+ my $ok = 0;
+ for my $path ($build->find) {
+ $build->dir($path);
+ my $mmn = $build->module_magic_number;
+ my $v = $build->httpd_version;
+ next unless $v;
+ next if $v lt $min_httpd_version;
+ $ok++ if $build->prompt_y("Configure mod_perl with $path?");
+ last if $ok;
+ }
+ until ($ok) {
+ my $ask = "Please provide the location of the Apache directory:";
+ my $ans = $build->prompt($ask) || "";
+ # strip leading/closing spaces
+ $ans =~ s/^\s*|\s*$//g;
+ if (defined $ans and -d $ans) {
+ $build->dir($ans);
+ $ok++;
+ }
+ else {
+ error "Can't find dir '$ans'";
+ last if UNATTENDED;
+ }
+ }
+ }
+
+ if ($build->should_build_apache) {
+ $build->configure_apache();
+ }
+
+ my $httpd_version = $build->httpd_version;
+ unless ($httpd_version) {
+ error 'Unable to determine server version, aborting.';
+ if ($build->{MP_APXS} || $build->{MP_AP_PREFIX}) {
+ my $what = $build->{MP_APXS} ? 'MP_APXS' : 'MP_AP_PREFIX';
+ error "Invalid $what specified?";
+ }
+ else {
+ error 'Please specify MP_APXS or MP_AP_PREFIX.';
+ }
+ exit(1);
+ }
+
+ if ($httpd_version lt $min_httpd_version) {
+ error "Apache/$httpd_version not supported, " .
+ "$min_httpd_version or higher is required";
+ exit(1);
+ }
+
+ printf "Configuring Apache/%s mod_perl/%s Perl/v%vd\n",
+ $httpd_version, $VERSION, $^V;
+
+ my $apr_config = $build->get_apr_config; #cache it
+
+ # we need to know where apr-config and apu-configs are
+ # which sometimes aren't placed into the same dir with apxs/httpd
+ # XXX: need to fix that for WIN32
+ # XXX: when the source tree is used, there is not much use for apr-config
+ unless (WIN32 || $build->apr_config_path || $build->httpd_is_source_tree) {
+ error "can't find 'apr-config', please pass " .
+ "MP_APR_CONFIG=/full/path/to/apr-config to 'perl Makefile.PL'";
+ exit 1;
+ }
+
+ for (@{ clean_files() }) {
+ debug "unlink...$_" if -e $_ && unlink;
+ }
+
+ #ModPerl::BuildMM will use Apache2::BuildConfig in subdir/Makefile.PL's
+ $build->save;
+
+ ModPerl::TestRun->generate_script;
+ ModPerl::TestReport->generate_script;
+ Apache::TestSmokePerl->generate_script;
+
+ my $tables_dir = tables_dir($httpd_version);
+
+ unshift @INC, $tables_dir;
+
+ if ($build->{MP_GENERATE_XS}) {
+ debug "generating XS code using $tables_dir...";
+ xs_generate($httpd_version);
+ }
+
+ install_typemap();
+}
+
+sub prompt_for_apxs {
+ my $build = shift;
+
+ print <<EOI;
+
+Next we need to know where the 'apxs' script is located. This script
+provides a lot of information about the Apache installation, and makes
+it easier to find things on your system. Normally it's located in the
+same directory as the 'httpd' executable.
+
+If you don't yet have Apache installed you can build Apache against
+the Apache source code, but you won't be able to run the test suite (a
+very important step). Therefore you may want to install Apache before
+proceeding.
+
+EOI
+
+ my $prompt = "\nPlease provide a full path to 'apxs' executable\n" .
+ "(press Enter if you don't have it installed):";
+ while (1) {
+ my $ans = $build->prompt($prompt) || "";
+
+ print "\n\n";
+
+ # strip leading/closing spaces
+ $ans =~ s/^\s*|\s*$//g;
+
+ last unless length $ans; # skip
+
+ unless (File::Spec->file_name_is_absolute($ans)) {
+ warn "The path '$ans' is not an absolute path. " .
+ "Please specify an absolute path.\n";
+ next;
+ }
+
+ warn("'$ans' doesn't exist.\n"), next unless -e $ans;
+ warn("'$ans' is not a file.\n"), next unless -f _;
+ warn("'$ans' is not executable.\n"), next unless -x _;
+
+ $build->{MP_APXS} = $ans;
+ last;
+ }
+}
+
+sub post_configure {
+
+ #now have any data subdir/Makefile.PL's save, e.g. XS
+ $build = Apache2::Build->build_config;
+
+ $build->write_src_makefile;
+ $build->save_ldopts;
+
+ $code->generate($build);
+
+ for my $type (qw(DSO STATIC)) {
+ next unless $build->{"MP_USE_$type"};
+ warning "mod_perl \L$type\E library will be built as ".
+ $build->{"MODPERL_LIB_$type"};
+ }
+
+ if ($build->is_dynamic) {
+ warning
+ "You'll need to add the following to httpd.conf:", "",
+ " LoadModule perl_module modules/$build->{MODPERL_LIB_DSO}", "",
+ "depending on your build, mod_perl might not live in",
+ "the modules/ directory.\n";
+ if ($build->{MP_APXS}) {
+ warning
+ "Check the results of", "",
+ " \$ $build->{MP_APXS} -q LIBEXECDIR", "",
+ "and adjust the LoadModule directive accordingly.\n";
+ }
+ }
+
+ $build->save;
+}
+
+sub tables_dir {
+ my $httpd_version = shift;
+
+ my $tables_version='';
+ if ($httpd_version lt MIN_HTTPD_24_VERSION) {
+ $tables_version='current';
+ }
+ else {
+ $tables_version='current24';
+ }
+
+ my $tables_dir = "xs/tables/$tables_version";
+}
+
+sub xs_generate {
+ require ModPerl::WrapXS;
+
+ my $xs = ModPerl::WrapXS->new;
+
+ $xs->generate;
+
+ #shift @INC; #ModPerl::Code needs this path too
+}
+
+sub install_typemap {
+ my $to_file = 'lib/typemap';
+
+ open my $to_fh, ">$to_file" or die "open $to_file: $!";
+
+ for my $from_file (qw(WrapXS/typemap xs/typemap)) {
+ open my $from_fh, $from_file or die "open $from_file: $!";
+ cp $from_fh, $to_fh;
+ close $from_fh;
+ }
+
+ close $to_fh or die "close $to_file: $!";
+}
+
+sub echo_cmd {
+ my $cmd = shift;
+ print "$cmd\n";
+ system($cmd) == 0 or exit(1);
+}
+
+sub clean_files {
+ my $path = $code->path;
+
+ my @files = ();
+ File::Find::find(sub { push @files, "$File::Find::dir/$_" if -f $_},
+ "WrapXS") if -d "WrapXS";
+
+ push @files, map { "xs/$_.h" }
+ qw(modperl_xs_typedefs modperl_xs_sv_convert);
+
+ return [@{ $build->clean_files },
+ @files,
+ qw(lib/typemap
+ lib/ModPerl/MethodLookup.pm
+ lib/ModPerl/DummyVersions.pm
+ t/htdocs/vhost/error_log
+ t/SMOKE
+ t/TEST
+ t/REPORT
+ ),
+ <t/htdocs/hooks/startup/open_logs*>,
+ <t/htdocs/hooks/startup/post_config*>,
+ <xs/*.exp>,
+ <xs/*.def>,
+ map { "$path/$_"} @{ $code->clean_files }
+ ];
+}
+
+sub set_modperl_version {
+ require './lib/mod_perl2.pm';
+
+ $VERSION = $mod_perl2::VERSION_TRIPLET;
+
+ open my $fh, 'Changes';
+ while (<$fh>) {
+ if (/^=item\s+\Q$VERSION\E-(dev|rc\d+)/) {
+ $VERSION .= "-$1";
+ last;
+ }
+ last if /^=item/;
+ }
+ close $fh;
+
+ $build->{VERSION} = $VERSION;
+ $build->{API_VERSION} = $mod_perl2::API_VERSION;
+}
+
+# needs to be run after configure() when apxs is setup
+sub perl_version_check {
+ my $build = shift;
+
+ my $perl_version = $];
+ $perl_version =~ s/5.00(\d)(?:00(\d))?/"5.$1." . ($2||0)/e;
+ my $perl_threads = Apache2::Build::PERL_HAS_ITHREADS ? "w/" : "w/o";
+ my $perl_string = "Using Perl $perl_version $perl_threads ithreads";
+ my $httpd_version = $build->httpd_version;
+ my $mpm = "";
+ my $build_threaded = 0;
+
+ # For httpd-2.4, we can't use mpm_is_threaded(), because MPMs are loadable
+ # modules. We therefore treat httpd as a whole project as threaded. It is
+ # still possible to disable threading by using MP_NO_THREADS=1
+ if ($httpd_version lt MIN_HTTPD_24_VERSION) {
+ $build_threaded = $build->mpm_is_threaded();
+ $mpm = $build->mpm_name();
+ }
+ else {
+ if ($build->{MP_NO_THREADS}) {
+ $build_threaded = 0;
+ }
+ else {
+ $build_threaded = 1;
+ }
+ }
+
+ # certain mpms require perl 5.8.0+ w/ithreads
+ if ($build_threaded) {
+ my @fail;
+ push @fail, "Perl 5.8 or higher"
+ unless $] >= 5.008;
+ push @fail, "Perl built with ithreads (build perl with -Duseithreads)"
+ unless Apache2::Build::PERL_HAS_ITHREADS();
+ if (@fail) {
+ if ($httpd_version lt MIN_HTTPD_24_VERSION) {
+ error "$perl_string and '$mpm' mpm httpd.",
+ "Failed requirements:",
+ join "", map {" - $_\n"} @fail;
+ }
+ else {
+ error "$perl_string and httpd-2.4.",
+ "Failed requirements:",
+ join "", map {" - $_\n"} @fail;
+ }
+ exit 1;
+ }
+ }
+ else {
+ # before 5.8.2, perl_shutdown is incomplete (in the case of ithreads
+ # each PerlInterpreter * gets tossed so it works)
+ if ($build->should_build_apache && !Apache2::Build::PERL_HAS_ITHREADS) {
+ # before 5.8.2, perl_shutdown is incomplete
+ if ($] < 5.008_002) {
+ if ($httpd_version lt MIN_HTTPD_24_VERSION) {
+ error "static $mpm mpm requires a threaded ".
+ "perl 5.6.1-5.8.1 or any perl 5.8.2+";
+ }
+ else {
+ error "httpd-2.4 requires a threaded ".
+ "perl 5.6.1-5.8.1 or any perl 5.8.2+";
+ }
+ exit 1;
+ }
+ }
+ }
+
+ if ($] < 5.006_001) {
+ error "$perl_string. You need at least Perl 5.6.1";
+ exit 1;
+ }
+
+ if ($] >= 5.007 and $] < 5.008) {
+ error "$perl_string.",
+ "5.7.x development versions of Perl are no longer supported",
+ "Upgrade to Perl 5.8.0 or higher";
+ exit 1;
+ }
+
+ if ($Config{usemultiplicity} xor $Config{useithreads}) {
+ error "mod_perl does not currently support multiplicity without ".
+ "ithreads.";
+ if ($build_threaded) {
+ error "Please recompile Perl with -Duseithreads and ".
+ "-Dusemultiplicity";
+ } else {
+ error "Please recompile Perl with either -Duseithreads and ".
+ "-Dusemultiplicity or -Uuseithreads and -Uusemultiplicity";
+ }
+ exit 1;
+ }
+}
+
+sub system_sanity_check {
+ return if WIN32;
+
+ my $ccflags = $build->perl_config('ccflags');
+ for (split /\s+/, $ccflags) {
+ next unless s/^-I//;
+ my $header = "$_/ap_mmn.h";
+ if (-e $header) {
+ $build->phat_warn(<<EOF);
+Apache headers found in unexpected location: ``$_'', suggestions:
+ *) Remove via ``rpm -e apache''
+ *) Remove by hand
+ *) Complain to your os vendor about their poor layout choice
+ *) Complain to your sysadmin about their poor layout choice
+EOF
+ }
+ }
+
+ $build->lib_check('gdbm');
+ malloc_check();
+ os_check();
+}
+
+sub malloc_check {
+ return unless $build->is_dynamic;
+ return unless $build->perl_config('usemymalloc') eq 'y';
+
+ my $abort = $^O eq 'solaris';
+
+ my $bincompat = $build->perl_config('bincompat5005');
+
+ if ($bincompat) {
+ $build->phat_warn(<<EOF, $abort);
+Your current configuration will most likely trigger core dumps, suggestions:
+ *) Do not configure mod_perl as a DSO
+ *) Rebuild Perl without malloc pollution (Configure -Ubincompat5005)
+EOF
+ }
+}
+
+sub os_check {
+ my $check = \&{"os_check_$^O"};
+ return unless defined &$check;
+ $check->()
+}
+
+sub os_check_hpux {
+ my $ccflags = $build->perl_config('ccflags');
+ my $ld = $build->perl_config('ld');
+
+ if ($build->is_dynamic and $ld eq 'ld') {
+ unless ($ccflags =~ /\+z/i) {
+ $build->phat_warn(<<EOF);
+mod_perl is unlikely to link with your libperl, suggestions:
+ *) Rebuild Perl with Configure -Accflags=+Z ...
+EOF
+ }
+ }
+}
+
+sub win32_fetch_apxs {
+ return unless (my $prefix = $build->{MP_AP_PREFIX});
+ my $script = catfile($build->{cwd}, 'build', 'win32_fetch_apxs');
+ my @args = ($^X, $script, "--with-apache2=$prefix");
+ system(@args) == 0 or die "system @args failed: $?";
+ my $apxs = catfile($prefix, 'bin', 'apxs.bat');
+ $build->{MP_APXS} = $apxs if -e $apxs;
+}
+
+
+package MY;
+
+use Config;
+use constant WIN32 => $^O eq 'MSWin32';
+use constant BUILD_APREXT => Apache2::Build::BUILD_APREXT;
+
+sub MY::top_targets {
+ my $self = shift;
+ my $string = $self->ModPerl::BuildMM::MY::top_targets;
+
+ if (BUILD_APREXT) {
+ ModPerl::MM::add_dep(\$string, pure_all => 'aprext');
+
+ # must not import File::Spec functions inside MY, it breaks
+ # 5.6.x builds
+ my ($apr_blib, $full_libname) = $build->mp_apr_blib();
+ my $from = File::Spec->catfile($apr_blib, $full_libname);
+ (my $ap_lib = $build->ap_includedir()) =~ s{include$}{lib};
+ my $to = File::Spec->catfile($ap_lib, $full_libname);
+ my $src_dir = File::Spec->catdir(qw(xs APR), 'aprext');
+ $string .= <<"EOF";
+
+aprext:
+ cd "$src_dir" && \$(MAKE) all \$(PASTHRU) LINKTYPE="static"
+
+aprext_install:
+ \@\$(MKPATH) "$ap_lib"
+ \$(CP) "$from" "$to"
+
+EOF
+ }
+
+ if ($build->should_build_apache) {
+ ModPerl::MM::add_dep(\$string, pure_all => 'ap_build');
+ $string .= <<"EOF";
+ap_build: modperl_lib
+ cd "$build->{MP_AP_PREFIX}" && make
+
+ap_install: ap_build
+ cd "$build->{MP_AP_PREFIX}" && make DESTDIR=\$(DESTDIR) install
+EOF
+ }
+
+ ModPerl::MM::add_dep(\$string, pure_all => 'modperl_lib');
+
+ $string .= <<'EOF';
+
+source_scan:
+ $(PERL) build/source_scan.pl
+
+xs_generate:
+ $(PERL) build/xs_generate.pl
+
+bugreport:
+ $(PERL) bin/mp2bug
+
+etags:
+ $(SHELL) build/make_etags
+
+modperl_lib:
+ cd "$(MODPERL_SRC)" && $(MAKE)
+
+modperl_lib_install:
+ cd "$(MODPERL_SRC)" && $(MAKE) DESTDIR=$(DESTDIR) install
+
+modperl_xs_h_install:
+ @$(MKPATH) $(DESTDIR)$(MODPERL_AP_INCLUDEDIR)
+ $(CP) $(MODPERL_XS_H_FILES) $(DESTDIR)$(MODPERL_AP_INCLUDEDIR)
+
+modperl_src_clean:
+ cd "$(MODPERL_SRC)" && $(MAKE) clean
+
+EOF
+
+ # $(ECHO) was broken before 6.10_01
+ # XXX: if ever require 6.11 we can remove this workaround
+ require ExtUtils::MakeMaker;
+ (my $mm_ver = ExtUtils::MakeMaker->VERSION) =~ s/_\d+//;
+ my $say = $mm_ver > 6.10
+ ? '@$(ECHO)'
+ : '@$(PERL) -le "print shift"';
+
+ $string .= <<"EOF";
+modperl_banner:
+ $say "+--------------------------------------------------------------+"
+ $say "| |"
+ $say "| For details on getting started with mod_perl 2, see: |"
+ $say "| |"
+ $say "| http://perl.apache.org/docs/2.0/user/intro/start_fast.html |"
+ $say "| |"
+ $say "| |"
+ $say "| Found a bug? File a bug report: |"
+ $say "| |"
+ $say "| http://perl.apache.org/bugs/ |"
+ $say "| |"
+ $say "+--------------------------------------------------------------+"
+
+EOF
+
+ $string;
+}
+
+sub MY::install {
+ my $self = shift;
+ my $string = $self->MM::install(@_);
+
+ for my $kind ('', '_site', '_vendor') {
+ ModPerl::MM::add_dep(\$string, "pure${kind}_install" => 'ap_install')
+ if $build->should_build_apache;
+ ModPerl::MM::add_dep(\$string, "pure${kind}_install" => 'modperl_lib_install');
+ ModPerl::MM::add_dep(\$string, "pure${kind}_install" => 'modperl_xs_h_install');
+ # ModPerl::MM::add_dep(\$string, "pure${kind}_install" => 'aprext_install')
+ # if BUILD_APREXT;
+
+ ModPerl::MM::add_dep_after(\$string, "install$kind", "doc${kind}_install", 'modperl_banner');
+
+ # glue_pods target must come first
+ ModPerl::MM::add_dep(\$string, "pure${kind}_install" => 'glue_pods');
+ }
+
+ $string;
+}
+
+sub MY::clean {
+ my $self = shift;
+ my $string = $self->MM::clean(@_);
+ ModPerl::MM::add_dep(\$string, clean => 'modperl_src_clean');
+ ModPerl::MM::add_dep(\$string, clean => 'test_clean');
+ $string;
+}
+
+sub MY::test {
+
+ my $preamble;
+ if (Apache::TestConfig::WIN32) {
+ # need to add the location of Apache's dlls to the PATH
+ my $ap_bindir = $build->apr_bindir() || '';
+ unless ($ap_bindir) {
+ $ap_bindir = File::Spec->catdir($build->{MP_AP_PREFIX}, 'bin')
+ if $build->{MP_AP_PREFIX};
+ }
+ my $modperl_libexecdir = '';
+ if ($build->is_dynamic) {
+ # need to add the location of mod_perl.so to the PATH
+ my $lib = $build->modperl_libpath() || '';
+ if ($lib) {
+ $modperl_libexecdir = File::Basename::dirname($lib);
+ }
+ else {
+ $modperl_libexecdir = File::Spec->catdir($build->{cwd},
+ 'src/modules/perl')
+ if $build->{cwd};
+ }
+ }
+ my $extra_path = '';
+ $extra_path .= ";$ap_bindir" if $ap_bindir;
+ $extra_path .= ";$modperl_libexecdir" if $modperl_libexecdir;
+ $preamble = <<EOF;
+PATH = \$(PATH)$extra_path
+EOF
+ }
+ else {
+ # PASSENV confuses the Win32 command-line build
+ my $env = Apache::TestConfig->passenv_makestr();
+ $preamble = <<EOF;
+PASSENV = $env
+EOF
+ }
+
+ $preamble .= <<'EOF';
+TEST_VERBOSE = 0
+TEST_FILES =
+
+test_clean :
+ $(FULLPERL) -I$(INST_ARCHLIB) -I$(INST_LIB) \
+ t/TEST -clean
+
+run_tests : test_clean
+ $(PASSENV) \
+ $(FULLPERL) -I$(INST_ARCHLIB) -I$(INST_LIB) \
+ t/TEST -bugreport -verbose=$(TEST_VERBOSE) $(TEST_FILES)
+
+run_subtests ::
+ cd ModPerl-Registry && $(MAKE) test
+
+run_subtests ::
+ cd Apache-Reload && $(MAKE) test
+
+EOF
+
+ $preamble .= <<'EOF' unless $build->mpm_is_threaded();
+run_subtests ::
+ cd Apache-SizeLimit && $(MAKE) test
+
+EOF
+
+ $preamble .= <<'EOF';
+test :: pure_all run_tests run_subtests
+EOF
+
+ return $preamble;
+}
+
+sub MY::postamble {
+ my $self = shift;
+
+ my $string = $self->ModPerl::BuildMM::MY::postamble;
+
+ if (!WIN32) {
+ $string .= <<'EOF';
+rpm: dist
+ @[ -d $(PWD)/rpm ] || mkdir $(PWD)/rpm
+ rpmbuild -ta --define "_rpmdir $(PWD)/rpm" \
+ --define "_srcrpmdir $(PWD)/rpm" \
+ $(DISTVNAME).tar.gz
+ @mv $(PWD)/rpm/*/*.rpm $(PWD)/rpm/
+ @rm -rf $(PWD)/rpm/*/
+
+EOF
+ }
+
+ my $q = (WIN32 ? '"' : "'");
+
+ $string .= <<"EOF";
+mydist : Apache-Test/META.yml mod_perl.spec manifest tardist
+
+mod_perl.spec: build/make_rpm_spec
+ \$(PERL) build/make_rpm_spec
+
+Apache-Test/META.yml:
+ cd Apache-Test && make metafile
+
+tag :
+ svn copy -m $q\$(VERSION_SYM) release branch$q https://svn.apache.org/repos/asf/perl/modperl/trunk https://svn.apache.org/repos/asf/perl/modperl/branches/release/\$(VERSION_SYM)
+ svn copy -m $q\$(VERSION_SYM) tag$q https://svn.apache.org/repos/asf/perl/modperl/branches/release/\$(VERSION_SYM) https://svn.apache.org/repos/asf/perl/modperl/tags/\$(VERSION_SYM)
+ svn copy -m $q\$(VERSION_SYM) tag$q https://svn.apache.org/repos/asf/perl/modperl/docs/trunk https://svn.apache.org/repos/asf/perl/modperl/docs/tags/\$(VERSION_SYM)
+EOF
+
+ return $string;
+}
+
+# this is a workaround so that ModPerl::MM will move MY::constants
+# away, and Apache-Test/Makefile.PL which has its own MY::constants
+# won't get complaints on MY::constants redefined
+sub MY::constants {
+ shift->ModPerl::BuildMM::MY::constants;
+}
+
+sub MY::tool_autosplit {
+ '';
+}
+
+sub MY::manifypods {
+ my $self = shift;
+ my $ver = $self->{VERSION} || "";
+ local $_ = $self->MM::manifypods(@_);
+ s/pod2man\s*$/pod2man --release mod_perl-$ver/m;
+ $_;
+}
+
+sub MY::pasthru {
+ my $self = shift;
+ chomp(my $str = $self->MM::pasthru);
+ join $/, "$str\\",
+ "\t".'PERL="$(PERL)"\\',
+ "\t".'DEFINE="$(DEFINE)"',
+ "";
+}
+
+sub MY::dist_basics {
+ my $self = shift;
+ my $str = $self->MM::dist_basics;
+
+ $str =~ s/(\"?)-MExtUtils(::Manifest=mkmanifest)/-Ilib $1-MModPerl$2/;
+
+ $str;
+}
diff --git a/2_0_13/ModPerl-Registry/MANIFEST b/2_0_13/ModPerl-Registry/MANIFEST
new file mode 100644
index 0000000..88a5ab6
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/MANIFEST
@@ -0,0 +1,19 @@
+MANIFEST This list of files
+Makefile.PL
+README
+TODO
+lib/ModPerl/PerlRun.pm
+lib/ModPerl/Registry.pm
+lib/ModPerl/RegistryBB.pm
+lib/ModPerl/RegistryCooker.pm
+t/TEST.PL
+t/basic.t
+t/closure.t
+t/cgi-bin/basic.pl
+t/cgi-bin/closure.pl
+t/cgi-bin/env.pl
+t/cgi-bin/local-conf.pl
+t/cgi-bin/not_executable.pl
+t/cgi-bin/require.pl
+t/conf/extra.conf.in
+
diff --git a/2_0_13/ModPerl-Registry/Makefile.PL b/2_0_13/ModPerl-Registry/Makefile.PL
new file mode 100644
index 0000000..0184b4c
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/Makefile.PL
@@ -0,0 +1,44 @@
+use strict;
+use warnings FATAL => 'all';
+no warnings 'redefine';
+
+use FindBin;
+use lib grep { -d } map "$FindBin::Bin/../$_", qw(lib Apache-Test/lib);
+
+use ModPerl::BuildMM ();
+use Apache::TestSmokePerl ();
+use Apache2::Build ();
+
+# enable 'make test|clean'
+use Apache::TestMM qw(test clean);
+
+# prerequisites
+my %require = (
+ "Apache::Test" => "0", # any version will do?
+);
+
+my @scripts = qw(t/TEST t/SMOKE);
+
+# accept the configs from comman line
+Apache::TestMM::filter_args();
+
+my $build = Apache2::Build->build_config;
+if ($build->should_build_apache) {
+ push @Apache::TestMM::Argv, ('httpd' => $build->{httpd});
+}
+Apache::TestMM::generate_script('t/TEST');
+
+# t/SMOKE
+Apache::TestSmokePerl->generate_script;
+
+ModPerl::BuildMM::WriteMakefile(
+ NAME => 'ModPerl::Registry',
+ VERSION_FROM => 'lib/ModPerl/RegistryCooker.pm',
+ PREREQ_PM => \%require,
+ clean => {
+ FILES => "@{ clean_files() }",
+ });
+
+sub clean_files {
+ return [@scripts, 'Makefile.old'];
+}
diff --git a/2_0_13/ModPerl-Registry/README b/2_0_13/ModPerl-Registry/README
new file mode 100644
index 0000000..a1ee07b
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/README
@@ -0,0 +1 @@
+to be written
diff --git a/2_0_13/ModPerl-Registry/TODO b/2_0_13/ModPerl-Registry/TODO
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/TODO
diff --git a/2_0_13/ModPerl-Registry/lib/ModPerl/PerlRun.pm b/2_0_13/ModPerl-Registry/lib/ModPerl/PerlRun.pm
new file mode 100644
index 0000000..9dc3ce9
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/lib/ModPerl/PerlRun.pm
@@ -0,0 +1,79 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+package ModPerl::PerlRun;
+
+use strict;
+use warnings FATAL => 'all';
+
+# we try to develop so we reload ourselves without die'ing on the warning
+no warnings qw(redefine); # XXX, this should go away in production!
+
+our $VERSION = '1.99';
+
+use base qw(ModPerl::RegistryCooker);
+
+sub handler : method {
+ my $class = (@_ >= 2) ? shift : __PACKAGE__;
+ my $r = shift;
+ return $class->new($r)->default_handler();
+}
+
+my $parent = 'ModPerl::RegistryCooker';
+# the following code:
+# - specifies package's behavior different from default of $parent class
+# - speeds things up by shortcutting @ISA search, so even if the
+# default is used we still use the alias
+my %aliases = (
+ new => 'new',
+ init => 'init',
+ default_handler => 'default_handler',
+ run => 'run',
+ can_compile => 'can_compile',
+ make_namespace => 'make_namespace',
+ namespace_root => 'namespace_root',
+ namespace_from => 'namespace_from_filename',
+ is_cached => 'FALSE',
+ should_compile => 'TRUE',
+ flush_namespace => 'flush_namespace_normal',
+ cache_table => 'cache_table_common',
+ cache_it => 'NOP',
+ read_script => 'read_script',
+ shebang_to_perl => 'shebang_to_perl',
+ get_script_name => 'get_script_name',
+ chdir_file => 'NOP',
+ get_mark_line => 'get_mark_line',
+ compile => 'compile',
+ error_check => 'error_check',
+ should_reset_inc_hash => 'TRUE',
+ strip_end_data_segment => 'strip_end_data_segment',
+ convert_script_to_compiled_handler => 'convert_script_to_compiled_handler',
+);
+
+# in this module, all the methods are inherited from the same parent
+# class, so we fixup aliases instead of using the source package in
+# first place.
+$aliases{$_} = $parent . "::" . $aliases{$_} for keys %aliases;
+
+__PACKAGE__->install_aliases(\%aliases);
+
+
+
+
+
+1;
+__END__
+
diff --git a/2_0_13/ModPerl-Registry/lib/ModPerl/PerlRunPrefork.pm b/2_0_13/ModPerl-Registry/lib/ModPerl/PerlRunPrefork.pm
new file mode 100644
index 0000000..445e599
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/lib/ModPerl/PerlRunPrefork.pm
@@ -0,0 +1,26 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+package ModPerl::PerlRunPrefork;
+
+use strict;
+use warnings FATAL => 'all';
+
+our $VERSION = '0.01';
+
+use base qw(ModPerl::PerlRun);
+
+if ($ENV{MOD_PERL}) {
+ require Apache2::MPM;
+ die "This package can't be used under threaded MPMs"
+ if Apache2::MPM->is_threaded;
+}
+
+sub handler : method {
+ my $class = (@_ >= 2) ? shift : __PACKAGE__;
+ my $r = shift;
+ return $class->new($r)->default_handler();
+}
+
+*chdir_file = \&ModPerl::RegistryCooker::chdir_file_normal;
+
+1;
+__END__
diff --git a/2_0_13/ModPerl-Registry/lib/ModPerl/Registry.pm b/2_0_13/ModPerl-Registry/lib/ModPerl/Registry.pm
new file mode 100644
index 0000000..9d7904e
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/lib/ModPerl/Registry.pm
@@ -0,0 +1,85 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+package ModPerl::Registry;
+
+use strict;
+use warnings FATAL => 'all';
+
+# we try to develop so we reload ourselves without die'ing on the warning
+no warnings qw(redefine); # XXX, this should go away in production!
+
+our $VERSION = '1.99';
+
+use base qw(ModPerl::RegistryCooker);
+
+sub handler : method {
+ my $class = (@_ >= 2) ? shift : __PACKAGE__;
+ my $r = shift;
+ return $class->new($r)->default_handler();
+}
+
+my $parent = 'ModPerl::RegistryCooker';
+# the following code:
+# - specifies package's behavior different from default of $parent class
+# - speeds things up by shortcutting @ISA search, so even if the
+# default is used we still use the alias
+my %aliases = (
+ new => 'new',
+ init => 'init',
+ default_handler => 'default_handler',
+ run => 'run',
+ can_compile => 'can_compile',
+ make_namespace => 'make_namespace',
+ namespace_root => 'namespace_root',
+ namespace_from => 'namespace_from_filename',
+ is_cached => 'is_cached',
+ should_compile => 'should_compile_if_modified',
+ flush_namespace => 'NOP',
+ cache_table => 'cache_table_common',
+ cache_it => 'cache_it',
+ read_script => 'read_script',
+ shebang_to_perl => 'shebang_to_perl',
+ get_script_name => 'get_script_name',
+ chdir_file => 'NOP',
+ get_mark_line => 'get_mark_line',
+ compile => 'compile',
+ error_check => 'error_check',
+ strip_end_data_segment => 'strip_end_data_segment',
+ convert_script_to_compiled_handler => 'convert_script_to_compiled_handler',
+);
+
+# in this module, all the methods are inherited from the same parent
+# class, so we fixup aliases instead of using the source package in
+# first place.
+$aliases{$_} = $parent . "::" . $aliases{$_} for keys %aliases;
+
+__PACKAGE__->install_aliases(\%aliases);
+
+# Note that you don't have to do the aliases if you use defaults, it
+# just speeds things up the first time the sub runs, after that
+# methods are cached.
+#
+# But it's still handy, since you explicitly specify which subs from
+# the parent package you are using
+#
+
+# META: if the ISA search results are cached on the first lookup, may
+# be we need to alias only those methods that override the defaults?
+
+
+1;
+__END__
diff --git a/2_0_13/ModPerl-Registry/lib/ModPerl/RegistryBB.pm b/2_0_13/ModPerl-Registry/lib/ModPerl/RegistryBB.pm
new file mode 100644
index 0000000..d3667a8
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/lib/ModPerl/RegistryBB.pm
@@ -0,0 +1,40 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+package ModPerl::RegistryBB;
+
+use strict;
+use warnings FATAL => 'all';
+
+# we try to develop so we reload ourselves without die'ing on the warning
+no warnings qw(redefine); # XXX, this should go away in production!
+
+our $VERSION = '1.99';
+
+use base qw(ModPerl::RegistryCooker);
+
+sub handler : method {
+ my $class = (@_ >= 2) ? shift : __PACKAGE__;
+ my $r = shift;
+ return $class->new($r)->default_handler();
+}
+
+# currently all the methods are inherited through the normal ISA
+# search may
+
+1;
+__END__
+
diff --git a/2_0_13/ModPerl-Registry/lib/ModPerl/RegistryCooker.pm b/2_0_13/ModPerl-Registry/lib/ModPerl/RegistryCooker.pm
new file mode 100644
index 0000000..cf50007
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/lib/ModPerl/RegistryCooker.pm
@@ -0,0 +1,788 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# VERY IMPORTANT: Be very careful modifying the defaults, since many
+# VERY IMPORTANT: packages rely on them. In fact you should never
+# VERY IMPORTANT: modify the defaults after the package gets released,
+# VERY IMPORTANT: since they are a hardcoded part of this suite's API.
+
+package ModPerl::RegistryCooker;
+
+require 5.006;
+
+use strict;
+use warnings FATAL => 'all';
+
+our $VERSION = '1.99';
+
+use Apache2::ServerUtil ();
+use Apache2::Response ();
+use Apache2::RequestRec ();
+use Apache2::RequestUtil ();
+use Apache2::RequestIO ();
+use Apache2::Log ();
+use Apache2::Access ();
+
+use APR::Table ();
+use APR::Finfo ();
+use APR::Status ();
+
+use ModPerl::Util ();
+use ModPerl::Global ();
+
+use File::Spec::Functions ();
+use File::Basename ();
+
+use Apache2::Const -compile => qw(:common &OPT_EXECCGI);
+use APR::Const -compile => qw(FILETYPE_REG);
+use ModPerl::Const -compile => 'EXIT';
+
+unless (defined $ModPerl::Registry::MarkLine) {
+ $ModPerl::Registry::MarkLine = 1;
+}
+
+#########################################################################
+# debug constants
+#
+#########################################################################
+use constant D_NONE => 0;
+use constant D_ERROR => 1;
+use constant D_WARN => 2;
+use constant D_COMPILE => 4;
+use constant D_NOISE => 8;
+
+# the debug level can be overriden on the main server level of
+# httpd.conf with:
+# PerlSetVar ModPerl::RegistryCooker::DEBUG 4
+use constant DEBUG => 0;
+#XXX: below currently crashes the server on win32
+# defined Apache2->server->dir_config('ModPerl::RegistryCooker::DEBUG')
+# ? Apache2->server->dir_config('ModPerl::RegistryCooker::DEBUG')
+# : D_NONE;
+
+#########################################################################
+# OS specific constants
+#
+#########################################################################
+use constant IS_WIN32 => $^O eq "MSWin32";
+
+#########################################################################
+# constant subs
+#
+#########################################################################
+use constant NOP => '';
+use constant TRUE => 1;
+use constant FALSE => 0;
+
+
+use constant NAMESPACE_ROOT => 'ModPerl::ROOT';
+
+
+#########################################################################
+
+unless (defined $ModPerl::RegistryCooker::NameWithVirtualHost) {
+ $ModPerl::RegistryCooker::NameWithVirtualHost = 1;
+}
+
+#########################################################################
+# func: new
+# dflt: new
+# args: $class - class to bless into
+# $r - Apache2::RequestRec object
+# desc: create the class's object and bless it
+# rtrn: the newly created object
+#########################################################################
+
+sub new {
+ my ($class, $r) = @_;
+ my $self = bless {}, $class;
+ $self->init($r);
+ return $self;
+}
+
+#########################################################################
+# func: init
+# dflt: init
+# desc: initializes the data object's fields: REQ FILENAME URI
+# args: $r - Apache2::RequestRec object
+# rtrn: nothing
+#########################################################################
+
+sub init {
+ $_[0]->{REQ} = $_[1];
+ $_[0]->{URI} = $_[1]->uri;
+ $_[0]->{FILENAME} = $_[1]->filename;
+}
+
+#########################################################################
+# func: handler
+# dflt: handler
+# desc: the handler() sub that is expected by Apache
+# args: $class - handler's class
+# $r - Apache2::RequestRec object
+# (o)can be called as handler($r) as well (without leading $class)
+# rtrn: handler's response status
+# note: must be implemented in a sub-class unless configured as
+# Apache2::Foo->handler in httpd.conf (because of the
+# __PACKAGE__, which is tied to the file)
+#########################################################################
+
+sub handler : method {
+ my $class = (@_ >= 2) ? shift : __PACKAGE__;
+ my $r = shift;
+ return $class->new($r)->default_handler();
+}
+
+#########################################################################
+# func: default_handler
+# dflt: META: see above
+# desc: META: see above
+# args: $self - registry blessed object
+# rtrn: handler's response status
+# note: that's what most sub-class handlers will call
+#########################################################################
+
+sub default_handler {
+ my $self = shift;
+
+ $self->make_namespace;
+
+ if ($self->should_compile) {
+ my $rc = $self->can_compile;
+ return $rc unless $rc == Apache2::Const::OK;
+ $rc = $self->convert_script_to_compiled_handler;
+ return $rc unless $rc == Apache2::Const::OK;
+ }
+
+ # handlers shouldn't set $r->status but return it, so we reset the
+ # status after running it
+ my $old_status = $self->{REQ}->status;
+ my $rc = $self->run;
+ my $new_status = $self->{REQ}->status($old_status);
+ return ($rc == Apache2::Const::OK && $old_status != $new_status)
+ ? $new_status
+ : $rc;
+}
+
+#########################################################################
+# func: run
+# dflt: run
+# desc: executes the compiled code
+# args: $self - registry blessed object
+# rtrn: execution status (Apache2::?)
+#########################################################################
+
+sub run {
+ my $self = shift;
+
+ my $r = $self->{REQ};
+ my $package = $self->{PACKAGE};
+
+ $self->chdir_file;
+
+ my $cv = \&{"$package\::handler"};
+
+ my %orig_inc;
+ if ($self->should_reset_inc_hash) {
+ %orig_inc = %INC;
+ }
+
+ my $rc = Apache2::Const::OK;
+ { # run the code and preserve warnings setup when it's done
+ no warnings FATAL => 'all';
+ #local $^W = 0;
+ eval { $cv->($r, @_) };
+
+ # log script's execution errors
+ $rc = $self->error_check;
+
+ {
+ # there might be no END blocks to call, so $@ will be not
+ # reset
+ local $@;
+ ModPerl::Global::special_list_call(END => $package);
+
+ # log script's END blocks execution errors
+ my $new_rc = $self->error_check;
+
+ # use the END blocks return status if the script's execution
+ # was successful
+ $rc = $new_rc if $rc == Apache2::Const::OK;
+ }
+
+ }
+
+ if ($self->should_reset_inc_hash) {
+ # to avoid the bite of require'ing a file with no package delaration
+ # Apache2::PerlRun in mod_perl 1.15_01 started to localize %INC
+ # later on it has been adjusted to preserve loaded .pm files,
+ # which presumably contained the package declaration
+ for (keys %INC) {
+ next if $orig_inc{$_};
+ next if /\.pm$/;
+ delete $INC{$_};
+ }
+ }
+
+ $self->flush_namespace;
+
+ $self->chdir_file(Apache2::ServerUtil::server_root());
+
+ return $rc;
+}
+
+
+
+#########################################################################
+# func: can_compile
+# dflt: can_compile
+# desc: checks whether the script is allowed and can be compiled
+# args: $self - registry blessed object
+# rtrn: $rc - return status to forward
+# efct: initializes the data object's fields: MTIME
+#########################################################################
+
+sub can_compile {
+ my $self = shift;
+ my $r = $self->{REQ};
+
+ return Apache2::Const::DECLINED
+ unless $r->finfo->filetype==APR::Const::FILETYPE_REG;
+
+ $self->{MTIME} = $r->finfo->mtime;
+
+ if (!($r->allow_options & Apache2::Const::OPT_EXECCGI)) {
+ $r->log_error("Options ExecCGI is off in this directory",
+ $self->{FILENAME});
+ return Apache2::Const::FORBIDDEN;
+ }
+
+ $self->debug("can compile $self->{FILENAME}") if DEBUG & D_NOISE;
+
+ return Apache2::Const::OK;
+
+}
+#########################################################################
+# func: namespace_root
+# dflt: namespace_root
+# desc: define the namespace root for storing compiled scripts
+# args: $self - registry blessed object
+# rtrn: the namespace root
+#########################################################################
+
+sub namespace_root {
+ my $self = shift;
+ join '::', NAMESPACE_ROOT, ref($self);
+}
+
+#########################################################################
+# func: make_namespace
+# dflt: make_namespace
+# desc: prepares the namespace
+# args: $self - registry blessed object
+# rtrn: the namespace
+# efct: initializes the field: PACKAGE
+#########################################################################
+
+sub make_namespace {
+ my $self = shift;
+
+ my $package = $self->namespace_from;
+
+ # Escape everything into valid perl identifiers
+ $package =~ s/([^A-Za-z0-9_])/sprintf("_%2x", unpack("C", $1))/eg;
+
+ # make sure that the sub-package doesn't start with a digit
+ $package =~ s/^(\d)/_$1/;
+
+ # prepend root
+ $package = $self->namespace_root() . "::$package";
+
+ $self->{PACKAGE} = $package;
+
+ return $package;
+}
+
+#########################################################################
+# func: namespace_from
+# dflt: namespace_from_filename
+# desc: returns a partial raw package name based on filename, uri, else
+# args: $self - registry blessed object
+# rtrn: a unique string
+#########################################################################
+
+*namespace_from = \&namespace_from_filename;
+
+# return a package name based on $r->filename only
+sub namespace_from_filename {
+ my $self = shift;
+
+ my ($volume, $dirs, $file) =
+ File::Spec::Functions::splitpath($self->{FILENAME});
+ my @dirs = File::Spec::Functions::splitdir($dirs);
+ return join '_', grep { defined && length } $volume, @dirs, $file;
+}
+
+# return a package name based on $r->uri only
+sub namespace_from_uri {
+ my $self = shift;
+
+ my $path_info = $self->{REQ}->path_info;
+ my $script_name = $path_info && $self->{URI} =~ /\Q$path_info\E$/
+ ? substr($self->{URI}, 0, length($self->{URI}) - length($path_info))
+ : $self->{URI};
+
+ if ($ModPerl::RegistryCooker::NameWithVirtualHost &&
+ $self->{REQ}->server->is_virtual) {
+ my $name = $self->{REQ}->get_server_name;
+ $script_name = join "", $name, $script_name if $name;
+ }
+
+ $script_name =~ s:/+$:/__INDEX__:;
+
+ return $script_name;
+}
+
+#########################################################################
+# func: convert_script_to_compiled_handler
+# dflt: convert_script_to_compiled_handler
+# desc: reads the script, converts into a handler and compiles it
+# args: $self - registry blessed object
+# rtrn: success/failure status
+#########################################################################
+
+sub convert_script_to_compiled_handler {
+ my $self = shift;
+
+ my $rc = Apache2::Const::OK;
+
+ $self->debug("Adding package $self->{PACKAGE}") if DEBUG & D_NOISE;
+
+ # get the script's source
+ $rc = $self->read_script;
+ return $rc unless $rc == Apache2::Const::OK;
+
+ # convert the shebang line opts into perl code
+ my $shebang = $self->shebang_to_perl;
+
+ # mod_cgi compat, should compile the code while in its dir, so
+ # relative require/open will work.
+ $self->chdir_file;
+
+# undef &{"$self->{PACKAGE}\::handler"}; unless DEBUG & D_NOISE; #avoid warnings
+# $self->{PACKAGE}->can('undef_functions') && $self->{PACKAGE}->undef_functions;
+
+ my $line = $self->get_mark_line;
+
+ $self->strip_end_data_segment;
+
+ # handle the non-parsed handlers ala mod_cgi (though mod_cgi does
+ # some tricks removing the header_out and other filters, here we
+ # just call assbackwards which has the same effect).
+ my $base = File::Basename::basename($self->{FILENAME});
+ my $nph = substr($base, 0, 4) eq 'nph-' ? '$_[0]->assbackwards(1);' : "";
+ my $script_name = $self->get_script_name || $0;
+
+ my $eval = join '',
+ 'package ',
+ $self->{PACKAGE}, ";",
+ "sub handler {",
+ "local \$0 = '$script_name';",
+ $nph,
+ $shebang,
+ $line,
+ ${ $self->{CODE} },
+ "\n}"; # last line comment without newline?
+
+ $rc = $self->compile(\$eval);
+ return $rc unless $rc == Apache2::Const::OK;
+ $self->debug(qq{compiled package \"$self->{PACKAGE}\"}) if DEBUG & D_NOISE;
+
+ $self->chdir_file(Apache2::ServerUtil::server_root());
+
+# if(my $opt = $r->dir_config("PerlRunOnce")) {
+# $r->child_terminate if lc($opt) eq "on";
+# }
+
+ $self->cache_it;
+
+ return $rc;
+}
+
+#########################################################################
+# func: cache_table
+# dflt: cache_table_common
+# desc: return a symbol table for caching compiled scripts in
+# args: $self - registry blessed object (or the class name)
+# rtrn: symbol table
+#########################################################################
+
+*cache_table = \&cache_table_common;
+
+sub cache_table_common {
+ \%ModPerl::RegistryCache;
+}
+
+
+sub cache_table_local {
+ my $self = shift;
+ my $class = ref($self) || $self;
+ no strict 'refs';
+ \%$class;
+}
+
+#########################################################################
+# func: cache_it
+# dflt: cache_it
+# desc: mark the package as cached by storing its modification time
+# args: $self - registry blessed object
+# rtrn: nothing
+#########################################################################
+
+sub cache_it {
+ my $self = shift;
+ $self->cache_table->{ $self->{PACKAGE} }{mtime} = $self->{MTIME};
+}
+
+
+#########################################################################
+# func: is_cached
+# dflt: is_cached
+# desc: checks whether the package is already cached
+# args: $self - registry blessed object
+# rtrn: TRUE if cached,
+# FALSE otherwise
+#########################################################################
+
+sub is_cached {
+ my $self = shift;
+ exists $self->cache_table->{ $self->{PACKAGE} }{mtime};
+}
+
+
+#########################################################################
+# func: should_compile
+# dflt: should_compile_once
+# desc: decide whether code should be compiled or not
+# args: $self - registry blessed object
+# rtrn: TRUE if should compile
+# FALSE otherwise
+# efct: sets MTIME if it's not set yet
+#########################################################################
+
+*should_compile = \&should_compile_once;
+
+# return false only if the package is cached and its source file
+# wasn't modified
+sub should_compile_if_modified {
+ my $self = shift;
+ $self->{MTIME} ||= $self->{REQ}->finfo->mtime;
+ !($self->is_cached &&
+ $self->cache_table->{ $self->{PACKAGE} }{mtime} == $self->{MTIME});
+}
+
+# return false if the package is cached already
+sub should_compile_once {
+ not shift->is_cached;
+}
+
+#########################################################################
+# func: should_reset_inc_hash
+# dflt: FALSE
+# desc: decide whether to localize %INC for required .pl files from the script
+# args: $self - registry blessed object
+# rtrn: TRUE if should reset
+# FALSE otherwise
+#########################################################################
+
+*should_reset_inc_hash = \&FALSE;
+
+#########################################################################
+# func: flush_namespace
+# dflt: NOP (don't flush)
+# desc: flush the compiled package's namespace
+# args: $self - registry blessed object
+# rtrn: nothing
+#########################################################################
+
+*flush_namespace = \&NOP;
+
+sub flush_namespace_normal {
+ my $self = shift;
+
+ $self->debug("flushing namespace") if DEBUG & D_NOISE;
+ ModPerl::Util::unload_package($self->{PACKAGE});
+}
+
+
+#########################################################################
+# func: read_script
+# dflt: read_script
+# desc: reads the script in
+# args: $self - registry blessed object
+# rtrn: Apache2::Const::OK on success, some other code on failure
+# efct: initializes the CODE field with the source script
+#########################################################################
+
+# reads the contents of the file
+sub read_script {
+ my $self = shift;
+
+ $self->debug("reading $self->{FILENAME}") if DEBUG & D_NOISE;
+ $self->{CODE} = eval { $self->{REQ}->slurp_filename(0) }; # untainted
+ if ($@) {
+ $self->log_error("$@");
+
+ if (ref $@ eq 'APR::Error') {
+ return Apache2::Const::FORBIDDEN if APR::Status::is_EACCES($@);
+ return Apache2::Const::NOT_FOUND if APR::Status::is_ENOENT($@);
+ }
+
+ return Apache2::Const::SERVER_ERROR;
+ }
+
+ return Apache2::Const::OK;
+}
+
+#########################################################################
+# func: shebang_to_perl
+# dflt: shebang_to_perl
+# desc: parse the shebang line and convert command line switches
+# (defined in %switches) into a perl code.
+# args: $self - registry blessed object
+# rtrn: a Perl snippet to be put at the beginning of the CODE field
+# by caller
+#########################################################################
+
+my %switches = (
+ 'T' => sub {
+ Apache2::ServerRec::warn("-T switch is ignored, enable " .
+ "with 'PerlSwitches -T' in httpd.conf\n")
+ unless ${^TAINT};
+ "";
+ },
+ 'w' => sub { "use warnings;\n" },
+);
+
+sub shebang_to_perl {
+ my $self = shift;
+ my ($line) = ${ $self->{CODE} } =~ /^(.*)$/m;
+ my @cmdline = split /\s+/, $line;
+ return "" unless @cmdline;
+ return "" unless shift(@cmdline) =~ /^\#!/;
+
+ my $prepend = "";
+ for my $s (@cmdline) {
+ next unless $s =~ s/^-//;
+ last if substr($s,0,1) eq "-";
+ for (split //, $s) {
+ next unless exists $switches{$_};
+ $prepend .= $switches{$_}->();
+ }
+ }
+
+ return $prepend;
+}
+
+#########################################################################
+# func: get_script_name
+# dflt: get_script_name
+# desc: get the script's name to set into $0
+# args: $self - registry blessed object
+# rtrn: path to the script's filename
+#########################################################################
+
+sub get_script_name {
+ shift->{FILENAME};
+}
+
+#########################################################################
+# func: chdir_file
+# dflt: NOP
+# desc: chdirs into $dir
+# args: $self - registry blessed object
+# $dir - a dir
+# rtrn: nothing (?or success/failure?)
+#########################################################################
+
+*chdir_file = \&NOP;
+
+sub chdir_file_normal {
+ my ($self, $dir) = @_;
+ $dir ||= File::Basename::dirname($self->{FILENAME});
+ $self->debug("chdir $dir") if DEBUG & D_NOISE;
+ chdir $dir or die "Can't chdir to $dir: $!";
+}
+
+#########################################################################
+# func: get_mark_line
+# dflt: get_mark_line
+# desc: generates the perl compiler #line directive
+# args: $self - registry blessed object
+# rtrn: returns the perl compiler #line directive
+#########################################################################
+
+sub get_mark_line {
+ my $self = shift;
+ $ModPerl::Registry::MarkLine ? "\n#line 1 $self->{FILENAME}\n" : "";
+}
+
+#########################################################################
+# func: strip_end_data_segment
+# dflt: strip_end_data_segment
+# desc: remove the trailing non-code from $self->{CODE}
+# args: $self - registry blessed object
+# rtrn: nothing
+#########################################################################
+
+sub strip_end_data_segment {
+ ${ +shift->{CODE} } =~ s/^__(END|DATA)__(.*)//ms;
+}
+
+
+
+#########################################################################
+# func: compile
+# dflt: compile
+# desc: compile the code in $eval
+# args: $self - registry blessed object
+# $eval - a ref to a scalar with the code to compile
+# rtrn: success/failure
+# note: $r must not be in scope of compile(), scripts must do
+# my $r = shift; to get it off the args stack
+#########################################################################
+
+sub compile {
+ my ($self, $eval) = @_;
+
+ $self->debug("compiling $self->{FILENAME}") if DEBUG && D_COMPILE;
+
+ ModPerl::Global::special_list_register(END => $self->{PACKAGE});
+ ModPerl::Global::special_list_clear( END => $self->{PACKAGE});
+
+ {
+ # let the code define its own warn and strict level
+ no strict;
+ no warnings FATAL => 'all'; # because we use FATAL
+ eval $$eval;
+ }
+
+ return $self->error_check;
+}
+
+#########################################################################
+# func: error_check
+# dflt: error_check
+# desc: checks $@ for errors
+# args: $self - registry blessed object
+# rtrn: Apache2::Const::SERVER_ERROR if $@ is set, Apache2::Const::OK otherwise
+#########################################################################
+
+sub error_check {
+ my $self = shift;
+
+ # ModPerl::Util::exit() throws an exception object whose rc is
+ # ModPerl::EXIT
+ # (see modperl_perl_exit() and modperl_errsv() C functions)
+ if ($@ && !(ref $@ eq 'APR::Error' && $@ == ModPerl::EXIT)) {
+ $self->log_error($@);
+ return Apache2::Const::SERVER_ERROR;
+ }
+ return Apache2::Const::OK;
+}
+
+
+#########################################################################
+# func: install_aliases
+# dflt: install_aliases
+# desc: install the method aliases into $class
+# args: $class - the class to install the methods into
+# $rh_aliases - a ref to a hash with aliases mapping
+# rtrn: nothing
+#########################################################################
+
+sub install_aliases {
+ my ($class, $rh_aliases) = @_;
+
+ no strict 'refs';
+ while (my ($k,$v) = each %$rh_aliases) {
+ if (my $sub = *{$v}{CODE}){
+ *{ $class . "::$k" } = $sub;
+ }
+ else {
+ die "$class: $k aliasing failed; sub $v doesn't exist";
+ }
+ }
+}
+
+### helper methods
+
+sub debug {
+ my $self = shift;
+ my $class = ref $self;
+ $self->{REQ}->log_error("$$: $class: " . join '', @_);
+}
+
+sub log_error {
+ my ($self, $msg) = @_;
+ my $class = ref $self;
+
+ $self->{REQ}->log_error($msg);
+ $self->{REQ}->notes->set('error-notes' => $msg);
+ $@{$self->{URI}} = $msg;
+}
+
+#########################################################################
+# func: uncache_myself
+# dflt: uncache_myself
+# desc: unmark the package as cached by forgetting its modification time
+# args: none
+# rtrn: nothing
+# note: this is a function and not a method, it should be called from
+# the registry script, and using the caller() method we figure
+# out the package the script was compiled into
+
+#########################################################################
+
+# this is a function should be called from the registry script, and
+# using the caller() method we figure out the package the script was
+# compiled into and trying to uncache it.
+#
+# it's currently used only for testing purposes and not a part of the
+# public interface. it expects to find the compiled package in the
+# symbol table cache returned by cache_table_common(), if you override
+# cache_table() to point to another function, this function will fail.
+sub uncache_myself {
+ my $package = scalar caller;
+ my ($class) = __PACKAGE__->cache_table_common();
+
+ unless (defined $class) {
+ Apache2->warn("$$: cannot figure out cache symbol table for $package");
+ return;
+ }
+
+ if (exists $class->{$package} && exists $class->{$package}{mtime}) {
+ Apache2->warn("$$: uncaching $package\n") if DEBUG & D_COMPILE;
+ delete $class->{$package}{mtime};
+ }
+ else {
+ Apache2->warn("$$: cannot find $package in cache");
+ }
+}
+
+
+1;
+__END__
diff --git a/2_0_13/ModPerl-Registry/lib/ModPerl/RegistryLoader.pm b/2_0_13/ModPerl-Registry/lib/ModPerl/RegistryLoader.pm
new file mode 100644
index 0000000..5f03c94
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/lib/ModPerl/RegistryLoader.pm
@@ -0,0 +1,168 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+package ModPerl::RegistryLoader;
+
+use strict;
+use warnings;
+
+use ModPerl::RegistryCooker ();
+use Apache2::ServerUtil ();
+use Apache2::Log ();
+use APR::Pool ();
+use APR::Finfo ();
+use APR::Const -compile=>qw(FINFO_MIN);
+
+use Carp;
+use File::Spec ();
+
+use Apache2::Const -compile => qw(OK HTTP_OK OPT_EXECCGI);
+
+our @ISA = ();
+
+sub new {
+ my $class = shift;
+ my $self = bless {@_} => ref($class)||$class;
+ $self->{package} ||= 'ModPerl::Registry';
+ $self->{pool} = APR::Pool->new();
+ $self->load_package($self->{package});
+ return $self;
+}
+
+sub handler {
+ my ($self, $uri, $filename, $virthost) = @_;
+
+ # set the inheritance rules at run time
+ @ISA = $self->{package};
+
+ unless (defined $uri) {
+ $self->warn("uri is a required argument");
+ return;
+ }
+
+ if (defined $filename) {
+ unless (-e $filename) {
+ $self->warn("Cannot find: $filename");
+ return;
+ }
+ }
+ else {
+ # try to translate URI->filename
+ if (exists $self->{trans} and ref($self->{trans}) eq 'CODE') {
+ no strict 'refs';
+ $filename = $self->{trans}->($uri);
+ unless (-e $filename) {
+ $self->warn("Cannot find a translated from uri: $filename");
+ return;
+ }
+ }
+ else {
+ # try to guess
+ (my $guess = $uri) =~ s|^/||;
+
+ $self->warn("Trying to guess filename based on uri")
+ if $self->{debug};
+
+ $filename = File::Spec->catfile(Apache2::ServerUtil::server_root,
+ $guess);
+ unless (-e $filename) {
+ $self->warn("Cannot find guessed file: $filename",
+ "provide \$filename or 'trans' sub");
+ return;
+ }
+ }
+ }
+
+ if ($self->{debug}) {
+ $self->warn("*** uri=$uri, filename=$filename");
+ }
+
+ my $rl = bless {
+ uri => $uri,
+ filename => $filename,
+ package => $self->{package},
+ } => ref($self) || $self;
+
+ $rl->{virthost} = $virthost if defined $virthost;
+
+ # can't call SUPER::handler here, because it usually calls new()
+ # and then the ModPerlRegistryLoader::new() will get called,
+ # instead of the super class' new, so we implement the super
+ # class' handler here. Hopefully all other subclasses use the same
+ # handler.
+ __PACKAGE__->SUPER::new($rl)->default_handler();
+
+}
+
+# XXX: s/my_// for qw(my_finfo my_slurp_filename);
+# when when finfo() and slurp_filename() are ported to 2.0 and
+# RegistryCooker is starting to use them
+
+sub get_server_name { return $_[0]->{virthost} if exists $_[0]->{virthost} }
+sub filename { shift->{filename} }
+sub status { Apache2::Const::HTTP_OK }
+sub pool { shift->{pool}||=APR::Pool->new() }
+sub finfo { $_[0]->{finfo}||=APR::Finfo::stat($_[0]->{filename},
+ APR::Const::FINFO_MIN,
+ $_[0]->pool); }
+sub uri { shift->{uri} }
+sub path_info {}
+sub allow_options { Apache2::Const::OPT_EXECCGI } #will be checked again at run-time
+sub log_error { shift; die @_ if $@; warn @_; }
+sub run { return Apache2::Const::OK } # don't run the script
+sub server { shift }
+sub is_virtual { exists shift->{virthost} }
+
+# the preloaded file needs to be precompiled into the package
+# specified by the 'package' attribute, not RegistryLoader
+sub namespace_root {
+ join '::', ModPerl::RegistryCooker::NAMESPACE_ROOT,
+ shift->{REQ}->{package};
+}
+
+# override Apache class methods called by Modperl::Registry*. normally
+# only available at request-time via blessed request_rec pointer
+sub slurp_filename {
+ my $r = shift;
+ my $tainted = @_ ? shift : 1;
+ my $filename = $r->filename;
+ open my $fh, $filename or die "can't open $filename: $!";
+ local $/;
+ my $code = <$fh>;
+ unless ($tainted) {
+ ($code) = $code =~ /(.*)/s; # untaint
+ }
+ close $fh;
+ return \$code;
+}
+
+sub load_package {
+ my ($self, $package) = @_;
+
+ croak "package to load wasn't specified" unless defined $package;
+
+ $package =~ s|::|/|g;
+ $package .= ".pm";
+ require $package;
+};
+
+sub warn {
+ my $self = shift;
+ Apache2::Log->warn(__PACKAGE__ . ": @_\n");
+}
+
+1;
+__END__
diff --git a/2_0_13/ModPerl-Registry/lib/ModPerl/RegistryPrefork.pm b/2_0_13/ModPerl-Registry/lib/ModPerl/RegistryPrefork.pm
new file mode 100644
index 0000000..9c41e77
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/lib/ModPerl/RegistryPrefork.pm
@@ -0,0 +1,26 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+package ModPerl::RegistryPrefork;
+
+use strict;
+use warnings FATAL => 'all';
+
+our $VERSION = '0.01';
+
+use base qw(ModPerl::Registry);
+
+if ($ENV{MOD_PERL}) {
+ require Apache2::MPM;
+ die "This package can't be used under threaded MPMs"
+ if Apache2::MPM->is_threaded;
+}
+
+sub handler : method {
+ my $class = (@_ >= 2) ? shift : __PACKAGE__;
+ my $r = shift;
+ return $class->new($r)->default_handler();
+}
+
+*chdir_file = \&ModPerl::RegistryCooker::chdir_file_normal;
+
+1;
+__END__
diff --git a/2_0_13/ModPerl-Registry/t/206.t b/2_0_13/ModPerl-Registry/t/206.t
new file mode 100644
index 0000000..7b72728
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/206.t
@@ -0,0 +1,25 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+use strict;
+use warnings FATAL => 'all';
+
+use Apache::Test;
+use Apache::TestUtil;
+use Apache::TestRequest qw(GET);
+
+plan tests => 2, need [qw(mod_alias.c HTML::HeadParser)];
+
+my $url = "/registry/206.pl";
+my $res = GET($url);
+my $body = '<?xml versi';
+
+ok t_cmp(
+ $res->code,
+ 206,
+ "test partial_content: response code",
+);
+
+ok t_cmp(
+ $res->content,
+ $body,
+ "test partial_content: response body",
+);
diff --git a/2_0_13/ModPerl-Registry/t/304.t b/2_0_13/ModPerl-Registry/t/304.t
new file mode 100644
index 0000000..dda87c9
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/304.t
@@ -0,0 +1,63 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+use strict;
+use warnings FATAL => 'all';
+
+use Apache::Test;
+use Apache::TestUtil;
+use Apache::TestRequest qw(GET);
+
+plan tests => 10, need [qw(mod_alias.c HTML::HeadParser)];
+
+my $url = "/registry/304.pl";
+
+{
+ # not modified
+ my $if_modified_since = 'Sun, 29 Oct 2000 15:55:00 GMT';
+ my $res = GET($url, 'If-Modified-Since' => $if_modified_since);
+
+ ok t_cmp(
+ $res->code,
+ 304,
+ "test HTTP_NOT_MODIFIED (304 status)",
+ );
+
+ ok t_cmp(
+ $res->content,
+ '',
+ "test HTTP_NOT_MODIFIED (null body)",
+ );
+
+ #t_debug $res->as_string;
+}
+
+{
+ # full response cases:
+ # 1) the resource has been modified since the If-Modified-Since date
+ # 2) bogus If-Modified-Since date => is considered as a
+ # non-If-Modified-Since require
+ #
+ my %dates = (
+ 'Sun, 29 Oct 2000 15:43:28 GMT' => "the resource was modified since #1",
+ 'Sun, 28 Oct 2000 15:43:29 GMT' => "the resource was modified since #2",
+ 'Thu, 32 Jun 1999 24:59:59 MIT' => "bogus If-Modified-Since #1",
+ 'Thu Juk 99 00:00:00 9999 FUK' => "bogus If-Modified-Since #2",
+ );
+ my $received = '<html><head></head><body>Test</body></html>';
+ while ( my ($if_modified_since, $debug) = each %dates) {
+ my $res = GET($url, 'If-Modified-Since' => $if_modified_since);
+ t_debug "If-Modified-Since $if_modified_since";
+ ok t_cmp(
+ $res->code,
+ 200,
+ "$debug (code)"
+ );
+
+ ok t_cmp(
+ $res->content,
+ $received,
+ "$debug (body)"
+ );
+
+ #t_debug $res->as_string;
+ }
+}
diff --git a/2_0_13/ModPerl-Registry/t/404-filename-with-newline.t b/2_0_13/ModPerl-Registry/t/404-filename-with-newline.t
new file mode 100644
index 0000000..f28710b
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/404-filename-with-newline.t
@@ -0,0 +1,20 @@
+#!perl
+
+use strict;
+use warnings FATAL => 'all';
+
+use Apache::Test;
+use Apache::TestUtil;
+use Apache::TestRequest qw(GET_RC);
+
+plan tests => 1, need 'mod_alias.c';
+
+{
+ # this used to result in 500 due to a combination of Perl warning about
+ # a newline in the filename passed to stat() and our
+ # use warnings FATAL=>'all'
+
+ t_client_log_error_is_expected();
+ my $url = '/registry/file%0dwith%0anl%0d%0aand%0a%0dcr';
+ ok t_cmp GET_RC($url), 404, 'URL with \\r and \\n embedded';
+}
diff --git a/2_0_13/ModPerl-Registry/t/404.t b/2_0_13/ModPerl-Registry/t/404.t
new file mode 100644
index 0000000..4b4271a
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/404.t
@@ -0,0 +1,31 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+use strict;
+use warnings FATAL => 'all';
+
+use Apache::Test;
+use Apache::TestUtil;
+use Apache::TestRequest qw(GET_BODY GET);
+
+plan tests => 2, need [qw(mod_alias.c HTML::HeadParser)];
+
+{
+ t_client_log_error_is_expected();
+ my $url = "/error_document/cannot_be_found";
+ my $response = "Oops, can't find the requested doc";
+ ok t_cmp(
+ GET_BODY($url),
+ $response,
+ "test ErrorDocument"
+ );
+}
+
+
+{
+ my $url = "/registry/status_change.pl";
+ my $res = GET($url);
+ ok t_cmp(
+ $res->code,
+ 404,
+ "the script has changed the status to 404"
+ );
+}
diff --git a/2_0_13/ModPerl-Registry/t/500.t b/2_0_13/ModPerl-Registry/t/500.t
new file mode 100644
index 0000000..a96e97f
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/500.t
@@ -0,0 +1,91 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+use strict;
+use warnings FATAL => 'all';
+
+use Apache::Test;
+use Apache::TestUtil;
+use Apache::TestRequest qw(GET);
+
+plan tests => 7, need 'mod_alias.c';
+
+{
+ # the script changes the status before the run-time error happens,
+ # this status change should be ignored
+ my $url = "/registry/runtime_error_n_status_change.pl";
+ my $res = GET($url);
+ #t_debug($res->content);
+ ok t_cmp(
+ $res->code,
+ 500,
+ "500 error on runtime error (when the script changes the status)",
+ );
+}
+
+{
+ my $url = "/registry/syntax_error.pl";
+ my $res = GET($url);
+ #t_debug($res->content);
+ ok t_cmp(
+ $res->code,
+ 500,
+ "500 compile time error (syntax error)",
+ );
+}
+
+{
+ my $url = "/registry/use_error.pl";
+ my $res = GET($url);
+ #t_debug($res->content);
+ ok t_cmp(
+ $res->code,
+ 500,
+ "500 compile error on use() failure",
+ );
+}
+
+{
+ my $url = "/registry/missing_headers.pl";
+ my $res = GET($url);
+ #t_debug($res->content);
+ ok t_cmp(
+ $res->code,
+ 500,
+ "500 error on missing HTTP headers",
+ );
+}
+
+{
+ # since we have a runtime error before any body is sent, mod_perl
+ # has a chance to communicate the return status of the script to
+ # Apache before headers are sent, so we get the code 500 in the
+ # HTTP headers
+ my $url = "/registry/runtime_error.pl";
+ my $res = GET($url);
+ #t_debug($res->content);
+ ok t_cmp(
+ $res->code,
+ 500,
+ "500 error on runtime error",
+ );
+}
+
+{
+ # even though we have a runtime error here, the scripts succeeds
+ # to send some body before the error happens and since by that
+ # time Apache has already sent the headers, they will include
+ # 200 OK
+ my $url = "/registry/runtime_error_plus_body.pl";
+ my $res = GET($url);
+ #t_debug($res->content);
+ ok t_cmp(
+ $res->code,
+ 200,
+ "200, followed by a runtime error",
+ );
+
+ # the error message is attached after the body
+ ok t_cmp($res->content,
+ qr/some body.*The server encountered an internal error/ms,
+ "200, followed by a runtime error",
+ );
+}
diff --git a/2_0_13/ModPerl-Registry/t/TEST.PL b/2_0_13/ModPerl-Registry/t/TEST.PL
new file mode 100644
index 0000000..4f82f04
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/TEST.PL
@@ -0,0 +1,56 @@
+use strict;
+use warnings FATAL => 'all';
+
+use FindBin;
+# test against the source lib for easier dev
+use lib "$FindBin::Bin/../lib";
+use lib grep { -d } map "$FindBin::Bin/../../$_", qw(lib Apache-Test/lib);
+
+# pick the common test libs
+use lib "$FindBin::Bin/../../t/lib";
+
+MyTest->new->run(@ARGV);
+
+
+
+# sub-class Apache::TestRunPerl
+package MyTest;
+
+use base qw(Apache::TestRunPerl);
+
+# redirect tests require 2 servers
+use constant MIN_CLIENTS => 2;
+
+use File::Spec::Functions qw(catdir);
+use File::Basename qw(dirname);
+
+use Apache2::Build;
+
+# default timeout in secs (threaded mpms are extremely slow to
+# startup, due to a slow perl_clone operation)
+use constant DEFAULT_STARTUP_TIMEOUT =>
+ Apache2::Build->build_config->mpm_is_threaded() ? 180 : 90;
+
+# subclass new_test_config to add some config vars which will be
+# replaced in generated httpd.conf
+sub new_test_config {
+ my $self = shift;
+
+ require Apache::Test;
+ my $mp2_root_dir = dirname Apache::Test::vars('top_dir');
+ $self->{conf_opts}->{src_dir} = catdir $mp2_root_dir,
+ qw(src modules perl);
+
+ $self->{conf_opts}->{startup_timeout} ||=
+ $ENV{APACHE_TEST_STARTUP_TIMEOUT} ||
+ DEFAULT_STARTUP_TIMEOUT;
+
+ $self->{conf_opts}->{minclients} ||= MIN_CLIENTS;
+
+ return $self->SUPER::new_test_config;
+}
+
+sub bug_report {
+ require ModPerl::TestRun;
+ shift->ModPerl::TestRun::bug_report();
+}
diff --git a/2_0_13/ModPerl-Registry/t/bad_scripts.t b/2_0_13/ModPerl-Registry/t/bad_scripts.t
new file mode 100644
index 0000000..8135484
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/bad_scripts.t
@@ -0,0 +1,20 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+use strict;
+use warnings FATAL => 'all';
+
+use Apache::Test;
+use Apache::TestUtil;
+use Apache::TestRequest qw(GET);
+
+plan tests => 1, need 'mod_alias.c';
+
+{
+ t_client_log_error_is_expected();
+ my $url = "/perlrun/r_inherited.pl";
+ my $res = GET($url);
+ ok t_cmp(
+ $res->code,
+ 500,
+ "the script hasn't declared its private \$r",
+ );
+}
diff --git a/2_0_13/ModPerl-Registry/t/basic.t b/2_0_13/ModPerl-Registry/t/basic.t
new file mode 100644
index 0000000..dcdc174
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/basic.t
@@ -0,0 +1,120 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+use strict;
+use warnings FATAL => 'all';
+
+use Apache::Test;
+use Apache::TestUtil qw(t_cmp t_catfile_apache t_client_log_error_is_expected);
+use Apache::TestRequest;
+use Apache::TestConfig ();
+
+my %modules = (
+ registry => 'ModPerl::Registry',
+ registry_bb => 'ModPerl::RegistryBB',
+ perlrun => 'ModPerl::PerlRun',
+);
+
+my @aliases = sort keys %modules;
+
+plan tests => @aliases * 5 + 3, need 'mod_alias.c';
+
+my $vars = Apache::Test::config()->{vars};
+my $script_file = t_catfile_apache $vars->{serverroot}, 'cgi-bin', 'basic.pl';
+
+# very basic compilation/response test
+for my $alias (@aliases) {
+ my $url = "/$alias/basic.pl";
+
+ ok t_cmp(
+ GET_BODY($url),
+ "ok $script_file",
+ "$modules{$alias} basic cgi test",
+ );
+}
+
+# test non-executable bit (it should be executed w/o a problem)
+for my $alias (@aliases) {
+ if (Apache::TestConfig::WIN32) {
+ skip "non-executable bit test for Win32", 0;
+ next;
+ }
+ my $url = "/$alias/not_executable.pl";
+
+ t_client_log_error_is_expected();
+ ok t_cmp(
+ HEAD($url)->code,
+ 200,
+ "$modules{$alias} non-executable file",
+ );
+}
+
+# test environment pre-set
+for my $alias (@aliases) {
+ my $url = "/$alias/env.pl?foo=bar";
+
+ ok t_cmp(
+ GET_BODY($url),
+ "foo=bar",
+ "$modules{$alias} mod_cgi-like environment pre-set",
+ );
+}
+
+# require (actually chdir test)
+for my $alias (@aliases) {
+ my $url = "/$alias/require.pl";
+
+ ok t_cmp(
+ GET_BODY($url),
+ "it works",
+ "$modules{$alias} mod_cgi-like environment pre-set",
+ );
+}
+
+
+# exit
+for my $alias (@aliases) {
+ my $url = "/$alias/exit.pl";
+
+ ok t_cmp(
+ GET_BODY_ASSERT($url),
+ "before exit",
+ "$modules{$alias} mod_cgi-like environment pre-set",
+ );
+}
+
+
+
+# test method handlers
+{
+ my $url = "/registry_oo_conf/env.pl?foo=bar";
+ ok t_cmp(
+ GET_BODY($url),
+ "foo=bar",
+ "ModPerl::Registry->handler mod_cgi-like environment pre-set",
+ );
+}
+
+# test mod_perl api usage
+{
+ my $url = "/registry/content_type.pl";
+ ok t_cmp(
+ GET_BODY($url),
+ "ok",
+ "\$r->content_type('text/plain')",
+ );
+}
+
+
+# test that files with .html extension, which are configured to run as
+# scripts get the headerparse stage working: the default mime handler
+# sets $r->content_type for .html files, so we can't rely on
+# content_type not being set in making the decision whether to parse
+# headers or not
+{
+ my $url = "/registry/send_headers.html";
+ my $res = GET $url;
+ ok t_cmp(
+ $res->content_type,
+ "text/plain",
+ "script's content-type",
+ );
+}
diff --git a/2_0_13/ModPerl-Registry/t/bin_resp.t b/2_0_13/ModPerl-Registry/t/bin_resp.t
new file mode 100644
index 0000000..5ffd780
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/bin_resp.t
@@ -0,0 +1,31 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+use strict;
+use warnings FATAL => 'all';
+
+# testing various binary responses
+
+use Apache::Test;
+use Apache::TestUtil;
+use Apache::TestRequest;
+
+plan tests => 2, need 'mod_alias.c';
+
+# 2 sub-tests
+{
+ # favicon.ico and other .ico image/x-icon images start with
+ # sequence:
+ my $expected = "\000\000\001\000";
+ my $location = "/registry/bin_resp_start_0.pl";
+ #my $location = "/cgi-bin/bin_resp_start_0.pl";
+
+ my $received = GET_BODY_ASSERT $location;
+
+ #t_debug "$received";
+
+ ok t_cmp(length($received), length($expected), "image size");
+
+ t_debug "comparing the binary contents";
+ ok $expected eq $received;
+}
+
+
diff --git a/2_0_13/ModPerl-Registry/t/cgi-bin/206.pl b/2_0_13/ModPerl-Registry/t/cgi-bin/206.pl
new file mode 100755
index 0000000..0aeac2b
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/cgi-bin/206.pl
@@ -0,0 +1,11 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+ print <<_OUT_;
+Status: 206 Partial Content
+Content-Type: text/html; charset=UTF-8
+Content-Length: 11
+Content-Range: bytes 0-10/1336
+Date: Fri, 31 Jan 2003 09:39:01 GMT
+ETag: "xxxx"
+
+_OUT_
+print '<?xml versi';
diff --git a/2_0_13/ModPerl-Registry/t/cgi-bin/304.pl b/2_0_13/ModPerl-Registry/t/cgi-bin/304.pl
new file mode 100755
index 0000000..8238112
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/cgi-bin/304.pl
@@ -0,0 +1,50 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+use strict;
+use warnings FATAL => 'all';
+
+# manually handle 'If-Modified-Since' requests
+
+use APR::Date ();
+use Apache2::Util ();
+use Apache2::RequestRec ();
+
+use constant FMT => '%a, %d %b %Y %H:%M:%S %Z';
+use constant GMT => 1;
+use Apache2::Const -compile => qw(HTTP_NOT_MODIFIED);
+
+my $last_modified = "Sun, 29 Oct 2000 15:43:29 GMT";
+
+my $r = shift;
+
+my $if_modified_since = $r->headers_in->{'If-Modified-Since'};
+
+my $status = 200;
+my $body = '<html><head></head><body>Test</body></html>';
+
+#APR::Date::parse_http may fail
+my $if_modified_since_secs =
+ ($if_modified_since && APR::Date::parse_http($if_modified_since)) || 0;
+my $last_modified_secs = APR::Date::parse_http($last_modified);
+
+#warn "If-Modified-Since $if_modified_since\n";
+#warn "last_modified_secs $last_modified_secs\n";
+#warn "if_modified_since_secs $if_modified_since_secs\n\n";
+
+if ($last_modified_secs < $if_modified_since_secs) {
+ $status = Apache2::Const::HTTP_NOT_MODIFIED;
+ $body = '';
+}
+
+my $date = Apache2::Util::ht_time($r->pool, $r->request_time, FMT, GMT);
+
+print <<HEADERS;
+Status: $status
+Date: $date
+Server: Apache/2.0.47
+Connection: close
+Last-Modified: $last_modified
+Content-Type: text/html; charset=iso-8859-1
+
+HEADERS
+
+print $body if length $body;
diff --git a/2_0_13/ModPerl-Registry/t/cgi-bin/404.pl b/2_0_13/ModPerl-Registry/t/cgi-bin/404.pl
new file mode 100755
index 0000000..ec1314f
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/cgi-bin/404.pl
@@ -0,0 +1,7 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+use strict;
+use warnings;
+
+my $r = shift;
+$r->content_type('text/plain');
+print "Oops, can't find the requested doc";
diff --git a/2_0_13/ModPerl-Registry/t/cgi-bin/basic.pl b/2_0_13/ModPerl-Registry/t/cgi-bin/basic.pl
new file mode 100755
index 0000000..2176f3c
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/cgi-bin/basic.pl
@@ -0,0 +1,16 @@
+#!perl -w
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+
+# test all the basic functionality
+
+print "Content-type: text/plain\n\n";
+
+# test that __END__ can appear in a comment w/o cutting data after it
+
+print "ok $0";
+
+# test that __END__ starting at the beginning of the line makes
+# everything following it, stripped
+__END__
+
+this is some irrelevant data
diff --git a/2_0_13/ModPerl-Registry/t/cgi-bin/bin_resp_start_0.pl b/2_0_13/ModPerl-Registry/t/cgi-bin/bin_resp_start_0.pl
new file mode 100755
index 0000000..4734b84
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/cgi-bin/bin_resp_start_0.pl
@@ -0,0 +1,14 @@
+#!/usr/bin/perl -w
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+
+use strict;
+use warnings FATAL => 'all';
+
+# favicon.ico and other .ico image/x-icon images start with this sequence
+my $response = "\000\000\001\000";
+
+# test here that the cgi header parser doesn't get confused and decide
+# that there is no response body if it starts with \000 sequence
+
+print "Content-type: image/x-icon\n\n";
+print $response;
diff --git a/2_0_13/ModPerl-Registry/t/cgi-bin/cgi.pl b/2_0_13/ModPerl-Registry/t/cgi-bin/cgi.pl
new file mode 100755
index 0000000..ef4941c
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/cgi-bin/cgi.pl
@@ -0,0 +1,5 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+use CGI qw/:standard :html3/;
+
+print header(-type=>'text/html');
+print b("done");
diff --git a/2_0_13/ModPerl-Registry/t/cgi-bin/closure.pl b/2_0_13/ModPerl-Registry/t/cgi-bin/closure.pl
new file mode 100755
index 0000000..495dd7a
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/cgi-bin/closure.pl
@@ -0,0 +1,23 @@
+#!perl -w
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+
+BEGIN {
+ use Apache::TestUtil qw/t_server_log_warn_is_expected/;
+ t_server_log_warn_is_expected();
+}
+
+# this script will suffer from a closure problem under registry
+# should see it under ::Registry
+# should not see it under ::PerlRun
+
+print "Content-type: text/plain\n\n";
+
+# this is a closure (when compiled inside handler()):
+my $counter = 0;
+counter();
+
+sub counter {
+ #warn "$$: counter=$counter";
+ print ++$counter;
+}
+
diff --git a/2_0_13/ModPerl-Registry/t/cgi-bin/content_type.pl b/2_0_13/ModPerl-Registry/t/cgi-bin/content_type.pl
new file mode 100755
index 0000000..ceb3678
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/cgi-bin/content_type.pl
@@ -0,0 +1,4 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+my $r = shift;
+$r->content_type('text/plain');
+$r->print('ok');
diff --git a/2_0_13/ModPerl-Registry/t/cgi-bin/env.pl b/2_0_13/ModPerl-Registry/t/cgi-bin/env.pl
new file mode 100755
index 0000000..d5990c5
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/cgi-bin/env.pl
@@ -0,0 +1,7 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+# test env vars
+
+print "Content-type: text/plain\n\n";
+print exists $ENV{QUERY_STRING} && $ENV{QUERY_STRING};
+
+__END__
diff --git a/2_0_13/ModPerl-Registry/t/cgi-bin/env_val.pl b/2_0_13/ModPerl-Registry/t/cgi-bin/env_val.pl
new file mode 100755
index 0000000..5632183
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/cgi-bin/env_val.pl
@@ -0,0 +1,8 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+# test env vars
+
+print "Content-type: text/plain\n\n";
+my $var = $ENV{QUERY_STRING};
+print exists $ENV{$var} && $ENV{$var};
+
+__END__
diff --git a/2_0_13/ModPerl-Registry/t/cgi-bin/exit.pl b/2_0_13/ModPerl-Registry/t/cgi-bin/exit.pl
new file mode 100755
index 0000000..90810ca
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/cgi-bin/exit.pl
@@ -0,0 +1,18 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+# XXX: exit should work by stopping the script, but not quitting the
+# interpreter, though it's not trivial to make an automated test since
+# what you really want to check whether the process didn't quit after
+# exit was called. Things become more complicated with
+# ithreads-enabled perls where one process may have many interpreters
+# and you can't really track those at the moment. So this test needs
+# more work.
+
+print "Content-type: text/plain\n\n";
+
+print "before exit";
+
+exit;
+
+print "after exit";
+
+
diff --git a/2_0_13/ModPerl-Registry/t/cgi-bin/flush.pl b/2_0_13/ModPerl-Registry/t/cgi-bin/flush.pl
new file mode 100755
index 0000000..b21f2cb
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/cgi-bin/flush.pl
@@ -0,0 +1,18 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+use strict;
+use warnings FATAL => 'all';
+
+local $| = 1; # unbuffered mode
+
+my $r = shift;
+
+print "Content-Type: text/html\n\n";
+print "yet another boring test string";
+
+# This line passes a bucket brigade with a single bucket FLUSH
+# it was causing problems in the mod_deflate filter which was trying to
+# deflate empty output buffer, (the previous print has already flushed
+# all the output) (the fix in mod_deflate.c was to check whether the
+# buffer is full)
+print "";
+
diff --git a/2_0_13/ModPerl-Registry/t/cgi-bin/ithreads_io_n_tie.pl b/2_0_13/ModPerl-Registry/t/cgi-bin/ithreads_io_n_tie.pl
new file mode 100755
index 0000000..50d5f71
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/cgi-bin/ithreads_io_n_tie.pl
@@ -0,0 +1,87 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+use strict;
+use warnings FATAL => 'all';
+
+#
+# there is a problem when STDOUT is internally opened to an
+# Apache2::PerlIO layer is cloned on a new thread start. PerlIO_clone
+# in perl_clone() is called too early, before PL_defstash is
+# cloned. As PerlIO_clone calls PerlIOApache_getarg, which calls
+# gv_fetchpv via sv_setref_pv and boom the segfault happens.
+#
+# at the moment we should either not use an internally opened to
+# :Apache2 streams, so the config must be:
+#
+# SetHandler modperl
+#
+# and then either use $r->print("foo") or tie *STDOUT, $r + print "foo"
+#
+# or close and re-open STDOUT to :Apache2 *after* the thread was spawned
+#
+# the above discussion equally applies to STDIN
+#
+# XXX: ->join calls leak under registry, this doesn't happen in the
+# non-registry tests.
+
+use threads;
+
+my $r = shift;
+$r->print("Content-type: text/plain\n\n");
+
+{
+ # now we can use $r->print API:
+ my $thr = threads->new(
+ sub {
+ my $id = shift;
+ $r->print("thread $id\n");
+ return 1;
+ }, 1);
+ # $thr->join; # XXX: leaks scalar
+}
+
+{
+ # close and re-open STDOUT to :Apache2 *after* the thread was
+ # spawned
+ my $thr = threads->new(
+ sub {
+ my $id = shift;
+ close STDOUT;
+ open STDOUT, ">:Apache2", $r
+ or die "can't open STDOUT via :Apache2 layer : $!";
+ print "thread $id\n";
+ return 1;
+ }, 2);
+ # $thr->join; # XXX: leaks scalar
+}
+
+{
+ # tie STDOUT to $r *after* the ithread was started has
+ # happened, in which case we can use print
+ my $thr = threads->new(
+ sub {
+ my $id = shift;
+ tie *STDOUT, $r;
+ print "thread $id\n";
+ return 1;
+ }, 3);
+ # $thr->join; # XXX: leaks scalar
+}
+
+{
+ # tie STDOUT to $r before the ithread was started has
+ # happened, in which case we can use print
+ tie *STDOUT, $r;
+ my $thr = threads->new(
+ sub {
+ my $id = shift;
+ print "thread $id\n";
+ return 1;
+ }, 4);
+ # $thr->join; # XXX: leaks scalar
+}
+
+sleep 2; # XXX: will go away ones join() calls are enabled
+
+print "parent\n";
+
+untie *STDOUT; # don't affect other tests
diff --git a/2_0_13/ModPerl-Registry/t/cgi-bin/local-conf.pl b/2_0_13/ModPerl-Registry/t/cgi-bin/local-conf.pl
new file mode 100644
index 0000000..e4e8dc9
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/cgi-bin/local-conf.pl
@@ -0,0 +1,4 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+$test_require = 'it works';
+
+1;
diff --git a/2_0_13/ModPerl-Registry/t/cgi-bin/missing_headers.pl b/2_0_13/ModPerl-Registry/t/cgi-bin/missing_headers.pl
new file mode 100755
index 0000000..5dad82d
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/cgi-bin/missing_headers.pl
@@ -0,0 +1,9 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+BEGIN {
+ use Apache::TestUtil;
+ t_server_log_error_is_expected();
+}
+print "No HTTP headers were sent\n\n";
+
+print "Here is some more body coming\n even with double new line\n\n";
+print "Here is some more body coming";
diff --git a/2_0_13/ModPerl-Registry/t/cgi-bin/not_executable.pl b/2_0_13/ModPerl-Registry/t/cgi-bin/not_executable.pl
new file mode 100644
index 0000000..d9ed3ba
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/cgi-bin/not_executable.pl
@@ -0,0 +1,11 @@
+#!perl -w
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+
+# this test should return forbidden, since it should be not-executable
+
+print "Content-type: text/plain\n\n";
+print "ok";
+
+__END__
+
+this is some irrelevant data
diff --git a/2_0_13/ModPerl-Registry/t/cgi-bin/nph-foo.pl b/2_0_13/ModPerl-Registry/t/cgi-bin/nph-foo.pl
new file mode 100755
index 0000000..a46836a
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/cgi-bin/nph-foo.pl
@@ -0,0 +1,14 @@
+#!/usr/bin/perl -w
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+
+my $r = shift;
+
+print "HTTP/1.0 250 Pretty OK\r\n";
+print join("\n",
+ 'Content-type: text/text',
+ 'Pragma: no-cache',
+ 'Cache-control: must-revalidate, no-cache, no-store',
+ 'Expires: -1',
+ "\n");
+
+print "non-parsed headers body";
diff --git a/2_0_13/ModPerl-Registry/t/cgi-bin/perlrun_decl.pm b/2_0_13/ModPerl-Registry/t/cgi-bin/perlrun_decl.pm
new file mode 100644
index 0000000..748b1af
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/cgi-bin/perlrun_decl.pm
@@ -0,0 +1,24 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+package perlrun_decl;
+
+use warnings;
+use strict;
+
+use base qw(Exporter);
+our @EXPORT = qw(decl_proto);
+
+# this BEGIN block is called only once, since this module doesn't get
+# removed from %INC after it was loaded
+BEGIN {
+ # use an external package which will persist across requests
+ $MyData::blocks{perlrun_decl}++;
+}
+
+sub decl_proto ($;$) { shift }
+
+# this END block won't be executed until the server shutdown
+END {
+ $MyData::blocks{perlrun_decl}--;
+}
+
+1;
diff --git a/2_0_13/ModPerl-Registry/t/cgi-bin/perlrun_extload.pl b/2_0_13/ModPerl-Registry/t/cgi-bin/perlrun_extload.pl
new file mode 100755
index 0000000..72269de
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/cgi-bin/perlrun_extload.pl
@@ -0,0 +1,62 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+use warnings;
+use strict;
+
+use Apache::Test ();
+use Apache::TestUtil;
+use File::Spec::Functions qw(catfile catdir);
+
+use lib catdir Apache::Test::vars('serverroot'), 'cgi-bin';
+my $require = catfile Apache::Test::vars('serverroot'),
+ qw(cgi-bin perlrun_nondecl.pl);
+
+print "Content-type: text/plain\n\n";
+
+### declared package module ###
+{
+ # require a module w/ package declaration (it doesn't get reloaded
+ # because it declares the package). But we still have a problem with
+ # subs declaring prototypes. When perlrun_decl->import is called, the
+ # original function's prototype doesn't match the aliases prototype.
+ # see decl_proto()
+ BEGIN { t_server_log_warn_is_expected()
+ if perlrun_decl->can("decl_proto");
+ }
+ use perlrun_decl;
+
+ die "perlrun_decl BEGIN block was run more than once"
+ if $MyData::blocks{perlrun_decl} > 1;
+
+ print "d";
+ print decl_proto(1);
+}
+
+### non-declared package module ###
+{
+ # how many times were were called from the same interpreter
+ $MyData::blocks{cycle}{perlrun_nondecl}++;
+ $MyData::blocks{BEGIN}{perlrun_nondecl} ||= 0;
+ $MyData::blocks{END} {perlrun_nondecl} ||= 0;
+
+ # require a lib w/o package declaration. Functions in that lib get
+ # automatically aliased to the functions in the current package.
+ require "$require";
+
+ die "perlrun_nondecl's BEGIN block wasn't run"
+ if $MyData::blocks{BEGIN}{perlrun_nondecl} !=
+ $MyData::blocks{cycle}{perlrun_nondecl};
+
+ # the END block for this cycle didn't run yet, but we can test the
+ # previous cycle's one
+ die "perlrun_nondecl's END block wasn't run"
+ if $MyData::blocks{END}{perlrun_nondecl} + 1 !=
+ $MyData::blocks{cycle}{perlrun_nondecl};
+
+ # they all get redefined warning inside perlrun_nondecl.pl, since that
+ # lib loads it into main::, vs. PerlRun undefs the current __PACKAGE__
+ print "nd";
+ print nondecl_no_proto();
+ print nondecl_proto(2);
+ print nondecl_proto_empty("whatever");
+ print nondecl_const();
+}
diff --git a/2_0_13/ModPerl-Registry/t/cgi-bin/perlrun_nondecl.pl b/2_0_13/ModPerl-Registry/t/cgi-bin/perlrun_nondecl.pl
new file mode 100644
index 0000000..da36515
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/cgi-bin/perlrun_nondecl.pl
@@ -0,0 +1,56 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+# we use this file to test how the files w/o package declaration,
+# required from perlrun, work
+
+use Apache::TestUtil;
+
+my $num;
+
+# this BEGIN block is called on every request, since this file gets
+# removed from %INC after it was loaded
+BEGIN {
+ # use an external package which will persist across requests
+ $MyData::blocks{BEGIN}{perlrun_nondecl}++;
+}
+
+use subs qw(warn_exp);
+
+# all subs in this file get 'redefined' warning because they are
+# reloaded in the main:: package, which is not under PerlRun's
+# control.
+
+BEGIN {
+ t_server_log_warn_is_expected()
+ if defined *{"nondecl_no_proto"}{CODE};
+}
+# normal sub, no prototype
+sub nondecl_no_proto { 1 }
+
+BEGIN {
+ t_server_log_warn_is_expected()
+ if defined *{"nondecl_proto"}{CODE};
+}
+# sub with a scalar proto
+sub nondecl_proto ($) { $num = shift }
+
+BEGIN {
+ t_server_log_warn_is_expected()
+ if defined *{"nondecl_proto_empty"}{CODE};
+}
+# sub with an empty proto, but not a constant
+sub nondecl_proto_empty () { $num + 1 }
+
+# besides the the constant sub will generate two warnings for nondecl_const:
+# - one for main::
+# - another for perlrun's virtual package
+BEGIN {
+ t_server_log_warn_is_expected(2);
+}
+# a constant.
+sub nondecl_const () { 4 }
+
+END {
+ $MyData::blocks{END}{perlrun_nondecl}++;
+}
+
+1;
diff --git a/2_0_13/ModPerl-Registry/t/cgi-bin/prefork.pl b/2_0_13/ModPerl-Registry/t/cgi-bin/prefork.pl
new file mode 100755
index 0000000..ae66b87
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/cgi-bin/prefork.pl
@@ -0,0 +1,20 @@
+#!perl -w
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+
+# test that prefork runs from the directory the script lives in
+
+# All Modperl::*Prefork modules must chdir into the current dir, so we
+# should be able to read ourselves via a relative path
+
+print "Content-type: text/plain\n\n";
+
+my $script = "prefork.pl";
+if (open my $fh, $script) {
+ print "ok $script";
+}
+else {
+ print "prefork didn't chdir into the scripts directory?";
+ print " The error was: $!";
+}
+
+
diff --git a/2_0_13/ModPerl-Registry/t/cgi-bin/r_inherited.pl b/2_0_13/ModPerl-Registry/t/cgi-bin/r_inherited.pl
new file mode 100755
index 0000000..a6eee27
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/cgi-bin/r_inherited.pl
@@ -0,0 +1,13 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+use strict;
+use warnings;
+
+# this script shouldn't work
+
+# this is to test that $r is not in the scope from the function that
+# has compiled this script in the registry module
+
+# my $r = shift;
+
+$r->content_type('text/plain');
+$r->print($r->args);
diff --git a/2_0_13/ModPerl-Registry/t/cgi-bin/redirect-cookie.pl b/2_0_13/ModPerl-Registry/t/cgi-bin/redirect-cookie.pl
new file mode 100755
index 0000000..41fd912
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/cgi-bin/redirect-cookie.pl
@@ -0,0 +1,19 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+# test env vars
+
+use Apache2::URI ();
+use Apache2::Const -compile => qw(REDIRECT SERVER_ERROR);
+
+my $r = shift;
+my $path = $r->args || '';
+$server = $r->construct_server;
+
+$r->err_headers_out->set('Set-Cookie' => "mod_perl=ubercool; path=/");
+$r->headers_out->set(Location => " http://$server$path");
+$r->status(Apache2::Const::REDIRECT);
+
+# exit status is completely ignored in Registry
+# due to $r->status hacking
+return Apache2::Const::SERVER_ERROR;
+
+__END__
diff --git a/2_0_13/ModPerl-Registry/t/cgi-bin/redirect.pl b/2_0_13/ModPerl-Registry/t/cgi-bin/redirect.pl
new file mode 100755
index 0000000..7c92679
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/cgi-bin/redirect.pl
@@ -0,0 +1,13 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+# test env vars
+
+use Apache2::URI ();
+
+my $r = shift;
+my $path = $r->args || '';
+$server = $r->construct_server;
+
+print "Location: http://$server$path\n\n";
+#warn "Location: http://$server$path\n\n";
+
+__END__
diff --git a/2_0_13/ModPerl-Registry/t/cgi-bin/require.pl b/2_0_13/ModPerl-Registry/t/cgi-bin/require.pl
new file mode 100755
index 0000000..43bd7eb
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/cgi-bin/require.pl
@@ -0,0 +1,17 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+# test the require
+
+use Apache::Test ();
+use File::Spec::Functions qw(catfile);
+
+my $vars = Apache::Test::config()->{vars};
+my $require = catfile $vars->{serverroot}, 'cgi-bin', 'local-conf.pl';
+
+print "Content-type: text/plain\n\n";
+
+# XXX: meanwhile we don't chdir to the script's dir
+delete $INC{$require};
+require $require;
+
+print defined $test_require && $test_require;
+
diff --git a/2_0_13/ModPerl-Registry/t/cgi-bin/runtime_error.pl b/2_0_13/ModPerl-Registry/t/cgi-bin/runtime_error.pl
new file mode 100755
index 0000000..9cf74a1
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/cgi-bin/runtime_error.pl
@@ -0,0 +1,11 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+BEGIN {
+ use Apache::TestUtil;
+ t_server_log_error_is_expected();
+}
+
+# this script sends no body at all, and since the error happens
+# the script will return 500
+
+print "Content-type: text/plain\n\n";
+print no_such_func();
diff --git a/2_0_13/ModPerl-Registry/t/cgi-bin/runtime_error_n_status_change.pl b/2_0_13/ModPerl-Registry/t/cgi-bin/runtime_error_n_status_change.pl
new file mode 100755
index 0000000..1687d2d
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/cgi-bin/runtime_error_n_status_change.pl
@@ -0,0 +1,12 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+BEGIN {
+ use Apache::TestUtil;
+ t_server_log_error_is_expected();
+}
+
+use Apache2::Const -compile => qw(NOT_FOUND);
+
+my $r = shift;
+$r->status(Apache2::Const::NOT_FOUND);
+$r->print("Content-type: text/plain\n\n");
+$r->print(no_such_func());
diff --git a/2_0_13/ModPerl-Registry/t/cgi-bin/runtime_error_plus_body.pl b/2_0_13/ModPerl-Registry/t/cgi-bin/runtime_error_plus_body.pl
new file mode 100755
index 0000000..c53f5dd
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/cgi-bin/runtime_error_plus_body.pl
@@ -0,0 +1,11 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+BEGIN {
+ use Apache::TestUtil;
+ t_server_log_error_is_expected();
+}
+
+# this script sends some body before the error happens,
+# so 200 OK is expected, followed by an error
+print "Content-type: text/plain\n\n";
+print "some body";
+print no_such_func();
diff --git a/2_0_13/ModPerl-Registry/t/cgi-bin/send_headers.html b/2_0_13/ModPerl-Registry/t/cgi-bin/send_headers.html
new file mode 100755
index 0000000..1c35576
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/cgi-bin/send_headers.html
@@ -0,0 +1,3 @@
+print "Content-type: text/plain\n\n";
+print "ok";
+
diff --git a/2_0_13/ModPerl-Registry/t/cgi-bin/special_blocks.pl b/2_0_13/ModPerl-Registry/t/cgi-bin/special_blocks.pl
new file mode 100755
index 0000000..d1d66f9
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/cgi-bin/special_blocks.pl
@@ -0,0 +1,35 @@
+#!perl -w
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+
+# test BEGIN/END blocks
+
+use Apache2::RequestRec ();
+
+use vars qw($query);
+$query = '' unless defined $query;
+
+BEGIN {
+ $query = $ENV{QUERY_STRING};
+}
+
+print "Content-type: text/plain\n\n";
+
+my $r = shift;
+our $test = $r->args || '';
+
+if ($test eq 'uncache') {
+ # mark the script as non-cached for the next execution
+ require ModPerl::RegistryCooker;
+ ModPerl::RegistryCooker::uncache_myself();
+}
+elsif ($test eq 'begin') {
+ print "begin ok" if $query eq 'begin';
+ # reset the global
+ $query = '';
+}
+
+END {
+ if (defined $test && $test eq 'end') {
+ print "end ok";
+ }
+}
diff --git a/2_0_13/ModPerl-Registry/t/cgi-bin/status_change.pl b/2_0_13/ModPerl-Registry/t/cgi-bin/status_change.pl
new file mode 100755
index 0000000..4475d5a
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/cgi-bin/status_change.pl
@@ -0,0 +1,6 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+use Apache2::Const -compile => qw(NOT_FOUND);
+
+my $r = shift;
+$r->status(Apache2::Const::NOT_FOUND);
+$r->print("Content-type: text/plain\n\n");
diff --git a/2_0_13/ModPerl-Registry/t/cgi-bin/syntax_error.pl b/2_0_13/ModPerl-Registry/t/cgi-bin/syntax_error.pl
new file mode 100755
index 0000000..1716354
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/cgi-bin/syntax_error.pl
@@ -0,0 +1,13 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+BEGIN {
+ use Apache::TestUtil;
+ t_server_log_error_is_expected();
+}
+
+print "Content-type: text/plain\n\n";
+
+# the following syntax error is here on purpose!
+
+lkj;\;
+
+print "done";
diff --git a/2_0_13/ModPerl-Registry/t/cgi-bin/use_error.pl b/2_0_13/ModPerl-Registry/t/cgi-bin/use_error.pl
new file mode 100755
index 0000000..00188c8
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/cgi-bin/use_error.pl
@@ -0,0 +1,10 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+BEGIN {
+ use Apache::TestUtil;
+ t_server_log_error_is_expected();
+}
+
+use DoesNotExist ();
+
+print "Content-type: text/plain\n\n";
+print "this script is expected to fail";
diff --git a/2_0_13/ModPerl-Registry/t/cgi.t b/2_0_13/ModPerl-Registry/t/cgi.t
new file mode 100644
index 0000000..b9133c5
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/cgi.t
@@ -0,0 +1,21 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+use strict;
+use warnings FATAL => 'all';
+
+use Apache::Test;
+use Apache::TestUtil;
+use Apache::TestRequest qw(GET);
+
+plan tests => 2, need [qw(mod_alias.c HTML::HeadParser)],
+ need_min_module_version CGI => 3.08;
+
+my $url = "/registry/cgi.pl";
+my $res = GET $url;
+
+ok t_cmp($res->header('Content-type'),
+ qr{^text/html},
+ "test 'Content-type header setting");
+
+ok t_cmp(lc($res->content),
+ '<b>done</b>',
+ "test body");
diff --git a/2_0_13/ModPerl-Registry/t/closure.t b/2_0_13/ModPerl-Registry/t/closure.t
new file mode 100644
index 0000000..dad160f
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/closure.t
@@ -0,0 +1,146 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+use strict;
+use warnings FATAL => 'all';
+
+use Apache::Test;
+use Apache::TestUtil;
+use Apache::TestRequest;
+use TestCommon::SameInterp;
+
+use File::Spec::Functions;
+
+# this test tests how various registry packages cache and flush the
+# scripts their run, and whether they check modification on the disk
+# or not. We don't test the closure side effect, but we use it as a
+# test aid. The tests makes sure that they run through the same
+# interpreter all the time (in case that the server is running more
+# than one interpreter)
+
+my @modules = qw(registry registry_bb perlrun);
+
+plan tests => 6, need [qw(mod_alias.c HTML::HeadParser)];
+
+my $cfg = Apache::Test::config();
+
+my $file = 'closure.pl';
+my $path = catfile $cfg->{vars}->{serverroot}, 'cgi-bin', $file;
+my $orig_mtime = (stat($path))[8];
+
+# for all sub-tests in this test, we make sure that we always get onto
+# the same interpreter. if this doesn't happen we skip the sub-test or
+# a group of them, where several sub-tests rely on each other.
+
+{
+ # ModPerl::PerlRun
+ # always flush
+ # no cache
+
+ my $url = "/same_interp/perlrun/$file";
+ my $same_interp = Apache::TestRequest::same_interp_tie($url);
+
+ # should be no closure effect, always returns 1
+ my $first = same_interp_req_body($same_interp, \&GET, $url);
+ my $second = same_interp_req_body($same_interp, \&GET, $url);
+ same_interp_skip_not_found(
+ (scalar(grep defined, $first, $second) != 2),
+ $first && $second && ($second - $first),
+ 0,
+ "never the closure problem",
+ );
+
+ # modify the file
+ touch_mtime($path);
+
+ # it doesn't matter, since the script is not cached anyway
+ my $third = same_interp_req_body($same_interp, \&GET, $url);
+ same_interp_skip_not_found(
+ (scalar(grep defined, $first, $second, $third) != 3),
+ $third,
+ 1,
+ "never the closure problem",
+ );
+
+ reset_mtime($path);
+}
+
+{
+ # ModPerl::Registry
+ # no flush
+ # cache, but reload on modification
+ my $url = "/same_interp/registry/$file";
+ my $same_interp = Apache::TestRequest::same_interp_tie($url);
+
+ # we don't know what other test has called this uri before, so we
+ # check the difference between two subsequent calls. In this case
+ # the difference should be 1.
+ my $first = same_interp_req_body($same_interp, \&GET, $url);
+ my $second = same_interp_req_body($same_interp, \&GET, $url);
+ same_interp_skip_not_found(
+ (scalar(grep defined, $first, $second) != 2),
+ $first && $second && ($second - $first),
+ 1,
+ "the closure problem should exist",
+ );
+
+ # modify the file
+ touch_mtime($path);
+
+ # should not notice closure effect on the first request
+ my $third = same_interp_req_body($same_interp, \&GET, $url);
+ same_interp_skip_not_found(
+ (scalar(grep defined, $first, $second, $third) != 3),
+ $third,
+ 1,
+ "no closure on the first request",
+ );
+
+ reset_mtime($path);
+}
+
+{
+ # ModPerl::RegistryBB
+ # no flush
+ # cache once, don't check for mods
+ my $url = "/same_interp/registry_bb/$file";
+ my $same_interp = Apache::TestRequest::same_interp_tie($url);
+
+ # we don't know what other test has called this uri before, so we
+ # check the difference between two subsequent calls. In this case
+ # the difference should be 1.
+ my $first = same_interp_req_body($same_interp, \&GET, $url);
+ my $second = same_interp_req_body($same_interp, \&GET, $url);
+ same_interp_skip_not_found(
+ (scalar(grep defined, $first, $second) != 2),
+ $first && $second && ($second - $first),
+ 1,
+ "the closure problem should exist",
+ );
+
+ # modify the file
+ touch_mtime($path);
+
+ # modification shouldn't be noticed
+ my $third = same_interp_req_body($same_interp, \&GET, $url);
+ same_interp_skip_not_found(
+ (scalar(grep defined, $first, $second, $third) != 3),
+ $first && $second && $third - $second,
+ 1,
+ "no reload on modification, the closure problem persists",
+ );
+
+ reset_mtime($path);
+}
+
+sub touch_mtime {
+ my $file = shift;
+ # push the mtime into the future (at least 2 secs to work on win32)
+ # so ModPerl::Registry will re-compile the package
+ my $time = time + 5; # make it 5 to be sure
+ utime $time, $time, $file;
+}
+
+sub reset_mtime {
+ my $file = shift;
+ # reset the timestamp to the original mod-time
+ utime $orig_mtime, $orig_mtime, $file;
+}
diff --git a/2_0_13/ModPerl-Registry/t/conf/extra.conf.in b/2_0_13/ModPerl-Registry/t/conf/extra.conf.in
new file mode 100644
index 0000000..1bdf835
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/conf/extra.conf.in
@@ -0,0 +1,235 @@
+#this file will be Include-d by @ServerRoot@/httpd.conf
+
+# Adjust PerlInterpMax and PerlInterpMaxSpare if the requirements change
+# at the moment all tests require only 1 interprter
+<IfDefine PERL_USEITHREADS>
+ PerlInterpStart 1
+ PerlInterpMax 1
+ PerlInterpMinSpare 1
+ PerlInterpMaxSpare 1
+</IfDefine>
+
+# make sure that we test under Taint and warnings mode enabled
+PerlSwitches -wT
+
+PerlSwitches -I@ServerRoot@/../lib \
+ -I@ServerRoot@/../../Apache-Test/lib \
+ -I@ServerRoot@/../../lib \
+ -I@ServerRoot@/../../blib/lib \
+ -I@ServerRoot@/../../blib/arch
+
+# run on startup
+PerlRequire @ServerRoot@/conf/modperl_extra_startup.pl
+
+PerlSetVar ModPerl::RegistryCooker::DEBUG 2
+
+PerlModule ModPerl::RegistryCooker
+PerlModule ModPerl::Util
+
+#############################
+### Normal registry setup ###
+#############################
+<IfModule mod_alias.c>
+ Alias /registry/ @ServerRoot@/cgi-bin/
+ Alias /dirindex/ @ServerRoot@/cgi-bin/
+ Alias /registry_bb/ @ServerRoot@/cgi-bin/
+ Alias /registry_oo_conf/ @ServerRoot@/cgi-bin/
+ Alias /registry_prefork/ @ServerRoot@/cgi-bin/
+ Alias /perlrun/ @ServerRoot@/cgi-bin/
+ Alias /perlrun_prefork/ @ServerRoot@/cgi-bin/
+ Alias /nph/ @ServerRoot@/cgi-bin/
+ Alias /registry_modperl_handler/ @ServerRoot@/cgi-bin/
+ Alias /rewrite_env/ @ServerRoot@/cgi-bin/
+
+ ScriptAlias /cgi-bin/ @ServerRoot@/cgi-bin/
+</IfModule>
+
+PerlModule ModPerl::RegistryBB
+<Location /registry_bb>
+ PerlOptions +GlobalRequest
+ SetHandler perl-script
+ Options +ExecCGI
+ PerlResponseHandler ModPerl::RegistryBB
+ PerlOptions +ParseHeaders
+</Location>
+
+PerlModule ModPerl::Registry
+<Location /registry>
+ SetHandler perl-script
+ Options +ExecCGI
+ PerlResponseHandler ModPerl::Registry
+ PerlOptions +ParseHeaders
+</Location>
+
+<IfModule mod_dir.c>
+ <Location /dirindex>
+ AddHandler perl-script .pl
+ Options +ExecCGI
+ PerlResponseHandler ModPerl::Registry
+ PerlOptions +ParseHeaders
+ DirectoryIndex cgi.pl
+ </Location>
+</IfModule>
+
+<Location /registry_modperl_handler>
+ SetHandler modperl
+ Options +ExecCGI
+ PerlResponseHandler ModPerl::Registry
+ PerlOptions +ParseHeaders
+</Location>
+
+<Location /registry_oo_conf>
+ SetHandler perl-script
+ Options +ExecCGI
+ PerlResponseHandler ModPerl::Registry->handler
+ PerlOptions +ParseHeaders
+</Location>
+
+<Location /nph>
+ SetHandler perl-script
+ Options +ExecCGI
+ PerlResponseHandler ModPerl::Registry
+</Location>
+
+# don't preload ModPerl::RegistryPrefork as it won't load under
+# threaded MPMs
+<Location /registry_prefork>
+ SetHandler perl-script
+ Options +ExecCGI
+ PerlResponseHandler ModPerl::RegistryPrefork
+ PerlOptions +ParseHeaders
+</Location>
+
+# don't preload ModPerl::PerlRunPrefork as it won't load under
+# threaded MPMs
+<Location /perlrun_prefork>
+ SetHandler perl-script
+ Options +ExecCGI
+ PerlResponseHandler ModPerl::PerlRunPrefork
+ PerlOptions +ParseHeaders
+</Location>
+
+PerlModule ModPerl::PerlRun
+<Location /perlrun>
+ SetHandler perl-script
+ Options +ExecCGI
+ PerlResponseHandler ModPerl::PerlRun
+ PerlOptions +ParseHeaders
+</Location>
+
+#######################################
+### Same interpreter registry setup ###
+#######################################
+<IfModule mod_alias.c>
+ Alias /same_interp/registry/ @ServerRoot@/cgi-bin/
+ Alias /same_interp/registry_bb/ @ServerRoot@/cgi-bin/
+ Alias /same_interp/registry_oo_conf/ @ServerRoot@/cgi-bin/
+ Alias /same_interp/perlrun/ @ServerRoot@/cgi-bin/
+</IfModule>
+
+PerlModule Apache::TestHandler
+
+<Location /same_interp/registry_bb>
+ PerlOptions +GlobalRequest
+ SetHandler perl-script
+ Options +ExecCGI
+ PerlFixupHandler Apache::TestHandler::same_interp_fixup
+ PerlResponseHandler ModPerl::RegistryBB
+ PerlOptions +ParseHeaders
+</Location>
+
+<Location /same_interp/registry>
+ # PerlOptions +GlobalRequest
+ SetHandler perl-script
+ Options +ExecCGI
+ PerlFixupHandler Apache::TestHandler::same_interp_fixup
+ PerlResponseHandler ModPerl::Registry
+ PerlOptions +ParseHeaders
+</Location>
+
+<Location /same_interp/registry_oo_conf>
+ PerlOptions +GlobalRequest
+ SetHandler perl-script
+ Options +ExecCGI
+ PerlFixupHandler Apache::TestHandler::same_interp_fixup
+ PerlResponseHandler ModPerl::Registry->handler
+ PerlOptions +ParseHeaders
+</Location>
+
+<Location /same_interp/perlrun>
+ PerlOptions +GlobalRequest
+ SetHandler perl-script
+ Options +ExecCGI
+ PerlFixupHandler Apache::TestHandler::same_interp_fixup
+ PerlResponseHandler ModPerl::PerlRun
+ PerlOptions +ParseHeaders
+</Location>
+
+### the 404 test ###
+<IfModule mod_alias.c>
+ Alias /error_document/ @ServerRoot@/cgi-bin/
+</IfModule>
+
+<Location /error_document>
+ ErrorDocument 404 /error_document/404.pl
+ SetHandler perl-script
+ Options +ExecCGI
+ PerlResponseHandler ModPerl::Registry
+</Location>
+
+### deflate tests ###
+<IfModule mod_alias.c>
+ Alias /registry_bb_deflate/ @ServerRoot@/cgi-bin/
+</IfModule>
+
+#PerlOutputFilterHandler ModPerl::TestFilterDebug::snoop_connection
+PerlModule ModPerl::RegistryBB
+<Location /registry_bb_deflate>
+ PerlOptions +GlobalRequest
+ SetHandler perl-script
+ Options +ExecCGI
+ PerlResponseHandler ModPerl::RegistryBB
+ PerlOptions +ParseHeaders
+ #PerlOutputFilterHandler ModPerl::TestFilterDebug::snoop_request
+ <IfModule mod_deflate.c>
+ SetOutputFilter DEFLATE
+ </IfModule>
+</Location>
+
+# <sandbox-friendly>
+# keep everything self-contained, to avoid problems with sandboxes
+# which break when things try to run off /tmp
+#
+# XXX: consider folding the the following two settings into
+# Apache-Test's autogenerated httpd.conf
+<IfModule mod_cgid.c>
+ ScriptSock logs/cgisock
+</IfModule>
+#
+# XXX: would be nice to have Apache-Test support a new 'tmp' token
+# (similar to t_logs) which will map onto t/tmp by default and provide
+# a new -tmp option to override this default
+<IfModule mod_env.c>
+ SetEnv TMPDIR @t_logs@
+</IfModule>
+# </sandbox-friendly>
+
+
+<IfModule mod_rewrite.c>
+
+ RewriteEngine On
+ <IfVersion < 2.4.0>
+ RewriteLogLevel 9
+ RewriteLog @ServerRoot@/logs/rewrite_log
+ </IfVersion>
+ RewriteRule /rewritetest /rewrite_env/env_val.pl?REWRITE_TEST [E=REWRITE_TEST:GOTCHA,PT,NS,L]
+
+ <Location /rewrite_env>
+ SetHandler perl-script
+ PerlResponseHandler ModPerl::Registry
+ Options +ExecCGI
+ PerlOptions +ParseHeaders
+ </Location>
+</IfModule>
+
+
diff --git a/2_0_13/ModPerl-Registry/t/conf/modperl_extra_startup.pl b/2_0_13/ModPerl-Registry/t/conf/modperl_extra_startup.pl
new file mode 100644
index 0000000..5511694
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/conf/modperl_extra_startup.pl
@@ -0,0 +1,53 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+use strict;
+use warnings FATAL => 'all';
+
+use ModPerl::RegistryLoader ();
+
+use Apache2::ServerRec ();
+use Apache2::ServerUtil ();
+use Apache2::Process ();
+
+use DirHandle ();
+
+my $proc = Apache2::ServerUtil->server->process;
+my $pool = $proc->pool;
+
+# can't use catfile with server_root as it contains unix dir
+# separators and in a few of our particular tests we compare against
+# win32 separators. in general avoid using server_root_relative in your
+# code, see the manpage for more details
+my $base_dir = Apache2::ServerUtil::server_root_relative($pool, "cgi-bin");
+
+# test the scripts pre-loading by explicitly specifying uri => filename
+my $rl = ModPerl::RegistryLoader->new(package => "ModPerl::Registry");
+my $base_uri = "/cgi-bin";
+for my $file (qw(basic.pl env.pl)) {
+ my $file_path = "$base_dir/$file";
+ my $uri = "$base_uri/$file";
+ $rl->handler($uri, $file_path);
+}
+
+
+# test the scripts pre-loading by using trans sub
+{
+ sub trans {
+ my $uri = shift;
+ $uri =~ s|^/registry_bb/|cgi-bin/|;
+ return Apache2::ServerUtil::server_root_relative($pool, $uri);
+ }
+
+ my $rl = ModPerl::RegistryLoader->new(
+ package => "ModPerl::RegistryBB",
+ trans => \&trans,
+ );
+
+ my @preload = qw(basic.pl env.pl require.pl special_blocks.pl
+ redirect.pl 206.pl content_type.pl);
+
+ for my $file (@preload) {
+ $rl->handler("/registry_bb/$file");
+ }
+}
+
+1;
diff --git a/2_0_13/ModPerl-Registry/t/dirindex.t b/2_0_13/ModPerl-Registry/t/dirindex.t
new file mode 100644
index 0000000..30520a7
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/dirindex.t
@@ -0,0 +1,23 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+use strict;
+use warnings FATAL => 'all';
+
+use Apache::Test;
+use Apache::TestUtil;
+use Apache::TestRequest qw(GET);
+
+plan tests => 2, need [qw(mod_alias.c HTML::HeadParser mod_dir.c)],
+ need_min_module_version CGI => 3.08;
+
+{
+ my $url = "/dirindex/";
+ my $res = GET $url;
+
+ ok t_cmp($res->header('Content-type'),
+ qr{^text/html},
+ "DirectoryIndex + AddHandler - Content-type");
+
+ ok t_cmp(lc($res->content),
+ '<b>done</b>',
+ "DirectoryIndex + AddHandler - body");
+}
diff --git a/2_0_13/ModPerl-Registry/t/fatalstobrowser.t b/2_0_13/ModPerl-Registry/t/fatalstobrowser.t
new file mode 100644
index 0000000..400d259
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/fatalstobrowser.t
@@ -0,0 +1,51 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+use strict;
+use warnings FATAL => 'all';
+
+use Apache::Test;
+use Apache::TestUtil qw(
+ t_cmp t_write_perl_script
+ t_client_log_error_is_expected
+ );
+use Apache::TestRequest qw(GET);
+
+use File::Spec::Functions qw(catfile);
+
+plan tests => 4, need need_module(qw(mod_alias)),
+ need_cgi,
+ need_min_module_version CGI => 99.99,
+ skip_reason('fatalsToBrowser known not to work');
+
+my $file = catfile(Apache::Test::vars('serverroot'),
+ qw(cgi-bin fatalstobrowser.pl));
+
+t_write_perl_script($file, <DATA>);
+
+foreach my $base (qw(cgi-bin registry)) {
+
+ my $url = "$base/fatalstobrowser.pl";
+ my $res = GET $url;
+
+ ok t_cmp($res->code,
+ 200,
+ "error intercepted");
+
+ t_client_log_error_is_expected();
+
+ ok t_cmp($res->content,
+ qr/uninitiated_scalar/,
+ "error message captured and returned");
+}
+
+__END__
+use strict;
+use CGI::Carp qw (fatalsToBrowser);
+
+use CGI;
+
+my $cgi = new CGI;
+print $cgi->header;
+
+print "$uninitiated_scalar";
+
+print "Hello World";
diff --git a/2_0_13/ModPerl-Registry/t/flush.t b/2_0_13/ModPerl-Registry/t/flush.t
new file mode 100644
index 0000000..d126ea8
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/flush.t
@@ -0,0 +1,28 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+use strict;
+use warnings FATAL => 'all';
+
+use Apache::Test;
+use Apache::TestUtil;
+use Apache::TestRequest qw(GET_BODY);
+
+plan tests => 1, need [qw(mod_alias.c deflate HTML::HeadParser)],
+ need_min_module_version("Compress::Zlib", "1.09"),
+ need_min_apache_version("2.0.48");
+# it requires httpd 2.0.48 because of the bug in mod_deflate:
+# http://nagoya.apache.org/bugzilla/show_bug.cgi?id=22259
+
+require Compress::Zlib;
+
+my $url = "/registry_bb_deflate/flush.pl";
+
+my $expected = "yet another boring test string";
+my $received = GET_BODY $url, 'Accept-encoding' => 'gzip';
+my $decompressed = Compress::Zlib::memGunzip($received);
+
+ok t_cmp(
+ $decompressed,
+ $expected,
+ "test flush body"
+ );
+
diff --git a/2_0_13/ModPerl-Registry/t/ithreads.t b/2_0_13/ModPerl-Registry/t/ithreads.t
new file mode 100644
index 0000000..7d91ce9
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/ithreads.t
@@ -0,0 +1,24 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+use strict;
+use warnings FATAL => 'all';
+
+use Apache::Test;
+use Apache::TestUtil;
+use Apache::TestRequest;
+
+use Config;
+
+use constant HAS_ITHREADS => ($] >= 5.008001 && $Config{useithreads});
+
+plan tests => 1, need 'mod_alias.c',
+ {"perl 5.8.1 or higher w/ithreads enabled is required" => HAS_ITHREADS};
+
+{
+ # the order of prints on the server side is not important here,
+ # what's important is that we get all the printed strings
+ my @expected = sort map("thread $_", 1..4), "parent";
+ my $url = "/registry_modperl_handler/ithreads_io_n_tie.pl";
+ my $received = GET_BODY_ASSERT($url) || '';
+ my @received = sort split /\n/, $received;
+ ok t_cmp \@received, \@expected;
+}
diff --git a/2_0_13/ModPerl-Registry/t/nph.t b/2_0_13/ModPerl-Registry/t/nph.t
new file mode 100644
index 0000000..f9b29e2
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/nph.t
@@ -0,0 +1,52 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+use strict;
+use warnings FATAL => 'all';
+
+use Apache::Test;
+use Apache::TestUtil;
+use Apache::TestRequest;
+
+plan tests => 6, need 'mod_alias.c';
+
+my $url = "/nph/nph-foo.pl";
+
+my %expected = (
+ code => '250',
+ body => "non-parsed headers body",
+ headers => {
+ 'content-type' => 'text/text',
+ 'pragma' => 'no-cache',
+ 'cache-control' => 'must-revalidate, no-cache, no-store',
+ 'expires' => '-1',
+ },
+);
+
+my $res = GET $url;
+
+my %received = (
+ code => $res->code,
+ body => $res->content,
+ headers => $res->headers, # LWP lc's the headers
+);
+
+for my $key (keys %expected) {
+ my $expected = $expected{$key};
+ my $received = $received{$key};
+ if ($key eq 'headers') {
+ for my $header (keys %$expected) {
+ ok t_cmp(
+ $received->{$header},
+ $expected->{$header},
+ "test header $header"
+ );
+ }
+ }
+ else {
+ ok t_cmp(
+ $received,
+ $expected,
+ "test key: $key"
+ );
+ }
+}
+
diff --git a/2_0_13/ModPerl-Registry/t/perlrun_extload.t b/2_0_13/ModPerl-Registry/t/perlrun_extload.t
new file mode 100644
index 0000000..e99fd65
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/perlrun_extload.t
@@ -0,0 +1,25 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+use strict;
+use warnings FATAL => 'all';
+
+use Apache::Test;
+use Apache::TestUtil;
+use Apache::TestRequest qw(GET);
+use TestCommon::SameInterp;
+
+plan tests => 2, need [qw(mod_alias.c HTML::HeadParser)];
+
+my $url = "/same_interp/perlrun/perlrun_extload.pl";
+my $same_interp = Apache::TestRequest::same_interp_tie($url);
+
+for (1..2) {
+ # should not fail on the second request
+ my $res = same_interp_req_body($same_interp, \&GET, $url);
+ same_interp_skip_not_found(
+ !defined($res),
+ $res,
+ "d1nd1234",
+ "PerlRun requiring an external lib with subs",
+ );
+}
+
diff --git a/2_0_13/ModPerl-Registry/t/prefork.t b/2_0_13/ModPerl-Registry/t/prefork.t
new file mode 100644
index 0000000..00376a3
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/prefork.t
@@ -0,0 +1,48 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+use strict;
+use warnings FATAL => 'all';
+
+use Apache::Test;
+use Apache::TestUtil;
+use Apache::TestRequest;
+use Apache::TestConfig ();
+
+use Apache2::Build ();
+
+my $mpm_is_threaded = Apache2::Build->build_config->mpm_is_threaded();
+
+my %modules = (
+ registry => 'ModPerl::Registry',
+ perlrun => 'ModPerl::PerlRun',
+ registry_prefork => 'ModPerl::RegistryPrefork',
+ perlrun_prefork => 'ModPerl::PerlRunPrefork',
+);
+
+my @aliases = sort keys %modules;
+
+plan tests => 1*@aliases, need 'mod_alias.c',
+ { "can't run under threaded MPMs" => !$mpm_is_threaded };
+
+my $script = "prefork.pl";
+
+# very basic compilation/response test
+for my $alias (qw(registry_prefork perlrun_prefork)) {
+ my $url = "/$alias/$script";
+
+ #t_debug "$url";
+ ok t_cmp GET_BODY($url), "ok $script", "$modules{$alias} test";
+}
+
+# the order is important, we also want to check that prefork specific
+# modules didn't affect the cwd of other modules
+
+# the normal handlers should not find the script in the cwd, as they
+# don't chdir to its directory before running the script
+for my $alias (qw(registry perlrun)) {
+ my $url = "/$alias/$script";
+
+ #t_debug "$url";
+ ok t_cmp GET_BODY($url),
+ qr/prefork didn't chdir into the scripts directory/,
+ "$modules{$alias} test";
+}
diff --git a/2_0_13/ModPerl-Registry/t/redirect.t b/2_0_13/ModPerl-Registry/t/redirect.t
new file mode 100644
index 0000000..b4e304e
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/redirect.t
@@ -0,0 +1,61 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+use strict;
+use warnings FATAL => 'all';
+
+use Apache::Test;
+use Apache::TestUtil;
+use Apache::TestRequest qw(GET_BODY HEAD);
+
+use Apache::TestUtil qw(t_catfile_apache);
+
+plan tests => 4, need [qw(mod_alias.c HTML::HeadParser)], need_lwp;
+
+# need LWP to handle redirects
+my $base_url = "/registry/redirect.pl";
+
+{
+ my $redirect_path = "/registry/basic.pl";
+ my $url = "$base_url?$redirect_path";
+ my $vars = Apache::Test::config()->{vars};
+ my $script_file = t_catfile_apache $vars->{serverroot}, 'cgi-bin', 'basic.pl';
+
+ ok t_cmp(
+ GET_BODY($url),
+ "ok $script_file",
+ "test redirect: existing target",
+ );
+}
+
+{
+ my $redirect_path = "/registry/does_not_exists.pl";
+ my $url = "$base_url?$redirect_path";
+ t_client_log_error_is_expected();
+ ok t_cmp(
+ HEAD($url)->code,
+ 404,
+ "test redirect: non-existing target",
+ );
+}
+
+{
+ local $Apache::TestRequest::RedirectOK = 0;
+
+ my $base_url = "/registry/redirect-cookie.pl";
+ my $redirect_path = "/registry/basic.pl";
+ my $url = "$base_url?$redirect_path";
+
+ my $response = HEAD $url;
+
+ ok t_cmp(
+ $response->code,
+ 302,
+ "test Registry style redirect: status",
+ );
+
+ ok t_cmp(
+ $response->header('Set-Cookie'),
+ "mod_perl=ubercool; path=/",
+ "test Registry style redirect: cookie",
+ );
+}
+
diff --git a/2_0_13/ModPerl-Registry/t/regex.t b/2_0_13/ModPerl-Registry/t/regex.t
new file mode 100644
index 0000000..4aba470
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/regex.t
@@ -0,0 +1,34 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+use strict;
+use warnings FATAL => 'all';
+
+use Apache::Test;
+use Apache::TestUtil qw(t_cmp t_catfile_apache);
+use Apache::TestRequest;
+use Apache::TestConfig ();
+
+my %modules = (
+ registry => 'ModPerl::Registry',
+ registry_bb => 'ModPerl::RegistryBB',
+ perlrun => 'ModPerl::PerlRun',
+);
+
+my @aliases = sort keys %modules;
+
+plan tests => @aliases * 1, need 'mod_alias.c';
+
+my $vars = Apache::Test::config()->{vars};
+my $script_file = t_catfile_apache $vars->{serverroot}, 'cgi-bin', 'basic.pl';
+
+# extended regex quoting
+# CVE-2007-1349 (which doesn't affect any of our shipped handlers)
+
+for my $alias (@aliases) {
+ my $url = "/$alias/basic.pl/(";
+
+ ok t_cmp(
+ GET_BODY($url),
+ "ok $script_file",
+ "$modules{$alias} regex in path_info",
+ );
+}
diff --git a/2_0_13/ModPerl-Registry/t/rewrite_env.t b/2_0_13/ModPerl-Registry/t/rewrite_env.t
new file mode 100644
index 0000000..b3e439d
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/rewrite_env.t
@@ -0,0 +1,18 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+use strict;
+use warnings FATAL => 'all';
+
+use Apache::Test;
+use Apache::TestUtil;
+use Apache::TestRequest qw(GET);
+
+plan tests => 1, need [qw(mod_alias.c mod_rewrite.c)];
+
+{
+ my $url = "/rewritetest";
+ my $res = GET $url;
+
+ ok t_cmp($res->content(),
+ "GOTCHA",
+ 'found environment variable from mod_rewrite');
+}
diff --git a/2_0_13/ModPerl-Registry/t/special_blocks.t b/2_0_13/ModPerl-Registry/t/special_blocks.t
new file mode 100644
index 0000000..2868064
--- /dev/null
+++ b/2_0_13/ModPerl-Registry/t/special_blocks.t
@@ -0,0 +1,140 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+use strict;
+use warnings FATAL => 'all';
+
+# test BEGIN/END blocks's behavior
+
+use Apache::Test;
+use Apache::TestUtil;
+use Apache::TestRequest;
+use TestCommon::SameInterp;
+
+my %modules = (
+ registry => 'ModPerl::Registry',
+ registry_bb => 'ModPerl::RegistryBB',
+ perlrun => 'ModPerl::PerlRun',
+);
+
+my @aliases = sort keys %modules;
+
+plan tests => @aliases * 4, need [qw(mod_alias.c HTML::HeadParser)];
+
+{
+ # PerlRun always run BEGIN/END since it's never cached
+
+ # see also t/perlrun_extload.t which exercises BEGIN/END blocks
+ # from external modules loaded from PerlRun scripts
+
+ my $alias = "perlrun";
+ my $url = "/same_interp/$alias/special_blocks.pl";
+ my $same_interp = Apache::TestRequest::same_interp_tie($url);
+
+ # if one sub-test has failed to run on the same interpreter, skip
+ # the rest in the same group
+ my $skip = 0;
+
+ my $res = same_interp_req_body($same_interp, \&GET, "$url?begin");
+ $skip++ unless defined $res;
+ same_interp_skip_not_found(
+ $skip,
+ $res,
+ "begin ok",
+ "$modules{$alias} is running BEGIN blocks on the first request",
+ );
+
+ $res = $skip ? undef : same_interp_req_body($same_interp, \&GET,
+ "$url?begin");
+ $skip++ unless defined $res;
+ same_interp_skip_not_found(
+ $skip,
+ $res,
+ "begin ok",
+ "$modules{$alias} is running BEGIN blocks on the second request",
+ );
+
+ $res = $skip ? undef : same_interp_req_body($same_interp, \&GET,
+ "$url?end");
+ $skip++ unless defined $res;
+ same_interp_skip_not_found(
+ $skip,
+ $res,
+ "end ok",
+ "$modules{$alias} is running END blocks on the third request",
+ );
+
+ $res = $skip ? undef : same_interp_req_body($same_interp, \&GET,
+ "$url?end");
+ $skip++ unless defined $res;
+ same_interp_skip_not_found(
+ $skip,
+ $res,
+ "end ok",
+ "$modules{$alias} is running END blocks on the fourth request",
+ );
+}
+
+# To properly test BEGIN/END blocks in registry implmentations
+# that do caching, we need to manually reset the registry* cache
+# for each given script, before starting each group of tests.
+
+
+for my $alias (grep !/^perlrun$/, @aliases) {
+ my $url = "/same_interp/$alias/special_blocks.pl";
+ my $same_interp = Apache::TestRequest::same_interp_tie($url);
+
+ # if one sub-test has failed to run on the same interpreter, skip
+ # the rest in the same group
+ my $skip = 0;
+
+ # clear the cache of the registry package for the script in $url
+ my $res = same_interp_req_body($same_interp, \&GET, "$url?uncache");
+ $skip++ unless defined $res;
+
+ $res = $skip ? undef : same_interp_req_body($same_interp, \&GET,
+ "$url?begin");
+ $skip++ unless defined $res;
+ same_interp_skip_not_found(
+ $skip,
+ $res,
+ "begin ok",
+ "$modules{$alias} is running BEGIN blocks on the first request",
+ );
+
+ $res = $skip ? undef : same_interp_req_body($same_interp, \&GET,
+ "$url?begin");
+ $skip++ unless defined $res;
+ t_debug($res);
+ same_interp_skip_not_found(
+ $skip,
+ $res,
+ "",
+ "$modules{$alias} is not running BEGIN blocks on the second request",
+ );
+
+ $same_interp = Apache::TestRequest::same_interp_tie($url);
+ $skip = 0;
+
+ # clear the cache of the registry package for the script in $url
+ $res = same_interp_req_body($same_interp, \&GET, "$url?uncache");
+ $skip++ unless defined $res;
+
+ $res = $skip ? undef : same_interp_req_body($same_interp, \&GET,
+ "$url?end");
+ $skip++ unless defined $res;
+ same_interp_skip_not_found(
+ $skip,
+ $res,
+ "end ok",
+ "$modules{$alias} is running END blocks on the first request",
+ );
+
+ $res = $skip ? undef : same_interp_req_body($same_interp, \&GET,
+ "$url?end");
+ $skip++ unless defined $res;
+ same_interp_skip_not_found(
+ $skip,
+ $res,
+ "end ok",
+ "$modules{$alias} is running END blocks on the second request",
+ );
+}
diff --git a/2_0_13/NOTICE b/2_0_13/NOTICE
new file mode 100644
index 0000000..3f59805
--- /dev/null
+++ b/2_0_13/NOTICE
@@ -0,0 +1,2 @@
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
diff --git a/2_0_13/README b/2_0_13/README
new file mode 100644
index 0000000..a9d3739
--- /dev/null
+++ b/2_0_13/README
@@ -0,0 +1,85 @@
+This is mod_perl version 2.0
+
+*** Prerequisites ***
+
+Apache:
+ Dynamic mod_perl (DSO): Apache 2.0.47 - 2.4.57.
+ Static mod_perl: Apache 2.0.51 - 2.4.57.
+
+ Newer Apache versions may work with this version of mod_perl. If
+ not, the svn version likely will, which can be obtained from:
+ http://perl.apache.org/download/source.html#Development_mod_perl_2_0_Source_Distribution
+
+Perl:
+ Any stable version of Perl currently in support by the Perl community,
+ as described in recent Perl distributions' "perlpolicy.pod" document.
+
+ Newer Perl versions may work with this version of mod_perl. If not,
+ the svn version likely will (see above).
+
+ Many older Perl versions also work with this version of mod_perl:
+ Perls back to version 5.8.2 (and possibly earlier in some build
+ configurations) are currently believed to work, but this is not
+ guaranteed to be the case, either now or in the future.
+
+*** Status ***
+
+mod_perl is currently considered stable.
+
+The following test failures are known (see CPAN RT #118919):
+
+ t/filter/in_bbs_inject_header.t (Fails tests 22, 26 and 30)
+
+There is currently a known test failure on Windows when using Perls built
+with the PERL_IMPLICIT_SYS build option enabled (which it is by default):
+
+ t/modperl/env.t (Fails many tests)
+
+Various other tests are also known to fail in certain configurations on
+Windows, including but not limited to:
+
+ t/modperl/setupenv.t (Fails tests 8, 22, 29, 36, 50 and 57)
+ t/preconnection/note.t (Fails test 1)
+
+*** Documentation ***
+
+Documentation can be found in the docs/ directory. Currently they
+don't get installed on 'make install'. Certain API documentation can
+be found in docs/api/. The online version is at
+http://perl.apache.org/docs/2.0/.
+
+*** Todo ***
+
+mod_perl-2.0 is not 100% feature complete with the 1.xx version.
+See the files in the todo/ directory for what remains to be done. Some
+of those features will be implemented after 2.0 is released. The goal
+is to empty the file todo/release and document/test/verify the API
+that's going to be supported by 2.0. More API will be supported post
+2.0 release.
+
+*** Support ***
+
+For comments, questions, bug-reports, etc., join the mod_perl users
+list by sending mail to modperl-subscribe@perl.apache.org.
+
+Bugs can also be reported at:
+https://rt.cpan.org/Dist/Display.html?Name=mod_perl
+which can be accessed from the "Issues" link in the left-hand menu on
+the metacpan.org page, https://metacpan.org/pod/mod_perl2 .
+(Note: You will need to log in to https://rt.cpan.org in order to get
+the "Report a new bug" button on the bug tracker page.)
+
+When reporting bugs please follow the instructions at:
+http://perl.apache.org/docs/2.0/user/help/help.html#Reporting_Problems
+
+For announcements join the mod_perl announce list by sending mail to
+announce-subscribe@perl.apache.org.
+
+*** Developers ***
+
+Development discussion takes place on dev (at) perl.apache.org
+
+*** Authors ***
+
+mod_perl-2.0 was designed and written by Doug MacEachern, with
+contributions from many others (see Changes files).
diff --git a/2_0_13/README-SVN b/2_0_13/README-SVN
new file mode 100644
index 0000000..ff929f5
--- /dev/null
+++ b/2_0_13/README-SVN
@@ -0,0 +1,59 @@
+this is a very simple document that outlines some of the important
+details about the mod_perl svn repository.
+
+
+LAYOUT
+
+the mod_perl project at the Apache Software Foundation lives here
+
+ http://svn.apache.org/repos/asf/perl/
+
+and uses the following structure
+
+ modperl/trunk # equivalent to cvs HEAD - currently
+ # the mod_perl 2.0 development branch
+
+ modperl/tags # every official mod_perl release
+
+ modperl/docs/trunk # the mod_perl documentation project
+
+modperl/trunk includes the following svn:externals properties:
+
+ % cd modperl
+ % svn propedit svn:externals .
+ [vi pops up]
+Apache-Test https://svn.apache.org/repos/asf/perl/Apache-Test/trunk
+Apache-Reload https://svn.apache.org/repos/asf/perl/Apache-Reload/trunk
+Apache-SizeLimit https://svn.apache.org/repos/asf/perl/Apache-SizeLimit/trunk
+docs https://svn.apache.org/repos/asf/perl/modperl/docs/trunk/src/docs/2.0
+
+DEVELOPER ACCESS
+
+assuming that you have already been granted commit access to the repository,
+you should follow the following steps to checkout mod_perl
+
+Change your password via:
+https://svn.apache.org/change-password
+
+ $ svn checkout https://svn.apache.org/repos/asf/perl/modperl/trunk/ mod_perl-2.0
+
+if you want to test that your commit access is working, this file is
+an acceptable place to take a test drive.
+
+
+FURTHER READING
+
+for more details, see
+
+ http://perl.apache.org/docs/2.0/user/install/install.html
+
+for information on getting httpd and mod_perl from svn, as well as
+
+ http://svnbook.red-bean.com/
+
+for svn information in general.
+
+svn for cvs users (including migration tools):
+
+ http://svnbook.red-bean.com/en/1.0/apa.html
+
diff --git a/2_0_13/RELEASE b/2_0_13/RELEASE
new file mode 100644
index 0000000..41b7404
--- /dev/null
+++ b/2_0_13/RELEASE
@@ -0,0 +1,211 @@
+Instructions for mod_perl 2.0 Release Manager
+
+0. make sure your public key is in the KEYS file in the mod_perl docs.
+ you should only need to do this if this is your first time playing
+ Release Manager
+
+ $ cd mod_perl-docs
+ $ grep $USER src/dist/KEYS
+
+ note that the KEYS file itself contains all the instructions you
+ need on how to add your key. if you need further help on gpg
+ (like how to create a key in the first place) you can look here
+
+ https://people.apache.org/~geoff/gpghowto.html
+
+ Copy the KEYS file into place:
+ % scp KEYS people.apache.org:/www/www.apache.org/dist/perl/KEYS
+
+ If this is your first release, ask someone with APML karma on PAUSE
+ to verify you have the appropriate permissions. Likely someone on
+ the PMC can do this.
+
+ a. login into https://pause.perl.org
+ b. menu click: Select Mailinglist/Action
+ c. choose APML and Change Permissions and click go
+ d. click 3.1 Make somebody else co-maintainer
+ e. choose the modules to give the perms to
+ type the username of the new co-maintainer
+ f. if you happen to know that packages were added this release,
+ make sure you give the correct permissions to them.
+
+1. 'make mydist' - to make sure nothing is missing from the manifest,
+ etc. Now test this generated package mod_perl-2.0.13.tar.gz (not
+ the current build) with as many
+ configurations as possible on as many platforms as possible,
+ unpacking the package each time afresh.
+
+ a. edit ./Changes
+ - change -dev to -rc\d+ starting with -rc1
+ - edit META.yml to the rc\d version above in the version key
+
+ b. commit Changes
+ % svn ci -m "2.0.13 rc1" Changes
+
+ c. nuke any preinstalled mod_perl libs and run 'make test'
+
+ d. test that you can 'make install' and then run 'make test' again
+
+ e. test whether we are still 100% OK on systems with no LWP:
+ % APACHE_TEST_PRETEND_NO_LWP=1 make test
+
+ f. build and test as root. double check that you have started from a
+ fresh source, without having any stale dirs from the previous
+ build laying around.
+
+2. once confident that the package is good, commit the release candidate
+ to https://dist.apache.org/repos/dist/dev/perl and post 24 hour-ish
+ candidate alert to the modperl/dev list (may be longer to give most
+ people a chance to catch up). no need to tag this package
+
+ Subject: [RELEASE CANDIDATE]: mod_perl-2.0.13 RC\d+
+
+2a. if problems are detected during stage 2, repeat stages 1 and 2.
+
+3. when the package has been reported to be good, prepare a new
+ package to be released
+
+ a. edit ./Changes:
+ - remove -rc\d+
+ - add release date
+ - edit META.yml to remove the -rc\d+ from the version key
+
+ b. check ./README and ./Makefile.PL
+ - make sure supported httpd versions (dso & static) are current
+
+ c. rerun:
+ % perl Makefile.PL
+ make sure tag looks right
+ % make -n tag
+
+ d. commit Changes README Makefile.PL
+ % svn ci -m "2.0.13 release" Changes README Makefile.PL
+
+ e. tag
+ % make tag
+
+ f. Update the svn:externals in the new tag to refer to the new docs tag that
+ was created by the previous step:
+ % svn co https://svn.apache.org/repos/asf/perl/modperl/tags/2_0_13
+ % svn propedit svn:externals 2_0_13
+ Update the docs line from:
+ ^/perl/modperl/docs/trunk/src/docs/2.0
+ to:
+ ^/perl/modperl/docs/tags/2_0_13/src/docs/2.0
+ The complete svn:externals should now look like:
+ % svn propget svn:externals 2_0_13
+ Apache-Test ^/perl/Apache-Test/tags/<X>
+ Apache-Reload ^/perl/Apache-Reload/tags/<Y>
+ Apache-SizeLimit ^/perl/Apache-SizeLimit/tags/<Z>
+ docs ^/perl/modperl/docs/tags/2_0_13/src/docs/2.0
+ where <X>, <Y> and <Z> are the tags of the releases of Apache-Test,
+ Apache-Reload and Apache-SizeLimit included in this release of mod_perl.
+ % svn ci -m "2.0.13 release"
+
+ g. create the final package
+ % make dist
+
+ h. test the final package again at least once
+
+4. Tarball signing
+
+ (depending on whether you use GPG or PGP, pick the first or the
+ second set of the commands):
+
+ a. sign your local copy of the tarball:
+
+ % gpg --detach-sign --armor mod_perl-2.0.13.tar.gz
+
+ % pgps -b --armor mod_perl-2.0.13.tar.gz
+
+ b. create SHA256 and SHA512 checksums of the tarball:
+ % sha256sum mod_perl-2.0.13.tar.gz >mod_perl-2.0.13.tar.gz.sha256
+ % sha512sum mod_perl-2.0.13.tar.gz >mod_perl-2.0.13.tar.gz.sha512
+
+5. Release the package and update links
+
+ a. commit the tarball, the signature file and the checksum files to
+ https://dist.apache.org/repos/dist/release/perl - ask the PMC
+ chair to give you the needed permissions if you do not have them.
+
+ b. delete the previous release's files from the same location (they will
+ already have been archived at https://archive.apache.org/dist/perl/)
+
+ c. update the example command-lines in README.html in the same location
+
+ d. ask one of the other developers to double check the signature file
+ and tarball: download both files and verify the signature:
+
+ https://www.apache.org/dist/perl/mod_perl-2.0.13.tar.gz.asc
+ https://www.apache.org/dist/perl/mod_perl-2.0.13.tar.gz
+
+ % gpg --verify mod_perl-2.0.13.tar.gz.asc
+
+ % pgpv mod_perl-2.0.13.tar.gz.asc
+
+ e. respond to the automated email that will arrive requesting that release
+ data be filled in at https://reporter.apache.org/addrelease.html?perl
+
+ f. update the version and release date in the docs:
+ % vi modperl-docs/src/download/index_top.html
+ % vi modperl-docs/doap_Perl.rdf
+ and commit.
+ % svn ci -m "2.0.13 release" \
+ modperl-docs/src/download/index_top.html \
+ modperl-docs/doap_Perl.rdf
+
+ Now run modperl-docs/bin/site_build to generate a local copy of the
+ website, and commit that to https://svn.apache.org/repos/asf/perl/site
+
+ (Alternatively, if running modperl-docs/bin/site_build is too difficult
+ on your local machine, you can just directly edit download/index.html
+ with the changes that were made to modperl-docs/download/index_top.html)
+
+ The change to the website will appear at https://perl.apache.org/ sometime
+ later (but maybe not until the next day).
+
+6. Upload the package to CPAN
+
+7. Announce the package
+
+ a. post to the following lists:
+
+ o dev/perl.apache.org
+ o modperl/perl.apache.org
+ o announce/apache.org
+
+ Note, to post to announce@, you must be sending from an apache.org address.
+
+ Subject: [ANNOUNCE] mod_perl 2.0.13
+
+ include:
+ - link at perl.apache.org:
+ https://perl.apache.org/download/index.html
+ - SHA256 and SHA512 sigs
+ - the latest Changes
+
+8. Prepare for the next cycle
+
+ a. increment version in lib/mod_perl2.pm
+
+ b. increment version in META.yml
+
+ c. edit ./Changes:
+ - start a new item with incremented version + '-dev'
+
+ =item 2.0.14-dev
+
+ d. add a release entry in STATUS
+
+ e. update this file versions to make it easy to copy-n-paste things
+ on the next release:
+ % perl -pi.bak -e 's/(\d+)([._])(\d+)(\2)(\d+)/join($2, $1, $3, $5+1)/eg' RELEASE
+
+ f. commit the changed files
+ % svn ci -m "start 2.0.13-dev cycle" Changes META.yml lib/mod_perl2.pm \
+ STATUS RELEASE
+
+9. Old Versions
+
+ Remind other developers to delete versions older then the prior release
+ from CPAN. Old releases can always be found on BACKPAN.
diff --git a/2_0_13/STATUS b/2_0_13/STATUS
new file mode 100644
index 0000000..1083f10
--- /dev/null
+++ b/2_0_13/STATUS
@@ -0,0 +1,44 @@
+mod_perl 2.0 STATUS: -*-text-*-
+ Last modified at [$Date$]
+
+Release:
+--------
+ 2.000.12 : Released Jan 30, 2022
+ 2.000.11 : Released Oct 05, 2019
+ 2.000.10 : Released Oct 27, 2016
+ 2.000.09 : Released Jun 18, 2015
+ 2.000.08 : Released Apr 17, 2013
+ 2.000.07 : Released Jun 05, 2012
+ 2.000.06 : Released Apr 24, 2012
+ 2.000.05 : Released Feb 07, 2011
+ 2.000.04 : Released Apr 16, 2008
+ 2.000.03 : Released Nov 29, 2006
+ 2.000.02 : Released Oct 20, 2005
+ 2.000.01 : Released Jun 17, 2005
+ 2.000.00 : Released May 20, 2005
+ 1.999.23 : Released May 03, 2005
+ 1.999.22 : Released Apr 14, 2005
+ 1.999.21 : Released Jan 22, 2005
+ 1.999.20 : Released Jan 05, 2005
+ 1.99_19 : Released Dec 22, 2004
+ 1.99_18 : Released Dec 12, 2004
+ 1.99_17 : Released Oct 22, 2004
+ 1.99_16 : Released Aug 22, 2004
+ 1.99_15 : Released Aug 20, 2004
+ 1.99_14 : Released May 21, 2004
+ 1.99_13 : Released Mar 08, 2004
+ 1.99_12 : Released Dec 22, 2003
+ 1.99_11 : Released Nov 10, 2003
+ 1.99_10 : Released Sep 30, 2003
+ 1.99_09 : Released Apr 28, 2003
+ 1.99_08 : Released Jan 10, 2003
+ 1.99_07 : Released Sep 27, 2002
+ 1.99_06 : Not released
+ 1.99_05 : Released Aug 20, 2002
+ 1.99_04 : Released Jun 21, 2002
+ 1.99_03 : Released Jun 16, 2002
+ 1.99_02 : Released Jun 01, 2002
+ 1.99_01 : Released Apr 06, 2002
+
+Issues, bugs and features and their implementation status are spread
+across several files under the todo/ directory
diff --git a/2_0_13/SVN-MOVE b/2_0_13/SVN-MOVE
new file mode 100644
index 0000000..e98bfc1
--- /dev/null
+++ b/2_0_13/SVN-MOVE
@@ -0,0 +1,30 @@
+This file tracks the things that need to be done to accomplish the
+move of modperl projects to SVN:
+
+* missing commit template files (à là CVS)
+ PR:
+ Obtained from:
+ Submitted by:
+ Reviewed by:
+ ...
+
+* commit messages should trim the unrelated crap in the file path
+ e.g. currently we get:
+
+ --- perl/modperl/docs/trunk/src/search/swish.conf (original)
+ +++ perl/modperl/docs/trunk/src/search/swish.conf Fri Nov 19 21:23:25 2004
+and it should be:
+
+ --- src/search/swish.conf (original)
+ +++ src/search/swish.conf Fri Nov 19 21:23:25 2004
+
+so it can be applied/edited easily.
+
+* improve the commit message subject line to print only important info
+ (currently may print 100 files listed in the subject), e.g.:
+
+ Subject: svn commit: r105803 - in httpd/test/trunk/perl-framework: . Apache-Test Apache-Test/lib/Apache Apache-Test/t Apache-Test/t/conf c-modules c-modules/authany c-modules/client_add_filter c-modules/eat_post c-modules/echo_post c-modules/echo_post_chunk c-modules/input_body_filter c-modules/list_modules c-modules/nntp_like c-modules/random_chunk c-modules/test_apr_uri c-modules/test_pass_brigade c-modules/test_rwrite c-modules/test_ssl t t/conf t/conf/ssl t/htdocs/modules/access/htaccess t/htdocs/modules/cgi t/htdocs/modules/rewrite t/modules
+
+ Proposed Subject format:
+
+ $svn_id $first_subdir/$first_file ($trunk)
diff --git a/2_0_13/bin/mp2bug b/2_0_13/bin/mp2bug
new file mode 100755
index 0000000..c3a312a
--- /dev/null
+++ b/2_0_13/bin/mp2bug
@@ -0,0 +1,36 @@
+#!perl
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+use strict;
+use warnings FATAL => 'all';
+
+use FindBin;
+
+use constant IS_MOD_PERL_BUILD => -e "$FindBin::Bin/../lib/mod_perl2.pm";
+
+if (IS_MOD_PERL_BUILD) {
+ unshift @INC, "$FindBin::Bin/../lib";
+}
+else {
+ eval { require mod_perl2 };
+ if ($@) {
+ die "This script requires mod_perl 2.0\n", "$@";
+ }
+}
+
+require ModPerl::TestReport;
+ModPerl::TestReport->new(@ARGV)->run;
diff --git a/2_0_13/build/config.pl b/2_0_13/build/config.pl
new file mode 100644
index 0000000..7b9e09c
--- /dev/null
+++ b/2_0_13/build/config.pl
@@ -0,0 +1,10 @@
+#!/usr/bin/perl -w
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+
+use strict;
+use FindBin qw($Bin);
+use lib "$Bin/../lib";
+
+use ModPerl::Config ();
+
+print ModPerl::Config::as_string();
diff --git a/2_0_13/build/make_etags b/2_0_13/build/make_etags
new file mode 100644
index 0000000..703588a
--- /dev/null
+++ b/2_0_13/build/make_etags
@@ -0,0 +1,27 @@
+search=".. ../.."
+for dir in $search; do
+ if test -d "`pwd`/$dir/modperl-2.0"; then
+ root="`pwd`/$dir"
+ echo "root=$root"
+ fi
+done
+
+#e.g. symlink to $HOME/perl/perl-current
+#XXX: perl has its own (more robust) TAGS generator: emacs/ptags
+perl_src=$root/perl/
+#XXX: apache has its own: build/MakeEtags
+apache_src=$root/httpd-2.0/
+modperl_src=$root/modperl-2.0/src/
+xs_src=$root/modperl-2.0/xs
+
+cd $root/modperl-2.0
+rm -f src/modules/perl/etag_files
+
+for dir in $apache_src $modperl_src $perl_src $xs_src; do
+ echo $dir
+ find $dir -follow -name '*.[ch]' >> src/modules/perl/etag_files
+done
+
+(cd src/modules/perl && etags `cat etag_files`)
+
+rm -f src/modules/perl/etag_files
diff --git a/2_0_13/build/make_rpm_spec b/2_0_13/build/make_rpm_spec
new file mode 100755
index 0000000..2ad2c4e
--- /dev/null
+++ b/2_0_13/build/make_rpm_spec
@@ -0,0 +1,146 @@
+#!perl
+use strict;
+
+require "./lib/mod_perl2.pm";
+
+my $dev_build = is_dev_build();
+my $release = $dev_build ? svn_release() : 1;
+my $version = $mod_perl2::VERSION_TRIPLET;
+my $path = $dev_build ? "mod_perl-$version-$dev_build" : "mod_perl-$version";
+my $tarname = "$path.tar.gz";
+
+my $httpd_ver = min_httpd_ver();
+
+open(my $spec, ">mod_perl.spec") || die "Can't open mod_perl.spec $!";
+
+print $spec <<"EOF";
+%define _version $mod_perl2::VERSION_TRIPLET
+%define _release $release
+%define _source https://apache.org/dist/perl/$tarname
+%define _dirname $path
+%define _httpd_min_ver $httpd_ver
+%define _perl_min_ver 5.6.1
+EOF
+
+print $spec <<'EOF';
+Name: mod_perl
+Version: %{_version}
+Release: %{_release}
+Summary: An embedded Perl interpreter for the Apache Web server
+Group: System Environment/Daemons
+License: Apache License, Version 2.0
+Packager: mod_perl Development Team <dev@perl.apache.org>
+URL: https://perl.apache.org/
+Source: %{_source}
+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+Requires: httpd >= %{_httpd_min_ver}
+BuildRequires: perl >= %{_perl_min_ver}
+BuildRequires: httpd-devel >= %{_httpd_min_ver}
+BuildRequires: apr-devel, apr-util-devel
+
+%description
+Mod_perl incorporates a Perl interpreter into the Apache web server,
+so that the Apache web server can directly execute Perl code.
+Mod_perl links the Perl runtime library into the Apache web server and
+provides an object-oriented Perl interface for Apache's C language
+API. The end result is a quicker CGI script turnaround process, since
+no external Perl interpreter has to be started.
+
+Install mod_perl if you're installing the Apache web server and you'd
+like for it to directly incorporate a Perl interpreter.
+
+%package devel
+Summary: Files needed for building XS modules that use mod_perl
+Group: Development/Libraries
+Requires: mod_perl = %{version}-%{release}, httpd-devel
+
+%description devel
+The mod_perl-devel package contains the files needed for building XS
+modules that use mod_perl.
+
+%prep
+%setup -q -n %{_dirname}
+
+%build
+CFLAGS="$RPM_OPT_FLAGS" %{__perl} Makefile.PL </dev/null \
+ PREFIX=$RPM_BUILD_ROOT/usr \
+ INSTALLDIRS=vendor \
+ MP_APXS=%{_sbindir}/apxs
+make %{?_smp_mflags} OPTIMIZE="$RPM_OPT_FLAGS"
+
+%install
+rm -rf $RPM_BUILD_ROOT
+install -d -m 755 $RPM_BUILD_ROOT%{_libdir}/httpd/modules
+make install \
+ MODPERL_AP_LIBEXECDIR=$RPM_BUILD_ROOT%{_libdir}/httpd/modules \
+ MODPERL_AP_INCLUDEDIR=$RPM_BUILD_ROOT%{_includedir}/httpd
+
+# Remove the temporary files.
+find $RPM_BUILD_ROOT -type f -name .packlist -exec rm -f {} ';'
+find $RPM_BUILD_ROOT -type f -name perllocal.pod -exec rm -f {} ';'
+find $RPM_BUILD_ROOT -type f -name '*.bs' -a -size 0 -exec rm -f {} ';'
+find $RPM_BUILD_ROOT -type d -depth -exec rmdir {} 2>/dev/null ';'
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%files
+%defattr(-,root,root,-)
+%doc Changes LICENSE README* STATUS SVN-MOVE docs/
+%{_bindir}/*
+%{_libdir}/httpd/modules/mod_perl.so
+%{perl_vendorarch}/auto/*
+%{perl_vendorarch}/Apache/
+%{perl_vendorarch}/Apache2/
+%{perl_vendorarch}/Bundle/
+%{perl_vendorarch}/APR/
+%{perl_vendorarch}/ModPerl/
+%{perl_vendorarch}/*.pm
+%{_mandir}/man?/*
+
+%files devel
+%defattr(-,root,root,-)
+%{_includedir}/httpd/*
+
+%changelog
+EOF
+
+sub min_httpd_ver {
+ my $min_httpd_ver;
+ open my $mk, 'Makefile.PL';
+ while (<$mk>) {
+ if (/MIN_HTTPD_VERSION_DYNAMIC\s*=>\s*'(.*)'/) {
+ $min_httpd_ver = $1;
+ last;
+ }
+ }
+ close $mk;
+ $min_httpd_ver;
+}
+
+sub svn_release {
+ open my $svn, "<.svn/entries";
+ my $revision;
+ while (<$svn>) {
+ if (/revision="(\d+)"/) {
+ $revision = $1;
+ last;
+ }
+ }
+ close $svn;
+ $revision;
+}
+
+sub is_dev_build {
+ my $dev;
+ open my $fh, 'Changes';
+ while (<$fh>) {
+ if (/^=item.*-(dev|rc\d+)/) {
+ $dev = $1;
+ last;
+ }
+ last if /^=item/;
+ }
+ close $fh;
+ $dev;
+}
diff --git a/2_0_13/build/source_scan.pl b/2_0_13/build/source_scan.pl
new file mode 100644
index 0000000..3a6da0e
--- /dev/null
+++ b/2_0_13/build/source_scan.pl
@@ -0,0 +1,27 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+#requires C::Scan 0.75+
+
+use lib qw(lib Apache-Test/lib);
+
+use strict;
+use Apache2::ParseSource ();
+use ModPerl::ParseSource ();
+use ModPerl::FunctionMap ();
+use ModPerl::WrapXS (); #XXX: we should not need to require this here
+
+my $p = Apache2::ParseSource->new(prefixes => ModPerl::FunctionMap->prefixes,
+ @ARGV);
+
+$p->parse;
+
+$p->write_constants_pm;
+
+$p->write_functions_pm;
+
+$p->write_structs_pm;
+
+$p = ModPerl::ParseSource->new(@ARGV);
+
+$p->parse;
+
+$p->write_functions_pm;
diff --git a/2_0_13/build/win32_fetch_apxs b/2_0_13/build/win32_fetch_apxs
new file mode 100755
index 0000000..ee6c964
--- /dev/null
+++ b/2_0_13/build/win32_fetch_apxs
@@ -0,0 +1,101 @@
+#!C:/Perl/bin/perl
+###################################################################
+# apxs, apr-config, and apu-config are Apache utilities used #
+# to both get certain configuration information and also to #
+# assist in building Apache modules. These utilities have not #
+# yet been officially ported to Win32. The following will fetch #
+# and install a development version of these scripts which can #
+# be used in both mod_perl 2 and Apache C modules. #
+# #
+# Please report problems in installing or using these utilties to #
+# Randy Kobes <randy@theoryx5.uwinnipeg.ca> #
+###################################################################
+use strict;
+use warnings;
+use Getopt::Long;
+use File::Spec::Functions;
+use File::Path;
+use ExtUtils::MakeMaker qw(prompt);
+use Cwd;
+
+die "This is intended for Win32" unless ($^O =~ /Win32/i);
+
+my $prefix;
+GetOptions( 'with-apache2=s' => \$prefix);
+unless ($prefix and -d $prefix) {
+ die << 'END';
+
+I could not determine a valid Apache2 directory. Please
+run this script specifying the option
+ --with-apache2=/Path/to/Apache2
+where /Path/to/Apache2 is the location of your installed
+Apache2 top-level directory.
+
+END
+}
+
+exit 0 if (-e catfile($prefix, 'bin', 'apxs.bat'));
+
+print << 'END';
+
+----------------------------------------------------------------------
+I could not find an apxs utility, which will be used in certain parts
+of the build, if present. This utility (and the apr-config and
+apu-config utilities) have not yet been ported to Apache2 on Win32,
+but a development port is available. You can either
+
+- ignore installing apxs by answering "no" at the prompt below
+ (mod_perl will still build),
+- install apxs by answering "yes" at the prompt below,
+- quit now, run the "fetch_win32_apxs.pl" script in the build/ directory
+ to fetch and install the utilities, and then rebuild mod_perl,
+- quit now, and from https://apache.org/dist/perl/win32-bin/ grab
+ apxs_win32.tar.gz; when unpacked, this contains a README explaining
+ how to install the utilities. Afterwards, rebuild mod_perl.
+----------------------------------------------------------------------
+
+END
+
+my $ans = prompt('Install apxs now?', 'yes');
+exit 0 unless $ans =~ /^y/i;
+
+my $prog;
+for my $trial(qw(Apache.exe httpd.exe)) {
+ next unless -e File::Spec->catfile($prefix, 'bin', $trial);
+ $prog = $trial;
+ last;
+}
+die "Could not determine the Apache2 binary name" unless $prog;
+
+require LWP::Simple;
+LWP::Simple->import(qw(is_success getstore));
+
+my $file = 'apxs_win32.tar.gz';
+unless (-e $file) {
+ my $remote = 'https://apache.org/dist/perl/win32-bin/' . $file;
+ print "Fetching $remote ... ";
+ die "Download of $remote failed"
+ unless (is_success(getstore($remote, $file)));
+ print " done!\n";
+}
+
+require Archive::Tar;
+my $cwd = getcwd;
+my $dir = 'apxs';
+my $arc = Archive::Tar->new($file, 1);
+$arc->extract($arc->list_files());
+die "Unpacking $file failed" unless (-d $dir);
+
+print "chdir $dir\n";
+chdir $dir or die "chdir to $dir failed: $!";
+
+my @args = ($^X, 'Configure.pl',
+ "--with-apache2=$prefix",
+ "--with-apache-prog=$prog");
+print "@args\n";
+system(@args) == 0 or die "system @args failed: $?";
+
+chdir $cwd;
+#rmtree($dir, 1, 1) or warn "rmtree of $dir failed: $!";
+#print "unlink $file\n\n";
+#unlink $file or warn "unlink of $file failed: $!";
diff --git a/2_0_13/build/xs_generate.pl b/2_0_13/build/xs_generate.pl
new file mode 100644
index 0000000..74761b5
--- /dev/null
+++ b/2_0_13/build/xs_generate.pl
@@ -0,0 +1,11 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+use lib qw(lib Apache-Test/lib);
+
+use Apache::TestConfig (); # needed to resolve circular use dependency
+
+use ModPerl::WrapXS ();
+
+my $xs = ModPerl::WrapXS->new;
+
+$xs->generate;
+
diff --git a/2_0_13/lib/APR/XSLoader.pm b/2_0_13/lib/APR/XSLoader.pm
new file mode 100644
index 0000000..fc390f2
--- /dev/null
+++ b/2_0_13/lib/APR/XSLoader.pm
@@ -0,0 +1,38 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+package APR::XSLoader;
+
+use strict;
+use warnings FATAL => 'all';
+
+use XSLoader ();
+
+BEGIN {
+ unless (defined &BOOTSTRAP) {
+ *BOOTSTRAP = sub () { 0 };
+ }
+}
+
+sub load {
+ return unless BOOTSTRAP;
+ # do not change the next line and do not insert anything below it in this
+ # function. XSLoader::load depends on it.
+ goto &XSLoader::load;
+}
+
+1;
+__END__
diff --git a/2_0_13/lib/Apache2/Build.pm b/2_0_13/lib/Apache2/Build.pm
new file mode 100644
index 0000000..19692a8
--- /dev/null
+++ b/2_0_13/lib/Apache2/Build.pm
@@ -0,0 +1,2400 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+package Apache2::Build;
+
+use 5.006;
+use strict;
+use warnings;
+
+use Config;
+use Cwd ();
+use File::Spec::Functions qw(catfile catdir canonpath rel2abs devnull
+ catpath splitpath);
+use File::Basename;
+use ExtUtils::Embed ();
+use File::Copy ();
+
+BEGIN { # check for a sane ExtUtils::Embed
+ unless ($ENV{MP_USE_MY_EXTUTILS_EMBED}) {
+ my ($version, $path)=(ExtUtils::Embed->VERSION,
+ $INC{q{ExtUtils/Embed.pm}});
+ my $msg=<<"EOF";
+I have found ExtUtils::Embed $version at
+
+ $path
+
+This is probably not the right one for this perl version. Please make sure
+there is only one version of this module installed and that it is the one
+that comes with this perl version.
+
+If you insist on using the ExtUtils::Embed as is set the environment
+variable MP_USE_MY_EXTUTILS_EMBED=1 and try again.
+
+EOF
+ if (eval {require Module::CoreList}) {
+ my $req=$Module::CoreList::version{$]}->{q/ExtUtils::Embed/};
+ die "Please repair your Module::CoreList" unless $req;
+ unless ($version eq $req) {
+ $msg.=("Details: expecting ExtUtils::Embed $req ".
+ "(according to Module::CoreList)\n\n");
+ die $msg;
+ }
+ }
+ else {
+ my $req=$Config{privlib}.'/ExtUtils/Embed.pm';
+ unless ($path eq $req) {
+ $msg.="Details: expecting ExtUtils::Embed at $req\n\n";
+ die $msg;
+ }
+ }
+ }
+}
+
+use constant IS_MOD_PERL_BUILD => grep
+ { -e "$_/Makefile.PL" && -e "$_/lib/mod_perl2.pm" } qw(. ..);
+
+use constant AIX => $^O eq 'aix';
+use constant DARWIN => $^O eq 'darwin';
+use constant CYGWIN => $^O eq 'cygwin';
+use constant IRIX => $^O eq 'irix';
+use constant HPUX => $^O eq 'hpux';
+use constant OPENBSD => $^O eq 'openbsd';
+use constant WIN32 => $^O eq 'MSWin32';
+
+use constant MSVC => WIN32() && ($Config{cc} eq 'cl');
+use constant DMAKE => WIN32() && ($Config{make} eq 'dmake');
+
+use constant REQUIRE_ITHREADS => grep { $^O eq $_ } qw(MSWin32);
+use constant PERL_HAS_ITHREADS =>
+ $Config{useithreads} && ($Config{useithreads} eq 'define');
+use constant BUILD_APREXT => WIN32() || CYGWIN();
+
+use ModPerl::Code ();
+use ModPerl::BuildOptions ();
+use Apache::TestTrace;
+use Apache::TestConfig ();
+
+our $VERSION = '0.01';
+our $AUTOLOAD;
+
+sub AUTOLOAD {
+ my $self = shift;
+ my $name = uc ((split '::', $AUTOLOAD)[-1]);
+ unless ($name =~ /^MP_/) {
+ die "no such method: $AUTOLOAD";
+ }
+ unless ($self->{$name}) {
+ return wantarray ? () : undef;
+ }
+ return wantarray ? (split /\s+/, $self->{$name}) : $self->{$name};
+}
+
+#--- apxs stuff ---
+
+our $APXS;
+
+my %apxs_query = (
+ INCLUDEDIR => 'include',
+ LIBEXECDIR => 'modules',
+ CFLAGS => undef,
+ PREFIX => '',
+);
+
+sub ap_prefix_invalid {
+ my $self = shift;
+
+ my $prefix = $self->{MP_AP_PREFIX};
+
+ unless (-d $prefix) {
+ return "$prefix: No such file or directory";
+ }
+
+ my $include_dir = $self->apxs(-q => 'INCLUDEDIR');
+
+ unless (-d $include_dir) {
+ return "include/ directory not found in $prefix";
+ }
+
+ return '';
+}
+
+sub httpd_is_source_tree {
+ my $self = shift;
+
+ return $self->{httpd_is_source_tree}
+ if exists $self->{httpd_is_source_tree};
+
+ my $prefix = $self->dir;
+ $self->{httpd_is_source_tree} =
+ defined $prefix && -d $prefix && -e "$prefix/CHANGES";
+}
+
+# try to find the apxs utility, set $self->{MP_APXS} to the path if found,
+# otherwise to ''
+sub find_apxs_util {
+ my $self = shift;
+
+ if (not defined $self->{MP_APXS}) {
+ $self->{MP_APXS} = ''; # not found
+ }
+
+ my @trys = ($Apache2::Build::APXS,
+ $self->{MP_APXS},
+ $ENV{MP_APXS});
+
+ push @trys, catfile $self->{MP_AP_PREFIX}, 'bin', 'apxs'
+ if exists $self->{MP_AP_PREFIX};
+
+ if (WIN32) {
+ my $ext = '.bat';
+ for (@trys) {
+ $_ .= $ext if ($_ and $_ !~ /$ext$/);
+ }
+ }
+
+ unless (IS_MOD_PERL_BUILD) {
+ #if we are building mod_perl via apxs, apxs should already be known
+ #these extra tries are for things built outside of mod_perl
+ #e.g. libapreq
+ # XXX: this may pick a wrong apxs version!
+ push @trys,
+ Apache::TestConfig::which('apxs'),
+ '/usr/local/apache/bin/apxs';
+ }
+
+ my $apxs_try;
+ for (@trys) {
+ next unless ($apxs_try = $_);
+ chomp $apxs_try;
+ if (-x $apxs_try) {
+ $self->{MP_APXS} = $apxs_try;
+ last;
+ }
+ }
+}
+
+# if MP_AP_DESTDIR was specified this sub will prepend this path to
+# any Apache-specific installation path (that option is used only by
+# package maintainers).
+sub ap_destdir {
+ my $self = shift;
+ my $path = shift || '';
+ return $path unless $self->{MP_AP_DESTDIR};
+
+ if (WIN32) {
+ my ($dest_vol, $dest_dir) = splitpath $self->{MP_AP_DESTDIR}, 1;
+ my $real_dir = (splitpath $path)[1];
+
+ $path = catpath $dest_vol, catdir($dest_dir, $real_dir), '';
+ }
+ else {
+ $path = catdir $self->{MP_AP_DESTDIR}, $path;
+ }
+
+ return canonpath $path;
+}
+
+sub apxs {
+ my $self = shift;
+
+ $self->find_apxs_util() unless defined $self->{MP_APXS};
+
+ my $is_query = (@_ == 2) && ($_[0] eq '-q');
+
+ $self = $self->build_config unless ref $self;
+
+ my $query_key;
+ if ($is_query) {
+ $query_key = 'APXS_' . uc $_[1];
+ if (exists $self->{$query_key}) {
+ return $self->{$query_key};
+ }
+ }
+
+ unless ($self->{MP_APXS}) {
+ my $prefix = $self->{MP_AP_PREFIX} || "";
+ return '' unless -d $prefix and $is_query;
+ my $val = $apxs_query{$_[1]};
+ return defined $val ? ($val ? "$prefix/$val" : $prefix) : "";
+ }
+
+ my $devnull = devnull();
+ my $val = qx($self->{MP_APXS} @_ 2>$devnull);
+ chomp $val if defined $val;
+
+ unless ($val) {
+ # do we have an error or is it just an empty value?
+ my $error = qx($self->{MP_APXS} @_ 2>&1);
+ chomp $error if defined $error;
+ if ($error) {
+ error "'$self->{MP_APXS} @_' failed:";
+ error $error;
+ }
+ else {
+ $val = '';
+ }
+ }
+
+ $self->{$query_key} = $val;
+}
+
+sub apxs_cflags {
+ my $who = caller_package(shift);
+ my $cflags = $who->apxs('-q' => 'CFLAGS');
+ $cflags =~ s/\"/\\\"/g;
+ $cflags;
+}
+
+sub apxs_extra_cflags {
+ my $who = caller_package(shift);
+ my $flags = $who->apxs('-q' => 'EXTRA_CFLAGS');
+ $flags =~ s/\"/\\\"/g;
+ $flags;
+}
+
+sub apxs_extra_cppflags {
+ my $who = caller_package(shift);
+ my $flags = $who->apxs('-q' => 'EXTRA_CPPFLAGS') ." ".
+ $who->apxs('-q' => 'NOTEST_CPPFLAGS');
+ $flags =~ s/\"/\\\"/g;
+ $flags;
+}
+
+sub caller_package {
+ my $arg = shift;
+ return ($arg and ref($arg) eq __PACKAGE__) ? $arg : __PACKAGE__;
+}
+
+my %threaded_mpms = map { $_ => 1 }
+ qw(worker winnt beos mpmt_os2 netware leader perchild threadpool
+ dynamic);
+sub mpm_is_threaded {
+ my $self = shift;
+ my $mpm_name = $self->mpm_name();
+ return exists $threaded_mpms{$mpm_name} ? 1 : 0;
+}
+
+sub mpm_name {
+ my $self = shift;
+
+ return $self->{mpm_name} if $self->{mpm_name};
+
+ if ($self->httpd_version =~ /^(\d+)\.(\d+)\.(\d+)/) {
+ delete $threaded_mpms{dynamic} if $self->mp_nonthreaded_ok;
+ return $self->{mpm_name} = 'dynamic' if ($1*1000+$2)*1000+$3>=2003000;
+ }
+
+ # XXX: hopefully apxs will work on win32 one day
+ return $self->{mpm_name} = 'winnt' if WIN32;
+
+ my $mpm_name;
+
+ # httpd >= 2.3
+ if ($self->httpd_version_as_int =~ m/^2[3-9]\d+/) {
+ $mpm_name = 'dynamic';
+ }
+ else {
+ $mpm_name = $self->apxs('-q' => 'MPM_NAME');
+ }
+
+ # building against the httpd source dir
+ unless (($mpm_name and $self->httpd_is_source_tree)) {
+ if ($self->dir) {
+ my $config_vars_file = catfile $self->dir,
+ "build", "config_vars.mk";
+ if (open my $fh, $config_vars_file) {
+ while (<$fh>) {
+ if (/MPM_NAME = (\w+)/) {
+ $mpm_name = $1;
+ last;
+ }
+ }
+ close $fh;
+ }
+ }
+ }
+
+ unless ($mpm_name) {
+ my $msg = 'Failed to obtain the MPM name.';
+ $msg .= " Please specify MP_APXS=/full/path/to/apxs to solve " .
+ "this problem." unless exists $self->{MP_APXS};
+ error $msg;
+ die "\n";
+ }
+
+ return $self->{mpm_name} = $mpm_name;
+}
+
+sub should_build_apache {
+ my ($self) = @_;
+ return $self->{MP_USE_STATIC} ? 1 : 0;
+}
+
+sub configure_apache {
+ my ($self) = @_;
+
+ unless ($self->{MP_AP_CONFIGURE}) {
+ error "You specified MP_USE_STATIC but did not specify the " .
+ "arguments to httpd's ./configure with MP_AP_CONFIGURE";
+ exit 1;
+ }
+
+ unless ($self->{MP_AP_PREFIX}) {
+ error "You specified MP_USE_STATIC but did not speficy the " .
+ "location of httpd's source tree with MP_AP_PREFIX";
+ exit 1;
+ }
+
+ debug "Configuring httpd in $self->{MP_AP_PREFIX}";
+
+ my $httpd = File::Spec->catfile($self->{MP_AP_PREFIX}, 'httpd');
+ $self->{'httpd'} ||= $httpd;
+ push @Apache::TestMM::Argv, ('httpd' => $self->{'httpd'});
+
+ my $mplibpath = '';
+ my $ldopts = $self->ldopts;
+
+ if (CYGWIN) {
+ # Cygwin's httpd port links its modules into httpd2core.dll,
+ # instead of httpd.exe. In this case, we have a problem,
+ # because libtool doesn't want to include static libs (.a)
+ # into a dynamic lib (.dll). Workaround this by setting
+ # mod_perl.a as a linker argument (including all other flags
+ # and libs).
+ my $mplib = "$self->{MP_LIBNAME}$Config{lib_ext}";
+
+ $ldopts = join ' ',
+ '--export-all-symbols',
+ '--enable-auto-image-base',
+ "$self->{cwd}/src/modules/perl/$mplib",
+ $ldopts;
+
+ $ldopts =~ s/(\S+)/-Wl,$1/g;
+
+ } else {
+ my $mplib = "$self->{MP_LIBNAME}$Config{lib_ext}";
+ $mplibpath = catfile($self->{cwd}, qw(src modules perl), $mplib);
+ }
+
+ local $ENV{BUILTIN_LIBS} = $mplibpath;
+ local $ENV{AP_LIBS} = $ldopts;
+ local $ENV{MODLIST} = 'perl';
+
+ # XXX: -Wall and/or -Werror at httpd configure time breaks things
+ local $ENV{CFLAGS} = join ' ', grep { ! /\-Wall|\-Werror/ }
+ split /\s+/, $ENV{CFLAGS} || '';
+
+ my $cd = qq(cd $self->{MP_AP_PREFIX});
+
+ # We need to clean the httpd tree before configuring it
+ if (-f File::Spec->catfile($self->{MP_AP_PREFIX}, 'Makefile')) {
+ my $cmd = qq(make clean);
+ debug "Running $cmd";
+ system("$cd && $cmd") == 0 or die "httpd: $cmd failed";
+ }
+
+ my $cmd = qq(./configure $self->{MP_AP_CONFIGURE});
+ debug "Running $cmd";
+ system("$cd && $cmd") == 0 or die "httpd: $cmd failed";
+
+ # Got to build in srclib/* early to have generated files present.
+ my $srclib = File::Spec->catfile($self->{MP_AP_PREFIX}, 'srclib');
+ $cd = qq(cd $srclib);
+ $cmd = qq(make);
+ debug "Building srclib in $srclib";
+ system("$cd && $cmd") == 0 or die "srclib: $cmd failed";
+}
+
+#--- Perl Config stuff ---
+
+my %gtop_config = ();
+sub find_gtop {
+ my $self = shift;
+
+ return %gtop_config if %gtop_config;
+
+ if (%gtop_config = find_gtop_config()) {
+ return %gtop_config;
+ }
+
+ if ($self->find_dlfile('gtop')) {
+ $gtop_config{ldopts} = $self->gtop_ldopts_old();
+ $gtop_config{ccopts} = '';
+ return %gtop_config;
+ }
+
+ return ();
+}
+
+sub find_gtop_config {
+ my %c = ();
+
+ my $ver_2_5_plus = 0;
+ if (system('pkg-config --exists libgtop-2.0') == 0) {
+ # 2.x
+ chomp($c{ccopts} = qx|pkg-config --cflags libgtop-2.0|);
+ chomp($c{ldopts} = qx|pkg-config --libs libgtop-2.0|);
+
+ # 2.0.0 bugfix
+ chomp(my $libdir = qx|pkg-config --variable=libdir libgtop-2.0|);
+ $c{ldopts} =~ s|\$\(libdir\)|$libdir|;
+
+ chomp($c{ver} = qx|pkg-config --modversion libgtop-2.0|);
+ ($c{ver_maj}, $c{ver_min}) = split /\./, $c{ver};
+ $ver_2_5_plus++ if $c{ver_maj} == 2 && $c{ver_min} >= 5;
+
+ if ($ver_2_5_plus) {
+ # some headers were removed in libgtop 2.5.0 so we need to
+ # be able to exclude them at compile time
+ $c{ccopts} .= ' -DGTOP_2_5_PLUS';
+ }
+
+ }
+ elsif (system('gnome-config --libs libgtop') == 0) {
+ chomp($c{ccopts} = qx|gnome-config --cflags libgtop|);
+ chomp($c{ldopts} = qx|gnome-config --libs libgtop|);
+
+ # buggy ( < 1.0.9?) versions fixup
+ $c{ccopts} =~ s|^/|-I/|;
+ $c{ldopts} =~ s|^/|-L/|;
+ }
+
+ # starting from 2.5.0 'pkg-config --cflags libgtop-2.0' already
+ # gives us all the cflags that are needed
+ if ($c{ccopts} && !$ver_2_5_plus) {
+ chomp(my $ginc = `glib-config --cflags`);
+ $c{ccopts} .= " $ginc";
+ }
+
+ if (%c) {
+ $c{ccopts} = " $c{ccopts}";
+ $c{ldopts} = " $c{ldopts}";
+ }
+
+ return %c;
+}
+
+my @Xlib = qw(/usr/X11/lib /usr/X11R6/lib);
+
+sub gtop_ldopts_old {
+ my $self = shift;
+ my $xlibs = "";
+
+ my ($path) = $self->find_dlfile('Xau', @Xlib);
+ if ($path) {
+ $xlibs = "-L$path -lXau";
+ }
+
+ if ($self->find_dlfile('intl')) {
+ $xlibs .= ' -lintl';
+ }
+
+ return " -lgtop -lgtop_sysdeps -lgtop_common $xlibs";
+}
+
+sub gtop_ldopts {
+ exists $gtop_config{ldopts} ? $gtop_config{ldopts} : '';
+}
+
+sub gtop_ccopts {
+ exists $gtop_config{ccopts} ? $gtop_config{ccopts} : '';
+}
+
+sub ldopts {
+ my ($self) = @_;
+
+ my $config = tied %Config;
+ my $ldflags = $config->{ldflags};
+
+ if (WIN32) {
+ $config->{ldflags} = ''; #same as lddlflags
+ }
+ elsif (DARWIN) {
+ #not sure how this can happen, but it shouldn't
+ my @bogus_flags = ('flat_namespace', 'bundle', 'undefined suppress');
+ for my $flag (@bogus_flags) {
+ $config->{ldflags} =~ s/-$flag\s*//;
+ }
+ }
+
+ my $ldopts = ExtUtils::Embed::ldopts();
+ chomp $ldopts;
+
+ my $ld = $self->perl_config('ld');
+
+ if (HPUX && $ld eq 'ld') {
+ while ($ldopts =~ s/-Wl,(\S+)/$1/) {
+ my $cp = $1;
+ (my $repl = $cp) =~ s/,/ /g;
+ $ldopts =~ s/\Q$cp/$repl/;
+ }
+ }
+
+ if ($self->{MP_USE_GTOP}) {
+ $ldopts .= $self->gtop_ldopts;
+ }
+
+ $config->{ldflags} = $ldflags; #reset
+
+ # on Irix mod_perl.so needs to see the libperl.so symbols, which
+ # requires the -exports option immediately before -lperl.
+ if (IRIX) {
+ ($ldopts =~ s/-lperl\b/-exports -lperl/)
+ or warn "Failed to fix Irix symbol exporting\n";
+ }
+
+ $ldopts;
+}
+
+my $Wall =
+ "-Wall -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations";
+
+# perl v5.6.1 and earlier produces lots of warnings, so we can't use
+# -Werror with those versions.
+$Wall .= " -Werror" if $] >= 5.006002;
+
+sub ap_ccopts {
+ my ($self) = @_;
+ my $ccopts = "-DMOD_PERL";
+
+ if ($self->{MP_USE_GTOP}) {
+ $ccopts .= " -DMP_USE_GTOP";
+ $ccopts .= $self->gtop_ccopts;
+ }
+
+ if ($self->{MP_MAINTAINER}) {
+ $self->{MP_DEBUG} = 1;
+ if ($self->perl_config('gccversion')) {
+ #same as --with-maintainter-mode
+ $ccopts .= " $Wall";
+ }
+
+ if (!OPENBSD &&
+ $self->has_gcc_version('3.3.2') &&
+ $ccopts !~ /declaration-after-statement/) {
+ debug "Adding -Wdeclaration-after-statement to ccopts";
+ $ccopts .= " -Wdeclaration-after-statement";
+ }
+ }
+
+ if ($self->{MP_COMPAT_1X}) {
+ $ccopts .= " -DMP_COMPAT_1X";
+ }
+
+ if ($self->{MP_DEBUG}) {
+ $self->{MP_TRACE} = 1;
+ my $win32_flags = MSVC ? '-Od -MD -Zi' : '';
+ my $debug_flags = WIN32 ? $win32_flags : '-g';
+ $ccopts .= " $debug_flags" unless $Config{optimize} =~ /$debug_flags/;
+ $ccopts .= ' -DMP_DEBUG';
+ }
+
+ if ($self->{MP_CCOPTS}) {
+ $ccopts .= " $self->{MP_CCOPTS}";
+ }
+
+ if ($self->{MP_TRACE}) {
+ $ccopts .= " -DMP_TRACE";
+ }
+
+ if ($self->has_gcc_version('5.0.0') && $ccopts !~ /-fgnu89-inline/) {
+ $ccopts .= " -fgnu89-inline";
+ }
+
+ if ($self->has_clang && $ccopts !~ /-std=gnu89/) {
+ $ccopts .= " -std=gnu89";
+ }
+
+ # make sure apr.h can be safely included
+ # for example Perl's included -D_GNU_SOURCE implies
+ # -D_LARGEFILE64_SOURCE on linux, but this won't happen on
+ # Solaris, so we need apr flags living in apxs' EXTRA_CPPFLAGS
+ my $extra_cppflags = $self->apxs_extra_cppflags;
+ $ccopts .= " " . $extra_cppflags;
+
+ # Make sure the evil AP_DEBUG is not defined when building mod_perl
+ $ccopts =~ s/ ?-DAP_DEBUG\b//;
+
+ $ccopts;
+}
+
+sub has_gcc_version {
+ my $self = shift;
+ my $requested_version = shift;
+
+ my $has_version = $self->perl_config('gccversion');
+
+ return 0 unless $has_version;
+
+ #Only interested in leading version digits
+ $has_version =~ s/^([0-9.]+).*/$1/;
+
+ my @tuples = split /\./, $has_version, 3;
+ my @r_tuples = split /\./, $requested_version, 3;
+
+ return cmp_tuples(\@tuples, \@r_tuples) == 1;
+}
+
+sub has_clang {
+ my $self = shift;
+
+ my $has_version = $self->perl_config('gccversion');
+
+ return 0 unless $has_version;
+
+ return $has_version =~ m/Clang/;
+}
+
+sub cmp_tuples {
+ my ($num_a, $num_b) = @_;
+
+ while (@$num_a && @$num_b) {
+ my $cmp = shift @$num_a <=> shift @$num_b;
+ return $cmp if $cmp;
+ }
+
+ return @$num_a <=> @$num_b;
+}
+
+sub perl_ccopts {
+ my $self = shift;
+
+ my $cflags = $self->strip_lfs(" $Config{ccflags} ");
+
+ my $fixup = \&{"ccopts_$^O"};
+ if (defined &$fixup) {
+ $fixup->(\$cflags);
+ }
+
+ if (WIN32 and $self->{MP_DEBUG}) {
+ #only win32 has -DDEBUGGING in both optimize and ccflags
+ my $optim = $Config{optimize};
+
+ unless ($optim =~ /-DDEBUGGING/) {
+ $cflags =~ s/$optim//;
+ }
+ }
+
+ if (CYGWIN) {
+ $cflags .= " -DCYGWIN ";
+ }
+
+ $cflags;
+}
+
+sub ccopts_hpux {
+ my $cflags = shift;
+ return if $Config{cc} eq 'gcc'; #XXX?
+ return if $$cflags =~ /(-Ae|\+e)/;
+ $$cflags .= " -Ae ";
+}
+
+# XXX: there could be more, but this is just for cosmetics
+my %cflags_dups = map { $_ => 1 } qw(-D_GNU_SOURCE -D_REENTRANT);
+sub ccopts {
+ my ($self) = @_;
+
+ my $cflags = $self->perl_ccopts . ExtUtils::Embed::perl_inc() .
+ $self->ap_ccopts;
+
+ # remove duplicates of certain cflags coming from perl and ap/apr
+ my @cflags = ();
+ my %dups = ();
+ for (split /\s+/, $cflags) {
+ if ($cflags_dups{$_}) {
+ next if $dups{$_};
+ $dups{$_}++;
+ }
+ push @cflags, $_;
+ }
+ $cflags = "@cflags";
+
+ $cflags;
+}
+
+sub ldopts_prefix {
+ my $self = shift;
+ $self->perl_config('ld') eq 'ld' ? '' : "-Wl,";
+}
+
+sub perl_config_optimize {
+ my ($self, $val) = @_;
+
+ $val ||= $Config{optimize};
+
+ if ($self->{MP_DEBUG}) {
+ return ' ' unless $Config{ccflags} =~ /-DDEBUGGING/;
+ }
+
+ $val;
+}
+
+sub perl_config_ld {
+ my ($self, $val) = @_;
+
+ $val ||= $Config{ld};
+
+ basename $val; #bleedperl hpux value is /usr/bin/ld !
+}
+
+sub perl_config_lddlflags {
+ my ($self, $val) = @_;
+
+ if ($self->{MP_DEBUG}) {
+ if (MSVC) {
+ unless ($val =~ s/-release/-debug/) {
+ $val .= ' -debug';
+ }
+ }
+ }
+
+ if (AIX) {
+ my $Wl = $self->ldopts_prefix;
+
+ # it's useless to import symbols from libperl.so this way,
+ # because perl.exp is incomplete. a better way is to link
+ # against -lperl which has all the symbols
+ $val =~ s|${Wl}-bI:\$\(PERL_INC\)/perl\.exp||;
+ # also in the case of Makefile.modperl PERL_INC is defined
+
+ # this works with at least ld(1) on powerpc-ibm-aix5.1.0.0:
+ # -berok ignores symbols resolution problems (they will be
+ # resolved at run-time
+ # -brtl prepares the object for run-time loading
+ # LDFLAGS already inserts -brtl
+ $val .= " ${Wl}-berok";
+ # XXX: instead of -berok, could make sure that we have:
+ # -Lpath/to/CORE -lperl
+ # -bI:$path/apr.exp -bI:$path/aprutil.exp -bI:$path/httpd.exp
+ # -bI:$path/modperl_*.exp
+ # - don't import modperl_*.exp in Makefile.modperl which
+ # exports -bE:$path/modperl_*.exp
+ # - can't rely on -bI:$path/perl.exp, because it's incomplete,
+ # use -lperl instead
+ # - the issue with using apr/aprutil/httpd.exp is to pick the
+ # right path if httpd wasn't yet installed
+ }
+
+ $val;
+}
+
+sub perl_config {
+ my ($self, $key) = @_;
+
+ my $val = $Config{$key} || '';
+
+ my $method = \&{"perl_config_$key"};
+ if (defined &$method) {
+ return $method->($self, $val);
+ }
+
+ return $val;
+}
+
+sub find_in_inc {
+ my $name = shift;
+ for (@INC) {
+ my $file;
+ if (-e ($file = "$_/auto/Apache2/$name")) {
+ return $file;
+ }
+ }
+}
+
+sub libpth {
+ my $self = shift;
+ $self->{libpth} ||= [split /\s+/, $Config{libpth}];
+ return wantarray ? @{ $self->{libpth} } : $self->{libpth};
+}
+
+sub find_dlfile {
+ my ($self, $name) = (shift, shift);
+
+ require DynaLoader;
+ require AutoLoader; #eek
+
+ my $found = 0;
+ my $loc = "";
+ my (@path) = ($self->libpth, @_);
+
+ for (@path) {
+ if ($found = DynaLoader::dl_findfile($_, "-l$name")) {
+ $loc = $_;
+ last;
+ }
+ }
+
+ return wantarray ? ($loc, $found) : $found;
+}
+
+sub find_dlfile_maybe {
+ my ($self, $name) = @_;
+
+ my $path = $self->libpth;
+
+ my @maybe;
+ my $lib = 'lib' . $name;
+
+ for (@$path) {
+ push @maybe, grep { ! -l $_ } <$_/$lib.*>;
+ }
+
+ return \@maybe;
+}
+
+sub lib_check {
+ my ($self, $name) = @_;
+ return unless $self->perl_config('libs') =~ /$name/;
+
+ return if $self->find_dlfile($name);
+
+ my $maybe = $self->find_dlfile_maybe($name);
+ my $suggest = @$maybe ?
+ "You could just symlink it to $maybe->[0]" :
+ 'You might need to install Perl from source';
+ $self->phat_warn(<<EOF);
+Your Perl is configured to link against lib$name,
+ but lib$name.so was not found.
+ $suggest
+EOF
+}
+
+#--- user interaction ---
+
+sub prompt {
+ my ($self, $q, $default) = @_;
+ return $default if $self->{MP_PROMPT_DEFAULT};
+ require ExtUtils::MakeMaker;
+ ExtUtils::MakeMaker::prompt($q, $default);
+}
+
+sub prompt_y {
+ my ($self, $q) = @_;
+ $self->prompt($q, 'y') =~ /^y/i;
+}
+
+sub prompt_n {
+ my ($self, $q) = @_;
+ $self->prompt($q, 'n') =~ /^n/i;
+}
+
+sub phat_warn {
+ my ($self, $msg, $abort) = @_;
+ my $level = $abort ? 'ERROR' : 'WARNING';
+ warn <<EOF;
+************* $level *************
+
+ $msg
+
+************* $level *************
+EOF
+ if ($abort) {
+ exit 1;
+ }
+ else {
+ sleep 5;
+ }
+}
+
+#--- constructors ---
+
+my $bpm = 'Apache2/BuildConfig.pm';
+
+sub build_config {
+ my $self = shift;
+ my $bpm_mtime = 0;
+
+ $bpm_mtime = (stat _)[9] if $INC{$bpm} && -e $INC{$bpm};
+
+ if (-e "lib/$bpm" and (stat _)[9] > $bpm_mtime) {
+ #reload if Makefile.PL has regenerated
+ unshift @INC, 'lib';
+ delete $INC{$bpm};
+ eval { require Apache2::BuildConfig; };
+ shift @INC;
+ }
+ else {
+ eval { require Apache2::BuildConfig; };
+ }
+
+ return bless {}, (ref($self) || $self) if $@;
+ return Apache2::BuildConfig->new;
+}
+
+sub new {
+ my $class = shift;
+
+ my $self = bless {
+ cwd => Cwd::fastcwd(),
+ MP_LIBNAME => 'mod_perl',
+ MP_APXS => undef, # so we know we haven't tried to set it yet
+ @_,
+ }, $class;
+
+ $self->{MP_APR_LIB} = 'aprext';
+
+ ModPerl::BuildOptions->init($self) if delete $self->{init};
+
+ $self;
+}
+
+sub DESTROY {}
+
+my %default_files = (
+ 'build_config' => 'lib/Apache2/BuildConfig.pm',
+ 'ldopts' => 'src/modules/perl/ldopts',
+ 'makefile' => 'src/modules/perl/Makefile',
+);
+
+sub clean_files {
+ my $self = shift;
+ [sort map { $self->default_file($_) } keys %default_files];
+}
+
+sub default_file {
+ my ($self, $name, $override) = @_;
+ my $key = join '_', 'file', $name;
+ $self->{$key} ||= ($override || $default_files{$name});
+}
+
+sub file_path {
+ my $self = shift;
+
+ # work around when Apache2::BuildConfig has not been created yet
+ return unless $self && $self->{cwd};
+
+ my @files = map { m:^/: ? $_ : join('/', $self->{cwd}, $_) } @_;
+ return wantarray ? @files : $files[0];
+}
+
+sub freeze {
+ require Data::Dumper;
+ local $Data::Dumper::Terse = 1;
+ local $Data::Dumper::Sortkeys = 1;
+ my $data = Data::Dumper::Dumper(shift);
+ chomp $data;
+ $data;
+}
+
+sub save_ldopts {
+ my ($self, $file) = @_;
+
+ $file ||= $self->default_file('ldopts', $file);
+ my $ldopts = $self->ldopts;
+
+ open my $fh, '>', $file or die "open $file: $!";
+ print $fh "#!/bin/sh\n\necho $ldopts\n";
+ close $fh;
+ chmod 0755, $file;
+}
+
+sub noedit_warning_hash {
+ ModPerl::Code::noedit_warning_hash(__PACKAGE__);
+}
+
+sub save {
+ my ($self, $file) = @_;
+
+ delete $INC{$bpm};
+
+ $file ||= $self->default_file('build_config');
+ $file = $self->file_path($file);
+
+ my $obj = $self->freeze;
+ $obj =~ s/^\s{9}//mg;
+ $obj =~ s/^/ /;
+
+ open my $fh, '>', $file or die "open $file: $!";
+
+ #work around autosplit braindeadness
+ my $package = 'package Apache2::BuildConfig';
+
+ print $fh noedit_warning_hash();
+
+ print $fh <<EOF;
+$package;
+
+use Apache2::Build ();
+
+sub new {
+$obj;
+}
+
+1;
+EOF
+
+ close $fh or die "failed to write $file: $!";
+}
+
+sub rebuild {
+ my $self = __PACKAGE__->build_config;
+ my @opts = map { qq[$_='$self->{$_}'] } sort grep /^MP_/, keys %$self;
+ my $command = "perl Makefile.PL @opts";
+ print "Running: $command\n";
+ system $command;
+}
+# % perl -MApache2::Build -e rebuild
+*main::rebuild = \&rebuild if $0 eq '-e';
+
+#--- attribute access ---
+
+sub is_dynamic { shift->{MP_USE_DSO} }
+
+sub default_dir {
+ my $build = shift->build_config;
+
+ return $build->dir || '../apache_x.x/src';
+}
+
+sub dir {
+ my ($self, $dir) = @_;
+
+ if ($dir) {
+ for (qw(ap_includedir)) {
+ delete $self->{$_};
+ }
+ if ($dir =~ m:^\.\.[/\\]:) {
+ $dir = "$self->{cwd}/$dir";
+ }
+ $self->{dir} = $dir;
+ }
+
+ return $self->{dir} if $self->{dir};
+
+ # be careful with the guesswork, or may pick up some wrong headers
+ if (IS_MOD_PERL_BUILD && $self->{MP_AP_PREFIX}) {
+ my $build = $self->build_config;
+
+ if (my $bdir = $build->{'dir'}) {
+ for ($bdir, "../$bdir", "../../$bdir") {
+ if (-d $_) {
+ $dir = $_;
+ last;
+ }
+ }
+ }
+ }
+
+ $dir ||= $self->{MP_AP_PREFIX};
+
+# we no longer install Apache headers, so don't bother looking in @INC
+# might end up finding 1.x headers anyhow
+# unless ($dir and -d $dir) {
+# for (@INC) {
+# last if -d ($dir = "$_/auto/Apache2/include");
+# }
+# }
+ return $self->{dir} = $dir ? canonpath(rel2abs $dir) : undef;
+}
+
+#--- finding apache *.h files ---
+
+sub find {
+ my $self = shift;
+ my %seen = ();
+ my @dirs = ();
+
+ for my $src_dir ($self->dir,
+ $self->default_dir,
+ '../httpd-2.0')
+ {
+ next unless $src_dir;
+ next unless (-d $src_dir || -l $src_dir);
+ next if $seen{$src_dir}++;
+ push @dirs, $src_dir;
+ #$modified{$src_dir} = (stat($src_dir))[9];
+ }
+
+ return @dirs;
+}
+
+sub ap_includedir {
+ my ($self, $d) = @_;
+
+ return $self->{ap_includedir}
+ if $self->{ap_includedir} and -d $self->{ap_includedir};
+
+ return unless $d ||= $self->apxs('-q' => 'INCLUDEDIR') || $self->dir;
+
+ if (-e "$d/include/ap_release.h") {
+ return $self->{ap_includedir} = "$d/include";
+ }
+
+ $self->{ap_includedir} = $d;
+}
+
+# This is necessary for static builds that needs to make a
+# difference between where the apache headers are (to build
+# against) and where they will be installed (to install our
+# own headers alongside)
+#
+# ap_exp_includedir is where apache is going to install its
+# headers to
+sub ap_exp_includedir {
+ my ($self) = @_;
+
+ return $self->{ap_exp_includedir} if $self->{ap_exp_includedir};
+
+ my $build_vars = File::Spec->catfile($self->{MP_AP_PREFIX},
+ qw(build config_vars.mk));
+ open my $vars, "<$build_vars" or die "Couldn't open $build_vars $!";
+ my $ap_exp_includedir;
+ while (<$vars>) {
+ if (/exp_includedir\s*=\s*(.*)/) {
+ $ap_exp_includedir = $1;
+ last;
+ }
+ }
+
+ $self->{ap_exp_includedir} = $ap_exp_includedir;
+}
+
+sub install_headers_dir {
+ my ($self) = @_;
+ if ($self->should_build_apache) {
+ return $self->ap_exp_includedir();
+ }
+ else {
+ return $self->ap_includedir();
+ }
+}
+
+
+# where apr-config and apu-config reside
+sub apr_bindir {
+ my ($self) = @_;
+
+ $self->apr_config_path unless $self->{apr_bindir};
+ $self->{apr_bindir};
+}
+
+sub apr_generation {
+ my ($self) = @_;
+ return $self->httpd_version_as_int =~ m/2[1-9]\d+/ ? 1 : 0;
+}
+
+# returns an array of apr/apu linking flags (--link-ld --libs) if found
+# an empty array otherwise
+my @apru_link_flags = ();
+sub apru_link_flags {
+ my ($self) = @_;
+
+ return @apru_link_flags if @apru_link_flags;
+
+ # first use apu_config_path and then apr_config_path in order to
+ # resolve the symbols right during linking
+ for ($self->apu_config_path, $self->apr_config_path) {
+ my $flags = '--link-ld --libs';
+ $flags .= ' --ldflags' unless (WIN32);
+ if (my $link = $_ && -x $_ && qx{$_ $flags}) {
+ chomp $link;
+
+ # Change '/path/to/libanything.la' to '-L/path/to -lanything'
+ if (CYGWIN) {
+ $link =~ s|(\S*)/lib([^.\s]+)\.\S+|-L$1 -l$2|g;
+ }
+
+ if ($self->httpd_is_source_tree) {
+ my @libs;
+ while ($link =~ m/-L(\S+)/g) {
+ my $dir = File::Spec->catfile($1, '.libs');
+ push @libs, $dir if -d $dir;
+ }
+ push @apru_link_flags, join ' ', map { "-L$_" } @libs;
+ }
+ push @apru_link_flags, $link;
+ }
+ }
+
+ return @apru_link_flags;
+}
+
+sub apr_config_path {
+ shift->apru_config_path("apr");
+}
+
+sub apu_config_path {
+ shift->apru_config_path("apu");
+}
+
+sub apru_config_path {
+ my ($self, $what) = @_;
+
+ my $key = "${what}_config_path"; # apr_config_path
+ my $mp_key = "MP_" . uc($what) . "_CONFIG"; # MP_APR_CONFIG
+ my $bindir = uc($what) . "_BINDIR"; # APR_BINDIR
+
+ return $self->{$key} if $self->{$key} and -x $self->{$key};
+
+ if (exists $self->{$mp_key} and -x $self->{$mp_key}) {
+ $self->{$key} = $self->{$mp_key};
+ }
+
+ my $config = $self->apr_generation ? "$what-1-config" : "$what-config";
+
+ if (!$self->{$key}) {
+ my @tries = ();
+ if ($self->httpd_is_source_tree) {
+ for my $base (grep defined $_, $self->dir) {
+ push @tries, grep -d $_,
+ map catdir($base, "srclib", $_), qw(apr apr-util);
+ }
+
+ # Check for MP_AP_CONFIGURE="--with-apr[-util]=DIR|FILE"
+ my $what_long = ($what eq 'apu') ? 'apr-util' : 'apr';
+ if ($self->{MP_AP_CONFIGURE} &&
+ $self->{MP_AP_CONFIGURE} =~ /--with-${what_long}=(\S+)/) {
+ my $dir = $1;
+ $dir = dirname $dir if -f $dir;
+ push @tries, grep -d $_, $dir, catdir $dir, 'bin';
+ }
+ }
+ else {
+ push @tries, grep length,
+ map $self->apxs(-q => $_), $bindir, "BINDIR";
+ push @tries, catdir $self->{MP_AP_PREFIX}, "bin"
+ if exists $self->{MP_AP_PREFIX} and -d $self->{MP_AP_PREFIX};
+ }
+
+ @tries = map { catfile $_, $config } @tries;
+ if (WIN32) {
+ my $ext = '.bat';
+ for (@tries) {
+ $_ .= $ext if ($_ and $_ !~ /$ext$/);
+ }
+ }
+
+ for my $try (@tries) {
+ next unless -x $try;
+ $self->{$key} = $try;
+ }
+ }
+
+ $self->{$key} ||= Apache::TestConfig::which($config);
+
+ # apr_bindir makes sense only if httpd/apr is installed, if we are
+ # building against the source tree we can't link against
+ # apr/aprutil libs
+ unless ($self->httpd_is_source_tree) {
+ $self->{apr_bindir} = $self->{$key}
+ ? dirname $self->{$key}
+ : '';
+ }
+
+ $self->{$key};
+}
+
+sub apr_includedir {
+ my ($self) = @_;
+
+ return $self->{apr_includedir}
+ if $self->{apr_includedir} and -d $self->{apr_includedir};
+
+ my $incdir;
+ my $apr_config_path = $self->apr_config_path;
+
+ if ($apr_config_path) {
+ my $httpd_version = $self->httpd_version;
+ chomp($incdir = `$apr_config_path --includedir`);
+ }
+
+ unless ($incdir and -d $incdir) {
+ # falling back to the default when apr header files are in the
+ # same location as the httpd header files
+ $incdir = $self->ap_includedir;
+ }
+
+ my @tries = ($incdir);
+ if ($self->httpd_is_source_tree) {
+ my $path = catdir $self->dir, "srclib", "apr", "include";
+ push @tries, $path if -d $path;
+ }
+
+
+ for (@tries) {
+ next unless $_ && -e catfile $_, "apr.h";
+ $self->{apr_includedir} = $_;
+ last;
+ }
+
+ unless ($self->{apr_includedir}) {
+ error "Can't find apr include/ directory,",
+ "use MP_APR_CONFIG=/path/to/apr-config";
+ exit 1;
+ }
+
+ $self->{apr_includedir};
+}
+
+#--- parsing apache *.h files ---
+
+sub mmn_eq {
+ my ($class, $dir) = @_;
+
+ return 1 if WIN32; #just assume, till Apache2::Build works under win32
+
+ my $instsrc;
+ {
+ local @INC = grep { !/blib/ } @INC;
+ my $instdir;
+ for (@INC) {
+ last if -d ($instdir = "$_/auto/Apache2/include");
+ }
+ $instsrc = $class->new(dir => $instdir);
+ }
+ my $targsrc = $class->new($dir ? (dir => $dir) : ());
+
+ my $inst_mmn = $instsrc->module_magic_number;
+ my $targ_mmn = $targsrc->module_magic_number;
+
+ unless ($inst_mmn && $targ_mmn) {
+ return 0;
+ }
+ if ($inst_mmn == $targ_mmn) {
+ return 1;
+ }
+ print "Installed MMN $inst_mmn does not match target $targ_mmn\n";
+
+ return 0;
+}
+
+sub module_magic_number {
+ my $self = shift;
+
+ return $self->{mmn} if $self->{mmn};
+
+ my $d = $self->ap_includedir;
+
+ return 0 unless $d;
+
+ #return $mcache{$d} if $mcache{$d};
+ my $fh;
+ for (qw(ap_mmn.h http_config.h)) {
+ last if open $fh, "$d/$_";
+ }
+ return 0 unless $fh;
+
+ my $n;
+ my $mmn_pat = join '|', qw(MODULE_MAGIC_NUMBER_MAJOR MODULE_MAGIC_NUMBER);
+ while(<$fh>) {
+ if(s/^\#define\s+($mmn_pat)\s+(\d+).*/$2/) {
+ chomp($n = $_);
+ last;
+ }
+ }
+ close $fh;
+
+ $self->{mmn} = $n
+}
+
+sub fold_dots {
+ my $v = shift;
+ $v =~ s/\.//g;
+ $v .= '0' if length $v < 3;
+ $v;
+}
+
+sub httpd_version_as_int {
+ my ($self, $dir) = @_;
+ my $v = $self->httpd_version($dir);
+ fold_dots($v);
+}
+
+sub httpd_version_cache {
+ my ($self, $dir, $v) = @_;
+ return '' unless $dir;
+ $self->{httpd_version}->{$dir} = $v if $v;
+ $self->{httpd_version}->{$dir};
+}
+
+sub httpd_version {
+ my ($self, $dir) = @_;
+
+ return unless $dir = $self->ap_includedir($dir);
+
+ if (my $v = $self->httpd_version_cache($dir)) {
+ return $v;
+ }
+
+ my $header = "$dir/ap_release.h";
+ open my $fh, $header or do {
+ error "Unable to open $header: $!";
+ return undef;
+ };
+
+ my $version;
+
+ while (<$fh>) {
+ #now taking bets on how many friggin times this will change
+ #over the course of apache 2.0. 1.3 changed it at least a half
+ #dozen times. hopefully it'll stay in the same file at least.
+ if (/^\#define\s+AP_SERVER_MAJORVERSION\s+\"(\d+)\"/) {
+ #XXX could be more careful here. whatever. see above.
+ my $major = $1;
+ my $minor = (split /\s+/, scalar(<$fh>))[-1];
+ my $patch = (split /\s+/, scalar(<$fh>))[-1];
+ $version = join '.', $major, $minor, $patch;
+ $version =~ s/\"//g;
+ last;
+ }
+ elsif (/^\#define\s+AP_SERVER_BASEREVISION\s+\"(.*)\"/) {
+ $version = $1;
+ last;
+ }
+ elsif(/^\#define\s+AP_SERVER_MAJORVERSION_NUMBER\s+(\d+)/) {
+ # new 2.1 config
+ my $major = $1;
+ my $minor = (split /\s+/, scalar(<$fh>))[-1];
+ my $patch = (split /\s+/, scalar(<$fh>))[-1];
+
+ my ($define, $macro, $dev) = (split /\s+/, scalar(<$fh>));
+
+ if ($macro =~ /AP_SERVER_DEVBUILD_BOOLEAN/ && $dev eq '1') {
+ $dev = "-dev";
+ }
+ else {
+ $dev = "";
+ }
+
+ $version = join '.', $major, $minor, "$patch$dev";
+ $version =~ s/\"//g;
+ last;
+ }
+ }
+
+ close $fh;
+
+ debug "parsed version $version from ap_release.h";
+
+ $self->httpd_version_cache($dir, $version);
+}
+
+my %wanted_apr_config = map { $_, 1} qw(
+ HAS_THREADS HAS_DSO HAS_MMAP HAS_RANDOM HAS_SENDFILE
+ HAS_LARGE_FILES HAS_INLINE HAS_FORK
+);
+
+sub get_apr_config {
+ my $self = shift;
+
+ return $self->{apr_config} if $self->{apr_config};
+
+ my $fh;
+ my $header = catfile $self->apr_includedir, "apr.h";
+ if (WIN32) {
+ open $fh, $header or do {
+ error "Unable to open $header: $!";
+ return undef;
+ };
+ }
+ else {
+ my @command = ($self->perl_config('cpp'), '-E', '-dM', $header);
+ open $fh, '-|', @command or do {
+ error "Unable to preprocess $header with @command: $!";
+ return undef;
+ };
+ }
+
+ my %cfg;
+ while (<$fh>) {
+ next unless s/^\#define\s+APR_((HAVE|HAS|USE)_\w+)/$1/;
+ chomp;
+ my ($name, $val) = split /\s+/, $_, 2;
+ next unless $wanted_apr_config{$name};
+ $val =~ s/\s+$//;
+ next unless $val =~ /^\d+$/;
+ $cfg{$name} = $val;
+ }
+
+ $self->{apr_config} = \%cfg;
+}
+
+#--- generate Makefile ---
+
+sub canon_make_attr {
+ my ($self, $name) = (shift, shift);
+
+ my $attr = join '_', 'MODPERL', uc $name;
+ $self->{$attr} = "@_";
+ "$attr = $self->{$attr}\n\n";
+}
+
+sub xsubpp {
+ my $self = shift;
+ my $xsubpp = join ' ', '$(MODPERL_PERLPATH)',
+ '$(MODPERL_PRIVLIBEXP)/ExtUtils/xsubpp',
+ '-typemap', '$(MODPERL_PRIVLIBEXP)/ExtUtils/typemap';
+
+ my $typemap = $self->file_path('lib/typemap');
+ if (-e $typemap) {
+ $xsubpp .= join ' ',
+ ' -typemap', $typemap;
+ }
+
+ $xsubpp;
+}
+
+sub make_xs {
+ my ($self, $fh) = @_;
+
+ print $fh $self->canon_make_attr(xsubpp => $self->xsubpp);
+
+ return [] unless $self->{XS};
+
+ my @files;
+ my @xs_targ;
+
+ foreach my $name (sort keys %{ $self->{XS} }) {
+ my $xs = $self->{XS}->{$name};
+ #Foo/Bar.xs => Foo_Bar.c
+ (my $c = $xs) =~ s:.*?WrapXS/::;
+ $c =~ s:/:_:g;
+ $c =~ s:\.xs$:.c:;
+
+ push @files, $c;
+
+ push @xs_targ, <<EOF;
+$c: $xs
+\t\$(MODPERL_XSUBPP) $xs > \$*.xsc && \$(MODPERL_MV) \$*.xsc \$@
+
+EOF
+ }
+
+ my %o = (xs_o_files => 'o', xs_o_pic_files => 'lo');
+
+ for my $ext (qw(xs_o_files xs_o_pic_files)) {
+ print $fh $self->canon_make_attr($ext, map {
+ (my $file = $_) =~ s/c$/$o{$ext}/; $file;
+ } @files);
+ }
+
+ print $fh $self->canon_make_attr(xs_clean_files => @files);
+
+ \@xs_targ;
+}
+
+#when we use a bit of MakeMaker, make it use our values for these vars
+my %perl_config_pm_alias = (
+ ABSPERL => 'perlpath',
+ ABSPERLRUN => 'perlpath',
+ PERL => 'perlpath',
+ PERLRUN => 'perlpath',
+ PERL_LIB => 'privlibexp',
+ PERL_ARCHLIB => 'archlibexp',
+);
+
+my $mm_replace = join '|', keys %perl_config_pm_alias;
+
+# get rid of dups
+my %perl_config_pm_alias_values = reverse %perl_config_pm_alias;
+my @perl_config_pm_alias_values = keys %perl_config_pm_alias_values;
+
+my @perl_config_pm = sort(@perl_config_pm_alias_values, qw(cc cpprun
+ rm ranlib lib_ext obj_ext cccdlflags lddlflags optimize));
+
+sub mm_replace {
+ my $val = shift;
+ $$val =~ s/\(($mm_replace)\)/(MODPERL_\U$perl_config_pm_alias{$1})/g;
+}
+
+#help prevent warnings
+my @mm_init_vars = (BASEEXT => '', NAME => '');
+
+sub make_tools {
+ my ($self, $fh) = @_;
+
+ for (@perl_config_pm) {
+ print $fh $self->canon_make_attr($_, $self->perl_config($_));
+ }
+
+ require ExtUtils::MakeMaker;
+ my $mm = bless { @mm_init_vars }, 'MM';
+
+ # Fake initialize MakeMaker
+ foreach my $m (qw(init_main init_others init_tools)) {
+ $mm->$m() if $mm->can($m);
+
+ # init_main() undefines the BASEEXT member which we initialized
+ # to a blank string to prevent warnings; reset it now
+ $mm->{BASEEXT} = '' if not defined $mm->{BASEEXT};
+ }
+
+ for (qw(rm_f mv ld ar cp test_f)) {
+ my $val = $mm->{"\U$_"};
+ if ($val) {
+ mm_replace(\$val);
+ }
+ else {
+ $val = $Config{$_};
+ }
+ print $fh $self->canon_make_attr($_ => $val);
+ }
+}
+
+sub export_files_MSWin32 {
+ my $self = shift;
+ my $xs_dir = $self->file_path("xs");
+ "-def:$xs_dir/modperl.def";
+}
+
+sub export_files_aix {
+ my $self = shift;
+
+ my $Wl = $self->ldopts_prefix;
+ # there are several modperl_*.exp, not just $(BASEEXT).exp
+ # $(BASEEXT).exp resolves to modperl_global.exp
+ my $xs_dir = $self->file_path("xs");
+ join " ", map "${Wl}-bE:$xs_dir/modperl_$_.exp", qw(inline ithreads);
+}
+
+sub dynamic_link_header_default {
+ return <<'EOF';
+$(MODPERL_LIBNAME).$(MODPERL_DLEXT): $(MODPERL_PIC_OBJS)
+ $(MODPERL_RM_F) $@
+ $(MODPERL_LD) $(MODPERL_LDDLFLAGS) \
+ $(MODPERL_AP_LIBS) \
+ $(MODPERL_PIC_OBJS) $(MODPERL_LDOPTS) \
+EOF
+}
+
+sub dynamic_link_default {
+ my $self = shift;
+
+ my $link = $self->dynamic_link_header_default . "\t" . '-o $@';
+
+ my $ranlib = "\t" . '$(MODPERL_RANLIB) $@' . "\n";
+
+ $link .= "\n" . $ranlib unless (DARWIN or OPENBSD);
+
+ $link;
+}
+
+sub dynamic_link_MSWin32 {
+ my $self = shift;
+ my $defs = $self->export_files_MSWin32;
+ my $symbols = $self->modperl_symbols_MSWin32;
+ return $self->dynamic_link_header_default .
+ "\t$defs" .
+ ($symbols ? ' \\' . "\n\t-pdb:$symbols" : '') .
+ ' -out:$@' . "\n\t" .
+ 'if exist $(MODPERL_MANIFEST_LOCATION)' . " \\\n\t" .
+ 'mt /nologo /manifest $(MODPERL_MANIFEST_LOCATION)' . " \\\n\t" .
+ '/outputresource:$@;2' . "\n\n";
+}
+
+sub dynamic_link_aix {
+ my $self = shift;
+ my $link = $self->dynamic_link_header_default .
+ "\t" . $self->export_files_aix . " \\\n" .
+ "\t" . '-o $@' . " \n" .
+ "\t" . '$(MODPERL_RANLIB) $@';
+}
+
+sub dynamic_link_cygwin {
+ my $self = shift;
+ return <<'EOF';
+$(MODPERL_LIBNAME).$(MODPERL_DLEXT): $(MODPERL_PIC_OBJS)
+ $(MODPERL_RM_F) $@
+ $(MODPERL_CC) -shared -o $@ \
+ -Wl,--out-implib=$(MODPERL_LIBNAME).dll.a \
+ -Wl,--export-all-symbols -Wl,--enable-auto-import \
+ -Wl,--enable-auto-image-base -Wl,--stack,8388608 \
+ $(MODPERL_PIC_OBJS) \
+ $(MODPERL_LDDLFLAGS) $(MODPERL_LDOPTS) \
+ $(MODPERL_AP_LIBS)
+ $(MODPERL_RANLIB) $@
+EOF
+}
+
+sub dynamic_link {
+ my $self = shift;
+ my $link = \&{"dynamic_link_$^O"};
+ $link = \&dynamic_link_default unless defined &$link;
+ $link->($self);
+}
+
+# Returns the link flags for the apache shared core library
+my $apache_corelib_cygwin;
+sub apache_corelib_cygwin {
+ return $apache_corelib_cygwin if $apache_corelib_cygwin;
+
+ my $self = shift;
+ my $mp_src = "$self->{cwd}/src/modules/perl";
+ my $core = 'httpd2core';
+
+ # There's a problem with user-installed perl on cygwin.
+ # MakeMaker doesn't know about the .dll.a libs and warns
+ # about missing -lhttpd2core. "Fix" it by copying
+ # the lib and adding .a suffix.
+ # For the static build create a soft link, because libhttpd2core.dll.a
+ # doesn't exist at this time.
+ if ($self->is_dynamic) {
+ my $libpath = $self->apxs(-q => 'exp_libdir');
+ File::Copy::copy("$libpath/lib$core.dll.a", "$mp_src/lib$core.a");
+ } else {
+ my $libpath = catdir($self->{MP_AP_PREFIX}, '.libs');
+ mkdir $libpath unless -d $libpath;
+ qx{touch $libpath/lib$core.dll.a && \
+ ln -fs $libpath/lib$core.dll.a $mp_src/lib$core.a};
+ }
+
+ $apache_corelib_cygwin = "-L$mp_src -l$core";
+}
+
+sub apache_libs_MSWin32 {
+ my $self = shift;
+ my $prefix = $self->apxs(-q => 'PREFIX') || $self->dir;
+ my $lib = catdir $prefix, 'lib';
+ opendir(my $dir, $lib) or die qq{Cannot opendir $lib: $!};
+ my @libs = map {catfile($lib, $_)}
+ grep /^lib(apr|aprutil|httpd)\b\S*?\.lib$/, readdir $dir;
+ closedir $dir;
+ "@libs";
+}
+
+sub apache_libs_cygwin {
+ my $self = shift;
+ join ' ', $self->apache_corelib_cygwin, $self->apru_link_flags;
+}
+
+sub apache_libs {
+ my $self = shift;
+ my $libs = \&{"apache_libs_$^O"};
+ return "" unless defined &$libs;
+ $libs->($self);
+}
+
+sub modperl_libs_MSWin32 {
+ my $self = shift;
+ "$self->{cwd}/src/modules/perl/$self->{MP_LIBNAME}.lib";
+}
+
+sub modperl_libs_cygwin {
+ my $self = shift;
+ return '' unless $self->is_dynamic;
+ return "-L$self->{cwd}/src/modules/perl -l$self->{MP_LIBNAME}";
+}
+
+sub modperl_libs {
+ my $self = shift;
+ my $libs = \&{"modperl_libs_$^O"};
+ return "" unless defined &$libs;
+ $libs->($self);
+}
+
+sub modperl_libpath_MSWin32 {
+ my $self = shift;
+ # mod_perl.lib will be installed into MP_AP_PREFIX/lib
+ # for use by 3rd party xs modules
+ "$self->{cwd}/src/modules/perl/$self->{MP_LIBNAME}.lib";
+}
+
+sub modperl_libpath_cygwin {
+ my $self = shift;
+ "$self->{cwd}/src/modules/perl/$self->{MP_LIBNAME}.dll.a";
+}
+
+sub modperl_libpath {
+ my $self = shift;
+ my $libpath = \&{"modperl_libpath_$^O"};
+ return "" unless defined &$libpath;
+ $libpath->($self);
+}
+
+# returns the directory and name of the aprext lib built under blib/
+sub mp_apr_blib {
+ my $self = shift;
+ return unless (my $mp_apr_lib = $self->{MP_APR_LIB});
+ my $lib_mp_apr_lib = 'lib' . $mp_apr_lib;
+ my @dirs = qw(blib arch auto);
+ my $apr_blib = catdir $self->{cwd}, @dirs, $lib_mp_apr_lib;
+ my $full_libname = $lib_mp_apr_lib . $Config{lib_ext};
+ return ($apr_blib, $full_libname);
+}
+
+sub mp_apr_lib_MSWin32 {
+ my $self = shift;
+ # The MP_APR_LIB will be installed into MP_AP_PREFIX/lib
+ # for use by 3rd party xs modules
+ my ($dir, $lib) = $self->mp_apr_blib();
+ $lib =~ s[^lib(\w+)$Config{lib_ext}$][$1];
+ $dir = Win32::GetShortPathName($dir);
+ return qq{ -L$dir -l$lib };
+}
+
+sub mp_apr_lib_cygwin {
+ my $self = shift;
+ my ($dir, $lib) = $self->mp_apr_blib();
+ $lib =~ s[^lib(\w+)$Config{lib_ext}$][$1];
+ my $libs = "-L$dir -l$lib";
+
+ # This is ugly, but is the only way to prevent the "undefined
+ # symbols" error
+ $libs .= join ' ', '',
+ '-L' . catdir($self->perl_config('archlibexp'), 'CORE'), '-lperl';
+
+ $libs;
+}
+
+# linking used for the aprext lib used to build APR/APR::*
+sub mp_apr_lib {
+ my $self = shift;
+ my $libs = \&{"mp_apr_lib_$^O"};
+ return "" unless defined &$libs;
+ $libs->($self);
+}
+
+sub modperl_symbols_MSWin32 {
+ my $self = shift;
+ return "" unless $self->{MP_DEBUG};
+ "$self->{cwd}/src/modules/perl/$self->{MP_LIBNAME}.pdb";
+}
+
+sub modperl_symbols {
+ my $self = shift;
+ my $symbols = \&{"modperl_symbols_$^O"};
+ return "" unless defined &$symbols;
+ $symbols->($self);
+}
+
+sub write_src_makefile {
+ my $self = shift;
+ my $code = ModPerl::Code->new;
+ my $path = $code->path;
+
+ my $install = <<'EOI';
+install:
+EOI
+ if (!$self->should_build_apache) {
+ $install .= <<'EOI';
+# install mod_perl.so
+ @$(MKPATH) $(DESTDIR)$(MODPERL_AP_LIBEXECDIR)
+ $(MODPERL_TEST_F) $(MODPERL_LIB_DSO) && \
+ $(MODPERL_CP) $(MODPERL_LIB_DSO) $(DESTDIR)$(MODPERL_AP_LIBEXECDIR)
+EOI
+ }
+
+ $install .= <<'EOI';
+# install mod_perl .h files
+ @$(MKPATH) $(DESTDIR)$(MODPERL_AP_INCLUDEDIR)
+ $(MODPERL_CP) $(MODPERL_H_FILES) $(DESTDIR)$(MODPERL_AP_INCLUDEDIR)
+EOI
+
+ my $mf = $self->default_file('makefile');
+
+ open my $fh, '>', $mf or die "open $mf: $!";
+
+ print $fh noedit_warning_hash();
+
+ print $fh $self->canon_make_attr('makefile', basename $mf);
+
+ $self->make_tools($fh);
+
+ print $fh $self->canon_make_attr('ap_libs', $self->apache_libs);
+
+ print $fh $self->canon_make_attr('libname', $self->{MP_LIBNAME});
+ print $fh $self->canon_make_attr('dlext', 'so'); #always use .so
+
+ if (AIX) {
+ my $xs_dir = $self->file_path("xs");
+ print $fh "BASEEXT = $xs_dir/modperl_global\n\n";
+ }
+
+ my %libs = (
+ dso => "$self->{MP_LIBNAME}.$self->{MODPERL_DLEXT}",
+ static => "$self->{MP_LIBNAME}$self->{MODPERL_LIB_EXT}",
+ );
+
+ #XXX short-term compat for Apache::TestConfigPerl
+ $libs{shared} = $libs{dso};
+
+ foreach my $type (sort keys %libs) {
+ my $lib = $libs{$type};
+ print $fh $self->canon_make_attr("lib_$type", $libs{$type});
+ }
+
+ if (my $symbols = $self->modperl_symbols) {
+ print $fh $self->canon_make_attr('lib_symbols', $symbols);
+ $install .= <<'EOI';
+# install mod_perl symbol file
+ @$(MKPATH) $(MODPERL_AP_LIBEXECDIR)
+ $(MODPERL_TEST_F) $(MODPERL_LIB_SYMBOLS) && \
+ $(MODPERL_CP) $(MODPERL_LIB_SYMBOLS) $(MODPERL_AP_LIBEXECDIR)
+EOI
+ }
+
+ if ($self->is_dynamic && (my $libs = $self->modperl_libpath)) {
+ print $fh $self->canon_make_attr('lib_location', $libs);
+
+ # Visual Studio 8 on Win32 uses manifest files
+ if (WIN32) {
+ (my $manifest = $libs) =~ s/\.lib$/.so.manifest/;
+ print $fh $self->canon_make_attr('manifest_location', $manifest);
+ }
+
+ print $fh $self->canon_make_attr('ap_libdir',
+ $self->ap_destdir(catdir $self->{MP_AP_PREFIX}, 'lib')
+ );
+
+ $install .= <<'EOI';
+# install mod_perl.lib
+ @$(MKPATH) $(MODPERL_AP_LIBDIR)
+ $(MODPERL_TEST_F) $(MODPERL_LIB_LOCATION) && \
+ $(MODPERL_CP) $(MODPERL_LIB_LOCATION) $(MODPERL_AP_LIBDIR)
+EOI
+ }
+
+ my $libperl = join '/',
+ $self->perl_config('archlibexp'), 'CORE', $self->perl_config('libperl');
+
+ #this is only used for deps, if libperl has changed, relink mod_perl.so
+ #not all perl dists put libperl where it should be, so just leave this
+ #out if it isn't in the proper place
+ if (-e $libperl) {
+ print $fh $self->canon_make_attr('libperl', $libperl);
+ }
+
+ for my $method (qw(ccopts ldopts inc)) {
+ print $fh $self->canon_make_attr($method, $self->$method());
+ }
+
+ for my $method (qw(c_files o_files o_pic_files h_files)) {
+ print $fh $self->canon_make_attr($method, @{ $code->$method() });
+ }
+
+ my @libs;
+ for my $type (sort map { uc } keys %libs) {
+ next unless $self->{"MP_USE_$type"};
+ # on win32 mod_perl.lib must come after mod_perl.so
+ $type eq 'STATIC'
+ ? push @libs, $self->{"MODPERL_LIB_$type"}
+ : unshift @libs, $self->{"MODPERL_LIB_$type"};
+ }
+
+ print $fh $self->canon_make_attr('lib', "@libs");
+
+ print $fh $self->canon_make_attr('AP_INCLUDEDIR',
+ $self->ap_destdir($self->install_headers_dir));
+
+ print $fh $self->canon_make_attr('AP_LIBEXECDIR',
+ $self->ap_destdir($self->apxs(-q => 'LIBEXECDIR')));
+
+ my $xs_targ = $self->make_xs($fh);
+
+ print $fh <<'EOF';
+MODPERL_CCFLAGS = $(MODPERL_INC) $(MODPERL_CCOPTS) $(MODPERL_OPTIMIZE)
+
+MODPERL_CCFLAGS_SHLIB = $(MODPERL_CCFLAGS) $(MODPERL_CCCDLFLAGS)
+
+MODPERL_OBJS = $(MODPERL_O_FILES) $(MODPERL_XS_O_FILES)
+
+MODPERL_PIC_OBJS = $(MODPERL_O_PIC_FILES) $(MODPERL_XS_O_PIC_FILES)
+
+MKPATH = $(MODPERL_PERLPATH) "-MExtUtils::Command" -e mkpath
+
+all: lib
+
+lib: $(MODPERL_LIB)
+
+EOF
+
+ print $fh $install;
+
+ print $fh <<'EOF' if DMAKE;
+
+.USESHELL :
+EOF
+
+ print $fh <<'EOF';
+
+.SUFFIXES: .xs .c $(MODPERL_OBJ_EXT) .lo .i .s
+
+.c.lo:
+ $(MODPERL_CC) $(MODPERL_CCFLAGS_SHLIB) \
+ -c $< && $(MODPERL_MV) $*$(MODPERL_OBJ_EXT) $*.lo
+
+.c$(MODPERL_OBJ_EXT):
+ $(MODPERL_CC) $(MODPERL_CCFLAGS) -c $<
+
+.c.i:
+ $(MODPERL_CPPRUN) $(MODPERL_CCFLAGS) -c $< > $*.i
+
+.c.s:
+ $(MODPERL_CC) -O -S $(MODPERL_CCFLAGS) -c $<
+
+.xs.c:
+ $(MODPERL_XSUBPP) $*.xs >$@
+
+.xs$(MODPERL_OBJ_EXT):
+ $(MODPERL_XSUBPP) $*.xs >$*.c
+ $(MODPERL_CC) $(MODPERL_CCFLAGS) -c $*.c
+
+.xs.lo:
+ $(MODPERL_XSUBPP) $*.xs >$*.c
+ $(MODPERL_CC) $(MODPERL_CCFLAGS_SHLIB) \
+ -c $*.c && $(MODPERL_MV) $*$(MODPERL_OBJ_EXT) $*.lo
+
+clean:
+ $(MODPERL_RM_F) *.a *.so *.xsc \
+ $(MODPERL_LIBNAME).exp $(MODPERL_LIBNAME).lib \
+ *$(MODPERL_OBJ_EXT) *.lo *.i *.s *.pdb *.manifest \
+ $(MODPERL_CLEAN_FILES) \
+ $(MODPERL_XS_CLEAN_FILES)
+
+$(MODPERL_OBJS): $(MODPERL_H_FILES) $(MODPERL_MAKEFILE)
+$(MODPERL_PIC_OBJS): $(MODPERL_H_FILES) $(MODPERL_MAKEFILE)
+$(MODPERL_LIB): $(MODPERL_LIBPERL)
+
+$(MODPERL_LIBNAME)$(MODPERL_LIB_EXT): $(MODPERL_OBJS)
+ $(MODPERL_RM_F) $@
+ $(MODPERL_AR) crv $@ $(MODPERL_OBJS)
+ $(MODPERL_RANLIB) $@
+
+EOF
+
+ print $fh $self->dynamic_link;
+
+ print $fh @$xs_targ;
+
+ print $fh "\n"; # Makefile must end with \n to avoid warnings
+
+ close $fh;
+}
+
+#--- generate MakeMaker parameter values ---
+
+sub otherldflags_default {
+ my $self = shift;
+ # e.g. aix's V:ldflags feeds -brtl and other flags
+ $self->perl_config('ldflags');
+}
+
+sub otherldflags {
+ my $self = shift;
+ my $flags = \&{"otherldflags_$^O"};
+ return $self->otherldflags_default unless defined &$flags;
+ $flags->($self);
+}
+
+sub otherldflags_MSWin32 {
+ my $self = shift;
+ my $flags = $self->otherldflags_default;
+ $flags .= ' -pdb:$(INST_ARCHAUTODIR)\$(BASEEXT).pdb' if $self->{MP_DEBUG};
+ $flags;
+}
+
+sub typemaps {
+ my $self = shift;
+ my @typemaps = ();
+
+ # XXX: could move here the code from ModPerl::BuildMM
+ return [] if IS_MOD_PERL_BUILD;
+
+ # for post install use
+ for (@INC) {
+ # make sure not to pick mod_perl 1.0 typemap
+ my $file = "$_/auto/Apache2/typemap";
+ push @typemaps, $file if -e $file;
+ }
+
+ return \@typemaps;
+}
+
+sub includes {
+ my $self = shift;
+
+ my @inc = ();
+
+ unless (IS_MOD_PERL_BUILD) {
+ # XXX: what if apxs is not available? win32?
+ my $ap_inc = $self->apxs('-q' => 'INCLUDEDIR');
+ if ($ap_inc && -d $ap_inc) {
+ push @inc, $ap_inc;
+ return \@inc;
+ }
+
+ # this is fatal
+ my $reason = $ap_inc
+ ? "path $ap_inc doesn't exist"
+ : "apxs -q INCLUDEDIR didn't return a value";
+ die "Can't find the mod_perl include dir (reason: $reason)";
+ }
+
+ my $os = WIN32 ? 'win32' : 'unix';
+ push @inc, $self->file_path("src/modules/perl", "xs");
+
+ push @inc, $self->mp_include_dir;
+
+ unless ($self->httpd_is_source_tree) {
+ push @inc, $self->apr_includedir;
+
+ my $apuc = $self->apu_config_path;
+ if ($apuc && -x $apuc) {
+ chomp(my $apuincs = qx($apuc --includes));
+ # win32: /Ipath, elsewhere -Ipath
+ $apuincs =~ s{^\s*(-|/)I}{};
+ push @inc, $apuincs;
+ }
+
+ my $ainc = $self->apxs('-q' => 'INCLUDEDIR');
+ if (-d $ainc) {
+ push @inc, $ainc;
+ return \@inc;
+ }
+ }
+
+ if ($self->{MP_AP_PREFIX}) {
+ my $src = $self->dir;
+ for ("$src/modules/perl", "$src/include",
+ "$src/srclib/apr/include",
+ "$src/srclib/apr-util/include",
+ "$src/os/$os")
+ {
+ push @inc, $_ if -d $_;
+ }
+ }
+
+ return \@inc;
+}
+
+sub inc {
+ local $_;
+ my @includes = map { "-I$_" } @{ shift->includes };
+ "@includes";
+}
+
+### Picking the right LFS support flags for mod_perl, by Joe Orton ###
+#
+# on Unix systems where by default off_t is a "long", a 32-bit integer,
+# there are two different ways to get "large file" support, i.e. the
+# ability to manipulate files bigger than 2Gb:
+#
+# 1) you compile using -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64. This
+# makes sys/types.h expose off_t as a "long long", a 64-bit integer, and
+# changes the size of a few other types too. The C library headers
+# automatically arrange to expose a correct implementation of functions
+# like lseek() which take off_t parameters.
+#
+# 2) you compile using -D_LARGEFILE64_SOURCE, and use what is called the
+# "transitional" interface. This means that the system headers expose a
+# new type, "off64_t", which is a long long, but the size of off_t is not
+# changed. A bunch of new functions like lseek64() are exposed by the C
+# library headers, which take off64_t parameters in place of off_t.
+#
+# Perl built with -Duselargefiles uses approach (1).
+#
+# APR HEAD uses (2) by default. APR 0.9 does not by default use either
+# approach, but random users can take a httpd-2.0.49 tarball, and do:
+#
+# export CPPFLAGS="-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64"
+# ./configure
+#
+# to build a copy of apr/httpd which uses approach (1), though this
+# isn't really a supported configuration.
+#
+# The problem that mod_perl has to work around is when you take a
+# package built with approach (1), i.e. Perl, and any package which was
+# *not* built with (1), i.e. APR, and want to interface between
+# them. [1]
+#
+# So what you want to know is whether APR was built using approach (1)
+# or not. APR_HAS_LARGE_FILES in HEAD just tells you whether APR was
+# built using approach (2) or not, which isn't useful in solving this
+# problem.
+#
+# [1]: In some cases, it may be OK to interface between packages which
+# use (1) and packages which use (2). APR HEAD is currently not such a
+# case, since the size of apr_ino_t is still changing when
+# _FILE_OFFSET_BITS is defined.
+#
+# If you want to see how this matters, get some httpd function to do at
+# the very beginning of main():
+#
+# printf("sizeof(request_rec) = %lu, sizeof(apr_finfo_t) = %ul",
+# sizeof(request_rec), sizeof(apr_finfo_t));
+#
+# and then put the same printf in mod_perl somewhere, and see the
+# differences. This is why it is a really terribly silly idea to ever
+# use approach (1) in anything other than an entirely self-contained
+# application.
+#
+# there is no conflict if both libraries either have or don't have
+# large files support enabled
+sub has_large_files_conflict {
+ my $self = shift;
+
+ my $apxs_flags = join $self->apxs_extra_cflags, $self->apxs_extra_cppflags;
+ my $apr_lfs64 = $apxs_flags =~ /-D_FILE_OFFSET_BITS=64/;
+ my $perl_lfs64 = $Config{ccflags} =~ /-D_FILE_OFFSET_BITS=64/;
+
+ # XXX: we don't really deal with the case where APR was built with
+ # -D_FILE_OFFSET_BITS=64 but perl wasn't, since currently we strip
+ # only perl's ccflags, not apr's flags. the reason we don't deal
+ # with it is that we didn't have such a case yet, but may need to
+ # deal with it later
+
+ return 0;
+ # $perl_lfs64 ^ $apr_lfs64;
+}
+
+# if perl is built with uselargefiles, but apr not, the build won't
+# work together as it uses two binary incompatible libraries, so
+# reduce the functionality to the greatest common denominator (C code
+# will have to make sure to prevent any operations that may rely on
+# effects created by uselargefiles, e.g. Off_t=8 instead of Off_t=4)
+sub strip_lfs {
+ my ($self, $cflags) = @_;
+ return $cflags unless $self->has_large_files_conflict();
+
+ my $lf = $Config{ccflags_uselargefiles}
+ || '-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64';
+ $cflags =~ s/$lf//;
+ $cflags;
+}
+
+sub define {
+ my $self = shift;
+
+ return "";
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Apache2::Build - Methods for locating and parsing bits of Apache source code
+
+=head1 SYNOPSIS
+
+ use Apache2::Build ();
+ my $build = Apache2::Build->new;
+
+ # rebuild mod_perl with build opts from the previous build
+ % cd modperl-2.0
+ % perl -MApache2::Build -e rebuild
+
+=head1 DESCRIPTION
+
+This module provides methods for locating and parsing bits of Apache
+source code.
+
+Since mod_perl remembers what build options were used to build it, you
+can use this knowledge to rebuild it using the same options. Simply
+chdir to the mod_perl source directory and run:
+
+ % cd modperl-2.0
+ % perl -MApache2::Build -e rebuild
+
+If you want to rebuild not yet installed, but already built mod_perl,
+run from its root directory:
+
+ % perl -Ilib -MApache2::Build -e rebuild
+
+=head1 METHODS
+
+=over 4
+
+=item new
+
+Create an object blessed into the B<Apache2::Build> class.
+
+ my $build = Apache2::Build->new;
+
+=item dir
+
+Top level directory where source files are located.
+
+ my $dir = $build->dir;
+ -d $dir or die "can't stat $dir $!\n";
+
+=item find
+
+Searches for apache source directories, return a list of those found.
+
+Example:
+
+ for my $dir ($build->find) {
+ my $yn = prompt "Configure with $dir ?", "y";
+ ...
+ }
+
+=item inc
+
+Print include paths for MakeMaker's B<INC> argument to
+C<WriteMakefile>.
+
+Example:
+
+ use ExtUtils::MakeMaker;
+
+ use Apache2::Build ();
+
+ WriteMakefile(
+ 'NAME' => 'Apache2::Module',
+ 'VERSION' => '0.01',
+ 'INC' => Apache2::Build->new->inc,
+ );
+
+
+=item module_magic_number
+
+Return the B<MODULE_MAGIC_NUMBER> defined in the apache source.
+
+Example:
+
+ my $mmn = $build->module_magic_number;
+
+=item httpd_version
+
+Return the server version.
+
+Example:
+
+ my $v = $build->httpd_version;
+
+=item otherldflags
+
+Return other ld flags for MakeMaker's B<dynamic_lib> argument to
+C<WriteMakefile>. This might be needed on systems like AIX that need
+special flags to the linker to be able to reference mod_perl or httpd
+symbols.
+
+Example:
+
+ use ExtUtils::MakeMaker;
+
+ use Apache2::Build ();
+
+ WriteMakefile(
+ 'NAME' => 'Apache2::Module',
+ 'VERSION' => '0.01',
+ 'INC' => Apache2::Build->new->inc,
+ 'dynamic_lib' => {
+ 'OTHERLDFLAGS' => Apache2::Build->new->otherldflags,
+ },
+ );
+
+=back
+
+
+=head1 AUTHOR
+
+Doug MacEachern
+
+=cut
diff --git a/2_0_13/lib/Apache2/ParseSource.pm b/2_0_13/lib/Apache2/ParseSource.pm
new file mode 100644
index 0000000..7dada94
--- /dev/null
+++ b/2_0_13/lib/Apache2/ParseSource.pm
@@ -0,0 +1,646 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+package Apache2::ParseSource;
+
+use strict;
+use warnings FATAL => 'all';
+
+use Apache2::Build ();
+use Config;
+use File::Basename;
+use File::Spec::Functions qw(catdir);
+
+our $VERSION = '0.02';
+
+sub new {
+ my $class = shift;
+
+ my $self = bless {
+ config => Apache2::Build->build_config,
+ @_,
+ }, $class;
+
+ my $prefixes = join '|', @{ $self->{prefixes} || [qw(ap_ apr_)] };
+ $self->{prefix_re} = qr{^($prefixes)};
+
+ $Apache2::Build::APXS ||= $self->{apxs};
+
+ $self;
+}
+
+sub config {
+ shift->{config};
+}
+
+sub parse {
+ my $self = shift;
+
+ $self->{scan_filename} = $self->generate_cscan_file;
+
+ $self->{c} = $self->scan;
+}
+
+sub DESTROY {
+ my $self = shift;
+ unlink $self->{scan_filename}
+}
+
+{
+ package Apache2::ParseSource::Scan;
+
+ our @ISA = qw(ModPerl::CScan);
+
+ sub get {
+ local $SIG{__DIE__} = \&Carp::confess;
+ shift->SUPER::get(@_);
+ }
+}
+
+my @c_scan_defines = (
+ 'CORE_PRIVATE', #so we get all of apache
+ 'MP_SOURCE_SCAN', #so we can avoid some c-scan barfing
+ '_NETINET_TCP_H', #c-scan chokes on netinet/tcp.h
+ '_BYTESWAP_H', #c-scan chokes on byteswap.h
+ '_BITS_BYTESWAP_H', #c-scan chokes on byteswap.h
+ 'Expat_INCLUDED', #c-scan chokes on expath.h
+ # 'APR_OPTIONAL_H', #c-scan chokes on apr_optional.h
+ 'apr_table_do_callback_fn_t=void', #c-scan chokes on function pointers
+);
+
+
+# some types c-scan failing to resolve
+push @c_scan_defines, map { "$_=void" }
+ qw(PPADDR_t PerlExitListEntry modperl_tipool_vtbl_t);
+
+sub scan {
+ require ModPerl::CScan;
+ ModPerl::CScan->VERSION(0.75);
+ require Carp;
+
+ my $self = shift;
+
+ my $c = ModPerl::CScan->new(filename => $self->{scan_filename});
+
+ my $includes = $self->includes;
+
+ # where to find perl headers, but we don't want to parse them otherwise
+ my $perl_core_path = catdir $Config{installarchlib}, "CORE";
+ push @$includes, $perl_core_path;
+
+ $c->set(includeDirs => $includes);
+
+ my @defines = @c_scan_defines;
+
+ unless ($Config{useithreads} and $Config{useithreads} eq 'define') {
+ #fake -DITHREADS so function tables are the same for
+ #vanilla and ithread perls, that is,
+ #make sure THX and friends are always expanded
+ push @defines, 'MP_SOURCE_SCAN_NEED_ITHREADS';
+ }
+
+ $c->set(Defines => join ' ', map "-D$_", @defines);
+
+ bless $c, 'Apache2::ParseSource::Scan';
+}
+
+sub include_dirs {
+ my $self = shift;
+ my $inc = $self->config->apxs('-q' => 'INCLUDEDIR');
+ my @dirs = ($inc, $self->config->mp_include_dir);
+ my $aprinc = $self->config->apxs('-q' => 'APR_INCLUDEDIR');
+
+ unless ($aprinc eq $inc) {
+ # Add APR include directory if different to httpd includedir
+ push @dirs, $aprinc;
+ }
+
+ @dirs;
+}
+
+sub includes { shift->config->includes }
+
+sub find_includes {
+ my $self = shift;
+
+ return $self->{includes} if $self->{includes};
+
+ require File::Find;
+
+ my @includes = ();
+ # don't pick preinstalled mod_perl headers if any, but pick the rest
+ {
+ my @dirs = $self->include_dirs;
+ die "could not find include directory (build the project first)"
+ unless -d $dirs[0];
+
+ my $unwanted = join '|', qw(ap_listen internal version
+ apr_optional mod_include mod_cgi
+ mod_proxy mod_ssl ssl_ apr_anylock
+ apr_rmm ap_config mod_log_config
+ mod_perl modperl_ apreq mod_cache
+ mod_serf mod_dav);
+ $unwanted = qr|^$unwanted|;
+ my $wanted = '';
+
+ push @includes, find_includes_wanted($wanted, $unwanted, @dirs);
+ }
+
+ # now add the live mod_perl headers (to make sure that we always
+ # work against the latest source)
+ {
+ my @dirs = map { catdir $self->config->{cwd}, $_ }
+ catdir(qw(src modules perl)), 'xs';
+
+ my $unwanted = '';
+ my $wanted = join '|', qw(mod_perl modperl_);
+ $wanted = qr|^$wanted|;
+
+ push @includes, find_includes_wanted($wanted, $unwanted, @dirs);
+ }
+
+ # now reorg the header files list, so the fragile scan won't choke
+ my @apr = ();
+ my @mp = ();
+ my @rest = ();
+ for (@includes) {
+ if (/mod_perl.h$/) {
+ # mod_perl.h needs to be included before other mod_perl
+ # headers
+ unshift @mp, $_;
+ }
+ elsif (/modperl_\w+.h$/) {
+ push @mp, $_;
+ }
+ elsif (/apr_\w+\.h$/ ) {
+ # apr headers need to be included first
+ push @apr, $_;
+ }
+ else {
+ push @rest, $_;
+ }
+ }
+ @includes = (@apr, @rest, @mp);
+
+ return $self->{includes} = \@includes;
+}
+
+sub find_includes_wanted {
+ my ($wanted, $unwanted, @dirs) = @_;
+ my @includes = ();
+ for my $dir (@dirs) {
+ File::Find::finddepth({
+ wanted => sub {
+ return unless /\.h$/;
+
+ if ($wanted) {
+ return unless /$wanted/;
+ }
+ else {
+ return if /$unwanted/;
+ }
+
+ my $dir = $File::Find::dir;
+ push @includes, "$dir/$_";
+ },
+ (Apache2::Build::WIN32 ? '' : follow => 1),
+ }, $dir);
+ }
+ return @includes;
+}
+
+sub generate_cscan_file {
+ my $self = shift;
+
+ my $includes = $self->find_includes;
+
+ my $filename = '.apache_includes';
+ open my $fh, '>', $filename or die "can't open $filename: $!";
+
+ for my $path (@$includes) {
+ my $filename = basename $path;
+ print $fh qq(\#include "$path"\n);
+ }
+
+ close $fh;
+
+ return $filename;
+}
+
+my %defines_wanted = (
+ 'Apache2::Const' => {
+ common => [qw{OK DECLINED DONE}],
+ config => [qw{DECLINE_CMD}],
+ context => [qw(NOT_IN_ GLOBAL_ONLY)],
+ http => [qw{HTTP_}],
+ log => [qw(APLOG_)],
+ methods => [qw{M_ METHODS}],
+ mpmq => [qw{AP_MPMQ_}],
+ options => [qw{OPT_}],
+ override => [qw{OR_ EXEC_ON_READ ACCESS_CONF RSRC_CONF}],
+ proxy => [qw{PROXYREQ_}],
+ platform => [qw{CRLF CR LF}],
+ remotehost => [qw{REMOTE_}],
+ satisfy => [qw{SATISFY_}],
+ types => [qw{DIR_MAGIC_TYPE}],
+ auth => [qw{AUTHN_ AUTHZ AP_AUTH_ AUTH_ AUTHZ_}],
+ },
+ 'APR::Const' => {
+ common => [qw{APR_SUCCESS}],
+ error => [qw{APR_E}],
+ filepath => [qw{APR_FILEPATH_}],
+ filetype => [qw{APR_FILETYPE_}],
+ fopen => [qw{APR_FOPEN_}],
+ fprot => [qw{APR_FPROT_}],
+ finfo => [qw{APR_FINFO_}],
+ flock => [qw{APR_FLOCK_}],
+ hook => [qw{APR_HOOK_}],
+ limit => [qw{APR_LIMIT}],
+ poll => [qw{APR_POLL}],
+ socket => [qw{APR_SO_}],
+ status => [qw{APR_TIMEUP}],
+ table => [qw{APR_OVERLAP_TABLES_}],
+ uri => [qw{APR_URI_}],
+ },
+ ModPerl => {
+ common => [qw{MODPERL_RC_}],
+ }
+);
+
+my %defines_wanted_re;
+while (my ($class, $groups) = each %defines_wanted) {
+ while (my ($group, $wanted) = each %$groups) {
+ my $pat = join '|', @$wanted;
+ $defines_wanted_re{$class}->{$group} = $pat; #qr{^($pat)};
+ }
+}
+
+my %enums_wanted = (
+ 'Apache2::Const' => { map { $_, 1 } qw(cmd_how input_mode filter_type conn_keepalive authn_status authz_status) },
+ 'APR::Const' => { map { $_, 1 } qw(apr_shutdown_how apr_read_type apr_lockmech) },
+);
+
+my $defines_unwanted = join '|', qw{
+HTTP_VERSION APR_EOL_STR APLOG_MARK APLOG_NOERRNO APR_SO_TIMEOUT
+APR_HOOK_PROBES_ENABLED APR_HOOK_INT_DCL_UD
+APLOG_MAX_LOGLEVEL
+APR_BEGIN_DECLS APR_END_DECLS
+};
+
+sub get_constants {
+ my ($self) = @_;
+
+ my $includes = $self->find_includes;
+ my (%constants, %seen);
+
+ for my $file (@$includes) {
+ open my $fh, $file or die "open $file: $!";
+ while (<$fh>) {
+ if (s/^\#define\s+(\w+)\s+.*/$1/) {
+ chomp;
+ next if /_H$/;
+ next if $seen{$_}++;
+ $self->handle_constant(\%constants);
+ }
+ elsif (m/enum[^\{]+\{/) {
+ $self->handle_enum($fh, \%constants);
+ }
+ }
+ close $fh;
+ }
+
+ #maintain a few handy shortcuts from 1.xx
+ #aliases are defined in ModPerl::Code
+ push @{ $constants{'Apache2::Const'}->{common} },
+ qw(NOT_FOUND FORBIDDEN AUTH_REQUIRED SERVER_ERROR REDIRECT);
+
+ return \%constants;
+}
+
+sub handle_constant {
+ my ($self, $constants) = @_;
+ my $keys = keys %defines_wanted_re;
+
+ return if /^($defines_unwanted)/o;
+
+ while (my ($class, $groups) = each %defines_wanted_re) {
+ my $keys = keys %$groups;
+
+ while (my ($group, $re) = each %$groups) {
+ next unless /^($re)/;
+ push @{ $constants->{$class}->{$group} }, $_;
+ return;
+ }
+ }
+}
+
+sub handle_enum {
+ my ($self, $fh, $constants) = @_;
+
+ my ($name, $e) = $self->parse_enum($fh);
+ return unless $name;
+
+ $name =~ s/^ap_//;
+ $name =~ s/_(e|t)$//;
+
+ my $class;
+ for (keys %enums_wanted) {
+ next unless $enums_wanted{$_}->{$name};
+ $class = $_;
+ }
+
+ return unless $class;
+ $name =~ s/^apr_//;
+
+ push @{ $constants->{$class}->{$name} }, @$e if $e;
+}
+
+#this should win an award for worlds lamest parser
+sub parse_enum {
+ my ($self, $fh) = @_;
+ my $code = $_;
+ my @e;
+
+ unless ($code =~ /;\s*$/) {
+ local $_;
+ while (<$fh>) {
+ $code .= $_;
+ last if /;\s*$/;
+ }
+ }
+
+ my $name;
+ if ($code =~ s/^\s*enum\s+(\w*)\s*//) {
+ $name = $1;
+ }
+ elsif ($code =~ s/^\s*typedef\s+enum\s+//) {
+ $code =~ s/\s*(\w+)\s*;\s*$//;
+ $name = $1;
+ }
+
+ $code =~ s:/\*.*?\*/::sg;
+ $code =~ s/\s*=\s*\w+//g;
+ $code =~ s/^[^\{]*\{//s;
+ $code =~ s/\}[^;]*;?//s;
+ $code =~ s/^\s*\n//gm;
+
+ while ($code =~ /\b(\w+)\b,?/g) {
+ push @e, $1;
+ }
+
+ return ($name, \@e);
+}
+
+sub wanted_functions { shift->{prefix_re} }
+sub wanted_structures { shift->{prefix_re} }
+
+sub get_functions {
+ my $self = shift;
+
+ my $key = 'parsed_fdecls';
+ return $self->{$key} if $self->{$key};
+
+ my $c = $self->{c};
+
+ my $fdecls = $c->get($key);
+ my $inlines = $c->get('parsed_inlines');
+ push @{$fdecls}, @{$inlines};
+
+ my %seen;
+ my $wanted = $self->wanted_functions;
+
+ my @functions;
+
+ for my $entry (@$fdecls) {
+ my ($rtype, $name, $args) = @$entry;
+ next unless $name =~ $wanted;
+ next if $seen{$name}++;
+ my @attr;
+
+ for (qw(static __inline__)) {
+ if ($rtype =~ s/^($_)\s+//) {
+ push @attr, $1;
+ }
+ }
+
+ #XXX: working around ModPerl::CScan confusion here
+ #macro defines ap_run_error_log causes
+ #cpp filename:linenumber to be included as part of the type
+ for (@$args) {
+ next unless $_->[0];
+ $_->[0] =~ s/^\#.*?\"\s+//;
+ $_->[0] =~ s/^register //;
+ }
+
+ my $func = {
+ name => $name,
+ return_type => $rtype,
+ args => [map {
+ { type => $_->[0], name => $_->[1] }
+ } @$args],
+ };
+
+ $func->{attr} = \@attr if @attr;
+
+ push @functions, $func;
+ }
+
+ # sort the functions by the 'name' attribute to ensure a
+ # consistent output on different systems.
+ $self->{$key} = [sort { $a->{name} cmp $b->{name} } @functions];
+}
+
+sub get_structs {
+ my $self = shift;
+
+ my $key = 'typedef_structs';
+ return $self->{$key} if $self->{$key};
+
+ my $c = $self->{c};
+
+ my $typedef_structs = $c->get($key);
+
+ my %seen;
+ my $wanted = $self->wanted_structures;
+ my $other = join '|', qw(_rec module
+ piped_log uri_t htaccess_result
+ cmd_parms cmd_func cmd_how);
+
+ my @structures;
+ my $sx = qr(^struct\s+);
+
+ while (my ($type, $elts) = each %$typedef_structs) {
+ next unless $type =~ $wanted or $type =~ /($other)$/o;
+
+ $type =~ s/$sx//;
+
+ next if $seen{$type}++;
+
+ my $struct = {
+ type => $type,
+ elts => [map {
+ my $type = $_->[0];
+ $type =~ s/$sx//;
+ $type .= $_->[1] if $_->[1];
+ $type =~ s/:\d+$//; #unsigned:1
+ { type => $type, name => $_->[2] }
+ } @$elts],
+ };
+
+ push @structures, $struct;
+ }
+
+ # sort the structs by the 'type' attribute to ensure a consistent
+ # output on different systems.
+ $self->{$key} = [sort { $a->{type} cmp $b->{type} } @structures];
+}
+
+sub write_functions_pm {
+ my $self = shift;
+ my $file = shift || 'FunctionTable.pm';
+ my $name = shift || 'Apache2::FunctionTable';
+
+ $self->write_pm($file, $name, $self->get_functions);
+}
+
+sub write_structs_pm {
+ my $self = shift;
+ my $file = shift || 'StructureTable.pm';
+ my $name = shift || 'Apache2::StructureTable';
+
+ $self->write_pm($file, $name, $self->get_structs);
+}
+
+sub write_constants_pm {
+ my $self = shift;
+ my $file = shift || 'ConstantsTable.pm';
+ my $name = shift || 'Apache2::ConstantsTable';
+
+ $self->write_pm($file, $name, $self->get_constants);
+}
+
+sub write_pm {
+ my ($self, $file, $name, $data) = @_;
+
+ require Data::Dumper;
+ local $Data::Dumper::Indent = 1;
+
+ my ($subdir) = (split '::', $name)[0];
+
+ my $tdir = '';
+ my $build = Apache2::Build->new(init => 1);
+ my $httpd_version = $build->httpd_version;
+ if ($httpd_version lt '2.4.0') {
+ $tdir='xs/tables/current';
+ }
+ else {
+ $tdir='xs/tables/current24';
+ }
+
+ if (-d "$tdir/$subdir") {
+ $file = "$tdir/$subdir/$file";
+ }
+
+ # sort the hashes (including nested ones) for a consistent dump
+ canonsort(\$data);
+
+ my $dump = Data::Dumper->new([$data],
+ [$name])->Dump;
+
+ my $package = ref($self) || $self;
+ my $version = $self->VERSION;
+ my $date = scalar localtime;
+
+ my $new_content = << "EOF";
+package $name;
+
+# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+# ! WARNING: generated by $package/$version
+# ! $date
+# ! do NOT edit, any changes will be lost !
+# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+$dump
+
+1;
+EOF
+
+ my $old_content = '';
+ if (-e $file) {
+ open my $pm, '<', $file or die "open $file: $!";
+ local $/ = undef; # slurp the file
+ $old_content = <$pm>;
+ close $pm;
+ }
+
+ my $overwrite = 1;
+ if ($old_content) {
+ # strip the date line, which will never be the same before
+ # comparing
+ my $table_header = qr{^\#\s!.*};
+ (my $old = $old_content) =~ s/$table_header//mg;
+ (my $new = $new_content) =~ s/$table_header//mg;
+ $overwrite = 0 if $old eq $new;
+ }
+
+ if ($overwrite) {
+ open my $pm, '>', $file or die "open $file: $!";
+ print $pm $new_content;
+ close $pm;
+ }
+
+}
+
+# canonsort(\$data);
+# sort nested hashes in the data structure.
+# the data structure itself gets modified
+
+sub canonsort {
+ my $ref = shift;
+ my $type = ref $$ref;
+
+ return unless $type;
+
+ require Tie::IxHash;
+
+ my $data = $$ref;
+
+ if ($type eq 'ARRAY') {
+ for (@$data) {
+ canonsort(\$_);
+ }
+ }
+ elsif ($type eq 'HASH') {
+ for (keys %$data) {
+ canonsort(\$data->{$_});
+ }
+
+ tie my %ixhash, 'Tie::IxHash';
+
+ # reverse sort so we get the order of:
+ # return_type, name, args { type, name } for functions
+ # type, elts { type, name } for structures
+
+ for (sort { $b cmp $a } keys %$data) {
+ $ixhash{$_} = $data->{$_};
+ }
+
+ $$ref = \%ixhash;
+ }
+}
+
+1;
+__END__
diff --git a/2_0_13/lib/Apache2/PerlSections.pm b/2_0_13/lib/Apache2/PerlSections.pm
new file mode 100644
index 0000000..69cd6b8
--- /dev/null
+++ b/2_0_13/lib/Apache2/PerlSections.pm
@@ -0,0 +1,233 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+package Apache2::PerlSections;
+
+use strict;
+use warnings FATAL => 'all';
+
+our $VERSION = '2.00';
+
+use Apache2::CmdParms ();
+use Apache2::Directive ();
+use APR::Table ();
+use Apache2::ServerRec ();
+use Apache2::ServerUtil ();
+use Apache2::Const -compile => qw(OK);
+
+use constant SPECIAL_NAME => 'PerlConfig';
+use constant SPECIAL_PACKAGE => 'Apache2::ReadConfig';
+
+sub new {
+ my ($package, @args) = @_;
+ return bless { @args }, ref($package) || $package;
+}
+
+sub parms { return shift->{'parms'} }
+sub directives { return shift->{'directives'} ||= [] }
+sub package { return shift->{'args'}->{'package'} }
+
+my @saved;
+sub save { return $Apache2::PerlSections::Save }
+sub server { return $Apache2::PerlSections::Server }
+sub saved { return @saved }
+
+sub handler : method {
+ my ($self, $parms, $args) = @_;
+
+ unless (ref $self) {
+ $self = $self->new('parms' => $parms, 'args' => $args);
+ }
+
+ if ($self->save) {
+ push @saved, $self->package;
+ }
+
+ my $special = $self->SPECIAL_NAME;
+
+ for my $entry ($self->symdump()) {
+ if ($entry->[0] !~ /$special/) {
+ $self->dump_any(@$entry);
+ }
+ }
+
+ {
+ no strict 'refs';
+ foreach my $package ($self->package) {
+ my @config = map { split /\n/ }
+ grep { defined }
+ (@{"${package}::$special"},
+ ${"${package}::$special"});
+ $self->dump_special(@config);
+ }
+ }
+
+ $self->post_config();
+
+ Apache2::Const::OK;
+}
+
+my %directives_seen_hack;
+
+sub symdump {
+ my ($self) = @_;
+
+ unless ($self->{symbols}) {
+ no strict;
+
+ $self->{symbols} = [];
+
+ #XXX: Here would be a good place to warn about NOT using
+ # Apache2::ReadConfig:: directly in <Perl> sections
+ foreach my $pack ($self->package, $self->SPECIAL_PACKAGE) {
+ #XXX: Shamelessly borrowed from Devel::Symdump;
+ while (my ($key, $val) = each(%{ *{"$pack\::"} })) {
+ #We don't want to pick up stashes...
+ next if ($key =~ /::$/);
+ local (*ENTRY) = $val;
+ if (defined $val && defined *ENTRY{SCALAR} && defined $ENTRY) {
+ push @{$self->{symbols}}, [$key, $ENTRY];
+ }
+ if (defined $val && defined *ENTRY{ARRAY}) {
+ unless (exists $directives_seen_hack{"$key$val"}) {
+ $directives_seen_hack{"$key$val"} = 1;
+ push @{$self->{symbols}}, [$key, \@ENTRY];
+ }
+ }
+ if (defined $val && defined *ENTRY{HASH} && $key !~ /::/) {
+ push @{$self->{symbols}}, [$key, \%ENTRY];
+ }
+ }
+ }
+ }
+
+ return @{$self->{symbols}};
+}
+
+sub dump_special {
+ my ($self, @data) = @_;
+ $self->add_config(@data);
+}
+
+sub dump_any {
+ my ($self, $name, $entry) = @_;
+ my $type = ref $entry;
+
+ if ($type eq 'ARRAY') {
+ $self->dump_array($name, $entry);
+ }
+ elsif ($type eq 'HASH') {
+ $self->dump_hash($name, $entry);
+ }
+ else {
+ $self->dump_entry($name, $entry);
+ }
+}
+
+sub dump_hash {
+ my ($self, $name, $hash) = @_;
+
+ for my $entry (keys %{ $hash || {} }) {
+ my $item = $hash->{$entry};
+ my $type = ref($item);
+
+ if ($type eq 'HASH') {
+ $self->dump_section($name, $entry, $item);
+ }
+ elsif ($type eq 'ARRAY') {
+ for my $e (@$item) {
+ $self->dump_section($name, $entry, $e);
+ }
+ }
+ }
+}
+
+sub dump_section {
+ my ($self, $name, $loc, $hash) = @_;
+
+ $self->add_config("<$name $loc>\n");
+
+ for my $entry (keys %{ $hash || {} }) {
+ $self->dump_entry($entry, $hash->{$entry});
+ }
+
+ $self->add_config("</$name>\n");
+}
+
+sub dump_array {
+ my ($self, $name, $entries) = @_;
+
+ for my $entry (@$entries) {
+ $self->dump_entry($name, $entry);
+ }
+}
+
+sub dump_entry {
+ my ($self, $name, $entry) = @_;
+ my $type = ref $entry;
+
+ if ($type eq 'SCALAR') {
+ $self->add_config("$name $$entry\n");
+ }
+ elsif ($type eq 'ARRAY') {
+ if (grep {ref} @$entry) {
+ $self->dump_entry($name, $_) for @$entry;
+ }
+ else {
+ $self->add_config("$name @$entry\n");
+ }
+ }
+ elsif ($type eq 'HASH') {
+ $self->dump_hash($name, $entry);
+ }
+ elsif ($type) {
+ #XXX: Could do $type->can('httpd_config') here on objects ???
+ die "Unknown type '$type' for directive $name";
+ }
+ elsif (defined $entry) {
+ $self->add_config("$name $entry\n");
+ }
+}
+
+sub add_config {
+ my ($self, @config) = @_;
+ foreach my $config (@config) {
+ return unless defined $config;
+ chomp($config);
+ push @{ $self->directives }, $config;
+ }
+}
+
+sub post_config {
+ my ($self) = @_;
+ my $errmsg = $self->parms->add_config($self->directives);
+ die $errmsg if $errmsg;
+}
+
+sub dump {
+ my $class = shift;
+ require Apache2::PerlSections::Dump;
+ return Apache2::PerlSections::Dump->dump(@_);
+}
+
+sub store {
+ my $class = shift;
+ require Apache2::PerlSections::Dump;
+ return Apache2::PerlSections::Dump->store(@_);
+}
+
+1;
+__END__
diff --git a/2_0_13/lib/Apache2/PerlSections/Dump.pm b/2_0_13/lib/Apache2/PerlSections/Dump.pm
new file mode 100644
index 0000000..4366410
--- /dev/null
+++ b/2_0_13/lib/Apache2/PerlSections/Dump.pm
@@ -0,0 +1,101 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+package Apache2::PerlSections::Dump;
+
+use strict;
+use warnings FATAL => 'all';
+
+our $VERSION = '0.01';
+
+use Apache2::PerlSections;
+our @ISA = qw(Apache2::PerlSections);
+
+use Data::Dumper;
+
+# Process all saved packages
+sub package { return shift->saved }
+
+# We don't want to save anything
+sub save { return }
+
+# We don't want to post any config to apache, we are dumping
+sub post_config { return }
+
+sub dump {
+ my $self = shift;
+ unless (ref $self) {
+ $self = $self->new;
+ }
+ $self->handler();
+ return join "\n", @{$self->directives}, '1;', '__END__', '';
+}
+
+sub store {
+ my ($class, $filename) = @_;
+ require IO::File;
+
+ my $fh = IO::File->new(">$filename") or die "can't open $filename $!\n";
+
+ $fh->print($class->dump);
+
+ $fh->close;
+}
+
+sub dump_array {
+ my ($self, $name, $entry) = @_;
+ $self->add_config(Data::Dumper->Dump([$entry], ["*$name"]));
+}
+
+sub dump_hash {
+ my ($self, $name, $entry) = @_;
+ for my $elem (sort keys %{$entry}) {
+ $self->add_config(Data::Dumper->Dump([$entry->{$elem}],
+ ["\$$name"."{'$elem'}"]));
+ }
+
+}
+
+sub dump_entry {
+ my ($self, $name, $entry) = @_;
+
+ return if not defined $entry;
+ my $type = ref($entry);
+
+ if ($type eq 'SCALAR') {
+ $self->add_config(Data::Dumper->Dump([$$entry],[$name]));
+ }
+ if ($type eq 'ARRAY') {
+ $self->dump_array($name,$entry);
+ }
+ else {
+ $self->add_config(Data::Dumper->Dump([$entry],[$name]));
+ }
+}
+
+sub dump_special {
+ my ($self, @data) = @_;
+
+ my @dump = grep { defined } @data;
+ return unless @dump;
+
+ $self->add_config(Data::Dumper->Dump([\@dump],['*'.$self->SPECIAL_NAME]));
+}
+
+
+
+1;
+__END__
diff --git a/2_0_13/lib/Apache2/Resource.pm b/2_0_13/lib/Apache2/Resource.pm
new file mode 100644
index 0000000..ccf70d9
--- /dev/null
+++ b/2_0_13/lib/Apache2/Resource.pm
@@ -0,0 +1,150 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+package Apache2::Resource;
+
+use strict;
+use warnings FATAL => 'all';
+
+use mod_perl2;
+
+use Apache2::Module ();
+
+use BSD::Resource qw(setrlimit getrlimit get_rlimits);
+
+use Apache2::Const -compile => qw(OK);
+
+$Apache2::Resource::VERSION = '1.72';
+
+our $Debug;
+
+$Debug ||= 0;
+
+sub MB ($) {
+ my $num = shift;
+ return ($num < (1024 * 1024)) ? $num*1024*1024 : $num;
+}
+
+sub BM ($) {
+ my $num = shift;
+ return ($num > (1024 * 1024)) ? '(' . ($num>>20) . 'Mb)' : '';
+}
+
+sub DEFAULT_RLIMIT_DATA () { 64 } # data (memory) size in MB
+sub DEFAULT_RLIMIT_AS () { 64 } # address space (memory) size in MB
+sub DEFAULT_RLIMIT_CPU () { 60*6 } # cpu time in seconds
+sub DEFAULT_RLIMIT_CORE () { 0 } # core file size (MB)
+sub DEFAULT_RLIMIT_RSS () { 16 } # resident set size (MB)
+sub DEFAULT_RLIMIT_FSIZE () { 10 } # file size (MB)
+sub DEFAULT_RLIMIT_STACK () { 20 } # stack size (MB)
+
+my %is_mb = map {$_, 1} qw{DATA RSS STACK FSIZE CORE MEMLOCK AS};
+
+sub debug { print STDERR @_ if $Debug }
+
+sub install_rlimit ($$$) {
+ my ($res, $soft, $hard) = @_;
+
+ my $name = $res;
+
+ my $cv = \&{"BSD::Resource::RLIMIT_${res}"};
+ eval { $res = $cv->() };
+ return if $@;
+
+ unless ($soft) {
+ my $defval = \&{"DEFAULT_RLIMIT_${name}"};
+ if (defined &$defval) {
+ $soft = $defval->();
+ } else {
+ warn "can't find default for `$defval'\n";
+ }
+ }
+
+ $hard ||= $soft;
+
+ debug "Apache2::Resource: PID $$ attempting to set `$name'=$soft:$hard ...";
+
+ ($soft, $hard) = (MB $soft, MB $hard) if $is_mb{$name};
+
+ return setrlimit $res, $soft, $hard;
+}
+
+sub handler {
+ while (my ($k, $v) = each %ENV) {
+ next unless $k =~ /^PERL_RLIMIT_(\w+)$/;
+ $k = $1;
+ next if $k eq "DEFAULTS";
+ my ($soft, $hard) = split ":", $v, 2;
+ $hard ||= $soft;
+
+ my $set = install_rlimit $k, $soft, $hard;
+ debug "not " unless $set;
+ debug "ok\n";
+ debug $@ if $@;
+ }
+
+ Apache2::Const::OK;
+}
+
+sub default_handler {
+ while (my ($k, $v) = each %Apache2::Resource::) {
+ next unless $k =~ s/^DEFAULT_/PERL_/;
+ $ENV{$k} = "";
+ }
+ handler();
+}
+
+sub status_rlimit {
+ my $lim = get_rlimits();
+ my @retval = ("<table border=1><tr>",
+ (map "<th>$_</th>", qw(Resource Soft Hard)),
+ "</tr>");
+
+ for my $res (keys %$lim) {
+ my ($soft, $hard) = getrlimit($lim->{$res});
+ (my $limit = $res) =~ s/^RLIMIT_//;
+ ($soft, $hard) = ("$soft " . BM($soft), "$hard ". BM($hard))
+ if $is_mb{$limit};
+ push @retval,
+ "<tr>", (map { "<td>$_</td>" } $res, $soft, $hard), "</tr>\n";
+ }
+
+ push @retval, "</table><P>";
+ push @retval, "<small>Apache2::Resource $Apache2::Resource::VERSION</small>";
+
+ return \@retval;
+}
+
+if ($ENV{MOD_PERL}) {
+ if ($ENV{PERL_RLIMIT_DEFAULTS}) {
+ require Apache2::ServerUtil;
+ Apache2::ServerUtil->server->push_handlers(
+ PerlChildInitHandler => \&default_handler);
+ }
+
+ Apache2::Status->menu_item(rlimit => "Resource Limits",
+ \&status_rlimit)
+ if Apache2::Module::loaded("Apache2::Status");
+}
+
+# perl Apache2/Resource.pm
+++$Debug, default_handler unless caller();
+
+1;
+
+__END__
+
diff --git a/2_0_13/lib/Apache2/SourceTables.pm b/2_0_13/lib/Apache2/SourceTables.pm
new file mode 100644
index 0000000..b82ba13
--- /dev/null
+++ b/2_0_13/lib/Apache2/SourceTables.pm
@@ -0,0 +1,32 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+package Apache2::SourceTables;
+
+use Apache2::StructureTable ();
+use Apache2::FunctionTable ();
+
+#build hash versions of the tables
+%Apache2::StructureTable =
+ map { $_->{type}, $_->{elts} } @$Apache2::StructureTable;
+
+%Apache2::FunctionTable =
+ map { $_->{name}, {elts => $_->{elts},
+ return_type => $_->{return_type} } }
+ @$Apache2::FunctionTable;
+
+1;
+__END__
diff --git a/2_0_13/lib/Apache2/Status.pm b/2_0_13/lib/Apache2/Status.pm
new file mode 100644
index 0000000..ee4bb8c
--- /dev/null
+++ b/2_0_13/lib/Apache2/Status.pm
@@ -0,0 +1,911 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+package Apache2::Status;
+
+use strict;
+use warnings FATAL => 'all';
+
+use mod_perl2;
+
+use Apache2::RequestIO ();
+use Apache2::RequestRec ();
+use Apache2::RequestUtil ();
+use Apache2::ServerUtil ();
+
+use File::Spec ();
+
+use Apache2::Const -compile => qw(OK);
+
+$Apache2::Status::VERSION = '4.01'; # mod_perl 2.0
+
+use constant IS_WIN32 => ($^O eq "MSWin32");
+
+my %status = (
+ script => "PerlRequire'd Files",
+ inc => "Loaded Modules",
+ rgysubs => "Compiled Registry Scripts",
+ symdump => "Symbol Table Dump",
+ inh_tree => "Inheritance Tree",
+ isa_tree => "ISA Tree",
+ env => "Environment",
+ sig => "Signal Handlers",
+ myconfig => "Perl Configuration",
+);
+delete $status{'sig'} if IS_WIN32;
+
+if ($Apache2::PerlSections::Save) {
+ $status{"section_config"} = "Perl Section Configuration";
+}
+
+my %requires = (
+ deparse => ["StatusDeparse", "B::Deparse", 0.59, ],
+ fathom => ["StatusFathom", "B::Fathom", 0.05, ],
+ symdump => ["", "Devel::Symdump", 2.00, ],
+ dumper => ["StatusDumper", "Data::Dumper", 0, ],
+ b => ["", "B", 0, ],
+ graph => ["StatusGraph", "B::Graph", 0.03, ],
+ lexinfo => ["StatusLexInfo", "B::LexInfo", 0, ],
+ xref => ["StatusXref", "B::Xref", 1.01, ],
+ terse => ["StatusTerse", "B::Terse", 0, ],
+ tersesize => ["StatusTerseSize", "B::TerseSize", 0.09, ],
+ packagesize => ["StatusPackageSize", "B::TerseSize", 0.09, ],
+ peek => ["StatusPeek", "Apache::Peek", 1.03, ],
+);
+
+sub has {
+ my ($r, $what) = @_;
+
+ return 0 unless exists $requires{$what};
+
+ my ($opt, $module, $version) = @{ $requires{$what} };
+
+ (my $file = $module) =~ s|::|/|;
+ $file .= ".pm";
+
+ # if !$opt we skip the testing for the option
+ return 0 if $opt && !status_config($r, $opt);
+ return 0 unless eval { require $file };
+ my $mod_ver = $module->VERSION;
+ $mod_ver =~ s/_.*//; # handle dev versions like 2.121_02
+ return 0 unless $mod_ver && $mod_ver >= $version;
+
+ return 1;
+}
+
+use constant CPAN_SEARCH => 'http://search.cpan.org/search?mode=module;query';
+
+sub install_hint {
+ my ($module) = @_;
+ return qq{<p>Please install the } .
+ qq{<a href="@{[CPAN_SEARCH]}=$module">$module</a> module.</p>};
+}
+
+sub status_config {
+ my ($r, $key) = @_;
+ return (lc($r->dir_config($key) || '') eq "on") ||
+ (lc($r->dir_config('StatusOptionsAll') || '') eq "on");
+}
+
+sub menu_item {
+ my ($self, $key, $val, $sub) = @_;
+ $status{$key} = $val;
+ no strict;
+ no warnings 'redefine';
+ *{"status_${key}"} = $sub if $sub and ref $sub eq 'CODE';
+}
+
+sub handler {
+ my ($r) = @_;
+ my $qs = $r->args || "";
+ my $sub = "status_$qs";
+ no strict 'refs';
+
+ if ($qs =~ s/^(noh_\w+).*/$1/) {
+ &{$qs}($r);
+ return Apache2::Const::OK;
+ }
+
+ header($r);
+ if (defined &$sub) {
+ $r->print(@{ &{$sub}($r) });
+ }
+ elsif ($qs and %{$qs."::"}) {
+ $r->print(symdump($r, $qs));
+ }
+ else {
+ my $uri = $r->location;
+ $r->print('<p>');
+ $r->print(
+ map { qq[<a href="$uri?$_">$status{$_}</a><br />\n] } sort { lc $a cmp lc $b } keys %status
+ );
+ $r->print('</p>');
+ }
+ $r->print("</body></html>");
+
+ Apache2::Const::OK;
+}
+
+sub header {
+ my $r = shift;
+ my $start = scalar localtime $^T;
+ my $srv = Apache2::ServerUtil::get_server_banner();
+ $r->content_type("text/html");
+ my $v = $^V ? sprintf "v%vd", $^V : $];
+ $r->print(<<"EOF");
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
+ <head>
+ <title>Apache2::Status $Apache2::Status::VERSION</title>
+ <style type="text/css">
+ body {
+ color: #000;
+ background-color: #fff;
+ }
+ p.hdr {
+ background-color: #ddd;
+ border: 2px outset;
+ padding: 3px;
+ width: 99%;
+ }
+ </style>
+ </head>
+ <body>
+ <p class="hdr">
+ Embedded Perl version <b>$v</b> for <b>$srv</b> process <b>$$</b>,<br />
+ running since $start
+ </p>
+EOF
+
+}
+
+sub symdump {
+ my ($r, $package) = @_;
+
+ return install_hint("Devel::Symdump") unless has($r, "symdump");
+
+ # lc generates a (FATAL) warning if $r->dir_config is undef
+ my $meth = lc($r->dir_config("StatusRdump") || '') eq "on"
+ ? "rnew" : "new";
+ my $sob = Devel::Symdump->$meth($package);
+ return $sob->Apache2::Status::as_HTML($package, $r);
+}
+
+sub status_symdump {
+ my ($r) = @_;
+ [symdump($r, 'main')];
+}
+
+sub status_section_config {
+ my ($r) = @_;
+ require Apache2::PerlSections;
+ ["<pre>", Apache2::PerlSections->dump, "</pre>"];
+}
+
+sub status_inc {
+ my ($r) = @_;
+
+ my $uri = $r->location;
+ my @retval = (
+ '<table border="1">',
+ "<tr>",
+ (map "<td><b>$_</b></td>", qw(Package Version Modified File)),
+ "</tr>\n"
+ );
+
+ foreach my $file (sort keys %INC) {
+ local $^W = 0;
+ next if $file =~ m:^/:;
+ next unless $file =~ m:\.pm:;
+ next unless $INC{$file}; #e.g. fake Apache2/TieHandle.pm
+
+ no strict 'refs';
+ (my $module = $file) =~ s,/,::,g;
+ $module =~ s,\.pm$,,;
+ next if $module eq 'mod_perl';
+ my $v = ${"$module\:\:VERSION"} || '0.00';
+ my $mtime = -e $INC{$file} ? scalar localtime((stat $INC{$file})[9]) :
+ 'N/A';
+
+ push @retval, (
+ "<tr>",
+ (map "<td>$_</td>",
+ qq(<a href="$uri?$module">$module</a>),
+ $v, $mtime, $INC{$file}),
+ "</tr>\n"
+ );
+ }
+ push @retval, "</table>\n";
+ push @retval, "<p><b>\@INC</b> = <br />", join "<br />\n", @INC, "";
+ \@retval;
+}
+
+sub status_script {
+ my ($r) = @_;
+
+ my @retval = (
+ '<table border="1">',
+ "<tr><td><b>PerlRequire</b></td><td><b>Location</b></td></tr>\n",
+ );
+
+ foreach my $file (sort keys %INC) {
+ next if $file =~ m:\.(pm|al|ix)$:;
+ push @retval,
+ qq(<tr><td>$file</td><td>$INC{$file}</td></tr>\n);
+ }
+ push @retval, "</table>";
+ \@retval;
+}
+
+my $RegistryCache;
+
+sub registry_cache {
+ my ($self, $cache) = @_;
+
+ # XXX: generalize
+
+ $RegistryCache = $cache if $cache;
+ $RegistryCache || $Apache2::Registry;
+}
+
+sub get_packages_per_handler {
+ my ($root, $stash) = @_;
+
+ my %handlers = ();
+ my @packages = get_packages($stash);
+ for (@packages) {
+ /^\*${root}::([\w:]+)::(\w+)::$/ && push @{ $handlers{$1} }, $2;
+ }
+
+ return %handlers;
+}
+
+sub get_packages {
+ my ($stash) = @_;
+
+ no strict 'refs';
+ my @packages = ();
+ for (keys %$stash) {
+ return $stash unless $stash->{$_} =~ /::$/;
+ push @packages, get_packages($stash->{$_});
+ }
+ return @packages;
+}
+
+sub status_rgysubs {
+ my ($r) = @_;
+
+ local $_;
+ my $uri = $r->location;
+ my $cache = __PACKAGE__->registry_cache;
+
+ my @retval = "<h2>Compiled registry scripts grouped by their handler</h2>";
+
+ push @retval,
+ "<p><b>Click on package name to see its symbol table</b></p>\n";
+
+ my $root = "ModPerl::ROOT";
+ no strict 'refs';
+ my %handlers = get_packages_per_handler($root, *{$root . "::"});
+ for my $handler (sort keys %handlers) {
+ push @retval, "<h4>$handler:</h4>\n<p>\n";
+ for (sort @{ $handlers{$handler} }) {
+ my $full = join '::', $root, $handler, $_;
+ push @retval, qq(<a href="$uri?$full">$_</a>\n), "<br />";
+ }
+ push @retval, "</p>\n";
+ }
+
+ \@retval;
+}
+
+sub status_env {
+ my ($r) = shift;
+
+ my @retval = ("<p>\n");
+
+ if ($r->handler eq 'modperl') {
+ # the handler can be executed under the "modperl" handler
+ push @retval,
+ qq{<b>Under the "modperl" handler, the environment is</b>:};
+ # XXX: I guess we could call $r->subprocess_env; and show how
+ # would it look like under the 'perl-script' environment, but
+ # under the 'modperl' handler %ENV doesn't get reset,
+ # therefore on the first reload it'll see the bloated %ENV in
+ # first place.
+ } else {
+ # the handler can be executed under the "perl-script" handler
+ push @retval,
+ qq{<b>Under the "perl-script" handler, the environment is</b>:};
+ }
+ push @retval, "\n</p>\n";
+ push @retval, "<pre>",
+ (map "$_ = " . escape_html($ENV{$_}||'') . "\n",
+ sort keys %ENV), "</pre>";
+
+ \@retval;
+}
+
+sub status_sig {
+ ["<pre>",
+ (map {
+ my $val = $SIG{$_} || "";
+ if ($val and ref $val eq "CODE") {
+ # XXX: 2.0 doesn't have Apache2::Symbol
+ if (my $cv = Apache2::Symbol->can('sv_name')) {
+ $val = "\\&". $cv->($val);
+ }
+ }
+ "$_ = $val\n" }
+ sort keys %SIG),
+ "</pre>"];
+}
+
+sub status_myconfig {
+ ["<pre>", myconfig(), "</pre>"];
+}
+
+sub status_inh_tree {
+ return has(shift, "symdump")
+ ? ["<pre>", Devel::Symdump->inh_tree, "</pre>"]
+ : install_hint("Devel::Symdump");
+}
+
+sub status_isa_tree {
+ return has(shift, "symdump")
+ ? ["<pre>", Devel::Symdump->isa_tree, "</pre>"]
+ : install_hint("Devel::Symdump");
+}
+
+sub status_data_dump {
+ my ($r) = @_;
+
+ return install_hint('Data::Dumper') unless has($r, "dumper");
+
+ my ($name, $type) = (split "/", $r->uri)[-2,-1];
+
+ no strict 'refs';
+ my @retval = "<p>\nData Dump of $name $type\n</p>\n<pre>\n";
+ my $str = Data::Dumper->Dump([*$name{$type}], ['*'.$name]);
+ $str = escape_html($str);
+ $str =~ s/= \\/= /; #whack backwack
+ push @retval, $str, "\n";
+ push @retval, peek_link($r, $name, $type);
+ push @retval, b_graph_link($r, $name);
+ push @retval, "</pre>";
+ \@retval;
+}
+
+sub cv_file {
+ my $obj = shift;
+ $obj->can('FILEGV') ? $obj->FILEGV->SV->PV : $obj->FILE;
+}
+
+sub status_cv_dump {
+ my ($r) = @_;
+ return [] unless has($r, "b");
+
+ no strict 'refs';
+ my ($name, $type) = (split "/", $r->uri)[-2,-1];
+ # could be another child, which doesn't have this symbol table?
+ return unless *$name{CODE};
+
+ my @retval = "<p>Subroutine info for <b>$name</b></p>\n<pre>\n";
+ my $obj = B::svref_2object(*$name{CODE});
+ my $file = cv_file($obj);
+ my $stash = $obj->GV->STASH->NAME;
+ my $script = $r->location;
+
+ push @retval, "File: ",
+ (-e $file ? qq(<a href="file:$file">$file</a>) : $file), "\n";
+
+ my $cv = $obj->GV->CV;
+ my $proto = $cv->PV if $cv->can('PV');
+
+ push @retval, qq(Package: <a href="$script?$stash">$stash</a>\n);
+ push @retval, "Line: ", $obj->GV->LINE, "\n";
+ push @retval, "Prototype: ", $proto || "none", "\n";
+ push @retval, "XSUB: ", $obj->XSUB ? "yes" : "no", "\n";
+ push @retval, peek_link($r, $name, $type);
+ push @retval, b_graph_link($r, $name);
+ push @retval, xref_link($r, $name);
+ push @retval, b_lexinfo_link($r, $name);
+ push @retval, b_terse_link($r, $name);
+ push @retval, b_terse_size_link($r, $name);
+ push @retval, b_deparse_link($r, $name);
+ push @retval, b_fathom_link($r, $name);
+ push @retval, "</pre>";
+ \@retval;
+}
+
+sub b_lexinfo_link {
+ my ($r, $name) = @_;
+
+ return unless has($r, "lexinfo");
+
+ my $script = $r->location;
+ return qq(\n<a href="$script/$name?noh_b_lexinfo">Lexical Info</a>\n);
+}
+
+sub noh_b_lexinfo {
+ my $r = shift;
+
+ $r->content_type("text/plain");
+ return unless has($r, "lexinfo");
+
+ no strict 'refs';
+ my ($name) = (split "/", $r->uri)[-1];
+ $r->print("Lexical Info for $name\n\n");
+ my $lexi = B::LexInfo->new;
+ my $info = $lexi->cvlexinfo($name);
+ $r->print(${ $lexi->dumper($info) });
+}
+
+my %b_terse_exp = ('slow' => 'syntax', 'exec' => 'execution', basic => 'syntax');
+
+sub b_terse_link {
+ my ($r, $name) = @_;
+
+ return unless has($r, "terse");
+
+ my $script = $r->location;
+ my @retval;
+ for (qw(exec basic)) {
+ my $exp = "$b_terse_exp{$_} order";
+ push @retval,
+ qq(\n<a href="$script/$_/$name?noh_b_terse">Syntax Tree Dump ($exp)</a>\n);
+ }
+ join '', @retval;
+}
+
+sub noh_b_terse {
+ my $r = shift;
+
+ $r->content_type("text/plain");
+ return unless has($r, "terse");
+
+ no strict 'refs';
+ my ($arg, $name) = (split "/", $r->uri)[-2,-1];
+ $r->print("Syntax Tree Dump ($b_terse_exp{$arg}) for $name\n\n");
+
+ # XXX: blead perl dumps things to STDERR, though the same version
+ # works fine with 1.27
+ # B::Concise couldn't parse XS code before perl patch 24681 (perl 5.9.3)
+ # B::Terse is deprecated and just a wrapper around B::Concise now adays
+ eval { B::Concise::compile("-terse", "-$arg", $name)->() };
+ if ($@) {
+ $r->print("B::Concise has failed: $@");
+ }
+}
+
+sub b_terse_size_link {
+ my ($r, $name) = @_;
+
+ return unless has($r, "tersesize");
+
+ my $script = $r->location;
+ my @retval;
+ for (qw(exec slow)) {
+ my $exp = "$b_terse_exp{$_} order";
+ push @retval,
+ qq(\n<a href="$script/$_/$name?noh_b_terse_size">Syntax Tree Size ($exp)</a>\n);
+ }
+ join '', @retval;
+}
+
+sub noh_b_terse_size {
+ my $r = shift;
+
+ $r->content_type("text/html");
+ return unless has($r, "tersesize");
+
+ $r->print('<pre>');
+ my ($arg, $name) = (split "/", $r->uri)[-2,-1];
+ my $uri = $r->location;
+ my $link = qq{<a href="$uri/$name/CODE?cv_dump">$name</a>};
+ $r->print("Syntax Tree Size ($b_terse_exp{$arg} order) for $link\n\n");
+ B::TerseSize::compile($arg, $name)->();
+}
+
+sub b_package_size_link {
+ my ($r, $name) = @_;
+
+ return unless has($r, "packagesize");
+
+ my $script = $r->location;
+ qq(<a href="$script/$name?noh_b_package_size">Memory Usage</a>\n);
+}
+
+sub noh_b_package_size {
+ my ($r) = @_;
+
+ $r->content_type("text/html");
+ return unless has($r, "packagesize");
+
+ $r->print('<pre>');
+
+ no strict 'refs';
+ my ($package) = (split "/", $r->uri)[-1];
+ my $script = $r->location;
+ $r->print("Memory Usage for package $package\n\n");
+ my ($subs, $opcount, $opsize) = B::TerseSize::package_size($package);
+ my $Kb = sprintf "%.2f", $opsize / 1024;
+ my $Mb = sprintf "%.2f", $Kb / 1000;
+ $r->print("Totals: $opsize bytes, $Kb Kb, $Mb Mb | $opcount OPs\n\n");
+
+ my $nlen = 0;
+ my @keys = map {
+ $nlen = length > $nlen ? length : $nlen;
+ $_;
+ } (sort { $subs->{$b}->{size} <=> $subs->{$a}->{size} } keys %$subs);
+
+ my $clen = $subs->{$keys[0]}->{count} ?
+ length $subs->{$keys[0]}->{count} : 0;
+ my $slen = length $subs->{$keys[0]}->{size};
+
+ for my $name (@keys) {
+ my $stats = $subs->{$name};
+ if ($name =~ /^my /) {
+ $r->printf("%-${nlen}s %${slen}d bytes\n", $name, $stats->{size});
+ }
+ elsif ($name =~ /^\*(\w+)\{(\w+)\}/) {
+ my $link = qq(<a href="$script/$package\::$1/$2?data_dump">);
+ $r->printf("$link%-${nlen}s</a> %${slen}d bytes\n",
+ $name, $stats->{size});
+ }
+ else {
+ my $link =
+ qq(<a href="$script/slow/$package\::$name?noh_b_terse_size">);
+ $r->printf("$link%-${nlen}s</a> %${slen}d bytes | %${clen}d OPs\n",
+ $name, $stats->{size}, $stats->{count});
+ }
+ }
+}
+
+sub b_deparse_link {
+ my ($r, $name) = @_;
+
+ return unless has($r, "deparse");
+
+ my $script = $r->location;
+ return qq(\n<a href="$script/$name?noh_b_deparse">Deparse</a>\n);
+}
+
+sub noh_b_deparse {
+ my $r = shift;
+
+ $r->content_type("text/plain");
+ return unless has($r, "deparse");
+
+ my $name = (split "/", $r->uri)[-1];
+ $r->print("Deparse of $name\n\n");
+ my $deparse = B::Deparse->new(split /\s+/,
+ $r->dir_config('StatusDeparseOptions')||"");
+ my $body = $deparse->coderef2text(\&{$name});
+ $r->print("sub $name $body");
+}
+
+sub b_fathom_link {
+ my ($r, $name) = @_;
+
+ return unless has($r, "fathom");
+
+ my $script = $r->location;
+ return qq(\n<a href="$script/$name?noh_b_fathom">Fathom Score</a>\n);
+}
+
+sub noh_b_fathom {
+ my $r = shift;
+
+ $r->content_type("text/plain");
+ return unless has($r, "fathom");
+
+ my $name = (split "/", $r->uri)[-1];
+ $r->print("Fathom Score of $name\n\n");
+ my $fathom = B::Fathom->new(split /\s+/,
+ $r->dir_config('StatusFathomOptions')||"");
+ $r->print($fathom->fathom(\&{$name}));
+}
+
+sub peek_link {
+ my ($r, $name, $type) = @_;
+
+ return unless has($r, "peek");
+
+ my $script = $r->location;
+ return qq(\n<a href="$script/$name/$type?noh_peek">Peek Dump</a>\n);
+}
+
+sub noh_peek {
+ my $r = shift;
+
+ $r->content_type("text/plain");
+ return unless has($r, "peek");
+
+ no strict 'refs';
+ my ($name, $type) = (split "/", $r->uri)[-2,-1];
+ $type =~ s/^FUNCTION$/CODE/;
+ $r->print("Peek Dump of $name $type\n\n");
+ Apache::Peek::Dump(*{$name}{$type});
+}
+
+sub xref_link {
+ my ($r, $name) = @_;
+
+ return unless has($r, "xref");
+
+ my $script = $r->location;
+ return qq(\n<a href="$script/$name?noh_xref">Cross Reference Report</a>\n);
+}
+
+sub noh_xref {
+ my $r = shift;
+
+ $r->content_type("text/plain");
+ return unless has($r, "xref");
+
+ (my $thing = $r->path_info) =~ s:^/::;
+ $r->print("Xref of $thing\n");
+ B::Xref::compile($thing)->();
+}
+
+$Apache2::Status::BGraphCache ||= 0;
+if ($Apache2::Status::BGraphCache) {
+ Apache2->server->push_handlers(PerlChildExitHandler => sub {
+ unlink keys %Apache2::Status::BGraphCache;
+ });
+}
+
+sub b_graph_link {
+ my ($r, $name) = @_;
+
+ return unless has($r, "graph");
+
+ my $script = $r->location;
+ return qq(\n<a href="$script/$name?noh_b_graph">OP Tree Graph</a>\n);
+}
+
+sub noh_b_graph {
+ my $r = shift;
+
+ return unless has($r, "graph");
+
+ untie *STDOUT;
+
+ my $dir = File::Spec->catfile(Apache2::ServerUtil::server_root(),
+ ($r->dir_config("GraphDir") || "logs/b_graphs"));
+
+ mkdir $dir, 0755 unless -d $dir;
+
+ (my $thing = $r->path_info) =~ s:^/::;
+ $thing =~ s{::}{-}g; # :: is not allowed in the filename on some OS
+ my $type = "dot";
+ my $file = "$dir/$thing.$$.gif";
+
+ unless (-e $file) {
+ my $rv = tie *STDOUT, "B::Graph", $r, $file;
+ unless ($rv) {
+ $r->content_type("text/plain");
+ $r->print("dot not found\n");
+ }
+ else {
+ B::Graph::compile("-$type", $thing)->();
+ (tied *STDOUT)->{graph}->close;
+ }
+ }
+
+ if (-s $file) {
+ $r->content_type("image/gif");
+ $r->sendfile($file);
+ }
+ else {
+ $r->content_type("text/plain");
+ $r->print("Graph of $thing failed!\n");
+ }
+ if ($Apache2::Status::BGraphCache) {
+ $Apache2::Status::BGraphCache{$file}++;
+ }
+ else {
+ unlink $file;
+ }
+
+ 0;
+}
+
+sub B::Graph::TIEHANDLE {
+ my ($class, $r, $file) = @_;
+
+ if ($file =~ /^([^<>|;]+)$/) {
+ $file = $1;
+ }
+ else {
+ die "TAINTED data in THING=> ($file)";
+ }
+
+ $ENV{PATH} = join ":", qw{/usr/bin /usr/local/bin};
+ my $dot = $r->dir_config("Dot") || "dot";
+
+ require IO::File;
+ my $pipe = IO::File->new("|$dot -Tgif -o $file");
+ $pipe && $pipe->autoflush(1);
+
+ if ($pipe) {
+ return bless {
+ graph => $pipe,
+ r => $r,
+ }, $class;
+ }
+ else {
+ return;
+ }
+}
+
+sub B::Graph::PRINT {
+ my $self = shift;
+
+ $self->{graph}->print(@_);
+}
+
+my %can_dump = map {$_,1} qw(scalars arrays hashes);
+
+sub as_HTML {
+ my ($self, $package, $r) = @_;
+
+ my @m = qw(<table>);
+ my $uri = $r->location;
+ my $is_main = $package eq "main";
+
+ my $do_dump = has($r, "dumper");
+
+ my @methods = sort keys %{$self->{'AUTOLOAD'}};
+
+ if ($is_main) {
+ @methods = grep { $_ ne "packages" } @methods;
+ unshift @methods, "packages";
+ }
+
+ for my $type (@methods) {
+ (my $dtype = uc $type) =~ s/E?S$//;
+ push @m, "<tr><td valign=\"top\"><b>$type</b></td>";
+ my @line = ();
+
+ for (sort $self->_partdump(uc $type)) {
+ s/([\000-\037\177])/ '^' . pack('c', ord($1) ^ 64)/eg;
+
+ if ($type eq "scalars") {
+ no strict 'refs';
+ next unless defined eval { $$_ };
+ }
+
+ if ($type eq "packages") {
+ push @line, qq(<a href="$uri?$_">$_</a>);
+ }
+ elsif ($type eq "functions") {
+ if (has($r, "b")) {
+ push @line, qq(<a href="$uri/$_/$dtype?cv_dump">$_</a>);
+ }
+ else {
+ push @line, $_;
+ }
+ }
+ elsif ($do_dump and $can_dump{$type}) {
+ next if /_</;
+ push @line, qq(<a href="$uri/$_/$dtype?data_dump">$_</a>);
+ }
+ else {
+ push @line, $_;
+ }
+ }
+ push @m, "<td>" . join(", ", @line) . "</td></tr>\n";
+ }
+ push @m, "</table>";
+
+ return join "\n", @m, "<hr>", b_package_size_link($r, $package);
+}
+
+sub escape_html {
+ my $str = shift;
+
+ $str =~ s/&/&/g;
+ $str =~ s/</</g;
+ $str =~ s/>/>/g;
+
+ return $str;
+}
+
+sub myconfig {
+ require Config;
+ # Config::myconfig(); fails under threads with (5.8.0 < perl < 5.8.3)
+ # "Modification of a read-only value attempted"
+ # provide a workaround
+ if ($Config::Config{useithreads} and $] > 5.008 and $] < 5.008003) {
+ return $Config::summary_expanded if $Config::summary_expanded;
+ ($Config::summary_expanded = $Config::summary) =~
+ s{\$(\w+)}
+ { my $c = $Config::Config{$1}; defined($c) ? $c : 'undef' }ge;
+ return $Config::summary_expanded;
+ }
+ else {
+ return Config::myconfig();
+ }
+}
+
+# mp2 modules have to deal with situations where a binary incompatible
+# mp1 version of the same module is installed in the same
+# tree. therefore when checking for a certain version, one wants to
+# check the version of the module 'require()' will find without
+# loading that module. this function partially adopted from
+# ExtUtils::MM_Unix does just that. it returns the version number of
+# the first module that it finds, forcing numerical context, making
+# the return value suitable for immediate numerical comparison
+# operation. (i.e. 2.03-dev will be returned as 2.03, 0 will be
+# returned when the parsing has failed or a module wasn't found).
+sub parse_version {
+ my $name = shift;
+ die "no module name passed" unless $name;
+ my $file = File::Spec->catfile(split /::/, $name) . '.pm';
+ for my $dir (@INC) {
+ next if ref $dir; # skip code refs
+
+ my $pmfile = File::Spec->catfile($dir, $file);
+ next unless -r $pmfile;
+
+ open my $fh, $pmfile or die "can't open $pmfile: $!";
+
+ my $inpod = 0;
+ my $version;
+ while (<$fh>) {
+ $inpod = /^=(?!cut)/ ? 1 : /^=cut/ ? 0 : $inpod;
+ next if $inpod || /^\s*#/;
+
+ chomp;
+ next unless /([\$*])(([\w\:\']*)\bVERSION)\b.*\=/;
+ { local($1, $2); ($_ = $_) = /(.*)/; } # untaint
+ my $eval = qq{
+ package Apache2::Status::_version;
+ no strict;
+
+ local $1$2;
+ \$$2=undef; do {
+ $_
+ }; \$$2
+ };
+ no warnings;
+ $version = eval $eval;
+ warn "Could not eval '$eval' in $pmfile: $@" if $@;
+ last;
+ }
+
+ close $fh;
+
+ # avoid situations like "2.03-dev" and return a numerical
+ # version
+ if (defined $version) {
+ no warnings;
+ $version += 0; # force number
+ return $version;
+ }
+ }
+
+ return 0; # didn't find the file or the version number
+}
+
+1;
+
+__END__
+
diff --git a/2_0_13/lib/Apache2/XSLoader.pm b/2_0_13/lib/Apache2/XSLoader.pm
new file mode 100644
index 0000000..0c848a1
--- /dev/null
+++ b/2_0_13/lib/Apache2/XSLoader.pm
@@ -0,0 +1,37 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+package Apache2::XSLoader;
+
+use strict;
+use warnings FATAL => 'all';
+
+use XSLoader ();
+
+BEGIN {
+ unless (defined &BOOTSTRAP) {
+ *BOOTSTRAP = sub () { 0 };
+ }
+}
+
+sub load {
+ return unless BOOTSTRAP;
+ # do not change the next line and do not insert anything below it in this
+ # function. XSLoader::load depends on it.
+ goto &XSLoader::load;
+}
+
+1;
diff --git a/2_0_13/lib/Apache2/compat.pm b/2_0_13/lib/Apache2/compat.pm
new file mode 100644
index 0000000..2a1a8d7
--- /dev/null
+++ b/2_0_13/lib/Apache2/compat.pm
@@ -0,0 +1,873 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+package Apache2::compat;
+
+use strict;
+use warnings FATAL => 'all';
+no warnings 'redefine';
+
+#1.xx compat layer
+#some of this will stay as-is
+#some will be implemented proper later on
+
+#there's enough here to get simple registry scripts working
+#add to startup.pl:
+#use Apache2::compat ();
+#use lib ...; #or something to find 1.xx Apache2::Registry
+
+#Alias /perl /path/to/perl/scripts
+#<Location /perl>
+# Options +ExecCGI
+# SetHandler modperl
+# PerlResponseHandler Apache2::Registry
+#</Location>
+
+use Apache2::Connection ();
+use Apache2::ServerRec ();
+use Apache2::ServerUtil ();
+use Apache2::Access ();
+use Apache2::Module ();
+use Apache2::RequestRec ();
+use Apache2::RequestIO ();
+use Apache2::RequestUtil ();
+use Apache2::Response ();
+use Apache2::SubRequest ();
+use Apache2::Filter ();
+use Apache2::Util ();
+use Apache2::Log ();
+use Apache2::URI ();
+use APR::Date ();
+use APR::Table ();
+use APR::Pool ();
+use APR::URI ();
+use APR::Util ();
+use APR::Brigade ();
+use APR::Bucket ();
+use mod_perl2 ();
+
+use Symbol ();
+use File::Spec ();
+
+use APR::Const -compile => qw(FINFO_NORM FINFO_PROT);
+
+use constant WIN32 => ($^O eq "MSWin32");
+
+BEGIN {
+ $INC{'Apache.pm'} = __FILE__;
+
+ $INC{'Apache/Constants.pm'} = __FILE__;
+
+ $INC{'Apache/File.pm'} = __FILE__;
+
+ $INC{'Apache/Table.pm'} = __FILE__;
+}
+
+($Apache::Server::Starting, $Apache::Server::ReStarting) =
+ Apache2::ServerUtil::restart_count() == 1 ? (1, 0) : (0, 1);
+
+# api => "overriding code"
+# the overriding code, needs to "return" the original CODE reference
+# when eval'ed , so that it can be restored later
+my %overridable_mp2_api = (
+ 'Apache2::RequestRec::filename' => <<'EOI',
+{
+ require Apache2::RequestRec;
+ require APR::Finfo;
+ my $orig_sub = *Apache2::RequestRec::filename{CODE};
+ *Apache2::RequestRec::filename = sub {
+ my ($r, $newfile) = @_;
+ my $old_filename;
+ if (defined $newfile) {
+ $old_filename = $r->$orig_sub($newfile);
+ die "'$newfile' doesn't exist" unless -e $newfile;
+ my $wanted = APR::Const::FINFO_NORM;
+ if (WIN32) {
+ $wanted &= ~APR::Const::FINFO_PROT;
+ }
+ $r->finfo(APR::Finfo::stat($newfile, $wanted, $r->pool));
+ }
+ else {
+ $old_filename = $r->$orig_sub();
+ }
+ return $old_filename;
+ };
+ $orig_sub;
+}
+
+EOI
+ 'Apache2::RequestRec::notes' => <<'EOI',
+{
+ require Apache2::RequestRec;
+ my $orig_sub = *Apache2::RequestRec::notes{CODE};
+ *Apache2::RequestRec::notes = sub {
+ my $r = shift;
+ return wantarray()
+ ? ($r->table_get_set(scalar($r->$orig_sub), @_))
+ : scalar($r->table_get_set(scalar($r->$orig_sub), @_));
+ };
+ $orig_sub;
+}
+EOI
+
+ 'Apache2::RequestRec::finfo' => <<'EOI',
+{
+ require APR::Finfo;
+ my $orig_sub = *APR::Finfo::finfo{CODE};
+ sub Apache2::RequestRec::finfo {
+ my $r = shift;
+ stat $r->filename;
+ \*_;
+ }
+ $orig_sub;
+}
+EOI
+
+ 'Apache2::Connection::local_addr' => <<'EOI',
+{
+ require Apache2::Connection;
+ require Socket;
+ require APR::SockAddr;
+ my $orig_sub = *Apache2::Connection::local_addr{CODE};
+ *Apache2::Connection::local_addr = sub {
+ my $c = shift;
+ Socket::pack_sockaddr_in($c->$orig_sub->port,
+ Socket::inet_aton($c->$orig_sub->ip_get));
+ };
+ $orig_sub;
+}
+EOI
+
+ 'Apache2::Connection::remote_addr' => <<'EOI',
+{
+ require Apache2::Connection;
+ require APR::SockAddr;
+ require Socket;
+ my $orig_sub;
+ if (defined *Apache2::Connection::client_addr{CODE}) { # httpd-2.4
+ $orig_sub = *Apache2::Connection::client_addr{CODE};
+ } else { # httpd-2.2
+ $orig_sub = *Apache2::Connection::remote_addr{CODE};
+ }
+ *Apache2::Connection::remote_addr = sub {
+ my $c = shift;
+ if (@_) {
+ my $addr_in = shift;
+ my ($port, $addr) = Socket::unpack_sockaddr_in($addr_in);
+ $c->$orig_sub->ip_set($addr);
+ $c->$orig_sub->port_set($port);
+ }
+ else {
+ Socket::pack_sockaddr_in($c->$orig_sub->port,
+ Socket::inet_aton($c->$orig_sub->ip_get));
+ }
+ };
+ $orig_sub;
+}
+EOI
+
+ 'Apache2::Module::top_module' => <<'EOI',
+{
+ require Apache2::Module;
+ my $orig_sub = *Apache2::Module::top_module{CODE};
+ *Apache2::Module::top_module = sub {
+ shift;
+ $orig_sub->(@_);
+ };
+ $orig_sub;
+}
+EOI
+
+ 'Apache2::Module::get_config' => <<'EOI',
+{
+ require Apache2::Module;
+ my $orig_sub = *Apache2::Module::get_config{CODE};
+ *Apache2::Module::get_config = sub {
+ shift;
+ $orig_sub->(@_);
+ };
+ $orig_sub;
+}
+EOI
+
+ 'APR::URI::unparse' => <<'EOI',
+{
+ require APR::URI;
+ my $orig_sub = *APR::URI::unparse{CODE};
+ *APR::URI::unparse = sub {
+ my ($uri, $flags) = @_;
+
+ if (defined $uri->hostname && !defined $uri->scheme) {
+ # we do this only for back compat, the new APR::URI is
+ # protocol-agnostic and doesn't fallback to 'http' when the
+ # scheme is not provided
+ $uri->scheme('http');
+ }
+
+ $orig_sub->(@_);
+ };
+ $orig_sub;
+}
+EOI
+
+ 'Apache2::Util::ht_time' => <<'EOI',
+{
+ require Apache2::Util;
+ my $orig_sub = *Apache2::Util::ht_time{CODE};
+ *Apache2::Util::ht_time = sub {
+ my $r = Apache2::compat::request('Apache2::Util::ht_time');
+ return $orig_sub->($r->pool, @_);
+ };
+ $orig_sub;
+}
+
+EOI
+
+);
+
+my %overridden_mp2_api = ();
+
+# this function enables back-compatible APIs which can't coexist with
+# mod_perl 2.0 APIs with the same name and therefore it should be
+# avoided if possible.
+#
+# it expects a list of fully qualified functions, like
+# "Apache2::RequestRec::finfo"
+sub override_mp2_api {
+ my (@subs) = @_;
+
+ for my $sub (@subs) {
+ unless (exists $overridable_mp2_api{$sub}) {
+ die __PACKAGE__ . ": $sub is not overridable";
+ }
+ if (exists $overridden_mp2_api{$sub}) {
+ warn __PACKAGE__ . ": $sub has been already overridden";
+ next;
+ }
+ $overridden_mp2_api{$sub} = eval $overridable_mp2_api{$sub};
+ if ($@) {
+ die "error overriding $sub : $@";
+ }
+ unless (exists $overridden_mp2_api{$sub} &&
+ ref($overridden_mp2_api{$sub}) eq 'CODE') {
+ die "overriding $sub didn't return a CODE ref";
+ }
+ }
+}
+
+# restore_mp2_api does the opposite of override_mp2_api(), it removes
+# the overriden API and restores the original mod_perl 2.0 API
+sub restore_mp2_api {
+ my (@subs) = @_;
+
+ for my $sub (@subs) {
+ unless (exists $overridable_mp2_api{$sub}) {
+ die __PACKAGE__ . ": $sub is not overridable";
+ }
+ unless (exists $overridden_mp2_api{$sub}) {
+ warn __PACKAGE__ . ": can't restore $sub, " .
+ "as it has not been overridden";
+ next;
+ }
+ # XXX: 5.8.2+ can't delete and assign at once - gives:
+ # Attempt to free unreferenced scalar
+ # after perl_clone. the 2 step works ok. to reproduce:
+ # t/TEST -maxclients 1 perl/ithreads2.t compat/request.t
+ my $original_sub = $overridden_mp2_api{$sub};
+ delete $overridden_mp2_api{$sub};
+ no warnings 'redefine';
+ no strict 'refs';
+ *$sub = $original_sub;
+ }
+}
+
+sub request {
+ my $what = shift;
+
+ my $r = Apache2::RequestUtil->request;
+
+ unless ($r) {
+ die "cannot use $what ",
+ "without 'SetHandler perl-script' ",
+ "or 'PerlOptions +GlobalRequest'";
+ }
+
+ $r;
+}
+
+{
+ my $orig_sub = *Apache2::Module::top_module{CODE};
+ *Apache2::Module::top_module = sub {
+ $orig_sub->();
+ };
+}
+
+{
+ my $orig_sub = *Apache2::Module::get_config{CODE};
+ *Apache2::Module::get_config = sub {
+ shift if $_[0] eq 'Apache2::Module';
+ $orig_sub->(@_);
+ };
+}
+
+package Apache::Server;
+# XXX: is that good enough? see modperl/src/modules/perl/mod_perl.c:367
+our $CWD = Apache2::ServerUtil::server_root();
+
+our $AddPerlVersion = 1;
+
+sub warn {
+ shift if @_ and $_[0] eq 'Apache::Server';
+ Apache2::ServerRec::warn(@_);
+}
+
+package Apache;
+
+sub request {
+ return Apache2::compat::request(@_);
+}
+
+sub unescape_url_info {
+ my ($class, $string) = @_;
+ Apache2::URI::unescape_url($string);
+ $string =~ tr/+/ /;
+ $string;
+}
+
+#sorry, have to use $r->Apache2::args at the moment
+#for list context splitting
+
+sub args {
+ my $r = shift;
+ my $args = $r->args;
+ return $args unless wantarray;
+ return $r->parse_args($args);
+}
+
+sub server_root_relative {
+ my $class = shift;
+ if (@_ && defined($_[0]) && File::Spec->file_name_is_absolute($_[0])) {
+ return File::Spec->catfile(@_);
+ }
+ else {
+ File::Spec->catfile(Apache2::ServerUtil::server_root(), @_);
+ }
+}
+
+sub exit {
+ require ModPerl::Util;
+
+ my $status = 0;
+ my $nargs = @_;
+
+ if ($nargs == 2) {
+ $status = $_[1];
+ }
+ elsif ($nargs == 1 and $_[0] =~ /^\d+$/) {
+ $status = $_[0];
+ }
+
+ ModPerl::Util::exit($status);
+}
+
+#XXX: warn
+sub import {
+}
+
+sub untaint {
+ shift;
+ require ModPerl::Util;
+ ModPerl::Util::untaint(@_);
+}
+
+sub module {
+ require Apache2::Module;
+ die 'Usage: Apache2->module($name)' if @_ != 2;
+ return Apache2::Module::loaded($_[1]);
+}
+
+sub gensym {
+ return Symbol::gensym();
+}
+
+sub define {
+ shift if @_ == 2;
+ Apache2::ServerUtil::exists_config_define(@_);
+}
+
+sub log_error {
+ Apache2::ServerUtil->server->log_error(@_);
+}
+
+sub warn {
+ shift if @_ and $_[0] eq 'Apache';
+ Apache2::ServerRec::warn(@_);
+}
+
+sub httpd_conf {
+ shift;
+ my $obj;
+ eval { $obj = Apache2::RequestUtil->request };
+ $obj = Apache2::ServerUtil->server if $@;
+ my $err = $obj->add_config([split /\n/, join '', @_]);
+ die $err if $err;
+}
+
+# mp2 always can stack handlers
+sub can_stack_handlers { 1; }
+
+sub push_handlers {
+ shift;
+ Apache2::ServerUtil->server->push_handlers(@_);
+}
+
+sub set_handlers {
+ shift;
+ Apache2::ServerUtil->server->set_handlers(@_);
+}
+
+sub get_handlers {
+ shift;
+ Apache2::ServerUtil->server->get_handlers(@_);
+}
+
+package Apache::Constants;
+
+use Apache2::Const ();
+
+sub import {
+ my $class = shift;
+ my $package = scalar caller;
+
+ my @args = @_;
+
+ # treat :response as :common - it's not perfect
+ # but simple and close enough for the majority
+ my %args = map { s/^:response$/:common/; $_ => 1 } @args;
+
+ Apache2::Const->compile($package => keys %args);
+}
+
+#no need to support in 2.0
+sub export {}
+
+sub SERVER_VERSION { Apache2::ServerUtil::get_server_version() }
+
+package Apache2::RequestRec;
+
+use Apache2::Const -compile => qw(REMOTE_NAME);
+
+#no longer exist in 2.0
+sub soft_timeout {}
+sub hard_timeout {}
+sub kill_timeout {}
+sub reset_timeout {}
+
+# this function is from mp1's Apache2::SubProcess 3rd party module
+# which is now a part of mp2 API. this function doesn't exist in 2.0.
+sub cleanup_for_exec {}
+
+sub current_callback {
+ require ModPerl::Util;
+ return ModPerl::Util::current_callback();
+}
+
+sub send_http_header {
+ my ($r, $type) = @_;
+
+ # since send_http_header() in mp1 was telling mod_perl not to
+ # parse headers and in mp2 one must call $r->content_type($type) to
+ # perform the same, we make sure that this happens
+ $type = $r->content_type || 'text/html' unless defined $type;
+
+ $r->content_type($type);
+}
+
+#we support Apache2::RequestUtil->request; this is needed to support $r->request
+#XXX: seems sorta backwards
+*request = \&Apache2::request;
+
+sub table_get_set {
+ my ($r, $table) = (shift, shift);
+ my ($key, $value) = @_;
+
+ if (1 == @_) {
+ return wantarray()
+ ? ($table->get($key))
+ : scalar($table->get($key));
+ }
+ elsif (2 == @_) {
+ if (defined $value) {
+ return wantarray()
+ ? ($table->set($key, $value))
+ : scalar($table->set($key, $value));
+ }
+ else {
+ return wantarray()
+ ? ($table->unset($key))
+ : scalar($table->unset($key));
+ }
+ }
+ elsif (0 == @_) {
+ return $table;
+ }
+ else {
+ my $name = (caller(1))[3];
+ $r->warn("Usage: \$r->$name([key [,val]])");
+ }
+}
+
+sub header_out {
+ my $r = shift;
+ return wantarray()
+ ? ($r->table_get_set(scalar($r->headers_out), @_))
+ : scalar($r->table_get_set(scalar($r->headers_out), @_));
+}
+
+sub header_in {
+ my $r = shift;
+ return wantarray()
+ ? ($r->table_get_set(scalar($r->headers_in), @_))
+ : scalar($r->table_get_set(scalar($r->headers_in), @_));
+}
+
+sub err_header_out {
+ my $r = shift;
+ return wantarray()
+ ? ($r->table_get_set(scalar($r->err_headers_out), @_))
+ : scalar($r->table_get_set(scalar($r->err_headers_out), @_));
+}
+
+
+sub register_cleanup {
+ shift->pool->cleanup_register(@_);
+}
+
+*post_connection = \®ister_cleanup;
+
+sub get_remote_host {
+ my ($r, $type) = @_;
+ $type = Apache2::Const::REMOTE_NAME unless defined $type;
+ $r->connection->get_remote_host($type, $r->per_dir_config);
+}
+
+sub parse_args {
+ my ($r, $string) = @_;
+ return () unless defined $string and $string;
+
+ return map {
+ tr/+/ /;
+ s/%([0-9a-fA-F]{2})/pack("C",hex($1))/ge;
+ $_;
+ } split /[=&;]/, $string, -1;
+}
+
+use Apache2::Const -compile => qw(MODE_READBYTES);
+use APR::Const -compile => qw(SUCCESS BLOCK_READ);
+
+use constant IOBUFSIZE => 8192;
+
+sub content {
+ my $r = shift;
+
+ my $bb = APR::Brigade->new($r->pool,
+ $r->connection->bucket_alloc);
+
+ my $data = '';
+ my $seen_eos = 0;
+ do {
+ $r->input_filters->get_brigade($bb, Apache2::Const::MODE_READBYTES,
+ APR::Const::BLOCK_READ, IOBUFSIZE);
+ while (!$bb->is_empty) {
+ my $b = $bb->first;
+
+ if ($b->is_eos) {
+ $seen_eos++;
+ last;
+ }
+
+ if ($b->read(my $buf)) {
+ $data .= $buf;
+ }
+
+ $b->delete;
+ }
+ } while (!$seen_eos);
+
+ $bb->destroy;
+
+ return $data unless wantarray;
+ return $r->parse_args($data);
+}
+
+sub server_root_relative {
+ my $r = shift;
+ File::Spec->catfile(Apache2::ServerUtil::server_root(), @_);
+}
+
+sub clear_rgy_endav {
+ my ($r, $script_name) = @_;
+ require ModPerl::Global;
+ my $package = 'Apache2::ROOT' . $script_name;
+ ModPerl::Global::special_list_clear(END => $package);
+}
+
+sub stash_rgy_endav {
+ #see run_rgy_endav
+}
+
+#if somebody really wants to have END subroutine support
+#with the 1.x Apache2::Registry they will need to configure:
+# PerlHandler Apache2::Registry Apache2::compat::run_rgy_endav
+sub Apache2::compat::run_rgy_endav {
+ my $r = shift;
+
+ require ModPerl::Global;
+ require Apache2::PerlRun; #1.x's
+ my $package = Apache2::PerlRun->new($r)->namespace;
+
+ ModPerl::Global::special_list_call(END => $package);
+}
+
+sub seqno {
+ 1;
+}
+
+sub chdir_file {
+ #XXX resolve '.' in @INC to basename $r->filename
+}
+
+#XXX: would like to have a proper implementation
+#that reads line-by-line as defined by $/
+#the best way will probably be to use perlio in 5.8.0
+#anything else would be more effort than it is worth
+sub READLINE {
+ my $r = shift;
+ my $line;
+ $r->read($line, $r->headers_in->get('Content-length'));
+ $line ? $line : undef;
+}
+
+#XXX: howto convert PerlIO to apr_file_t
+#so we can use the real ap_send_fd function
+#2.0 ap_send_fd() also has an additional offset parameter
+
+sub send_fd_length {
+ my ($r, $fh, $length) = @_;
+
+ my $buff;
+ my $total_bytes_sent = 0;
+ my $len;
+
+ return 0 if $length == 0;
+
+ if (($length > 0) && ($total_bytes_sent + IOBUFSIZE) > $length) {
+ $len = $length - $total_bytes_sent;
+ }
+ else {
+ $len = IOBUFSIZE;
+ }
+
+ binmode $fh;
+
+ while (CORE::read($fh, $buff, $len)) {
+ $total_bytes_sent += $r->puts($buff);
+ }
+
+ $total_bytes_sent;
+}
+
+sub send_fd {
+ my ($r, $fh) = @_;
+ $r->send_fd_length($fh, -1);
+}
+
+sub is_main { !shift->main }
+
+# really old back-compat methods, they shouldn't be used in mp1
+*cgi_var = *cgi_env = \&Apache2::RequestRec::subprocess_env;
+
+package Apache::File;
+
+use Fcntl ();
+use Symbol ();
+use Carp ();
+
+sub new {
+ my ($class) = shift;
+ my $fh = Symbol::gensym;
+ my $self = bless $fh, ref($class)||$class;
+ if (@_) {
+ return $self->open(@_) ? $self : undef;
+ }
+ else {
+ return $self;
+ }
+}
+
+sub open {
+ my ($self) = shift;
+
+ Carp::croak("no Apache2::File object passed")
+ unless $self && ref($self);
+
+ # cannot forward @_ to open() because of its prototype
+ if (@_ > 1) {
+ my ($mode, $file) = @_;
+ CORE::open $self, $mode, $file;
+ }
+ else {
+ my $file = shift;
+ CORE::open $self, $file;
+ }
+}
+
+sub close {
+ my ($self) = shift;
+ CORE::close $self;
+}
+
+my $TMPNAM = 'aaaaaa';
+my $TMPDIR = $ENV{'TMPDIR'} || $ENV{'TEMP'} || '/tmp';
+($TMPDIR) = $TMPDIR =~ /^([^<>|;*]+)$/; #untaint
+my $Mode = Fcntl::O_RDWR()|Fcntl::O_EXCL()|Fcntl::O_CREAT();
+my $Perms = 0600;
+
+sub tmpfile {
+ my $class = shift;
+ my $limit = 100;
+ my $r = Apache2::compat::request('Apache::File->tmpfile');
+
+ while ($limit--) {
+ my $tmpfile = "$TMPDIR/${$}" . $TMPNAM++;
+ my $fh = $class->new;
+
+ sysopen $fh, $tmpfile, $Mode, $Perms
+ or die "failed to open $tmpfile: $!";
+ $r->pool->cleanup_register(sub { unlink $tmpfile });
+
+ if ($fh) {
+ return wantarray ? ($tmpfile, $fh) : $fh;
+ }
+ }
+}
+
+# the following functions now live in Apache2::RequestIO
+# * discard_request_body
+
+# the following functions now live in Apache2::Response
+# * meets_conditions
+# * set_content_length
+# * set_etag
+# * set_last_modified
+# * update_mtime
+
+# the following functions now live in Apache2::RequestRec
+# * mtime
+
+package Apache::Util;
+
+sub size_string {
+ my ($size) = @_;
+
+ if (!$size) {
+ $size = " 0k";
+ }
+ elsif ($size == -1) {
+ $size = " -";
+ }
+ elsif ($size < 1024) {
+ $size = " 1k";
+ }
+ elsif ($size < 1048576) {
+ $size = sprintf "%4dk", ($size + 512) / 1024;
+ }
+ elsif ($size < 103809024) {
+ $size = sprintf "%4.1fM", $size / 1048576.0;
+ }
+ else {
+ $size = sprintf "%4dM", ($size + 524288) / 1048576;
+ }
+
+ return $size;
+}
+
+*unescape_uri = \&Apache2::URI::unescape_url;
+
+*escape_path = \&Apache2::Util::escape_path;
+
+sub escape_uri {
+ my $path = shift;
+ my $r = Apache2::compat::request('Apache2::Util::escape_uri');
+ Apache2::Util::escape_path($path, $r->pool);
+}
+
+#tmp compat until ap_escape_html is reworked to not require a pool
+my %html_escapes = (
+ '<' => 'lt',
+ '>' => 'gt',
+ '&' => 'amp',
+ '"' => 'quot',
+);
+
+%html_escapes = map { $_, "&$html_escapes{$_};" } keys %html_escapes;
+
+my $html_escape = join '|', keys %html_escapes;
+
+sub escape_html {
+ my $html = shift;
+ $html =~ s/($html_escape)/$html_escapes{$1}/go;
+ $html;
+}
+
+*parsedate = \&APR::Date::parse_http;
+
+*validate_password = \&APR::Util::password_validate;
+
+sub Apache2::URI::parse {
+ my ($class, $r, $uri) = @_;
+
+ $uri ||= $r->construct_url;
+
+ APR::URI->parse($r->pool, $uri);
+}
+
+package Apache::Table;
+
+sub new {
+ my ($class, $r, $nelts) = @_;
+ $nelts ||= 10;
+ APR::Table::make($r->pool, $nelts);
+}
+
+package Apache::SIG;
+
+use Apache2::Const -compile => 'DECLINED';
+
+sub handler {
+ # don't set the SIGPIPE
+ return Apache2::Const::DECLINED;
+}
+
+package Apache2::Connection;
+
+# auth_type and user records don't exist in 2.0 conn_rec struct
+# 'PerlOptions +GlobalRequest' is required
+sub auth_type { shift; Apache2::RequestUtil->request->ap_auth_type(@_) }
+sub user { shift; Apache2::RequestUtil->request->user(@_) }
+
+1;
+__END__
diff --git a/2_0_13/lib/Apache2/porting.pm b/2_0_13/lib/Apache2/porting.pm
new file mode 100644
index 0000000..2432604
--- /dev/null
+++ b/2_0_13/lib/Apache2/porting.pm
@@ -0,0 +1,105 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+package Apache2::porting;
+
+use strict;
+use warnings FATAL => 'all';
+
+use Carp 'croak';
+
+use ModPerl::MethodLookup ();
+use Apache2::ServerUtil;
+
+use Apache2::Const -compile => 'OK';
+
+our $AUTOLOAD;
+
+### methods ###
+# handle:
+# - removed and replaced methods
+# - hinting the package names in which methods reside
+
+my %avail_methods = map { $_ => 1 }
+ (ModPerl::MethodLookup::avail_methods(),
+ ModPerl::MethodLookup::avail_methods_compat());
+
+# XXX: unfortunately it doesn't seem to be possible to install
+# *UNIVERSAL::AUTOLOAD at the server startup, httpd segfaults,
+# child_init seems to be the first stage where it works.
+Apache2::ServerUtil->server->push_handlers(
+ PerlChildInitHandler => \&porting_autoload);
+
+sub porting_autoload {
+ *UNIVERSAL::AUTOLOAD = sub {
+ # This is a porting module, no compatibility layers are allowed in
+ # this zone
+ croak("Apache2::porting can't be used with Apache2::compat")
+ if exists $ENV{"Apache2/compat.pm"};
+
+ (my $method = $AUTOLOAD) =~ s/.*:://;
+
+ # we skip DESTROY methods
+ return if $method eq 'DESTROY';
+
+ # we don't handle methods that we don't know about
+ croak "Undefined subroutine $AUTOLOAD called"
+ unless defined $method && exists $avail_methods{$method};
+
+ my ($hint, @modules) =
+ ModPerl::MethodLookup::lookup_method($method, @_);
+ $hint ||= "Can't find method $AUTOLOAD";
+ croak $hint;
+ };
+
+ return Apache2::Const::OK;
+}
+
+### packages ###
+# handle:
+# - removed and replaced packages
+
+my %packages = (
+ 'Apache::Constants' => [qw(Apache2::Const)],
+ 'Apache::Table' => [qw(APR::Table)],
+ 'Apache::File' => [qw(Apache2::Response Apache2::RequestRec)],
+ 'Apache' => [qw(ModPerl::Util Apache2::Module)],
+);
+
+BEGIN {
+ sub my_require {
+ my $package = $_[0];
+ $package =~ s|/|::|g;
+ $package =~ s|.pm$||;
+
+ # this picks the original require (which could be overriden
+ # elsewhere, so we don't lose that) because we haven't
+ # overriden it yet
+ return require $_[0] unless $packages{$package};
+
+ my $msg = "mod_perl 2.0 API doesn't include package '$package'.";
+ my @replacements = @{ $packages{$package}||[] };
+ if (@replacements) {
+ $msg .= " The package '$package' has moved to " .
+ join " ", map qq/'$_'/, @replacements;
+ }
+ croak $msg;
+ };
+
+ *CORE::GLOBAL::require = sub (*) { my_require($_[0])};
+}
+
+1;
diff --git a/2_0_13/lib/Bundle/Apache2.pm b/2_0_13/lib/Bundle/Apache2.pm
new file mode 100644
index 0000000..7b9ec42
--- /dev/null
+++ b/2_0_13/lib/Bundle/Apache2.pm
@@ -0,0 +1,70 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+package Bundle::Apache2;
+
+$VERSION = '1.00';
+
+1;
+
+__END__
+
+=head1 NAME
+
+Bundle::Apache2 - Install Apache mod_perl2 and related modules
+
+
+
+=head1 SYNOPSIS
+
+C<perl -MCPAN -e 'install Bundle::Apache2'>
+
+
+
+=head1 CONTENTS
+
+Bundle::ApacheTest - Needs for testing
+
+CGI 3.11 - Used in testing (it's in core, but some vendors exclude it)
+
+Chatbot::Eliza - Used in testing
+
+Compress::Zlib - Used in testing
+
+Devel::Symdump - Symbol table browsing with Apache::Status
+
+HTML::HeadParser - Used in testing
+
+IPC::Run3 - Used in testing
+
+LWP - Used in testing
+
+
+
+
+=head1 DESCRIPTION
+
+This bundle contains modules used by Apache mod_perl2.
+
+Asking CPAN.pm to install a bundle means to install the bundle itself
+along with all the modules contained in the CONTENTS section
+above. Modules that are up to date are not installed, of course.
+
+
+
+=head1 AUTHOR
+
+mod_perl 2 development team
diff --git a/2_0_13/lib/ModPerl/BuildMM.pm b/2_0_13/lib/ModPerl/BuildMM.pm
new file mode 100644
index 0000000..849f35e
--- /dev/null
+++ b/2_0_13/lib/ModPerl/BuildMM.pm
@@ -0,0 +1,377 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+package ModPerl::BuildMM;
+
+use strict;
+use warnings;
+
+use ExtUtils::MakeMaker ();
+use Cwd ();
+use File::Spec::Functions qw(catdir catfile splitdir);
+use File::Basename;
+use File::Find;
+
+use Apache2::Build ();
+use ModPerl::MM;
+use constant WIN32 => Apache2::Build::WIN32;
+use constant CYGWIN => Apache2::Build::CYGWIN;
+
+our %PM; #add files to installation
+
+# MM methods that this package overrides
+no strict 'refs';
+my $stash = \%{__PACKAGE__ . '::MY::'};
+my @methods = grep *{$stash->{$_}}{CODE}, keys %$stash;
+ModPerl::MM::override_eu_mm_mv_all_methods(@methods);
+use strict 'refs';
+
+my $apache_test_dir = catdir Cwd::getcwd(), "Apache-Test", "lib";
+
+#to override MakeMaker MOD_INSTALL macro
+sub mod_install {
+ q{$(PERL) -I$(INST_LIB) -I$(PERL_LIB) \\}."\n" .
+ qq{-I$apache_test_dir -MModPerl::BuildMM \\}."\n" .
+ q{-e "ExtUtils::Install::install({@ARGV},'$(VERBINST)',0,'$(UNINST)');"}."\n";
+}
+
+my $build;
+
+sub build_config {
+ my $key = shift;
+ $build ||= Apache2::Build->build_config;
+ return $build unless $key;
+ $build->{$key};
+}
+
+#the parent WriteMakefile moves MY:: methods into a different class
+#so alias them each time WriteMakefile is called in a subdir
+
+sub my_import {
+ no strict 'refs';
+ my $stash = \%{__PACKAGE__ . '::MY::'};
+ for my $sym (keys %$stash) {
+ next unless *{$stash->{$sym}}{CODE};
+ my $name = "MY::$sym";
+ undef &$name if defined &$name;
+ *$name = *{$stash->{$sym}}{CODE};
+ }
+}
+
+sub WriteMakefile {
+ my %args = @_;
+
+ $build ||= build_config();
+ ModPerl::MM::my_import(__PACKAGE__);
+
+ my $inc = $args{INC} || '';
+ $inc = $args{INC} if $args{INC};
+ $inc .= " " . $build->inc;
+ if (my $glue_inc = $build->{MP_XS_GLUE_DIR}) {
+ for (split /\s+/, $glue_inc) {
+ $inc .= " -I$_";
+ }
+ }
+
+ my $libs;
+ my @libs = ();
+ push @libs, $args{LIBS} if $args{LIBS};
+ if (Apache2::Build::BUILD_APREXT) {
+ # in order to decouple APR/APR::* from mod_perl.so,
+ # link these modules against the static MP_APR_LIB lib,
+ # rather than the mod_perl lib (which would demand mod_perl.so
+ # be available). For other modules, use mod_perl.lib as
+ # usual. This is done for APR in xs/APR/APR/Makefile.PL.
+ my $name = $args{NAME};
+ if ($name =~ /^APR::\w+$/) {
+ # For cygwin compatibility, the order of the libs should be
+ # <mod_perl libs> <apache libs>
+ @libs = ($build->mp_apr_lib, $build->apache_libs);
+ }
+ else {
+ @libs = ($build->modperl_libs, $build->apache_libs);
+ }
+ }
+ else {
+ @libs = ($build->modperl_libs, $build->apache_libs);
+ }
+ $libs = join ' ', @libs;
+
+ my $ccflags;
+ $ccflags = $args{CCFLAGS} if $args{CCFLAGS};
+ $ccflags = " " . $build->perl_ccopts . $build->ap_ccopts;
+
+ my $optimize;
+ $optimize = $args{OPTIMIZE} if $args{OPTIMIZE};
+ $optimize = " " . $build->perl_config('optimize');
+
+ my $lddlflags;
+ $lddlflags = $args{LDDLFLAGS} if $args{LDDLFLAGS};
+ $lddlflags = " " . $build->perl_config('lddlflags');
+
+ my %dynamic_lib;
+ %dynamic_lib = %{ $args{dynamic_lib}||{} } if $args{dynamic_lib};
+ $dynamic_lib{OTHERLDFLAGS} = $build->otherldflags;
+
+ my @opts = (
+ INC => $inc,
+ CCFLAGS => $ccflags,
+ OPTIMIZE => $optimize,
+ LDDLFLAGS => $lddlflags,
+ LIBS => $libs,
+ dynamic_lib => \%dynamic_lib,
+ );
+
+ my @typemaps;
+ push @typemaps, $args{TYPEMAPS} if $args{TYPEMAPS};
+ my $pwd = Cwd::fastcwd();
+ for ('xs', $pwd, "$pwd/..") {
+ my $typemap = $build->file_path("$_/typemap");
+ if (-e $typemap) {
+ push @typemaps, $typemap;
+ }
+ }
+ push @opts, TYPEMAPS => \@typemaps if @typemaps;
+
+ my $clean_files = (exists $args{clean} && exists $args{clean}{FILES}) ?
+ $args{clean}{FILES} : '';
+ $clean_files .= " glue_pods"; # cleanup the dependency target
+ $args{clean}{FILES} = $clean_files;
+
+ ExtUtils::MakeMaker::WriteMakefile(@opts, %args);
+}
+
+my %always_dynamic = map { $_, 1 }
+ qw(ModPerl::Const Apache2::Const APR::Const APR APR::PerlIO);
+
+sub ModPerl::BuildMM::MY::constants {
+ my $self = shift;
+ $build ||= build_config();
+
+ #"discover" xs modules. since there is no list hardwired
+ #any module can be unpacked in the mod_perl-2.xx directory
+ #and built static
+
+ #this stunt also make it possible to leave .xs files where
+ #they are, unlike 1.xx where *.xs live in src/modules/perl
+ #and are copied to subdir/ if DYNAMIC=1
+
+ if ($build->{MP_STATIC_EXTS}) {
+ #skip .xs -> .so if we are linking static
+ my $name = $self->{NAME};
+ unless ($always_dynamic{$name}) {
+ if (my ($xs) = keys %{ $self->{XS} }) {
+ $self->{HAS_LINK_CODE} = 0;
+ print "$name will be linked static\n";
+ #propagate static xs module to src/modules/perl/Makefile
+ $build->{XS}->{$name} =
+ join '/', Cwd::fastcwd(), $xs;
+ $build->save;
+ }
+ }
+ }
+
+ $self->MM::constants;
+}
+
+sub ModPerl::BuildMM::MY::top_targets {
+ my $self = shift;
+ my $string = $self->MM::top_targets;
+
+ return $string;
+}
+
+sub ModPerl::BuildMM::MY::postamble {
+ my $self = shift;
+
+ my $doc_root = catdir Cwd::getcwd(), "docs", "api";
+
+ my @targets = ();
+
+ # reasons for glueing pods to the respective .pm files:
+ # - manpages will get installed over the mp1 manpages and vice
+ # versa. glueing pods avoids creation of manpages, but may be we
+ # could just tell make to skip manpages creation?
+ # if pods are installed directly they need to be also redirected,
+ # some into Apache2/ others (e.g. Apache2) not
+
+ # add the code to glue the existing pods to the .pm files in blib.
+ # create a dependency on pm_to_blib subdirs linkext targets to
+ # allow 'make -j'
+ require ExtUtils::MakeMaker;
+ my $mm_ver = $ExtUtils::MakeMaker::VERSION;
+ $mm_ver =~ s/_.*//; # handle dev versions like 6.30_01
+ my $pm_to_blib = ($mm_ver >= 6.22 && $mm_ver <= 6.25)
+ ? "pm_to_blib.ts"
+ : "pm_to_blib";
+ my @target = ("glue_pods: $pm_to_blib subdirs linkext");
+
+ if (-d $doc_root) {
+ my $build = build_config();
+
+ # those living in modperl-2.0/lib are already nicely mapped
+ my %pms = %{ $self->{PM} };
+
+ my $cwd = Cwd::getcwd();
+ my $blib_dir = catdir qw(blib lib);
+
+ # those autogenerated under WrapXS/
+ # those living under xs/
+ # those living under ModPerl-Registry/lib/
+ my @src = ('WrapXS', 'xs', catdir(qw(ModPerl-Registry lib)));
+
+ for my $base (@src) {
+ chdir $base;
+ my @files = ();
+ find({ no_chdir => 1,
+ wanted => sub { push @files, $_ if /.pm$/ },
+ }, ".");
+ chdir $cwd;
+
+ for (@files) {
+ my $pm = catfile $base, $_;
+ my $blib;
+ if ($base =~ /^(xs|WrapXS)/) {
+ my @segm = splitdir $_;
+ splice @segm, -2, 1; # xs/APR/Const/Const.pm
+ splice @segm, -2, 1 if /APR.pm/; # odd case
+ $blib = catfile $blib_dir, @segm;
+ }
+ else {
+ $blib = catfile $blib_dir, $_;
+ }
+ $pms{$pm} = $blib;
+ }
+ }
+
+ foreach my $pm (sort keys %pms) {
+ my $blib = $pms{$pm};
+ $pm =~ s|/\./|/|g; # clean the path
+ $blib =~ s|/\./|/|g; # clean the path
+ my @segm = splitdir $blib;
+ for my $i (1..2) {
+ # try APR.pm and APR/Bucket.pm
+ my $pod = catdir(@segm[-$i .. -1]);
+ $pod =~ s/\.pm/\.pod/;
+ my $podpath = catfile $doc_root, $pod;
+ next unless -r $podpath;
+
+ push @target,
+ '$(FULLPERL) -I$(INST_LIB) ' .
+ "-I$apache_test_dir -MModPerl::BuildMM " .
+ "-e ModPerl::BuildMM::glue_pod $pm $podpath $blib";
+
+ # Win32 doesn't normally install man pages
+ # and Cygwin doesn't allow '::' in file names
+ next if WIN32 || CYGWIN;
+
+ # manify while we're at it
+ my (undef, $man, undef) = $blib =~ m!(blib/lib/)(.*)(\.pm)!;
+ $man =~ s!/!::!g;
+
+ push @target,
+ '$(NOECHO) $(POD2MAN_EXE) --section=3 ' .
+ "$podpath \$(INST_MAN3DIR)/$man.\$(MAN3EXT)"
+ }
+ }
+
+ push @target, $self->{NOECHO} . '$(TOUCH) $@';
+ }
+ else {
+ # we don't have the docs sub-cvs repository extracted, skip
+ # the docs gluing
+ push @target, $self->{NOECHO} . '$(NOOP)';
+ }
+ push @targets, join "\n\t", @target;
+
+# # next target: cleanup the dependency file
+# @target = ('glue_pods_clean:');
+# push @target, '$(RM_F) glue_pods';
+# push @targets, join "\n\t", @target;
+
+ return join "\n\n", @targets, '';
+}
+
+sub glue_pod {
+
+ die "expecting 3 arguments: pm, pod, dst" unless @ARGV == 3;
+ my ($pm, $pod, $dst) = @ARGV;
+
+ # it's possible that the .pm file is not existing
+ # (e.g. ThreadMutex.pm is not created on unless
+ # $apr_config->{HAS_THREADS})
+ return unless -e $pm && -e $dst;
+
+ # have we already glued the doc?
+ exit 0 unless -s $pm == -s $dst;
+
+ # ExtUtils::Install::pm_to_blib removes the 'w' perms, so we can't
+ # just append the doc there
+ my $orig_mode = (stat $dst)[2];
+ my $rw_mode = 0666;
+
+ chmod $rw_mode, $dst or die "Can't chmod $rw_mode $dst: $!";
+ open my $pod_fh, "<$pod" or die "Can't open $pod: $!";
+ open my $dst_fh, ">>$dst" or die "Can't open $dst: $!";
+ print $dst_fh "\n"; # must add one line separation
+ print $dst_fh (<$pod_fh>);
+ close $pod_fh;
+ close $dst_fh;
+ # restore the perms
+ chmod $orig_mode, $dst or die "Can't chmod $orig_mode $dst: $!";
+}
+
+sub ModPerl::BuildMM::MY::post_initialize {
+ my $self = shift;
+ $build ||= build_config();
+ my $pm = $self->{PM};
+
+ while (my ($k, $v) = each %PM) {
+ if (-e $k) {
+ $pm->{$k} = $v;
+ }
+ }
+
+ # prefix typemap with Apache2/ so when installed in the
+ # perl-lib-tree it won't be picked by non-mod_perl modules
+ if (exists $pm->{'lib/typemap'} ) {
+ $pm->{'lib/typemap'} = '$(INST_ARCHLIB)/auto/Apache2/typemap';
+ }
+
+ '';
+}
+
+my $apr_config;
+
+sub ModPerl::BuildMM::MY::libscan {
+ my ($self, $path) = @_;
+
+ $apr_config ||= $build->get_apr_config();
+
+ if ($path =~ m/(Thread|Global)(Mutex|RWLock)/) {
+ return unless $apr_config->{HAS_THREADS};
+ }
+
+ return '' if $path =~ /DummyVersions.pm/;
+
+ return '' if $path =~ m/\.pl$/;
+ return '' if $path =~ m/~$/;
+ return '' if $path =~ /\B\.svn\b/;
+
+ $path;
+}
+
+1;
diff --git a/2_0_13/lib/ModPerl/BuildOptions.pm b/2_0_13/lib/ModPerl/BuildOptions.pm
new file mode 100644
index 0000000..b54bd8e
--- /dev/null
+++ b/2_0_13/lib/ModPerl/BuildOptions.pm
@@ -0,0 +1,271 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+package ModPerl::BuildOptions;
+
+use strict;
+use warnings;
+
+use Apache2::Build ();
+use Apache::TestTrace;
+use Config ();
+my $param_qr = qr([\s=]+);
+
+use constant VERBOSE => 1;
+use constant UNKNOWN_FATAL => 2;
+
+use File::Spec;
+
+sub init {
+ my ($class, $build) = @_;
+
+ #@ARGV should override what's in .makepl_args.mod_perl2
+ #but @ARGV might also override the default MP_OPTS_FILE
+ #so snag that first
+ parse($build, [grep { /^MP_OPTIONS_FILE/ } @ARGV]);
+ parse_file($build);
+ parse_argv($build);
+
+ # if AP_PREFIX is used apxs and apr-config from the apache build
+ # tree won't work, so it can't co-exist with APXS and APR_CONFIG
+ # options
+ if ($build->{MP_AP_PREFIX} and $build->{MP_APXS}) {
+ error "You need to pass either MP_AP_PREFIX or MP_APXS, but not both";
+ die "\n";
+ }
+ if ($build->{MP_AP_PREFIX} and $build->{MP_APR_CONFIG}) {
+ error "You need to pass either MP_AP_PREFIX or MP_APR_CONFIG, " .
+ "but not both";
+ die "\n";
+ }
+
+ if ($build->{MP_DEBUG} and $build->{MP_USE_GTOP} and !$build->find_gtop) {
+ error "Can't find libgtop, resetting MP_USE_GTOP=0";
+ $build->{MP_USE_GTOP} = 0;
+ }
+
+ unless ($build->{MP_USE_DSO} or $build->{MP_USE_STATIC}) {
+ # default to DSO
+ $build->{MP_USE_DSO} = 1;
+ }
+
+ $build->{MP_GENERATE_XS} = 1 unless exists $build->{MP_GENERATE_XS};
+
+ # define MP_COMPAT_1X unless explicitly told to disable it
+ $build->{MP_COMPAT_1X} = 1
+ unless exists $build->{MP_COMPAT_1X} && !$build->{MP_COMPAT_1X};
+
+ # try to find apxs
+ if (!$build->{MP_AP_PREFIX} && !$build->{MP_APXS}) {
+ $build->find_apxs_util();
+
+ # make a last ditch effort to find apxs in $ENV{PATH}
+ if (!$build->{MP_APXS}) {
+ my @paths = split(/$Config::Config{path_sep}/, $ENV{PATH});
+ my $potential_apxs;
+ while (!$potential_apxs) {
+ last if scalar(@paths) == 0; # don't loop endlessly
+ $potential_apxs = File::Spec->catfile(shift @paths, 'apxs');
+ $potential_apxs .= '.bat' if Apache2::Build::WIN32();
+ if (-e $potential_apxs && -x $potential_apxs) {
+ $build->{MP_APXS} = $potential_apxs;
+ } else {
+ undef $potential_apxs;
+ }
+ }
+ }
+ }
+}
+
+sub parse {
+ my ($build, $lines, $opts) = @_;
+
+ $opts = VERBOSE|UNKNOWN_FATAL unless defined $opts;
+ my $table = table();
+ my @unknown;
+ my $continue = "";
+
+ my @data = ();
+ for (@$lines) {
+ chomp;
+ s/^\s+//; s/\s+$//;
+ next if /^\#/ || /^$/;
+ last if /^__END__/;
+
+ # more than one entry on the same line (but make sure to leave
+ # -DMP_* alone)
+ push @data, split /(?=\WMP_)/, $_;
+ }
+
+ for (@data) {
+ #XXX: this "parser" should be more robust
+
+ s/^\s+//; s/\s+$//;
+
+ $_ = "$continue $_" if $continue;
+
+ #example: +"MP_CCOPTS=-Werror" if $] >= 5.007
+ if (s/^\+//) {
+ $_ = eval $_;
+ }
+
+ if (/^MP_/) {
+ my ($key, $val) = split $param_qr, $_, 2;
+ $val ||= "" unless defined $val && $val eq '0';
+ $continue = $val =~ s/\\$// ? $key : "";
+
+ if (!$table->{$key} and $opts & UNKNOWN_FATAL) {
+ my $usage = usage();
+ die "Unknown Option: $key\nUsage:\n$usage\n";
+ }
+
+ if ($key eq 'MP_APXS') {
+ $val = File::Spec->canonpath(File::Spec->rel2abs($val));
+ }
+
+ if ($key eq 'MP_AP_PREFIX') {
+ $val = File::Spec->canonpath(File::Spec->rel2abs($val));
+
+ if (Apache2::Build::WIN32()) {
+ # MP_AP_PREFIX may not contain spaces
+ require Win32;
+ $val = Win32::GetShortPathName($val);
+ }
+
+ if (!$val || !-d $val) {
+ error "MP_AP_PREFIX must point to a valid directory.";
+ die "\n";
+ }
+ }
+
+ if ($table->{$key}->{append}){
+ $build->{$key} = join " ", grep $_, $build->{$key}, $val;
+ }
+ else {
+ $build->{$key} = $val;
+ }
+
+ print " $key = $val\n" if $opts & VERBOSE;
+ }
+ else {
+ push @unknown, $_;
+ }
+ }
+
+ return \@unknown;
+}
+
+sub parse_file {
+ my $build = shift;
+
+ my $fh;
+ my @dirs = qw(./ ../ ./. ../.);
+ push @dirs, "$ENV{HOME}/." if exists $ENV{HOME};
+ my @files = map { $_ . 'makepl_args.mod_perl2' } @dirs;
+ unshift @files, $build->{MP_OPTIONS_FILE} if $build->{MP_OPTIONS_FILE};
+
+ for my $file (@files) {
+ if (open $fh, $file) {
+ $build->{MP_OPTIONS_FILE} = $file;
+ last;
+ }
+ $fh = undef;
+ }
+
+ return unless $fh;
+
+ print "Reading Makefile.PL args from $build->{MP_OPTIONS_FILE}\n";
+ my $unknowns = parse($build, [<$fh>]);
+ push @ARGV, @$unknowns if $unknowns;
+
+ close $fh;
+}
+
+sub parse_argv {
+ my $build = shift;
+ return unless @ARGV;
+
+ my @args = @ARGV;
+ @ARGV = ();
+
+ print "Reading Makefile.PL args from \@ARGV\n";
+ my $unknowns = parse($build, \@args);
+ push @ARGV, @$unknowns if $unknowns;
+}
+
+sub usage {
+ my $table = table();
+ my @opts = map { "$_ - $table->{$_}->{val}" } sort keys %$table;
+ join "\n", @opts;
+}
+
+sub parse_table {
+ my ($fh) = @_;
+ my %table;
+ local $_;
+
+ while (<$fh>) {
+ chomp;
+ s/^\s+//; s/\s+$//;
+ next if /^\#/ || /^$/;
+ last if /^__END__/;
+ my ($key, $append, $val) = split /\s+/, $_, 3;
+ $table{'MP_' . $key} = { append => $append, val => $val };
+ }
+
+ return \%table;
+}
+
+my $Table;
+
+sub table {
+ $Table ||= parse_table(\*DATA);
+}
+
+1;
+
+# __DATA__ format:
+# key append description
+# where:
+# key: is the option name
+# append: is whether we want to replace a default option (0)
+# or append the arg to the option (1)
+# desc: description for this option
+
+__DATA__
+USE_GTOP 0 Link with libgtop and enable libgtop reporting
+DEBUG 0 Turning on debugging (-g -lperld) and tracing
+MAINTAINER 0 Maintainer mode: DEBUG=1 -DAP_DEBUG -Wall ...
+CCOPTS 1 Add to compiler flags
+TRACE 0 Turn on tracing
+USE_DSO 0 Build mod_perl as a dso
+USE_STATIC 0 Build mod_perl static
+PROMPT_DEFAULT 0 Accept default value for all would-be prompts
+OPTIONS_FILE 0 Read options from given file
+STATIC_EXTS 0 Build Apache2::*.xs as static extensions
+APXS 0 Path to apxs
+AP_DESTDIR 0 Destination for Apache specific mod_perl bits
+AP_PREFIX 0 Apache installation or source tree prefix
+AP_CONFIGURE 0 Apache ./configure arguments
+APR_CONFIG 0 Path to apr-config
+APU_CONFIG 0 Path to apu-config
+XS_GLUE_DIR 1 Directories containing extension glue
+INCLUDE_DIR 1 Add directories to search for header files
+GENERATE_XS 0 Generate XS code based on httpd version
+LIBNAME 0 Name of the modperl dso library (default is mod_perl)
+COMPAT_1X 0 Compile-time mod_perl 1.0 backcompat (default is on)
+APR_LIB 0 Lib used to build APR::* on Win32 (default is aprext)
+NO_THREADS 0 Build mod_perl without thread support with httpd >= 2.4
diff --git a/2_0_13/lib/ModPerl/CScan.pm b/2_0_13/lib/ModPerl/CScan.pm
new file mode 100644
index 0000000..4985ef0
--- /dev/null
+++ b/2_0_13/lib/ModPerl/CScan.pm
@@ -0,0 +1,1010 @@
+# please insert nothing before this line: -*- mode: cperl; cperl-indent-level: 4; cperl-continued-statement-offset: 4; indent-tabs-mode: nil -*-
+package ModPerl::CScan;
+
+require Exporter;
+use Config '%Config';
+use File::Basename;
+
+# NOTE to distributors: this module is needed only for mp2 developers,
+# it's not a requirement for mod_perl users
+use Data::Flow qw(0.05);
+
+use strict; # Earlier it catches ISA and EXPORT.
+
+@ModPerl::CScan::ISA = qw(Exporter Data::Flow);
+
+# Items to export into callers namespace by default. Note: do not export
+# names by default without a very good reason. Use EXPORT_OK instead.
+# Do not simply export all your public functions/methods/constants.
+
+@ModPerl::CScan::EXPORT = qw(
+ );
+@ModPerl::CScan::EXPORT_OK = qw(
+ );
+# this flag tells cpp to only output macros
+$ModPerl::CScan::MACROS_ONLY = '-dM';
+
+$ModPerl::CScan::VERSION = '0.75';
+
+my (%keywords,%style_keywords);
+for (qw(asm auto break case char continue default do double else enum
+ extern float for fortran goto if int long register return short
+ sizeof static struct switch typedef union unsigned signed while void volatile)) {
+ $keywords{$_}++;
+}
+for (qw(bool class const delete friend inline new operator overload private
+ protected public virtual)) {
+ $style_keywords{'C++'}{$_}++;
+}
+for (qw(__func__ _Complex _Imaginary _Bool inline restrict)) {
+ $style_keywords{'C9X'}{$_}++;
+}
+for (qw(inline const asm noreturn section
+ constructor destructor unused weak)) {
+ $style_keywords{'GNU'}{$_}++;
+ $style_keywords{'GNU'}{"__$ {_}__"}++;
+}
+ $style_keywords{'GNU'}{__attribute__}++;
+ $style_keywords{'GNU'}{__extension__}++;
+ $style_keywords{'GNU'}{__consts}++;
+ $style_keywords{'GNU'}{__const}++;
+ $style_keywords{'GNU'}{__restrict}++;
+
+my $recipes
+ = { Defines => { default => '' },
+ cppstdin => { default => $Config{cppstdin} },
+ cppflags => { default => $Config{cppflags} },
+ cppminus => { default => $Config{cppminus} },
+ c_styles => { default => [qw(C++ GNU C9X)] },
+ add_cppflags => { default => '' },
+ keywords => { prerequisites => ['c_styles'],
+ output => sub {
+ my %kw = %keywords;
+ my %add;
+ for ( @{ shift->{c_styles} } ) {
+ %add = %{ $style_keywords{$_} };
+ %kw = (%kw, %add);
+ }
+ \%kw;
+ }, },
+ 'undef' => { default => undef },
+ filename_filter => { default => undef },
+ full_text => { class_filter => [ 'text', 'C::Preprocessed',
+ qw(undef filename Defines includeDirs Cpp)] },
+ text => { class_filter => [ 'text', 'C::Preprocessed',
+ qw(filename_filter filename Defines includeDirs Cpp)] },
+ text_only_from => { class_filter => [ 'text_only_from', 'C::Preprocessed',
+ qw(filename_filter filename Defines includeDirs Cpp)] },
+ includes => { filter => [ \&includes,
+ qw(filename Defines includeDirs Cpp) ], },
+ includeDirs => { prerequisites => ['filedir'],
+ output => sub {
+ my $data = shift;
+ [ $data->{filedir}, '/usr/local/include', '.'];
+ } },
+ Cpp => { prerequisites => [qw(cppminus add_cppflags cppflags cppstdin)],
+ output => sub {
+ my $data = shift;
+ return { cppstdin => $data->{cppstdin},
+ cppflags => "$data->{cppflags} $data->{add_cppflags}",
+ cppminus => $data->{cppminus} };
+ } },
+ filedir => { output => sub { dirname ( shift->{filename} || '.' ) } },
+ sanitized => { filter => [ \&sanitize, 'text'], },
+ toplevel => { filter => [ \&top_level, 'sanitized'], },
+ full_sanitized => { filter => [ \&sanitize, 'full_text'], },
+ full_toplevel => { filter => [ \&top_level, 'full_sanitized'], },
+ no_type_decl => { filter => [ \&remove_type_decl, 'toplevel'], },
+ typedef_chunks => { filter => [ \&typedef_chunks, 'full_toplevel'], },
+ struct_chunks => { filter => [ \&struct_chunks, 'full_toplevel'], },
+ typedefs_whited => { filter => [ \&typedefs_whited,
+ 'full_sanitized', 'typedef_chunks',
+ 'keywords_rex'], },
+ typedef_texts => { filter => [ \&typedef_texts,
+ 'full_text', 'typedef_chunks'], },
+ struct_texts => { filter => [ \&typedef_texts,
+ 'full_text', 'struct_chunks'], },
+ typedef_hash => { filter => [ \&typedef_hash,
+ 'typedef_texts', 'typedefs_whited'], },
+ typedef_structs => { filter => [ \&typedef_structs,
+ 'typedef_hash', 'struct_texts'], },
+ typedefs_maybe => { filter => [ sub {[keys %{+shift}]},
+ 'typedef_hash'], },
+ defines_maybe => { filter => [ \&defines_maybe, 'filename'], },
+ defines_no_args => { prerequisites => ['defines_maybe'],
+ output => sub { shift->{defines_maybe}->[0] }, },
+ defines_args => { prerequisites => ['defines_maybe'],
+ output => sub { shift->{defines_maybe}->[1] }, },
+
+ defines_full => { filter => [ \&defines_full,
+ qw(filename Defines includeDirs Cpp) ], },
+ defines_no_args_full => { prerequisites => ['defines_full'],
+ output => sub { shift->{defines_full}->[0] }, },
+ defines_args_full => { prerequisites => ['defines_full'],
+ output => sub { shift->{defines_full}->[1] }, },
+
+ decl_inlines => { filter => [ \&functions_in, 'no_type_decl'], },
+ inline_chunks => { filter => [ sub { shift->[0] }, 'decl_inlines'], },
+ inlines => { filter => [ \&from_chunks, 'inline_chunks', 'text'], },
+ decl_chunks => { filter => [ sub { shift->[1] }, 'decl_inlines'], },
+ decls => { filter => [ \&from_chunks, 'decl_chunks', 'text'], },
+ fdecl_chunks => { filter => [ sub { shift->[4] }, 'decl_inlines'], },
+ fdecls => { filter => [ \&from_chunks, 'fdecl_chunks', 'text'], },
+ mdecl_chunks => { filter => [ sub { shift->[2] }, 'decl_inlines'], },
+ mdecls => { filter => [ \&from_chunks, 'mdecl_chunks', 'text'], },
+ vdecl_chunks => { filter => [ sub { shift->[3] }, 'decl_inlines'], },
+ vdecls => { filter => [ \&from_chunks, 'vdecl_chunks', 'text'], },
+ vdecl_hash => { filter => [ \&vdecl_hash, 'vdecls', 'mdecls' ], },
+ parsed_fdecls => { filter => [ \&do_declarations, 'fdecls',
+ 'typedef_hash', 'keywords'], },
+ parsed_inlines => { filter => [ \&do_declarations, 'inlines',
+ 'typedef_hash', 'keywords'], },
+ keywords_rex => { filter => [ sub { my @k = keys %{ shift() };
+ local $" = '|';
+ my $r = "(?:@k)";
+ eval 'qr/$r/' or $r # Older Perls
+ }, 'keywords'], },
+ };
+
+sub from_chunks {
+ my $chunks = shift;
+ my $txt = shift;
+ my @out;
+ my $i = 0;
+ while ($i < @$chunks) {
+ push @out, substr $txt, $chunks->[$i], $chunks->[ $i + 1 ] - $chunks->[$i];
+ $i += 2;
+ }
+ \@out;
+}
+
+#sub process { request($recipes, @_) }
+# Preloaded methods go here.
+
+sub includes {
+ my %seen;
+ my $stream = new C::Preprocessed (@_)
+ or die "Cannot open pipe from cppstdin: $!\n";
+
+ while (<$stream>) {
+ next unless m(^\s*\#\s* # Leading hash
+ (line\s*)? # 1: Optional line
+ ([0-9]+)\s* # 2: Line number
+ (.*) # 3: The rest
+ )x;
+ my $include = $3;
+ $include = $1 if $include =~ /"(.*)"/; # Filename may be in quotes
+ $include =~ s,\\\\,/,g if $^O eq 'os2';
+ $seen{$include}++ if $include ne "";
+ }
+ [keys %seen];
+}
+
+sub defines_maybe {
+ my $file = shift;
+ my ($mline,$line,%macros,%macrosargs,$sym,$args);
+ open(C, $file) or die "Cannot open file $file: $!\n";
+ while (not eof(C) and $line = <C>) {
+ next unless
+ ( $line =~ s[
+ ^ \s* \# \s* # Start of directive
+ define \s+
+ (\w+) # 1: symbol
+ (?:
+ \( (.*?) \s* \) # 2: Minimal match for arguments
+ # in parenths (without trailing
+ # spaces)
+ )? # optional, no grouping
+ \s* # rest is the definition
+ ([\s\S]*) # 3: the rest
+ ][]x );
+ ($sym, $args, $mline) = ($1, $2, $3);
+ $mline .= <C> while not eof(C) and $mline =~ s/\\\n/\n/;
+ chomp $mline;
+ #print "sym: `$sym', args: `$args', mline: `$mline'\n";
+ if (defined $args) {
+ $macrosargs{$sym} = [ [split /\s*,\s*/, $args], $mline];
+ } else {
+ $macros{$sym} = $mline;
+ }
+ }
+ close(C) or die "Cannot close file $file: $!\n";
+ [\%macros, \%macrosargs];
+}
+
+sub defines_full {
+ my $Cpp = $_[3];
+ my ($mline,$line,%macros,%macrosargs,$sym,$args);
+
+ # save the old cppflags and add the flag for only ouputting macro definitions
+ my $old_cppstdin = $Cpp->{'cppstdin'};
+ $Cpp->{'cppstdin'} = $old_cppstdin . " " . $ModPerl::CScan::MACROS_ONLY;
+
+ my $stream = new C::Preprocessed (@_)
+ or die "Cannot open pipe from cppstdin: $!\n";
+
+ while (defined ($line = <$stream>)) {
+ next unless
+ ( $line =~ s[
+ ^ \s* \# \s* # Start of directive
+ define \s+
+ (\w+) # 1: symbol
+ (?:
+ \( (.*?) \s* \) # 2: Minimal match for arguments
+ # in parenths (without trailing
+ # spaces)
+ )? # optional, no grouping
+ \s* # rest is the definition
+ ([\s\S]*) # 3: the rest
+ ][]x );
+ ($sym, $args, $mline) = ($1, $2, $3);
+ $mline .= <$stream> while ($mline =~ s/\\\n/\n/);
+ chomp $mline;
+#print STDERR "sym: `$sym', args: `$args', mline: `$mline'\n";
+ if (defined $args) {
+ $macrosargs{$sym} = [ [split /\s*,\s*/, $args], $mline];
+ } else {
+ $macros{$sym} = $mline;
+ }
+ }
+ # restore the original cppflags
+ $Cpp->{'cppstdin'} = $old_cppstdin;
+ [\%macros, \%macrosargs];
+}
+
+sub typedef_chunks { # Input is toplevel, output: starts and ends
+ my $txt = shift;
+ pos $txt = 0;
+ my ($b, $e, @out);
+ while ($txt =~ /\btypedef\b/g) {
+ push @out, pos $txt;
+ $txt =~ /(?=;)|\Z/g;
+ push @out, pos $txt;
+ }
+ \@out;
+}
+
+sub struct_chunks {
+ my $txt = shift;
+ pos $txt = 0;
+ my ($b, $e, @out);
+ while ($txt =~ /\b(?=struct\s*(\w*\s*)?\{)/g) {
+ push @out, pos $txt;
+ $txt =~ /(?=;)|\Z/g;
+ push @out, pos $txt;
+ }
+ \@out;
+}
+
+sub typedefs_whited { # Input is sanitized text, and list of beg/end.
+ my @lst = @{$_[1]};
+ my @out;
+ my ($b, $e);
+ while ($b = shift @lst) {
+ $e =