* Login/Logout * * [when] * In <filename>login.php</filename>, just before destroying the user * session. * * [input] * None * * [output] * None */ if (isset($PHORUM['hooks']['before_logout'])) { phorum_api_hook('before_logout'); } phorum_api_user_session_destroy(PHORUM_FORUM_SESSION); // Determine the URL to redirect the user to. The hook "after_logout" // can be used by module writers to set a custom redirect URL. if (isset($_SERVER['HTTP_REFERER']) && !empty($_SERVER['HTTP_REFERER'])) { $url = $_SERVER['HTTP_REFERER']; } else { $url = phorum_api_url_no_uri_auth(PHORUM_LIST_URL); } /* * [hook] * after_logout * * [description] * This hook can be used for performing tasks after a successful * user logout and for changing the page to which the user will be * redirected (by returning a different redirection URL). The user
/** * Restore a Phorum user session. * * This function will check for a valid user session for either the * forum or the admin interface (based on the $type parameter). If a valid * session is found, then the user session will be restored. * * Before calling this function, the variable $PHORUM['use_cookies'] * should be set to one of {@link PHORUM_NO_COOKIES}, * {@link PHORUM_USE_COOKIES} or {@link PHORUM_REQUIRE_COOKIES}. * * @param string $type * The type of session to check for. This must be one of * {@link PHORUM_FORUM_SESSION} or {@link PHORUM_ADMIN_SESSION}. * See the documentation for {@link phorum_api_user_session_create()} * for more information on Phorum user sessions. * * @return boolean * TRUE in case a valid session is detected, otherwise FALSE. * Note that a {@link PHORUM_FORUM_SESSION} will return TRUE if * a long term session is detected and that the sort term session * might be missing. Code which depends on short term sessions should * investigate the $PHORUM["DATA"]["FULLY_LOGGEDIN"] variable. */ function phorum_api_user_session_restore($type) { $PHORUM = $GLOBALS['PHORUM']; // ---------------------------------------------------------------------- // Determine which session cookie(s) to check. // ---------------------------------------------------------------------- // A list of session cookies to lookup. // The possible values for the items in this array are: // // 0: this cookie does not have to be checked // 1: a check has to be done or failed for this cookie // 2: the check for this cookie was successful // $check_session = array(PHORUM_SESSION_LONG_TERM => 0, PHORUM_SESSION_SHORT_TERM => 0, PHORUM_SESSION_ADMIN => 0); if ($type == PHORUM_FORUM_SESSION) { // Lookup the long term cookie. $check_session[PHORUM_SESSION_LONG_TERM] = 1; // Lookup the short term cookie if tight security is enabled. if (!empty($PHORUM['tight_security'])) { $check_session[PHORUM_SESSION_SHORT_TERM] = 1; } } elseif ($type == PHORUM_ADMIN_SESSION) { // Lookup the admin cookie. $check_session[PHORUM_SESSION_ADMIN] = 1; } else { trigger_error('phorum_api_user_session_restore(): Illegal session type: ' . htmlspecialchars($type), E_USER_ERROR); return NULL; } // ---------------------------------------------------------------------- // Check the session cookie(s). // ---------------------------------------------------------------------- // Now we decided what session cookie(s) we want to check, we allow // modules to hook into the session system to do the check for us. // This can for example be used to let Phorum inherit an already // running authenticated session in some external system. /** * [hook] * user_session_restore * * [description] * Allow modules to override Phorum's session restore management. * This hook is the designated hook if you need to let Phorum * inherit an authenticated session from some external system.<sbr/> * <sbr/> * The array that is passed to this hook, * contains a key for each of the Phorum session types: * <ul> * <li>PHORUM_SESSION_LONG_TERM</li> * <li>PHORUM_SESSION_SHORT_TERM</li> * <li>PHORUM_SESSION_ADMIN</li> * </ul> * What the module has to do, is fill the values for each of these * keys with the user_id of the Phorum user for which the session that * the key represents should be considered active. Other options * are FALSE to indicate that no session is active and NULL to * tell Phorum to handle session restore on its own.<sbr/> * <sbr/> * Note that the user for which a user_id is provided through this * hook must exist in the Phorum system before returning from this * hook. One option to take care of that constraint is letting * this hook create the user on-the-fly if needed. A cleaner way * would be to synchronize the user data from the main system at those * times when the user data changes (create, update and delete user). * Of course it is highly dependent on the other system whether * you can implement that kind of Phorum user management in the main * application.<sbr/> * <sbr/> * Hint: Creating users can be done using the * <literal> phorum_api_user_save()</literal> user API function. * * [category] * User authentication and session handling * * [when] * Just before Phorum runs its own session restore code * in the user API function * <literal>phorum_api_user_session_restore()</literal>. * * [input] * An array containing three keys: * <ul> * <li>PHORUM_SESSION_LONG_TERM</li> * <li>PHORUM_SESSION_SHORT_TERM</li> * <li>PHORUM_SESSION_ADMIN</li> * </ul> * By default, all values for these keys are NULL. * * [output] * Same as input, possibly with updated array values. * * [example] * See the <hook>user_session_create</hook> hook for an example * of how to let Phorum setup the PHP session that is picked up * in this example hook. * <hookcode> * function phorum_mod_foo_user_session_restore($sessions) * { * // Override the session handling for front end forum sessions. * // We could for example retrieve a session from a standard PHP * // session by first starting a PHP session if that was * // not done yet... * if (!session_id()) session_start(); * * // ...and then retrieving the user_id of the current user * // from the PHP session data. The user_id is really the * // only thing that needs to be remembered for a Phorum * // session, because all other data for the user is stored * // in the database. If no user id was set in the session, * // then use FALSE to flag this to Phorum. * $phorum_user_id = empty($_SESSION['phorum_user_id']) * ? FALSE : $_SESSION['phorum_user_id']; * * // If we only use session inheritance for the front end * // forum session (highly recommended for security), then * // We keep PHORUM_SESSION_ADMIN at NULL (default value). * // The other two need to be updated. If the main system does * // not use the concept of one long and one short term cookie * // (named "tight security" by Phorum), then simply assign * // the user_id to both PHORUM_SESSION_LONG_TERM and * // PHORUM_SESSION_SHORT_TERM. * $sessions[PHORUM_SESSION_SHORT_TERM] = $phorum_user_id; * $sessions[PHORUM_SESSION_LONG_TERM] = $phorum_user_id; * * return $sessions; * } * </hookcode> */ $hook_sessions = array(PHORUM_SESSION_LONG_TERM => NULL, PHORUM_SESSION_SHORT_TERM => NULL, PHORUM_SESSION_ADMIN => NULL); if (isset($PHORUM['hooks']['user_session_restore'])) { $hook_sessions = phorum_hook('user_session_restore', $hook_sessions); } $real_cookie = FALSE; $session_user = NULL; foreach ($check_session as $cookie => $do_check) { if (!$do_check) { continue; } // Check if a module did provide a user_id for the checked session. $user_id_from_hook_session = FALSE; if ($hook_sessions[$cookie] !== NULL) { // Continue with the next cookie, if a module specified the // session cookie as invalid. if ($hook_sessions[$cookie] === FALSE) { continue; } // Pass on the user_id that was set by the module. // We add a fake a session id to the user_id here, // to make the split from below work. $value = $hook_sessions[$cookie] . ':dummy'; $user_id_from_hook_session = TRUE; // To not let Phorum fall back to URI authentication. $real_cookie = TRUE; } elseif (($cookie != PHORUM_SESSION_LONG_TERM || isset($PHORUM['use_cookies']) && $PHORUM['use_cookies'] > PHORUM_NO_COOKIES) && isset($_COOKIE[$cookie])) { $value = $_COOKIE[$cookie]; $real_cookie = TRUE; } elseif ($PHORUM['use_cookies'] < PHORUM_REQUIRE_COOKIES && isset($PHORUM['args'][$cookie])) { $value = urldecode($PHORUM['args'][$cookie]); } elseif ($PHORUM['use_cookies'] < PHORUM_REQUIRE_COOKIES && isset($_POST[$cookie])) { $value = $_POST[$cookie]; } elseif ($PHORUM['use_cookies'] < PHORUM_REQUIRE_COOKIES && isset($_GET[$cookie])) { $value = $_GET[$cookie]; } else { continue; } // Cookie incorrectly formatted. Continue with the next one. if (strstr($value, ':') === FALSE) { continue; } // The cookie value is formatted as <user id>:<session id>. // Split these into separate parts. list($user_id, $sessid) = explode(':', $value, 2); // The user_id should be numerical at all times. if (!is_numeric($user_id)) { continue; } // Find the data for the session user by its user_id. If the user // cannot be found, then the session is destroyed and the // anonymous user is setup. if ($session_user === NULL) { $session_user = phorum_api_user_get($user_id, TRUE); if (empty($session_user) || $session_user['active'] != PHORUM_USER_ACTIVE) { phorum_api_user_session_destroy($type); return FALSE; } } else { // The user_id should be the same for all cookies. // If a different user_id is found, then the cookie // that we're currently looking at is ignored. It could // be an old cookie for a different user. if ($session_user['user_id'] != $user_id) { continue; } } // Check if the session id from the cookie is valid for the user. $valid_session = $user_id_from_hook_session || $cookie == PHORUM_SESSION_LONG_TERM && !empty($session_user['sessid_lt']) && $session_user['sessid_lt'] == $sessid || $cookie == PHORUM_SESSION_SHORT_TERM && !empty($session_user['sessid_st']) && $session_user['sessid_st'] == $sessid || $cookie == PHORUM_SESSION_ADMIN && !empty($session_user['sessid_lt']) && md5($session_user['sessid_lt'] . $PHORUM['admin_session_salt']) == $sessid; // Keep track of valid session cookies. if ($valid_session) { $check_session[$cookie] = 2; } } // No real cookie found for a long term session? Then we will ignore // short term sessions (short term sessions are not implemented for URI // authentication) and update the "use_cookies" setting accordingly. if ($check_session[PHORUM_SESSION_LONG_TERM] == 2 && !$real_cookie) { $check_session[PHORUM_SESSION_SHORT_TERM] = 0; $GLOBALS['PHORUM']['use_cookies'] = PHORUM_NO_COOKIES; } // ---------------------------------------------------------------------- // Check if a user session needs to be restored. // ---------------------------------------------------------------------- $do_restore_session = FALSE; $do_restore_short_term_session = FALSE; if ($type == PHORUM_FORUM_SESSION) { // Valid long term forum session found. if ($check_session[PHORUM_SESSION_LONG_TERM] == 2) { $do_restore_session = TRUE; if ($check_session[PHORUM_SESSION_SHORT_TERM] == 1) { // Checked short term session, but no valid session found. $do_restore_short_term_session = FALSE; } else { // Short term session not checked (0) or valid (2). $do_restore_short_term_session = TRUE; } } } elseif ($type == PHORUM_ADMIN_SESSION) { // Valid admin session found. Note that the function // phorum_api_user_set_active_user() might still reject the user // if it's not an admin user (anymore). if ($check_session[PHORUM_SESSION_ADMIN] == 2) { $do_restore_session = TRUE; } } // ---------------------------------------------------------------------- // Restore the user session. // ---------------------------------------------------------------------- // No session to restore? Then destroy the session // and setup the anonymous user. if (!$do_restore_session) { phorum_api_user_session_destroy($type); return FALSE; } else { // Setup the Phorum user. $flags = 0; if ($do_restore_short_term_session) { $flags |= PHORUM_FLAG_SESSION_ST; } phorum_api_user_set_active_user($type, $session_user, $flags); // Refresh and keep the session alive for the user. phorum_api_user_session_create($type); return TRUE; } }