PHP Classes

File: cleantalk.class.php

Recommend this page to a friend!
  Classes of Alexey Znaev   CleanTalk PHP Spam Filter Class   cleantalk.class.php   Download  
File: cleantalk.class.php
Role: Class source
Content type: text/plain
Description: Base class
Class: CleanTalk PHP Spam Filter Class
Detect spam in comments using the CleanTalk API
Author: By
Last change: New version.
Date: 9 years ago
Size: 25,827 bytes
 

Contents

Class file image Download
<?php /** * Cleantalk base class * * @version 1.23 * @package Cleantalk * @subpackage Base * @author Сleantalk team (welcome@cleantalk.ru) * @copyright (C) 2013 СleanTalk team (http://cleantalk.org) * @license GNU/GPL: http://www.gnu.org/copyleft/gpl.html * @see https://github.com/CleanTalk/php-antispam * */ /** * Load JSON functions if they are not exists */ if(!function_exists('json_encode')) { require_once 'JSON.php'; function json_encode($data) { $json = new Services_JSON(); return( $json->encode($data) ); } } if(!function_exists('json_decode')) { require_once 'JSON.php'; function json_decode($data) { $json = new Services_JSON(); return( $json->decode($data) ); } } /** * 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 { /** * 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 = 15; /** * 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'; /** * Function checks whether it is possible to publish the message * @param CleantalkRequest $request * @return type */ public function isAllowMessage(CleantalkRequest $request) { $error_params = $this->filterRequest('check_message', $request); if (!empty($error_params)) { $response = new CleantalkResponse( array( 'allow' => 0, 'comment' => 'CleanTalk. Request params error: ' . implode(', ', $error_params) ), null); return $response; } $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) { $error_params = $this->filterRequest('check_newuser', $request); if (!empty($error_params)) { $response = new CleantalkResponse( array( 'allow' => 0, 'comment' => 'CleanTalk. Request params error: ' . implode(', ', $error_params) ), null); return $response; } $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) { $error_params = $this->filterRequest('send_feedback', $request); if (!empty($error_params)) { $response = new CleantalkResponse( array( 'allow' => 0, 'comment' => 'Cleantalk. Spam protect. Request params error: ' . implode(', ', $error_params) ), null); return $response; } $msg = $this->createMsg('send_feedback', $request); return $this->httpRequest($msg); } /** * Filter request params * @param CleantalkRequest $request * @return type */ private function filterRequest($method, CleantalkRequest $request) { $error_params = array(); // 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)) { $error_params[] = $param; } } if (in_array($param, array('stoplist_check', 'allow_links')) && !empty($value)) { if (!in_array($value, array(1, 2))) { $error_params[] = $param; } } if (in_array($param, array('js_on')) && !empty($value)) { if (!is_integer($value)) { $error_params[] = $param; } } if ($param == 'sender_ip' && !empty($value)) { if (!is_string($value)) { $error_params[] = $param; } } if ($param == 'sender_email' && !empty($value)) { if (!is_string($value)) { $error_params[] = $param; } } if ($param == 'submit_time' && !empty($value)) { if (!is_int($value)) { $error_params[] = $param; } } } // special and must be switch ($method) { case 'check_message': break; case 'check_newuser': break; case 'send_feedback': if (empty($request->feedback)) { $error_params[] = 'feedback'; } break; } return $error_params; } /** * 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; 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 = json_decode(json_encode($data), true); // Convert to JSON $data = json_encode($data); if (isset($this->api_version)) $url = $url . $this->api_version; $result = false; 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:')); $result = curl_exec($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; $response['errstr'] = 'No CURL support compiled in. Disabled allow_url_fopen in php.ini.'; $response = json_decode(json_encode($response)); return $response; } $errstr = null; $response = json_decode($result); if ($result !== false && is_object($response)) { $response->errno = 0; $response->errstr = $errstr; } else { $errstr = 'Failed connect to ' . $url . '.' . ' ' . $result; $response = null; $response['errno'] = 1; $response['errstr'] = $errstr; $response = json_decode(json_encode($response)); } return $response; } /** * httpRequest * @param $msg * @return boolean|\CleantalkResponse */ private function httpRequest($msg) { $result = false; 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 = gethostbyaddr($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 and $i = 0; $r_temp = null; foreach ($response as $server) { $ping = $this->httpPing($server['ip']); // -1 server is down, skips not reachable server if ($ping != -1) $r_temp[$ping * 10000 + $i] = $server; $i++; } 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 */ public function ct_session_ip( $data_ip ) { if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) { $forwarded_for = (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) ? htmlentities($_SERVER['HTTP_X_FORWARDED_FOR']) : ''; } // 127.0.0.1 usually used at reverse proxy $session_ip = ($data_ip == '127.0.0.1' && !empty($forwarded_for)) ? $forwarded_for : $data_ip; return $session_ip; } /** * 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; } } ?>