Код: Выделить всё
<?php
/**
* PhpBBIdentity
*
* Сверяет логин-пароль по базе форума PhpBB3
*
* user_type
* ---------
* 0 - users
* 1 - inactive
* 2 - bots
* 3 - super user
*
* group_id
* --------
* 1 - anonymous
* 2 - user
* 3 - coppa user
* 4 - super moderator
* 5 - admin
* 6 - bots
*
* @version 1.0
*
* @author Alenxander Makarov
* @link http://rmcreative.ru/
*
*/
class PhpBBIdentity extends CUserIdentity {
protected $_id;
function authenticate() {
//TODO: move connection to config
$conn = Yii::app()->forumDb;
$command = $conn->createCommand(
'SELECT `user_id`, `username_clean`, `user_password`, `user_type`, `group_id`
FROM `users`
WHERE `user_type` NOT IN (1, 2)
AND `group_id` NOT IN (1, 3, 6)
AND `username_clean` = LOWER(:username)
LIMIT 1'
);
$command->bindParam(":username", $this->username, PDO::PARAM_STR);
$user = $command->queryRow();
if(!$user) {
$this->errorCode = self::ERROR_UNKNOWN_IDENTITY;
return !$this->errorCode;
}
if ($this->phpbb_check_hash($this->password, $user['user_password'])){
$this->_id = $user['user_id'];
$this->errorCode = self::ERROR_NONE;
$this->setRole($user);
}
else {
$this->errorCode = self::ERROR_PASSWORD_INVALID;
}
return !$this->errorCode;
}
function getId() {
return $this->_id;
}
function setRole($user){
if($user['user_type']==3) {
$role = 'admin';
}
else {
switch($user['group_id']){
case 2:
$role = 'user';
break;
case 3:
$role = 'moderator';
break;
case 5:
$role = 'administrator';
break;
}
}
$this->setState('role', $role);
}
/**
* Check for correct password
*
* @param string $password The password in plain text
* @param string $hash The stored password hash
*
* @return bool Returns true if the password is correct, false if not.
*/
private function phpbb_check_hash($password, $hash){
$itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
if (strlen($hash) == 34){
return ($this->_hash_crypt_private($password, $hash, $itoa64) === $hash) ? true : false;
}
return (md5($password) === $hash) ? true : false;
}
/**
* The crypt function/replacement
*/
private function _hash_crypt_private($password, $setting, &$itoa64){
$output = '*';
// Check for correct hash
if (substr($setting, 0, 3) != '$H$'){
return $output;
}
$count_log2 = strpos($itoa64, $setting[3]);
if ($count_log2 < 7 || $count_log2 > 30){
return $output;
}
$count = 1 << $count_log2;
$salt = substr($setting, 4, 8);
if (strlen($salt) != 8){
return $output;
}
/**
* We're kind of forced to use MD5 here since it's the only
* cryptographic primitive available in all versions of PHP
* currently in use. To implement our own low-level crypto
* in PHP would result in much worse performance and
* consequently in lower iteration counts and hashes that are
* quicker to crack (by non-PHP code).
*/
if (PHP_VERSION >= 5){
$hash = md5($salt . $password, true);
do {
$hash = md5($hash . $password, true);
}
while (--$count);
}
else {
$hash = pack('H*', md5($salt . $password));
do {
$hash = pack('H*', md5($hash . $password));
}
while (--$count);
}
$output = substr($setting, 0, 12);
$output .= $this->_hash_encode64($hash, 16, $itoa64);
return $output;
}
/**
* Encode hash
*/
private function _hash_encode64($input, $count, &$itoa64){
$output = '';
$i = 0;
do {
$value = ord($input[$i++]);
$output .= $itoa64[$value & 0x3f];
if ($i < $count) {
$value |= ord($input[$i]) << 8;
}
$output .= $itoa64[($value >> 6) & 0x3f];
if ($i++ >= $count) break;
if ($i < $count) {
$value |= ord($input[$i]) << 16;
}
$output .= $itoa64[($value >> 12) & 0x3f];
if ($i++ >= $count) break;
$output .= $itoa64[($value >> 18) & 0x3f];
}
while ($i < $count);
return $output;
}
}