PageRenderTime 49ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/Http/Header/SetCookie.php

https://bitbucket.org/netglue/zf-1.12-release
PHP | 546 lines | 278 code | 71 blank | 197 comment | 46 complexity | 194d2c762018cc2ce7fb83dcc686d05a 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 Header
  18. * @version $Id$
  19. * @copyright Copyright (c) 2005-2011 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_Http_Header_Exception_InvalidArgumentException
  24. */
  25. require_once "Zend/Http/Header/Exception/InvalidArgumentException.php";
  26. /**
  27. * @see Zend_Http_Header_Exception_RuntimeException
  28. */
  29. require_once "Zend/Http/Header/Exception/RuntimeException.php";
  30. /**
  31. * Zend_Http_Client is an implementation of an HTTP client in PHP. The client
  32. * supports basic features like sending different HTTP requests and handling
  33. * redirections, as well as more advanced features like proxy settings, HTTP
  34. * authentication and cookie persistence (using a Zend_Http_CookieJar object)
  35. *
  36. * @todo Implement proxy settings
  37. * @category Zend
  38. * @package Zend_Http
  39. * @subpackage Header
  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_Header_SetCookie
  44. {
  45. /**
  46. * Cookie name
  47. *
  48. * @var string
  49. */
  50. protected $name = null;
  51. /**
  52. * Cookie value
  53. *
  54. * @var string
  55. */
  56. protected $value = null;
  57. /**
  58. * Version
  59. *
  60. * @var integer
  61. */
  62. protected $version = null;
  63. /**
  64. * Max Age
  65. *
  66. * @var integer
  67. */
  68. protected $maxAge = null;
  69. /**
  70. * Cookie expiry date
  71. *
  72. * @var int
  73. */
  74. protected $expires = null;
  75. /**
  76. * Cookie domain
  77. *
  78. * @var string
  79. */
  80. protected $domain = null;
  81. /**
  82. * Cookie path
  83. *
  84. * @var string
  85. */
  86. protected $path = null;
  87. /**
  88. * Whether the cookie is secure or not
  89. *
  90. * @var boolean
  91. */
  92. protected $secure = null;
  93. /**
  94. * @var true
  95. */
  96. protected $httponly = null;
  97. /**
  98. * Generate a new Cookie object from a cookie string
  99. * (for example the value of the Set-Cookie HTTP header)
  100. *
  101. * @static
  102. * @throws Zend_Http_Header_Exception_InvalidArgumentException
  103. * @param $headerLine
  104. * @param bool $bypassHeaderFieldName
  105. * @return array|SetCookie
  106. */
  107. public static function fromString($headerLine, $bypassHeaderFieldName = false)
  108. {
  109. list($name, $value) = explode(': ', $headerLine, 2);
  110. // check to ensure proper header type for this factory
  111. if (strtolower($name) !== 'set-cookie') {
  112. throw new Zend_Http_Header_Exception_InvalidArgumentException('Invalid header line for Set-Cookie string: "' . $name . '"');
  113. }
  114. $multipleHeaders = preg_split('#(?<!Sun|Mon|Tue|Wed|Thu|Fri|Sat),\s*#', $value);
  115. $headers = array();
  116. foreach ($multipleHeaders as $headerLine) {
  117. $header = new self();
  118. $keyValuePairs = preg_split('#;\s*#', $headerLine);
  119. foreach ($keyValuePairs as $keyValue) {
  120. if (strpos($keyValue, '=')) {
  121. list($headerKey, $headerValue) = preg_split('#=\s*#', $keyValue, 2);
  122. } else {
  123. $headerKey = $keyValue;
  124. $headerValue = null;
  125. }
  126. // First K=V pair is always the cookie name and value
  127. if ($header->getName() === NULL) {
  128. $header->setName($headerKey);
  129. $header->setValue($headerValue);
  130. continue;
  131. }
  132. // Process the remanining elements
  133. switch (str_replace(array('-', '_'), '', strtolower($headerKey))) {
  134. case 'expires' : $header->setExpires($headerValue); break;
  135. case 'domain' : $header->setDomain($headerValue); break;
  136. case 'path' : $header->setPath($headerValue); break;
  137. case 'secure' : $header->setSecure(true); break;
  138. case 'httponly': $header->setHttponly(true); break;
  139. case 'version' : $header->setVersion((int) $headerValue); break;
  140. case 'maxage' : $header->setMaxAge((int) $headerValue); break;
  141. default:
  142. // Intentionally omitted
  143. }
  144. }
  145. $headers[] = $header;
  146. }
  147. return count($headers) == 1 ? array_pop($headers) : $headers;
  148. }
  149. /**
  150. * Cookie object constructor
  151. *
  152. * @todo Add validation of each one of the parameters (legal domain, etc.)
  153. *
  154. * @param string $name
  155. * @param string $value
  156. * @param int $expires
  157. * @param string $path
  158. * @param string $domain
  159. * @param bool $secure
  160. * @param bool $httponly
  161. * @param string $maxAge
  162. * @param int $version
  163. * @return SetCookie
  164. */
  165. public function __construct($name = null, $value = null, $expires = null, $path = null, $domain = null, $secure = false, $httponly = false, $maxAge = null, $version = null)
  166. {
  167. $this->type = 'Cookie';
  168. if ($name) {
  169. $this->setName($name);
  170. }
  171. if ($value) {
  172. $this->setValue($value); // in parent
  173. }
  174. if ($version) {
  175. $this->setVersion($version);
  176. }
  177. if ($maxAge) {
  178. $this->setMaxAge($maxAge);
  179. }
  180. if ($domain) {
  181. $this->setDomain($domain);
  182. }
  183. if ($expires) {
  184. $this->setExpires($expires);
  185. }
  186. if ($path) {
  187. $this->setPath($path);
  188. }
  189. if ($secure) {
  190. $this->setSecure($secure);
  191. }
  192. if ($httponly) {
  193. $this->setHttponly($httponly);
  194. }
  195. }
  196. /**
  197. * @return string 'Set-Cookie'
  198. */
  199. public function getFieldName()
  200. {
  201. return 'Set-Cookie';
  202. }
  203. /**
  204. * @throws Zend_Http_Header_Exception_RuntimeException
  205. * @return string
  206. */
  207. public function getFieldValue()
  208. {
  209. if ($this->getName() == '') {
  210. throw new Zend_Http_Header_Exception_RuntimeException('A cookie name is required to generate a field value for this cookie');
  211. }
  212. $value = $this->getValue();
  213. if (strpos($value,'"')!==false) {
  214. $value = '"'.urlencode(str_replace('"', '', $value)).'"';
  215. } else {
  216. $value = urlencode($value);
  217. }
  218. $fieldValue = $this->getName() . '=' . $value;
  219. $version = $this->getVersion();
  220. if ($version!==null) {
  221. $fieldValue .= '; Version=' . $version;
  222. }
  223. $maxAge = $this->getMaxAge();
  224. if ($maxAge!==null) {
  225. $fieldValue .= '; Max-Age=' . $maxAge;
  226. }
  227. $expires = $this->getExpires();
  228. if ($expires) {
  229. $fieldValue .= '; Expires=' . $expires;
  230. }
  231. $domain = $this->getDomain();
  232. if ($domain) {
  233. $fieldValue .= '; Domain=' . $domain;
  234. }
  235. $path = $this->getPath();
  236. if ($path) {
  237. $fieldValue .= '; Path=' . $path;
  238. }
  239. if ($this->isSecure()) {
  240. $fieldValue .= '; Secure';
  241. }
  242. if ($this->isHttponly()) {
  243. $fieldValue .= '; HttpOnly';
  244. }
  245. return $fieldValue;
  246. }
  247. /**
  248. * @param string $name
  249. * @return SetCookie
  250. */
  251. public function setName($name)
  252. {
  253. if (preg_match("/[=,; \t\r\n\013\014]/", $name)) {
  254. throw new Zend_Http_Header_Exception_InvalidArgumentException("Cookie name cannot contain these characters: =,; \\t\\r\\n\\013\\014 ({$name})");
  255. }
  256. $this->name = $name;
  257. return $this;
  258. }
  259. /**
  260. * @return string
  261. */
  262. public function getName()
  263. {
  264. return $this->name;
  265. }
  266. /**
  267. * @param string $value
  268. */
  269. public function setValue($value)
  270. {
  271. $this->value = $value;
  272. return $this;
  273. }
  274. /**
  275. * @return string
  276. */
  277. public function getValue()
  278. {
  279. return $this->value;
  280. }
  281. /**
  282. * Set version
  283. *
  284. * @param integer $version
  285. */
  286. public function setVersion($version)
  287. {
  288. if (!is_int($version)) {
  289. throw new Zend_Http_Header_Exception_InvalidArgumentException('Invalid Version number specified');
  290. }
  291. $this->version = $version;
  292. }
  293. /**
  294. * Get version
  295. *
  296. * @return integer
  297. */
  298. public function getVersion()
  299. {
  300. return $this->version;
  301. }
  302. /**
  303. * Set Max-Age
  304. *
  305. * @param integer $maxAge
  306. */
  307. public function setMaxAge($maxAge)
  308. {
  309. if (!is_int($maxAge) || ($maxAge<0)) {
  310. throw new Zend_Http_Header_Exception_InvalidArgumentException('Invalid Max-Age number specified');
  311. }
  312. $this->maxAge = $maxAge;
  313. }
  314. /**
  315. * Get Max-Age
  316. *
  317. * @return integer
  318. */
  319. public function getMaxAge()
  320. {
  321. return $this->maxAge;
  322. }
  323. /**
  324. * @param int $expires
  325. * @return SetCookie
  326. */
  327. public function setExpires($expires)
  328. {
  329. if (!empty($expires)) {
  330. if (is_string($expires)) {
  331. $expires = strtotime($expires);
  332. } elseif (!is_int($expires)) {
  333. throw new Zend_Http_Header_Exception_InvalidArgumentException('Invalid expires time specified');
  334. }
  335. $this->expires = (int) $expires;
  336. }
  337. return $this;
  338. }
  339. /**
  340. * @return int
  341. */
  342. public function getExpires($inSeconds = false)
  343. {
  344. if ($this->expires == null) {
  345. return;
  346. }
  347. if ($inSeconds) {
  348. return $this->expires;
  349. }
  350. return gmdate('D, d-M-Y H:i:s', $this->expires) . ' GMT';
  351. }
  352. /**
  353. * @param string $domain
  354. */
  355. public function setDomain($domain)
  356. {
  357. $this->domain = $domain;
  358. return $this;
  359. }
  360. /**
  361. * @return string
  362. */
  363. public function getDomain()
  364. {
  365. return $this->domain;
  366. }
  367. /**
  368. * @param string $path
  369. */
  370. public function setPath($path)
  371. {
  372. $this->path = $path;
  373. return $this;
  374. }
  375. /**
  376. * @return string
  377. */
  378. public function getPath()
  379. {
  380. return $this->path;
  381. }
  382. /**
  383. * @param boolean $secure
  384. */
  385. public function setSecure($secure)
  386. {
  387. $this->secure = $secure;
  388. return $this;
  389. }
  390. /**
  391. * @return boolean
  392. */
  393. public function isSecure()
  394. {
  395. return $this->secure;
  396. }
  397. /**
  398. * @param bool $httponly
  399. */
  400. public function setHttponly($httponly)
  401. {
  402. $this->httponly = $httponly;
  403. return $this;
  404. }
  405. /**
  406. * @return bool
  407. */
  408. public function isHttponly()
  409. {
  410. return $this->httponly;
  411. }
  412. /**
  413. * Check whether the cookie has expired
  414. *
  415. * Always returns false if the cookie is a session cookie (has no expiry time)
  416. *
  417. * @param int $now Timestamp to consider as "now"
  418. * @return boolean
  419. */
  420. public function isExpired($now = null)
  421. {
  422. if ($now === null) {
  423. $now = time();
  424. }
  425. if (is_int($this->expires) && $this->expires < $now) {
  426. return true;
  427. } else {
  428. return false;
  429. }
  430. }
  431. /**
  432. * Check whether the cookie is a session cookie (has no expiry time set)
  433. *
  434. * @return boolean
  435. */
  436. public function isSessionCookie()
  437. {
  438. return ($this->expires === null);
  439. }
  440. public function isValidForRequest($requestDomain, $path, $isSecure = false)
  441. {
  442. if ($this->getDomain() && (strrpos($requestDomain, $this->getDomain()) !== false)) {
  443. return false;
  444. }
  445. if ($this->getPath() && (strpos($path, $this->getPath()) !== 0)) {
  446. return false;
  447. }
  448. if ($this->secure && $this->isSecure()!==$isSecure) {
  449. return false;
  450. }
  451. return true;
  452. }
  453. public function toString()
  454. {
  455. return $this->getFieldName() . ': ' . $this->getFieldValue();
  456. }
  457. public function __toString()
  458. {
  459. return $this->toString();
  460. }
  461. public function toStringMultipleHeaders(array $headers)
  462. {
  463. $headerLine = $this->toString();
  464. /* @var $header SetCookie */
  465. foreach ($headers as $header) {
  466. if (!$header instanceof Zend_Http_Header_SetCookie) {
  467. throw new Zend_Http_Header_Exception_RuntimeException(
  468. 'The SetCookie multiple header implementation can only accept an array of SetCookie headers'
  469. );
  470. }
  471. $headerLine .= ', ' . $header->getFieldValue();
  472. }
  473. return $headerLine;
  474. }
  475. }