#!/usr/bin/perl -wT
###
# Note: It isn't a requirement of GD::Security::AC itself
# that CGI::Minimal and Class::ParmList be used, that is
# just how I coded up the example.
use strict;
use GD::SecurityImage::AC;
use CGI::Minimal;
use Class::ParmList qw (simple_parms);
our $Captcha_Data_Folder = '/var/www/databases/captchas';
our $Captcha_Output_Folder = '/var/www/html/images/captchas';
our $Captcha_Output_URI = '/images/captchas';
our $Captcha_Length = 5;
our $Captcha_Expire = 1800; # 30 minutes
our $Captcha_Lines = 4;
our $Captcha_Scrambled = 1;
our $Captcha_Font = 'Giant'; # Possible are 'Small','Large', 'MediumBold', 'Giant'
our $Captcha_Style = 'default'; # Possible are 'default','rect','box','circle','ellipse','ec','blank'
our $Captcha_Text_Color = '#505050';
our $Captcha_Line_Color = '#505050';
our $Captcha_Bg_Color = '#FFFFFF';
my $output = eval {
my $cgi = CGI::Minimal->new;
my $request = $cgi->param('request');
$request = defined($request) ? $request : '';
my $actions_table = {
'' => \&show_captcha,
'show' => \&show_captcha,
'validate' => \&validate_captcha,
'bad_request' => \&bad_request,
};
my $action = exists($actions_table->{$request}) ? $actions_table->{$request} : $actions_table->{'bad_request'};
my $output = &$action({ cgi => $cgi });
return $output;
};
if (defined ($output) && ($output ne '')) {
print $output;
} else {
print "Content-Type: text/plain\015\012\015\012Script Error\n$@\n";
}
#################
sub show_captcha {
my ($cgi) = simple_parms(['cgi'], @_);
my ($new_captcha_md5, $new_captcha_image) = new_captcha();
my $output =<<"EOT";
Content-Type: text/html; charset=utf-8
CAPTCHA Example
EOT
}
#################
sub validate_captcha {
my ($cgi) = simple_parms(['cgi'], @_);
my $captcha_value = $cgi->param('captcha_value');
my $captcha_md5 = $cgi->param('captcha_md5');
my $captcha_results = check_captcha({ 'value' => $captcha_value, 'md5sum' => $captcha_md5 });
my $captcha_result_desc = {
1 => 'passed',
0 => 'error: file error (code not checked)',
-1 => 'failed: code expired',
-2 => 'failed: invalid code (not in database)',
-3 => 'failed: invalid code (bad checksum)',
};
my $result_desc = $captcha_result_desc->{$captcha_results};
my ($new_captcha_md5, $new_captcha_image) = new_captcha();
my $output =<<"EOT";
Content-Type: text/html; charset=utf-8
CAPTCHA Example
Result: $result_desc
EOT
}
#################
sub bad_request {
my ($cgi) = simple_parms(['cgi'], @_);
my $request = $cgi->param('request');
my $output =<<"EOT";
Content-Type: text/plain\015\012\015\012
Unrecognized request of '$request'.
EOT
return $output;
}
################
# Checks the captcha for validity.
#
sub check_captcha {
my ($raw_value, $raw_md5sum) = simple_parms(['value','md5sum'], @_);
my ($captcha_md5) = $raw_md5sum =~ m/^([a-zA-Z0-9]{1,50})$/s;
$captcha_md5 = defined($captcha_md5) ? $captcha_md5 : '';
my ($captcha_value) = $raw_value =~ m/^([a-zA-Z0-9]{1,50})$/s;
$captcha_value = defined($captcha_value) ? $captcha_value : '';
my $captcha = captcha();
my $result = $captcha->check_code($captcha_value, $captcha_md5);
return $result;
}
################
sub new_captcha {
my $captcha = captcha();
my $md5sum = $captcha->generate_code($Captcha_Length);
my $image_uri = "$Captcha_Output_URI/${md5sum}.png";
return ($md5sum, $image_uri);
}
################
# Comment out 'gd_font' and uncomment 'font' and 'create' to use a true-type font
# instead of the GD built-on fonts
sub captcha {
my $captcha = Authen::Captcha->new(
data_folder => $Captcha_Data_Folder,
output_folder => $Captcha_Output_Folder,
expire => $Captcha_Expire,
)->gdsi(
new => {
bgcolor => $Captcha_Bg_Color,
lines => $Captcha_Lines,
gd_font => $Captcha_Font,
# font => '/var/www/databases/captchas/LucidaSansDemiBold.ttf',
ptsize => 16,
height => 60,
width => 200,
scramble => $Captcha_Scrambled,
},
# create => [ 'ttf' => $Captcha_Style, $Captcha_Text_Color, $Captcha_Line_Color],
);
return $captcha;
}