Июл 30

Делаем форму обратной связи на сайт с защитой от спама

Встала задача организовать на сайте "Уголок веб-разработчика" форму обратной связи для сбора пользовательских мнений о том, какую тему они хотели бы видеть раскрытой на сайте. Естественно, форма не должна пропускать спам. В этой заметке я рассказываю, как сделать подобную форму.

Самый простой способ защиты формы от спама - это использование CAPTCHA. Как сделать собственную CAPTCHA можно прочитать в моей статье "Скрипт текстовой CAPTCHA для защиты от спам-ботов". Но в данном примере мы используем проект KCAPTCHA - готовое решение, разработанное Сергеем Кругловым.

Скачаем содержимое KCAPTCHA с сайта автора и обязательно сохраним в корень сайта, в котором будет выполняться наш скрипт с формой.

Далее - спроектируем форму с интеграцией модуля KCAPTCHA. Файл, содержащий форму обязательно должен быть PHP-скриптом и в самой верхней строчке должен содержать функцию session_start().

<form method="post">
<input type="hidden" name="send" value="1"/>
<p>Уважаемый гость! Если Вам интересен наш проект, 
предложите, пожалуйста, тему, которую Вам было бы интересно
видеть разобранной на страницах нашего
сайта или блога:</p>
<textarea name="theme"></textarea>
<br/>
<img src="kindex.php?<?php echo session_name()?>=<?php echo session_id()?>" 
width="120" height="60"><br/>
Введите анти-спам код с картинки:<br/>
<input name="keystring"><br/>
<input type="submit" value="Отправить"/>
</table>
</form>

Форма приведена без какого-либо оформления и CSS-стилей.

Далее рассмотрим скрипт отправки письма:

// получение темы
$theme = htmlspecialchars($_REQUEST['theme'], ENT_QUOTES);

// отправка письма
$subject = 'Тема для разбора с сайта codething.ru';
$mailto = 'mike@pestr.ru';
$headers = "From: mike@pestr.ru";
$message = "Тема: $theme";
$message = iconv("utf-8", "koi8-r", $message);
mail($mailto, $subject, $message, $headers);

Не забывайте заменить мой почтовый адрес mike@pestr.ru на свой!

Перед отправкой функцией mail() сообщение перекодируется в кодировку KOI8-R (так исторически сложилось для электронной почты), в данном скрипте перекодировка идет из формата UTF-8, т.к. сами скрипты я всегда сохраняю в UTF-8, но если вы решите, что вам удобнее использовать windows-кодировку, то пожалуйста, только не забудьте заменить "UTF-8" на "CP1251" в вызове функции iconv() и перекодировка также будет проходить нормально.

Теперь осталось собрать всё в кучу и добавить проверку правильности ввода CAPTCHA для защиты от спама.

Получившийся в итоге программный код будет выглядеть так:

<?php
session_start();
if ($_REQUEST['send']!='')
{

  if(!isset($_SESSION['captcha_keystring']) || 
     $_SESSION['captcha_keystring'] != $_REQUEST['keystring'])
  {
    $message="<p>Форма не отправлена!</p>";
  }
  else
  {
    // получение темы
    $theme = htmlspecialchars($_REQUEST['theme'], ENT_QUOTES);

    // отправка письма
    $subject = 'Тема для разбора с сайта codething.ru';
    $mailto = 'mike@pestr.ru';
    $headers = "From: mike@pestr.ru";
    $message = "Тема: $theme";
    $message = iconv("utf-8", "koi8-r", $message);
    mail($mailto, $subject, $message, $headers);
    $message="<p>Форма отправлена!</p>";
  }
}

if ($message!="")
{
  echo $message;
}
else
{
?>
  <form method="post">
  <input type="hidden" name="send" value="1"/>
  <p>Уважаемый гость! Если Вам интересен наш проект,
  предложите, пожалуйста, тему, которую Вам было бы интересно
  видеть разобранной на страницах нашего сайта или блога:</p>
  <textarea name="theme" ></textarea>
  <br/>
  <img src="kindex.php?<?php echo session_name()?>=<?php echo session_id()?>"
  width="120" height="60"><br/>
  Введите анти-спам код с картинки:<br/>
  <input name="keystring"><br/>
  <input type="submit" value="Отправить"/>
  </table>
  </form>
<?
}
?>

Конечно, код упрощен и не содержит дизайна и оформления. Отчасти это сделано специально, чтобы облегчить понимание примера.

Вставку этого кода к себе на сайт я сделал через тег <IFRAME>, можно посмотреть, как это работает на главной странице сайта codething.ru.

Мар 11

С чем едят JSON?

Как и обещалось после Нового года, что не пройдет и года, как я напишу новую статью про передачу параметров от PHP к JavaScript по средствам передачи данных в формате JSON.

Встречайте: AJAX и jQuery. Передача параметров из PHP в JavaScript. Использование JSON

По моему мнению, эта статья завершает цикл статей посвященных механизму AJAX на моём основном сайте http://codething.ru/. Так как рассмотрены уже все основные функции, возможности и примеры.

Что дальше? Пока не знаю. Может быть сделать платный курс или давать консультации? Если есть какие-то соображения, идеи - пишите: mike@pestr.ru.

p.s. Кстати, готов разместить рекламу на сайте, т.к. ежедневная аудитория довольно большая. Подробности здесь.

Июн 09

Скрипт для ротации баннеров

Решил сделать на своем сайте ротацию баннеров от различных партнерских программ. Сайт самописный и различные готовые решения, которые есть, например, для WordPress не подходят (кстати, в WordPress для этих же целей я использую плагин AdRotate, весьма удобный).

Поскольку простейшая ротация баннеров не требует слонжого программирования, то на создание скрипта и его тестирование отладку ушло ~20 минут.
Код баннерного ротатора выглядит следующим образом.

<? 
function rotator($filename)
 {
   if (file_exists($filename)) // проверяем наличие файла
    {
      $s=file_get_contents($filename); // читаем файл в строку
      $n = explode("###", $s);	// разделяем строку на отдельные баннеры
      $r = rand(0,count($n)-1); // выбираем случайное число (по кол-ву баннеров)
      echo $n[$r]; // выводим код баннера в поток вывода
     }
 }
?>

Для удобства использования ротатор реализован в виде функции, параметром которой является имя файла с HTML-кодом рекламных объявлений.
Файл с рекламными объявлениями выглядит следующим образом.

<a href="http://codething.ru/">Уголок веб-разработчика</a>
###
<a href="http://blog.codething.ru/">Блог веб-разработчика</a>
###
<a href="http://forum.codething.ru/">Форум о веб-разработке</a>

В качестве разделителя используется последовательность ###.

Вызов показа баннеров выполняется в коде следующим образом

<?php
 include ("rotator.php");
 rotator("file"); // запускаем с именем файла, в котором код баннеров
?>

Задача ротации баннеров решена.

Июн 07

Формируем PDF файл из PHP

Столкнулся недавно с задачей формирования PDF файла из PHP.  Немного погуглив нашел два программных решения: FPDF и TCPDF. Первое значительно компактнее второго, но мне не подошло, т.к. там имелись проблемы с русскими шрифтами. Шрифты для него необходимо как-то обрабатывать и включать в состав продукта, после чего можно работать. С этим разбираться не хотелось и поэтому я стал смотреть второй вариант - TCPDF. В кодировке UTF-8 всё отображается сразу нормально.

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

Весьма просто создать PDF-файл из HTML кода средствами TCPDF, вот пример:

1. сначала копируете файлы TCPDF в необходимую папку на хостинге.

2.  пишете программный код.

<?
require_once('tcpdf/config/lang/eng.php');
require_once('tcpdf/tcpdf.php');
$pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);

// устанавливаем описание документа
$pdf->SetCreator(PDF_CREATOR);
$pdf->SetAuthor('Test');
$pdf->SetTitle('Test');
$pdf->SetSubject('Test');
$pdf->SetKeywords('Test');

// выключаем заголовки, т.к. они нам не нужны
$pdf->setPrintHeader(false);
$pdf->setPrintFooter(false);

// устанавливаем поля
$pdf->SetMargins(10,10,10,10);

// автоперенос на новую страницу
$pdf->SetAutoPageBreak(TRUE, PDF_MARGIN_BOTTOM);

// пропорционирование картинок
$pdf->setImageScale(PDF_IMAGE_SCALE_RATIO);

// языковые настройки
$pdf->setLanguageArray($l);

// Устанавливаем шрифт
$pdf->setFontSubsetting(true);
$pdf->SetFont('dejavusans', '', 12, '', true);
$pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED);

// Вывод данных из HTML в PDF
$pdf->AddPage();
$s= '<h1>Привет мир!</h1><p>Это тестовый пример!</p>';
$pdf->writeHTML($s, true, false, true, false, '');
$pdf->Output('test.pdf', 'I');
?>

ВАЖНО! Файл примера должен быть записан в кодировке UTF-8! Иначе ничего не увидите в сгенерированном PDF-файле.

На сайте TCPDF имеется множество других примеров.

P.S. Если при запуске примеров Вы видите ошибку:

TCPDF ERROR: Some data has already been output, can't send PDF file

необходимо перед строками

require_once('tcpdf/config/lang/eng.php');
require_once('tcpdf/tcpdf.php');

вызвать функцию ob_end_clean().

Помогает. Почему-то так было на хостинге от Мастерхост, а на jino.ru сразу все нормально.

P.P.S. TCPDF распространяется по лицензии LGPL, следовательно может встраиваться (при соблюдении лицензионных требований) даже в коммерческие продукты.