Apache-ASP
view release on metacpan or search on metacpan
if($compressgzip_config) {
if($self->LoadModule('Gzip','Compress::Zlib')) {
$self->{compressgzip} = 1;
}
}
# must have global directory into which we put the global.asa
# and possibly state files, optimize out the case of . or ..
if($self->{global} !~ /^(\.|\.\.)$/) {
-d $self->{global} or
$self->Error("global path, $self->{global}, is not a directory");
}
# includes_dir calculation
if($filename =~ m,^((/|[a-zA-Z]:).*[/\\])[^/\\]+?$,) {
$self->{dirname} = $1;
} else {
$self->{dirname} = '.';
}
$self->{includes_dir} = [
$self->{dirname},
$self->{global},
split(/;/, &config($self, 'IncludesDir') || ''),
];
# register cleanup before the state files get set in InitObjects
# this way DESTROY gets called every time this script is done
# we must cache $self for lookups later
&RegisterCleanup($self, sub { $self->DESTROY });
#### WAS INIT OBJECTS, REMOVED DECOMP FOR SPEED
# GLOBALASA, RESPONSE, REQUEST, SERVER
# always create these
# global_asa assigns itself to parent object automatically
my $global_asa = &Apache::ASP::GlobalASA::new($self);
$self->{Request} = &Apache::ASP::Request::new($self);
$self->{Response} = &Apache::ASP::Response::new($self);
# Server::new() is just one line, so execute directly
$self->{Server} = bless {asp => $self}, 'Apache::ASP::Server';
#&Apache::ASP::Server::new($self);
# After GlobalASA Init, init the package that this script will execute in
# must be here, and not end of new before things like Application_OnStart get run
# UniquePackages & NoCache configs do not work together, NoCache wins here
if(&config($self, 'UniquePackages')) {
# id is not generally useful for the ASP object now, so calculate
# it here now, only to twist the package object for this script
# pass in basename for where to find the file for InodeNames, and the full path
# for the FileId otherwise
my $package = $global_asa->{'package'}.'::'.&FileId($self, $self->{basename}, $self->{filename});
$self->{'package'} = $package;
$self->{init_packages} = ['main', $global_asa->{'package'}, $self->{'package'}];
} else {
$self->{'package'} = $global_asa->{'package'};
$self->{init_packages} = ['main', $global_asa->{'package'}];
}
$self->{state_dir} = &config($self, 'StateDir', undef, $self->{global}.'/.state');
$self->{state_dir} =~ tr///; # untaint
# if no state has been config'd, then set up none of the
# state objects: Application, Internal, Session
unless(&get_dir_config($dir_config, 'NoState')) {
# load at runtime for CGI environments, preloaded for mod_perl
require Apache::ASP::StateManager;
&InitState($self);
}
$self;
}
# called upon every end of connection by RegisterCleanup
sub DESTROY {
my $self = shift;
return unless $self->{destroy}; # still active object
$self->{dbg} && $self->Debug("destroying ASP object $self");
# do before undef'ing the object references in main
for my $code ( @{$self->{cleanup}} ) {
$self->{dbg} && $self->Debug("executing cleanup $code");
eval { &$code() };
$@ && $self->Error("executing cleanup $code error: $@");
}
local $^W = 0; # suppress untie while x inner references warnings
select(STDOUT);
untie *RESPONSE if tied *RESPONSE;
# can't move this to Request::DESTROY(), then CGI object compatibility
# in test ./site/eg/cgi.htm test fails, don't know why, --jc, 12/06/2002
untie *STDIN if tied *STDIN;
# in case there is a dummy session here by the
# end of object execution
if($self->{Session}) {
if(eval { $self->{Session}->isa('Apache::ASP::Session') }) {
# only the cleanup master may cleanup groups now, so OK
# to call just CleanupGroups
$self->CleanupGroups();
} else {
$self->Debug("$self->{Session} is not an Apache::ASP::Session");
eval { $self->{Session}->DESTROY };
$self->{Session} = undef;
}
}
# free file handles here. mod_perl tends to be pretty clingy
# to memory
for('Application', 'Internal', 'Session') {
# all this stuff in here is very necessary for total cleanup
# the DESTROY is the most important, as we need to explicitly free
# state objects, just in case anyone else is keeping references to them
# But the destroy won't work without first untieing, go figure
next unless defined $self->{$_};
my $tied = tied %{$self->{$_}};
next unless $tied;
untie %{$self->{$_}};
$tied->DESTROY(); # call explicit DESTROY
}
if(my $caches = $self->{Caches}) {
# default cache size to 10M
$self->{cache_size} = &config($self, 'CacheSize') || $CacheSize;
if($self->{cache_size} =~ /^([\d\.]+)(M|K|B)?$/) {
my($size, $unit) = ($1, $2);
if($unit eq 'M') {
$size *= 1024*1024;
} elsif($unit eq 'K') {
$size *= 1024;
}
if($size ne $self->{cache_size}) {
$self->{dbg} && $self->Debug("converting CacheSize $self->{cache_size} to $size bytes");
$self->{cache_size} = $size;
}
}
for my $cache (values %$caches) {
my $tied = $cache;
if($tied->{writes} && $tied->Size > $self->{cache_size}) {
$self->{dbg} && $self->Debug("deleting cache $cache, size: ".$tied->Size);
$tied->Delete;
} else {
$self->{dbg} && $self->Debug("cache $cache OK size, size: ".$tied->Size);
}
$tied->DESTROY();
}
}
# $self->{'dbg'} && $self->Debug("END ASP DESTROY");
$self->{Request} && &Apache::ASP::Request::DESTROY($self->{Request});
$self->{Server} && ( %{$self->{Server}} = () );
$self->{Response} && ( %{$self->{Response}} = () );
%$self = ();
1;
}
sub RegisterCleanup {
my $self = shift;
if($ModPerl2) {
$self->{r}->pool->cleanup_register(@_);
} else {
$self->{r}->register_cleanup(@_);
}
}
sub InitPaths {
# we load this module just to detect where the shared directory really is
use Apache::ASP::Share::CORE;
# major problem with %INC if we cannot get this information
my $share_path = $INC{'Apache/ASP/Share/CORE.pm'}
|| die(q(can't find path for $INC{'Apache/ASP/Share/CORE.pm'}));
$share_path =~ s/CORE\.pm$//s;
unless($share_path =~ /$AbsoluteFileMatch/) {
# this %ENV manipulation is just to allow cwd() to run in taint check mode
local %ENV = %ENV;
$ENV{PATH} = '/bin:/usr/bin:/usr/sbin';
delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'};
my $currdir = cwd();
$share_path = "$currdir/$share_path";
}
# not finding the ShareDir creates a hard error, because the Apache/ASP/Share
# directory will become one of the fundamental underpinings of the project
# People will need to rely on being able to load shared includes, and not have
# to discover the lack of loading Share:: at runtime, rather this is a compile
# time error.
-d $share_path || die("Apache::ASP::Share directory not found. ".
"Please make sure to install all the modules that make up the Apache::ASP installation."
);
$ShareDir = $share_path;
# once we find the $ShareDir, we can truncate the library path
# and push it onto @INC with use lib... this is to help with loading
# future Apache::ASP::* modules when the lib path it was found at is
# relative to some directory. This was needed to have the "make test"
# test suite to work which loads libraries from "blib/lib", but Apache::ASP
# will chdir() into the script directory so that can ruin this
# library lookup.
#
my $lib_path = $share_path;
$lib_path =~ s/Apache.ASP.Share.?$//s;
-d $lib_path || die("\%INC library path $lib_path not found.");
$INCDir = $lib_path;
# clear taint, for some reason, tr/// or s/^(.*)$/ did not work on perl 5.6.1
$INCDir =~ /^(.*)$/s;
$INCDir = $1;
# make sure this gets on @INC at startup, can't hurt
eval "use lib qw($INCDir);";
1;
}
sub FileId {
my($self, $file, $abs_file, $no_compile_checksum) = @_;
$file || die("no file passed to FileId()");
my $id;
# calculate compile checksum for file id
unless($self->{compile_checksum}) {
my $r = $self->{r};
my $checksum = md5_hex(join('&-+',
$VERSION,
map { &config($self, $_) || '' }
@CompileChecksumKeys
)
);
# $self->{dbg} && $self->Debug("compile checksum $checksum");
$self->{compile_checksum} = $checksum;
}
my $compile_checksum = $no_compile_checksum ? '' : $self->{compile_checksum};
my @inode_stat = ();
if($self->{inode_names}) {
@inode_stat = stat($file);
# one or the other device or file ids must be not 0
unless($inode_stat[0] || $inode_stat[1]) {
@inode_stat = ();
}
}
if(@inode_stat) {
$id = sprintf("____DEV%X_INODE%X",@inode_stat[0,1]);
$id .= 'x'.$compile_checksum;
} else {
if($abs_file) {
$file = $abs_file;
}
$file =~ s|/+|/|sg;
$file =~ s/[\Wx]/_/sg;
my $file_name_length = length($file);
if($file_name_length >= 35) {
$id = substr($file, $file_name_length - 35, 36);
# only do the hex of the original file to create a unique identifier for the long id
$id .= 'x'.&md5_hex($file.$compile_checksum);
} else {
$id = $file.'x'.$compile_checksum;
}
}
$id = '__ASP_'.$id;
}
sub UndefRoutine {
my($self, $subid) = @_;
my $code = \&{$subid};
if($code) {
$self->{dbg} && $self->Debug("undefing sub $subid code $code");
undef(&$code); # method for perl 5.6.1
undef($code); # older perls ??
}
}
sub ReadFile {
my($self, $file) = @_;
local *READFILE;
open(READFILE, $file) || $self->Error("can't open file $file for reading");
local $/ = undef;
my $data = <READFILE>;
close READFILE;
\$data;
}
# if the $file is an absolute path, then just return the file
# if the $file is a relative path, concat it with the passed in directory
sub AbsPath {
my($file, $dir) = @_;
# we test for first unix style and then win32 style path conventions
if($file =~ m|^/| or $file =~ m|^.\:|) {
$file;
} else {
# we only can absolute the path if the directory path is absolute
if($dir =~ m|^/| or $dir =~ m|^.\:|) {
$file = $dir.'/'.$file;
} else {
$file;
}
}
}
sub CompilePerl {
my($self, $script, $subid, $package) = @_;
$package ||= $self->{GlobalASA}{'package'};
$subid ||= '';
ref($script) || die("no ref to perl script to compile");
$subid && $self->UndefRoutine($subid);
$self->{dbg} && $self->Debug("compiling into package $package subid [$subid]");
$self->{compile_perl_count}++; # counter used in test case closure.t
my $eval =
join(" ;; ",
"package $package;", # for no sub closure
"sub $subid { ",
"package $package;", # for sub closure
$$script,
'}',
);
# $eval =~ tr///; # untaint
$eval =~ /^(.*)$/s;
$eval = $1;
my $sub_ref;
if($self->{use_strict}) {
local $SIG{__WARN__} = sub { die("maybe use strict error: ", @_) };
# comment out for now, until 3.0 release for this may create lots
# of compile time errors for people that will need to fix scripts
# local $^W = 1; # trigger my closure errors, --jc 9/7/2002
$sub_ref = eval $eval;
} else {
local $SIG{__WARN__} = sub { $self->Out(@_) };
$sub_ref = eval $eval;
}
my $rv; # for readability
my $error = $@;
if($@) {
$self->CompileError($eval); # don't throw error, so we can throw die later
$subid && $self->UndefRoutine($subid);
$rv = undef;
} else {
if($subid) {
if(&config($self, 'RegisterIncludes')) {
$self->RegisterIncludes($script);
}
$rv = $subid;
} else {
$rv = $sub_ref;
}
}
$@ = $error;
$rv;
}
sub TestForSubs {
my($self, $script) = @_;
$$script =~ /(^|\n)\s*sub\s+([^\s\{]+)\s*\{/ ? 1 : 0;
}
sub InitPackageGlobals {
my $self = shift;
unless($self->{response_tied}) {
# set printing to Response object
$self->{response_tied} = 1;
tie *RESPONSE, 'Apache::ASP::Response', $self->{Response};
select(RESPONSE);
}
# ---- init package objects ----
# unoptimized this because we should only call this function once
# and maybe twice if there is a defined Script_OnStart
for my $object (@Apache::ASP::Objects) {
for my $import_package (@{$self->{init_packages}}) {
my $init_var = $import_package.'::'.$object;
push(@to, @receivers);
}
$self->Debug("sending mail to: ".join(',', @to));
($mail->{From}) = split(/\s*,\s*/,($mail->{From} || '')); # just the first one
$smtp->mail($mail->{From}) || return(0);
# put test before $smtp->to() because we might get a relaying denied error otherwise
if($mail->{Test}) {
return $rv;
}
$smtp->to(@to) || return(0);
my($data);
my $body = $mail->{Body};
delete $mail->{Body};
# assumes MIME-Version 1.0 for Content-Type header, according to RFC 1521
# http://www.ietf.org/rfc/rfc1521.txt
if($mail->{'Content-Type'} && ! $mail->{'MIME-Version'}) {
$mail->{'MIME-Version'} = '1.0';
}
my %done;
for('Subject', 'From', 'Reply-To', 'Organization', 'To', keys %$mail) {
next unless $mail->{$_};
next if $done{lc($_)}++;
my $add = ref($mail->{$_}) ? join(",", @{$mail->{$_}}) : $mail->{$_};
$add =~ s/^[\n]*(.*?)[\n]*$/$1/;
$data .= "$_: $add\n";
}
$data .= "\n" . $body;
$smtp->data($data) || ($rv = 0);
$smtp->quit();
$rv && $self->Debug("mail sent successfully");
$rv;
}
*LoadModule = *LoadModules;
sub LoadModules {
my($self, $category, @modules) = @_;
my $load_errors = 0;
for(@modules) {
if(defined $LoadedModules{$_}) {
if($LoadedModules{$_} == 0) {
if($LoadModuleErrors{$category}) {
$self->Error("cannot load $_ for $category: $LoadModuleErrors{$category}; $@");
} else {
$self->Debug("already failed to load $_");
}
$load_errors++;
}
next;
}
$_ =~ tr///; # untaint
eval "use $_";
if($@) {
if($LoadModuleErrors{$category}) {
$self->Error("cannot load $_ for $category: $LoadModuleErrors{$category}; $@");
} else {
# don't wan't Log() output for make test when optional modules aren't installed
# is not installed, --jc 6/11/2001
$self->Debug("cannot load $_ for $category: $@");
}
$load_errors++;
$LoadedModules{$_} = 0;
} else {
$self->{dbg} && $self->Debug("loaded module $_");
$LoadedModules{$_} = 1;
}
}
! $load_errors;
}
sub Loader {
# this is enough to load Apache::ASP::Load, we only need to do it
# at runtime since the purpose of Loader() is to be run from
# the httpd.conf during parent startup time, so this module will
# be cached just fine at that time.
#
require Apache::ASP::Load;
&Apache::ASP::Load::Run(@_);
}
sub DSOError {
my $r = shift;
# this could happen with a bad filtering sequence
warn(<<ERROR);
No valid request object ($r) passed to ASP handler
If you are getting this error message and are using mod_perl 1.x and Apache 1.x,
you likely have a broken DSO version of mod_perl which often occurs
when using RedHat RPMs. One fix reported is to configure "PerlSendHeader On".
Another fix is to compile statically the apache + mod_perl build as
RedHat RPMs have been trouble.
If you are using a newer mod_perl2 + Apache2, make sure you have
upgraded to the last Apache::ASP release, and report the issue
if problems continue to the Apache::ASP mailing list. As of
December 2002, mod_perl2 + Apache2 combination is still experimental
and under development.
Please check FAQ or mod_perl archives for more information.
ERROR
;
500;
}
sub CompileChecksumKeys() { \@CompileChecksumKeys };
sub get_dir_config {
should now work. Thanks for bug report from David Kulp.
+ Added an early srand() for better $ServerID creation
+ Work around for DSO problems where $r is not always correctly
defined in Apache::ASP::handler(). Thanks to Tom Lear for patch.
=item $VERSION = 2.31; $DATE="01/22/2002";
+ $Server->MapInclude() API extension created to wrap up Apache::ASP::SearchDirs
functionality so one may do an conditional check for an include existence befor
executing $Response->Include(). Added API test to server.t
+ $Server->Transfer() now allows arguments like $Response->Include(), and now acts just
as a wrapper for:
$Response->Include($file, @args);
$Response->End();
added test case at t/server_transfer.t
+ Removed dependency of StatINC functionality on Apache::Symbol. Apache::Symbol
is no longer required. Added test of t/stat_inc.t for correct StatINC initialization
for platforms where Devel::Symdump is present.
+ Better error message when $Request->Params has not been defined with RequestParams
config & it gets used in script. Added test case as t/request_params_none.t
+ Directories cannot now be included as scripts via $Response->Include(), added
test case to t/include.t
- No longer make $Response->Flush dependent on $Response->IsClientConnected() to
be true to write output to client. There have been spurious errors reported
about the new ( >= 2.25 ) IsClientConnected code, and this will limit the impact
of that functionality possibly not working still to those users explicitly using
that API.
+ $Response->AddHeader($header_name, $value) now will set $Response members
for these headers: Content-Type, Cache-Control, Expires. This is to avoid
both the application & Apache::ASP sending out duplicate headers. Added
test cases for this to t/response.t
+ split up Bundle::Apache::ASP into that, and Bundle::Apache::ASP::Extra
the former with just the required modules to run, and the latter
for extra functionality in Apache::ASP
+ new $Request->{Method} member to return $r->method of GET or POST that
client browser is requesting, added t/request.t sub test to cover this member.
=item $VERSION = 2.29; $DATE="11/19/2001";
+Added some extra help text to the ./cgi/asp --help message
to clarify how to pass arguments to a script from the command line.
+When using $Server->Mail() API, if Content-Type header is set,
and MIME-Version is not, then a "MIME-Version: 1.0" header will be sent
for the email. This is correct according to RFC 1521 which specifies
for the first time the Content-Type: header for email documents.
Thanks to Philip Mak for pointing out this correct behavior.
+Made dependent on MLDBM::Sync version .25 to pass the taint_check.t test
+Improved server_mail.t test to work with mail servers were relaying is denied
+Added <html><body> tags to MailErrorsTo email
--Fixed SessionCount / Session_OnEnd bug, where these things were not
working for $Sessions that never had anything written to them.
This bug was introduced in 2.23/2.25 release.
There was an optimization in 2.23/2.25 where a $Session that was never
used does not write its state lock file & dbm files to disk, only if
it gets written too like $Session->{MARK}++. Tracking of these NULL $Sessions
then is handled solely in the internal database. For $Session garbage
collection though which would fire Session_OnEnd events and update
SessionCount, the Apache::ASP::State->GroupMembers() function was just
looking for state files on disk ... now it looks in the internal database
too for SessionID records for garbage collection.
Added a test at ./t/session_events.t for these things.
+Some optimizations for $Session API use.
+Added support for XSLT via XML::LibXSLT, patch courtesy of Michael Buschauer
-Got rid of an warning when recompiling changing includes under perl 5.6.1...
undef($code) method did not work for this perl version, rather undef(&$code) does.
Stopped using using Apache::Symbol for this when available.
-Make Apache::ASP script run under perl taint checking -T for perl 5.6.1...
$code =~ tr///; does not work to untaint here, so much use the slower:
$code =~ /^(.*)$/s; $code = $1; method to untaint.
-Check for inline includes changing, included in a dynamic included
loaded at runtime via $Response->Include(). Added test case for
this at t/include_change.t. If an inline include of a dynamic include
changes, the dynamic include should get recompiled now.
-Make OK to use again with PerlTaintCheck On, with MLDBM::Sync 2.25.
Fixed in ASP.pm, t/global.asa, and created new t/taint_check.t test script
+Load more modules when Apache::ASP is loaded so parent will share more
with children httpd:
Apache::Symbol
Devel::Symdump
Config
lib
MLDBM::Sync::SDBM_File
+When FileUploadMax bytes is exceeded for a file upload, there will not
be an odd error anymore resulting from $CGI::POST_MAX being triggered,
instead the file upload input will simply be ignored via $CGI::DISABLE_UPLOADS.
This gives the developer the opportunity to tell the user the the file upload
was too big, as demonstrated by the ./site/eg/file_upload.asp example.
To not let the web client POST a lot of data to your scripts as a form
of a denial of service attack use the apache config LimitRequestBody for the
max limits. You can think of PerlSetVar FileUploadMax as a soft limit, and
apache's LimitRequestBody as a hard limit.
--Under certain circumstances with file upload, it seems that IsClientConnected()
would return an aborted client value from $r->connection->aborted, so
the buffer output data would not be flushed to the client, and
the HTML page would return to the browser empty. This would be under
normal file upload use. One work-around was to make sure to initialize
the $Request object before $Response->IsClientConnected is called,
then $r->connection->aborted returns the right value.
This problem was probably introduced with IsClientConnected() code changes
starting in the 2.25 release.
=item $VERSION = 2.27; $DATE="10/31/2001";
+ Wrapped call to $r->connection->fileno in eval {} so to
preserve backwards compatibility with older mod_perl versions
that do not have this method defined. Thanks to Helmut Zeilinger
for catching this.
+ removed ./dev directory from distribution, useless clutter
+ Removed dependency on HTTP::Date by taking code into
Apache::ASP as Apache::ASP::Date. This relieves
the dependency of Apache::ASP on libwww LWP libraries.
If you were using HTTP::Date functions before without loading
"use HTTP::Date;" on your own, you will have to do this now.
+ Streamlined code execution. Especially worked on
$Response->IsClientConnected which gets called during
a normal request execution, and got rid of IO::Select
dependency. Some function style calls instead of OO style
calls where private functions were being invokes that one
would not need to override.
- Fixed possible bug when flushing a data buffer where there
is just a '0' in it.
+ Updated docs to note that StateCache config was deprecated
as of 2.23. Removed remaining code that referenced the config.
+ Removed references to unused OrderCollections code.
+UseStrict setting compiles all scripts including
global.asa with "use strict" turned on for catching
more coding errors. With this setting enabled,
use strict errors die during compilation forcing
Apache::ASP to try to recompile the script until
successful.
-Object use in includes like $Response->Write()
no longer error with "use strict" programming.
+SessionQuery config setting with $Server->URL($url, { %params } )
alpha API extensions to enable cookieless sessions.
+Debugging not longer produces internal debugging
by default. Set to -1,-2 for internal debugging
for Debug settings 1 & 2.
+Both StateSerializer & StateDB can be changed
without affecting a live web site, by storing
the configurations for $Application & $Session
in an internal database, so that if $Session was
created with SDBM_File for the StateDB (default),
it will keep this StateDB setting until it ends.
+StateSerializer config setting. Default Data::Dumper,
can also be set to Storable. Controls how data is
serialized before writing to $Application & $Session.
+Beefed up the make test suite.
+Improved the locking, streamlining a bit of the
$Application / $Session setup process. Bench is up to
22 from 21 hits / sec on dev NT box.
+Cut more fat for faster startup, now on my dev box
I get 44 hits per sec Apache::ASP vs. 48 Embperl
vs. 52 CGI via Apache::Registry for the HelloWorld Scripts.
-Improved linking for the online site documentation,
where a few links before were bad.
=item $VERSION = 0.17; $DATE="11/15/99";
++20%+ faster startup script execution, as measured by the
HelloWorld bench. I cut a lot of the fat out of
the code, and is now at least 20% faster on startup
both with and without state.
On my dev (NT, apache 1.3.6+mod_perl) machine, I now get:
42 hits per sec on Apache::ASP HelloWorld bench
46 hits per sec on Embperl (1.2b10) and
51 hits per sec for CGI Apache::Registry scripts
Before Apache::ASP was clocking some 31 hits per sec.
Apache::ASP also went from 75 to 102 hits per second
on Solaris.
+PerlTaintCheck On friendly. This is mod_perl's way
of providing -T taint checking. When Apache::ASP
is used with state objects like $Session or $Application,
MLDBM must also be made taint friendly with:
$MLDBM::RemoveTaint = 1;
which could be put in the global.asa. Documented.
+Added $Response->ErrorDocument($error_code, $uri_or_string)
API extension which allows for setting of Apache's error
document at runtime. This is really just a wrapper
for Apache->custom_response() renamed so it syncs with
the Apache ErrorDocument config setting. Updated
documentation, and added error_document.htm example.
=OrderCollections setting was added, but then REMOVED
because it was not going to be used. It bound
$Request->* collections/hashes to Tie::IxHash, so that data
in those collections would be read in the order the
browser sent it, when eaching through or with keys.
-global.asa will be reloaded when changed. This broke
when I optimized the modification times with (stat($file))[9]
rather than "use File::stat; stat($file)->mtime"
-Make Apache::ASP->Loader() PerlRestartHandler safe,
had some unstrict code that was doing the wrong thing.
-IncludesDir config now works with DynamicIncludes.
+DebugBufferLength feature added, giving control to
how much buffered output gets shown when debugging errors.
++Tuning of $Response->Write(), which processes all
static html internally, to be almost 50% faster for
its typical use, when BufferingOn is enabled, and
CgiHeaders are disabled, both being defaults.
This can show significant speed improvements for tight
loops that render ASP output.
+Auto linking of ./site/eg/ text to example scripts
at web site.
+$Application->GetSession($session_id) API extension, useful
for managing active user sessions when storing session ids
in $Application. Documented.
-disable use of flock() on Win95/98 where it is unimplemented
-@array context of $Request->Form('name') returns
undef when value for 'name' is undefined. Put extra
logic in there to make sure this happens.
=item $VERSION = 0.16; $DATE="09/22/99";
-$Response->{Buffer} and PerlSetVar BufferingOn
configs now work when set to 0, to unbuffer output,
and send it out to the web client as the script generates it.
Buffering is enabled by default, as it is faster, and
allows a script to error cleanly in the middle of execution.
( run in 1.089 second using v1.01-cache-2.11-cpan-39bf76dae61 )