Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
97.14% covered (success)
97.14%
34 / 35
50.00% covered (danger)
50.00%
1 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
CheckSignatures
97.14% covered (success)
97.14%
34 / 35
50.00% covered (danger)
50.00%
1 / 2
7
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 execute
96.88% covered (success)
96.88%
31 / 32
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2/**
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 * http://www.gnu.org/copyleft/gpl.html
17 *
18 * @file
19 * @ingroup Maintenance
20 */
21
22use MediaWiki\Maintenance\Maintenance;
23use MediaWiki\Parser\ParserOptions;
24
25// @codeCoverageIgnoreStart
26require_once __DIR__ . '/Maintenance.php';
27// @codeCoverageIgnoreEnd
28
29/**
30 * Maintenance script to list users with invalid signatures.
31 *
32 * @ingroup Maintenance
33 */
34class CheckSignatures extends Maintenance {
35
36    public function __construct() {
37        parent::__construct();
38        $this->addDescription( 'List users with invalid signatures' );
39        $this->setBatchSize( 1000 );
40    }
41
42    public function execute() {
43        $dbr = $this->getReplicaDB();
44        $userFactory = $this->getServiceContainer()->getUserIdentityLookup();
45        $userOptions = $this->getServiceContainer()->getUserOptionsLookup();
46        $signatureValidatorFactory = $this->getServiceContainer()->getSignatureValidatorFactory();
47        $contentLanguage = $this->getServiceContainer()->getContentLanguage();
48
49        $count = 0;
50        $maxUserId = 0;
51        do {
52            // List users who may have a signature that needs validation
53            $res = $dbr->newSelectQueryBuilder()
54                ->from( 'user_properties' )
55                ->select( 'up_user' )
56                ->where( [ 'up_property' => 'fancysig' ] )
57                ->andWhere( $dbr->expr( 'up_user', '>', $maxUserId ) )
58                ->orderBy( [ 'up_property', 'up_user' ] )
59                ->limit( $this->getBatchSize() )
60                ->caller( __METHOD__ )
61                ->fetchResultSet();
62
63            foreach ( $res as $row ) {
64                // Double-check effective preferences and check validation
65                $user = $userFactory->getUserIdentityByUserId( $row->up_user );
66                if ( !$user ) {
67                    continue;
68                }
69                $signature = $userOptions->getOption( $user, 'nickname' );
70                $useFancySig = $userOptions->getBoolOption( $user, 'fancysig' );
71                if ( $useFancySig && $signature !== '' ) {
72                    $parserOpts = new ParserOptions( $user, $contentLanguage );
73                    $validator = $signatureValidatorFactory->newSignatureValidator( $user, null, $parserOpts );
74                    $signatureErrors = $validator->validateSignature( $signature );
75                    if ( $signatureErrors ) {
76                        $count++;
77                        $this->output( $user->getName() . "\n" );
78                    }
79                }
80
81                $maxUserId = $row->up_user;
82            }
83        } while ( $res->numRows() );
84
85        $this->output( "-- $count invalid signatures --\n" );
86    }
87}
88
89// @codeCoverageIgnoreStart
90$maintClass = CheckSignatures::class;
91require_once RUN_MAINTENANCE_IF_MAIN;
92// @codeCoverageIgnoreEnd