| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294 | <?php/** * Session API: WP_Session_Tokens class * * @package WordPress * @subpackage Session * @since 4.7.0 *//** * Abstract class for managing user session tokens. * * @since 4.0.0 */abstract class WP_Session_Tokens {	/**	 * User ID.	 *	 * @since 4.0.0	 * @var int User ID.	 */	protected $user_id;	/**	 * Protected constructor. Use the `get_instance()` method to get the instance.	 *	 * @since 4.0.0	 *	 * @param int $user_id User whose session to manage.	 */	protected function __construct( $user_id ) {		$this->user_id = $user_id;	}	/**	 * Retrieves a session manager instance for a user.	 *	 * This method contains a {@see 'session_token_manager'} filter, allowing a plugin to swap out	 * the session manager for a subclass of `WP_Session_Tokens`.	 *	 * @since 4.0.0	 *	 * @param int $user_id User whose session to manage.	 * @return WP_Session_Tokens The session object, which is by default an instance of	 *                           the `WP_User_Meta_Session_Tokens` class.	 */	final public static function get_instance( $user_id ) {		/**		 * Filters the class name for the session token manager.		 *		 * @since 4.0.0		 *		 * @param string $session Name of class to use as the manager.		 *                        Default 'WP_User_Meta_Session_Tokens'.		 */		$manager = apply_filters( 'session_token_manager', 'WP_User_Meta_Session_Tokens' );		return new $manager( $user_id );	}	/**	 * Hashes the given session token for storage.	 *	 * @since 4.0.0	 *	 * @param string $token Session token to hash.	 * @return string A hash of the session token (a verifier).	 */	final private function hash_token( $token ) {		// If ext/hash is not present, use sha1() instead.		if ( function_exists( 'hash' ) ) {			return hash( 'sha256', $token );		} else {			return sha1( $token );		}	}	/**	 * Retrieves a user's session for the given token.	 *	 * @since 4.0.0	 *	 * @param string $token Session token.	 * @return array|null The session, or null if it does not exist.	 */	final public function get( $token ) {		$verifier = $this->hash_token( $token );		return $this->get_session( $verifier );	}	/**	 * Validates the given session token for authenticity and validity.	 *	 * Checks that the given token is present and hasn't expired.	 *	 * @since 4.0.0	 *	 * @param string $token Token to verify.	 * @return bool Whether the token is valid for the user.	 */	final public function verify( $token ) {		$verifier = $this->hash_token( $token );		return (bool) $this->get_session( $verifier );	}	/**	 * Generates a session token and attaches session information to it.	 *	 * A session token is a long, random string. It is used in a cookie	 * to link that cookie to an expiration time and to ensure the cookie	 * becomes invalidated when the user logs out.	 *	 * This function generates a token and stores it with the associated	 * expiration time (and potentially other session information via the	 * {@see 'attach_session_information'} filter).	 *	 * @since 4.0.0	 *	 * @param int $expiration Session expiration timestamp.	 * @return string Session token.	 */	final public function create( $expiration ) {		/**		 * Filters the information attached to the newly created session.		 *		 * Can be used to attach further information to a session.		 *		 * @since 4.0.0		 *		 * @param array $session Array of extra data.		 * @param int   $user_id User ID.		 */		$session               = apply_filters( 'attach_session_information', array(), $this->user_id );		$session['expiration'] = $expiration;		// IP address.		if ( ! empty( $_SERVER['REMOTE_ADDR'] ) ) {			$session['ip'] = $_SERVER['REMOTE_ADDR'];		}		// User-agent.		if ( ! empty( $_SERVER['HTTP_USER_AGENT'] ) ) {			$session['ua'] = wp_unslash( $_SERVER['HTTP_USER_AGENT'] );		}		// Timestamp		$session['login'] = time();		$token = wp_generate_password( 43, false, false );		$this->update( $token, $session );		return $token;	}	/**	 * Updates the data for the session with the given token.	 *	 * @since 4.0.0	 *	 * @param string $token Session token to update.	 * @param array  $session Session information.	 */	final public function update( $token, $session ) {		$verifier = $this->hash_token( $token );		$this->update_session( $verifier, $session );	}	/**	 * Destroys the session with the given token.	 *	 * @since 4.0.0	 *	 * @param string $token Session token to destroy.	 */	final public function destroy( $token ) {		$verifier = $this->hash_token( $token );		$this->update_session( $verifier, null );	}	/**	 * Destroys all sessions for this user except the one with the given token (presumably the one in use).	 *	 * @since 4.0.0	 *	 * @param string $token_to_keep Session token to keep.	 */	final public function destroy_others( $token_to_keep ) {		$verifier = $this->hash_token( $token_to_keep );		$session  = $this->get_session( $verifier );		if ( $session ) {			$this->destroy_other_sessions( $verifier );		} else {			$this->destroy_all_sessions();		}	}	/**	 * Determines whether a session is still valid, based on its expiration timestamp.	 *	 * @since 4.0.0	 *	 * @param array $session Session to check.	 * @return bool Whether session is valid.	 */	final protected function is_still_valid( $session ) {		return $session['expiration'] >= time();	}	/**	 * Destroys all sessions for a user.	 *	 * @since 4.0.0	 */	final public function destroy_all() {		$this->destroy_all_sessions();	}	/**	 * Destroys all sessions for all users.	 *	 * @since 4.0.0	 */	final public static function destroy_all_for_all_users() {		/** This filter is documented in wp-includes/class-wp-session-tokens.php */		$manager = apply_filters( 'session_token_manager', 'WP_User_Meta_Session_Tokens' );		call_user_func( array( $manager, 'drop_sessions' ) );	}	/**	 * Retrieves all sessions for a user.	 *	 * @since 4.0.0	 *	 * @return array Sessions for a user.	 */	final public function get_all() {		return array_values( $this->get_sessions() );	}	/**	 * Retrieves all sessions of the user.	 *	 * @since 4.0.0	 *	 * @return array Sessions of the user.	 */	abstract protected function get_sessions();	/**	 * Retrieves a session based on its verifier (token hash).	 *	 * @since 4.0.0	 *	 * @param string $verifier Verifier for the session to retrieve.	 * @return array|null The session, or null if it does not exist.	 */	abstract protected function get_session( $verifier );	/**	 * Updates a session based on its verifier (token hash).	 *	 * Omitting the second argument destroys the session.	 *	 * @since 4.0.0	 *	 * @param string $verifier Verifier for the session to update.	 * @param array  $session  Optional. Session. Omitting this argument destroys the session.	 */	abstract protected function update_session( $verifier, $session = null );	/**	 * Destroys all sessions for this user, except the single session with the given verifier.	 *	 * @since 4.0.0	 *	 * @param string $verifier Verifier of the session to keep.	 */	abstract protected function destroy_other_sessions( $verifier );	/**	 * Destroys all sessions for the user.	 *	 * @since 4.0.0	 */	abstract protected function destroy_all_sessions();	/**	 * Destroys all sessions for all users.	 *	 * @since 4.0.0	 */	public static function drop_sessions() {}}
 |