wp/wp-includes/class-wp-http-cookie.php
changeset 7 cf61fcea0001
child 9 177826044cd9
equal deleted inserted replaced
6:490d5cc509ed 7:cf61fcea0001
       
     1 <?php
       
     2 /**
       
     3  * HTTP API: WP_Http_Cookie class
       
     4  *
       
     5  * @package WordPress
       
     6  * @subpackage HTTP
       
     7  * @since 4.4.0
       
     8  */
       
     9 
       
    10 /**
       
    11  * Core class used to encapsulate a single cookie object for internal use.
       
    12  *
       
    13  * Returned cookies are represented using this class, and when cookies are set, if they are not
       
    14  * already a WP_Http_Cookie() object, then they are turned into one.
       
    15  *
       
    16  * @todo The WordPress convention is to use underscores instead of camelCase for function and method
       
    17  * names. Need to switch to use underscores instead for the methods.
       
    18  *
       
    19  * @since 2.8.0
       
    20  */
       
    21 class WP_Http_Cookie {
       
    22 
       
    23 	/**
       
    24 	 * Cookie name.
       
    25 	 *
       
    26 	 * @since 2.8.0
       
    27 	 * @var string
       
    28 	 */
       
    29 	public $name;
       
    30 
       
    31 	/**
       
    32 	 * Cookie value.
       
    33 	 *
       
    34 	 * @since 2.8.0
       
    35 	 * @var string
       
    36 	 */
       
    37 	public $value;
       
    38 
       
    39 	/**
       
    40 	 * When the cookie expires.
       
    41 	 *
       
    42 	 * @since 2.8.0
       
    43 	 * @var string
       
    44 	 */
       
    45 	public $expires;
       
    46 
       
    47 	/**
       
    48 	 * Cookie URL path.
       
    49 	 *
       
    50 	 * @since 2.8.0
       
    51 	 * @var string
       
    52 	 */
       
    53 	public $path;
       
    54 
       
    55 	/**
       
    56 	 * Cookie Domain.
       
    57 	 *
       
    58 	 * @since 2.8.0
       
    59 	 * @var string
       
    60 	 */
       
    61 	public $domain;
       
    62 
       
    63 	/**
       
    64 	 * Sets up this cookie object.
       
    65 	 *
       
    66 	 * The parameter $data should be either an associative array containing the indices names below
       
    67 	 * or a header string detailing it.
       
    68 	 *
       
    69 	 * @since 2.8.0
       
    70 	 *
       
    71 	 * @param string|array $data {
       
    72 	 *     Raw cookie data as header string or data array.
       
    73 	 *
       
    74 	 *     @type string     $name    Cookie name.
       
    75 	 *     @type mixed      $value   Value. Should NOT already be urlencoded.
       
    76 	 *     @type string|int $expires Optional. Unix timestamp or formatted date. Default null.
       
    77 	 *     @type string     $path    Optional. Path. Default '/'.
       
    78 	 *     @type string     $domain  Optional. Domain. Default host of parsed $requested_url.
       
    79 	 *     @type int        $port    Optional. Port. Default null.
       
    80 	 * }
       
    81 	 * @param string       $requested_url The URL which the cookie was set on, used for default $domain
       
    82 	 *                                    and $port values.
       
    83 	 */
       
    84 	public function __construct( $data, $requested_url = '' ) {
       
    85 		if ( $requested_url )
       
    86 			$arrURL = @parse_url( $requested_url );
       
    87 		if ( isset( $arrURL['host'] ) )
       
    88 			$this->domain = $arrURL['host'];
       
    89 		$this->path = isset( $arrURL['path'] ) ? $arrURL['path'] : '/';
       
    90 		if (  '/' != substr( $this->path, -1 ) )
       
    91 			$this->path = dirname( $this->path ) . '/';
       
    92 
       
    93 		if ( is_string( $data ) ) {
       
    94 			// Assume it's a header string direct from a previous request.
       
    95 			$pairs = explode( ';', $data );
       
    96 
       
    97 			// Special handling for first pair; name=value. Also be careful of "=" in value.
       
    98 			$name  = trim( substr( $pairs[0], 0, strpos( $pairs[0], '=' ) ) );
       
    99 			$value = substr( $pairs[0], strpos( $pairs[0], '=' ) + 1 );
       
   100 			$this->name  = $name;
       
   101 			$this->value = urldecode( $value );
       
   102 
       
   103 			// Removes name=value from items.
       
   104 			array_shift( $pairs );
       
   105 
       
   106 			// Set everything else as a property.
       
   107 			foreach ( $pairs as $pair ) {
       
   108 				$pair = rtrim($pair);
       
   109 
       
   110 				// Handle the cookie ending in ; which results in a empty final pair.
       
   111 				if ( empty($pair) )
       
   112 					continue;
       
   113 
       
   114 				list( $key, $val ) = strpos( $pair, '=' ) ? explode( '=', $pair ) : array( $pair, '' );
       
   115 				$key = strtolower( trim( $key ) );
       
   116 				if ( 'expires' == $key )
       
   117 					$val = strtotime( $val );
       
   118 				$this->$key = $val;
       
   119 			}
       
   120 		} else {
       
   121 			if ( !isset( $data['name'] ) )
       
   122 				return;
       
   123 
       
   124 			// Set properties based directly on parameters.
       
   125 			foreach ( array( 'name', 'value', 'path', 'domain', 'port' ) as $field ) {
       
   126 				if ( isset( $data[ $field ] ) )
       
   127 					$this->$field = $data[ $field ];
       
   128 			}
       
   129 
       
   130 			if ( isset( $data['expires'] ) )
       
   131 				$this->expires = is_int( $data['expires'] ) ? $data['expires'] : strtotime( $data['expires'] );
       
   132 			else
       
   133 				$this->expires = null;
       
   134 		}
       
   135 	}
       
   136 
       
   137 	/**
       
   138 	 * Confirms that it's OK to send this cookie to the URL checked against.
       
   139 	 *
       
   140 	 * Decision is based on RFC 2109/2965, so look there for details on validity.
       
   141 	 *
       
   142 	 * @since 2.8.0
       
   143 	 *
       
   144 	 * @param string $url URL you intend to send this cookie to
       
   145 	 * @return bool true if allowed, false otherwise.
       
   146 	 */
       
   147 	public function test( $url ) {
       
   148 		if ( is_null( $this->name ) )
       
   149 			return false;
       
   150 
       
   151 		// Expires - if expired then nothing else matters.
       
   152 		if ( isset( $this->expires ) && time() > $this->expires )
       
   153 			return false;
       
   154 
       
   155 		// Get details on the URL we're thinking about sending to.
       
   156 		$url = parse_url( $url );
       
   157 		$url['port'] = isset( $url['port'] ) ? $url['port'] : ( 'https' == $url['scheme'] ? 443 : 80 );
       
   158 		$url['path'] = isset( $url['path'] ) ? $url['path'] : '/';
       
   159 
       
   160 		// Values to use for comparison against the URL.
       
   161 		$path   = isset( $this->path )   ? $this->path   : '/';
       
   162 		$port   = isset( $this->port )   ? $this->port   : null;
       
   163 		$domain = isset( $this->domain ) ? strtolower( $this->domain ) : strtolower( $url['host'] );
       
   164 		if ( false === stripos( $domain, '.' ) )
       
   165 			$domain .= '.local';
       
   166 
       
   167 		// Host - very basic check that the request URL ends with the domain restriction (minus leading dot).
       
   168 		$domain = substr( $domain, 0, 1 ) == '.' ? substr( $domain, 1 ) : $domain;
       
   169 		if ( substr( $url['host'], -strlen( $domain ) ) != $domain )
       
   170 			return false;
       
   171 
       
   172 		// Port - supports "port-lists" in the format: "80,8000,8080".
       
   173 		if ( !empty( $port ) && !in_array( $url['port'], explode( ',', $port) ) )
       
   174 			return false;
       
   175 
       
   176 		// Path - request path must start with path restriction.
       
   177 		if ( substr( $url['path'], 0, strlen( $path ) ) != $path )
       
   178 			return false;
       
   179 
       
   180 		return true;
       
   181 	}
       
   182 
       
   183 	/**
       
   184 	 * Convert cookie name and value back to header string.
       
   185 	 *
       
   186 	 * @since 2.8.0
       
   187 	 *
       
   188 	 * @return string Header encoded cookie name and value.
       
   189 	 */
       
   190 	public function getHeaderValue() {
       
   191 		if ( ! isset( $this->name ) || ! isset( $this->value ) )
       
   192 			return '';
       
   193 
       
   194 		/**
       
   195 		 * Filters the header-encoded cookie value.
       
   196 		 *
       
   197 		 * @since 3.4.0
       
   198 		 *
       
   199 		 * @param string $value The cookie value.
       
   200 		 * @param string $name  The cookie name.
       
   201 		 */
       
   202 		return $this->name . '=' . apply_filters( 'wp_http_cookie_value', $this->value, $this->name );
       
   203 	}
       
   204 
       
   205 	/**
       
   206 	 * Retrieve cookie header for usage in the rest of the WordPress HTTP API.
       
   207 	 *
       
   208 	 * @since 2.8.0
       
   209 	 *
       
   210 	 * @return string
       
   211 	 */
       
   212 	public function getFullHeader() {
       
   213 		return 'Cookie: ' . $this->getHeaderValue();
       
   214 	}
       
   215 
       
   216 	/**
       
   217 	 * Retrieves cookie attributes.
       
   218 	 *
       
   219 	 * @since 4.6.0
       
   220 	 *
       
   221 	 * @return array {
       
   222 	 *    List of attributes.
       
   223 	 *
       
   224 	 *    @type string $expires When the cookie expires.
       
   225 	 *    @type string $path    Cookie URL path.
       
   226 	 *    @type string $domain  Cookie domain.
       
   227 	 * }
       
   228 	 */
       
   229 	public function get_attributes() {
       
   230 		return array(
       
   231 			'expires' => $this->expires,
       
   232 			'path'    => $this->path,
       
   233 			'domain'  => $this->domain,
       
   234 		);
       
   235 	}
       
   236 }