20 сентября 2008 г.

Если у вас нету капчи

Развитие Shop-Script Pro и Premium остановлено, вместо них теперь WebAssyst Shop-Script. Спору нет, обновка хороша, но особых причин переводить уже работающие проекты на новый движок я не вижу.

Раз нет поддержки, то дорабатывать старые версии придется самостоятельно. Спамеры, похоже, отлично умеют распознавать старый движок и спамить по формам описания и обсуждения товаров. Поэтому нужно к ним приделать капчу. Вся эта операция займет 10-15 минут.

Первым делом, надо скачать отличный скрипт KCaptcha. Из архива надо извлечь полностью папку ‘fonts’ и файлы kcaptcha.php и kcaptcha_config.php. Сложить их в отдельную директорию на сервере, я, например, поместил их в ‘/kcaptcha’.

После этого на основе примера надо написать маленький скрипт, который будет по запросу генерировать картинку и записывать код, отображенный на ней, в переменную сессии. Я сделал вот такой:


<?php
include('kcaptcha.php');
session_start();
$captcha = new KCAPTCHA();
$_SESSION['captcha_keystring'] = $captcha->getKeyString();
?>

назвал его ‘captcha.php’ и положил в ту же директорию ‘/kcaptcha’.

Можно проверить, как оно работает, набрав в браузере адрес ‘http://mysite.com/kcaptcha/captcha.php’ – должна показаться картинка.

Теперь надо внести изменения в файлы shop-script’а и шаблона:

  • /includes/product_detailed.php – просмотр информации о продукте и обработка данных формы запроса
  • /includes/product_discussion.php – просмотр и обработка данных формы обсуждения товара
  • /templates/frontend/{шаблон}/product_detailed.tpl – шаблон информации о товаре и форма запроса
  • /templates/frontend/{шаблон}/product_discussion.tpl – шаблон обсуждения товара и форма добавления сообщения

Файл product_detailed.php

Найти условие:


if (isset($_POST["request_information"])) //email inquiry to administrator

чуть ниже есть проверка введенных данных:


 //validate input data
 if (trim($customer_email)!="" && …)

в эту проверку надо давить проверку введеной строки CAPTCHA. Если все условия выполнены, не забываем убрать значение CAPTCHA из сессии – кто-то может стартовать сессию 1 раз, а потом слать кучу писем. Должно получиться что-то типа:


//validate input data
if (
  trim($customer_email)!="" &&
  trim($customer_name)!="" &&
  trim($message_subject)!="" &&
  trim($message_text)!="" &&
  eregi("^[_\.0-9a-zA-Z-]+@([0-9a-zA-Z][0-9a-zA-Z-]+\.)+[a-zA-Z]{2,6}$", $customer_email) &&
  isset($_SESSION['captcha_keystring']) &&
  !empty($_SESSION['captcha_keystring']) &&
  isset($_POST['captcha_string']) &&
  $_SESSION['captcha_keystring'] === $_POST['captcha_string']
)
  {
    unset($_SESSION['captcha_keystring']);

Дальше в этом же файле ищем код, который отвечает за установку переменных шаблона. Выглядит он примерно как-то так:


//show product information
if (isset($productID) && $productID>=0 &&
  !isset($_POST["add_topic"]) && !isset($_POST["discuss"]) )

Листаем ниже и находим такую строку:


if ($a) //product found
  {

Там довольно много строчек, смотрим где назначаются переменные Smarty. Вот примерно так выглядят:


$smarty->assign("product_info", $a);
$smarty->assign("product_reviews_count", $k);
$smarty->assign("product_extra", $extra);
$smarty->assign("product_related", $related);

и добавляем к ним строку


$smarty->assign('kaptcha_img_url',
  '/kcaptcha/captcha.php?' . 
  str_replace(array(' ', '.'), '', microtime()));

Значение microtime() добавляется к URL, чтоб предотвратить кэширование картинки браузером и никакой смысловой нагрузки не несет.

На этом изменения этого файла закончены. Подредактируем шаблон

Шаблон product_detailed.tpl

В шаблоне надо найти форму зпроса информации о продукте. Поможет поиск строки ‘{$smarty.const.STRING_FEEDBACK_PRODUCT_INQUIRY_EXPLANATION} {$product_info.name}:’ и дальше поле textarea. Вот после этого поля надо добавить вывод картинки и поле ввода кода капчи. URL картинки с капчей мы передали в переменной kaptcha_img_url. Сделать что-то типа такого:


<img src="{$kaptcha_img_url}" alt="Kaptcha" />
<p>Что видишь? <input type="text" name='captcha_string' /></p>

Посоветуйтесь с дизайнером и/или верстальщиком, которые делали Ваш шаблон, как и куда лучше эту картинку с полем ввода вписать.

Файл product_discussion.php

Изменения в нем похожи на правку предыдущего скрипта.

В самом начале скрипта есть строки:


if (isset($_POST["add_topic"]) && isset($productID)) // add post to the product discussion
{

их надо заменить на:


if (
  isset($_POST["add_topic"]) &&
  isset($productID) &&
  isset($_SESSION['captcha_keystring']) &&
  !empty($_SESSION['captcha_keystring']) &&
  isset($_POST['captcha_string']) &&
  $_SESSION['captcha_keystring'] === $_POST['captcha_string']
 )
 {
  unset($_SESSION['captcha_keystring']);

Найти чуть ниже строки:


$smarty->assign("discuss","yes");
$smarty->assign("main_content_template", "product_discussion.tpl.html");

и добавить после них (можно в одну строку):


$smarty->assign('kaptcha_img_url',
  '/kcaptcha/captcha.php?' .
  str_replace(array(' ', '.'), '', microtime()));

а после этого поправить шаблон.

Шаблон product_discussion.tpl

В шаблоне форма добавления сообщения (в стандартном это таблица), перед ней есть строка ‘{$smarty.const.DISCUSSION_ADD_MESSAGE}:’. В таблицу надо добавить еще одну строку:


<tr>
<td>Что видишь? <img src="{$kaptcha_img_url}"
alt="Kaptcha" /></td>

<td><input type="text" name='captcha_string' /></td>

</tr>

Что еще доработать?

  • Обработку строки с CAPTCHA можно убрать из общего условия if() и вынести в одельный обработчик, чтобы можно было назначить другую строку с обшибкой типа “Неправильно введен код с картинки”.
  • В обсуждениях маленький скрипт на javascript проверяет заполненность полей – в него можно добавить проверку и нашего поля с кодом CAPTCHA
  • Добавить CAPTCHA в форму регистрации пользователя – спаммеры зачем-то иногда регистрируют пачки пользователей. Действовать по похожему алгоритму, кто сам не справится – пишите.