From b9cf8dfb715e7cc6b639150ea16b1ef044e60b1f Mon Sep 17 00:00:00 2001 From: Taylor Otwell Date: Wed, 1 May 2013 14:19:10 -0500 Subject: [PATCH] Upgrade to latest Symfony HttpFoundation tag. Closes #1865. --- .../Component/HttpFoundation/AcceptHeader.php | 172 +++++++++++ .../HttpFoundation/AcceptHeaderItem.php | 226 ++++++++++++++ .../HttpFoundation/BinaryFileResponse.php | 278 ++++++++++++++++++ .../Component/HttpFoundation/CHANGELOG.md | 14 + .../Component/HttpFoundation/Cookie.php | 2 + .../MimeType/FileBinaryMimeTypeGuesser.php | 4 +- .../File/MimeType/MimeTypeGuesser.php | 5 +- .../HttpFoundation/File/UploadedFile.php | 13 + .../Component/HttpFoundation/HeaderBag.php | 4 +- .../Component/HttpFoundation/IpUtils.php | 111 +++++++ .../Component/HttpFoundation/JsonResponse.php | 14 +- .../Symfony/Component/HttpFoundation/LICENSE | 2 +- .../Component/HttpFoundation/ParameterBag.php | 2 + .../Component/HttpFoundation/README.md | 6 +- .../HttpFoundation/RedirectResponse.php | 4 + .../Component/HttpFoundation/Request.php | 197 +++++++++---- .../HttpFoundation/RequestMatcher.php | 87 +----- .../Component/HttpFoundation/Response.php | 71 +++-- .../HttpFoundation/ResponseHeaderBag.php | 34 ++- .../Session/Attribute/AttributeBag.php | 2 +- .../HttpFoundation/Session/Flash/FlashBag.php | 7 + .../HttpFoundation/Session/Session.php | 14 + .../Storage/Handler/MongoDbSessionHandler.php | 45 ++- .../Session/Storage/NativeSessionStorage.php | 10 +- .../Session/Storage/Proxy/AbstractProxy.php | 4 + .../HttpFoundation/StreamedResponse.php | 2 + .../Component/HttpFoundation/composer.json | 13 +- .../Component/HttpFoundation/phpunit.xml.dist | 30 ++ 28 files changed, 1154 insertions(+), 219 deletions(-) create mode 100644 laravel/vendor/Symfony/Component/HttpFoundation/AcceptHeader.php create mode 100644 laravel/vendor/Symfony/Component/HttpFoundation/AcceptHeaderItem.php create mode 100644 laravel/vendor/Symfony/Component/HttpFoundation/BinaryFileResponse.php create mode 100644 laravel/vendor/Symfony/Component/HttpFoundation/IpUtils.php create mode 100644 laravel/vendor/Symfony/Component/HttpFoundation/phpunit.xml.dist diff --git a/laravel/vendor/Symfony/Component/HttpFoundation/AcceptHeader.php b/laravel/vendor/Symfony/Component/HttpFoundation/AcceptHeader.php new file mode 100644 index 00000000..48c10c15 --- /dev/null +++ b/laravel/vendor/Symfony/Component/HttpFoundation/AcceptHeader.php @@ -0,0 +1,172 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation; + +/** + * Represents an Accept-* header. + * + * An accept header is compound with a list of items, + * sorted by descending quality. + * + * @author Jean-François Simon + */ +class AcceptHeader +{ + /** + * @var AcceptHeaderItem[] + */ + private $items = array(); + + /** + * @var bool + */ + private $sorted = true; + + /** + * Constructor. + * + * @param AcceptHeaderItem[] $items + */ + public function __construct(array $items) + { + foreach ($items as $item) { + $this->add($item); + } + } + + /** + * Builds an AcceptHeader instance from a string. + * + * @param string $headerValue + * + * @return AcceptHeader + */ + public static function fromString($headerValue) + { + $index = 0; + + return new self(array_map(function ($itemValue) use (&$index) { + $item = AcceptHeaderItem::fromString($itemValue); + $item->setIndex($index++); + + return $item; + }, preg_split('/\s*(?:,*("[^"]+"),*|,*(\'[^\']+\'),*|,+)\s*/', $headerValue, 0, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE))); + } + + /** + * Returns header value's string representation. + * + * @return string + */ + public function __toString() + { + return implode(',', $this->items); + } + + /** + * Tests if header has given value. + * + * @param string $value + * + * @return Boolean + */ + public function has($value) + { + return isset($this->items[$value]); + } + + /** + * Returns given value's item, if exists. + * + * @param string $value + * + * @return AcceptHeaderItem|null + */ + public function get($value) + { + return isset($this->items[$value]) ? $this->items[$value] : null; + } + + /** + * Adds an item. + * + * @param AcceptHeaderItem $item + * + * @return AcceptHeader + */ + public function add(AcceptHeaderItem $item) + { + $this->items[$item->getValue()] = $item; + $this->sorted = false; + + return $this; + } + + /** + * Returns all items. + * + * @return AcceptHeaderItem[] + */ + public function all() + { + $this->sort(); + + return $this->items; + } + + /** + * Filters items on their value using given regex. + * + * @param string $pattern + * + * @return AcceptHeader + */ + public function filter($pattern) + { + return new self(array_filter($this->items, function (AcceptHeaderItem $item) use ($pattern) { + return preg_match($pattern, $item->getValue()); + })); + } + + /** + * Returns first item. + * + * @return AcceptHeaderItem|null + */ + public function first() + { + $this->sort(); + + return !empty($this->items) ? reset($this->items) : null; + } + + /** + * Sorts items by descending quality + */ + private function sort() + { + if (!$this->sorted) { + uasort($this->items, function ($a, $b) { + $qA = $a->getQuality(); + $qB = $b->getQuality(); + + if ($qA === $qB) { + return $a->getIndex() > $b->getIndex() ? 1 : -1; + } + + return $qA > $qB ? -1 : 1; + }); + + $this->sorted = true; + } + } +} diff --git a/laravel/vendor/Symfony/Component/HttpFoundation/AcceptHeaderItem.php b/laravel/vendor/Symfony/Component/HttpFoundation/AcceptHeaderItem.php new file mode 100644 index 00000000..9d4c3132 --- /dev/null +++ b/laravel/vendor/Symfony/Component/HttpFoundation/AcceptHeaderItem.php @@ -0,0 +1,226 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation; + +/** + * Represents an Accept-* header item. + * + * @author Jean-François Simon + */ +class AcceptHeaderItem +{ + /** + * @var string + */ + private $value; + + /** + * @var float + */ + private $quality = 1.0; + + /** + * @var int + */ + private $index = 0; + + /** + * @var array + */ + private $attributes = array(); + + /** + * Constructor. + * + * @param string $value + * @param array $attributes + */ + public function __construct($value, array $attributes = array()) + { + $this->value = $value; + foreach ($attributes as $name => $value) { + $this->setAttribute($name, $value); + } + } + + /** + * Builds an AcceptHeaderInstance instance from a string. + * + * @param string $itemValue + * + * @return AcceptHeaderItem + */ + public static function fromString($itemValue) + { + $bits = preg_split('/\s*(?:;*("[^"]+");*|;*(\'[^\']+\');*|;+)\s*/', $itemValue, 0, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE); + $value = array_shift($bits); + $attributes = array(); + + $lastNullAttribute = null; + foreach ($bits as $bit) { + if (($start = substr($bit, 0, 1)) === ($end = substr($bit, -1)) && ($start === '"' || $start === '\'')) { + $attributes[$lastNullAttribute] = substr($bit, 1, -1); + } elseif ('=' === $end) { + $lastNullAttribute = $bit = substr($bit, 0, -1); + $attributes[$bit] = null; + } else { + $parts = explode('=', $bit); + $attributes[$parts[0]] = isset($parts[1]) && strlen($parts[1]) > 0 ? $parts[1] : ''; + } + } + + return new self(($start = substr($value, 0, 1)) === ($end = substr($value, -1)) && ($start === '"' || $start === '\'') ? substr($value, 1, -1) : $value, $attributes); + } + + /** + * Returns header value's string representation. + * + * @return string + */ + public function __toString() + { + $string = $this->value.($this->quality < 1 ? ';q='.$this->quality : ''); + if (count($this->attributes) > 0) { + $string .= ';'.implode(';', array_map(function($name, $value) { + return sprintf(preg_match('/[,;=]/', $value) ? '%s="%s"' : '%s=%s', $name, $value); + }, array_keys($this->attributes), $this->attributes)); + } + + return $string; + } + + /** + * Set the item value. + * + * @param string $value + * + * @return AcceptHeaderItem + */ + public function setValue($value) + { + $this->value = $value; + + return $this; + } + + /** + * Returns the item value. + * + * @return string + */ + public function getValue() + { + return $this->value; + } + + /** + * Set the item quality. + * + * @param float $quality + * + * @return AcceptHeaderItem + */ + public function setQuality($quality) + { + $this->quality = $quality; + + return $this; + } + + /** + * Returns the item quality. + * + * @return float + */ + public function getQuality() + { + return $this->quality; + } + + /** + * Set the item index. + * + * @param int $index + * + * @return AcceptHeaderItem + */ + public function setIndex($index) + { + $this->index = $index; + + return $this; + } + + /** + * Returns the item index. + * + * @return int + */ + public function getIndex() + { + return $this->index; + } + + /** + * Tests if an attribute exists. + * + * @param string $name + * + * @return Boolean + */ + public function hasAttribute($name) + { + return isset($this->attributes[$name]); + } + + /** + * Returns an attribute by its name. + * + * @param string $name + * @param mixed $default + * + * @return mixed + */ + public function getAttribute($name, $default = null) + { + return isset($this->attributes[$name]) ? $this->attributes[$name] : $default; + } + + /** + * Returns all attributes. + * + * @return array + */ + public function getAttributes() + { + return $this->attributes; + } + + /** + * Set an attribute. + * + * @param string $name + * @param string $value + * + * @return AcceptHeaderItem + */ + public function setAttribute($name, $value) + { + if ('q' === $name) { + $this->quality = (float) $value; + } else { + $this->attributes[$name] = (string) $value; + } + + return $this; + } +} diff --git a/laravel/vendor/Symfony/Component/HttpFoundation/BinaryFileResponse.php b/laravel/vendor/Symfony/Component/HttpFoundation/BinaryFileResponse.php new file mode 100644 index 00000000..cb6c8a1e --- /dev/null +++ b/laravel/vendor/Symfony/Component/HttpFoundation/BinaryFileResponse.php @@ -0,0 +1,278 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation; + +use Symfony\Component\HttpFoundation\File\File; +use Symfony\Component\HttpFoundation\File\Exception\FileException; + +/** + * BinaryFileResponse represents an HTTP response delivering a file. + * + * @author Niklas Fiekas + * @author stealth35 + * @author Igor Wiedler + * @author Jordan Alliot + * @author Sergey Linnik + */ +class BinaryFileResponse extends Response +{ + protected static $trustXSendfileTypeHeader = false; + + protected $file; + protected $offset; + protected $maxlen; + + /** + * Constructor. + * + * @param SplFileInfo|string $file The file to stream + * @param integer $status The response status code + * @param array $headers An array of response headers + * @param boolean $public Files are public by default + * @param null|string $contentDisposition The type of Content-Disposition to set automatically with the filename + * @param boolean $autoEtag Whether the ETag header should be automatically set + * @param boolean $autoLastModified Whether the Last-Modified header should be automatically set + */ + public function __construct($file, $status = 200, $headers = array(), $public = true, $contentDisposition = null, $autoEtag = false, $autoLastModified = true) + { + parent::__construct(null, $status, $headers); + + $this->setFile($file, $contentDisposition, $autoEtag, $autoLastModified); + + if ($public) { + $this->setPublic(); + } + } + + /** + * {@inheritdoc} + */ + public static function create($file = null, $status = 200, $headers = array(), $public = true, $contentDisposition = null, $autoEtag = false, $autoLastModified = true) + { + return new static($file, $status, $headers, $public, $contentDisposition, $autoEtag, $autoLastModified); + } + + /** + * Sets the file to stream. + * + * @param SplFileInfo|string $file The file to stream + * @param string $contentDisposition + * @param Boolean $autoEtag + * @param Boolean $autoLastModified + * + * @return BinaryFileResponse + * + * @throws FileException + */ + public function setFile($file, $contentDisposition = null, $autoEtag = false, $autoLastModified = true) + { + $file = new File((string) $file); + + if (!$file->isReadable()) { + throw new FileException('File must be readable.'); + } + + $this->file = $file; + + if ($autoEtag) { + $this->setAutoEtag(); + } + + if ($autoLastModified) { + $this->setAutoLastModified(); + } + + if ($contentDisposition) { + $this->setContentDisposition($contentDisposition); + } + + return $this; + } + + /** + * Gets the file. + * + * @return File The file to stream + */ + public function getFile() + { + return $this->file; + } + + /** + * Automatically sets the Last-Modified header according the file modification date. + */ + public function setAutoLastModified() + { + $this->setLastModified(\DateTime::createFromFormat('U', $this->file->getMTime())); + + return $this; + } + + /** + * Automatically sets the ETag header according to the checksum of the file. + */ + public function setAutoEtag() + { + $this->setEtag(sha1_file($this->file->getPathname())); + + return $this; + } + + /** + * Sets the Content-Disposition header with the given filename. + * + * @param string $disposition ResponseHeaderBag::DISPOSITION_INLINE or ResponseHeaderBag::DISPOSITION_ATTACHMENT + * @param string $filename Optionally use this filename instead of the real name of the file + * @param string $filenameFallback A fallback filename, containing only ASCII characters. Defaults to an automatically encoded filename + * + * @return BinaryFileResponse + */ + public function setContentDisposition($disposition, $filename = '', $filenameFallback = '') + { + if ($filename === '') { + $filename = $this->file->getFilename(); + } + + $dispositionHeader = $this->headers->makeDisposition($disposition, $filename, $filenameFallback); + $this->headers->set('Content-Disposition', $dispositionHeader); + + return $this; + } + + /** + * {@inheritdoc} + */ + public function prepare(Request $request) + { + $this->headers->set('Content-Length', $this->file->getSize()); + $this->headers->set('Accept-Ranges', 'bytes'); + $this->headers->set('Content-Transfer-Encoding', 'binary'); + + if (!$this->headers->has('Content-Type')) { + $this->headers->set('Content-Type', $this->file->getMimeType() ?: 'application/octet-stream'); + } + + if ('HTTP/1.0' != $request->server->get('SERVER_PROTOCOL')) { + $this->setProtocolVersion('1.1'); + } + + $this->offset = 0; + $this->maxlen = -1; + + if (self::$trustXSendfileTypeHeader && $request->headers->has('X-Sendfile-Type')) { + // Use X-Sendfile, do not send any content. + $type = $request->headers->get('X-Sendfile-Type'); + $path = $this->file->getRealPath(); + if (strtolower($type) == 'x-accel-redirect') { + // Do X-Accel-Mapping substitutions. + foreach (explode(',', $request->headers->get('X-Accel-Mapping', '')) as $mapping) { + $mapping = explode('=', $mapping, 2); + + if (2 == count($mapping)) { + $location = trim($mapping[0]); + $pathPrefix = trim($mapping[1]); + + if (substr($path, 0, strlen($pathPrefix)) == $pathPrefix) { + $path = $location . substr($path, strlen($pathPrefix)); + break; + } + } + } + } + $this->headers->set($type, $path); + $this->maxlen = 0; + } elseif ($request->headers->has('Range')) { + // Process the range headers. + if (!$request->headers->has('If-Range') || $this->getEtag() == $request->headers->get('If-Range')) { + $range = $request->headers->get('Range'); + $fileSize = $this->file->getSize(); + + list($start, $end) = explode('-', substr($range, 6), 2) + array(0); + + $end = ('' === $end) ? $fileSize - 1 : (int) $end; + + if ('' === $start) { + $start = $fileSize - $end; + $end = $fileSize - 1; + } else { + $start = (int) $start; + } + + $start = max($start, 0); + $end = min($end, $fileSize - 1); + + $this->maxlen = $end < $fileSize ? $end - $start + 1 : -1; + $this->offset = $start; + + $this->setStatusCode(206); + $this->headers->set('Content-Range', sprintf('bytes %s-%s/%s', $start, $end, $fileSize)); + } + } + + return $this; + } + + /** + * Sends the file. + */ + public function sendContent() + { + if (!$this->isSuccessful()) { + parent::sendContent(); + + return; + } + + if (0 === $this->maxlen) { + return; + } + + $out = fopen('php://output', 'wb'); + $file = fopen($this->file->getPathname(), 'rb'); + + stream_copy_to_stream($file, $out, $this->maxlen, $this->offset); + + fclose($out); + fclose($file); + } + + /** + * {@inheritdoc} + * + * @throws \LogicException when the content is not null + */ + public function setContent($content) + { + if (null !== $content) { + throw new \LogicException('The content cannot be set on a BinaryFileResponse instance.'); + } + } + + /** + * {@inheritdoc} + * + * @return false + */ + public function getContent() + { + return false; + } + + /** + * Trust X-Sendfile-Type header. + */ + public static function trustXSendfileTypeHeader() + { + self::$trustXSendfileTypeHeader = true; + } +} diff --git a/laravel/vendor/Symfony/Component/HttpFoundation/CHANGELOG.md b/laravel/vendor/Symfony/Component/HttpFoundation/CHANGELOG.md index 4a00207e..318383aa 100755 --- a/laravel/vendor/Symfony/Component/HttpFoundation/CHANGELOG.md +++ b/laravel/vendor/Symfony/Component/HttpFoundation/CHANGELOG.md @@ -1,6 +1,20 @@ CHANGELOG ========= +2.2.0 +----- + + * fixed the Request::create() precedence (URI information always take precedence now) + * added Request::getTrustedProxies() + * deprecated Request::isProxyTrusted() + * [BC BREAK] JsonResponse does not turn a top level empty array to an object anymore, use an ArrayObject to enforce objects + * added a IpUtils class to check if an IP belongs to a CIDR + * added Request::getRealMethod() to get the "real" HTTP method (getMethod() returns the "intended" HTTP method) + * disabled _method request parameter support by default (call Request::enableHttpMethodParameterOverride() to + enable it, and Request::getHttpMethodParameterOverride() to check if it is supported) + * Request::splitHttpAcceptHeader() method is deprecated and will be removed in 2.3 + * Deprecated Flashbag::count() and \Countable interface, will be removed in 2.3 + 2.1.0 ----- diff --git a/laravel/vendor/Symfony/Component/HttpFoundation/Cookie.php b/laravel/vendor/Symfony/Component/HttpFoundation/Cookie.php index fe3a4cff..fdc33e36 100755 --- a/laravel/vendor/Symfony/Component/HttpFoundation/Cookie.php +++ b/laravel/vendor/Symfony/Component/HttpFoundation/Cookie.php @@ -39,6 +39,8 @@ class Cookie * @param Boolean $secure Whether the cookie should only be transmitted over a secure HTTPS connection from the client * @param Boolean $httpOnly Whether the cookie will be made accessible only through the HTTP protocol * + * @throws \InvalidArgumentException + * * @api */ public function __construct($name, $value = null, $expire = 0, $path = '/', $domain = null, $secure = false, $httpOnly = true) diff --git a/laravel/vendor/Symfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.php b/laravel/vendor/Symfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.php index 3da63dd4..f23ddd2f 100755 --- a/laravel/vendor/Symfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.php +++ b/laravel/vendor/Symfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.php @@ -45,7 +45,7 @@ public function __construct($cmd = 'file -b --mime %s 2>/dev/null') */ public static function isSupported() { - return !defined('PHP_WINDOWS_VERSION_BUILD'); + return !defined('PHP_WINDOWS_VERSION_BUILD') && function_exists('passthru') && function_exists('escapeshellarg'); } /** @@ -77,7 +77,7 @@ public function guess($path) $type = trim(ob_get_clean()); - if (!preg_match('#^([a-z0-9\-]+/[a-z0-9\-]+)#i', $type, $match)) { + if (!preg_match('#^([a-z0-9\-]+/[a-z0-9\-\.]+)#i', $type, $match)) { // it's not a type, but an error message return null; } diff --git a/laravel/vendor/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesser.php b/laravel/vendor/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesser.php index a8247ab4..59ddc077 100755 --- a/laravel/vendor/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesser.php +++ b/laravel/vendor/Symfony/Component/HttpFoundation/File/MimeType/MimeTypeGuesser.php @@ -11,7 +11,6 @@ namespace Symfony\Component\HttpFoundation\File\MimeType; -use Symfony\Component\HttpFoundation\File\Exception\FileException; use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException; @@ -99,7 +98,9 @@ public function register(MimeTypeGuesserInterface $guesser) * * @return string The mime type or NULL, if none could be guessed * - * @throws FileException If the file does not exist + * @throws \LogicException + * @throws FileNotFoundException + * @throws AccessDeniedException */ public function guess($path) { diff --git a/laravel/vendor/Symfony/Component/HttpFoundation/File/UploadedFile.php b/laravel/vendor/Symfony/Component/HttpFoundation/File/UploadedFile.php index d201e2dc..63c5386a 100755 --- a/laravel/vendor/Symfony/Component/HttpFoundation/File/UploadedFile.php +++ b/laravel/vendor/Symfony/Component/HttpFoundation/File/UploadedFile.php @@ -118,6 +118,19 @@ public function getClientOriginalName() return $this->originalName; } + /** + * Returns the original file extension + * + * It is extracted from the original file name that was uploaded. + * Then is should not be considered as a safe value. + * + * @return string The extension + */ + public function getClientOriginalExtension() + { + return pathinfo($this->originalName, PATHINFO_EXTENSION); + } + /** * Returns the file mime type. * diff --git a/laravel/vendor/Symfony/Component/HttpFoundation/HeaderBag.php b/laravel/vendor/Symfony/Component/HttpFoundation/HeaderBag.php index 2360e55b..b579eb99 100755 --- a/laravel/vendor/Symfony/Component/HttpFoundation/HeaderBag.php +++ b/laravel/vendor/Symfony/Component/HttpFoundation/HeaderBag.php @@ -149,7 +149,7 @@ public function get($key, $default = null, $first = true) * * @param string $key The key * @param string|array $values The value or an array of values - * @param Boolean $replace Whether to replace the actual value of not (true by default) + * @param Boolean $replace Whether to replace the actual value or not (true by default) * * @api */ @@ -223,7 +223,7 @@ public function remove($key) * @param string $key The parameter key * @param \DateTime $default The default value * - * @return null|\DateTime The filtered value + * @return null|\DateTime The parsed DateTime or the default value if the header does not exist * * @throws \RuntimeException When the HTTP header is not parseable * diff --git a/laravel/vendor/Symfony/Component/HttpFoundation/IpUtils.php b/laravel/vendor/Symfony/Component/HttpFoundation/IpUtils.php new file mode 100644 index 00000000..2e3e1aa7 --- /dev/null +++ b/laravel/vendor/Symfony/Component/HttpFoundation/IpUtils.php @@ -0,0 +1,111 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation; + +/** + * Http utility functions. + * + * @author Fabien Potencier + */ +class IpUtils +{ + /** + * This class should not be instantiated + */ + private function __construct() {} + + /** + * Validates an IPv4 or IPv6 address. + * + * @param string $requestIp + * @param string $ip + * + * @return boolean Whether the IP is valid + */ + public static function checkIp($requestIp, $ip) + { + if (false !== strpos($requestIp, ':')) { + return self::checkIp6($requestIp, $ip); + } + + return self::checkIp4($requestIp, $ip); + } + + /** + * Validates an IPv4 address. + * + * @param string $requestIp + * @param string $ip + * + * @return boolean Whether the IP is valid + */ + public static function checkIp4($requestIp, $ip) + { + if (false !== strpos($ip, '/')) { + list($address, $netmask) = explode('/', $ip, 2); + + if ($netmask < 1 || $netmask > 32) { + return false; + } + } else { + $address = $ip; + $netmask = 32; + } + + return 0 === substr_compare(sprintf('%032b', ip2long($requestIp)), sprintf('%032b', ip2long($address)), 0, $netmask); + } + + /** + * Validates an IPv6 address. + * + * @author David Soria Parra + * @see https://github.com/dsp/v6tools + * + * @param string $requestIp + * @param string $ip + * + * @return boolean Whether the IP is valid + * + * @throws \RuntimeException When IPV6 support is not enabled + */ + public static function checkIp6($requestIp, $ip) + { + if (!((extension_loaded('sockets') && defined('AF_INET6')) || @inet_pton('::1'))) { + throw new \RuntimeException('Unable to check Ipv6. Check that PHP was not compiled with option "disable-ipv6".'); + } + + if (false !== strpos($ip, '/')) { + list($address, $netmask) = explode('/', $ip, 2); + + if ($netmask < 1 || $netmask > 128) { + return false; + } + } else { + $address = $ip; + $netmask = 128; + } + + $bytesAddr = unpack("n*", inet_pton($address)); + $bytesTest = unpack("n*", inet_pton($requestIp)); + + for ($i = 1, $ceil = ceil($netmask / 16); $i <= $ceil; $i++) { + $left = $netmask - 16 * ($i-1); + $left = ($left <= 16) ? $left : 16; + $mask = ~(0xffff >> $left) & 0xffff; + if (($bytesAddr[$i] & $mask) != ($bytesTest[$i] & $mask)) { + return false; + } + } + + return true; + } +} diff --git a/laravel/vendor/Symfony/Component/HttpFoundation/JsonResponse.php b/laravel/vendor/Symfony/Component/HttpFoundation/JsonResponse.php index 29b4cc7b..b6ac8017 100755 --- a/laravel/vendor/Symfony/Component/HttpFoundation/JsonResponse.php +++ b/laravel/vendor/Symfony/Component/HttpFoundation/JsonResponse.php @@ -28,17 +28,20 @@ class JsonResponse extends Response * @param integer $status The response status code * @param array $headers An array of response headers */ - public function __construct($data = array(), $status = 200, $headers = array()) + public function __construct($data = null, $status = 200, $headers = array()) { parent::__construct('', $status, $headers); + if (null === $data) { + $data = new \ArrayObject(); + } $this->setData($data); } /** * {@inheritDoc} */ - public static function create($data = array(), $status = 200, $headers = array()) + public static function create($data = null, $status = 200, $headers = array()) { return new static($data, $status, $headers); } @@ -49,6 +52,8 @@ public static function create($data = array(), $status = 200, $headers = array() * @param string $callback * * @return JsonResponse + * + * @throws \InvalidArgumentException */ public function setCallback($callback = null) { @@ -77,11 +82,6 @@ public function setCallback($callback = null) */ public function setData($data = array()) { - // root should be JSON object, not array - if (is_array($data) && 0 === count($data)) { - $data = new \ArrayObject(); - } - // Encode <, >, ', &, and " for RFC4627-compliant JSON, which may also be embedded into HTML. $this->data = json_encode($data, JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT); diff --git a/laravel/vendor/Symfony/Component/HttpFoundation/LICENSE b/laravel/vendor/Symfony/Component/HttpFoundation/LICENSE index cdffe7ae..88a57f8d 100755 --- a/laravel/vendor/Symfony/Component/HttpFoundation/LICENSE +++ b/laravel/vendor/Symfony/Component/HttpFoundation/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2012 Fabien Potencier +Copyright (c) 2004-2013 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/laravel/vendor/Symfony/Component/HttpFoundation/ParameterBag.php b/laravel/vendor/Symfony/Component/HttpFoundation/ParameterBag.php index 0273d933..c8720cdc 100755 --- a/laravel/vendor/Symfony/Component/HttpFoundation/ParameterBag.php +++ b/laravel/vendor/Symfony/Component/HttpFoundation/ParameterBag.php @@ -96,6 +96,8 @@ public function add(array $parameters = array()) * * @return mixed * + * @throws \InvalidArgumentException + * * @api */ public function get($path, $default = null, $deep = false) diff --git a/laravel/vendor/Symfony/Component/HttpFoundation/README.md b/laravel/vendor/Symfony/Component/HttpFoundation/README.md index bb6f02c4..ed49b4e1 100755 --- a/laravel/vendor/Symfony/Component/HttpFoundation/README.md +++ b/laravel/vendor/Symfony/Component/HttpFoundation/README.md @@ -31,7 +31,7 @@ Loading ------- -If you are using PHP 5.3.x you must add the following to your autoloader: +If you are not using Composer but are using PHP 5.3.x, you must add the following to your autoloader: // SessionHandlerInterface if (!interface_exists('SessionHandlerInterface')) { @@ -43,4 +43,6 @@ You can run the unit tests with the following command: - phpunit + $ cd path/to/Symfony/Component/HttpFoundation/ + $ composer.phar install --dev + $ phpunit diff --git a/laravel/vendor/Symfony/Component/HttpFoundation/RedirectResponse.php b/laravel/vendor/Symfony/Component/HttpFoundation/RedirectResponse.php index a9d98e6b..54f57216 100755 --- a/laravel/vendor/Symfony/Component/HttpFoundation/RedirectResponse.php +++ b/laravel/vendor/Symfony/Component/HttpFoundation/RedirectResponse.php @@ -29,6 +29,8 @@ class RedirectResponse extends Response * @param integer $status The status code (302 by default) * @param array $headers The headers (Location is always set to the given url) * + * @throws \InvalidArgumentException + * * @see http://tools.ietf.org/html/rfc2616#section-10.3 * * @api @@ -72,6 +74,8 @@ public function getTargetUrl() * @param string $url The URL to redirect to * * @return RedirectResponse The current response. + * + * @throws \InvalidArgumentException */ public function setTargetUrl($url) { diff --git a/laravel/vendor/Symfony/Component/HttpFoundation/Request.php b/laravel/vendor/Symfony/Component/HttpFoundation/Request.php index 18e5480c..c48082a6 100755 --- a/laravel/vendor/Symfony/Component/HttpFoundation/Request.php +++ b/laravel/vendor/Symfony/Component/HttpFoundation/Request.php @@ -30,10 +30,10 @@ */ class Request { - const HEADER_CLIENT_IP = 'client_ip'; - const HEADER_CLIENT_HOST = 'client_host'; + const HEADER_CLIENT_IP = 'client_ip'; + const HEADER_CLIENT_HOST = 'client_host'; const HEADER_CLIENT_PROTO = 'client_proto'; - const HEADER_CLIENT_PORT = 'client_port'; + const HEADER_CLIENT_PORT = 'client_port'; protected static $trustProxy = false; @@ -53,6 +53,8 @@ class Request self::HEADER_CLIENT_PORT => 'X_FORWARDED_PORT', ); + protected static $httpMethodParameterOverride = false; + /** * @var \Symfony\Component\HttpFoundation\ParameterBag * @@ -251,6 +253,9 @@ public static function createFromGlobals() /** * Creates a Request based on a given URI and configuration. * + * The information contained in the URI always take precedence + * over the other information (server and parameters). + * * @param string $uri The URI * @param string $method The HTTP method * @param array $parameters The query (GET) or request (POST) parameters @@ -265,7 +270,7 @@ public static function createFromGlobals() */ public static function create($uri, $method = 'GET', $parameters = array(), $cookies = array(), $files = array(), $server = array(), $content = null) { - $defaults = array( + $server = array_replace(array( 'SERVER_NAME' => 'localhost', 'SERVER_PORT' => 80, 'HTTP_HOST' => 'localhost', @@ -278,32 +283,38 @@ public static function create($uri, $method = 'GET', $parameters = array(), $coo 'SCRIPT_FILENAME' => '', 'SERVER_PROTOCOL' => 'HTTP/1.1', 'REQUEST_TIME' => time(), - ); + ), $server); + + $server['PATH_INFO'] = ''; + $server['REQUEST_METHOD'] = strtoupper($method); $components = parse_url($uri); if (isset($components['host'])) { - $defaults['SERVER_NAME'] = $components['host']; - $defaults['HTTP_HOST'] = $components['host']; + $server['SERVER_NAME'] = $components['host']; + $server['HTTP_HOST'] = $components['host']; } if (isset($components['scheme'])) { if ('https' === $components['scheme']) { - $defaults['HTTPS'] = 'on'; - $defaults['SERVER_PORT'] = 443; + $server['HTTPS'] = 'on'; + $server['SERVER_PORT'] = 443; + } else { + unset($server['HTTPS']); + $server['SERVER_PORT'] = 80; } } if (isset($components['port'])) { - $defaults['SERVER_PORT'] = $components['port']; - $defaults['HTTP_HOST'] = $defaults['HTTP_HOST'].':'.$components['port']; + $server['SERVER_PORT'] = $components['port']; + $server['HTTP_HOST'] = $server['HTTP_HOST'].':'.$components['port']; } if (isset($components['user'])) { - $defaults['PHP_AUTH_USER'] = $components['user']; + $server['PHP_AUTH_USER'] = $components['user']; } if (isset($components['pass'])) { - $defaults['PHP_AUTH_PW'] = $components['pass']; + $server['PHP_AUTH_PW'] = $components['pass']; } if (!isset($components['path'])) { @@ -314,7 +325,9 @@ public static function create($uri, $method = 'GET', $parameters = array(), $coo case 'POST': case 'PUT': case 'DELETE': - $defaults['CONTENT_TYPE'] = 'application/x-www-form-urlencoded'; + if (!isset($server['CONTENT_TYPE'])) { + $server['CONTENT_TYPE'] = 'application/x-www-form-urlencoded'; + } case 'PATCH': $request = $parameters; $query = array(); @@ -331,14 +344,8 @@ public static function create($uri, $method = 'GET', $parameters = array(), $coo } $queryString = http_build_query($query, '', '&'); - $uri = $components['path'].('' !== $queryString ? '?'.$queryString : ''); - - $server = array_replace($defaults, $server, array( - 'REQUEST_METHOD' => strtoupper($method), - 'PATH_INFO' => '', - 'REQUEST_URI' => $uri, - 'QUERY_STRING' => $queryString, - )); + $server['REQUEST_URI'] = $components['path'].('' !== $queryString ? '?'.$queryString : ''); + $server['QUERY_STRING'] = $queryString; return new static($query, $request, array(), $cookies, $files, $server, $content); } @@ -464,6 +471,8 @@ public function overrideGlobals() */ public static function trustProxyData() { + trigger_error('trustProxyData() is deprecated since version 2.0 and will be removed in 2.3. Use setTrustedProxies() instead.', E_USER_DEPRECATED); + self::$trustProxy = true; } @@ -482,6 +491,16 @@ public static function setTrustedProxies(array $proxies) self::$trustProxy = $proxies ? true : false; } + /** + * Gets the list of trusted proxies. + * + * @return array An array of trusted proxies. + */ + public static function getTrustedProxies() + { + return self::$trustedProxies; + } + /** * Sets the name for trusted headers. * @@ -496,6 +515,8 @@ public static function setTrustedProxies(array $proxies) * * @param string $key The header key * @param string $value The header name + * + * @throws \InvalidArgumentException */ public static function setTrustedHeaderName($key, $value) { @@ -511,6 +532,8 @@ public static function setTrustedHeaderName($key, $value) * false otherwise. * * @return boolean + * + * @deprecated Deprecated since version 2.2, to be removed in 2.3. Use getTrustedProxies instead. */ public static function isProxyTrusted() { @@ -560,6 +583,29 @@ public static function normalizeQueryString($qs) return implode('&', $parts); } + /** + * Enables support for the _method request parameter to determine the intended HTTP method. + * + * Be warned that enabling this feature might lead to CSRF issues in your code. + * Check that you are using CSRF tokens when required. + * + * The HTTP method can only be overridden when the real HTTP method is POST. + */ + public static function enableHttpMethodParameterOverride() + { + self::$httpMethodParameterOverride = true; + } + + /** + * Checks whether support for the _method request parameter is enabled. + * + * @return Boolean True when the _method request parameter is enabled, false otherwise + */ + public static function getHttpMethodParameterOverride() + { + return self::$httpMethodParameterOverride; + } + /** * Gets a "parameter" value. * @@ -657,8 +703,6 @@ public function setSession(SessionInterface $session) * * @see http://en.wikipedia.org/wiki/X-Forwarded-For * - * @deprecated The proxy argument is deprecated since version 2.0 and will be removed in 2.3. Use setTrustedProxies instead. - * * @api */ public function getClientIp() @@ -703,7 +747,7 @@ public function getScriptName() * * * http://localhost/mysite returns an empty string * * http://localhost/mysite/about returns '/about' - * * htpp://localhost/mysite/enco%20ded returns '/enco%20ded' + * * http://localhost/mysite/enco%20ded returns '/enco%20ded' * * http://localhost/mysite/about?var=1 returns '/about' * * @return string The raw path (i.e. not urldecoded) @@ -897,8 +941,7 @@ public function getSchemeAndHttpHost() */ public function getUri() { - $qs = $this->getQueryString(); - if (null !== $qs) { + if (null !== $qs = $this->getQueryString()) { $qs = '?'.$qs; } @@ -1017,26 +1060,51 @@ public function setMethod($method) } /** - * Gets the request method. + * Gets the request "intended" method. + * + * If the X-HTTP-Method-Override header is set, and if the method is a POST, + * then it is used to determine the "real" intended HTTP method. + * + * The _method request parameter can also be used to determine the HTTP method, + * but only if enableHttpMethodParameterOverride() has been called. * * The method is always an uppercased string. * * @return string The request method * * @api + * + * @see getRealMethod */ public function getMethod() { if (null === $this->method) { $this->method = strtoupper($this->server->get('REQUEST_METHOD', 'GET')); + if ('POST' === $this->method) { - $this->method = strtoupper($this->headers->get('X-HTTP-METHOD-OVERRIDE', $this->request->get('_method', $this->query->get('_method', 'POST')))); + if ($method = $this->headers->get('X-HTTP-METHOD-OVERRIDE')) { + $this->method = strtoupper($method); + } elseif (self::$httpMethodParameterOverride) { + $this->method = strtoupper($this->request->get('_method', $this->query->get('_method', 'POST'))); + } } } return $this->method; } + /** + * Gets the "real" request method. + * + * @return string The request method + * + * @see getMethod + */ + public function getRealMethod() + { + return strtoupper($this->server->get('REQUEST_METHOD', 'GET')); + } + /** * Gets the mime type associated with the format. * @@ -1216,6 +1284,8 @@ public function isMethodSafe() * @param Boolean $asResource If true, a resource will be returned * * @return string|resource The request body content or a resource to read the body stream. + * + * @throws \LogicException */ public function getContent($asResource = false) { @@ -1275,7 +1345,18 @@ public function getPreferredLanguage(array $locales = null) return $locales[0]; } - $preferredLanguages = array_values(array_intersect($preferredLanguages, $locales)); + $extendedPreferredLanguages = array(); + foreach ($preferredLanguages as $language) { + $extendedPreferredLanguages[] = $language; + if (false !== $position = strpos($language, '_')) { + $superLanguage = substr($language, 0, $position); + if (!in_array($superLanguage, $preferredLanguages)) { + $extendedPreferredLanguages[] = $superLanguage; + } + } + } + + $preferredLanguages = array_values(array_intersect($extendedPreferredLanguages, $locales)); return isset($preferredLanguages[0]) ? $preferredLanguages[0] : $locales[0]; } @@ -1293,9 +1374,9 @@ public function getLanguages() return $this->languages; } - $languages = $this->splitHttpAcceptHeader($this->headers->get('Accept-Language')); + $languages = AcceptHeader::fromString($this->headers->get('Accept-Language'))->all(); $this->languages = array(); - foreach ($languages as $lang => $q) { + foreach (array_keys($languages) as $lang) { if (strstr($lang, '-')) { $codes = explode('-', $lang); if ($codes[0] == 'i') { @@ -1335,7 +1416,7 @@ public function getCharsets() return $this->charsets; } - return $this->charsets = array_keys($this->splitHttpAcceptHeader($this->headers->get('Accept-Charset'))); + return $this->charsets = array_keys(AcceptHeader::fromString($this->headers->get('Accept-Charset'))->all()); } /** @@ -1351,14 +1432,15 @@ public function getAcceptableContentTypes() return $this->acceptableContentTypes; } - return $this->acceptableContentTypes = array_keys($this->splitHttpAcceptHeader($this->headers->get('Accept'))); + return $this->acceptableContentTypes = array_keys(AcceptHeader::fromString($this->headers->get('Accept'))->all()); } /** * Returns true if the request is a XMLHttpRequest. * * It works if your JavaScript library set an X-Requested-With HTTP header. - * It is known to work with Prototype, Mootools, jQuery. + * It is known to work with common JavaScript frameworks: + * @link http://en.wikipedia.org/wiki/List_of_Ajax_frameworks#JavaScript * * @return Boolean true if the request is an XMLHttpRequest, false otherwise * @@ -1375,40 +1457,23 @@ public function isXmlHttpRequest() * @param string $header Header to split * * @return array Array indexed by the values of the Accept-* header in preferred order + * + * @deprecated Deprecated since version 2.2, to be removed in 2.3. */ public function splitHttpAcceptHeader($header) { - if (!$header) { - return array(); - } + trigger_error('splitHttpAcceptHeader() is deprecated since version 2.2 and will be removed in 2.3.', E_USER_DEPRECATED); - $values = array(); - $groups = array(); - foreach (array_filter(explode(',', $header)) as $value) { - // Cut off any q-value that might come after a semi-colon - if (preg_match('/;\s*(q=.*$)/', $value, $match)) { - $q = substr(trim($match[1]), 2); - $value = trim(substr($value, 0, -strlen($match[0]))); - } else { - $q = 1; + $headers = array(); + foreach (AcceptHeader::fromString($header)->all() as $item) { + $key = $item->getValue(); + foreach ($item->getAttributes() as $name => $value) { + $key .= sprintf(';%s=%s', $name, $value); } - - $groups[$q][] = $value; + $headers[$key] = $item->getQuality(); } - krsort($groups); - - foreach ($groups as $q => $items) { - $q = (float) $q; - - if (0 < $q) { - foreach ($items as $value) { - $values[trim($value)] = $q; - } - } - } - - return $values; + return $headers; } /* @@ -1426,12 +1491,16 @@ protected function prepareRequestUri() if ($this->headers->has('X_ORIGINAL_URL') && false !== stripos(PHP_OS, 'WIN')) { // IIS with Microsoft Rewrite Module $requestUri = $this->headers->get('X_ORIGINAL_URL'); + $this->headers->remove('X_ORIGINAL_URL'); } elseif ($this->headers->has('X_REWRITE_URL') && false !== stripos(PHP_OS, 'WIN')) { // IIS with ISAPI_Rewrite $requestUri = $this->headers->get('X_REWRITE_URL'); + $this->headers->remove('X_REWRITE_URL'); } elseif ($this->server->get('IIS_WasUrlRewritten') == '1' && $this->server->get('UNENCODED_URL') != '') { // IIS7 with URL Rewrite: make sure we get the unencoded url (double slash problem) $requestUri = $this->server->get('UNENCODED_URL'); + $this->server->remove('UNENCODED_URL'); + $this->server->remove('IIS_WasUrlRewritten'); } elseif ($this->server->has('REQUEST_URI')) { $requestUri = $this->server->get('REQUEST_URI'); // HTTP proxy reqs setup request uri with scheme and host [and port] + the url path, only use url path @@ -1445,8 +1514,12 @@ protected function prepareRequestUri() if ('' != $this->server->get('QUERY_STRING')) { $requestUri .= '?'.$this->server->get('QUERY_STRING'); } + $this->server->remove('ORIG_PATH_INFO'); } + // normalize the request URI to ease creating sub-requests from this request + $this->server->set('REQUEST_URI', $requestUri); + return $requestUri; } diff --git a/laravel/vendor/Symfony/Component/HttpFoundation/RequestMatcher.php b/laravel/vendor/Symfony/Component/HttpFoundation/RequestMatcher.php index 7ebae28b..49b92f0e 100755 --- a/laravel/vendor/Symfony/Component/HttpFoundation/RequestMatcher.php +++ b/laravel/vendor/Symfony/Component/HttpFoundation/RequestMatcher.php @@ -143,95 +143,10 @@ public function matches(Request $request) return false; } - if (null !== $this->ip && !$this->checkIp($request->getClientIp(), $this->ip)) { + if (null !== $this->ip && !IpUtils::checkIp($request->getClientIp(), $this->ip)) { return false; } return true; } - - /** - * Validates an IP address. - * - * @param string $requestIp - * @param string $ip - * - * @return boolean True valid, false if not. - */ - protected function checkIp($requestIp, $ip) - { - // IPv6 address - if (false !== strpos($requestIp, ':')) { - return $this->checkIp6($requestIp, $ip); - } else { - return $this->checkIp4($requestIp, $ip); - } - } - - /** - * Validates an IPv4 address. - * - * @param string $requestIp - * @param string $ip - * - * @return boolean True valid, false if not. - */ - protected function checkIp4($requestIp, $ip) - { - if (false !== strpos($ip, '/')) { - list($address, $netmask) = explode('/', $ip, 2); - - if ($netmask < 1 || $netmask > 32) { - return false; - } - } else { - $address = $ip; - $netmask = 32; - } - - return 0 === substr_compare(sprintf('%032b', ip2long($requestIp)), sprintf('%032b', ip2long($address)), 0, $netmask); - } - - /** - * Validates an IPv6 address. - * - * @author David Soria Parra - * @see https://github.com/dsp/v6tools - * - * @param string $requestIp - * @param string $ip - * - * @return boolean True valid, false if not. - */ - protected function checkIp6($requestIp, $ip) - { - if (!((extension_loaded('sockets') && defined('AF_INET6')) || @inet_pton('::1'))) { - throw new \RuntimeException('Unable to check Ipv6. Check that PHP was not compiled with option "disable-ipv6".'); - } - - if (false !== strpos($ip, '/')) { - list($address, $netmask) = explode('/', $ip, 2); - - if ($netmask < 1 || $netmask > 128) { - return false; - } - } else { - $address = $ip; - $netmask = 128; - } - - $bytesAddr = unpack("n*", inet_pton($address)); - $bytesTest = unpack("n*", inet_pton($requestIp)); - - for ($i = 1, $ceil = ceil($netmask / 16); $i <= $ceil; $i++) { - $left = $netmask - 16 * ($i-1); - $left = ($left <= 16) ? $left : 16; - $mask = ~(0xffff >> $left) & 0xffff; - if (($bytesAddr[$i] & $mask) != ($bytesTest[$i] & $mask)) { - return false; - } - } - - return true; - } } diff --git a/laravel/vendor/Symfony/Component/HttpFoundation/Response.php b/laravel/vendor/Symfony/Component/HttpFoundation/Response.php index 7428b9a9..7ac4e800 100755 --- a/laravel/vendor/Symfony/Component/HttpFoundation/Response.php +++ b/laravel/vendor/Symfony/Component/HttpFoundation/Response.php @@ -131,6 +131,8 @@ class Response * @param integer $status The response status code * @param array $headers An array of response headers * + * @throws \InvalidArgumentException When the HTTP status code is not valid + * * @api */ public function __construct($content = '', $status = 200, $headers = array()) @@ -231,7 +233,7 @@ public function prepare(Request $request) $headers->remove('Content-Length'); } - if ('HEAD' === $request->getMethod()) { + if ($request->isMethod('HEAD')) { // cf. RFC2616 14.13 $length = $headers->get('Content-Length'); $this->setContent(null); @@ -251,6 +253,16 @@ public function prepare(Request $request) $this->headers->set('expires', -1); } + /** + * Check if we need to remove Cache-Control for ssl encrypted downloads when using IE < 9 + * @link http://support.microsoft.com/kb/323308 + */ + if (false !== stripos($this->headers->get('Content-Disposition'), 'attachment') && preg_match('/MSIE (.*?);/i', $request->server->get('HTTP_USER_AGENT'), $match) == 1 && true === $request->isSecure()) { + if (intval(preg_replace("/(MSIE )(.*?);/", "$2", $match[0])) < 9) { + $this->headers->remove('Cache-Control'); + } + } + return $this; } @@ -270,7 +282,7 @@ public function sendHeaders() header(sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText)); // headers - foreach ($this->headers->all() as $name => $values) { + foreach ($this->headers->allPreserveCase() as $name => $values) { foreach ($values as $value) { header($name.': '.$value, false); } @@ -336,6 +348,8 @@ public function send() * * @return Response * + * @throws \UnexpectedValueException + * * @api */ public function setContent($content) @@ -431,7 +445,7 @@ public function setStatusCode($code, $text = null) /** * Retrieves the status code for the current web response. * - * @return string Status code + * @return integer Status code * * @api */ @@ -499,7 +513,7 @@ public function isCacheable() * * Fresh responses may be served from cache without any interaction with the * origin. A response is considered fresh when it includes a Cache-Control/max-age - * indicator or Expiration header and the calculated age is less than the freshness lifetime. + * indicator or Expires header and the calculated age is less than the freshness lifetime. * * @return Boolean true if the response is fresh, false otherwise * @@ -612,8 +626,8 @@ public function setDate(\DateTime $date) */ public function getAge() { - if ($age = $this->headers->get('Age')) { - return $age; + if (null !== $age = $this->headers->get('Age')) { + return (int) $age; } return max(time() - $this->getDate()->format('U'), 0); @@ -638,21 +652,26 @@ public function expire() /** * Returns the value of the Expires header as a DateTime instance. * - * @return \DateTime A DateTime instance + * @return \DateTime|null A DateTime instance or null if the header does not exist * * @api */ public function getExpires() { - return $this->headers->getDate('Expires'); + try { + return $this->headers->getDate('Expires'); + } catch (\RuntimeException $e) { + // according to RFC 2616 invalid date formats (e.g. "0" and "-1") must be treated as in the past + return \DateTime::createFromFormat(DATE_RFC2822, 'Sat, 01 Jan 00 00:00:00 +0000'); + } } /** * Sets the Expires HTTP header with a DateTime instance. * - * If passed a null value, it removes the header. + * Passing null as value will remove the header. * - * @param \DateTime $date A \DateTime instance + * @param \DateTime|null $date A \DateTime instance or null to remove the header * * @return Response * @@ -672,7 +691,7 @@ public function setExpires(\DateTime $date = null) } /** - * Sets the number of seconds after the time specified in the response's Date + * Returns the number of seconds after the time specified in the response's Date * header when the the response should no longer be considered fresh. * * First, it checks for a s-maxage directive, then a max-age directive, and then it falls @@ -684,12 +703,12 @@ public function setExpires(\DateTime $date = null) */ public function getMaxAge() { - if ($age = $this->headers->getCacheControlDirective('s-maxage')) { - return $age; + if ($this->headers->hasCacheControlDirective('s-maxage')) { + return (int) $this->headers->getCacheControlDirective('s-maxage'); } - if ($age = $this->headers->getCacheControlDirective('max-age')) { - return $age; + if ($this->headers->hasCacheControlDirective('max-age')) { + return (int) $this->headers->getCacheControlDirective('max-age'); } if (null !== $this->getExpires()) { @@ -750,7 +769,7 @@ public function setSharedMaxAge($value) */ public function getTtl() { - if ($maxAge = $this->getMaxAge()) { + if (null !== $maxAge = $this->getMaxAge()) { return $maxAge - $this->getAge(); } @@ -796,7 +815,9 @@ public function setClientTtl($seconds) /** * Returns the Last-Modified HTTP header as a DateTime instance. * - * @return \DateTime A DateTime instance + * @return \DateTime|null A DateTime instance or null if the header does not exist + * + * @throws \RuntimeException When the HTTP header is not parseable * * @api */ @@ -808,9 +829,9 @@ public function getLastModified() /** * Sets the Last-Modified HTTP header with a DateTime instance. * - * If passed a null value, it removes the header. + * Passing null as value will remove the header. * - * @param \DateTime $date A \DateTime instance + * @param \DateTime|null $date A \DateTime instance or null to remove the header * * @return Response * @@ -832,7 +853,7 @@ public function setLastModified(\DateTime $date = null) /** * Returns the literal value of the ETag HTTP header. * - * @return string The ETag HTTP header + * @return string|null The ETag HTTP header or null if it does not exist * * @api */ @@ -844,8 +865,8 @@ public function getEtag() /** * Sets the ETag value. * - * @param string $etag The ETag unique identifier - * @param Boolean $weak Whether you want a weak ETag or not + * @param string|null $etag The ETag unique identifier or null to remove the header + * @param Boolean $weak Whether you want a weak ETag or not * * @return Response * @@ -875,6 +896,8 @@ public function setEtag($etag = null, $weak = false) * * @return Response * + * @throws \InvalidArgumentException + * * @api */ public function setCache(array $options) @@ -952,7 +975,7 @@ public function setNotModified() */ public function hasVary() { - return (Boolean) $this->headers->get('Vary'); + return null !== $this->headers->get('Vary'); } /** @@ -1108,7 +1131,7 @@ public function isOk() } /** - * Is the reponse forbidden? + * Is the response forbidden? * * @return Boolean * diff --git a/laravel/vendor/Symfony/Component/HttpFoundation/ResponseHeaderBag.php b/laravel/vendor/Symfony/Component/HttpFoundation/ResponseHeaderBag.php index c27d8116..f52f0488 100755 --- a/laravel/vendor/Symfony/Component/HttpFoundation/ResponseHeaderBag.php +++ b/laravel/vendor/Symfony/Component/HttpFoundation/ResponseHeaderBag.php @@ -36,6 +36,11 @@ class ResponseHeaderBag extends HeaderBag */ protected $cookies = array(); + /** + * @var array + */ + protected $headerNames = array(); + /** * Constructor. * @@ -48,7 +53,7 @@ public function __construct(array $headers = array()) parent::__construct($headers); if (!isset($this->headers['cache-control'])) { - $this->set('cache-control', ''); + $this->set('Cache-Control', ''); } } @@ -62,9 +67,21 @@ public function __toString() $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} * @@ -72,10 +89,12 @@ public function __toString() */ public function replace(array $headers = array()) { + $this->headerNames = array(); + parent::replace($headers); if (!isset($this->headers['cache-control'])) { - $this->set('cache-control', ''); + $this->set('Cache-Control', ''); } } @@ -88,10 +107,14 @@ 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(strtr(strtolower($key), '_', '-'), array('cache-control', 'etag', 'last-modified', 'expires'))) { + 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); } } @@ -105,7 +128,10 @@ public function remove($key) { parent::remove($key); - if ('cache-control' === strtr(strtolower($key), '_', '-')) { + $uniqueKey = strtr(strtolower($key), '_', '-'); + unset($this->headerNames[$uniqueKey]); + + if ('cache-control' === $uniqueKey) { $this->computedCacheControl = array(); } } diff --git a/laravel/vendor/Symfony/Component/HttpFoundation/Session/Attribute/AttributeBag.php b/laravel/vendor/Symfony/Component/HttpFoundation/Session/Attribute/AttributeBag.php index 2f1a4222..e9d02571 100755 --- a/laravel/vendor/Symfony/Component/HttpFoundation/Session/Attribute/AttributeBag.php +++ b/laravel/vendor/Symfony/Component/HttpFoundation/Session/Attribute/AttributeBag.php @@ -31,7 +31,7 @@ class AttributeBag implements AttributeBagInterface, \IteratorAggregate, \Counta /** * Constructor. * - * @param string $storageKey The key used to store flashes in the session. + * @param string $storageKey The key used to store attributes in the session. */ public function __construct($storageKey = '_sf2_attributes') { diff --git a/laravel/vendor/Symfony/Component/HttpFoundation/Session/Flash/FlashBag.php b/laravel/vendor/Symfony/Component/HttpFoundation/Session/Flash/FlashBag.php index ce9308e1..5bb43bc5 100755 --- a/laravel/vendor/Symfony/Component/HttpFoundation/Session/Flash/FlashBag.php +++ b/laravel/vendor/Symfony/Component/HttpFoundation/Session/Flash/FlashBag.php @@ -177,10 +177,17 @@ public function getIterator() /** * Returns the number of flashes. * + * This method does not work. + * + * @deprecated in 2.2, removed in 2.3 + * @see https://github.com/symfony/symfony/issues/6408 + * * @return int The number of flashes */ public function count() { + trigger_error(sprintf('%s() is deprecated since 2.2 and will be removed in 2.3', __METHOD__), E_USER_DEPRECATED); + return count($this->flashes); } } diff --git a/laravel/vendor/Symfony/Component/HttpFoundation/Session/Session.php b/laravel/vendor/Symfony/Component/HttpFoundation/Session/Session.php index ee987c67..b0b3ff3d 100755 --- a/laravel/vendor/Symfony/Component/HttpFoundation/Session/Session.php +++ b/laravel/vendor/Symfony/Component/HttpFoundation/Session/Session.php @@ -259,6 +259,8 @@ public function getFlashBag() */ public function getFlashes() { + trigger_error('getFlashes() is deprecated since version 2.1 and will be removed in 2.3. Use the FlashBag instead.', E_USER_DEPRECATED); + $all = $this->getBag($this->flashName)->all(); $return = array(); @@ -282,6 +284,8 @@ public function getFlashes() */ public function setFlashes($values) { + trigger_error('setFlashes() is deprecated since version 2.1 and will be removed in 2.3. Use the FlashBag instead.', E_USER_DEPRECATED); + foreach ($values as $name => $value) { $this->getBag($this->flashName)->set($name, $value); } @@ -297,6 +301,8 @@ public function setFlashes($values) */ public function getFlash($name, $default = null) { + trigger_error('getFlash() is deprecated since version 2.1 and will be removed in 2.3. Use the FlashBag instead.', E_USER_DEPRECATED); + $return = $this->getBag($this->flashName)->get($name); return empty($return) ? $default : reset($return); @@ -310,6 +316,8 @@ public function getFlash($name, $default = null) */ public function setFlash($name, $value) { + trigger_error('setFlash() is deprecated since version 2.1 and will be removed in 2.3. Use the FlashBag instead.', E_USER_DEPRECATED); + $this->getBag($this->flashName)->set($name, $value); } @@ -322,6 +330,8 @@ public function setFlash($name, $value) */ public function hasFlash($name) { + trigger_error('hasFlash() is deprecated since version 2.1 and will be removed in 2.3. Use the FlashBag instead.', E_USER_DEPRECATED); + return $this->getBag($this->flashName)->has($name); } @@ -332,6 +342,8 @@ public function hasFlash($name) */ public function removeFlash($name) { + trigger_error('removeFlash() is deprecated since version 2.1 and will be removed in 2.3. Use the FlashBag instead.', E_USER_DEPRECATED); + $this->getBag($this->flashName)->get($name); } @@ -342,6 +354,8 @@ public function removeFlash($name) */ public function clearFlashes() { + trigger_error('clearFlashes() is deprecated since version 2.1 and will be removed in 2.3. Use the FlashBag instead.', E_USER_DEPRECATED); + return $this->getBag($this->flashName)->clear(); } } diff --git a/laravel/vendor/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php b/laravel/vendor/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php index 93a57296..69ebae95 100755 --- a/laravel/vendor/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php +++ b/laravel/vendor/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php @@ -36,6 +36,13 @@ class MongoDbSessionHandler implements \SessionHandlerInterface /** * Constructor. * + * List of available options: + * * database: The name of the database [required] + * * collection: The name of the collection [required] + * * id_field: The field name for storing the session id [default: _id] + * * data_field: The field name for storing the session data [default: data] + * * time_field: The field name for storing the timestamp [default: time] + * * @param \Mongo|\MongoClient $mongo A MongoClient or Mongo instance * @param array $options An associative array of field options * @@ -55,9 +62,9 @@ public function __construct($mongo, array $options) $this->mongo = $mongo; $this->options = array_merge(array( - 'id_field' => 'sess_id', - 'data_field' => 'sess_data', - 'time_field' => 'sess_time', + 'id_field' => '_id', + 'data_field' => 'data', + 'time_field' => 'time', ), $options); } @@ -82,10 +89,9 @@ public function close() */ public function destroy($sessionId) { - $this->getCollection()->remove( - array($this->options['id_field'] => $sessionId), - array('justOne' => true) - ); + $this->getCollection()->remove(array( + $this->options['id_field'] => $sessionId + )); return true; } @@ -95,11 +101,21 @@ public function destroy($sessionId) */ public function gc($lifetime) { - $time = new \MongoTimestamp(time() - $lifetime); + /* Note: MongoDB 2.2+ supports TTL collections, which may be used in + * place of this method by indexing the "time_field" field with an + * "expireAfterSeconds" option. Regardless of whether TTL collections + * are used, consider indexing this field to make the remove query more + * efficient. + * + * See: http://docs.mongodb.org/manual/tutorial/expire-data/ + */ + $time = new \MongoDate(time() - $lifetime); $this->getCollection()->remove(array( $this->options['time_field'] => array('$lt' => $time), )); + + return true; } /** @@ -107,16 +123,13 @@ public function gc($lifetime) */ public function write($sessionId, $data) { - $data = array( - $this->options['id_field'] => $sessionId, - $this->options['data_field'] => new \MongoBinData($data, \MongoBinData::BYTE_ARRAY), - $this->options['time_field'] => new \MongoTimestamp() - ); - $this->getCollection()->update( array($this->options['id_field'] => $sessionId), - array('$set' => $data), - array('upsert' => true) + array('$set' => array( + $this->options['data_field'] => new \MongoBinData($data, \MongoBinData::BYTE_ARRAY), + $this->options['time_field'] => new \MongoDate(), + )), + array('upsert' => true, 'multiple' => false) ); return true; diff --git a/laravel/vendor/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php b/laravel/vendor/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php index 2dc85648..4b9be5e9 100755 --- a/laravel/vendor/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php +++ b/laravel/vendor/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php @@ -27,17 +27,17 @@ class NativeSessionStorage implements SessionStorageInterface /** * Array of SessionBagInterface * - * @var array + * @var SessionBagInterface[] */ protected $bags; /** - * @var boolean + * @var Boolean */ protected $started = false; /** - * @var boolean + * @var Boolean */ protected $closed = false; @@ -332,9 +332,9 @@ public function setOptions(array $options) * Registers save handler as a PHP session handler. * * To use internal PHP session save handlers, override this method using ini_set with - * session.save_handlers and session.save_path e.g. + * session.save_handler and session.save_path e.g. * - * ini_set('session.save_handlers', 'files'); + * ini_set('session.save_handler', 'files'); * ini_set('session.save_path', /tmp'); * * @see http://php.net/session-set-save-handler diff --git a/laravel/vendor/Symfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.php b/laravel/vendor/Symfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.php index 0d4cb8b6..1f68f249 100755 --- a/laravel/vendor/Symfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.php +++ b/laravel/vendor/Symfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.php @@ -99,6 +99,8 @@ public function getId() * Sets the session ID. * * @param string $id + * + * @throws \LogicException */ public function setId($id) { @@ -123,6 +125,8 @@ public function getName() * Sets the session name. * * @param string $name + * + * @throws \LogicException */ public function setName($name) { diff --git a/laravel/vendor/Symfony/Component/HttpFoundation/StreamedResponse.php b/laravel/vendor/Symfony/Component/HttpFoundation/StreamedResponse.php index 53bdbe64..ae579bea 100755 --- a/laravel/vendor/Symfony/Component/HttpFoundation/StreamedResponse.php +++ b/laravel/vendor/Symfony/Component/HttpFoundation/StreamedResponse.php @@ -62,6 +62,8 @@ public static function create($callback = null, $status = 200, $headers = array( * Sets the PHP callback associated with this Response. * * @param mixed $callback A valid PHP callback + * + * @throws \LogicException */ public function setCallback($callback) { diff --git a/laravel/vendor/Symfony/Component/HttpFoundation/composer.json b/laravel/vendor/Symfony/Component/HttpFoundation/composer.json index e9f54948..09b87253 100755 --- a/laravel/vendor/Symfony/Component/HttpFoundation/composer.json +++ b/laravel/vendor/Symfony/Component/HttpFoundation/composer.json @@ -19,11 +19,14 @@ "php": ">=5.3.3" }, "autoload": { - "psr-0": { - "Symfony\\Component\\HttpFoundation": "", - "SessionHandlerInterface": "Symfony/Component/HttpFoundation/Resources/stubs" - } + "psr-0": { "Symfony\\Component\\HttpFoundation\\": "" }, + "classmap": [ "Symfony/Component/HttpFoundation/Resources/stubs" ] }, "target-dir": "Symfony/Component/HttpFoundation", - "minimum-stability": "dev" + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "2.2-dev" + } + } } diff --git a/laravel/vendor/Symfony/Component/HttpFoundation/phpunit.xml.dist b/laravel/vendor/Symfony/Component/HttpFoundation/phpunit.xml.dist new file mode 100644 index 00000000..df11f72c --- /dev/null +++ b/laravel/vendor/Symfony/Component/HttpFoundation/phpunit.xml.dist @@ -0,0 +1,30 @@ + + + + + + ./Tests/ + + + + + + ./ + + ./Resources + ./Tests + ./vendor + + + +