/usr/local/CPAN/Apache-SWIT/Apache/SWIT/Session.pm
use strict;
use warnings FATAL => 'all';
package Apache::SWIT::Session;
use Storable qw(thaw freeze);
use HTML::Tested::Seal;
sub access_handler($$) {
my ($class, $r) = @_;
my $session = $class->begin($r);
$r->pnotes("SWITSession", $session);
return Apache2::Const::OK();
}
sub begin {
my ($class, $r) = @_;
my %args = (_request => $r);
my %cookies = Apache2::Cookie->fetch($r);
$args{session_value} = $cookies{$class->cookie_name}->value
if $cookies{$class->cookie_name};
my $self = $class->new(%args);
$self->read_stash;
return $self;
}
sub request { return shift()->{_request}; }
sub end {
my $self = shift;
$self->write_stash;
my $cookie = Apache2::Cookie->new($self->{_request},
'-name' => $self->cookie_name,
'-value' => $self->session_value);
$cookie->path($self->{_request}->dir_config("SWITRootLocation") . ";HttpOnly");
$cookie->bake($self->{_request});
}
sub new {
my ($class, %args) = @_;
return bless(\%args, $class);
}
sub _get {
my ($self, $name, $val) = @_;
return $self->{_stash}->{$name};
}
sub _delete_children {
my ($self, $name) = @_;
for my $d (@{ $self->_get_args($name)->{children} || [] }) {
my $f = "delete_$d";
$self->$f;
}
}
sub _set {
my ($self, $name, $val) = @_;
$self->{_stash}->{$name} = $val;
$self->_delete_children($name);
}
sub _delete {
my ($self, $name) = @_;
my $res = delete $self->{_stash}->{$name};
$self->_delete_children($name);
return $res;
}
sub add_class_dbi_var {
my ($class, $var, $dbi_class) = @_;
$class->add_var($var, inflate => sub {
return $dbi_class->retrieve(shift());
}, deflate => sub { return shift()->id });
}
sub _get_args {
my ($self, $name) = @_;
my $p_args = "$name\_args";
return $self->$p_args;
}
sub add_var {
my ($class, $name, %args) = @_;
no strict 'refs';
*{ "$class\::get_$name" } = sub {
return shift()->_get($name, @_);
};
*{ "$class\::set_$name" } = sub {
return shift()->_set($name, @_);
};
*{ "$class\::delete_$name" } = sub {
return shift()->_delete($name, @_);
};
*{ "$class\::$name\_args" } = sub { return \%args; };
$args{children} = [] unless $args{children};
for my $d (@{ $args{depends_on} || [] }) {
push @{ $class->_get_args($d)->{children} }, $name;
}
}
sub session_value { return shift()->{session_value}; }
sub write_stash {
my $self = shift;
my %s;
while (my ($n, $v) = each %{ $self->{_stash} }) {
my $in = $self->_get_args($n)->{deflate};
$s{$n} = $in ? $in->($v) : $v;
}
$self->{session_value} = HTML::Tested::Seal->instance->encrypt(
freeze(\%s));
}
sub _thaw {
my $v = shift->session_value or return {};
my $res = HTML::Tested::Seal->instance->decrypt($v) or return {};
return thaw($res);
}
sub read_stash {
my $self = shift;
my $s = $self->_thaw;
my %stash;
while (my ($n, $v) = each %$s) {
my $d = $self->_get_args($n)->{inflate};
$stash{$n} = $d ? $d->($v) : $v;
}
$self->{_stash} = \%stash;
}
sub swit_startup {}
1;