PageRenderTime 47ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/libs/Zend/Http/Cookie.php

https://github.com/quarkness/piwik
PHP | 424 lines | 174 code | 49 blank | 201 comment | 40 complexity | 49b0fe908daf285e5b8c731da406ecdf 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 Cookie
  18. * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @version $Id: Cookie.php 23775 2011-03-01 17:25:24Z ralph $
  20. * @license http://framework.zend.com/license/new-bsd New BSD License
  21. */
  22. /**
  23. * @see Zend_Uri_Http
  24. */
  25. // require_once 'Zend/Uri/Http.php';
  26. /**
  27. * Zend_Http_Cookie is a class describing an HTTP cookie and all it's parameters.
  28. *
  29. * Zend_Http_Cookie is a class describing an HTTP cookie and all it's parameters. The
  30. * class also enables validating whether the cookie should be sent to the server in
  31. * a specified scenario according to the request URI, the expiry time and whether
  32. * session cookies should be used or not. Generally speaking cookies should be
  33. * contained in a Cookiejar object, or instantiated manually and added to an HTTP
  34. * request.
  35. *
  36. * See http://wp.netscape.com/newsref/std/cookie_spec.html for some specs.
  37. *
  38. * @category Zend
  39. * @package Zend_Http
  40. * @copyright Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
  41. * @license http://framework.zend.com/license/new-bsd New BSD License
  42. */
  43. class Zend_Http_Cookie
  44. {
  45. /**
  46. * Cookie name
  47. *
  48. * @var string
  49. */
  50. protected $name;
  51. /**
  52. * Cookie value
  53. *
  54. * @var string
  55. */
  56. protected $value;
  57. /**
  58. * Cookie expiry date
  59. *
  60. * @var int
  61. */
  62. protected $expires;
  63. /**
  64. * Cookie domain
  65. *
  66. * @var string
  67. */
  68. protected $domain;
  69. /**
  70. * Cookie path
  71. *
  72. * @var string
  73. */
  74. protected $path;
  75. /**
  76. * Whether the cookie is secure or not
  77. *
  78. * @var boolean
  79. */
  80. protected $secure;
  81. /**
  82. * Whether the cookie value has been encoded/decoded
  83. *
  84. * @var boolean
  85. */
  86. protected $encodeValue;
  87. /**
  88. * Cookie object constructor
  89. *
  90. * @todo Add validation of each one of the parameters (legal domain, etc.)
  91. *
  92. * @param string $name
  93. * @param string $value
  94. * @param string $domain
  95. * @param int $expires
  96. * @param string $path
  97. * @param bool $secure
  98. */
  99. public function __construct($name, $value, $domain, $expires = null, $path = null, $secure = false)
  100. {
  101. if (preg_match("/[=,; \t\r\n\013\014]/", $name)) {
  102. // require_once 'Zend/Http/Exception.php';
  103. throw new Zend_Http_Exception("Cookie name cannot contain these characters: =,; \\t\\r\\n\\013\\014 ({$name})");
  104. }
  105. if (! $this->name = (string) $name) {
  106. // require_once 'Zend/Http/Exception.php';
  107. throw new Zend_Http_Exception('Cookies must have a name');
  108. }
  109. if (! $this->domain = (string) $domain) {
  110. // require_once 'Zend/Http/Exception.php';
  111. throw new Zend_Http_Exception('Cookies must have a domain');
  112. }
  113. $this->value = (string) $value;
  114. $this->expires = ($expires === null ? null : (int) $expires);
  115. $this->path = ($path ? $path : '/');
  116. $this->secure = $secure;
  117. }
  118. /**
  119. * Get Cookie name
  120. *
  121. * @return string
  122. */
  123. public function getName()
  124. {
  125. return $this->name;
  126. }
  127. /**
  128. * Get cookie value
  129. *
  130. * @return string
  131. */
  132. public function getValue()
  133. {
  134. return $this->value;
  135. }
  136. /**
  137. * Get cookie domain
  138. *
  139. * @return string
  140. */
  141. public function getDomain()
  142. {
  143. return $this->domain;
  144. }
  145. /**
  146. * Get the cookie path
  147. *
  148. * @return string
  149. */
  150. public function getPath()
  151. {
  152. return $this->path;
  153. }
  154. /**
  155. * Get the expiry time of the cookie, or null if no expiry time is set
  156. *
  157. * @return int|null
  158. */
  159. public function getExpiryTime()
  160. {
  161. return $this->expires;
  162. }
  163. /**
  164. * Check whether the cookie should only be sent over secure connections
  165. *
  166. * @return boolean
  167. */
  168. public function isSecure()
  169. {
  170. return $this->secure;
  171. }
  172. /**
  173. * Check whether the cookie has expired
  174. *
  175. * Always returns false if the cookie is a session cookie (has no expiry time)
  176. *
  177. * @param int $now Timestamp to consider as "now"
  178. * @return boolean
  179. */
  180. public function isExpired($now = null)
  181. {
  182. if ($now === null) $now = time();
  183. if (is_int($this->expires) && $this->expires < $now) {
  184. return true;
  185. } else {
  186. return false;
  187. }
  188. }
  189. /**
  190. * Check whether the cookie is a session cookie (has no expiry time set)
  191. *
  192. * @return boolean
  193. */
  194. public function isSessionCookie()
  195. {
  196. return ($this->expires === null);
  197. }
  198. /**
  199. * Checks whether the cookie should be sent or not in a specific scenario
  200. *
  201. * @param string|Zend_Uri_Http $uri URI to check against (secure, domain, path)
  202. * @param boolean $matchSessionCookies Whether to send session cookies
  203. * @param int $now Override the current time when checking for expiry time
  204. * @return boolean
  205. */
  206. public function match($uri, $matchSessionCookies = true, $now = null)
  207. {
  208. if (is_string ($uri)) {
  209. $uri = Zend_Uri_Http::factory($uri);
  210. }
  211. // Make sure we have a valid Zend_Uri_Http object
  212. if (! ($uri->valid() && ($uri->getScheme() == 'http' || $uri->getScheme() =='https'))) {
  213. // require_once 'Zend/Http/Exception.php';
  214. throw new Zend_Http_Exception('Passed URI is not a valid HTTP or HTTPS URI');
  215. }
  216. // Check that the cookie is secure (if required) and not expired
  217. if ($this->secure && $uri->getScheme() != 'https') return false;
  218. if ($this->isExpired($now)) return false;
  219. if ($this->isSessionCookie() && ! $matchSessionCookies) return false;
  220. // Check if the domain matches
  221. if (! self::matchCookieDomain($this->getDomain(), $uri->getHost())) {
  222. return false;
  223. }
  224. // Check that path matches using prefix match
  225. if (! self::matchCookiePath($this->getPath(), $uri->getPath())) {
  226. return false;
  227. }
  228. // If we didn't die until now, return true.
  229. return true;
  230. }
  231. /**
  232. * Get the cookie as a string, suitable for sending as a "Cookie" header in an
  233. * HTTP request
  234. *
  235. * @return string
  236. */
  237. public function __toString()
  238. {
  239. if ($this->encodeValue) {
  240. return $this->name . '=' . urlencode($this->value) . ';';
  241. }
  242. return $this->name . '=' . $this->value . ';';
  243. }
  244. /**
  245. * Generate a new Cookie object from a cookie string
  246. * (for example the value of the Set-Cookie HTTP header)
  247. *
  248. * @param string $cookieStr
  249. * @param Zend_Uri_Http|string $refUri Reference URI for default values (domain, path)
  250. * @param boolean $encodeValue Whether or not the cookie's value should be
  251. * passed through urlencode/urldecode
  252. * @return Zend_Http_Cookie A new Zend_Http_Cookie object or false on failure.
  253. */
  254. public static function fromString($cookieStr, $refUri = null, $encodeValue = true)
  255. {
  256. // Set default values
  257. if (is_string($refUri)) {
  258. $refUri = Zend_Uri_Http::factory($refUri);
  259. }
  260. $name = '';
  261. $value = '';
  262. $domain = '';
  263. $path = '';
  264. $expires = null;
  265. $secure = false;
  266. $parts = explode(';', $cookieStr);
  267. // If first part does not include '=', fail
  268. if (strpos($parts[0], '=') === false) return false;
  269. // Get the name and value of the cookie
  270. list($name, $value) = explode('=', trim(array_shift($parts)), 2);
  271. $name = trim($name);
  272. if ($encodeValue) {
  273. $value = urldecode(trim($value));
  274. }
  275. // Set default domain and path
  276. if ($refUri instanceof Zend_Uri_Http) {
  277. $domain = $refUri->getHost();
  278. $path = $refUri->getPath();
  279. $path = substr($path, 0, strrpos($path, '/'));
  280. }
  281. // Set other cookie parameters
  282. foreach ($parts as $part) {
  283. $part = trim($part);
  284. if (strtolower($part) == 'secure') {
  285. $secure = true;
  286. continue;
  287. }
  288. $keyValue = explode('=', $part, 2);
  289. if (count($keyValue) == 2) {
  290. list($k, $v) = $keyValue;
  291. switch (strtolower($k)) {
  292. case 'expires':
  293. if(($expires = strtotime($v)) === false) {
  294. /**
  295. * The expiration is past Tue, 19 Jan 2038 03:14:07 UTC
  296. * the maximum for 32-bit signed integer. Zend_Date
  297. * can get around that limit.
  298. *
  299. * @see Zend_Date
  300. */
  301. // require_once 'Zend/Date.php';
  302. $expireDate = new Zend_Date($v);
  303. $expires = $expireDate->getTimestamp();
  304. }
  305. break;
  306. case 'path':
  307. $path = $v;
  308. break;
  309. case 'domain':
  310. $domain = $v;
  311. break;
  312. default:
  313. break;
  314. }
  315. }
  316. }
  317. if ($name !== '') {
  318. $ret = new self($name, $value, $domain, $expires, $path, $secure);
  319. $ret->encodeValue = ($encodeValue) ? true : false;
  320. return $ret;
  321. } else {
  322. return false;
  323. }
  324. }
  325. /**
  326. * Check if a cookie's domain matches a host name.
  327. *
  328. * Used by Zend_Http_Cookie and Zend_Http_CookieJar for cookie matching
  329. *
  330. * @param string $cookieDomain
  331. * @param string $host
  332. *
  333. * @return boolean
  334. */
  335. public static function matchCookieDomain($cookieDomain, $host)
  336. {
  337. if (! $cookieDomain) {
  338. // require_once 'Zend/Http/Exception.php';
  339. throw new Zend_Http_Exception("\$cookieDomain is expected to be a cookie domain");
  340. }
  341. if (! $host) {
  342. // require_once 'Zend/Http/Exception.php';
  343. throw new Zend_Http_Exception("\$host is expected to be a host name");
  344. }
  345. $cookieDomain = strtolower($cookieDomain);
  346. $host = strtolower($host);
  347. if ($cookieDomain[0] == '.') {
  348. $cookieDomain = substr($cookieDomain, 1);
  349. }
  350. // Check for either exact match or suffix match
  351. return ($cookieDomain == $host ||
  352. preg_match('/\.' . preg_quote($cookieDomain) . '$/', $host));
  353. }
  354. /**
  355. * Check if a cookie's path matches a URL path
  356. *
  357. * Used by Zend_Http_Cookie and Zend_Http_CookieJar for cookie matching
  358. *
  359. * @param string $cookiePath
  360. * @param string $path
  361. * @return boolean
  362. */
  363. public static function matchCookiePath($cookiePath, $path)
  364. {
  365. if (! $cookiePath) {
  366. // require_once 'Zend/Http/Exception.php';
  367. throw new Zend_Http_Exception("\$cookiePath is expected to be a cookie path");
  368. }
  369. if (! $path) {
  370. // require_once 'Zend/Http/Exception.php';
  371. throw new Zend_Http_Exception("\$path is expected to be a host name");
  372. }
  373. return (strpos($path, $cookiePath) === 0);
  374. }
  375. }