view release on metacpan or search on metacpan
my $checksum = &md5_hex($key).'x'.length($key);
my $metakey = $checksum . 'xMETA';
my $rv;
eval {
$cache_dbm->{dbm}->Lock;
if(defined $value) {
my $meta = { ServerID => $ServerID, Creation => time() };
if(defined $expires && ($expires =~ /^\-?\d+$/)) {
$meta->{Expires} = $expires;
$meta->{Timeout} = time + $expires;
};
$self->{dbg} && $self->Debug("storing $checksum in $cache_name cache");
$cache_dbm->STORE($metakey, $meta);
$self->{cache_count_store}++;
$rv = $cache_dbm->STORE($checksum, $value);
} else {
# don't check meta data for XSLT since transformations don't expire ever
if($no_check_meta) {
$self->{dbg} && $self->Debug("cache $cache_name fetch checksum $checksum no check meta");
$self->{cache_count_fetch}++;
if(! $meta) {
$meta = { Creation => 0, ServerID => 'NULL' };
$new = 1;
} else {
# NEW EXPIRES FOR EXISTING ITEM
if(defined $expires && ($expires =~ /^\-?\d+$/) && ($expires != $meta->{Expires})) {
$self->Debug("new expires $expires, old ".($meta->{Expires} || '')." for $checksum");
$meta->{Expires} = $expires;
# use creation timestamp for expires calculation, not current
# time, or we would refresh the entry
$meta->{Timeout} = $meta->{Creation} + $expires;
$cache_dbm->STORE($metakey, $meta);
};
}
# LastModified calculations
if(defined $last_modified) {
if($last_modified !~ /^\d+$/) {
my $old_last_modified = $last_modified;
$last_modified = &Apache::ASP::Date::str2time($last_modified);
$self->{dbg} && $self->Debug("converting string date for LastModified $old_last_modified to unix time $last_modified");
}
if($last_modified < 0) {
$self->{dbg} && $self->Debug("negative LastModified $last_modified ignored");
$last_modified = undef;
}
}
# EARLY TIMEOUT CALCULATION
if($meta->{Timeout}) {
# 10% chance to expire early to prevent collision
my $early = ($meta->{Expires} || 0) * rand() * '.1';
$self->{dbg} && $self->Debug("will reduce expires for $meta->{Expires} by random $early seconds, checksum $checksum");
$meta->{Timeout} = $meta->{Timeout} - $early;
}
$self->{dbg} && $self->Debug("meta cache data for checksum $checksum", $meta);
if($new) {
$self->{dbg} && $self->Debug("no cache entry, checksum $checksum");
$self->{cache_count_miss}++;
$rv = undef;
} elsif(defined $meta->{ServerID} && ($$ ne $ServerPID) && ($meta->{ServerID} ne $ServerID)) {
# can only run like this when running in preloaded mod_perl mode
# This will allow for caching in other modes that simply does not reset
# upon server restart
$self->{dbg} && $self->Debug("cache expires new server $ServerID, was $meta->{ServerID}");
$self->{cache_count_restart}++;
$rv = undef;
} elsif($meta->{Timeout} && ($meta->{Timeout} <= time())) {
$self->{dbg} && $self->Debug("cache expires timeout $meta->{Timeout}, checksum $checksum, time ".time);
$self->{cache_count_expires}++;
$rv = undef;
} elsif(defined($last_modified) && ($last_modified >= $meta->{Creation})) {
$self->{dbg} && $self->Debug("cache expires, checksum $checksum, LastModified $last_modified, Creation $meta->{Creation}");
$self->{cache_count_last_modified_expires}++;
$rv = undef;
} else {
$self->{dbg} && $self->Debug("cache $cache_name fetch checksum $checksum");
$self->{cache_count_fetch}++;
$rv = $cache_dbm->{dbm}->FETCH($checksum);
# in case of system level debugging, mark Net::SMTP debug also
if((&config($self, 'Debug') || 0) < 0) {
$args{Debug} = 1;
}
}
# connect to server
{
local $SIG{__WARN__} = sub { $self->Debug('Net::SMTP->new() warning', @_) };
if($mail->{Test}) {
$args{Timeout} = 5;
}
$smtp = Net::SMTP->new(%args);
}
unless($smtp) {
$self->Out("[ERROR] can't connect to SMTP server with args ", \%args);
return 0;
} else {
$self->Debug("connected to SMTP server with args ", \%args);
}
The reason for this config option is to allow operating systems with caching
file systems like Solaris to specify a state directory separately
from the Global directory, which contains more permanent files.
This way one may point StateDir to /tmp/myaspapp, and make one's ASP
application scream with speed.
PerlSetVar StateDir ./.state
=item StateManager
default 10, this number specifies the numbers of times per SessionTimeout
that timed out sessions are garbage collected. The bigger the number,
the slower your system, but the more precise Session_OnEnd's will be
run from global.asa, which occur when a timed out session is cleaned up,
and the better able to withstand Session guessing hacking attempts.
The lower the number, the faster a normal system will run.
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
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
Triggered by a user session ending, Session_OnEnd can be useful
for cleaning up and analyzing user data accumulated during a session.
Sessions end when the session timeout expires, and the StateManager
performs session cleanup. The timing of the Session_OnEnd does not
occur immediately after the session times out, but when the first
script runs after the session expires, and the StateManager allows
for that session to be cleaned up.
So on a busy site with default SessionTimeout (20 minutes) and
StateManager (10 times) settings, the Session_OnEnd for a particular
session should be run near 22 minutes past the last activity that Session saw.
A site infrequently visited will only have the Session_OnEnd run
when a subsequent visit occurs, and theoretically the last session
of an application ever run will never have its Session_OnEnd run.
Thus I would not put anything mission-critical in the Session_OnEnd,
just stuff that would be nice to run whenever it gets run.
=head2 Script_OnFlush
=item $Session->{LCID}
Not implemented. May never be until someone needs it.
=item $Session->{SessionID}
SessionID property, returns the id for the current session,
which is exchanged between the client and the server as a cookie.
=item $Session->{Timeout} [= $minutes]
Timeout property, if minutes is being assigned, sets this
default timeout for the user session, else returns
the current session timeout.
If a user session is inactive for the full
timeout, the session is destroyed by the system.
No one can access the session after it times out, and the system
garbage collects it eventually.
=item $Session->Abandon()
=head2 $Server Object
The server object is that object that handles everything the other
objects do not. The best part of the server object for Win32 users is
the CreateObject method which allows developers to create instances of
ActiveX components, like the ADO component.
=over
=item $Server->{ScriptTimeout} = $seconds
Not implemented. May never be. Please see the
Apache Timeout configuration option, normally in httpd.conf.
=item $Server->Config($setting)
API extension. Allows a developer to read the CONFIG
settings, like Global, GlobalPackage, StateDir, etc.
Currently implemented as a wrapper around
Apache->dir_config($setting)
May also be invoked as $Server->Config(), which will
on a simple hello world benchmark on a WinNT PII300.
++Better SessionManagement, more aware of server farms that
don't have reliable NFS locking. The key here is to have only
one process on one server in charge of session garbage collection
at any one time, and try to create this situation with a snazzy
CleanupMaster routine. This is done by having a process register
itself in the internal database with a server key created at
apache start time. If this key gets stale, another process can
become the master, and this period will not exceed the period
SessionTimeout / StateManager.
** Work on session manager sponsored by LRN, http://www.lrn.com. **
** This work was used to deploy a server farm in production with **
** NFS mounted StateDir. Thanks to Craig Samuel for his belief in **
** open source. :) **
Future work for server farm capabilities might include breaking
up the internal database into one of 256 internal databases
hashed by the first 2 chars of the session id. Also on the plate
is Apache::Session like abilities with locking and/or data storage
+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
++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
-----------
$Session, $Application, $Response, $Request objects available
for use in asp pages.
$Session & $Application data is preserved using SDBM files.
$Session id's are tracked through the use of cookies.
Security
--------
Timeouts any attempt to use a session id that doesn't already
exist. Should stop hackers, since there is no wire speed guessing
cookies.
=head1 LICENSE
Copyright (c) 1998-2018, Josh Chamas
All rights reserved. This program is free software; you can
redistribute it and/or modify it under the same terms as Perl itself.
The reason for this config option is to allow operating systems with
caching file systems like Solaris to specify a state directory
separately from the Global directory, which contains more permanent
files. This way one may point StateDir to /tmp/myaspapp, and make one's
ASP application scream with speed.
PerlSetVar StateDir ./.state
StateManager
default 10, this number specifies the numbers of times per
SessionTimeout that timed out sessions are garbage collected. The bigger
the number, the slower your system, but the more precise Session_OnEnd's
will be run from global.asa, which occur when a timed out session is
cleaned up, and the better able to withstand Session guessing hacking
attempts. The lower the number, the faster a normal system will run.
The defaults of 20 minutes for SessionTimeout and 10 times for
StateManager, has dead Sessions being cleaned up every 2 minutes.
PerlSetVar StateManager 10
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.
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
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
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
HTTPOnlySession
default 0. Sets HttpOnly flag to session cookie to mitigate XSS attacks.
Session_OnEnd
Triggered by a user session ending, Session_OnEnd can be useful for cleaning
up and analyzing user data accumulated during a session.
Sessions end when the session timeout expires, and the StateManager performs
session cleanup. The timing of the Session_OnEnd does not occur immediately
after the session times out, but when the first script runs after the
session expires, and the StateManager allows for that session to be cleaned
up.
So on a busy site with default SessionTimeout (20 minutes) and StateManager
(10 times) settings, the Session_OnEnd for a particular session should be
run near 22 minutes past the last activity that Session saw. A site
infrequently visited will only have the Session_OnEnd run when a subsequent
visit occurs, and theoretically the last session of an application ever run
will never have its Session_OnEnd run.
Thus I would not put anything mission-critical in the Session_OnEnd, just
stuff that would be nice to run whenever it gets run.
Script_OnFlush
$Session->{CodePage}
Not implemented. May never be until someone needs it.
$Session->{LCID}
Not implemented. May never be until someone needs it.
$Session->{SessionID}
SessionID property, returns the id for the current session, which is
exchanged between the client and the server as a cookie.
$Session->{Timeout} [= $minutes]
Timeout property, if minutes is being assigned, sets this default
timeout for the user session, else returns the current session timeout.
If a user session is inactive for the full timeout, the session is
destroyed by the system. No one can access the session after it times
out, and the system garbage collects it eventually.
$Session->Abandon()
The abandon method times out the session immediately. All Session data
is cleared in the process, just as when any session times out.
object model, but is implemented here because it is useful. In
particular, when accessing databases with license requirements, one can
monitor usage effectively through accessing this value.
$Server Object
The server object is that object that handles everything the other objects
do not. The best part of the server object for Win32 users is the
CreateObject method which allows developers to create instances of ActiveX
components, like the ADO component.
$Server->{ScriptTimeout} = $seconds
Not implemented. May never be. Please see the Apache Timeout
configuration option, normally in httpd.conf.
$Server->Config($setting)
API extension. Allows a developer to read the CONFIG settings, like
Global, GlobalPackage, StateDir, etc. Currently implemented as a wrapper
around
Apache->dir_config($setting)
May also be invoked as $Server->Config(), which will return a hash ref
on a simple hello world benchmark on a WinNT PII300.
++Better SessionManagement, more aware of server farms that
don't have reliable NFS locking. The key here is to have only
one process on one server in charge of session garbage collection
at any one time, and try to create this situation with a snazzy
CleanupMaster routine. This is done by having a process register
itself in the internal database with a server key created at
apache start time. If this key gets stale, another process can
become the master, and this period will not exceed the period
SessionTimeout / StateManager.
** Work on session manager sponsored by LRN, http://www.lrn.com. **
** This work was used to deploy a server farm in production with **
** NFS mounted StateDir. Thanks to Craig Samuel for his belief in **
** open source. :) **
Future work for server farm capabilities might include breaking
up the internal database into one of 256 internal databases
hashed by the first 2 chars of the session id. Also on the plate
is Apache::Session like abilities with locking and/or data storage
+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
++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
-----------
$Session, $Application, $Response, $Request objects available
for use in asp pages.
$Session & $Application data is preserved using SDBM files.
$Session id's are tracked through the use of cookies.
Security
--------
Timeouts any attempt to use a session id that doesn't already
exist. Should stop hackers, since there is no wire speed guessing
cookies.
LICENSE
Copyright (c) 1998-2018, Josh Chamas
All rights reserved. This program is free software; you can redistribute it
and/or modify it under the same terms as Perl itself.
Apache::ASP is a perl native port of Active Server Pages for Apache and
lib/Apache/ASP/Session.pm view on Meta::CPAN
my($self, $index) = @_;
# putting these comparisons in a regexp was a little
# slower than keeping them in these 'eq' statements
if($index eq '_SELF') {
$self;
} elsif($index eq '_STATE') {
$self->{state};
} elsif($index eq 'SessionID') {
$self->{id};
} elsif($index eq 'Timeout') {
$self->Timeout();
} else {
$self->{state}->FETCH($index);
}
}
sub STORE {
my($self, $index, $value) = @_;
if($index eq 'Timeout') {
$self->Timeout($value);
} else {
$self->{state}->STORE($index, $value);
}
}
# firstkey and nextkey skip the _UA key so the user
# we need to keep the ua info in the session db itself,
# so we are not dependent on writes going through to Internal
# for this very critical informatioh. _UA is used for security
# validation / the user's user agent.
lib/Apache/ASP/Session.pm view on Meta::CPAN
my $rv = $state->CLEAR();
$ua && $state->STORE('_UA', $ua);
$rv;
}
sub SessionID {
my $self = shift;
tied(%$self)->{id};
}
sub Timeout {
my($self, $minutes) = @_;
if(tied(%$self)) {
$self = tied(%$self);
}
if($minutes) {
$self->{asp}{Internal}->LOCK;
my($internal_session) = $self->{asp}{Internal}{$self->{id}};
$internal_session->{refresh_timeout} = $minutes * 60;
lib/Apache/ASP/Session.pm view on Meta::CPAN
$self->{asp}{Internal}{$self->{id}} = $internal_session;
$self->{asp}{Internal}->UNLOCK;
} else {
my($refresh) = $self->{asp}{Internal}{$self->{id}}{refresh_timeout};
$refresh ||= $self->{asp}{session_timeout};
$refresh / 60;
}
}
sub Abandon {
shift->Timeout(-1);
}
sub TTL {
my $self = shift;
$self = tied(%$self);
# time to live is current timeout - time... positive means
# session is still active, returns ttl in seconds
my $timeout = $self->{asp}{Internal}{$self->{id}}{timeout};
my $ttl = $timeout - time();
}
lib/Apache/ASP/StateManager.pm view on Meta::CPAN
package Apache::ASP;
# quickly decomped out of Apache::ASP so we could load the routines only
# when we are managing State objects
use Apache::ASP::State;
use strict;
use vars qw(
$CleanupGroups
$SessionIDLength $SessionTimeout $StateManager
$DefaultStateDB $DefaultStateSerializer
);
$SessionTimeout = 20;
$StateManager = 10;
# Some OS's have hashed directory lookups up to 16 bytes, so we leave room
# for .lock extension ... nevermind, security is more important, back to 32
# $SessionIDLength = 11;
$SessionIDLength = 32;
$DefaultStateDB = 'SDBM_File';
$DefaultStateSerializer = 'Data::Dumper';
sub InitState {
lib/Apache/ASP/StateManager.pm view on Meta::CPAN
$self->{session_url_parse_match} = &config($self, 'SessionQueryParseMatch');
$self->{session_url_parse} = $self->{session_url_parse_match} || &config($self, 'SessionQueryParse');
$self->{session_url_match} = $self->{session_url_parse_match} || &config($self, 'SessionQueryMatch');
$self->{session_url} = $self->{session_url_parse} || $self->{session_url_match} || &config($self, 'SessionQuery');
$self->{session_url_force} = &config($self, 'SessionQueryForce');
$self->{session_serialize} = &config($self, 'SessionSerialize');
$self->{secure_session} = &config($self, 'SecureSession');
$self->{http_only_session} = &config($self, 'HTTPOnlySession');
# session timeout in seconds since that is what we work with internally
$self->{session_timeout} = &config($self, 'SessionTimeout', undef, $SessionTimeout) * 60;
$self->{'ua'} = $self->{headers_in}->get('User-Agent') || 'UNKNOWN UA';
# refresh group by some increment smaller than session timeout
# to withstand DoS, bruteforce guessing attacks
# defaults to checking the group once every 2 minutes
$self->{group_refresh} = int($self->{session_timeout} / $self->{state_manager});
# Session state is dependent on internal state
# load at runtime for CGI environments, preloaded for mod_perl
require Apache::ASP::Session;
lib/Apache/ASP/StateManager.pm view on Meta::CPAN
$self->{Response}->IsClientConnected();
# POSTPOSE STATE EVENTS, so we can delay the Response object creation
# until after the state objects are created
if($session) {
my $last_session_timeout;
if($session->Started()) {
# we only want one process purging at a time
if($self->{app_state}) {
$internal->LOCK();
if(($last_session_timeout = $internal->{LastSessionTimeout} || 0) < time()) {
$internal->{'LastSessionTimeout'} = $self->{session_timeout} + time;
$internal->UNLOCK();
$self->{Application}->Lock;
my $obj = tied(%{$self->{Application}});
if($self->CleanupGroups('PURGE')) {
$last_session_timeout && $global_asa->ApplicationOnEnd();
$global_asa->ApplicationOnStart();
}
$self->{Application}->UnLock;
}
$internal->UNLOCK();
}
$global_asa->SessionOnStart();
}
if($self->{app_state}) {
# The last session timeout should only be updated every group_refresh period
# another optimization, rand() so not all at once either
$internal->LOCK();
$last_session_timeout ||= $internal->{'LastSessionTimeout'};
if($last_session_timeout < $self->{session_timeout} + time +
(rand() * $self->{group_refresh} / 2))
{
$self->{dbg} && $self->Debug("updating LastSessionTimeout from $last_session_timeout");
$internal->{'LastSessionTimeout'} =
$self->{session_timeout} + time() + $self->{group_refresh};
}
$internal->UNLOCK();
}
}
$self;
}
# Cleanup a state group, by default the group of the current session
site/apps/bookmarks/.htaccess view on Meta::CPAN
DirectoryIndex index.asp
<Files ~ \.asp$>
SetHandler perl-script
PerlHandler Apache::ASP
PerlSetVar Global .
PerlSetVar GlobalPackage My::Bookmarks
PerlSetVar StateDir /tmp/asp_apps_bookmarks
PerlSetVar Debug 2
PerlSetVar SessionTimeout 15
PerlSetVar StatScripts On
PerlSetVar AllowApplicationState On
PerlSetVar AllowSessionState On
PerlSetVar TimeHiRes On
</Files>
site/articles/perlmonth1_intro.html view on Meta::CPAN
set of objects and events, my favorite being $Session, which was one of ASP's
key selling points for me. $Session is ASP's answer to the problem of HTTP being a
stateless protocol. By using temporary session cookies, each web user
has a unique $Session in which you may store data, and that follows them from
script to script. Because the data storage
for $Session is handled on the server, you do not have to worry about
size limits of cookies as an alternate mechanism of storing user session data.
<p>
There are some very useful events as well. Let's say that you are
using <tt>$Session->{login}</tt> to control a user account login and logout. Because
$Session automatically times out every SessionTimeout, if a user
walks away from her/his computer for SessionTimeout minutes, the
<tt>$Session->{login}</tt> is destroyed along with the rest of the data stored in
$Session, and the next person that uses the computer will find themselves
automatically logged out from the account. This is a huge security win if
you maintain a set of accounts at your web site that hold sensitive information like
credit card numbers.
<p>
Here is a basic listing of the built-in <a href=http://www.apache-asp.org/objects.html>objects</a>
available to the developer within every <a href=http://www.apache-asp.org>Apache::ASP</a>
script:
<pre>
site/articles/perlmonth2_build.html view on Meta::CPAN
first user's bookmarks.
<p>
<h3>Specification</h3>
Often times, there is a specification round that we
must do to pick our web application environment and
hardware, as well as supported client software, but this is a no
brainer here. We are choosing Apache::ASP because of its built
in <tt>$Session</tt> which make user logins easy, and its built
in event <tt>Session_OnEnd</tt> which will automatically destroy
the contents of <tt>$Session</tt> every <tt>SessionTimeout</tt>, which
defaults to 20 minutes.
<p>
Also, because our web application has more than one page, we
will make use of the same headers and footers for each
page, using the includes <tt><!--#include file=src.inc--></tt>
functionality to modularize the html.
<h3>Design</h3>
Before we start coding, let's take a minute to diagram
what pages and actions our MyBookmarks web application
site/articles/perlmonth2_build.html view on Meta::CPAN
<tr bgcolor=gray><td><font color=white><b># .htaccess</b></td></tr>
<tr bgcolor=#c0c0c0><td><pre>
<tt>DirectoryIndex index.asp
<Files ~ \.asp$>
SetHandler perl-script
PerlHandler Apache::ASP
PerlSetVar Global .
PerlSetVar GlobalPackage My::Bookmarks
PerlSetVar StateDir /tmp/asp_apps_bookmarks
PerlSetVar Debug 2
PerlSetVar SessionTimeout 15
PerlSetVar StatScripts 1
PerlSetVar AllowApplicationState 1
PerlSetVar AllowSessionState 1
</Files></tt></pre></td></tr>
</table>
</center>
<p>
<p>
site/articles/perlmonth3_tune.html view on Meta::CPAN
<td bgcolor=#c0c0c0>My::Bookmarks</td>
</tr>
<tr>
<td bgcolor=#c0c0c0>SessionSerialize</td>
<td bgcolor=#c0c0c0>0</td>
<td bgcolor=#c0c0c0>0</td>
</tr>
<tr>
<td bgcolor=#c0c0c0>SessionTimeout</td>
<td bgcolor=#c0c0c0>15</td>
<td bgcolor=#c0c0c0>15</td>
</tr>
<tr>
<td bgcolor=pink>StateDir</td>
<td bgcolor=pink>.state</td>
<td bgcolor=pink>/tmp/bookmarks</td>
</tr>
site/articles/perlmonth3_tune.html view on Meta::CPAN
<td bgcolor=#c0c0c0>My::Bookmarks</td>
</tr>
<tr>
<td bgcolor=#c0c0c0>SessionSerialize</td>
<td bgcolor=#c0c0c0>0</td>
<td bgcolor=#c0c0c0>0</td>
</tr>
<tr>
<td bgcolor=#c0c0c0>SessionTimeout</td>
<td bgcolor=#c0c0c0>15</td>
<td bgcolor=#c0c0c0>15</td>
</tr>
<tr>
<td bgcolor=#c0c0c0>StateDir</td>
<td bgcolor=#c0c0c0>/tmp/bookmarks</td>
<td bgcolor=#c0c0c0>/tmp/bookmarks</td>
</tr>
site/articles/perlmonth3_tune.html view on Meta::CPAN
<td bgcolor=#c0c0c0>My::Bookmarks</td>
</tr>
<tr>
<td bgcolor=#c0c0c0>SessionSerialize</td>
<td bgcolor=#c0c0c0>0</td>
<td bgcolor=#c0c0c0>0</td>
</tr>
<tr>
<td bgcolor=#c0c0c0>SessionTimeout</td>
<td bgcolor=#c0c0c0>15</td>
<td bgcolor=#c0c0c0>15</td>
</tr>
<tr>
<td bgcolor=#c0c0c0>StateDir</td>
<td bgcolor=#c0c0c0>/tmp/bookmarks</td>
<td bgcolor=#c0c0c0>/tmp/bookmarks</td>
</tr>
site/articles/perlmonth3_tune.html view on Meta::CPAN
<td bgcolor=#c0c0c0>My::Bookmarks</td>
</tr>
<tr>
<td bgcolor=#c0c0c0>SessionSerialize</td>
<td bgcolor=#c0c0c0>0</td>
<td bgcolor=#c0c0c0>0</td>
</tr>
<tr>
<td bgcolor=#c0c0c0>SessionTimeout</td>
<td bgcolor=#c0c0c0>15</td>
<td bgcolor=#c0c0c0>15</td>
</tr>
<tr>
<td bgcolor=#c0c0c0>StateDir</td>
<td bgcolor=#c0c0c0>/tmp/bookmarks</td>
<td bgcolor=#c0c0c0>/tmp/bookmarks</td>
</tr>
site/articles/perlmonth3_tune.html view on Meta::CPAN
<td bgcolor=#c0c0c0>My::Bookmarks</td>
</tr>
<tr>
<td bgcolor=pink>SessionSerialize</td>
<td bgcolor=pink>0</td>
<td bgcolor=pink>1</td>
</tr>
<tr>
<td bgcolor=#c0c0c0>SessionTimeout</td>
<td bgcolor=#c0c0c0>15</td>
<td bgcolor=#c0c0c0>15</td>
</tr>
<tr>
<td bgcolor=#c0c0c0>StateDir</td>
<td bgcolor=#c0c0c0>/tmp/bookmarks</td>
<td bgcolor=#c0c0c0>/tmp/bookmarks</td>
</tr>
site/articles/perlmonth3_tune.html view on Meta::CPAN
<td bgcolor=#c0c0c0>My::Bookmarks</td>
</tr>
<tr>
<td bgcolor=pink>SessionSerialize</td>
<td bgcolor=pink>0</td>
<td bgcolor=pink>1</td>
</tr>
<tr>
<td bgcolor=#c0c0c0>SessionTimeout</td>
<td bgcolor=#c0c0c0>15</td>
<td bgcolor=#c0c0c0>15</td>
</tr>
<tr>
<td bgcolor=pink>StateDir</td>
<td bgcolor=pink>.state</td>
<td bgcolor=pink>/tmp/bookmarks</td>
</tr>
site/changes.html view on Meta::CPAN
on a simple hello world benchmark on a WinNT PII300.
++Better SessionManagement, more aware of server farms that
don't have reliable NFS locking. The key here is to have only
one process on one server in charge of session garbage collection
at any one time, and try to create this situation with a snazzy
CleanupMaster routine. This is done by having a process register
itself in the internal database with a server key created at
apache start time. If this key gets stale, another process can
become the master, and this period will not exceed the period
SessionTimeout / StateManager.
** Work on session manager sponsored by LRN, <a href=http://www.lrn.com>http://www.lrn.com</a>. **
** This work was used to deploy a server farm in production with **
** NFS mounted StateDir. Thanks to Craig Samuel for his belief in **
** open source. :) **
Future work for server farm capabilities might include breaking
up the internal database into one of 256 internal databases
hashed by the first 2 chars of the session id. Also on the plate
is Apache::Session like abilities with locking and/or data storage
site/changes.html view on Meta::CPAN
+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
site/changes.html view on Meta::CPAN
++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
site/changes.html view on Meta::CPAN
-----------
$Session, $Application, $Response, $Request objects available
for use in asp pages.
$Session & $Application data is preserved using SDBM files.
$Session id's are tracked through the use of cookies.
Security
--------
Timeouts any attempt to use a session id that doesn't already
exist. Should stop hackers, since there is no wire speed guessing
cookies.
</pre></font>
</font>
</td>
<td bgcolor=white valign=top>
site/config.html view on Meta::CPAN
<a href=#StatINC>StatINC</a>
</font>
</td>
</tr>
<tr>
<td valign=top >
<font face="lucida console" size=-1>
<a href=#SessionTimeo21fc354e>SessionTimeout</a>
</font>
</td>
<td valign=top >
<font face="lucida console" size=-1>
<a href=#StatINCMatch>StatINCMatch</a>
</font>
</td>
</tr>
site/config.html view on Meta::CPAN
This way one may point StateDir to /tmp/myaspapp, and make one's ASP
application scream with speed.
<font face="courier new" size=3><pre>
PerlSetVar StateDir ./.state
</pre></font>
<p>
<a name=StateManager></a>
<font face=verdana><font class=title size=-1 color=#555555><b>StateManager</b></font>
<font face="courier new" size=3><pre>
</pre></font>default 10, this number specifies the numbers of times per SessionTimeout
that timed out sessions are garbage collected. The bigger the number,
the slower your system, but the more precise Session_OnEnd's will be
run from global.asa, which occur when a timed out session is cleaned up,
and the better able to withstand Session guessing hacking attempts.
The lower the number, the faster a normal system will run.
<font face="courier new" size=3><pre>
</pre></font>The defaults of 20 minutes for SessionTimeout and 10 times for
StateManager, has dead Sessions being cleaned up every 2 minutes.
<font face="courier new" size=3><pre>
PerlSetVar StateManager 10
</pre></font>
<p>
<a name=StateDB></a>
<font face=verdana><font class=title size=-1 color=#555555><b>StateDB</b></font>
<font face="courier new" size=3><pre>
</pre></font>default SDBM_File, this is the internal database used for state
site/config.html view on Meta::CPAN
across web sites. Whatever this is set to, that will add a
<font face="courier new" size=3><pre>
; domain=$CookieDomain
</pre></font>part to the Set-Cookie: header set for the session-id cookie.
<font face="courier new" size=3><pre>
PerlSetVar CookieDomain .your.global.domain
</pre></font>
<p>
<a name=SessionTimeo21fc354e></a>
<font face=verdana><font class=title size=-1 color=#555555><b>SessionTimeout</b></font>
<font face="courier new" size=3><pre>
</pre></font>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.
<font face="courier new" size=3><pre>
PerlSetVar SessionTimeout 20
</pre></font>
<p>
<a name=SecureSessio77114c01></a>
<font face=verdana><font class=title size=-1 color=#555555><b>SecureSession</b></font>
<font face="courier new" size=3><pre>
</pre></font>default 0. Sets the secure tag for the session cookie, so that the cookie
will only be transmitted by the browser under https transmissions.
<font face="courier new" size=3><pre>
PerlSetVar SecureSession 1
site/eg/.htaccess view on Meta::CPAN
PerlSetVar CompressGzip 0
PerlSetVar UseStrict 1
#PerlSetVar CacheDB DB_File
PerlSetVar CacheDB MLDBM::Sync::SDBM_File
# .asp files for Session state enabled
<Files ~ (\.asp)>
SetHandler perl-script
PerlHandler Apache::ASP
PerlSetVar CookiePath /
PerlSetVar SessionTimeout 5
PerlSetVar RegisterIncludes 1
PerlSetVar XMLSubsMatch my:\w+
PerlSetVar AllowApplicationState 1
PerlSetVar AllowSessionState 1
# PerlSetVar StateSerializer Storable
# PerlSetVar StateDB DB_File
# PerlSetVar StatScripts 0
</Files>
# .htm files for the ASP parsing, but not the $Session object
site/eg/.htaccess view on Meta::CPAN
SetHandler perl-script
PerlHandler Apache::ASP Apache::ASP
PerlSetVar Global .
PerlSetVar Filter On
</Files>
<Files ~ (session_query_parse.asp$)>
SetHandler perl-script
PerlHandler Apache::ASP
PerlSetVar CookiePath /
PerlSetVar SessionTimeout 1
PerlSetVar SessionQueryParseMatch ^http://localhost
</Files>
<Files ~ (xml_subs_strict\.asp)>
SetHandler perl-script
PerlHandler Apache::ASP
PerlSetVar CookiePath /
PerlSetVar SessionTimeout 5
PerlSetVar RegisterIncludes 1
PerlSetVar XMLSubsMatch my:\w+
PerlSetVar XMLSubsStrict 1
</Files>
site/eg/session.asp view on Meta::CPAN
#!/usr/bin/perl /usr/bin/asp-perl
<%
my $form = $Request->Form();
# process form here
if($form->{increment}) {
$Session->{Count}++;
} elsif($form->{timeout}) {
$Session->Timeout(.25);
} elsif($form->{abandon}) {
$Session->Abandon();
}
my @rows = (
'$Session->{Count}',
'$Session->{Timeout}',
'$Session->{SessionID}'
);
%>
<!--#include file=header.inc-->
This file demonstrates the use of the $Session object, as well
as one implementantion of cookieless sessions involving the
use of the SessionQuery setting, and the <nobr>$Server->URL($url, \%params)</nobr>
method to add session ids to the form query string.
<p>
To demo the cookieless sessions, just turn off your cookies
and use this form.
<p>
<center>
<table border=1>
<tr><td colspan=2 align=center><b>Session Object Demonstration</b></td></tr>
<form action=<%=$Server->URL($demo->{file})%> method=POST>
<tr>
<td colspan=2 align=center>
<input type=submit name=increment value="Increment Count">
<input type=submit name=timeout value="Timeout 15 Seconds">
<input type=submit name=abandon value="Abandon">
<td>
</tr>
</form>
<% for (@rows){ %>
<tr>
<td><tt><%=$Server->HTMLEncode($_)%></tt></td>
<td><%=eval($_) || $@%></td>
</tr>
<% } %>
site/events.html view on Meta::CPAN
<font face="courier new" size=3><pre>
</pre></font>Triggered by a user session ending, Session_OnEnd can be useful
for cleaning up and analyzing user data accumulated during a session.
<font face="courier new" size=3><pre>
</pre></font>Sessions end when the session timeout expires, and the StateManager
performs session cleanup. The timing of the Session_OnEnd does not
occur immediately after the session times out, but when the first
script runs after the session expires, and the StateManager allows
for that session to be cleaned up.
<font face="courier new" size=3><pre>
</pre></font>So on a busy site with default SessionTimeout (20 minutes) and
StateManager (10 times) settings, the Session_OnEnd for a particular
session should be run near 22 minutes past the last activity that Session saw.
A site infrequently visited will only have the Session_OnEnd run
when a subsequent visit occurs, and theoretically the last session
of an application ever run will never have its Session_OnEnd run.
<font face="courier new" size=3><pre>
</pre></font>Thus I would not put anything mission-critical in the Session_OnEnd,
just stuff that would be nice to run whenever it gets run.</font>
<p>
site/objects.html view on Meta::CPAN
<a href=#%24Request-%3E%7BM81641f4a>$Request->{Method}</a>
</font>
</td>
</tr>
<tr>
<td valign=top >
<font face="lucida console" size=-1>
<a href=#%24Session-%3E%7BTf539b225>$Session->{Timeout} [= $minutes]</a>
</font>
</td>
<td valign=top >
<font face="lucida console" size=-1>
<a href=#%24Request-%3E%7BT6acbcf5a>$Request->{TotalBytes}</a>
</font>
</td>
</tr>
site/objects.html view on Meta::CPAN
<tr>
<td valign=top >
<font face="lucida console" size=-1>
<a href=#%24Response-%3E%7Bc48a3e9e>$Response->{PICS}</a>
</font>
</td>
<td valign=top >
<font face="lucida console" size=-1>
<a href=#%24Server-%3E%7BSc74a89b4a>$Server->{ScriptTimeout} = $seconds</a>
</font>
</td>
</tr>
<tr>
<td valign=top >
<font face="lucida console" size=-1>
<a href=#%24Response-%3E%7B7098f2f6>$Response->{Status} = $status</a>
site/objects.html view on Meta::CPAN
<p>
<a name=%24Session-%3E%7BS1049f4e8></a>
<font face=verdana><font class=title size=-1 color=#555555><b>$Session->{SessionID}</b></font>
<font face="courier new" size=3><pre>
</pre></font>SessionID property, returns the id for the current session,
which is exchanged between the client and the server as a cookie.</font>
<p>
<a name=%24Session-%3E%7BTf539b225></a>
<font face=verdana><font class=title size=-1 color=#555555><b>$Session->{Timeout} [= $minutes]</b></font>
<font face="courier new" size=3><pre>
</pre></font>Timeout property, if minutes is being assigned, sets this
default timeout for the user session, else returns
the current session timeout.
<font face="courier new" size=3><pre>
</pre></font>If a user session is inactive for the full
timeout, the session is destroyed by the system.
No one can access the session after it times out, and the system
garbage collects it eventually.</font>
<p>
<a name=%24Session-%3EAbc5f4cea0></a>
site/objects.html view on Meta::CPAN
<a name=%24Server%20Objeed08cf85></a>
<font face=verdana><font class=title size=+0 color=#555555><b>$Server Object</b></font>
<font face="courier new" size=3><pre>
</pre></font>The server object is that object that handles everything the other
objects do not. The best part of the server object for Win32 users is
the CreateObject method which allows developers to create instances of
ActiveX components, like the ADO component.</font>
<p>
<a name=%24Server-%3E%7BSc74a89b4a></a>
<font face=verdana><font class=title size=-1 color=#555555><b>$Server->{ScriptTimeout} = $seconds</b></font>
<font face="courier new" size=3><pre>
</pre></font>Not implemented. May never be. Please see the
Apache Timeout configuration option, normally in httpd.conf.</font>
<p>
<a name=%24Server-%3ECon7d9785f8></a>
<font face=verdana><font class=title size=-1 color=#555555><b>$Server->Config($setting)</b></font>
<font face="courier new" size=3><pre>
</pre></font>API extension. Allows a developer to read the <a href=config.html><font size=-1 face=verdana><b>CONFIG</b></font></a>
settings, like Global, GlobalPackage, StateDir, etc.
Currently implemented as a wrapper around
<font face="courier new" size=3><pre>
Apache->dir_config($setting)
t/session.inc view on Meta::CPAN
<%
eval { $Session->Lock };
$t->eok($Session->Timeout > 1, "timeout check > 1");
$t->eok($Session->{Timeout} > 1, "timeout check > 1");
$t->eok(! $@, "\$Session->Lock: $@");
$t->eok(length($Session->{SessionID}) >= 8, "session id not long enough");
my $count = 0;
for(1..3) {
$Session->{count}++;
$count++;
$t->eok($count == $Session->{count},
'failure to increment $Session->{count}');
}
eval { $Session->UnLock() };
t/session_events.t view on Meta::CPAN
$0 =~ /^(.*)$/;
$0 = $1;
chdir(dirname($0));
$0 = basename($0);
my $t = T->new();
my %config = (
'NoState' => 0,
'SessionTimeout' => 20,
'Debug' => 0,
'SessionCount' => 1,
'Global' => 'session_events',
'SessionQuery' => 1,
);
my $r = Apache::ASP::CGI->init($0);
map { $r->dir_config->set($_, $config{$_}) } keys %config;
my $ASP = Apache::ASP->new($r);