<?php
/*
Plugin Name: Antispam Bee
Text Domain: antispam_bee
Domain Path: /lang
Description: Easy and extremely productive spam-fighting plugin with many sophisticated solutions. Includes protection again trackback spam.
Author: Sergej Müller
Author URI: http://wpcoder.de
Plugin URI: http://antispambee.com
Version: 2.5.6
*/
/* Sicherheitsabfrage */
if ( ! class_exists('WP') ) {
die();
}
/**
* Antispam_Bee
*
* @since 0.1
* @change 2.4
*/
class Antispam_Bee {
/* Init */
public static $defaults;
private static $_base;
private static $_secret;
private static $_reason;
/**
* "Konstruktor" der Klasse
*
* @since 0.1
* @change 2.4.3
*/
public static function init()
{
/* AJAX & Co. */
if ( (defined('DOING_AJAX') && DOING_AJAX) or (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) ) {
return;
}
/* Initialisierung */
self::_init_internal_vars();
/* Cronjob */
if ( defined('DOING_CRON') ) {
add_action(
'antispam_bee_daily_cronjob',
array(
__CLASS__,
'start_daily_cronjob'
)
);
/* Admin */
} elseif ( is_admin() ) {
/* Menü */
add_action(
'admin_menu',
array(
__CLASS__,
'add_sidebar_menu'
)
);
/* Dashboard */
if ( self::_current_page('dashboard') ) {
add_action(
'init',
array(
__CLASS__,
'load_plugin_lang'
)
);
add_action(
'right_now_discussion_table_end',
array(
__CLASS__,
'add_dashboard_count'
)
);
add_action(
'wp_dashboard_setup',
array(
__CLASS__,
'add_dashboard_chart'
)
);
/* Plugins */
} else if ( self::_current_page('plugins') ) {
add_action(
'init',
array(
__CLASS__,
'load_plugin_lang'
)
);
add_action(
'admin_notices',
array(
__CLASS__,
'init_admin_notice'
)
);
add_filter(
'plugin_row_meta',
array(
__CLASS__,
'init_row_meta'
),
10,
2
);
add_filter(
'plugin_action_links_' .self::$_base,
array(
__CLASS__,
'init_action_links'
)
);
/* Optionen */
} else if ( self::_current_page('options') ) {
add_action(
'admin_init',
array(
__CLASS__,
'load_plugin_lang'
)
);
add_action(
'admin_init',
array(
__CLASS__,
'init_plugin_sources'
)
);
} else if ( self::_current_page('admin-post') ) {
require_once( dirname(__FILE__). '/inc/gui.class.php' );
add_action(
'admin_post_ab_save_changes',
array(
'Antispam_Bee_GUI',
'save_changes'
)
);
}
/* Frontend */
} else {
add_action(
'template_redirect',
array(
__CLASS__,
'prepare_comment_field'
)
);
add_action(
'init',
array(
__CLASS__,
'precheck_incoming_request'
)
);
add_action(
'preprocess_comment',
array(
__CLASS__,
'handle_incoming_request'
),
1
);
add_action(
'antispam_bee_count',
array(
__CLASS__,
'the_spam_count'
)
);
}
}
############################
######## INSTALL #########
############################
/**
* Aktion bei der Aktivierung des Plugins
*
* @since 0.1
* @change 2.4
*/
public static function activate()
{
/* Option anlegen */
add_option(
'antispam_bee',
array(),
'',
'no'
);
/* Cron aktivieren */
if ( self::get_option('cronjob_enable') ) {
self::init_scheduled_hook();
}
}
/**
* Aktion bei der Deaktivierung des Plugins
*
* @since 0.1
* @change 2.4
*/
public static function deactivate()
{
self::clear_scheduled_hook();
}
/**
* Aktion beim Löschen des Plugins
*
* @since 2.4
* @change 2.4
*/
public static function uninstall()
{
/* Global */
global $wpdb;
/* Remove settings */
delete_option('antispam_bee');
/* Clean DB */
$wpdb->query("OPTIMIZE TABLE `" .$wpdb->options. "`");
}
############################
######### INTERN #########
############################
/**
* Initialisierung der internen Variablen
*
* @since 2.4
* @change 2.5.2
*/
private static function _init_internal_vars()
{
self::$_base = plugin_basename(__FILE__);
self::$_secret = substr(md5(get_bloginfo('url')), 0, 5). '-comment';
self::$defaults = array(
'options' => array(
/* Allgemein */
'advanced_check' => 1,
'regexp_check' => 1,
'spam_ip' => 1,
'already_commented' => 1,
'ignore_pings' => 0,
'always_allowed' => 0,
'dashboard_chart' => 1,
'dashboard_count' => 0,
/* Filter */
'country_code' => 0,
'country_black' => '',
'country_white' => '',
'translate_api' => 0,
'translate_lang' => '',
'dnsbl_check' => 0,
'bbcode_check' => 1,
/* Erweitert */
'flag_spam' => 1,
'email_notify' => 1,
'no_notice' => 1,
'cronjob_enable' => 0,
'cronjob_interval' => 0,
'ignore_filter' => 0,
'ignore_type' => 0,
'reasons_enable' => 0,
'ignore_reasons' => array()
),
'reasons' => array(
'css' => 'CSS Hack',
'empty' => 'Empty Data',
'server' => 'Server IP',
'localdb' => 'Local DB Spam',
'country' => 'Country Check',
'dnsbl' => 'DNSBL Spam',
'bbcode' => 'BBCode',
'lang' => 'Comment Language',
'regexp' => 'RegExp'
)
);
}
/**
* Prüfung und Rückgabe eines Array-Keys
*
* @since 2.4.2
* @change 2.4.2
*
* @param array $array Array mit Werten
* @param string $key Name des Keys
* @return mixed Wert des angeforderten Keys
*/
public static function get_key($array, $key)
{
if ( empty($array) or empty($key) or empty($array[$key]) ) {
return null;
}
return $array[$key];
}
/**
* Lokalisierung der Admin-Seiten
*
* @since 0.1
* @change 2.4
*
* @param string $page Kennzeichnung der Seite
* @return boolean TRUE Bei Erfolg
*/
private static function _current_page($page)
{
switch ($page) {
case 'dashboard':
return ( empty($GLOBALS['pagenow']) or ( !empty($GLOBALS['pagenow']) && $GLOBALS['pagenow'] == 'index.php' ) );
case 'options':
return ( !empty($_REQUEST['page']) && $_REQUEST['page'] == 'antispam_bee' );
case 'plugins':
return ( !empty($GLOBALS['pagenow']) && $GLOBALS['pagenow'] == 'plugins.php' );
case 'admin-post':
return ( !empty($GLOBALS['pagenow']) && $GLOBALS['pagenow'] == 'admin-post.php' );
default:
return false;
}
}
/**
* Einbindung der Sprachdatei
*
* @since 0.1
* @change 2.4
*/
public static function load_plugin_lang()
{
load_plugin_textdomain(
'antispam_bee',
false,
'antispam-bee/lang'
);
}
/**
* Hinzufügen des Links zu den Einstellungen
*
* @since 1.1
* @change 1.1
*/
public static function init_action_links($data)
{
/* Rechte? */
if ( !current_user_can('manage_options') ) {
return $data;
}
return array_merge(
$data,
array(
sprintf(
'<a href="%s">%s</a>',
add_query_arg(
array(
'page' => 'antispam_bee'
),
admin_url('options-general.php')
),
__('Settings')
)
)
);
}
/**
* Meta-Links des Plugins
*
* @since 0.1
* @change 2.4.4
*
* @param array $input Bereits vorhandene Links
* @param string $file Aktuelle Seite
* @return array $data Modifizierte Links
*/
public static function init_row_meta($input, $file)
{
/* Rechte */
if ( $file != self::$_base ) {
return $input;
}
return array_merge(
$input,
array(
'<a href="https://flattr.com/t/1323822" target="_blank">Flattr</a>',
'<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=5RDDW9FEHGLG6" target="_blank">PayPal</a>'
)
);
}
/**
* Anzeige der Admin-Notiz
*
* @since 2.4.3
* @change 2.5.1
*/
public static function init_admin_notice() {
/* Alles klar? */
if ( self::_is_version($GLOBALS['wp_version'], '3.4') && self::_is_version(phpversion(), '5.2.4') ) {
return;
}
/* Warnung */
echo sprintf(
'<div class="error"><p>%s</p></div>',
esc_html__('Antispam Bee requires WordPress 3.4 and PHP 5.2.4', 'antispam_bee')
);
}
/**
* Vergleich der Versionen
*
* @since 2.4.3
* @change 2.4.3
*
* @param integer $current Aktuelle Version
* @param integer $required Mindestversion
* @return boolean TRUE, wenn Voraussetzungen erfüllt
*/
private static function _is_version($current, $required) {
return version_compare(
$current,
$required. 'alpha',
'>='
);
}
############################
####### RESSOURCEN #######
############################
/**
* Registrierung von Ressourcen (CSS & JS)
*
* @since 1.6
* @change 2.4.5
*/
public static function init_plugin_sources()
{
/* Infos auslesen */
$plugin = get_plugin_data(__FILE__);
/* JS einbinden */
wp_register_script(
'ab_script',
plugins_url('js/scripts.min.js', __FILE__),
array('jquery'),
$plugin['Version']
);
/* CSS einbinden */
wp_register_style(
'ab_style',
plugins_url('css/styles.min.css', __FILE__),
array(),
$plugin['Version']
);
}
/**
* Initialisierung der Optionsseite
*
* @since 0.1
* @change 2.4.3
*/
public static function add_sidebar_menu()
{
/* Menü anlegen */
$page = add_options_page(
'Antispam Bee',
'Antispam Bee',
'manage_options',
'antispam_bee',
array(
'Antispam_Bee_GUI',
'options_page'
)
);
/* JS einbinden */
add_action(
'admin_print_scripts-' . $page,
array(
__CLASS__,
'add_options_script'
)
);
/* CSS einbinden */
add_action(
'admin_print_styles-' . $page,
array(
__CLASS__,
'add_options_style'
)
);
/* PHP laden */
add_action(
'load-' .$page,
array(
__CLASS__,
'init_options_page'
)
);
}
/**
* Initialisierung von JavaScript
*
* @since 1.6
* @change 2.4
*/
public static function add_options_script()
{
wp_enqueue_script('ab_script');
}
/**
* Initialisierung von Stylesheets
*
* @since 1.6
* @change 2.4
*/
public static function add_options_style()
{
wp_enqueue_style('ab_style');
}
/**
* Einbindung der GUI
*
* @since 2.4
* @change 2.4
*/
public static function init_options_page()
{
require_once( dirname(__FILE__). '/inc/gui.class.php' );
}
############################
####### DASHBOARD ########
############################
/**
* Anzeige des Spam-Counters auf dem Dashboard
*
* @since 0.1
* @change 2.4
*/
public static function add_dashboard_count()
{
/* Aktiv? */
if ( !self::get_option('dashboard_count') ) {
return;
}
/* Ausgabe */
echo sprintf(
'<tr>
<td class="b b-spam" style="font-size:18px">%s</td>
<td class="last t">%s</td>
</tr>',
esc_html( self::_get_spam_count() ),
esc_html__('Blocked', 'antispam_bee')
);
}
/**
* Initialisierung des Dashboard-Chart
*
* @since 1.9
* @change 2.5.6
*/
public static function add_dashboard_chart()
{
/* Filter */
if ( !current_user_can('publish_posts') or !self::get_option('dashboard_chart') ) {
return;
}
/* Widget hinzufügen */
wp_add_dashboard_widget(
'ab_widget',
'Antispam Bee',
array(
__CLASS__,
'show_spam_chart'
)
);
/* JS laden */
add_action(
'wp_print_scripts',
array(
__CLASS__,
'add_dashboard_script'
)
);
/* CSS laden */
add_action(
'admin_head',
array(
__CLASS__,
'add_dashboard_style'
)
);
}
/**
* Ausgabe der Dashboard-CSS
*
* @since 1.9
* @change 2.4.4
*/
public static function add_dashboard_style()
{
/* Plugin-Info */
$plugin = get_plugin_data(__FILE__);
/* CSS registrieren */
wp_register_style(
'ab_chart',
plugins_url('css/dashboard.min.css', __FILE__),
array(),
$plugin['Version']
);
/* CSS ausgeben */
wp_print_styles('ab_chart');
}
/**
* Ausgabe der Dashboard-JS
*
* @since 1.9
* @change 2.4.4
*/
public static function add_dashboard_script()
{
/* Init */
$items = (array)self::get_option('daily_stats');
/* Leer? */
if ( empty($items) ) {
return;
}
/* Sortieren */
krsort($items, SORT_NUMERIC);
/* Init */
$output = array(
'created' => array(),
'count' => array()
);
/* Init */
$i = 0;
/* Zeilen loopen */
foreach($items as $timestamp => $count) {
array_push(
$output['created'],
( $timestamp == strtotime('today', current_time('timestamp')) ? __('Today', 'antispam_bee') : date('d.m', $timestamp) )
);
array_push(
$output['count'],
(int)$count
);
}
/* Zusammenfassen */
$stats = array(
'created' => implode(',', $output['created']),
'count' => implode(',', $output['count'])
);
/* Plugin-Info */
$plugin = get_plugin_data(__FILE__);
/* JS einbinden */
wp_register_script(
'ab_chart',
plugins_url('js/dashboard.min.js', __FILE__),
array('jquery'),
$plugin['Version']
);
wp_register_script(
'google_jsapi',
'https://www.google.com/jsapi',
false
);
/* Einbinden */
wp_enqueue_script('google_jsapi');
wp_enqueue_script('ab_chart');
/* Ãbergeben */
wp_localize_script(
'ab_chart',
'antispambee',
$stats
);
}
/**
* Ausgabe des Dashboard-Chart
*
* @since 1.9
* @change 2.4
*/
public static function show_spam_chart()
{
/* Init */
$items = (array)self::get_option('daily_stats');
/* Ausgabe */
echo sprintf(
'<div id="ab_chart">%s</div>',
( empty($items) ? esc_html__('No data available.', 'antispam_bee') : '' )
);
}
############################
######## OPTIONS #########
############################
/**
* Rückgabe der Optionen
*
* @since 2.4
* @change 2.4
*
* @return array $options Array mit Optionen
*/
public static function get_options()
{
if ( !$options = wp_cache_get('antispam_bee') ) {
$options = wp_parse_args(
get_option('antispam_bee'),
self::$defaults['options']
);
wp_cache_set(
'antispam_bee',
$options
);
}
return $options;
}
/**
* Rückgabe eines Optionsfeldes
*
* @since 0.1
* @change 2.4.2
*
* @param string $field Name des Feldes
* @return mixed Wert des Feldes
*/
public static function get_option($field)
{
$options = self::get_options();
return self::get_key($options, $field);
}
/**
* Aktualisiert ein Optionsfeld
*
* @since 0.1
* @change 2.4
*
* @param string $field Name des Feldes
* @param mixed Wert des Feldes
*/
private static function _update_option($field, $value)
{
self::update_options(
array(
$field => $value
)
);
}
/**
* Aktualisiert mehrere Optionsfelder
*
* @since 0.1
* @change 2.4
*
* @param array $data Array mit Feldern
*/
public static function update_options($data)
{
/* Option zuweisen */
$options = array_merge(
(array)get_option('antispam_bee'),
$data
);
/* DB updaten */
update_option(
'antispam_bee',
$options
);
/* Cache updaten */
wp_cache_set(
'antispam_bee',
$options
);
}
############################
######## CRONJOBS ########
############################
/**
* Ausführung des täglichen Cronjobs
*
* @since 0.1
* @change 2.4
*/
public static function start_daily_cronjob()
{
/* Kein Cronjob? */
if ( !self::get_option('cronjob_enable') ) {
return;
}
/* Timestamp updaten */
self::_update_option(
'cronjob_timestamp',
time()
);
/* Spam löschen */
self::_delete_old_spam();
}
/**
* Löschung alter Spamkommentare
*
* @since 0.1
* @change 2.4
*/
private static function _delete_old_spam()
{
/* Anzahl der Tage */
$days = (int)self::get_option('cronjob_interval');
/* Kein Wert? */
if ( empty($days) ) {
return false;
}
/* Global */
global $wpdb;
/* Kommentare löschen */
$wpdb->query(
$wpdb->prepare(
"DELETE FROM `$wpdb->comments` WHERE `comment_approved` = 'spam' AND SUBDATE(NOW(), %d) > comment_date_gmt",
$days
)
);
/* DB optimieren */
$wpdb->query("OPTIMIZE TABLE `$wpdb->comments`");
}
/**
* Initialisierung des Cronjobs
*
* @since 0.1
* @change 2.4
*/
public static function init_scheduled_hook()
{
if ( ! wp_next_scheduled('antispam_bee_daily_cronjob') ) {
wp_schedule_event(
time(),
'daily',
'antispam_bee_daily_cronjob'
);
}
}
/**
* Löschung des Cronjobs
*
* @since 0.1
* @change 2.4
*/
public static function clear_scheduled_hook()
{
if ( wp_next_scheduled('antispam_bee_daily_cronjob') ) {
wp_clear_scheduled_hook('antispam_bee_daily_cronjob');
}
}
############################
###### SPAMPRÃFUNG #######
############################
/**
* Ãberprüfung der POST-Werte
*
* @since 0.1
* @change 2.4.2
*/
public static function precheck_incoming_request()
{
/* Nur Frontend */
if ( is_feed() or is_trackback() or self::_is_mobile() ) {
return;
}
/* Allgemeine Werte */
$request_url = self::get_key($_SERVER, 'REQUEST_URI');
$hidden_field = self::get_key($_POST, 'comment');
$plugin_field = self::get_key($_POST, self::$_secret);
/* Falsch verbunden */
if ( empty($_POST) or empty($request_url) or strpos($request_url, 'wp-comments-post.php') === false ) {
return;
}
/* Felder prüfen */
if ( empty($hidden_field) && !empty($plugin_field) ) {
$_POST['comment'] = $plugin_field;
unset($_POST[self::$_secret]);
} else {
$_POST['bee_spam'] = 1;
}
}
/**
* Prüfung der eingehenden Anfragen auf Spam
*
* @since 0.1
* @change 2.4.2
*
* @param array $comment Unbehandelter Kommentar
* @return array $comment Behandelter Kommentar
*/
public static function handle_incoming_request($comment)
{
/* Server-Werte */
$url = self::get_key($_SERVER, 'REQUEST_URI');
/* Leere Werte? */
if ( empty($url) ) {
return self::_handle_spam_request(
$comment,
'empty'
);
}
/* Ping-Optionen */
$ping = array(
'types' => array('pingback', 'trackback', 'pings'),
'allowed' => !self::get_option('ignore_pings')
);
/* Kommentar */
if ( strpos($url, 'wp-comments-post.php') !== false && !empty($_POST) ) {
/* Filter ausführen */
$status = self::_verify_comment_request($comment);
/* Spam lokalisiert */
if ( !empty($status['reason']) ) {
return self::_handle_spam_request(
$comment,
$status['reason']
);
}
/* Trackback */
} else if ( in_array(self::get_key($comment, 'comment_type'), $ping['types']) && $ping['allowed'] ) {
/* Filter ausführen */
$status = self::_verify_trackback_request($comment);
/* Spam lokalisiert */
if ( !empty($status['reason']) ) {
return self::_handle_spam_request(
$comment,
$status['reason'],
true
);
}
}
return $comment;
}
/**
* Bereitet die Ersetzung des KOmmentarfeldes vor
*
* @since 0.1
* @change 2.4
*/
public static function prepare_comment_field()
{
/* Nur Frontend */
if ( is_feed() or is_trackback() or is_robots() or self::_is_mobile() ) {
return;
}
/* Nur Beiträge */
if ( !is_singular() && !self::get_option('always_allowed') ) {
return;
}
/* Fire! */
ob_start(
array(
'Antispam_Bee',
'replace_comment_field'
)
);
}
/**
* ersetzt das Kommentarfeld
*
* @since 2.4
* @change 2.4.1
*
* @param string $data HTML-Code der Webseite
* @return string Behandelter HTML-Code
*/
public static function replace_comment_field($data)
{
/* Leer? */
if ( empty($data) ) {
return;
}
/* Convert */
return preg_replace(
'#<textarea(.+?)name=["\']comment["\'](.+?)</textarea>#s',
'<textarea$1name="' .self::$_secret. '"$2</textarea><textarea name="comment" style="display:none" rows="1" cols="1"></textarea>',
(string) $data,
1
);
}
/**
* Prüfung der Trackbacks
*
* @since 2.4
* @change 2.5.4
*
* @param array $comment Daten des Trackbacks
* @return array Array mit dem Verdachtsgrund [optional]
*/
private static function _verify_trackback_request($comment)
{
/* IP */
$ip = self::get_key($_SERVER, 'REMOTE_ADDR');
/* Kommentarwerte */
$url = self::get_key($comment, 'comment_author_url');
$body = self::get_key($comment, 'comment_content');
/* Leere Werte ? */
if ( empty($url) or empty($body) ) {
return array(
'reason' => 'empty'
);
}
/* IP? */
if ( empty($ip) or (function_exists('filter_var') && !filter_var($ip, FILTER_VALIDATE_IP)) ) {
return array(
'reason' => 'empty'
);
}
/* Optionen */
$options = self::get_options();
/* BBCode Spam */
if ( $options['bbcode_check'] && self::_is_bbcode_spam($body) ) {
return array(
'reason' => 'bbcode'
);
}
/* IP != Server */
if ( $options['advanced_check'] && self::_is_fake_ip($ip, parse_url($url, PHP_URL_HOST)) ) {
return array(
'reason' => 'server'
);
}
/* IP im lokalen Spam */
if ( $options['spam_ip'] && self::_is_db_spam($ip, $url) ) {
return array(
'reason' => 'localdb'
);
}
/* DNSBL Spam */
if ( $options['dnsbl_check'] && self::_is_dnsbl_spam($ip) ) {
return array(
'reason' => 'dnsbl'
);
}
/* Country Code prüfen */
if ( $options['country_code'] && self::_is_country_spam($ip) ) {
return array(
'reason' => 'country'
);
}
}
/**
* Prüfung den Kommentar
*
* @since 2.4
* @change 2.5.6
*
* @param array $comment Daten des Kommentars
* @return array Array mit dem Verdachtsgrund [optional]
*/
private static function _verify_comment_request($comment)
{
/* IP */
$ip = self::get_key($_SERVER, 'REMOTE_ADDR');
/* Kommentarwerte */
$url = self::get_key($comment, 'comment_author_url');
$body = self::get_key($comment, 'comment_content');
$email = self::get_key($comment, 'comment_author_email');
$author = self::get_key($comment, 'comment_author');
/* Leere Werte ? */
if ( empty($body) ) {
return array(
'reason' => 'empty'
);
}
/* IP? */
if ( empty($ip) or (function_exists('filter_var') && !filter_var($ip, FILTER_VALIDATE_IP)) ) {
return array(
'reason' => 'empty'
);
}
/* Leere Werte ? */
if ( get_option('require_name_email') && ( empty($email) OR empty($author) ) ) {
return array(
'reason' => 'empty'
);
}
/* Optionen */
$options = self::get_options();
/* Bereits kommentiert? */
if ( $options['already_commented'] && !empty($email) && self::_is_approved_email($email) ) {
return;
}
/* Bot erkannt */
if ( !empty($_POST['bee_spam']) ) {
return array(
'reason' => 'css'
);
}
/* BBCode Spam */
if ( $options['bbcode_check'] && self::_is_bbcode_spam($body) ) {
return array(
'reason' => 'bbcode'
);
}
/* Erweiterter Schutz */
if ( $options['advanced_check'] && self::_is_fake_ip($ip) ) {
return array(
'reason' => 'server'
);
}
/* Regexp für Spam */
if ( $options['regexp_check'] && self::_is_regexp_spam(
array(
'ip' => $ip,
'host' => parse_url($url, PHP_URL_HOST),
'body' => $body,
'email' => $email,
'author' => $author
)
) ) {
return array(
'reason' => 'regexp'
);
}
/* IP im lokalen Spam */
if ( $options['spam_ip'] && self::_is_db_spam($ip, $url, $email) ) {
return array(
'reason' => 'localdb'
);
}
/* DNSBL Spam */
if ( $options['dnsbl_check'] && self::_is_dnsbl_spam($ip) ) {
return array(
'reason' => 'dnsbl'
);
}
/* Country Code prüfen */
if ( $options['country_code'] && self::_is_country_spam($ip) ) {
return array(
'reason' => 'country'
);
}
/* Translate API */
if ( $options['translate_api'] && self::_is_lang_spam($body) ) {
return array(
'reason' => 'lang'
);
}
}
/**
* Anwendung von Regexp, auch benutzerdefiniert
*
* @since 2.5.2
* @change 2.5.6
*
* @param array $comment Array mit Kommentardaten
* @return boolean TRUE bei verdächtigem Kommentar
*/
private static function _is_regexp_spam($comment)
{
/* Felder */
$fields = array(
'ip',
'host',
'body',
'email',
'author'
);
/* Regexp */
$patterns = array(
0 => array(
'host' => '^(www\.)?\d+\w+\.com$',
'body' => '^\w+\s\d+$',
'email' => '@gmail.com$'
),
1 => array(
'body' => '\<\!.+?mfunc.+?\>'
)
);
/* Spammy author */
if ( $quoted_author = preg_quote($comment['author']) ) {
$patterns[] = array(
'body' => sprintf(
'<a.+?>%s<\/a>$',
$quoted_author
)
);
$patterns[] = array(
'body' => sprintf(
'%s https?:.+?$',
$quoted_author
)
);
}
/* Hook */
$patterns = apply_filters(
'antispam_bee_patterns',
$patterns
);
/* Leer? */
if ( ! $patterns ) {
return false;
}
/* Ausdrücke loopen */
foreach ($patterns as $pattern) {
$hits = array();
/* Felder loopen */
foreach ($pattern as $field => $regexp) {
if ( empty($field) or !in_array($field, $fields) or empty($comment[$field]) or empty($regexp) ) {
continue;
}
if ( preg_match('|' .$regexp. '|isu', $comment[$field]) ) {
$hits[$field] = true;
}
}
if ( count($hits) === count($pattern) ) {
return true;
}
}
return false;
}
/**
* Prüfung eines Kommentars auf seine Existenz im lokalen Spam
*
* @since 2.0.0
* @change 2.5.4
*
* @param string $ip Kommentar-IP
* @param string $url Kommentar-URL [optional]
* @param string $email Kommentar-Email [optional]
* @return boolean TRUE bei verdächtigem Kommentar
*/
private static function _is_db_spam($ip, $url = '', $email = '')
{
/* Global */
global $wpdb;
/* Default */
$filter = array('`comment_author_IP` = %s');
$params = array($ip);
/* URL abgleichen */
if ( !empty($url) ) {
$filter[] = '`comment_author_url` = %s';
$params[] = $url;
}
/* E-Mail abgleichen */
if ( !empty($email) ) {
$filter[] = '`comment_author_email` = %s';
$params[] = $email;
}
/* Query ausführen */
$result = $wpdb->get_var(
$wpdb->prepare(
sprintf(
"SELECT `comment_ID` FROM `$wpdb->comments` WHERE `comment_approved` = 'spam' AND (%s) LIMIT 1",
implode(' OR ', $filter)
),
$params
)
);
return !empty($result);
}
/**
* Prüfung auf erlaubten Ländercodes
*
* @since 0.1
* @change 2.5.1
*
* @param string $ip IP-Adresse
* @return boolean TRUE bei unerwünschten Ländercodes
*/
private static function _is_country_spam($ip)
{
/* Optionen */
$options = self::get_options();
/* White & Black */
$white = preg_split(
'/ /',
$options['country_white'],
-1,
PREG_SPLIT_NO_EMPTY
);
$black = preg_split(
'/ /',
$options['country_black'],
-1,
PREG_SPLIT_NO_EMPTY
);
/* Leere Listen? */
if ( empty($white) && empty($black) ) {
return false;
}
/* IP abfragen */
$response = wp_remote_get(
esc_url_raw(
sprintf(
'https://geoip.maxmind.com/a?l=%s&i=%s',
strrev('1Lbn0ZsL08e1'),
self::_anonymize_ip($ip)
),
'https'
)
);
/* Fehler? */
if ( is_wp_error($response) ) {
return false;
}
/* Land auslesen */
$country = wp_remote_retrieve_body($response);
/* Kein Land? */
if ( empty($country) ) {
return false;
}
/* Blacklist */
if ( !empty($black) ) {
return ( in_array($country, $black) ? true : false );
}
/* Whitelist */
return ( in_array($country, $white) ? false : true );
}
/**
* Prüfung auf DNSBL Spam
*
* @since 2.4.5
* @change 2.4.5
*
* @param string $ip IP-Adresse
* @return boolean TRUE bei gemeldeter IP
*/
private static function _is_dnsbl_spam($ip)
{
/* Funktionscheck */
if ( ! function_exists('checkdnsrr') ) {
return false;
}
return (bool) checkdnsrr(
self::_reverse_ip($ip). '.opm.tornevall.org.',
'A'
);
}
/**
* Prüfung auf BBCode Spam
*
* @since 2.5.1
* @change 2.5.1
*
* @param string $body Inhalt eines Kommentars
* @return boolean TRUE bei BBCode im Inhalt
*/
private static function _is_bbcode_spam($body)
{
return (bool) preg_match('/\[url[=\]].*\[\/url\]/is', $body);
}
/**
* Prüfung auf eine bereits freigegebene E-Mail-Adresse
*
* @since 2.0
* @change 2.5.1
*
* @param string $email E-Mail-Adresse
* @return boolean TRUE bei einem gefundenen Eintrag
*/
private static function _is_approved_email($email)
{
/* Global */
global $wpdb;
/* Suchen */
$result = $wpdb->get_var(
$wpdb->prepare(
"SELECT `comment_ID` FROM `$wpdb->comments` WHERE `comment_approved` = '1' AND `comment_author_email` = %s LIMIT 1",
(string)$email
)
);
/* Gefunden? */
if ( $result ) {
return true;
}
return false;
}
/**
* Prüfung auf eine gefälschte IP
*
* @since 2.0
* @change 2.5.1
*
* @param string $ip IP-Adresse
* @param string $host Host [optional]
* @return boolean TRUE bei gefälschter IP
*/
private static function _is_fake_ip($ip, $host = false)
{
/* Remote Host */
$hostbyip = gethostbyaddr($ip);
/* IPv6 */
if ( !self::_is_ipv4($ip) ) {
return $ip != $hostbyip;
}
/* IPv4 / Kommentar */
if ( empty($host) ) {
$found = strpos(
$ip,
self::_cut_ip(
gethostbyname($hostbyip)
)
);
/* IPv4 / Trackback */
} else {
/* IP-Vergleich */
if ( $hostbyip == $ip ) {
return true;
}
/* Treffer suchen */
$found = strpos(
$ip,
self::_cut_ip(
gethostbyname($host)
)
);
}
return $found === false;
}
/**
* Prüfung auf unerwünschte Sprachen
*
* @since 2.0
* @change 2.4.2
*
* @param string $content Inhalt des Kommentars
* @return boolean TRUE bei Spam
*/
private static function _is_lang_spam($content)
{
/* Init */
$lang = self::get_option('translate_lang');
/* Formatieren */
$content = wp_strip_all_tags($content);
/* Keine Daten? */
if ( empty($lang) or empty($content) ) {
return false;
}
/* Formatieren */
$content = rawurlencode(
( function_exists('mb_substr') ? mb_substr($content, 0, 200) : substr($content, 0, 200) )
);
/* IP abfragen */
$response = wp_remote_get(
esc_url_raw(
sprintf(
'http://translate.google.com/translate_a/t?client=x&text=%s',
$content
),
'http'
)
);
/* Fehler? */
if ( is_wp_error($response) ) {
return false;
}
/* Parsen */
preg_match(
'/"src":"(\\D{2})"/',
wp_remote_retrieve_body($response),
$matches
);
/* Fehler? */
if ( empty($matches[1]) ) {
return false;
}
return ( strtolower($matches[1]) != $lang );
}
/**
* Kürzung der IP-Adressen
*
* @since 0.1
* @change 2.5.1
*
* @param string $ip Original IP
* @param boolean $cut_end Kürzen vom Ende?
* @return string Gekürzte IP
*/
private static function _cut_ip($ip, $cut_end = true)
{
/* Trenner */
$separator = ( self::_is_ipv4($ip) ? '.' : ':' );
return str_replace(
( $cut_end ? strrchr( $ip, $separator) : strstr( $ip, $separator) ),
'',
$ip
);
}
/**
* Anonymisierung der IP-Adressen
*
* @since 2.5.1
* @change 2.5.1
*
* @param string $ip Original IP
* @return string Anonyme IP
*/
private static function _anonymize_ip($ip)
{
if ( self::_is_ipv4($ip) ) {
return self::_cut_ip($ip). '.0';
}
return self::_cut_ip($ip, false). ':0:0:0:0:0:0:0';
}
/**
* Dreht die IP-Adresse
*
* @since 2.4.5
* @change 2.4.5
*
* @param string $ip IP-Adresse
* @return string Gedrehte IP-Adresse
*/
private static function _reverse_ip($ip)
{
return implode(
'.',
array_reverse(
explode(
'.',
$ip
)
)
);
}
/**
* Prüfung auf eine IPv4-Adresse
*
* @since 2.4
* @change 2.4
*
* @param string $ip Zu prüfende IP
* @return integer Anzahl der Treffer
*/
private static function _is_ipv4($ip)
{
return preg_match('/^\d{1,3}(\.\d{1,3}){3,3}$/', $ip);
}
/**
* Prüfung auf Mobile
*
* @since 0.1
* @change 2.4
*
* @return boolean TRUE, wenn "wptouch" aktiv ist
*/
private static function _is_mobile()
{
return strpos(TEMPLATEPATH, 'wptouch');
}
############################
##### SPAM-BEHANDLUNG ####
############################
/**
* Ausführung des Lösch-/Markier-Vorgangs
*
* @since 0.1
* @change 2.5.2
*
* @param array $comment Unbehandelte Kommentardaten
* @param string $reason Verdachtsgrund
* @param boolean $is_ping Ping (ja oder nein) [optional]
* @return array $comment Behandelte Kommentardaten
*/
private static function _handle_spam_request($comment, $reason, $is_ping = false)
{
/* Optionen */
$options = self::get_options();
/* Einstellungen */
$spam_remove = !$options['flag_spam'];
$spam_notice = !$options['no_notice'];
/* Filter-Einstellungen */
$ignore_filter = $options['ignore_filter'];
$ignore_type = $options['ignore_type'];
$ignore_reason = in_array($reason, (array)$options['ignore_reasons']);
/* Spam hochzählen */
self::_update_spam_count();
self::_update_daily_stats();
/* Spam löschen */
if ( $spam_remove ) {
self::_go_in_peace();
}
/* Typen behandeln */
if ( $ignore_filter && (( $ignore_type == 1 && $is_ping ) or ( $ignore_type == 2 && !$is_ping )) ) {
self::_go_in_peace();
}
/* Spamgrund */
if ( $ignore_reason ) {
self::_go_in_peace();
}
/* Spam-Grund */
self::$_reason = $reason;
/* Spam markieren */
add_filter(
'pre_comment_approved',
create_function(
'',
'return "spam";'
)
);
/* E-Mail senden */
add_filter(
'trackback_post',
array(
__CLASS__,
'send_mail_notification'
)
);
add_filter(
'comment_post',
array(
__CLASS__,
'send_mail_notification'
)
);
/* Notiz setzen */
if ( $spam_notice ) {
/* Sprache laden */
self::load_plugin_lang();
/* Markierung hinzufügen */
$comment['comment_content'] = sprintf(
'[%s: %s]%s%s',
esc_html__('Marked as spam by Antispam Bee |Â Spam reason', 'antispam_bee'),
esc_html__(self::$defaults['reasons'][self::$_reason], 'antispam_bee'),
"\n",
$comment['comment_content']
);
}
return $comment;
}
/**
* Sendet den 403-Header und beendet die Verbindung
*
* @since 2.5.6
* @change 2.5.6
*/
private static function _go_in_peace()
{
status_header(403);
die('Spam deleted.');
}
/**
* Versand einer Benachrichtigung via E-Mail
*
* @since 0.1
* @change 2.4.3
*
* @param intval $id ID des Kommentars
* @return intval $id ID des Kommentars
*/
public static function send_mail_notification($id)
{
/* Optionen */
$options = self::get_options();
/* Keine Benachrichtigung? */
if ( !$options['email_notify'] ) {
return $id;
}
/* Kommentar */
$comment = get_comment($id, ARRAY_A);
/* Keine Werte? */
if ( empty($comment) ) {
return $id;
}
/* Parent-Post */
if ( !$post = get_post($comment['comment_post_ID']) ) {
return $id;
}
/* Sprache laden */
self::load_plugin_lang();
/* Betreff */
$subject = sprintf(
'[%s] %s',
get_bloginfo('name'),
__('Comment marked as spam', 'antispam_bee')
);
/* Content */
if ( !$content = strip_tags(stripslashes($comment['comment_content'])) ) {
$content = sprintf(
'-- %s --',
__('Content removed by Antispam Bee', 'antispam_bee')
);
}
/* Body */
$body = sprintf(
"%s \"%s\"\r\n\r\n",
__('New spam comment on your post', 'antispam_bee'),
strip_tags($post->post_title)
).sprintf(
"%s: %s\r\n",
__('Author'),
( empty($comment['comment_author']) ? '' : strip_tags($comment['comment_author']) )
).sprintf(
"URL: %s\r\n",
esc_url($comment['comment_author_url']) /* empty check exists */
).sprintf(
"%s: %s\r\n",
__('Type', 'antispam_bee'),
__( ( empty($comment['comment_type']) ? 'Comment' : 'Trackback' ), 'antispam_bee' )
).sprintf(
"Whois: http://whois.arin.net/rest/ip/%s\r\n",
$comment['comment_author_IP']
).sprintf(
"%s: %s\r\n\r\n",
__('Spam Reason', 'antispam_bee'),
__(self::$defaults['reasons'][self::$_reason], 'antispam_bee')
).sprintf(
"%s\r\n\r\n\r\n",
$content
).(
EMPTY_TRASH_DAYS ? (
sprintf(
"%s: %s\r\n",
__('Trash it', 'antispam_bee'),
admin_url('comment.php?action=trash&c=' .$id)
)
) : (
sprintf(
"%s: %s\r\n",
__('Delete it', 'antispam_bee'),
admin_url('comment.php?action=delete&c=' .$id)
)
)
).sprintf(
"%s: %s\r\n",
__('Approve it', 'antispam_bee'),
admin_url('comment.php?action=approve&c=' .$id)
).sprintf(
"%s: %s\r\n\r\n",
__('Spam list', 'antispam_bee'),
admin_url('edit-comments.php?comment_status=spam')
).sprintf(
"%s\r\n%s\r\n",
__('Notify message by Antispam Bee', 'antispam_bee'),
__('http://antispambee.com', 'antispam_bee')
);
/* Send */
wp_mail(
get_bloginfo('admin_email'),
$subject,
$body
);
return $id;
}
############################
####### STATISTIK ########
############################
/**
* Rückgabe der Anzahl von Spam-Kommentaren
*
* @since 0.1
* @change 2.4
*
* @param intval $count Anzahl der Spam-Kommentare
*/
private static function _get_spam_count()
{
/* Init */
$count = self::get_option('spam_count');
/* Fire */
return ( get_locale() == 'de_DE' ? number_format($count, 0, '', '.') : number_format_i18n($count) );
}
/**
* Ausgabe der Anzahl von Spam-Kommentaren
*
* @since 0.1
* @change 2.4
*/
public static function the_spam_count()
{
echo esc_html( self::_get_spam_count() );
}
/**
* Aktualisierung der Anzahl von Spam-Kommentaren
*
* @since 0.1
* @change 2.4
*/
private static function _update_spam_count()
{
self::_update_option(
'spam_count',
intval( self::get_option('spam_count') + 1 )
);
}
/**
* Aktualisierung der Statistik
*
* @since 1.9
* @change 2.4
*/
private static function _update_daily_stats()
{
/* Init */
$stats = (array)self::get_option('daily_stats');
$today = (int)strtotime('today');
/* Hochzählen */
if ( array_key_exists($today, $stats) ) {
$stats[$today] ++;
} else {
$stats[$today] = 1;
}
/* Sortieren */
krsort($stats, SORT_NUMERIC);
/* Speichern */
self::_update_option(
'daily_stats',
array_slice($stats, 0, 31, true)
);
}
}
/* Fire */
add_action(
'plugins_loaded',
array(
'Antispam_Bee',
'init'
)
);
/* Activation */
register_activation_hook(
__FILE__,
array(
'Antispam_Bee',
'activate'
)
);
/* Deactivation */
register_deactivation_hook(
__FILE__,
array(
'Antispam_Bee',
'deactivate'
)
);
/* Uninstall */
register_uninstall_hook(
__FILE__,
array(
'Antispam_Bee',
'uninstall'
)
);