Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 32
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
FixWrongPasswordPrefixes
0.00% covered (danger)
0.00%
0 / 32
0.00% covered (danger)
0.00%
0 / 3
56
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 getUpdateKey
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 doDBUpdates
0.00% covered (danger)
0.00%
0 / 29
0.00% covered (danger)
0.00%
0 / 1
30
1<?php
2/**
3 * @license GPL-2.0-or-later
4 * @file
5 * @ingroup Maintenance
6 */
7
8use MediaWiki\Maintenance\LoggedUpdateMaintenance;
9use Wikimedia\Rdbms\IExpression;
10use Wikimedia\Rdbms\LikeValue;
11
12// @codeCoverageIgnoreStart
13require_once __DIR__ . '/Maintenance.php';
14// @codeCoverageIgnoreEnd
15
16/**
17 * An error in a previous version of MediaWiki caused B type passwords to be written with
18 * an :A: prefix to the database. This script corrects this.
19 *
20 * @since 1.44
21 * @ingroup Maintenance
22 */
23class FixWrongPasswordPrefixes extends LoggedUpdateMaintenance {
24    public function __construct() {
25        parent::__construct();
26        $this->setBatchSize( 100 );
27    }
28
29    /** @inheritDoc */
30    protected function getUpdateKey() {
31        return __CLASS__;
32    }
33
34    /** @inheritDoc */
35    protected function doDBUpdates() {
36        $dbw = $this->getPrimaryDB();
37        $batchSize = $this->getBatchSize();
38        $minUserId = 0;
39
40        while ( true ) {
41            $res = $dbw->newSelectQueryBuilder()
42                ->select( [ 'user_id', 'user_password' ] )
43                ->from( 'user' )
44                ->where( $dbw->expr( 'user_id', '>', $minUserId ) )
45                ->andWhere(
46                    $dbw->expr( 'user_password', IExpression::LIKE, new LikeValue( ':A:', $dbw->anyString() ) )
47                )
48                ->orderBy( 'user_id' )
49                ->limit( $batchSize )
50                ->caller( __METHOD__ )
51                ->fetchResultSet();
52
53            if ( $res->numRows() === 0 ) {
54                break;
55            }
56
57            foreach ( $res as $row ) {
58                $passwordHash = substr( $row->user_password, 3 );
59                if ( strpos( $passwordHash, ':' ) > 0 ) {
60                    $dbw->newUpdateQueryBuilder()
61                        ->update( 'user' )
62                        ->set( [ 'user_password' => ':B:' . $passwordHash ] )
63                        ->where( [ 'user_id' => $row->user_id ] )
64                        ->caller( __METHOD__ )
65                        ->execute();
66                }
67
68                $minUserId = $row->user_id;
69            }
70        }
71
72        $this->output( "Wrongly prefixed user password hashes, if present, have been fixed.\n" );
73        return true;
74    }
75}
76
77// @codeCoverageIgnoreStart
78$maintClass = FixWrongPasswordPrefixes::class;
79require_once RUN_MAINTENANCE_IF_MAIN;
80// @codeCoverageIgnoreEnd