PageRenderTime 45ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/library/Zend/Http/CookieJar.php

https://bitbucket.org/Ebozavrik/test-application
PHP | 441 lines | 192 code | 48 blank | 201 comment | 34 complexity | 1adfa94bec425e354af79687fda15781 MD5 | raw file
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Http
  17. * @subpackage CookieJar
  18. * @version $Id: CookieJar.php 24856 2012-06-01 01:10:47Z adamlundrigan $
  19. * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  20. * @license http://framework.zend.com/license/new-bsd New BSD License
  21. */
  22. /**
  23. * @see Zend_Uri
  24. */
  25. require_once "Zend/Uri.php";
  26. /**
  27. * @see Zend_Http_Cookie
  28. */
  29. require_once "Zend/Http/Cookie.php";
  30. /**
  31. * @see Zend_Http_Response
  32. */
  33. require_once "Zend/Http/Response.php";
  34. /**
  35. * A Zend_Http_CookieJar object is designed to contain and maintain HTTP cookies, and should
  36. * be used along with Zend_Http_Client in order to manage cookies across HTTP requests and
  37. * responses.
  38. *
  39. * The class contains an array of Zend_Http_Cookie objects. Cookies can be added to the jar
  40. * automatically from a request or manually. Then, the jar can find and return the cookies
  41. * needed for a specific HTTP request.
  42. *
  43. * A special parameter can be passed to all methods of this class that return cookies: Cookies
  44. * can be returned either in their native form (as Zend_Http_Cookie objects) or as strings -
  45. * the later is suitable for sending as the value of the "Cookie" header in an HTTP request.
  46. * You can also choose, when returning more than one cookie, whether to get an array of strings
  47. * (by passing Zend_Http_CookieJar::COOKIE_STRING_ARRAY) or one unified string for all cookies
  48. * (by passing Zend_Http_CookieJar::COOKIE_STRING_CONCAT).
  49. *
  50. * @link http://wp.netscape.com/newsref/std/cookie_spec.html for some specs.
  51. *
  52. * @category Zend
  53. * @package Zend_Http
  54. * @subpackage CookieJar
  55. * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  56. * @license http://framework.zend.com/license/new-bsd New BSD License
  57. */
  58. class Zend_Http_CookieJar implements Countable, IteratorAggregate
  59. {
  60. /**
  61. * Return cookie(s) as a Zend_Http_Cookie object
  62. *
  63. */
  64. const COOKIE_OBJECT = 0;
  65. /**
  66. * Return cookie(s) as a string (suitable for sending in an HTTP request)
  67. *
  68. */
  69. const COOKIE_STRING_ARRAY = 1;
  70. /**
  71. * Return all cookies as one long string (suitable for sending in an HTTP request)
  72. *
  73. */
  74. const COOKIE_STRING_CONCAT = 2;
  75. /**
  76. * Return all cookies as one long string (strict mode)
  77. * - Single space after the semi-colon separating each cookie
  78. * - Remove trailing semi-colon, if any
  79. */
  80. const COOKIE_STRING_CONCAT_STRICT = 3;
  81. /**
  82. * Array storing cookies
  83. *
  84. * Cookies are stored according to domain and path:
  85. * $cookies
  86. * + www.mydomain.com
  87. * + /
  88. * - cookie1
  89. * - cookie2
  90. * + /somepath
  91. * - othercookie
  92. * + www.otherdomain.net
  93. * + /
  94. * - alsocookie
  95. *
  96. * @var array
  97. */
  98. protected $cookies = array();
  99. /**
  100. * The Zend_Http_Cookie array
  101. *
  102. * @var array
  103. */
  104. protected $_rawCookies = array();
  105. /**
  106. * Construct a new CookieJar object
  107. *
  108. */
  109. public function __construct ()
  110. {
  111. }
  112. /**
  113. * Add a cookie to the jar. Cookie should be passed either as a Zend_Http_Cookie object
  114. * or as a string - in which case an object is created from the string.
  115. *
  116. * @param Zend_Http_Cookie|string $cookie
  117. * @param Zend_Uri_Http|string $ref_uri Optional reference URI (for domain, path, secure)
  118. * @param boolean $encodeValue
  119. */
  120. public function addCookie ($cookie, $ref_uri = null, $encodeValue = true)
  121. {
  122. if (is_string($cookie)) {
  123. $cookie = Zend_Http_Cookie::fromString($cookie, $ref_uri, $encodeValue);
  124. }
  125. if ($cookie instanceof Zend_Http_Cookie) {
  126. $domain = $cookie->getDomain();
  127. $path = $cookie->getPath();
  128. if (!isset( $this->cookies[$domain] )) $this->cookies[$domain] = array();
  129. if (!isset( $this->cookies[$domain][$path] )) $this->cookies[$domain][$path] = array();
  130. $this->cookies[$domain][$path][$cookie->getName()] = $cookie;
  131. $this->_rawCookies[] = $cookie;
  132. } else {
  133. require_once 'Zend/Http/Exception.php';
  134. throw new Zend_Http_Exception( 'Supplient argument is not a valid cookie string or object' );
  135. }
  136. }
  137. /**
  138. * Parse an HTTP response, adding all the cookies set in that response
  139. * to the cookie jar.
  140. *
  141. * @param Zend_Http_Response $response
  142. * @param Zend_Uri_Http|string $ref_uri Requested URI
  143. * @param boolean $encodeValue
  144. */
  145. public function addCookiesFromResponse ($response, $ref_uri, $encodeValue = true)
  146. {
  147. if (!$response instanceof Zend_Http_Response) {
  148. require_once 'Zend/Http/Exception.php';
  149. throw new Zend_Http_Exception( '$response is expected to be a Response object, ' .
  150. gettype($response) . ' was passed' );
  151. }
  152. $cookie_hdrs = $response->getHeader('Set-Cookie');
  153. if (is_array($cookie_hdrs)) {
  154. foreach ($cookie_hdrs as $cookie) {
  155. $this->addCookie($cookie, $ref_uri, $encodeValue);
  156. }
  157. } elseif (is_string($cookie_hdrs)) {
  158. $this->addCookie($cookie_hdrs, $ref_uri, $encodeValue);
  159. }
  160. }
  161. /**
  162. * Get all cookies in the cookie jar as an array
  163. *
  164. * @param int $ret_as Whether to return cookies as objects of Zend_Http_Cookie or as strings
  165. *
  166. * @return array|string
  167. */
  168. public function getAllCookies ($ret_as = self::COOKIE_OBJECT)
  169. {
  170. $cookies = $this->_flattenCookiesArray($this->cookies, $ret_as);
  171. if ($ret_as == self::COOKIE_STRING_CONCAT_STRICT) {
  172. $cookies = rtrim(trim($cookies), ';');
  173. }
  174. return $cookies;
  175. }
  176. /**
  177. * Return an array of all cookies matching a specific request according to the request URI,
  178. * whether session cookies should be sent or not, and the time to consider as "now" when
  179. * checking cookie expiry time.
  180. *
  181. * @param string|Zend_Uri_Http $uri URI to check against (secure, domain, path)
  182. * @param boolean $matchSessionCookies Whether to send session cookies
  183. * @param int $ret_as Whether to return cookies as objects of Zend_Http_Cookie or as strings
  184. * @param int $now Override the current time when checking for expiry time
  185. *
  186. * @return array|string
  187. */
  188. public function getMatchingCookies ($uri, $matchSessionCookies = true,
  189. $ret_as = self::COOKIE_OBJECT, $now = null)
  190. {
  191. if (is_string($uri)) $uri = Zend_Uri::factory($uri);
  192. if (!$uri instanceof Zend_Uri_Http) {
  193. require_once 'Zend/Http/Exception.php';
  194. throw new Zend_Http_Exception( "Invalid URI string or object passed" );
  195. }
  196. // First, reduce the array of cookies to only those matching domain and path
  197. $cookies = $this->_matchDomain($uri->getHost());
  198. $cookies = $this->_matchPath($cookies, $uri->getPath());
  199. $cookies = $this->_flattenCookiesArray($cookies, self::COOKIE_OBJECT);
  200. // Next, run Cookie->match on all cookies to check secure, time and session mathcing
  201. $ret = array();
  202. foreach ($cookies as $cookie)
  203. if ($cookie->match($uri, $matchSessionCookies, $now))
  204. $ret[] = $cookie;
  205. // Now, use self::_flattenCookiesArray again - only to convert to the return format ;)
  206. $ret = $this->_flattenCookiesArray($ret, $ret_as);
  207. if ($ret_as == self::COOKIE_STRING_CONCAT_STRICT) {
  208. $ret = rtrim(trim($ret), ';');
  209. }
  210. return $ret;
  211. }
  212. /**
  213. * Get a specific cookie according to a URI and name
  214. *
  215. * @param Zend_Uri_Http|string $uri The uri (domain and path) to match
  216. * @param string $cookie_name The cookie's name
  217. * @param int $ret_as Whether to return cookies as objects of Zend_Http_Cookie or as strings
  218. *
  219. * @return Zend_Http_Cookie|string
  220. */
  221. public function getCookie ($uri, $cookie_name, $ret_as = self::COOKIE_OBJECT)
  222. {
  223. if (is_string($uri)) {
  224. $uri = Zend_Uri::factory($uri);
  225. }
  226. if (!$uri instanceof Zend_Uri_Http) {
  227. require_once 'Zend/Http/Exception.php';
  228. throw new Zend_Http_Exception( 'Invalid URI specified' );
  229. }
  230. // Get correct cookie path
  231. $path = $uri->getPath();
  232. $path = substr($path, 0, strrpos($path, '/'));
  233. if (!$path) $path = '/';
  234. if (isset( $this->cookies[$uri->getHost()][$path][$cookie_name] )) {
  235. $cookie = $this->cookies[$uri->getHost()][$path][$cookie_name];
  236. switch ($ret_as) {
  237. case self::COOKIE_OBJECT:
  238. return $cookie;
  239. break;
  240. case self::COOKIE_STRING_CONCAT_STRICT:
  241. return rtrim(trim($cookie->__toString()), ';');
  242. break;
  243. case self::COOKIE_STRING_ARRAY:
  244. case self::COOKIE_STRING_CONCAT:
  245. return $cookie->__toString();
  246. break;
  247. default:
  248. require_once 'Zend/Http/Exception.php';
  249. throw new Zend_Http_Exception( "Invalid value passed for \$ret_as: {$ret_as}" );
  250. break;
  251. }
  252. } else {
  253. return false;
  254. }
  255. }
  256. /**
  257. * Helper function to recursivly flatten an array. Shoud be used when exporting the
  258. * cookies array (or parts of it)
  259. *
  260. * @param Zend_Http_Cookie|array $ptr
  261. * @param int $ret_as What value to return
  262. *
  263. * @return array|string
  264. */
  265. protected function _flattenCookiesArray ($ptr, $ret_as = self::COOKIE_OBJECT)
  266. {
  267. if (is_array($ptr)) {
  268. $ret = ( $ret_as == self::COOKIE_STRING_CONCAT || $ret_as == self::COOKIE_STRING_CONCAT_STRICT ) ? '' : array();
  269. foreach ($ptr as $item) {
  270. if ($ret_as == self::COOKIE_STRING_CONCAT_STRICT) {
  271. $postfix_combine = ( !is_array($item) ? ' ' : '' );
  272. $ret .= $this->_flattenCookiesArray($item, $ret_as) . $postfix_combine;
  273. } elseif ($ret_as == self::COOKIE_STRING_CONCAT) {
  274. $ret .= $this->_flattenCookiesArray($item, $ret_as);
  275. } else {
  276. $ret = array_merge($ret, $this->_flattenCookiesArray($item, $ret_as));
  277. }
  278. }
  279. return $ret;
  280. } elseif ($ptr instanceof Zend_Http_Cookie) {
  281. switch ($ret_as) {
  282. case self::COOKIE_STRING_ARRAY:
  283. return array( $ptr->__toString() );
  284. break;
  285. case self::COOKIE_STRING_CONCAT_STRICT:
  286. // break intentionally omitted
  287. case self::COOKIE_STRING_CONCAT:
  288. return $ptr->__toString();
  289. break;
  290. case self::COOKIE_OBJECT:
  291. default:
  292. return array( $ptr );
  293. break;
  294. }
  295. }
  296. return null;
  297. }
  298. /**
  299. * Return a subset of the cookies array matching a specific domain
  300. *
  301. * @param string $domain
  302. *
  303. * @return array
  304. */
  305. protected function _matchDomain ($domain)
  306. {
  307. $ret = array();
  308. foreach (array_keys($this->cookies) as $cdom) {
  309. if (Zend_Http_Cookie::matchCookieDomain($cdom, $domain)) {
  310. $ret[$cdom] = $this->cookies[$cdom];
  311. }
  312. }
  313. return $ret;
  314. }
  315. /**
  316. * Return a subset of a domain-matching cookies that also match a specified path
  317. *
  318. * @param array $dom_array
  319. * @param string $path
  320. *
  321. * @return array
  322. */
  323. protected function _matchPath ($domains, $path)
  324. {
  325. $ret = array();
  326. foreach ($domains as $dom => $paths_array) {
  327. foreach (array_keys($paths_array) as $cpath) {
  328. if (Zend_Http_Cookie::matchCookiePath($cpath, $path)) {
  329. if (!isset( $ret[$dom] )) {
  330. $ret[$dom] = array();
  331. }
  332. $ret[$dom][$cpath] = $paths_array[$cpath];
  333. }
  334. }
  335. }
  336. return $ret;
  337. }
  338. /**
  339. * Create a new CookieJar object and automatically load into it all the
  340. * cookies set in an Http_Response object. If $uri is set, it will be
  341. * considered as the requested URI for setting default domain and path
  342. * of the cookie.
  343. *
  344. * @param Zend_Http_Response $response HTTP Response object
  345. * @param Zend_Uri_Http|string $uri The requested URI
  346. *
  347. * @return Zend_Http_CookieJar
  348. * @todo Add the $uri functionality.
  349. */
  350. public static function fromResponse (Zend_Http_Response $response, $ref_uri)
  351. {
  352. $jar = new self();
  353. $jar->addCookiesFromResponse($response, $ref_uri);
  354. return $jar;
  355. }
  356. /**
  357. * Required by Countable interface
  358. *
  359. * @return int
  360. */
  361. public function count ()
  362. {
  363. return count($this->_rawCookies);
  364. }
  365. /**
  366. * Required by IteratorAggregate interface
  367. *
  368. * @return ArrayIterator
  369. */
  370. public function getIterator ()
  371. {
  372. return new ArrayIterator( $this->_rawCookies );
  373. }
  374. /**
  375. * Tells if the jar is empty of any cookie
  376. *
  377. * @return bool
  378. */
  379. public function isEmpty ()
  380. {
  381. return count($this) == 0;
  382. }
  383. /**
  384. * Empties the cookieJar of any cookie
  385. *
  386. * @return Zend_Http_CookieJar
  387. */
  388. public function reset ()
  389. {
  390. $this->cookies = $this->_rawCookies = array();
  391. return $this;
  392. }
  393. }