В статье "защита форума phpbb" рассматривался прием замены стандратной капчи на самодельную. Трудность применимости приведенного метода заключалась в необходимости генерации файла шрифта в формате, требуемом функцией imageloadfont. Сейчас мы приведем метод выведения капчи с применением широко распространненных TTF шифтов.
PHP функция imagettftext (из графической библиотеки GD/GD2) позволяет выводить текст шрифтом TrueType и кроме того задавать угол наклона для выводимого текста. TTF-файлы в Windows можно взять из папки "каталог установки windows\Fonts\" (обычно C:\Windows\Fonts\). Для вывода капчи нам потребуется следующий код.
<?php
$fontsize = 16; //размер шрифта
$font = $_SERVER['DOCUMENT_ROOT'].'/verdana.ttf'; //полный путь до файла шрифта
$bg_file = $_SERVER['DOCUMENT_ROOT'].'/rnumberfon.png'; //полный путь до файла фона
$a = imagettfbbox ($fontsize, 0, $font, 'M'); // получаем размеры одной буквы шрифта
$letter_w = abs($a[2]-$a[0]); // ширина буквы M
$letter_h = abs($a[1]-$a[7]); // высота буквы M
$im = @imagecreatefrompng($bg_file); // создаем изображения из файла фона
$textcolor = imagecolorallocate($im, 255, 255, 64); // цвет текста
$nChars = strlen($code); // число символов в коде
$cell_w = round(imagesx($im)/$nChars); // ширина ячейки для одной буквы
$pich = imagesy($im); // высота картинки
srand(time()); // инициируем счетчик случайных чисел
$indent = round(($cell_w-$letter_w)/2); //отступ от границы ячейки для буквы
if($indent<0) $indent = 0;
$bottom = round(($pich + $letter_h)/2); $top = $bottom - $letter_h;
for($i=0; $i<$nChars; $i++){
$letter = charcode($code{$i}); //получаем код символа для функции imagettftext
$fontangle = 30 * round(2 * rand() / getrandmax ()-1); //случайный угол наклона в пределах 30°
$indenty = $top * 0.5 * round(2 * rand() / getrandmax() - 1); // случайный отступ по вертикали
imagettftext($im, $fontsize, $fontangle, $cell_w*$i+$indent, $bottom-$indenty, $textcolor, $font, $letter);//выводим букву
}
//выводим заголовки для выводимого файла
header('Content-Type: image/png'); header ('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); header ('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT'); header ('Cache-Control: no-cache, must-revalidate'); header ('Pragma: no-cache');
ImagePng($im); // выводим полученное изображение в браузер
// функция для преобразования кода русской буквы в html код
function charcode($char){
$charcode = ord($char);
return ($charcode>191) ? "&#" . (1040 + $charcode - 192). ";" : $char;
}
exit();
?>
На вход данного кода должна поступить определенная переменная $code, которая содержит выводимый графический код. Кроме того вам возможно понадобится подправить пути к файлам и другие параметры для более точного выполнения вашей задачи.
Рассмотрим как применить данный код для вывода капчи на форуме phpBB 2-й версии.
Вставляем в файл includes/usercp_confirm.php после строк
// If we have a row then grab data else create a new id
if ($row = $db->sql_fetchrow($result))
{
$db->sql_freeresult($result);
$code = $row['code'];
}
else
{
exit;
}
Это русский алфавит, используемый для отображения кода. Букву Ё выкинули из алфавита, т.к. шрифтом verdana, она отображается некорректно. Вы можете расширить этот алфавит какими угодно символами, добавив их в конец строки.
В данном случае, пользователю будет выдаваться код русскими буквами, что отсечет спамеров, не пользующихся русской клавиатурой.
Ну и для модификации и усложения кода вы также можете
создать несколько файлов фонов и несколько файлов шрифтов и выбирать их случайным образом, тогда комбинация "фон-шрифт" будет случайная, что затруднит роботу работу;
можно самим генерировать случайный фон, используя библиотеку GD (функции imagecreate и imagecreatetruecolor);
использовать разный цвет шрифта кода (будьте уверены, что код достаточно различим поверх фоновой картинки).