<?php

/*
    pw hash: md5(md5(email.uid.username.plaintext-pw))
    cookie pw salt: md5(md5(SALT).pw-hash)
*/

defined('in_tw') or exit;

class 
user {

    const 
COOKIE_NAME 'persist_auth';
    const 
COOKIE_PW_SALT '';
    
    
// single instance
    
private static $instance;

    function 
__construct() {
        
self::$instance $this;
        
$this->init();
    }

    function 
singleton() {
        return 
self::$instance;
    }


    
// actual work

    
private $db;

    
// relating to a current user session
    
private $user = array();
    private 
$logged_in false;

    private function 
init() {
        
$this->db mysql::singleton();
        
$this->handle_auth();
    }

    public 
sec_key() {}
    public 
sec_val() {}
    public 
sec_verified() {}

    private function 
test_cookie() {
        list(
$uid$hash) = explode('|'trim($_COOKIE[self::COOKIE_NAME]), 2);
        if (!
is_numeric($uid) || strlen($hash) == 32)
            return 
false;
        
$uid $this->db->escape($uid);
        
$hash $this->db->escape($hash);
        
$check_user $this->db->query("select `authhash` from `users` where `id` = '$uid' limit 1");
        if (
$this->db->num($check_user) == 0) {
            
$this->db->free($check_user);
            return 
false;
        }
        list(
$authhash) = $this->db->fetch_row($check_user);
        
$this->db->free($check_user);
        
        if (
md5(md5(self::COOKIE_PW_SALT).$authhash) === $authhash)
            return array(
$uid$authhash);
        else
            return 
false;
    }

    private function 
kill_cookie() {
        
setcookie(self::COOKIE_NAME''time()-200);
    }

    private function 
cookie_exists() {
        return 
array_key_exists(self::COOKIE_NAME$_COOKIE) && trim($_COOKIE[self::COOKIE_NAME]) != '';
    }

    private function 
handle_login_form() {
        if (!
array_key_exists('l_username'$_POST) || !array_key_exists('l_pw'$_POST))
            return array(
                
'success' => false,
                
'reason' => 'Form not filled out'
            
);

        
$_POST['l_username'] = trim($_POST['l_username']);
        
$_POST['l_pw'] = trim($_POST['l_pw']);
        
        if (
$_POST['l_username'] == '' || $_POST['l_pw'] == '')
            return array(
                
'success' => false,
                
'reason' => 'Form not filled out'
            
);

        
$test_creds $this->db->query("
            select
                `id`, `email`, `authhash`
            from
                `users`
            where
                `username` = '"
.$this->db->escape($_POST['l_username'])."' 
            limit 1
        "
);

        if (
$this->db->num($test_creds) == 0) {    
            
$this->db->free($test_creds);
            return array(
                
'success' => false,
                
'reason' => 'Nonexistant user'
            
);
        }

        
$user_info $this->db->fetch_assoc($test_creds);
        
$this->db->free($test_creds);

        
$correct_hash md5(md5($user_info['email'] . $user_info['id'] . $user_info['username'] . $_POST['l_pw']));

        if (
$user_info['authhash'] !== $correct_hash)
            return array(
                
'success' => false,
                
'reason' => 'Invalid password'
            
);

        
// correct info was provided, save it in session
        
$_SESSION['uid'] = $user_info['id'];
        
$_SESSION['auth'] = $user_info['authhash'];

        
// set a fucking cookie
        
if (array_key_exists('pers_auth'$_POST) && $_POST['pers_auth'] == 'yes')
            
setcookie(self::COOKIE_NAMEmd5(md5(self::COOKIE_SALT).$user_info['authhash']), time()+60*60*24*30);

        return 
true;
    }

    private function 
handle_auth() {

        
// possibly use login info in cookie to auth with
        
$use_cookie false;
        if (
$this->cookie_exists()) {
            if ((
$cookie_info $this->test_cookie()) === false
                
$this->kill_cookie();
            else
                list(
$_SESSION['uid'], $_SESSION['auth']) = $cookie_info;
        }

        
// deal with session auth
        
if (!array_key_exists('uid'$_SESSION) || !array_key_exists('auth'$_SESSION)) {
            
$this->user = array();
            
$this->logged_in false;
            return;
        }

        
$_SESSION['uid'] = $this->db->escape($_SESSION['uid']);
        
$_SESSION['auth'] = $this->db->escape($_SESSION['auth']);

        
$test_auth $this->db->query("
        select
            `id`, `username`, `email`, `activated`
        from
            `users`
        where
            `id` = '
{$_SESSION['uid']}' and
            `authhash` = '
{$_SESSION['auth']}'
        limit 1"
);
        
        if (
$this->db->num($test_auth) == 0) {
            
$this->db->free($test_auth);
            
$this->user = array();
            
$this->cookie_exists() && $this->kill_cookie();
            
$this->logged_in false;
            
$_SESSION['uid'] = '';
            
$_SESSION['auth'] = '';
            unset(
$_SESSION['uid']);
            unset(
$_SESSION['auth']);
            return;
        }

        
$db_info $this->db->fetch_assoc($test_auth);
        
$this->db->free($test_auth);

        
$this->user = array(
            
'uid' => $db_info['id'],
            
'username' => $db_info['username'],
            
'email' => $db_info['email'],
            
'activated' => $db_info['activated'] === '1'
        
);

        
$this->logged_in true;

        
$this->db->query("update `users` set `lastseen` = unix_timestamp() where `id` = '{$this->user['uid']}' limit 1");
    }

    public function 
kill_auth() {
        
$this->cookie_exists() && $this->kill_cookie();
        
$this->user = array();
        
$this->logged_in false;
        
$_SESSION['uid'] = '';
        
$_SESSION['auth'] = '';
        unset(
$_SESSION['uid']);
        unset(
$_SESSION['auth']);
    }

    public function 
logged_in() {
        return 
$this->logged_in;
    }

    public function 
my_uid () {
        return 
$this->logged_in $this->user['uid'] : false;
    }

    public function 
my_email () {
        return 
$this->logged_in $this->user['email'] : false;
    }

    public function 
activated() {
        return 
$this->logged_in $this->user['activated'] : false;
    }
}