PageRenderTime 62ms CodeModel.GetById 34ms RepoModel.GetById 1ms app.codeStats 0ms

/classes/kohana/session.php

https://github.com/essjayhch/core
PHP | 463 lines | 399 code | 14 blank | 50 comment | 6 complexity | 04072ee496c30317112d2d028dcce591 MD5 | raw file
  1. <?php defined('SYSPATH') or die('No direct script access.');
  2. /**
  3. * Base session class.
  4. *
  5. * @package Kohana
  6. * @category Session
  7. * @author Kohana Team
  8. * @copyright (c) 2008-2010 Kohana Team
  9. * @license http://kohanaframework.org/license
  10. */
  11. abstract class Kohana_Session {
  12. /**
  13. * @var string default session adapter
  14. */
  15. public static $default = null;
  16. /**
  17. * @var array session instances
  18. */
  19. protected static $instances = array();
  20. /**
  21. *
  22. * Function used to create a singleton instance of a session. This functionality changed in 3.0 so the function has
  23. * been renamed to conform with the Lazy Initialization pattern as opposed to Singleton.
  24. * The result is that this function will return the same session of a given type.
  25. *
  26. * @deprecated deprecated as it doesn't do what it says on the tin. Use getSession instead. Should be removed in next major release.
  27. * @param string type of session (native, cookie, etc)
  28. * @param string session identifier
  29. * @return Session
  30. * @uses self::getSession()
  31. */
  32. public static function instance($type = NULL, $id = NULL)
  33. {
  34. return Session::getSession($type,$id);
  35. }
  36. /**
  37. * Creates a Lazy Initialization (singleton of a given type) session of the given type. Some session types
  38. * (native, database) also support restarting a session by passing a
  39. * session id as the second parameter.
  40. *
  41. * $session = Session::instance();
  42. *
  43. * [!!] [Session::write] will automatically be called when the request ends.
  44. *
  45. * @param string type of session (native, cookie, etc)
  46. * @param string session identifier
  47. * @return Session
  48. * @uses Kohana::config
  49. * @throws Kohana_Exception if session cookie name isn't defined in configuration or if there is a name collision.
  50. */
  51. public static function getSession($type = NULL, $id = NULL)
  52. {
  53. if ($type === NULL)
  54. {
  55. // Use the default type
  56. // Either from the config, or from Session::$default if it is present
  57. // If both are NULL, then it will set it to native.
  58. $type = Session::$default===NULL?Kohana::config("session")->get('default','native'):Session::$default;
  59. }
  60. if ( ! isset(Session::$instances[$type]))
  61. {
  62. //Check for collisions of driver cookie names.
  63. $driver_names = array();
  64. foreach(($config = Kohana::config("session")) as $driver => $driver_config)
  65. {
  66. if(!isset($driver_config['name'])||array_key_exists($driver_config['name'],$driver_names))
  67. throw new Kohana_Exception("Session 'name' missing or collision error in configuration for :driver driver",array(":driver"=>$driver));
  68. $driver_names[$driver_config['name']]=true;
  69. }
  70. // Load the configuration for this type
  71. $config = $config[$type];
  72. // Set the session class name
  73. $class = 'Session_'.ucfirst($type);
  74. // Create a new session instance
  75. Session::$instances[$type] = $session = new $class($config, $id);
  76. // Write the session at shutdown
  77. register_shutdown_function(array($session, 'write'));
  78. }
  79. else if(isset($id)&&Session::$instances[$type]->id()!==$id)
  80. throw Kohana_Exception("You can't change session IDs half way through execution");
  81. return Session::$instances[$type];
  82. }
  83. /**
  84. * @var string cookie name
  85. */
  86. protected $_name = 'session';
  87. /**
  88. * @var int cookie lifetime
  89. */
  90. protected $_lifetime = 0;
  91. /**
  92. * @var bool encrypt session data?
  93. */
  94. protected $_encrypted = FALSE;
  95. /**
  96. * @var array session data
  97. */
  98. protected $_data = array();
  99. /**
  100. * @var bool session destroyed?
  101. */
  102. protected $_destroyed = FALSE;
  103. /**
  104. * Overloads the name, lifetime, and encrypted session settings.
  105. *
  106. * [!!] Sessions can only be created using the [Session::instance] method.
  107. *
  108. * @param array configuration
  109. * @param string session id
  110. * @return void
  111. * @uses Session::read
  112. */
  113. public function __construct(array $config = NULL, $id = NULL)
  114. {
  115. if (isset($config['name']))
  116. {
  117. // Cookie name to store the session id in
  118. $this->_name = (string) $config['name'];
  119. }
  120. if (isset($config['lifetime']))
  121. {
  122. // Cookie lifetime
  123. $this->_lifetime = (int) $config['lifetime'];
  124. }
  125. if (isset($config['encrypted']))
  126. {
  127. if ($config['encrypted'] === TRUE)
  128. {
  129. // Use the default Encrypt instance
  130. $config['encrypted'] = 'default';
  131. }
  132. // Enable or disable encryption of data
  133. $this->_encrypted = $config['encrypted'];
  134. }
  135. // Load the session
  136. $this->read($id);
  137. }
  138. /**
  139. * Session object is rendered to a serialized string. If encryption is
  140. * enabled, the session will be encrypted. If not, the output string will
  141. * be encoded using [base64_encode].
  142. *
  143. * echo $session;
  144. *
  145. * @return string
  146. * @uses Encrypt::encode
  147. */
  148. public function __toString()
  149. {
  150. // Serialize the data array
  151. $data = serialize($this->_data);
  152. if ($this->_encrypted)
  153. {
  154. // Encrypt the data using the default key
  155. $data = Encrypt::instance($this->_encrypted)->encode($data);
  156. }
  157. else
  158. {
  159. // Obfuscate the data with base64 encoding
  160. $data = base64_encode($data);
  161. }
  162. return $data;
  163. }
  164. /**
  165. * Returns the current session array. The returned array can also be
  166. * assigned by reference.
  167. *
  168. * // Get a copy of the current session data
  169. * $data = $session->as_array();
  170. *
  171. * // Assign by reference for modification
  172. * $data =& $session->as_array();
  173. *
  174. * @return array
  175. */
  176. public function & as_array()
  177. {
  178. return $this->_data;
  179. }
  180. /**
  181. * Get the current session id, if the session supports it.
  182. *
  183. * $id = $session->id();
  184. *
  185. * [!!] Not all session types have ids.
  186. *
  187. * @return string
  188. * @since 3.0.8
  189. */
  190. public function id()
  191. {
  192. return NULL;
  193. }
  194. /**
  195. * Get the current session cookie name.
  196. *
  197. * $name = $session->name();
  198. *
  199. * @return string
  200. * @since 3.0.8
  201. */
  202. public function name()
  203. {
  204. return $this->_name;
  205. }
  206. /**
  207. * Get a variable from the session array.
  208. *
  209. * $foo = $session->get('foo');
  210. *
  211. * @param string variable name
  212. * @param mixed default value to return
  213. * @return mixed
  214. */
  215. public function get($key, $default = NULL)
  216. {
  217. return array_key_exists($key, $this->_data) ? $this->_data[$key] : $default;
  218. }
  219. /**
  220. * Get and delete a variable from the session array.
  221. *
  222. * $bar = $session->get_once('bar');
  223. *
  224. * @param string variable name
  225. * @param mixed default value to return
  226. * @return mixed
  227. */
  228. public function get_once($key, $default = NULL)
  229. {
  230. $value = $this->get($key, $default);
  231. unset($this->_data[$key]);
  232. return $value;
  233. }
  234. /**
  235. * Set a variable in the session array.
  236. *
  237. * $session->set('foo', 'bar');
  238. *
  239. * @param string variable name
  240. * @param mixed value
  241. * @return $this
  242. */
  243. public function set($key, $value)
  244. {
  245. $this->_data[$key] = $value;
  246. return $this;
  247. }
  248. /**
  249. * Set a variable by reference.
  250. *
  251. * $session->bind('foo', $foo);
  252. *
  253. * @param string variable name
  254. * @param mixed referenced value
  255. * @return $this
  256. */
  257. public function bind($key, & $value)
  258. {
  259. $this->_data[$key] =& $value;
  260. return $this;
  261. }
  262. /**
  263. * Removes a variable in the session array.
  264. *
  265. * $session->delete('foo');
  266. *
  267. * @param string variable name
  268. * @param ...
  269. * @return $this
  270. */
  271. public function delete($key)
  272. {
  273. $args = func_get_args();
  274. foreach ($args as $key)
  275. {
  276. unset($this->_data[$key]);
  277. }
  278. return $this;
  279. }
  280. /**
  281. * Loads existing session data.
  282. *
  283. * $session->read();
  284. *
  285. * @param string session id
  286. * @return void
  287. */
  288. public function read($id = NULL)
  289. {
  290. if (is_string($data = $this->_read($id)))
  291. {
  292. try
  293. {
  294. if ($this->_encrypted)
  295. {
  296. // Decrypt the data using the default key
  297. $data = Encrypt::instance($this->_encrypted)->decode($data);
  298. }
  299. else
  300. {
  301. // Decode the base64 encoded data
  302. $data = base64_decode($data);
  303. }
  304. // Unserialize the data
  305. $data = unserialize($data);
  306. }
  307. catch (Exception $e)
  308. {
  309. // Ignore all reading errors
  310. }
  311. }
  312. if (is_array($data))
  313. {
  314. // Load the data locally
  315. $this->_data = $data;
  316. }
  317. }
  318. /**
  319. * Generates a new session id and returns it.
  320. *
  321. * $id = $session->regenerate();
  322. *
  323. * @return string
  324. */
  325. public function regenerate()
  326. {
  327. return $this->_regenerate();
  328. }
  329. /**
  330. * Sets the last_active timestamp and saves the session.
  331. *
  332. * $session->write();
  333. *
  334. * [!!] Any errors that occur during session writing will be logged,
  335. * but not displayed, because sessions are written after output has
  336. * been sent.
  337. *
  338. * @return boolean
  339. * @uses Kohana::$log
  340. */
  341. public function write()
  342. {
  343. if (headers_sent() OR $this->_destroyed)
  344. {
  345. // Session cannot be written when the headers are sent or when
  346. // the session has been destroyed
  347. return FALSE;
  348. }
  349. // Set the last active timestamp
  350. $this->_data['last_active'] = time();
  351. try
  352. {
  353. return $this->_write();
  354. }
  355. catch (Exception $e)
  356. {
  357. // Log & ignore all errors when a write fails
  358. Kohana::$log->add(Kohana::ERROR, Kohana::exception_text($e))->write();
  359. return FALSE;
  360. }
  361. }
  362. /**
  363. * Completely destroy the current session.
  364. *
  365. * $success = $session->destroy();
  366. *
  367. * @return boolean
  368. */
  369. public function destroy()
  370. {
  371. if ($this->_destroyed === FALSE)
  372. {
  373. if ($this->_destroyed = $this->_destroy())
  374. {
  375. // The session has been destroyed, clear all data
  376. $this->_data = array();
  377. }
  378. }
  379. return $this->_destroyed;
  380. }
  381. /**
  382. * Loads the raw session data string and returns it.
  383. *
  384. * @param string session id
  385. * @return string
  386. */
  387. abstract protected function _read($id = NULL);
  388. /**
  389. * Generate a new session id and return it.
  390. *
  391. * @return string
  392. */
  393. abstract protected function _regenerate();
  394. /**
  395. * Writes the current session.
  396. *
  397. * @return boolean
  398. */
  399. abstract protected function _write();
  400. /**
  401. * Destroys the current session.
  402. *
  403. * @return boolean
  404. */
  405. abstract protected function _destroy();
  406. } // End Session