Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
86.96% covered (warning)
86.96%
20 / 23
33.33% covered (danger)
33.33%
1 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
ParameterizedPassword
86.96% covered (warning)
86.96%
20 / 23
33.33% covered (danger)
33.33%
1 / 3
9.18
0.00% covered (danger)
0.00%
0 / 1
 parseHash
86.67% covered (warning)
86.67%
13 / 15
0.00% covered (danger)
0.00%
0 / 1
5.06
 needsUpdate
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 toString
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
3
 getDelimiter
n/a
0 / 0
n/a
0 / 0
0
 getDefaultParams
n/a
0 / 0
n/a
0 / 0
0
1<?php
2/**
3 * Implements the ParameterizedPassword class for the MediaWiki software.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * http://www.gnu.org/copyleft/gpl.html
19 *
20 * @file
21 */
22
23declare( strict_types = 1 );
24
25/**
26 * Helper class for password hash types that have a delimited set of parameters
27 * inside of the hash.
28 *
29 * All passwords are in the form of :<TYPE>:... as explained in the main Password
30 * class. This class is for hashes in the form of :<TYPE>:<PARAM1>:<PARAM2>:... where
31 * <PARAM1>, <PARAM2>, etc. are parameters that determine how the password was hashed.
32 * Of course, the internal delimiter (which is : by convention and default), can be
33 * changed by overriding the ParameterizedPassword::getDelimiter() function.
34 *
35 * This class requires overriding an additional function: ParameterizedPassword::getDefaultParams().
36 * See the function description for more details on the implementation.
37 *
38 * @since 1.24
39 */
40abstract class ParameterizedPassword extends Password {
41    /**
42     * Named parameters that have default values for this password type
43     * @var array
44     */
45    protected $params = [];
46
47    /**
48     * Extra arguments that were found in the hash. This may or may not make
49     * the hash invalid.
50     * @var string[]
51     */
52    protected $args = [];
53
54    /**
55     * @inheritDoc
56     */
57    protected function parseHash( ?string $hash ): void {
58        parent::parseHash( $hash );
59
60        if ( $hash === null ) {
61            $this->params = $this->getDefaultParams();
62            return;
63        }
64
65        $parts = explode( $this->getDelimiter(), $hash );
66        $paramKeys = array_keys( $this->getDefaultParams() );
67
68        if ( count( $parts ) < count( $paramKeys ) ) {
69            throw new PasswordError( 'Hash is missing required parameters.' );
70        }
71
72        if ( $paramKeys ) {
73            $this->args = array_splice( $parts, count( $paramKeys ) );
74            $this->params = array_combine( $paramKeys, $parts );
75        } else {
76            $this->args = $parts;
77        }
78
79        if ( $this->args ) {
80            $this->hash = array_pop( $this->args );
81        } else {
82            $this->hash = null;
83        }
84    }
85
86    public function needsUpdate(): bool {
87        return $this->params !== $this->getDefaultParams();
88    }
89
90    public function toString(): string {
91        $str = ':' . $this->config['type'] . ':';
92
93        if ( count( $this->params ) || count( $this->args ) ) {
94            $str .= implode( $this->getDelimiter(), array_merge( $this->params, $this->args ) );
95            $str .= $this->getDelimiter();
96        }
97
98        $res = $str . $this->hash;
99        $this->assertIsSafeSize( $res );
100        return $res;
101    }
102
103    /**
104     * Returns the delimiter for the parameters inside the hash
105     *
106     * @return string
107     */
108    abstract protected function getDelimiter(): string;
109
110    /**
111     * Return an ordered array of default parameters for this password hash
112     *
113     * The keys should be the parameter names and the values should be the default
114     * values. Additionally, the order of the array should be the order in which they
115     * appear in the hash.
116     *
117     * When parsing a password hash, the constructor will split the hash based on
118     * the delimiter, and consume as many parts as it can, matching each to a parameter
119     * in this list. Once all the parameters have been filled, all remaining parts will
120     * be considered extra arguments, except, of course, for the very last part, which
121     * is the hash itself.
122     *
123     * @return array
124     */
125    abstract protected function getDefaultParams(): array;
126}