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 }