# введи число, изображенное на картинке # защита от заполнения формы с данными роботами # Vladimir Maximenko 4raznoe@mail.ru package anti_robot_img; use Digest::MD5; use Image::Magick; require Exporter; @ISA = qw( Exporter ); @EXPORT = qw( anti_new_session get_pass_str get_pass_img check_anti_robot ); $flag_dir="/tmp"; $time_flag_live=60*60; # генерация пароля $kol_digit=5; @pass_chars=(0..9); #@pass_chars=("A".."Z", "a".."z", 0..9); # возвращаемая картинка $img_width=80; $img_height=30; $noise_pixels=100; # строка случайных символов для картинки sub get_pass_str { srand(); return join("", @pass_chars[map {rand @pass_chars}(1..$kol_digit)]); } # шифрованый код сессии sub enctypt_session_code { my $salt=Digest::MD5->new; # уникальная строка для шифрования my $hash = $salt->add(time().$$); # шифруем методом ASCII-HEX return $hash->hexdigest; } # удаляем старые сессии sub del_old_session { opendir (DIR, $flag_dir); my @flag_files=readdir (DIR); closedir (DIR); shift(@flag_files);shift(@flag_files); foreach $f (@flag_files) { if ($f =~ /\.anti_robot$/) { my $mtime=(stat("$flag_dir/$f"))[9]; if ($mtime) { $check_pass.=$_; } close(FILE); if ($pass_str eq $check_pass) { return(1); } else { return(0); } } else { return(0); } } # новая сессия, готовим ловушку для робота sub anti_new_session { # новые случайные значения my $new_pass_str=&get_pass_str(); my $new_session_code=&enctypt_session_code(); # удаляем старые сессии &del_old_session(); # пишем в проверочный файл open(FILE,">$flag_dir/$new_session_code.anti_robot") || die "$!"; print FILE $new_pass_str; close(FILE); return $new_pass_str, $new_session_code; } # выводим подготовленную картинку с паролем sub get_pass_img { # из номера сессии достаем пароль if ($_[0] and -e "$flag_dir/$_[0].anti_robot") { $pass_str=""; open(FILE,"$flag_dir/$_[0].anti_robot") || die "$!"; while () { $pass_str.=$_; } close(FILE); } else { $pass_str=&get_pass_str(); } # новая картинка $image = Image::Magick->new; $image->Set(size=>$img_width."x".$img_height); $image->ReadImage('xc:white'); # выводим пароль с искажением текста my $step_x=15; my $base_x=5; my $base_y=$img_height-5; foreach my $letter (split(//, $pass_str)) { # сдвиг и вращение буквы my $sdvig_x=int(rand(4))-2; my $sdvig_y=int(rand(10))-5; my $rotate=int(rand(60))-30; $image->Annotate( antialias => 'true', pointsize => 22, x => $base_x+$sdvig_x, y => $base_y+$sdvig_y, rotate => $rotate, fill => 'black', encoding=> 'windows1251', text => $letter ); $base_x+=$step_x; } # добавляем шум (для затруднения восприятия) for my $i (1..$noise_pixels) { my $rnd_x=int(rand($img_width)); my $rnd_y=int(rand($img_height)); $image->Set("pixel[$rnd_x,$rnd_y]"=>"red"); } # выводим картинку binmode STDOUT; $image->Write('gif:-'); } 1;