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
00085 protected $_aRequireCookiesInFncs = array();
00086
00095 protected $_aRequireSessionWithParams = array(
00096 'cl' => array (
00097 'register' => true,
00098 'account' => true,
00099 ),
00100 'fnc' => array (
00101 'tobasket' => true,
00102 'login_noredirect' => true,
00103 'tocomparelist' => true,
00104 ),
00105 '_artperpage' => true,
00106 'listorderby' => true,
00107 );
00108
00114 protected $_blSidNeeded = null;
00115
00121 protected $_aPersistentParams = array("actshop", "lang", "currency", "language", "tpllanguage");
00122
00128 public static function getInstance()
00129 {
00130 if ( defined('OXID_PHP_UNIT')) {
00131 if ( isset( modSession::$unitMOD) && is_object( modSession::$unitMOD)) {
00132 return modSession::$unitMOD;
00133 }
00134 }
00135 if (!isset(self::$_instance)) {
00136 self::$_instance = oxNew( 'oxsession' );
00137 }
00138 return self::$_instance;
00139 }
00140
00146 public function getId()
00147 {
00148 return $this->_sId;
00149 }
00150
00158 public function setId($sVal)
00159 {
00160 $this->_sId = $sVal;
00161 }
00162
00170 public function setName($sVal)
00171 {
00172 $this->_sName = $sVal;
00173 }
00174
00180 public function getForcedName()
00181 {
00182 return $this->_sForcedPrefix . $this->getName();
00183 }
00184
00190 public function getName()
00191 {
00192 return $this->_sName;
00193 }
00194
00200 public function start()
00201 {
00202 $myConfig = $this->getConfig();
00203 $sid = null;
00204
00205 if ( $this->isAdmin() ) {
00206 $this->setName("admin_sid");
00207 } else {
00208 $this->setName("sid");
00209 }
00210
00211 $sForceSidParam = oxConfig::getParameter($this->getForcedName());
00212 $sSidParam = oxConfig::getParameter($this->getName());
00213
00214
00215 if ($sForceSidParam) {
00216 $sid = $sForceSidParam;
00217 } elseif ($this->_getSessionUseCookies() && $this->_getCookieSid()) {
00218 $sid = $this->_getCookieSid();
00219 } elseif ($sSidParam) {
00220 $sid = $sSidParam;
00221 }
00222
00223
00224 if ( $this->_allowSessionStart() ) {
00225
00226
00227 if ( !$sid ) {
00228 self::$_blIsNewSession = true;
00229 $this->initNewSession();
00230 } else {
00231 self::$_blIsNewSession = false;
00232 $this->_setSessionId( $sid );
00233 $this->_sessionStart();
00234 }
00235
00236
00237 if ( $this->_sId != session_id() ) {
00238 $this->_setSessionId( session_id() );
00239 }
00240
00241
00242 if ( !self::$_blIsNewSession && $this->_isSwappedClient() ) {
00243 $this->initNewSession();
00244
00245
00246 if ( $this->_sErrorMsg && $myConfig->getConfigParam( 'iDebug' ) ) {
00247 oxUtilsView::getInstance()->addErrorToDisplay( new oxException( $this->_sErrorMsg ) );
00248 }
00249 }
00250 }
00251 }
00252
00258 public function getRequestChallengeToken()
00259 {
00260 return preg_replace('/[^a-z0-9]/i', '', oxConfig::getParameter('stoken'));
00261 }
00262
00268 public function getSessionChallengeToken()
00269 {
00270 $sRet = preg_replace('/[^a-z0-9]/i', '', self::getVar('sess_stoken'));
00271 if (!$sRet) {
00272 $this->_initNewSessionChallenge();
00273 $sRet = self::getVar('sess_stoken');
00274 }
00275 return $sRet;
00276 }
00277
00284 public function checkSessionChallenge()
00285 {
00286 $sToken = $this->getSessionChallengeToken();
00287 return $sToken && ($sToken == $this->getRequestChallengeToken());
00288 }
00289
00295 protected function _initNewSessionChallenge()
00296 {
00297 self::setVar('sess_stoken', sprintf('%X', crc32(oxUtilsObject::getInstance()->generateUID())));
00298 }
00299
00305 protected function _sessionStart()
00306 {
00307
00308 session_cache_limiter( 'nocache' );
00309
00310
00311
00312 if (strpos($_SERVER['HTTP_USER_AGENT'], 'AOL') !== false ) {
00313 session_cache_limiter(false);
00314 header("Cache-Control: no-store, private, must-revalidate, proxy-revalidate, post-check=0, pre-check=0, max-age=0, s-maxage=0");
00315 }
00316
00317 $ret = @session_start();
00318 if (!$this->getSessionChallengeToken()) {
00319 $this->_initNewSessionChallenge();
00320 }
00321
00322 return $ret;
00323 }
00324
00330 public function initNewSession()
00331 {
00332
00333 if ( self::$_blIsNewSession ) {
00334 $this->_sessionStart();
00335 }
00336
00337
00338 $aPersistent = array();
00339 foreach ($this->_aPersistentParams as $sParam) {
00340 if ( self::getVar($sParam)) {
00341 $aPersistent[$sParam] = self::getVar($sParam);
00342 }
00343 }
00344
00345 $sid = md5(oxUtilsObject::getInstance()->generateUID());
00346
00347 $this->_setSessionId($sid);
00348 session_unset();
00349
00350
00351 foreach ($aPersistent as $key => $sParam) {
00352 self::setVar($key, $aPersistent[$key]);
00353 }
00354
00355 $this->_initNewSessionChallenge();
00356
00357
00358 self::setVar( "sessionagent", oxUtilsServer::getInstance()->getServerVar( 'HTTP_USER_AGENT' ) );
00359 }
00360
00366 public function freeze()
00367 {
00368
00369 self::setVar( $this->_getBasketName(), serialize( $this->getBasket() ) );
00370
00371 session_write_close();
00372 }
00373
00379 public function destroy()
00380 {
00381
00382 unset($_SESSION);
00383 session_destroy();
00384 }
00385
00393 public static function hasVar( $name )
00394 {
00395 if ( defined( 'OXID_PHP_UNIT' ) ) {
00396 if ( isset( modSession::$unitMOD ) && is_object( modSession::$unitMOD ) ) {
00397 try{
00398 $sVal = modSession::getInstance()->getVar( $name );
00399 return isset( $sVal );
00400 } catch( Exception $e ) {
00401
00402 }
00403 }
00404 }
00405
00406 return isset($_SESSION[$name]);
00407 }
00408
00417 public static function setVar( $name, $value)
00418 {
00419 if ( defined( 'OXID_PHP_UNIT' ) ) {
00420 if ( isset( modSession::$unitMOD ) && is_object( modSession::$unitMOD ) ) {
00421 try{
00422 return modSession::getInstance()->setVar( $name, $value );
00423 } catch( Exception $e ) {
00424
00425 }
00426 }
00427 }
00428
00429 $_SESSION[$name] = $value;
00430
00431 }
00432
00440 public static function getVar( $name )
00441 {
00442 if ( defined( 'OXID_PHP_UNIT' ) ) {
00443 if ( isset( modSession::$unitMOD ) && is_object( modSession::$unitMOD ) ) {
00444 try{
00445 return modSession::getInstance()->getVar( $name );
00446 } catch( Exception $e ) {
00447
00448 }
00449 }
00450 }
00451
00452 if ( isset( $_SESSION[$name] )) {
00453 return $_SESSION[$name];
00454 } else {
00455 return null;
00456 }
00457 }
00458
00466 public static function deleteVar( $name )
00467 {
00468 if ( defined( 'OXID_PHP_UNIT' ) ) {
00469 if ( isset( modSession::$unitMOD ) && is_object( modSession::$unitMOD ) ) {
00470 try{
00471 return modSession::getInstance()->setVar( $name, null );
00472 } catch( Exception $e ) {
00473
00474 }
00475 }
00476 }
00477
00478 $_SESSION[$name] = null;
00479
00480 unset($_SESSION[$name]);
00481 }
00482
00493 public function url( $sUrl )
00494 {
00495 $myConfig = $this->getConfig();
00496 $blUseCookies = $this->_getSessionUseCookies();
00497 $sSeparator = getStr()->strstr( $sUrl, "?" ) !== false ? "&" : "?";
00498 $sUrl .= $sSeparator;
00499
00500 if ( $blUseCookies && $this->_getCookieSid() ) {
00501
00502 if ( ( strpos( $sUrl, "https:" ) === 0 && !$myConfig->isSsl() ) ||
00503 ( strpos( $sUrl, "http:" ) === 0 && $myConfig->isSsl() ) ) {
00504 $sUrl .= $this->getForcedName(). '=' . $this->getId() . "&";
00505 }
00506 if ($this->isAdmin()) {
00507
00508 $sUrl .= 'stoken='.$this->getSessionChallengeToken().'&';
00509 }
00510 } elseif ( oxUtils::getInstance()->isSearchEngine() ) {
00511
00512 $sLangParam = (int) oxConfig::getParameter( "lang" );
00513 $sConfLang = (int) $myConfig->getConfigParam( "sDefaultLang" );
00514 if ( $sLangParam != $sConfLang ) {
00515 $sUrl .= "lang={$sLangParam}&";
00516 }
00517 } elseif ( ( $sIcludeParams = $this->sid() ) ) {
00518
00519 $sUrl .= "{$sIcludeParams}&";
00520 }
00521
00522 return $sUrl;
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 if ( $sBasket && $oBasket = unserialize( $sBasket ) ) {
00587 $this->setBasket( $oBasket );
00588 } else {
00589 $this->setBasket( oxNew( 'oxbasket' ) );
00590 }
00591 }
00592
00593 return $this->_oBasket;
00594 }
00595
00603 public function setBasket( $oBasket )
00604 {
00605
00606 $this->_oBasket = $oBasket;
00607 }
00608
00614 public function delBasket()
00615 {
00616 $this->setBasket( null );
00617 self::deleteVar( $this->_getBasketName());
00618 }
00619
00625 public function isNewSession()
00626 {
00627 return self::$_blIsNewSession;
00628 }
00629
00637 public function isSidNeeded( $sUrl = null )
00638 {
00639 if ( $blUseCookies && $this->_getCookieSid() ) {
00640
00641 if ( ( strpos( $sUrl, "https:" ) === 0 && !$this->getConfig()->isSsl() ) ||
00642 ( strpos( $sUrl, "http:" ) === 0 && $this->getConfig()->isSsl() ) ) {
00643 return true;
00644 }
00645 }
00646
00647 if ( $sUrl && !$this->getConfig()->isCurrentUrl( $sUrl ) ) {
00648 return true;
00649 } elseif ( $this->_blSidNeeded === null ) {
00650
00651 $this->_blSidNeeded = false;
00652
00653
00654 if ( !oxUtils::getInstance()->isSearchEngine() ) {
00655
00656 if ( oxUtilsServer::getInstance()->getOxCookie( $this->getName() ) ) {
00657 $this->_blSidNeeded = false;
00658 } elseif ( $this->_forceSessionStart() ) {
00659 $this->_blSidNeeded = true;
00660 } else {
00661
00662 if ( $blSidNeeded = self::getVar( 'blSidNeeded' ) ) {
00663 $this->_blSidNeeded = true;
00664 } elseif ( $this->_isSessionRequiredAction() ) {
00665 $this->_blSidNeeded = true;
00666
00667
00668 self::setVar( 'blSidNeeded', $this->_blSidNeeded );
00669 }
00670 }
00671 }
00672 }
00673
00674 return $this->_blSidNeeded;
00675 }
00676
00688 public function processUrl( $sUrl )
00689 {
00690 if (!$this->isAdmin()) {
00691 $sSid = '';
00692 if ( $this->isSidNeeded( $sUrl ) ) {
00693
00694 $sSid = $this->sid( true );
00695 } else {
00696 $sSid = $this->sid();
00697 }
00698 if ($sSid) {
00699 $oStr = getStr();
00700 if ( !$oStr->preg_match('/(\?|&(amp;)?)sid=/i', $sUrl) && (false === $oStr->strpos($sUrl, $sSid))) {
00701 if (!$oStr->preg_match('/(\?|&(amp;)?)$/', $sUrl)) {
00702 $sUrl .= ( $oStr->strstr( $sUrl, '?' ) !== false ? '&' : '?' );
00703 }
00704 $sUrl .= $sSid . '&';
00705 }
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
00737 protected function _forceSessionStart()
00738 {
00739 return ( !oxUtils::getInstance()->isSearchEngine() ) && ( ( bool ) $this->getConfig()->getConfigParam( 'blForceSessionStart' ) ) ;
00740 }
00741
00747 protected function _allowSessionStart()
00748 {
00749 $blAllowSessionStart = true;
00750
00751
00752 if ( !$this->isAdmin() ) {
00753 if ( oxUtils::getInstance()->isSearchEngine() || oxConfig::getParameter( 'skipSession' ) ) {
00754 $blAllowSessionStart = false;
00755 } elseif ( !$this->_forceSessionStart() && !oxUtilsServer::getInstance()->getOxCookie( 'sid_key' ) ) {
00756
00757
00758
00759
00760 if ( !oxUtilsServer::getInstance()->getOxCookie( $this->getName() ) &&
00761 !( oxConfig::getParameter( $this->getName() ) || oxConfig::getParameter( $this->getForcedName() ) ) &&
00762 !$this->_isSessionRequiredAction() ) {
00763 $blAllowSessionStart = false;
00764 }
00765 }
00766 }
00767
00768 return $blAllowSessionStart;
00769 }
00770
00778 protected function _isSwappedClient()
00779 {
00780 $blSwapped = false;
00781 $myUtilsServer = oxUtilsServer::getInstance();
00782
00783
00784 if ( !oxUtils::getInstance()->isSearchEngine() && !$myUtilsServer->isTrustedClientIp() && !$this->_isValidRemoteAccessToken()) {
00785
00786 $myConfig = $this->getConfig();
00787
00788
00789 $blSwapped = $this->_checkUserAgent( $myUtilsServer->getServerVar( 'HTTP_USER_AGENT' ), self::getVar( 'sessionagent' ) );
00790 if ( !$blSwapped ) {
00791 if ( $myConfig->getConfigParam( 'blAdodbSessionHandler' ) ) {
00792 $blSwapped = $this->_checkSid();
00793 }
00794
00795 if ( !$blSwapped ) {
00796 $blDisableCookieCheck = $myConfig->getConfigParam( 'blDisableCookieCheck' );
00797 $blUseCookies = $this->_getSessionUseCookies();
00798 if ( !$blDisableCookieCheck && $blUseCookies ) {
00799 $blSwapped = $this->_checkCookies( $myUtilsServer->getOxCookie( 'sid_key' ), self::getVar( "sessioncookieisset" ) );
00800 }
00801 }
00802 }
00803 }
00804
00805 return $blSwapped;
00806 }
00807
00816 protected function _checkUserAgent( $sAgent, $sExistingAgent )
00817 {
00818 $blCheck = false;
00819 if ( $sAgent && $sAgent !== $sExistingAgent ) {
00820 if ( $sExistingAgent ) {
00821 $this->_sErrorMsg = "Different browser ({$sExistingAgent}, {$sAgent}), creating new SID...<br>";
00822 }
00823 $blCheck = true;
00824 }
00825
00826 return $blCheck;
00827 }
00828
00834 protected function _checkSid()
00835 {
00836
00837 $sSID = oxDb::getDb()->GetOne("select SessionID from oxsessions where SessionID = '".$this->getId()."'");
00838
00839
00840
00841 if ( !$this->_blNewSession && (!isset( $sSID) || !$sSID)) {
00842
00843 $this->_sErrorMsg = "Session has expired in the past and someone uses this sid to reactivate it, creating new SID...<br>";
00844 return true;
00845 }
00846 return false;
00847 }
00848
00858 protected function _checkCookies( $sCookieSid, $aSessCookieSetOnce )
00859 {
00860 $blSwapped = false;
00861 $myConfig = $this->getConfig();
00862 $sCurrUrl = $myConfig->isSsl() ? $myConfig->getSslShopUrl( 0 ) : $myConfig->getShopUrl( 0 );
00863
00864 $blSessCookieSetOnce = false;
00865 if ( isset( $aSessCookieSetOnce[$sCurrUrl] ) ) {
00866 $blSessCookieSetOnce = $aSessCookieSetOnce[$sCurrUrl];
00867 }
00868
00869
00870 if ( $blSessCookieSetOnce && !$sCookieSid ) {
00871 if ( $myConfig->getConfigParam( 'iDebug' ) ) {
00872 $this->_sErrorMsg = "Cookie not found, creating new SID...<br>";
00873 $this->_sErrorMsg .= "Cookie: $sCookieSid<br>";
00874 $this->_sErrorMsg .= "Session: $blSessCookieSetOnce<br>";
00875 $this->_sErrorMsg .= "URL: ".$sCurrUrl."<br>";
00876 }
00877 $blSwapped = true;
00878 }
00879
00880
00881 if ( $sCookieSid == "oxid" && !$blSessCookieSetOnce ) {
00882 $aSessCookieSetOnce[$sCurrUrl] = "ox_true";
00883 self::setVar( "sessioncookieisset", $aSessCookieSetOnce );
00884 }
00885
00886
00887 if ( !$sCookieSid ) {
00888 oxUtilsServer::getInstance()->setOxCookie( 'sid_key', 'oxid' );
00889 }
00890 return $blSwapped;
00891 }
00892
00900 protected function _setSessionId($sSessId)
00901 {
00902
00903 if ( $sSessId && session_id() != $sSessId ) {
00904 $this->_blNewSession = true;
00905 }
00906
00907 session_id( $sSessId );
00908
00909 $this->setId( $sSessId );
00910
00911 $blUseCookies = $this->_getSessionUseCookies();
00912
00913 if ( !$this->_allowSessionStart() ) {
00914 if ( $blUseCookies ) {
00915 oxUtilsServer::getInstance()->setOxCookie( $this->getName(), null );
00916 }
00917 return;
00918 }
00919
00920 if ( $blUseCookies ) {
00921
00922 oxUtilsServer::getInstance()->setOxCookie( $this->getName(), $sSessId );
00923 }
00924 }
00925
00931 protected function _getBasketName()
00932 {
00933 $myConfig = $this->getConfig();
00934 if ( $myConfig->getConfigParam( 'blMallSharedBasket' ) == 0 ) {
00935 return $myConfig->getShopId()."_basket";
00936 }
00937 return "basket";
00938 }
00939
00945 protected function _getCookieSid()
00946 {
00947 return oxUtilsServer::getInstance()->getOxCookie($this->getName());
00948 }
00949
00956 protected function _getRequireSessionWithParams()
00957 {
00958 $aCfgArray = $this->getConfig()->getConfigParam('aRequireSessionWithParams');
00959 if (is_array($aCfgArray)) {
00960 $aDefault = $this->_aRequireSessionWithParams;
00961 foreach ($aCfgArray as $key => $val) {
00962 if (!is_array($val) && $val) {
00963 unset($aDefault[$key]);
00964 }
00965 }
00966 return array_merge_recursive($aCfgArray, $aDefault);
00967 }
00968 return $this->_aRequireSessionWithParams;
00969 }
00970
00976 protected function _isSessionRequiredAction()
00977 {
00978
00979 $sFunction = oxConfig::getParameter( 'fnc' );
00980 $sClass = oxConfig::getParameter( 'cl' );
00981
00982 if (( $sFunction && in_array( strtolower( $sFunction ), $this->_aRequireCookiesInFncs ) ) ||
00983 ( $sClass && array_key_exists( strtolower( $sClass ), $this->_aRequireCookiesInFncs ) )) {
00984 return true;
00985 }
00986
00987 foreach ($this->_getRequireSessionWithParams() as $sParam => $aValues) {
00988 $sValue = oxConfig::getParameter( $sParam );
00989 if (isset($sValue)) {
00990 if (is_array($aValues)) {
00991 if (isset($aValues[$sValue]) && $aValues[$sValue]) {
00992 return true;
00993 }
00994 } elseif ($aValues) {
00995 return true;
00996 }
00997 }
00998 }
00999
01000 return ($_SERVER['REQUEST_METHOD'] == 'POST');
01001 }
01002
01008 protected function _getSessionUseCookies()
01009 {
01010 return $this->isAdmin() || $this->getConfig()->getConfigParam( 'blSessionUseCookies');
01011 }
01012
01018 protected function _isValidRemoteAccessToken()
01019 {
01020 $sInputToken = oxConfig::getInstance()->getParameter('rtoken');
01021 $sToken = $this->getRemoteAccessToken(false);
01022 $blTokenEqual = !(bool)strcmp($sInputToken, $sToken);
01023 $blValid = $sInputToken && $blTokenEqual;
01024
01025 return $blValid;
01026 }
01027 }