00001 <?php
00002
00003 DEFINE('_DB_SESSION_HANDLER', getShopBasePath() . 'core/adodblite/session/adodb-session.php');
00004
00005 if (oxConfig::getInstance()->getConfigParam( 'blAdodbSessionHandler' ) ) {
00006 $oDB = oxDb::getDb();
00007 include_once _DB_SESSION_HANDLER;
00008 }
00009
00015 class oxSession extends oxSuperCfg
00016 {
00022 protected $_sName = 'sid';
00023
00029 protected $_sForcedPrefix = 'force_';
00030
00035 protected $_sId = null;
00036
00042 protected static $_blIsNewSession = false;
00043
00047 protected static $_instance = null;
00048
00053 protected static $_oUser = null;
00054
00061 protected $_blNewSession = false;
00062
00068 protected $_blForceNewSession = false;
00069
00075 protected $_sErrorMsg = null;
00076
00082 protected $_oBasket = null;
00083
00089 protected $_oBasketReservations = null;
00090
00099 protected $_aRequireSessionWithParams = array(
00100 'cl' => array (
00101 'register' => true,
00102 'account' => true,
00103 ),
00104 'fnc' => array (
00105 'tobasket' => true,
00106 'login_noredirect' => true,
00107 'tocomparelist' => true,
00108 ),
00109 '_artperpage' => true,
00110 'ldtype' => true,
00111 'listorderby' => true,
00112 );
00113
00119 protected $_blSidNeeded = null;
00120
00126 protected $_aPersistentParams = array("actshop", "lang", "currency", "language", "tpllanguage");
00127
00133 public static function getInstance()
00134 {
00135 if ( defined('OXID_PHP_UNIT')) {
00136 if ( isset( modSession::$unitMOD) && is_object( modSession::$unitMOD)) {
00137 return modSession::$unitMOD;
00138 }
00139 }
00140 if (!isset(self::$_instance)) {
00141 self::$_instance = oxNew( 'oxsession' );
00142 }
00143 return self::$_instance;
00144 }
00145
00151 public function getId()
00152 {
00153 return $this->_sId;
00154 }
00155
00163 public function setId($sVal)
00164 {
00165 $this->_sId = $sVal;
00166 }
00167
00175 public function setName($sVal)
00176 {
00177 $this->_sName = $sVal;
00178 }
00179
00185 public function getForcedName()
00186 {
00187 return $this->_sForcedPrefix . $this->getName();
00188 }
00189
00195 public function getName()
00196 {
00197 return $this->_sName;
00198 }
00199
00205 public function start()
00206 {
00207 $myConfig = $this->getConfig();
00208 $sid = null;
00209
00210 if ( $this->isAdmin() ) {
00211 $this->setName("admin_sid");
00212 } else {
00213 $this->setName("sid");
00214 }
00215
00216 $sForceSidParam = oxConfig::getParameter($this->getForcedName());
00217 $sSidParam = oxConfig::getParameter($this->getName());
00218
00219
00220 if ($sForceSidParam) {
00221 $sid = $sForceSidParam;
00222 } elseif ($this->_getSessionUseCookies() && $this->_getCookieSid()) {
00223 $sid = $this->_getCookieSid();
00224 } elseif ($sSidParam) {
00225 $sid = $sSidParam;
00226 }
00227
00228
00229 if ( $this->_allowSessionStart() ) {
00230
00231
00232 if ( !$sid ) {
00233 self::$_blIsNewSession = true;
00234 $this->initNewSession();
00235 } else {
00236 self::$_blIsNewSession = false;
00237 $this->_setSessionId( $sid );
00238 $this->_sessionStart();
00239 }
00240
00241
00242 if ( $this->_sId != session_id() ) {
00243 $this->_setSessionId( session_id() );
00244 }
00245
00246
00247 $blSwapped = $this->_isSwappedClient();
00248 if ( !self::$_blIsNewSession && $blSwapped ) {
00249 $this->initNewSession();
00250
00251
00252 if ( $this->_sErrorMsg && $myConfig->getConfigParam( 'iDebug' ) ) {
00253 oxUtilsView::getInstance()->addErrorToDisplay( new oxException( $this->_sErrorMsg ) );
00254 }
00255 } elseif ( !$blSwapped ) {
00256
00257 oxUtilsServer::getInstance()->loadSessionCookies();
00258 }
00259 }
00260 }
00261
00267 public function getRequestChallengeToken()
00268 {
00269 return preg_replace('/[^a-z0-9]/i', '', oxConfig::getParameter('stoken'));
00270 }
00271
00277 public function getSessionChallengeToken()
00278 {
00279 $sRet = preg_replace('/[^a-z0-9]/i', '', self::getVar('sess_stoken'));
00280 if (!$sRet) {
00281 $this->_initNewSessionChallenge();
00282 $sRet = self::getVar('sess_stoken');
00283 }
00284 return $sRet;
00285 }
00286
00293 public function checkSessionChallenge()
00294 {
00295 $sToken = $this->getSessionChallengeToken();
00296 return $sToken && ($sToken == $this->getRequestChallengeToken());
00297 }
00298
00304 protected function _initNewSessionChallenge()
00305 {
00306 self::setVar('sess_stoken', sprintf('%X', crc32(oxUtilsObject::getInstance()->generateUID())));
00307 }
00308
00314 protected function _sessionStart()
00315 {
00316
00317 session_cache_limiter( 'nocache' );
00318
00319
00320
00321 if (strpos($_SERVER['HTTP_USER_AGENT'], 'AOL') !== false ) {
00322 session_cache_limiter(false);
00323 header("Cache-Control: no-store, private, must-revalidate, proxy-revalidate, post-check=0, pre-check=0, max-age=0, s-maxage=0");
00324 }
00325
00326 $blStarted = @session_start();
00327 if ( !$this->getSessionChallengeToken() ) {
00328 $this->_initNewSessionChallenge();
00329 }
00330
00331 return $blStarted;
00332 }
00333
00339 public function initNewSession()
00340 {
00341
00342 if ( self::$_blIsNewSession ) {
00343 $this->_sessionStart();
00344 }
00345
00346
00347 $aPersistent = array();
00348 foreach ( $this->_aPersistentParams as $sParam ) {
00349 if ( ( $sValue = self::getVar( $sParam ) ) ) {
00350 $aPersistent[$sParam] = $sValue;
00351 }
00352 }
00353
00354 $this->_setSessionId( $this->_getNewSessionId() );
00355
00356
00357 foreach ( $aPersistent as $sKey => $sParam ) {
00358 self::setVar( $sKey, $aPersistent[$sKey] );
00359 }
00360
00361 $this->_initNewSessionChallenge();
00362
00363
00364 self::setVar( "sessionagent", oxUtilsServer::getInstance()->getServerVar( 'HTTP_USER_AGENT' ) );
00365 }
00366
00372 public function regenerateSessionId()
00373 {
00374
00375 if ( self::$_blIsNewSession ) {
00376 $this->_sessionStart();
00377
00378
00379 self::setVar( "sessionagent", oxUtilsServer::getInstance()->getServerVar( 'HTTP_USER_AGENT' ) );
00380 }
00381
00382 $this->_setSessionId( $this->_getNewSessionId( false ) );
00383 $this->_initNewSessionChallenge();
00384 }
00385
00394 protected function _getNewSessionId( $blUnset = true )
00395 {
00396 session_regenerate_id( true );
00397 if ( $blUnset ) {
00398 session_unset();
00399 }
00400 return session_id();
00401 }
00402
00408 public function freeze()
00409 {
00410
00411 self::setVar( $this->_getBasketName(), serialize( $this->getBasket() ) );
00412
00413 session_write_close();
00414 }
00415
00421 public function destroy()
00422 {
00423
00424 unset($_SESSION);
00425 session_destroy();
00426 }
00427
00435 public static function hasVar( $name )
00436 {
00437 if ( defined( 'OXID_PHP_UNIT' ) ) {
00438 if ( isset( modSession::$unitMOD ) && is_object( modSession::$unitMOD ) ) {
00439 try{
00440 $sVal = modSession::getInstance()->getVar( $name );
00441 return isset( $sVal );
00442 } catch( Exception $e ) {
00443
00444 }
00445 }
00446 }
00447
00448 return isset($_SESSION[$name]);
00449 }
00450
00459 public static function setVar( $name, $value)
00460 {
00461 if ( defined( 'OXID_PHP_UNIT' ) ) {
00462 if ( isset( modSession::$unitMOD ) && is_object( modSession::$unitMOD ) ) {
00463 try{
00464 return modSession::getInstance()->setVar( $name, $value );
00465 } catch( Exception $e ) {
00466
00467 }
00468 }
00469 }
00470
00471 $_SESSION[$name] = $value;
00472
00473 }
00474
00482 public static function getVar( $name )
00483 {
00484 if ( defined( 'OXID_PHP_UNIT' ) ) {
00485 if ( isset( modSession::$unitMOD ) && is_object( modSession::$unitMOD ) ) {
00486 try{
00487 return modSession::getInstance()->getVar( $name );
00488 } catch( Exception $e ) {
00489
00490 }
00491 }
00492 }
00493
00494 if ( isset( $_SESSION[$name] )) {
00495 return $_SESSION[$name];
00496 } else {
00497 return null;
00498 }
00499 }
00500
00508 public static function deleteVar( $name )
00509 {
00510 if ( defined( 'OXID_PHP_UNIT' ) ) {
00511 if ( isset( modSession::$unitMOD ) && is_object( modSession::$unitMOD ) ) {
00512 try{
00513 return modSession::getInstance()->setVar( $name, null );
00514 } catch( Exception $e ) {
00515
00516 }
00517 }
00518 }
00519
00520 $_SESSION[$name] = null;
00521
00522 unset($_SESSION[$name]);
00523 }
00524
00534 public function sid( $blForceSid = false )
00535 {
00536 $myConfig = $this->getConfig();
00537 $blUseCookies = $this->_getSessionUseCookies();
00538 $sRet = '';
00539
00540 $blDisableSid = oxUtils::getInstance()->isSearchEngine()
00541 && is_array($myConfig->getConfigParam( 'aCacheViews' ) )
00542 && !$this->isAdmin();
00543
00544
00545 if ( !$blDisableSid && $this->getId() && ($blForceSid || !$blUseCookies || !$this->_getCookieSid())) {
00546 $sRet = ( $blForceSid ? $this->getForcedName() : $this->getName() )."=".$this->getId();
00547 }
00548
00549 if ($this->isAdmin()) {
00550
00551 if ($sRet) {
00552 $sRet .= '&';
00553 }
00554 $sRet .= 'stoken='.$this->getSessionChallengeToken();
00555 }
00556
00557 return $sRet;
00558 }
00559
00565 public function hiddenSid()
00566 {
00567 $sToken = "<input type=\"hidden\" name=\"stoken\" value=\"".$this->getSessionChallengeToken(). "\">";
00568 $sSid = "<input type=\"hidden\" name=\"".$this->getForcedName()."\" value=\"". $this->getId() . "\">";
00569 return $sToken.$sSid;
00570 }
00571
00577 public function getBasket()
00578 {
00579 if ( $this->_oBasket === null ) {
00580 $sBasket = self::getVar( $this->_getBasketName() );
00581
00582
00583
00584 oxNew('oxbasketitem');
00585
00586 $oBasket = ( $sBasket && ( $oBasket = unserialize( $sBasket ) ) ) ? $oBasket : oxNew( 'oxbasket' );
00587 $this->setBasket( $oBasket );
00588 }
00589
00590 return $this->_oBasket;
00591 }
00592
00600 public function setBasket( $oBasket )
00601 {
00602
00603 $this->_oBasket = $oBasket;
00604 }
00605
00611 public function delBasket()
00612 {
00613 $this->setBasket( null );
00614 self::deleteVar( $this->_getBasketName());
00615 }
00616
00622 public function isNewSession()
00623 {
00624 return self::$_blIsNewSession;
00625 }
00626
00633 public function setForceNewSession()
00634 {
00635 $this->_blForceNewSession = true;
00636 }
00637
00645 public function isSidNeeded( $sUrl = null )
00646 {
00647 if ( $this->_getSessionUseCookies() && $this->_getCookieSid() ) {
00648
00649 if ( ( strpos( $sUrl, "https:" ) === 0 && !$this->getConfig()->isSsl() ) ||
00650 ( strpos( $sUrl, "http:" ) === 0 && $this->getConfig()->isSsl() ) ) {
00651 return true;
00652 }
00653 }
00654
00655 if ( $sUrl && !$this->getConfig()->isCurrentUrl( $sUrl ) ) {
00656 return true;
00657 } elseif ( $this->_blSidNeeded === null ) {
00658
00659 $this->_blSidNeeded = false;
00660
00661
00662 if ( !oxUtils::getInstance()->isSearchEngine() ) {
00663
00664 if ( oxUtilsServer::getInstance()->getOxCookie( $this->getName() ) ) {
00665 $this->_blSidNeeded = false;
00666 } elseif ( $this->_forceSessionStart() ) {
00667 $this->_blSidNeeded = true;
00668 } else {
00669
00670 if ( $blSidNeeded = self::getVar( 'blSidNeeded' ) ) {
00671 $this->_blSidNeeded = true;
00672 } elseif ( $this->_isSessionRequiredAction() ) {
00673 $this->_blSidNeeded = true;
00674
00675
00676 self::setVar( 'blSidNeeded', $this->_blSidNeeded );
00677 }
00678 }
00679 }
00680 }
00681
00682 return $this->_blSidNeeded;
00683 }
00684
00696 public function processUrl( $sUrl )
00697 {
00698 $sSid = $this->sid( $this->isSidNeeded( $sUrl ) );
00699 if ($sSid) {
00700 $oStr = getStr();
00701 if ( !$oStr->preg_match('/(\?|&(amp;)?)sid=/i', $sUrl) && (false === $oStr->strpos($sUrl, $sSid))) {
00702 if (!$oStr->preg_match('/(\?|&(amp;)?)$/', $sUrl)) {
00703 $sUrl .= ( $oStr->strstr( $sUrl, '?' ) !== false ? '&' : '?' );
00704 }
00705 $sUrl .= $sSid . '&';
00706 }
00707 }
00708 return $sUrl;
00709 }
00710
00720 public function getRemoteAccessToken($blGenerateNew = true)
00721 {
00722 $sToken = $this->getVar('_rtoken');
00723 if (!$sToken && $blGenerateNew) {
00724 $sToken = md5(rand() . $this->getId());
00725 $sToken = substr($sToken, 0, 8);
00726 $this->setVar('_rtoken', $sToken);
00727 }
00728
00729 return $sToken;
00730 }
00731
00738 protected function _forceSessionStart()
00739 {
00740 return ( !oxUtils::getInstance()->isSearchEngine() ) && ( (( bool ) $this->getConfig()->getConfigParam( 'blForceSessionStart' )) || oxConfig::getParameter( "su" ) || $this->_blForceNewSession );
00741 }
00742
00748 protected function _allowSessionStart()
00749 {
00750 $blAllowSessionStart = true;
00751
00752
00753 if ( !$this->isAdmin() ) {
00754 if ( oxUtils::getInstance()->isSearchEngine() || oxConfig::getParameter( 'skipSession' ) ) {
00755 $blAllowSessionStart = false;
00756 } elseif ( !$this->_forceSessionStart() && !oxUtilsServer::getInstance()->getOxCookie( 'sid_key' ) ) {
00757
00758
00759
00760
00761 if ( !oxUtilsServer::getInstance()->getOxCookie( $this->getName() ) &&
00762 !( oxConfig::getParameter( $this->getName() ) || oxConfig::getParameter( $this->getForcedName() ) ) &&
00763 !$this->_isSessionRequiredAction() ) {
00764 $blAllowSessionStart = false;
00765 }
00766 }
00767 }
00768
00769 return $blAllowSessionStart;
00770 }
00771
00779 protected function _isSwappedClient()
00780 {
00781 $blSwapped = false;
00782 $myUtilsServer = oxUtilsServer::getInstance();
00783
00784
00785 if ( !oxUtils::getInstance()->isSearchEngine() && !$myUtilsServer->isTrustedClientIp() && !$this->_isValidRemoteAccessToken()) {
00786
00787 $myConfig = $this->getConfig();
00788
00789
00790 $blSwapped = $this->_checkUserAgent( $myUtilsServer->getServerVar( 'HTTP_USER_AGENT' ), self::getVar( 'sessionagent' ) );
00791 if ( !$blSwapped ) {
00792 if ( $myConfig->getConfigParam( 'blAdodbSessionHandler' ) ) {
00793 $blSwapped = $this->_checkSid();
00794 }
00795
00796 if ( !$blSwapped ) {
00797 $blDisableCookieCheck = $myConfig->getConfigParam( 'blDisableCookieCheck' );
00798 $blUseCookies = $this->_getSessionUseCookies();
00799 if ( !$blDisableCookieCheck && $blUseCookies ) {
00800 $blSwapped = $this->_checkCookies( $myUtilsServer->getOxCookie( 'sid_key' ), self::getVar( "sessioncookieisset" ) );
00801 }
00802 }
00803 }
00804 }
00805
00806 return $blSwapped;
00807 }
00808
00817 protected function _checkUserAgent( $sAgent, $sExistingAgent )
00818 {
00819 $blCheck = false;
00820
00821
00822 $oUtils = oxUtilsServer::getInstance();
00823 $sAgent = $oUtils->processUserAgentInfo( $sAgent );
00824 $sExistingAgent = $oUtils->processUserAgentInfo( $sExistingAgent );
00825
00826 if ( $sAgent && $sAgent !== $sExistingAgent ) {
00827 if ( $sExistingAgent ) {
00828 $this->_sErrorMsg = "Different browser ({$sExistingAgent}, {$sAgent}), creating new SID...<br>";
00829 }
00830 $blCheck = true;
00831 }
00832
00833 return $blCheck;
00834 }
00835
00841 protected function _checkSid()
00842 {
00843
00844 $sSID = oxDb::getDb()->GetOne("select SessionID from oxsessions where SessionID = '".$this->getId()."'");
00845
00846
00847
00848 if ( !$this->_blNewSession && (!isset( $sSID) || !$sSID)) {
00849
00850 $this->_sErrorMsg = "Session has expired in the past and someone uses this sid to reactivate it, creating new SID...<br>";
00851 return true;
00852 }
00853 return false;
00854 }
00855
00865 protected function _checkCookies( $sCookieSid, $aSessCookieSetOnce )
00866 {
00867 $blSwapped = false;
00868 $myConfig = $this->getConfig();
00869 $sCurrUrl = $myConfig->isSsl() ? $myConfig->getSslShopUrl( 0 ) : $myConfig->getShopUrl( 0 );
00870
00871 $blSessCookieSetOnce = false;
00872 if ( isset( $aSessCookieSetOnce[$sCurrUrl] ) ) {
00873 $blSessCookieSetOnce = $aSessCookieSetOnce[$sCurrUrl];
00874 }
00875
00876
00877 if ( $blSessCookieSetOnce && !$sCookieSid ) {
00878 if ( $myConfig->getConfigParam( 'iDebug' ) ) {
00879 $this->_sErrorMsg = "Cookie not found, creating new SID...<br>";
00880 $this->_sErrorMsg .= "Cookie: $sCookieSid<br>";
00881 $this->_sErrorMsg .= "Session: $blSessCookieSetOnce<br>";
00882 $this->_sErrorMsg .= "URL: ".$sCurrUrl."<br>";
00883 }
00884 $blSwapped = true;
00885 }
00886
00887
00888 if ( $sCookieSid == "oxid" && !$blSessCookieSetOnce ) {
00889 $aSessCookieSetOnce[$sCurrUrl] = "ox_true";
00890 self::setVar( "sessioncookieisset", $aSessCookieSetOnce );
00891 }
00892
00893
00894 if ( !$sCookieSid ) {
00895 oxUtilsServer::getInstance()->setOxCookie( 'sid_key', 'oxid' );
00896 }
00897 return $blSwapped;
00898 }
00899
00907 protected function _setSessionId($sSessId)
00908 {
00909
00910 if ( $sSessId && session_id() != $sSessId ) {
00911 $this->_blNewSession = true;
00912 }
00913
00914 session_id( $sSessId );
00915
00916 $this->setId( $sSessId );
00917
00918 $blUseCookies = $this->_getSessionUseCookies();
00919
00920 if ( !$this->_allowSessionStart() ) {
00921 if ( $blUseCookies ) {
00922 oxUtilsServer::getInstance()->setOxCookie( $this->getName(), null );
00923 }
00924 return;
00925 }
00926
00927 if ( $blUseCookies ) {
00928
00929 oxUtilsServer::getInstance()->setOxCookie( $this->getName(), $sSessId );
00930 }
00931 }
00932
00938 protected function _getBasketName()
00939 {
00940 $myConfig = $this->getConfig();
00941 if ( $myConfig->getConfigParam( 'blMallSharedBasket' ) == 0 ) {
00942 return $myConfig->getShopId()."_basket";
00943 }
00944 return "basket";
00945 }
00946
00952 protected function _getCookieSid()
00953 {
00954 return oxUtilsServer::getInstance()->getOxCookie($this->getName());
00955 }
00956
00963 protected function _getRequireSessionWithParams()
00964 {
00965 $aCfgArray = $this->getConfig()->getConfigParam('aRequireSessionWithParams');
00966 if (is_array($aCfgArray)) {
00967 $aDefault = $this->_aRequireSessionWithParams;
00968 foreach ($aCfgArray as $key => $val) {
00969 if (!is_array($val) && $val) {
00970 unset($aDefault[$key]);
00971 }
00972 }
00973 return array_merge_recursive($aCfgArray, $aDefault);
00974 }
00975 return $this->_aRequireSessionWithParams;
00976 }
00977
00983 protected function _isSessionRequiredAction()
00984 {
00985 foreach ($this->_getRequireSessionWithParams() as $sParam => $aValues) {
00986 $sValue = oxConfig::getParameter( $sParam );
00987 if (isset($sValue)) {
00988 if (is_array($aValues)) {
00989 if (isset($aValues[$sValue]) && $aValues[$sValue]) {
00990 return true;
00991 }
00992 } elseif ($aValues) {
00993 return true;
00994 }
00995 }
00996 }
00997
00998 return ($_SERVER['REQUEST_METHOD'] == 'POST');
00999 }
01000
01006 protected function _getSessionUseCookies()
01007 {
01008 return $this->isAdmin() || $this->getConfig()->getConfigParam( 'blSessionUseCookies');
01009 }
01010
01016 protected function _isValidRemoteAccessToken()
01017 {
01018 $sInputToken = oxConfig::getInstance()->getParameter('rtoken');
01019 $sToken = $this->getRemoteAccessToken(false);
01020 $blTokenEqual = !(bool)strcmp($sInputToken, $sToken);
01021 $blValid = $sInputToken && $blTokenEqual;
01022
01023 return $blValid;
01024 }
01025
01031 public function getBasketReservations()
01032 {
01033 if (!$this->_oBasketReservations) {
01034 $this->_oBasketReservations = oxNew('oxBasketReservation');
01035 }
01036 return $this->_oBasketReservations;
01037 }
01038
01044 public function isHeaderSent()
01045 {
01046 return headers_sent();
01047 }
01048
01049 }