Apache2-ASP
view release on metacpan or search on metacpan
lib/Apache2/ASP/SessionStateManager.pm view on Meta::CPAN
#==============================================================================
sub new
{
my ($class, %args) = @_;
my $s = bless {}, $class;
my $conn = $s->context->config->data_connections->session;
local $^W = 0;
__PACKAGE__->set_db('Main',
$conn->dsn,
$conn->username,
$conn->password
);
# Prepare our Session:
if( my $id = $s->parse_session_id() )
{
if( $s->verify_session_id( $id ) )
{
$s->{SessionID} = $id;
return $s->retrieve( $id );
}
else
{
$s->{SessionID} = $s->new_session_id();
$s->write_session_cookie();
return $s->create( $s->{SessionID} );
}# end if()
}
else
{
$s->{SessionID} = $s->new_session_id();
$s->write_session_cookie();
return $s->create( $s->{SessionID} );
}# end if()
}# end new()
#==============================================================================
sub context
{
$Apache2::ASP::HTTPContext::ClassName->current;
}# end context()
#==============================================================================
sub parse_session_id
{
my ($s) = @_;
my $cookiename = $s->context->config->data_connections->session->cookie_name;
no warnings 'uninitialized';
if( my ($id) = $ENV{HTTP_COOKIE} =~ m/$cookiename\=([a-f0-9]+)/ )
{
return $id;
}
elsif( ($id) = $s->context->r->headers_in->{Cookie} =~ m/$cookiename\=([a-f0-9]+)/ )
{
return $id;
}
else
{
return;
}# end if()
}# end parse_session_id()
#==============================================================================
# Returns true if the session exists and has not timed out:
sub verify_session_id
{
my ($s, $id) = @_;
my $range_start = time() - ( $s->context->config->data_connections->session->session_timeout * 60 );
local $s->db_Main->{AutoCommit} = 1;
my $sth = $s->db_Main->prepare_cached(<<"");
SELECT COUNT(*)
FROM asp_sessions
WHERE session_id = ?
AND modified_on BETWEEN ? AND ?
$sth->execute( $id, time2iso($range_start), time2iso() );
my ($active) = $sth->fetchrow();
$sth->finish();
return $active;
}# end verify_session_id()
#==============================================================================
sub create
{
my ($s, $id) = @_;
local $s->db_Main->{AutoCommit} = 1;
my $sth = $s->db_Main->prepare_cached(<<"");
INSERT INTO asp_sessions (
session_id,
session_data,
created_on,
modified_on
)
VALUES (
?, ?, ?, ?
)
my $now = time2iso();
no warnings 'uninitialized';
$s->{__signature} = md5_hex(
join ":",
map { "$_:$s->{$_}" }
grep { $_ ne '__signature' } sort keys(%$s)
);
my %clone = %$s;
lib/Apache2/ASP/SessionStateManager.pm view on Meta::CPAN
#==============================================================================
sub save
{
my ($s) = @_;
no warnings 'uninitialized';
return if $s->{__signature} eq md5_hex(
join ":", map { "$_:$s->{$_}" }
grep { $_ ne '__signature' } sort keys(%$s)
);
$s->{__signature} = md5_hex(
join ":",
map { "$_:$s->{$_}" }
grep { $_ ne '__signature' } sort keys(%$s)
);
local $s->db_Main->{AutoCommit} = 1;
my $sth = $s->db_Main->prepare_cached(<<"");
UPDATE asp_sessions SET
session_data = ?,
modified_on = ?
WHERE session_id = ?
my %clone = %$s;
my $data = freeze( \%clone );
$sth->execute( $data, time2iso(), $s->{SessionID} );
$sth->finish();
1;
}# end save()
#=========================================================================
sub reset
{
my ($s) = @_;
# Remove everything *but* our important parts:
my %saves = map { $_ => 1 } qw/ SessionID /;
delete( $s->{$_} ) foreach grep { ! $saves{$_} } keys(%$s);
$s->save;
}# end reset()
#==============================================================================
sub new_session_id
{
my $s = shift;
md5_hex( $s->context->config->web->application_name . rand() );
}# end new_session_id()
#==============================================================================
sub write_session_cookie
{
my $s = shift;
my $state = $s->context->config->data_connections->session;
my $cookiename = $state->cookie_name;
my $domain = eval { $state->cookie_domain } ? " domain=" . $state->cookie_domain . ";" : "";
$s->context->r->err_headers_out->{'Set-Cookie'} = "$cookiename=$s->{SessionID}; path=/; $domain";
# If we weren't given an HTTP cookie value, set it here.
# This prevents subsequent calls to 'parse_session_id()' to fail:
$ENV{HTTP_COOKIE} ||= '';
if( $ENV{HTTP_COOKIE} !~ m/\b$cookiename\=.*?\b/ )
{
my @cookies = split /;/, $ENV{HTTP_COOKIE};
push @cookies, "$cookiename=$s->{SessionID}";
$ENV{HTTP_COOKIE} = join ';', @cookies;
}# end if()
1;
}# end write_session_cookie()
#==============================================================================
sub dbh
{
my $s = shift;
return $s->db_Main;
}# end dbh()
#==============================================================================
sub DESTROY
{
my $s = shift;
delete($s->{$_}) foreach keys(%$s);
}# end DESTROY()
1;# return true:
__END__
=pod
=head1 NAME
Apache2::ASP::SessionStateManager - Base class for Session State Managers.
=head1 SYNOPSIS
Within your ASP script:
<%
$Session->{counter}++;
$Response->Write("You have viewed this page $Session->{counter} times.");
%>
=head1 DESCRIPTION
The global C<$Session> object is an instance of C<Apache2::ASP::SessionStateManager>
or one of its subclasses.
It is a blessed hash that is persisted to a database. Use it to share information across all requests for
one user.
B<NOTE:> - do not store database connections or filehandles within the C<$Session> object because they cannot be shared across
different processes or threads.
( run in 1.286 second using v1.01-cache-2.11-cpan-39bf76dae61 )