<?php

if (!defined('BASEPATH'))
    exit('No direct script access allowed');

/**
 * @author D.Tereschuk
 */
class RT_Session extends CI_Session {

    var $js_session;

    /**
     * Return either the session name or data
     *
     * @access	public
     * @return	string
     */
    function get_js_session($name = FALSE) {
        if ($name) {

            return $this->create_hash($this->sess_cookie_name);
        }

        $session = ( $this->js_session != '' ) ? $this->js_session : $this->CI->input->cookie($this->sess_cookie_name);

        return base64_encode($session);
    }

    /**
     * Return string hash
     * @param string $data
     * @return string
     */
    function create_hash($data) {

        return md5(md5($data) . $this->CI->config->item('encryption_key'));
    }

    /**
     * Fetch the current session data if it exists
     *
     * @access	public
     * @return	bool
     */
    function sess_read() {
        // Get encoded session data from $_POST
        $session = $this->CI->input->post($this->create_hash($this->sess_cookie_name));

        if ($session !== FALSE) {
            $this->js_session = $session = base64_decode($session);
        } else {
            // Fetch the cookie
            $this->js_session = $session = $this->CI->input->cookie($this->sess_cookie_name);
        }

        // No cookie?  Goodbye cruel world!...
        if ($session === FALSE) {
            log_message('error', 'A session cookie was not found.');
            return FALSE;
        }

        // Decrypt the cookie data
        if ($this->sess_encrypt_cookie == TRUE) {
            $session = $this->CI->encrypt->decode($session);
        } else {
            // encryption was not used, so we need to check the md5 hash
            $hash = substr($session, strlen($session) - 32); // get last 32 chars
            $session = substr($session, 0, strlen($session) - 32);

            // Does the md5 hash match?  This is to prevent manipulation of session data in userspace
            if ($hash !== md5($session . $this->encryption_key)) {
                log_message('debug', 'The session cookie data did not match what was expected. This could be a possible hacking attempt.');
                $this->sess_destroy();
                return FALSE;
            }
        }

        // Unserialize the session array
        $session = $this->_unserialize($session);

        // Is the session data we unserialized an array with the correct format?
        if (!is_array($session) || !isset($session['session_id']) || !isset($session['ip_address']) || !isset($session['user_agent']) || !isset($session['last_activity'])) {
            $this->sess_destroy();
            log_message('debug', 'Session data is incorrect format');
            return FALSE;
        }

        // Is the session current?
        if (($session['last_activity'] + $this->sess_expiration) < $this->now) {
            $this->sess_destroy();
            log_message('debug', 'Session has expired');
            return FALSE;
        }

        // Does the IP Match?
        if (!$this->js_session && $this->sess_match_ip == TRUE && $session['ip_address'] != $this->CI->input->ip_address()) {
            $this->sess_destroy();
            log_message('debug', 'Session IP match fail');
            return FALSE;
        }

        // Does the User Agent Match?
        if (!$this->js_session && $this->sess_match_useragent == TRUE && trim($session['user_agent']) != trim(substr($this->CI->input->user_agent(), 0, 50))) {
            $this->sess_destroy();
            log_message('debug', 'Session User Agent match fail');
            return FALSE;
        }

        // Is there a corresponding session in the DB?
        if ($this->sess_use_database === TRUE) {
            $this->CI->db->where('session_id', $session['session_id']);

            if ($this->sess_match_ip == TRUE) {
                $this->CI->db->where('ip_address', $session['ip_address']);
            }

            if ($this->sess_match_useragent == TRUE) {
                $this->CI->db->where('user_agent', $session['user_agent']);
            }

            $query = $this->CI->db->get($this->sess_table_name);

            // No result?  Kill it!
            if ($query->num_rows() == 0) {
                $this->sess_destroy();
                log_message('debug', 'Session data not found in database');
                return FALSE;
            }

            // Is there custom data?  If so, add it to the main session array
            $row = $query->row();
            if (isset($row->user_data) && $row->user_data != '') {
                $custom_data = $this->_unserialize($row->user_data);

                if (is_array($custom_data)) {
                    foreach ($custom_data as $key => $val) {
                        $session[$key] = $val;
                    }
                }
            }
        }

        // Session is valid!
        $this->userdata = $session;
        unset($session);

        return TRUE;
    }

}