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 $_sErrorMsg = null;
00069
00075 protected $_oBasket = null;
00076
00082 protected $_oBasketReservations = null;
00083
00092 protected $_aRequireCookiesInFncs = array();
00093
00102 protected $_aRequireSessionWithParams = array(
00103 'cl' => array (
00104 'register' => true,
00105 'account' => true,
00106 ),
00107 'fnc' => array (
00108 'tobasket' => true,
00109 'login_noredirect' => true,
00110 'tocomparelist' => true,
00111 ),
00112 '_artperpage' => true,
00113 'listorderby' => true,
00114 );
00115
00121 protected $_blSidNeeded = null;
00122
00128 protected $_aPersistentParams = array("actshop", "lang", "currency", "language", "tpllanguage");
00129
00135 public static function getInstance()
00136 {
00137 if ( defined('OXID_PHP_UNIT')) {
00138 if ( isset( modSession::$unitMOD) && is_object( modSession::$unitMOD)) {
00139 return modSession::$unitMOD;
00140 }
00141 }
00142 if (!isset(self::$_instance)) {
00143 self::$_instance = oxNew( 'oxsession' );
00144 }
00145 return self::$_instance;
00146 }
00147
00153 public function getId()
00154 {
00155 return $this->_sId;
00156 }
00157
00165 public function setId($sVal)
00166 {
00167 $this->_sId = $sVal;
00168 }
00169
00177 public function setName($sVal)
00178 {
00179 $this->_sName = $sVal;
00180 }
00181
00187 public function getForcedName()
00188 {
00189 return $this->_sForcedPrefix . $this->getName();
00190 }
00191
00197 public function getName()
00198 {
00199 return $this->_sName;
00200 }
00201
00207 public function start()
00208 {
00209 $myConfig = $this->getConfig();
00210 $sid = null;
00211
00212 if ( $this->isAdmin() ) {
00213 $this->setName("admin_sid");
00214 } else {
00215 $this->setName("sid");
00216 }
00217
00218 $sForceSidParam = oxConfig::getParameter($this->getForcedName());
00219 $sSidParam = oxConfig::getParameter($this->getName());
00220
00221
00222 if ($sForceSidParam) {
00223 $sid = $sForceSidParam;
00224 } elseif ($this->_getSessionUseCookies() && $this->_getCookieSid()) {
00225 $sid = $this->_getCookieSid();
00226 } elseif ($sSidParam) {
00227 $sid = $sSidParam;
00228 }
00229
00230
00231 if ( $this->_allowSessionStart() ) {
00232
00233
00234 if ( !$sid ) {
00235 self::$_blIsNewSession = true;
00236 $this->initNewSession();
00237 } else {
00238 self::$_blIsNewSession = false;
00239 $this->_setSessionId( $sid );
00240 $this->_sessionStart();
00241 }
00242
00243
00244 if ( $this->_sId != session_id() ) {
00245 $this->_setSessionId( session_id() );
00246 }
00247
00248
00249 $blSwapped = $this->_isSwappedClient();
00250 if ( !self::$_blIsNewSession && $blSwapped ) {
00251 $this->initNewSession();
00252
00253
00254 if ( $this->_sErrorMsg && $myConfig->getConfigParam( 'iDebug' ) ) {
00255 oxUtilsView::getInstance()->addErrorToDisplay( new oxException( $this->_sErrorMsg ) );
00256 }
00257 } elseif ( !$blSwapped ) {
00258
00259 oxUtilsServer::getInstance()->loadSessionCookies();
00260 }
00261 }
00262 }
00263
00269 public function getRequestChallengeToken()
00270 {
00271 return preg_replace('/[^a-z0-9]/i', '', oxConfig::getParameter('stoken'));
00272 }
00273
00279 public function getSessionChallengeToken()
00280 {
00281 $sRet = preg_replace('/[^a-z0-9]/i', '', self::getVar('sess_stoken'));
00282 if (!$sRet) {
00283 $this->_initNewSessionChallenge();
00284 $sRet = self::getVar('sess_stoken');
00285 }
00286 return $sRet;
00287 }
00288
00295 public function checkSessionChallenge()
00296 {
00297 $sToken = $this->getSessionChallengeToken();
00298 return $sToken && ($sToken == $this->getRequestChallengeToken());
00299 }
00300
00306 protected function _initNewSessionChallenge()
00307 {
00308 self::setVar('sess_stoken', sprintf('%X', crc32(oxUtilsObject::getInstance()->generateUID())));
00309 }
00310
00316 protected function _sessionStart()
00317 {
00318
00319 session_cache_limiter( 'nocache' );
00320
00321
00322
00323 if (strpos($_SERVER['HTTP_USER_AGENT'], 'AOL') !== false ) {
00324 session_cache_limiter(false);
00325 header("Cache-Control: no-store, private, must-revalidate, proxy-revalidate, post-check=0, pre-check=0, max-age=0, s-maxage=0");
00326 }
00327
00328 $blStarted = @session_start();
00329 if ( !$this->getSessionChallengeToken() ) {
00330 $this->_initNewSessionChallenge();
00331 }
00332
00333 return $blStarted;
00334 }
00335
00341 public function initNewSession()
00342 {
00343
00344 if ( self::$_blIsNewSession ) {
00345 $this->_sessionStart();
00346 }
00347
00348
00349 $aPersistent = array();
00350 foreach ( $this->_aPersistentParams as $sParam ) {
00351 if ( ( $sValue = self::getVar( $sParam ) ) ) {
00352 $aPersistent[$sParam] = $sValue;
00353 }
00354 }
00355
00356 $this->_setSessionId( $this->_getNewSessionId() );
00357
00358
00359 foreach ( $aPersistent as $sKey => $sParam ) {
00360 self::setVar( $sKey, $aPersistent[$sKey] );
00361 }
00362
00363 $this->_initNewSessionChallenge();
00364
00365
00366 self::setVar( "sessionagent", oxUtilsServer::getInstance()->getServerVar( 'HTTP_USER_AGENT' ) );
00367 }
00368
00375 protected function _getNewSessionId()
00376 {
00377 session_regenerate_id( true );
00378 session_unset();
00379 return session_id();
00380 }
00381
00387 public function freeze()
00388 {
00389
00390 self::setVar( $this->_getBasketName(), serialize( $this->getBasket() ) );
00391
00392 session_write_close();
00393 }
00394
00400 public function destroy()
00401 {
00402
00403 unset($_SESSION);
00404 session_destroy();
00405 }
00406
00414 public static function hasVar( $name )
00415 {
00416 if ( defined( 'OXID_PHP_UNIT' ) ) {
00417 if ( isset( modSession::$unitMOD ) && is_object( modSession::$unitMOD ) ) {
00418 try{
00419 $sVal = modSession::getInstance()->getVar( $name );
00420 return isset( $sVal );
00421 } catch( Exception $e ) {
00422
00423 }
00424 }
00425 }
00426
00427 return isset($_SESSION[$name]);
00428 }
00429
00438 public static function setVar( $name, $value)
00439 {
00440 if ( defined( 'OXID_PHP_UNIT' ) ) {
00441 if ( isset( modSession::$unitMOD ) && is_object( modSession::$unitMOD ) ) {
00442 try{
00443 return modSession::getInstance()->setVar( $name, $value );
00444 } catch( Exception $e ) {
00445
00446 }
00447 }
00448 }
00449
00450 $_SESSION[$name] = $value;
00451
00452 }
00453
00461 public static function getVar( $name )
00462 {
00463 if ( defined( 'OXID_PHP_UNIT' ) ) {
00464 if ( isset( modSession::$unitMOD ) && is_object( modSession::$unitMOD ) ) {
00465 try{
00466 return modSession::getInstance()->getVar( $name );
00467 } catch( Exception $e ) {
00468
00469 }
00470 }
00471 }
00472
00473 if ( isset( $_SESSION[$name] )) {
00474 return $_SESSION[$name];
00475 } else {
00476 return null;
00477 }
00478 }
00479
00487 public static function deleteVar( $name )
00488 {
00489 if ( defined( 'OXID_PHP_UNIT' ) ) {
00490 if ( isset( modSession::$unitMOD ) && is_object( modSession::$unitMOD ) ) {
00491 try{
00492 return modSession::getInstance()->setVar( $name, null );
00493 } catch( Exception $e ) {
00494
00495 }
00496 }
00497 }
00498
00499 $_SESSION[$name] = null;
00500
00501 unset($_SESSION[$name]);
00502 }
00503
00514 public function url( $sUrl )
00515 {
00516 $myConfig = $this->getConfig();
00517 $blUseCookies = $this->_getSessionUseCookies();
00518 $sSeparator = getStr()->strstr( $sUrl, "?" ) !== false ? "&" : "?";
00519 $sUrl .= $sSeparator;
00520
00521 if ( $blUseCookies && $this->_getCookieSid() ) {
00522
00523 if ( ( strpos( $sUrl, "https:" ) === 0 && !$myConfig->isSsl() ) ||
00524 ( strpos( $sUrl, "http:" ) === 0 && $myConfig->isSsl() ) ) {
00525 $sUrl .= $this->getForcedName(). '=' . $this->getId() . "&";
00526 }
00527 if ($this->isAdmin()) {
00528
00529 $sUrl .= 'stoken='.$this->getSessionChallengeToken().'&';
00530 }
00531 } elseif ( oxUtils::getInstance()->isSearchEngine() ) {
00532
00533 $sLangParam = (int) oxConfig::getParameter( "lang" );
00534 $sConfLang = (int) $myConfig->getConfigParam( "sDefaultLang" );
00535 if ( $sLangParam != $sConfLang ) {
00536 $sUrl .= "lang={$sLangParam}&";
00537 }
00538 } elseif ( ( $sIcludeParams = $this->sid() ) ) {
00539
00540 $sUrl .= "{$sIcludeParams}&";
00541 }
00542
00543 return $sUrl;
00544 }
00545
00555 public function sid( $blForceSid = false )
00556 {
00557 $myConfig = $this->getConfig();
00558 $blUseCookies = $this->_getSessionUseCookies();
00559 $sRet = '';
00560
00561 $blDisableSid = oxUtils::getInstance()->isSearchEngine()
00562 && is_array($myConfig->getConfigParam( 'aCacheViews' ) )
00563 && !$this->isAdmin();
00564
00565
00566 if ( !$blDisableSid && $this->getId() && ($blForceSid || !$blUseCookies || !$this->_getCookieSid())) {
00567 $sRet = ( $blForceSid ? $this->getForcedName() : $this->getName() )."=".$this->getId();
00568 }
00569
00570 if ($this->isAdmin()) {
00571
00572 if ($sRet) {
00573 $sRet .= '&';
00574 }
00575 $sRet .= 'stoken='.$this->getSessionChallengeToken();
00576 }
00577
00578 return $sRet;
00579 }
00580
00586 public function hiddenSid()
00587 {
00588 $sToken = "<input type=\"hidden\" name=\"stoken\" value=\"".$this->getSessionChallengeToken(). "\">";
00589 $sSid = "<input type=\"hidden\" name=\"".$this->getForcedName()."\" value=\"". $this->getId() . "\">";
00590 return $sToken.$sSid;
00591 }
00592
00598 public function getBasket()
00599 {
00600 if ( $this->_oBasket === null ) {
00601 $sBasket = self::getVar( $this->_getBasketName() );
00602
00603
00604
00605 oxNew('oxbasketitem');
00606
00607 $oBasket = ( $sBasket && ( $oBasket = unserialize( $sBasket ) ) ) ? $oBasket : oxNew( 'oxbasket' );
00608 $this->setBasket( $oBasket );
00609 }
00610
00611 return $this->_oBasket;
00612 }
00613
00621 public function setBasket( $oBasket )
00622 {
00623
00624 $this->_oBasket = $oBasket;
00625 }
00626
00632 public function delBasket()
00633 {
00634 $this->setBasket( null );
00635 self::deleteVar( $this->_getBasketName());
00636 }
00637
00643 public function isNewSession()
00644 {
00645 return self::$_blIsNewSession;
00646 }
00647
00655 public function isSidNeeded( $sUrl = null )
00656 {
00657 if ( $this->_getSessionUseCookies() && $this->_getCookieSid() ) {
00658
00659 if ( ( strpos( $sUrl, "https:" ) === 0 && !$this->getConfig()->isSsl() ) ||
00660 ( strpos( $sUrl, "http:" ) === 0 && $this->getConfig()->isSsl() ) ) {
00661 return true;
00662 }
00663 }
00664
00665 if ( $sUrl && !$this->getConfig()->isCurrentUrl( $sUrl ) ) {
00666 return true;
00667 } elseif ( $this->_blSidNeeded === null ) {
00668
00669 $this->_blSidNeeded = false;
00670
00671
00672 if ( !oxUtils::getInstance()->isSearchEngine() ) {
00673
00674 if ( oxUtilsServer::getInstance()->getOxCookie( $this->getName() ) ) {
00675 $this->_blSidNeeded = false;
00676 } elseif ( $this->_forceSessionStart() ) {
00677 $this->_blSidNeeded = true;
00678 } else {
00679
00680 if ( $blSidNeeded = self::getVar( 'blSidNeeded' ) ) {
00681 $this->_blSidNeeded = true;
00682 } elseif ( $this->_isSessionRequiredAction() ) {
00683 $this->_blSidNeeded = true;
00684
00685
00686 self::setVar( 'blSidNeeded', $this->_blSidNeeded );
00687 }
00688 }
00689 }
00690 }
00691
00692 return $this->_blSidNeeded;
00693 }
00694
00706 public function processUrl( $sUrl )
00707 {
00708 if (!$this->isAdmin()) {
00709 $sSid = '';
00710 if ( $this->isSidNeeded( $sUrl ) ) {
00711
00712 $sSid = $this->sid( true );
00713 } else {
00714 $sSid = $this->sid();
00715 }
00716 if ($sSid) {
00717 $oStr = getStr();
00718 if ( !$oStr->preg_match('/(\?|&(amp;)?)sid=/i', $sUrl) && (false === $oStr->strpos($sUrl, $sSid))) {
00719 if (!$oStr->preg_match('/(\?|&(amp;)?)$/', $sUrl)) {
00720 $sUrl .= ( $oStr->strstr( $sUrl, '?' ) !== false ? '&' : '?' );
00721 }
00722 $sUrl .= $sSid . '&';
00723 }
00724 }
00725 }
00726 return $sUrl;
00727 }
00728
00738 public function getRemoteAccessToken($blGenerateNew = true)
00739 {
00740 $sToken = $this->getVar('_rtoken');
00741 if (!$sToken && $blGenerateNew) {
00742 $sToken = md5(rand() . $this->getId());
00743 $sToken = substr($sToken, 0, 8);
00744 $this->setVar('_rtoken', $sToken);
00745 }
00746
00747 return $sToken;
00748 }
00749
00756 protected function _forceSessionStart()
00757 {
00758 return ( !oxUtils::getInstance()->isSearchEngine() ) && ( (( bool ) $this->getConfig()->getConfigParam( 'blForceSessionStart' )) || oxConfig::getParameter( "su" ) ) ;
00759 }
00760
00766 protected function _allowSessionStart()
00767 {
00768 $blAllowSessionStart = true;
00769
00770
00771 if ( !$this->isAdmin() ) {
00772 if ( oxUtils::getInstance()->isSearchEngine() || oxConfig::getParameter( 'skipSession' ) ) {
00773 $blAllowSessionStart = false;
00774 } elseif ( !$this->_forceSessionStart() && !oxUtilsServer::getInstance()->getOxCookie( 'sid_key' ) ) {
00775
00776
00777
00778
00779 if ( !oxUtilsServer::getInstance()->getOxCookie( $this->getName() ) &&
00780 !( oxConfig::getParameter( $this->getName() ) || oxConfig::getParameter( $this->getForcedName() ) ) &&
00781 !$this->_isSessionRequiredAction() ) {
00782 $blAllowSessionStart = false;
00783 }
00784 }
00785 }
00786
00787 return $blAllowSessionStart;
00788 }
00789
00797 protected function _isSwappedClient()
00798 {
00799 $blSwapped = false;
00800 $myUtilsServer = oxUtilsServer::getInstance();
00801
00802
00803 if ( !oxUtils::getInstance()->isSearchEngine() && !$myUtilsServer->isTrustedClientIp() && !$this->_isValidRemoteAccessToken()) {
00804
00805 $myConfig = $this->getConfig();
00806
00807
00808 $blSwapped = $this->_checkUserAgent( $myUtilsServer->getServerVar( 'HTTP_USER_AGENT' ), self::getVar( 'sessionagent' ) );
00809 if ( !$blSwapped ) {
00810 if ( $myConfig->getConfigParam( 'blAdodbSessionHandler' ) ) {
00811 $blSwapped = $this->_checkSid();
00812 }
00813
00814 if ( !$blSwapped ) {
00815 $blDisableCookieCheck = $myConfig->getConfigParam( 'blDisableCookieCheck' );
00816 $blUseCookies = $this->_getSessionUseCookies();
00817 if ( !$blDisableCookieCheck && $blUseCookies ) {
00818 $blSwapped = $this->_checkCookies( $myUtilsServer->getOxCookie( 'sid_key' ), self::getVar( "sessioncookieisset" ) );
00819 }
00820 }
00821 }
00822 }
00823
00824 return $blSwapped;
00825 }
00826
00835 protected function _checkUserAgent( $sAgent, $sExistingAgent )
00836 {
00837 $blCheck = false;
00838
00839
00840 $oUtils = oxUtilsServer::getInstance();
00841 $sAgent = $oUtils->processUserAgentInfo( $sAgent );
00842 $sExistingAgent = $oUtils->processUserAgentInfo( $sExistingAgent );
00843
00844 if ( $sAgent && $sAgent !== $sExistingAgent ) {
00845 if ( $sExistingAgent ) {
00846 $this->_sErrorMsg = "Different browser ({$sExistingAgent}, {$sAgent}), creating new SID...<br>";
00847 }
00848 $blCheck = true;
00849 }
00850
00851 return $blCheck;
00852 }
00853
00859 protected function _checkSid()
00860 {
00861
00862 $sSID = oxDb::getDb()->GetOne("select SessionID from oxsessions where SessionID = '".$this->getId()."'");
00863
00864
00865
00866 if ( !$this->_blNewSession && (!isset( $sSID) || !$sSID)) {
00867
00868 $this->_sErrorMsg = "Session has expired in the past and someone uses this sid to reactivate it, creating new SID...<br>";
00869 return true;
00870 }
00871 return false;
00872 }
00873
00883 protected function _checkCookies( $sCookieSid, $aSessCookieSetOnce )
00884 {
00885 $blSwapped = false;
00886 $myConfig = $this->getConfig();
00887 $sCurrUrl = $myConfig->isSsl() ? $myConfig->getSslShopUrl( 0 ) : $myConfig->getShopUrl( 0 );
00888
00889 $blSessCookieSetOnce = false;
00890 if ( isset( $aSessCookieSetOnce[$sCurrUrl] ) ) {
00891 $blSessCookieSetOnce = $aSessCookieSetOnce[$sCurrUrl];
00892 }
00893
00894
00895 if ( $blSessCookieSetOnce && !$sCookieSid ) {
00896 if ( $myConfig->getConfigParam( 'iDebug' ) ) {
00897 $this->_sErrorMsg = "Cookie not found, creating new SID...<br>";
00898 $this->_sErrorMsg .= "Cookie: $sCookieSid<br>";
00899 $this->_sErrorMsg .= "Session: $blSessCookieSetOnce<br>";
00900 $this->_sErrorMsg .= "URL: ".$sCurrUrl."<br>";
00901 }
00902 $blSwapped = true;
00903 }
00904
00905
00906 if ( $sCookieSid == "oxid" && !$blSessCookieSetOnce ) {
00907 $aSessCookieSetOnce[$sCurrUrl] = "ox_true";
00908 self::setVar( "sessioncookieisset", $aSessCookieSetOnce );
00909 }
00910
00911
00912 if ( !$sCookieSid ) {
00913 oxUtilsServer::getInstance()->setOxCookie( 'sid_key', 'oxid' );
00914 }
00915 return $blSwapped;
00916 }
00917
00925 protected function _setSessionId($sSessId)
00926 {
00927
00928 if ( $sSessId && session_id() != $sSessId ) {
00929 $this->_blNewSession = true;
00930 }
00931
00932 session_id( $sSessId );
00933
00934 $this->setId( $sSessId );
00935
00936 $blUseCookies = $this->_getSessionUseCookies();
00937
00938 if ( !$this->_allowSessionStart() ) {
00939 if ( $blUseCookies ) {
00940 oxUtilsServer::getInstance()->setOxCookie( $this->getName(), null );
00941 }
00942 return;
00943 }
00944
00945 if ( $blUseCookies ) {
00946
00947 oxUtilsServer::getInstance()->setOxCookie( $this->getName(), $sSessId );
00948 }
00949 }
00950
00956 protected function _getBasketName()
00957 {
00958 $myConfig = $this->getConfig();
00959 if ( $myConfig->getConfigParam( 'blMallSharedBasket' ) == 0 ) {
00960 return $myConfig->getShopId()."_basket";
00961 }
00962 return "basket";
00963 }
00964
00970 protected function _getCookieSid()
00971 {
00972 return oxUtilsServer::getInstance()->getOxCookie($this->getName());
00973 }
00974
00981 protected function _getRequireSessionWithParams()
00982 {
00983 $aCfgArray = $this->getConfig()->getConfigParam('aRequireSessionWithParams');
00984 if (is_array($aCfgArray)) {
00985 $aDefault = $this->_aRequireSessionWithParams;
00986 foreach ($aCfgArray as $key => $val) {
00987 if (!is_array($val) && $val) {
00988 unset($aDefault[$key]);
00989 }
00990 }
00991 return array_merge_recursive($aCfgArray, $aDefault);
00992 }
00993 return $this->_aRequireSessionWithParams;
00994 }
00995
01001 protected function _isSessionRequiredAction()
01002 {
01003
01004 $sFunction = oxConfig::getParameter( 'fnc' );
01005 $sClass = oxConfig::getParameter( 'cl' );
01006
01007 if (( $sFunction && in_array( strtolower( $sFunction ), $this->_aRequireCookiesInFncs ) ) ||
01008 ( $sClass && array_key_exists( strtolower( $sClass ), $this->_aRequireCookiesInFncs ) )) {
01009 return true;
01010 }
01011
01012 foreach ($this->_getRequireSessionWithParams() as $sParam => $aValues) {
01013 $sValue = oxConfig::getParameter( $sParam );
01014 if (isset($sValue)) {
01015 if (is_array($aValues)) {
01016 if (isset($aValues[$sValue]) && $aValues[$sValue]) {
01017 return true;
01018 }
01019 } elseif ($aValues) {
01020 return true;
01021 }
01022 }
01023 }
01024
01025 return ($_SERVER['REQUEST_METHOD'] == 'POST');
01026 }
01027
01033 protected function _getSessionUseCookies()
01034 {
01035 return $this->isAdmin() || $this->getConfig()->getConfigParam( 'blSessionUseCookies');
01036 }
01037
01043 protected function _isValidRemoteAccessToken()
01044 {
01045 $sInputToken = oxConfig::getInstance()->getParameter('rtoken');
01046 $sToken = $this->getRemoteAccessToken(false);
01047 $blTokenEqual = !(bool)strcmp($sInputToken, $sToken);
01048 $blValid = $sInputToken && $blTokenEqual;
01049
01050 return $blValid;
01051 }
01052
01058 public function getBasketReservations()
01059 {
01060 if (!$this->_oBasketReservations) {
01061 $this->_oBasketReservations = oxNew('oxBasketReservation');
01062 }
01063 return $this->_oBasketReservations;
01064 }
01065 }