| 
									
										
										
										
											2011-06-22 17:21:15 -04:00
										 |  |  | <?php | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Stores cookies and passes them between HTTP requests | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * PHP version 5 | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2014-07-10 16:23:21 +02:00
										 |  |  |  * LICENSE | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This source file is subject to BSD 3-Clause License that is bundled | 
					
						
							|  |  |  |  * with this package in the file LICENSE and available at the URL | 
					
						
							|  |  |  |  * https://raw.github.com/pear/HTTP_Request2/trunk/docs/LICENSE | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * @category  HTTP | 
					
						
							|  |  |  |  * @package   HTTP_Request2 | 
					
						
							|  |  |  |  * @author    Alexey Borzov <avb@php.net> | 
					
						
							|  |  |  |  * @copyright 2008-2014 Alexey Borzov <avb@php.net> | 
					
						
							|  |  |  |  * @license   http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License | 
					
						
							|  |  |  |  * @link      http://pear.php.net/package/HTTP_Request2 | 
					
						
							| 
									
										
										
										
											2011-06-22 17:21:15 -04:00
										 |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** Class representing a HTTP request message */ | 
					
						
							|  |  |  | require_once 'HTTP/Request2.php'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * Stores cookies and passes them between HTTP requests | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2013-10-05 14:29:02 +02:00
										 |  |  |  * @category HTTP | 
					
						
							|  |  |  |  * @package  HTTP_Request2 | 
					
						
							|  |  |  |  * @author   Alexey Borzov <avb@php.net> | 
					
						
							| 
									
										
										
										
											2014-07-10 16:23:21 +02:00
										 |  |  |  * @license  http://opensource.org/licenses/BSD-3-Clause BSD 3-Clause License | 
					
						
							| 
									
										
										
										
											2013-10-05 14:29:02 +02:00
										 |  |  |  * @version  Release: @package_version@ | 
					
						
							|  |  |  |  * @link     http://pear.php.net/package/HTTP_Request2 | 
					
						
							| 
									
										
										
										
											2011-06-22 17:21:15 -04:00
										 |  |  |  */ | 
					
						
							|  |  |  | class HTTP_Request2_CookieJar implements Serializable | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2013-10-05 14:29:02 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Array of stored cookies | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * The array is indexed by domain, path and cookie name | 
					
						
							|  |  |  |      *   .example.com | 
					
						
							|  |  |  |      *     / | 
					
						
							|  |  |  |      *       some_cookie => cookie data | 
					
						
							|  |  |  |      *     /subdir | 
					
						
							|  |  |  |      *       other_cookie => cookie data | 
					
						
							|  |  |  |      *   .example.org | 
					
						
							|  |  |  |      *     ... | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @var array | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2011-06-22 17:21:15 -04:00
										 |  |  |     protected $cookies = array(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-05 14:29:02 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Whether session cookies should be serialized when serializing the jar | 
					
						
							|  |  |  |      * @var bool | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2011-06-22 17:21:15 -04:00
										 |  |  |     protected $serializeSession = false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-05 14:29:02 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Whether Public Suffix List should be used for domain matching | 
					
						
							|  |  |  |      * @var bool | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2011-06-22 17:21:15 -04:00
										 |  |  |     protected $useList = true; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-05 14:29:02 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Array with Public Suffix List data | 
					
						
							|  |  |  |      * @var  array | 
					
						
							|  |  |  |      * @link http://publicsuffix.org/ | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2011-06-22 17:21:15 -04:00
										 |  |  |     protected static $psl = array(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-05 14:29:02 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Class constructor, sets various options | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param bool $serializeSessionCookies Controls serializing session cookies, | 
					
						
							|  |  |  |      *                                      see {@link serializeSessionCookies()} | 
					
						
							|  |  |  |      * @param bool $usePublicSuffixList     Controls using Public Suffix List, | 
					
						
							|  |  |  |      *                                      see {@link usePublicSuffixList()} | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function __construct( | 
					
						
							|  |  |  |         $serializeSessionCookies = false, $usePublicSuffixList = true | 
					
						
							|  |  |  |     ) { | 
					
						
							| 
									
										
										
										
											2011-06-22 17:21:15 -04:00
										 |  |  |         $this->serializeSessionCookies($serializeSessionCookies); | 
					
						
							|  |  |  |         $this->usePublicSuffixList($usePublicSuffixList); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-05 14:29:02 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Returns current time formatted in ISO-8601 at UTC timezone | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return string | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2011-06-22 17:21:15 -04:00
										 |  |  |     protected function now() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $dt = new DateTime(); | 
					
						
							|  |  |  |         $dt->setTimezone(new DateTimeZone('UTC')); | 
					
						
							|  |  |  |         return $dt->format(DateTime::ISO8601); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-05 14:29:02 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Checks cookie array for correctness, possibly updating its 'domain', 'path' and 'expires' fields | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * The checks are as follows: | 
					
						
							|  |  |  |      *   - cookie array should contain 'name' and 'value' fields; | 
					
						
							|  |  |  |      *   - name and value should not contain disallowed symbols; | 
					
						
							|  |  |  |      *   - 'expires' should be either empty parseable by DateTime; | 
					
						
							|  |  |  |      *   - 'domain' and 'path' should be either not empty or an URL where | 
					
						
							|  |  |  |      *     cookie was set should be provided. | 
					
						
							|  |  |  |      *   - if $setter is provided, then document at that URL should be allowed | 
					
						
							|  |  |  |      *     to set a cookie for that 'domain'. If $setter is not provided, | 
					
						
							|  |  |  |      *     then no domain checks will be made. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * 'expires' field will be converted to ISO8601 format from COOKIE format, | 
					
						
							|  |  |  |      * 'domain' and 'path' will be set from setter URL if empty. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param array    $cookie cookie data, as returned by | 
					
						
							|  |  |  |      *                         {@link HTTP_Request2_Response::getCookies()} | 
					
						
							|  |  |  |      * @param Net_URL2 $setter URL of the document that sent Set-Cookie header | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return   array    Updated cookie array | 
					
						
							|  |  |  |      * @throws   HTTP_Request2_LogicException | 
					
						
							|  |  |  |      * @throws   HTTP_Request2_MessageException | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2011-06-22 17:21:15 -04:00
										 |  |  |     protected function checkAndUpdateFields(array $cookie, Net_URL2 $setter = null) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if ($missing = array_diff(array('name', 'value'), array_keys($cookie))) { | 
					
						
							|  |  |  |             throw new HTTP_Request2_LogicException( | 
					
						
							|  |  |  |                 "Cookie array should contain 'name' and 'value' fields", | 
					
						
							|  |  |  |                 HTTP_Request2_Exception::MISSING_VALUE | 
					
						
							|  |  |  |             ); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (preg_match(HTTP_Request2::REGEXP_INVALID_COOKIE, $cookie['name'])) { | 
					
						
							|  |  |  |             throw new HTTP_Request2_LogicException( | 
					
						
							|  |  |  |                 "Invalid cookie name: '{$cookie['name']}'", | 
					
						
							|  |  |  |                 HTTP_Request2_Exception::INVALID_ARGUMENT | 
					
						
							|  |  |  |             ); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (preg_match(HTTP_Request2::REGEXP_INVALID_COOKIE, $cookie['value'])) { | 
					
						
							|  |  |  |             throw new HTTP_Request2_LogicException( | 
					
						
							|  |  |  |                 "Invalid cookie value: '{$cookie['value']}'", | 
					
						
							|  |  |  |                 HTTP_Request2_Exception::INVALID_ARGUMENT | 
					
						
							|  |  |  |             ); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         $cookie += array('domain' => '', 'path' => '', 'expires' => null, 'secure' => false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Need ISO-8601 date @ UTC timezone
 | 
					
						
							|  |  |  |         if (!empty($cookie['expires']) | 
					
						
							|  |  |  |             && !preg_match('/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}\\+0000$/', $cookie['expires']) | 
					
						
							|  |  |  |         ) { | 
					
						
							|  |  |  |             try { | 
					
						
							|  |  |  |                 $dt = new DateTime($cookie['expires']); | 
					
						
							|  |  |  |                 $dt->setTimezone(new DateTimeZone('UTC')); | 
					
						
							|  |  |  |                 $cookie['expires'] = $dt->format(DateTime::ISO8601); | 
					
						
							|  |  |  |             } catch (Exception $e) { | 
					
						
							|  |  |  |                 throw new HTTP_Request2_LogicException($e->getMessage()); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (empty($cookie['domain']) || empty($cookie['path'])) { | 
					
						
							|  |  |  |             if (!$setter) { | 
					
						
							|  |  |  |                 throw new HTTP_Request2_LogicException( | 
					
						
							|  |  |  |                     'Cookie misses domain and/or path component, cookie setter URL needed', | 
					
						
							|  |  |  |                     HTTP_Request2_Exception::MISSING_VALUE | 
					
						
							|  |  |  |                 ); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (empty($cookie['domain'])) { | 
					
						
							|  |  |  |                 if ($host = $setter->getHost()) { | 
					
						
							|  |  |  |                     $cookie['domain'] = $host; | 
					
						
							|  |  |  |                 } else { | 
					
						
							|  |  |  |                     throw new HTTP_Request2_LogicException( | 
					
						
							|  |  |  |                         'Setter URL does not contain host part, can\'t set cookie domain', | 
					
						
							|  |  |  |                         HTTP_Request2_Exception::MISSING_VALUE | 
					
						
							|  |  |  |                     ); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (empty($cookie['path'])) { | 
					
						
							|  |  |  |                 $path = $setter->getPath(); | 
					
						
							|  |  |  |                 $cookie['path'] = empty($path)? '/': substr($path, 0, strrpos($path, '/') + 1); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ($setter && !$this->domainMatch($setter->getHost(), $cookie['domain'])) { | 
					
						
							|  |  |  |             throw new HTTP_Request2_MessageException( | 
					
						
							|  |  |  |                 "Domain " . $setter->getHost() . " cannot set cookies for " | 
					
						
							|  |  |  |                 . $cookie['domain'] | 
					
						
							|  |  |  |             ); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $cookie; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-05 14:29:02 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Stores a cookie in the jar | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param array    $cookie cookie data, as returned by | 
					
						
							|  |  |  |      *                         {@link HTTP_Request2_Response::getCookies()} | 
					
						
							|  |  |  |      * @param Net_URL2 $setter URL of the document that sent Set-Cookie header | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @throws   HTTP_Request2_Exception | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2011-06-22 17:21:15 -04:00
										 |  |  |     public function store(array $cookie, Net_URL2 $setter = null) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $cookie = $this->checkAndUpdateFields($cookie, $setter); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (strlen($cookie['value']) | 
					
						
							|  |  |  |             && (is_null($cookie['expires']) || $cookie['expires'] > $this->now()) | 
					
						
							|  |  |  |         ) { | 
					
						
							|  |  |  |             if (!isset($this->cookies[$cookie['domain']])) { | 
					
						
							|  |  |  |                 $this->cookies[$cookie['domain']] = array(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (!isset($this->cookies[$cookie['domain']][$cookie['path']])) { | 
					
						
							|  |  |  |                 $this->cookies[$cookie['domain']][$cookie['path']] = array(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             $this->cookies[$cookie['domain']][$cookie['path']][$cookie['name']] = $cookie; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         } elseif (isset($this->cookies[$cookie['domain']][$cookie['path']][$cookie['name']])) { | 
					
						
							|  |  |  |             unset($this->cookies[$cookie['domain']][$cookie['path']][$cookie['name']]); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-05 14:29:02 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Adds cookies set in HTTP response to the jar | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param HTTP_Request2_Response $response HTTP response message | 
					
						
							|  |  |  |      * @param Net_URL2               $setter   original request URL, needed for | 
					
						
							|  |  |  |      *                               setting default domain/path | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2011-06-22 17:21:15 -04:00
										 |  |  |     public function addCookiesFromResponse(HTTP_Request2_Response $response, Net_URL2 $setter) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         foreach ($response->getCookies() as $cookie) { | 
					
						
							|  |  |  |             $this->store($cookie, $setter); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-05 14:29:02 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Returns all cookies matching a given request URL | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * The following checks are made: | 
					
						
							|  |  |  |      *   - cookie domain should match request host | 
					
						
							|  |  |  |      *   - cookie path should be a prefix for request path | 
					
						
							|  |  |  |      *   - 'secure' cookies will only be sent for HTTPS requests | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param Net_URL2 $url      Request url | 
					
						
							|  |  |  |      * @param bool     $asString Whether to return cookies as string for "Cookie: " header | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return array|string Matching cookies | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2011-06-22 17:21:15 -04:00
										 |  |  |     public function getMatching(Net_URL2 $url, $asString = false) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $host   = $url->getHost(); | 
					
						
							|  |  |  |         $path   = $url->getPath(); | 
					
						
							|  |  |  |         $secure = 0 == strcasecmp($url->getScheme(), 'https'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         $matched = $ret = array(); | 
					
						
							|  |  |  |         foreach (array_keys($this->cookies) as $domain) { | 
					
						
							|  |  |  |             if ($this->domainMatch($host, $domain)) { | 
					
						
							|  |  |  |                 foreach (array_keys($this->cookies[$domain]) as $cPath) { | 
					
						
							|  |  |  |                     if (0 === strpos($path, $cPath)) { | 
					
						
							|  |  |  |                         foreach ($this->cookies[$domain][$cPath] as $name => $cookie) { | 
					
						
							|  |  |  |                             if (!$cookie['secure'] || $secure) { | 
					
						
							|  |  |  |                                 $matched[$name][strlen($cookie['path'])] = $cookie; | 
					
						
							|  |  |  |                             } | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         foreach ($matched as $cookies) { | 
					
						
							|  |  |  |             krsort($cookies); | 
					
						
							|  |  |  |             $ret = array_merge($ret, $cookies); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (!$asString) { | 
					
						
							|  |  |  |             return $ret; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             $str = ''; | 
					
						
							|  |  |  |             foreach ($ret as $c) { | 
					
						
							|  |  |  |                 $str .= (empty($str)? '': '; ') . $c['name'] . '=' . $c['value']; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             return $str; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-05 14:29:02 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Returns all cookies stored in a jar | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return array | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2011-06-22 17:21:15 -04:00
										 |  |  |     public function getAll() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $cookies = array(); | 
					
						
							|  |  |  |         foreach (array_keys($this->cookies) as $domain) { | 
					
						
							|  |  |  |             foreach (array_keys($this->cookies[$domain]) as $path) { | 
					
						
							|  |  |  |                 foreach ($this->cookies[$domain][$path] as $name => $cookie) { | 
					
						
							|  |  |  |                     $cookies[] = $cookie; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return $cookies; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-05 14:29:02 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Sets whether session cookies should be serialized when serializing the jar | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param boolean $serialize serialize? | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2011-06-22 17:21:15 -04:00
										 |  |  |     public function serializeSessionCookies($serialize) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->serializeSession = (bool)$serialize; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-05 14:29:02 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Sets whether Public Suffix List should be used for restricting cookie-setting | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * Without PSL {@link domainMatch()} will only prevent setting cookies for | 
					
						
							|  |  |  |      * top-level domains like '.com' or '.org'. However, it will not prevent | 
					
						
							|  |  |  |      * setting a cookie for '.co.uk' even though only third-level registrations | 
					
						
							|  |  |  |      * are possible in .uk domain. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * With the List it is possible to find the highest level at which a domain | 
					
						
							|  |  |  |      * may be registered for a particular top-level domain and consequently | 
					
						
							|  |  |  |      * prevent cookies set for '.co.uk' or '.msk.ru'. The same list is used by | 
					
						
							|  |  |  |      * Firefox, Chrome and Opera browsers to restrict cookie setting. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * Note that PSL is licensed differently to HTTP_Request2 package (refer to | 
					
						
							|  |  |  |      * the license information in public-suffix-list.php), so you can disable | 
					
						
							|  |  |  |      * its use if this is an issue for you. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param boolean $useList use the list? | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @link     http://publicsuffix.org/learn/ | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2011-06-22 17:21:15 -04:00
										 |  |  |     public function usePublicSuffixList($useList) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $this->useList = (bool)$useList; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-05 14:29:02 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Returns string representation of object | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return string | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @see    Serializable::serialize() | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2011-06-22 17:21:15 -04:00
										 |  |  |     public function serialize() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $cookies = $this->getAll(); | 
					
						
							|  |  |  |         if (!$this->serializeSession) { | 
					
						
							|  |  |  |             for ($i = count($cookies) - 1; $i >= 0; $i--) { | 
					
						
							|  |  |  |                 if (empty($cookies[$i]['expires'])) { | 
					
						
							|  |  |  |                     unset($cookies[$i]); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return serialize(array( | 
					
						
							|  |  |  |             'cookies'          => $cookies, | 
					
						
							|  |  |  |             'serializeSession' => $this->serializeSession, | 
					
						
							|  |  |  |             'useList'          => $this->useList | 
					
						
							|  |  |  |         )); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-05 14:29:02 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Constructs the object from serialized string | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param string $serialized string representation | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @see   Serializable::unserialize() | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2011-06-22 17:21:15 -04:00
										 |  |  |     public function unserialize($serialized) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $data = unserialize($serialized); | 
					
						
							|  |  |  |         $now  = $this->now(); | 
					
						
							|  |  |  |         $this->serializeSessionCookies($data['serializeSession']); | 
					
						
							|  |  |  |         $this->usePublicSuffixList($data['useList']); | 
					
						
							|  |  |  |         foreach ($data['cookies'] as $cookie) { | 
					
						
							|  |  |  |             if (!empty($cookie['expires']) && $cookie['expires'] <= $now) { | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (!isset($this->cookies[$cookie['domain']])) { | 
					
						
							|  |  |  |                 $this->cookies[$cookie['domain']] = array(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (!isset($this->cookies[$cookie['domain']][$cookie['path']])) { | 
					
						
							|  |  |  |                 $this->cookies[$cookie['domain']][$cookie['path']] = array(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             $this->cookies[$cookie['domain']][$cookie['path']][$cookie['name']] = $cookie; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-05 14:29:02 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Checks whether a cookie domain matches a request host. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * The method is used by {@link store()} to check for whether a document | 
					
						
							|  |  |  |      * at given URL can set a cookie with a given domain attribute and by | 
					
						
							|  |  |  |      * {@link getMatching()} to find cookies matching the request URL. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param string $requestHost  request host | 
					
						
							|  |  |  |      * @param string $cookieDomain cookie domain | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return   bool    match success | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2011-06-22 17:21:15 -04:00
										 |  |  |     public function domainMatch($requestHost, $cookieDomain) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if ($requestHost == $cookieDomain) { | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         // IP address, we require exact match
 | 
					
						
							|  |  |  |         if (preg_match('/^(?:\d{1,3}\.){3}\d{1,3}$/', $requestHost)) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if ('.' != $cookieDomain[0]) { | 
					
						
							|  |  |  |             $cookieDomain = '.' . $cookieDomain; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         // prevents setting cookies for '.com' and similar domains
 | 
					
						
							|  |  |  |         if (!$this->useList && substr_count($cookieDomain, '.') < 2 | 
					
						
							|  |  |  |             || $this->useList && !self::getRegisteredDomain($cookieDomain) | 
					
						
							|  |  |  |         ) { | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return substr('.' . $requestHost, -strlen($cookieDomain)) == $cookieDomain; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-05 14:29:02 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Removes subdomains to get the registered domain (the first after top-level) | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * The method will check Public Suffix List to find out where top-level | 
					
						
							|  |  |  |      * domain ends and registered domain starts. It will remove domain parts | 
					
						
							|  |  |  |      * to the left of registered one. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param string $domain domain name | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return string|bool   registered domain, will return false if $domain is | 
					
						
							|  |  |  |      *                       either invalid or a TLD itself | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2011-06-22 17:21:15 -04:00
										 |  |  |     public static function getRegisteredDomain($domain) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $domainParts = explode('.', ltrim($domain, '.')); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // load the list if needed
 | 
					
						
							|  |  |  |         if (empty(self::$psl)) { | 
					
						
							|  |  |  |             $path = '@data_dir@' . DIRECTORY_SEPARATOR . 'HTTP_Request2'; | 
					
						
							|  |  |  |             if (0 === strpos($path, '@' . 'data_dir@')) { | 
					
						
							| 
									
										
										
										
											2013-10-05 14:29:02 +02:00
										 |  |  |                 $path = realpath( | 
					
						
							|  |  |  |                     dirname(__FILE__) . DIRECTORY_SEPARATOR . '..' | 
					
						
							|  |  |  |                     . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'data' | 
					
						
							|  |  |  |                 ); | 
					
						
							| 
									
										
										
										
											2011-06-22 17:21:15 -04:00
										 |  |  |             } | 
					
						
							|  |  |  |             self::$psl = include_once $path . DIRECTORY_SEPARATOR . 'public-suffix-list.php'; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!($result = self::checkDomainsList($domainParts, self::$psl))) { | 
					
						
							|  |  |  |             // known TLD, invalid domain name
 | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // unknown TLD
 | 
					
						
							|  |  |  |         if (!strpos($result, '.')) { | 
					
						
							|  |  |  |             // fallback to checking that domain "has at least two dots"
 | 
					
						
							|  |  |  |             if (2 > ($count = count($domainParts))) { | 
					
						
							|  |  |  |                 return false; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             return $domainParts[$count - 2] . '.' . $domainParts[$count - 1]; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return $result; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-10-05 14:29:02 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * Recursive helper method for {@link getRegisteredDomain()} | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param array $domainParts remaining domain parts | 
					
						
							|  |  |  |      * @param mixed $listNode    node in {@link HTTP_Request2_CookieJar::$psl} to check | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @return string|null   concatenated domain parts, null in case of error | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2011-06-22 17:21:15 -04:00
										 |  |  |     protected static function checkDomainsList(array $domainParts, $listNode) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $sub    = array_pop($domainParts); | 
					
						
							|  |  |  |         $result = null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!is_array($listNode) || is_null($sub) | 
					
						
							|  |  |  |             || array_key_exists('!' . $sub, $listNode) | 
					
						
							| 
									
										
										
										
											2013-10-05 14:29:02 +02:00
										 |  |  |         ) { | 
					
						
							| 
									
										
										
										
											2011-06-22 17:21:15 -04:00
										 |  |  |             return $sub; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         } elseif (array_key_exists($sub, $listNode)) { | 
					
						
							|  |  |  |             $result = self::checkDomainsList($domainParts, $listNode[$sub]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         } elseif (array_key_exists('*', $listNode)) { | 
					
						
							|  |  |  |             $result = self::checkDomainsList($domainParts, $listNode['*']); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             return $sub; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return (strlen($result) > 0) ? ($result . '.' . $sub) : null; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | ?>
 |