Итак, закончили мы на том, что нарисовали все цифры, создали массивы php с псевдографическими изображениями цифр и написали отладочную функцию, которая выводит конкретную цифру. Продолжаем!
Для начала условимся, то нашему злодею-хацкеру, распознающему каптчу, мы, хоть и ненамного, но усложним задачу: "пробельные" ("пустые") символы в изображении каждой цифры, а также сами символы, изображающие цифру, будут выбраны случайно из заранее заданного набора. Зададим набор символов, изображающих цифру, в виде строки:
$pgstring="#$%@!?0"; //символы, из которых будут составлены цифры
Аналогично и для "пустых" символов:
$spstring="- "; //пробельные символы
Тут все зависит от вкуса, цвета и лично ваших глазок. Главное, чтобы в строке с возможными "пустыми" символами и в строке с возможными символами, изображающими цифру, не встретилось одинаковых символов, иначе при определенных условиях, пользователь вполне может получить вот такую вот гадость, вместо каптчи:
###### ###### ###### ###### ###### ###### ######
###### ###### ###### ###### ###### ###### ######
###### ###### ###### ###### ###### ###### ######
###### ###### ###### ###### ###### ###### ######
###### ###### ###### ###### ###### ###### ######
Заведем еще две переменные, которые будут хранить выбранные символы для "пробельных" и символов изображения:
$pgchar="";
$spchar="";
Пока просто оставим их пустыми, потом к ним еще вернемся.
Приступаем к написанию скрипта. Небольшие и вспомогательные функции.
Первым делом, нам понадобится функция, генерирующая код каптчи нужной длины. Она довольно проста:
function getcaptchacode($codelen)
{
$ans="";
for ($i=0;$i<$codelen;$i++)
{
$r=rand(0,9);
$ans=$ans.$r;
}
return $ans;
}
В качестве параметра ($codelen) функции передается длина необходимого нам кода каптчи, далее функция генерирует строку, состоящую из символов от 0 до 9 заданной длины. На самом деле на каждой итерации цикла for генерируется ($r=rand(0,9);
) случайное число в диапазоне от 0 до 9, но PHP такой странный язык, что отдельно (если кто не знает) заниматься преобразованием числа в строку, нам не требуется. После генерации числа от 0 до 9 просто присоединяем его к строке $ans ($ans=$ans.$r;), а конвертацией занимается интерпретатор.
Если философствовать, то это вообще-то большой минус, но в данном случае он вполне себе плюс. Но философствовать мы не будем, лучше продолжим.
Функция, возвращающая случайный символ из заданной строки.
//получает случайный символ из строки
function randomchar($srcstr)
{
$i=rand(0,strlen($srcstr)-1);
return $srcstr{$i};
}
Тут вообще все просто - на входе передаем строку с набором символов ($srcstr), случайно выбираем позицию любого символа в строке, начиная с первого (нулевого) и заканчивая последним (длина строки, возвращаемая стандартной функцией strlen - 1). Записываем полученное значение в переменную $i ($i=rand(0,strlen($srcstr)-1);) обращаемся к конкретному символу в строке по ранее сохраненному номеру (позиции) с помощью конструкции "{}" и возвращаем его (return $srcstr{$i}).
Формирование изображения каптчи. Определение функции, основных внутренних переменных и подготовительные действия.
Этим делом будет заниматься функция getpgnum:
function getpgnum($numstr,$numarr,$spchr,$spctr,$startsp,$endsp)
{
...
}
Ей передаются следующие параметры:
$numstr (строка, состоящая из цифр) - Строка цифр, в случае каптчи, это будет код, сгенерированный ранее вызванной функцией getcaptchacode.
$numarr - массив, содержащий псевдографические изображения всех цифр (
ранее созданный $allnum)
$spchr (строка) - символ для промежутка между цифрами каптчи
$spctr (целое число) - количество символов между цифрами каптчи.
Т.е. если мы в качестве параметра $spchr зададим символ [!], а в параметре $spctr передадим число, например 4, то цифры каптчи будут разделены четырьмя восклицательными знаками. Вообще использовать можно любой символ, даже случайно выбранный. На практике я использую пробел. А тут восклицательные знаки для наглядности.
$startsp (логическое значение) - если установлено в true, то перед самим изображением каптчи так же будут добавлены символы, заданные в параметре $spchr в количестве заданном в параметре $spctr
$endsp (логическое значение) - то же самое, что и предыдущий параметр, но только для пробелов в конце строк изображения каптчи.
Определяем основные внутренние переменные функции:
Переменная, в которой будет храниться готовое псевдографическое изображение каптчи - результат работы функции:
$ans="";
Переменная, для хранения строки из пробелов между числами:
$spstr="";
Переменная, для хранения отдельной цифры из строки $numstr:
$num=0;
Текущая строка формируемого псевдографического изображения:
$curline="";
Проверяем, что строка в переменной $numstr состоит только из цифр:
if (!is_numeric($numstr)) //если в строку запихали не цифру
{
echo ("ERROR: NOT NUMBER ".$numstr); //выводим ошибку и
//завершаем скрипт
die();
}
Формируем строку символов между цифрами каптчи:
//формируем строку пробельных символов
for ($i=0;$i<$spctr;$i++)
{
$spstr=$spstr.$spchr;
}
Формирование изображения каптчи. Краткое описание алгоритма.
Формируя изображение каптчи, алгоритм будет действовать примерно, как ЭЛТ-монитор, т.е. формировать изображение сразу всех цифр, но построчно, т.е. брать первую строку, из всех изображений цифр, указанных в переменной $numstr, дополнять ее после перехода к следующей цифре из переменной $numstr пробелами. Получившуюся строчку при надобности обрабатывать (добавлять начальные и удалять конечные пробелы, добавлять перенос строки) и присовокуплять обработанную строчку к значению, возвращаемому функцией.
Вот видео, иллюстрирующее процесс:
Click to view
Прямая ссылка Формирование изображения каптчи. Основной код с описанием.
//проходим по всем строчкам изображения
//цифры все одинаковой высоты - 5 строк
for ($j=0;$j<5;$j++)
{
//проходим по строке с числом
for ($i=0;$i
Во внешнем цикле (for ($j=0;$j<5;$j++)) проходим по всем строчкам изображения каптчи, поскольку у нас все цифры одинаковой высоты, то это можно прямо на месте и указать ($j<5). Сразу же начинаем внутренний цикл, формирующий конкретную строчку изображения всей каптчи (for ($i=0;$i). Этот цикл пройдет по всей строке с заданным кодом ($numstr).
В нем сначала извлекаем из строки конкретную цифру и сохраняем ее значение в переменной $num ($num=$numstr{$i}).
Далее, копируем псевдографическое изображение отдельной цифры в переменную $imgnum ($imgnum=$numarr[$num];).
Формируем текущую строку ($curline) изображения всех цифр каптчи с пробелами ($spstr) между строками изображения конкретной цифры ($curline=$curline.$imgnum[$j].$spstr). Переменная $j, задается во внешнем цикле - это номер строки изображения, обрабатываемый в данный момент.
После внутренний цикл завершается, и готовая строка ($curline) дообрабатывается во внешнем цикле, ей добавляются или из нее удаляются начальные/конечные пробелы, в зависимости от установленных переменных ($startsp и $endsp):
//линия сформирована
if ($startsp) //если нужны стартовые пробелы - добавляем
{
$curline=$spstr.$curline;
}
if (!$endsp) //если НЕ нужны конечные пробелы - удаляем
{
$curline=substr($curline,0,strlen($curline)-$spctr);
}
Далее добавляются символы переноса строки, сформированная строка присоединяется к общему ответу функции:
$ans=$ans.$curline."\r\n";
Текущая строка изображения обнуляется, и внешний цикл переходит к формированию следующей строки.
$curline=""; //очищаем переменную для хранения текущей строки
//каптчи
Если цикл формирования изображения завершился, то функция возвращает значение:
return $ans;
Замена символов в изображении на случайные
С функциями вроде закончили. Осталось, как я и обещал в самом начале, немного подгадить злодею, подбирающему каптчу. Ранее были заданы переменные $pgchar и $spchar, пока никак не использованные, строки $pgstring и $spstring содержащие заданный набор символов, а также создана функция randomchar, возвращающая случайный символ из строки.
В первой части мы условились, что символы, формирующие изображение цифры, это символы $, а символы, занимающие пустые места в изображении - *.
Настало время ОТКРЫТЬ ВРАТА ШТАЙНЕРА, ХА-ХА-ХА использовать это и функцию randomchar, наконец.
После области функций пишем следующий код.
1. Случайно выбираем символ для символа изображения ($pgchar) и пустого ($spchar), из содержащихся в заранее заданных строках ($pgstring и $spstring):
$pgchar=randomchar($pgstring);
$spchar=randomchar($spstring);
2. Теперь заменяем заранее определенные символы * и $ в массиве с изображением цифр, на полученные случайные:
//заменяем символы в псевдографике на случайные
for ($i=0; $i
Итого
В данный момент, мы имеем готовый include-модуль, формирующий код каптчи и ее псевдографическое изображение. В следующей части будут примеры ее использования.
Код каптчи
Смотреть на PasteBin Начало здесьПродолжение Это репост заметки из моего блога на сайте
http://tolik-punkoff.comОригинал заметки находится здесь:
http://tolik-punkoff.com/2017/04/13/ascii-kaptcha-kaptcha-psevdografikoj-chast-ii-v-kotoroj-generiruetsya-kaptcha/(
![](http://lj.rossia.org/numreplies/hex_laden/366520)
Comments |
Comment on this)