summaryrefslogblamecommitdiffstats
path: root/inc/session.inc.php
blob: f89d87e39eae5bfddb5eec9f04881eeb1d999ba6 (plain) (tree)
1
2
3
4
5
6
7
8
9




             


                                               
        
                                                         
         
                                        
                                                                                                  












                                                     
                                             

                                          


                                      
                                           






                                                                                     
                             



                                       
                                        

         
                                                   
         
                                       
                                                                       
                                         








                                                 
                                                             








                                                                                             
                                                     
         
                                        
                                                                                              







                                                                          
 
                                             
         
                                                
                                                                                                      
                                                                                                                                                 

                                   
         
 
                                           
         
                                                                                      
                               






                                                                                                      
                                                                                                                                                                

                                                                                                          
         
 
                                                      
         
                                                                

                                                                                                                                           
                                      
                                     
                 




                                                                          

                                                           


                            

 
<?php


class Session
{
	private static ?string $sid = null;
	private static ?array $data = null;
	private static bool $needUpdate = true;
	
	private static function generateSessionId(): void
	{
		if (self::$sid !== null)
			Util::traceError('Error: Asked to generate session id when already set.');
		self::$sid = sha1(
			mt_rand(0, 65535)
			. $_SERVER['REMOTE_ADDR']
			. mt_rand(0, 65535)
			. $_SERVER['REMOTE_PORT']
			. mt_rand(0, 65535)
			. $_SERVER['HTTP_USER_AGENT']
			. mt_rand(0, 65535)
			. microtime(true)
			. mt_rand(0, 65535)
		);
	}

	public static function create(): void
	{
		self::generateSessionId();
		self::$data = array();
	}

	public static function load(): bool
	{
		// Try to load session id from cookie
		if (!self::loadSessionId()) return false;
		// Succeded, now try to load session data. If successful, job is done
		if (self::readSessionData()) return true;
		// Loading session data failed
		self::delete();
		return false;
	}

	public static function getUid()
	{
		return self::get('uid');
	}

	public static function setUid($value): void
	{
		if (strlen($value) < 5)
			Util::traceError('Invalid user id: ' . $value);
		self::set('uid', $value);
	}

	public static function get($key)
	{
		if (isset(self::$data[$key]))
			return self::$data[$key];
		return false;
	}

	public static function set(string $key, $value): void
	{
		if (!is_array(self::$data))
			Util::traceError('Tried to set session data with no active session');
		if (isset(self::$data[$key]) && self::$data[$key] === $value)
			return;
		self::$data[$key] = $value;
		self::$needUpdate = true;
	}

	private static function loadSessionId(): bool
	{
		if (self::$sid !== null)
			Util::traceError('Error: Asked to load session id when already set.');
		if (empty($_COOKIE['sid']))
			return false;
		$id = preg_replace('/[^a-zA-Z0-9]/', '', $_COOKIE['sid']);
		if (empty($id))
			return false;
		self::$sid = $id;
		return true;
	}

	public static function delete(): void
	{
		if (self::$sid === null) return;
		Database::exec('DELETE FROM websession WHERE sid = :sid', array('sid' => self::$sid));
		setcookie('sid', '', time() - CONFIG_SESSION_TIMEOUT, null, null, !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off', true);
		self::$sid = null;
		self::$data = null;
	}

	public static function save(): void
	{
		if (self::$sid === null || self::$data === null || !self::$needUpdate)
			return;
		$data = json_encode(self::$data);
		$ret = Database::exec('INSERT INTO websession (sid, dateline, data) '
			. ' VALUES (:sid, UNIX_TIMESTAMP(), :data) '
			. ' ON DUPLICATE KEY UPDATE dateline = VALUES(dateline), data = VALUES(data)',
			array('sid' => self::$sid, 'data' => $data));
		if ($ret === false)
			Util::traceError('Storing session data in Dahdähbank failed.');
		$ret = setcookie('sid', self::$sid, time() + CONFIG_SESSION_TIMEOUT, null, null, !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off', true);
		if ($ret === false)
			Util::traceError('Error: Could not set Cookie for Client (headers already sent)');
	}

	public static function readSessionData(): bool
	{
		if (self::$sid === null || self::$data !== null)
			Util::traceError('Tried to readSessionData on an active session!');
		$data = Database::queryFirst('SELECT dateline, data FROM websession WHERE sid = :sid LIMIT 1', array('sid' => self::$sid));
		if ($data === false) {
			return false;
		}
		if ($data['dateline'] + CONFIG_SESSION_TIMEOUT < time()) {
			self::delete();
			return false;
		}
		self::$needUpdate = ($data['dateline'] + 3600 < time());
		$data = @json_decode($data['data'], true);
		self::$data = is_array($data) ? $data : [];
		return true;
	}

}