"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "mrbs-1.9.4/web/lib/MRBS/Auth/AuthDb.php" between
mrbs-1.9.4.tar.gz and mrbs-1.10.0.tar.gz

About: MRBS is a web application for booking meeting rooms or other resources (using PHP and MySQL/pgsql).

AuthDb.php  (mrbs-1.9.4):AuthDb.php  (mrbs-1.10.0)
<?php <?php
namespace MRBS\Auth; namespace MRBS\Auth;
use MRBS\MailQueue; use MRBS\MailQueue;
use MRBS\User; use MRBS\User;
use PHPMailer\PHPMailer\PHPMailer; use PHPMailer\PHPMailer\PHPMailer;
use function MRBS\_tbl;
use function MRBS\auth;
use function MRBS\db;
use function MRBS\generate_global_uid;
use function MRBS\generate_token;
use function MRBS\get_mail_charset;
use function MRBS\get_vocab;
use function MRBS\multisite;
use function MRBS\parse_email;
use function MRBS\toTimeString;
use function MRBS\url_base;
use function MRBS\utf8_strpos;
use function MRBS\utf8_strtolower;
class AuthDb extends Auth class AuthDb extends Auth
{ {
/* validateUser($user, $pass) /* validateUser($user, $pass)
* *
* Checks if the specified username/password pair are valid * Checks if the specified username/password pair are valid
* *
* $user - The user name * $user - The user name
* $pass - The password * $pass - The password
* *
* Returns: * Returns:
* false - The pair are invalid or do not exist * false - The pair are invalid or do not exist
* string - The validated username * string - The validated username
*/ */
public function validateUser($user, $pass) public function validateUser(?string $user, ?string $pass)
{ {
// The string $user that the user logged on with could be either a username or // The string $user that the user logged on with could be either a username or
// an email address, or even possibly just the local part of an email addres s. // an email address, or even possibly just the local part of an email addres s.
// So it's just possible that there is more than one user with this password and // So it's just possible that there is more than one user with this password and
// username | email address | local-part. If we get more than one, then w e don't // username | email address | local-part. If we get more than one, then w e don't
// know which user it is, so we return false. // know which user it is, so we return false.
$valid_usernames = array(); $valid_usernames = array();
if (($valid_username = $this->validateUsername($user, $pass)) !== false) if (($valid_username = $this->validateUsername($user, $pass)) !== false)
{ {
skipping to change at line 43 skipping to change at line 56
} }
$valid_usernames = array_merge($valid_usernames, $this->validateEmail($user, $pass)); $valid_usernames = array_merge($valid_usernames, $this->validateEmail($user, $pass));
$valid_usernames = array_unique($valid_usernames); $valid_usernames = array_unique($valid_usernames);
if (count($valid_usernames) == 1) if (count($valid_usernames) == 1)
{ {
$result = $valid_usernames[0]; $result = $valid_usernames[0];
// Update the database with this login, but don't change the timestamp // Update the database with this login, but don't change the timestamp
$now = time(); $now = time();
$sql = "UPDATE " . \MRBS\_tbl('users') . " $sql = "UPDATE " . _tbl('users') . "
SET last_login=?, timestamp=timestamp SET last_login=?, timestamp=timestamp
WHERE name=?"; WHERE name=?";
$sql_params = array($now, $result); $sql_params = array($now, $result);
\MRBS\db()->command($sql, $sql_params); db()->command($sql, $sql_params);
return $result; return $result;
} }
else else
{ {
return false; return false;
} }
} }
/* validateUsername($user, $pass) /* validateUsername($user, $pass)
* *
* Checks if the specified username/password pair are valid * Checks if the specified username/password pair are valid
* *
* $user - The user name * $user - The user name
* $pass - The password * $pass - The password
* *
* Returns: * Returns:
* false - The pair are invalid or do not exist * false - The pair are invalid or do not exist
* string - The validated username * string - The validated username
*/ */
private function validateUsername($user, $pass) private function validateUsername(string $user, string $pass)
{ {
$sql_params = array(); $sql_params = array();
// We use syntax_casesensitive_equals() rather than just '=' because '=' in MySQL // We use syntax_casesensitive_equals() rather than just '=' because '=' in MySQL
// permits trailing spacings, eg 'john' = 'john '. We could use LIKE, but that then // permits trailing spacings, eg 'john' = 'john '. We could use LIKE, but that then
// permits wildcards, so we could use a combination of LIKE and '=' but that 's a bit // permits wildcards, so we could use a combination of LIKE and '=' but that 's a bit
// messy. WE could use STRCMP, but that's MySQL only. // messy. WE could use STRCMP, but that's MySQL only.
// Usernames are unique in the users table, so we only look for one. // Usernames are unique in the users table, so we only look for one.
$sql = "SELECT password_hash, name $sql = "SELECT password_hash, name
FROM " . \MRBS\_tbl('users') . " FROM " . _tbl('users') . "
WHERE " . \MRBS\db()->syntax_casesensitive_equals('name', \MRBS\utf8_ WHERE " . db()->syntax_casesensitive_equals('name', utf8_strtolower($
strtolower($user), $sql_params) . " user), $sql_params) . "
LIMIT 1"; LIMIT 1";
$res = \MRBS\db()->query($sql, $sql_params); $res = db()->query($sql, $sql_params);
$row = $res->next_row_keyed(); $row = $res->next_row_keyed();
if (!isset($row['password_hash'])) if (!isset($row['password_hash']))
{ {
// No user found with that name // No user found with that name
return false; return false;
} }
return ($this->checkPassword($pass, $row['password_hash'], 'name', $row['nam e'])) ? $row['name'] : false; return ($this->checkPassword($pass, $row['password_hash'], 'name', $row['nam e'])) ? $row['name'] : false;
skipping to change at line 105 skipping to change at line 118
/* authValidateEmail($email, $pass) /* authValidateEmail($email, $pass)
* *
* Checks if the specified email/password pair are valid * Checks if the specified email/password pair are valid
* *
* $email - The email address * $email - The email address
* $pass - The password * $pass - The password
* *
* Returns: * Returns:
* array - An array of valid usernames, empty if none found * array - An array of valid usernames, empty if none found
*/ */
private function validateEmail($email, $pass) private function validateEmail(string $email, string $pass) : array
{ {
$valid_usernames = array(); $valid_usernames = array();
// Email addresses are not unique in the users table, so we need to find all of them. // Email addresses are not unique in the users table, so we need to find all of them.
$users = self::getUsersByEmail($email); $users = self::getUsersByEmail($email);
// Check all the users that have this email address and password hash. // Check all the users that have this email address and password hash.
foreach($users as $user) foreach($users as $user)
{ {
if ($this->checkPassword($pass, $user['password_hash'], 'email', $email)) if (isset($user['password_hash']) &&
$this->checkPassword($pass, $user['password_hash'], 'email', $email))
{ {
$valid_usernames[] = $user['name']; $valid_usernames[] = $user['name'];
} }
} }
return $valid_usernames; return $valid_usernames;
} }
public function getUser($username) public function getUser(string $username) : ?User
{ {
$row = $this->getUserByUsername($username); $row = $this->getUserByUsername($username);
// The username doesn't exist - return NULL // The username doesn't exist - return NULL
if (!isset($row)) if (!isset($row))
{ {
return null; return null;
} }
// The username does exist - return a User object // The username does exist - return a User object
skipping to change at line 152 skipping to change at line 166
// This has already been set as the 'username' property; // This has already been set as the 'username' property;
continue; continue;
} }
$user->$key = $value; $user->$key = $value;
} }
return $user; return $user;
} }
// Return an array of users, indexed by 'username' and 'display_name' // Return an array of users, indexed by 'username' and 'display_name'
public function getUsernames() public function getUsernames() : array
{ {
$sql = "SELECT name AS username, display_name AS display_name $sql = "SELECT name AS username, display_name AS display_name
FROM " . \MRBS\_tbl('users') . " FROM " . _tbl('users') . "
ORDER BY display_name"; ORDER BY display_name";
$res = \MRBS\db()->query($sql); $res = db()->query($sql);
return $res->all_rows_keyed(); $users = $res->all_rows_keyed();
// Although the users are probably already sorted, we sort them again becaus
e MRBS
// offers an option for sorting by first or last name.
self::sortUsers($users);
return $users;
} }
// Return an array of all users // Return an array of all users
public function getUsers() public function getUsers() : array
{ {
$sql = "SELECT * $sql = "SELECT *
FROM " . \MRBS\_tbl('users') . " FROM " . _tbl('users') . "
ORDER BY name"; ORDER BY name";
$res = \MRBS\db()->query($sql); $res = db()->query($sql);
return $res->all_rows_keyed(); return $res->all_rows_keyed();
} }
// Checks whether validation of a user by email address is possible and allowe d. // Checks whether validation of a user by email address is possible and allowe d.
public function canValidateByEmail() public function canValidateByEmail() : bool
{ {
return true; return true;
} }
// Checks whether the method has a password reset facility // Checks whether the method has a password reset facility
public function canResetPassword() public function canResetPassword() : bool
{ {
return true; return true;
} }
// Checks whether the password by reset by supplying an email address. // Checks whether the password by reset by supplying an email address.
// We allow resetting by email, even if there are multiple users with the // We allow resetting by email, even if there are multiple users with the
// same email address. // same email address.
public function canResetByEmail() public function canResetByEmail() : bool
{ {
return $this->canValidateByEmail(); return $this->canValidateByEmail();
} }
public function requestPassword($login) public function requestPassword(?string $login) : bool
{ {
if (!isset($login) || ($login === '')) if (!isset($login) || ($login === ''))
{ {
return false; return false;
} }
// Get the possible users given this login, which could be a username or ema il address. // Get the possible users given this login, which could be a username or ema il address.
// However all the possible users must have the same email address, so check the email // However all the possible users must have the same email address, so check the email
// addresses at the same time. // addresses at the same time.
$possible_users = array(); $possible_users = array();
skipping to change at line 222 skipping to change at line 242
$possible_users[] = $user; $possible_users[] = $user;
} }
if ($this->canValidateByEmail()) if ($this->canValidateByEmail())
{ {
$users = $this->getUsersByEmail($login); $users = $this->getUsersByEmail($login);
if (!empty($users)) if (!empty($users))
{ {
// Check that the email addresses are the same // Check that the email addresses are the same
if (!empty($possible_users) && if (!empty($possible_users) &&
(\MRBS\utf8_strtolower($possible_users[0]['email']) !== \MRBS\utf8_s trtolower($login))) (utf8_strtolower($possible_users[0]['email']) !== utf8_strtolower($l ogin)))
{ {
return false; return false;
} }
foreach ($users as $user) foreach ($users as $user)
{ {
$possible_users[] = $user; $possible_users[] = $user;
} }
} }
} }
if (!empty($possible_users)) if (!empty($possible_users))
{ {
// Generate a key // Generate a key
$key = \MRBS\generate_token(32); $key = generate_token(32);
// Update the database // Update the database
if ($this->setResetKey($possible_users, $key)) if ($this->setResetKey($possible_users, $key))
{ {
// Email the user // Email the user
return $this->notifyUser($possible_users, $key); return $this->notifyUser($possible_users, $key);
} }
} }
return false; return false;
} }
public function resetPassword($username, $key, $password) public function resetPassword(?string $username, ?string $key, ?string $passwo rd) : bool
{ {
// Check that we've got a password and we're allowed to reset the password // Check that we've got a password and we're allowed to reset the password
if (!isset($password) || !\MRBS\auth()->isValidReset($username, $key)) if (!isset($password) || !auth()->isValidReset($username, $key))
{ {
return false; return false;
} }
// Set the new password and clear the reset key // Set the new password and clear the reset key
$sql = "UPDATE " . \MRBS\_tbl('users') . " $sql = "UPDATE " . _tbl('users') . "
SET password_hash=:password_hash, SET password_hash=:password_hash,
reset_key_hash=NULL, reset_key_hash=NULL,
reset_key_expiry=0 reset_key_expiry=0
WHERE name=:name"; // PostgreSQL does not support LIMIT with UPDAT E WHERE name=:name"; // PostgreSQL does not support LIMIT with UPDAT E
$sql_params = array( $sql_params = array(
':password_hash' => password_hash($password, PASSWORD_DEFAULT), ':password_hash' => password_hash($password, PASSWORD_DEFAULT),
':name' => $username ':name' => $username
); );
\MRBS\db()->command($sql, $sql_params); db()->command($sql, $sql_params);
return true; return true;
} }
public function isValidReset($user, $key) public function isValidReset(?string $user, ?string $key) : bool
{ {
if (!isset($user) || !isset($key) || ($user === '') || ($key === '')) if (!isset($user) || !isset($key) || ($user === '') || ($key === ''))
{ {
return false; return false;
} }
$sql = "SELECT reset_key_hash, reset_key_expiry $sql = "SELECT reset_key_hash, reset_key_expiry
FROM " . \MRBS\_tbl('users') . " FROM " . _tbl('users') . "
WHERE name=:name WHERE name=:name
LIMIT 1"; LIMIT 1";
$sql_params = array(':name' => $user); $sql_params = array(':name' => $user);
$res = \MRBS\db()->query($sql,$sql_params); $res = db()->query($sql,$sql_params);
// Check we've found a row // Check we've found a row
if ($res->count() == 0) if ($res->count() == 0)
{ {
return false; return false;
} }
$row = $res->next_row_keyed(); $row = $res->next_row_keyed();
// Check that the reset hasn't expired // Check that the reset hasn't expired
if (time() > $row['reset_key_expiry']) if (time() > $row['reset_key_expiry'])
{ {
return false; return false;
} }
// Check we've got the correct key // Check we've got the correct key
return password_verify($key, $row['reset_key_hash']); return password_verify($key, $row['reset_key_hash']);
} }
private function notifyUser(array $users, $key) protected function getRegistrantsDisplayNamesUnsorted(int $id) : array
{
// For the 'db' auth type we can improve performance by doing a single query
// on the participants table joined with the users table. (Actually it's tw
o
// queries in a UNION: one getting the rows where there isn't an entry in th
e
// users table and another the rows where there is.)
$sql = "SELECT P.username as display_name
FROM " . _tbl('participants') . " P
LEFT JOIN " . _tbl('users') . " U
ON P.username=U.name
WHERE P.entry_id=:entry_id
AND U.name IS NULL
UNION
SELECT U.display_name
FROM " . _tbl('participants') . " P
LEFT JOIN " . _tbl('users') . " U
ON P.username=U.name
WHERE P.entry_id=:entry_id
AND U.name IS NOT NULL";
return db()->query_array($sql, array(':entry_id' => $id));
}
private function notifyUser(array $users, string $key) : bool
{ {
global $auth, $mail_settings; global $auth, $mail_settings;
if (empty($users) || !isset($users[0]['email']) || ($users[0]['email'] === ' ')) if (empty($users) || !isset($users[0]['email']) || ($users[0]['email'] === ' '))
{ {
return false; return false;
} }
$expiry_time = $auth['db']['reset_key_expiry']; $expiry_time = $auth['db']['reset_key_expiry'];
\MRBS\toTimeString($expiry_time, $expiry_units, true, 'hours'); toTimeString($expiry_time, $expiry_units, true, 'hours');
$addresses = array( $addresses = array(
'from' => $mail_settings['from'] 'from' => $mail_settings['from']
); );
// Add the To address, using the display name if possible (ie if it exists a nd there's // Add the To address, using the display name if possible (ie if it exists a nd there's
// only one user). // only one user).
// Also get a name to use in the message body // Also get a name to use in the message body
if ((count($users) == 1) && if ((count($users) == 1) &&
isset($users[0]['display_name']) && isset($users[0]['display_name']) &&
($users[0]['display_name'] !== '')) ($users[0]['display_name'] !== ''))
{ {
$mailer = new PHPMailer(); $mailer = new PHPMailer();
$mailer->CharSet = \MRBS\get_mail_charset(); $mailer->CharSet = get_mail_charset();
// Note that addrFormat() returns a MIME-encoded address // Note that addrFormat() returns a MIME-encoded address
$addresses['to'] = $mailer->addrFormat(array($users[0]['email'], $users[0] ['display_name'])); $addresses['to'] = $mailer->addrFormat(array($users[0]['email'], $users[0] ['display_name']));
$name = $users[0]['display_name']; $name = $users[0]['display_name'];
} }
else else
{ {
$addresses['to'] = $users[0]['email']; $addresses['to'] = $users[0]['email'];
// If there's only one user we can use the username, otherwise we have to use the // If there's only one user we can use the username, otherwise we have to use the
// email address which is the same for all users. // email address which is the same for all users.
$name = (count($users) == 1) ? $users[0]['name'] : $users[0]['email']; $name = (count($users) == 1) ? $users[0]['name'] : $users[0]['email'];
} }
$subject = \MRBS\get_vocab('password_reset_subject'); $subject = get_vocab('password_reset_subject');
$body = '<p>'; $body = '<p>';
$body .= \MRBS\get_vocab('password_reset_body', intval($expiry_time), $expir y_units, $name); $body .= get_vocab('password_reset_body', intval($expiry_time), $expiry_unit s, $name);
$body .= "</p>\n"; $body .= "</p>\n";
// Construct and add in the link // Construct and add in the link
$usernames = array(); $usernames = array();
foreach ($users as $user) foreach ($users as $user)
{ {
$usernames[] = $user['name']; $usernames[] = $user['name'];
} }
$usernames = array_unique($usernames); $usernames = array_unique($usernames);
$vars = array( $vars = array(
'action' => 'reset', 'action' => 'reset',
'usernames' => $usernames, 'usernames' => $usernames,
'key' => $key 'key' => $key
); );
$query = http_build_query($vars, '', '&'); $query = http_build_query($vars, '', '&');
$href = (\MRBS\is_https()) ? 'https' : 'http'; $href = url_base() . multisite("reset_password.php?$query");
$href .= '://' . \MRBS\url_base() . \MRBS\multisite("reset_password.php?$que $body .= "<p><a href=\"$href\">" . get_vocab('reset_password') . "</a>.</p>"
ry"); ;
$body .= "<p><a href=\"$href\">" . \MRBS\get_vocab('reset_password') . "</a>
.</p>";
MailQueue::add( MailQueue::add(
$addresses, $addresses,
$subject, $subject,
array('content' => strip_tags($body)), array('content' => strip_tags($body)),
array('content' => $body, array('content' => $body,
'cid' => \MRBS\generate_global_uid("html")), 'cid' => generate_global_uid("html")),
null, null,
\MRBS\get_mail_charset() get_mail_charset()
); );
return true; return true;
} }
private function setResetKey(array $users, $key) private function setResetKey(array $users, string $key) : bool
{ {
global $auth; global $auth;
if (empty($users)) if (empty($users))
{ {
return false; return false;
} }
$ids = array(); $ids = array();
foreach($users as $user) foreach($users as $user)
{ {
// Use intval to make sure the string is safe for the SQL query // Use intval to make sure the string is safe for the SQL query
$ids[] = intval($user['id']); $ids[] = intval($user['id']);
} }
$sql = "UPDATE " . \MRBS\_tbl('users') . " $sql = "UPDATE " . _tbl('users') . "
SET reset_key_hash=:reset_key_hash, SET reset_key_hash=:reset_key_hash,
reset_key_expiry=:reset_key_expiry reset_key_expiry=:reset_key_expiry
WHERE id IN (" . implode(',', $ids) . ")"; WHERE id IN (" . implode(',', $ids) . ")";
$sql_params = array( $sql_params = array(
':reset_key_hash' => password_hash($key, PASSWORD_DEFAULT), ':reset_key_hash' => password_hash($key, PASSWORD_DEFAULT),
':reset_key_expiry' => time() + $auth['db']['reset_key_expiry'] ':reset_key_expiry' => time() + $auth['db']['reset_key_expiry']
); );
\MRBS\db()->command($sql, $sql_params); db()->command($sql, $sql_params);
return true; return true;
} }
private function getUserByUsername($username) private function getUserByUsername(string $username) : ?array
{ {
$sql = "SELECT * $sql = "SELECT *
FROM " . \MRBS\_tbl('users') . " FROM " . _tbl('users') . "
WHERE name=:name WHERE name=:name
LIMIT 1"; LIMIT 1";
$result = \MRBS\db()->query($sql, array(':name' => $username)); $result = db()->query($sql, array(':name' => $username));
// The username doesn't exist - return NULL // The username doesn't exist - return NULL
if ($result->count() === 0) if ($result->count() === 0)
{ {
return null; return null;
} }
return $result->next_row_keyed(); return $result->next_row_keyed();
} }
private function getUserByUserId($id) private function getUserByUserId(int $id) : ?array
{ {
$sql = "SELECT * $sql = "SELECT *
FROM " . \MRBS\_tbl('users') . " FROM " . _tbl('users') . "
WHERE id=:id WHERE id=:id
LIMIT 1"; LIMIT 1";
$result = \MRBS\db()->query($sql, array(':id' => $id)); $result = db()->query($sql, array(':id' => $id));
// The username doesn't exist - return NULL // The username doesn't exist - return NULL
if ($result->count() === 0) if ($result->count() === 0)
{ {
return null; return null;
} }
return $result->next_row_keyed(); return $result->next_row_keyed();
} }
// Returns an array of rows for all users with the email address $email. // Returns an array of rows for all users with the email address $email.
// Assumes that email addresses are case insensitive. // Assumes that email addresses are case insensitive.
// Allows equivalent Gmail addresses, ie ignores dots in the local part and // Allows equivalent Gmail addresses, ie ignores dots in the local part and
// treats gmail.com and googlemail.com as equivalent domains. // treats gmail.com and googlemail.com as equivalent domains.
private function getUsersByEmail($email) private function getUsersByEmail(string $email) : array
{ {
global $auth; global $auth;
$result = array(); $result = array();
// For the moment we will assume that email addresses are case insensitive. Whilst it is true // For the moment we will assume that email addresses are case insensitive. Whilst it is true
// on most systems, it isn't always true. The domain is case insensitive bu t the local-part can // on most systems, it isn't always true. The domain is case insensitive bu t the local-part can
// be case sensitive. But before we can take account of this, the email add resses in the database // be case sensitive. But before we can take account of this, the email add resses in the database
// need to be normalised so that all the domain names are stored in lower ca se. Then it will be // need to be normalised so that all the domain names are stored in lower ca se. Then it will be
// possible to do a case sensitive comparison. // possible to do a case sensitive comparison.
if (\MRBS\utf8_strpos($email, '@') === false) if (utf8_strpos($email, '@') === false)
{ {
if (!empty($auth['allow_local_part_email'])) if (!empty($auth['allow_local_part_email']))
{ {
// We're just checking the local-part of the email address // We're just checking the local-part of the email address
$sql_params = array($email); $sql_params = array($email);
$condition = "LOWER(?)=LOWER(" . \MRBS\db()->syntax_simple_split('email' , '@', 1, $sql_params) .")"; $condition = "LOWER(?)=LOWER(" . db()->syntax_simple_split('email', '@', 1, $sql_params) .")";
} }
else else
{ {
return $result; return $result;
} }
} }
else else
{ {
$address = \MRBS\parse_email($email); $address = parse_email($email);
// Invalid email address // Invalid email address
if ($address === false) if ($address === false)
{ {
return $result; return $result;
} }
// Special case for Gmail addresses: ignore dots in the local part and tre at gmail.com and // Special case for Gmail addresses: ignore dots in the local part and tre at gmail.com and
// googlemail.com as equivalent domains. // googlemail.com as equivalent domains.
elseif (in_array(\MRBS\utf8_strtolower($address['domain']), array('gmail.c om', 'googlemail.com'))) elseif (in_array(utf8_strtolower($address['domain']), array('gmail.com', ' googlemail.com')))
{ {
$sql_params = array(str_replace('.', '', $address['local'])); $sql_params = array(str_replace('.', '', $address['local']));
$sql_params[] = $sql_params[0]; $sql_params[] = $sql_params[0];
$condition = "(LOWER(?) = REPLACE(TRIM(TRAILING '@gmail.com' FROM LOWER( email)), '.', '')) OR " . $condition = "(LOWER(?) = REPLACE(TRIM(TRAILING '@gmail.com' FROM LOWER( email)), '.', '')) OR " .
"(LOWER(?) = REPLACE(TRIM(TRAILING '@googlemail.com' FROM L OWER(email)), '.', ''))"; "(LOWER(?) = REPLACE(TRIM(TRAILING '@googlemail.com' FROM L OWER(email)), '.', ''))";
} }
// Everything else: check the complete email address // Everything else: check the complete email address
else else
{ {
$sql_params = array($email); $sql_params = array($email);
$condition = "LOWER(?)=LOWER(email)"; $condition = "LOWER(?)=LOWER(email)";
} }
} }
$sql = "SELECT * $sql = "SELECT *
FROM " . \MRBS\_tbl('users') . " FROM " . _tbl('users') . "
WHERE $condition"; WHERE $condition";
$res = \MRBS\db()->query($sql, $sql_params); $res = db()->query($sql, $sql_params);
while (false !== ($row = $res->next_row_keyed())) while (false !== ($row = $res->next_row_keyed()))
{ {
$result[] = $row; $result[] = $row;
} }
return $result; return $result;
} }
private function rehash($password, $column_name, $column_value) private function rehash(string $password, string $column_name, string $column_ value) : void
{ {
$sql_params = array(password_hash($password, PASSWORD_DEFAULT)); $sql_params = array(password_hash($password, PASSWORD_DEFAULT));
switch ($column_name) switch ($column_name)
{ {
case 'name': case 'name':
$condition = \MRBS\db()->syntax_casesensitive_equals($column_name, \MRBS \utf8_strtolower($column_value), $sql_params); $condition = db()->syntax_casesensitive_equals($column_name, utf8_strtol ower($column_value), $sql_params);
break; break;
case 'email': case 'email':
// For the moment we will assume that email addresses are case insensiti ve. Whilst it is true // For the moment we will assume that email addresses are case insensiti ve. Whilst it is true
// on most systems, it isn't always true. The domain is case insensitiv e but the local-part can // on most systems, it isn't always true. The domain is case insensitiv e but the local-part can
// be case sensitive. But before we can take account of this, the emai l addresses in the database // be case sensitive. But before we can take account of this, the emai l addresses in the database
// need to be normalised so that all the domain names are stored in lowe r case. Then it will be possible // need to be normalised so that all the domain names are stored in lowe r case. Then it will be possible
// to do a case sensitive comparison. // to do a case sensitive comparison.
$sql_params[] = $column_value; $sql_params[] = $column_value;
$condition = "LOWER($column_name)=LOWER(?)"; $condition = "LOWER($column_name)=LOWER(?)";
break; break;
default: default:
trigger_error("Unsupported column name '$column_name'.", E_USER_NOTICE); trigger_error("Unsupported column name '$column_name'.", E_USER_NOTICE);
return; return;
break; break;
} }
$sql = "UPDATE " . \MRBS\_tbl('users') . " $sql = "UPDATE " . _tbl('users') . "
SET password_hash=? SET password_hash=?
WHERE $condition"; WHERE $condition";
\MRBS\db()->command($sql, $sql_params); db()->command($sql, $sql_params);
} }
// Checks $password against $password_hash for the row in the user table // Checks $password against $password_hash for the row in the user table
// where $column_name=$column_value. Typically $column_name will be either // where $column_name=$column_value. Typically $column_name will be either
// 'name' or 'email'. // 'name' or 'email'.
// Returns a boolean: true if they match, otherwise false. // Returns a boolean: true if they match, otherwise false.
private function checkPassword($password, $password_hash, $column_name, $colum n_value) private function checkPassword(string $password, string $password_hash, string $column_name, string $column_value) : bool
{ {
$result = false; $result = false;
$do_rehash = false; $do_rehash = false;
/* If the hash starts '$' it's a PHP password hash */ /* If the hash starts '$' it's a PHP password hash */
if (substr($password_hash, 0, 1) == '$') if (substr($password_hash, 0, 1) == '$')
{ {
if (password_verify($password, $password_hash)) if (password_verify($password, $password_hash))
{ {
$result = true; $result = true;
 End of changes. 59 change blocks. 
64 lines changed or deleted 108 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)