Merge branch 'release/1.5.0'
This commit is contained in:
commit
f946d3415a
12
.gitattributes
vendored
Normal file
12
.gitattributes
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
/assets export-ignore
|
||||
/test export-ignore
|
||||
.gitattributes export-ignore
|
||||
.gitignore export-ignore
|
||||
.travis.yml export-ignore
|
||||
composer.json export-ignore
|
||||
composer.lock export-ignore
|
||||
CONTRIBUTING.md export-ignore
|
||||
package.json export-ignore
|
||||
phpcs.xml export-ignore
|
||||
phpunit.xml export-ignore
|
||||
RoboFile.php export-ignore
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -5,3 +5,4 @@ composer.lock
|
||||
.idea
|
||||
tests-clover.xml
|
||||
tests-junit.xml
|
||||
.phpunit.result.cache
|
||||
|
@ -1,12 +1,13 @@
|
||||
language: php
|
||||
dist: trusty
|
||||
php:
|
||||
- '5.5'
|
||||
- '5.6'
|
||||
- '7.0'
|
||||
- '7.1'
|
||||
- '7.2'
|
||||
- '7.3'
|
||||
- '7.4'
|
||||
before_script:
|
||||
- composer install
|
||||
script:
|
||||
- composer test-all
|
||||
notifications:
|
||||
slack:
|
||||
secure: "ScXTSMO65veI1jA6TBHGDUtvDqEMkqJykaNf7vLLbb7YIxPIHHNBiX/wcjOHVFfQXZCV3qxQrflB7Lbm9qVUsAv861jTO9x/ZkECl5QhRoc0DIznejwZoypx0HJ9tBZFYT6qNUkViXRKZ/ILAiBLU9Yw52WACtQB9hu3FNFZwmKsjipvV8Sne1qEyTkLYLaMphsbC5mtXYdKMHvdt39jsYsk91UWGeYbXQ37LkMbsaG/8YHXF724d5JO7BRGoThw6p5knKAO5fk29V7GfNqg2h+hnGyNIUOcmxujgMDMFLyFCGMZpPoBa+3jyWWgq4PgpQt0F5VZtJFGoXCGcoMQm5IbVfqkSKJ4jYhqiSIrqSebLmzoPHepWX3yn8tpfOiBWjC6K9w9esp6vcZf26rnAJcjcGkA01rMrHRwR+UEMCLvj7q0DR0qzi/AFeED6gtpODzUf93Rp42Tz1iGvWIbgeCtkCWjfPO6XLuNiqGVPEVaT5BDKqlqbijdKxxp7yh1fdt8s0fInWdIsgoWTbU9DC1W4ZiqtQW7oYO+QtFZMaD6kZWpSqJUwB3kW5JL3odAUEm8bLbRWBvK5ZjGdaGqSbOs6f9gAKcf86iQQhwzCJSOgFlLlKFv9smicjPC+BGOxgx32pgseHNPWn6tmEo/ihmmr/NbbqoOusUKX9gQbA4="
|
||||
|
@ -33,17 +33,19 @@ If the changes introduce new functionality or affect major parts of existing cod
|
||||
|
||||
For adding new functionality a new test case the corresponding PHPUnit test would be nice (no hard criterion though).
|
||||
|
||||
The `master` branch should also be target for most pull requests.
|
||||
However it it features new functionality you might want to target the `develop` branch instead (see next section for details on branches).
|
||||
|
||||
### Branches
|
||||
|
||||
The `master` branch represents the current state of development.
|
||||
Please ensure your initial code is up to date with it at the time you start development.
|
||||
The `master` should also be target for most pull requests.
|
||||
|
||||
In addition, this project features a `develop` branch, which holds bleeding edge developments, not necessarily considered stable or even compatible.
|
||||
Do not expect this code to run smoothly, but you might have a look into the history to see if some work on an issue has already been started there.
|
||||
|
||||
For fixes and features, there might be additional branches, likely prefixed by `ft-` (feature) or `hf-` (hotfix) followed by an issue number (if applicable) and/or a title.
|
||||
Feel free to adapt these naming scheme to your forks.
|
||||
For fixes and features, there might be additional branches, likely prefixed by `hotfix/` or `feature/` followed by an issue number (if applicable) and/or a title.
|
||||
Feel free to adapt this naming scheme to your forks.
|
||||
|
||||
### Merge Requirements
|
||||
|
||||
|
65
Gulpfile.js
65
Gulpfile.js
@ -1,65 +0,0 @@
|
||||
var gulp = require('gulp');
|
||||
var clean = require('gulp-clean');
|
||||
var copy = require('gulp-copy');
|
||||
var zip = require('gulp-zip');
|
||||
var composer = require('gulp-composer');
|
||||
var phpunit = require('gulp-phpunit');
|
||||
var exec = require('child_process').exec;
|
||||
var phpcs = require('gulp-phpcs');
|
||||
var config = require('./package.json');
|
||||
|
||||
// Clean the target directory.
|
||||
gulp.task('clean', function () {
|
||||
console.log('Cleaning up target directory ...');
|
||||
return gulp.src('dist', {read: false})
|
||||
.pipe(clean());
|
||||
});
|
||||
|
||||
// Prepare composer.
|
||||
gulp.task('compose', function () {
|
||||
console.log('Preparing Composer ...');
|
||||
return composer('install');
|
||||
});
|
||||
|
||||
// Execute unit tests.
|
||||
gulp.task('test', ['compose'], function () {
|
||||
console.log('Running PHPUnit tests ...');
|
||||
return gulp.src('phpunit.xml')
|
||||
.pipe(phpunit('./vendor/bin/phpunit', {debug: false}));
|
||||
});
|
||||
|
||||
// Execute PHP Code Sniffer.
|
||||
gulp.task('test-cs', function (cb) {
|
||||
return exec('./vendor/bin/phpcs --config-set installed_paths vendor/wimg/php-compatibility,vendor/wp-coding-standards/wpcs', function (err, stdout, stderr) {
|
||||
console.log(stdout);
|
||||
console.log(stderr);
|
||||
if (null === err) {
|
||||
console.log('Running PHP Code Sniffer tests ...');
|
||||
// exec('./vendor/bin/phpcs --standard=phpcs.xml', function(err, stdout, stderr) {
|
||||
// console.log(stdout);
|
||||
// console.log(stderr);
|
||||
// });
|
||||
gulp.src(['statify-blacklist.php', 'inc/**/*.php'])
|
||||
.pipe(phpcs({bin: './vendor/bin/phpcs', standard: 'phpcs.xml'}))
|
||||
.pipe(phpcs.reporter('log'));
|
||||
}
|
||||
cb(err);
|
||||
});
|
||||
});
|
||||
|
||||
// Bundle files as required for plugin distribution..
|
||||
gulp.task('bundle', ['clean'], function () {
|
||||
console.log('Collecting files for package dist/' + config.name + config.version + ' ...');
|
||||
return gulp.src(['**/*.php', '!RoboFile.php', '!test/**', '!vendor/**', 'README.md', 'LICENSE.md'], {base: './'})
|
||||
.pipe(copy('./dist/' + config.name + '.' + config.version + '/' + config.name));
|
||||
});
|
||||
|
||||
// Create a ZIP package of the relevant files for plugin distribution.
|
||||
gulp.task('package', ['bundle'], function () {
|
||||
console.log('Building package dist/' + config.name + config.version + '.zip ...');
|
||||
return gulp.src('./dist/' + config.name + '.' + config.version + '/**')
|
||||
.pipe(zip(config.name + '.' + config.version + '.zip'))
|
||||
.pipe(gulp.dest('./dist'));
|
||||
});
|
||||
|
||||
gulp.task('default', ['clean', 'compose', 'test', 'test-cs', 'bundle', 'package']);
|
@ -357,5 +357,5 @@ into proprietary programs. If your program is a subroutine library,
|
||||
you may consider it more useful to permit linking proprietary
|
||||
applications with the library. If this is what you want to do, use the
|
||||
[GNU Lesser General Public
|
||||
License](http://www.gnu.org/licenses/lgpl.html) instead of this
|
||||
License](https://www.gnu.org/licenses/lgpl.html) instead of this
|
||||
License.
|
||||
|
52
README.md
52
README.md
@ -1,16 +1,21 @@
|
||||
[](https://travis-ci.org/stklcode/statify-blacklist)
|
||||
[](https://sonarcloud.io/dashboard?id=de.stklcode.web.wordpress.plugins%3Astatify-blacklist)
|
||||
[](https://packagist.org/packages/stklcode/statify-blacklist)
|
||||
[](https://github.com/stklcode/statify-blacklist/blob/master/LICENSE.md)
|
||||
|
||||
# Statify Blacklist #
|
||||
* Contributors: Stefan Kalscheuer
|
||||
* Requires at least: 4.4
|
||||
* Requires at least: 4.7
|
||||
* Tested up to: 5.4
|
||||
* Requires PHP: 5.5
|
||||
* Stable tag: 1.4.4
|
||||
* Stable tag: 1.5.0
|
||||
* License: GPLv2 or later
|
||||
* License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
||||
|
||||
## Description ##
|
||||
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.
|
||||
This plugin adds a customizable blacklist to Statify to allow blocking of referer spam or internal interactions.
|
||||
|
||||
### Features ##
|
||||
|
||||
@ -27,7 +32,7 @@ Add a list of IP addresses or subnets (e.g. _192.0.2.123_, _198.51.100.0/24_, _2
|
||||
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 up to version 1.5.1
|
||||
This plugin requires Statify to be installed. The extension has been tested with Statify up to version 1.7
|
||||
The plugin is capable of handling multisite installations.
|
||||
|
||||
### Support & Contributions ###
|
||||
@ -37,51 +42,62 @@ The plugin is capable of handling multisite installations.
|
||||
|
||||
### Credits ###
|
||||
* Author: Stefan Kalscheuer
|
||||
* Special Thanks to [pluginkollektiv](https://github.com/pluginkollektiv) for maintaining _Statify_
|
||||
* Special Thanks to [pluginkollektiv](https://pluginkollektiv.org/) for maintaining _Statify_
|
||||
|
||||
## Installation ##
|
||||
* If you don’t know how to install a plugin for WordPress, [here’s how](http://codex.wordpress.org/Managing_Plugins#Installing_Plugins).
|
||||
* If you don’t know how to install a plugin for WordPress, [here’s how](https://wordpress.org/support/article/managing-plugins/#installing-plugins).
|
||||
* Make sure _Statify_ plugin is installed and active
|
||||
* Goto _Settings_ -> _Statify Blacklist_ to configure the plugin
|
||||
|
||||
### Requirements ###
|
||||
* PHP 5.5 or above
|
||||
* WordPress 4.4 or above
|
||||
* Statify plugin installed and activated (1.5.0 or above)
|
||||
* WordPress 4.7 or above
|
||||
* _Statify_ plugin installed and activated (1.5 or above)
|
||||
|
||||
## Frequently Asked Questions ##
|
||||
|
||||
### What is blocked by default? ###
|
||||
Nothing. By default all blacklists are empty and disabled. They can and have to be filled by the blog administrator.
|
||||
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, just "false" referers from 301 redirects or you own IP address used for testing only depends on you.
|
||||
visitors from search engines, just "false" referrers 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.
|
||||
No. It only prevents _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 negligible compared to the total loading procedure.
|
||||
Yes, but probably 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? ###
|
||||
Yes, it is. Just select if you want to filter using regular expressions case sensitive or insensitive.
|
||||
|
||||
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.
|
||||
Yes, it is. Just select regular expressions (case-sensitive or insensitive) as matching method instead of exact or keyword match.
|
||||
|
||||
### 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.
|
||||
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.
|
||||
|
||||
### Can whole IP subnet be blocked? ###
|
||||
Yes. The plugin features subnet blacklists using CIDR notation.
|
||||
For example _198.51.100.0/24_ blacklists all sources from _198.51.100.1_ to _198.51.100.254_.
|
||||
Same for IPv6 prefixes like _2001:db8:a0b:12f0::/64_.
|
||||
|
||||
|
||||
## Screenshots ##
|
||||
1. Statify Blacklist settings page
|
||||
|
||||
## Changelog ##
|
||||
|
||||
### 1.5.0 / 13.05.2020 ###
|
||||
* Minimum required WordPress version is 4.7
|
||||
* Removed `load_plugin_textdomain()` and `Domain Path` header
|
||||
* Added automatic compatibility check for WP and PHP version (#17)
|
||||
* Added keyword filter mode for referer blacklist (#15)
|
||||
* Layout adjustments on settings page
|
||||
* Regular expression filters are validated before saving (#13)
|
||||
|
||||
### 1.4.4 / 19.05.2018 ###
|
||||
* Fix live filter chain when regular expressions are active (#12)
|
||||
|
||||
@ -115,7 +131,7 @@ Because of this, an IP blacklist can only be applied while processing the reques
|
||||
|
||||
### 1.2.0 / 29.08.2016 ###
|
||||
* Switched from `in_array()` to faster `isset()` for referer checking
|
||||
* Optional cron execiton implemented
|
||||
* Optional cron execution implemented
|
||||
|
||||
### 1.1.2 / 17.08.2016 ###
|
||||
* Prepared for localization
|
||||
|
16
RoboFile.php
16
RoboFile.php
@ -8,7 +8,7 @@
|
||||
* @author Stefan Kalscheuer <stefan@stklcode.de>
|
||||
*
|
||||
* @package Statify_Blacklist
|
||||
* @version 1.4.4
|
||||
* @version 1.5.0
|
||||
*/
|
||||
|
||||
use Robo\Exception\TaskException;
|
||||
@ -134,13 +134,21 @@ class RoboFile extends Tasks {
|
||||
*/
|
||||
private function bundle() {
|
||||
$this->say( 'Bundling resources...' );
|
||||
$this->taskCopyDir( [
|
||||
$this->taskCopyDir(
|
||||
[
|
||||
'inc' => $this->target_dir . '/' . $this->final_name . '/inc',
|
||||
'views' => $this->target_dir . '/' . $this->final_name . '/views',
|
||||
] )->run();
|
||||
]
|
||||
)->run();
|
||||
$this->_copy( 'statify-blacklist.php', $this->target_dir . '/' . $this->final_name . '/statify-blacklist.php' );
|
||||
$this->_copy( 'README.md', $this->target_dir . '/' . $this->final_name . '/README.md' );
|
||||
$this->_copy( 'LICENSE.md', $this->target_dir . '/' . $this->final_name . '/LICENSE.md' );
|
||||
$this->_copy( 'README.md', $this->target_dir . '/' . $this->final_name . '/README.md' );
|
||||
|
||||
// Remove content before title (e.g. badges) from README file.
|
||||
$this->taskReplaceInFile( $this->target_dir . '/' . $this->final_name . '/README.md' )
|
||||
->regex( '/^[^\\#]*/' )
|
||||
->to( '' )
|
||||
->run();
|
||||
}
|
||||
|
||||
/**
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 93 KiB |
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "stklcode/statify-blacklist",
|
||||
"version": "1.4.4",
|
||||
"version": "1.5.0",
|
||||
"description": "A blacklist extension for the famous Statify WordPress plugin",
|
||||
"keywords": [
|
||||
"wordpress",
|
||||
@ -19,17 +19,17 @@
|
||||
"type": "wordpress-plugin",
|
||||
"require": {
|
||||
"php": ">=5.5",
|
||||
"composer/installers": "~1.0"
|
||||
"composer/installers": "~1.7"
|
||||
},
|
||||
"require-dev": {
|
||||
"dealerdirect/phpcodesniffer-composer-installer": "^0.4",
|
||||
"consolidation/robo": "^1.0.0",
|
||||
"dealerdirect/phpcodesniffer-composer-installer": "^0.5",
|
||||
"consolidation/robo": "^1.4",
|
||||
"phpunit/phpunit": "*",
|
||||
"phpunit/php-code-coverage": "*",
|
||||
"slowprog/composer-copy-file": "~0.2",
|
||||
"squizlabs/php_codesniffer": "^3.1",
|
||||
"wimg/php-compatibility": "^8.0",
|
||||
"wp-coding-standards/wpcs": "~0.14"
|
||||
"squizlabs/php_codesniffer": "^3.5",
|
||||
"phpcompatibility/php-compatibility": "^9.3",
|
||||
"wp-coding-standards/wpcs": "^2.1"
|
||||
},
|
||||
"scripts": {
|
||||
"build": [
|
||||
|
@ -9,8 +9,10 @@
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
// Quit.
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
// Quit if accessed directly.
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Statify Blacklist admin configuration.
|
||||
@ -18,37 +20,101 @@ defined( 'ABSPATH' ) || exit;
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class StatifyBlacklist_Admin extends StatifyBlacklist {
|
||||
|
||||
/**
|
||||
* Initialize admin-only components of the plugin.
|
||||
*
|
||||
* @since 1.5.0
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function init() {
|
||||
// Add actions.
|
||||
add_action( 'wpmu_new_blog', array( 'StatifyBlacklist_System', 'install_site' ) );
|
||||
add_action( 'delete_blog', array( 'StatifyBlacklist_System', 'uninstall_site' ) );
|
||||
add_filter( 'plugin_row_meta', array( 'StatifyBlacklist_Admin', 'plugin_meta_link' ), 10, 2 );
|
||||
|
||||
if ( self::$multisite ) {
|
||||
add_action( 'network_admin_menu', array( 'StatifyBlacklist_Admin', 'add_menu_page' ) );
|
||||
add_filter(
|
||||
'network_admin_plugin_action_links',
|
||||
array(
|
||||
'StatifyBlacklist_Admin',
|
||||
'plugin_actions_links',
|
||||
),
|
||||
10,
|
||||
2
|
||||
);
|
||||
} else {
|
||||
add_action( 'admin_menu', array( 'StatifyBlacklist_Admin', 'add_menu_page' ) );
|
||||
add_filter( 'plugin_action_links', array( 'StatifyBlacklist_Admin', 'plugin_actions_links' ), 10, 2 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update options.
|
||||
*
|
||||
* @since 1.1.1
|
||||
*
|
||||
* @param array $options Optional. 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.
|
||||
|
||||
// Sanitize referer list.
|
||||
$given_referer = $options['referer']['blacklist'];
|
||||
if ( 0 === $options['referer']['regexp'] ) {
|
||||
$sanitized_referer = self::sanitizeURLs( $given_referer );
|
||||
$invalid_referer = array();
|
||||
if ( self::MODE_NORMAL === $options['referer']['regexp'] ) {
|
||||
// Sanitize URLs and remove empty inputs.
|
||||
$sanitized_referer = self::sanitize_urls( $given_referer );
|
||||
} elseif ( self::MODE_REGEX === $options['referer']['regexp'] || self::MODE_REGEX_CI === $options['referer']['regexp'] ) {
|
||||
$sanitized_referer = $given_referer;
|
||||
// Check regular expressions.
|
||||
$invalid_referer = self::sanitize_regex( $given_referer );
|
||||
} else {
|
||||
$sanitized_referer = $given_referer;
|
||||
}
|
||||
|
||||
// Sanitize IPs and Subnets and remove empty inputs.
|
||||
// Sanitize target list.
|
||||
$given_target = $options['target']['blacklist'];
|
||||
$invalid_target = array();
|
||||
if ( self::MODE_REGEX === $options['target']['regexp'] || self::MODE_REGEX_CI === $options['target']['regexp'] ) {
|
||||
$sanitized_target = $given_target;
|
||||
// Check regular expressions.
|
||||
$invalid_target = self::sanitize_regex( $given_target );
|
||||
} else {
|
||||
$sanitized_target = $given_target;
|
||||
}
|
||||
|
||||
// Sanitize IPs and subnets and remove empty inputs.
|
||||
$given_ip = $options['ip']['blacklist'];
|
||||
$sanitized_ip = self::sanitizeIPs( $given_ip );
|
||||
$sanitized_ip = self::sanitize_ips( $given_ip );
|
||||
|
||||
// Abort on errors.
|
||||
if ( ! empty( array_diff( array_keys( $given_referer ), array_keys( $sanitized_referer ) ) ) ) {
|
||||
return array(
|
||||
'referer' => $sanitized_referer,
|
||||
);
|
||||
} elseif ( ! empty( array_diff( $given_ip, $sanitized_ip ) ) ) {
|
||||
return array(
|
||||
'ip' => array_diff( $given_ip, $sanitized_ip ),
|
||||
$errors = array(
|
||||
'referer' => array(
|
||||
'sanitized' => $sanitized_referer,
|
||||
'diff' => array_diff( $given_referer, $sanitized_referer ),
|
||||
'invalid' => $invalid_referer,
|
||||
),
|
||||
'target' => array(
|
||||
'sanitized' => $sanitized_target,
|
||||
'diff' => array_diff( $given_target, $sanitized_target ),
|
||||
'invalid' => $invalid_target,
|
||||
),
|
||||
'ip' => array(
|
||||
'sanitized' => $sanitized_ip,
|
||||
'diff' => array_diff( $given_ip, $sanitized_ip ),
|
||||
),
|
||||
);
|
||||
if ( ! empty( $errors['referer']['diff'] )
|
||||
|| ! empty( $errors['referer']['invalid'] )
|
||||
|| ! empty( $errors['target']['diff'] )
|
||||
|| ! empty( $errors['target']['invalid'] )
|
||||
|| ! empty( $errors['ip']['diff'] ) ) {
|
||||
return $errors;
|
||||
}
|
||||
|
||||
// Update database on success.
|
||||
@ -74,14 +140,24 @@ class StatifyBlacklist_Admin extends StatifyBlacklist {
|
||||
$title = __( 'Statify Blacklist', 'statify-blacklist' );
|
||||
if ( self::$multisite ) {
|
||||
add_submenu_page(
|
||||
'settings.php', $title, $title, 'manage_network_plugins', 'statify-blacklist-settings', array(
|
||||
'settings.php',
|
||||
$title,
|
||||
$title,
|
||||
'manage_network_plugins',
|
||||
'statify-blacklist-settings',
|
||||
array(
|
||||
'StatifyBlacklist_Admin',
|
||||
'settings_page',
|
||||
)
|
||||
);
|
||||
} else {
|
||||
add_submenu_page(
|
||||
'options-general.php', $title, $title, 'manage_options', 'statify-blacklist', array(
|
||||
'options-general.php',
|
||||
$title,
|
||||
$title,
|
||||
'manage_options',
|
||||
'statify-blacklist',
|
||||
array(
|
||||
'StatifyBlacklist_Admin',
|
||||
'settings_page',
|
||||
)
|
||||
@ -154,20 +230,20 @@ class StatifyBlacklist_Admin extends StatifyBlacklist {
|
||||
}
|
||||
|
||||
if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
|
||||
$clean_ref = ( 1 === self::$_options['referer']['cron'] );
|
||||
$clean_trg = ( 1 === self::$_options['target']['cron'] );
|
||||
$clean_ref = ( 1 === self::$options['referer']['cron'] );
|
||||
$clean_trg = ( 1 === self::$options['target']['cron'] );
|
||||
} else {
|
||||
$clean_ref = true;
|
||||
$clean_trg = true;
|
||||
}
|
||||
|
||||
if ( $clean_ref ) {
|
||||
if ( isset( self::$_options['referer']['regexp'] ) && self::$_options['referer']['regexp'] > 0 ) {
|
||||
if ( isset( self::$options['referer']['regexp'] ) && self::$options['referer']['regexp'] > 0 ) {
|
||||
// Merge given regular expressions into one.
|
||||
$referer_regexp = implode( '|', array_keys( self::$_options['referer']['blacklist'] ) );
|
||||
$referer_regexp = implode( '|', array_keys( self::$options['referer']['blacklist'] ) );
|
||||
} else {
|
||||
// Sanitize URLs.
|
||||
$referer = self::sanitizeURLs( self::$_options['referer']['blacklist'] );
|
||||
$referer = self::sanitize_urls( self::$options['referer']['blacklist'] );
|
||||
|
||||
// Build filter regexp.
|
||||
$referer_regexp = str_replace( '.', '\.', implode( '|', array_flip( $referer ) ) );
|
||||
@ -175,12 +251,12 @@ class StatifyBlacklist_Admin extends StatifyBlacklist {
|
||||
}
|
||||
|
||||
if ( $clean_trg ) {
|
||||
if ( isset( self::$_options['target']['regexp'] ) && self::$_options['target']['regexp'] > 0 ) {
|
||||
if ( isset( self::$options['target']['regexp'] ) && self::$options['target']['regexp'] > 0 ) {
|
||||
// Merge given regular expressions into one.
|
||||
$target_regexp = implode( '|', array_keys( self::$_options['target']['blacklist'] ) );
|
||||
$target_regexp = implode( '|', array_keys( self::$options['target']['blacklist'] ) );
|
||||
} else {
|
||||
// Build filter regexp.
|
||||
$target_regexp = str_replace( '.', '\.', implode( '|', array_flip( self::$_options['target']['blacklist'] ) ) );
|
||||
$target_regexp = str_replace( '.', '\.', implode( '|', array_flip( self::$options['target']['blacklist'] ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
@ -188,13 +264,14 @@ class StatifyBlacklist_Admin extends StatifyBlacklist {
|
||||
global $wpdb;
|
||||
|
||||
// Execute filter on database.
|
||||
// @codingStandardsIgnoreStart These statements prouce warnings, rework in future release (TODO).
|
||||
// phpcs:disable WordPress.DB.PreparedSQL.NotPrepared -- These statements produce warnings, rework in future release (TODO).
|
||||
if ( ! empty( $referer_regexp ) ) {
|
||||
$wpdb->query(
|
||||
$wpdb->prepare(
|
||||
"DELETE FROM `$wpdb->statify` WHERE "
|
||||
. ( ( 1 === self::$_options['referer']['regexp'] ) ? ' BINARY ' : '' )
|
||||
. 'referrer REGEXP %s', $referer_regexp
|
||||
. ( ( 1 === self::$options['referer']['regexp'] ) ? ' BINARY ' : '' )
|
||||
. 'referrer REGEXP %s',
|
||||
$referer_regexp
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -202,12 +279,13 @@ class StatifyBlacklist_Admin extends StatifyBlacklist {
|
||||
$wpdb->query(
|
||||
$wpdb->prepare(
|
||||
"DELETE FROM `$wpdb->statify` WHERE "
|
||||
. ( ( 1 === self::$_options['target']['regexp'] ) ? ' BINARY ' : '' )
|
||||
. 'target REGEXP %s', $target_regexp
|
||||
. ( ( 1 === self::$options['target']['regexp'] ) ? ' BINARY ' : '' )
|
||||
. 'target REGEXP %s',
|
||||
$target_regexp
|
||||
)
|
||||
);
|
||||
}
|
||||
// @codingStandardsIgnoreEnd
|
||||
// phpcs:enable WordPress.DB.PreparedSQL.NotPrepared
|
||||
|
||||
// Optimize DB.
|
||||
$wpdb->query( "OPTIMIZE TABLE `$wpdb->statify`" );
|
||||
@ -227,7 +305,7 @@ class StatifyBlacklist_Admin extends StatifyBlacklist {
|
||||
*
|
||||
* @return array sanitized array.
|
||||
*/
|
||||
private static function sanitizeURLs( $urls ) {
|
||||
private static function sanitize_urls( $urls ) {
|
||||
return array_flip(
|
||||
array_filter(
|
||||
array_map(
|
||||
@ -249,16 +327,40 @@ class StatifyBlacklist_Admin extends StatifyBlacklist {
|
||||
*
|
||||
* @return array sanitized array.
|
||||
*/
|
||||
private static function sanitizeIPs( $ips ) {
|
||||
private static function sanitize_ips( $ips ) {
|
||||
return array_filter(
|
||||
$ips, function ( $ip ) {
|
||||
$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
|
||||
'/^((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
|
||||
'/^(([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
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate regular expressions, i.e. remove duplicates and empty values and validate others.
|
||||
*
|
||||
* @since 1.5.0 #13
|
||||
*
|
||||
* @param array $expressions Given pre-sanitized array of regular expressions.
|
||||
*
|
||||
* @return array Array of invalid expressions.
|
||||
*/
|
||||
private static function sanitize_regex( $expressions ) {
|
||||
return array_filter(
|
||||
array_flip( $expressions ),
|
||||
function ( $re ) {
|
||||
// Check of preg_match() fails (warnings suppressed).
|
||||
|
||||
// phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
|
||||
return false === @preg_match( StatifyBlacklist::regex( $re, false ), null );
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
/**
|
||||
* Statify Blacklist: StatifyBlacklist_Syste, class
|
||||
* Statify Blacklist: StatifyBlacklist_System class
|
||||
*
|
||||
* This file contains the derived class for the plugin's system operations.
|
||||
*
|
||||
@ -9,8 +9,10 @@
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
// Quit.
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
// Quit if accessed directly.
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Statify Blacklist system configuration.
|
||||
@ -25,15 +27,14 @@ class StatifyBlacklist_System extends StatifyBlacklist {
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param bool $network_wide Whether the plugin was activated network-wide or not.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function install( $network_wide = false ) {
|
||||
// Create tables for each site in a network.
|
||||
if ( $network_wide && is_multisite() ) {
|
||||
if ( function_exists( 'get_sites' ) ) {
|
||||
$sites = get_sites();
|
||||
} elseif ( function_exists( 'wp_get_sites' ) ) {
|
||||
// @codingStandardsIgnoreLine Legacy support for WP < 4.6.
|
||||
$sites = wp_get_sites();
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
@ -62,6 +63,8 @@ class StatifyBlacklist_System extends StatifyBlacklist {
|
||||
* @since 1.4.3
|
||||
*
|
||||
* @param integer $site_id Site ID.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function install_site( $site_id ) {
|
||||
switch_to_blog( (int) $site_id );
|
||||
@ -77,6 +80,8 @@ class StatifyBlacklist_System extends StatifyBlacklist {
|
||||
* Plugin uninstall handler.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function uninstall() {
|
||||
if ( is_multisite() ) {
|
||||
@ -85,7 +90,7 @@ class StatifyBlacklist_System extends StatifyBlacklist {
|
||||
if ( function_exists( 'get_sites' ) ) {
|
||||
$sites = get_sites();
|
||||
} elseif ( function_exists( 'wp_get_sites' ) ) {
|
||||
// @codingStandardsIgnoreLine Legacy support for WP < 4.6.
|
||||
// phpcs:ignore WordPress.WP.DeprecatedFunctions.wp_get_sitesFound -- Legacy support for WP < 4.6.
|
||||
$sites = wp_get_sites();
|
||||
} else {
|
||||
return;
|
||||
@ -112,6 +117,8 @@ class StatifyBlacklist_System extends StatifyBlacklist {
|
||||
* @since 1.4.3
|
||||
*
|
||||
* @param integer $site_id Site ID.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function uninstall_site( $site_id ) {
|
||||
$old = get_current_blog_id();
|
||||
@ -124,14 +131,16 @@ class StatifyBlacklist_System extends StatifyBlacklist {
|
||||
* Upgrade plugin options.
|
||||
*
|
||||
* @since 1.2.0
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function upgrade() {
|
||||
self::update_options();
|
||||
// Check if config array is not associative (pre 1.2.0).
|
||||
if ( array_keys( self::$_options['referer'] ) === range( 0, count( self::$_options['referer'] ) - 1 ) ) {
|
||||
if ( array_keys( self::$options['referer'] ) === range( 0, count( self::$options['referer'] ) - 1 ) ) {
|
||||
// Flip referer array to make domains keys.
|
||||
$options = self::$_options;
|
||||
$options['referer'] = array_flip( self::$_options['referer'] );
|
||||
$options = self::$options;
|
||||
$options['referer'] = array_flip( self::$options['referer'] );
|
||||
if ( self::$multisite ) {
|
||||
update_site_option( 'statify-blacklist', $options );
|
||||
} else {
|
||||
@ -140,14 +149,14 @@ class StatifyBlacklist_System extends StatifyBlacklist {
|
||||
}
|
||||
|
||||
// Version not set (pre 1.3.0) or older than 1.4.
|
||||
if ( ! isset( self::$_options['version'] ) || self::$_options['version'] < 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'],
|
||||
'active' => self::$options['active_referer'],
|
||||
'cron' => self::$options['cron_referer'],
|
||||
'regexp' => self::$options['referer_regexp'],
|
||||
'blacklist' => self::$options['referer'],
|
||||
),
|
||||
'target' => array(
|
||||
'active' => 0,
|
||||
@ -170,9 +179,9 @@ class StatifyBlacklist_System extends StatifyBlacklist {
|
||||
}
|
||||
|
||||
// Version older than current major release.
|
||||
if ( self::VERSION_MAIN > self::$_options['version'] ) {
|
||||
if ( self::VERSION_MAIN > self::$options['version'] ) {
|
||||
// Merge default options with current config, assuming only additive changes.
|
||||
$options = array_merge_recursive( self::default_options(), self::$_options );
|
||||
$options = array_merge_recursive( self::default_options(), self::$options );
|
||||
$options['version'] = self::VERSION_MAIN;
|
||||
if ( self::$multisite ) {
|
||||
update_site_option( 'statify-blacklist', $options );
|
||||
|
@ -8,8 +8,10 @@
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
// Quit.
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
// Quit if accessed directly.
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Statify Blacklist.
|
||||
@ -26,13 +28,42 @@ class StatifyBlacklist {
|
||||
*/
|
||||
const VERSION_MAIN = 1.4;
|
||||
|
||||
/**
|
||||
* Operation mode "normal".
|
||||
*
|
||||
* @var integer MODE_NORMAL
|
||||
*/
|
||||
const MODE_NORMAL = 0;
|
||||
|
||||
/**
|
||||
* Operation mode "regular expression".
|
||||
*
|
||||
* @var integer MODE_REGEX
|
||||
*/
|
||||
const MODE_REGEX = 1;
|
||||
|
||||
/**
|
||||
* Operation mode "regular expression case insensitive".
|
||||
*
|
||||
* @var integer MODE_REGEX_CI
|
||||
*/
|
||||
const MODE_REGEX_CI = 2;
|
||||
|
||||
/**
|
||||
* Operation mode "keyword".
|
||||
*
|
||||
* @since 1.5.0
|
||||
* @var integer MODE_KEYWORD
|
||||
*/
|
||||
const MODE_KEYWORD = 3;
|
||||
|
||||
/**
|
||||
* Plugin options.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @var array $_options
|
||||
* @var array $options
|
||||
*/
|
||||
public static $_options;
|
||||
public static $options;
|
||||
|
||||
/**
|
||||
* Multisite Status.
|
||||
@ -42,30 +73,12 @@ class StatifyBlacklist {
|
||||
*/
|
||||
public static $multisite;
|
||||
|
||||
/**
|
||||
* Class self initialize.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @deprecated 1.4.2 Replaced by init().
|
||||
*/
|
||||
public static function instance() {
|
||||
self::init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Class constructor.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @deprecated 1.4.2 Replaced by init().
|
||||
*/
|
||||
public function __construct() {
|
||||
self::init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Plugin initialization.
|
||||
*
|
||||
* @since 1.4.2
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function init() {
|
||||
// Skip on autosave or AJAX.
|
||||
@ -80,43 +93,21 @@ class StatifyBlacklist {
|
||||
self::update_options();
|
||||
|
||||
// Add Filter to statify hook if enabled.
|
||||
if ( 0 !== self::$_options['referer']['active'] || 0 !== self::$_options['target']['active'] || 0 !== self::$_options['ip']['active'] ) {
|
||||
if ( 0 !== self::$options['referer']['active'] || 0 !== self::$options['target']['active'] || 0 !== self::$options['ip']['active'] ) {
|
||||
add_filter( 'statify__skip_tracking', array( 'StatifyBlacklist', 'apply_blacklist_filter' ) );
|
||||
}
|
||||
|
||||
// Admin only filters.
|
||||
if ( is_admin() ) {
|
||||
// Load Textdomain (only needed for backend.
|
||||
load_plugin_textdomain( 'statifyblacklist', false, STATIFYBLACKLIST_DIR . '/lang/' );
|
||||
|
||||
// Add actions.
|
||||
add_action( 'wpmu_new_blog', array( 'StatifyBlacklist_System', 'install_site' ) );
|
||||
add_action( 'delete_blog', array( 'StatifyBlacklist_System', 'uninstall_site' ) );
|
||||
add_filter( 'plugin_row_meta', array( 'StatifyBlacklist_Admin', 'plugin_meta_link' ), 10, 2 );
|
||||
|
||||
if ( self::$multisite ) {
|
||||
add_action( 'network_admin_menu', array( 'StatifyBlacklist_Admin', 'add_menu_page' ) );
|
||||
add_filter(
|
||||
'network_admin_plugin_action_links', array(
|
||||
'StatifyBlacklist_Admin',
|
||||
'plugin_actions_links',
|
||||
),
|
||||
10,
|
||||
2
|
||||
);
|
||||
} else {
|
||||
add_action( 'admin_menu', array( 'StatifyBlacklist_Admin', 'add_menu_page' ) );
|
||||
add_filter( 'plugin_action_links', array( 'StatifyBlacklist_Admin', 'plugin_actions_links' ), 10, 2 );
|
||||
}
|
||||
StatifyBlacklist_Admin::init();
|
||||
}
|
||||
|
||||
// CronJob to clean up database.
|
||||
if ( defined( 'DOING_CRON' ) && DOING_CRON ) {
|
||||
if ( 1 === self::$_options['referer']['cron'] || 1 === self::$_options['target']['cron'] ) {
|
||||
if ( defined( 'DOING_CRON' ) && DOING_CRON &&
|
||||
( 1 === self::$options['referer']['cron'] || 1 === self::$options['target']['cron'] ) ) {
|
||||
add_action( 'statify_cleanup', array( 'StatifyBlacklist_Admin', 'cleanup_database' ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update options.
|
||||
@ -125,6 +116,8 @@ class StatifyBlacklist {
|
||||
* @since 1.2.1 update_options($options = null) Parameter with default value introduced.
|
||||
*
|
||||
* @param array $options Optional. New options to save.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function update_options( $options = null ) {
|
||||
if ( self::$multisite ) {
|
||||
@ -132,7 +125,7 @@ class StatifyBlacklist {
|
||||
} else {
|
||||
$o = get_option( 'statify-blacklist' );
|
||||
}
|
||||
self::$_options = wp_parse_args( $o, self::default_options() );
|
||||
self::$options = wp_parse_args( $o, self::default_options() );
|
||||
}
|
||||
|
||||
/**
|
||||
@ -173,31 +166,53 @@ class StatifyBlacklist {
|
||||
*/
|
||||
public static function apply_blacklist_filter() {
|
||||
// Referer blacklist.
|
||||
if ( isset( self::$_options['referer']['active'] ) && 0 !== self::$_options['referer']['active'] ) {
|
||||
// Regular Expression filtering since 1.3.0.
|
||||
if ( isset( self::$_options['referer']['regexp'] ) && self::$_options['referer']['regexp'] > 0 ) {
|
||||
if ( isset( self::$options['referer']['active'] ) && 0 !== self::$options['referer']['active'] ) {
|
||||
// Determine filter mode.
|
||||
$mode = isset( self::$options['referer']['regexp'] ) ? intval( self::$options['referer']['regexp'] ) : 0;
|
||||
|
||||
// Get full referer string.
|
||||
$referer = wp_get_raw_referer();
|
||||
if ( ! $referer ) {
|
||||
$referer = '';
|
||||
}
|
||||
|
||||
switch ( $mode ) {
|
||||
|
||||
// Regular Expression filtering since 1.3.0.
|
||||
case self::MODE_REGEX:
|
||||
case self::MODE_REGEX_CI:
|
||||
// Merge given regular expressions into one.
|
||||
$regexp = '/' . implode( '|', array_keys( self::$_options['referer']['blacklist'] ) ) . '/';
|
||||
if ( 2 === self::$_options['referer']['regexp'] ) {
|
||||
$regexp .= 'i';
|
||||
}
|
||||
$regexp = self::regex(
|
||||
array_keys( self::$options['referer']['blacklist'] ),
|
||||
self::MODE_REGEX_CI === self::$options['referer']['regexp']
|
||||
);
|
||||
|
||||
// Check blacklist (no return to continue filtering #12).
|
||||
if ( 1 === preg_match( $regexp, $referer ) ) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
|
||||
// Keyword filter since 1.5.0 (#15).
|
||||
case self::MODE_KEYWORD:
|
||||
// Get blacklist.
|
||||
$blacklist = self::$options['referer']['blacklist'];
|
||||
|
||||
foreach ( array_keys( $blacklist ) as $keyword ) {
|
||||
if ( false !== strpos( strtolower( $referer ), strtolower( $keyword ) ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// Standard domain filter.
|
||||
default:
|
||||
// Extract relevant domain parts.
|
||||
$referer = wp_parse_url( wp_get_raw_referer() );
|
||||
$referer = wp_parse_url( $referer );
|
||||
$referer = strtolower( ( isset( $referer['host'] ) ? $referer['host'] : '' ) );
|
||||
|
||||
// Get blacklist.
|
||||
$blacklist = self::$_options['referer']['blacklist'];
|
||||
$blacklist = self::$options['referer']['blacklist'];
|
||||
|
||||
// Check blacklist.
|
||||
if ( isset( $blacklist[ $referer ] ) ) {
|
||||
@ -207,18 +222,16 @@ class StatifyBlacklist {
|
||||
}
|
||||
|
||||
// Target blacklist (since 1.4.0).
|
||||
if ( isset( self::$_options['target']['active'] ) && 0 !== self::$_options['target']['active'] ) {
|
||||
if ( isset( self::$options['target']['active'] ) && 0 !== self::$options['target']['active'] ) {
|
||||
// Regular Expression filtering since 1.3.0.
|
||||
if ( isset( self::$_options['target']['regexp'] ) && 0 < self::$_options['target']['regexp'] ) {
|
||||
if ( isset( self::$options['target']['regexp'] ) && 0 < self::$options['target']['regexp'] ) {
|
||||
// Get full referer string.
|
||||
// @codingStandardsIgnoreStart The globals are checked.
|
||||
$target = ( isset( $_SERVER['REQUEST_URI'] ) ? $_SERVER['REQUEST_URI'] : '/' );
|
||||
// @codingStandardsIgnoreEnd
|
||||
$target = ( isset( $_SERVER['REQUEST_URI'] ) ? filter_var( wp_unslash( $_SERVER['REQUEST_URI'] ), FILTER_SANITIZE_URL ) : '/' );
|
||||
// Merge given regular expressions into one.
|
||||
$regexp = '/' . implode( '|', array_keys( self::$_options['target']['blacklist'] ) ) . '/';
|
||||
if ( 2 === self::$_options['target']['regexp'] ) {
|
||||
$regexp .= 'i';
|
||||
}
|
||||
$regexp = self::regex(
|
||||
array_keys( self::$options['target']['blacklist'] ),
|
||||
self::MODE_REGEX_CI === self::$options['target']['regexp']
|
||||
);
|
||||
|
||||
// Check blacklist (no return to continue filtering #12).
|
||||
if ( 1 === preg_match( $regexp, $target ) ) {
|
||||
@ -226,11 +239,9 @@ class StatifyBlacklist {
|
||||
}
|
||||
} else {
|
||||
// Extract target page.
|
||||
// @codingStandardsIgnoreStart The globals are checked.
|
||||
$target = ( isset( $_SERVER['REQUEST_URI'] ) ? $_SERVER['REQUEST_URI'] : '/' );
|
||||
// @codingStandardsIgnoreEnd
|
||||
$target = ( isset( $_SERVER['REQUEST_URI'] ) ? filter_var( wp_unslash( $_SERVER['REQUEST_URI'] ), FILTER_SANITIZE_URL ) : '/' );
|
||||
// Get blacklist.
|
||||
$blacklist = self::$_options['target']['blacklist'];
|
||||
$blacklist = self::$options['target']['blacklist'];
|
||||
// Check blacklist.
|
||||
if ( isset( $blacklist[ $target ] ) ) {
|
||||
return true;
|
||||
@ -239,10 +250,10 @@ class StatifyBlacklist {
|
||||
}
|
||||
|
||||
// IP blacklist (since 1.4.0).
|
||||
if ( isset( self::$_options['ip']['active'] ) && 0 !== self::$_options['ip']['active'] ) {
|
||||
if ( isset( self::$options['ip']['active'] ) && 0 !== self::$options['ip']['active'] ) {
|
||||
$ip = self::get_ip();
|
||||
if ( false !== ( $ip ) ) {
|
||||
foreach ( self::$_options['ip']['blacklist'] as $net ) {
|
||||
foreach ( self::$options['ip']['blacklist'] as $net ) {
|
||||
if ( self::cidr_match( $ip, $net ) ) {
|
||||
return true;
|
||||
}
|
||||
@ -254,6 +265,37 @@ class StatifyBlacklist {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Preprocess regular expression provided by the user, i.e. add delimiters and optional ci flag.
|
||||
*
|
||||
* @param string|array $expression Original expression string or array of expressions.
|
||||
* @param string|array $case_insensitive Make expression match case-insensitive.
|
||||
*
|
||||
* @return string Preprocessed expression ready for preg_match().
|
||||
*/
|
||||
protected static function regex( $expression, $case_insensitive ) {
|
||||
$res = '/';
|
||||
if ( is_string( $expression ) ) {
|
||||
$res .= str_replace( '/', '\/', $expression );
|
||||
} elseif ( is_array( $expression ) ) {
|
||||
$res .= implode(
|
||||
'|',
|
||||
array_map(
|
||||
function ( $e ) {
|
||||
return str_replace( '/', '\/', $e );
|
||||
},
|
||||
$expression
|
||||
)
|
||||
);
|
||||
}
|
||||
$res .= '/';
|
||||
if ( $case_insensitive ) {
|
||||
$res .= 'i';
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to determine the client's IP address.
|
||||
*
|
||||
@ -277,15 +319,14 @@ class StatifyBlacklist {
|
||||
'REMOTE_ADDR',
|
||||
) as $k
|
||||
) {
|
||||
// @codingStandardsIgnoreStart The globals are checked.
|
||||
if ( isset( $_SERVER[ $k ] ) ) {
|
||||
// phpcs:ignore
|
||||
foreach ( explode( ',', $_SERVER[ $k ] ) as $ip ) {
|
||||
if ( false !== filter_var( $ip, FILTER_VALIDATE_IP ) ) {
|
||||
return $ip;
|
||||
}
|
||||
}
|
||||
}
|
||||
// @codingStandardsIgnoreEnd
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -361,6 +402,6 @@ class StatifyBlacklist {
|
||||
}
|
||||
|
||||
return ( 0 === substr_compare( sprintf( '%032b', ip2long( $ip ) ), sprintf( '%032b', ip2long( $base ) ), 0, $mask ) );
|
||||
} // End if().
|
||||
}
|
||||
}
|
||||
}
|
||||
|
14
package.json
14
package.json
@ -1,17 +1,7 @@
|
||||
{
|
||||
"name": "statify-blacklist",
|
||||
"version": "1.4.4",
|
||||
"version": "1.5.0",
|
||||
"description": "A blacklist extension for the famous Statify WordPress plugin",
|
||||
"author": "Stefan Kalscheuer",
|
||||
"license": "GPL-2.0+",
|
||||
"devDependencies": {
|
||||
"gulp": "^3.9.1",
|
||||
"gulp-clean": "^0.3.2",
|
||||
"gulp-copy": "^1.0.1",
|
||||
"gulp-zip": "^4.0.0",
|
||||
"gulp-composer": "^0.4.4",
|
||||
"gulp-phpunit": "^0.24.1",
|
||||
"gulp-phpcs": "^2.1.0",
|
||||
"child_process": "^1.0.2"
|
||||
}
|
||||
"license": "GPL-2.0+"
|
||||
}
|
||||
|
15
phpcs.xml
15
phpcs.xml
@ -2,23 +2,20 @@
|
||||
<ruleset name="StatifyBlacklist">
|
||||
<description>Derived from WordPress Coding Standard</description>
|
||||
|
||||
<arg value="psvn"/>
|
||||
<arg value="psv"/>
|
||||
<arg name="colors"/>
|
||||
|
||||
<!-- Files to sniff -->
|
||||
<file>inc</file>
|
||||
<file>statify-blacklist.php</file>
|
||||
<file>inc</file>
|
||||
<file>views</file>
|
||||
|
||||
<!-- Compliance with WordPress Coding Standard -->
|
||||
<config name="minimum_supported_wp_version" value="4.4"/>
|
||||
<config name="minimum_supported_wp_version" value="4.7"/>
|
||||
<rule ref="WordPress">
|
||||
<!-- The plugin uses switch_to_blog for multisite handling. -->
|
||||
<exclude name="WordPress.VIP.RestrictedFunctions.switch_to_blog"/>
|
||||
<exclude name="WordPress.VIP.RestrictedFunctions.switch_to_blog_switch_to_blog"/>
|
||||
|
||||
<!-- Direct queries used to clean up statify table. -->
|
||||
<exclude name="WordPress.VIP.DirectDatabaseQuery.DirectQuery"/>
|
||||
<exclude name="WordPress.VIP.DirectDatabaseQuery.NoCaching"/>
|
||||
<exclude name="WordPress.DB.DirectDatabaseQuery.DirectQuery"/>
|
||||
<exclude name="WordPress.DB.DirectDatabaseQuery.NoCaching"/>
|
||||
</rule>
|
||||
|
||||
<!-- PHP compatibility level -->
|
||||
|
@ -12,6 +12,6 @@
|
||||
</filter>
|
||||
<logging>
|
||||
<log type="coverage-clover" target="tests-clover.xml"/>
|
||||
<log type="junit" target="tests-junit.xml" logIncompleteSkipped="false"/>
|
||||
<log type="junit" target="tests-junit.xml"/>
|
||||
</logging>
|
||||
</phpunit>
|
||||
|
@ -10,11 +10,10 @@
|
||||
* Plugin Name: Statify Blacklist
|
||||
* Plugin URI: https://wordpress.org/plugins/statify-blacklist/
|
||||
* Description: Extension for the Statify plugin to add a customizable blacklists.
|
||||
* Version: 1.4.4
|
||||
* Version: 1.5.0
|
||||
* Author: Stefan Kalscheuer (@stklcode)
|
||||
* Author URI: https://www.stklcode.de
|
||||
* Text Domain: statify-blacklist
|
||||
* Domain Path: /lang
|
||||
* License: GPLv2 or later
|
||||
*
|
||||
* Statify Blacklist is free software: you can redistribute it and/or modify
|
||||
@ -28,29 +27,37 @@
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Statify Blacklist. If not, see http://www.gnu.org/licenses/gpl-2.0.html.
|
||||
* along with Statify Blacklist. If not, see https://www.gnu.org/licenses/gpl-2.0.html.
|
||||
*/
|
||||
|
||||
// Quit.
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
// Quit if accessed directly.
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// Constants.
|
||||
define( 'STATIFYBLACKLIST_FILE', __FILE__ );
|
||||
define( 'STATIFYBLACKLIST_DIR', dirname( __FILE__ ) );
|
||||
define( 'STATIFYBLACKLIST_BASE', plugin_basename( __FILE__ ) );
|
||||
|
||||
// System Hooks.
|
||||
add_action( 'plugins_loaded', array( 'StatifyBlacklist', 'init' ) );
|
||||
// Check for compatibility.
|
||||
if ( statify_blacklist_compatibility_check() ) {
|
||||
// System Hooks.
|
||||
add_action( 'plugins_loaded', array( 'StatifyBlacklist', 'init' ) );
|
||||
|
||||
register_activation_hook( STATIFYBLACKLIST_FILE, array( 'StatifyBlacklist_System', 'install' ) );
|
||||
register_activation_hook( STATIFYBLACKLIST_FILE, array( 'StatifyBlacklist_System', 'install' ) );
|
||||
|
||||
register_uninstall_hook( STATIFYBLACKLIST_FILE, array( 'StatifyBlacklist_System', 'uninstall' ) );
|
||||
register_uninstall_hook( STATIFYBLACKLIST_FILE, array( 'StatifyBlacklist_System', 'uninstall' ) );
|
||||
|
||||
// Upgrade hook.
|
||||
register_activation_hook( STATIFYBLACKLIST_FILE, array( 'StatifyBlacklist_System', 'upgrade' ) );
|
||||
// Upgrade hook.
|
||||
register_activation_hook( STATIFYBLACKLIST_FILE, array( 'StatifyBlacklist_System', 'upgrade' ) );
|
||||
|
||||
// Autoload.
|
||||
spl_autoload_register( 'statify_blacklist_autoload' );
|
||||
// Autoload.
|
||||
spl_autoload_register( 'statify_blacklist_autoload' );
|
||||
} else {
|
||||
// Disable plugin, if active.
|
||||
add_action( 'admin_init', 'statify_blacklist_disable' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Autoloader for StatifyBlacklist classes.
|
||||
@ -74,3 +81,59 @@ function statify_blacklist_autoload( $class ) {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for compatibility with PHP and WP version.
|
||||
*
|
||||
* @since 1.5.0
|
||||
*
|
||||
* @return boolean Whether minimum WP and PHP versions are met.
|
||||
*/
|
||||
function statify_blacklist_compatibility_check() {
|
||||
return version_compare( $GLOBALS['wp_version'], '4.7', '>=' ) &&
|
||||
version_compare( phpversion(), '5.5', '>=' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable plugin if active and incompatible.
|
||||
*
|
||||
* @since 1.5.0
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function statify_blacklist_disable() {
|
||||
if ( is_plugin_active( STATIFYBLACKLIST_BASE ) ) {
|
||||
deactivate_plugins( STATIFYBLACKLIST_BASE );
|
||||
add_action( 'admin_notices', 'statify_blacklist_disabled_notice' );
|
||||
// phpcs:disable WordPress.Security.NonceVerification.Recommended
|
||||
if ( isset( $_GET['activate'] ) ) {
|
||||
unset( $_GET['activate'] );
|
||||
}
|
||||
// phpcs:enable
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Admin notification for unmet requirements.
|
||||
*
|
||||
* @since 1.5.0
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function statify_blacklist_disabled_notice() {
|
||||
echo '<div class="notice notice-error is-dismissible"><p><strong>';
|
||||
printf(
|
||||
/* translators: minimum version numbers for WordPress and PHP inserted at placeholders */
|
||||
esc_html__( 'Statify Blacklist requires at least WordPress %1$s and PHP %2$s.', 'statify-blacklist' ),
|
||||
'4.7',
|
||||
'5.5'
|
||||
);
|
||||
echo '<br>';
|
||||
printf(
|
||||
/* translators: current version numbers for WordPress and PHP inserted at placeholders */
|
||||
esc_html__( 'Your site is running WordPress %1$s on PHP %2$s, thus the plugin has been disabled.', 'statify-blacklist' ),
|
||||
esc_html( $GLOBALS['wp_version'] ),
|
||||
esc_html( phpversion() )
|
||||
);
|
||||
echo '</strong></p></div>';
|
||||
}
|
||||
|
@ -20,17 +20,17 @@ const ABSPATH = false;
|
||||
/**
|
||||
* The StatifyBlacklist base class.
|
||||
*/
|
||||
require_once( 'inc/class-statifyblacklist.php' );
|
||||
require_once __DIR__ . '/../inc/class-statifyblacklist.php';
|
||||
|
||||
/**
|
||||
* The StatifyBlacklist system class.
|
||||
*/
|
||||
require_once( 'inc/class-statifyblacklist-system.php' );
|
||||
require_once __DIR__ . '/../inc/class-statifyblacklist-system.php';
|
||||
|
||||
/**
|
||||
* The StatifyBlacklist admin class.
|
||||
*/
|
||||
require_once( 'inc/class-statifyblacklist-admin.php' );
|
||||
require_once __DIR__ . '/../inc/class-statifyblacklist-admin.php';
|
||||
|
||||
/**
|
||||
* Class StatifyBlacklistTest.
|
||||
@ -43,10 +43,12 @@ class StatifyBlacklist_Test extends PHPUnit\Framework\TestCase {
|
||||
|
||||
/**
|
||||
* Test simple referer filter.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function test_referer_filter() {
|
||||
// Prepare Options: 2 blacklisted domains, disabled.
|
||||
StatifyBlacklist::$_options = array(
|
||||
StatifyBlacklist::$options = array(
|
||||
'referer' => array(
|
||||
'active' => 0,
|
||||
'cron' => 0,
|
||||
@ -86,7 +88,7 @@ class StatifyBlacklist_Test extends PHPUnit\Framework\TestCase {
|
||||
$this->assertNull( StatifyBlacklist::apply_blacklist_filter() );
|
||||
|
||||
// Activate filter and run tests again.
|
||||
StatifyBlacklist::$_options['referer']['active'] = 1;
|
||||
StatifyBlacklist::$options['referer']['active'] = 1;
|
||||
|
||||
unset( $_SERVER['HTTP_REFERER'] );
|
||||
$this->assertNull( StatifyBlacklist::apply_blacklist_filter() );
|
||||
@ -103,10 +105,12 @@ class StatifyBlacklist_Test extends PHPUnit\Framework\TestCase {
|
||||
|
||||
/**
|
||||
* Test referer filter using regular expressions.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testRefererRegexFilter() {
|
||||
public function test_referer_regex_filter() {
|
||||
// Prepare Options: 2 regular expressions.
|
||||
StatifyBlacklist::$_options = array(
|
||||
StatifyBlacklist::$options = array(
|
||||
'referer' => array(
|
||||
'active' => 1,
|
||||
'cron' => 0,
|
||||
@ -147,19 +151,74 @@ class StatifyBlacklist_Test extends PHPUnit\Framework\TestCase {
|
||||
// Matching both.
|
||||
$_SERVER['HTTP_REFERER'] = 'http://example.net/test/me';
|
||||
$this->assertTrue( StatifyBlacklist::apply_blacklist_filter() );
|
||||
// Mathinc with wrong case.
|
||||
// Matching 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;
|
||||
StatifyBlacklist::$options['referer']['regexp'] = 2;
|
||||
$this->assertTrue( StatifyBlacklist::apply_blacklist_filter() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test referer filter using keywords.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function test_referer_keyword_filter() {
|
||||
// Prepare Options: 2 regular expressions.
|
||||
StatifyBlacklist::$options = array(
|
||||
'referer' => array(
|
||||
'active' => 1,
|
||||
'cron' => 0,
|
||||
'regexp' => StatifyBlacklist::MODE_KEYWORD,
|
||||
'blacklist' => array(
|
||||
'example' => 0,
|
||||
'test' => 1,
|
||||
),
|
||||
),
|
||||
'target' => array(
|
||||
'active' => 0,
|
||||
'cron' => 0,
|
||||
'regexp' => StatifyBlacklist::MODE_NORMAL,
|
||||
'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() );
|
||||
// Matching with wrong case.
|
||||
$_SERVER['HTTP_REFERER'] = 'http://eXaMpLe.NeT/tEsT/mE';
|
||||
$this->assertTrue( StatifyBlacklist::apply_blacklist_filter() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test the upgrade methodology for configuration options.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testUpgrade() {
|
||||
public function test_upgrade() {
|
||||
// Create configuration of version 1.3.
|
||||
$options13 = array(
|
||||
'active_referer' => 1,
|
||||
@ -179,138 +238,141 @@ class StatifyBlacklist_Test extends PHPUnit\Framework\TestCase {
|
||||
StatifyBlacklist_System::upgrade();
|
||||
|
||||
// Retrieve updated options.
|
||||
$optionsUpdated = get_option( 'statify-blacklist' );
|
||||
$options_updated = get_option( 'statify-blacklist' );
|
||||
|
||||
// Verify size against default options (no junk left).
|
||||
$this->assertEquals( 4, count( $optionsUpdated ) );
|
||||
$this->assertEquals( 4, count( $optionsUpdated['referer'] ) );
|
||||
$this->assertEquals( 4, count( $optionsUpdated['target'] ) );
|
||||
$this->assertEquals( 2, count( $optionsUpdated['ip'] ) );
|
||||
$this->assertEquals( 4, count( $options_updated ) );
|
||||
$this->assertEquals( 4, count( $options_updated['referer'] ) );
|
||||
$this->assertEquals( 4, count( $options_updated['target'] ) );
|
||||
$this->assertEquals( 2, count( $options_updated['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'] );
|
||||
$this->assertEquals( $options13['active_referer'], $options_updated['referer']['active'] );
|
||||
$this->assertEquals( $options13['cron_referer'], $options_updated['referer']['cron'] );
|
||||
$this->assertEquals( $options13['referer'], $options_updated['referer']['blacklist'] );
|
||||
$this->assertEquals( $options13['referer_regexp'], $options_updated['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'] );
|
||||
$this->assertEquals( 0, $options_updated['target']['active'] );
|
||||
$this->assertEquals( 0, $options_updated['target']['cron'] );
|
||||
$this->assertEquals( 0, $options_updated['target']['regexp'] );
|
||||
$this->assertEquals( array(), $options_updated['target']['blacklist'] );
|
||||
$this->assertEquals( 0, $options_updated['ip']['active'] );
|
||||
$this->assertEquals( array(), $options_updated['ip']['blacklist'] );
|
||||
|
||||
// Verify that version number has changed to current release.
|
||||
$this->assertEquals( StatifyBlacklist::VERSION_MAIN, $optionsUpdated['version'] );
|
||||
$this->assertEquals( StatifyBlacklist::VERSION_MAIN, $options_updated['version'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test CIDR address matching for IP filter (#7)
|
||||
* Test CIDR address matching for IP filter (#7).
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testCidrMatch() {
|
||||
public function test_cidr_match() {
|
||||
// IPv4 tests.
|
||||
$this->assertTrue( invokeStatic( StatifyBlacklist::class, 'cidr_match', array( '127.0.0.1', '127.0.0.1' ) ) );
|
||||
$this->assertTrue( invokeStatic( StatifyBlacklist::class, 'cidr_match', array( '127.0.0.1', '127.0.0.1/32' ) ) );
|
||||
$this->assertTrue( invoke_static( StatifyBlacklist::class, 'cidr_match', array( '127.0.0.1', '127.0.0.1' ) ) );
|
||||
$this->assertTrue( invoke_static( StatifyBlacklist::class, 'cidr_match', array( '127.0.0.1', '127.0.0.1/32' ) ) );
|
||||
$this->assertFalse(
|
||||
invokeStatic(
|
||||
StatifyBlacklist::class, 'cidr_match', array(
|
||||
'127.0.0.1',
|
||||
'127.0.0.1/33',
|
||||
)
|
||||
invoke_static(
|
||||
StatifyBlacklist::class,
|
||||
'cidr_match',
|
||||
array( '127.0.0.1', '127.0.0.1/33' )
|
||||
)
|
||||
);
|
||||
$this->assertFalse(
|
||||
invokeStatic(
|
||||
StatifyBlacklist::class, 'cidr_match', array(
|
||||
'127.0.0.1',
|
||||
'127.0.0.1/-1',
|
||||
)
|
||||
invoke_static(
|
||||
StatifyBlacklist::class,
|
||||
'cidr_match',
|
||||
array( '127.0.0.1', '127.0.0.1/-1' )
|
||||
)
|
||||
);
|
||||
$this->assertTrue(
|
||||
invokeStatic(
|
||||
StatifyBlacklist::class, 'cidr_match', array(
|
||||
'192.0.2.123',
|
||||
'192.0.2.0/24',
|
||||
)
|
||||
invoke_static(
|
||||
StatifyBlacklist::class,
|
||||
'cidr_match',
|
||||
array( '192.0.2.123', '192.0.2.0/24' )
|
||||
)
|
||||
);
|
||||
$this->assertFalse(
|
||||
invokeStatic(
|
||||
StatifyBlacklist::class, 'cidr_match', array(
|
||||
'192.0.3.123',
|
||||
'192.0.2.0/24',
|
||||
)
|
||||
invoke_static(
|
||||
StatifyBlacklist::class,
|
||||
'cidr_match',
|
||||
array( '192.0.3.123', '192.0.2.0/24' )
|
||||
)
|
||||
);
|
||||
$this->assertTrue(
|
||||
invokeStatic(
|
||||
StatifyBlacklist::class, 'cidr_match', array(
|
||||
'192.0.2.123',
|
||||
'192.0.2.120/29',
|
||||
)
|
||||
invoke_static(
|
||||
StatifyBlacklist::class,
|
||||
'cidr_match',
|
||||
array( '192.0.2.123', '192.0.2.120/29' )
|
||||
)
|
||||
);
|
||||
$this->assertFalse(
|
||||
invokeStatic(
|
||||
StatifyBlacklist::class, 'cidr_match', array(
|
||||
'192.0.2.128',
|
||||
'192.0.2.120/29',
|
||||
)
|
||||
invoke_static(
|
||||
StatifyBlacklist::class,
|
||||
'cidr_match',
|
||||
array( '192.0.2.128', '192.0.2.120/29' )
|
||||
)
|
||||
);
|
||||
$this->assertTrue( invokeStatic( StatifyBlacklist::class, 'cidr_match', array( '10.11.12.13', '10.0.0.0/8' ) ) );
|
||||
$this->assertTrue( invoke_static( StatifyBlacklist::class, 'cidr_match', array( '10.11.12.13', '10.0.0.0/8' ) ) );
|
||||
$this->assertFalse(
|
||||
invokeStatic(
|
||||
StatifyBlacklist::class, 'cidr_match', array(
|
||||
'10.11.12.345',
|
||||
'10.0.0.0/8',
|
||||
)
|
||||
invoke_static(
|
||||
StatifyBlacklist::class,
|
||||
'cidr_match',
|
||||
array( '10.11.12.345', '10.0.0.0/8' )
|
||||
)
|
||||
);
|
||||
|
||||
// IPv6 tests.
|
||||
$this->assertTrue( invokeStatic( StatifyBlacklist::class, 'cidr_match', array( '::1', '::1' ) ) );
|
||||
$this->assertTrue( invokeStatic( StatifyBlacklist::class, 'cidr_match', array( '::1', '::1/128' ) ) );
|
||||
$this->assertFalse( invokeStatic( StatifyBlacklist::class, 'cidr_match', array( '::1', '::1/129' ) ) );
|
||||
$this->assertFalse( invokeStatic( StatifyBlacklist::class, 'cidr_match', array( '::1', '::1/-1' ) ) );
|
||||
$this->assertTrue( invoke_static( StatifyBlacklist::class, 'cidr_match', array( '::1', '::1' ) ) );
|
||||
$this->assertTrue( invoke_static( StatifyBlacklist::class, 'cidr_match', array( '::1', '::1/128' ) ) );
|
||||
$this->assertFalse( invoke_static( StatifyBlacklist::class, 'cidr_match', array( '::1', '::1/129' ) ) );
|
||||
$this->assertFalse( invoke_static( StatifyBlacklist::class, 'cidr_match', array( '::1', '::1/-1' ) ) );
|
||||
$this->assertTrue(
|
||||
invokeStatic(
|
||||
StatifyBlacklist::class, 'cidr_match', array(
|
||||
'2001:db8:a0b:12f0:1:2:3:4',
|
||||
'2001:db8:a0b:12f0::1/64 ',
|
||||
)
|
||||
invoke_static(
|
||||
StatifyBlacklist::class,
|
||||
'cidr_match',
|
||||
array( '2001:db8:a0b:12f0:1:2:3:4', '2001:db8:a0b:12f0::1/64 ' )
|
||||
)
|
||||
);
|
||||
$this->assertTrue(
|
||||
invokeStatic(
|
||||
StatifyBlacklist::class, 'cidr_match', array(
|
||||
'2001:db8:a0b:12f0::123:456',
|
||||
'2001:db8:a0b:12f0::1/96 ',
|
||||
)
|
||||
invoke_static(
|
||||
StatifyBlacklist::class,
|
||||
'cidr_match',
|
||||
array( '2001:db8:a0b:12f0::123:456', '2001:db8:a0b:12f0::1/96 ' )
|
||||
)
|
||||
);
|
||||
$this->assertFalse(
|
||||
invokeStatic(
|
||||
StatifyBlacklist::class, 'cidr_match', array(
|
||||
'2001:db8:a0b:12f0::1:132:465',
|
||||
'2001:db8:a0b:12f0::1/96 ',
|
||||
)
|
||||
invoke_static(
|
||||
StatifyBlacklist::class,
|
||||
'cidr_match',
|
||||
array( '2001:db8:a0b:12f0::1:132:465', '2001:db8:a0b:12f0::1/96 ' )
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test sanitization of IP addresses
|
||||
* Test sanitization of IP addresses.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSanitizeIPs() {
|
||||
public function test_sanitize_ips() {
|
||||
// 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 ) ) );
|
||||
$result = invoke_static( StatifyBlacklist_Admin::class, 'sanitize_ips', array( array_merge( $valid, $invalid ) ) );
|
||||
$this->assertNotFalse( $result );
|
||||
|
||||
/*
|
||||
* Unfortunately this is necessary as long as we run PHP 5 tests, because "assertInternalType" is deprecated
|
||||
* as of PHPUnit 8, but "assertIsArray" has been introduces in PHPUnit 7.5 which requires PHP >= 7.1.
|
||||
*/
|
||||
if ( method_exists( $this, 'assertIsArray' ) ) {
|
||||
$this->assertIsArray( $result );
|
||||
} else {
|
||||
$this->assertInternalType( 'array', $result );
|
||||
}
|
||||
$this->assertEquals( $valid, $result );
|
||||
|
||||
// IPv6 tests.
|
||||
@ -327,28 +389,34 @@ class StatifyBlacklist_Test extends PHPUnit\Framework\TestCase {
|
||||
'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 ) ) );
|
||||
$result = invoke_static( StatifyBlacklist_Admin::class, 'sanitize_ips', array( array_merge( $valid, $invalid ) ) );
|
||||
$this->assertNotFalse( $result );
|
||||
if ( method_exists( $this, 'assertIsArray' ) ) {
|
||||
$this->assertIsArray( $result );
|
||||
} else {
|
||||
$this->assertInternalType( 'array', $result );
|
||||
}
|
||||
$this->assertEquals( $valid, $result );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test IP filter (#7).
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testIPFilter() {
|
||||
public function test_ip_filter() {
|
||||
// Prepare Options: 2 blacklisted IPs, disabled.
|
||||
StatifyBlacklist::$_options = array(
|
||||
StatifyBlacklist::$options = array(
|
||||
'referer' => array(
|
||||
'active' => 0,
|
||||
'cron' => 0,
|
||||
'regexp' => 0,
|
||||
'regexp' => StatifyBlacklist::MODE_NORMAL,
|
||||
'blacklist' => array(),
|
||||
),
|
||||
'target' => array(
|
||||
'active' => 0,
|
||||
'cron' => 0,
|
||||
'regexp' => 0,
|
||||
'regexp' => StatifyBlacklist::MODE_NORMAL,
|
||||
'blacklist' => array(),
|
||||
),
|
||||
'ip' => array(
|
||||
@ -368,7 +436,7 @@ class StatifyBlacklist_Test extends PHPUnit\Framework\TestCase {
|
||||
$_SERVER['REMOTE_ADDR'] = '192.0.2.123';
|
||||
$this->assertNull( StatifyBlacklist::apply_blacklist_filter() );
|
||||
// Activate filter.
|
||||
StatifyBlacklist::$_options['ip']['active'] = 1;
|
||||
StatifyBlacklist::$options['ip']['active'] = 1;
|
||||
$this->assertTrue( StatifyBlacklist::apply_blacklist_filter() );
|
||||
// Try matching v6 address.
|
||||
$_SERVER['REMOTE_ADDR'] = '2001:db8:a0b:12f0::1';
|
||||
@ -379,7 +447,7 @@ class StatifyBlacklist_Test extends PHPUnit\Framework\TestCase {
|
||||
$_SERVER['REMOTE_ADDR'] = '2001:db8:a0b:12f0::2';
|
||||
$this->assertNull( StatifyBlacklist::apply_blacklist_filter() );
|
||||
// Subnet matching.
|
||||
StatifyBlacklist::$_options['ip']['blacklist'] = array(
|
||||
StatifyBlacklist::$options['ip']['blacklist'] = array(
|
||||
'192.0.2.0/25',
|
||||
'2001:db8:a0b:12f0::/96',
|
||||
);
|
||||
@ -405,20 +473,22 @@ class StatifyBlacklist_Test extends PHPUnit\Framework\TestCase {
|
||||
|
||||
/**
|
||||
* Test simple target filter.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testTargetFilter() {
|
||||
public function test_target_filter() {
|
||||
// Prepare Options: 2 blacklisted domains, disabled.
|
||||
StatifyBlacklist::$_options = array(
|
||||
StatifyBlacklist::$options = array(
|
||||
'referer' => array(
|
||||
'active' => 0,
|
||||
'cron' => 0,
|
||||
'regexp' => 0,
|
||||
'regexp' => StatifyBlacklist::MODE_NORMAL,
|
||||
'blacklist' => array(),
|
||||
),
|
||||
'target' => array(
|
||||
'active' => 0,
|
||||
'cron' => 0,
|
||||
'regexp' => 0,
|
||||
'regexp' => StatifyBlacklist::MODE_NORMAL,
|
||||
'blacklist' => array(
|
||||
'/excluded/page/' => 0,
|
||||
'/?page_id=3' => 1,
|
||||
@ -451,7 +521,7 @@ class StatifyBlacklist_Test extends PHPUnit\Framework\TestCase {
|
||||
$this->assertNull( StatifyBlacklist::apply_blacklist_filter() );
|
||||
|
||||
// Activate filter and run tests again.
|
||||
StatifyBlacklist::$_options['target']['active'] = 1;
|
||||
StatifyBlacklist::$options['target']['active'] = 1;
|
||||
|
||||
unset( $_SERVER['REQUEST_URI'] );
|
||||
$this->assertNull( StatifyBlacklist::apply_blacklist_filter() );
|
||||
@ -483,11 +553,11 @@ class StatifyBlacklist_Test extends PHPUnit\Framework\TestCase {
|
||||
*/
|
||||
public function test_combined_filters() {
|
||||
// Prepare Options: simple referer + simple target + ip.
|
||||
StatifyBlacklist::$_options = array(
|
||||
StatifyBlacklist::$options = array(
|
||||
'referer' => array(
|
||||
'active' => 1,
|
||||
'cron' => 0,
|
||||
'regexp' => 0,
|
||||
'regexp' => StatifyBlacklist::MODE_NORMAL,
|
||||
'blacklist' => array(
|
||||
'example.com' => 0,
|
||||
),
|
||||
@ -495,15 +565,15 @@ class StatifyBlacklist_Test extends PHPUnit\Framework\TestCase {
|
||||
'target' => array(
|
||||
'active' => 1,
|
||||
'cron' => 0,
|
||||
'regexp' => 0,
|
||||
'regexp' => StatifyBlacklist::MODE_NORMAL,
|
||||
'blacklist' => array(
|
||||
'/excluded/page/' => 0
|
||||
'/excluded/page/' => 0,
|
||||
),
|
||||
),
|
||||
'ip' => array(
|
||||
'active' => 1,
|
||||
'blacklist' => array(
|
||||
'192.0.2.123'
|
||||
'192.0.2.123',
|
||||
),
|
||||
),
|
||||
'version' => StatifyBlacklist::VERSION_MAIN,
|
||||
@ -535,14 +605,19 @@ class StatifyBlacklist_Test extends PHPUnit\Framework\TestCase {
|
||||
$_SERVER['REMOTE_ADDR'] = '192.0.2.234';
|
||||
|
||||
// Same for RegExp filters.
|
||||
StatifyBlacklist::$_options['referer']['regexp'] = 1;
|
||||
StatifyBlacklist::$_options['referer']['blacklist'] = array( 'example\.com' => 0 );
|
||||
StatifyBlacklist::$_options['target']['regexp'] = 1;
|
||||
StatifyBlacklist::$_options['target']['blacklist'] = array( '\/excluded\/.*' => 0 );
|
||||
StatifyBlacklist::$options['referer']['regexp'] = StatifyBlacklist::MODE_REGEX;
|
||||
StatifyBlacklist::$options['referer']['blacklist'] = array( 'example\.com' => 0 );
|
||||
StatifyBlacklist::$options['target']['regexp'] = StatifyBlacklist::MODE_REGEX;
|
||||
StatifyBlacklist::$options['target']['blacklist'] = array( '/excluded/.*' => 0 );
|
||||
|
||||
$this->assertNull( StatifyBlacklist::apply_blacklist_filter() );
|
||||
$_SERVER['HTTP_REFERER'] = 'https://example.com';
|
||||
$this->assertTrue( StatifyBlacklist::apply_blacklist_filter() );
|
||||
// Check case-insensitive match.
|
||||
$_SERVER['HTTP_REFERER'] = 'https://eXaMpLe.com';
|
||||
$this->assertNull( StatifyBlacklist::apply_blacklist_filter() );
|
||||
StatifyBlacklist::$options['referer']['regexp'] = StatifyBlacklist::MODE_REGEX_CI;
|
||||
$this->assertTrue( StatifyBlacklist::apply_blacklist_filter() );
|
||||
$_SERVER['HTTP_REFERER'] = 'https://example.net';
|
||||
$_SERVER['REQUEST_URI'] = '/excluded/page/';
|
||||
$this->assertTrue( StatifyBlacklist::apply_blacklist_filter() );
|
||||
@ -556,9 +631,9 @@ class StatifyBlacklist_Test extends PHPUnit\Framework\TestCase {
|
||||
|
||||
|
||||
/** @ignore */
|
||||
function invokeStatic( $class, $methodName, $parameters = array() ) {
|
||||
function invoke_static( $class, $method_name, $parameters = array() ) {
|
||||
$reflection = new \ReflectionClass( $class );
|
||||
$method = $reflection->getMethod( $methodName );
|
||||
$method = $reflection->getMethod( $method_name );
|
||||
$method->setAccessible( true );
|
||||
|
||||
return $method->invokeArgs( null, $parameters );
|
||||
|
@ -9,6 +9,8 @@
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
// phpcs:disable WordPress.WhiteSpace.PrecisionAlignment.Found
|
||||
|
||||
// Quit.
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
@ -19,7 +21,7 @@ if ( ! empty( $_POST['statifyblacklist'] ) ) {
|
||||
|
||||
// Check user capabilities.
|
||||
if ( ! current_user_can( 'manage_options' ) ) {
|
||||
die( __( 'Are you sure you want to do this?' ) );
|
||||
die( esc_html__( 'Are you sure you want to do this?' ) );
|
||||
}
|
||||
|
||||
if ( ! empty( $_POST['cleanUp'] ) ) {
|
||||
@ -27,24 +29,63 @@ if ( ! empty( $_POST['statifyblacklist'] ) ) {
|
||||
StatifyBlacklist_Admin::cleanup_database();
|
||||
} else {
|
||||
// Extract referer array.
|
||||
if ( empty( trim( $_POST['statifyblacklist']['referer']['blacklist'] ) ) ) {
|
||||
if ( isset( $_POST['statifyblacklist']['referer']['blacklist'] ) ) {
|
||||
$referer_str = sanitize_textarea_field( wp_unslash( $_POST['statifyblacklist']['referer']['blacklist'] ) );
|
||||
}
|
||||
if ( empty( trim( $referer_str ) ) ) {
|
||||
$referer = array();
|
||||
} else {
|
||||
$referer = explode( "\r\n", $_POST['statifyblacklist']['referer']['blacklist'] );
|
||||
$referer = array_filter(
|
||||
array_map(
|
||||
function ( $a ) {
|
||||
return trim( $a );
|
||||
},
|
||||
explode( "\r\n", $referer_str )
|
||||
),
|
||||
function ( $a ) {
|
||||
return ! empty( $a );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Extract target array.
|
||||
if ( empty( trim( $_POST['statifyblacklist']['target']['blacklist'] ) ) ) {
|
||||
if ( isset( $_POST['statifyblacklist']['target']['blacklist'] ) ) {
|
||||
$target_str = sanitize_textarea_field( wp_unslash( $_POST['statifyblacklist']['target']['blacklist'] ) );
|
||||
}
|
||||
if ( empty( trim( $target_str ) ) ) {
|
||||
$target = array();
|
||||
} else {
|
||||
$target = explode( "\r\n", str_replace( '\\\\', '\\', $_POST['statifyblacklist']['target']['blacklist'] ) );
|
||||
$target = array_filter(
|
||||
array_map(
|
||||
function ( $a ) {
|
||||
return trim( $a );
|
||||
},
|
||||
explode( "\r\n", str_replace( '\\\\', '\\', $target_str ) )
|
||||
),
|
||||
function ( $a ) {
|
||||
return ! empty( $a );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Extract IP array.
|
||||
if ( empty( trim( $_POST['statifyblacklist']['ip']['blacklist'] ) ) ) {
|
||||
if ( isset( $_POST['statifyblacklist']['ip']['blacklist'] ) ) {
|
||||
$ip_str = sanitize_textarea_field( wp_unslash( $_POST['statifyblacklist']['ip']['blacklist'] ) );
|
||||
}
|
||||
if ( empty( trim( $ip_str ) ) ) {
|
||||
$ip = array();
|
||||
} else {
|
||||
$ip = explode( "\r\n", $_POST['statifyblacklist']['ip']['blacklist'] );
|
||||
$ip = array_filter(
|
||||
array_map(
|
||||
function ( $a ) {
|
||||
return trim( $a );
|
||||
},
|
||||
explode( "\r\n", $ip_str )
|
||||
),
|
||||
function ( $a ) {
|
||||
return ! empty( $a );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Update options (data will be sanitized).
|
||||
@ -79,21 +120,33 @@ if ( ! empty( $_POST['statifyblacklist'] ) ) {
|
||||
|
||||
// Generate messages.
|
||||
if ( false !== $statifyblacklist_update_result ) {
|
||||
if ( array_key_exists( 'referer', $statifyblacklist_update_result ) ) {
|
||||
$statifyblacklist_post_warning = __( 'Some URLs are invalid and have been sanitized.', 'statify-blacklist' );
|
||||
} elseif ( array_key_exists( 'ip', $statifyblacklist_update_result ) ) {
|
||||
$statifyblacklist_post_warning = array();
|
||||
if ( ! empty( $statifyblacklist_update_result['referer']['diff'] ) ) {
|
||||
$statifyblacklist_post_warning[] = __( 'Some URLs are invalid and have been sanitized.', 'statify-blacklist' );
|
||||
}
|
||||
if ( ! empty( $statifyblacklist_update_result['referer']['invalid'] ) ) {
|
||||
$statifyblacklist_post_warning[] = __( 'Some regular expressions are invalid:', 'statify-blacklist' ) . '<br>' . implode( '<br>', $statifyblacklist_update_result['referer']['invalid'] );
|
||||
}
|
||||
if ( ! empty( $statifyblacklist_update_result['ip']['diff'] ) ) {
|
||||
// translators: List of invalid IP addresses (comma separated).
|
||||
$statifyblacklist_post_warning = sprintf( __( 'Some IPs are invalid : %s', 'statify-blacklist' ), implode( ', ', $statifyblacklist_update_result['ip'] ) );
|
||||
$statifyblacklist_post_warning[] = sprintf( __( 'Some IPs are invalid: %s', 'statify-blacklist' ), implode( ', ', $statifyblacklist_update_result['ip']['diff'] ) );
|
||||
}
|
||||
} else {
|
||||
$statifyblacklist_post_success = __( 'Settings updated successfully.', 'statify-blacklist' );
|
||||
}
|
||||
} // End if().
|
||||
} // End if().
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable some code style rules that are impractical for textarea content:
|
||||
*
|
||||
* phpcs:disable Squiz.PHP.EmbeddedPhp.ContentBeforeOpen
|
||||
* phpcs:disable Squiz.PHP.EmbeddedPhp.ContentAfterEnd
|
||||
*/
|
||||
?>
|
||||
|
||||
<div class="wrap">
|
||||
<h1><?php esc_html_e( 'Statify Blacklist', 'statify-blacklist' ) ?></h1>
|
||||
<h1><?php esc_html_e( 'Statify Blacklist', 'statify-blacklist' ); ?></h1>
|
||||
<?php
|
||||
if ( is_plugin_inactive( 'statify/statify.php' ) ) {
|
||||
print '<div class="notice notice-warning"><p>';
|
||||
@ -101,11 +154,12 @@ if ( ! empty( $_POST['statifyblacklist'] ) ) {
|
||||
print '</p></div>';
|
||||
}
|
||||
if ( isset( $statifyblacklist_post_warning ) ) {
|
||||
foreach ( $statifyblacklist_post_warning as $w ) {
|
||||
print '<div class="notice notice-warning"><p>' .
|
||||
esc_html( $statifyblacklist_post_warning );
|
||||
print '<br/>';
|
||||
esc_html_e( 'Settings have not been saved yet.', 'statify-blacklist' );
|
||||
print '</p></div>';
|
||||
wp_kses( $w, array( 'br' => array() ) ) .
|
||||
'</p></div>';
|
||||
}
|
||||
print '<div class="notice notice-warning"><p>' . esc_html__( 'Settings have not been saved yet.', 'statify-blacklist' ) . '</p></div>';
|
||||
}
|
||||
if ( isset( $statifyblacklist_post_success ) ) {
|
||||
print '<div class="notice notice-success"><p>' .
|
||||
@ -114,179 +168,223 @@ if ( ! empty( $_POST['statifyblacklist'] ) ) {
|
||||
}
|
||||
?>
|
||||
<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( $statifyblacklist_update_result['referer'] ) ) {
|
||||
print esc_html( implode( "\r\n", array_keys( $statifyblacklist_update_result['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( $statifyblacklist_update_result['target'] ) ) {
|
||||
print esc_html( implode( "\r\n", array_keys( $statifyblacklist_update_result['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( $statifyblacklist_update_result['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.', 'statify-blacklist' ) ?>
|
||||
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' ); ?>
|
||||
|
||||
<h2><?php esc_html_e( 'Referer blacklist', 'statify-blacklist' ); ?></h2>
|
||||
|
||||
<table class="form-table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for="statify-blacklist_active_referer">
|
||||
<?php esc_html_e( 'Activate live filter', 'statify-blacklist' ); ?>
|
||||
</label>
|
||||
</th>
|
||||
<td>
|
||||
<input type="checkbox" name="statifyblacklist[referer][active]"
|
||||
id="statify-blacklist_active_referer"
|
||||
value="1" <?php checked( StatifyBlacklist::$options['referer']['active'], 1 ); ?>>
|
||||
<p class="description">
|
||||
<?php esc_html_e( 'Filter at time of tracking, before anything is stored', 'statify-blacklist' ); ?>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for="statify-blacklist_cron_referer">
|
||||
<?php esc_html_e( 'CronJob execution', 'statify-blacklist' ); ?>
|
||||
</label>
|
||||
</th>
|
||||
<td>
|
||||
<input type="checkbox" name="statifyblacklist[referer][cron]" id="statify-blacklist_cron_referer"
|
||||
value="1" <?php checked( StatifyBlacklist::$options['referer']['cron'], 1 ); ?>>
|
||||
<p class="description"><?php esc_html_e( 'Periodically clean up database in background', 'statify-blacklist' ); ?></p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for="statify-blacklist_referer_regexp"><?php esc_html_e( 'Matching method', 'statify-blacklist' ); ?></label>
|
||||
</th>
|
||||
<td>
|
||||
<select name="statifyblacklist[referer][regexp]" id="statify-blacklist_referer_regexp">
|
||||
<option value="<?php print esc_attr( StatifyBlacklist::MODE_NORMAL ); ?>" <?php selected( StatifyBlacklist::$options['referer']['regexp'], StatifyBlacklist::MODE_NORMAL ); ?>>
|
||||
<?php esc_html_e( 'Domain', 'statify-blacklist' ); ?>
|
||||
</option>
|
||||
<option value="<?php print esc_attr( StatifyBlacklist::MODE_KEYWORD ); ?>" <?php selected( StatifyBlacklist::$options['referer']['regexp'], StatifyBlacklist::MODE_KEYWORD ); ?>>
|
||||
<?php esc_html_e( 'Keyword', 'statify-blacklist' ); ?>
|
||||
</option>
|
||||
<option value="<?php print esc_attr( StatifyBlacklist::MODE_REGEX ); ?>" <?php selected( StatifyBlacklist::$options['referer']['regexp'], StatifyBlacklist::MODE_REGEX ); ?>>
|
||||
<?php esc_html_e( 'RegEx case-sensitive', 'statify-blacklist' ); ?>
|
||||
</option>
|
||||
<option value="<?php print esc_attr( StatifyBlacklist::MODE_REGEX_CI ); ?>" <?php selected( StatifyBlacklist::$options['referer']['regexp'], StatifyBlacklist::MODE_REGEX_CI ); ?>>
|
||||
<?php esc_html_e( 'RegEx case-insensitive', 'statify-blacklist' ); ?>
|
||||
</option>
|
||||
</select>
|
||||
|
||||
<p class="description">
|
||||
<?php esc_html_e( 'Domain', 'statify-blacklist' ); ?> - <?php esc_html_e( 'Match given domain including subdomains', 'statify-blacklist' ); ?>
|
||||
<br>
|
||||
<?php esc_html_e( 'Keyword', 'statify-blacklist' ); ?> - <?php esc_html_e( 'Match every referer that contains one of the keywords', 'statify-blacklist' ); ?>
|
||||
<br>
|
||||
<?php esc_html_e( 'RegEx', 'statify-blacklist' ); ?> - <?php esc_html_e( 'Match referer by regular expression', 'statify-blacklist' ); ?>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for="statify-blacklist_referer"><?php esc_html_e( 'Referer blacklist', 'statify-blacklist' ); ?></label>
|
||||
</th>
|
||||
<td>
|
||||
<textarea cols="40" rows="5" name="statifyblacklist[referer][blacklist]" id="statify-blacklist_referer"><?php
|
||||
if ( empty( $statifyblacklist_update_result['referer'] ) ) {
|
||||
print esc_html( implode( "\r\n", array_keys( StatifyBlacklist::$options['referer']['blacklist'] ) ) );
|
||||
} else {
|
||||
print esc_html( implode( "\r\n", array_keys( $statifyblacklist_update_result['referer']['sanitized'] ) ) );
|
||||
}
|
||||
?></textarea>
|
||||
<p class="description">
|
||||
<?php esc_html_e( 'Add one domain (without subdomains) each line, e.g. example.com', 'statify-blacklist' ); ?>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h2><?php esc_html_e( 'Target blacklist', 'statify-blacklist' ); ?></h2>
|
||||
|
||||
<table class="form-table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for="statify-blacklist_active_target">
|
||||
<?php esc_html_e( 'Activate live filter', 'statify-blacklist' ); ?>
|
||||
</label>
|
||||
</th>
|
||||
<td>
|
||||
<input type="checkbox" name="statifyblacklist[target][active]"
|
||||
id="statify-blacklist_active_target"
|
||||
value="1" <?php checked( StatifyBlacklist::$options['target']['active'], 1 ); ?>>
|
||||
<p class="description">
|
||||
<?php esc_html_e( 'Filter at time of tracking, before anything is stored', 'statify-blacklist' ); ?>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for="statify-blacklist_cron_target">
|
||||
<?php esc_html_e( 'CronJob execution', 'statify-blacklist' ); ?>
|
||||
</label>
|
||||
</th>
|
||||
<td>
|
||||
<input type="checkbox" name="statifyblacklist[target][cron]" id="statify-blacklist_cron_target"
|
||||
value="1" <?php checked( StatifyBlacklist::$options['target']['cron'], 1 ); ?>>
|
||||
<p class="description">
|
||||
<?php esc_html_e( 'Clean database periodically in background', 'statify-blacklist' ); ?>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for="statify-blacklist_target_regexp">
|
||||
<?php esc_html_e( 'Matching method', 'statify-blacklist' ); ?>
|
||||
</label>
|
||||
</th>
|
||||
<td>
|
||||
<select name="statifyblacklist[target][regexp]" id="statify-blacklist_referer_regexp">
|
||||
<option value="<?php print esc_attr( StatifyBlacklist::MODE_NORMAL ); ?>" <?php selected( StatifyBlacklist::$options['target']['regexp'], StatifyBlacklist::MODE_NORMAL ); ?>>
|
||||
<?php esc_html_e( 'Exact', 'statify-blacklist' ); ?>
|
||||
</option>
|
||||
<option value="<?php print esc_attr( StatifyBlacklist::MODE_REGEX ); ?>" <?php selected( StatifyBlacklist::$options['target']['regexp'], StatifyBlacklist::MODE_REGEX ); ?>>
|
||||
<?php esc_html_e( 'RegEx case-sensitive', 'statify-blacklist' ); ?>
|
||||
</option>
|
||||
<option value="<?php print esc_attr( StatifyBlacklist::MODE_REGEX_CI ); ?>" <?php selected( StatifyBlacklist::$options['target']['regexp'], StatifyBlacklist::MODE_REGEX_CI ); ?>>
|
||||
<?php esc_html_e( 'RegEx case-insensitive', 'statify-blacklist' ); ?>
|
||||
</option>
|
||||
</select>
|
||||
|
||||
<p class="description">
|
||||
<?php esc_html_e( 'Exact', 'statify-blacklist' ); ?> - <?php esc_html_e( 'Match only given targets', 'statify-blacklist' ); ?>
|
||||
<br>
|
||||
<?php esc_html_e( 'RegEx', 'statify-blacklist' ); ?> - <?php esc_html_e( 'Match target by regular expression', 'statify-blacklist' ); ?>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for="statify-blacklist_target">
|
||||
<?php esc_html_e( 'Target blacklist', 'statify-blacklist' ); ?>
|
||||
</label>
|
||||
</th>
|
||||
<td>
|
||||
<textarea cols="40" rows="5" name="statifyblacklist[target][blacklist]" id="statify-blacklist_target"><?php
|
||||
if ( empty( $statifyblacklist_update_result['target'] ) ) {
|
||||
print esc_html( implode( "\r\n", array_keys( StatifyBlacklist::$options['target']['blacklist'] ) ) );
|
||||
} else {
|
||||
print esc_html( implode( "\r\n", array_keys( $statifyblacklist_update_result['target']['sanitized'] ) ) );
|
||||
}
|
||||
?></textarea>
|
||||
|
||||
<p class="description">
|
||||
(<?php esc_html_e( 'Add one target URL each line, e.g.', 'statify-blacklist' ); ?> /, /test/page/, /?page_id=123)
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<h2><?php esc_html_e( 'IP blacklist', 'statify-blacklist' ); ?></h2>
|
||||
|
||||
<table class="form-table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for="statify-blacklist_active_ip">
|
||||
<?php esc_html_e( 'Activate live filter', 'statify-blacklist' ); ?>
|
||||
</label>
|
||||
</th>
|
||||
<td>
|
||||
<input type="checkbox" name="statifyblacklist[ip][active]" id="statify-blacklist_active_ip"
|
||||
value="1" <?php checked( StatifyBlacklist::$options['ip']['active'], 1 ); ?>>
|
||||
<p class="description">
|
||||
<?php esc_html_e( 'Filter at time of tracking, before anything is stored', 'statify-blacklist' ); ?>
|
||||
<br>
|
||||
<?php esc_html_e( 'Cron execution is not possible for IP filter, because IP addresses are not stored.', 'statify-blacklist' ); ?>
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
<label for="statify-blacklist_ip"><?php esc_html_e( 'IP blacklist', 'statify-blacklist' ); ?></label>:
|
||||
</th>
|
||||
<td>
|
||||
<textarea cols="40" rows="5" name="statifyblacklist[ip][blacklist]" id="statify-blacklist_ip"><?php
|
||||
if ( empty( $statifyblacklist_update_result['ip'] ) ) {
|
||||
print esc_html( implode( "\r\n", StatifyBlacklist::$options['ip']['blacklist'] ) );
|
||||
} else {
|
||||
print esc_html( implode( "\r\n", $statifyblacklist_update_result['ip']['sanitized'] ) );
|
||||
}
|
||||
?></textarea>
|
||||
|
||||
<p class="description">
|
||||
<?php esc_html_e( 'Add one IP address or range per line, e.g.', 'statify-blacklist' ); ?>
|
||||
127.0.0.1, 192.168.123.0/24, 2001:db8:a0b:12f0::1/64
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<p class="submit">
|
||||
<input class="button-primary" type="submit" name="submit" value="<?php esc_html_e( 'Save Changes' ) ?>">
|
||||
<hr />
|
||||
<input class="button-primary" type="submit" name="submit" value="<?php esc_html_e( 'Save Changes' ); ?>">
|
||||
<hr>
|
||||
<input class="button-secondary" type="submit" name="cleanUp"
|
||||
value="<?php esc_html_e( 'CleanUp Database', 'statify-blacklist' ) ?>"
|
||||
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' ); ?>
|
||||
<em><?php esc_html_e( 'This cannot be undone!', 'statify-blacklist' ); ?></em></small>
|
||||
<br>
|
||||
<p class="description">
|
||||
<?php esc_html_e( 'Applies referer and target filter (even if disabled) to data stored in database.', 'statify-blacklist' ); ?>
|
||||
<em><?php esc_html_e( 'This cannot be undone!', 'statify-blacklist' ); ?></em>
|
||||
</p>
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
|
Loading…
x
Reference in New Issue
Block a user