From 47a47fb9fafdb26206d01d846d8013f6e883eb37 Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Sat, 31 May 2014 16:08:30 +0300 Subject: Initial version of new Session library --- .../Session/drivers/Session_files_driver.php | 276 +++++++++++++++++++++ 1 file changed, 276 insertions(+) create mode 100644 system/libraries/Session/drivers/Session_files_driver.php (limited to 'system/libraries/Session/drivers/Session_files_driver.php') diff --git a/system/libraries/Session/drivers/Session_files_driver.php b/system/libraries/Session/drivers/Session_files_driver.php new file mode 100644 index 000000000..4acbcf6c5 --- /dev/null +++ b/system/libraries/Session/drivers/Session_files_driver.php @@ -0,0 +1,276 @@ +_save_path)) + { + $this->_save_path = rtrim($this->_save_path, '/\\'); + ini_set('session.save_path', $this->_save_path); + } + else + { + $this->_save_path = rtrim(ini_get('session.save_path'), '/\\'); + } + } + + // ------------------------------------------------------------------------ + + public function open($save_path, $name) + { + if ( ! is_dir($save_path) && ! mkdir($save_path, 0700, TRUE)) + { + log_message('error', "Session: Configured save path '".$this->_save_path."' is not a directory, doesn't exist or cannot be created."); + return FALSE; + } + + $this->_save_path = $save_path; + $this->_file_path = $this->_save_path.DIRECTORY_SEPARATOR + .$name // we'll use the session cookie name as a prefix to avoid collisions + .($this->_match_ip ? md5($_SERVER['REMOTE_ADDR']) : ''); + + return TRUE; + } + + // ------------------------------------------------------------------------ + + public function read($session_id) + { + // This might seem weird, but PHP 5.6 introduces session_reset(), + // which re-reads session data + if ($this->_file_handle === NULL) + { + $this->_file_path .= $session_id; + + // Just using fopen() with 'c+b' mode would be perfect, but it is only + // available since PHP 5.2.6 and we have to set permissions for new files, + // so we'd have to hack around this ... + if (($this->_file_new = ! file_exists($this->_file_path)) === TRUE) + { + if (($this->_file_handle = fopen($this->_file_path, 'w+b')) === FALSE) + { + log_message('error', "Session: File '".$this->_file_path."' doesn't exist and cannot be created."); + return FALSE; + } + } + elseif (($this->_file_handle = fopen($this->_file_path, 'r+b')) === FALSE) + { + log_message('error', "Session: Unable to open file '".$this->_file_path."'."); + return FALSE; + } + + if (flock($this->_file_handle, LOCK_EX) === FALSE) + { + log_message('error', "Session: Unable to obtain lock for file '".$this->_file_path."'."); + fclose($this->_file_handle); + $this->_file_handle = NULL; + return FALSE; + } + + if ($this->_file_new) + { + chmod($this->_file_path, 0600); + $this->_fingerprint = md5(''); + return ''; + } + } + else + { + rewind($this->_file_handle); + } + + $session_data = ''; + for ($read = 0, $length = filesize($this->_file_path); $read < $length; $read += strlen($buffer)) + { + if (($buffer = fread($this->_file_handle, $length - $read)) === FALSE) + { + break; + } + + $session_data .= $buffer; + } + + $this->_fingerprint = md5($session_data); + return $session_data; + } + + public function write($session_id, $session_data) + { + if ( ! is_resource($this->_file_handle)) + { + return FALSE; + } + elseif ($this->_fingerprint === md5($session_data)) + { + return ($this->_file_new) + ? TRUE + : touch($this->_file_path); + } + + if ( ! $this->_file_new) + { + ftruncate($this->_file_handle, 0); + rewind($this->_file_handle); + } + + for ($written = 0, $length = strlen($session_data); $written < $length; $written += $result) + { + if (($result = fwrite($this->_file_handle, substr($session_data, $written))) === FALSE) + { + break; + } + } + + if ( ! is_int($result)) + { + $this->_fingerprint = md5(substr($session_data, 0, $written)); + log_message('error', 'Session: Unable to write data.'); + return FALSE; + } + + $this->_fingerprint = md5($session_data); + return TRUE; + } + + // ------------------------------------------------------------------------ + + public function close() + { + if (is_resource($this->_file_handle)) + { + flock($this->_file_handle, LOCK_UN); + fclose($this->_file_handle); + + $this->_file_handle = $this->_file_new = NULL; + return TRUE; + } + + return FALSE; + } + + // ------------------------------------------------------------------------ + + public function destroy($session_id) + { + if ($this->close()) + { + return unlink($this->_file_path) && $this->_cookie_destroy(); + } + elseif ($this->_file_path !== NULL) + { + clearstatcache(); + return file_exists($this->_file_path) + ? (unlink($this->_file_path) && $this->_cookie_destroy()) + : TRUE; + } + + return FALSE; + } + + // ------------------------------------------------------------------------ + + public function gc($maxlifetime) + { + if ( ! is_dir($this->_save_path) OR ($files = scandir($this->_save_path)) === FALSE) + { + log_message('debug', "Session: Garbage collector couldn't list files under directory '".$this->_save_path."'."); + return FALSE; + } + + $ts = time() - $maxlifetime; + + foreach ($files as $file) + { + // If the filename doesn't match this pattern, it's either not a session file or is not ours + if ( ! preg_match('/(?:[0-9a-f]{32})?[0-9a-f]{40}$/i', $file) + OR ! is_file($this->_save_path.DIRECTORY_SEPARATOR.$file) + OR ($mtime = filemtime($file)) === FALSE + OR $mtime > $ts) + { + continue; + } + + unlink($this->_save_path.DIRECTORY_SEPARATOR.$file); + } + + return TRUE; + } + +} + +/* End of file Session_files_driver.php */ +/* Location: ./system/libraries/Session/drivers/Session_files_driver.php */ \ No newline at end of file -- cgit v1.2.3-24-g4f1b