session.php 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. <?php
  2. /*
  3. Copyright (c) 2009-2014 F3::Factory/Bong Cosca, All rights reserved.
  4. This file is part of the Fat-Free Framework (http://fatfree.sf.net).
  5. THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF
  6. ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  7. IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  8. PURPOSE.
  9. Please see the license.txt file for more information.
  10. */
  11. //! Cache-based session handler
  12. class Session {
  13. protected
  14. //! Session ID
  15. $sid;
  16. /**
  17. * Open session
  18. * @return TRUE
  19. * @param $path string
  20. * @param $name string
  21. **/
  22. function open($path,$name) {
  23. return TRUE;
  24. }
  25. /**
  26. * Close session
  27. * @return TRUE
  28. **/
  29. function close() {
  30. return TRUE;
  31. }
  32. /**
  33. * Return session data in serialized format
  34. * @return string|FALSE
  35. * @param $id string
  36. **/
  37. function read($id) {
  38. if ($id!=$this->sid)
  39. $this->sid=$id;
  40. return Cache::instance()->exists($id.'.@',$data)?$data['data']:FALSE;
  41. }
  42. /**
  43. * Write session data
  44. * @return TRUE
  45. * @param $id string
  46. * @param $data string
  47. **/
  48. function write($id,$data) {
  49. $fw=Base::instance();
  50. $sent=headers_sent();
  51. $headers=$fw->get('HEADERS');
  52. $csrf=$fw->hash($fw->get('ROOT').$fw->get('BASE')).'.'.
  53. $fw->hash(mt_rand());
  54. $jar=$fw->get('JAR');
  55. if ($id!=$this->sid)
  56. $this->sid=$id;
  57. Cache::instance()->set($id.'.@',
  58. array(
  59. 'data'=>$data,
  60. 'csrf'=>$sent?$this->csrf():$csrf,
  61. 'ip'=>$fw->get('IP'),
  62. 'agent'=>isset($headers['User-Agent'])?
  63. $headers['User-Agent']:'',
  64. 'stamp'=>time()
  65. ),
  66. $jar['expire']?($jar['expire']-time()):0
  67. );
  68. return TRUE;
  69. }
  70. /**
  71. * Destroy session
  72. * @return TRUE
  73. * @param $id string
  74. **/
  75. function destroy($id) {
  76. Cache::instance()->clear($id.'.@');
  77. setcookie(session_name(),'',strtotime('-1 year'));
  78. unset($_COOKIE[session_name()]);
  79. header_remove('Set-Cookie');
  80. return TRUE;
  81. }
  82. /**
  83. * Garbage collector
  84. * @return TRUE
  85. * @param $max int
  86. **/
  87. function cleanup($max) {
  88. Cache::instance()->reset('.@',$max);
  89. return TRUE;
  90. }
  91. /**
  92. * Return anti-CSRF token
  93. * @return string|FALSE
  94. **/
  95. function csrf() {
  96. return Cache::instance()->
  97. exists(($this->sid?:session_id()).'.@',$data)?
  98. $data['csrf']:FALSE;
  99. }
  100. /**
  101. * Return IP address
  102. * @return string|FALSE
  103. **/
  104. function ip() {
  105. return Cache::instance()->
  106. exists(($this->sid?:session_id()).'.@',$data)?
  107. $data['ip']:FALSE;
  108. }
  109. /**
  110. * Return Unix timestamp
  111. * @return string|FALSE
  112. **/
  113. function stamp() {
  114. return Cache::instance()->
  115. exists(($this->sid?:session_id()).'.@',$data)?
  116. $data['stamp']:FALSE;
  117. }
  118. /**
  119. * Return HTTP user agent
  120. * @return string|FALSE
  121. **/
  122. function agent() {
  123. return Cache::instance()->
  124. exists(($this->sid?:session_id()).'.@',$data)?
  125. $data['agent']:FALSE;
  126. }
  127. /**
  128. * Instantiate class
  129. * @return object
  130. **/
  131. function __construct() {
  132. session_set_save_handler(
  133. array($this,'open'),
  134. array($this,'close'),
  135. array($this,'read'),
  136. array($this,'write'),
  137. array($this,'destroy'),
  138. array($this,'cleanup')
  139. );
  140. register_shutdown_function('session_commit');
  141. @session_start();
  142. $fw=\Base::instance();
  143. $headers=$fw->get('HEADERS');
  144. if (($ip=$this->ip()) && $ip!=$fw->get('IP') ||
  145. ($agent=$this->agent()) &&
  146. (!isset($headers['User-Agent']) ||
  147. $agent!=$headers['User-Agent'])) {
  148. session_destroy();
  149. \Base::instance()->error(403);
  150. }
  151. $csrf=$fw->hash($fw->get('ROOT').$fw->get('BASE')).'.'.
  152. $fw->hash(mt_rand());
  153. $jar=$fw->get('JAR');
  154. if (Cache::instance()->exists(($this->sid=session_id()).'.@',$data)) {
  155. $data['csrf']=$csrf;
  156. Cache::instance()->set($this->sid.'.@',
  157. $data,
  158. $jar['expire']?($jar['expire']-time()):0
  159. );
  160. }
  161. }
  162. }