$code = lc($code);
warn "$code $crypt\n" if($self->debug() >= 2);
my $current_time = time;
my $return_value = 0;
my $database_file = File::Spec->catfile($self->data_folder(),"codes.txt");
# create database file if it doesn't already exist
$self->_touch_file($database_file);
# zeros (0) and ones (1) are not part of the code
# they could be confused with (o) and (l), so we swap them in
$code =~ tr/01/ol/;
my $md5 = md5_hex($code);
# pull in current database
warn "Open File: $database_file\n" if($self->debug() >= 2);
open (DATA, "<$database_file") or die "Can't open File: $database_file\n";
flock DATA, 1; # read lock
my @data=<DATA>;
close(DATA);
warn "Close File: $database_file\n" if($self->debug() >= 2);
my $passed=0;
# $new_data will hold the part of the database we want to keep and
# write back out
my $new_data = "";
my $found;
foreach my $line (@data)
{
$line =~ s/\n//;
my ($data_time,$data_code) = split(/::/,$line);
my $png_file = File::Spec->catfile($self->output_folder(),$data_code . ".png");
if ($data_code eq $crypt)
{
# the crypt was found in the database
if (($current_time - $data_time) > $self->expire())
{
warn "Crypt Found But Expired\n" if($self->debug() >= 2);
# the crypt was found but has expired
$return_value = -1;
} else {
warn "Match Crypt in File Crypt: $crypt\n" if($self->debug() >= 2);
$found = 1;
}
if ( ($md5 ne $crypt) && ($return_value != -1) && $self->keep_failures())
{ # solution was wrong, not expired, and we're keeping failures
$new_data .= $line."\n";
} else {
# remove the found crypt so it can't be used again
warn "Unlink File: " . $png_file . "\n" if($self->debug() >= 2);
unlink($png_file) or carp("Can't remove png file [$png_file]\n");
}
} elsif (($current_time - $data_time) > $self->expire()) {
# removed expired crypt
warn "Removing Expired Crypt File: " . $png_file ."\n" if($self->debug() >= 2);
unlink($png_file) or carp("Can't remove png file [$png_file]\n");
} else {
# crypt not found or expired, keep it
$new_data .= $line."\n";
}
}
if ($md5 eq $crypt)
{
warn "Match: " . $md5 . " And " . $crypt . "\n" if($self->debug() >= 2);
# solution was correct
if ($found)
{
# solution was correct and was found in database - passed
$return_value = 1;
} elsif (!$return_value) {
# solution was not found in database
$return_value = -2;
}
} else {
warn "No Match: " . $md5 . " And " . $crypt . "\n" if($self->debug() >= 2);
# incorrect solution
$return_value = -3;
}
# update database
open(DATA,">$database_file") or die "Can't open File: $database_file\n";
flock DATA, 2; # write lock
print DATA $new_data;
close(DATA);
return $return_value;
}
sub _touch_file
{
ref(my $self = shift) or croak "instance variable needed";
my $file = shift;
# create database file if it doesn't already exist
if (! -e $file)
=3= |