CGI-SecureState
view release on metacpan or search on metacpan
SecureState.pm view on Meta::CPAN
#Set this to 0 if you do not want CGI::SecureState to use flock() to assure that
#only one instance of CGI::SecureState is accessing the state file at a time.
#Leave this at 1 unless you really have a good reason not to.
$USE_FLOCK = 1;
#The operating systems below do not support flock, except for Windows NT systems,
#but it is impossible to distinguish WinNT systems from Win9x systems only based
#on $^O
local $_=$^O;
$USE_FLOCK = 0 if (/MacOS/i || /V[MO]S/i || /MSWin32/i);
#Workaround for Perl v5.005_03
$SEEK_SET = ($]<5.006) ? 0 : &Fcntl::SEEK_SET;
}
sub import {
foreach (@_) {
$NASTY_WARNINGS=0, next if (/[:-]?no_nasty_warnings/);
$AVOID_SYMLINKS=0, next if (/[:-]?dont_avoid_symlinks/);
$USE_FLOCK=0, next if (/[:-]?no_flock/);
$USE_FLOCK=1, next if (/[:-]?use_flock/);
if (/[:-]?(extra|paranoid|no)_secure/) {
$CGI::PRIVATE_TEMPFILES = ! /no_/;
$CGI::POST_MAX = /no_/ ? -1 : 10240;
$CGI::DISABLE_UPLOADS = /paranoid_/;
}
}
}
sub new
{
#Obtain the class (should be CGI::SecureState in most cases)
my $class = shift;
#populate the argument array
my %args = args_to_hash([qw(-stateDir -mindSet -memory -temp -key)], @_);
#Set up the CGI object to our liking
my $cgi=new CGI;
#We don't want any nassssty tricksssy people playing with things that we
#should be setting ourselves
$cgi->delete($_) foreach (qw(.statefile .cipher .isforgetful .memory
.recent_memory .age .errormsg));
#if the user has an error message subroutine, we should use it:
$cgi->{'.errormsg'} = $args{'-errorSub'} || $args{'-errorsub'} || undef;
#set the forgetfulness; By default, this is "forgetful" because it encourages
#cleaner programming, but if the user is upgrading from 0.2x series, this will be
#undef; if so, be backwards-compatible but give them a few nasty warning messages.
$args{'-mindSet'} = $args{'-mindset'} unless (defined $args{'-mindSet'});
$cgi->{'.isforgetful'} = $args{'-mindSet'};
if (defined $args{'-mindSet'}) {
$cgi->{'.isforgetful'} = 0 if ($args{'-mindSet'} =~ /unforgetful/i);
} elsif ($NASTY_WARNINGS) {
warn "Programmer did not set mindset when declaring new CGI::SecureState object at ",
(caller)[1], " line ", (caller)[2], ". Please tell him/her to read the new CGI::SecureState ",
"documentation.\n";
}
#Set up long-term memory
$args{'-memory'} ||= $args{'-longTerm'} || $args{'-longterm'} || [];
$cgi->{'.memory'} = {map {$_ => 1} @{$args{'-memory'}}};
#Set up short-term memory
$args{'-temp'} ||= $args{'-shortTerm'} || $args{'-shortterm'} || [];
$cgi->{'.recent_memory'} = {map {$_ => undef} @{$args{'-temp'}}};
#Check for ID tag in url if it is not in the normal parameters list
if (!defined($cgi->param('.id')) && $cgi->request_method() eq 'POST') {
$cgi->param('.id', $cgi->url_param('.id'));
}
#Set up the encryption part
my $id = $cgi->param('.id') || sha1_hex($args{'-key'} or generate_id());
my $remote_addr = $cgi->remote_addr();
my $remoteip = pack("CCCC", split (/\./, $remote_addr));
my $key = pack("H*",$id) . $remoteip;
$cgi->{'.cipher'} = new Crypt::Blowfish($key) || errormsg($cgi, 'invalid state file');
#set the directory where we will store saved information
my $statedir = $args{'-stateDir'} || $args{'-statedir'} || ".";
#Set up (and untaint) the name of the location to store data
my $statefile = sha1_base64($id.$remote_addr);
$statefile =~ tr|+/|_-|;
$statefile =~ /([\w-]{27})/;
$cgi->{'.statefile'} = File::Spec->catfile($statedir,$1);
#convert $cgi into a CGI::SecureState object
bless $cgi, $class;
#if this is not a new session, attempt to read from the state file
$cgi->param('.id') ? $cgi->recover_memory : $cgi->param('.id' => $id);
#save any changes to the state file; if there are none, then update only the timestamp
my $newmemory = (@{$args{'-memory'}}) ? 1 : 0;
($newmemory || !$cgi->{'.isforgetful'}) ? $cgi->save_memory : $cgi->encipher;
#finish
return $cgi;
}
sub add {
my $self = shift;
my %params = (ref($_[1]) eq 'ARRAY') ? @_ : (shift, \@_);
$self->param($_, @{$params{$_}}) foreach (keys %params);
$self->remember(keys %params);
}
sub remember {
my $self = shift;
my ($isforgetful,$memory) = @$self{'.isforgetful','.memory'};
$isforgetful ? $memory->{$_}=1 : delete($memory->{$_}) foreach (@_);
$self->save_memory;
}
( run in 2.426 seconds using v1.01-cache-2.11-cpan-e93a5daba3e )