blob: 4acbcf6c50de67d94a1411aa39f39b5276196395 [file] [log] [blame]
<?php
/**
* CodeIgniter
*
* An open source application development framework for PHP 5.2.4 or newer
*
* NOTICE OF LICENSE
*
* Licensed under the Open Software License version 3.0
*
* This source file is subject to the Open Software License (OSL 3.0) that is
* bundled with this package in the files license.txt / license.rst. It is
* also available through the world wide web at this URL:
* http://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to obtain it
* through the world wide web, please send an email to
* licensing@ellislab.com so we can send you a copy immediately.
*
* @package CodeIgniter
* @author Andrey Andreev
* @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
* @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* @link http://codeigniter.com
* @since Version 3.0
* @filesource
*/
defined('BASEPATH') OR exit('No direct script access allowed');
/**
* CodeIgniter Session Files Driver
*
* @package CodeIgniter
* @subpackage Libraries
* @category Sessions
* @author Andrey Andreev
* @link http://codeigniter.com/user_guide/libraries/sessions.html
*/
class CI_Session_files_driver extends CI_Session_driver implements SessionHandlerInterface {
/**
* Save path
*
* @var string
*/
protected $_save_path;
/**
* File handle
*
* @var resource
*/
protected $_file_handle;
/**
* File name
*
* @var resource
*/
protected $_file_path;
/**
* File new flag
*
* @var bool
*/
protected $_file_new;
// ------------------------------------------------------------------------
/**
* Class constructor
*
* @param array $params Configuration parameters
* @return void
*/
public function __construct(&$params)
{
parent::__construct($params);
if (isset($this->_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 */