File indexing completed on 2024-12-22 05:36:47
0001 <?php 0002 0003 /** 0004 * Zend Framework 0005 * 0006 * LICENSE 0007 * 0008 * This source file is subject to the new BSD license that is bundled 0009 * with this package in the file LICENSE.txt. 0010 * It is also available through the world-wide-web at this URL: 0011 * http://framework.zend.com/license/new-bsd 0012 * If you did not receive a copy of the license and are unable to 0013 * obtain it through the world-wide-web, please send an email 0014 * to license@zend.com so we can send you a copy immediately. 0015 * 0016 * @category Zend 0017 * @package Zend_Http 0018 * @subpackage Header 0019 * @version $Id$ 0020 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0021 * @license http://framework.zend.com/license/new-bsd New BSD License 0022 */ 0023 0024 /** 0025 * @see Zend_Http_Header_Exception_InvalidArgumentException 0026 */ 0027 // require_once "Zend/Http/Header/Exception/InvalidArgumentException.php"; 0028 0029 /** 0030 * @see Zend_Http_Header_Exception_RuntimeException 0031 */ 0032 // require_once "Zend/Http/Header/Exception/RuntimeException.php"; 0033 0034 /** 0035 * @see Zend_Http_Header_HeaderValue 0036 */ 0037 // require_once "Zend/Http/Header/HeaderValue.php"; 0038 0039 /** 0040 * Zend_Http_Client is an implementation of an HTTP client in PHP. The client 0041 * supports basic features like sending different HTTP requests and handling 0042 * redirections, as well as more advanced features like proxy settings, HTTP 0043 * authentication and cookie persistence (using a Zend_Http_CookieJar object) 0044 * 0045 * @todo Implement proxy settings 0046 * @category Zend 0047 * @package Zend_Http 0048 * @subpackage Header 0049 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0050 * @license http://framework.zend.com/license/new-bsd New BSD License 0051 */ 0052 class Zend_Http_Header_SetCookie 0053 { 0054 0055 /** 0056 * Cookie name 0057 * 0058 * @var string 0059 */ 0060 protected $name = null; 0061 0062 /** 0063 * Cookie value 0064 * 0065 * @var string 0066 */ 0067 protected $value = null; 0068 0069 /** 0070 * Version 0071 * 0072 * @var integer 0073 */ 0074 protected $version = null; 0075 0076 /** 0077 * Max Age 0078 * 0079 * @var integer 0080 */ 0081 protected $maxAge = null; 0082 0083 /** 0084 * Cookie expiry date 0085 * 0086 * @var int 0087 */ 0088 protected $expires = null; 0089 0090 /** 0091 * Cookie domain 0092 * 0093 * @var string 0094 */ 0095 protected $domain = null; 0096 0097 /** 0098 * Cookie path 0099 * 0100 * @var string 0101 */ 0102 protected $path = null; 0103 0104 /** 0105 * Whether the cookie is secure or not 0106 * 0107 * @var boolean 0108 */ 0109 protected $secure = null; 0110 0111 /** 0112 * @var true 0113 */ 0114 protected $httponly = null; 0115 0116 /** 0117 * Generate a new Cookie object from a cookie string 0118 * (for example the value of the Set-Cookie HTTP header) 0119 * 0120 * @static 0121 * @throws Zend_Http_Header_Exception_InvalidArgumentException 0122 * @param $headerLine 0123 * @param bool $bypassHeaderFieldName 0124 * @return array|SetCookie 0125 */ 0126 public static function fromString($headerLine, $bypassHeaderFieldName = false) 0127 { 0128 list($name, $value) = explode(': ', $headerLine, 2); 0129 0130 // check to ensure proper header type for this factory 0131 if (strtolower($name) !== 'set-cookie') { 0132 throw new Zend_Http_Header_Exception_InvalidArgumentException('Invalid header line for Set-Cookie string: "' . $name . '"'); 0133 } 0134 0135 $multipleHeaders = preg_split('#(?<!Sun|Mon|Tue|Wed|Thu|Fri|Sat),\s*#', $value); 0136 $headers = array(); 0137 foreach ($multipleHeaders as $headerLine) { 0138 $header = new self(); 0139 $keyValuePairs = preg_split('#;\s*#', $headerLine); 0140 foreach ($keyValuePairs as $keyValue) { 0141 if (strpos($keyValue, '=')) { 0142 list($headerKey, $headerValue) = preg_split('#=\s*#', $keyValue, 2); 0143 } else { 0144 $headerKey = $keyValue; 0145 $headerValue = null; 0146 } 0147 0148 // First K=V pair is always the cookie name and value 0149 if ($header->getName() === NULL) { 0150 $header->setName($headerKey); 0151 $header->setValue($headerValue); 0152 continue; 0153 } 0154 0155 // Process the remanining elements 0156 switch (str_replace(array('-', '_'), '', strtolower($headerKey))) { 0157 case 'expires' : $header->setExpires($headerValue); break; 0158 case 'domain' : $header->setDomain($headerValue); break; 0159 case 'path' : $header->setPath($headerValue); break; 0160 case 'secure' : $header->setSecure(true); break; 0161 case 'httponly': $header->setHttponly(true); break; 0162 case 'version' : $header->setVersion((int) $headerValue); break; 0163 case 'maxage' : $header->setMaxAge((int) $headerValue); break; 0164 default: 0165 // Intentionally omitted 0166 } 0167 } 0168 $headers[] = $header; 0169 } 0170 return count($headers) == 1 ? array_pop($headers) : $headers; 0171 } 0172 0173 /** 0174 * Cookie object constructor 0175 * 0176 * @todo Add validation of each one of the parameters (legal domain, etc.) 0177 * 0178 * @param string $name 0179 * @param string $value 0180 * @param int $expires 0181 * @param string $path 0182 * @param string $domain 0183 * @param bool $secure 0184 * @param bool $httponly 0185 * @param string $maxAge 0186 * @param int $version 0187 * @return SetCookie 0188 */ 0189 public function __construct($name = null, $value = null, $expires = null, $path = null, $domain = null, $secure = false, $httponly = false, $maxAge = null, $version = null) 0190 { 0191 $this->type = 'Cookie'; 0192 0193 if ($name) { 0194 $this->setName($name); 0195 } 0196 0197 if ($value) { 0198 $this->setValue($value); // in parent 0199 } 0200 0201 if ($version) { 0202 $this->setVersion($version); 0203 } 0204 0205 if ($maxAge) { 0206 $this->setMaxAge($maxAge); 0207 } 0208 0209 if ($domain) { 0210 $this->setDomain($domain); 0211 } 0212 0213 if ($expires) { 0214 $this->setExpires($expires); 0215 } 0216 0217 if ($path) { 0218 $this->setPath($path); 0219 } 0220 0221 if ($secure) { 0222 $this->setSecure($secure); 0223 } 0224 0225 if ($httponly) { 0226 $this->setHttponly($httponly); 0227 } 0228 } 0229 0230 /** 0231 * @return string 'Set-Cookie' 0232 */ 0233 public function getFieldName() 0234 { 0235 return 'Set-Cookie'; 0236 } 0237 0238 /** 0239 * @throws Zend_Http_Header_Exception_RuntimeException 0240 * @return string 0241 */ 0242 public function getFieldValue() 0243 { 0244 if ($this->getName() == '') { 0245 throw new Zend_Http_Header_Exception_RuntimeException('A cookie name is required to generate a field value for this cookie'); 0246 } 0247 0248 $value = $this->getValue(); 0249 if (strpos($value,'"')!==false) { 0250 $value = '"'.urlencode(str_replace('"', '', $value)).'"'; 0251 } else { 0252 $value = urlencode($value); 0253 } 0254 $fieldValue = $this->getName() . '=' . $value; 0255 0256 $version = $this->getVersion(); 0257 if ($version!==null) { 0258 $fieldValue .= '; Version=' . $version; 0259 } 0260 0261 $maxAge = $this->getMaxAge(); 0262 if ($maxAge!==null) { 0263 $fieldValue .= '; Max-Age=' . $maxAge; 0264 } 0265 0266 $expires = $this->getExpires(); 0267 if ($expires) { 0268 $fieldValue .= '; Expires=' . $expires; 0269 } 0270 0271 $domain = $this->getDomain(); 0272 if ($domain) { 0273 $fieldValue .= '; Domain=' . $domain; 0274 } 0275 0276 $path = $this->getPath(); 0277 if ($path) { 0278 $fieldValue .= '; Path=' . $path; 0279 } 0280 0281 if ($this->isSecure()) { 0282 $fieldValue .= '; Secure'; 0283 } 0284 0285 if ($this->isHttponly()) { 0286 $fieldValue .= '; HttpOnly'; 0287 } 0288 0289 return $fieldValue; 0290 } 0291 0292 /** 0293 * @param string $name 0294 * @return SetCookie 0295 */ 0296 public function setName($name) 0297 { 0298 if (preg_match("/[=,; \t\r\n\013\014]/", $name)) { 0299 throw new Zend_Http_Header_Exception_InvalidArgumentException("Cookie name cannot contain these characters: =,; \\t\\r\\n\\013\\014 ({$name})"); 0300 } 0301 0302 $this->name = $name; 0303 return $this; 0304 } 0305 0306 /** 0307 * @return string 0308 */ 0309 public function getName() 0310 { 0311 return $this->name; 0312 } 0313 0314 /** 0315 * @param string $value 0316 */ 0317 public function setValue($value) 0318 { 0319 Zend_Http_Header_HeaderValue::assertValid($value); 0320 $this->value = $value; 0321 return $this; 0322 } 0323 0324 /** 0325 * @return string 0326 */ 0327 public function getValue() 0328 { 0329 return $this->value; 0330 } 0331 0332 /** 0333 * Set version 0334 * 0335 * @param integer $version 0336 */ 0337 public function setVersion($version) 0338 { 0339 if (!is_int($version)) { 0340 throw new Zend_Http_Header_Exception_InvalidArgumentException('Invalid Version number specified'); 0341 } 0342 $this->version = $version; 0343 } 0344 0345 /** 0346 * Get version 0347 * 0348 * @return integer 0349 */ 0350 public function getVersion() 0351 { 0352 return $this->version; 0353 } 0354 0355 /** 0356 * Set Max-Age 0357 * 0358 * @param integer $maxAge 0359 */ 0360 public function setMaxAge($maxAge) 0361 { 0362 if (!is_int($maxAge) || ($maxAge<0)) { 0363 throw new Zend_Http_Header_Exception_InvalidArgumentException('Invalid Max-Age number specified'); 0364 } 0365 $this->maxAge = $maxAge; 0366 } 0367 0368 /** 0369 * Get Max-Age 0370 * 0371 * @return integer 0372 */ 0373 public function getMaxAge() 0374 { 0375 return $this->maxAge; 0376 } 0377 0378 /** 0379 * @param int $expires 0380 * @return SetCookie 0381 */ 0382 public function setExpires($expires) 0383 { 0384 if (!empty($expires)) { 0385 if (is_string($expires)) { 0386 $expires = strtotime($expires); 0387 } elseif (!is_int($expires)) { 0388 throw new Zend_Http_Header_Exception_InvalidArgumentException('Invalid expires time specified'); 0389 } 0390 $this->expires = (int) $expires; 0391 } 0392 return $this; 0393 } 0394 0395 /** 0396 * @return int 0397 */ 0398 public function getExpires($inSeconds = false) 0399 { 0400 if ($this->expires == null) { 0401 return; 0402 } 0403 if ($inSeconds) { 0404 return $this->expires; 0405 } 0406 return gmdate('D, d-M-Y H:i:s', $this->expires) . ' GMT'; 0407 } 0408 0409 /** 0410 * @param string $domain 0411 */ 0412 public function setDomain($domain) 0413 { 0414 Zend_Http_Header_HeaderValue::assertValid($domain); 0415 $this->domain = $domain; 0416 return $this; 0417 } 0418 0419 /** 0420 * @return string 0421 */ 0422 public function getDomain() 0423 { 0424 return $this->domain; 0425 } 0426 0427 /** 0428 * @param string $path 0429 */ 0430 public function setPath($path) 0431 { 0432 Zend_Http_Header_HeaderValue::assertValid($path); 0433 $this->path = $path; 0434 return $this; 0435 } 0436 0437 /** 0438 * @return string 0439 */ 0440 public function getPath() 0441 { 0442 return $this->path; 0443 } 0444 0445 /** 0446 * @param boolean $secure 0447 */ 0448 public function setSecure($secure) 0449 { 0450 $this->secure = $secure; 0451 return $this; 0452 } 0453 0454 /** 0455 * @return boolean 0456 */ 0457 public function isSecure() 0458 { 0459 return $this->secure; 0460 } 0461 0462 /** 0463 * @param bool $httponly 0464 */ 0465 public function setHttponly($httponly) 0466 { 0467 $this->httponly = $httponly; 0468 return $this; 0469 } 0470 0471 /** 0472 * @return bool 0473 */ 0474 public function isHttponly() 0475 { 0476 return $this->httponly; 0477 } 0478 0479 /** 0480 * Check whether the cookie has expired 0481 * 0482 * Always returns false if the cookie is a session cookie (has no expiry time) 0483 * 0484 * @param int $now Timestamp to consider as "now" 0485 * @return boolean 0486 */ 0487 public function isExpired($now = null) 0488 { 0489 if ($now === null) { 0490 $now = time(); 0491 } 0492 0493 if (is_int($this->expires) && $this->expires < $now) { 0494 return true; 0495 } else { 0496 return false; 0497 } 0498 } 0499 0500 /** 0501 * Check whether the cookie is a session cookie (has no expiry time set) 0502 * 0503 * @return boolean 0504 */ 0505 public function isSessionCookie() 0506 { 0507 return ($this->expires === null); 0508 } 0509 0510 public function isValidForRequest($requestDomain, $path, $isSecure = false) 0511 { 0512 if ($this->getDomain() && (strrpos($requestDomain, $this->getDomain()) !== false)) { 0513 return false; 0514 } 0515 0516 if ($this->getPath() && (strpos($path, $this->getPath()) !== 0)) { 0517 return false; 0518 } 0519 0520 if ($this->secure && $this->isSecure()!==$isSecure) { 0521 return false; 0522 } 0523 0524 return true; 0525 0526 } 0527 0528 public function toString() 0529 { 0530 return $this->getFieldName() . ': ' . $this->getFieldValue(); 0531 } 0532 0533 public function __toString() 0534 { 0535 return $this->toString(); 0536 } 0537 0538 public function toStringMultipleHeaders(array $headers) 0539 { 0540 $headerLine = $this->toString(); 0541 /* @var $header SetCookie */ 0542 foreach ($headers as $header) { 0543 if (!$header instanceof Zend_Http_Header_SetCookie) { 0544 throw new Zend_Http_Header_Exception_RuntimeException( 0545 'The SetCookie multiple header implementation can only accept an array of SetCookie headers' 0546 ); 0547 } 0548 $headerLine .= ', ' . $header->getFieldValue(); 0549 } 0550 return $headerLine; 0551 } 0552 0553 0554 }