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 if ( !self::$_blIsNewSession && $this->_isSwappedClient() ) {
00250 $this->initNewSession();
00251
00252
00253 if ( $this->_sErrorMsg && $myConfig->getConfigParam( 'iDebug' ) ) {
00254 oxUtilsView::getInstance()->addErrorToDisplay( new oxException( $this->_sErrorMsg ) );
00255 }
00256 }
00257 }
00258 }
00259
00265 public function getRequestChallengeToken()
00266 {
00267 return preg_replace('/[^a-z0-9]/i', '', oxConfig::getParameter('stoken'));
00268 }
00269
00275 public function getSessionChallengeToken()
00276 {
00277 $sRet = preg_replace('/[^a-z0-9]/i', '', self::getVar('sess_stoken'));
00278 if (!$sRet) {
00279 $this->_initNewSessionChallenge();
00280 $sRet = self::getVar('sess_stoken');
00281 }
00282 return $sRet;
00283 }
00284
00291 public function checkSessionChallenge()
00292 {
00293 $sToken = $this->getSessionChallengeToken();
00294 return $sToken && ($sToken == $this->getRequestChallengeToken());
00295 }
00296
00302 protected function _initNewSessionChallenge()
00303 {
00304 self::setVar('sess_stoken', sprintf('%X', crc32(oxUtilsObject::getInstance()->generateUID())));
00305 }
00306
00312 protected function _sessionStart()
00313 {
00314
00315 session_cache_limiter( 'nocache' );
00316
00317
00318
00319 if (strpos($_SERVER['HTTP_USER_AGENT'], 'AOL') !== false ) {
00320 session_cache_limiter(false);
00321 header("Cache-Control: no-store, private, must-revalidate, proxy-revalidate, post-check=0, pre-check=0, max-age=0, s-maxage=0");
00322 }
00323
00324 $ret = @session_start();
00325 if (!$this->getSessionChallengeToken()) {
00326 $this->_initNewSessionChallenge();
00327 }
00328
00329 return $ret;
00330 }
00331
00337 public function initNewSession()
00338 {
00339
00340 if ( self::$_blIsNewSession ) {
00341 $this->_sessionStart();
00342 }
00343
00344
00345 $aPersistent = array();
00346 foreach ($this->_aPersistentParams as $sParam) {
00347 if ( self::getVar($sParam)) {
00348 $aPersistent[$sParam] = self::getVar($sParam);
00349 }
00350 }
00351
00352 $sid = md5(oxUtilsObject::getInstance()->generateUID());
00353
00354 $this->_setSessionId($sid);
00355 session_unset();
00356
00357
00358 foreach ($aPersistent as $key => $sParam) {
00359 self::setVar($key, $aPersistent[$key]);
00360 }
00361
00362 $this->_initNewSessionChallenge();
00363
00364
00365 self::setVar( "sessionagent", oxUtilsServer::getInstance()->getServerVar( 'HTTP_USER_AGENT' ) );
00366 }
00367
00373 public function freeze()
00374 {
00375
00376 self::setVar( $this->_getBasketName(), serialize( $this->getBasket() ) );
00377
00378 session_write_close();
00379 }
00380
00386 public function destroy()
00387 {
00388
00389 unset($_SESSION);
00390 session_destroy();
00391 }
00392
00400 public static function hasVar( $name )
00401 {
00402 if ( defined( 'OXID_PHP_UNIT' ) ) {
00403 if ( isset( modSession::$unitMOD ) && is_object( modSession::$unitMOD ) ) {
00404 try{
00405 $sVal = modSession::getInstance()->getVar( $name );
00406 return isset( $sVal );
00407 } catch( Exception $e ) {
00408
00409 }
00410 }
00411 }
00412
00413 return isset($_SESSION[$name]);
00414 }
00415
00424 public static function setVar( $name, $value)
00425 {
00426 if ( defined( 'OXID_PHP_UNIT' ) ) {
00427 if ( isset( modSession::$unitMOD ) && is_object( modSession::$unitMOD ) ) {
00428 try{
00429 return modSession::getInstance()->setVar( $name, $value );
00430 } catch( Exception $e ) {
00431
00432 }
00433 }
00434 }
00435
00436 $_SESSION[$name] = $value;
00437
00438 }
00439
00447 public static function getVar( $name )
00448 {
00449 if ( defined( 'OXID_PHP_UNIT' ) ) {
00450 if ( isset( modSession::$unitMOD ) && is_object( modSession::$unitMOD ) ) {
00451 try{
00452 return modSession::getInstance()->getVar( $name );
00453 } catch( Exception $e ) {
00454
00455 }
00456 }
00457 }
00458
00459 if ( isset( $_SESSION[$name] )) {
00460 return $_SESSION[$name];
00461 } else {
00462 return null;
00463 }
00464 }
00465
00473 public static function deleteVar( $name )
00474 {
00475 if ( defined( 'OXID_PHP_UNIT' ) ) {
00476 if ( isset( modSession::$unitMOD ) && is_object( modSession::$unitMOD ) ) {
00477 try{
00478 return modSession::getInstance()->setVar( $name, null );
00479 } catch( Exception $e ) {
00480
00481 }
00482 }
00483 }
00484
00485 $_SESSION[$name] = null;
00486
00487 unset($_SESSION[$name]);
00488 }
00489
00500 public function url( $sUrl )
00501 {
00502 $myConfig = $this->getConfig();
00503 $blUseCookies = $this->_getSessionUseCookies();
00504 $sSeparator = getStr()->strstr( $sUrl, "?" ) !== false ? "&" : "?";
00505 $sUrl .= $sSeparator;
00506
00507 if ( $blUseCookies && $this->_getCookieSid() ) {
00508
00509 if ( ( strpos( $sUrl, "https:" ) === 0 && !$myConfig->isSsl() ) ||
00510 ( strpos( $sUrl, "http:" ) === 0 && $myConfig->isSsl() ) ) {
00511 $sUrl .= $this->getForcedName(). '=' . $this->getId() . "&";
00512 }
00513 if ($this->isAdmin()) {
00514
00515 $sUrl .= 'stoken='.$this->getSessionChallengeToken().'&';
00516 }
00517 } elseif ( oxUtils::getInstance()->isSearchEngine() ) {
00518
00519 $sLangParam = (int) oxConfig::getParameter( "lang" );
00520 $sConfLang = (int) $myConfig->getConfigParam( "sDefaultLang" );
00521 if ( $sLangParam != $sConfLang ) {
00522 $sUrl .= "lang={$sLangParam}&";
00523 }
00524 } elseif ( ( $sIcludeParams = $this->sid() ) ) {
00525
00526 $sUrl .= "{$sIcludeParams}&";
00527 }
00528
00529 return $sUrl;
00530 }
00531
00541 public function sid( $blForceSid = false )
00542 {
00543 $myConfig = $this->getConfig();
00544 $blUseCookies = $this->_getSessionUseCookies();
00545 $sRet = '';
00546
00547 $blDisableSid = oxUtils::getInstance()->isSearchEngine()
00548 && is_array($myConfig->getConfigParam( 'aCacheViews' ) )
00549 && !$this->isAdmin();
00550
00551
00552 if ( !$blDisableSid && $this->getId() && ($blForceSid || !$blUseCookies || !$this->_getCookieSid())) {
00553 $sRet = ( $blForceSid ? $this->getForcedName() : $this->getName() )."=".$this->getId();
00554 }
00555
00556 if ($this->isAdmin()) {
00557
00558 if ($sRet) {
00559 $sRet .= '&';
00560 }
00561 $sRet .= 'stoken='.$this->getSessionChallengeToken();
00562 }
00563
00564 return $sRet;
00565 }
00566
00572 public function hiddenSid()
00573 {
00574 $sToken = "<input type=\"hidden\" name=\"stoken\" value=\"".$this->getSessionChallengeToken(). "\">";
00575 $sSid = "<input type=\"hidden\" name=\"".$this->getForcedName()."\" value=\"". $this->getId() . "\">";
00576 return $sToken.$sSid;
00577 }
00578
00584 public function getBasket()
00585 {
00586 if ( $this->_oBasket === null ) {
00587 $sBasket = self::getVar( $this->_getBasketName() );
00588
00589
00590
00591 oxNew('oxbasketitem');
00592
00593 if ( $sBasket && $oBasket = unserialize( $sBasket ) ) {
00594 $this->setBasket( $oBasket );
00595 } else {
00596 $this->setBasket( oxNew( 'oxbasket' ) );
00597 }
00598 }
00599
00600 return $this->_oBasket;
00601 }
00602
00610 public function setBasket( $oBasket )
00611 {
00612
00613 $this->_oBasket = $oBasket;
00614 }
00615
00621 public function delBasket()
00622 {
00623 $this->setBasket( null );
00624 self::deleteVar( $this->_getBasketName());
00625 }
00626
00632 public function isNewSession()
00633 {
00634 return self::$_blIsNewSession;
00635 }
00636
00644 public function isSidNeeded( $sUrl = null )
00645 {
00646 if ( $this->_getSessionUseCookies() && $this->_getCookieSid() ) {
00647
00648 if ( ( strpos( $sUrl, "https:" ) === 0 && !$this->getConfig()->isSsl() ) ||
00649 ( strpos( $sUrl, "http:" ) === 0 && $this->getConfig()->isSsl() ) ) {
00650 return true;
00651 }
00652 }
00653
00654 if ( $sUrl && !$this->getConfig()->isCurrentUrl( $sUrl ) ) {
00655 return true;
00656 } elseif ( $this->_blSidNeeded === null ) {
00657
00658 $this->_blSidNeeded = false;
00659
00660
00661 if ( !oxUtils::getInstance()->isSearchEngine() ) {
00662
00663 if ( oxUtilsServer::getInstance()->getOxCookie( $this->getName() ) ) {
00664 $this->_blSidNeeded = false;
00665 } elseif ( $this->_forceSessionStart() ) {
00666 $this->_blSidNeeded = true;
00667 } else {
00668
00669 if ( $blSidNeeded = self::getVar( 'blSidNeeded' ) ) {
00670 $this->_blSidNeeded = true;
00671 } elseif ( $this->_isSessionRequiredAction() ) {
00672 $this->_blSidNeeded = true;
00673
00674
00675 self::setVar( 'blSidNeeded', $this->_blSidNeeded );
00676 }
00677 }
00678 }
00679 }
00680
00681 return $this->_blSidNeeded;
00682 }
00683
00695 public function processUrl( $sUrl )
00696 {
00697 if (!$this->isAdmin()) {
00698 $sSid = '';
00699 if ( $this->isSidNeeded( $sUrl ) ) {
00700
00701 $sSid = $this->sid( true );
00702 } else {
00703 $sSid = $this->sid();
00704 }
00705 if ($sSid) {
00706 $oStr = getStr();
00707 if ( !$oStr->preg_match('/(\?|&(amp;)?)sid=/i', $sUrl) && (false === $oStr->strpos($sUrl, $sSid))) {
00708 if (!$oStr->preg_match('/(\?|&(amp;)?)$/', $sUrl)) {
00709 $sUrl .= ( $oStr->strstr( $sUrl, '?' ) !== false ? '&' : '?' );
00710 }
00711 $sUrl .= $sSid . '&';
00712 }
00713 }
00714 }
00715 return $sUrl;
00716 }
00717
00727 public function getRemoteAccessToken($blGenerateNew = true)
00728 {
00729 $sToken = $this->getVar('_rtoken');
00730 if (!$sToken && $blGenerateNew) {
00731 $sToken = md5(rand() . $this->getId());
00732 $sToken = substr($sToken, 0, 8);
00733 $this->setVar('_rtoken', $sToken);
00734 }
00735
00736 return $sToken;
00737 }
00738
00745 protected function _forceSessionStart()
00746 {
00747 return ( !oxUtils::getInstance()->isSearchEngine() ) && ( (( bool ) $this->getConfig()->getConfigParam( 'blForceSessionStart' )) || oxConfig::getParameter( "su" ) ) ;
00748 }
00749
00755 protected function _allowSessionStart()
00756 {
00757 $blAllowSessionStart = true;
00758
00759
00760 if ( !$this->isAdmin() ) {
00761 if ( oxUtils::getInstance()->isSearchEngine() || oxConfig::getParameter( 'skipSession' ) ) {
00762 $blAllowSessionStart = false;
00763 } elseif ( !$this->_forceSessionStart() && !oxUtilsServer::getInstance()->getOxCookie( 'sid_key' ) ) {
00764
00765
00766
00767
00768 if ( !oxUtilsServer::getInstance()->getOxCookie( $this->getName() ) &&
00769 !( oxConfig::getParameter( $this->getName() ) || oxConfig::getParameter( $this->getForcedName() ) ) &&
00770 !$this->_isSessionRequiredAction() ) {
00771 $blAllowSessionStart = false;
00772 }
00773 }
00774 }
00775
00776 return $blAllowSessionStart;
00777 }
00778
00786 protected function _isSwappedClient()
00787 {
00788 $blSwapped = false;
00789 $myUtilsServer = oxUtilsServer::getInstance();
00790
00791
00792 if ( !oxUtils::getInstance()->isSearchEngine() && !$myUtilsServer->isTrustedClientIp() && !$this->_isValidRemoteAccessToken()) {
00793
00794 $myConfig = $this->getConfig();
00795
00796
00797 $blSwapped = $this->_checkUserAgent( $myUtilsServer->getServerVar( 'HTTP_USER_AGENT' ), self::getVar( 'sessionagent' ) );
00798 if ( !$blSwapped ) {
00799 if ( $myConfig->getConfigParam( 'blAdodbSessionHandler' ) ) {
00800 $blSwapped = $this->_checkSid();
00801 }
00802
00803 if ( !$blSwapped ) {
00804 $blDisableCookieCheck = $myConfig->getConfigParam( 'blDisableCookieCheck' );
00805 $blUseCookies = $this->_getSessionUseCookies();
00806 if ( !$blDisableCookieCheck && $blUseCookies ) {
00807 $blSwapped = $this->_checkCookies( $myUtilsServer->getOxCookie( 'sid_key' ), self::getVar( "sessioncookieisset" ) );
00808 }
00809 }
00810 }
00811 }
00812
00813 return $blSwapped;
00814 }
00815
00824 protected function _checkUserAgent( $sAgent, $sExistingAgent )
00825 {
00826 $blCheck = false;
00827 if ( $sAgent && $sAgent !== $sExistingAgent ) {
00828 if ( $sExistingAgent ) {
00829 $this->_sErrorMsg = "Different browser ({$sExistingAgent}, {$sAgent}), creating new SID...<br>";
00830 }
00831 $blCheck = true;
00832 }
00833
00834 return $blCheck;
00835 }
00836
00842 protected function _checkSid()
00843 {
00844
00845 $sSID = oxDb::getDb()->GetOne("select SessionID from oxsessions where SessionID = '".$this->getId()."'");
00846
00847
00848
00849 if ( !$this->_blNewSession && (!isset( $sSID) || !$sSID)) {
00850
00851 $this->_sErrorMsg = "Session has expired in the past and someone uses this sid to reactivate it, creating new SID...<br>";
00852 return true;
00853 }
00854 return false;
00855 }
00856
00866 protected function _checkCookies( $sCookieSid, $aSessCookieSetOnce )
00867 {
00868 $blSwapped = false;
00869 $myConfig = $this->getConfig();
00870 $sCurrUrl = $myConfig->isSsl() ? $myConfig->getSslShopUrl( 0 ) : $myConfig->getShopUrl( 0 );
00871
00872 $blSessCookieSetOnce = false;
00873 if ( isset( $aSessCookieSetOnce[$sCurrUrl] ) ) {
00874 $blSessCookieSetOnce = $aSessCookieSetOnce[$sCurrUrl];
00875 }
00876
00877
00878 if ( $blSessCookieSetOnce && !$sCookieSid ) {
00879 if ( $myConfig->getConfigParam( 'iDebug' ) ) {
00880 $this->_sErrorMsg = "Cookie not found, creating new SID...<br>";
00881 $this->_sErrorMsg .= "Cookie: $sCookieSid<br>";
00882 $this->_sErrorMsg .= "Session: $blSessCookieSetOnce<br>";
00883 $this->_sErrorMsg .= "URL: ".$sCurrUrl."<br>";
00884 }
00885 $blSwapped = true;
00886 }
00887
00888
00889 if ( $sCookieSid == "oxid" && !$blSessCookieSetOnce ) {
00890 $aSessCookieSetOnce[$sCurrUrl] = "ox_true";
00891 self::setVar( "sessioncookieisset", $aSessCookieSetOnce );
00892 }
00893
00894
00895 if ( !$sCookieSid ) {
00896 oxUtilsServer::getInstance()->setOxCookie( 'sid_key', 'oxid' );
00897 }
00898 return $blSwapped;
00899 }
00900
00908 protected function _setSessionId($sSessId)
00909 {
00910
00911 if ( $sSessId && session_id() != $sSessId ) {
00912 $this->_blNewSession = true;
00913 }
00914
00915 session_id( $sSessId );
00916
00917 $this->setId( $sSessId );
00918
00919 $blUseCookies = $this->_getSessionUseCookies();
00920
00921 if ( !$this->_allowSessionStart() ) {
00922 if ( $blUseCookies ) {
00923 oxUtilsServer::getInstance()->setOxCookie( $this->getName(), null );
00924 }
00925 return;
00926 }
00927
00928 if ( $blUseCookies ) {
00929
00930 oxUtilsServer::getInstance()->setOxCookie( $this->getName(), $sSessId );
00931 }
00932 }
00933
00939 protected function _getBasketName()
00940 {
00941 $myConfig = $this->getConfig();
00942 if ( $myConfig->getConfigParam( 'blMallSharedBasket' ) == 0 ) {
00943 return $myConfig->getShopId()."_basket";
00944 }
00945 return "basket";
00946 }
00947
00953 protected function _getCookieSid()
00954 {
00955 return oxUtilsServer::getInstance()->getOxCookie($this->getName());
00956 }
00957
00964 protected function _getRequireSessionWithParams()
00965 {
00966 $aCfgArray = $this->getConfig()->getConfigParam('aRequireSessionWithParams');
00967 if (is_array($aCfgArray)) {
00968 $aDefault = $this->_aRequireSessionWithParams;
00969 foreach ($aCfgArray as $key => $val) {
00970 if (!is_array($val) && $val) {
00971 unset($aDefault[$key]);
00972 }
00973 }
00974 return array_merge_recursive($aCfgArray, $aDefault);
00975 }
00976 return $this->_aRequireSessionWithParams;
00977 }
00978
00984 protected function _isSessionRequiredAction()
00985 {
00986
00987 $sFunction = oxConfig::getParameter( 'fnc' );
00988 $sClass = oxConfig::getParameter( 'cl' );
00989
00990 if (( $sFunction && in_array( strtolower( $sFunction ), $this->_aRequireCookiesInFncs ) ) ||
00991 ( $sClass && array_key_exists( strtolower( $sClass ), $this->_aRequireCookiesInFncs ) )) {
00992 return true;
00993 }
00994
00995 foreach ($this->_getRequireSessionWithParams() as $sParam => $aValues) {
00996 $sValue = oxConfig::getParameter( $sParam );
00997 if (isset($sValue)) {
00998 if (is_array($aValues)) {
00999 if (isset($aValues[$sValue]) && $aValues[$sValue]) {
01000 return true;
01001 }
01002 } elseif ($aValues) {
01003 return true;
01004 }
01005 }
01006 }
01007
01008 return ($_SERVER['REQUEST_METHOD'] == 'POST');
01009 }
01010
01016 protected function _getSessionUseCookies()
01017 {
01018 return $this->isAdmin() || $this->getConfig()->getConfigParam( 'blSessionUseCookies');
01019 }
01020
01026 protected function _isValidRemoteAccessToken()
01027 {
01028 $sInputToken = oxConfig::getInstance()->getParameter('rtoken');
01029 $sToken = $this->getRemoteAccessToken(false);
01030 $blTokenEqual = !(bool)strcmp($sInputToken, $sToken);
01031 $blValid = $sInputToken && $blTokenEqual;
01032
01033 return $blValid;
01034 }
01035
01041 public function getBasketReservations()
01042 {
01043 if (!$this->_oBasketReservations) {
01044 $this->_oBasketReservations = oxNew('oxBasketReservation');
01045 }
01046 return $this->_oBasketReservations;
01047 }
01048 }