/home/coolpkct/www/websites/cake3.cool.rocks/admin/classes/auth.php
<?php
/**
 * Part of Showkase web site management package
 *
 * @package Showkase
 * @author Jack Hardie {@link http://www.jhardie.com}
 * @copyright Copyright (c) 2012, SimpleViewer Inc.
 */
defined('SK_ACCESS')||die('<h1>403: Forbidden</h1>');
/**
 * Authentication class
 *
 * @access public
 * @package Showkase
 */
Class Auth
{
    /**
     * @var array in form user=>password
     */
    private $authData = array();
    
    /**
     * @var object instance of site singleton
     */
    private $config;
    
    /**
     * Constructor
     *
     */
    public function __construct()
    {
        $this->config = SkConfig::getInstance();
        $this->authPath = $this->config->getAuthPath();
    }
    
    /**
     * Generate hash
     *
     * @return string hash
     * @param string plain text password
     * @param string stored hash
     */
    private function generateHash($plainText, $hash = null)
    {
        if ($hash === null) {
          $salt = substr(md5(uniqid(mt_rand(), true)), 0, SALT_LENGTH);
        } else {
          $salt = substr($hash, 0, SALT_LENGTH);
        }
        return $salt . sha1($salt.$plainText);
    }
  
  
   /**
    * Sets-up the session variables for valid users
    *
    * @access public
    * @return boolean logged-in
    */
    public function login()
    {
        if (isset($_SESSION[SESSION_HASH])) {
            return $this->confirmAuth();
        }
        if (!isset($_POST['user']) || !isset($_POST['password'])) {
            return false;
        }
        $authdata = array();
        try {
            $authData = $this->readAuthData();
        }  catch (Exception $e) {
            Board::addMessage($e->getMessage(), 'error');
            return false;
        }
        sleep(SLEEP_TIME);
        $user = $_POST['user'];
        $password = $_POST['password'];
        unset($_POST['user']);
        unset($_POST['password']);
        $userCount = 0;
        foreach ($authData as $validUser => $validPasswordHash) {
            $passwordHash = $this->generateHash($password, $validPasswordHash);
            if ($user == $validUser && $passwordHash == $validPasswordHash) {
                $userCount++;
            }
        }
        if ($userCount != 1) {
            Board::addMessage('Incorrect user name or password', 'error');
            return false;
        }
        $_SESSION[SESSION_DEFAULT_PASS] = ($password == 'admin');
        $_SESSION[SESSION_USER] = $user;
        $_SESSION[SESSION_PASS] = $passwordHash;
        $_SESSION[SESSION_HASH] = md5(SALT.$user.$passwordHash);
        $_SESSION[LOGIN_TIME] = time();
        return true;  
    }
    
    /**
     * Attempt to read auth file or reset file
     *
     * @return array of auth data
     */
    private function readAuthData()
    {
        $noFileMessage = (DEMO_MODE)
            ? 'Demo is off-line. Please try again later.'
            : 'Error: cannot find authorisation data';
        $authPath = file_exists($this->config->getAuthResetPath())
            ? $this->config->getAuthResetPath()
            : $this->authPath;
        if (!file_exists($authPath)) {
            throw new Exception($noFileMessage);
        }
        if (!is_readable($authPath)) {
            throw new Exception('Error: cannot read the authorisation file');
        }
        @$authData = file_get_contents($authPath);
        if ($authData === false) {
            throw new Exception('Error: cannot get authorisation file contents');
        }
        $authData = substr($authData, 16);
        @$authData = unserialize($authData);
        if (!is_array($authData) || (count($authData) != 1)) {
            throw new Exception('Error: authorisation file format is incorrect');
        }
        return $authData;
    }
  
    /**
     * Checks for valid session variable
     *
     * @access private
     * @return boolean session variable contains valid user name and password
     */
    private function confirmAuth()
    {
        if (!isset($_SESSION[SESSION_USER]) || !isset($_SESSION[SESSION_PASS]) || !isset($_SESSION[SESSION_HASH])) {
            return false;
        }
        $user = $_SESSION[SESSION_USER];
        $passwordHash = $_SESSION[SESSION_PASS];
        $loginHash = $_SESSION[SESSION_HASH];
        return (md5(SALT.$user.$passwordHash) == $loginHash);     
    }
  
   /**
    * Destroy session and cookies
    * http://www.php.net/manual/en/function.session-destroy.php
    *
    * @access public
    * @return void
    */
    function logout()
    {
        if (!isset($_SESSION)) return;
        $_SESSION = array();
        if (ini_get("session.use_cookies")) {
            $params = session_get_cookie_params();
            setcookie(
                session_name(),
                '',
                time() - 42000,
                $params["path"],
                $params["domain"],
                $params["secure"],
                $params["httponly"]
            );
        }
        session_destroy();
    }
    
   /* Confirm password only, irrespective of user name
    * Used when changing passwords
    * @access public
    * @return boolean
    */
    public function confirmPass($plainPass)
    {
        $authdata = array();
        try {
            $authData = $this->readAuthData();
        }  catch (Exception $e) {
            Board::addMessage($e->getMessage(), 'error');
            return false;
        }
        sleep(SLEEP_TIME);
        $userCount = 0;
        foreach ($authData as $validUser => $validPasswordHash) {
            $passwordHash = $this->generateHash($plainPass, $validPasswordHash);
            if ($passwordHash == $validPasswordHash) {
                $userCount++;
            }
        }
        return ($userCount == 1);
    }
    
   /*
    * Change user name and password
    *
    * @access public
    * @return boolean true on success
    * @param string user name
    * @param string password
    */
    function changeLogin($user, $password)
    {
        $passwordHash = $this->generateHash($password);
        $authData = '<?php exit(); ?>'.serialize(array($user => $passwordHash));
        if (false === Filer::skPutContents($this->authPath, $authData, LOCK_EX)) {
            throw new Exception('User and password have not been changed: unable to store new user name and password');
        }
        $_SESSION[SESSION_DEFAULT_PASS] = ($password == 'admin');
        $_SESSION[SESSION_USER] = $user;
        $_SESSION[SESSION_PASS] = $passwordHash;
        $_SESSION[SESSION_HASH] = md5(SALT.$user.$passwordHash);  
        return true;
    }   
}