PHP Classes

File: engine/class.www-sessions.php

Recommend this page to a friend!
  Classes of Kristo Vaher  >  Wave Framework  >  engine/class.www-sessions.php  >  Download  
File: engine/class.www-sessions.php
Role: Class source
Content type: text/plain
Description: Sessions Class
Class: Wave Framework
MVC framework for building Web sites and APIs
Author: By
Last change: Updated jQuery 1.10.0 and 2.0.1. Added better API versioning support that also takes into account overrides folders. Refactoring of Imager class to reduce duplicate code between Image Handler and Imager. Also fixed the bug introduced in 3.6.2 that generated incorrect image sprite sizes in dynamic image loading. Code review and some minor changes.
Date: 8 years ago
Size: 11,209 bytes
 

Contents

Class file image Download
<?php

/**
 * Wave Framework <http://www.example.com>
 * Session Handler
 *
 * This is a project specific sessions handler that is used by Wave Framework. Custom sessions 
 * handler is needed by Wave Framework because certain projects need distributed sessions or 
 * other forms of session handling. Note that while you can edit this class to your liking, 
 * you should not change the default method names and variables as these are called by State 
 * class of Wave Framework. This class does not do garbage collection, it is recommended to use 
 * Cleaner maintenance script to clean session storage every now and then.
 *
 * @package    State
 * @author     Kristo Vaher <kristo@waher.net>
 * @copyright  Copyright (c) 2012, Kristo Vaher
 * @license    GNU Lesser General Public License Version 3
 * @tutorial   /doc/pages/sessions.htm
 * @since      3.2.0
 * @version    3.6.4
 */
 
final class WWW_Sessions {
	 
	/**
	 * This is the default session name. Wave Framework does not use 'PHPSESSID' by default and 
	 * instead sets the session name (and cookie value) that starts with WWW prefix and is followed
	 * by a number generated from system folder specific folders.
	 */
	public $sessionName='PHPSESSID';

	/**
	 * This carries the currently known session ID value. This is the value of the session cookie.
	 */
	public $sessionId=false;

	/**
	 * This array stores session data. This data will be stored as serialized string in session storage
	 * in filesystem or (if you rewrite methods of this class) in database.
	 */
	public $sessionData=array();
	
	/**
	 * This holds information about session cookie and its various configuration settings. These will 
	 * be used whenever sessions are created.
	 */
	public $sessionCookie=array(
		'lifetime'=>0,
		'path'=>'/',
		'domain'=>false,
		'secure'=>false,
		'http-only'=>true
	);
	
	/**
	 * This is a true-false flag about whether session ID should be regenerated. This can be sent by 
	 * the system that uses the Session Handler at any time before sessions are commited. Wave 
	 * Framework uses this to regenerate cookies when it detects the cookie lifetime is about to end.
	 */
	public $regenerateId=false;
	
	/**
	 * This tells Wave Framework to remove the old cookie if ID is being regenerated.
	 */
	public $regenerateRemoveOld=true;
	
	/**
	 * This holds connection to database link. This is WWW_Database class by default, if database 
	 * connection is used. Thus you can use these values to log session creation or entirely replace
	 * filesystem specific session creation with your own.
	 */
	private $databaseConnection=false;
	
	/**
	 * This holds the cookie folder for the session. This is where the cookie will be stored in the 
	 * filesystem.
	 */
	private $cookieFolder=false;
	
	/**
	 * This holds whether sessions are actually committed or not. This is set to true when Test Suite is run.
	 */
	private $noCommit=false;
	
	/**
	 * Construction method of Session Handler takes two parameters. One for session name and another
	 * for database connection link to (preferably) WWW_Database class. Construction also starts 
	 * sessions automatically if it detects that the user agent has provided a session cookie with
	 * a value.
	 *
	 * @param string $sessionName session and cookie name
	 * @param integer $sessionLifetime how long sessions last
	 * @param boolean|object $databaseConnection database object
	 * @param boolean $noCommit whether databases will actually be commited
	 * @return WWW_Sessions
	 */
	public function __construct($sessionName='PHPSESSID',$sessionLifetime=0,$databaseConnection=false,$noCommit=false){
	
		// This loads the same database connection that is loaded by Data and API Handlers if
		// the settings are used in Configuration file. Database is not used by Session Handler
		// by default, but it can be used for distributed database sessions.
		$this->databaseConnection=$databaseConnection;
		// Session name is what will be set as cookie name
		$this->sessionName=$sessionName;
		// Session name is what will be set as cookie name
		$this->noCommit=$noCommit;
		// Handler will attempt to load session data if session cookie is sent by the user agent
		if(isset($_COOKIE[$this->sessionName])){
			$this->sessionOpen($this->sessionName,$sessionLifetime);
		}
		
	}
	
	/**
	 * This method opens sessions. It checks if a previous session is active and closes it. This
	 * method functions differently based on if session cookie is set or not. If session cookie
	 * is set, then it attempts to populate session data from session storage if it finds a matching
	 * session. If not, then it generates a new session ID and clears the session data array.
	 *
	 * @param boolean|string $sessionName if session name is sent, then sessions will be started with this name.
	 * @param integer $sessionLifetime the age of token file to be still considered a valid token
	 * @return boolean
	 */
	public function sessionOpen($sessionName=false,$sessionLifetime=0){
	
		// Assigning session name, if sent
		if($sessionName){
			// New session name based on the value sent
			$this->sessionName=$sessionName;
		}
		
		// If another session is already running, it is commited
		if($this->sessionId){
			// This stores session data in filesystem or in database
			$this->sessionCommit();
			// Defaults for regenerate values for the newly opened session
			$this->regenerateId=false;
			$this->regenerateRemoveOld=true;
			$this->sessionData=array();
		}
		
		// If session cookie exists, then session data will be loaded
		if(isset($_COOKIE[$this->sessionName])){
			// Making sure that the session does not include any dangerous characters before it is used to load session data
			$this->sessionId=preg_replace('/[^0-9a-z]/i','',$_COOKIE[$this->sessionName]);
			// Session storage address is based on session ID name in the filesystem
			$this->cookieFolder=__ROOT__.'filesystem'.DIRECTORY_SEPARATOR.'sessions'.DIRECTORY_SEPARATOR.substr($this->sessionId,0,2).DIRECTORY_SEPARATOR;
			// If file exists and is not older than the maximum allowed age for a session storage file, then session data is loaded from that file
			if(file_exists($this->cookieFolder.$this->sessionId.'.tmp') && ($sessionLifetime==0 || filemtime($this->cookieFolder.$this->sessionId.'.tmp')>($_SERVER['REQUEST_TIME']-$sessionLifetime))){
				// Loading actual session data and casting the data to array
				$this->sessionData=json_decode(file_get_contents($this->cookieFolder.$this->sessionId.'.tmp'),true);
				// Updating the last-modified time of the session storage file
				if(!$this->noCommit){
					touch($this->cookieFolder.$this->sessionId.'.tmp');
				}
			} else {
				// Since session cookie was found, but there was no session storage anymore, 
				// the session cookie is assigned to be regenerated
				$this->regenerateId=true;
				$this->regenerateRemoveOld=true;
				// Data array is also emptied
				$this->sessionData=array();
			}
		}
		
		// Sessions are started
		return true;
		
	}
	
	/**
	 * This method commits sessions to database. It uses current session configuration and 
	 * also creates or removes session cookies, if this is necessary. Wave Framework calls
	 * this method ONLY if sessions have actually changed or if they are assigned to be
	 * regenerated. This method is not the place to track if sessions are still active (use
	 * the sessionOpen() method for that).
	 * 
	 * @return boolean
	 */
	public function sessionCommit(){
		
		// If session data is empty, then session storage is deleted and session cookie
		// is removed if the user agent has one set.
		if(isset($_COOKIE[$this->sessionName]) && empty($this->sessionData)){
		
			// This is only done if sessions are actually commited and not just simulated
			if(!$this->noCommit){
				// Removing the session storage file
				if(file_exists($this->cookieFolder.$this->sessionId.'.tmp')){
					unlink($this->cookieFolder.$this->sessionId.'.tmp');
				}
				// Removing session cookie
				if(isset($_COOKIE[$this->sessionName])){
					setcookie($this->sessionName,false,1,$this->sessionCookie['path'],$this->sessionCookie['domain'],$this->sessionCookie['secure'],$this->sessionCookie['http-only']);
				}
			}
			
		} else {
		
			// This is only done if sessions are actually commited and not just simulated
			if(!$this->noCommit){
				// If there is no session cookie from the user agent or it is set to be regenerated
				if(!isset($_COOKIE[$this->sessionName]) || $this->regenerateId){
					// If the old storage is assigned to be deleted
					if($this->regenerateRemoveOld){
						if(file_exists($this->cookieFolder.$this->sessionId.'.tmp')){
							unlink($this->cookieFolder.$this->sessionId.'.tmp');
						}
					}
					// Generating a new session ID
					$this->sessionId=$this->generateSessionId();
					// Session storage address is based on session ID name in the filesystem
					$this->cookieFolder=__ROOT__.'filesystem'.DIRECTORY_SEPARATOR.'sessions'.DIRECTORY_SEPARATOR.substr($this->sessionId,0,2).DIRECTORY_SEPARATOR;
					// If lifetime is set to 0, then cookie will last as long as session lasts in browser
					if($this->sessionCookie['lifetime']==0){
						setcookie($this->sessionName,$this->sessionId,0,$this->sessionCookie['path'],$this->sessionCookie['domain'],$this->sessionCookie['secure'],$this->sessionCookie['http-only']);
					} else {
						setcookie($this->sessionName,$this->sessionId,(time()+$this->sessionCookie['lifetime']),$this->sessionCookie['path'],$this->sessionCookie['domain'],$this->sessionCookie['secure'],$this->sessionCookie['http-only']);
					}
				}
				// If session cookie storage subfolder does not exist, then the handler creates it
				if(!is_dir($this->cookieFolder)){
					if(!mkdir($this->cookieFolder,0755)){
						trigger_error('Cannot create session folder in '.$this->cookieFolder,E_USER_ERROR);
					}
				}
				// Session data is stored in session storage
				if(!file_put_contents($this->cookieFolder.$this->sessionId.'.tmp',json_encode($this->sessionData))){
					trigger_error('Cannot write session data to /filesystem/sessions/',E_USER_ERROR);
				}	
			}
			
		}
		
		// Commit complete
		return true;
		
	}
	
	/**
	 * This function simply sets session cookie configuration to Session Handler. This
	 * is used by Session Handler to set session cookies.
	 * 
	 * @param array $settings array of session cookie configuration
	 * @return boolean
	 */
	public function sessionCookie($settings){
	
		// Configuration must be an array
		if(is_array($settings)){
			// Overloading the default cookie session data with the new settings
			$this->sessionCookie=$settings+$this->sessionCookie;
			return true;
		} else {
			return false;
		}
		
	}
	
	/**
	 * This method generates a new session ID value. By default the SHA-1 hash string is generated 
	 * from user IP, server host address, request unique ID, microtime() and a custom salt.
	 *
	 * @param string $salt used for salting session hash
	 * @return string
	 */
	private function generateSessionId($salt=''){
		// Salt is not sent by default in Wave Framework
		return sha1(__IP__.$_SERVER['HTTP_HOST'].(isset($_SERVER['UNIQUE_ID'])?$_SERVER['UNIQUE_ID']:uniqid('www',true)).microtime().$salt);
	}

}
	
?>
For more information send a message to info at phpclasses dot org.