'ip',
'referrer' => 'referer',
'email' => 'email',
'url' => 'url',
'body' => 'body',
'name' => 'author'
);
var $path;
function introspect(&$propbag) {
global $serendipity;
$this->title = PLUGIN_EVENT_SPAMBLOCK_BAYES_NAME;
$propbag->add ( 'description', PLUGIN_EVENT_SPAMBLOCK_BAYES_DESC);
$propbag->add ( 'name', $this->title);
$propbag->add ( 'version', '0.4.3' );
$propbag->add ( 'event_hooks', array ('frontend_saveComment' => true,
'backend_spamblock_comments_shown' => true,
'external_plugin' => true,
'backend_view_comment' => true,
'backend_comments_top' => true,
'backend_sendcomment' => true,
'backend_sidebar_entries' => true,
'backend_sidebar_entries_event_display_spamblock_bayes' => true
));
$propbag->add ( 'groups', array ('ANTISPAM' ) );
$propbag->add ( 'author', 'kleinerChemiker, Malte Paskuda, based upon b8 by Tobias Leupold');
$propbag->add('configuration', array(
'method',
'moderateBarrier',
'blockBarrier',
'autolearn',
'ignore',
'menu',
'recycler',
'recyclerdelete',
'path',
'logtype',
'logfile'
));
}
function introspect_config_item($name, &$propbag)
{
global $serendipity;
switch($name) {
case 'method':
$propbag->add('type', 'select');
$propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_METHOD);
$propbag->add('select_values', array(
'moderate' => PLUGIN_EVENT_SPAMBLOCK_BAYES_METHOD_MODERATE,
'block' => PLUGIN_EVENT_SPAMBLOCK_BAYES_METHOD_BLOCK,
'custom' => PLUGIN_EVENT_SPAMBLOCK_BAYES_METHOD_CUSTOM,
));
$propbag->add('default', 'moderation');
break;
case 'moderateBarrier':
$propbag->add('type', 'string');
$propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_BAYES_BARRIER_MODERATE);
$propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_BAYES_BARRIER_MODERATE_DESC);
$propbag->add('default', 70);
break;
case 'blockBarrier':
$propbag->add('type', 'string');
$propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_BAYES_BARRIER_BLOCK);
$propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_BAYES_BARRIER_BLOCK_DESC);
$propbag->add('default', 90);
break;
case 'autolearn':
$propbag->add('type', 'boolean');
$propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_BAYES_AUTOLEARN);
$propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_BAYES_AUTOLEARN_DESC);
$propbag->add('default', false);
break;
case 'menu':
$propbag->add('type', 'boolean');
$propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_BAYES_MENU);
$propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_BAYES_MENU_DESC);
$propbag->add('default', true);
break;
case 'recycler':
$propbag->add('type', 'boolean');
$propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_BAYES_MENU_RECYCLER);
$propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_BAYES_RECYCLER_DESC);
$propbag->add('default', true);
break;
case 'recyclerdelete':
$propbag->add('type', 'string');
$propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_BAYES_RECYCLER_DELETE);
$propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_BAYES_RECYCLER_DELETE_DESC);
$propbag->add('default', '');
return true;
break;
case 'path':
$propbag->add('type', 'string');
$propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_BAYES_PATH);
$propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_BAYES_PATH_DESC);
$propbag->add('default', $serendipity['serendipityHTTPPath'] . 'plugins/serendipity_event_spamblock_bayes/');
return true;
break;
case 'logfile':
$propbag->add('type', 'string');
$propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_BAYES_LOGFILE);
$propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_BAYES_LOGFILE_DESC);
$propbag->add('default', $serendipity['serendipityPath'] . 'spamblock-bayes.log');
break;
case 'logtype':
$propbag->add('type', 'radio');
$propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_BAYES_LOGTYPE);
$propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_BAYES_LOGTYPE_DESC);
$propbag->add('default', 'none');
$propbag->add('radio', array(
'value' => array('file', 'db', 'none'),
'desc' => array(PLUGIN_EVENT_SPAMBLOCK_BAYES_LOGTYPE_FILE, PLUGIN_EVENT_SPAMBLOCK_BAYES_LOGTYPE_DB, PLUGIN_EVENT_SPAMBLOCK_BAYES_LOGTYPE_NONE)
));
$propbag->add('radio_per_row', '1');
break;
case 'ignore':
$propbag->add('type', 'string');
$propbag->add('name', PLUGIN_EVENT_SPAMBLOCK_BAYES_IGNORE);
$propbag->add('description', PLUGIN_EVENT_SPAMBLOCK_BAYES_IGNORE_DESC);
$propbag->add('default', '');
return true;
break;
default:
return false;
}
return true;
}
function generate_content(&$title) {
$title = $this->title;
}
function install() {
$this->setupDB();
}
function learnFromOld() {
global $serendipity;
//approved comments are ham
$sql = "SELECT
author,email,url,body,ip,referer
FROM
{$serendipity['dbPrefix']}comments
WHERE
status = 'approved'
LIMIT 100;";
$ham_comments = serendipity_db_query ( $sql );
if (is_array($ham_comments[0])) {
foreach ($ham_comments as $comment) {
$this->startLearn($comment, 'ham');
}
}
//maybe unset helps against the ram-issue
unset($ham_comments);
//learn via the spamblock-log what is spam:
$sql = "SELECT
author,email,url,body,ip,referer
FROM
{$serendipity['dbPrefix']}spamblocklog
WHERE
type = 'REJECTED'
LIMIT 100;";
$spam_comments = serendipity_db_query ( $sql );
if (is_array($spam_comments[0])) {
foreach ($spam_comments as $comment) {
$this->startLearn($comment, 'spam');
}
}
}
/*
* get ratings of every part of the comment and combine
* Wrapper for classify()
* $db: true if comment is fetched from db
*/
function startClassify($comment) {
$divider = 0;
$ratings = array();
$types = array_keys($this->type);
foreach($types as $type) {
$rating = $this->classify($comment[$type], $this->type[$type]);
if (is_numeric($rating)) {
$ratings[] = $rating;
$divider++;
}
}
#catch error when failing to rate anything
if (empty($ratings)) {
return 0;
}
if($this->get_config('method', 'moderate') == 'custom') {
$spamBarrier = max(array(
$this->get_config('moderateBarrier', 70) / 100,
$this->get_config('blockBarrier', 90) / 100
));
} else {
$spamBarrier = 0.9;
}
#If a field is clearly spam, a spammer probably mixed
#its spam with valid content to fool the spamfilter.
$max_ratings = array();
$min_ratings = array();
foreach ($ratings as $rating) {
if ($rating >= $spamBarrier) {
$max_ratings[] = $rating;
}
if ($rating <= 0.1) {
$min_ratings[] = $rating;
}
}
if (count($max_ratings) > count($min_ratings)) {
return max($ratings);
}
return (array_sum($ratings) / $divider);
}
#Wrapper to call learn()
function startLearn($comment, $category) {
$types = array_keys($this->type);
foreach ($types as $type) {
$this->learn($comment[$type], $category, $this->type[$type]);
}
}
/*
* classify a string in the boundaries of 0 (ham) to 1 (spam)
* */
function classify($comment = '', $type) {
global $serendipity;
$ignore = explode(',', $this->get_config('ignore', ''));
if (in_array($type, $ignore)) {
//we ignore fields on the ignorelist
return;
}
$spam_texts = $this->get_config("{$type}_spam", 0);
$ham_texts = $this->get_config("{$type}_ham", 0);
if ($comment == '' && ! is_string($comment)) {
return false;
}
if ($spam_texts == 0 || $ham_texts == 0) {
return false;
}
if ($type == $this->type['ip']) {
$tokens = array($comment => 1);
} else {
$tokens = $this->tokenize($comment);
}
if ($tokens === false|| empty($tokens)) {
return false;
}
$words = array_keys($tokens);
foreach ($words AS $word) {
$temp[] = '\'' . serendipity_db_escape_string($word) . '\'';
}
#Die gespeicherten Werte der Tokens aus DB holen
$sql = 'SELECT token, ham, spam FROM ' . $serendipity ['dbPrefix'] . 'spamblock_bayes WHERE ' . serendipity_db_in_sql ( 'token', $temp ) .' AND type = \''. $type .'\'';
unset ($temp);
$stored_tokens = serendipity_db_query ( $sql, FALSE, 'assoc', FALSE, 'token' );
foreach($tokens as $word => $count) {
$word_count[$word] = $count;
if (!isset($stored_tokens[$word])) {
$rating = 1;
} else if (empty($word)) {
continue;
} else {
$rating = ($stored_tokens[$word]['ham'] / $ham_texts) / (($stored_tokens[$word]['ham'] / $ham_texts) + ($stored_tokens[$word]['spam'] / $spam_texts));
}
$ratings[$word] = (0.15 + (($stored_tokens[$word]['ham'] + $stored_tokens[$word]['spam']) * $rating)) / (0.3 + $stored_tokens[$word]['ham'] + $stored_tokens[$word]['spam']);
# Importance (distance to 0.5)
$importance[$word] = abs(0.5 - $ratings[$word]);
}
//importance can be null if the comment don't contains real tokens
//(like the smiley :) )
if (is_array($importance)) {
arsort($importance);
reset($importance);
}
#number of important words
$n = 0;
$probability = 0;
foreach($tokens as $word => $count) {
if ($importance[$word] > 0.2) {
$n++;
$probability += $ratings[$word];
}
}
if ( $n > 0 ) {
$probability = $probability / $n;
} else {
// was: = 1, but if undecided, we better want to be at
// "undecided" than "ham"
$probability = 0.5;
}
return abs(1 - $probability);
}
/*
* learn string as ham or spam
* $text: string
* $category: string (ham, spam)
* $type: string (ip, body, ...)
**/
function learn($text, $group, $type) {
global $serendipity;
$this->setupDB();
if ($group != 'ham' && $group != 'spam') {
return FALSE;
}
if ($text == '' or ! is_string ($text)) {
return FALSE;
}
#split text in tokens
if ($type == $this->type['ip']) {
$tokens = array( $text => 1);
} else {
$tokens = $this->tokenize($text, $type);
}
$words = array_keys($tokens);
foreach ($words AS $word) {
$temp[] = '\'' . serendipity_db_escape_string($word) . '\'';
}
#get already saved value of tokens
$sql = 'SELECT token, ' . $group . ' FROM ' . $serendipity ['dbPrefix'] . 'spamblock_bayes WHERE ' . serendipity_db_in_sql('token', $temp) . 'AND type = \'' . $type . '\' ';
unset ($temp);
$stored_values = serendipity_db_query ( $sql, FALSE, 'assoc', FALSE, 'token', $group );
#Save new amount of all tokens
foreach ($tokens as $token => $value) {
if (isset ($stored_values [$token])) {
$new_value [$token] = $stored_values [$token] + $value;
if ($serendipity['dbType'] == 'mysql') {
$sql = "INSERT INTO
{$serendipity[dbPrefix]}spamblock_bayes
(token, $group, type)
VALUES('$token', $value, '$type')
ON DUPLICATE KEY
UPDATE
$group = $group + VALUES($group);";
} else {
$sql = "UPDATE
{$serendipity[dbPrefix]}spamblock_bayes
SET
$group = $group + $value
WHERE
token = '$token' AND type = '$type';";
}
} else {
$new_value [$token] = $value;
if ($serendipity['dbType'] == 'mysql') {
$sql = "INSERT INTO
{$serendipity[dbPrefix]}spamblock_bayes
(token, $group, type)
VALUES('$token', $value, '$type')
ON DUPLICATE KEY
UPDATE
$group = $group + VALUES($group);";
} else {
$sql = "INSERT INTO
{$serendipity[dbPrefix]}spamblock_bayes
(token, $group, type)
VALUES('$token', $value, '$type')";
}
}
serendipity_db_query ($sql);
}
#Save amount of ham/spam
$this->set_config("{$type}_{$group}", $this->get_config("{$type}_{$group}", 0) + 1);
return true;
}
/*
* Split text in words
* param1: string $text
* return: array Tokens
**/
function tokenize($text = '') {
if ($text == '' or ! is_string($text)) {
return false;
}
//preg_split won't accept e.g. Umlaute as part of \w
mb_regex_encoding('UTF-8');
$tokens = mb_split("\W", $text );
#preg_match_all('/[\w]+/u', "aaa´bbb", $words);
$temp = array ();
foreach ( $tokens as $token ) {
if (isset ( $temp ["$token"] )) {
$temp ["$token"] ++;
} else {
$temp ["$token"] = 1;
}
}
#prevent the whitespaces to get saved in the database, they
#would displace more important markers
if (isset($temp[""])) {
unset($temp[""]);
}
return $temp;
}
function getAmount($category, $type) {
global $serendipity;
$sql = "SELECT $category FROM
{$serendipity['dbPrefix']}spamblock_bayes
WHERE
type = '$type'";
$ratings = serendipity_db_query($sql);
$amount = 0;
if (is_array($ratings)) {
foreach($ratings as $rating) {
$amount += $rating[0];
}
}
return $amount;
}
/**
* initialize the db at first install or change after upgrade
* */
function setupDB() {
global $serendipity;
#main-table
$sql = "CREATE TABLE
{$serendipity['dbPrefix']}spamblock_bayes (
token VARCHAR(100) NOT NULL,
ham BIGINT UNSIGNED NOT NULL DEFAULT '0',
spam BIGINT UNSIGNED NOT NULL DEFAULT '0',
type VARCHAR(20) DEFAULT '{$this->type['body']}'
) {UTF_8};";
serendipity_db_schema_import($sql);
#recycler-table
if ($serendipity['dbType'] == 'mysql') {
$sql = "CREATE TABLE
{$serendipity['dbPrefix']}spamblock_bayes_recycler
LIKE
{$serendipity['dbPrefix']}comments";
} else {
$sql = "CREATE TABLE
{$serendipity['dbPrefix']}spamblock_bayes_recycler
as SELECT * FROM
{$serendipity['dbPrefix']}comments LIMIT 1";
serendipity_db_query($sql);
$sql = "DELETE FROM
{$serendipity['dbPrefix']}spamblock_bayes_recycler;";
}
serendipity_db_query($sql);
$dbversion = $this->get_config('dbversion', 1);
if ($dbversion == '1') {
$this->updateDB1();
}
$dbversion = $this->get_config('dbversion', 1);
if ($dbversion == '2') {
$this->updateDB2();
}
}
#when upgrading to 0.3, type has to get added
function updateDB1() {
global $serendipity;
$sql = "ALTER TABLE {$serendipity['dbPrefix']}spamblock_bayes
ADD type VARCHAR(20) DEFAULT '{$this->type['body']}'";
serendipity_db_query($sql);
$sql = "ALTER TABLE {$serendipity['dbPrefix']}spamblock_bayes
DROP {PRIMARY}";
serendipity_db_schema_import($sql);
$this->set_config($this->type['body'] .'_spam' , $this->get_config('spam', 0));
$this->set_config($this->type['body'] . '_ham' , $this->get_config('ham', 0));
$this->set_config('dbversion', 2);
}
#when upgrading to 0.3.9
#This Upgrade shall give a perfomance-boost which is needed
#for proper import/export in large databases
function updateDB2() {
global $serendipity;
set_time_limit(0);
serendipity_db_begin_transaction();
#Under mySQL, we may have duplicates in the Database (hello,
#Hello) which prevent us from using an index. So we remove them.
$sql1 = "CREATE TEMPORARY TABLE {$serendipity['dbPrefix']}spamblock_bayes_temp (
token VARCHAR(100) NOT NULL,
ham BIGINT UNSIGNED NOT NULL DEFAULT '0',
spam BIGINT UNSIGNED NOT NULL DEFAULT '0',
type VARCHAR(20) DEFAULT '{$this->type['body']}',
{PRIMARY} (token, type)
) {UTF_8};";
serendipity_db_schema_import($sql1);
if ($serendipity['dbType'] == 'mysql'
|| $serendipity['dbType'] == 'mysqli') {
$sql2 = "INSERT INTO
{$serendipity['dbPrefix']}spamblock_bayes_temp
(token, ham, spam, type)
SELECT
orig.token, orig.ham, orig.spam, orig.type
FROM
{$serendipity['dbPrefix']}spamblock_bayes as orig
ON DUPLICATE KEY UPDATE
ham = {$serendipity['dbPrefix']}spamblock_bayes_temp.ham + VALUES(ham),
spam = {$serendipity['dbPrefix']}spamblock_bayes_temp.spam + VALUES(spam);";
serendipity_db_query($sql2);
} else {
$sql = "SELECT
token, ham, spam, type
FROM
{$serendipity['dbPrefix']}spamblock_bayes;";
$results = serendipity_db_query($sql);
foreach ($results as $result) {
$token = $result['token'];
$ham = $result['ham'];
$spam = $result['spam'];
$type = $result['type'];
$sql = "SELECT
token
FROM
{$serendipity['dbPrefix']}spamblock_bayes_temp
WHERE
token = '$token' AND type = '$type';";
$tester = serendipity_db_query($sql);
if (empty($tester['0'])) {
$sql2 = "INSERT INTO
{$serendipity['dbPrefix']}spamblock_bayes_temp
(token, ham, spam, type)
VALUES
('$token', $ham, $spam, '$type');";
} else {
$sql2 = "UPDATE
{$serendipity['dbPrefix']}spamblock_bayes_temp
WHERE
token = '$token' AND type = '$type'
SET
ham = ham + $ham,
spam = spam + $spam;";
}
serendipity_db_query($sql2);
}
}
$sql3 = "DROP TABLE {$serendipity['dbPrefix']}spamblock_bayes;";
serendipity_db_query($sql3);
$sql4 = "CREATE TABLE {$serendipity['dbPrefix']}spamblock_bayes (
token VARCHAR(100) NOT NULL,
ham BIGINT UNSIGNED NOT NULL DEFAULT '0',
spam BIGINT UNSIGNED NOT NULL DEFAULT '0',
type VARCHAR(20) DEFAULT '{$this->type['body']}',
{PRIMARY} (token, type)
) {UTF_8};";
serendipity_db_schema_import($sql4);
$sql5 = "INSERT INTO
{$serendipity['dbPrefix']}spamblock_bayes
(token, ham, spam, type)
SELECT
token, ham, spam, type
FROM
{$serendipity['dbPrefix']}spamblock_bayes_temp;
";
serendipity_db_schema_import($sql5);
serendipity_db_end_transaction(true);
$this->set_config('dbversion', 3);
}
function deleteDB() {
global $serendipity;
$sql = "DROP TABLE
{$serendipity['dbPrefix']}spamblock_bayes";
serendipity_db_query($sql);
foreach($this->type as $type) {
$this->set_config("{$type}_ham", 0);
$this->set_config("{$type}_spam", 0);
}
$this->set_config('dbversion', 1);
}
function checkIfSpam($comment) {
$rating = $this->startClassify($comment);
$this->lastRating = $rating;
//a rating greater 0.8 is probably spam
if ($rating >= 0.8) {
$autolearn = $this->get_config('autolearn', false);
if( ($rating > 0.9) && $autolearn) {
$this->startLearn($comment, 'spam');
}
return true;
}
return false;
}
function event_hook($event, &$bag, &$eventData, $addData = null) {
global $serendipity;
$hooks = &$bag->get ( 'event_hooks' );
if (isset ( $hooks [$event] )) {
switch ($event) {
case 'external_plugin' :
//catch learnAction here because the GET-Params prevent
//the normal switch/case to find this
if (strpos($eventData, 'learnAction') !== false) {
$this->learnAction($_REQUEST['id'], $_REQUEST['category'], $_REQUEST['action'], $_REQUEST['entry_id']);
return true;
break;
}
switch ($eventData) {
case 'learncomment':
if (!serendipity_checkPermission('adminComments')) {
break;
}
$category = $_REQUEST ['category'];
$ids = $_REQUEST ['id'];
$ids = explode(';', $ids);
foreach($ids as $id) {
$comment = $this->getComment($id);
if (is_array ($comment)) {
$comment = $comment['0'];
$entry_id = $comment['entry_id'];
}
$this->startLearn($comment, $category);
//Ham shall be approved, Spam deleted
if ($category == 'ham') {
serendipity_approveComment($id, $entry_id);
} elseif ($category == 'spam') {
if($this->get_config('method', 'moderate') == 'custom') {
$spamBarrier = min(array(
$this->get_config('moderateBarrier', 70) / 100,
$this->get_config('blockBarrier', 90) / 100
));
} else {
$spamBarrier = 0.7;
}
//spam shall not get through the filter twice - so make sure, it really is marked as spam
$loop = 0;
while ($this->startClassify($comment) < $spamBarrier && $loop < 5) {
$this->startLearn($comment, $category);
//prevent infinite loop
$loop++;
}
if ($this->get_config('recycler', true)) {
$this->recycleComment($id, $entry_id);
}
serendipity_deleteComment($id, $entry_id);
}
}
break;
case 'spamblock_bayes.load.gif':
header('Content-Type: image/gif');
echo file_get_contents(dirname(__FILE__). '/img/spamblock_bayes.load.gif');
break;
case 'spamblock_bayes.spam.png':
header('Content-Type: image/png');
echo file_get_contents(dirname(__FILE__). '/img/spamblock_bayes.spam.png');
break;
case 'jquery.tablesorter.js':
header('Content-Type: text/javascript');
echo file_get_contents(dirname(__FILE__). '/jquery.tablesorter.js');
break;
case 'jquery.heatcolor.js':
header('Content-Type: text/javascript');
echo file_get_contents(dirname(__FILE__). '/jquery.heatcolor.js');
break;
case 'jquery.excerpt.js':
header('Content-Type: text/javascript');
echo file_get_contents(dirname(__FILE__). '/jquery.excerpt.js');
break;
case 'serendipity_event_spamblock_bayes.js':
header('Content-Type: text/javascript');
echo file_get_contents(dirname(__FILE__). '/serendipity_event_spamblock_bayes.js');
break;
case 'getRating':
$ids = $_REQUEST ['id'];
$ids = explode(';', $ids);
//we get the comments in wrong order
$comments = array_reverse($this->getComment($ids));
$i = 0;
foreach ($comments as $comment) {
$ratings .= preg_replace('/\..*/', '', $this->startClassify($comment) * 100) .'%;'. $ids[$i] . ';';
$i++;
}
echo $ratings;
break;
case 'bayesMenuLearn':
if (!serendipity_checkPermission('adminComments')) {
break;
}
//the POST-Data of the form is almost exactly like the result of the database-query
$comment = $_POST;
//TODO: determine category
if (serendipity_db_bool($comment['ham'])) {
$category = 'ham';
} else {
$category = 'spam';
}
$this->startLearn($comment, $category);
$redirect= '';
echo $redirect . $url;
break;
case 'bayesLearnFromOld':
if (!serendipity_checkPermission('adminComments')) {
break;
}
$this->learnFromOld();
#redirect the user back to the menu
$redirect= '';
echo $redirect . $url;
break;
case 'bayesDeleteDatabase':
if (!serendipity_checkPermission('adminComments')) {
break;
}
$this->deleteDB();
$redirect= '';
echo $redirect . $url;
break;
case 'bayesSetupDatabase':
if (!serendipity_checkPermission('adminComments')) {
break;
}
$this->setupDB();
$redirect= '';
echo $redirect . $url;
break;
case 'bayesRecycler':
if (!serendipity_checkPermission('adminComments')) {
break;
}
if(isset($_REQUEST['restore'])) {
if ( !empty($_REQUEST['serendipity']['selected'])) {
$ids = array_keys($_REQUEST['serendipity']['selected']);
#When restoring a comment we can be pretty sure it's a valid one
$comments = $this->getRecyclerComment($ids);
foreach ($comments as $comment) {
$this->startLearn($comment, 'ham');
}
$this->restoreComments($ids);
if (in_array(0, $ids)) {
#this happened when the recyclercode was broken
$msg = "Not able to restore comment with id 0";
$msgtype = 'error';
}
if (count($ids) > 1) {
$msg = 'Comments '. implode(', ', $ids) .' restored';
} else {
$msg = 'Comment '. implode(', ', $ids) .' restored';
}
$msgtype = 'success';
} else {
$msg = 'No comment selected';
$msgtype = 'message';
}
}
if(isset($_REQUEST['empty'])) {
if (isset($_REQUEST['recyclerSpam'])) {
$comments = $this->getAllRecyclerComments();
foreach ($comments as $comment) {
$this->startLearn($comment, 'spam');
}
}
$success = $this->emptyRecycler();
if (serendipity_db_bool($success)) {
$msg = 'Recycler emptied';
$msgtype = 'success';
} else {
$msg = urlencode($success);
$msgtype = 'error';
}
}
$redirect= '';
} else {
$url .= '" />';
}
echo $redirect . $url;
break;
case 'bayesAnalyse':
if(isset($_REQUEST['comments'])) {
$comment_ids = array_keys($_REQUEST['comments']);
} else {
$msg = 'Please select at least one comment';
$msgtype = 'message';
}
$redirect= '';
} else {
$url .= '" />';
}
echo $redirect . $url;
break;
case 'bayesImport':
#Showing the menu
$redirect= '';
echo $redirect . $url;
break;
case 'bayesExportDatabase':
$this->exportDatabase();
header('Content-type: application/x-download');
header('Content-Disposition: attachment; filename=spamblock_bayes.csv');
echo file_get_contents($serendipity['serendipityPath']. 'templates_c/spamblock_bayes.csv');
}
return true;
break;
case 'frontend_saveComment' :
if (! is_array ( $eventData ) || serendipity_db_bool ( $eventData ['allow_comments'] )) {
$serendipity ['csuccess'] = 'true';
$comment = array( 'url' => $addData['url'],
'body' => $addData['comment'],
'name' => $addData['name'],
'email' => $addData['email'],
'ip' => serendipity_db_escape_string(isset($addData['ip']) ? $addData['ip'] : $_SERVER['REMOTE_ADDR']),
'referrer' => substr((isset($_SESSION['HTTP_REFERER']) ? serendipity_db_escape_string($_SESSION['HTTP_REFERER']) : ''), 0, 200)
);
if ($this->checkIfSpam($comment)) {
$method = $this->get_config('method', 'moderate');
if ($method == 'moderate') {
$this->moderate($eventData, $addData);
return false;
} elseif($method == 'block') {
$this->block($eventData, $addData);
return false;
}
}
$blockBarrier = $this->get_config('blockBarrier', 90) / 100;
$moderateBarrier = $this->get_config('moderateBarrier', 70) / 100;
//now this either wasn't spam or method custom is selected.
if ($this->lastRating > $blockBarrier) {
$this->block($eventData, $addData);
return false;
} elseif ($this->lastRating > $moderateBarrier) {
$this->moderate($eventData, $addData);
return false;
}
}
return true;
break;
case 'backend_view_comment':
$path = $this->path = $this->get_config('path', $serendipity['serendipityHTTPPath'] . 'plugins/serendipity_event_spamblock_bayes/');
if (!empty($path) && $path != 'default' && $path != 'none' && $path != 'empty') {
$path_defined = true;
$imgpath = $path . 'img/';
} else {
$path_defined = false;
$imgpath = $serendipity['baseURL'] . 'index.php?/plugin/';
}
$comment = $eventData;
//change $comment into the needed form
$comment['referrer'] = $comment[$this->type['referrer']];
$comment['name'] = $comment[$this->type['name']];
$comment['body'] = $comment['fullBody'];
unset($comment[$this->type['referrer']]);
unset($comment[$this->type['name']]);
unset($comment['fullBody']);
$eventData['action_more'] = ''. PLUGIN_EVENT_SPAMBLOCK_BAYES_HAM.'
'. PLUGIN_EVENT_SPAMBLOCK_BAYES_SPAM.'
'. preg_replace('/\..*/', '', $this->startClassify($comment) * 100) .'%
';
return true;
break;
case 'backend_sendcomment':
$delete = PLUGIN_EVENT_SPAMBLOCK_BAYES_DELETE . ': ';
$delete .= $serendipity['baseURL'] . 'index.php?/plugin/learnAction&action=delete&category=spam&id=' . $eventData['comment_id'] . '&entry_id='. $eventData['entry_id'];
$eventData['action_more']['delete'] = $delete;
if (!empty($eventData['moderate_comment']) && $eventData['moderate_comment']) {
$delete = PLUGIN_EVENT_SPAMBLOCK_BAYES_APPROVE . ': ';
$approve .= $serendipity['baseURL'] . 'index.php?/plugin/learnAction&action=approve&category=ham&id=' . $eventData['comment_id'] . '&entry_id='. $eventData['entry_id'];
$eventData['action_more']['approve'] = $approve;
}
return true;
break;
case 'backend_comments_top':
$path = $this->path = $this->get_config('path', $serendipity['serendipityHTTPPath'] . 'plugins/serendipity_event_spamblock_bayes/');
if (!empty($path) && $path != 'default' && $path != 'none' && $path != 'empty') {
$path_defined = true;
$imgpath = $path . 'img/';
} else {
$path_defined = false;
$imgpath = $serendipity['baseURL'] . 'index.php?/plugin/';
}
echo "
";
return true;
break;
case 'backend_sidebar_entries':
if ($this->get_config('menu', true)) {
echo '
'.htmlspecialchars($serendipity['GET']['message']).'
'; } if (isset($serendipity['GET']['success'])) { echo ''.htmlspecialchars($serendipity['GET']['success']).'
'; } if (isset($serendipity['GET']['error'])) { echo ''.htmlspecialchars($serendipity['GET']['error']).'
'; } $this->get = $serendipity['GET']; $this->displayMenu($serendipity['GET']['subpage']); return true; break; default : return false; break; } } else { return false; } } #Show the whole additional configuration, specifiy subpage for a specific tab function displayMenu($subpage=0) { $css = file_get_contents(dirname(__FILE__). '/serendipity_event_spamblock_bayes.css'); echo ""; #add javascript for usability if (!$serendipity['capabilities']['jquery']) { echo ''; } echo ''; #Navigation: $menuNames = array( PLUGIN_EVENT_SPAMBLOCK_BAYES_MENU_LEARN, PLUGIN_EVENT_SPAMBLOCK_BAYES_MENU_DATABASE, PLUGIN_EVENT_SPAMBLOCK_BAYES_MENU_RECYCLER, PLUGIN_EVENT_SPAMBLOCK_BAYES_MENU_ANALYSIS); $menu =''.$type.' | '; } $thead .= '|
---|---|
'.HAM.' | '; $thead .= ''.SPAM.' | '; } $thead .= '
'.$this->get_config("{$type}_ham", 0).' | '; $tbody .= ''.$this->get_config("{$type}_spam", 0).' | '; } $tbody .= '
' . PLUGIN_EVENT_SPAMBLOCK_BAYES_IMPORT_EXPLANATION . '
'; } function showAnalysis($comment_id) { $comments = $this->getComment($comment_id); for ($i=0; $i < count($comments); $i++) { $comment = $comments[$i]; if (is_array($comment_id)) { echo '"; } $names = array_keys($selectedTable[0]); $names = array_filter($names, create_function('$name', 'return ! is_numeric($name);')); foreach ($names as $name) { if (empty($include) || in_array($name, $include)) { $output .= " | $name | "; } } $output .= '|
---|---|---|
'; } foreach ($names as $name) {; if (empty($include) || in_array($name, $include)) { if (isset($formatFunctions[$name])) { $output .= " | ". $formatFunctions[$name]($column[$name])." | "; } else { $output .= "{$column[$name]} | "; } } } $output .= '