* @copyright Yuji Iwashita */ class beatSession { /** * Generate key * * @access private * @var string $__genKey */ var $__genKey = null; /** * Server key * * @access private * @var string $__serverKey */ var $__serverKey = null; /** * Server key * * @access private * @var boolean $__validateIp */ var $__validateIp = false; /** * Session file suffix * * File sessin hadler only. * * @access protected * @var string $_fileSuffix */ var $_fileSuffix = '.sess'; /** * Constructor * * @access public * @param string $genKey * @param string $serverKey * @return void */ function beatSession ( $genKey = null, $serverKey = null, $validateIp = false ) { $this->__construct($genKey, $serverKey); } function __construct ( $genKey = null, $serverKey = null, $validateIp = false ) { $this->setGenKey($genKey); $this->setServerKey($serverKey); $this->__validateIp = ($validateIp) ? true: false; } /** * Start Session * * @access public * @param boolean $reGenerate * @return boolean */ function start ( $reGenerate = false ) { // regist session handler $this->_setHandler(); // validate session id $sess_name = session_name(); $oldId = ''; if (isset($_POST[$sess_name])) { $oldId = $_POST[$sess_name]; // $reGenerate = true; if (isset($_GET[$sess_name])) { $oldId = $_GET[$sess_name]; // $reGenerate = true; } elseif (isset($_COOKIE[$sess_name])) { $oldId = $_COOKIE[$sess_name]; } if ($this->_validateId($oldId)) { $oldStorageId = $this->_getStorageId($oldId); if ($this->_sessionExists($oldStorageId)) { if ($this->_sessionAlive($oldStorageId, (int)ini_get('session.gc_maxlifetime') )) { if ($reGenerate) { $sessId = $this->_generateId(); $this->saveHandler_write($sessId, $this->saveHandler_read($oldId)); $this->saveHandler_destroy($oldId); } else { $sessId = $oldId; } } else { $this->saveHandler_destroy($oldId); $sessId = $this->_generateId(); } } else { $sessId = $this->_generateId(); } } else { $sessId = $this->_generateId(); } // set session id session_id($sessId); // start session return session_start(); } /** * Remove session * * @access public * @return boolean */ function remove () { if (!isset($_SESSION)) { return false; } $_SESSION = array(); $result1 = session_destroy(); if (!headers_sent()) { $params = session_get_cookie_params(); $result2 = (isset($params['domain']{0})) ? setcookie(session_name(), '', 100000000, $params['path'], $params['domain']): setcookie(session_name(), '', 100000000, $params['path']); } if ($result1 && $result2) { return true; } else { return false; } } /** * Set Generator key * * @access public * @param string $genKey * @return void */ function setGenKey ( $genKey = null ) { $this->__genKey = (null === $genKey) ? __FILE__.':'.filemtime(__FILE__): (string)$genKey; } /** * Set Server key * * @access public * @param string $serverKey * @return void */ function setServerKey ( $serverKey = null ) { $this->__serverKey = (null === $serverKey) ? $_SERVER['HTTP_HOST'].filemtime(__FILE__): $serverKey; } /** * Set Validate IP address * * @access public * @param boolean $validateIp * @return void */ function setValidateIp ( $validateIp = null ) { $this->__validateIp = ($validateIp) ? true: false; } /** * Set Session Handler * * @access protected * @return boolean */ function _setHandler () { return session_set_save_handler ( array($this, 'saveHandler_open'), array($this, 'saveHandler_close'), array($this, 'saveHandler_read'), array($this, 'saveHandler_write'), array($this, 'saveHandler_destroy'), array($this, 'saveHandler_gc') ); } /** * Validate Session Id * * @access protected * @param string $sessId client side session id * @return boolean */ function _validateId ( $sessId ) { if ( !is_string($sessId) || !isset($sessId{0}) || false === strpos($sessId, '_') ) { return false; } $sessId = explode('_', $sessId); if (3 !== count($sessId)) { return false; } if ($sessId[2] !== $this->_generateServerHash($sessId[0])) { return false; } if ( $this->__validateIp && $sessId[1] !== $this->_generateClientHash($sessId[0]) ) { return false; } return true; } /** * Get microtime strings * * @access protected * @return string sec.msec */ function _getMicrotimeStr () { list($msec, $sec) = explode(' ', microtime()); return $sec. substr($msec, 1); } /** * Generate New Session Id * * @access protected * @return string client side session id */ function _generateId () { do { $timeStr = $this->_getMicrotimeStr(); $sessId = $timeStr.'_'.$this->_generateClientHash($timeStr) .'_'.$this->_generateServerHash($timeStr);; } while ($this->_sessionExists($this->_getStorageId($sessId))); return $sessId; } /** * Generate Server Hash * * @access protected * @param string $timeStr microtime strings * @return string sha1 */ function _generateServerHash ( $timeStr ) { $sep = $this->__SEP($timeStr); $ua = (isset($_SERVER['HTTP_USER_AGENT'])) ? $_SERVER['HTTP_USER_AGENT']: ''; return sha1($sep.$this->__genKey.$sep.$this->__serverKey.$sep.$ua); } /** * Generate Client Hash * * @access protected * @param string $timeStr microtime strings * @return string sha1 */ function _generateClientHash ( $timeStr ) { $sep = $this->__SEP($timeStr); return sha1($sep.$this->__genKey.$sep.$_SERVER['REMOTE_ADDR']); } /** * Get Storage Id * * @access protected * @param string $sessId client side session id * @return string storage side id */ function _getStorageId ( $sessId ) { $ids = explode('_', $sessId); $sep = $this->__SEP($ids[0]); return sha1($sep.$this->__genKey.$sep.$this->__serverKey); } /** * Get Separator str * * @access private * @param string $gen * @return string */ function __SEP ( $gen = '' ) { switch (strlen($this->__genKey) % 3) { case 2: return sha1($this->__genKey.$gen); case 1: return md5($this->__genKey.$gen); case 0: return (string)crc32($this->__genKey.$gen); } } /** * session_set_save_handler */ /** * Save handler - Open * * @access public * @param string $save_path * @param string $sess_name * @return boolean */ function saveHandler_open ( $save_path, $sess_name ) { return $this->open( $save_path, $sess_name ); } /** * Save handler - Close * * @access public * @return boolean */ function saveHandler_close () { return $this->close(); } /** * Save handler - Read * * @access public * @param string $sessId client side session id * @return string */ function saveHandler_read ( $sessId ) { return $this->read($this->_getStorageId($sessId)); } /** * Save handler - Write * * @access public * @param string $sessId client side session id * @param string $data * @return boolean */ function saveHandler_write ( $sessId, $data ) { return $this->write($this->_getStorageId($sessId), $data); } /** * Save handler - Destroy * * @access public * @param string $sessId client side session id * @return boolean */ function saveHandler_destroy ( $sessId ) { return $this->destroy($this->_getStorageId($sessId)); } /** * Save handler - Gc * * @access public * @param string $maxlifetime * @return boolean */ function saveHandler_gc ( $maxlifetime ) { return $this->gc($maxlifetime); } /** * Override with subclass */ /** * file handler - Session Exists * * @access protected * @param string $id storage side id * @return boolean */ function _sessionExists ( $id ) { $filename = $this->_getFilename($id); if (!is_file($filename) || !is_readable($filename)) { return false; } return true; } /** * file handler - Ssession Alive * * @access protected * @param string $id storage side id * @param int $maxlifetime sec * @return boolean */ function _sessionAlive ( $id, $maxlifetime ) { $filename = $this->_getFilename($id); if (time() > (filemtime($filename) + $maxlifetime)) { return false; } return true; } /** * file handler - Open * * @access public * @param string $save_path * @param string $sess_name * @return boolean */ function open ( $save_path, $sess_name ) { return true; } /** * file handler - Close * * @access public * @return boolean */ function close () { return true; } /** * file handler - Read * * @access public * @param string $id storage side id * @return string */ function read ( $id ) { $filename = $this->_getFilename($id); if (!is_file($filename) || !is_readable($filename)) { return ''; } return (string)file_get_contents($filename); } /** * file handler - Write * * @access public * @param string $id storage side id * @param string $data * @return boolean */ function write ( $id, $data ) { $filename = $this->_getFilename($id); if ($fp = @fopen($filename, 'w')) { $return = fwrite($fp, $data); fclose($fp); return $return; } else { return false; } } /** * file handler - Destroy * * @access public * @param string $id storage side id * @return boolean */ function destroy ( $id ) { $filename = $this->_getFilename($id); return @unlink($filename); } /** * file handler - Gc * * @access public * @param string $maxlifetime * @return boolean */ function gc ( $maxlifetime ) { $files = glob(session_save_path().DIRECTORY_SEPARATOR.'*'.$this->_fileSuffix); if (!is_array($files) || !count($files)) { return true; } foreach ($files as $file) { if ((filemtime($file) + $maxlifetime) < time()) { @unlink($file); } } return true; } /** * File handler utils */ /** * file handler - Get Session filename * * @access protected * @param string $id storage side id * @return boolean */ function _getFilename ( $id ) { return session_save_path().DIRECTORY_SEPARATOR.$id.$this->_fileSuffix; } } /* end of beatSession */