From 7196e623cfc68d9e996aa45901e62f0a77b130c6 Mon Sep 17 00:00:00 2001 From: garvinhicking Date: Tue, 18 Apr 2006 10:04:30 +0000 Subject: [PATCH] Add Akismet antispam support --- .../lang_en.inc.php | 6 + .../serendipity_event_spamblock.php | 257 ++++++++++++++---- 2 files changed, 212 insertions(+), 51 deletions(-) diff --git a/plugins/serendipity_event_spamblock/lang_en.inc.php b/plugins/serendipity_event_spamblock/lang_en.inc.php index bc98a2d..3a3fce8 100644 --- a/plugins/serendipity_event_spamblock/lang_en.inc.php +++ b/plugins/serendipity_event_spamblock/lang_en.inc.php @@ -100,3 +100,9 @@ @define('PLUGIN_EVENT_SPAMBLOCK_HIDE', 'Disable spamblock for Authors'); @define('PLUGIN_EVENT_SPAMBLOCK_HIDE_DESC', 'You can allow authors in the following usergroups to post comments without them being checked by the spamblock plugin.'); + +@define('PLUGIN_EVENT_SPAMBLOCK_AKISMET', 'Akismet API Key'); +@define('PLUGIN_EVENT_SPAMBLOCK_AKISMET_DESC', 'Akismet.com is a central anti-spam and blacklisting server. It can analyze your incoming comments and check if that comment has been listed as Spam. Akismet was developed for WordPress specifically, but can be used by other systems. You just need an API Key from http://www.akismet.com by registering an account at http://www.wordpress.com/. If you leave this API key empty, Akismet will not be used.'); +@define('PLUGIN_EVENT_SPAMBLOCK_AKISMET_FILTER', 'How to treat Akismet-reported spam'); +@define('PLUGIN_EVENT_SPAMBLOCK_REASON_AKISMET_SPAMLIST', 'Filtered by Akismet.com Blacklist'); + diff --git a/plugins/serendipity_event_spamblock/serendipity_event_spamblock.php b/plugins/serendipity_event_spamblock/serendipity_event_spamblock.php index b9fdc09..c7f3ec9 100644 --- a/plugins/serendipity_event_spamblock/serendipity_event_spamblock.php +++ b/plugins/serendipity_event_spamblock/serendipity_event_spamblock.php @@ -34,7 +34,7 @@ var $filter_defaults; 'smarty' => '2.6.7', 'php' => '4.1.0' )); - $propbag->add('version', '1.40'); + $propbag->add('version', '1.50'); $propbag->add('event_hooks', array( 'frontend_saveComment' => true, 'external_plugin' => true, @@ -43,7 +43,31 @@ var $filter_defaults; 'backend_comments_top' => true, 'backend_view_comment' => true )); - $propbag->add('configuration', array('killswitch', 'hide_for_authors', 'bodyclone', 'entrytitle', 'ipflood', 'captchas', 'captchas_ttl', 'captcha_color', 'forcemoderation', 'disable_api_comments', 'trackback_check_url', 'links_moderate', 'links_reject', 'contentfilter_activate', 'contentfilter_urls', 'bloggdeblacklist', 'contentfilter_authors', 'hide_email', 'checkmail', 'required_fields', 'logtype', 'logfile')); + $propbag->add('configuration', array( + 'killswitch', + 'hide_for_authors', + 'bodyclone', + 'entrytitle', + 'ipflood', + 'captchas', + 'captchas_ttl', + 'captcha_color', + 'forcemoderation', + 'disable_api_comments', + 'trackback_check_url', + 'links_moderate', + 'links_reject', + 'contentfilter_activate', + 'contentfilter_urls', + 'contentfilter_authors', + 'bloggdeblacklist', + 'akismet', + 'akismet_filter', + 'hide_email', + 'checkmail', + 'required_fields', + 'logtype', + 'logfile')); $propbag->add('groups', array('ANTISPAM')); $this->filter_defaults = array( @@ -176,6 +200,32 @@ var $filter_defaults; break; + case 'akismet': + $propbag->add('type', 'string'); + $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_AKISMET); + $propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_AKISMET_DESC); + $propbag->add('default', ''); + $propbag->add('radio', array( + 'value' => array('moderate', 'reject', 'none'), + 'desc' => array(PLUGIN_EVENT_SPAMBLOCK_API_MODERATE, PLUGIN_EVENT_SPAMBLOCK_API_REJECT, NONE) + )); + $propbag->add('radio_per_row', '1'); + + break; + + case 'akismet_filter': + $propbag->add('type', 'radio'); + $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_AKISMET_FILTER); + $propbag->add('description', ''); + $propbag->add('default', 'reject'); + $propbag->add('radio', array( + 'value' => array('moderate', 'reject', 'none'), + 'desc' => array(PLUGIN_EVENT_SPAMBLOCK_API_MODERATE, PLUGIN_EVENT_SPAMBLOCK_API_REJECT, NONE) + )); + $propbag->add('radio_per_row', '1'); + + break; + case 'contentfilter_urls': $propbag->add('type', 'text'); $propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_FILTER_URLS); @@ -267,10 +317,95 @@ var $filter_defaults; return true; } - function getBlacklist($where) { + function &getBlacklist($where, $api_key = '', &$eventData, &$addData) { global $serendipity; + $ret = false; + if (function_exists('serendipity_request_start')) serendipity_request_start(); switch($where) { + case 'akismet.com': + $ret = array(); + $data = array( + 'blog' => $serendipity['baseURL'], + 'user_agent' => $_SERVER['HTTP_USER_AGENT'], + 'referrer' => $_SERVER['HTTP_REFERER'], + 'user_ip' => $_SERVER['REMOTE_ADDR'] != getenv('SERVER_ADDR') ? $_SERVER['REMOTE_ADDR'] : getenv('HTTP_X_FORWARDED_FOR'), + 'permalink' => serendipity_archiveURL($eventData['id'], $eventData['title'], 'serendipityHTTPPath', true, array('timestamp' => $eventData['timestamp'])), + 'comment_type' => ($addData['type'] == 'NORMAL' ? 'comment' : 'trackback'), + 'comment_author' => $addData['name'], + 'comment_author_email' => $addData['email'], + 'comment_author_url' => $addData['url'], + 'comment_content' => $addData['comment'] + ); + $opt = array( + 'method' => 'POST', + 'http' => '1.1', + 'timeout' => 20, + 'allowRedirects' => true, + 'maxRedirects' => 3 + ); + + require_once S9Y_PEAR_PATH . 'HTTP/Request.php'; + + $req = &new HTTP_Request( + 'http://rest.akismet.com/1.1/verify-key', + $opt + ); + + $req->addPostData('key', $api_key); + $req->addPostData('blog', $serendipity['baseURL']); + + if (PEAR::isError($req->sendRequest()) || $req->getResponseCode() != '200') { + $ret['is_spam'] = false; + $ret['message'] = 'API Verification Request failed'; + $this->log($this->logfile, $eventData['id'], 'API_ERROR', 'Akismet HTTP verification request failed.', $addData); + break; + } else { + // Fetch response + $reqdata = $req->getResponseBody(); + } + + if (!preg_match('@valid@i', $reqdata)) { + $ret['is_spam'] = false; + $ret['message'] = 'API Verification failed'; + $this->log($this->logfile, $eventData['id'], 'API_ERROR', 'Akismet API verification failed: ' . $reqdata, $addData); + break; + } + + $req = &new HTTP_Request( + 'http://' . $api_key . '.rest.akismet.com/1.1/comment-check', + $opt + ); + + foreach($data AS $key => $value) { + $req->addPostData($key, $value); + } + + if (PEAR::isError($req->sendRequest()) || $req->getResponseCode() != '200') { + $ret['is_spam'] = false; + $ret['message'] = 'Akismet Request failed'; + $this->log($this->logfile, $eventData['id'], 'API_ERROR', 'Akismet HTTP request failed.', $addData); + break; + } else { + // Fetch response + $reqdata = $req->getResponseBody(); + } + + if (preg_match('@true@i', $reqdata)) { + $ret['is_spam'] = true; + $ret['message'] = $reqdata; + } elseif (preg_match('@false@i', $reqdata)) { + $ret['is_spam'] = false; + $ret['message'] = $reqdata; + $this->log($this->logfile, $eventData['id'], 'API_ERROR', 'Akismet API verification failed: ' . $reqdata, $addData); + } else { + $ret['is_spam'] = false; + $ret['message'] = 'Akismet API failure'; + $this->log($this->logfile, $eventData['id'], 'API_ERROR', 'Akismet API failure: ' . $reqdata, $addData); + } + + break; + case 'blogg.de': $target = $serendipity['serendipityPath'] . PATH_SMARTY_COMPILE . '/blogg.de.blacklist.txt'; $timeout = 3600; // One hour @@ -279,8 +414,6 @@ var $filter_defaults; $data = file_get_contents($target); } else { $data = ''; - require_once S9Y_PEAR_PATH . 'HTTP/Request.php'; - if (function_exists('serendipity_request_start')) serendipity_request_start(); $req = &new HTTP_Request('http://spam.blogg.de/blacklist.txt'); @@ -298,15 +431,17 @@ var $filter_defaults; fclose($fp); } } - if (function_exists('serendipity_request_end')) serendipity_request_end(); } $blacklist = explode("\n", $data); - return $blacklist; + $ret =& $blacklist; default: - return false; + break; } + + if (function_exists('serendipity_request_end')) serendipity_request_end(); + return $ret; } function checkScheme($maxVersion) { @@ -419,7 +554,7 @@ var $filter_defaults; } $serendipity['csuccess'] = 'true'; - $logfile = $this->get_config('logfile', $serendipity['serendipityPath'] . 'spamblock.log'); + $logfile = $this->logfile = $this->get_config('logfile', $serendipity['serendipityPath'] . 'spamblock.log'); $required_fields = $this->get_config('required_fields', ''); // Check required fields @@ -473,6 +608,26 @@ var $filter_defaults; } } + // Filter Akismet Blacklist? + $akismet_apikey = $this->get_config('akismet'); + $akismet = $this->get_config('akismet_filter'); + if (!empty($akismet_apikey) && ($akismet == 'moderate' || $akismet == 'reject')) { + $spam = $this->getBlacklist('akismet.com', $akismet_apikey, $eventData, $addData); + if ($spam['is_spam'] !== false) { + if ($akismet == 'moderate') { + $this->log($logfile, $eventData['id'], 'MODERATE', PLUGIN_EVENT_SPAMBLOCK_REASON_AKISMET_SPAMLIST . ': ' . $spam['message'], $addData); + $eventData['moderate_comments'] = true; + $serendipity['csuccess'] = 'moderate'; + $serendipity['moderate_reason'] = PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY; + } else { + $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_REASON_AKISMET_SPAMLIST . ': ' . $spam['message'], $addData); + $eventData = array('allow_comments' => false); + $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY; + return false; + } + } + } + // Check Trackback URLs? if ($addData['type'] == 'TRACKBACK' && serendipity_db_bool($this->get_config('trackback_check_url'))) { require_once S9Y_PEAR_PATH . 'HTTP/Request.php'; @@ -549,54 +704,54 @@ var $filter_defaults; } } } + } - // Filter Content - $filter_bodys = explode(';', $this->get_config('contentfilter_words', $this->filter_defaults['words'])); - if (is_array($filter_bodys)) { - foreach($filter_bodys AS $filter_body) { - if (empty($filter_body)) { - continue; - } - if (preg_match('@' . $filter_body . '@', $addData['comment'])) { - if ($filter_type == 'moderate') { - $this->log($logfile, $eventData['id'], 'MODERATE', PLUGIN_EVENT_SPAMBLOCK_FILTER_WORDS, $addData); - $eventData['moderate_comments'] = true; - $serendipity['csuccess'] = 'moderate'; - $serendipity['moderate_reason'] = PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY; - } else { - $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_FILTER_WORDS, $addData); - $eventData = array('allow_comments' => false); - $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY; - return false; - } + // Filter Content + $filter_bodys = explode(';', $this->get_config('contentfilter_words', $this->filter_defaults['words'])); + if (is_array($filter_bodys)) { + foreach($filter_bodys AS $filter_body) { + if (empty($filter_body)) { + continue; + } + if (preg_match('@' . $filter_body . '@', $addData['comment'])) { + if ($filter_type == 'moderate') { + $this->log($logfile, $eventData['id'], 'MODERATE', PLUGIN_EVENT_SPAMBLOCK_FILTER_WORDS, $addData); + $eventData['moderate_comments'] = true; + $serendipity['csuccess'] = 'moderate'; + $serendipity['moderate_reason'] = PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY; + } else { + $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_FILTER_WORDS, $addData); + $eventData = array('allow_comments' => false); + $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY; + return false; } } } } + } // Content filtering end + + // Filter Blogg.de Blacklist? + $bloggdeblacklist = $this->get_config('bloggdeblacklist'); + if ($bloggdeblacklist == 'moderate' || $bloggdeblacklist == 'reject') { + $domains = $this->getBlacklist('blogg.de', '', $eventData, $addData); + if (is_array($domains)) { + foreach($domains AS $domain) { + $domain = trim($domain); + if (empty($domain)) { + continue; + } - // Filter Blogg.de Blacklist? - $bloggdeblacklist = $this->get_config('bloggdeblacklist'); - if ($bloggdeblacklist == 'moderate' || $bloggdeblacklist == 'reject') { - $domains = $this->getBlacklist('blogg.de'); - if (is_array($domains)) { - foreach($domains AS $domain) { - $domain = trim($domain); - if (empty($domain)) { - continue; - } - - if (preg_match('@' . preg_quote($domain) . '@i', $addData['url'])) { - if ($bloggdeblacklist == 'moderate') { - $this->log($logfile, $eventData['id'], 'MODERATE', PLUGIN_EVENT_SPAMBLOCK_REASON_BLOGG_SPAMLIST . ': ' . $domain, $addData); - $eventData['moderate_comments'] = true; - $serendipity['csuccess'] = 'moderate'; - $serendipity['moderate_reason'] = PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY; - } else { - $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_REASON_BLOGG_SPAMLIST . ': ' . $domain, $addData); - $eventData = array('allow_comments' => false); - $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY; - return false; - } + if (preg_match('@' . preg_quote($domain) . '@i', $addData['url'])) { + if ($bloggdeblacklist == 'moderate') { + $this->log($logfile, $eventData['id'], 'MODERATE', PLUGIN_EVENT_SPAMBLOCK_REASON_BLOGG_SPAMLIST . ': ' . $domain, $addData); + $eventData['moderate_comments'] = true; + $serendipity['csuccess'] = 'moderate'; + $serendipity['moderate_reason'] = PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY; + } else { + $this->log($logfile, $eventData['id'], 'REJECTED', PLUGIN_EVENT_SPAMBLOCK_REASON_BLOGG_SPAMLIST . ': ' . $domain, $addData); + $eventData = array('allow_comments' => false); + $serendipity['messagestack']['comments'][] = PLUGIN_EVENT_SPAMBLOCK_ERROR_BODY; + return false; } } } -- 2.39.5