Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
<?php
|
|
|
|
|
2020-09-20 22:31:41 +00:00
|
|
|
use MediaWiki\Extension\AbuseFilter\AbuseFilterServices;
|
2020-10-13 16:01:18 +00:00
|
|
|
use MediaWiki\Extension\AbuseFilter\ChangeTagger;
|
2020-09-20 22:31:41 +00:00
|
|
|
use MediaWiki\Extension\AbuseFilter\FilterProfiler;
|
2020-06-03 00:43:22 +00:00
|
|
|
use MediaWiki\Extension\AbuseFilter\Hooks\AbuseFilterHookRunner;
|
2019-06-25 16:39:57 +00:00
|
|
|
use MediaWiki\Extension\AbuseFilter\VariableGenerator\VariableGenerator;
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
use MediaWiki\Logger\LoggerFactory;
|
|
|
|
use MediaWiki\MediaWikiServices;
|
|
|
|
use MediaWiki\Session\SessionManager;
|
2020-01-24 17:26:03 +00:00
|
|
|
use Wikimedia\IPUtils;
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
use Wikimedia\Rdbms\IDatabase;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This class contains the logic for executing abuse filters and their actions. The entry points are
|
|
|
|
* run() and runForStash(). Note that run() can only be executed once on a given instance.
|
|
|
|
* @todo In a perfect world, every time this class gets constructed we should have a context
|
|
|
|
* source at hand. Unfortunately, this currently isn't true, as the hooks used for filtering
|
|
|
|
* don't pass a full context. If they did, this class would just extend ContextSource and use
|
|
|
|
* that to retrieve user, title, globals etc.
|
|
|
|
*/
|
|
|
|
class AbuseFilterRunner {
|
|
|
|
/**
|
|
|
|
* @var User The user who performed the action being filtered
|
|
|
|
*/
|
|
|
|
protected $user;
|
|
|
|
/**
|
|
|
|
* @var Title The title where the action being filtered was performed
|
|
|
|
*/
|
|
|
|
protected $title;
|
|
|
|
/**
|
|
|
|
* @var AbuseFilterVariableHolder The variables for the current action
|
|
|
|
*/
|
|
|
|
protected $vars;
|
|
|
|
/**
|
|
|
|
* @var string The group of filters to check (as defined in $wgAbuseFilterValidGroups)
|
|
|
|
*/
|
|
|
|
protected $group;
|
2020-03-06 16:21:51 +00:00
|
|
|
/**
|
|
|
|
* @var string The action we're filtering
|
|
|
|
*/
|
|
|
|
protected $action;
|
2019-01-30 19:30:59 +00:00
|
|
|
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
/**
|
2019-01-30 19:30:59 +00:00
|
|
|
* @var array Data from per-filter profiling. Shape:
|
2019-10-09 10:37:38 +00:00
|
|
|
* [ filterName => [ 'time' => float, 'conds' => int, 'result' => bool ] ]
|
|
|
|
* @phan-var array<string,array{time:float,conds:int,result:bool}>
|
2019-01-30 19:30:59 +00:00
|
|
|
*
|
|
|
|
* Where 'timeTaken' is in seconds, 'result' is a boolean indicating whether the filter matched
|
|
|
|
* the action, and 'filterID' is "{prefix}-{ID}" ; Prefix should be empty for local
|
|
|
|
* filters. In stash mode this member is saved in cache, while in execute mode it's used to
|
|
|
|
* update profiling after checking all filters.
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
*/
|
2019-01-30 19:30:59 +00:00
|
|
|
protected $profilingData;
|
|
|
|
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
/**
|
|
|
|
* @var AbuseFilterParser The parser instance to use to check all filters
|
|
|
|
* @protected Public for back-compat only, will be made protected. self::init already handles
|
|
|
|
* building a parser object.
|
|
|
|
*/
|
|
|
|
public $parser;
|
|
|
|
/**
|
|
|
|
* @var bool Whether a run() was already performed. Used to avoid multiple executions with the
|
|
|
|
* same members.
|
|
|
|
*/
|
|
|
|
private $executed = false;
|
|
|
|
|
2020-06-03 00:43:22 +00:00
|
|
|
/** @var AbuseFilterHookRunner */
|
|
|
|
private $hookRunner;
|
|
|
|
|
2020-09-20 22:31:41 +00:00
|
|
|
/** @var FilterProfiler */
|
|
|
|
private $filterProfiler;
|
|
|
|
|
2020-10-13 16:01:18 +00:00
|
|
|
/** @var ChangeTagger */
|
|
|
|
private $changeTagger;
|
|
|
|
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
/**
|
|
|
|
* @param User $user The user who performed the action being filtered
|
|
|
|
* @param Title $title The title where the action being filtered was performed
|
|
|
|
* @param AbuseFilterVariableHolder $vars The variables for the current action
|
|
|
|
* @param string $group The group of filters to check. It must be defined as so in
|
|
|
|
* $wgAbuseFilterValidGroups, or this will throw.
|
|
|
|
* @throws InvalidArgumentException
|
|
|
|
*/
|
|
|
|
public function __construct( User $user, Title $title, AbuseFilterVariableHolder $vars, $group ) {
|
|
|
|
global $wgAbuseFilterValidGroups;
|
|
|
|
if ( !in_array( $group, $wgAbuseFilterValidGroups ) ) {
|
|
|
|
throw new InvalidArgumentException( '$group must be defined in $wgAbuseFilterValidGroups' );
|
|
|
|
}
|
2020-03-06 16:21:51 +00:00
|
|
|
if ( !$vars->varIsSet( 'action' ) ) {
|
|
|
|
throw new InvalidArgumentException( "The 'action' variable is not set." );
|
|
|
|
}
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
$this->user = $user;
|
|
|
|
$this->title = $title;
|
|
|
|
$this->vars = $vars;
|
2019-08-11 13:11:20 +00:00
|
|
|
$this->vars->setLogger( LoggerFactory::getInstance( 'AbuseFilter' ) );
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
$this->group = $group;
|
2020-03-06 16:21:51 +00:00
|
|
|
$this->action = $vars->getVar( 'action' )->toString();
|
2020-06-03 00:43:22 +00:00
|
|
|
$this->hookRunner = AbuseFilterHookRunner::getRunner();
|
2020-09-20 22:31:41 +00:00
|
|
|
$this->filterProfiler = AbuseFilterServices::getFilterProfiler();
|
2020-10-13 16:01:18 +00:00
|
|
|
$this->changeTagger = AbuseFilterServices::getChangeTagger();
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Inits variables and parser right before running
|
|
|
|
*/
|
|
|
|
private function init() {
|
|
|
|
// Add vars from extensions
|
2020-06-03 00:43:22 +00:00
|
|
|
$this->hookRunner->onAbuseFilterFilterAction(
|
|
|
|
$this->vars,
|
|
|
|
$this->title
|
|
|
|
);
|
|
|
|
$this->hookRunner->onAbuseFilterAlterVariables(
|
|
|
|
$this->vars,
|
|
|
|
$this->title,
|
|
|
|
$this->user
|
|
|
|
);
|
2019-06-25 16:39:57 +00:00
|
|
|
$generator = new VariableGenerator( $this->vars );
|
2019-12-17 15:06:44 +00:00
|
|
|
$this->vars = $generator->addGenericVars()->getVariableHolder();
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
|
|
|
|
$this->vars->forFilter = true;
|
|
|
|
$this->vars->setVar( 'timestamp', (int)wfTimestamp( TS_UNIX ) );
|
|
|
|
$this->parser = $this->getParser();
|
2019-09-19 17:06:14 +00:00
|
|
|
$this->parser->setStatsd( MediaWikiServices::getInstance()->getStatsdDataFactory() );
|
2019-01-30 19:30:59 +00:00
|
|
|
$this->profilingData = [];
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2019-08-21 10:04:10 +00:00
|
|
|
* Shortcut method, so that it can be overridden in mocks.
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
* @return AbuseFilterParser
|
|
|
|
*/
|
|
|
|
protected function getParser() : AbuseFilterParser {
|
2019-08-21 10:04:10 +00:00
|
|
|
return AbuseFilter::getDefaultParser( $this->vars );
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The main entry point of this class. This method runs all filters and takes their consequences.
|
|
|
|
*
|
|
|
|
* @param bool $allowStash Whether we are allowed to check the cache to see if there's a cached
|
|
|
|
* result of a previous execution for the same edit.
|
|
|
|
* @throws BadMethodCallException If run() was already called on this instance
|
|
|
|
* @return Status Good if no action has been taken, a fatal otherwise.
|
|
|
|
*/
|
|
|
|
public function run( $allowStash = true ) : Status {
|
|
|
|
if ( $this->executed ) {
|
|
|
|
throw new BadMethodCallException( 'run() was already called on this instance.' );
|
|
|
|
}
|
|
|
|
$this->executed = true;
|
|
|
|
$this->init();
|
|
|
|
|
2019-07-29 16:56:21 +00:00
|
|
|
$skipReasons = [];
|
2020-06-03 00:43:22 +00:00
|
|
|
$shouldFilter = $this->hookRunner->onAbuseFilterShouldFilterAction(
|
|
|
|
$this->vars, $this->title, $this->user, $skipReasons
|
2019-07-29 16:56:21 +00:00
|
|
|
);
|
|
|
|
if ( !$shouldFilter ) {
|
|
|
|
$logger = LoggerFactory::getInstance( 'AbuseFilter' );
|
2020-03-06 16:21:51 +00:00
|
|
|
$logger->info(
|
|
|
|
'Skipping action {action}. Reasons provided: {reasons}',
|
|
|
|
[ 'action' => $this->action, 'reasons' => implode( ', ', $skipReasons ) ]
|
|
|
|
);
|
2019-07-29 16:56:21 +00:00
|
|
|
return Status::newGood();
|
|
|
|
}
|
|
|
|
|
2020-03-06 16:21:51 +00:00
|
|
|
$useStash = $allowStash && $this->action === 'edit';
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
|
|
|
|
$fromCache = false;
|
|
|
|
$result = [];
|
|
|
|
if ( $useStash ) {
|
|
|
|
$cacheData = $this->seekCache();
|
|
|
|
if ( $cacheData !== false ) {
|
2019-01-30 19:30:59 +00:00
|
|
|
// Use cached vars (T176291) and profiling data (T191430)
|
|
|
|
$this->vars = AbuseFilterVariableHolder::newFromArray( $cacheData['vars'] );
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
$result = [
|
2020-10-13 12:22:17 +00:00
|
|
|
'hitCondLimit' => $cacheData['hitCondLimit'],
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
'matches' => $cacheData['matches'],
|
|
|
|
'runtime' => $cacheData['runtime'],
|
|
|
|
'condCount' => $cacheData['condCount'],
|
2019-01-30 19:30:59 +00:00
|
|
|
'profiling' => $cacheData['profiling']
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
];
|
|
|
|
$fromCache = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( !$fromCache ) {
|
2019-01-30 19:30:59 +00:00
|
|
|
$startTime = microtime( true );
|
2019-03-25 19:19:17 +00:00
|
|
|
// Ensure there's no extra time leftover
|
|
|
|
AFComputedVariable::$profilingExtraTime = 0;
|
|
|
|
|
2020-10-13 12:22:17 +00:00
|
|
|
$hitCondLimit = false;
|
2019-01-30 19:30:59 +00:00
|
|
|
// This also updates $this->profilingData and $this->parser->mCondCount used later
|
2020-10-13 12:22:17 +00:00
|
|
|
$matches = $this->checkAllFilters( $hitCondLimit );
|
2019-03-25 19:19:17 +00:00
|
|
|
$timeTaken = ( microtime( true ) - $startTime - AFComputedVariable::$profilingExtraTime ) * 1000;
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
$result = [
|
2020-10-13 12:22:17 +00:00
|
|
|
'hitCondLimit' => $hitCondLimit,
|
2019-01-30 19:30:59 +00:00
|
|
|
'matches' => $matches,
|
|
|
|
'runtime' => $timeTaken,
|
|
|
|
'condCount' => $this->parser->getCondCount(),
|
|
|
|
'profiling' => $this->profilingData
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
];
|
|
|
|
}
|
2020-10-13 12:22:17 +00:00
|
|
|
'@phan-var array{hitCondLimit:bool,matches:array,runtime:int,condCount:int,profiling:array} $result';
|
2019-03-24 18:01:35 +00:00
|
|
|
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
$matchedFilters = array_keys( array_filter( $result['matches'] ) );
|
2019-03-24 18:01:35 +00:00
|
|
|
$allFilters = array_keys( $result['matches'] );
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
|
2019-03-24 18:01:35 +00:00
|
|
|
$this->profileExecution( $result, $matchedFilters, $allFilters );
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
|
2020-10-13 12:22:17 +00:00
|
|
|
if ( $result['hitCondLimit'] ) {
|
2020-10-13 16:01:18 +00:00
|
|
|
$this->changeTagger->addConditionsLimitTag( $this->getSpecsForTagger() );
|
2020-10-13 12:22:17 +00:00
|
|
|
}
|
|
|
|
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
if ( count( $matchedFilters ) === 0 ) {
|
|
|
|
return Status::newGood();
|
|
|
|
}
|
|
|
|
|
|
|
|
$status = $this->executeFilterActions( $matchedFilters );
|
|
|
|
$actionsTaken = $status->getValue();
|
|
|
|
|
2019-01-30 19:30:59 +00:00
|
|
|
$this->addLogEntries( $actionsTaken );
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
|
|
|
|
return $status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Similar to run(), but runs in "stash" mode, which means filters are executed, no actions are
|
|
|
|
* taken, and the result is saved in cache to be later reused. This can only be used for edits,
|
|
|
|
* and not doing so will throw.
|
|
|
|
*
|
|
|
|
* @throws InvalidArgumentException
|
|
|
|
* @return Status Always a good status, since we're only saving data.
|
|
|
|
*/
|
|
|
|
public function runForStash() : Status {
|
2020-03-06 16:21:51 +00:00
|
|
|
if ( $this->action !== 'edit' ) {
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
throw new InvalidArgumentException(
|
2020-03-06 16:21:51 +00:00
|
|
|
__METHOD__ . " can only be called for edits, called for action {$this->action}."
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->init();
|
|
|
|
|
2019-07-29 16:56:21 +00:00
|
|
|
$skipReasons = [];
|
2020-06-03 00:43:22 +00:00
|
|
|
$shouldFilter = $this->hookRunner->onAbuseFilterShouldFilterAction(
|
|
|
|
$this->vars, $this->title, $this->user, $skipReasons
|
2019-07-29 16:56:21 +00:00
|
|
|
);
|
|
|
|
if ( !$shouldFilter ) {
|
|
|
|
// Don't log it yet
|
|
|
|
return Status::newGood();
|
|
|
|
}
|
|
|
|
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
$cache = ObjectCache::getLocalClusterInstance();
|
|
|
|
$stashKey = $this->getStashKey( $cache );
|
|
|
|
|
|
|
|
$startTime = microtime( true );
|
2019-03-25 19:19:17 +00:00
|
|
|
// Ensure there's no extra time leftover
|
|
|
|
AFComputedVariable::$profilingExtraTime = 0;
|
|
|
|
|
2020-10-13 12:22:17 +00:00
|
|
|
$hitCondLimit = false;
|
|
|
|
$matchedFilters = $this->checkAllFilters( $hitCondLimit );
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
// Save the filter stash result and do nothing further
|
|
|
|
$cacheData = [
|
|
|
|
'matches' => $matchedFilters,
|
2020-10-13 12:22:17 +00:00
|
|
|
'hitCondLimit' => $hitCondLimit,
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
'condCount' => $this->parser->getCondCount(),
|
2019-03-25 19:19:17 +00:00
|
|
|
'runtime' => ( microtime( true ) - $startTime - AFComputedVariable::$profilingExtraTime ) * 1000,
|
2019-01-30 19:30:59 +00:00
|
|
|
'vars' => $this->vars->dumpAllVars(),
|
|
|
|
'profiling' => $this->profilingData
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
];
|
|
|
|
|
|
|
|
$cache->set( $stashKey, $cacheData, $cache::TTL_MINUTE );
|
|
|
|
$this->logCache( 'store', $stashKey );
|
|
|
|
|
|
|
|
return Status::newGood();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Search the cache to find data for a previous execution done for the current edit.
|
|
|
|
*
|
|
|
|
* @return false|array False on failure, the array with data otherwise
|
|
|
|
*/
|
|
|
|
protected function seekCache() {
|
|
|
|
$cache = ObjectCache::getLocalClusterInstance();
|
|
|
|
$stashKey = $this->getStashKey( $cache );
|
|
|
|
|
|
|
|
$ret = $cache->get( $stashKey );
|
|
|
|
$status = $ret !== false ? 'hit' : 'miss';
|
|
|
|
$this->logCache( $status, $stashKey );
|
|
|
|
|
|
|
|
return $ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the stash key for the current variables
|
|
|
|
*
|
|
|
|
* @param BagOStuff $cache
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
protected function getStashKey( BagOStuff $cache ) {
|
|
|
|
$inputVars = $this->vars->exportNonLazyVars();
|
|
|
|
// Exclude noisy fields that have superficial changes
|
|
|
|
$excludedVars = [
|
|
|
|
'old_html' => true,
|
|
|
|
'new_html' => true,
|
|
|
|
'user_age' => true,
|
|
|
|
'timestamp' => true,
|
|
|
|
'page_age' => true,
|
|
|
|
'moved_from_age' => true,
|
|
|
|
'moved_to_age' => true
|
|
|
|
];
|
|
|
|
|
|
|
|
$inputVars = array_diff_key( $inputVars, $excludedVars );
|
|
|
|
ksort( $inputVars );
|
|
|
|
$hash = md5( serialize( $inputVars ) );
|
|
|
|
|
|
|
|
return $cache->makeKey(
|
|
|
|
'abusefilter',
|
|
|
|
'check-stash',
|
|
|
|
$this->group,
|
|
|
|
$hash,
|
2019-08-04 16:07:54 +00:00
|
|
|
'v2'
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Log cache operations related to stashed edits, i.e. store, hit and miss
|
|
|
|
*
|
|
|
|
* @param string $type Either 'store', 'hit' or 'miss'
|
|
|
|
* @param string $key The cache key used
|
|
|
|
* @throws InvalidArgumentException
|
|
|
|
*/
|
|
|
|
protected function logCache( $type, $key ) {
|
|
|
|
if ( !in_array( $type, [ 'store', 'hit', 'miss' ] ) ) {
|
|
|
|
throw new InvalidArgumentException( '$type must be either "store", "hit" or "miss"' );
|
|
|
|
}
|
|
|
|
$logger = LoggerFactory::getInstance( 'StashEdit' );
|
|
|
|
// Bots do not use edit stashing, so avoid distorting the stats
|
|
|
|
$statsd = $this->user->isBot()
|
|
|
|
? new NullStatsdDataFactory()
|
|
|
|
: MediaWikiServices::getInstance()->getStatsdDataFactory();
|
|
|
|
|
|
|
|
$logger->debug( __METHOD__ . ": cache $type for '{$this->title}' (key $key)." );
|
|
|
|
$statsd->increment( "abusefilter.check-stash.$type" );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns an associative array of filters which were tripped
|
|
|
|
*
|
|
|
|
* @protected Public for back compat only; this will actually be made protected in the future.
|
|
|
|
* You should either rely on $this->run() or subclass this class.
|
|
|
|
* @todo This method should simply return an array with IDs of matched filters as values,
|
|
|
|
* since we always end up filtering it after calling this method.
|
2020-10-13 12:22:17 +00:00
|
|
|
* @param bool|null &$hitCondLimit TEMPORARY
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
* @return bool[] Map of (integer filter ID => bool)
|
|
|
|
*/
|
2020-10-13 12:22:17 +00:00
|
|
|
public function checkAllFilters( &$hitCondLimit = false ) : array {
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
global $wgAbuseFilterCentralDB, $wgAbuseFilterIsCentral, $wgAbuseFilterConditionLimit;
|
|
|
|
|
|
|
|
// Ensure that we start fresh, see T193374
|
|
|
|
$this->parser->resetCondCount();
|
|
|
|
|
|
|
|
$matchedFilters = [];
|
|
|
|
|
2019-12-16 14:08:45 +00:00
|
|
|
foreach ( $this->getLocalFilters() as $row ) {
|
2019-01-30 19:30:59 +00:00
|
|
|
$matchedFilters[$row->af_id] = $this->checkFilter( $row );
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ( $wgAbuseFilterCentralDB && !$wgAbuseFilterIsCentral ) {
|
2019-12-16 14:08:45 +00:00
|
|
|
foreach ( $this->getGlobalFilters() as $row ) {
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
$matchedFilters[ AbuseFilter::buildGlobalName( $row->af_id ) ] =
|
2019-01-30 19:30:59 +00:00
|
|
|
$this->checkFilter( $row, true );
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-01 04:51:16 +00:00
|
|
|
// Tag the action if the condition limit was hit
|
2020-10-13 12:22:17 +00:00
|
|
|
$hitCondLimit = $this->parser->getCondCount() > $wgAbuseFilterConditionLimit;
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
|
|
|
|
return $matchedFilters;
|
|
|
|
}
|
|
|
|
|
2019-12-16 14:08:45 +00:00
|
|
|
/**
|
|
|
|
* @return array abuse_filter DB rows
|
|
|
|
*/
|
|
|
|
protected function getLocalFilters() : array {
|
|
|
|
return iterator_to_array( wfGetDB( DB_REPLICA )->select(
|
|
|
|
'abuse_filter',
|
|
|
|
AbuseFilter::ALL_ABUSE_FILTER_FIELDS,
|
|
|
|
[
|
|
|
|
'af_enabled' => 1,
|
|
|
|
'af_deleted' => 0,
|
|
|
|
'af_group' => $this->group,
|
|
|
|
],
|
|
|
|
__METHOD__
|
|
|
|
) );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return array abuse_filter rows from the foreign DB
|
|
|
|
*/
|
|
|
|
protected function getGlobalFilters() : array {
|
|
|
|
$globalRulesKey = AbuseFilter::getGlobalRulesKey( $this->group );
|
|
|
|
$fname = __METHOD__;
|
|
|
|
|
|
|
|
return MediaWikiServices::getInstance()->getMainWANObjectCache()->getWithSetCallback(
|
|
|
|
$globalRulesKey,
|
|
|
|
WANObjectCache::TTL_WEEK,
|
|
|
|
function () use ( $fname ) {
|
|
|
|
$fdb = AbuseFilter::getCentralDB( DB_REPLICA );
|
|
|
|
|
|
|
|
return iterator_to_array( $fdb->select(
|
|
|
|
'abuse_filter',
|
|
|
|
AbuseFilter::ALL_ABUSE_FILTER_FIELDS,
|
|
|
|
[
|
|
|
|
'af_enabled' => 1,
|
|
|
|
'af_deleted' => 0,
|
|
|
|
'af_global' => 1,
|
|
|
|
'af_group' => $this->group,
|
|
|
|
],
|
|
|
|
$fname
|
|
|
|
) );
|
|
|
|
},
|
|
|
|
[
|
|
|
|
'checkKeys' => [ $globalRulesKey ],
|
|
|
|
'lockTSE' => 300,
|
|
|
|
'version' => 1
|
|
|
|
]
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
/**
|
|
|
|
* Check the conditions of a single filter, and profile it if $this->executeMode is true
|
|
|
|
*
|
|
|
|
* @param stdClass $row
|
2019-01-30 19:30:59 +00:00
|
|
|
* @param bool $global
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
* @return bool
|
|
|
|
*/
|
2019-01-30 19:30:59 +00:00
|
|
|
protected function checkFilter( $row, $global = false ) {
|
|
|
|
$filterName = AbuseFilter::buildGlobalName( $row->af_id, $global );
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
|
|
|
|
$startConds = $this->parser->getCondCount();
|
|
|
|
$startTime = microtime( true );
|
2019-03-25 19:19:17 +00:00
|
|
|
$origExtraTime = AFComputedVariable::$profilingExtraTime;
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
|
|
|
|
// Store the row somewhere convenient
|
2019-01-30 19:30:59 +00:00
|
|
|
AbuseFilter::cacheFilter( $filterName, $row );
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
|
|
|
|
$pattern = trim( $row->af_pattern );
|
2019-08-10 16:34:42 +00:00
|
|
|
$this->parser->setFilter( $filterName );
|
2020-09-19 22:30:14 +00:00
|
|
|
$result = $this->parser->checkConditions( $pattern, true, $filterName );
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
|
2019-03-25 19:19:17 +00:00
|
|
|
$actualExtra = AFComputedVariable::$profilingExtraTime - $origExtraTime;
|
|
|
|
$timeTaken = 1000 * ( microtime( true ) - $startTime - $actualExtra );
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
$condsUsed = $this->parser->getCondCount() - $startConds;
|
|
|
|
|
2019-01-30 19:30:59 +00:00
|
|
|
$this->profilingData[$filterName] = [
|
|
|
|
'time' => $timeTaken,
|
|
|
|
'conds' => $condsUsed,
|
|
|
|
'result' => $result
|
|
|
|
];
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
|
2019-01-30 19:30:59 +00:00
|
|
|
return $result;
|
|
|
|
}
|
|
|
|
|
2019-03-24 18:01:35 +00:00
|
|
|
/**
|
|
|
|
* @param array $result Result of the execution, as created in run()
|
|
|
|
* @param string[] $matchedFilters
|
|
|
|
* @param string[] $allFilters
|
|
|
|
*/
|
|
|
|
protected function profileExecution( array $result, array $matchedFilters, array $allFilters ) {
|
2020-09-20 22:31:41 +00:00
|
|
|
$this->filterProfiler->checkResetProfiling( $this->group, $allFilters );
|
|
|
|
$this->filterProfiler->recordRuntimeProfilingResult(
|
2019-09-29 09:02:29 +00:00
|
|
|
count( $allFilters ),
|
2019-03-24 18:01:35 +00:00
|
|
|
$result['condCount'],
|
|
|
|
$result['runtime']
|
|
|
|
);
|
2020-09-20 22:31:41 +00:00
|
|
|
$this->filterProfiler->recordPerFilterProfiling( $this->title, $result['profiling'] );
|
|
|
|
$this->filterProfiler->recordStats(
|
|
|
|
$this->group,
|
|
|
|
$result['condCount'],
|
|
|
|
$result['runtime'],
|
|
|
|
(bool)$matchedFilters
|
2015-04-01 04:51:16 +00:00
|
|
|
);
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Executes a set of actions.
|
|
|
|
*
|
|
|
|
* @param string[] $filters
|
|
|
|
* @return Status returns the operation's status. $status->isOK() will return true if
|
|
|
|
* there were no actions taken, false otherwise. $status->getValue() will return
|
|
|
|
* an array listing the actions taken. $status->getErrors() etc. will provide
|
|
|
|
* the errors and warnings to be shown to the user to explain the actions.
|
|
|
|
*/
|
|
|
|
protected function executeFilterActions( array $filters ) : Status {
|
2018-09-22 10:18:50 +00:00
|
|
|
global $wgMainCacheType, $wgAbuseFilterLocallyDisabledGlobalActions,
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
$wgAbuseFilterBlockDuration, $wgAbuseFilterAnonBlockDuration;
|
|
|
|
|
2020-10-17 13:09:33 +00:00
|
|
|
$actionsByFilter = AbuseFilter::getConsequencesForFilters( $filters, false );
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
$actionsTaken = array_fill_keys( $filters, [] );
|
|
|
|
|
|
|
|
$messages = [];
|
|
|
|
// Accumulator to track max block to issue
|
|
|
|
$maxExpiry = -1;
|
|
|
|
|
|
|
|
foreach ( $actionsByFilter as $filter => $actions ) {
|
|
|
|
// Special-case handling for warnings.
|
|
|
|
$filterPublicComments = AbuseFilter::getFilter( $filter )->af_public_comments;
|
|
|
|
|
|
|
|
$isGlobalFilter = AbuseFilter::splitGlobalName( $filter )[1];
|
|
|
|
|
|
|
|
// If the filter has "throttle" enabled and throttling is available via object
|
|
|
|
// caching, check to see if the user has hit the throttle.
|
2020-10-17 13:09:33 +00:00
|
|
|
if ( isset( $actions['throttle'] ) && $wgMainCacheType !== CACHE_NONE ) {
|
|
|
|
$parameters = $actions['throttle'];
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
$throttleId = array_shift( $parameters );
|
|
|
|
list( $rateCount, $ratePeriod ) = explode( ',', array_shift( $parameters ) );
|
2019-12-07 17:20:10 +00:00
|
|
|
$rateCount = (int)$rateCount;
|
|
|
|
$ratePeriod = (int)$ratePeriod;
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
|
|
|
|
$hitThrottle = false;
|
|
|
|
|
|
|
|
// The rest are throttle-types.
|
|
|
|
foreach ( $parameters as $throttleType ) {
|
|
|
|
$hitThrottle = $hitThrottle || $this->isThrottled(
|
|
|
|
$throttleId, $throttleType, $rateCount, $ratePeriod, $isGlobalFilter );
|
|
|
|
}
|
|
|
|
|
|
|
|
unset( $actions['throttle'] );
|
|
|
|
if ( !$hitThrottle ) {
|
|
|
|
$actionsTaken[$filter][] = 'throttle';
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-22 10:18:50 +00:00
|
|
|
if ( $isGlobalFilter ) {
|
|
|
|
$actions = array_diff_key(
|
|
|
|
$actions,
|
|
|
|
array_filter( $wgAbuseFilterLocallyDisabledGlobalActions )
|
|
|
|
);
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
}
|
|
|
|
|
2020-10-17 13:09:33 +00:00
|
|
|
if ( isset( $actions['warn'] ) ) {
|
|
|
|
$parameters = $actions['warn'];
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
// Generate a unique key to determine whether the user has already been warned.
|
|
|
|
// We'll warn again if one of these changes: session, page, triggered filter or action
|
|
|
|
$warnKey = 'abusefilter-warned-' . md5( $this->title->getPrefixedText() ) .
|
2020-03-06 16:21:51 +00:00
|
|
|
'-' . $filter . '-' . $this->action;
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
|
|
|
|
// Make sure the session is started prior to using it
|
|
|
|
$session = SessionManager::getGlobalSession();
|
|
|
|
$session->persist();
|
|
|
|
|
|
|
|
if ( !isset( $session[$warnKey] ) || !$session[$warnKey] ) {
|
|
|
|
$session[$warnKey] = true;
|
|
|
|
|
|
|
|
$msg = $parameters[0] ?? 'abusefilter-warning';
|
|
|
|
$messages[] = [ $msg, $filterPublicComments, $filter ];
|
|
|
|
|
|
|
|
$actionsTaken[$filter][] = 'warn';
|
|
|
|
|
|
|
|
// Don't do anything else.
|
|
|
|
continue;
|
|
|
|
} else {
|
|
|
|
// We already warned them
|
|
|
|
$session[$warnKey] = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
unset( $actions['warn'] );
|
|
|
|
}
|
|
|
|
|
2018-09-22 10:18:50 +00:00
|
|
|
// Don't show the disallow message if a blocking action is executed
|
|
|
|
if ( count( array_intersect( array_keys( $actions ), AbuseFilter::getDangerousActions() ) ) > 0
|
2020-10-17 13:09:33 +00:00
|
|
|
&& isset( $actions['disallow'] )
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
) {
|
|
|
|
unset( $actions['disallow'] );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find out the max expiry to issue the longest triggered block.
|
|
|
|
// Need to check here since methods like user->getBlock() aren't available
|
2020-10-17 13:09:33 +00:00
|
|
|
if ( isset( $actions['block'] ) ) {
|
|
|
|
$parameters = $actions['block'];
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
|
|
|
|
if ( count( $parameters ) === 3 ) {
|
|
|
|
// New type of filters with custom block
|
|
|
|
if ( $this->user->isAnon() ) {
|
|
|
|
$expiry = $parameters[1];
|
|
|
|
} else {
|
|
|
|
$expiry = $parameters[2];
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Old type with fixed expiry
|
|
|
|
if ( $this->user->isAnon() && $wgAbuseFilterAnonBlockDuration !== null ) {
|
|
|
|
// The user isn't logged in and the anon block duration
|
|
|
|
// doesn't default to $wgAbuseFilterBlockDuration.
|
|
|
|
$expiry = $wgAbuseFilterAnonBlockDuration;
|
|
|
|
} else {
|
|
|
|
$expiry = $wgAbuseFilterBlockDuration;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$currentExpiry = SpecialBlock::parseExpiryInput( $expiry );
|
2019-11-20 17:56:31 +00:00
|
|
|
if ( $maxExpiry === -1 || $currentExpiry > SpecialBlock::parseExpiryInput( $maxExpiry ) ) {
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
// Save the parameters to issue the block with
|
|
|
|
$maxExpiry = $expiry;
|
|
|
|
$blockValues = [
|
|
|
|
AbuseFilter::getFilter( $filter )->af_public_comments,
|
|
|
|
$filter,
|
|
|
|
is_array( $parameters ) && in_array( 'blocktalk', $parameters )
|
|
|
|
];
|
|
|
|
}
|
|
|
|
unset( $actions['block'] );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Do the rest of the actions
|
|
|
|
foreach ( $actions as $action => $info ) {
|
|
|
|
$newMsg = $this->takeConsequenceAction(
|
|
|
|
$action,
|
2020-10-17 13:09:33 +00:00
|
|
|
$info,
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
AbuseFilter::getFilter( $filter )->af_public_comments,
|
|
|
|
$filter
|
|
|
|
);
|
|
|
|
|
|
|
|
if ( $newMsg !== null ) {
|
|
|
|
$messages[] = $newMsg;
|
|
|
|
}
|
|
|
|
$actionsTaken[$filter][] = $action;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Since every filter has been analysed, we now know what the
|
|
|
|
// longest block duration is, so we can issue the block if
|
|
|
|
// maxExpiry has been changed.
|
|
|
|
if ( $maxExpiry !== -1 ) {
|
2019-09-30 10:26:09 +00:00
|
|
|
// @phan-suppress-next-line PhanTypeMismatchArgumentNullable
|
|
|
|
$this->doBlock( $blockValues[0], $blockValues[1], $maxExpiry, $blockValues[2] );
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
$message = [
|
|
|
|
'abusefilter-blocked-display',
|
|
|
|
$blockValues[0],
|
|
|
|
$blockValues[1]
|
|
|
|
];
|
|
|
|
// Manually add the message. If we're here, there is one.
|
|
|
|
$messages[] = $message;
|
2020-01-28 17:43:26 +00:00
|
|
|
// @phan-suppress-next-line PhanTypeMismatchDimAssignment
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
$actionsTaken[$blockValues[1]][] = 'block';
|
|
|
|
}
|
|
|
|
|
|
|
|
return $this->buildStatus( $actionsTaken, $messages );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param string $throttleId
|
|
|
|
* @param string $types
|
2019-12-07 17:20:10 +00:00
|
|
|
* @param int $rateCount
|
|
|
|
* @param int $ratePeriod
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
* @param bool $global
|
|
|
|
* @return bool
|
|
|
|
*/
|
2019-12-07 17:20:10 +00:00
|
|
|
protected function isThrottled(
|
|
|
|
$throttleId,
|
|
|
|
$types,
|
|
|
|
int $rateCount,
|
|
|
|
int $ratePeriod,
|
|
|
|
$global = false
|
|
|
|
) {
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
$stash = MediaWikiServices::getInstance()->getMainObjectStash();
|
|
|
|
$key = $this->throttleKey( $throttleId, $types, $global );
|
2020-01-07 16:52:16 +00:00
|
|
|
$count = (int)$stash->get( $key );
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
|
|
|
|
$logger = LoggerFactory::getInstance( 'AbuseFilter' );
|
|
|
|
$logger->debug( "Got value $count for throttle key $key" );
|
|
|
|
|
2020-01-07 16:52:16 +00:00
|
|
|
$count = $stash->incrWithInit( $key, $ratePeriod );
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
|
|
|
|
if ( $count > $rateCount ) {
|
|
|
|
$logger->debug( "Throttle $key hit value $count -- maximum is $rateCount." );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
$logger->debug( "Throttle $key not hit!" );
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param string $throttleId
|
|
|
|
* @param string $type
|
|
|
|
* @param bool $global
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
protected function throttleKey( $throttleId, $type, $global = false ) {
|
|
|
|
global $wgAbuseFilterIsCentral, $wgAbuseFilterCentralDB;
|
|
|
|
|
|
|
|
$types = explode( ',', $type );
|
|
|
|
|
|
|
|
$identifiers = [];
|
|
|
|
|
|
|
|
foreach ( $types as $subtype ) {
|
|
|
|
$identifiers[] = $this->throttleIdentifier( $subtype );
|
|
|
|
}
|
|
|
|
|
|
|
|
$identifier = sha1( implode( ':', $identifiers ) );
|
|
|
|
|
|
|
|
$cache = MediaWikiServices::getInstance()->getMainWANObjectCache();
|
|
|
|
if ( $global && !$wgAbuseFilterIsCentral ) {
|
|
|
|
return $cache->makeGlobalKey(
|
|
|
|
'abusefilter', 'throttle', $wgAbuseFilterCentralDB, $throttleId, $type, $identifier
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $cache->makeKey( 'abusefilter', 'throttle', $throttleId, $type, $identifier );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param string $type
|
|
|
|
* @return int|string
|
|
|
|
*/
|
|
|
|
protected function throttleIdentifier( $type ) {
|
|
|
|
$request = RequestContext::getMain()->getRequest();
|
|
|
|
|
|
|
|
switch ( $type ) {
|
|
|
|
case 'ip':
|
|
|
|
$identifier = $request->getIP();
|
|
|
|
break;
|
|
|
|
case 'user':
|
|
|
|
$identifier = $this->user->getId();
|
|
|
|
break;
|
|
|
|
case 'range':
|
2020-01-24 17:26:03 +00:00
|
|
|
$identifier = substr( IPUtils::toHex( $request->getIP() ), 0, 4 );
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
break;
|
|
|
|
case 'creationdate':
|
2019-12-07 17:20:10 +00:00
|
|
|
$reg = (int)$this->user->getRegistration();
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
$identifier = $reg - ( $reg % 86400 );
|
|
|
|
break;
|
|
|
|
case 'editcount':
|
|
|
|
// Hack for detecting different single-purpose accounts.
|
2019-12-07 17:20:10 +00:00
|
|
|
$identifier = (int)$this->user->getEditCount();
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
break;
|
|
|
|
case 'site':
|
|
|
|
$identifier = 1;
|
|
|
|
break;
|
|
|
|
case 'page':
|
|
|
|
$identifier = $this->title->getPrefixedText();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
// Should never happen
|
|
|
|
// @codeCoverageIgnoreStart
|
|
|
|
$identifier = 0;
|
|
|
|
// @codeCoverageIgnoreEnd
|
|
|
|
}
|
|
|
|
|
|
|
|
return $identifier;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param string $action
|
|
|
|
* @param array $parameters
|
|
|
|
* @param string $ruleDescription
|
|
|
|
* @param int|string $ruleNumber
|
|
|
|
*
|
|
|
|
* @return array|null a message describing the action that was taken,
|
|
|
|
* or null if no action was taken. The message is given as an array
|
|
|
|
* containing the message key followed by any message parameters.
|
|
|
|
*/
|
|
|
|
protected function takeConsequenceAction( $action, $parameters, $ruleDescription, $ruleNumber ) {
|
2019-09-15 04:09:02 +00:00
|
|
|
global $wgAbuseFilterCustomActionsHandlers, $wgAbuseFilterBlockAutopromoteDuration;
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
|
|
|
|
$message = null;
|
|
|
|
|
|
|
|
switch ( $action ) {
|
|
|
|
case 'disallow':
|
|
|
|
$msg = $parameters[0] ?? 'abusefilter-disallowed';
|
|
|
|
$message = [ $msg, $ruleDescription, $ruleNumber ];
|
|
|
|
break;
|
|
|
|
case 'rangeblock':
|
2019-09-30 10:26:09 +00:00
|
|
|
$this->doRangeBlock( $ruleDescription, $ruleNumber, '1 week' );
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
|
|
|
|
$message = [
|
|
|
|
'abusefilter-blocked-display',
|
|
|
|
$ruleDescription,
|
|
|
|
$ruleNumber
|
|
|
|
];
|
|
|
|
break;
|
|
|
|
case 'degroup':
|
|
|
|
if ( !$this->user->isAnon() ) {
|
2020-10-11 21:35:13 +00:00
|
|
|
$userGroupsManager = MediaWikiServices::getInstance()->getUserGroupManager();
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
// Pull the groups from the VariableHolder, so that they will always be computed.
|
|
|
|
// This allow us to pull the groups from the VariableHolder to undo the degroup
|
|
|
|
// via Special:AbuseFilter/revert.
|
2019-08-11 13:11:20 +00:00
|
|
|
$groups = $this->vars->getVar( 'user_groups', AbuseFilterVariableHolder::GET_LAX );
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
if ( $groups->type !== AFPData::DARRAY ) {
|
|
|
|
// Somehow, the variable wasn't set
|
2020-10-11 21:35:13 +00:00
|
|
|
$groups = $userGroupsManager->getUserEffectiveGroups( $this->user );
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
$this->vars->setVar( 'user_groups', $groups );
|
|
|
|
} else {
|
|
|
|
$groups = $groups->toNative();
|
|
|
|
}
|
|
|
|
$this->vars->setVar( 'user_groups', $groups );
|
|
|
|
|
2020-10-16 14:36:46 +00:00
|
|
|
$implicitGroups = $userGroupsManager->listAllImplicitGroups();
|
|
|
|
$removeGroups = array_diff( $groups, $implicitGroups );
|
|
|
|
foreach ( $removeGroups as $group ) {
|
2020-10-11 21:35:13 +00:00
|
|
|
$userGroupsManager->removeUserFromGroup( $this->user, $group );
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
$message = [
|
|
|
|
'abusefilter-degrouped',
|
|
|
|
$ruleDescription,
|
|
|
|
$ruleNumber
|
|
|
|
];
|
|
|
|
|
|
|
|
// Don't log it if there aren't any groups being removed!
|
2020-10-16 14:36:46 +00:00
|
|
|
if ( !count( $removeGroups ) ) {
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-10-12 11:53:55 +00:00
|
|
|
// TODO Core should provide a logging method
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
$logEntry = new ManualLogEntry( 'rights', 'rights' );
|
|
|
|
$logEntry->setPerformer( AbuseFilter::getFilterUser() );
|
|
|
|
$logEntry->setTarget( $this->user->getUserPage() );
|
|
|
|
$logEntry->setComment(
|
|
|
|
wfMessage(
|
|
|
|
'abusefilter-degroupreason',
|
|
|
|
$ruleDescription,
|
|
|
|
$ruleNumber
|
|
|
|
)->inContentLanguage()->text()
|
|
|
|
);
|
|
|
|
$logEntry->setParameters( [
|
2020-10-16 14:36:46 +00:00
|
|
|
'4::oldgroups' => $removeGroups,
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
'5::newgroups' => []
|
|
|
|
] );
|
|
|
|
$logEntry->publish( $logEntry->insert() );
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
case 'blockautopromote':
|
|
|
|
if ( !$this->user->isAnon() ) {
|
2019-09-15 04:09:02 +00:00
|
|
|
$duration = $wgAbuseFilterBlockAutopromoteDuration * 86400;
|
2020-10-21 14:18:08 +00:00
|
|
|
$store = AbuseFilterServices::getBlockAutopromoteStore();
|
|
|
|
$blocked = $store->blockAutoPromote(
|
2019-07-06 23:35:03 +00:00
|
|
|
$this->user,
|
2018-07-16 12:10:36 +00:00
|
|
|
wfMessage(
|
|
|
|
'abusefilter-blockautopromotereason',
|
|
|
|
$ruleDescription,
|
|
|
|
$ruleNumber
|
2019-09-15 04:09:02 +00:00
|
|
|
)->inContentLanguage()->text(),
|
|
|
|
$duration
|
2018-07-16 12:10:36 +00:00
|
|
|
);
|
|
|
|
|
2019-08-10 13:17:20 +00:00
|
|
|
if ( $blocked ) {
|
|
|
|
$message = [
|
|
|
|
'abusefilter-autopromote-blocked',
|
|
|
|
$ruleDescription,
|
2019-09-15 04:09:02 +00:00
|
|
|
$ruleNumber,
|
|
|
|
$duration
|
2019-08-10 13:17:20 +00:00
|
|
|
];
|
|
|
|
}
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'block':
|
|
|
|
// Do nothing, handled at the end of executeFilterActions. Here for completeness.
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'tag':
|
|
|
|
// Mark with a tag on recentchanges.
|
2020-10-13 16:01:18 +00:00
|
|
|
$this->changeTagger->addTags( $this->getSpecsForTagger(), $parameters );
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if ( isset( $wgAbuseFilterCustomActionsHandlers[$action] ) ) {
|
|
|
|
$customFunction = $wgAbuseFilterCustomActionsHandlers[$action];
|
|
|
|
if ( is_callable( $customFunction ) ) {
|
|
|
|
$msg = call_user_func(
|
|
|
|
$customFunction,
|
|
|
|
$action,
|
|
|
|
$parameters,
|
|
|
|
$this->title,
|
|
|
|
$this->vars,
|
|
|
|
$ruleDescription,
|
|
|
|
$ruleNumber
|
|
|
|
);
|
|
|
|
}
|
|
|
|
if ( isset( $msg ) ) {
|
|
|
|
$message = [ $msg ];
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$logger = LoggerFactory::getInstance( 'AbuseFilter' );
|
|
|
|
$logger->warning( "Unrecognised action $action" );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $message;
|
|
|
|
}
|
|
|
|
|
2019-09-30 10:26:09 +00:00
|
|
|
/**
|
|
|
|
* @param string $ruleDesc
|
|
|
|
* @param string|int $ruleNumber
|
|
|
|
* @param string $expiry
|
|
|
|
*/
|
|
|
|
private function doRangeBlock( $ruleDesc, $ruleNumber, $expiry ) {
|
|
|
|
global $wgAbuseFilterRangeBlockSize, $wgBlockCIDRLimit;
|
|
|
|
|
|
|
|
$ip = RequestContext::getMain()->getRequest()->getIP();
|
|
|
|
$type = IPUtils::isIPv6( $ip ) ? 'IPv6' : 'IPv4';
|
|
|
|
$CIDRsize = max( $wgAbuseFilterRangeBlockSize[$type], $wgBlockCIDRLimit[$type] );
|
|
|
|
$blockCIDR = $ip . '/' . $CIDRsize;
|
|
|
|
|
|
|
|
$target = IPUtils::sanitizeRange( $blockCIDR );
|
|
|
|
$autoblock = false;
|
|
|
|
$this->doBlockInternal( $ruleDesc, $ruleNumber, $target, $expiry, $autoblock, false );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param string $ruleDesc
|
|
|
|
* @param string|int $ruleNumber
|
|
|
|
* @param string $expiry
|
|
|
|
* @param bool $preventsTalk
|
|
|
|
*/
|
|
|
|
private function doBlock( $ruleDesc, $ruleNumber, $expiry, $preventsTalk ) {
|
|
|
|
$target = $this->user->getName();
|
|
|
|
$autoblock = true;
|
|
|
|
$this->doBlockInternal( $ruleDesc, $ruleNumber, $target, $expiry, $autoblock, $preventsTalk );
|
|
|
|
}
|
|
|
|
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
/**
|
|
|
|
* Perform a block by the AbuseFilter system user
|
2019-09-30 10:26:09 +00:00
|
|
|
* @param string $ruleDesc
|
|
|
|
* @param int|string $ruleNumber
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
* @param string $target
|
|
|
|
* @param string $expiry
|
|
|
|
* @param bool $isAutoBlock
|
|
|
|
* @param bool $preventEditOwnUserTalk
|
|
|
|
*/
|
2019-09-30 10:26:09 +00:00
|
|
|
private function doBlockInternal(
|
|
|
|
$ruleDesc,
|
|
|
|
$ruleNumber,
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
$target,
|
|
|
|
$expiry,
|
|
|
|
$isAutoBlock,
|
2019-09-30 10:26:09 +00:00
|
|
|
$preventEditOwnUserTalk
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
) {
|
2020-10-11 21:35:13 +00:00
|
|
|
$blockUserFactory = MediaWikiServices::getInstance()->getBlockUserFactory();
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
$filterUser = AbuseFilter::getFilterUser();
|
|
|
|
$reason = wfMessage(
|
|
|
|
'abusefilter-blockreason',
|
2019-09-30 10:26:09 +00:00
|
|
|
$ruleDesc, $ruleNumber
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
)->inContentLanguage()->text();
|
|
|
|
|
2020-10-11 21:35:13 +00:00
|
|
|
$blockUserFactory->newBlockUser(
|
|
|
|
$target,
|
|
|
|
$filterUser,
|
|
|
|
$expiry,
|
|
|
|
$reason,
|
|
|
|
[
|
|
|
|
'isHardBlock' => false,
|
|
|
|
'isAutoblocking' => $isAutoBlock,
|
|
|
|
'isCreateAccountBlocked' => true,
|
|
|
|
'isUserTalkEditBlocked' => $preventEditOwnUserTalk
|
|
|
|
]
|
|
|
|
)->placeBlockUnsafe();
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Constructs a Status object as returned by executeFilterActions() from the list of
|
|
|
|
* actions taken and the corresponding list of messages.
|
|
|
|
*
|
|
|
|
* @param array[] $actionsTaken associative array mapping each filter to the list if
|
|
|
|
* actions taken because of that filter.
|
|
|
|
* @param array[] $messages a list of arrays, where each array contains a message key
|
|
|
|
* followed by any message parameters.
|
|
|
|
*
|
|
|
|
* @return Status
|
|
|
|
*/
|
|
|
|
protected function buildStatus( array $actionsTaken, array $messages ) : Status {
|
|
|
|
$status = Status::newGood( $actionsTaken );
|
|
|
|
|
|
|
|
foreach ( $messages as $msg ) {
|
|
|
|
$status->fatal( ...$msg );
|
|
|
|
}
|
|
|
|
|
|
|
|
return $status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates a template to use for logging taken actions
|
|
|
|
*
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
protected function buildLogTemplate() : array {
|
|
|
|
global $wgAbuseFilterLogIP;
|
|
|
|
|
|
|
|
$request = RequestContext::getMain()->getRequest();
|
|
|
|
// If $this->user isn't safe to load (e.g. a failure during
|
|
|
|
// AbortAutoAccount), create a dummy anonymous user instead.
|
|
|
|
$user = $this->user->isSafeToLoad() ? $this->user : new User;
|
|
|
|
// Create a template
|
|
|
|
$logTemplate = [
|
|
|
|
'afl_user' => $user->getId(),
|
|
|
|
'afl_user_text' => $user->getName(),
|
|
|
|
'afl_timestamp' => wfGetDB( DB_REPLICA )->timestamp(),
|
|
|
|
'afl_namespace' => $this->title->getNamespace(),
|
|
|
|
'afl_title' => $this->title->getDBkey(),
|
2020-03-06 16:21:51 +00:00
|
|
|
'afl_action' => $this->action,
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
'afl_ip' => $wgAbuseFilterLogIP ? $request->getIP() : ''
|
|
|
|
];
|
|
|
|
// Hack to avoid revealing IPs of people creating accounts
|
2020-03-06 16:21:51 +00:00
|
|
|
if (
|
|
|
|
!$user->getId() &&
|
|
|
|
( $this->action === 'createaccount' || $this->action === 'autocreateaccount' )
|
|
|
|
) {
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
$logTemplate['afl_user_text'] = $this->vars->getVar( 'accountname' )->toString();
|
|
|
|
}
|
|
|
|
return $logTemplate;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create and publish log entries for taken actions
|
|
|
|
*
|
|
|
|
* @param array[] $actionsTaken
|
|
|
|
* @todo Split this method
|
|
|
|
*/
|
|
|
|
protected function addLogEntries( array $actionsTaken ) {
|
|
|
|
$dbw = wfGetDB( DB_MASTER );
|
|
|
|
$logTemplate = $this->buildLogTemplate();
|
|
|
|
$centralLogTemplate = [
|
2020-01-08 13:33:10 +00:00
|
|
|
'afl_wiki' => WikiMap::getCurrentWikiDbDomain()->getId(),
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
];
|
|
|
|
|
|
|
|
$logRows = [];
|
|
|
|
$centralLogRows = [];
|
|
|
|
$loggedLocalFilters = [];
|
|
|
|
$loggedGlobalFilters = [];
|
|
|
|
|
|
|
|
foreach ( $actionsTaken as $filter => $actions ) {
|
|
|
|
list( $filterID, $global ) = AbuseFilter::splitGlobalName( $filter );
|
|
|
|
$thisLog = $logTemplate;
|
|
|
|
$thisLog['afl_filter'] = $filter;
|
|
|
|
$thisLog['afl_actions'] = implode( ',', $actions );
|
|
|
|
|
|
|
|
// Don't log if we were only throttling.
|
|
|
|
if ( $thisLog['afl_actions'] !== 'throttle' ) {
|
|
|
|
$logRows[] = $thisLog;
|
|
|
|
// Global logging
|
|
|
|
if ( $global ) {
|
|
|
|
$centralLog = $thisLog + $centralLogTemplate;
|
|
|
|
$centralLog['afl_filter'] = $filterID;
|
|
|
|
$centralLog['afl_title'] = $this->title->getPrefixedText();
|
|
|
|
$centralLog['afl_namespace'] = 0;
|
|
|
|
|
|
|
|
$centralLogRows[] = $centralLog;
|
|
|
|
$loggedGlobalFilters[] = $filterID;
|
|
|
|
} else {
|
|
|
|
$loggedLocalFilters[] = $filter;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( !count( $logRows ) ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Only store the var dump if we're actually going to add log rows.
|
|
|
|
$varDump = AbuseFilter::storeVarDump( $this->vars );
|
2019-01-06 14:20:10 +00:00
|
|
|
$varDump = "tt:$varDump";
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
|
|
|
|
$localLogIDs = [];
|
|
|
|
global $wgAbuseFilterNotifications, $wgAbuseFilterNotificationsPrivate;
|
|
|
|
foreach ( $logRows as $data ) {
|
|
|
|
$data['afl_var_dump'] = $varDump;
|
|
|
|
$dbw->insert( 'abuse_filter_log', $data, __METHOD__ );
|
|
|
|
$localLogIDs[] = $data['afl_id'] = $dbw->insertId();
|
|
|
|
// Give grep a chance to find the usages:
|
|
|
|
// logentry-abusefilter-hit
|
|
|
|
$entry = new ManualLogEntry( 'abusefilter', 'hit' );
|
|
|
|
// Construct a user object
|
|
|
|
$user = User::newFromId( $data['afl_user'] );
|
|
|
|
$user->setName( $data['afl_user_text'] );
|
|
|
|
$entry->setPerformer( $user );
|
|
|
|
$entry->setTarget( $this->title );
|
|
|
|
// Additional info
|
|
|
|
$entry->setParameters( [
|
|
|
|
'action' => $data['afl_action'],
|
|
|
|
'filter' => $data['afl_filter'],
|
|
|
|
'actions' => $data['afl_actions'],
|
|
|
|
'log' => $data['afl_id'],
|
|
|
|
] );
|
|
|
|
|
|
|
|
// Send data to CheckUser if installed and we
|
|
|
|
// aren't already sending a notification to recentchanges
|
|
|
|
if ( ExtensionRegistry::getInstance()->isLoaded( 'CheckUser' )
|
|
|
|
&& strpos( $wgAbuseFilterNotifications, 'rc' ) === false
|
|
|
|
) {
|
2020-08-13 12:15:59 +00:00
|
|
|
global $wgCheckUserLogAdditionalRights;
|
|
|
|
$wgCheckUserLogAdditionalRights[] = 'abusefilter-view';
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
$rc = $entry->getRecentChange();
|
|
|
|
CheckUserHooks::updateCheckUserData( $rc );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( $wgAbuseFilterNotifications !== false ) {
|
|
|
|
list( $filterID, $global ) = AbuseFilter::splitGlobalName( $data['afl_filter'] );
|
|
|
|
if ( AbuseFilter::filterHidden( $filterID, $global ) && !$wgAbuseFilterNotificationsPrivate ) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
$this->publishEntry( $dbw, $entry, $wgAbuseFilterNotifications );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$method = __METHOD__;
|
|
|
|
|
|
|
|
if ( count( $loggedLocalFilters ) ) {
|
|
|
|
// Update hit-counter.
|
|
|
|
$dbw->onTransactionPreCommitOrIdle(
|
|
|
|
function () use ( $dbw, $loggedLocalFilters, $method ) {
|
|
|
|
$dbw->update( 'abuse_filter',
|
|
|
|
[ 'af_hit_count=af_hit_count+1' ],
|
|
|
|
[ 'af_id' => $loggedLocalFilters ],
|
|
|
|
$method
|
|
|
|
);
|
2020-06-06 23:54:41 +00:00
|
|
|
},
|
|
|
|
$method
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
$globalLogIDs = [];
|
|
|
|
|
|
|
|
// Global stuff
|
|
|
|
if ( count( $loggedGlobalFilters ) ) {
|
|
|
|
$this->vars->computeDBVars();
|
|
|
|
$globalVarDump = AbuseFilter::storeVarDump( $this->vars, true );
|
2019-01-06 14:20:10 +00:00
|
|
|
$globalVarDump = "tt:$globalVarDump";
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
foreach ( $centralLogRows as $index => $data ) {
|
|
|
|
$centralLogRows[$index]['afl_var_dump'] = $globalVarDump;
|
|
|
|
}
|
|
|
|
|
|
|
|
$fdb = AbuseFilter::getCentralDB( DB_MASTER );
|
|
|
|
|
|
|
|
foreach ( $centralLogRows as $row ) {
|
|
|
|
$fdb->insert( 'abuse_filter_log', $row, __METHOD__ );
|
|
|
|
$globalLogIDs[] = $fdb->insertId();
|
|
|
|
}
|
|
|
|
|
|
|
|
$fdb->onTransactionPreCommitOrIdle(
|
|
|
|
function () use ( $fdb, $loggedGlobalFilters, $method ) {
|
|
|
|
$fdb->update( 'abuse_filter',
|
|
|
|
[ 'af_hit_count=af_hit_count+1' ],
|
|
|
|
[ 'af_id' => $loggedGlobalFilters ],
|
|
|
|
$method
|
|
|
|
);
|
2020-06-06 23:54:41 +00:00
|
|
|
},
|
|
|
|
$method
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
AbuseFilter::$logIds[ $this->title->getPrefixedText() ] = [
|
|
|
|
'local' => $localLogIDs,
|
|
|
|
'global' => $globalLogIDs
|
|
|
|
];
|
|
|
|
|
|
|
|
$this->checkEmergencyDisable( $loggedLocalFilters );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Like LogEntry::publish, but doesn't require an ID (which we don't have) and skips the
|
|
|
|
* tagging part
|
|
|
|
*
|
|
|
|
* @param IDatabase $dbw To cancel the callback if the log insertion fails
|
|
|
|
* @param ManualLogEntry $entry
|
|
|
|
* @param string $to One of 'udp', 'rc' and 'rcandudp'
|
|
|
|
*/
|
|
|
|
private function publishEntry( IDatabase $dbw, ManualLogEntry $entry, $to ) {
|
|
|
|
DeferredUpdates::addCallableUpdate(
|
|
|
|
function () use ( $entry, $to ) {
|
|
|
|
$rc = $entry->getRecentChange();
|
|
|
|
|
|
|
|
if ( $to === 'rc' || $to === 'rcandudp' ) {
|
|
|
|
$rc->save( $rc::SEND_NONE );
|
|
|
|
}
|
|
|
|
if ( $to === 'udp' || $to === 'rcandudp' ) {
|
|
|
|
$rc->notifyRCFeeds();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
DeferredUpdates::POSTSEND,
|
|
|
|
$dbw
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Determine whether a filter must be throttled, i.e. its potentially dangerous
|
|
|
|
* actions must be disabled.
|
|
|
|
*
|
|
|
|
* @param string[] $filters The filters to check
|
|
|
|
*/
|
|
|
|
protected function checkEmergencyDisable( array $filters ) {
|
|
|
|
// @ToDo this is an amount between 1 and AbuseFilterProfileActionsCap, which means that the
|
|
|
|
// reliability of this number may strongly vary. We should instead use a fixed one.
|
2020-09-20 22:31:41 +00:00
|
|
|
$groupProfile = $this->filterProfiler->getGroupProfile( $this->group );
|
2015-04-01 04:51:16 +00:00
|
|
|
$totalActions = $groupProfile['total'];
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
|
|
|
|
foreach ( $filters as $filter ) {
|
|
|
|
$threshold = AbuseFilter::getEmergencyValue( 'threshold', $this->group );
|
|
|
|
$hitCountLimit = AbuseFilter::getEmergencyValue( 'count', $this->group );
|
|
|
|
$maxAge = AbuseFilter::getEmergencyValue( 'age', $this->group );
|
|
|
|
|
2020-09-20 22:31:41 +00:00
|
|
|
$filterProfile = $this->filterProfiler->getFilterProfile( $filter );
|
|
|
|
$matchCount = ( $filterProfile['matches'] ?? 0 ) + 1;
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
|
|
|
|
// Figure out if the filter is subject to being throttled.
|
2019-12-07 17:20:10 +00:00
|
|
|
$filterAge = (int)wfTimestamp( TS_UNIX, AbuseFilter::getFilter( $filter )->af_timestamp );
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
$exemptTime = $filterAge + $maxAge;
|
|
|
|
|
|
|
|
if ( $totalActions && $exemptTime > time() && $matchCount > $hitCountLimit &&
|
|
|
|
( $matchCount / $totalActions ) > $threshold
|
|
|
|
) {
|
|
|
|
// More than $wgAbuseFilterEmergencyDisableCount matches, constituting more than
|
|
|
|
// $threshold (a fraction) of last few edits. Disable it.
|
|
|
|
DeferredUpdates::addUpdate(
|
|
|
|
new AutoCommitUpdate(
|
|
|
|
wfGetDB( DB_MASTER ),
|
|
|
|
__METHOD__,
|
|
|
|
function ( IDatabase $dbw, $fname ) use ( $filter ) {
|
|
|
|
$dbw->update(
|
|
|
|
'abuse_filter',
|
|
|
|
[ 'af_throttled' => 1 ],
|
|
|
|
[ 'af_id' => $filter ],
|
|
|
|
$fname
|
|
|
|
);
|
|
|
|
}
|
|
|
|
)
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2020-10-13 16:01:18 +00:00
|
|
|
* @return array
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
*/
|
2020-10-13 16:01:18 +00:00
|
|
|
private function getSpecsForTagger() : array {
|
|
|
|
return [
|
|
|
|
'action' => $this->action,
|
|
|
|
'username' => $this->user->getName(),
|
|
|
|
'target' => $this->title,
|
|
|
|
'accountname' => $this->vars->getVar(
|
|
|
|
'accountname',
|
|
|
|
AbuseFilterVariableHolder::GET_BC
|
|
|
|
)->toNative()
|
|
|
|
];
|
Add a new class for methods related to running filters
Currently we strongly abuse (pardon the pun) the AbuseFilter class: its
purpose should be to hold static functions intended as generic utility
functions (e.g. to format messages, determine whether a filter is global
etc.), but we actually use it for all methods related to running filters.
This patch creates a new class, AbuseFilterRunner, containing all such
methods, which have been made non-static. This leads to several
improvements (also for related methods and the parser), and opens the
way to further improve the code.
Aside from making the code prettier, less global and easier to test,
this patch could also produce a performance improvement, although I
don't have tools to measure that.
Also note that many public methods have been removed, and almost any of
them has been made protected; a couple of them (the ones used from outside)
are left for back-compat, and will be removed in the future.
Change-Id: I2eab2e50356eeb5224446ee2d0df9c787ae95b80
2018-12-07 17:46:02 +00:00
|
|
|
}
|
|
|
|
}
|