/wp-includes/class-wp-http-cookie.php

https://gitlab.com/campus-academy/krowkaramel · PHP · 276 lines · 100 code · 29 blank · 147 comment · 21 complexity · 27cfa6dd2371108a72df4c043fb0c4f1 MD5 · raw file

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