CGI-SecureState
view release on metacpan or search on metacpan
SecureState.pm view on Meta::CPAN
syswrite(STATEFILE,$cipher->encrypt($buffer));
}
else {
#add metadata to the beginning of the plaintext
$length=length($buffer);
$buffer=pack("N",$length).$time.$buffer;
#pad the buffer to have a length that is divisible by 8
if ($length%=8) {
$length=8-$length;
$buffer.=chr(int(rand(256))) while ($length--);
}
#encrypt in reverse-CBC mode
$block=$cipher->encrypt(substr($buffer,-8,8));
substr($buffer,-8,8,$block);
$length=length($buffer) - 8;
while(($length-=8)>-8) {
$block^=substr($buffer,$length,8);
$block=$cipher->encrypt($block);
substr($buffer,$length,8,$block);
}
#blast it to the file
syswrite(STATEFILE,$buffer);
}
if ($USE_FLOCK) { flock(STATEFILE, LOCK_UN) || $self->errormsg('failed to unlock the state file') }
close(STATEFILE) || $self->errormsg('failed to close the state file');
}
sub decipher
{
my $self = shift;
my ($cipher,$statefile) = @$self{'.cipher','.statefile'};
my ($length,$extra,$decoded,$buffer,$block);
if ($AVOID_SYMLINKS) { -l $statefile and $self->errormsg('symlink encountered')}
sysopen(STATEFILE,$statefile, O_RDONLY) || $self->errormsg('failed to open the state file');
if ($USE_FLOCK) { flock(STATEFILE, LOCK_SH) || $self->errormsg('failed to lock the state file') }
binmode STATEFILE;
#read metadata
sysread(STATEFILE,$block,8);
$block = $cipher->decrypt($block);
#if there is nothing in the file, only set the age; otherwise read the contents
unless (sysread(STATEFILE,$buffer,8)==8) {
$self->{'.age'} = unpack("N",substr($block,4,4));
$buffer = "";
} else {
#parse metadata
$block^=$buffer;
$self->{'.age'} = unpack("N",substr($block,4,4));
$length = unpack("N",substr($block,0,4));
$extra = ($length % 8) ? (8-($length % 8)) : 0;
$decoded=-8;
#sanity check
if ((stat(STATEFILE))[7] != ($length+$extra+8))
{ $self->errormsg('invalid state file') }
#read the rest of the file
sysseek(STATEFILE, 8, $SEEK_SET);
unless (sysread(STATEFILE,$buffer,$length+$extra) == ($length+$extra))
{ $self->errormsg('invalid state file') }
my $next_block;
$block = $cipher->decrypt(substr($buffer,0,8));
#decrypt it
while (($decoded+=8)<$length-8) {
$next_block = substr($buffer,$decoded+8,8);
$block^=$next_block;
substr($buffer, $decoded, 8, $block);
$block=$cipher->decrypt($next_block);
}
substr($buffer, $decoded, 8, $block);
substr($buffer, -$extra, $extra, "");
}
if ($USE_FLOCK) { flock(STATEFILE, LOCK_UN) || $self->errormsg('failed to unlock the state file') }
close(STATEFILE) || $self->errormsg('failed to close the state file');
return($buffer);
}
END_OF_FUNCTIONS
;
eval(($]<5.006) ? $subs : "use bytes; $subs");
}
"True Value";
=head1 NAME
CGI::SecureState -- Transparent, secure statefulness for CGI programs
=head1 SYNOPSIS
use CGI::SecureState;
my @memory = qw(param1 param2 other_params_to_remember);
my $cgi = new CGI::SecureState(-stateDir => "states",
-mindSet => 'forgetful',
-memory => \@memory);
print $cgi->header(), $cgi->start_html;
my $url = $cgi->state_url();
my $param = $cgi->state_param();
print "<a href=\"$url\">I am a stateful CGI session.</a>";
print "<a href=\"other_url.pl?$param\">I am a different ",
"script that also has access to this session.</a>";
=head2 Very Important Note for Users of CGI::SecureState 0.2x
For those still using the 0.2x series, CGI::SecureState changed enormously between
0.26 and 0.30. Specifically, the addition of mindsets is so important that if you
run your old scripts unchanged under CGI::SecureState 0.3x, you will receive nasty
warnings (likely both in output web pages and your log files) that will tell you not
to do so. Please do yourself a favor by re-reading this documentation, as this
( run in 1.807 second using v1.01-cache-2.11-cpan-39bf76dae61 )