BxDolSession.php 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. <?php defined('BX_DOL') or die('hack attempt');
  2. /**
  3. * Copyright (c) UNA, Inc - https://una.io
  4. * MIT License - https://opensource.org/licenses/MIT
  5. *
  6. * @defgroup UnaCore UNA Core
  7. * @{
  8. */
  9. define('BX_DOL_SESSION_LIFETIME', 3600);
  10. define('BX_DOL_SESSION_COOKIE', 'memberSession');
  11. class BxDolSession extends BxDolFactory implements iBxDolSingleton
  12. {
  13. protected $oDb;
  14. protected $sId;
  15. protected $iUserId;
  16. protected $aData;
  17. protected $bAutoLogout; //--- Auto logout with broken session
  18. protected function __construct()
  19. {
  20. if (isset($GLOBALS['bxDolClasses'][get_class($this)]))
  21. trigger_error ('Multiple instances are not allowed for the class: ' . get_class($this), E_USER_ERROR);
  22. parent::__construct();
  23. $this->oDb = new BxDolSessionQuery();
  24. $this->sId = '';
  25. $this->iUserId = 0;
  26. $this->aData = array();
  27. $this->bAutoLogout = false; // when changing to 'true', it's better to increase BX_DOL_SESSION_LIFETIME to 1 month or so
  28. }
  29. /**
  30. * Prevent cloning the instance
  31. */
  32. public function __clone()
  33. {
  34. if (isset($GLOBALS['bxDolClasses'][get_class($this)]))
  35. trigger_error('Clone is not allowed for the class: ' . get_class($this), E_USER_ERROR);
  36. }
  37. /**
  38. * Get singleton instance of the class
  39. */
  40. public static function getInstance()
  41. {
  42. if(!isset($GLOBALS['bxDolClasses'][__CLASS__]))
  43. $GLOBALS['bxDolClasses'][__CLASS__] = new BxDolSession();
  44. if(!$GLOBALS['bxDolClasses'][__CLASS__]->getId())
  45. $GLOBALS['bxDolClasses'][__CLASS__]->start();
  46. return $GLOBALS['bxDolClasses'][__CLASS__];
  47. }
  48. function start()
  49. {
  50. if (defined('BX_DOL_CRON_EXECUTE'))
  51. return true;
  52. if ($this->exists($this->sId)) {
  53. if ($this->iUserId == getLoggedId())
  54. return true;
  55. $this->destroy(false);
  56. }
  57. /**
  58. * Force logout a logged in user if his session wasn't found and required to be automatically recreated.
  59. * It's needed to avoid problems when different users are logged in at the same time under one account.
  60. */
  61. if($this->bAutoLogout && isLogged())
  62. bx_logout();
  63. $this->sId = genRndPwd(32, true);
  64. $aUrl = parse_url(BX_DOL_URL_ROOT);
  65. $sPath = isset($aUrl['path']) && !empty($aUrl['path']) ? $aUrl['path'] : '/';
  66. setcookie(BX_DOL_SESSION_COOKIE, $this->sId, 0, $sPath, '', false, true);
  67. $this->save();
  68. return true;
  69. }
  70. function destroy($bDeleteCookies = true)
  71. {
  72. if ($bDeleteCookies) {
  73. $aUrl = parse_url(BX_DOL_URL_ROOT);
  74. $sPath = isset($aUrl['path']) && !empty($aUrl['path']) ? $aUrl['path'] : '/';
  75. setcookie(BX_DOL_SESSION_COOKIE, '', time() - 86400, $sPath, '', false, true);
  76. unset($_COOKIE[BX_DOL_SESSION_COOKIE]);
  77. }
  78. $this->oDb->delete($this->sId);
  79. $this->sId = '';
  80. $this->iUserId = 0;
  81. $this->aData = array();
  82. }
  83. function exists($sId = '')
  84. {
  85. if(empty($sId) && isset($_COOKIE[BX_DOL_SESSION_COOKIE]))
  86. $sId = bx_process_input($_COOKIE[BX_DOL_SESSION_COOKIE]);
  87. $mixedSession = $this->oDb->exists($sId);
  88. if($mixedSession === false)
  89. return false;
  90. $this->sId = $mixedSession['id'];
  91. $this->iUserId = (int)$mixedSession['user_id'];
  92. $this->aData = unserialize($mixedSession['data']);
  93. $this->oDb->update($this->sId); //--- update session's time
  94. return true;
  95. }
  96. function getId()
  97. {
  98. return $this->sId;
  99. }
  100. function setUserId($iUserId)
  101. {
  102. $this->iUserId = $iUserId;
  103. $this->save();
  104. }
  105. function setValue($sKey, $mixedValue)
  106. {
  107. if(empty($this->sId))
  108. $this->start();
  109. $this->aData[$sKey] = $mixedValue;
  110. $this->save();
  111. }
  112. function unsetValue($sKey)
  113. {
  114. if(empty($this->sId))
  115. $this->start();
  116. unset($this->aData[$sKey]);
  117. if(!empty($this->aData))
  118. $this->save();
  119. else
  120. $this->destroy();
  121. }
  122. function isValue($sKey)
  123. {
  124. if(empty($this->sId))
  125. $this->start();
  126. return isset($this->aData[$sKey]);
  127. }
  128. function getValue($sKey)
  129. {
  130. if(empty($this->sId))
  131. $this->start();
  132. return isset($this->aData[$sKey]) ? $this->aData[$sKey] : false;
  133. }
  134. function getUnsetValue($sKey)
  135. {
  136. $mixedValue = $this->getValue($sKey);
  137. if($mixedValue !== false)
  138. $this->unsetValue($sKey);
  139. return $mixedValue;
  140. }
  141. public function maintenance()
  142. {
  143. return $this->oDb->deleteExpired();
  144. }
  145. protected function save()
  146. {
  147. if($this->iUserId == 0)
  148. $this->iUserId = getLoggedId();
  149. $this->oDb->save($this->sId, array(
  150. 'user_id' => $this->iUserId,
  151. 'data' => serialize($this->aData)
  152. ));
  153. }
  154. }
  155. /** @} */