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