Click

CAPTCHA Perl. Генерация при помощи ImageMagick

Небольшая функция генерации капчи для perl при помощи вызова imagemagick через библиотеку Image::Magick.
Может пригодиться в том случае, когда хостер не позволяет устанавливать свои модули для perl (например GD::SecurityImage или Auchten::Captcha). Модуль для работы с ImageMagick не стоит по умолчанию разве что у самого нерадивого хостера.
Функцию можно использовать как библиотечный вызов, при вызове передавать имя файла и строку для генерации капчи.

Код самой функции:

#!/usr/bin/perl
# Генератор капчи. Идея и параметры вызова Convert взяты с captcha.ru (http://captcha.ru/captchas/multiswirl/).
# Реализация под библиотеку Image::Magick для perl - dimio (www.dimio.org).
# 27.09.2009
use Image::Magick;
sub CreateCapImage($$){
my($cap_string,$filename) = @_;
my $font = 'times.ttf';
my $pointsize = 70;
my $path = './';

my $image = new Image::Magick;

# 1. Создаём поле 300x100 белого цвета.
$image->Set(size => '300x100');
$image->ReadImage('xc:white');
# 2. Печатаем черным с антиалиасингом
$image->Set(
			type 		=> 'TrueColor',
			antialias	=>	'True',
			fill		=>	'black',
# строку STRING шрифтом $font размером $pointsize
			font		=>	$font,
			pointsize	=>	$pointsize,
			);
$image->Draw(
			primitive	=>	'text',
			points		=>	'20,70', # ориентация строки текста внутри картинки
			text		=>	$cap_string, # что печатаем
			);
# 3. Подвинуть центр влево на 100 точек +случайная флуктуация
$image->Extent(
			geometry	=>	'400x120', # меняем размер картинки
			);
$image->Roll(
			x			=>	101+int(rand(4)),
			);
# 4. Первый swirl на случайный угол (от 37 до 51)
$image->Swirl(
			degrees		=>	int(rand(14))+37,
			);
# 5. Подвинуть центр вправо на 200 точек, тоже со случайной флуктуацией
$image->Extent(
			geometry	=>	'600x140', # меняем размер картинки
			);
$image->Roll(
			x			=>	3-int(rand(4)),
			);
# 6. Второй поворот (от 20 до 35)
$image->Swirl(
			degrees		=>	int(rand(15))+20,,
			);
# 7. Окончательная обработка и вывод
$image->Crop('300x100+100+17');
$image->Resize('150x50');

$filename = $path . $filename;
$filename .= '.png';
open(IMAGE,'>',$filename) or die $!;
$image->Write(file=>\*IMAGE, filename=>$filename);
close(IMAGE);

return $filename;
}

1;

Пример вызова:

# Вызов капчи из скрипта
my $num1 = int(rand(11))+int(rand(3));
my $num2 = int(rand(8))+int(rand(4));
my $sum = $num1+$num2;
my $cap_string = $num1.'+'.$num2.'=';
my $cap_digest = md5_hex($sum+rand(100)+rand(50));
my $cap_url = &CreateCapImage($cap_string,$cap_digest);
	$cap_url =~ s|/home/dimioorg/public_html/dimioorg||;
	$cap_url = 'http://www.dimio.org'.$cap_url;
print	$query->em("<img src=\"$cap_url\">"),
		$query->textfield(
				-name		=>	'cap_value',
				-size		=>	2,
				-maxlength	=>	2,
			);

В результате на странице будет выведена картинка с символами вида “12+7=”. Строка в принципе может быть какой угодно.

Кому лень копипастить – может скачать функцию captcha.pl и три ttf шрифта.

Написано на правах памятки для себя, но вдруг кому пригодится :)

Еще на похожие темы:

Category Рубрики: Интернет, Кодинг | Tag Метки: , , , , | Comments 10 комментариев

Comments

10 комментариев to “CAPTCHA Perl. Генерация при помощи ImageMagick”

  1. mike пишет:

    Что-то не работает!
    Рисунок – просто белый прямоугольник,без текста, а потом
    вываливается на
    print $query->em(“”),
    $query->textfield(
    -name => ‘cap_value’,
    -size => 2,
    -maxlength => 2,
    );

    с сообщением
    Can’t call method “em” on an undefined value at /home/…….

    • dimio пишет:

      В примере указано так:

      print $query->em(““),

      ,а вы передаёте пустую строку.
      Модуль CGI подключен кстати?

      Что касается рисунка – во-первых – шрифт указан правильно? Во-вторых – можно покрутить параметры генерации. У меня получалась нормальная картинка с капчей при указанных в примере параметрах.

    • dimio пишет:

      Понятно, это движок режет код…

  2. mike пишет:

    Сделал так:
    $query = new CGI;
    print $query->em(“”),
    $query->textfield(
    -name => ‘cap_value’,
    -size => 10,
    -maxlength => 5,
    );
    все заработало, но картинка пустая :(

  3. bash пишет:

    вот сделал капчу… все работает.
    а как правильно проверять ее и ввод юзера ?

    • dimio пишет:

      Я бы вычислял хэш сгенерированного слова для капчи и хэш пользовательского ввода, а затем сравнивал их. Модуль Digest::MD5 в помощь.

  4. bash пишет:

    ну хэш пользовательского ввода вычислить без проблем… а вот хэш капчи как ?? он же уже забыт, т.к. скрипт отработался на выводе капчи ). да и вобще это разные скрипты могут быть – один выводит капчу, а другой принимает ввод… вот и заморочка у меня тут (

    • dimio пишет:

      Хэш капчи класть в файл или иную БД (в файл логичней и проще, но если уже есть БД для движка – почему бы не создать там таблицу), отработавшие (и при желании – протухшие) хэши капч удалять. Для удобства можно капчам идентификаторы присваивать некие.

Leave a Reply