installed plugin Easy Digital Downloads
version 3.1.0.3
This commit is contained in:
@ -0,0 +1,332 @@
|
||||
<?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
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
||||
$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
|
||||
*/
|
||||
protected 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 );
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user