Apache-ASP
view release on metacpan or search on metacpan
# For documentation for this module, please see the end of this file
# or try `perldoc Apache::ASP`
package Apache::ASP;
$VERSION = 2.63;
#require DynaLoader;
#@ISA = qw(DynaLoader);
#bootstrap Apache::ASP $VERSION;
use Digest::MD5 qw(md5_hex);
use Cwd qw(cwd);
# create multiple entries for this symbols for StatINC
use Fcntl qw(:flock O_RDWR O_CREAT);
# load these always, but only load ::State, ::Session, ::Application
# at runtime in non mod_perl environments since they may not be needed
use Apache::ASP::GlobalASA;
use Apache::ASP::Response;
use Apache::ASP::Request;
use Apache::ASP::Server;
use Apache::ASP::Date;
use Apache::ASP::Lang::PerlScript;
use Carp qw(confess cluck);
use strict;
no strict qw(refs);
use vars qw($VERSION
%NetConfig %LoadedModules %LoadModuleErrors
%Codes %includes %Includes %CompiledIncludes
@Objects %Register %XSLT
$ServerID $ServerPID $SrandPid
$CompileErrorSize $CacheSize @CompileChecksumKeys
%ScriptLanguages $ShareDir $INCDir $AbsoluteFileMatch
$QuickStartTime
$SessionCookieName
$LoadModPerl
$ModPerl2
);
# other common modules load now, these are optional though, so we do not error upon failure
# just do this once perl mod_perl parent startup
unless($LoadModPerl++) {
my @load_modules = qw( Config lib Time::HiRes );
if($ENV{MOD_PERL}) {
# Only pre-load these if in a mod_perl environment for sharing memory post fork.
# These will not be loaded then for CGI until absolutely necessary at runtime
push(@load_modules, qw(
mod_perl
MLDBM::Serializer::Data::Dumper Devel::Symdump CGI
Apache::ASP::StateManager Apache::ASP::Session Apache::ASP::Application
Apache::ASP::StatINC Apache::ASP::Error
)
);
}
for my $module ( @load_modules ) {
eval "use $module ();";
}
if(exists $ENV{MOD_PERL_API_VERSION}) {
if($ModPerl2 = ($ENV{MOD_PERL_API_VERSION} >= 2)) {
if($ModPerl2) {
eval "use Apache::ASP::ApacheCommon ();";
die($@) if $@;
}
}
}
}
## HEADER TOKEN TWEAK
# This must be called outside the above load module block, so that
# its gets run whenever this module is loaded
# This didn't work in 1.27 mod_perl, with DSO enabled, would
# put the Apache::ASP token in front.
# eval { &Apache::add_version_component("Apache::ASP/$VERSION"); };
# $Apache::Server::AddPerlVersion = 1;
#use integer; # don't use screws up important numeric logic
@Objects = ('Application', 'Session', 'Response', 'Server', 'Request');
map { eval "sub $_ { shift->{$_} }" } @Objects;
# use regexp directly, not sub for speed
$AbsoluteFileMatch = '^(/|[a-zA-Z]:)';
$CacheSize = 1024*1024*10;
$SessionCookieName = 'session-id';
# ServerID creates a unique identifier for the server
srand();
$ServerID = substr(md5_hex($$.rand().time().(-M('..')||'').(-M('/')||'')), 0, 16);
$ServerPID = $$;
# DEFAULT VALUES
$Apache::ASP::CompileErrorSize = 500;
@CompileChecksumKeys = qw ( Global DynamicIncludes UseStrict XMLSubsMatch XMLSubsPerlArgs XMLSubsStrict GlobalPackage UniquePackages IncludesDir InodeNames PodComments );
%ScriptLanguages = (
'PerlScript' => 1,
);
&InitPaths();
%Apache::ASP::LoadModuleErrors =
(
'Filter' =>
"Apache::Filter was not loaded correctly for using SSI filtering. ".
"If you don't want to use filtering, make sure you turn the Filter ".
"config option off whereever it's being used",
Clean => undef,
CreateObject =>
'OLE-active objects not supported for this platform, '.
'try installing Win32::OLE',
Gzip =>
'Compress::Zlib is needed to make gzip content-encoding work, '.
'If you want to use this feature, get yourself the latest '.
'Compress::Zlib from CPAN. ',
HiRes => undef,
FormFill =>
'HTML::FillInForm is needed to use the FormFill feature '.
'for auto filling forms with $Response->Form() data',
MailAlert => undef,
SendMail => "No mailing support",
StateDB =>
'cannot load StateDB '.
'must be a valid perl module with a db tied hash interface '.
'such as: SDBM_File (default), or DB_File',
StateSerializer =>
'cannot load StateSerializer '.
'must be a valid serializing perl module for use with MLDBM '.
'such as Data::Dumper (default), or Storable',
StatINC => "You need this module for StatINC, please download it from CPAN",
'Cache' => "You need this module for xml output caching",
XSLT => 'Cannot load XML::XSLT. Try installing the module.',
The defaults of 20 minutes for SessionTimeout and 10 times for
StateManager, has dead Sessions being cleaned up every 2 minutes.
PerlSetVar StateManager 10
=item StateDB
default SDBM_File, this is the internal database used for state
objects like $Application and $Session. Because an SDBM_File %hash
has a limit on the size of a record key+value pair, usually 1024 bytes,
you may want to use another tied database like DB_File or
MLDBM::Sync::SDBM_File.
With lightweight $Session and $Application use, you can get
away with SDBM_File, but if you load it up with complex data like
$Session{key} = { # very large complex object }
you might max out the 1024 limit.
Currently StateDB can be: SDBM_File, MLDBM::Sync::SDBM_File,
DB_File, and GDBM_File. Please let me know if you would like to
add any more to this list.
As of version .18, you may change this setting in a live production
environment, and new state databases created will be of this format.
With a prior version if you switch to a new StateDB, you would want to
delete the old StateDir, as there will likely be incompatibilities between
the different database formats, including the way garbage collection
is handled.
PerlSetVar StateDB SDBM_File
=item StateCache
Deprecated as of 2.23. There is no equivalent config for
the functionality this represented from that version on.
The 2.23 release represented a significant rewrite
of the state management, moving to MLDBM::Sync for its
subsystem.
=item StateSerializer
default Data::Dumper, you may set this to Storable for
faster serialization and storage of data into state objects.
This is particularly useful when storing large objects in
$Session and $Application, as the Storable.pm module has a faster
implementation of freezing and thawing data from and to
perl structures. Note that if you are storing this much
data in your state databases, you may want to use
DB_File since it does not have the default 1024 byte limit
that SDBM_File has on key/value lengths.
This configuration setting may be changed in production
as the state database's serializer type is stored
in the internal state manager which will always use
Data::Dumper & SDBM_File to store data.
PerlSetVar StateSerializer Data::Dumper
=head2 Sessions
=item CookiePath
URL root that client responds to by sending the session cookie.
If your asp application falls under the server url "/asp",
then you would set this variable to /asp. This then allows
you to run different applications on the same server, with
different user sessions for each application.
PerlSetVar CookiePath /
=item CookieDomain
Default 0, this NON-PORTABLE configuration will allow sessions to span
multiple web sites that match the same domain root. This is useful if
your web sites are hosted on the same machine and can share the same
StateDir configuration, and you want to shared the $Session data
across web sites. Whatever this is set to, that will add a
; domain=$CookieDomain
part to the Set-Cookie: header set for the session-id cookie.
PerlSetVar CookieDomain .your.global.domain
=item SessionTimeout
Default 20 minutes, when a user's session has been inactive for this
period of time, the Session_OnEnd event is run, if defined, for
that session, and the contents of that session are destroyed.
PerlSetVar SessionTimeout 20
=item SecureSession
default 0. Sets the secure tag for the session cookie, so that the cookie
will only be transmitted by the browser under https transmissions.
PerlSetVar SecureSession 1
=item HTTPOnlySession
default 0. Sets HttpOnly flag to session cookie to mitigate XSS attacks.
Supported by most modern browsers, it only allows access to the
session cookie by the server (ie NOT Javascript)
PerlSetVar HTTPOnlySession 1
=item ParanoidSession
default 0. When true, stores the user-agent header of the browser
that creates the session and validates this against the session cookie presented.
If this check fails, the session is killed, with the rationale that
there is a hacking attempt underway.
This config option was implemented to be a smooth upgrade, as
you can turn it off and on, without disrupting current sessions.
Sessions must be created with this turned on for the security to take effect.
This config option is to help prevent a brute force cookie search from
being successful. The number of possible cookies is huge, 2^128, thus making such
a hacking attempt VERY unlikely. However, on the off chance that such
an attack is successful, the hacker must also present identical
browser headers to authenticate the session, or the session will be
destroyed. Thus the User-Agent acts as a backup to the real session id.
The IP address of the browser cannot be used, since because of proxies,
IP addresses may change between requests during a session.
There are a few browsers that will not present a User-Agent header.
These browsers are considered to be browsers of type "Unknown", and
this method works the same way for them.
Most people agree that this level of security is unnecessary, thus
it is titled paranoid :)
PerlSetVar ParanoidSession 0
=item SessionSerialize
default 0, if true, locks $Session for duration of script, which
serializes requests to the $Session object. Only one script at
a time may run, per user $Session, with sessions allowed.
Serialized requests to the session object is the Microsoft ASP way,
but is dangerous in a production environment, where there is risk
of long-running or run-away processes. If these things happen,
a session may be locked for an indefinite period of time. A user
STOP button should safely quit the session however.
PerlSetVar SessionSerialize 0
=item SessionCount
default 0, if true enables the $Application->SessionCount API
which returns how many sessions are currently active in
the application. This config was created
because there is a performance hit associated with this
count tracking, so it is disabled by default.
PerlSetVar SessionCount 1
=head2 Cookieless Sessions
=item SessionQueryParse
default 0, if true, will automatically parse the $Session
session id into the query string of each local URL found in the
$Response buffer. For this setting to work therefore,
buffering must be enabled. This parsing will only occur
when a session cookie has not been sent by a browser, so the
first script of a session enabled site, and scripts viewed by
web browsers that have cookies disabled will trigger this behavior.
Although this runtime parsing method is computationally
expensive, this cost should be amortized across most users
that will not need this URL parsing. This is a lazy programmer's
dream. For something more efficient, look at the SessionQuery
setting. For more information about this solution, please
read the SESSIONS section.
PerlSetVar SessionQueryParse 0
=item SessionQueryParseMatch
default 0, set to a regexp pattern that matches all URLs that you
want to have SessionQueryParse parse in session ids. By default
SessionQueryParse only modifies local URLs, but if you name
your URLs of your site with absolute URLs like http://localhost
then you will need to use this setting. So to match
http://localhost URLs, you might set this pattern to
^http://localhost. Note that by setting this config,
you are also setting SessionQueryParse.
PerlSetVar SessionQueryParseMatch ^https?://localhost
=item SessionQuery
default 0, if set, the session id will be initialized from
the $Request->QueryString if not first found as a cookie.
You can use this setting coupled with the
$Server->URL($url, \%params)
API extension to generate local URLs with session ids in their
query strings, for efficient cookieless session support.
Note that if a browser has cookies disabled, every URL
to any page that needs access to $Session will need to
be created by this method, unless you are using SessionQueryParse
which will do this for you automatically.
PerlSetVar SessionQuery 0
=item SessionQueryMatch
default 0, set to a regexp pattern that will match
URLs for $Server->URL() to add a session id to. SessionQuery
normally allows $Server->URL() to add session ids just to
local URLs, so if you use absolute URL references like
http://localhost/ for your web site, then just like
with SessionQueryParseMatch, you might set this pattern
to ^http://localhost
next server restart or stop/start.
There are a few advantages for not reloading scripts and modules
in production. First there is a slight performance improvement
by not having to stat() the script, its includes and the global.asa
every request.
From an application deployment standpoint, you
also gain the ability to deploy your application as a
snapshot taken when the server starts and restarts.
This provides you with the reassurance that during a
production server update from development sources, you
do not have to worry with sources being used for the
wrong libraries and such, while they are all being
copied over.
Finally, though you really should not do this, you can
work on a live production application, with a test server
reloading changes, but your production server does see
the changes until you restart or stop/start it. This
saves your public from syntax errors while you are just
doing a quick bug fix.
PerlSetVar StatScripts 1
=item SoftRedirect
default 0, if true, a $Response->Redirect() does not end the
script. Normally, when a Redirect() is called, the script
is ended automatically. SoftRedirect 1, is a standard
way of doing redirects, allowing for html output after the
redirect is specified.
PerlSetVar SoftRedirect 0
=item Filter
On/Off, default Off. With filtering enabled, you can take advantage of
full server side includes (SSI), implemented through Apache::SSI.
SSI is implemented through this mechanism by using Apache::Filter.
A sample configuration for full SSI with filtering is in the
./site/eg/.htaccess file, with a relevant example script ./site/eg/ssi_filter.ssi.
You may only use this option with modperl v1.16 or greater installed
and PERL_STACKED_HANDLERS enabled. Filtering may be used in
conjunction with other handlers that are also "filter aware".
If in doubt, try building your mod_perl with
perl Makefile.PL EVERYTHING=1
With filtering through Apache::SSI, you should expect near a
a 20% performance decrease.
PerlSetVar Filter Off
=item CgiHeaders
default 0. When true, script output that looks like HTTP / CGI
headers, will be added to the HTTP headers of the request.
So you could add:
Set-Cookie: test=message
<html>...
to the top of your script, and all the headers preceding a newline
will be added as if with a call to $Response->AddHeader(). This
functionality is here for compatibility with raw cgi scripts,
and those used to this kind of coding.
When set to 0, CgiHeaders style headers will not be parsed from the
script response.
PerlSetVar CgiHeaders 0
=item Clean
default 0, may be set between 1 and 9. This setting determine how much
text/html output should be compressed. A setting of 1 strips mostly
white space saving usually 10% in output size, at a performance cost
of less than 5%. A setting of 9 goes much further saving anywhere
25% to 50% typically, but with a performance hit of 50%.
This config option is implemented via HTML::Clean. Per script
configuration of this setting is available via the $Response->{Clean}
property, which may also be set between 0 and 9.
PerlSetVar Clean 0
=item CompressGzip
default 0, if true will gzip compress HTML output on the
fly if Compress::Zlib is installed, and the client browser
supports it. Depending on the HTML being compressed,
the client may see a 50% to 90% reduction in HTML output.
I have seen 40K of HTML squeezed down to just under 6K.
This will come at a 5%-20% hit to CPU usage per request
compressed.
Note there are some cases when a browser says it will accept
gzip encoding, but then not render it correctly. This
behavior has been seen with IE5 when set to use a proxy but
not using a proxy, and the URL does not end with a .html or .htm.
No work around has yet been found for this case so use at your
own risk.
PerlSetVar CompressGzip 1
=item FormFill
default 0, if true will auto fill HTML forms with values
from $Request->Form(). This functionality is provided
by use of HTML::FillInForm. For more information please
see "perldoc HTML::FillInForm", and the
example ./site/eg/formfill.asp.
This feature can be enabled on a per form basis at runtime
with $Response->{FormFill} = 1
PerlSetVar FormFill 1
=item TimeHiRes
called at the end of the HTML output.
As of version 2.23 this value is updated correctly
before global.asa Script_OnStart is called, so
global script termination may be correctly handled
during that event, which one might want to do
with excessive user STOP/RELOADS when the web
server is very busy.
An API extension $Response->IsClientConnected
may be called for refreshed connection status
without calling first a $Response->Flush
=item $Response->{PICS}
If this property has been set, a PICS-Label HTTP header will be
sent with its value. For those that do not know, PICS is a header
that is useful in rating the internet. It stands for
Platform for Internet Content Selection, and you can find more
info about it at: http://www.w3.org
=item $Response->{Status} = $status
Sets the status code returned by the server. Can be used to
set messages like 500, internal server error
=item $Response->AddHeader($name, $value)
Adds a custom header to a web page. Headers are sent only before any
text from the main page is sent, so if you want to set a header
after some text on a page, you must turn BufferingOn.
=item $Response->AppendToLog($message)
Adds $message to the server log. Useful for debugging.
=item $Response->BinaryWrite($data)
Writes binary data to the client. The only
difference from $Response->Write() is that $Response->Flush()
is called internally first, so the data cannot be parsed
as an html header. Flushing flushes the header if has not
already been written.
If you have set the $Response->{ContentType}
to something other than text/html, cgi header parsing (see CGI
notes), will be automatically be turned off, so you will not
necessarily need to use BinaryWrite for writing binary data.
For an example of BinaryWrite, see the binary_write.htm example
in ./site/eg/binary_write.htm
Please note that if you are on Win32, you will need to
call binmode on a file handle before reading, if
its data is binary.
=item $Response->Clear()
Erases buffered ASP output.
=item $Response->Cookies($name, [$key,] $value)
Sets the key or attribute of cookie with name $name to the value $value.
If $key is not defined, the Value of the cookie is set.
ASP CookiePath is assumed to be / in these examples.
$Response->Cookies('name', 'value');
--> Set-Cookie: name=value; path=/
$Response->Cookies("Test", "data1", "test value");
$Response->Cookies("Test", "data2", "more test");
$Response->Cookies(
"Test", "Expires",
&HTTP::Date::time2str(time+86400)
);
$Response->Cookies("Test", "Secure", 1);
$Response->Cookies("Test", "Path", "/");
$Response->Cookies("Test", "Domain", "host.com");
--> Set-Cookie:Test=data1=test%20value&data2=more%20test; \
expires=Fri, 23 Apr 1999 07:19:52 GMT; \
path=/; domain=host.com; secure
The latter use of $key in the cookies not only sets cookie attributes
such as Expires, but also treats the cookie as a hash of key value pairs
which can later be accesses by
$Request->Cookies('Test', 'data1');
$Request->Cookies('Test', 'data2');
Because this is perl, you can (NOT PORTABLE) reference the cookies
directly through hash notation. The same 5 commands above could be compressed to:
$Response->{Cookies}{Test} =
{
Secure => 1,
Value =>
{
data1 => 'test value',
data2 => 'more test'
},
Expires => 86400, # not portable, see above
Domain => 'host.com',
Path => '/'
};
and the first command would be:
# you don't need to use hash notation when you are only setting
# a simple value
$Response->{Cookies}{'Test Name'} = 'Test Value';
I prefer the hash notation for cookies, as this looks nice, and is
quite perlish. It is here to stay. The Cookie() routine is
very complex and does its best to allow access to the
underlying hash structure of the data. This is the best emulation
I could write trying to match the Collections functionality of
cookies in IIS ASP.
For more information on Cookies, please go to the source at
http://home.netscape.com/newsref/std/cookie_spec.html
=item $Response->Debug(@args)
API Extension. If the Debug config option is set greater than 0,
this routine will write @args out to server error log. refs in @args
will be expanded one level deep, so data in simple data structures
like one-level hash refs and array refs will be displayed. CODE
refs like
$Response->Debug(sub { "some value" });
will be executed and their output added to the debug output.
This extension allows the user to tie directly into the
debugging capabilities of this module.
While developing an app on a production server, it is often
useful to have a separate error log for the application
to catch debugging output separately. One way of implementing
this is to use the Apache ErrorLog configuration directive to
create a separate error log for a virtual host.
If you want further debugging support, like stack traces
in your code, consider doing things like:
$Response->Debug( sub { Carp::longmess('debug trace') };
$SIG{__WARN__} = \&Carp::cluck; # then warn() will stack trace
The only way at present to see exactly where in your script
an error occurred is to set the Debug config directive to 2,
and match the error line number to perl script generated
from your ASP script.
However, as of version 0.10, the perl script generated from the
asp script should match almost exactly line by line, except in
cases of inlined includes, which add to the text of the original script,
pod comments which are entirely yanked out, and <% # comment %> style
comments which have a \n added to them so they still work.
If you would like to see the HTML preceding an error
while developing, consider setting the BufferingOn
config directive to 0.
=item $Response->End()
Sends result to client, and immediately exits script.
Automatically called at end of script, if not already called.
=item $Response->ErrorDocument($code, $uri)
API extension that allows for the modification the Apache
ErrorDocument at runtime. $uri may be a on site document,
off site URL, or string containing the error message.
This extension is useful if you want to have scripts
set error codes with $Response->{Status} like 401
for authentication failure, and to then control from
the script what the error message looks like.
For more information on the Apache ErrorDocument mechanism,
ActiveState PerlScript, so if you use the hashes returned by such
a technique, it will not be portable.
A normal use of this feature would be to iterate through the
form variables in the form hash...
$form = $Request->Form();
for(keys %{$form}) {
$Response->Write("$_: $form->{$_}<br>\n");
}
Please see the ./site/eg/server_variables.htm asp file for this
method in action.
Note that if a form POST or query string contains duplicate
values for a key, those values will be returned through
normal use of the $Request object:
@values = $Request->Form('key');
but you can also access the internal storage, which is
an array reference like so:
$array_ref = $Request->{Form}{'key'};
@values = @{$array_ref};
Please read the PERLSCRIPT section for more information
on how things like $Request->QueryString() & $Request->Form()
behave as collections.
=over
=item $Request->{Method}
API extension. Returns the client HTTP request method, as in
GET or POST. Added in version 2.31.
=item $Request->{TotalBytes}
The amount of data sent by the client in the body of the
request, usually the length of the form data. This is
the same value as $Request->ServerVariables('CONTENT_LENGTH')
=item $Request->BinaryRead([$length])
Returns a string whose contents are the first $length bytes
of the form data, or body, sent by the client request.
If $length is not given, will return all of the form data.
This data is the raw data sent by the client, without any
parsing done on it by Apache::ASP.
Note that BinaryRead will not return any data for file uploads.
Please see the $Request->FileUpload() interface for access
to this data. $Request->Form() data will also be available
as normal.
=item $Request->ClientCertificate()
Not implemented.
=item $Request->Cookies($name [,$key])
Returns the value of the Cookie with name $name. If a $key is
specified, then a lookup will be done on the cookie as if it were
a query string. So, a cookie set by:
Set-Cookie: test=data1=1&data2=2
would have a value of 2 returned by $Request->Cookies('test','data2').
If no name is specified, a hash will be returned of cookie names
as keys and cookie values as values. If the cookie value is a query string,
it will automatically be parsed, and the value will be a hash reference to
these values.
When in doubt, try it out. Remember that unless you set the Expires
attribute of a cookie with $Response->Cookies('cookie', 'Expires', $xyz),
the cookies that you set will only last until you close your browser,
so you may find your self opening & closing your browser a lot when
debugging cookies.
For more information on cookies in ASP, please read $Response->Cookies()
=item $Request->FileUpload($form_field, $key)
API extension. The FileUpload interface to file upload data is
stabilized. The internal representation of the file uploads
is a hash of hashes, one hash per file upload found in
the $Request->Form() collection. This collection of collections
may be queried through the normal interface like so:
$Request->FileUpload('upload_file', 'ContentType');
$Request->FileUpload('upload_file', 'FileHandle');
$Request->FileUpload('upload_file', 'BrowserFile');
$Request->FileUpload('upload_file', 'Mime-Header');
$Request->FileUpload('upload_file', 'TempFile');
* note that TempFile must be use with the UploadTempFile
configuration setting.
The above represents the old slow collection interface,
but like all collections in Apache::ASP, you can reference
the internal hash representation more easily.
my $fileup = $Request->{FileUpload}{upload_file};
$fileup->{ContentType};
$fileup->{BrowserFile};
$fileup->{FileHandle};
$fileup->{Mime-Header};
$fileup->{TempFile};
=item $Request->Form($name)
Returns the value of the input of name $name used in a form
with POST method. If $name is not specified, returns a ref to
a hash of all the form data. One can use this hash to
create a nice alias to the form data like:
# in global.asa
use vars qw( $Form );
sub Script_OnStart {
$Form = $Request->Form;
}
# then in ASP scripts
<%= $Form->{var} %>
File upload data will be loaded into $Request->Form('file_field'),
where the value is the actual file name of the file uploaded, and
the contents of the file can be found by reading from the file
name as a file handle as in:
while(read($Request->Form('file_field_name'), $data, 1024)) {};
For more information, please see the CGI / File Upload section,
as file uploads are implemented via the CGI.pm module. An
example can be found in the installation
samples ./site/eg/file_upload.asp
=item $Request->Params($name)
API extension. If RequestParams CONFIG is set, the $Request->Params
object is created with combined contents of $Request->QueryString
one may execute an include at runtime by utilizing
this API extension
$Response->Include("filename.inc", @args);
which is a direct translation of the dynamic include above.
Although inline includes should be a little faster,
runtime dynamic includes represent great potential
savings in httpd memory, as includes are shared
between scripts keeping the size of each script
to a minimum. This can often be significant saving
if much of the formatting occurs in an included
header of a www page.
By default, all includes will be inlined unless
called with an args parameter. However, if you
want all your includes to be compiled as subs and
dynamically executed at runtime, turn the DynamicIncludes
config option on as documented above.
=head2 Apache::SSI for mod_perl 1.3.x only
One of the things missing above is the
<!--#include virtual=filename.cgi-->
tag. This and many other SSI code extensions are available
by filtering Apache::ASP output through Apache::SSI via
the Apache::Filter and the Filter config options, available in mod_perl 1.3.x / Apache 1.3.x.
Unfortunately this functionality is not available with mod_perl 2 / Apache 2.
For more information on how to wire Apache::ASP and Apache::SSI
together, please see the Filter config option documented
above. Also please see Apache::SSI for further information
on the capabilities it offers.
=head2 SSI with mod_filter in Apache 2
Apache 2 offers chained filters. It may be possible to chain filters to
Apache::ASP output through mod_filter for SSI processing:
http://httpd.apache.org/docs/2.1/mod/mod_filter.html
=head1 EXAMPLES
Use with Apache. Copy the ./site/eg directory from the ASP installation
to your Apache document tree and try it out! You have to put
"AllowOverride All" in your <Directory> config section to let the
.htaccess file in the ./site/eg installation directory do its work.
IMPORTANT (FAQ): Make sure that the web server has write access to
that directory. Usually a
chmod -R 0777 eg
will do the trick :)
=head1 SESSIONS
Cookies are used by default for user $Session support ( see OBJECTS ).
In order to track a web user and associate server side data
with that client, the web server sets, and the web client returns
a 32 byte session id identifier cookie. This implementation
is very secure and may be used in secure HTTPS transactions,
and made stronger with SecureSession, HTTPOnlySession and
ParanoidSession settings (see CONFIG ).
However good cookies are for this kind of persistent
state management between HTTP requests, they have long
been under fire for security risks associated with
JavaScript security exploits and privacy abuse by
large data tracking companies.
Because of these reasons, web users will sometimes turn off
their cookies, rendering normal ASP session implementations
powerless, resulting in a new $Session generated every request.
This is not good for ASP style sessions.
=head2 Cookieless Sessions
*** See WARNING Below ***
So we now have more ways to track sessions with the
SessionQuery* CONFIG settings, that allow a web developer
to embed the session id in URL query strings when use
of cookies is denied. The implementations work such that
if a user has cookies turned on, then cookies will be
used, but for those users with cookies turned off,
the session ids will be parsed into document URLs.
The first and easiest method that a web developer may use
to implement cookieless sessions are with SessionQueryParse*
directives which enable Apache::ASP to the parse the session id
into document URLs on the fly. Because this is resource
inefficient, there is also the SessionQuery* directives
that may be used with the $Server->URL($url,\%params) method to
generate custom URLs with the session id in its query string.
To see an example of these cookieless sessions in action,
check out the ./site/eg/session_query_parse.asp example.
*** WARNING ***
If you do use these methods, then be VERY CAREFUL
of linking offsite from a page that was accessed with a
session id in a query string. This is because this session
id will show up in the HTTP_REFERER logs of the linked to
site, and a malicious hacker could use this information to
compromise the security of your site's $Sessions, even if
these are run under a secure web server.
In order to shake a session id off an HTTP_REFERER for a link
taking a user offsite, you must point that link to a redirect
page that will redirect a user, like so:
<%
# "cross site scripting bug" prevention
my $sanitized_url =
$Server->HTMLEncode($Response->QueryString('OffSiteUrl'));
%>
<html>
<head>
<meta http-equiv=refresh content='0;URL=<%=$sanitized_url%>'>
</head>
<body>
Redirecting you offsite to
<a href=<%=$sanitized_url%> >here</a>...
</body>
</html>
Because the web browser visits a real page before being redirected
with the <meta> tag, the HTTP_REFERER will be set to this page.
Just be sure to not link to this page with a session id in its
query string.
Unfortunately a simple $Response->Redirect() will not work here,
because the web browser will keep the HTTP_REFERER of the
original web page if only a normal redirect is used.
print $filehandle; # will get you the file name
my $data;
while(read($filehandle, $data, 1024)) {
# data from the uploaded file read into $data
};
Please see the docs on CGI.pm (try perldoc CGI) for more information
on this topic, and ./site/eg/file_upload.asp for an example of its use.
Also, for more details about CGI.pm itself, please see the web site:
http://search.cpan.org/dist/CGI/
Occasionally, a newer version of CGI.pm will be released which breaks
file upload compatibility with Apache::ASP. If you find this to occur,
then you might consider downgrading to a version that works. For example,
one can install a working CGI.pm v2.78 for a working version, and to
get old versions of this module, one can go to BACKPAN at:
http://backpan.cpan.org/modules/by-authors/id/L/LD/LDS/
There is also $Request->FileUpload() API extension that you can use to get
more data about a file upload, so that the following properties are
available for querying:
my $file_upload = $Request->{FileUpload}{upload_field};
$file_upload->{BrowserFile}
$file_upload->{FileHandle}
$file_upload->{ContentType}
# only if FileUploadTemp is set
$file_upload->{TempFile}
# whatever mime headers are sent with the file upload
# just "keys %$file_upload" to find out
$file_upload->{?Mime-Header?}
Please see the $Request section in OBJECTS for more information.
=back
=head1 PERLSCRIPT
Much work has been done to bring compatibility with ASP applications
written in PerlScript under IIS. Most of that work revolved around
bringing a Win32::OLE Collection interface to many of the objects
in Apache::ASP, which are natively written as perl hashes.
New as of version 2.05 is new functionality enabled with the
CollectionItem setting, to giver better support to more recent PerlScript syntax.
This seems helpful when porting from an IIS/PerlScript code base.
Please see the CONFIG section for more info.
The following objects in Apache::ASP respond as Collections:
$Application
$Session
$Request->FileUpload *
$Request->FileUpload('upload_file') *
$Request->Form
$Request->QueryString
$Request->Cookies
$Response->Cookies
$Response->Cookies('some_cookie')
* FileUpload API Extensions
And as such may be used with the following syntax, as compared
with the Apache::ASP native calls. Please note the native Apache::ASP
interface is compatible with the deprecated PerlScript interface.
C = PerlScript Compatibility N = Native Apache::ASP
## Collection->Contents($name)
[C] $Application->Contents('XYZ')
[N] $Application->{XYZ}
## Collection->SetProperty($property, $name, $value)
[C] $Application->Contents->SetProperty('Item', 'XYZ', "Fred");
[N] $Application->{XYZ} = "Fred"
## Collection->GetProperty($property, $name)
[C] $Application->Contents->GetProperty('Item', 'XYZ')
[N] $Application->{XYZ}
## Collection->Item($name)
[C] print $Request->QueryString->Item('message'), "<br>\n\n";
[N] print $Request->{QueryString}{'message'}, "<br>\n\n";
## Working with Cookies
[C] $Response->SetProperty('Cookies', 'Testing', 'Extra');
[C] $Response->SetProperty('Cookies', 'Testing', {'Path' => '/'});
[C] print $Request->Cookies(Testing) . "<br>\n";
[N] $Response->{Cookies}{Testing} = {Value => Extra, Path => '/'};
[N] print $Request->{Cookies}{Testing} . "<br>\n";
Several incompatibilities exist between PerlScript and Apache::ASP:
> Collection->{Count} property has not been implemented.
> VBScript dates may not be used for Expires property of cookies.
> Win32::OLE::in may not be used. Use keys() to iterate over.
> The ->{Item} property does not work, use the ->Item() method.
=head1 STYLE GUIDE
Here are some general style guidelines. Treat these as tips for
best practices on Apache::ASP development if you will.
=head2 UseStrict
One of perl's blessings is also its bane, variables do not need to be
declared, and are by default globally scoped. The problem with this in
mod_perl is that global variables persist from one request to another
even if a different web browser is viewing a page.
To avoid this problem, perl programmers have often been advised to
add to the top of their perl scripts:
use strict;
In Apache::ASP, you can do this better by setting:
PerlSetVar UseStrict 1
which will cover both script & global.asa compilation and will catch
"use strict" errors correctly. For perl modules, please continue to
add "use strict" to the top of them.
Because its so essential in catching hard to find errors, this
configuration will likely become the default in some future release.
For now, keep setting it.
=head2 Do not define subroutines in scripts.
DO NOT add subroutine declarations in scripts. Apache::ASP is optimized
by compiling a script into a subroutine for faster future invocation.
Adding a subroutine definition to a script then looks like this to
the compiler:
sub page_script_sub {
...
... some HTML ...
...
sub your_sub {
...
}
...
}
The biggest problem with subroutines defined in subroutines is the
side effect of creating closures, which will not behave as usually
desired in a mod_perl environment. To understand more about closures,
please read up on them & "Nested Subroutines" at:
http://perl.apache.org/docs/general/perl_reference/perl_reference.html
tools that understand ASP, which reduces the amount of code they break
when editing the HTML. Using Apache::ASP instead of M$ ASP allows us to
use perl (far superior to VBScript) and Apache (far superior to IIS).
We've been very pleased with Apache::ASP and its support.
=item Planet of Music
Apache::ASP has been a great tool. Just a little
background.... the whole site had been in cgi flat files when I started
here. I was looking for a technology that would allow me to write the
objects and NEVER invoke CGI.pm... I found it and hopefuly I will be able to
implement this every site I go to.
When I got here there was a huge argument about needing a game engine
and I belive this has been the key... Games are approx. 10 time faster than
before. The games don't break anylonger. All in all a great tool for
advancement.
-- JC Fant IV
=item Cine.gr
=begin html
<a href="http://www.cine.gr"><img src="cine.gr.gif" border=0></a>
=end html
...we ported our biggest yet ASP site from IIS (well, actually rewrote),
Cine.gr and it is a killer site. In some cases, the whole thing got almost 25 (no typo) times faster...
None of this would ever be possible without Apache::ASP (I do not ever want to write ``print "<HTML>\n";''
again).
=head1 RESOURCES
Here are some important resources listed related to
the use of Apache::ASP for publishing web applications.
If you have any more to suggest, please email the Apache::ASP list
at asp[at]perl.apache.org
=head2 Articles
Apache::ASP Introduction ( #1 in 3 part series )
http://www.apache-asp.org/articles/perlmonth1_intro.html
Apache::ASP Site Building ( #2 in 3 part series )
http://www.apache-asp.org/articles/perlmonth2_build.html
Apache::ASP Site Tuning ( #3 in 3 part series )
http://www.apache-asp.org/articles/perlmonth3_tune.html
Embedded Perl ( part of a series on Perl )
http://www.wdvl.com/Authoring/Languages/Perl/PerlfortheWeb/index15.html
=head2 Books
mod_perl "Eagle" Book
http://www.modperl.com
mod_perl Developer's Cookbook
http://www.modperlcookbook.org
Programming the Perl DBI
http://www.oreilly.com/catalog/perldbi/
=head2 Reference Cards
Apache & mod_perl Reference Cards
http://www.refcards.com/
=head2 Web Sites
mod_perl Apache web module
http://perl.apache.org
mod_perl 1.x Guide
http://perl.apache.org/guide/
Perl Programming Language
http://www.perl.com
Apache Web Server
http://www.apache.org
=head1 TODO
There is no specific time frame in which these things will be
implemented. Please let me know if any of these is of particular
interest to you, and I will give it higher priority.
=head2 WILL BE DONE
+ Database storage of $Session & $Application, so web clusters
may scale better than the current NFS/CIFS StateDir implementation
allows, maybe via Apache::Session.
=head1 CHANGES
Apache::ASP has been in development since 1998, and
was production ready since its .02 release. Releases
are always used in a production setting before being
made publically available.
In July 2000, the version numbers of releases went
from .19 to 1.9 which is more relevant to software development
outside the perl community. Where a .10 perl module usually
means first production ready release, this would be the
equivalent of a 1.0 release for other kinds of software.
+ = improvement - = bug fix (d) = documentations
=item $VERSION = 2.63; $DATE="03/14/2018"
+ Added section ``raw'' to MailErrors.inc to debug POSTs without
form fields
- MailErrorsHTML now uses monospaced fonts for errors. Easier on
the eyes and more informative
=item $VERSION = 2.62; $DATE="08/16/2011"
- Fixed 'application/x-www-form-urlencoded' for AJAX POSTs post
Firefox 3.x
+ First sourceforge.net hosted version
+ Incremented version number to actually match SVN branch tag
=item $VERSION = 2.61; $DATE="05/24/2008"
- updated for more recent mod_perl 2 environment to trigger correct loading of modules
+ loads modules in a backwards compatible way for older versions of mod_perl 1.99_07 to 1.99_09
+ license changes from GPL to Perl Artistic License
=item $VERSION = 2.59; $DATE="05/23/2005"
+ added "use bytes" to Response object to calculate Content-Length
correctly for UTF8 data, which should require therefore at least
perl version 5.6 installed
+ updated to work with latest mod_perl 2.0 module naming convention,
thanks to Randy Kobes for patch
+ examples now exclude usage of Apache::Filter & Apache::SSI under mod_perl 2.0
=item $VERSION = 2.57; $DATE="01/29/2004"
- $Server->Transfer will update $0 correctly
- return 0 for mod_perl handler to work with latest mod_perl 2 release
when we were returning 200 ( HTTP_OK ) before
- fixed bug in $Server->URL when called like $Server->URL($url)
without parameters. Its not clear which perl versions this bug
affected.
=item $VERSION = 2.55; $DATE="08/09/2003"
- Bug fixes for running on standalone CGI mode on Win32 submitted
by Francesco Pasqualini
+ Added Apache::ASP::Request::BINMODE for binmode() being
called on STDIN after STDIN is tied to $Request object
+ New RequestBinaryRead configuration created, may be turned off
to prevent $Request object from reading POST data
++ mod_perl 2 optmizations, there was a large code impact on this,
as much code was restructured to reduce the differences between
mod_perl 1 and mod_perl 2, most importantly, Apache::compat is
no longer used
+ preloaded CGI for file uploads in the mod_perl environment
- When XSLT config is set, $Response->Redirect() should work now
Thanks to Marcus Zoller for pointing problem out
+ Added CookieDomain setting, documented, and added test to cover
it in t/cookies.t . Setting suggested by Uwe Riehm, who nicely
submitted some code for this.
=item $VERSION = 2.53; $DATE="04/10/2003"
+ XMLSubs tags with "-" in them will have "-" replaced with "_" or underscore, so a
tag like <my:render-table /> will be translated to &my::render_table() ... tags with
- in them are common in extended XML syntaxes, but perl subs cannot have - in them only.
+ Clean setting now works on output when $Response->{ContentType} begins with text/html;
like "text/html; charset=iso-8859-2" ... before Clean would only work on output marked
with ContentType text/html. Thanks to Szymon Juraszczyk for recommending fix.
--Fixed a bug which would cause Session_OnEnd to be called twice on sessions in a certain case,
particularly when an old expired session gets reused by and web browser... this bug was
a result of a incomplete session cleanup method in this case. Thanks to Oleg Kobyakovskiy
for reporting this bug. Added test in t/session_events.t to cover this problem going forward.
- Compile errors from Apache::ASP->Loader() were not being reported. They will
be reported again now. Thanks to Thanos Chatziathanassiou for discovering and
documenting this bug. Added test in t/load.t to cover this problem going forward.
+ use of chr(hex($1)) to decode URI encoded parameters instead of pack("c",hex($1))
faster & more correct, thanks to Nikolay Melekhin for pointing out this need.
(d) Added old perlmonth.com articles to ./site/articles in distribution
and linked to them from the docs RESOURCES section
(d) Updated documention for the $Application->SessionCount API
+ Scripts with named subroutines, which is warned against in the style guide,
will not be cached to help prevent my closure problems that often
hurt new developers working in mod_perl environments. The downside
is that these script will have a performance penalty having to be
recompiled each invocation, but this will kill many closure caching
bugs that are hard to detect.
- $Request->FileUpload('upload_file', 'BrowserFile') would return
a glob before that would be the file name in scalar form. However
this would be interpreted as a reference incorrectly. The fix
is to make sure this is always a scalar by stringifying
this data internally. Thanks to Richard Curtis for pointing
out this bug.
=item $VERSION = 2.51; $DATE="02/10/2003"
+ added t/session_query_parse.t test to cover use of SessionQueryParse
and $Server->URL APIs
- Fixed duplicate "&" bug associated with using $Server->URL
and SessionQueryParse together
+ Patch to allow $Server->URL() to be called multiple times on the same URL
as in $Server->URL($Server->URL($url, \%params), \%more_params)
(d) Added new testimonials & sites & created a separate testimonials page.
- SessionQueryParse will now add to & to the query strings
embedded in the HTML, instead of & for proper HTML generation.
Thanks to Peter Galbavy for pointing out and Thanos Chatziathanassiou
- Couple of minor bug fixes under PerlWarn use, thanks Peter Galbavy
for reporting.
+ Added automatic load of "use Apache2" for compat with mod_perl2
request objects when Apache::ASP is loaded via "PerlModule Apache::ASP"
Thanks to Richard Curtis for reporting bug & subsequent testing.
- When GlobalPackage config changes, but global.asa has not, global.asa
will be recompiled anyway to update the GlobalPackage correctly.
Changing GlobalPackage before would cause errors if global.asa was
already compiled.
++ For ANY PerlSetVar type config, OFF/Off/off will be assumed
to have value of 0 for that setting. Before, only a couple settings
had this semantics, but they all do now for consistency.
- Fix for InodeNames config on OpenBSD, or any OS that might have
a device # of 0 for the file being stat()'d, thanks to Peter Galbavy
for bug report.
++ Total XSLT speedups, 5-10% on large XSLT, 10-15% on small XSLT
+ bypass meta data check like expires for XSLT Cache() API use
because XSLT tranformations don't expire, saves hit to cache dbm
for meta data
+ use of direct Apache::ASP::State methods like FETCH/STORE
in Cache() layer so we don't have to go through slower tied interface.
This will speed up XSLT & and include output caching mostly.
+ minor optimizations for speed & memory usage
=item $VERSION = 2.49; $DATE="11/10/2002"
-- bug introduced in 2.47 cached script compilations for executing
scripts ( not includes ) of the same name in different directories
for the same Global/GlobalPackage config for an application.
Fix was to remove optimization that caused problem, and
created test case t/same_name.t to cover bug.
=item $VERSION = 2.47; $DATE="11/06/2002"
++ Runtime speed enhancements for 15-20% improvement including:
+ INTERNAL API ReadFile() now returns scalar ref as memory optimization
+ cache InodeNames config setting in ASP object now for common lookups
+ removed CompileChecksum() INTERNAL API, since it was an unnecesary
method decomposition along a common code path
+ removed IsChanged() INTERNAL API since compiling of scripts
is now handled by CompileInclude() which does this functionality already
+ removed unnecessary decomp of IncludesChanged() INTERNAL API, which was along
critical code path
+ do not call INTERNAL SearchDirs() API when compiling base script
since we have already validated its path earlier
+ Use stat(_) type shortcut for stat() & -X calls where possible
+ Moved @INC initilization up to handler() & consolidated with $INCDir lib
+ removed useless Apache::ASP::Collection::DESTROY
+ removed useless Apache::ASP::Server::DESTROY
+ removed useless Apache::ASP::GlobalASA::DESTROY
+ removed useless Apache::ASP::Response::DESTROY
- Default path for $Response->{Cookies} was from CookiePath
config, but this was incorrect as CookiePath config is only
for $Session cookie, so now path for $Response->{Cookies}
defaults to /
- Fixed bug where global.asa events would get undefined with
StatINC and GlobalPackage set when the GlobalPackage library
changed & get reloaded.
(d) Documented long time config NoCache.
-- Fixed use with Apache::Filter, capable as both source
and destination filter. Added ./site/eg/filter.filter example
to demonstrate these abilities.
+ Use $r->err_headers_out->add Apache::Table API for cookies
now instead of $r->cgi_header_out. Added t/cookies.t test to
cover new code path as well as general $Response->Cookies API.
Also make cookies headers sorted by cookie and dictionary key
while building headers for repeatable behavior, this latter was
to facilitate testing.
- fixed $Server->Mail error_log output when failing to connect
to SMTP server.
+ added tests to cover UniquePackages & NoCache configs since this
config logic was updated
+ made deprecated warnings for use of certain $Response->Member
calls more loudly write to error_log, so I can remove the AUTOLOAD
for Response one day
- Probably fixed behavior in CgiHeaders, at least under perl 5.8.0, and
added t/cgi_headers.t to cover this config.
+ removed $Apache::ASP::CompressGzip setting ability, used to possibly
set CompressGzip in the module before, not documented anyway
+ removed $Apache::ASP::Filter setting ability to set Filter globally,
not documented anyway
+ removed old work around for setting ServerStarting to 0
at runtime, which was bad for Apache::DBI on win32 a long
time ago:
$Apache::ServerStarting and $Apache::ServerStarting = 0;
If this code is still needed in Apache::ASP->handler() let
me know.
+ check to make sure data in internal database is a HASH ref
before using it for session garbage collection. This is to
help prevent against internal database corruption in a
network share that does not support flock() file locking.
+ For new XMLSubs ASP type <%= %> argument interpolation
activated with XMLSubsPerlArgs 0, data references can now
be passed in addition to SCALAR/string references, so one
can pass an object reference like so:
<my:tag value="<%= $Object %>" />
This will only work as long as the variable interpolation <%= %>
are flushed against the containing " " or ' ', or else the object
reference will be stringified when it is concatenated with
the rest of the data.
Testing for this feature was added to ./t/xmlsubs_aspargs.t
This feature is still experimental, and its interface may change.
However it is slated for the 3.0 release as default method,
so feedback is appreciated.
+ For new XMLSubs ASP type <%= %> argument interpolation
activated with XMLSubsPerlArgs 0, <% %> will no longer work,
just <%= %>, as in
<my:tag value="some value <%= $value %> more data" />
Like the XSLTCache, it uses MLDBM::Sync::SDBM_File
by default, but can use DB_File or GDBM_File if
CacheDB is set to these.
See t/cache.t for API support until this is documented.
+CacheSize now supports units of M, K, B like
CacheSize 10M
CacheSize 10240K
CacheSize 10000000B
CacheSize 10000000
-Better handling of $Session->Abandon() so multiple
request to the same session while its being destroyed
will have the right effect.
+Optimized XMLSubs parsing. Scripts with lots lof XMLSubs
now parse faster for the first time. One test script with
almost 200 such tags went from a parse time of around 3 seconds
to .7 seconds after optimizations.
+Updated performance tuning docs, particularly for using
Apache::ASP->Loader()
+$Server->URL($url, \%params) now handles array refs
in the params values like
$Server->URL($url, { key => [ qw( value1 value2 ) ] })
This is so that query string data found in
$Request->QueryString that gets parsed into this form
from a string like: ?key=value&key=value2 would be
able to be reused passed back to $Server->URL to
create self referencing URLs more easily.
-Bug fix where XMLSubs like <s:td /> now works on perl
5.005xx, thanks to Philip Mak for reporting & fix.
+When searching for included files, will now join
the absolute path of the directory of the script
with the name of the file if its a relative file
name like ./header.inc. Before, would just look
for something like ././header.inc by using '.'
as the first directory to look for includes in.
The result of this is that scripts in two directories
configured with the same Global setting should be able
to have separate local header.inc files without causing
a cached namespace collision.
+$Server->Config() call will return a hash ref
to all the config setting for that request, like
Apache->dir_config would.
-StatINC setting with Apache::ASP->Loader() works again.
This makes StatINC & StatINCMatch settings viable
for production & development use when the system has
very many modules.
-Cookieless session support with configs like SessionQueryParse
and SessionQuery now work for URLs with frags in them
like http://localhost?arg=value#frag
+@rv = $Response->Include() now works where there are
multiple return values from an include like:
<% return(1,2); %>
=item $VERSION = 2.21; $DATE="8/5/2001";
+Documented RequestParams config in CONFIG misc section.
+Documented new XSLT caching directives.
+Updated ./site/eg/.htaccess XSLT example config
to use XSLTCache setting.
+New FAQ section on why perl variables are sticky globals,
suggested by Mark Seger.
-push Global directory onto @INC during ASP script execution
Protect contents of original @INC with local. This makes
things compatible with .09 Apache::ASP where we always had
Global in @INC. Fixed needed by Henrik Tougaard
- ; is a valid separator like & for QueryString Parameters
Fixed wanted by Anders
-XSMLSubsMatch doc fix in CONFIG section
+Reduces number of Session groups to 16 from 32, so
session manager for small user sets will be that much faster.
+optimizations for internal database, $Application, and $Session
creation.
+XSLTCache must be set for XSLT caching to begin using CacheDir
+CacheDB like StateDB bug sets dbm format for caching, which
defaults to MLDBM::Sync::SDBM_File, which works well for caching
output sizes < 50K
+CacheDir config for XSLT caching ... defaults to StateDir
+CacheSize in bytes determines whether the caches in CacheDir
are deleted at the end of the request. A cache will be
reset in this way back to 0 bytes. Defaults to 10000000 bytes
or about 10M.
+Caching infrastructure work that is being used in XSLT
can be leveraged later for output caching of includes,
or arbitrary user caching.
-t/server_mail.t test now uses valid email for testing
purposes ... doesn't actually send a mail, but for SMTP
runtime validation purposes it should be OK.
+fixed where POST data was read from under MOD_PERL,
harmless bug this was that just generated the wrong
system debugging message.
-XSLTCacheSize config no longer supported. Was a bad
Tie::Cache implementation. Should be file based cache
to greatly increases cache hit ratio.
++$Response->Include(), $Response->TrapInclude(),
and $Server->Execute() will all take a scalar ref
or \'asdfdsafa' type code as their first argument to execute
a raw script instead of a script file name. At this time,
compilation of such a script, will not be cached. It is
compiled/executed as an anonymous subroutine and will be freed
when it goes out of scope.
+ -p argument to cgi/asp script to set GlobalPackage
config for static site builds
-pod commenting fix where windows clients are used for
ASP script generation.
+Some nice performance enhancements, thank to submissions from
Ime Smits. Added some 1-2% per request execution speed.
+Added StateDB MLDBM::Sync::SDBM_File support for faster
$Session + $Application than DB_File, yet still overcomes
SDBM_File's 1024 bytes value limitation. Documented in
StateDB config, and added Makefile.PL entry.
+Removed deprecated MD5 use and replace with Digest::MD5 calls
+PerlSetVar InodeNames 1 config which will compile scripts hashed by
their device & inode identifiers, from a stat($file)[0,1] call.
This allows for script directories, the Global directory,
and IncludesDir directories to be symlinked to without
recompiling identical scripts. Likely only works on Unix
systems. Thanks to Ime Smits for this one.
+Streamlined code internally so that includes & scripts were
compiled by same code. This is a baby step toward fusing
include & script code compilation models, leading to being
able to compile bits of scripts on the fly as ASP subs,
and being able to garbage collect ASP code subroutines.
-removed @_ = () in script compilation which would trigger warnings
under PerlWarn being set, thanks for Carl Lipo for reporting this.
-StatINC/StatINCMatch fix for not undeffing compiled includes
and pages in the GlobalPackage namespace
-Create new HTML::FillInForm object for each FormFill
done, to avoid potential bug with multiple forms filled
by same object. Thanks to Jim Pavlick for the tip.
+Added PREREQ_PM to Makefile.PL, so CPAN installation will
pick up the necessary modules correctly, without having
to use Bundle::Apache::ASP, thanks to Michael Davis.
+ > mode for opening lock files, not >>, since its faster
+$Response->Flush() fixed, by giving $| = 1 perl hint
to $r->print() and the rest of the perl sub.
+$Response->{Cookies}{cookie_name}{Expires} = -86400 * 300;
works so negative relative time may be used to expire cookies.
+Count() + Key() Collection class API implementations
+Added editors/aasp.vim VIM syntax file for Apache::ASP,
courtesy of Jon Topper.
++Better line numbering with #line perl pragma. Especially
helps with inline includes. Lots of work here, & integrated
with Debug 2 runtime pretty print debugging.
+$Response->{Debug} member toggles on/off whether
$Response->Debug() is active, overriding the Debug setting
for this purpose. Documented.
-When Filter is on, Content-Length won't be set and compression
won't be used. These things would not work with a filtering
handler after Apache::ASP
=item $VERSION = 2.09; $DATE="01/30/2001";
+Examples in ./site/eg are now UseStrict friendly.
Also fixed up ./site/eg/ssi_filter.ssi example.
+Auto purge of old stale session group directories, increasing
session manager performance when using Sessions when migrating
to Apache::ASP 2.09+ from older versions.
+SessionQueryParse now works for all $Response->{ContentType}
starting with 'text' ... before just worked with text/html,
now other text formats like wml will work too.
+32 groups instead of 64, better inactive site session group purging.
+Default session-id length back up to 32 hex bytes.
Better security vs. performance, security more important,
especially when performance difference was very little.
+PerlSetVar RequestParams 1 creates $Request->Params
object with combined contents of $Request->QueryString
and $Request->Form
++FormFill feature via HTML::FillInForm. Activate with
$Response->{FormFill} = 1 or PerlSetVar FormFill 1
See site/eg/formfill.asp for example.
++XMLSubs tags of the same name may be embedded in each other
recursively now.
+No umask() use on Win32 as it seems unclear what it would do
+simpler Apache::ASP::State file handle mode of >> when opening
lock file. saves doing a -e $file test.
+AuthServerVariables config to init $Request->ServerVariables
with basic auth data as documented. This used to be default
behavior, but triggers "need AuthName" warnings from recent
versions of Apache when AuthName is not set.
-Renamed Apache::ASP::Loader class to Apache::ASP::Load
-CGI & StatINC or StatINCMatch would have bad results
at times, with StatINC deleting dynamically compiled
CGI subroutines, that were imported into other scripts
and modules namespaces.
A couple tweaks, and now StatINC & CGI play nice again ;)
StatINCMatch should be safe to use in production with CGI.
This affects in particular environments that use file upload,
since CGI is loaded automatically by Apache::ASP to handle
file uploads.
This fix should also affect other seemingly random
times when StatINC or StatINCMatch don't seem to do
the right thing.
+use of ASP objects like $Response are now "use strict"
safe in scripts, while UniquePackages config is set.
+Better handling of "use strict" errors in ASP scripts.
The error is detected, and the developer is pointed to the
Apache error log for the exact error.
The script with "use strict" errors will be recompiled again. Its seems
though that "use strict" will only throw its error once, so that a script
can be recompiled with the same errors, and work w/o any use strict
error messaging.
=item $VERSION = 0.12; $DATE="07/01/1999";
-Compiles are now 10 +times faster for scripts with lots of big
embedded perl blocks <% #perl %>
Compiles were slow because of an old PerlScript compatibility
parsing trick where $Request->QueryString('hi')->{item}
would be parsed to $Request->QueryString('hi') which works.
I think the regexp that I was using had O(n^2) characteristics
and it took a really big perl block to 10 +seconds to parse
to understand there was a problem :(
I doubt anyone needed this compatibility, I don't even see
any code that looks like this in the online PerlScript examples,
so I've commented out this parsing trick for now. If you
need me to bring back this functionality, it will be in the
form of a config setting.
For information on PerlScript compatibility, see the PerlScript
section in the ASP docs.
-Added UniquePackages config option, that if set brings back
the old method of compiling each ASP script into its own
separate package. As of v.10, scripts are compiled by default
into the same package, so that scripts, dynamic includes & global.asa
can share globals. This BROKE scripts in the same ASP Application
that defined the same sub routines, as their subs would redefine
each other.
UniquePackages has scripts compiled into separate perl packages,
so they may define subs with the same name, w/o fear of overlap.
Under this settings, scripts will not be able to share globals.
-Secure field for cookies in $Response->Cookies() must be TRUE to
force cookie to be secure. Before, it just had to be defined,
which gave wrong behavior for Secure => 0.
+$Response->{IsClientConnected} set to one by default. Will
work out a real value when I upgrade to apache 1.3.6. This
value has no meaning before, as apache aborts the perl code
when a client drops its connection in earlier versions.
+better compile time debugging of dynamic includes, with
Debug 2 setting
+"use strict" friendly handling of compiling dynamic includes
with errors
=item $VERSION = 0.11; $DATE="06/24/1999";
+Lots of documentation updates
+The MailHost config option is the smtp server used for
relay emails for the Mail* config options.
+MailAlertTo config option used for sending a short administrative
alert for an internal ASP error, server code 500. This is the
compliment to MailErrorsTo, but is suited for sending a to a
small text based pager. The email sent by MailErrorsTo would
then be checked by the web admin for quick response & debugging
for the incident.
The MailAlertPeriod config specifies the time in minutes during
which only one alert will be sent, which defaults to 20.
+MailErrorsTo config options sends the results of a 500 error
to the email address specified as if Debug were set to 2.
If Debug 2 is set, this config will not be on, as it is
for production use only. Debug settings less than 2 only
log errors to the apache server error log.
-StatINCMatch / StatINC can be used in production and work
even after a server graceful restart, which is essential for
a production server.
-Content-Length header is set again, if BufferingOn is set, and
haven't $Response->Flush()'d. This broke when I introduce
the Script_OnEnd event handler.
+Optimized reloading of the GlobalPackage perl module upon changes,
so that scripts and dynamic includes don't have to be recompiled.
The global.asa will still have to be though. Since we started
compiling all routines into a package that can be named with
GlobalPackage, we've been undeffing compiled scripts and includes
when the real GlobalPackage changed on disk, as we do a full sweep
through the namespace. Now, we skip those subs that we know to
be includes or scripts.
-Using Apache::Symbol::undef() to undefine precompiled scripts
and includes when reloading those scripts. Doing just an undef()
would sometimes result in an "active subroutine undef" error.
This bug came out when I started thrashing the StatINC system
for production use.
+Using pod style commenting no longer confuses the line
numbering. ASP script line numbers are almost exactly match
their compiled perl version, except that normal inline includes
(not dynamic) insert extra text which can confuse line numbering.
If you want perl error line numbers to entirely sync with your
ASP scripts, I would suggest learning how to use dynamic includes,
as opposed to inline includes.
-Wrapped StatINC reloading of libs in an eval, and capturing
error for Debug 2 setting. This makes changing libs with StatINC
on a little more friendly when there are errors.
-$Request->QueryString() now stores multiple values for the
same key, just as $Request->Form() has since v.07. In
wantarray() context like @vals = $Request->QueryString('dupkey'),
@vals will store whatever values where associated with dupkey
in the query string like (1,2) from: ?dupkey=1&dupkey=2
+The GlobalPackage config directive may be defined
to explicitly set the perl module that all scripts and global.asa
are compiled into.
-Dynamic includes may be in the Global directory, just like
normal includes.
+Perl script generated from asp scripts should match line
for line, seen in errors, except when using inline (default)
includes, pod comments, or <% #comment %> perl comments, which
will throw off the line counts by adding text, removing
text, or having an extra newline added, respectively.
-Script_OnEnd may now send output to the browser. Before
$main::Response->End() was being called at the end of the
main script preventing further output.
++All scripts are compiled as routines in a namespace uniquely
defined by the global.asa of the ASP application. Thus,
scripts, includes, and global.asa routines will share
all globals defined in the global.asa namespace. This means
that globals between scripts will be shared, and globals
defined in a global.asa will be available to scripts.
Scripts used to have their own namespace, thus globals
were not shared between them.
+a -o $output_dir switch on the ./cgi/asp script allows
it to execute scripts and write their output to an output
directory. Useful for building static html sites, based on
asp scripts. An example use would be:
asp -b -o out *.asp
Without an output directory, script output is written to STDOUT
=item $VERSION = 0.09; $DATE="04/22/1999";
+Updated Makefile.PL optional modules output for CGI & DB_File
+Improved docs on $Response->Cookies() and $Request->Cookies()
+Added PERFORMANCE doc to main README, and added sub section
on precompiling scripts with Apache::ASP->Loader()
+Naming of CompileIncludes switched over to DynamicIncludes
for greater clarity.
+Dynamic includes can now reference ASP objects like $Session
w/o the $main::* syntax. These subs are no longer anonymous
subs, and are now compiled into the namespace of the global.asa package.
+Apache::ASP->Loader() precompiles dynamic includes too. Making this work
required fixing some subtle bugs / dependencies in the compiling process.
+Added Apache::ASP->Loader() similar to Apache::RegistryLoader for
precompiling ASP scripts. Precompile a whole site at server
startup with one function call.
+Prettied the error messaging with Debug 2.
+$Response->Debug(@args) debugging extension, which
allows a developer to hook into the module's debugging,
and only have @args be written to error_log when Debug is greater
than 0.
-Put write locking code around State writes, like $Session
and $Application. I thought I fixed this bug a while ago.
-API change: converted $Session->Timeout() and $Session->SessionID()
methods into $Session->{Timeout} and $Session->{SessionID} properties.
The use of these properties as methods is deprecated, but
backwards compatibility will remain. Updated ./eg/session.asp
to use these new properties.
+Implemented $Response->{PICS} which if set sends out a PICS-Label
HTTP header, useful for ratings.
+Implemented $Response->{CacheControl} and $Response->{Charset} members.
By default, CacheControl is 'private', and this value gets sent out
every request as HTTP header Cache-Control. Charset appends itself
onto the content type header.
+Implemented $Request->BinaryRead(), $Request->{TotalBytes},
documented them, and updated ./eg/form.asp for an example usage.
+Implemented $Response->BinaryWrite(), documented, and created
and example in ./eg/binary_write.htm
+Implemented $Server->MapPath() and created example of its use
in ./eg/server.htm
-$Request->Form() now reads file uploads correctly with
the latest CGI.pm, where $Request->Form('file_field') returns
the actual file name uploaded, which can be used as a file handle
to read in the data. Before, $Request->Form('file_field') would
return a glob that looks like *Fh::filename, so to get the file
name, you would have to parse it like =~ s/^\*Fh\:\://,
which you no longer have to do. As long as parsing was done as
mentioned, the change should be backwards compatible.
file upload FAQ.
+Reworked ./eg/cgi.htm example to use CGI input routines
after doing a native read of STDIN.
++Added dynamic includes with <!--include file=file args=@args-->
extension. This style of include is compiled as an anonymous sub &
cached, and then executed with @args passed to the subroutine for
execution. This is include may also be rewritten as a new API
extension: $Response->Include('file', @args)
+Added ./eg/compiled_includes.htm example documenting new dynamic includes.
+Documented SSI: native file includes, and the rest with filtering
to Apache::SSI
+Turned the documentation of Filter config to value of Off so
people won't cut and paste the On config by default.
+Added SecureSession config option, which forces session cookie to
be sent only under https secured www page requests.
+Added StateDB config option allows use of DB_File for $Session, since
default use of SDBM_File is limited. See StateDB in README.
+file include syntax w/o quotes supported like <!--#include file=test.inc-->
+Nested includes are supported, with includes including each other.
Recursive includes are detected and errors out when an include has been
included 100 times for a script. Better to quit early than
have a process spin out of control. (PORTABLE ? probably not)
+Allow <!--include file=file.inc--> notation w/o quotes around file names
-PerlSetEnv apache conf setting now get passed through to
$Request->ServerVariables. This update has ServerVariables
getting data from %ENV instead of $r->cgi_env
+README FAQ for PerlHandler errors
=item $VERSION = 0.08; $DATE="02/06/1999";
++SSI with Apache::Filter & Apache::SSI, see config options & ./eg files
Currently filtering only works in the direction Apache::ASP -> Apache::SSI,
will not work the other way around, as SSI must come last in a set of filters
+SSI file includes may reference files in the Global directory, better
code sharing
- <% @array... %> no longer dropped from code.
+perl =pod comments are stripped from script before compiling, and associated
PodComments configuration options.
+Command line cgi/asp script takes various options, and allows execution
of multiple asp scripts at one time. This script should be used for
command line debugging. This is also the beginning of building
a static site from asp scripts with the -b option, suppressing headers.
+$Response->AddHeader('Set-Cookie') works for multiple cookies.
-$Response->Cookies('foo', '0') works, was dropping 0 because of boolean test
-Fixed up some config doc errors.
=item $VERSION = 0.07; $DATE="01/20/1999";
-removed SIG{__WARN__} handler, it was a bad idea.
-fixes file locking on QNX, work around poor flock porting
+removed message about Win32::OLE on UNIX platforms from Makefile.PL
-Better lock garbage collection. Works with StatINC seamlessly.
-Multiple select forms now work in array context with $Response->Form()
@values = $Response->Form('multi');
-Better CGI.pm compatibility with $r->header_out('Content-type'),
improved garbage collection under modperl, esp. w/ file uploads
=item $VERSION = 0.06; $DATE="12/21/1998";
+Application_OnStart & Application_OnEnd event handlers support.
-Compatible with CGI.pm 2.46 headers()
-Compatible with CGI.pm $q = new CGI({}), caveat: does not set params
+use strict; followed by use of objects like $Session is fine.
-Multiple cookies may be set per script execution.
+file upload implemented via CGI.pm
++global.asa implemented with events Session_OnStart and Session_OnEnd
working appropriately.
+StateDir configuration directive implemented.
StateDir allows the session state directory to be specified separately
from the Global directory, useful for operating systems with caching file
systems.
+StateManager config directive. StateManager specifies how frequently
Sessions are cleaned up, with 10 (default) meaning that old Sessions
will be cleaned up 10 times per SessionTimeout period (default 20 minutes).
+$Application->SessionCount() implemented, non-portable method.
: returns the number of currently active sessions
-STOP button fix. Users may hit STOP button during script
execution, and Apache::ASP will cleanup with a routine registered
in Apache's $r->register_cleanup. Works well supposedly.
+PerlScript compatibility work, trying to make ports smoother.
: Collection emulator, no ->{Count} property
: $.*(.*)->{Item} parsed automatically,
shedding the ->{Item} for Collection support (? better way ?)
: No VBScript dates support, just HTTP RFC dates with HTTP::Date
: Win32::OLE::in not supported, just use "keys %{$Collection}"
=item $VERSION = 0.05; $DATE="10/19/1998";
+Added PERFORMANCE doc, which includes benchmarks +hints.
+Better installation warnings and errors for other modules required.
-Turned off StatINC in eg/.htaccess, as not everyone installs Devel::Symdump
-Fixed AUTOLOAD state bug, which wouldn't let you each through state
objects, like %{$Session}, or each %$Session, (bug introduced in v.04)
+Parses ASP white space better. HTML output matches author's intent
by better dealing with white space surrounding <% perl blocks %>
-Scalar insertion code <%=$foo%> can now span many lines.
+Added include.t test script for includes.
+Script recompiles when included files change.
+Files can be included in script with
SSI <!--#include file="filename"--> syntax, needs to be
done in ASP module to allow compilation of included code and html
into script. Future chaining with Apache::SSI will allow static
html includes, and other SSI directives
=item $VERSION = 0.04; $DATE="10/14/1998";
+Example script eg/cgi.htm demonstrating CGI.pm use for output.
+Optimized ASP parsing, faster and more legible executing code
: try 'die();' in code with setting PerlSetVar Debug 2
+Cleaned up code for running with 'use strict'
-Fixed directory handle leak on Solaris, from not closing after opendir()
+StatINC overhaul. StatINC setting now works as it should, with
the caveat that exported functions will not be refreshed.
+NoState setting optimization, disallows $Application & $Session
+$Application->*Lock() functions implemented
-SoftRedirect setting for those who want scripts to keep running
after a Redirect()
+SessionSerialize setting to lock session while script is running
: Microsoft ASP style session locking
: For a session, scripts execute one at a time
: NOT recommended use, please see note.
-MLDBM can be used for other things without messing up internal use
: before if it was used with different DB's and serializers,
internal state could be lost.
--State file locking. Corruption worries, and loss of data no more.
+CGI header support, developer can use CGI.pm for *output*, or just print()
: print "Set-Cookie: test=cookie\n", and things will just work
: use CGI.pm for output
: utilizes $r->send_cgi_header(), thanks Doug!
+Improved Cookie implementation, more flexible and complete
- Domain cookie key now works
: Expire times now taken from time(), and relative time in sec
: Request->Cookies() reading more flexible, with wantarray()
on hash cookie values, %hash = $Request->Cookie('test');
-make test module naming correction, was t.pm, now T.pm for Unix
+POD / README cleanup, formatting and HTML friendly.
=item $VERSION = 0.03; $DATE="09/14/1998";
+Installation 'make test' now works
+ActiveX objects on Win32 implemented with $Server->CreateObject()
+Cookies implemented: $Response->Cookies() & $Request->Cookies()
-Fixed $Response object API, converting some methods to object members.
Deprecated methods, but backwards compatible.
+Improved error messaging, debug output
+$, influences $Response->Write(@strings) behavior
+perl print() works, sending output to $Response object
+$Response->Write() prints scalars, arrays, and hashes. Before only scalars.
+Begin implementation of $Server object.
+Implemented $Response->{Expires} and $Response->{ExpiresAbsolute}
+Added "PerlSetVar StatINC" config option
+$0 is aliased to current script filename
+ASP Objects ($Response, etc.) are set in main package
Thus notation like $main::Response->Write() can be used anywhere.
=item $VERSION = 0.02; $DATE="07/12/1998";
++Session Manager, won't break under denial of service attack
+Fleshed out $Response, $Session objects, almost full implementation.
+Enormously more documentation.
-Fixed error handling with Debug = 2.
-Documentation fixed for pod2man support. README now more man-like.
-Stripped \r\n dos characters from installation files
-755 mode set for session state directory when created
-Loads Win32/OLE properly, won't break with UNIX
=item $VERSION = 0.01; $DATE="06/26/1998";
Syntax Support
--------------
Initial release, could be considered alpha software.
Allows developers to embed perl in html ASP style.
<!-- sample here -->
<html>
<body>
<% for(1..10) { %>
counting: <%=$_%> <br>
<% } %>
</body>
</html>
ASP Objects
( run in 1.063 second using v1.01-cache-2.11-cpan-df04353d9ac )