You are here

cleantalk.module in Anti Spam by CleanTalk 7

Main CleanTalk integration module functions.

File

cleantalk.module
View source
<?php

/**
 * @file
 * Main CleanTalk integration module functions.
 */

/**
 * Implements hook_html_head_alter(&$head_elements).
 */
$cleantalk_executed = false;
error_reporting(E_ALL);

/**
 * Cleantalk base class
 *
 * @version 2.0.0
 * @package Cleantalk
 * @subpackage Base
 * @author Cleantalk team (welcome@cleantalk.org)
 * @copyright (C) 2014 CleanTalk team (http://cleantalk.org)
 * @license GNU/GPL: http://www.gnu.org/copyleft/gpl.html
 * @see https://github.com/CleanTalk/php-antispam 
 *
 */

/**
 * Response class
 */
class CleantalkResponse {

  /**
   *  Is stop words
   * @var int
   */
  public $stop_words = null;

  /**
   * Cleantalk comment
   * @var string
   */
  public $comment = null;

  /**
   * Is blacklisted
   * @var int
   */
  public $blacklisted = null;

  /**
   * Is allow, 1|0
   * @var int
   */
  public $allow = null;

  /**
   * Request ID
   * @var int
   */
  public $id = null;

  /**
   * Request errno
   * @var int
   */
  public $errno = null;

  /**
   * Error string
   * @var string
   */
  public $errstr = null;

  /**
   * Is fast submit, 1|0
   * @var string
   */
  public $fast_submit = null;

  /**
   * Is spam comment
   * @var string
   */
  public $spam = null;

  /**
   * Is JS
   * @var type
   */
  public $js_disabled = null;

  /**
   * Sms check
   * @var type
   */
  public $sms_allow = null;

  /**
   * Sms code result
   * @var type
   */
  public $sms = null;

  /**
   * Sms error code
   * @var type
   */
  public $sms_error_code = null;

  /**
   * Sms error code
   * @var type
   */
  public $sms_error_text = null;

  /**
   * Stop queue message, 1|0
   * @var int
   */
  public $stop_queue = null;

  /**
   * Account shuld by deactivated after registration, 1|0
   * @var int
   */
  public $inactive = null;

  /**
   * Account status
   * @var int
   */
  public $account_status = -1;

  /**
   * Create server response
   *
   * @param type $response
   * @param type $obj
   */
  function __construct($response = null, $obj = null) {
    if ($response && is_array($response) && count($response) > 0) {
      foreach ($response as $param => $value) {
        $this->{$param} = $value;
      }
    }
    else {
      $this->errno = $obj->errno;
      $this->errstr = $obj->errstr;
      $this->errstr = preg_replace("/.+(\\*\\*\\*.+\\*\\*\\*).+/", "\$1", $this->errstr);
      $this->stop_words = isset($obj->stop_words) ? utf8_decode($obj->stop_words) : null;
      $this->comment = isset($obj->comment) ? utf8_decode($obj->comment) : null;
      $this->blacklisted = isset($obj->blacklisted) ? $obj->blacklisted : null;
      $this->allow = isset($obj->allow) ? $obj->allow : 0;
      $this->id = isset($obj->id) ? $obj->id : null;
      $this->fast_submit = isset($obj->fast_submit) ? $obj->fast_submit : 0;
      $this->spam = isset($obj->spam) ? $obj->spam : 0;
      $this->js_disabled = isset($obj->js_disabled) ? $obj->js_disabled : 0;
      $this->sms_allow = isset($obj->sms_allow) ? $obj->sms_allow : null;
      $this->sms = isset($obj->sms) ? $obj->sms : null;
      $this->sms_error_code = isset($obj->sms_error_code) ? $obj->sms_error_code : null;
      $this->sms_error_text = isset($obj->sms_error_text) ? $obj->sms_error_text : null;
      $this->stop_queue = isset($obj->stop_queue) ? $obj->stop_queue : 0;
      $this->inactive = isset($obj->inactive) ? $obj->inactive : 0;
      $this->account_status = isset($obj->account_status) ? $obj->account_status : -1;
      if ($this->errno !== 0 && $this->errstr !== null && $this->comment === null) {
        $this->comment = '*** ' . $this->errstr . ' Antispam service cleantalk.org ***';
      }
    }
  }

}

/**
 * Request class
 */
class CleantalkRequest {

  /**
   *  All http request headers
   * @var string
   */
  public $all_headers = null;

  /**
   *  IP address of connection
   * @var string
   */

  //public $remote_addr = null;

  /**
   *  Last error number
   * @var integer
   */
  public $last_error_no = null;

  /**
   *  Last error time
   * @var integer
   */
  public $last_error_time = null;

  /**
   *  Last error text
   * @var string
   */
  public $last_error_text = null;

  /**
   * User message
   * @var string
   */
  public $message = null;

  /**
   * Post example with last comments
   * @var string
   */
  public $example = null;

  /**
   * Auth key
   * @var string
   */
  public $auth_key = null;

  /**
   * Engine
   * @var string
   */
  public $agent = null;

  /**
   * Is check for stoplist,
   * valid are 0|1
   * @var int
   */
  public $stoplist_check = null;

  /**
   * Language server response,
   * valid are 'en' or 'ru'
   * @var string
   */
  public $response_lang = null;

  /**
   * User IP
   * @var strings
   */
  public $sender_ip = null;

  /**
   * User email
   * @var strings
   */
  public $sender_email = null;

  /**
   * User nickname
   * @var string
   */
  public $sender_nickname = null;

  /**
   * Sender info JSON string
   * @var string
   */
  public $sender_info = null;

  /**
   * Post info JSON string
   * @var string
   */
  public $post_info = null;

  /**
   * Is allow links, email and icq,
   * valid are 1|0
   * @var int
   */
  public $allow_links = null;

  /**
   * Time form filling
   * @var int
   */
  public $submit_time = null;

  /**
   * Is enable Java Script,
   * valid are 0|1|2
   * Status:
   *  null - JS html code not inserted into phpBB templates
   *  0 - JS disabled at the client browser
   *  1 - JS enabled at the client broswer
   * @var int
   */
  public $js_on = null;

  /**
   * user time zone
   * @var string
   */
  public $tz = null;

  /**
   * Feedback string,
   * valid are 'requset_id:(1|0)'
   * @var string
   */
  public $feedback = null;

  /**
   * Phone number
   * @var type
   */
  public $phone = null;

  /**
   * Method name
   * @var string
   */
  public $method_name = 'check_message';

  /**
   * Fill params with constructor
   * @param type $params
   */
  public function __construct($params = null) {
    if (is_array($params) && count($params) > 0) {
      foreach ($params as $param => $value) {
        $this->{$param} = $value;
      }
    }
  }

}

/**
 * Cleantalk class create request
 */
class Cleantalk {

  /**
   * Debug level
   * @var int
   */
  public $debug = 0;

  /**
   * Maximum data size in bytes
   * @var int
   */
  private $dataMaxSise = 32768;

  /**
   * Data compression rate
   * @var int
   */
  private $compressRate = 6;

  /**
   * Server connection timeout in seconds
   * @var int
   */
  private $server_timeout = 3;

  /**
   * Cleantalk server url
   * @var string
   */
  public $server_url = null;

  /**
   * Last work url
   * @var string
   */
  public $work_url = null;

  /**
   * WOrk url ttl
   * @var int
   */
  public $server_ttl = null;

  /**
   * Time wotk_url changer
   * @var int
   */
  public $server_changed = null;

  /**
   * Flag is change server url
   * @var bool
   */
  public $server_change = false;

  /**
   * Use TRUE when need stay on server. Example: send feedback
   * @var bool
   */
  public $stay_on_server = false;

  /**
   * Codepage of the data
   * @var bool
   */
  public $data_codepage = null;

  /**
   * API version to use
   * @var string
   */
  public $api_version = '/api2.0';

  /**
   * Use https connection to servers
   * @var bool
   */
  public $ssl_on = false;

  /**
   * Minimal server response in miliseconds to catch the server
   *
   */
  public $min_server_timeout = 50;

  /**
   * Function checks whether it is possible to publish the message
   * @param CleantalkRequest $request
   * @return type
   */
  public function isAllowMessage(CleantalkRequest $request) {
    $this
      ->filterRequest($request);
    $msg = $this
      ->createMsg('check_message', $request);
    return $this
      ->httpRequest($msg);
  }

  /**
   * Function checks whether it is possible to publish the message
   * @param CleantalkRequest $request
   * @return type
   */
  public function isAllowUser(CleantalkRequest $request) {
    $this
      ->filterRequest($request);
    $msg = $this
      ->createMsg('check_newuser', $request);
    return $this
      ->httpRequest($msg);
  }

  /**
   * Function sends the results of manual moderation
   *
   * @param CleantalkRequest $request
   * @return type
   */
  public function sendFeedback(CleantalkRequest $request) {
    $this
      ->filterRequest($request);
    $msg = $this
      ->createMsg('send_feedback', $request);
    return $this
      ->httpRequest($msg);
  }

  /**
   *  Filter request params
   * @param CleantalkRequest $request
   * @return type
   */
  private function filterRequest(CleantalkRequest &$request) {

    // general and optional
    foreach ($request as $param => $value) {
      if (in_array($param, array(
        'message',
        'example',
        'agent',
        'sender_info',
        'sender_nickname',
        'post_info',
        'phone',
      )) && !empty($value)) {
        if (!is_string($value) && !is_integer($value)) {
          $request->{$param} = NULL;
        }
      }
      if (in_array($param, array(
        'stoplist_check',
        'allow_links',
      )) && !empty($value)) {
        if (!in_array($value, array(
          1,
          2,
        ))) {
          $request->{$param} = NULL;
        }
      }
      if (in_array($param, array(
        'js_on',
      )) && !empty($value)) {
        if (!is_integer($value)) {
          $request->{$param} = NULL;
        }
      }
      if ($param == 'sender_ip' && !empty($value)) {
        if (!is_string($value)) {
          $request->{$param} = NULL;
        }
      }
      if ($param == 'sender_email' && !empty($value)) {
        if (!is_string($value)) {
          $request->{$param} = NULL;
        }
      }
      if ($param == 'submit_time' && !empty($value)) {
        if (!is_int($value)) {
          $request->{$param} = NULL;
        }
      }
    }
  }

  /**
   * Compress data and encode to base64
   * @param type string
   * @return string
   */
  private function compressData($data = null) {
    if (strlen($data) > $this->dataMaxSise && function_exists('gzencode') && function_exists('base64_encode')) {
      $localData = gzencode($data, $this->compressRate, FORCE_GZIP);
      if ($localData === false) {
        return $data;
      }
      $localData = base64_encode($localData);
      if ($localData === false) {
        return $data;
      }
      return $localData;
    }
    return $data;
  }

  /**
   * Create msg for cleantalk server
   * @param type $method
   * @param CleantalkRequest $request
   * @return \xmlrpcmsg
   */
  private function createMsg($method, CleantalkRequest $request) {
    switch ($method) {
      case 'check_message':

        // Convert strings to UTF8
        $request->message = $this
          ->stringToUTF8($request->message, $this->data_codepage);
        $request->example = $this
          ->stringToUTF8($request->example, $this->data_codepage);
        $request->sender_email = $this
          ->stringToUTF8($request->sender_email, $this->data_codepage);
        $request->sender_nickname = $this
          ->stringToUTF8($request->sender_nickname, $this->data_codepage);
        $request->message = $this
          ->compressData($request->message);
        $request->example = $this
          ->compressData($request->example);
        break;
      case 'check_newuser':

        // Convert strings to UTF8
        $request->sender_email = $this
          ->stringToUTF8($request->sender_email, $this->data_codepage);
        $request->sender_nickname = $this
          ->stringToUTF8($request->sender_nickname, $this->data_codepage);
        break;
      case 'send_feedback':
        if (is_array($request->feedback)) {
          $request->feedback = implode(';', $request->feedback);
        }
        break;
    }
    $request->method_name = $method;

    //
    // Removing non UTF8 characters from request, because non UTF8 or malformed characters break json_encode().
    //
    foreach ($request as $param => $value) {
      if (!preg_match('//u', $value)) {
        $request->{$param} = 'Nulled. Not UTF8 encoded or malformed.';
      }
    }
    return $request;
  }

  /**
   * Send JSON request to servers
   * @param $msg
   * @return boolean|\CleantalkResponse
   */
  private function sendRequest($data = null, $url, $server_timeout = 3) {

    // Convert to array
    $data = drupal_json_decode(drupal_json_encode($data));

    // Convert to JSON
    $data = drupal_json_encode($data);
    if (isset($this->api_version)) {
      $url = $url . $this->api_version;
    }

    // Switching to secure connection
    if ($this->ssl_on && !preg_match("/^https:/", $url)) {
      $url = preg_replace("/^(http)/i", "\$1s", $url);
    }
    $result = false;
    $curl_error = null;
    if (function_exists('curl_init')) {
      $ch = curl_init();
      curl_setopt($ch, CURLOPT_URL, $url);
      curl_setopt($ch, CURLOPT_TIMEOUT, $server_timeout);
      curl_setopt($ch, CURLOPT_POST, 1);
      curl_setopt($ch, CURLOPT_POSTFIELDS, $data);

      // receive server response ...
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

      // resolve 'Expect: 100-continue' issue
      curl_setopt($ch, CURLOPT_HTTPHEADER, array(
        'Expect:',
      ));

      // see http://stackoverflow.com/a/23322368
      curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);

      // Disabling CA cert verivication
      // Disabling common name verification
      if ($this->ssl_on) {
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
      }
      $result = curl_exec($ch);
      if (!$result) {
        $curl_error = curl_error($ch);
      }
      curl_close($ch);
    }
    if (!$result) {
      $allow_url_fopen = ini_get('allow_url_fopen');
      if (function_exists('file_get_contents') && isset($allow_url_fopen) && $allow_url_fopen == '1') {
        $opts = array(
          'http' => array(
            'method' => 'POST',
            'header' => "Content-Type: text/html\r\n",
            'content' => $data,
            'timeout' => $server_timeout,
          ),
        );
        $context = stream_context_create($opts);
        $result = @file_get_contents($url, false, $context);
      }
    }
    if (!$result) {
      $response = null;
      $response['errno'] = 1;
      if ($curl_error) {
        $response['errstr'] = sprintf("CURL error: '%s'", $curl_error);
      }
      else {
        $response['errstr'] = 'No CURL support compiled in';
      }
      $response['errstr'] .= ' or disabled allow_url_fopen in php.ini.';
      $response = (object) drupal_json_decode(drupal_json_encode($response));
      return $response;
    }
    $errstr = null;
    $response = (object) drupal_json_decode($result);
    if ($result !== false && is_object($response)) {
      $response->errno = 0;
      $response->errstr = $errstr;
    }
    else {
      $errstr = 'Unknown response from ' . $url . '.' . ' ' . $result;
      $response = null;
      $response['errno'] = 1;
      $response['errstr'] = $errstr;
      $response = (object) drupal_json_decode(drupal_json_encode($response));
    }
    return $response;
  }

  /**
   * httpRequest
   * @param $msg
   * @return boolean|\CleantalkResponse
   */
  private function httpRequest($msg) {
    $result = false;
    $msg->all_headers = drupal_json_encode(apache_request_headers());

    //$msg->remote_addr=$_SERVER['REMOTE_ADDR'];

    //$msg->sender_info['remote_addr']=$_SERVER['REMOTE_ADDR'];
    $si = drupal_json_decode($msg->sender_info);
    $si['remote_addr'] = $_SERVER['REMOTE_ADDR'];
    $msg->sender_info = drupal_json_encode($si);
    if (isset($this->work_url) && $this->work_url !== '' && $this->server_changed + $this->server_ttl > time() || $this->stay_on_server == true) {
      $url = !empty($this->work_url) ? $this->work_url : $this->server_url;
      $result = $this
        ->sendRequest($msg, $url, $this->server_timeout);
    }
    if (($result === false || $result->errno != 0) && $this->stay_on_server == false) {

      // Split server url to parts
      preg_match("@^(https?://)([^/:]+)(.*)@i", $this->server_url, $matches);
      $url_prefix = '';
      if (isset($matches[1])) {
        $url_prefix = $matches[1];
      }
      $pool = null;
      if (isset($matches[2])) {
        $pool = $matches[2];
      }
      $url_suffix = '';
      if (isset($matches[3])) {
        $url_suffix = $matches[3];
      }
      if ($url_prefix === '') {
        $url_prefix = 'http://';
      }
      if (empty($pool)) {
        return false;
      }
      else {

        // Loop until find work server
        foreach ($this
          ->get_servers_ip($pool) as $server) {
          if ($server['host'] === 'localhost' || $server['ip'] === null) {
            $work_url = $server['host'];
          }
          else {
            $server_host = $server['ip'];
            $work_url = $server_host;
          }
          $work_url = $url_prefix . $work_url;
          if (isset($url_suffix)) {
            $work_url = $work_url . $url_suffix;
          }
          $this->work_url = $work_url;
          $this->server_ttl = $server['ttl'];
          $result = $this
            ->sendRequest($msg, $this->work_url, $this->server_timeout);
          if ($result !== false && $result->errno === 0) {
            $this->server_change = true;
            break;
          }
        }
      }
    }
    $response = new CleantalkResponse(null, $result);
    if (!empty($this->data_codepage) && $this->data_codepage !== 'UTF-8') {
      if (!empty($response->comment)) {
        $response->comment = $this
          ->stringFromUTF8($response->comment, $this->data_codepage);
      }
      if (!empty($response->errstr)) {
        $response->errstr = $this
          ->stringFromUTF8($response->errstr, $this->data_codepage);
      }
      if (!empty($response->sms_error_text)) {
        $response->sms_error_text = $this
          ->stringFromUTF8($response->sms_error_text, $this->data_codepage);
      }
    }
    return $response;
  }

  /**
   * Function DNS request
   * @param $host
   * @return array
   */
  public function get_servers_ip($host) {
    $response = null;
    if (!isset($host)) {
      return $response;
    }
    if (function_exists('dns_get_record')) {
      $records = dns_get_record($host, DNS_A);
      if ($records !== FALSE) {
        foreach ($records as $server) {
          $response[] = $server;
        }
      }
    }
    if (count($response) == 0 && function_exists('gethostbynamel')) {
      $records = gethostbynamel($host);
      if ($records !== FALSE) {
        foreach ($records as $server) {
          $response[] = array(
            "ip" => $server,
            "host" => $host,
            "ttl" => $this->server_ttl,
          );
        }
      }
    }
    if (count($response) == 0) {
      $response[] = array(
        "ip" => null,
        "host" => $host,
        "ttl" => $this->server_ttl,
      );
    }
    else {

      // $i - to resolve collisions with localhost
      $i = 0;
      $r_temp = null;
      $fast_server_found = false;
      foreach ($response as $server) {

        // Do not test servers because fast work server found
        if ($fast_server_found) {
          $ping = $this->min_server_timeout;
        }
        else {
          $ping = $this
            ->httpPing($server['ip']);
          $ping = $ping * 1000;
        }

        // -1 server is down, skips not reachable server
        if ($ping != -1) {
          $r_temp[$ping + $i] = $server;
        }
        $i++;
        if ($ping < $this->min_server_timeout) {
          $fast_server_found = true;
        }
      }
      if (count($r_temp)) {
        ksort($r_temp);
        $response = $r_temp;
      }
    }
    return $response;
  }

  /**
   * Function to get the message hash from Cleantalk.ru comment
   * @param $message
   * @return null
   */
  public function getCleantalkCommentHash($message) {
    $matches = array();
    if (preg_match('/\\n\\n\\*\\*\\*.+([a-z0-9]{32}).+\\*\\*\\*$/', $message, $matches)) {
      return $matches[1];
    }
    else {
      if (preg_match('/\\<br.*\\>[\\n]{0,1}\\<br.*\\>[\\n]{0,1}\\*\\*\\*.+([a-z0-9]{32}).+\\*\\*\\*$/', $message, $matches)) {
        return $matches[1];
      }
    }
    return NULL;
  }

  /**
   * Function adds to the post comment Cleantalk.ru
   * @param $message
   * @param $comment
   * @return string
   */
  public function addCleantalkComment($message, $comment) {
    $comment = preg_match('/\\*\\*\\*(.+)\\*\\*\\*/', $comment, $matches) ? $comment : '*** ' . $comment . ' ***';
    return $message . "\n\n" . $comment;
  }

  /**
   * Function deletes the comment Cleantalk.ru
   * @param $message
   * @return mixed
   */
  public function delCleantalkComment($message) {
    $message = preg_replace('/\\n\\n\\*\\*\\*.+\\*\\*\\*$/', '', $message);

    // DLE sign cut
    $message = preg_replace('/<br\\s?\\/><br\\s?\\/>\\*\\*\\*.+\\*\\*\\*$/', '', $message);
    $message = preg_replace('/\\<br.*\\>[\\n]{0,1}\\<br.*\\>[\\n]{0,1}\\*\\*\\*.+\\*\\*\\*$/', '', $message);
    return $message;
  }

  /**
   *   Get user IP behind proxy server
   */
  public function ct_session_ip($data_ip) {
    if (!$data_ip || !preg_match("/^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\$/", $data_ip)) {
      return $data_ip;
    }

    /*if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {

                $forwarded_ip = explode(",", $_SERVER['HTTP_X_FORWARDED_FOR']);

                // Looking for first value in the list, it should be sender real IP address
                if (!preg_match("/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/", $forwarded_ip[0])) {
                    return $data_ip;
                }

                $private_src_ip = false;
                $private_nets = array(
                    '10.0.0.0/8',
                    '127.0.0.0/8',
                    '176.16.0.0/12',
                    '192.168.0.0/16',
                );

                foreach ($private_nets as $v) {

                    // Private IP found
                    if ($private_src_ip) {
                        continue;
                    }

                    if ($this->net_match($v, $data_ip)) {
                        $private_src_ip = true;
                    }
                }
                if ($private_src_ip) {
                    // Taking first IP from the list HTTP_X_FORWARDED_FOR
                    $data_ip = $forwarded_ip[0];
                }
            }

            return $data_ip;*/
    return cleantalk_get_real_ip();
  }

  /**
   * From http://php.net/manual/en/function.ip2long.php#82397
   */
  public function net_match($CIDR, $IP) {
    list($net, $mask) = explode('/', $CIDR);
    return (ip2long($IP) & ~((1 << 32 - $mask) - 1)) == ip2long($net);
  }

  /**
   * Function to check response time
   * param string
   * @return int
   */
  function httpPing($host) {

    // Skip localhost ping cause it raise error at fsockopen.
    // And return minimun value
    if ($host == 'localhost') {
      return 0.001;
    }
    $starttime = microtime(true);
    $file = @fsockopen($host, 80, $errno, $errstr, $this->server_timeout);
    $stoptime = microtime(true);
    $status = 0;
    if (!$file) {
      $status = -1;

      // Site is down
    }
    else {
      fclose($file);
      $status = $stoptime - $starttime;
      $status = round($status, 4);
    }
    return $status;
  }

  /**
   * Function convert string to UTF8 and removes non UTF8 characters
   * param string
   * param string
   * @return string
   */
  function stringToUTF8($str, $data_codepage = null) {
    if (!preg_match('//u', $str) && function_exists('mb_detect_encoding') && function_exists('mb_convert_encoding')) {
      if ($data_codepage !== null) {
        return mb_convert_encoding($str, 'UTF-8', $data_codepage);
      }
      $encoding = mb_detect_encoding($str);
      if ($encoding) {
        return mb_convert_encoding($str, 'UTF-8', $encoding);
      }
    }
    return $str;
  }

  /**
   * Function convert string from UTF8
   * param string
   * param string
   * @return string
   */
  function stringFromUTF8($str, $data_codepage = null) {
    if (preg_match('//u', $str) && function_exists('mb_convert_encoding') && $data_codepage !== null) {
      return mb_convert_encoding($str, $data_codepage, 'UTF-8');
    }
    return $str;
  }

}

/**
 * Function gets access key automatically
 *
 * @param string website admin email
 * @param string website host
 * @param string website platform
 * @return type
 */
function getAutoKey($email, $host, $platform) {
  $request = array();
  $request['method_name'] = 'get_api_key';
  $request['email'] = $email;
  $request['website'] = $host;
  $request['platform'] = $platform;
  $url = 'https://api.cleantalk.org';
  $result = sendRawRequest($url, $request);
  return $result;
}

/**
 * Function gets information about renew notice
 *
 * @param string api_key
 * @return type
 */
function noticePaidTill($api_key) {
  $request = array();
  $request['method_name'] = 'notice_paid_till';
  $request['auth_key'] = $api_key;
  $url = 'https://api.cleantalk.org';
  $result = sendRawRequest($url, $request);
  return $result;
}

/**
 * Function sends raw request to API server
 *
 * @param string url of API server
 * @param array data to send
 * @param boolean is data have to be JSON encoded or not
 * @param integer connect timeout
 * @return type
 */
function sendRawRequest($url, $data, $isJSON = false, $timeout = 3) {
  $result = null;
  if (!$isJSON) {
    $data = http_build_query($data);
  }
  else {
    $data = json_encode($data);
  }
  $curl_exec = false;
  if (function_exists('curl_init') && function_exists('json_decode')) {
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $data);

    // receive server response ...
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

    // resolve 'Expect: 100-continue' issue
    curl_setopt($ch, CURLOPT_HTTPHEADER, array(
      'Expect:',
    ));
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    $result = @curl_exec($ch);
    if ($result !== false) {
      $curl_exec = true;
    }
    @curl_close($ch);
  }
  if (!$curl_exec) {
    $opts = array(
      'http' => array(
        'method' => "POST",
        'content' => $data,
      ),
    );
    $context = stream_context_create($opts);
    $result = @file_get_contents($url, 0, $context);
  }
  return $result;
}
if (!function_exists('apache_request_headers')) {
  function apache_request_headers() {
    $arh = array();
    $rx_http = '/\\AHTTP_/';
    foreach ($_SERVER as $key => $val) {
      if (preg_match($rx_http, $key)) {
        $arh_key = preg_replace($rx_http, '', $key);
        $rx_matches = array();
        $rx_matches = explode('_', $arh_key);
        if (count($rx_matches) > 0 and strlen($arh_key) > 2) {
          foreach ($rx_matches as $ak_key => $ak_val) {
            $rx_matches[$ak_key] = ucfirst($ak_val);
          }
          $arh_key = implode('-', $rx_matches);
        }
        $arh[$arh_key] = $val;
      }
    }
    return $arh;
  }
}
function cleantalk_get_real_ip() {
  if (function_exists('apache_request_headers')) {
    $headers = apache_request_headers();
  }
  else {
    $headers = $_SERVER;
  }
  if (array_key_exists('X-Forwarded-For', $headers) && filter_var($headers['X-Forwarded-For'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
    $the_ip = $headers['X-Forwarded-For'];
  }
  elseif (array_key_exists('HTTP_X_FORWARDED_FOR', $headers) && filter_var($headers['HTTP_X_FORWARDED_FOR'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
    $the_ip = $headers['HTTP_X_FORWARDED_FOR'];
  }
  else {
    $the_ip = filter_var($_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);
  }
  return $the_ip;
}

/*
*
*
*   END OF CLEANTALK BASE CLASS
*
*/
function cleantalk_page_build(&$page) {
  drupal_session_start();
  $ct_check_def = '0';
  $ct_check_value = _cleantalk_get_checkjs_value();
  $js_template = 'function ctSetCookie(c_name, value, def_value) {
  document.cookie = c_name + "=" + escape(value.replace(/^def_value$/, value)) + "; path=/";
}
setTimeout("ctSetCookie(\\"%s\\", \\"%s\\", \\"%s\\");",1000);';
  $js_addon_body = sprintf($js_template, 'ct_checkjs', $ct_check_value, $ct_check_def);
  drupal_add_js($js_addon_body, array(
    'type' => 'inline',
    'scope' => 'footer',
    'weight' => 5,
    'cache' => FALSE,
    'every_page' => TRUE,
  ));
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function cleantalk_form_user_register_form_alter(&$form, &$form_state, $form_id) {
  _cleantalk_form_alter($form, $form_state, $form_id);
}

/**
 * Implements hook_form_BASE_FORM_ID_alter().
 */
function cleantalk_form_comment_form_alter(&$form, &$form_state, $form_id) {
  _cleantalk_form_alter($form, $form_state, $form_id);
}

/**
 * Implements hook_form_BASE_FORM_ID_alter()
 */
function cleantalk_form_comment_node_webform_form_alter(&$form, &$form_state, $form_id) {
  _cleantalk_form_alter($form, $form_state, $form_id);
}

/**
 * Implements hook_form_BASE_FORM_ID_alter()
 */
function cleantalk_form_mailchimp_signup_subscribe_form_alter(&$form, &$form_state, $form_id) {
  drupal_session_start();
  $_SESSION['ct_submit_comment_time'] = REQUEST_TIME;
  $field_name = 'ct_checkjs';
  $ct_check_def = '0';
  if (!isset($_COOKIE[$field_name])) {
    setcookie($field_name, $ct_check_def, 0, '/');
  }

  // We cannot place JS in separate file.
  // Because it is not static - we have to use generated values.

  /*  $ct_check_value = _cleantalk_get_checkjs_value();
    $js_template = 'function ctSetCookie(c_name, value, def_value) {
    document.cookie = c_name + "=" + escape(value.replace(/^def_value$/, value)) + "; path=/";
  }
  setTimeout("ctSetCookie(\"%s\", \"%s\", \"%s\");",1000);';
    $js_addon_body = sprintf($js_template, $field_name, $ct_check_value, $ct_check_def);

    drupal_add_js($js_addon_body,
      array(
        'type' => 'inline',
        'scope' => 'footer',
        'weight' => 5,
        'cache' => FALSE,
        'every_page' => FALSE,
      )
    );*/
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function cleantalk_form_contact_site_form_alter(&$form, &$form_state, $form_id) {
  _cleantalk_form_alter($form, $form_state, $form_id);
}

/**
 * Implements hook_form_FORM_ID_alter().
 */
function cleantalk_form_contact_personal_form_alter(&$form, &$form_state, $form_id) {
  _cleantalk_form_alter($form, $form_state, $form_id);
}

/**
 * Implements hook_user_presave().
 */
function cleantalk_user_presave(&$edit, $account, $category) {
  $ct_result = _cleantalk_ct_result();
  if ($account->is_new && @empty($ct_result['ct_request_id'])) {
    $spam_check = array();
    $spam_check['type'] = 'register';
    $spam_check['sender_email'] = !empty($_POST['mail']) ? $_POST['mail'] : '';
    $spam_check['sender_nickname'] = !empty($_POST['name']) ? $_POST['name'] : '';
    $spam_result = _cleantalk_check_spam($spam_check);
    if (isset($spam_result) && is_array($spam_result) && $spam_result['errno'] == 0 && $spam_result['allow'] != 1) {
      _cleantalk_die($spam_result['ct_result_comment']);
    }
  }
}

/**
 * Cleantalk registration validation function.
 */
function cleantalk_validate_register(&$form, &$form_state) {
  $spam_check = array();
  $spam_check['type'] = 'register';
  $spam_check['sender_email'] = !empty($form_state['values']['mail']) ? $form_state['values']['mail'] : '';
  $spam_check['sender_nickname'] = !empty($form_state['values']['name']) ? $form_state['values']['name'] : '';
  $spam_check['timezone'] = !empty($form_state['values']['timezone']) ? $form_state['values']['timezone'] : '';
  $spam_result = _cleantalk_check_spam($spam_check);
  if (isset($spam_result) && is_array($spam_result) && $spam_result['errno'] == 0 && $spam_result['allow'] != 1) {

    // Value of ct_result_comment is sanitized already (before storing).
    form_set_error('mail', $spam_result['ct_result_comment']);
  }
}

/**
 * Cleantalk comment validation function.
 */
function cleantalk_validate_comment(&$form, &$form_state) {
  global $user;

  // Don't check reged user with >= 'cleantalk_comments' approved msgs.
  if ($user->uid > 0) {
    $result = db_query('SELECT count(*) AS count FROM {comment} WHERE uid=:uid AND status=1', array(
      ':uid' => $user->uid,
    ));
    $count = intval($result
      ->fetchObject()->count);
    $ct_comments = variable_get('cleantalk_comments', 3);
    if ($count >= $ct_comments) {
      return;
    }
  }
  $comment_lang = array_key_exists('language', $form_state['values']) ? $form_state['values']['language'] : LANGUAGE_NONE;
  $comment_body = $form_state['values']['comment_body'][$comment_lang][0];
  $spam_check = array();
  $spam_check['type'] = 'comment';
  $spam_check['sender_email'] = !empty($form_state['values']['mail']) ? $form_state['values']['mail'] : '';
  $spam_check['sender_nickname'] = !empty($form_state['values']['name']) ? $form_state['values']['name'] : '';
  $spam_check['message_title'] = !empty($form_state['values']['subject']) ? $form_state['values']['subject'] : '';
  $spam_check['message_body'] = isset($comment_body['value']) ? $comment_body['value'] : '';
  $spam_result = _cleantalk_check_spam($spam_check);
  if (isset($spam_result) && is_array($spam_result) && $spam_result['errno'] == 0 && $spam_result['allow'] != 1 && $spam_result['stop_queue'] == 1) {

    // Value of ct_result_comment is sanitized already (before storing).
    form_set_error('comment_body', $spam_result['ct_result_comment']);
  }
}

/**
 * Cleantalk contact message validation function.
 */
function cleantalk_validate_contact_message(&$form, &$form_state) {
  global $user;

  // Don't check reged user with >= 'cleantalk_comments' approved msgs.
  if ($user->uid > 0) {
    $result = db_query('SELECT count(*) AS count FROM {comment} WHERE uid=:uid AND status=1', array(
      ':uid' => $user->uid,
    ));
    $count = intval($result
      ->fetchObject()->count);
    $ct_comments = variable_get('cleantalk_comments', 3);
    if ($count >= $ct_comments) {
      return;
    }
  }
  $spam_check = array();
  $spam_check['type'] = 'contact';
  $spam_check['sender_email'] = !empty($form_state['values']['mail']) ? $form_state['values']['mail'] : '';
  $spam_check['sender_nickname'] = !empty($form_state['values']['name']) ? $form_state['values']['name'] : '';
  $spam_check['message_title'] = !empty($form_state['values']['subject']) ? $form_state['values']['subject'] : '';
  $spam_check['message_body'] = !empty($form_state['values']['message']) ? $form_state['values']['message'] : '';
  $spam_result = _cleantalk_check_spam($spam_check);
  if (isset($spam_result) && is_array($spam_result) && $spam_result['errno'] == 0 && $spam_result['allow'] != 1 && $spam_result['stop_queue'] == 1) {

    // Value of ct_result_comment is sanitized already (before storing).
    form_set_error('comment_body', $spam_result['ct_result_comment']);
  }
}

/**
 * Implements hook_comment_presave().
 */
function cleantalk_comment_presave($comment) {
  $ct_result = _cleantalk_ct_result();
  if (!empty($ct_result['ct_request_id'])) {
    $ct_automod = variable_get('cleantalk_automod', 1);
    if ($ct_automod == 1) {

      // Automoderation enabled - change comment status.
      // Not empty 'ct_result_comment' means bad comment, set status = 0.
      // Empty 'ct_result_comment' means good comment, set status = 1.
      $comment->status = empty($ct_result['ct_result_comment']) ? COMMENT_PUBLISHED : COMMENT_NOT_PUBLISHED;
    }

    // Don't clear 'ct_request_id', use it in cleantalk_comment_insert().
  }
}

/**
 * Implements hook_comment_insert().
 */
function cleantalk_comment_insert($comment) {
  $ct_result = _cleantalk_ct_result();
  if (!empty($ct_result['ct_request_id'])) {

    // Values of request_id and comment are stored in globals.
    // Store them in DB now.
    db_insert('cleantalk_cids')
      ->fields(array(
      'cid' => $comment->cid,
      'ct_request_id' => $ct_result['ct_request_id'],
      'ct_result_comment' => empty($ct_result['ct_result_comment']) ? '' : $ct_result['ct_result_comment'],
    ))
      ->execute();
    _cleantalk_ct_result('set');
  }
}

/**
 * Implements hook_user_insert().
 */
function cleantalk_user_insert(&$edit, $account, $category) {
  if ($category != 'account') {
    return;
  }
  $ct_result = _cleantalk_ct_result();
  if (!empty($ct_result['ct_request_id'])) {
    db_insert('cleantalk_uids')
      ->fields(array(
      'uid' => $account->uid,
      'ct_request_id' => $ct_result['ct_request_id'],
      'ct_result_comment' => empty($ct_result['ct_result_comment']) ? '' : $GLOBALS['ct_result_comment'],
    ))
      ->execute();
    _cleantalk_ct_result('set');
  }
}

/**
 * Implements hook_comment_publish().
 */
function cleantalk_comment_publish($comment) {
  $result = db_select('cleantalk_cids', 'c')
    ->fields('c', array(
    'ct_request_id',
    'ct_result_comment',
  ))
    ->condition('cid', $comment->cid, '=')
    ->range(0, 1)
    ->execute();
  if ($result
    ->rowCount() > 0) {
    $ct_result = $result
      ->fetchObject();

    // If ct_result_comment is not empty then comment is not approved by server.
    // But we publish it then comment is approved by admin.
    // We need to send positive feedback.
    _cleantalk_send_feedback($ct_result->ct_request_id, 1);
    db_delete('cleantalk_cids')
      ->condition('cid', $comment->cid, '=')
      ->execute();
  }
}

/**
 * Implements hook_comment_delete().
 */
function cleantalk_comment_delete($comment) {
  $result = db_select('cleantalk_cids', 'c')
    ->fields('c', array(
    'ct_request_id',
    'ct_result_comment',
  ))
    ->condition('cid', $comment->cid, '=')
    ->range(0, 1)
    ->execute();
  if ($result
    ->rowCount() > 0) {
    $ct_result = $result
      ->fetchObject();

    // If ct_result_comment is empty then comment is approved by server.
    // But we delete it then comment is not approved by admin.
    // We need to send negative feedback.
    _cleantalk_send_feedback($ct_result->ct_request_id, 0);
    db_delete('cleantalk_cids')
      ->condition('cid', $comment->cid, '=')
      ->execute();
  }
}

/**
 * Implements hook_user_delete().
 */
function cleantalk_user_delete($account) {
  $result = db_select('cleantalk_uids', 'c')
    ->fields('c', array(
    'ct_request_id',
    'ct_result_comment',
  ))
    ->condition('uid', $account->uid, '=')
    ->range(0, 1)
    ->execute();
  if ($result
    ->rowCount() > 0) {
    $ct_result = $result
      ->fetchObject();

    // If ct_result_comment is empty then user is approved by server.
    // But we delete it then user is not approved by admin.
    // We need to send negative feedback.
    _cleantalk_send_feedback($ct_result->ct_request_id, 0);
    db_delete('cleantalk_uids')
      ->condition('uid', $account->uid, '=')
      ->execute();
  }
}

/**
 * Implements hook_comment_view_alter().
 */
function cleantalk_comment_view_alter(&$build) {
  if (user_access('administer comments')) {
    $result = db_select('cleantalk_cids', 'c')
      ->fields('c', array(
      'ct_request_id',
      'ct_result_comment',
    ))
      ->condition('cid', $build['#comment']->cid, '=')
      ->range(0, 1)
      ->execute();
    if ($result
      ->rowCount() > 0) {
      $ct_result = $result
        ->fetchObject();
      if (!empty($ct_result->ct_result_comment)) {

        // Value of ct_result_comment is sanitized already (before storing).
        $build['comment_body'][0]['#markup'] .= '<hr>' . $ct_result->ct_result_comment;
      }
    }
  }
}

/**
 * Implements hook_menu().
 */
function cleantalk_menu() {
  $items['admin/config/cleantalk'] = array(
    'title' => 'Antispam by CleanTalk',
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'cleantalk_settings_form',
    ),
    'access arguments' => array(
      'administer site configuration',
    ),
    'file' => 'cleantalk.admin.inc',
  );
  return $items;
}

/**
 * Implements hook_mail().
 */
function cleantalk_mail($key, &$message, $params) {
  if (isset($params['subject'])) {
    $message['subject'] = $params['subject'];
  }
  if (isset($params['body'])) {
    $message['body'][] = $params['body'];
  }
  if (isset($params['headers']) && is_array($params['headers'])) {
    $message['headers'] += $params['headers'];
  }
}

/**
 * Implements hook_libraries_info().
 *
 * For defining external CleanTalk librariy.
 */

/*function cleantalk_libraries_info() {
  // Expected to be extracted into 'sites/all/libraries/cleantalk'.
  $libraries['cleantalk'] = array(
    'name' => 'CleanTalk PHP-antispam classes',
    'vendor url' => 'http://cleantalk.org',
    'download url' => 'https://github.com/CleanTalk/php-antispam',
    'version arguments' => array(
      'file' => 'cleantalk.class.php',
      'pattern' => '/@version\s+([0-9a-zA-Z\.-]+)/',
      'lines' => 10,
    ),
    'files' => array(
      'php' => array('cleantalk.class.php'),
    ),
  );
  return $libraries;
}*/

/**
 * Cleantalk inner function - gets working server.
 */
function _cleantalk_get_ws() {
  return array(
    'work_url' => variable_get('cleantalk_work_url', 'http://moderate.cleantalk.ru'),
    'server_url' => variable_get('cleantalk_server_url', 'http://moderate.cleantalk.ru'),
    'server_ttl' => variable_get('cleantalk_server_ttl', 0),
    'server_changed' => variable_get('cleantalk_server_changed', 0),
  );
}

/**
 * Cleantalk inner function - sets working server.
 */
function _cleantalk_set_ws($work_url = 'http://moderate.cleantalk.ru', $server_url = 'http://moderate.cleantalk.ru', $server_ttl = 0, $server_changed = 0) {
  variable_set('cleantalk_work_url', $work_url);
  variable_set('cleantalk_server_url', $server_url);
  variable_set('cleantalk_server_ttl', $server_ttl);
  variable_set('cleantalk_server_changed', $server_changed);
}

/**
 * Cleantalk inner function - sends feedback to server.
 */
function _cleantalk_send_feedback($request_id, $feedback) {
  $ct_authkey = variable_get('cleantalk_authkey', '');
  $ct_ws = _cleantalk_get_ws();
  $ct = new Cleantalk();
  $ct->work_url = $ct_ws['work_url'];
  $ct->server_url = $ct_ws['server_url'];
  $ct->server_ttl = $ct_ws['server_ttl'];
  $ct->server_changed = $ct_ws['server_changed'];
  $ct_request = new CleantalkRequest();
  $ct_request->auth_key = $ct_authkey;
  $ct_request->agent = 'drupal-1120';
  $ct_request->sender_ip = ip_address();
  $ct_request->feedback = $request_id . ':' . $feedback;
  $ct
    ->sendFeedback($ct_request);
}

/**
 * Cleantalk inner function - missing CleanTalk library message for runtime.
 */

/*function _cleantalk_library_missing_message_4runtime($title, $path) {
  $t = get_t();
  return
    $t(
      '"Antispam by CleanTalk" module is NOT WORKING' .
      ' due to missing or broken CleanTalk library.'
    ) .
    ' <br />' .
    $t(
      'Please download <a target="_blank" href="@url">@title</a>, extract ' .
      'the archive and copy the contents to the following location:' .
      '<br /><code>@path</code>.',
      array(
        '@url' => 'https://github.com/CleanTalk/php-antispam',
        '@path' => $path,
        '@title' => $title,
      )
    ) .
    ' <br />' .
    $t(
      'Make sure 2 files <strong>cleantalk.class.php</strong> and ' .
      '<strong>JSON.php</strong> are located there.'
    ) .
    '<br />';
}*/

/**
 * Cleantalk inner function - alters needed form.
 */
function _cleantalk_form_alter(&$form, &$form_state, $form_id) {
  static $js_cookie_added = FALSE;

  /*if ($js_cookie_added) {
      return;
    }*/
  $ct_link = variable_get('cleantalk_link', 0);
  if ($ct_link != 0) {
    $form['terms_of_use'] = array(
      '#type' => 'item',
      '#markup' => t("<a href='https://cleantalk.org/drupal-anti-spam-module-wo-captcha'>Drupal spam</a> blocked by CleanTalk."),
      '#required' => FALSE,
    );
  }
  $js_cookie_added = TRUE;
  if ($form_id == 'user_register_form') {
    $session_time_key = 'ct_submit_register_time';
    $form['#validate'][] = 'cleantalk_validate_register';
  }
  else {
    $session_time_key = 'ct_submit_comment_time';
    if ($form_id == 'contact_site_form' || $form_id == 'contact_personal_form') {
      $form['#validate'][] = 'cleantalk_validate_contact_message';
    }
    else {
      $form['#validate'][] = 'cleantalk_validate_comment';
    }
  }
  drupal_session_start();
  $_SESSION[$session_time_key] = REQUEST_TIME;
  $field_name = 'ct_checkjs';
  $ct_check_def = '0';
  if (!isset($_COOKIE[$field_name])) {
    setcookie($field_name, $ct_check_def, 0, '/');
  }

  // We cannot place JS in separate file.
  // Because it is not static - we have to use generated values.

  /*  $ct_check_value = _cleantalk_get_checkjs_value();
    $js_template = 'function ctSetCookie(c_name, value, def_value) {
    document.cookie = c_name + "=" + escape(value.replace(/^def_value$/, value)) + "; path=/";
  }
  setTimeout("ctSetCookie(\"%s\", \"%s\", \"%s\");",1000);';
    $js_addon_body = sprintf($js_template, $field_name, $ct_check_value, $ct_check_def);

    drupal_add_js($js_addon_body,
      array(
        'type' => 'inline',
        'scope' => 'footer',
        'weight' => 5,
        'cache' => FALSE,
        'every_page' => FALSE,
      )
    );*/
}

/**
 * Cleantalk inner function - gets JavaScript checking value.
 */
function _cleantalk_get_checkjs_value() {
  return md5(variable_get('cleantalk_authkey', '') . '+' . variable_get('site_mail', ini_get('sendmail_from')));
}

/**
 * Cleantalk inner function - performs antispam checking.
 */
function _cleantalk_check_spam($spam_check) {
  $ct_authkey = variable_get('cleantalk_authkey', '');
  $ct_ws = _cleantalk_get_ws();
  $checkjs = 0;
  if (!isset($_COOKIE['ct_checkjs'])) {
    $checkjs = NULL;
  }
  elseif ($_COOKIE['ct_checkjs'] == _cleantalk_get_checkjs_value()) {
    $checkjs = 1;
  }
  else {
    $checkjs = 0;
  }
  $user_agent = $_SERVER['HTTP_USER_AGENT'];
  $refferrer = $_SERVER['HTTP_REFERER'];
  $ct = new Cleantalk();
  $ct->work_url = $ct_ws['work_url'];
  $ct->server_url = $ct_ws['server_url'];
  $ct->server_ttl = $ct_ws['server_ttl'];
  $ct->server_changed = $ct_ws['server_changed'];
  $ct_options = array(
    'access_key' => $ct_authkey,
    'cleantalk_automod' => variable_get('cleantalk_automod', ''),
  );
  $sender_info = drupal_json_encode(array(
    'cms_lang' => 'en',
    'REFFERRER' => $refferrer,
    'post_url' => $refferrer,
    'USER_AGENT' => $user_agent,
    'ct_options' => drupal_json_encode($ct_options),
  ));
  $ct_request = new CleantalkRequest();
  $ct_request->auth_key = $ct_authkey;
  $ct_request->agent = 'drupal-1120';
  $ct_request->response_lang = 'en';
  $ct_request->js_on = $checkjs;
  $ct_request->sender_info = $sender_info;
  $ct_request->sender_email = $spam_check['sender_email'];
  $ct_request->sender_nickname = $spam_check['sender_nickname'];
  $ct_request->sender_ip = ip_address();
  $ct_submit_time = NULL;
  drupal_session_start();
  switch ($spam_check['type']) {
    case 'comment':
    case 'contact':
      if (isset($_SESSION['ct_submit_comment_time'])) {
        $ct_submit_time = REQUEST_TIME - $_SESSION['ct_submit_comment_time'];
      }
      $timelabels_key = 'mail_error_comment';
      $ct_request->submit_time = $ct_submit_time;
      $ct_request->message = $spam_check['message_title'] . " \n\n" . $spam_check['message_body'];

      // Additional info.
      $post_info = '';
      $a_post_info['comment_type'] = 'comment';

      // JSON format.
      $post_info = drupal_json_encode($a_post_info);

      // Plain text format.
      if ($post_info === FALSE) {
        $post_info = '';
      }
      $ct_request->post_info = $post_info;

      // Example is obsolete now.
      $ct_request->example = '';
      $ct_result = $ct
        ->isAllowMessage($ct_request);
      break;
    case 'register':
      if (isset($_SESSION['ct_submit_register_time'])) {
        $ct_submit_time = REQUEST_TIME - $_SESSION['ct_submit_register_time'];
      }
      $timelabels_key = 'mail_error_reg';
      $ct_request->submit_time = $ct_submit_time;
      $ct_request->tz = $spam_check['timezone'];
      $ct_result = $ct
        ->isAllowUser($ct_request);
      break;
  }
  $ret_val = array();
  $ret_val['ct_request_id'] = $ct_result->id;
  if ($ct->server_change) {
    _cleantalk_set_ws($ct->work_url, $ct->server_url, $ct->server_ttl, REQUEST_TIME);
  }

  // First check errstr flag.
  if (!empty($ct_result->errstr) || !empty($ct_result->inactive) && $ct_result->inactive == 1) {

    // Cleantalk error so we go default way (no action at all).
    $ret_val['errno'] = 1;
    if ($checkjs == 0) {
      $ret_val['allow'] = 0;
    }

    // Just inform admin.
    $err_title = $_SERVER['SERVER_NAME'] . ' - CleanTalk hook error';
    if (!empty($ct_result->errstr)) {
      $ret_val['errstr'] = _cleantalk_filter_response($ct_result->errstr);
    }
    else {
      $ret_val['errstr'] = _cleantalk_filter_response($ct_result->comment);
    }
    $send_flag = FALSE;
    $result = db_select('cleantalk_timelabels', 'c')
      ->fields('c', array(
      'ct_value',
    ))
      ->condition('ct_key', $timelabels_key, '=')
      ->execute();
    if ($result
      ->rowCount() == 0) {
      $send_flag = TRUE;
    }
    elseif (REQUEST_TIME - 900 > $result
      ->fetchObject()->ct_value) {

      // 15 minutes.
      $send_flag = TRUE;
    }
    if ($send_flag) {
      db_merge('cleantalk_timelabels')
        ->key(array(
        'ct_key' => $timelabels_key,
      ))
        ->fields(array(
        'ct_value' => REQUEST_TIME,
      ))
        ->execute();
      $to = variable_get('site_mail', ini_get('sendmail_from'));
      if (!empty($to)) {
        drupal_mail($my_module, $timelabels_key, $to, language_default(), array(
          'subject' => $err_title,
          'body' => $ret_val['errstr'],
          'headers' => array(),
        ), $to, TRUE);
      }
    }
    return $ret_val;
  }
  $ret_val['errno'] = 0;
  if ($ct_result->allow == 1) {

    // Not spammer.
    $ret_val['allow'] = 1;

    // Store request_id in globals to store it in DB later.
    _cleantalk_ct_result('set', $ct_result->id);

    // Don't store 'ct_result_comment', means good comment.
  }
  else {

    // Spammer.
    $ret_val['allow'] = 0;
    $ret_val['ct_result_comment'] = _cleantalk_filter_response($ct_result->comment);

    // Check stop_queue flag.
    if ($spam_check['type'] == 'comment' && $ct_result->stop_queue == 0) {

      // Spammer and stop_queue == 0 - to manual approvement.
      $ret_val['stop_queue'] = 0;

      // Store request_id and comment in static to store them in DB later.
      // Store 'ct_result_comment' - means bad comment.
      _cleantalk_ct_result('set', $ct_result->id, $ret_val['ct_result_comment']);
    }
    else {

      // New user or Spammer and stop_queue == 1 - display form error message.
      $ret_val['stop_queue'] = 1;
    }
  }
  return $ret_val;
}

/**
 * Cleantalk inner function - performs CleanTalk comment|errstr filtering.
 */
function _cleantalk_filter_response($ct_response) {
  if (preg_match('//u', $ct_response)) {
    $err_str = preg_replace('/\\*\\*\\*/iu', '', $ct_response);
  }
  else {
    $err_str = preg_replace('/\\*\\*\\*/i', '', $ct_response);
  }
  return filter_xss($err_str, array(
    'a',
  ));
}

/**
 * Cleantalk inner function - stores spam checking result.
 */
function _cleantalk_ct_result($cmd = 'get', $id = '', $comment = '') {
  static $request_id = '';
  static $result_comment = '';
  if ($cmd == 'set') {
    $request_id = $id;
    $result_comment = $comment;
  }
  else {
    return array(
      'ct_request_id' => $request_id,
      'ct_result_comment' => $result_comment,
    );
  }
}

/**
 * Cleantalk inner function - show error message and exit.
 */
function _cleantalk_die($message) {
  print '<!DOCTYPE html><!-- Ticket #11289, IE bug fix: always pad the error page with enough characters such that it is greater than 512 bytes, even after gzip compression abcdefghijklmnopqrstuvwxyz1234567890aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz11223344556677889900abacbcbdcdcededfefegfgfhghgihihjijikjkjlklkmlmlnmnmononpopoqpqprqrqsrsrtstsubcbcdcdedefefgfabcadefbghicjkldmnoepqrfstugvwxhyz1i234j567k890laabmbccnddeoeffpgghqhiirjjksklltmmnunoovppqwqrrxsstytuuzvvw0wxx1yyz2z113223434455666777889890091abc2def3ghi4jkl5mno6pqr7stu8vwx9yz11aab2bcc3dd4ee5ff6gg7hh8ii9j0jk1kl2lmm3nnoo4p5pq6qrr7ss8tt9uuvv0wwx1x2yyzz13aba4cbcb5dcdc6dedfef8egf9gfh0ghg1ihi2hji3jik4jkj5lkl6kml7mln8mnm9ono--><html xmlns="http://www.w3.org/1999/xhtml" lang="en-US"><head>    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />    <title>Blacklisted</title>    <style type="text/css">        html {            background: #f1f1f1;        }        body {            background: #fff;            color: #444;            font-family: "Open Sans", sans-serif;            margin: 2em auto;            padding: 1em 2em;            max-width: 700px;            -webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.13);            box-shadow: 0 1px 3px rgba(0,0,0,0.13);        }        h1 {            border-bottom: 1px solid #dadada;            clear: both;            color: #666;            font: 24px "Open Sans", sans-serif;            margin: 30px 0 0 0;            padding: 0;            padding-bottom: 7px;        }        #error-page {            margin-top: 50px;        }        #error-page p {            font-size: 14px;            line-height: 1.5;            margin: 25px 0 20px;        }        a {            color: #21759B;            text-decoration: none;        }        a:hover {            color: #D54E21;        }            </style></head><body id="error-page">    <p><center><b style="color: #49C73B;">Clean</b><b style="color: #349ebf;">Talk.</b> Spam protection</center><br><br>' . $message . '<script>setTimeout("history.back()", 5000);</script></p><p><a href="javascript:history.back()">&laquo; Back</a></p></body></html>';
  drupal_exit();
}

/**
 * Inner function - Finds and returns pattern in string
 * @return null|bool
 */
function cleantalk_get_data_from_submit($value = null, $field_name = null) {
  if (!$value || !$field_name || !is_string($value)) {
    return false;
  }
  if (preg_match("/[a-z0-9_\\-]*" . $field_name . "[a-z0-9_\\-]*\$/", $value)) {
    return true;
  }
}

/**
* gets data for checking recursively
*/
function cleantalk_get_fields_any(&$email, &$message, &$nickname, &$subject, $arr) {
  foreach ($arr as $key => $value) {
    if (!is_array($value) && !is_object($value)) {
      if ($email === '' && @preg_match("/^\\S+@\\S+\\.\\S+\$/", $value)) {
        $email = $value;
      }
      else {
        if ($nickname === '' && cleantalk_get_data_from_submit($value, 'name')) {
          $nickname = $value;
        }
        else {
          if ($subject === '' && cleantalk_get_data_from_submit($value, 'subject')) {
            $subject = $value;
          }
          else {
            @($message .= "{$value}\n");
          }
        }
      }
    }
    else {
      if (!is_object($value)) {
        cleantalk_get_fields_any($email, $message, $nickname, $subject, $value);
      }
    }
  }
}

/**
 * Implements hook_boot()
 */
function cleantalk_boot() {
  if (isset($_POST['cleantalk_authkey'])) {
    $url = 'http://moderate.cleantalk.org/api2.0';
    $dt = array(
      'auth_key' => $_POST['cleantalk_authkey'],
      'method_name' => 'check_message',
      'message' => 'This message is a test to check the connection to the CleanTalk servers.',
      'example' => null,
      'agent' => 'drupal-1120',
      'sender_ip' => $_SERVER['REMOTE_ADDR'],
      'sender_email' => 'good@cleantalk.org',
      'sender_nickname' => 'CleanTalk',
      'js_on' => 1,
    );
    sendRawRequest($url, $dt, true);
  }
  $ct_ccf = variable_get('cleantalk_ccf', 0);
  if (sizeof($_POST) > 0 && !isset($_POST['form_build_id']) && !isset($_POST['form_id']) && $ct_ccf == 1) {

    //Custom Contact forms
    $sender_email = '';
    $sender_nickname = '';
    $subject = '';
    $message = '';
    $contact_form = true;
    get_fields_any($sender_email, $message, $sender_nickname, $subject, $contact_form, $_POST);
    if ($sender_email != '') {
      $ct_authkey = variable_get('cleantalk_authkey', '');
      if (!isset($_COOKIE['ct_checkjs'])) {
        $checkjs = NULL;
      }
      elseif ($_COOKIE['ct_checkjs'] == _cleantalk_get_checkjs_value()) {
        $checkjs = 1;
      }
      else {
        $checkjs = 0;
      }
      $data = array(
        'type' => 'comment',
        'auth_key' => $ct_authkey,
        'method_name' => 'check_message',
        'message' => $message,
        'example' => null,
        'agent' => 'drupal-1120',
        'sender_ip' => $_SERVER['REMOTE_ADDR'],
        'sender_email' => $sender_email,
        'sender_nickname' => $sender_nickname,
        'message_title' => $subject,
        'message_body' => '',
        'example_title' => '',
        'example_body' => '',
        'example_comments' => '',
        'comment_body' => '',
        'js_on' => $checkjs,
      );
      if (!function_exists('drupal_json_encode')) {
        include_once DRUPAL_ROOT . '/includes/common.inc';
      }
      if (!function_exists('libraries_load')) {
        include_once drupal_get_path('module', 'libraries') . '/libraries.module';
      }
      $result = _cleantalk_check_spam($data);
      if ($result['allow'] === 0) {
        drupal_set_message($result['ct_result_comment'], 'error');
      }
    }
  }
  if (isset($_POST['mergevars'])) {
    $sender_email = null;
    $message = '';
    foreach ($_POST['mergevars'] as $key => $value) {
      if ($sender_email === null && preg_match("/^\\S+@\\S+\\.\\S+\$/", $value)) {
        $sender_email = $value;
      }
      else {
        $message .= "{$value}\n";
      }
    }
    if ($sender_email != null) {
      $url = 'http://moderate.cleantalk.org/api2.0';
      $ct_authkey = variable_get('cleantalk_authkey', '');
      if (!isset($_COOKIE['ct_checkjs'])) {
        $checkjs = NULL;
      }
      elseif ($_COOKIE['ct_checkjs'] == _cleantalk_get_checkjs_value()) {
        $checkjs = 1;
      }
      else {
        $checkjs = 0;
      }
      $data = array(
        'type' => 'comment',
        'auth_key' => $ct_authkey,
        'method_name' => 'check_message',
        'message' => $message,
        'example' => null,
        'agent' => 'drupal-1120',
        'sender_ip' => $_SERVER['REMOTE_ADDR'],
        'sender_email' => $sender_email,
        'sender_nickname' => '',
        'message_title' => '',
        'message_body' => '',
        'example_title' => '',
        'example_body' => '',
        'example_comments' => '',
        'comment_body' => '',
        'js_on' => $checkjs,
      );
      if (!function_exists('drupal_json_encode')) {
        include_once DRUPAL_ROOT . '/includes/common.inc';
      }
      if (!function_exists('libraries_load')) {
        include_once drupal_get_path('module', 'libraries') . '/libraries.module';
      }
      $result = _cleantalk_check_spam($data);
      if ($result['allow'] === 0) {
        drupal_set_message($result['ct_result_comment'], 'error');
        $_POST['mergevars']['EMAIL'] = '';
      }
    }
  }
}

/**
 * Implements hook_webform_submission_presave()
 */
function cleantalk_webform_submission_presave($node, &$submission) {
  global $user;

  // Don't check reged user with >= 'cleantalk_comments' approved msgs.
  if ($user->uid > 0) {
    $result = db_query('SELECT count(*) AS count FROM {comment} WHERE uid=:uid AND status=1', array(
      ':uid' => $user->uid,
    ));
    $count = intval($result
      ->fetchObject()->count);
    $ct_comments = variable_get('cleantalk_comments', 3);
    if ($count >= $ct_comments) {
      return;
    }
  }
  $sender_email = null;
  $message = '';
  foreach ($_POST['submitted'] as $key => $value) {
    if ($sender_email === null && !is_array($value) && preg_match("/^\\S+@\\S+\\.\\S+\$/", $value)) {
      $sender_email = $value;
    }
    else {
      $message .= "{$value}\n";
    }
  }
  $spam_check = array();
  $spam_check['type'] = 'comment';
  $spam_check['sender_email'] = !empty($sender_email) ? $sender_email : '';
  $spam_check['sender_nickname'] = '';
  $spam_check['message_title'] = '';
  $spam_check['message_body'] = $message;
  $spam_check['example_title'] = '';
  $spam_check['example_body'] = '';
  $spam_check['example_comments'] = '';
  $spam_result = _cleantalk_check_spam($spam_check);
  if (isset($spam_result) && is_array($spam_result) && $spam_result['errno'] == 0 && $spam_result['allow'] != 1 && $spam_result['stop_queue'] == 1) {
    $ct_automod = variable_get('cleantalk_automod', 1);
    if ($ct_automod == 1) {
      $submission->is_draft = empty($spam_result['ct_result_comment']) ? 0 : 1;
    }
    drupal_set_message($spam_result['ct_result_comment'], 'error');
  }
}

/*
* implemments hook_uc_order - UberCart hook for order processing
*/
function cleantalk_uc_order($op, $order, $arg2) {
  global $cleantalk_executed;
  $email = '';
  $message = '';
  $nickname = '';
  $subject = '';
  cleantalk_get_fields_any($email, $message, $nickname, $subject, $_POST);
  if ($email != '' && !$cleantalk_executed && $op != 'total' && $op != 'presave' && $op != 'save') {
    $spam_check = array();
    $spam_check['type'] = 'comment';
    $spam_check['sender_email'] = $email;
    $spam_check['sender_nickname'] = $nickname;
    $spam_check['message_title'] = $subject;
    $spam_check['message_body'] = $message;
    $spam_check['example_title'] = '';
    $spam_check['example_body'] = '';
    $spam_check['example_comments'] = '';
    $spam_result = _cleantalk_check_spam($spam_check);
    $cleantalk_executed = true;
    if (isset($spam_result) && is_array($spam_result) && $spam_result['errno'] == 0 && $spam_result['allow'] != 1 && $spam_result['stop_queue'] == 1) {
      if (strpos($_SERVER['REQUEST_URI'], 'ajax') !== false) {
        print $spam_result['ct_result_comment'];
        drupal_exit();
      }
      else {
        _cleantalk_die($spam_result['ct_result_comment']);
      }
    }
  }
}
function cleantalk_install() {
  $spam_check = array();
  $spam_check['type'] = 'comment';
  $spam_check['sender_email'] = 'good@cleantalk.org';
  $spam_check['sender_nickname'] = 'CleanTalk';
  $spam_check['message_title'] = '';
  $spam_check['message_body'] = 'This message is a test to check the connection to the CleanTalk servers.';
  $spam_check['example_title'] = '';
  $spam_check['example_body'] = '';
  $spam_check['example_comments'] = '';
  if (!function_exists('drupal_json_encode')) {
    include_once DRUPAL_ROOT . '/includes/common.inc';
  }
  if (!function_exists('libraries_load')) {
    include_once drupal_get_path('module', 'libraries') . '/libraries.module';
  }
  $spam_result = _cleantalk_check_spam($spam_check);
}

/**
 * Inner function - Finds and returns pattern in string
 * @return null|bool
 */
function get_data_from_submit($value = null, $field_name = null) {
  if (!$value || !$field_name || !is_string($value)) {
    return false;
  }
  if (preg_match("/[a-z0-9_\\-]*" . $field_name . "[a-z0-9_\\-]*\$/", $value)) {
    return true;
  }
}

/*
* Get data from submit recursively
*/
function get_fields_any(&$email, &$message, &$nickname, &$subject, &$contact, $arr) {
  $skip_params = array(
    'ipn_track_id',
    // PayPal IPN #
    'txn_type',
    // PayPal transaction type
    'payment_status',
  );
  foreach ($arr as $key => $value) {
    if (!is_array($value) && !is_object($value)) {
      if (in_array($key, $skip_params) && $key != 0 && $key != '' || preg_match("/^ct_checkjs/", $key)) {
        $contact = false;
      }
      if ($email === '' && preg_match("/^\\S+@\\S+\\.\\S+\$/", $value)) {
        $email = $value;
      }
      else {
        if ($nickname === '' && get_data_from_submit($value, 'name')) {
          $nickname = $value;
        }
        else {
          if ($subject === '' && get_data_from_submit($value, 'subject')) {
            $subject = $value;
          }
          else {
            $message .= "{$value}\n";
          }
        }
      }
    }
    else {
      get_fields_any($email, $message, $nickname, $subject, $contact, $value);
    }
  }
}

Functions

Namesort descending Description
cleantalk_boot Implements hook_boot()
cleantalk_comment_delete Implements hook_comment_delete().
cleantalk_comment_insert Implements hook_comment_insert().
cleantalk_comment_presave Implements hook_comment_presave().
cleantalk_comment_publish Implements hook_comment_publish().
cleantalk_comment_view_alter Implements hook_comment_view_alter().
cleantalk_form_comment_form_alter Implements hook_form_BASE_FORM_ID_alter().
cleantalk_form_comment_node_webform_form_alter Implements hook_form_BASE_FORM_ID_alter()
cleantalk_form_contact_personal_form_alter Implements hook_form_FORM_ID_alter().
cleantalk_form_contact_site_form_alter Implements hook_form_FORM_ID_alter().
cleantalk_form_mailchimp_signup_subscribe_form_alter Implements hook_form_BASE_FORM_ID_alter()
cleantalk_form_user_register_form_alter Implements hook_form_FORM_ID_alter().
cleantalk_get_data_from_submit Inner function - Finds and returns pattern in string
cleantalk_get_fields_any gets data for checking recursively
cleantalk_get_real_ip
cleantalk_install
cleantalk_mail Implements hook_mail().
cleantalk_menu Implements hook_menu().
cleantalk_page_build
cleantalk_uc_order
cleantalk_user_delete Implements hook_user_delete().
cleantalk_user_insert Implements hook_user_insert().
cleantalk_user_presave Implements hook_user_presave().
cleantalk_validate_comment Cleantalk comment validation function.
cleantalk_validate_contact_message Cleantalk contact message validation function.
cleantalk_validate_register Cleantalk registration validation function.
cleantalk_webform_submission_presave Implements hook_webform_submission_presave()
getAutoKey Function gets access key automatically
get_data_from_submit Inner function - Finds and returns pattern in string
get_fields_any
noticePaidTill Function gets information about renew notice
sendRawRequest Function sends raw request to API server
_cleantalk_check_spam Cleantalk inner function - performs antispam checking.
_cleantalk_ct_result Cleantalk inner function - stores spam checking result.
_cleantalk_die Cleantalk inner function - show error message and exit.
_cleantalk_filter_response Cleantalk inner function - performs CleanTalk comment|errstr filtering.
_cleantalk_form_alter Cleantalk inner function - alters needed form.
_cleantalk_get_checkjs_value Cleantalk inner function - gets JavaScript checking value.
_cleantalk_get_ws Cleantalk inner function - gets working server.
_cleantalk_send_feedback Cleantalk inner function - sends feedback to server.
_cleantalk_set_ws Cleantalk inner function - sets working server.

Classes

Namesort descending Description
Cleantalk Cleantalk class create request
CleantalkRequest Request class
CleantalkResponse Response class