| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344 |
- <?php
- /**
- * WordPress session managment.
- *
- * Standardizes WordPress session data using database-backed options for storage.
- * for storing user session information.
- *
- * @package WordPress
- * @subpackage Session
- * @since 3.7.0
- */
- // Exit if accessed directly
- if ( ! defined( 'ABSPATH' ) ) exit;
- /*
- * MODIFICATIONS
- *
- * - Remove `set_cooke()` from constructor
- * - Give `set_cookie()` public access
- */
- /**
- * WordPress Session class for managing user session data.
- *
- * @package WordPress
- * @since 3.7.0
- */
- final class WP_Session extends Recursive_ArrayAccess implements Iterator, Countable {
- /**
- * ID of the current session.
- *
- * @var string
- */
- public $session_id;
- /**
- * Unix timestamp when session expires.
- *
- * @var int
- */
- protected $expires;
- /**
- * Unix timestamp indicating when the expiration time needs to be reset.
- *
- * @var int
- */
- protected $exp_variant;
- /**
- * Singleton instance.
- *
- * @var bool|WP_Session
- */
- private static $instance = false;
- /**
- * Retrieve the current session instance.
- *
- * @param bool $session_id Session ID from which to populate data.
- *
- * @return bool|WP_Session
- */
- public static function get_instance() {
- if ( ! self::$instance ) {
- self::$instance = new self();
- }
- return self::$instance;
- }
- /**
- * Default constructor.
- * Will rebuild the session collection from the given session ID if it exists. Otherwise, will
- * create a new session with that ID.
- *
- * @param $session_id
- * @uses apply_filters Calls `wp_session_expiration` to determine how long until sessions expire.
- */
- protected function __construct() {
- if ( isset( $_COOKIE[WP_SESSION_COOKIE] ) ) {
- $cookie = stripslashes( $_COOKIE[WP_SESSION_COOKIE] );
- $cookie_crumbs = explode( '||', $cookie );
- if( $this->is_valid_md5( $cookie_crumbs[0] ) ) {
-
- $this->session_id = $cookie_crumbs[0];
-
- } else {
-
- $this->regenerate_id( true );
-
- }
-
- $this->expires = $cookie_crumbs[1];
- $this->exp_variant = $cookie_crumbs[2];
- // Update the session expiration if we're past the variant time
- if ( time() > $this->exp_variant ) {
- $this->set_expiration();
- delete_option( "_wp_session_expires_{$this->session_id}" );
- add_option( "_wp_session_expires_{$this->session_id}", $this->expires, '', 'no' );
- }
- } else {
- $this->session_id = $this->generate_id();
- $this->set_expiration();
- }
- $this->read_data();
- /*
- * MODIFICATION: Only set the cookie manually.
- */
- //$this->set_cookie();
- }
- /**
- * Set both the expiration time and the expiration variant.
- *
- * If the current time is below the variant, we don't update the session's expiration time. If it's
- * greater than the variant, then we update the expiration time in the database. This prevents
- * writing to the database on every page load for active sessions and only updates the expiration
- * time if we're nearing when the session actually expires.
- *
- * By default, the expiration time is set to 30 minutes.
- * By default, the expiration variant is set to 24 minutes.
- *
- * As a result, the session expiration time - at a maximum - will only be written to the database once
- * every 24 minutes. After 30 minutes, the session will have been expired. No cookie will be sent by
- * the browser, and the old session will be queued for deletion by the garbage collector.
- *
- * @uses apply_filters Calls `wp_session_expiration_variant` to get the max update window for session data.
- * @uses apply_filters Calls `wp_session_expiration` to get the standard expiration time for sessions.
- */
- protected function set_expiration() {
- $this->exp_variant = time() + (int) apply_filters( 'wp_session_expiration_variant', 24 * 60 );
- $this->expires = time() + (int) apply_filters( 'wp_session_expiration', 30 * 60 );
- }
- /**
- * Set the session cookie
- */
- /*
- * MODIFICATION: Change access to public for manually setting cookie.
- */
- public function set_cookie() {
- @setcookie( WP_SESSION_COOKIE, $this->session_id . '||' . $this->expires . '||' . $this->exp_variant , $this->expires, COOKIEPATH, COOKIE_DOMAIN );
- }
- /**
- * Generate a cryptographically strong unique ID for the session token.
- *
- * @return string
- */
- protected function generate_id() {
- require_once( ABSPATH . 'wp-includes/class-phpass.php');
- $hasher = new PasswordHash( 8, false );
- return md5( $hasher->get_random_bytes( 32 ) );
- }
- /**
- * Checks if is valid md5 string
- *
- * @param string $md5
- * @return int
- */
- protected function is_valid_md5( $md5 = '' ){
- return preg_match( '/^[a-f0-9]{32}$/', $md5 );
- }
- /**
- * Read data from a transient for the current session.
- *
- * Automatically resets the expiration time for the session transient to some time in the future.
- *
- * @return array
- */
- protected function read_data() {
- $this->container = get_option( "_wp_session_{$this->session_id}", array() );
- return $this->container;
- }
- /**
- * Write the data from the current session to the data storage system.
- */
- public function write_data() {
- $option_key = "_wp_session_{$this->session_id}";
- // Only write the collection to the DB if it's changed.
- if ( $this->dirty ) {
- if ( false === get_option( $option_key ) ) {
- add_option( "_wp_session_{$this->session_id}", $this->container, '', 'no' );
- add_option( "_wp_session_expires_{$this->session_id}", $this->expires, '', 'no' );
- } else {
- delete_option( "_wp_session_{$this->session_id}" );
- add_option( "_wp_session_{$this->session_id}", $this->container, '', 'no' );
- }
- }
- }
- /**
- * Output the current container contents as a JSON-encoded string.
- *
- * @return string
- */
- public function json_out() {
- return json_encode( $this->container );
- }
- /**
- * Decodes a JSON string and, if the object is an array, overwrites the session container with its contents.
- *
- * @param string $data
- *
- * @return bool
- */
- public function json_in( $data ) {
- $array = json_decode( $data );
- if ( is_array( $array ) ) {
- $this->container = $array;
- return true;
- }
- return false;
- }
- /**
- * Regenerate the current session's ID.
- *
- * @param bool $delete_old Flag whether or not to delete the old session data from the server.
- */
- public function regenerate_id( $delete_old = false ) {
- if ( $delete_old ) {
- delete_option( "_wp_session_{$this->session_id}" );
- }
- $this->session_id = $this->generate_id();
- $this->set_cookie();
- }
- /**
- * Check if a session has been initialized.
- *
- * @return bool
- */
- public function session_started() {
- return !!self::$instance;
- }
- /**
- * Return the read-only cache expiration value.
- *
- * @return int
- */
- public function cache_expiration() {
- return $this->expires;
- }
- /**
- * Flushes all session variables.
- */
- public function reset() {
- $this->container = array();
- }
- /*****************************************************************/
- /* Iterator Implementation */
- /*****************************************************************/
- /**
- * Current position of the array.
- *
- * @link http://php.net/manual/en/iterator.current.php
- *
- * @return mixed
- */
- public function current() {
- return current( $this->container );
- }
- /**
- * Key of the current element.
- *
- * @link http://php.net/manual/en/iterator.key.php
- *
- * @return mixed
- */
- public function key() {
- return key( $this->container );
- }
- /**
- * Move the internal point of the container array to the next item
- *
- * @link http://php.net/manual/en/iterator.next.php
- *
- * @return void
- */
- public function next() {
- next( $this->container );
- }
- /**
- * Rewind the internal point of the container array.
- *
- * @link http://php.net/manual/en/iterator.rewind.php
- *
- * @return void
- */
- public function rewind() {
- reset( $this->container );
- }
- /**
- * Is the current key valid?
- *
- * @link http://php.net/manual/en/iterator.rewind.php
- *
- * @return bool
- */
- public function valid() {
- return $this->offsetExists( $this->key() );
- }
- /*****************************************************************/
- /* Countable Implementation */
- /*****************************************************************/
- /**
- * Get the count of elements in the container array.
- *
- * @link http://php.net/manual/en/countable.count.php
- *
- * @return int
- */
- public function count() {
- return count( $this->container );
- }
- }
|