| Viewing file:  ResponseHeaderBag.php (8.64 KB)      -rw-r--r-- Select action/file-type:
 
  (+) |  (+) |  (+) | Code (+) | Session (+) |  (+) | SDB (+) |  (+) |  (+) |  (+) |  (+) |  (+) | 
 
<?php
 /*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
 
 namespace Symfony\Component\HttpFoundation;
 
 /**
 * ResponseHeaderBag is a container for Response HTTP headers.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @api
 */
 class ResponseHeaderBag extends HeaderBag
 {
 const COOKIES_FLAT           = 'flat';
 const COOKIES_ARRAY          = 'array';
 
 const DISPOSITION_ATTACHMENT = 'attachment';
 const DISPOSITION_INLINE     = 'inline';
 
 /**
 * @var array
 */
 protected $computedCacheControl = array();
 
 /**
 * @var array
 */
 protected $cookies              = array();
 
 /**
 * @var array
 */
 protected $headerNames          = array();
 
 /**
 * Constructor.
 *
 * @param array $headers An array of HTTP headers
 *
 * @api
 */
 public function __construct(array $headers = array())
 {
 parent::__construct($headers);
 
 if (!isset($this->headers['cache-control'])) {
 $this->set('Cache-Control', '');
 }
 }
 
 /**
 * {@inheritdoc}
 */
 public function __toString()
 {
 $cookies = '';
 foreach ($this->getCookies() as $cookie) {
 $cookies .= 'Set-Cookie: '.$cookie."\r\n";
 }
 
 ksort($this->headerNames);
 
 return parent::__toString().$cookies;
 }
 
 /**
 * Returns the headers, with original capitalizations.
 *
 * @return array An array of headers
 */
 public function allPreserveCase()
 {
 return array_combine($this->headerNames, $this->headers);
 }
 
 /**
 * {@inheritdoc}
 *
 * @api
 */
 public function replace(array $headers = array())
 {
 $this->headerNames = array();
 
 parent::replace($headers);
 
 if (!isset($this->headers['cache-control'])) {
 $this->set('Cache-Control', '');
 }
 }
 
 /**
 * {@inheritdoc}
 *
 * @api
 */
 public function set($key, $values, $replace = true)
 {
 parent::set($key, $values, $replace);
 
 $uniqueKey = strtr(strtolower($key), '_', '-');
 $this->headerNames[$uniqueKey] = $key;
 
 // ensure the cache-control header has sensible defaults
 if (in_array($uniqueKey, array('cache-control', 'etag', 'last-modified', 'expires'))) {
 $computed = $this->computeCacheControlValue();
 $this->headers['cache-control'] = array($computed);
 $this->headerNames['cache-control'] = 'Cache-Control';
 $this->computedCacheControl = $this->parseCacheControl($computed);
 }
 }
 
 /**
 * {@inheritdoc}
 *
 * @api
 */
 public function remove($key)
 {
 parent::remove($key);
 
 $uniqueKey = strtr(strtolower($key), '_', '-');
 unset($this->headerNames[$uniqueKey]);
 
 if ('cache-control' === $uniqueKey) {
 $this->computedCacheControl = array();
 }
 }
 
 /**
 * {@inheritdoc}
 */
 public function hasCacheControlDirective($key)
 {
 return array_key_exists($key, $this->computedCacheControl);
 }
 
 /**
 * {@inheritdoc}
 */
 public function getCacheControlDirective($key)
 {
 return array_key_exists($key, $this->computedCacheControl) ? $this->computedCacheControl[$key] : null;
 }
 
 /**
 * Sets a cookie.
 *
 * @param Cookie $cookie
 *
 * @api
 */
 public function setCookie(Cookie $cookie)
 {
 $this->cookies[$cookie->getDomain()][$cookie->getPath()][$cookie->getName()] = $cookie;
 }
 
 /**
 * Removes a cookie from the array, but does not unset it in the browser
 *
 * @param string $name
 * @param string $path
 * @param string $domain
 *
 * @api
 */
 public function removeCookie($name, $path = '/', $domain = null)
 {
 if (null === $path) {
 $path = '/';
 }
 
 unset($this->cookies[$domain][$path][$name]);
 
 if (empty($this->cookies[$domain][$path])) {
 unset($this->cookies[$domain][$path]);
 
 if (empty($this->cookies[$domain])) {
 unset($this->cookies[$domain]);
 }
 }
 }
 
 /**
 * Returns an array with all cookies
 *
 * @param string $format
 *
 * @throws \InvalidArgumentException When the $format is invalid
 *
 * @return array
 *
 * @api
 */
 public function getCookies($format = self::COOKIES_FLAT)
 {
 if (!in_array($format, array(self::COOKIES_FLAT, self::COOKIES_ARRAY))) {
 throw new \InvalidArgumentException(sprintf('Format "%s" invalid (%s).', $format, implode(', ', array(self::COOKIES_FLAT, self::COOKIES_ARRAY))));
 }
 
 if (self::COOKIES_ARRAY === $format) {
 return $this->cookies;
 }
 
 $flattenedCookies = array();
 foreach ($this->cookies as $path) {
 foreach ($path as $cookies) {
 foreach ($cookies as $cookie) {
 $flattenedCookies[] = $cookie;
 }
 }
 }
 
 return $flattenedCookies;
 }
 
 /**
 * Clears a cookie in the browser
 *
 * @param string $name
 * @param string $path
 * @param string $domain
 *
 * @api
 */
 public function clearCookie($name, $path = '/', $domain = null)
 {
 $this->setCookie(new Cookie($name, null, 1, $path, $domain));
 }
 
 /**
 * Generates a HTTP Content-Disposition field-value.
 *
 * @param string $disposition      One of "inline" or "attachment"
 * @param string $filename         A unicode string
 * @param string $filenameFallback A string containing only ASCII characters that
 *                                 is semantically equivalent to $filename. If the filename is already ASCII,
 *                                 it can be omitted, or just copied from $filename
 *
 * @return string A string suitable for use as a Content-Disposition field-value.
 *
 * @throws \InvalidArgumentException
 * @see RFC 6266
 */
 public function makeDisposition($disposition, $filename, $filenameFallback = '')
 {
 if (!in_array($disposition, array(self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE))) {
 throw new \InvalidArgumentException(sprintf('The disposition must be either "%s" or "%s".', self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE));
 }
 
 if ('' == $filenameFallback) {
 $filenameFallback = $filename;
 }
 
 // filenameFallback is not ASCII.
 if (!preg_match('/^[\x20-\x7e]*$/', $filenameFallback)) {
 throw new \InvalidArgumentException('The filename fallback must only contain ASCII characters.');
 }
 
 // percent characters aren't safe in fallback.
 if (false !== strpos($filenameFallback, '%')) {
 throw new \InvalidArgumentException('The filename fallback cannot contain the "%" character.');
 }
 
 // path separators aren't allowed in either.
 if (false !== strpos($filename, '/') || false !== strpos($filename, '\\') || false !== strpos($filenameFallback, '/') || false !== strpos($filenameFallback, '\\')) {
 throw new \InvalidArgumentException('The filename and the fallback cannot contain the "/" and "\\" characters.');
 }
 
 $output = sprintf('%s; filename="%s"', $disposition, str_replace('"', '\\"', $filenameFallback));
 
 if ($filename !== $filenameFallback) {
 $output .= sprintf("; filename*=utf-8''%s", rawurlencode($filename));
 }
 
 return $output;
 }
 
 /**
 * Returns the calculated value of the cache-control header.
 *
 * This considers several other headers and calculates or modifies the
 * cache-control header to a sensible, conservative value.
 *
 * @return string
 */
 protected function computeCacheControlValue()
 {
 if (!$this->cacheControl && !$this->has('ETag') && !$this->has('Last-Modified') && !$this->has('Expires')) {
 return 'no-cache';
 }
 
 if (!$this->cacheControl) {
 // conservative by default
 return 'private, must-revalidate';
 }
 
 $header = $this->getCacheControlHeader();
 if (isset($this->cacheControl['public']) || isset($this->cacheControl['private'])) {
 return $header;
 }
 
 // public if s-maxage is defined, private otherwise
 if (!isset($this->cacheControl['s-maxage'])) {
 return $header.', private';
 }
 
 return $header;
 }
 }
 
 |