PageRenderTime 43ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/library/Zend/Http/Header/SetCookie.php

https://github.com/mfairchild365/zf2
PHP | 399 lines | 221 code | 52 blank | 126 comment | 36 complexity | 6872f3864081d4ea286239668b3892f5 MD5 | raw file
  1. <?php
  2. namespace Zend\Http\Header;
  3. /**
  4. * @throws Exception\InvalidArgumentException
  5. * @see http://www.ietf.org/rfc/rfc2109.txt
  6. * @see http://www.w3.org/Protocols/rfc2109/rfc2109
  7. */
  8. class SetCookie implements MultipleHeaderDescription
  9. {
  10. /**
  11. * Cookie name
  12. *
  13. * @var string
  14. */
  15. protected $name = null;
  16. /**
  17. * Cookie value
  18. *
  19. * @var string
  20. */
  21. protected $value = null;
  22. /**
  23. * Cookie expiry date
  24. *
  25. * @var int
  26. */
  27. protected $expires = null;
  28. /**
  29. * Cookie domain
  30. *
  31. * @var string
  32. */
  33. protected $domain = null;
  34. /**
  35. * Cookie path
  36. *
  37. * @var string
  38. */
  39. protected $path = null;
  40. /**
  41. * Whether the cookie is secure or not
  42. *
  43. * @var boolean
  44. */
  45. protected $secure = null;
  46. /**
  47. * @var true
  48. */
  49. protected $httponly = null;
  50. /**
  51. * @static
  52. * @throws Exception\InvalidArgumentException
  53. * @param $headerLine
  54. * @param bool $bypassHeaderFieldName
  55. * @return array|SetCookie
  56. */
  57. public static function fromString($headerLine, $bypassHeaderFieldName = false)
  58. {
  59. /* @var $setCookieProcessor Closure */
  60. static $setCookieProcessor = null;
  61. if ($setCookieProcessor === null) {
  62. $setCookieClass = get_called_class();
  63. $setCookieProcessor = function($headerLine) use ($setCookieClass) {
  64. $header = new $setCookieClass;
  65. $keyValuePairs = preg_split('#;\s*#', $headerLine);
  66. foreach ($keyValuePairs as $keyValue) {
  67. if (strpos($keyValue, '=')) {
  68. list($headerKey, $headerValue) = preg_split('#=\s*#', $keyValue, 2);
  69. } else {
  70. $headerKey = $keyValue;
  71. $headerValue = null;
  72. }
  73. switch (str_replace(array('-', '_'), '', strtolower($headerKey))) {
  74. case 'expires': $header->setExpires($headerValue); break;
  75. case 'domain': $header->setDomain($headerValue); break;
  76. case 'path': $header->setPath($headerValue); break;
  77. case 'secure': $header->setSecure(true); break;
  78. case 'httponly': $header->setHttponly(true); break;
  79. default:
  80. $header->setName($headerKey);
  81. $header->setValue($headerValue);
  82. }
  83. }
  84. return $header;
  85. };
  86. }
  87. list($name, $value) = preg_split('#: #', $headerLine, 2);
  88. // check to ensure proper header type for this factory
  89. if (strtolower($name) !== 'set-cookie') {
  90. throw new Exception\InvalidArgumentException('Invalid header line for Set-Cookie string');
  91. }
  92. $multipleHeaders = preg_split('#(?<!Sun|Mon|Tue|Wed|Thu|Fri|Sat),\s*#', $value);
  93. if (count($multipleHeaders) <= 1) {
  94. return $setCookieProcessor(array_pop($multipleHeaders));
  95. } else {
  96. $headers = array();
  97. foreach ($multipleHeaders as $headerLine) {
  98. $headers[] = $setCookieProcessor($headerLine);
  99. }
  100. return $headers;
  101. }
  102. }
  103. /**
  104. * Cookie object constructor
  105. *
  106. * @todo Add validation of each one of the parameters (legal domain, etc.)
  107. *
  108. * @param string $name
  109. * @param string $value
  110. * @param string $domain
  111. * @param int $expires
  112. * @param string $path
  113. * @param bool $secure
  114. * @param bool $httponly
  115. * @return SetCookie
  116. */
  117. public function __construct($name = null, $value = null, $domain = null, $expires = null, $path = null, $secure = false, $httponly = true)
  118. {
  119. $this->type = 'Cookie';
  120. if ($name) {
  121. $this->setName($name);
  122. }
  123. if ($value) {
  124. $this->setValue($value); // in parent
  125. }
  126. if ($domain) {
  127. $this->setDomain($domain);
  128. }
  129. if ($expires) {
  130. $this->setExpires($expires);
  131. }
  132. if ($secure) {
  133. $this->setSecure($secure);
  134. }
  135. }
  136. /**
  137. * @return string 'Set-Cookie'
  138. */
  139. public function getFieldName()
  140. {
  141. return 'Set-Cookie';
  142. }
  143. /**
  144. * @throws Exception\RuntimeException
  145. * @return string
  146. */
  147. public function getFieldValue()
  148. {
  149. if ($this->getName() == '') {
  150. throw new Exception\RuntimeException('A cookie name is required to generate a field value for this cookie');
  151. }
  152. $fieldValue = $this->getName() . '=' . urlencode($this->getValue());
  153. if (($expires = $this->getExpires())) {
  154. $fieldValue .= '; Expires=' . $expires;
  155. }
  156. if (($domain = $this->getDomain())) {
  157. $fieldValue .= '; Domain=' . $domain;
  158. }
  159. if (($path = $this->getPath())) {
  160. $fieldValue .= '; Path=' . $path;
  161. }
  162. if ($this->isSecure()) {
  163. $fieldValue .= '; Secure';
  164. }
  165. if ($this->isHttponly()) {
  166. $fieldValue .= '; HttpOnly';
  167. }
  168. return $fieldValue;
  169. }
  170. /**
  171. * @param string $name
  172. * @return SetCookie
  173. */
  174. public function setName($name)
  175. {
  176. if (preg_match("/[=,; \t\r\n\013\014]/", $name)) {
  177. throw new Exception\InvalidArgumentException("Cookie name cannot contain these characters: =,; \\t\\r\\n\\013\\014 ({$name})");
  178. }
  179. $this->name = $name;
  180. return $this;
  181. }
  182. /**
  183. * @return string
  184. */
  185. public function getName()
  186. {
  187. return $this->name;
  188. }
  189. /**
  190. * @param string $value
  191. */
  192. public function setValue($value)
  193. {
  194. $this->value = $value;
  195. }
  196. /**
  197. * @return string
  198. */
  199. public function getValue()
  200. {
  201. return $this->value;
  202. }
  203. /**
  204. * @param int $expires
  205. * @return SetCookie
  206. */
  207. public function setExpires($expires)
  208. {
  209. if (!empty($expires)) {
  210. if (is_string($expires)) {
  211. $expires = strtotime($expires);
  212. } elseif (!is_int($expires)) {
  213. throw new Exception\InvalidArgumentException('Invalid expires time specified');
  214. }
  215. $this->expires = (int) $expires;
  216. }
  217. return $this;
  218. }
  219. /**
  220. * @return int
  221. */
  222. public function getExpires($inSeconds = false)
  223. {
  224. if ($this->expires == null) {
  225. return;
  226. }
  227. if ($inSeconds) {
  228. return $this->expires;
  229. }
  230. return gmdate('D, d-M-Y H:i:s', $this->expires) . ' GMT';
  231. }
  232. /**
  233. * @param string $domain
  234. */
  235. public function setDomain($domain)
  236. {
  237. $this->domain = $domain;
  238. }
  239. /**
  240. * @return string
  241. */
  242. public function getDomain()
  243. {
  244. return $this->domain;
  245. }
  246. /**
  247. * @param string $path
  248. */
  249. public function setPath($path)
  250. {
  251. $this->path = $path;
  252. }
  253. /**
  254. * @return string
  255. */
  256. public function getPath()
  257. {
  258. return $this->path;
  259. }
  260. /**
  261. * @param boolean $secure
  262. */
  263. public function setSecure($secure)
  264. {
  265. $this->secure = $secure;
  266. }
  267. /**
  268. * @return boolean
  269. */
  270. public function isSecure()
  271. {
  272. return $this->secure;
  273. }
  274. /**
  275. * @param \Zend\Http\Header\true $httponly
  276. */
  277. public function setHttponly($httponly)
  278. {
  279. $this->httponly = $httponly;
  280. }
  281. /**
  282. * @return \Zend\Http\Header\true
  283. */
  284. public function isHttponly()
  285. {
  286. return $this->httponly;
  287. }
  288. /**
  289. * Check whether the cookie has expired
  290. *
  291. * Always returns false if the cookie is a session cookie (has no expiry time)
  292. *
  293. * @param int $now Timestamp to consider as "now"
  294. * @return boolean
  295. */
  296. public function isExpired($now = null)
  297. {
  298. if ($now === null) {
  299. $now = time();
  300. }
  301. if (is_int($this->expires) && $this->expires < $now) {
  302. return true;
  303. } else {
  304. return false;
  305. }
  306. }
  307. /**
  308. * Check whether the cookie is a session cookie (has no expiry time set)
  309. *
  310. * @return boolean
  311. */
  312. public function isSessionCookie()
  313. {
  314. return ($this->expires === null);
  315. }
  316. public function isValidForRequest($requestDomain, $path, $isSecure = false)
  317. {
  318. if ($this->getDomain() && (strrpos($requestDomain, $this->getDomain()) !== false)) {
  319. return false;
  320. }
  321. if ($this->getPath() && (strpos($path, $this->getPath()) !== 0)) {
  322. return false;
  323. }
  324. if ($this->secure && $this->isSecure()!==$isSecure) {
  325. return false;
  326. }
  327. return true;
  328. }
  329. public function toString()
  330. {
  331. return 'Set-Cookie: ' . $this->getFieldValue();
  332. }
  333. public function toStringMultipleHeaders(array $headers)
  334. {
  335. $headerLine = $this->toString();
  336. /* @var $header SetCookie */
  337. foreach ($headers as $header) {
  338. if (!$header instanceof SetCookie) {
  339. throw new Exception\RuntimeException(
  340. 'The SetCookie multiple header implementation can only accept an array of SetCookie headers'
  341. );
  342. }
  343. $headerLine .= ', ' . $header->getFieldValue();
  344. }
  345. return $headerLine;
  346. }
  347. }