20 июня 2011 г.

Защита email от спамеров с помощью JavaScript и PHP

В процессе допиливания сайта столкнулся с проблемой защиты email адрессов от спамеров. Проблема заключалась в том что email может быть вставлен в произвольный текст в произвольной форме. Вот примеры как он может быть вставлен:

<a href="mailto:email@amail.com">email@amail.com</a>
<a href="mailto:email@amail.com">anytext</a>
<a href="mailto:email@amail.com"><img anything></a>
<a href="mailto:email@amail.com?subject=Text">email@amail.com</a>
<a href="mailto:email@amail.com?subject=Text">anytext</a>
и просто email@amail.com.

И вот это всё надо как-то вычленить и закрыть от спамеров.
Погуглив обнаружил различные варианты защиты email вот хорошая статья на Хабре на эту тему http://habrahabr.ru/blogs/webdev/22549/

Решил использовать вариант с защитой с помощью JavaScript, вроде как самый надёжный.
Решив не писать свой велосипед с квадратными колёсами порывшись в инете нашёл плагин к Joomla - "Email Cloacker", который и делает что мне нужно, вот только делает он это для Joomla, а мне нужно его было от этого отвязать. В результате сделал класс EmailCloacker который обрабатывает нужный мне текст и заменяет email на JavaScript.
Код класса в продолжении записи. Может кому то пригодится.


class EmailCloacker {

 protected function _getPattern ($link, $text) {
  $pattern = '~(?:' . $text . '~i';
  return $pattern;
 }
 
 protected function _cloak($mail, $mailto=1, $text='', $email=1) {
  // convert text
  $mail   = self::_convertEncoding($mail);
  // split email by @ symbol
  $mail   = explode('@', $mail);
  $mail_parts  = explode('.', $mail[1]);
  // random number
  $rand   = rand(1, 100000);

  $replacement = "\n ";
  $replacement .= "\n ";
  $replacement .= "\n ';

  // XHTML compliance `No Javascript` text handling
  
  $replacement .= "\n ";
  $replacement .= "\n This e-mail address is being protected from spambots. You need JavaScript enabled to view it.";
  $replacement .= "\n ";
  $replacement .= "\n ";
  
  return $replacement;
 }

 protected  function _convertEncoding($text) {
  // replace vowels with character encoding
  $text = str_replace('a', 'a', $text);
  $text = str_replace('e', 'e', $text);
  $text = str_replace('i', 'i', $text);
  $text = str_replace('o', 'o', $text);
  $text = str_replace('u', 'u', $text);

  return $text;
 } 

 /**
  * Cloak all emails in text from spambots via Javascript.
  *
  * @param string The string to be cloaked.
  * replaces addresses with "mailto:" links if nonzero.
  * @return text with changed emails.
  */
 public function replaceEmailOnJs($text) {

  // Simple performance check to determine whether bot should process further.
  if (strpos($text, '@') === false) {
   return $text;
  }

  $mode = 1;

  // any@email.address.com
  $searchEmail = '([\w\.\-]+\@(?:[a-z0-9\.\-]+\.)+(?:[a-z0-9\-]{2,4}))';
  // any@email.address.com?subject=anyText
  $searchEmailLink = $searchEmail . '([?&][\x20-\x7f][^"<>]+)';
  // anyText
  $searchText = '([\x20-\x7f][^<>]+)';
  //Any Image link
  $searchImage = "(]+>)";

  /*
   * Search and fix derivatives of link code email@email.com. This happens when inserting an email in TinyMCE, cancelling its suggestion to add
   * the mailto: prefix...
   */
  $pattern = self::_getPattern($searchEmail, $searchEmail);
  $pattern = str_replace('"mailto:', '"http://mce_host([\x20-\x7f][^<>]+/)', $pattern);
  while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE)) {
   $mail = $regs[2][0];
   $mailText = $regs[3][0];

   // Check to see if mail text is different from mail addy
   $replacement = self::_cloak( $mail, $mode, $mailText);

   // Replace the found address with the js cloaked email
   $text = substr_replace($text, $replacement, $regs[0][1], strlen($regs[0][0]));
  }

  /*
   * Search and fix derivatives of link code anytext. This happens when inserting an email in TinyMCE, cancelling its suggestion to add
   * the mailto: prefix...
   */
  $pattern = self::_getPattern($searchEmail, $searchText);
  $pattern = str_replace('"mailto:', '"http://mce_host([\x20-\x7f][^<>]+/)', $pattern);
  while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE)) {
   $mail = $regs[2][0];
   $mailText = $regs[3][0];

   // Check to see if mail text is different from mail addy
   $replacement = self::_cloak( $mail, $mode, $mailText, 0);

   // Replace the found address with the js cloaked email
   $text = substr_replace($text, $replacement, $regs[0][1], strlen($regs[0][0]));
  }

  /*
   * Search for derivatives of link code email@amail.com
   */
  $pattern = self::_getPattern($searchEmail, $searchEmail);
  while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE)) {
   $mail = $regs[1][0];
   $mailText = $regs[2][0];

   // Check to see if mail text is different from mail addy
   $replacement = self::_cloak( $mail, $mode, $mailText);

   // Replace the found address with the js cloaked email
   $text = substr_replace($text, $replacement, $regs[0][1], strlen($regs[0][0]));
  }

  /*
   * Search for derivatives of link code 
   * anytext
   */
  $pattern = self::_getPattern($searchEmail, $searchText);
  while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE)) {
   $mail = $regs[1][0];
   $mailText = $regs[2][0];

   $replacement = self::_cloak( $mail, $mode, $mailText, 0);

   // Replace the found address with the js cloaked email
   $text = substr_replace($text, $replacement, $regs[0][1], strlen($regs[0][0]));
  }
  
 /*
   * Search for derivatives of link code 
   * 
   */
  $pattern = self::_getPattern($searchEmail, $searchImage);
  while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE)) {
   $mail = $regs[1][0];
   $mailText = $regs[2][0];

   $replacement = self::_cloak( $mail, $mode, $mailText, 0);

   // Replace the found address with the js cloaked email
   $text = substr_replace($text, $replacement, $regs[0][1], strlen($regs[0][0]));
  }

  /*
   * Search for derivatives of link code email@amail.com
   */
  $pattern = self::_getPattern($searchEmailLink, $searchEmail);
  while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE)) {
   $mail = $regs[1][0] . $regs[2][0];
   $mailText = $regs[3][0];
   // Needed for handling of Body parameter
   $mail = str_replace('&', '&', $mail);

   // Check to see if mail text is different from mail addy
   $replacement = self::_cloak( $mail, $mode, $mailText);

   // Replace the found address with the js cloaked email
   $text = substr_replace($text, $replacement, $regs[0][1], strlen($regs[0][0]));
  }

  /*
   * Search for derivatives of link code anytext
   */
  $pattern = self::_getPattern($searchEmailLink, $searchText);
  while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE)) {
   $mail = $regs[1][0] . $regs[2][0];
   $mailText = $regs[3][0];
   // Needed for handling of Body parameter
   $mail = str_replace('&', '&', $mail);

   $replacement = self::_cloak( $mail, $mode, $mailText, 0);

   // Replace the found address with the js cloaked email
   $text = substr_replace($text, $replacement, $regs[0][1], strlen($regs[0][0]));
  }

  // Search for plain text email@amail.com
  $pattern = '~' . $searchEmail . '([^a-z0-9]|$)~i';
  while (preg_match($pattern, $text, $regs, PREG_OFFSET_CAPTURE)) {
   $mail = $regs[1][0];

   $replacement = self::_cloak( $mail, $mode);
   // Replace the found address with the js cloaked email
   $text = substr_replace($text, $replacement, $regs[1][1], strlen($mail));
  }
  
  return $text;
 }
 
}



Комментариев нет:

Отправить комментарий