/** * Changes the user stored in the session, this method is different from changeUser() because it * attempts to re-use sessions unless there are other virtual sessions for the same user (userID != 0). * In reverse, logging out attempts to re-use the current session or spawns a new session depending * on other virtual sessions. * * @param \wcf\data\user\User $user */ protected function changeUserVirtual(User $user) { $sessionTable = call_user_func(array($this->sessionClassName, 'getDatabaseTableName')); switch ($user->userID) { // // user -> guest (logout) // case 0: // delete virtual session if ($this->virtualSession) { $virtualSessionEditor = new SessionVirtualEditor($this->virtualSession); $virtualSessionEditor->delete(); } // there are still other virtual sessions, create a new session if (SessionVirtual::countVirtualSessions($this->session->sessionID)) { // save session $sessionData = array('sessionID' => StringUtil::getRandomID(), 'userID' => $user->userID, 'ipAddress' => UserUtil::getIpAddress(), 'userAgent' => UserUtil::getUserAgent(), 'lastActivityTime' => TIME_NOW, 'requestURI' => UserUtil::getRequestURI(), 'requestMethod' => !empty($_SERVER['REQUEST_METHOD']) ? substr($_SERVER['REQUEST_METHOD'], 0, 7) : ''); $this->session = call_user_func(array($this->sessionEditorClassName, 'create'), $sessionData); HeaderUtil::setCookie('cookieHash', $this->session->sessionID); } else { // this was the last virtual session, re-use current session // update session $sessionEditor = new $this->sessionEditorClassName($this->session); $sessionEditor->update(array('userID' => $user->userID)); } break; // // guest -> user (login) // // // guest -> user (login) // default: // find existing session for this user $session = call_user_func(array($this->sessionClassName, 'getSessionByUserID'), $user->userID); // no session exists, re-use current session if ($session === null) { // update session $sessionEditor = new $this->sessionEditorClassName($this->session); try { $this->register('__changeSessionID', true); $sessionEditor->update(array('userID' => $user->userID)); } catch (DatabaseException $e) { // MySQL error 23000 = unique key // do not check against the message itself, some weird systems localize them if ($e->getCode() == 23000) { // delete guest session $sessionEditor = new $this->sessionEditorClassName($this->session); $sessionEditor->delete(); // inherit existing session $this->session = $session; } else { // not our business throw $e; } } } else { // delete guest session $sessionEditor = new $this->sessionEditorClassName($this->session); $sessionEditor->delete(); // inherit existing session $this->session = $session; // inherit security token $variables = @unserialize($this->session->sessionVariables); if (is_array($variables) && !empty($variables['__SECURITY_TOKEN'])) { $this->register('__SECURITY_TOKEN', $variables['__SECURITY_TOKEN']); } HeaderUtil::setCookie('cookieHash', $this->session->sessionID); } break; } $this->user = $user; $this->loadVirtualSession(true); }