]>
git.agnieray.net Git - galette.git/blob - galette/lib/Galette/Util/Password.php
3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
10 * Copyright © 2020-2023 The Galette Team
12 * This file is part of Galette (http://galette.tuxfamily.org).
14 * Galette is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation, either version 3 of the License, or
17 * (at your option) any later version.
19 * Galette is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with Galette. If not, see <http://www.gnu.org/licenses/>.
30 * @author Johan Cwiklinski <johan@x-tnd.be>
31 * @copyright 2020-2023 The Galette Team
32 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
33 * @link http://galette.tuxfamily.org
34 * @since Available since 0.9.4
37 namespace Galette\Util
;
40 use Galette\Core\Preferences
;
41 use Galette\Entity\Adherent
;
49 * @author Johan Cwiklinski <johan@x-tnd.be>
50 * @copyright 2020-2023 The Galette Team
51 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
52 * @link http://galette.tuxfamily.org
53 * @see https://github.com/rollerworks/PasswordStrengthValidator
54 * @since Available since 0.9.4
58 protected $preferences;
59 protected $errors = [];
60 protected $strength_errors = [];
61 protected $strength = null;
62 protected $blacklisted = false;
63 protected $personal_infos = [];
68 * @param Preferences $prefs Preferences instance
70 public function __construct(Preferences
$prefs)
72 $this->preferences
= $prefs;
76 * Does password suits requirements?
78 * @param string $password Password to test
82 public function isValid($password)
84 $this->errors
= []; //reset
86 if ($this->isBlacklisted($password)) {
87 $this->errors
[] = _T('Password is blacklisted!');
88 //no need here to check lenght/strength
93 if (mb_strlen($password) < $this->preferences
->pref_password_length
) {
94 $this->errors
[] = str_replace(
95 ['%lenght', '%count'],
96 [$this->preferences
->pref_password_length
, mb_strlen($password)],
97 _T('Too short (%lenght characters minimum, %count found)')
101 $this->strength
= $this->calculateStrength($password);
102 if ($this->strength
< $this->preferences
->pref_password_strength
) {
103 $this->errors
= array_merge($this->errors
, $this->strength_errors
);
106 if ($this->preferences
->pref_password_strength
> Preferences
::PWD_NONE
) {
107 //check also against personal information
108 if (in_array(mb_strtolower($password), $this->personal_infos
)) {
109 $this->errors
[] = _T('Do not use any of your personal information as password!');
113 return (count($this->errors
) === 0);
117 * Is password blacklisted?
119 * @param string $password Password to check
123 public function isBlacklisted($password)
125 if (!$this->preferences
->pref_password_blacklist
) {
130 mb_strtolower($password),
131 $this->getBlacklistedPasswords()
136 * Calculate pasword strength
138 * @param string $password Password to check
142 public function calculateStrength($password)
146 if (preg_match('/\p{L}/u', $password)) {
149 if (!preg_match('/\p{Ll}/u', $password)) {
150 $this->strength_errors
[] = _T('Does not contains lowercase letters');
151 } elseif (preg_match('/\p{Lu}/u', $password)) {
154 $this->strength_errors
[] = _T('Does not contains uppercase letters');
157 $this->strength_errors
[] = _T('Does not contains letters');
160 if (preg_match('/\p{N}/u', $password)) {
163 $this->strength_errors
[] = _T('Does not contains numbers');
166 if (preg_match('/[^\p{L}\p{N}]/u', $password)) {
169 $this->strength_errors
[] = _T('Does not contains special characters');
176 * Get current strength
180 public function getStrenght()
182 return $this->strength
;
190 public function getErrors()
192 return $this->errors
;
196 * Get strength errors
200 public function getStrenghtErrors()
202 return $this->strength_errors
;
206 * Build password blacklist
210 public function getBlacklistedPasswords()
212 $file = GALETTE_DATA_PATH
. '/blacklist.txt';
214 if (!file_exists($file)) {
215 //copy default provided list
216 $worst500 = explode(PHP_EOL
, file_get_contents(GALETTE_ROOT
. 'includes/fields_defs/pass_blacklist'));
217 file_put_contents($file, implode(PHP_EOL
, $worst500));
220 $blacklist = explode(PHP_EOL
, file_get_contents($file));
221 $blacklist[] = 'galette'; //that one should always be blacklisted... :)
227 * Add personal information to check against
229 * @param array $infos Personal information
233 public function addPersonalInformation(array $infos)
235 $this->personal_infos
= array_merge(
236 $this->personal_infos
,
237 array_map('mb_strtolower', array_values($infos))
239 return $this->personal_infos
;
243 * Set member and calculate personal information to blacklist
245 * @param Adherent $adh Adherent instance
249 public function setAdherent(Adherent
$adh)
254 $adh->birthdate ??
'', //locale formatted
255 $adh->rbirthdate
, //raw
262 //handle date formats
263 $bdate = \DateTime
::createFromFormat('Y-m-d', $adh->rbirthdate
);
264 if ($bdate !== false) {
265 $infos[] = $bdate->format('Y-m-d'); //standard format
266 //TRANS: see https://www.php.net/manual/datetime.format.php
267 $infos[] = $bdate->format(__('Y-m-d')); //localized format
268 $infos[] = $bdate->format('Ymd');
269 $infos[] = $bdate->format('dmY');
270 $infos[] = $bdate->format('Ydm');
273 //some possible combinations
274 foreach ([$adh->surname
, $adh->nickname
, $adh->login
] as $surname) {
275 if ($surname === null) {
278 $infos[] = mb_substr($surname, 0, 1) . $adh->name
;
279 $infos[] = $adh->name
. mb_substr($surname, 0, 1);
280 $infos[] = $surname . $adh->name
;
281 $infos[] = $adh->name
. $surname;
284 $parts = preg_split('/[- _]/', $surname);
285 if (count($parts) > 1) {
287 foreach ($parts as $part) {
288 $letters .= mb_substr($part, 0, 1);
290 $infos[] = $letters . $adh->name
;
291 $infos[] = $adh->name
. $letters;
295 $this->addPersonalInformation($infos);