20 Commits

Author SHA1 Message Date
76cd908861 Preparations for 1.4.0 release 2017-06-10 14:44:03 +02:00
0bf0f3fb9b Change filter hook name to statify__skip_tracking (as of Statify 1.5.0) 2017-06-10 14:36:38 +02:00
9dae145637 Contribution notes added to readme 2017-06-09 09:59:41 +02:00
7929dd66bd PHPdoc and ReadMe corrections 2017-06-05 18:13:36 +02:00
df59e43b29 Config array restructured 2017-06-05 12:03:11 +02:00
152a800a4a #8 Target filter implemented 2017-06-04 21:29:08 +02:00
0cf4548d45 assets added to git 2017-06-04 11:48:32 +02:00
4a0fee572b #7 implementation of IP blacklists 2017-06-04 11:42:21 +02:00
9f9c7af298 Minor corrections 2017-06-02 18:14:06 +02:00
e66e3745a5 Bump minimum supported PHP version to 5.5 2017-06-02 17:46:54 +02:00
4562901f59 ReadMe updates 2017-06-01 20:07:38 +02:00
35b00ac485 Fix #6: hook returns NULL instead of FALSE 2016-12-09 09:37:58 +01:00
d5a947cfbb Tested up to 4.7 2016-12-07 20:12:37 +01:00
b5a6cdf026 Stable tag 1.3.0 2016-10-17 17:45:34 +02:00
2f55ada8e5 1.3.0 finalized 2016-10-17 17:36:13 +02:00
57e2870904 Upgrade hook adds version in options 2016-10-10 10:07:48 +02:00
e7e2ef639c Corrections for case-(in)sensitive DB cleanup 2016-10-10 10:00:01 +02:00
036c1927fd Simple unit test for live filter 2016-10-10 09:17:32 +02:00
25b16746b2 Feature #4 Regular expression filters 2016-10-10 09:17:32 +02:00
e80040fb7e fix #5 Live filter configuration inverted 2016-10-10 09:12:01 +02:00
12 changed files with 1114 additions and 168 deletions

View File

@ -1,13 +1,13 @@
# Statify Blacklist #
* Contributors: Stefan Kalscheuer
* Requires at least: 3.9
* Tested up to: 4.6
* Stable tag: 1.2.0
* Tested up to: 4.8
* Stable tag: 1.4.0
* License: GPLv3 or later
* License URI: https://www.gnu.org/licenses/gpl-3.0.html
## Description ##
A blacklist extension for the famous [Statify](http://statify.de) Wordpress plugin.
A blacklist extension for the famous [Statify](https://wordpress.org/plugins/statify/) Wordpress plugin.
This plugin adds customizable blacklist to Statify to allow blocking of referer spam or internal interactions.
@ -15,16 +15,27 @@ This plugin adds customizable blacklist to Statify to allow blocking of referer
#### Referer Blacklist ####
Add a list of domains (for simplicity only second-level, e.g. _example.com_ which blocks _everything.example.com_).
#### Target Blacklist ####
Add a list of target pages (e.g. _/test/page/_, _/?page_id=123_) that will be excluded from tracking.
#### IP Blacklist ####
Add a list of IP addresses or subnets (e.g. _192.0.2.123_, _198.51.100.0/24_, _2001:db8:a0b:12f0::/64_).
#### CleanUp Database ####
Filters can be applied to data stored in database after modifying filter rules or for one-time clean-up.
#### Compatibility ####
This plugin requires Statify to be installed. The extension has been tested with Statify 1.4.3
This plugin requires Statify to be installed. The extension has been tested with Statify up to version 1.5.1
The plugin is capable of handling multisite installations.
### Support & Contributions ###
* If experience any issues, use the [support forums](https://wordpress.org/support/plugin/statify-statify).
* Latest sources and development are handled on [GitHub](https://github.com/stklcode/statify-blacklist). You might contribute there or file an issue for code related bugs.
* If you want to translate this plugin you can do this on [WordPress Translate](https://translate.wordpress.org/projects/wp-plugins/statify-blacklist).
### Credits ###
* Author: Stefan Kalscheuer
* Special Thanks to [pluginkollektiv](http://pluginkollektiv.org/) for maintaining _Statify_
* Special Thanks to [pluginkollektiv](https://github.com/pluginkollektiv) for maintaining _Statify_
## Installation ##
* If you dont know how to install a plugin for WordPress, [heres how](http://codex.wordpress.org/Managing_Plugins#Installing_Plugins).
@ -32,9 +43,9 @@ The plugin is capable of handling multisite installations.
* Goto _Settings_ -> _Statify Blacklist_ to configure the plugin
### Requirements ###
* PHP 5.2.4
* WordPress 3.9
* Statify plugin installed and activated (tested up to 1.4.3)
* PHP 5.5 or above
* WordPress 3.9 or above
* Statify plugin installed and activated (tested up to 1.5.1)
## Frequently Asked Questions ##
@ -42,28 +53,48 @@ The plugin is capable of handling multisite installations.
Nothing. By default all blacklists are empty and disabled. They can and have to be filled by the blog administrator.
A default blacklist is not provided, as the plugin itself is totally neutral. If you want to filter out referer spam,
visitors from search engines or just "false" referers from 301 redirects only depends on you.
visitors from search engines, just "false" referers from 301 redirects or you own IP address used for testing only depends on you.
### Does the filter effect user experience? ###
No. It only prevent's _Statify_ from tracking, nothing more or less.
### Does live filtering impact performance? ###
Yes, but probalby not noticeable. Checking a single referer string against a (usually small) list should be neglectible compared to the total loading procedure.
Yes, but probalby not noticeable. Checking a single referer string against a (usually small) list should be negligible compared to the total loading procedure.
If this still is an issue for you, consider deactivating the filter and only run the one-time-cleanup or activate the cron job.
### Is any personal data collected? ###
No. The privacy policy of _Statify_ is untouched. Data is only processed, not stored or exposed to anyone.
### Are regular expression filters possible? ###
Not for now. At the moment it's only a simple domain filter, as regular expression matching is significantly slower.
Yes, it is. Just select if you want to filter using regular expressions case sensitive or insensitive.
If you like to have this feature, please leave a feature request in GitHub or the WordPress support forum.
Note, that regular expression matching is significantly slower than the plain domain filter. Hence it is only recommended for asynchronous cron or manual execution and not for live filtering.
### Why is IP filtering only available as live filter? ###
As you might know, Statify does not store any personal information, including IP addresses in the database.
Because of this, an IP blacklist can only be applied while processing the request and not afterwards.
## Screenshots ##
1. Statify Blacklist settings page
## Changelog ##
### 1.4.0 / 10.06.2017 ###
* IP blacklist implemented (#7)
* Target page blacklist implemented (#8)
* Internal configuration restructured (upgrade on plugin activation)
* Statify hook name changed to `statify__skip_tracking` (as of Statify 1.5.0)
### 1.3.1 / 09.12.2016 ###
* Continue filtering if no filter applies (#6)
### 1.3.0 / 17.10.2016 ###
* Regular expressions filtering implemented
### 1.2.1 / 10.10.2016 ###
* Fix live filter configuration check
### 1.2.0 / 29.08.2016 ###
* Switched from `in_array()` to faster `isset()` for referer checking
* Optional cron execiton implemented
@ -78,4 +109,4 @@ If you like to have this feature, please leave a feature request in GitHub or th
* One-time execution on database
### 1.0.0 / 14.08.2016 ###
* First release
* First release

BIN
assets/banner-1544x500.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

BIN
assets/banner-772x250.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

BIN
assets/icon-128x128.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

BIN
assets/icon-256x256.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

BIN
assets/screenshot-1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

View File

@ -6,14 +6,18 @@ defined( 'ABSPATH' ) OR exit;
/**
* Statify Blacklist
*
* @since 1.0.0
* @since 1.0.0
* @version 1.4.0
*/
class StatifyBlacklist {
const VERSION_MAIN = 1.4;
/**
* Plugin options
*
* @var array
* @since 1.0.0
* @since 1.0.0
*/
public static $_options;
@ -21,14 +25,14 @@ class StatifyBlacklist {
* Multisite Status
*
* @var bool
* @since 1.0.0
* @since 1.0.0
*/
public static $multisite;
/**
* Class self initialize
*
* @since 1.0.0
* @since 1.0.0
*/
public static function instance() {
new self();
@ -37,8 +41,7 @@ class StatifyBlacklist {
/**
* Class constructor
*
* @since 1.0.0
* @changed 1.1.2
* @since 1.0.0
*/
public function __construct() {
/* Skip on autosave or AJAX */
@ -53,8 +56,8 @@ class StatifyBlacklist {
self::$multisite = ( is_multisite() && array_key_exists( STATIFYBLACKLIST_BASE, (array) get_site_option( 'active_sitewide_plugins' ) ) );
/* Add Filter to statify hook if enabled */
if ( self::$_options['active_referer'] != 1 ) {
add_filter( 'statify_skip_tracking', array( 'StatifyBlacklist', 'apply_blacklist_filter' ) );
if ( self::$_options['referer']['active'] != 0 ) {
add_filter( 'statify__skip_tracking', array( 'StatifyBlacklist', 'apply_blacklist_filter' ) );
}
/* Admin only filters */
@ -81,7 +84,7 @@ class StatifyBlacklist {
/* CronJob to clean up database */
if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
if ( self::$_options['cron_referer'] == 1 ) {
if ( self::$_options['referer']['cron'] == 1 || self::$_options['target']['cron'] == 1 ) {
add_action( 'statify_cleanup', array( 'StatifyBlacklist_Admin', 'cleanup_database' ) );
}
}
@ -90,50 +93,223 @@ class StatifyBlacklist {
/**
* Update options
*
* @param $options array New options to save
* @param array $options New options to save
*
* @since 1.0.0
* @changed 1.1.1
* @since 1.0.0
* @since 1.2.1 update_options($options = null) Parameter with default value introduced
*/
public static function update_options( $options = null ) {
self::$_options = wp_parse_args(
get_option( 'statify-blacklist' ),
array(
'active_referer' => 0,
'cron_referer' => 0,
'referer' => array()
)
self::defaultOptions()
);
}
/**
* Create default plugin configuration.
*
* @since 1.4.0
*
* @return array the options array
*/
protected static function defaultOptions() {
return array(
'referer' => array(
'active' => 0,
'cron' => 0,
'regexp' => 0,
'blacklist' => array()
),
'target' => array(
'active' => 0,
'cron' => 0,
'regexp' => 0,
'blacklist' => array()
),
'ip' => array(
'active' => 0,
'blacklist' => array()
),
'version' => self::VERSION_MAIN
);
}
/**
* Apply the blacklist filter if active
*
* @return TRUE if referer matches blacklist.
* @return bool TRUE if referer matches blacklist.
*
* @since 1.0.0
* @changed 1.2.0
* @since 1.0.0
*/
public static function apply_blacklist_filter() {
/* Skip if blacklist is inactive */
if ( self::$_options['active_referer'] != 1 ) {
return false;
/* Referer blacklist */
if ( isset( self::$_options['referer']['active'] ) && self::$_options['referer']['active'] != 0 ) {
/* Regular Expression filtering since 1.3.0 */
if ( isset( self::$_options['referer']['regexp'] ) && self::$_options['referer']['regexp'] > 0 ) {
/* Get full referer string */
$referer = ( isset( $_SERVER['HTTP_REFERER'] ) ? $_SERVER['HTTP_REFERER'] : '' );
/* Merge given regular expressions into one */
$regexp = '/' . implode( "|", array_keys( self::$_options['referer']['blacklist'] ) ) . '/';
if ( self::$_options['referer']['regexp'] == 2 ) {
$regexp .= 'i';
}
/* Check blacklist (return NULL to continue filtering) */
return ( preg_match( $regexp, $referer ) === 1 ) ? true : null;
} else {
/* Extract relevant domain parts */
$referer = strtolower( ( isset( $_SERVER['HTTP_REFERER'] ) ? parse_url( $_SERVER['HTTP_REFERER'], PHP_URL_HOST ) : '' ) );
/* Get blacklist */
$blacklist = self::$_options['referer']['blacklist'];
/* Check blacklist */
if ( isset( $blacklist[ $referer ] ) ) {
return true;
}
}
}
/* Extract relevant domain parts */
$referer = strtolower( ( isset( $_SERVER['HTTP_REFERER'] ) ? parse_url( $_SERVER['HTTP_REFERER'], PHP_URL_HOST ) : '' ) );
$referer = explode( '.', $referer );
// if ( count( $referer ) > 1 ) {
// $referer = implode( '.', array_slice( $referer, - 2 ) );
// } else {
$referer = implode( '.', $referer );
// }
/* Target blacklist (since 1.4.0) */
if ( isset( self::$_options['target']['active'] ) && self::$_options['target']['active'] != 0 ) {
/* Regular Expression filtering since 1.3.0 */
if ( isset( self::$_options['target']['regexp'] ) && self::$_options['target']['regexp'] > 0 ) {
/* Get full referer string */
$target = ( isset( $_SERVER['REQUEST_URI'] ) ? wp_unslash( $_SERVER['REQUEST_URI'] ) : '/' );
/* Merge given regular expressions into one */
$regexp = '/' . implode( "|", array_keys( self::$_options['target']['blacklist'] ) ) . '/';
if ( self::$_options['target']['regexp'] == 2 ) {
$regexp .= 'i';
}
/* Get blacklist */
$blacklist = self::$_options['referer'];
/* Check blacklist (return NULL to continue filtering) */
/* Check blacklist */
return ( preg_match( $regexp, $target ) === 1 ) ? true : null;
} else {
/* Extract target page */
$target = ( isset( $_SERVER['REQUEST_URI'] ) ? wp_unslash( $_SERVER['REQUEST_URI'] ) : '/' );
/* Get blacklist */
$blacklist = self::$_options['target']['blacklist'];
/* Check blacklist */
if ( isset( $blacklist[ $target ] ) ) {
return true;
}
}
}
return isset( $blacklist[ $referer ] );
/* IP blacklist (since 1.4.0) */
if ( isset ( self::$_options['ip']['active'] ) && self::$_options['ip']['active'] != 0 ) {
if ( ( $ip = self::getIP() ) !== false ) {
foreach ( self::$_options['ip']['blacklist'] as $net ) {
if ( self::cidrMatch( $ip, $net ) ) {
return true;
}
}
}
}
/* Skip and continue (return NULL), if all blacklists are inactive */
return null;
}
/**
* Helper method to determine the client's IP address.
* If a proxy is used, the X-Real-IP or X-Forwarded-For header is checked, otherwise the default remote address.
* For performance reasons only the most common flags are checked. This might be even reduce by user configuration.
* Maybe some community feedback will ease the decision on that.
*
* @return string|bool the client's IP address or FALSE, if none could be determined
*/
private static function getIP() {
foreach (
array(
// 'HTTP_CLIENT_IP',
'HTTP_X_REAL_IP',
'HTTP_X_FORWARDED_FOR',
// 'HTTP_X_FORWARDED',
// 'HTTP_X_CLUSTER_CLIENT_IP',
// 'HTTP_FORWARDED_FOR',
// 'HTTP_FORWARDED',
'REMOTE_ADDR'
) as $k
) {
if ( isset( $_SERVER[ $k ] ) ) {
foreach ( explode( ',', $_SERVER[ $k ] ) as $ip ) {
if ( filter_var( $ip, FILTER_VALIDATE_IP ) !== false ) {
return $ip;
}
}
}
}
return false;
}
/**
* Helper function to check if an IP address matches a given subnet.
*
* @param string $ip IP address to check
* @param string $net IP address or subnet in CIDR notation
*
* @return bool TRUE, if the given IP addresses matches the given subnet
*/
private static function cidrMatch( $ip, $net ) {
if ( substr_count( $net, ':' ) > 1 ) { /* Check for IPv6 */
if ( ! ( ( extension_loaded( 'sockets' ) && defined( 'AF_INET6' ) ) || @inet_pton( '::1' ) ) ) {
return false;
}
if ( false !== strpos( $net, '/' ) ) { /* Parse CIDR subnet */
list( $base, $mask ) = explode( '/', $net, 2 );
if ( $mask < 1 || $mask > 128 ) {
return false;
}
} else {
$base = $net;
$mask = 128;
}
$bytesAddr = unpack( 'n*', @inet_pton( $base ) );
$bytesTest = unpack( 'n*', @inet_pton( $ip ) );
if ( ! $bytesAddr || ! $bytesTest ) {
return false;
}
for ( $i = 1, $ceil = ceil( $mask / 16 ); $i <= $ceil; ++ $i ) {
$left = $mask - 16 * ( $i - 1 );
$left = ( $left <= 16 ) ? $left : 16;
$maskB = ~( 0xffff >> $left ) & 0xffff;
if ( ( $bytesAddr[ $i ] & $maskB ) != ( $bytesTest[ $i ] & $maskB ) ) {
return false;
}
}
return true;
} else { /* Check for IPv4 */
if ( ! filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 ) ) {
return false;
}
if ( false !== strpos( $net, '/' ) ) { /* Parse CIDR subnet */
list( $base, $mask ) = explode( '/', $net, 2 );
if ( $mask === '0' ) {
return filter_var( $base, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 );
}
if ( $mask < 0 || $mask > 32 ) {
return false;
}
} else { /* Use single address */
$base = $net;
$mask = 32;
}
return 0 === substr_compare( sprintf( '%032b', ip2long( $ip ) ), sprintf( '%032b', ip2long( $base ) ), 0, $mask );
}
}
}

View File

@ -6,25 +6,37 @@ defined( 'ABSPATH' ) OR exit;
/**
* Statify Blacklist admin configuration
*
* @since 1.0.0
* @since 1.0.0
* @version 1.4.0
*/
class StatifyBlacklist_Admin extends StatifyBlacklist {
/**
* Update options
*
* @param $options array New options to save
* @return mixed array of sanitized array on errors, FALSE if there were none
* @since 1.1.1
* @param array $options New options to save
*
* @return array|bool array of sanitized array on errors, FALSE if there were none
* @since 1.1.1
*/
public static function update_options( $options = null ) {
if ( isset( $options ) && current_user_can( 'manage_options' ) ) {
/* Sanitize URLs and remove empty inputs */
$givenReferer = $options['referer'];
$sanitizedReferer = self::sanitizeURLs( $givenReferer );
$givenReferer = $options['referer']['blacklist'];
if ( $options['referer']['regexp'] == 0 ) {
$sanitizedReferer = self::sanitizeURLs( $givenReferer );
} else {
$sanitizedReferer = $givenReferer;
}
/* Sanitize IPs and Subnets and remove empty inputs */
$givenIP = $options['ip']['blacklist'];
$sanitizedIP = self::sanitizeIPs( $givenIP );
/* Abort on errors */
if ( ! empty( array_diff( $givenReferer, $sanitizedReferer ) ) ) {
return $sanitizedReferer;
if ( ! empty( array_diff( array_keys( $givenReferer ), array_keys( $sanitizedReferer ) ) ) ) {
return array( 'referer' => $sanitizedReferer );
} elseif ( ! empty( array_diff( $givenIP, $sanitizedIP ) ) ) {
return array( 'ip' => array_diff( $givenIP, $sanitizedIP ) );
}
/* Update database on success */
@ -44,7 +56,7 @@ class StatifyBlacklist_Admin extends StatifyBlacklist {
/**
* Add configuration page to admin menu
*
* @since 1.0.0
* @since 1.0.0
*/
public function _add_menu_page() {
$title = __( 'Statify Blacklist', 'statify-blacklist' );
@ -69,12 +81,12 @@ class StatifyBlacklist_Admin extends StatifyBlacklist {
/**
* Add plugin meta links
*
* @param $links
* @param $file
* @param array $links Registered links
* @param string $file The filename
*
* @return array
* @return array Merged links
*
* @since 1.0.0
* @since 1.0.0
*/
public static function plugin_meta_link( $links, $file ) {
if ( $file == STATIFYBLACKLIST_BASE ) {
@ -87,11 +99,12 @@ class StatifyBlacklist_Admin extends StatifyBlacklist {
/**
* Add plugin action links
*
* @param array $input Registered links
* @param array $links Registered links
* @param string $file The filename
*
* @return array Merged links
* @return array Merged links
*
* @since 1.0.0
* @since 1.0.0
*/
public static function plugin_actions_links( $links, $file ) {
$base = self::$multisite ? network_admin_url( 'settings.php' ) : admin_url( 'options-general.php' );
@ -109,33 +122,71 @@ class StatifyBlacklist_Admin extends StatifyBlacklist {
/**
* Filter database for cleanup.
*
* @since 1.1.0
* @changed 1.2.0
* @since 1.1.0
*/
public static function cleanup_database() {
/* Check user permissions */
if ( ! current_user_can( 'manage_options' ) && ! ( defined( 'DOING_CRON' ) && DOING_CRON ) ) {
die( _e( 'Are you sure you want to do this?' ) );
die( __( 'Are you sure you want to do this?' ) );
}
global $wpdb;
if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
$cleanRef = ( self::$_options['referer']['cron'] == 1 );
$cleanTrg = ( self::$_options['target']['cron'] == 1 );
} else {
$cleanRef = true;
$cleanTrg = true;
}
/* Sanitize URLs */
$referer = self::sanitizeURLs( self::$_options['referer'] );
/* Build filter regexp */
$refererRegexp = str_replace( '.', '\.', implode( '|', array_flip( $referer ) ) );
if ( ! empty( $refererRegexp ) ) {
if ( $cleanRef ) {
if ( isset( self::$_options['referer']['regexp'] ) && self::$_options['referer']['regexp'] > 0 ) {
/* Merge given regular expressions into one */
$refererRegexp = implode( "|", array_keys( self::$_options['referer']['blacklist'] ) );
} else {
/* Sanitize URLs */
$referer = self::sanitizeURLs( self::$_options['referer']['blacklist'] );
/* Build filter regexp */
$refererRegexp = str_replace( '.', '\.', implode( '|', array_flip( $referer ) ) );
}
}
if ( $cleanTrg ) {
if ( isset( self::$_options['target']['regexp'] ) && self::$_options['target']['regexp'] > 0 ) {
/* Merge given regular expressions into one */
$targetRegexp = implode( "|", array_keys( self::$_options['target']['blacklist'] ) );
} else {
/* Build filter regexp */
$targetRegexp = str_replace( '.', '\.', implode( '|', array_flip( self::$_options['target']['blacklist'] ) ) );
}
}
if ( ! empty( $refererRegexp ) || ! empty( $targetRegexp ) ) {
global $wpdb;
/* Execute filter on database */
$wpdb->query(
$wpdb->prepare( "DELETE FROM `$wpdb->statify` WHERE referrer REGEXP %s", $refererRegexp )
);
if ( ! empty( $refererRegexp ) ) {
$wpdb->query(
$wpdb->prepare( "DELETE FROM `$wpdb->statify` WHERE "
. ( ( self::$_options['referer']['regexp'] == 1 ) ? " BINARY " : "" )
. "referrer REGEXP %s", $refererRegexp )
);
}
if ( ! empty( $targetRegexp ) ) {
$wpdb->query(
$wpdb->prepare( "DELETE FROM `$wpdb->statify` WHERE "
. ( ( self::$_options['target']['regexp'] == 1 ) ? " BINARY " : "" )
. "target REGEXP %s", $targetRegexp )
);
}
/* Optimize DB */
$wpdb->query( "OPTIMIZE TABLE `$wpdb->statify`" );
/* Delete transient statify data */
delete_transient('statify_data');
delete_transient( 'statify_data' );
}
}
@ -143,12 +194,11 @@ class StatifyBlacklist_Admin extends StatifyBlacklist {
/**
* Sanitize URLs and remove empty results
*
* @param $urls array given array of URLs
* @param array $urls given array of URLs
*
* @return array sanitized array
*
* @since 1.1.1
* @changed 1.2.0
* @since 1.1.1
*/
private static function sanitizeURLs( $urls ) {
return array_flip(
@ -162,4 +212,22 @@ class StatifyBlacklist_Admin extends StatifyBlacklist {
)
);
}
/**
* Sanitize IP addresses with optional CIDR notation and remove empty results
*
* @param array $ips given array of URLs
*
* @return array sanitized array
*
* @since 1.4.0
*/
private static function sanitizeIPs( $ips ) {
return array_filter( $ips, function ( $ip ) {
return preg_match( '/^((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])' .
'(\/([0-9]|[1-2][0-9]|3[0-2]))?$/', $ip ) ||
preg_match( '/^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))' .
'(\/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8]))?$/', $ip );
} );
}
}

View File

@ -6,9 +6,11 @@ defined( 'ABSPATH' ) OR exit;
/**
* Statify Blacklist system configuration
*
* @since 1.0.0
* @since 1.0.0
* @version 1.4.0
*/
class StatifyBlacklist_System extends StatifyBlacklist {
/**
* Plugin install handler.
*
@ -17,21 +19,21 @@ class StatifyBlacklist_System extends StatifyBlacklist {
* @param bool $network_wide Whether the plugin was activated network-wide or not.
*/
public static function install( $network_wide = false ) {
global $wpdb;
// Create tables for each site in a network.
if ( is_multisite() && $network_wide ) {
// Todo: Use get_sites() in WordPress 4.6+
$ids = $wpdb->get_col( "SELECT blog_id FROM `$wpdb->blogs`" );
if ( function_exists( 'get_sites' ) ) {
$sites = get_sites();
} elseif ( function_exists( 'wp_get_sites' ) ) {
$sites = wp_get_sites(); /* legacy support for WP < 4.6 */
} else {
return;
}
foreach ( $ids as $site_id ) {
switch_to_blog( $site_id );
foreach ( $sites as $site ) {
switch_to_blog( $site['blog_id'] );
add_option(
'statify-blacklist',
array(
'activate-referer' => 0,
'referer' => array()
)
self::defaultOptions()
);
}
@ -39,10 +41,7 @@ class StatifyBlacklist_System extends StatifyBlacklist {
} else {
add_option(
'statify-blacklist',
array(
'activate-referer' => 0,
'referer' => array()
)
self::defaultOptions()
);
}
}
@ -54,16 +53,19 @@ class StatifyBlacklist_System extends StatifyBlacklist {
* @since 1.0.0
*/
public static function uninstall() {
global $wpdb;
if ( is_multisite() ) {
$old = get_current_blog_id();
// Todo: Use get_sites() in WordPress 4.6+
$ids = $wpdb->get_col( "SELECT blog_id FROM `$wpdb->blogs`" );
if ( function_exists( 'get_sites' ) ) {
$sites = get_sites();
} elseif ( function_exists( 'wp_get_sites' ) ) {
$sites = wp_get_sites(); /* legacy support for WP < 4.6 */
} else {
return;
}
foreach ( $ids as $id ) {
switch_to_blog( $id );
foreach ( $sites as $site ) {
switch_to_blog( $site['blog_id'] );
delete_option( 'statify-blacklist' );
}
@ -77,9 +79,6 @@ class StatifyBlacklist_System extends StatifyBlacklist {
/**
* Upgrade plugin options.
*
* @param object $upgrader Upgrader object (unused)
* @param array $options Options array
*
* @since 1.2.0
*/
public static function upgrade() {
@ -95,5 +94,47 @@ class StatifyBlacklist_System extends StatifyBlacklist {
update_option( 'statify-blacklist', $options );
}
}
/* Version not set (pre 1.3.0) or older than 1.4 */
if ( ! isset( self::$_options['version'] ) || self::$_options['version'] < 1.4 ) {
/* Upgrade options to new schema */
$options = array(
'referer' => array(
'active' => self::$_options['active_referer'],
'cron' => self::$_options['cron_referer'],
'regexp' => self::$_options['referer_regexp'],
'blacklist' => self::$_options['referer']
),
'target' => array(
'active' => 0,
'cron' => 0,
'regexp' => 0,
'blacklist' => array()
),
'ip' => array(
'active' => 0,
'blacklist' => array()
),
'version' => 1.4
);
if ( ( is_multisite() && array_key_exists( STATIFYBLACKLIST_BASE, (array) get_site_option( 'active_sitewide_plugins' ) ) ) ) {
update_site_option( 'statify-blacklist', $options );
} else {
update_option( 'statify-blacklist', $options );
}
self::update_options();
}
/* Version older than current major release */
if ( self::$_options['version'] < self::VERSION_MAIN ) {
/* Merge default options with current config, assuming only additive changes */
$options = array_merge_recursive( self::defaultOptions(), self::$_options );
$options['version'] = self::VERSION_MAIN;
if ( ( is_multisite() && array_key_exists( STATIFYBLACKLIST_BASE, (array) get_site_option( 'active_sitewide_plugins' ) ) ) ) {
update_site_option( 'statify-blacklist', $options );
} else {
update_option( 'statify-blacklist', $options );
}
}
}
}

View File

@ -5,10 +5,10 @@ Description: Extension for the statify plugin to add a customizable blacklists.
Text Domain: statify-blacklist
Domain Path: /lang
Author: Stefan Kalscheuer
Author URI: https://stklcode.de
Author URI: https://www.stklcode.de
Plugin URI: https://wordpress.org/plugins/statify-blacklist
License: GPLv3 or later
Version: 1.2.0
Version: 1.4.0
*/
/* Quit */
@ -26,7 +26,7 @@ register_activation_hook( STATIFYBLACKLIST_FILE, array( 'StatifyBlacklist_System
register_uninstall_hook( STATIFYBLACKLIST_FILE, array( 'StatifyBlacklist_System', 'uninstall' ) );
/* Upgrade hook to v1.2.0 */
/* Upgrade hook */
register_activation_hook( STATIFYBLACKLIST_FILE, array( 'StatifyBlacklist_System', 'upgrade' ) );
/* Autoload */
@ -35,7 +35,7 @@ spl_autoload_register( 'statifyBlacklist_autoload' );
/**
* Autoloader for StatifyBlacklist classes.
*
* @param $class
* @param string $class name of the class to load
*
* @since 1.0.0
*/

View File

@ -0,0 +1,468 @@
<?php
const ABSPATH = false;
require_once( '../inc/statifyblacklist.class.php' );
require_once( '../inc/statifyblacklist_system.class.php' );
require_once( '../inc/statifyblacklist_admin.class.php' );
/**
* Class StatifyBlacklistTest
*
* PHPUnit test class for StatifyBlacklist
*
* @version 1.4.0
*/
class StatifyBlacklistTest extends PHPUnit_Framework_TestCase {
/**
* Test simple referer filter.
*/
public function testRefererFilter() {
/* Prepare Options: 2 blacklisted domains, disabled */
StatifyBlacklist::$_options = array(
'referer' => array(
'active' => 0,
'cron' => 0,
'regexp' => 0,
'blacklist' => array(
'example.com' => 0,
'example.net' => 1
)
),
'target' => array(
'active' => 0,
'cron' => 0,
'regexp' => 0,
'blacklist' => array()
),
'ip' => array(
'active' => 0,
'blacklist' => array()
),
'version' => StatifyBlacklist::VERSION_MAIN
);
/* No multisite */
StatifyBlacklist::$multisite = false;
/* No referer */
unset( $_SERVER['HTTP_REFERER'] );
$this->assertNull( StatifyBlacklist::apply_blacklist_filter() );
/* Non-blacklisted referer */
$_SERVER['HTTP_REFERER'] = 'http://example.org';
$this->assertNull( StatifyBlacklist::apply_blacklist_filter() );
/* Blacklisted referer */
$_SERVER['HTTP_REFERER'] = 'http://example.com';
$this->assertNull( StatifyBlacklist::apply_blacklist_filter() );
/* Blacklisted referer with path */
$_SERVER['HTTP_REFERER'] = 'http://example.net/foo/bar.html';
$this->assertNull( StatifyBlacklist::apply_blacklist_filter() );
/* Activate filter and run tests again */
StatifyBlacklist::$_options['referer']['active'] = 1;
unset( $_SERVER['HTTP_REFERER'] );
$this->assertNull( StatifyBlacklist::apply_blacklist_filter() );
$_SERVER['HTTP_REFERER'] = 'http://example.org';
$this->assertNull( StatifyBlacklist::apply_blacklist_filter() );
$_SERVER['HTTP_REFERER'] = 'http://example.com';
$this->assertTrue( StatifyBlacklist::apply_blacklist_filter() );
$_SERVER['HTTP_REFERER'] = 'http://example.net/foo/bar.html';
$this->assertTrue( StatifyBlacklist::apply_blacklist_filter() );
}
/**
* Test referer filter using regular expressions.
*/
public function testRefererRegexFilter() {
/* Prepare Options: 2 regular expressions */
StatifyBlacklist::$_options = array(
'referer' => array(
'active' => 1,
'cron' => 0,
'regexp' => 1,
'blacklist' => array(
'example.[a-z]+' => 0,
'test' => 1
)
),
'target' => array(
'active' => 0,
'cron' => 0,
'regexp' => 0,
'blacklist' => array()
),
'ip' => array(
'active' => 0,
'blacklist' => array()
),
'version' => StatifyBlacklist::VERSION_MAIN
);
/* No multisite */
StatifyBlacklist::$multisite = false;
/* No referer */
unset( $_SERVER['HTTP_REFERER'] );
$this->assertNull( StatifyBlacklist::apply_blacklist_filter() );
/* Non-blacklisted referer */
$_SERVER['HTTP_REFERER'] = 'http://not.evil';
$this->assertNull( StatifyBlacklist::apply_blacklist_filter() );
/* Blacklisted referer */
$_SERVER['HTTP_REFERER'] = 'http://example.com';
$this->assertTrue( StatifyBlacklist::apply_blacklist_filter() );
/* Blacklisted referer with path */
$_SERVER['HTTP_REFERER'] = 'http://foobar.net/test/me';
$this->assertTrue( StatifyBlacklist::apply_blacklist_filter() );
/* Matching both */
$_SERVER['HTTP_REFERER'] = 'http://example.net/test/me';
$this->assertTrue( StatifyBlacklist::apply_blacklist_filter() );
/* Mathinc with wrong case */
$_SERVER['HTTP_REFERER'] = 'http://eXaMpLe.NeT/tEsT/mE';
$this->assertNull( StatifyBlacklist::apply_blacklist_filter() );
/* Set RegExp filter to case insensitive */
StatifyBlacklist::$_options['referer']['regexp'] = 2;
$this->assertTrue( StatifyBlacklist::apply_blacklist_filter() );
}
/**
* Test the upgrade methodology for configuration options.
*/
public function testUpgrade() {
/* Create configuration of version 1.3 */
$options13 = array(
'active_referer' => 1,
'cron_referer' => 0,
'referer' => array(
'example.net' => 0,
'example.com' => 1
),
'referer_regexp' => 0,
'version' => 1.3
);
/* Set options in mock */
update_option( 'statify-blacklist', $options13 );
/* Execute upgrade */
StatifyBlacklist_System::upgrade();
/* Retrieve updated options */
$optionsUpdated = get_option( 'statify-blacklist' );
/* Verify size against default options (no junk left) */
$this->assertEquals( 4, sizeof( $optionsUpdated ) );
$this->assertEquals( 4, sizeof( $optionsUpdated['referer'] ) );
$this->assertEquals( 4, sizeof( $optionsUpdated['target'] ) );
$this->assertEquals( 2, sizeof( $optionsUpdated['ip'] ) );
/* Verify that original attributes are unchanged */
$this->assertEquals( $options13['active_referer'], $optionsUpdated['referer']['active'] );
$this->assertEquals( $options13['cron_referer'], $optionsUpdated['referer']['cron'] );
$this->assertEquals( $options13['referer'], $optionsUpdated['referer']['blacklist'] );
$this->assertEquals( $options13['referer_regexp'], $optionsUpdated['referer']['regexp'] );
/* Verify that new attributes are present in config and filled with default values (disabled, empty) */
$this->assertEquals( 0, $optionsUpdated['target']['active'] );
$this->assertEquals( 0, $optionsUpdated['target']['cron'] );
$this->assertEquals( 0, $optionsUpdated['target']['regexp'] );
$this->assertEquals( array(), $optionsUpdated['target']['blacklist'] );
$this->assertEquals( 0, $optionsUpdated['ip']['active'] );
$this->assertEquals( array(), $optionsUpdated['ip']['blacklist'] );
/* Verify that version number has changed to current release */
$this->assertEquals( StatifyBlacklist::VERSION_MAIN, $optionsUpdated['version'] );
}
/**
* Test CIDR address matching for IP filter (#7)
*/
public function testCidrMatch() {
/* IPv4 tests */
$this->assertTrue( invokeStatic( StatifyBlacklist::class, 'cidrMatch', array( '127.0.0.1', '127.0.0.1' ) ) );
$this->assertTrue( invokeStatic( StatifyBlacklist::class, 'cidrMatch', array( '127.0.0.1', '127.0.0.1/32' ) ) );
$this->assertFalse( invokeStatic( StatifyBlacklist::class, 'cidrMatch', array(
'127.0.0.1',
'127.0.0.1/33'
) ) );
$this->assertFalse( invokeStatic( StatifyBlacklist::class, 'cidrMatch', array(
'127.0.0.1',
'127.0.0.1/-1'
) ) );
$this->assertTrue( invokeStatic( StatifyBlacklist::class, 'cidrMatch', array(
'192.0.2.123',
'192.0.2.0/24'
) ) );
$this->assertFalse( invokeStatic( StatifyBlacklist::class, 'cidrMatch', array(
'192.0.3.123',
'192.0.2.0/24'
) ) );
$this->assertTrue( invokeStatic( StatifyBlacklist::class, 'cidrMatch', array(
'192.0.2.123',
'192.0.2.120/29'
) ) );
$this->assertFalse( invokeStatic( StatifyBlacklist::class, 'cidrMatch', array(
'192.0.2.128',
'192.0.2.120/29'
) ) );
$this->assertTrue( invokeStatic( StatifyBlacklist::class, 'cidrMatch', array( '10.11.12.13', '10.0.0.0/8' ) ) );
$this->assertFalse( invokeStatic( StatifyBlacklist::class, 'cidrMatch', array(
'10.11.12.345',
'10.0.0.0/8'
) ) );
/* IPv6 tests */
$this->assertTrue( invokeStatic( StatifyBlacklist::class, 'cidrMatch', array( '::1', '::1' ) ) );
$this->assertTrue( invokeStatic( StatifyBlacklist::class, 'cidrMatch', array( '::1', '::1/128' ) ) );
$this->assertFalse( invokeStatic( StatifyBlacklist::class, 'cidrMatch', array( '::1', '::1/129' ) ) );
$this->assertFalse( invokeStatic( StatifyBlacklist::class, 'cidrMatch', array( '::1', '::1/-1' ) ) );
$this->assertTrue( invokeStatic( StatifyBlacklist::class, 'cidrMatch', array(
'2001:db8:a0b:12f0:1:2:3:4',
'2001:db8:a0b:12f0::1/64 '
) ) );
$this->assertTrue( invokeStatic( StatifyBlacklist::class, 'cidrMatch', array(
'2001:db8:a0b:12f0::123:456',
'2001:db8:a0b:12f0::1/96 '
) ) );
$this->assertFalse( invokeStatic( StatifyBlacklist::class, 'cidrMatch', array(
'2001:db8:a0b:12f0::1:132:465',
'2001:db8:a0b:12f0::1/96 '
) ) );
}
/**
* Test sanitization of IP addresses
*/
public function testSanitizeIPs() {
/* IPv4 tests */
$valid = array( '192.0.2.123', '192.0.2.123/32', '192.0.2.0/24', '192.0.2.128/25' );
$invalid = array( '12.34.56.789', '192.0.2.123/33', '192.0.2.123/-1' );
$result = invokeStatic( StatifyBlacklist_Admin::class, 'sanitizeIPs', array( array_merge( $valid, $invalid ) ) );
$this->assertNotFalse( $result );
$this->assertInternalType( 'array', $result );
$this->assertEquals( $valid, $result );
/* IPv6 tests */
$valid = array(
'2001:db8:a0b:12f0::',
'2001:db8:a0b:12f0::1',
'2001:db8:a0b:12f0::1/128',
'2001:db8:a0b:12f0::/64'
);
$invalid = array(
'2001:db8:a0b:12f0::x',
'2001:db8:a0b:12f0:::',
'2001:fffff:a0b:12f0::1',
'2001:db8:a0b:12f0::/129',
'1:2:3:4:5:6:7:8:9'
);
$result = invokeStatic( StatifyBlacklist_Admin::class, 'sanitizeIPs', array( array_merge( $valid, $invalid ) ) );
$this->assertNotFalse( $result );
$this->assertInternalType( 'array', $result );
$this->assertEquals( $valid, $result );
}
/**
* Test IP filter (#7).
*/
public function testIPFilter() {
/* Prepare Options: 2 blacklisted IPs, disabled */
StatifyBlacklist::$_options = array(
'referer' => array(
'active' => 0,
'cron' => 0,
'regexp' => 0,
'blacklist' => array()
),
'target' => array(
'active' => 0,
'cron' => 0,
'regexp' => 0,
'blacklist' => array()
),
'ip' => array(
'active' => 0,
'blacklist' => array(
'192.0.2.123',
'2001:db8:a0b:12f0::1'
)
),
'version' => StatifyBlacklist::VERSION_MAIN
);
/* No multisite */
StatifyBlacklist::$multisite = false;
/* Set matching IP */
$_SERVER['REMOTE_ADDR'] = '192.0.2.123';
$this->assertNull( StatifyBlacklist::apply_blacklist_filter() );
/* Activate filter */
StatifyBlacklist::$_options['ip']['active'] = 1;
$this->assertTrue( StatifyBlacklist::apply_blacklist_filter() );
/* Try matching v6 address */
$_SERVER['REMOTE_ADDR'] = '2001:db8:a0b:12f0::1';
$this->assertTrue( StatifyBlacklist::apply_blacklist_filter() );
/* Non-matching addresses */
$_SERVER['REMOTE_ADDR'] = '192.0.2.234';
$this->assertNull( StatifyBlacklist::apply_blacklist_filter() );
$_SERVER['REMOTE_ADDR'] = '2001:db8:a0b:12f0::2';
$this->assertNull( StatifyBlacklist::apply_blacklist_filter() );
/* Subnet matching */
StatifyBlacklist::$_options['ip']['blacklist'] = array(
'192.0.2.0/25',
'2001:db8:a0b:12f0::/96'
);
$_SERVER['REMOTE_ADDR'] = '192.0.2.123';
$this->assertTrue( StatifyBlacklist::apply_blacklist_filter() );
$_SERVER['REMOTE_ADDR'] = '192.0.2.234';
$this->assertNull( StatifyBlacklist::apply_blacklist_filter() );
$_SERVER['REMOTE_ADDR'] = '2001:db8:a0b:12f0::5';
$this->assertTrue( StatifyBlacklist::apply_blacklist_filter() );
$_SERVER['REMOTE_ADDR'] = '2001:db8:a0b:12f0:0:1111::1';
$this->assertNull( StatifyBlacklist::apply_blacklist_filter() );
/* Filter using proxy header */
$_SERVER['REMOTE_ADDR'] = '127.0.0.1';
$this->assertNull( StatifyBlacklist::apply_blacklist_filter() );
$_SERVER['HTTP_X_FORWARDED_FOR'] = '192.0.2.123';
$this->assertTrue( StatifyBlacklist::apply_blacklist_filter() );
$_SERVER['HTTP_X_REAL_IP'] = '2001:db8:a0b:12f0:0:1111::1';
$this->assertNull( StatifyBlacklist::apply_blacklist_filter() );
$_SERVER['HTTP_X_REAL_IP'] = '2001:db8:a0b:12f0:0::1';
$this->assertTrue( StatifyBlacklist::apply_blacklist_filter() );
}
/**
* Test simple target filter.
*/
public function testTargetFilter() {
/* Prepare Options: 2 blacklisted domains, disabled */
StatifyBlacklist::$_options = array(
'referer' => array(
'active' => 0,
'cron' => 0,
'regexp' => 0,
'blacklist' => array()
),
'target' => array(
'active' => 0,
'cron' => 0,
'regexp' => 0,
'blacklist' => array(
'/excluded/page/' => 0,
'/?page_id=3' => 1
)
),
'ip' => array(
'active' => 0,
'blacklist' => array()
),
'version' => StatifyBlacklist::VERSION_MAIN
);
/* No multisite */
StatifyBlacklist::$multisite = false;
/* Empty target */
unset( $_SERVER['REQUEST_URI'] );
$this->assertNull( StatifyBlacklist::apply_blacklist_filter() );
/* Non-blacklisted targets */
$_SERVER['REQUEST_URI'] = '';
$this->assertNull( StatifyBlacklist::apply_blacklist_filter() );
$_SERVER['REQUEST_URI'] = '/';
$this->assertNull( StatifyBlacklist::apply_blacklist_filter() );
$_SERVER['REQUEST_URI'] = '/?page_id=1';
$this->assertNull( StatifyBlacklist::apply_blacklist_filter() );
/* Blacklisted referer */
$_SERVER['REQUEST_URI'] = '/excluded/page/';
$this->assertNull( StatifyBlacklist::apply_blacklist_filter() );
$_SERVER['REQUEST_URI'] = '/?page_id=3';
$this->assertNull( StatifyBlacklist::apply_blacklist_filter() );
/* Activate filter and run tests again */
StatifyBlacklist::$_options['target']['active'] = 1;
unset( $_SERVER['REQUEST_URI'] );
$this->assertNull( StatifyBlacklist::apply_blacklist_filter() );
$_SERVER['REQUEST_URI'] = '';
$this->assertNull( StatifyBlacklist::apply_blacklist_filter() );
$_SERVER['REQUEST_URI'] = '/';
$this->assertNull( StatifyBlacklist::apply_blacklist_filter() );
$_SERVER['REQUEST_URI'] = '/?page_id=1';
$this->assertNull( StatifyBlacklist::apply_blacklist_filter() );
$_SERVER['REQUEST_URI'] = '/excluded/page/';
$this->assertTrue( StatifyBlacklist::apply_blacklist_filter() );
$_SERVER['REQUEST_URI'] = '/?page_id=3';
$this->assertTrue( StatifyBlacklist::apply_blacklist_filter() );
$_SERVER['REQUEST_URI'] = '/?page_id=3';
$this->assertTrue( StatifyBlacklist::apply_blacklist_filter() );
}
/**
* Test target filter using regular expressions.
*/
public function testTargetRegexFilter() {
// TODO
}
}
/**
* Helper for testing inaccessible static methods
*/
function invokeStatic( $class, $methodName, $parameters = array() ) {
$reflection = new \ReflectionClass( $class );
$method = $reflection->getMethod( $methodName );
$method->setAccessible( true );
return $method->invokeArgs( null, $parameters );
}
/* Some mocked functions */
$mock_options = array();
$mock_multisite = false;
function is_multisite() {
global $mock_multisite;
return $mock_multisite;
}
function wp_parse_args( $args, $defaults = '' ) {
if ( is_object( $args ) ) {
$r = get_object_vars( $args );
} elseif ( is_array( $args ) ) {
$r =& $args;
} else {
parse_str( $args, $r );
}
if ( is_array( $defaults ) ) {
return array_merge( $defaults, $r );
}
return $r;
}
function get_option( $option, $default = false ) {
global $mock_options;
return isset( $mock_options[ $option ] ) ? $mock_options[ $option ] : $default;
}
function update_option( $option, $value, $autoload = null ) {
global $mock_options;
$mock_options[ $option ] = $value;
}
function wp_unslash ( $value ) {
return is_string( $value ) ? stripslashes( $value ) : $value;
}

View File

@ -10,7 +10,7 @@ if ( ! empty( $_POST['statifyblacklist'] ) ) {
/* Check user capabilities */
if ( ! current_user_can( 'manage_options' ) ) {
die( _e( 'Are you sure you want to do this?' ) );
die( __( 'Are you sure you want to do this?' ) );
}
if ( ! empty( $_POST['cleanUp'] ) ) {
@ -18,95 +18,257 @@ if ( ! empty( $_POST['statifyblacklist'] ) ) {
StatifyBlacklist_Admin::cleanup_database();
} else {
/* Extract referer array */
if ( empty( trim( $_POST['statifyblacklist']['referer'] ) ) ) {
if ( empty( trim( $_POST['statifyblacklist']['referer']['blacklist'] ) ) ) {
$referer = array();
} else {
$referer = explode( "\r\n", $_POST['statifyblacklist']['referer'] );
$referer = explode( "\r\n", $_POST['statifyblacklist']['referer']['blacklist'] );
}
/* Extract target array */
if ( empty( trim( $_POST['statifyblacklist']['target']['blacklist'] ) ) ) {
$target = array();
} else {
$target = explode( "\r\n", str_replace( '\\\\', '\\', $_POST['statifyblacklist']['target']['blacklist'] ) );
}
/* Extract IP array */
if ( empty( trim( $_POST['statifyblacklist']['ip']['blacklist'] ) ) ) {
$ip = array();
} else {
$ip = explode( "\r\n", $_POST['statifyblacklist']['ip']['blacklist'] );
}
/* Update options (data will be sanitized) */
$statifyBlacklistUpdateResult = StatifyBlacklist_Admin::update_options(
array(
'active_referer' => (int) @$_POST['statifyblacklist']['active_referer'],
'cron_referer' => (int) @$_POST['statifyblacklist']['cron_referer'],
'referer' => array_flip( $referer )
'referer' => array(
'active' => (int) @$_POST['statifyblacklist']['referer']['active'],
'cron' => (int) @$_POST['statifyblacklist']['referer']['cron'],
'regexp' => (int) @$_POST['statifyblacklist']['referer']['regexp'],
'blacklist' => array_flip( $referer )
),
'target' => array(
'active' => (int) @$_POST['statifyblacklist']['target']['active'],
'cron' => (int) @$_POST['statifyblacklist']['target']['cron'],
'regexp' => (int) @$_POST['statifyblacklist']['target']['regexp'],
'blacklist' => array_flip( $target )
),
'ip' => array(
'active' => (int) @$_POST['statifyblacklist']['ip']['active'],
'blacklist' => $ip
),
'version' => StatifyBlacklist::VERSION_MAIN
)
);
/* Generate messages */
if ( $statifyBlacklistUpdateResult !== false ) {
$statifyBlacklistPostWarning = 'Some URLs are invalid and have been sanitized. Settings have not been saved yet.';
if ( array_key_exists( 'referer', $statifyBlacklistUpdateResult ) ) {
$statifyBlacklistPostWarning = __( 'Some URLs are invalid and have been sanitized.', 'statify-blacklist' );
} elseif ( array_key_exists( 'ip', $statifyBlacklistUpdateResult ) ) {
$statifyBlacklistPostWarning = sprintf( __( 'Some IPs are invalid : %s', 'statify-blacklist' ), implode( ', ', $statifyBlacklistUpdateResult['ip'] ) );
}
} else {
$statifyBlacklistPostSuccess = 'Settings updated successfully.';
$statifyBlacklistPostSuccess = __( 'Settings updated successfully.', 'statify-blacklist' );
}
}
}
?>
<div class="wrap">
<h1><?php _e( 'Statify Blacklist', 'statify-blacklist' ) ?></h1>
<h1><?php _e( 'Statify Blacklist', 'statify-blacklist' ) ?></h1>
<?php
if ( is_plugin_inactive( 'statify/statify.php' ) ) {
print '<div class="notice notice-warning"><p>';
esc_html_e( 'Statify plugin is not active.', 'statify-blacklist' );
esc_html( 'Statify plugin is not active.' );
print '</p></div>';
}
if ( isset( $statifyBlacklistPostWarning ) ) {
print '<div class="notice notice-warning"><p>';
esc_html_e( $statifyBlacklistPostWarning );
print '<div class="notice notice-warning"><p>' .
esc_html( $statifyBlacklistPostWarning );
print '<br/>';
esc_html_e( 'Settings have not been saved yet.', 'statify-blacklist' );
print '</p></div>';
}
if ( isset( $statifyBlacklistPostSuccess ) ) {
print '<div class="notice notice-success"><p>';
esc_html_e( $statifyBlacklistPostSuccess );
print '</p></div>';
print '<div class="notice notice-success"><p>' .
esc_html( $statifyBlacklistPostSuccess ) .
'</p></div>';
}
?>
<form action="" method="post" id="statify-blacklist-settings">
<ul style="list-style: none;">
<li>
<label for="statify-blacklist_active_referer">
<input type="checkbox" name="statifyblacklist[active_referer]" id="statifyblacklist_active_referer"
value="1" <?php checked( StatifyBlacklist::$_options['active_referer'], 1 ); ?> />
<?php esc_html_e( 'Activate referer blacklist', 'statify-blacklist' ); ?>
</label>
</li>
<li>
<label for="statify-blacklist_cron_referer">
<input type="checkbox" name="statifyblacklist[cron_referer]" id="statifyblacklist_cron_referer"
value="1" <?php checked( StatifyBlacklist::$_options['cron_referer'], 1 ); ?> />
<?php esc_html_e( 'CronJob execution', 'statify-blacklist' ); ?>
<small>(<?php esc_html_e( 'Clean database periodically in background', 'statify-blacklist' ); ?>)</small>
</label>
</li>
<li>
<label for="statify-blacklist_referer">
<?php esc_html_e( 'Referer blacklist:', 'statify-blacklist' ); ?><br/>
<textarea cols="40" rows="5" name="statifyblacklist[referer]" id="statify-blacklist_referer"><?php
if ( isset( $statifyBlacklistUpdateResult ) && $statifyBlacklistUpdateResult !== false ) {
print esc_html( implode( "\r\n", array_keys( $statifyBlacklistUpdateResult ) ) );
} else {
print esc_html( implode( "\r\n", array_keys( StatifyBlacklist::$_options['referer'] ) ) );
}
?></textarea>
<br />
<small>
(<?php esc_html_e( 'Add one domain (without subdomains) each line, e.g. example.com', 'statify-blacklist' ); ?>
)
</small>
</label>
</li>
</ul>
<form action="" method="post" id="statify-blacklist-settings">
<fieldset>
<h2><?php esc_html_e( 'Referer blacklist', 'statify-blacklist' ); ?></h2>
<ul style="list-style: none;">
<li>
<label for="statify-blacklist_active_referer">
<input type="checkbox" name="statifyblacklist[referer][active]"
id="statifyblacklist_active_referer"
value="1" <?php checked( StatifyBlacklist::$_options['referer']['active'], 1 ); ?> />
<?php esc_html_e( 'Activate live fiter', 'statify-blacklist' ); ?>
</label>
</li>
<li>
<label for="statify-blacklist_cron_referer">
<input type="checkbox" name="statifyblacklist[referer][cron]" id="statifyblacklist_cron_referer"
value="1" <?php checked( StatifyBlacklist::$_options['referer']['cron'], 1 ); ?> />
<?php esc_html_e( 'CronJob execution', 'statify-blacklist' ); ?>
<small>(<?php esc_html_e( 'Clean database periodically in background', 'statify-blacklist' ); ?>
)
</small>
</label>
</li>
<li>
<label for="statify-blacklist_referer_regexp">
<?php esc_html_e( 'Use regular expressions', 'statify-blacklist' ); ?>:
<br/>
<select name="statifyblacklist[referer][regexp]" id="statifyblacklist_referer_regexp">
<option value="0" <?php selected( StatifyBlacklist::$_options['referer']['regexp'], 0 ); ?>>
<?php esc_html_e( 'Disabled', 'statify-blacklist' ); ?>
</option>
<option value="1" <?php selected( StatifyBlacklist::$_options['referer']['regexp'], 1 ); ?>>
<?php esc_html_e( 'Case-sensitive', 'statify-blacklist' ); ?>
</option>
<option value="2" <?php selected( StatifyBlacklist::$_options['referer']['regexp'], 2 ); ?>>
<?php esc_html_e( 'Case-insensitive', 'statify-blacklist' ); ?>
</option>
</select>
<small>
(<?php esc_html_e( 'Performance slower than standard filter. Recommended for cron or manual execition only.', 'statify-blacklist' ); ?>
)
</small>
</label>
</li>
<li>
<label for="statify-blacklist_referer">
<?php esc_html_e( 'Referer blacklist', 'statify-blacklist' ); ?>:<br/>
<textarea cols="40" rows="5" name="statifyblacklist[referer][blacklist]" id="statify-blacklist_referer"><?php
if ( isset( $statifyBlacklistUpdateResult['referer'] ) ) {
print esc_html( implode( "\r\n", array_keys( $statifyBlacklistUpdateResult['referer'] ) ) );
} else {
print esc_html( implode( "\r\n", array_keys( StatifyBlacklist::$_options['referer']['blacklist'] ) ) );
}
?></textarea>
<br/>
<small>
(<?php esc_html_e( 'Add one domain (without subdomains) each line, e.g. example.com', 'statify-blacklist' ); ?>
)
</small>
</label>
</li>
</ul>
</fieldset>
<fieldset>
<h2><?php esc_html_e( 'Target blacklist', 'statify-blacklist' ); ?></h2>
<ul style="list-style: none;">
<li>
<label for="statify-blacklist_active_target">
<input type="checkbox" name="statifyblacklist[target][active]"
id="statifyblacklist_active_target"
value="1" <?php checked( StatifyBlacklist::$_options['target']['active'], 1 ); ?> />
<?php esc_html_e( 'Activate live fiter', 'statify-blacklist' ); ?>
</label>
</li>
<li>
<label for="statify-blacklist_cron_target">
<input type="checkbox" name="statifyblacklist[target][cron]" id="statifyblacklist_cron_target"
value="1" <?php checked( StatifyBlacklist::$_options['target']['cron'], 1 ); ?> />
<?php esc_html_e( 'CronJob execution', 'statify-blacklist' ); ?>
<small>(<?php esc_html_e( 'Clean database periodically in background', 'statify-blacklist' ); ?>
)
</small>
</label>
</li>
<li>
<label for="statify-blacklist_target_regexp">
<?php esc_html_e( 'Use regular expressions', 'statify-blacklist' ); ?>:
<br/>
<select name="statifyblacklist[target][regexp]" id="statifyblacklist_target_regexp">
<option value="0" <?php selected( StatifyBlacklist::$_options['target']['regexp'], 0 ); ?>>
<?php esc_html_e( 'Disabled', 'statify-blacklist' ); ?>
</option>
<option value="1" <?php selected( StatifyBlacklist::$_options['target']['regexp'], 1 ); ?>>
<?php esc_html_e( 'Case-sensitive', 'statify-blacklist' ); ?>
</option>
<option value="2" <?php selected( StatifyBlacklist::$_options['target']['regexp'], 2 ); ?>>
<?php esc_html_e( 'Case-insensitive', 'statify-blacklist' ); ?>
</option>
</select>
<small>
(<?php esc_html_e( 'Performance slower than standard filter. Recommended for cron or manual execition only.', 'statify-blacklist' ); ?>
)
</small>
</label>
</li>
<li>
<label for="statify-blacklist_target">
<?php esc_html_e( 'Target blacklist', 'statify-blacklist' ); ?>:<br/>
<textarea cols="40" rows="5" name="statifyblacklist[target][blacklist]" id="statify-blacklist_target"><?php
if ( isset( $statifyBlacklistUpdateResult['target'] ) ) {
print esc_html( implode( "\r\n", array_keys( $statifyBlacklistUpdateResult['target'] ) ) );
} else {
print esc_html( implode( "\r\n", array_keys( StatifyBlacklist::$_options['target']['blacklist'] ) ) );
}
?></textarea>
<br/>
<small>
(<?php esc_html_e( 'Add one target URL each line, e.g.', 'statify-blacklist' );
print ' /, /test/page/, /?page_id=123' ?>
)
</small>
</label>
</li>
</ul>
</fieldset>
<fieldset>
<h2><?php esc_html_e( 'IP blacklist', 'statify-blacklist' ); ?></h2>
<ul style="list-style: none;">
<li>
<label for="statify-blacklist_active_ip">
<input type="checkbox" name="statifyblacklist[ip][active]" id="statifyblacklist_active_ip"
value="1" <?php checked( StatifyBlacklist::$_options['ip']['active'], 1 ); ?> />
<?php esc_html_e( 'Activate live fiter', 'statify-blacklist' ); ?>
</label>
</li>
<li>
<small>
(<?php esc_html_e( 'Cron execution is not possible for IP filter, because IP addresses are not stored.', 'statify-blacklist' ); ?>
)
</small>
</li>
<li>
<label for="statify-blacklist_ip">
<?php esc_html_e( 'IP blacklist', 'statify-blacklist' ); ?>:<br/>
<textarea cols="40" rows="5" name="statifyblacklist[ip][blacklist]" id="statify-blacklist_ip"><?php
if ( isset( $statifyBlacklistUpdateResult['ip'] ) ) {
print esc_html( $_POST['statifyblacklist']['ip']['blacklist'] );
} else {
print esc_html( implode( "\r\n", StatifyBlacklist::$_options['ip']['blacklist'] ) );
}
?></textarea>
<br/>
<small>
(<?php esc_html_e( 'Add one IP address or range per line, e.g.' ) ?> 127.0.0.1,
192.168.123.0/24, 2001:db8:a0b:12f0::1/64
)
</small>
</label>
</li>
</ul>
</fieldset>
<?php wp_nonce_field( 'statify-blacklist-settings' ); ?>
<p class="submit">
<input class="button-primary" type="submit" name="submit" value="<?php _e( 'Save Changes' ) ?>">
<hr />
<input class="button-secondary" type="submit" name="cleanUp"
value="<?php esc_html_e( 'CleanUp Database', 'statify-blacklist' ) ?>"
onclick="return confirm('Do you really want to apply filters to database? This cannot be undone.');">
<br />
<small><?php esc_html_e( 'Applies filter (even if disabled) to data stored in database. This cannot be undone!', 'statify-blacklist' ); ?></small>
</p>
</form>
<p class="submit">
<input class="button-primary" type="submit" name="submit" value="<?php _e( 'Save Changes' ) ?>">
<hr/>
<input class="button-secondary" type="submit" name="cleanUp"
value="<?php esc_html_e( 'CleanUp Database', 'statify-blacklist' ) ?>"
onclick="return confirm('Do you really want to apply filters to database? This cannot be undone.');">
<br/>
<small><?php esc_html_e( 'Applies referer and target filter (even if disabled) to data stored in database.', 'statify-blacklist' ); ?> <b><?php esc_html_e( 'This cannot be undone!', 'statify-blacklist' ); ?></b></small>
</p>
</form>
</div>